File indexing completed on 2024-03-24 03:54:00
0001 /* 0002 SPDX-FileCopyrightText: 2007-2008 Frederik Gladhorn <frederik.gladhorn@kdemail.net> 0003 SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 0006 #include "parleydocument.h" 0007 0008 #include "editor/editor.h" 0009 #include "parleymainwindow.h" 0010 #include "prefs.h" 0011 0012 #include "dashboard/dashboard.h" 0013 #include "settings/documentproperties.h" 0014 #include "vocabularyview.h" 0015 0016 #include <KEduVocExpression> 0017 #include <KEduVocLeitnerBox> 0018 #include <KEduVocLesson> 0019 #include <KEduVocWordtype> 0020 0021 #include <KEMailSettings> 0022 #include <KMessageBox> 0023 #include <KProcess> 0024 #include <KRecentFilesAction> 0025 #include <QFileDialog> 0026 #include <QMimeDatabase> 0027 #include <QStandardPaths> 0028 #include <QTemporaryDir> 0029 #include <knewstuff_version.h> 0030 0031 #include <QDialog> 0032 #include <QDialogButtonBox> 0033 #include <QTimer> 0034 0035 #ifdef HAVE_LIBXSLT 0036 #include "exportdialog.h" 0037 #include <libxml/parser.h> 0038 #include <libxml/tree.h> 0039 #include <libxslt/transform.h> 0040 #include <libxslt/xslt.h> 0041 #include <libxslt/xsltInternals.h> 0042 #include <libxslt/xsltutils.h> 0043 #endif 0044 0045 #include "settings/languageproperties.h" 0046 0047 namespace DocumentHelper 0048 { 0049 void fetchGrammar(KEduVocDocument *doc, int languageIndex) 0050 { 0051 QString locale = doc->identifier(languageIndex).locale(); 0052 0053 QUrl location(QUrl::fromUserInput(QStringLiteral("https://edu.kde.org/parley/locale/") + locale.split('_').at(0).toLower() + QStringLiteral(".kvtml"))); 0054 0055 KEduVocDocument grammarDoc; 0056 if (grammarDoc.open(location) == KEduVocDocument::NoError) { 0057 doc->identifier(languageIndex).setArticle(grammarDoc.identifier(0).article()); 0058 doc->identifier(languageIndex).setPersonalPronouns(grammarDoc.identifier(0).personalPronouns()); 0059 // @todo m_doc->identifier(index).setDeclension(grammarDoc.identifier(0).declension()); 0060 doc->identifier(languageIndex).setTenseList(grammarDoc.identifier(0).tenseList()); 0061 } else { 0062 qDebug() << "Download of " << location << " failed."; 0063 } 0064 } 0065 } // namespace DocumentHelper 0066 0067 ParleyDocument::ParleyDocument(ParleyMainWindow *parleyMainWindow) 0068 : QObject(parleyMainWindow) 0069 , m_parleyApp(parleyMainWindow) 0070 , m_doc(new KEduVocDocument) 0071 { 0072 } 0073 0074 ParleyDocument::~ParleyDocument() 0075 { 0076 close(); 0077 } 0078 0079 std::shared_ptr<KEduVocDocument> ParleyDocument::document() 0080 { 0081 // If there is no present vocabulary document, create an empty one. 0082 if (!m_doc) { 0083 m_doc.reset(new KEduVocDocument); 0084 } 0085 0086 return m_doc; 0087 } 0088 0089 void ParleyDocument::setTitle(const QString &title) 0090 { 0091 m_doc->setTitle(title); 0092 } 0093 0094 void ParleyDocument::slotFileNew() 0095 { 0096 if (queryClose()) { 0097 newDocument(true); 0098 } 0099 } 0100 0101 void ParleyDocument::newDocument(bool wizard) 0102 { 0103 std::shared_ptr<KEduVocDocument> newDoc(new KEduVocDocument); 0104 0105 initializeDefaultGrammar(newDoc.get()); 0106 setDefaultDocumentProperties(newDoc.get()); 0107 bool showGrammarDialog = false; 0108 bool fetchGrammarOnline = false; 0109 if (wizard) { 0110 DocumentProperties *titleAuthorWidget = new DocumentProperties(newDoc.get(), true, m_parleyApp); 0111 0112 QDialogButtonBox *button_dialog = new QDialogButtonBox; 0113 button_dialog->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); 0114 0115 QVBoxLayout *layout = new QVBoxLayout; 0116 layout->addWidget(titleAuthorWidget); 0117 layout->addWidget(button_dialog); 0118 0119 QDialog *titleAuthorDialog = new QDialog; 0120 titleAuthorDialog->setLayout(layout); 0121 titleAuthorDialog->setWindowTitle(i18nc("@title:window document properties", "Properties for %1", newDoc->url().url())); 0122 0123 connect(titleAuthorDialog, &QDialog::accepted, titleAuthorWidget, &DocumentProperties::accept); 0124 connect(button_dialog, &QDialogButtonBox::accepted, titleAuthorDialog, &QDialog::accept); 0125 connect(button_dialog, &QDialogButtonBox::rejected, titleAuthorDialog, &QDialog::reject); 0126 0127 if (titleAuthorDialog->exec()) { 0128 showGrammarDialog = titleAuthorWidget->grammarCheckBox->isChecked(); 0129 fetchGrammarOnline = titleAuthorWidget->downloadGrammarCheckBox->isChecked(); 0130 delete titleAuthorDialog; 0131 } else { 0132 delete titleAuthorDialog; 0133 return; 0134 } 0135 } 0136 0137 close(); 0138 m_doc = std::move(newDoc); 0139 Q_EMIT documentChanged(m_doc); 0140 enableAutoBackup(Prefs::autoBackup()); 0141 0142 if (fetchGrammarOnline) { 0143 DocumentHelper::fetchGrammar(m_doc.get(), 0); 0144 DocumentHelper::fetchGrammar(m_doc.get(), 1); 0145 } 0146 if (showGrammarDialog) { 0147 languageProperties(); 0148 } 0149 0150 m_parleyApp->showEditor(); 0151 } 0152 0153 void ParleyDocument::slotFileOpen() 0154 { 0155 if (queryClose()) { 0156 ///@todo frameworks check filters are fixed in kvocdoc 0157 ///@todo frameworks check how to add child checkbox to this dialog 0158 QFileDialog dialog(m_parleyApp, i18nc("@title:window", "Open Vocabulary Collection"), QString(), KEduVocDocument::pattern(KEduVocDocument::Reading)); 0159 QCheckBox *practiceCheckBox = new QCheckBox(i18n("Open in practice &mode"), &dialog); 0160 practiceCheckBox->setChecked(m_parleyApp->currentComponent() != ParleyMainWindow::EditorComponent); 0161 dialog.setFileMode(QFileDialog::ExistingFile); 0162 if (dialog.exec() && !dialog.selectedFiles().isEmpty() && open(QUrl::fromLocalFile(dialog.selectedFiles().constFirst()))) { 0163 if (practiceCheckBox->isChecked()) { 0164 m_parleyApp->showPracticeConfiguration(); 0165 } else { 0166 m_parleyApp->showEditor(); 0167 } 0168 } 0169 } 0170 } 0171 0172 void ParleyDocument::slotFileOpenRecent(const QUrl &url) 0173 { 0174 if (queryClose() && open(url)) { 0175 m_parleyApp->showEditor(); ///@todo: start practice directly depending on current component 0176 } 0177 } 0178 0179 bool ParleyDocument::open(const QUrl &url) 0180 { 0181 if (url.path().isEmpty()) { 0182 return false; 0183 } 0184 0185 close(); 0186 0187 m_doc.reset(new KEduVocDocument); 0188 Q_EMIT documentChanged(m_doc); 0189 m_doc->setCsvDelimiter(Prefs::separator()); 0190 0191 bool isSuccess = false, isError = false; 0192 0193 KEduVocDocument::ErrorCode ret = m_doc->open(url, KEduVocDocument::FileDefaultHandling); 0194 switch (ret) { 0195 case KEduVocDocument::NoError: 0196 isSuccess = true; 0197 break; 0198 case KEduVocDocument::FileLocked: { 0199 int exit = 0200 KMessageBox::warningTwoActions(m_parleyApp, 0201 i18n("The vocabulary collection is locked by another process. You can open the file if you take over the lock, " 0202 "but you will lose any changes from the other process.\n\nDo you want to take over the lock?\n"), 0203 i18n("Take Over Lock"), 0204 KStandardGuiItem::open(), 0205 KStandardGuiItem::cancel()); 0206 if (exit == KMessageBox::PrimaryAction) { // attempt to steal lock 0207 0208 ret = m_doc->open(url, KEduVocDocument::FileIgnoreLock); 0209 if (ret == KEduVocDocument::NoError) { 0210 qDebug() << "Lock stolen"; 0211 isSuccess = true; 0212 } else { 0213 isError = true; 0214 } 0215 } else { // Don't Steal continue work without saving !!! 0216 } 0217 0218 break; 0219 } 0220 default: 0221 isError = true; 0222 } 0223 0224 if (isSuccess) { 0225 qDebug() << "Open success."; 0226 // m_parleyApp->editor()->updateDocument(); 0227 m_parleyApp->addRecentFile(url, m_doc->title()); 0228 0229 enableAutoBackup(Prefs::autoBackup()); 0230 0231 } else { 0232 if (isError) { 0233 KMessageBox::error(m_parleyApp, 0234 i18n("Opening collection \"%1\" resulted in an error: %2", m_doc->url().url(), m_doc->errorDescription(ret)), 0235 i18nc("@title:window", "Open Collection")); 0236 } 0237 m_doc.reset(); 0238 Q_EMIT documentChanged(m_doc); 0239 } 0240 0241 return isSuccess; 0242 } 0243 0244 void ParleyDocument::close() 0245 { 0246 enableAutoBackup(false); 0247 if (m_doc) { 0248 m_doc.reset(); 0249 Q_EMIT documentChanged(m_doc); 0250 } 0251 } 0252 0253 bool ParleyDocument::queryClose() 0254 { 0255 if (!m_doc || !m_doc->isModified()) { 0256 return true; 0257 } 0258 0259 bool canSave = Prefs::autoSave(); // save without asking 0260 0261 if (!canSave) { 0262 int exit = KMessageBox::warningTwoActionsCancel(m_parleyApp, 0263 i18n("Vocabulary is modified.\n\nSave file before exit?\n"), 0264 QString(), 0265 KStandardGuiItem::save(), 0266 KStandardGuiItem::discard()); 0267 switch (exit) { 0268 case KMessageBox::PrimaryAction: 0269 canSave = true; // save and exit 0270 break; 0271 case KMessageBox::SecondaryAction: 0272 canSave = false; // don't save but exit 0273 break; 0274 case KMessageBox::Continue: 0275 default: 0276 return false; // continue work without saving !!! 0277 } 0278 } 0279 0280 if (canSave) { 0281 save(); // save and exit 0282 } 0283 0284 close(); 0285 return true; 0286 } 0287 0288 void ParleyDocument::openGHNS() 0289 { 0290 if (m_parleyApp->queryClose()) { 0291 QDir downloadDir(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + '/' + "kvtml/"); 0292 0293 downloadDir.mkpath(downloadDir.absolutePath()); 0294 0295 QUrl url = QUrl::fromUserInput(QFileDialog::getOpenFileName(m_parleyApp, 0296 i18nc("@title:window", "Open Downloaded Vocabulary Collection"), 0297 downloadDir.path(), 0298 KEduVocDocument::pattern(KEduVocDocument::Reading))); 0299 0300 if (open(url)) { 0301 m_parleyApp->showPracticeConfiguration(); 0302 } 0303 } 0304 } 0305 0306 void ParleyDocument::save() 0307 { 0308 if (m_doc->url().fileName().isEmpty()) { 0309 saveAs(); 0310 return; 0311 } 0312 0313 // remove previous backup 0314 QFile::remove(m_doc->url().toLocalFile() + '~'); 0315 QFile::copy(QFile::encodeName(m_doc->url().toLocalFile()), QFile::encodeName(m_doc->url().toLocalFile() + '~')); 0316 0317 m_doc->setCsvDelimiter(Prefs::separator()); 0318 0319 Q_EMIT statesNeedSaving(); 0320 0321 QString newgenerator = QLatin1String("Parley ") + PARLEY_VERSION_STRING; 0322 m_doc->setGenerator(newgenerator); 0323 0324 bool isSuccess = false, isError = false; 0325 0326 KEduVocDocument::ErrorCode ret = m_doc->saveAs(m_doc->url(), KEduVocDocument::Automatic, KEduVocDocument::FileIgnoreLock); 0327 0328 switch (ret) { 0329 case KEduVocDocument::NoError: 0330 isSuccess = true; 0331 break; 0332 case KEduVocDocument::FileLocked: { 0333 int exit = 0334 KMessageBox::warningTwoActions(m_parleyApp, 0335 i18n("File \"%1\" is locked by another process. You can save to the file if you take over the lock, but you will " 0336 "lose any changes from the other process.\n\nDo you want to take over the lock?\n", 0337 m_doc->url().url()), 0338 QString(), 0339 KStandardGuiItem::save(), 0340 KStandardGuiItem::cancel()); 0341 if (exit == KMessageBox::PrimaryAction) { 0342 m_doc->setGenerator(newgenerator); 0343 ret = m_doc->saveAs(m_doc->url(), KEduVocDocument::Automatic, KEduVocDocument::FileIgnoreLock); 0344 0345 if (ret == KEduVocDocument::NoError) { 0346 isSuccess = true; 0347 qDebug() << "Lock stolen"; 0348 } else { 0349 isError = true; 0350 } 0351 } else { 0352 // Intentionally empty else. Try to saveAs another filename 0353 } 0354 break; 0355 } 0356 default: 0357 isError = true; 0358 } 0359 0360 if (isSuccess) { 0361 m_parleyApp->addRecentFile(m_doc->url(), m_doc->title()); 0362 enableAutoBackup(Prefs::autoBackup()); 0363 } else { 0364 if (isError) { 0365 KMessageBox::error(m_parleyApp, 0366 i18n("Writing file \"%1\" resulted in an error: %2", m_doc->url().url(), m_doc->errorDescription(ret)), 0367 i18nc("@title:window", "Save File")); 0368 } 0369 qDebug() << "Save failed trying save as for " << m_doc->url().url(); 0370 saveAs(); 0371 } 0372 } 0373 0374 void ParleyDocument::saveAs(QUrl url) 0375 { 0376 if (!m_doc) { 0377 return; 0378 } 0379 0380 if (url.isEmpty()) { 0381 url = QUrl::fromLocalFile(QFileDialog::getSaveFileName(m_parleyApp->parentWidget(), 0382 i18nc("@title:window", "Save Vocabulary As"), 0383 QString(), 0384 KEduVocDocument::pattern(KEduVocDocument::Writing))); 0385 0386 if (url.isEmpty()) { 0387 return; 0388 } 0389 } 0390 0391 QFileInfo fileinfo(url.toLocalFile()); 0392 if (fileinfo.exists()) { 0393 if (KMessageBox::warningContinueCancel(nullptr, 0394 i18n("<qt>The file<p><b>%1</b></p>already exists. Do you want to overwrite it?</qt>", url.toLocalFile()), 0395 QString(), 0396 KStandardGuiItem::overwrite()) 0397 == KMessageBox::Cancel) { 0398 return; 0399 } 0400 } 0401 0402 QString msg = i18nc("@info:status saving a file", "Saving %1", url.toLocalFile()); 0403 0404 QFile::remove(url.toLocalFile() + '~'); // remove previous backup 0405 QFile::copy(QFile::encodeName(url.toLocalFile()), QFile::encodeName(QString(url.toLocalFile() + '~'))); 0406 0407 m_doc->setCsvDelimiter(Prefs::separator()); 0408 0409 if (!url.toLocalFile().contains('.')) { 0410 url = QUrl::fromLocalFile(url.toLocalFile() + QLatin1String(".kvtml")); 0411 } 0412 0413 bool isSuccess = false, isError = false; 0414 m_doc->setGenerator(QStringLiteral("Parley")); 0415 int ret = m_doc->saveAs(url, KEduVocDocument::Automatic); 0416 switch (ret) { 0417 case KEduVocDocument::NoError: 0418 isSuccess = true; 0419 break; 0420 case KEduVocDocument::FileLocked: { 0421 int exit = 0422 KMessageBox::warningTwoActions(m_parleyApp, 0423 i18n("File \"%1\" is locked by another process. You can save to the file if you take over the lock, but you will " 0424 "lose any changes from the other process.\n\nDo you want to take over the lock?\n", 0425 m_doc->url().url()), 0426 QString(), 0427 KStandardGuiItem::save(), 0428 KStandardGuiItem::cancel()); 0429 if (exit == KMessageBox::PrimaryAction) { // attempt lock steal 0430 m_doc->setGenerator(QLatin1String("Parley ") + PARLEY_VERSION_STRING); 0431 ret = m_doc->saveAs(m_doc->url(), KEduVocDocument::Automatic, KEduVocDocument::FileIgnoreLock); 0432 0433 if (ret == KEduVocDocument::NoError) { 0434 isSuccess = true; 0435 qDebug() << "Lock stolen"; 0436 } else { 0437 isError = true; 0438 } 0439 break; 0440 } else { // don't steal the lock 0441 } 0442 0443 break; 0444 } 0445 default: 0446 isError = true; 0447 break; 0448 } 0449 0450 if (isSuccess) { 0451 qDebug() << "SaveAs success."; 0452 m_parleyApp->addRecentFile(m_doc->url(), m_doc->title()); 0453 Q_EMIT statesNeedSaving(); 0454 0455 } else { 0456 qDebug() << "SaveAs failed for " << m_doc->url().url() << " \nwhy " << m_doc->errorDescription(ret); 0457 if (isError) { 0458 KMessageBox::error(m_parleyApp, 0459 i18n("Writing file \"%1\" resulted in an error: %2", m_doc->url().url(), m_doc->errorDescription(ret)), 0460 i18nc("@title:window", "Save File")); 0461 } 0462 } 0463 } 0464 0465 void ParleyDocument::initializeDefaultGrammar(KEduVocDocument *doc) 0466 { 0467 KEduVocWordType *root = doc->wordTypeContainer(); 0468 KEduVocWordType *noun = new KEduVocWordType(i18n("Noun"), root); 0469 noun->setWordType(KEduVocWordFlag::Noun); 0470 root->appendChildContainer(noun); 0471 0472 KEduVocWordType *nounChild = new KEduVocWordType(i18n("Masculine"), noun); 0473 nounChild->setWordType(KEduVocWordFlag::Noun | KEduVocWordFlag::Masculine); 0474 noun->appendChildContainer(nounChild); 0475 nounChild = new KEduVocWordType(i18n("Feminine"), noun); 0476 nounChild->setWordType(KEduVocWordFlag::Noun | KEduVocWordFlag::Feminine); 0477 noun->appendChildContainer(nounChild); 0478 nounChild = new KEduVocWordType(i18n("Neuter"), noun); 0479 nounChild->setWordType(KEduVocWordFlag::Noun | KEduVocWordFlag::Neuter); 0480 noun->appendChildContainer(nounChild); 0481 0482 KEduVocWordType *verb = new KEduVocWordType(i18n("Verb"), root); 0483 verb->setWordType(KEduVocWordFlag::Verb); 0484 root->appendChildContainer(verb); 0485 0486 KEduVocWordType *adjective = new KEduVocWordType(i18n("Adjective"), root); 0487 adjective->setWordType(KEduVocWordFlag::Adjective); 0488 root->appendChildContainer(adjective); 0489 0490 KEduVocWordType *adverb = new KEduVocWordType(i18n("Adverb"), root); 0491 adverb->setWordType(KEduVocWordFlag::Adverb); 0492 root->appendChildContainer(adverb); 0493 0494 KEduVocWordType *conjunction = new KEduVocWordType(i18n("Conjunction"), root); 0495 conjunction->setWordType(KEduVocWordFlag::Conjunction); 0496 root->appendChildContainer(conjunction); 0497 } 0498 0499 void ParleyDocument::setDefaultDocumentProperties(KEduVocDocument *doc) 0500 { 0501 KEMailSettings emailSettings; 0502 emailSettings.setProfile(emailSettings.defaultProfileName()); 0503 doc->setAuthor(emailSettings.getSetting(KEMailSettings::RealName)); 0504 doc->setAuthorContact(emailSettings.getSetting(KEMailSettings::EmailAddress)); 0505 0506 doc->setLicense(i18n("Public Domain")); 0507 doc->setCategory(i18n("Languages")); 0508 0509 QString locale = QLocale().name(); 0510 0511 doc->appendIdentifier(); 0512 doc->appendIdentifier(); 0513 doc->identifier(0).setName(QLocale(locale).nativeLanguageName()); 0514 doc->identifier(0).setLocale(locale); 0515 doc->identifier(1).setName(i18n("A Second Language")); 0516 doc->identifier(1).setLocale(locale); 0517 0518 KEduVocLesson *lesson = new KEduVocLesson(i18n("Lesson 1"), doc->lesson()); 0519 doc->lesson()->appendChildContainer(lesson); 0520 0521 // add some entries 0522 for (int i = 0; i < 15; i++) { 0523 lesson->appendEntry(new KEduVocExpression()); 0524 } 0525 0526 doc->setModified(false); 0527 } 0528 0529 void ParleyDocument::slotGHNS(const QList<KNSCore::Entry> &entries) 0530 { 0531 QMimeDatabase db; 0532 QString fileName; 0533 int numberInstalled = 0; 0534 for (const auto &entry : entries) { 0535 if (entry.status() != KNSCore::Entry::Installed) { 0536 continue; 0537 } 0538 ++numberInstalled; 0539 // check mime type and if kvtml, open it 0540 const QStringList installedFiles = entry.installedFiles(); 0541 for (const QString &file : installedFiles) { 0542 QMimeType mimeType = db.mimeTypeForFile(file); 0543 qDebug() << "KNS2 file of mime type:" << db.mimeTypeForFile(file).name(); 0544 if (mimeType.inherits(QStringLiteral("application/x-kvtml"))) { 0545 ParleyMainWindow::instance()->addRecentFile(QUrl::fromLocalFile(file), QString()); ///@todo: title! 0546 fileName = file; 0547 } 0548 } 0549 } 0550 0551 // to enable the display in the welcome screen 0552 Prefs::self()->save(); 0553 m_parleyApp->updateRecentFilesModel(); 0554 if (numberInstalled > 1) { 0555 openGHNS(); 0556 } else if (numberInstalled == 1) { 0557 if (open(QUrl::fromLocalFile(fileName))) 0558 m_parleyApp->showPracticeConfiguration(); 0559 else 0560 KMessageBox::error(m_parleyApp, i18n("Could not open vocabulary collection \"%1\"", entries.first().name())); 0561 } 0562 } 0563 0564 void ParleyDocument::documentProperties() 0565 { 0566 DocumentProperties *titleAuthorWidget = new DocumentProperties(m_doc.get(), false, m_parleyApp); 0567 0568 QDialogButtonBox *button_dialog = new QDialogButtonBox; 0569 button_dialog->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); 0570 0571 QVBoxLayout *layout = new QVBoxLayout; 0572 layout->addWidget(titleAuthorWidget); 0573 layout->addWidget(button_dialog); 0574 0575 QDialog *titleAuthorDialog = new QDialog; 0576 titleAuthorDialog->setLayout(layout); 0577 titleAuthorDialog->setWindowTitle(i18nc("@title:window document properties", "Properties for %1", m_doc->url().url())); 0578 0579 // the language options are only shown, when this is used to create a new document. 0580 titleAuthorWidget->languageGroupBox->setVisible(false); 0581 0582 connect(titleAuthorDialog, &QDialog::accepted, titleAuthorWidget, &DocumentProperties::accept); 0583 connect(button_dialog, &QDialogButtonBox::accepted, titleAuthorDialog, &QDialog::accept); 0584 connect(button_dialog, &QDialogButtonBox::rejected, titleAuthorDialog, &QDialog::reject); 0585 0586 titleAuthorDialog->exec(); 0587 delete titleAuthorDialog; 0588 Q_EMIT documentChanged(m_doc); 0589 } 0590 0591 void ParleyDocument::languageProperties() 0592 { 0593 LanguageProperties properties(m_doc.get(), m_parleyApp); 0594 if (properties.exec() == QDialog::Accepted) { 0595 Q_EMIT languagesChanged(); 0596 } 0597 } 0598 0599 void ParleyDocument::exportDialog() 0600 { 0601 #ifdef HAVE_LIBXSLT 0602 ExportDialog dialog(this, m_parleyApp); 0603 dialog.exec(); 0604 #endif 0605 } 0606 0607 void ParleyDocument::slotFileMerge() 0608 { 0609 ///@todo as soon as some brave soul descends into the lib and implements merging this should be enabled 0610 // KUrl url = KFileDialog::getOpenUrl(QString(), KEduVocDocument::pattern(KEduVocDocument::Reading), parentWidget(), i18n("Merge Vocabulary File")); 0611 // 0612 // if (!url.isEmpty()) { 0613 // QString msg = i18n("Loading %1", url.path()); 0614 // slotStatusMsg(msg); 0615 // 0616 // KEduVocDocument *new_doc = new KEduVocDocument(this); 0617 // new_doc->setCsvDelimiter(Prefs::separator()); 0618 // new_doc->open(url); 0619 // 0620 // m_doc->merge(new_doc, true); 0621 // 0622 // KEduVocWordFlag::setTenseNames(m_doc->tenseDescriptions()); 0623 // KVTUsage::setUsageNames(m_doc->usageDescriptions()); 0624 // 0625 // delete(new_doc); 0626 // m_recentFilesAction->addUrl(url); 0627 // m_tableModel->reset(); 0628 // m_lessonModel->setDocument(m_doc); 0629 // m_tableView->adjustContent(); 0630 // } 0631 } 0632 0633 void ParleyDocument::enableAutoBackup(bool enable) 0634 { 0635 if (!enable) { 0636 if (m_backupTimer) { 0637 m_backupTimer->stop(); 0638 } 0639 } else { 0640 if (!m_backupTimer) { 0641 m_backupTimer = new QTimer(this); 0642 connect(m_backupTimer, &QTimer::timeout, this, &ParleyDocument::save); 0643 } 0644 m_backupTimer->start(Prefs::backupTime() * 60 * 1000); 0645 } 0646 } 0647 0648 #include "moc_parleydocument.cpp"