00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "parleydocument.h"
00017
00018 #include "../config-parley.h"
00019 #include "parleymainwindow.h"
00020 #include "editor/editor.h"
00021 #include "version.h"
00022 #include "prefs.h"
00023
00024 #include "vocabulary/vocabularyview.h"
00025 #include "settings/documentproperties.h"
00026 #include "welcomescreen/welcomescreen.h"
00027
00028 #include <keduvoclesson.h>
00029 #include <keduvocleitnerbox.h>
00030 #include <keduvocexpression.h>
00031 #include <keduvocwordtype.h>
00032
00033 #include <KFileDialog>
00034 #include <KRecentFilesAction>
00035 #include <KStandardDirs>
00036 #include <knewstuff3/downloaddialog.h>
00037 #include <knewstuff3/uploaddialog.h>
00038 #include <KUser>
00039 #include <KMessageBox>
00040 #include <KProcess>
00041 #include <KTempDir>
00042
00043 #include <QTimer>
00044 #include <QtGui/QPrinter>
00045 #include <QtGui/QPrintDialog>
00046
00047 #ifdef HAVE_LIBXSLT
00048 #include "export/exportdialog.h"
00049 #include <libxml/parser.h>
00050 #include <libxml/tree.h>
00051 #include <libxslt/xslt.h>
00052 #include <libxslt/xsltInternals.h>
00053 #include <libxslt/transform.h>
00054 #include <libxslt/xsltutils.h>
00055 #endif
00056
00057 ParleyDocument* ParleyDocument::s_instance = 0;
00058
00059 ParleyDocument* ParleyDocument::instance()
00060 {
00061 if (!s_instance) {
00062 s_instance = new ParleyDocument;
00063 }
00064 return s_instance;
00065 }
00066
00067 void ParleyDocument::destroy()
00068 {
00069 if (s_instance) {
00070 delete s_instance;
00071 s_instance = 0;
00072 }
00073 }
00074
00075 ParleyDocument::ParleyDocument()
00076 :QObject(ParleyMainWindow::instance()), m_doc(new KEduVocDocument(this)), m_backupTimer(0)
00077 {
00078 }
00079
00080 ParleyDocument::~ParleyDocument()
00081 {
00082 delete m_backupTimer;
00083 delete m_doc;
00084 }
00085
00086 KEduVocDocument * ParleyDocument::document()
00087 {
00088 return m_doc;
00089 }
00090
00091 void ParleyDocument::setTitle(const QString& title)
00092 {
00093 m_doc->setTitle(title);
00094 ParleyMainWindow::instance()->slotUpdateWindowCaption();
00095 m_doc->setModified(true);
00096 }
00097
00098 void ParleyDocument::slotFileNew()
00099 {
00100 if (ParleyMainWindow::instance()->queryExit()) {
00101 newDocument(true);
00102 }
00103 }
00104
00105 void ParleyDocument::newDocument(bool wizard)
00106 {
00107 KEduVocDocument *newDoc = new KEduVocDocument();
00108
00109 initializeDefaultGrammar(newDoc);
00110 setDefaultDocumentProperties(newDoc);
00111 bool showGrammarDialog = false;
00112 bool fetchGrammarOnline = false;
00113 if (wizard) {
00114 DocumentProperties* titleAuthorWidget = new DocumentProperties(newDoc, true, ParleyMainWindow::instance());
00115 KDialog* titleAuthorDialog;
00116 titleAuthorDialog = new KDialog(ParleyMainWindow::instance());
00117 titleAuthorDialog->setMainWidget( titleAuthorWidget );
00118 titleAuthorDialog->setCaption(i18nc("@title:window document properties", "Properties for %1", newDoc->url().url()));
00119 connect(titleAuthorDialog, SIGNAL(accepted()), titleAuthorWidget, SLOT(accept()));
00120 if(titleAuthorDialog->exec()) {
00121 showGrammarDialog = titleAuthorWidget->grammarCheckBox->isChecked();
00122 fetchGrammarOnline = titleAuthorWidget->downloadGrammarCheckBox->isChecked();
00123 delete titleAuthorDialog;
00124 } else {
00125 delete titleAuthorDialog;
00126 delete newDoc;
00127 return;
00128 }
00129 }
00130
00131 close();
00132 m_doc = newDoc;
00133 ParleyMainWindow::instance()->editor()->updateDocument();
00134 enableAutoBackup(Prefs::autoBackup());
00135 emit documentChanged(m_doc);
00136
00137 if(fetchGrammarOnline) {
00138 fetchGrammar(0);
00139 fetchGrammar(1);
00140 }
00141 if(showGrammarDialog) {
00142 ParleyMainWindow::instance()->editor()->slotLanguageProperties();
00143 }
00144
00145 ParleyMainWindow::instance()->showEditor();
00146 }
00147
00148 void ParleyDocument::fetchGrammar(int languageIndex)
00149 {
00150 QString locale = m_doc->identifier(languageIndex).locale();
00151
00152 KUrl location(QString("http://edu.kde.org/parley/locale/") + locale + QString(".kvtml"));
00153
00154 KEduVocDocument grammarDoc;
00155 if (grammarDoc.open(location) == KEduVocDocument::NoError) {
00156 m_doc->identifier(languageIndex).setArticle(grammarDoc.identifier(0).article());
00157 m_doc->identifier(languageIndex).setPersonalPronouns(grammarDoc.identifier(0).personalPronouns());
00158
00159 m_doc->identifier(languageIndex).setTenseList(grammarDoc.identifier(0).tenseList());
00160 } else {
00161 kDebug() << "Download of " << location.url() << " failed.";
00162 }
00163 }
00164
00165 void ParleyDocument::slotFileOpen()
00166 {
00167 if (ParleyMainWindow::instance()->queryExit()) {
00168 QCheckBox *practiceCheckBox = new QCheckBox(i18n("Open in practice &mode"));
00169 KFileDialog dialog(QString(), KEduVocDocument::pattern(KEduVocDocument::Reading), ParleyMainWindow::instance(), practiceCheckBox);
00170 dialog.setCaption(i18n("Open Vocabulary Collection"));
00171 if(dialog.exec() && !dialog.selectedUrl().isEmpty()) {
00172 open(dialog.selectedUrl());
00173 if(practiceCheckBox->isChecked()) {
00174 ParleyMainWindow::instance()->startPractice();
00175 } else {
00176 ParleyMainWindow::instance()->showEditor();
00177 }
00178 }
00179 }
00180 }
00181
00182 void ParleyDocument::slotFileOpenRecent(const KUrl& url)
00183 {
00184 if (ParleyMainWindow::instance()->queryExit()) {
00185 open(url);
00186 ParleyMainWindow::instance()->showEditor();
00187 }
00188 }
00189
00190 void ParleyDocument::open(const KUrl & url)
00191 {
00192 if (!url.path().isEmpty()) {
00193 close();
00194 m_doc = new KEduVocDocument(this);
00195 m_doc->setCsvDelimiter(Prefs::separator());
00196 m_doc->open(url);
00197
00198 ParleyMainWindow::instance()->editor()->updateDocument();
00199 ParleyMainWindow::instance()->addRecentFile(url, m_doc->title());
00200
00201 enableAutoBackup(Prefs::autoBackup());
00202 emit documentChanged(m_doc);
00203 }
00204 }
00205
00206 void ParleyDocument::close() {
00207 enableAutoBackup(false);
00208 emit documentChanged(0);
00209 disconnect(m_doc);
00210 delete m_doc;
00211 m_doc = 0;
00212 ParleyMainWindow::instance()->slotUpdateWindowCaption();
00213 }
00214
00215 void ParleyDocument::openGHNS()
00216 {
00217 if (ParleyMainWindow::instance()->queryExit()) {
00218 QString downloadDir = KStandardDirs::locateLocal("data", "kvtml/");
00219 KUrl url = KFileDialog::getOpenUrl(
00220 downloadDir,
00221 KEduVocDocument::pattern(KEduVocDocument::Reading),
00222 ParleyMainWindow::instance(),
00223 i18n("Open Downloaded Vocabulary Collection"));
00224 if (!url.isEmpty()) {
00225 open(url);
00226 ParleyMainWindow::instance()->showEditor();
00227 }
00228 }
00229 }
00230
00231 void ParleyDocument::save()
00232 {
00233 if (m_doc->url().fileName() == i18n("Untitled")) {
00234 saveAs();
00235 return;
00236 }
00237
00238
00239 QFile::remove(m_doc->url().toLocalFile()+'~');
00240 ::rename(QFile::encodeName(m_doc->url().toLocalFile()), QFile::encodeName(m_doc->url().toLocalFile()+'~'));
00241
00242 m_doc->setCsvDelimiter(Prefs::separator());
00243
00244 ParleyMainWindow::instance()->editor()->saveState();
00245
00246 int result = m_doc->saveAs(m_doc->url(), KEduVocDocument::Automatic, QString::fromLatin1("Parley ") + PARLEY_VERSION_STRING);
00247 if ( result != 0 ) {
00248 KMessageBox::error(ParleyMainWindow::instance(),
00249 i18n("Writing file \"%1\" resulted in an error: %2", m_doc->url().url(),
00250 m_doc->errorDescription(result)), i18n("Save File"));
00251 saveAs();
00252 return;
00253 }
00254 ParleyMainWindow::instance()->addRecentFile(m_doc->url(), m_doc->title());
00255 enableAutoBackup(Prefs::autoBackup());
00256 }
00257
00258 void ParleyDocument::saveAs(KUrl url)
00259 {
00260 if (!m_doc) {
00261 return;
00262 }
00263
00264 if (url.isEmpty()) {
00265 url = KFileDialog::getSaveUrl(QString(),
00266 KEduVocDocument::pattern(KEduVocDocument::Writing),
00267 ParleyMainWindow::instance()->parentWidget(),
00268 i18n("Save Vocabulary As"));
00269 }
00270 if (url.isEmpty()) {
00271 return;
00272 }
00273
00274 QFileInfo fileinfo(url.toLocalFile());
00275 if (fileinfo.exists()) {
00276 if(KMessageBox::warningContinueCancel(0,
00277 i18n("<qt>The file<p><b>%1</b></p>already exists. Do you want to overwrite it?</qt>",
00278 url.toLocalFile()),QString(),KStandardGuiItem::overwrite()) == KMessageBox::Cancel) {
00279 return;
00280 }
00281 }
00282
00283 QString msg = i18nc("@info:status saving a file", "Saving %1", url.toLocalFile());
00284
00285 QFile::remove(url.toLocalFile()+'~');
00286 QFile::rename(QFile::encodeName(url.toLocalFile()), QFile::encodeName(QString(url.toLocalFile()+'~')));
00287
00288 m_doc->setCsvDelimiter(Prefs::separator());
00289
00290 if ( !url.fileName().contains('.') ) {
00291 url.setFileName(url.fileName() + QString::fromLatin1(".kvtml"));
00292 }
00293
00294 int result = m_doc->saveAs(url, KEduVocDocument::Automatic, "Parley");
00295 if (result == 0) {
00296 ParleyMainWindow::instance()->addRecentFile(m_doc->url(), m_doc->title());
00297 ParleyMainWindow::instance()->editor()->saveState();
00298 } else {
00299 KMessageBox::error(ParleyMainWindow::instance(), i18n("Writing file \"%1\" resulted in an error: %2",
00300 m_doc->url().url(), m_doc->errorDescription(result)), i18n("Save File"));
00301 }
00302 }
00303
00304 void ParleyDocument::initializeDefaultGrammar(KEduVocDocument *doc)
00305 {
00306 KEduVocWordType *root = doc->wordTypeContainer();
00307 KEduVocWordType *noun = new KEduVocWordType(i18n("Noun"), root);
00308 noun->setWordType(KEduVocWordFlag::Noun);
00309 root->appendChildContainer(noun);
00310
00311 KEduVocWordType *nounChild = new KEduVocWordType(i18n("Masculine"), noun);
00312 nounChild->setWordType(KEduVocWordFlag::Noun | KEduVocWordFlag::Masculine);
00313 noun->appendChildContainer(nounChild);
00314 nounChild = new KEduVocWordType(i18n("Feminine"), noun);
00315 nounChild->setWordType(KEduVocWordFlag::Noun | KEduVocWordFlag::Feminine);
00316 noun->appendChildContainer(nounChild);
00317 nounChild = new KEduVocWordType(i18n("Neuter"), noun);
00318 nounChild->setWordType(KEduVocWordFlag::Noun | KEduVocWordFlag::Neuter);
00319 noun->appendChildContainer(nounChild);
00320
00321 KEduVocWordType *verb = new KEduVocWordType(i18n("Verb"), root);
00322 verb->setWordType(KEduVocWordFlag::Verb);
00323 root->appendChildContainer(verb);
00324
00325 KEduVocWordType *adjective = new KEduVocWordType(i18n("Adjective"), root);
00326 adjective->setWordType(KEduVocWordFlag::Adjective);
00327 root->appendChildContainer(adjective);
00328
00329 KEduVocWordType *adverb = new KEduVocWordType(i18n("Adverb"), root);
00330 adverb->setWordType(KEduVocWordFlag::Adverb);
00331 root->appendChildContainer(adverb);
00332 }
00333
00334 void ParleyDocument::setDefaultDocumentProperties(KEduVocDocument *doc)
00335 {
00336
00337 KUser user;
00338 QString userName = user.property(KUser::FullName).toString();
00339 if ( userName.isEmpty() ) {
00340 userName = user.loginName();
00341 }
00342 doc->setAuthor( userName );
00343 doc->setLicense( i18n("Public Domain") );
00344 doc->setCategory( i18n("Languages") );
00345
00346 QString locale = KGlobal::locale()->language();
00347
00348 doc->appendIdentifier();
00349 doc->appendIdentifier();
00350 doc->identifier(0).setName( KGlobal::locale()->languageCodeToName( locale) );
00351 doc->identifier(0).setLocale( locale );
00352 doc->identifier(1).setName( i18n("A Second Language") );
00353 doc->identifier(1).setLocale( locale );
00354
00355 KEduVocLesson* lesson = new KEduVocLesson(i18n("Lesson 1"), doc->lesson());
00356 doc->lesson()->appendChildContainer(lesson);
00357
00358 KEduVocLeitnerBox *box = doc->leitnerContainer();
00359 box->appendChildContainer(new KEduVocLesson(i18n("Box 7 (best)"), box));
00360 box->appendChildContainer(new KEduVocLesson(i18n("Box 6"), box));
00361 box->appendChildContainer(new KEduVocLesson(i18n("Box 5"), box));
00362 box->appendChildContainer(new KEduVocLesson(i18n("Box 4"), box));
00363 box->appendChildContainer(new KEduVocLesson(i18n("Box 3"), box));
00364 box->appendChildContainer(new KEduVocLesson(i18n("Box 2"), box));
00365 box->appendChildContainer(new KEduVocLesson(i18n("Box 1 (lowest)"), box));
00366
00367
00368 for ( int i = 0; i < 15 ; i++ ) {
00369 lesson->appendEntry(new KEduVocExpression());
00370 }
00371
00372 doc->setModified(false);
00373 }
00374
00375 void ParleyDocument::slotGHNS()
00376 {
00377 QString fileName;
00378 KNS3::DownloadDialog newStuffDialog(ParleyMainWindow::instance());
00379 newStuffDialog.exec();
00380 KNS3::Entry::List entries = newStuffDialog.installedEntries();
00381 int numberInstalled = entries.size();
00382 foreach(const KNS3::Entry& entry, entries) {
00383
00384 foreach(const QString &file, entry.installedFiles()) {
00385 KMimeType::Ptr mimeType = KMimeType::findByPath(file);
00386 kDebug() << "KNS2 file of mime type:" << KMimeType::findByPath(file)->name();
00387 if (mimeType->name() == "application/x-kvtml") {
00388 ParleyMainWindow::instance()->addRecentFile(file, QString());
00389 fileName = file;
00390 }
00391 }
00392 }
00393
00394
00395 Prefs::self()->writeConfig();
00396 ParleyMainWindow::instance()->updateRecentFilesModel();
00397 if (numberInstalled > 1) {
00398 openGHNS();
00399 } else if (numberInstalled == 1) {
00400 open(KUrl(fileName));
00401 ParleyMainWindow::instance()->showEditor();
00402 }
00403 }
00404
00405 void ParleyDocument::uploadFile()
00406 {
00407
00408 KTempDir dir;
00409 KUrl url(dir.name() + m_doc->url().fileName());
00410 kDebug() << "save in " << url.url();
00411 m_doc->saveAs(url, KEduVocDocument::Automatic, "Parley");
00412
00413 KEduVocDocument tempDoc(this);
00414 tempDoc.open(url);
00415
00416 tempDoc.lesson()->resetGrades(-1, KEduVocContainer::Recursive);
00417 tempDoc.saveAs(url, KEduVocDocument::Automatic, "Parley");
00418
00419
00420 KNS3::UploadDialog dialog(ParleyMainWindow::instance());
00421 dialog.setUploadFile(url);
00422 dialog.exec();
00423 }
00424
00425 void ParleyDocument::exportDialog()
00426 {
00427 #ifdef HAVE_LIBXSLT
00428 ExportDialog dialog(this, ParleyMainWindow::instance());
00429 dialog.exec();
00430 #endif
00431 }
00432
00433 void ParleyDocument::slotFileMerge()
00434 {
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457 }
00458
00459 void ParleyDocument::enableAutoBackup(bool enable)
00460 {
00461 if ( !enable ) {
00462 if ( m_backupTimer ) {
00463 m_backupTimer->stop();
00464 }
00465 } else {
00466 if ( !m_backupTimer ) {
00467 m_backupTimer = new QTimer(this);
00468 connect(m_backupTimer, SIGNAL(timeout()), this, SLOT(save()));
00469 }
00470 m_backupTimer->start(Prefs::backupTime() * 60 * 1000);
00471 }
00472 }
00473
00474 #include "parleydocument.moc"