diff --git a/org.kde.kwordquiz.appdata.xml b/org.kde.kwordquiz.appdata.xml index 4f9c0c8..bc4b8f0 100644 --- a/org.kde.kwordquiz.appdata.xml +++ b/org.kde.kwordquiz.appdata.xml @@ -1,128 +1,129 @@ org.kde.kwordquiz.desktop CC0-1.0 GPL-2.0+ KWordQuiz KWordQuiz KWordQuiz KWordQuiz KWordQuiz KWordQuiz KWordQuiz KWordQuiz KWordQuiz KWordQuiz KWordQuiz KWordQuiz KWordQuiz KWordQuiz KWordQuiz KWordQuiz KWordQuiz KWordQuiz KWordQuiz KWordQuiz KWordQuiz KWordQuiz KWordQuiz KWordQuiz KWordQuiz KWordQuiz KWordQuiz KWordQuiz KWordQuiz xxKWordQuizxx KWordQuiz 語言_KWordQuiz Flash Card Trainer Učitelj fleš karticama Entrenador per targetes ràpides Entrenador per targetes ràpides Procvičování slovní zásoby s kartičkami Karteikartentrainer Flash Card Trainer Entrenador de tarjetas Sähvikute treening Sanaston harjoittelu kysymyskorteilla Entraînement aux cartes mémoire Adestrador de vocabulario Pelatihan Kartu Flash Apprendimento con carte mnemoniche 플래시 카드 트레이너 Mokymasis iš kortelių Koorten-Lehrprogramm Woorden oefenen Spørsmålskort Ćwiczenie z fiszkami Treinador de Cartões Treinador de cartões Программа для изучения новой лексики Precvičovanie slovnej zásoby s kartičkami Učenje s spominskimi kartami Flash Card Trainer Fiş Çalıştırıcı Тренування словникового запасу xxFlash Card Trainerxx 卡片式训练程序 閃卡訓練師

KWordQuiz is a general purpose flash card program. It can be used for vocabulary learning and many other subjects. It provides an editor and five different flashcard quiz modes. It uses the KVTML file format and contributed files can be downloaded from within the application.

KWordQuiz je program opšte namjene fleš kartica. Može se koristiti za učenje riječi i s mnogim drugim temama. On pruža urednik i pet različitih flashcard kviz režima. Koristi format KVTML datoteke i doprinesni fajlovi mogu se preuzeti u okviru same aplikacije.

El KWordQuiz és un programa de targetes ràpides de propòsit general. Es pot utilitzar per aprendre vocabulari altres temes. Proporciona un editor i cinc modes diferents de targetes ràpides. Utilitza el format de fitxer KVTML i es poden baixar fitxers de col·laboracions a l'aplicació.

El KWordQuiz és un programa de targetes ràpides de propòsit general. Es pot utilitzar per aprendre vocabulari altres temes. Proporciona un editor i cinc modes diferents de targetes ràpides. Utilitza el format de fitxer KVTML i es poden baixar fitxers de col·laboracions a l'aplicació.

KWordQuiz is a general purpose flash card program. It can be used for vocabulary learning and many other subjects. It provides an editor and five different flashcard quiz modes. It uses the KVTML file format and contributed files can be downloaded from within the application.

KWordQuiz es un programa de tarjetas de propósito general. Se puede utilizar para aprender vocabulario y otras muchas tareas. Proporciona un editor y cinco modos de tarjetas diferentes. Utiliza el formato de archivo KVTML y los archivos con los que han contribuido los usuarios se pueden descargar desde la aplicación.

KWordQuiz on üldotstarbeline sähvikute rakendus. Seda saab kasutada sõnavara omandamiseks, aga veel paljuks muuks. Rakendus pakub redaktorit ja viit eri viisi korraldada sähvikute abil viktoriine. Failivorminguks on KVTML, mis lubab otse rakenduses alla laadida teiste kasutajate loodud huvitavaid faile.

KWordQuiz on yleiskäyttöinen kysymyskorttiohjelma. Sitä voi käyttää sanastojen ja monen muun harjoittelemiseen. Siinä on muokkain ja viisi erilaista kyselytapaa. Se käyttää KVTML-tiedostomuotoa ja lahjoitettuja tiedostoja voi ladata suoraan ohjelmasta.

KWordQuiz est un programme générique pour les cartes mémoire. Il peut être utilisé pour apprendre du vocabulaire et plein d'autres choses. Il fournit un éditeur et cinq modes de quiz différents. Il utilise le format de fichier KVTML et des extensions conformes à ce format peuvent être téléchargés à partir de l'application.

KWordQuiz é un programa de fichas de propósito xeral. Pode usarse para adestrar vocabulario e para moitas outras cousas. Fornece un editor e cinco modos distintos de preguntas mediante fichas. Usa o formato de ficheiro KVTML e os ficheiros doados poden descargarse desde o propio aplicativo.

KWordQuiz adalah program kartu flash pada umumnya. Ini dapat digunakan untuk pembelajaran kosa kata dan banyak mata pelajaran lainnya. Ini menyediakan editor dan lima mode kuis flashcard yang berbeda. Ini menggunakan format file KVTML dan file kontribusi dapat diunduh dari dalam aplikasi.

KWordQuiz è un programma di carte mnemoniche. Può essere usato per l'apprendimento di vocaboli e moltre altre materie. Fornisce un editor e cinque diversi tipi di quiz con carte menmoniche. Usa il formato di file KVTML e permette di scaricare file inviati da altri utenti.

KWordQuiz is en allmeen Naslakoortprogramm. Du kannst dat för't Öven vun Wöör, man ok to anner Saken bruken. Dat hett en Editor un fief Affraag-Bedriefoorden. As Dateiformaat warrt dat KVTML-Formaat bruukt un vun Brukers bidragen Dateien laat sik binnen dat Programm daalladen.

KWordQuiz is een draaikaart programma voor algemene doeleinden. Het kan gebruikt worden voor het leren van woordjes en vele andere onderwerpen. Het biedt een editor en vijf verschillende manieren om draaikaarten te gebruiken. Het gebruikt het KVTML bestandsformaat en aanvullende bestanden kunnen gedownload worden vanuit de toepassing.

KWordQuiz jest programem do ćwiczenia na fiszkach ogólnego przeznaczenia. Dostarcza edytor i pięć różnych trybów quizów na fiszkach. Program używa formatu plików KVTML, a pliki stworzone przez innych użytkowników można pobrać z wewnątrz programu.

O KWordQuiz é um programa de cartões de uso geral. Poderá ser usado para a aprendizagem de vocabulário e para muitos outros assuntos. Oferece um editor e cinco modos diferentes de questionários por cartões. Ele usa o formato de ficheiros KVTML e os ficheiros contribuídos poderão ser transferidos a partir da aplicação.

KWordQuiz é um programa de cartões de uso geral. Ele pode ser usado para aprendizagem de vocabulário e muitos outros assuntos. Oferece um editor e cinco modos diferentes de perguntas em forma de cartões. Ele usa o formato de arquivo KVTML e os arquivos disponibilizados por terceiros podem ser baixados a partir do aplicativo.

KWordQuiz — программа для заучивания новых слов по системе Лейтнера, то есть с помощью карточек. Таким же образом в этой программе можно учить не только слова, но и например ответы на вопросы из различных областей знаний. В программу встроен редактор карточек. На ваш выбор есть пять режимов тренировки. Файлы сохраняются в формате KVTML. Готовые файлы, предоставленные другими пользователями KWordQuiz, можно загрузить прямо из программы.

KWordQuiz je všeobecný kartový program. Dá sa použiť na učenie slovnej zásoby a na mnoho iných účelov. Obsahuje editor a 5 rôznych režimov kvízov s kartami. Používa formát súborov KVTML a súbory sa dajú stiahnuť priamo z aplikácie.

KWordQuiz je splošen program za učenje s spominskimi kartami. Uporabite ga lahko za učenje besedišča in drugih zadev. Ponuja urejevalnik in pet različnih načinov kviza s spominskimi kartami. Uporabniško prispevane datoteke KVTML, ki jih uporablja, lahko prejmete znotraj programa.

Kwordquiz är ett generellt program för snabbkort. Det kan användas för inlärning av ordförråd och många andra ämnen. Det tillhandahåller en editor och fem olika frågemetoder för snabbkort. Det använder filformatet KVTML, och bidragna filer kan laddas ner inne i programmet.

KWordQuiz genel amaçlı bir fiş çalıştırma programıdır. Kelime öğrenmek veya başka bir çok konu için kullanılabilir. Bir düzenleyici ve beş farklı fiş sınav kipi içerir. KVTML dosya biçimini kullanır ve katkı verilmiş dosyalar uygulama içinden indirilebilir.

KWordQuiz — програма для навчання за допомогою карток загального призначення. Нею можна скористатися для поповнення словникового запасу іноземною мовою або вивчення інших дисциплін. У програмі передбачено редактор та п’ять різних режимів навчання за допомогою карток. Для даних використовується формат файлів KVTML, файли даних, створені іншими користувачами, можна отримати безпосередньо за допомогою програми.

xxKWordQuiz is a general purpose flash card program. It can be used for vocabulary learning and many other subjects. It provides an editor and five different flashcard quiz modes. It uses the KVTML file format and contributed files can be downloaded from within the application.xx

KWordQuiz 是一套閃卡記憶訓練程式。它可以用於字彙學習,還有許多其它的用途。它提供了一個編輯器與五種不同的閃卡模式。它使用 KVTML 檔案格式,並且可以下載其他人所製作的閃卡檔。

https://edu.kde.org/kwordquiz/ https://bugs.kde.org/enter_bug.cgi?format=guided&product=kwordquiz https://docs.kde.org/stable/en/kdeedu/kwordquiz/index.html https://www.kde.org/community/donations/?app=kwordquiz&source=appdata Flashcard quiz in KWordQuiz Qüestionari de fitxes ràpides al KWordQuiz Qüestionari de fitxes ràpides al KWordQuiz Karteikartenquiz in KWordQuiz Flashcard quiz in KWordQuiz Juego de tarjetas de KWordQuiz Questionnaire à cartes sur KWordQuiz Proba de cartas en KWordQuiz Kuis flashcard di KWordQuiz Quiz di carte mnemoniche in KWordQuiz Flashkaart-toets in KWordQuiz Fiszki w KWordQuiz Questionário com cartões no KWordQuiz Modo de perguntas em cartões no KWordQuiz + Kvíz s kartami v KWordQuiz Snabbkortsprov i KWordQuiz Тест за допомогою карток у KWordQuiz xxFlashcard quiz in KWordQuizxx KWordQuiz 中的抽认卡测试 在 KWordQuiz 中測驗閃卡 https://kde.org/images/screenshots/kwordquiz.png KDE kwordquiz
diff --git a/src/kwordquiz.cpp b/src/kwordquiz.cpp index 4c1dcde..7af6bfe 100644 --- a/src/kwordquiz.cpp +++ b/src/kwordquiz.cpp @@ -1,1546 +1,1548 @@ /*************************************************************************** kwordquiz.cpp ------------------- begin : Wed Jul 24 20:12:30 PDT 2002 copyright : (C) 2002-2010 Peter Hedlund ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "kwordquiz.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "filterproxysearchline.h" #include "keduvocdocument.h" #include "keduvoclesson.h" #include "keduvocexpression.h" #include "kwqtablemodel.h" #include "kwqsortfiltermodel.h" #include "kwqtableview.h" #include "kwqcommands.h" #include "dlglanguage.h" #include "kwordquizprefs.h" #include "qaview.h" #include "flashview.h" #include "multipleview.h" #include "wqprintdialogpage.h" #include "prefs.h" #include "kwordquiz_version.h" KWordQuizApp::KWordQuizApp(QWidget*):KXmlGuiWindow(0) { m_quiz = 0; m_prefDialog = 0; initStatusBar(); initActions(); initDocument(); initModel(); readOptions(); initView(); m_dirWatch = KDirWatch::self(); slotModeActionGroupTriggered(m_modeActionGroup->actions().at(Prefs::mode() - 1)); editMarkBlank->setEnabled(Prefs::enableBlanks()); editUnmarkBlank->setEnabled(Prefs::enableBlanks()); if (Prefs::firstRun()) { fileOpenRecent->addUrl(QUrl::fromLocalFile(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kwordquiz/examples/example.kvtml")))); fileOpenRecent->addUrl(QUrl::fromLocalFile(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kwordquiz/examples/french_verbs.kvtml")))); fileOpenRecent->addUrl(QUrl::fromLocalFile(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kwordquiz/examples/fill_in_the_blank.kvtml")))); fileOpenRecent->addUrl(QUrl::fromLocalFile(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kwordquiz/examples/us_states_and_capitals.kvtml")))); Prefs::setFirstRun(false); } } KWordQuizApp::~KWordQuizApp() { + disconnect(m_undoStack, &QUndoStack::undoTextChanged, this, &KWordQuizApp::slotUndoTextChanged); + disconnect(m_undoStack, &QUndoStack::redoTextChanged, this, &KWordQuizApp::slotRedoTextChanged); } void KWordQuizApp::initActions() { QAction* configToolbar; QAction* configNotifications; QAction* configApp; QAction * a; fileNew = KStandardAction::openNew(this, SLOT(slotFileNew()), actionCollection()); fileNew->setWhatsThis(i18n("Creates a new blank vocabulary document")); fileNew->setToolTip(fileNew->whatsThis()); fileNew->setStatusTip(fileNew->whatsThis()); fileOpen = KStandardAction::open(this, SLOT(slotFileOpen()), actionCollection()); fileOpen->setWhatsThis(i18n("Opens an existing vocabulary document")); fileOpen->setToolTip(fileOpen->whatsThis()); fileOpen->setStatusTip(fileOpen->whatsThis()); fileOpenRecent = KStandardAction::openRecent(this, SLOT(slotFileOpenRecent(QUrl)), actionCollection()); fileGHNS = KNS3::standardAction(i18n("Download New Vocabularies..."), this, SLOT(slotFileGHNS()), actionCollection(), "file_ghns"); actionCollection()->setDefaultShortcut(fileGHNS, QKeySequence(Qt::CTRL + Qt::Key_G)); fileGHNS->setWhatsThis(i18n("Downloads new vocabularies")); fileGHNS->setToolTip(fileGHNS->whatsThis()); fileGHNS->setStatusTip(fileGHNS->whatsThis()); fileSave = KStandardAction::save(this, SLOT(slotFileSave()), actionCollection()); fileSave->setWhatsThis(i18n("Saves the active vocabulary document")); fileSave->setToolTip(fileSave->whatsThis()); fileSave->setStatusTip(fileSave->whatsThis()); fileSaveAs = KStandardAction::saveAs(this, SLOT(slotFileSaveAs()), actionCollection()); fileSaveAs->setWhatsThis(i18n("Saves the active vocabulary document with a different name")); fileSaveAs->setToolTip(fileSaveAs->whatsThis()); fileSaveAs->setStatusTip(fileSaveAs->whatsThis()); fileClose = KStandardAction::close(this, SLOT(slotFileClose()), actionCollection()); fileClose->setWhatsThis(i18n("Closes the active vocabulary document")); fileClose->setStatusTip(fileClose->whatsThis()); filePrint = KStandardAction::print(this, SLOT(slotFilePrint()), actionCollection()); filePrint->setWhatsThis(i18n("Prints the active vocabulary document")); filePrint->setToolTip(filePrint->whatsThis()); filePrint->setStatusTip(filePrint->whatsThis()); filePrintPreview = KStandardAction::printPreview(this, SLOT(slotFilePrintPreview()), actionCollection()); filePrintPreview->setWhatsThis(i18n("Shows a preview of the active vocabulary document")); filePrintPreview->setToolTip(filePrintPreview->whatsThis()); filePrintPreview->setStatusTip(filePrintPreview->whatsThis()); fileQuit = KStandardAction::quit(this, SLOT(slotFileQuit()), actionCollection()); fileQuit->setWhatsThis(i18n("Quits KWordQuiz")); fileQuit->setToolTip(fileQuit->whatsThis()); fileQuit->setStatusTip(fileQuit->whatsThis()); m_undoStack = new QUndoStack(this); editUndo = KUndoActions::createUndoAction(m_undoStack, actionCollection()); editRedo = KUndoActions::createRedoAction(m_undoStack, actionCollection()); connect(m_undoStack, &QUndoStack::cleanChanged, this, &KWordQuizApp::slotCleanChanged); connect(m_undoStack, &QUndoStack::undoTextChanged, this, &KWordQuizApp::slotUndoTextChanged); connect(m_undoStack, &QUndoStack::redoTextChanged, this, &KWordQuizApp::slotRedoTextChanged); editCut = KStandardAction::cut(this, SLOT(slotEditCut()), actionCollection()); editCut->setWhatsThis(i18n("Cuts the text from the selected cells and places it on the clipboard")); editCut->setToolTip(editCut->whatsThis()); editCut->setStatusTip(editCut->whatsThis()); editCopy = KStandardAction::copy(this, SLOT(slotEditCopy()), actionCollection()); editCopy->setWhatsThis(i18n("Copies the text from the selected cells and places it on the clipboard")); editCopy->setToolTip(editCopy->whatsThis()); editCopy->setStatusTip(editCopy->whatsThis()); editPaste = KStandardAction::paste(this, SLOT(slotEditPaste()), actionCollection()); editPaste->setWhatsThis(i18n("Pastes previously cut or copied text from the clipboard into the selected cells")); editPaste->setToolTip(editPaste->whatsThis()); editPaste->setStatusTip(editPaste->whatsThis()); editClear = KStandardAction::clear(this, SLOT(slotEditClear()), actionCollection()); actionCollection()->setDefaultShortcut(editClear, Qt::Key_Delete); editClear->setWhatsThis(i18n("Clears the content of the selected cells")); editClear->setToolTip(editClear->whatsThis()); editClear->setStatusTip(editClear->whatsThis()); editInsert = actionCollection()->addAction(QStringLiteral("edit_insert")); editInsert->setIcon(QIcon::fromTheme(QStringLiteral("insert-table-row"))); editInsert->setText(i18n("&Insert Row")); actionCollection()->setDefaultShortcut(editInsert, QKeySequence(Qt::CTRL + Qt::Key_I)); editInsert->setWhatsThis(i18n("Inserts a new row above the current row")); editInsert->setToolTip(editInsert->whatsThis()); editInsert->setStatusTip(editInsert->whatsThis()); connect(editInsert, &QAction::triggered, this, &KWordQuizApp::slotEditInsert); editDelete = actionCollection()->addAction(QStringLiteral("edit_delete")); editDelete->setIcon(QIcon::fromTheme(QStringLiteral("delete-table-row"))); editDelete->setText(i18n("&Delete Row")); actionCollection()->setDefaultShortcut(editDelete, QKeySequence(Qt::CTRL + Qt::Key_K)); editDelete->setWhatsThis(i18n("Deletes the selected row(s)")); editDelete->setToolTip(editDelete->whatsThis()); editDelete->setStatusTip(editDelete->whatsThis()); connect(editDelete, &QAction::triggered, this, &KWordQuizApp::slotEditDelete); editMarkBlank = actionCollection()->addAction(QStringLiteral("edit_mark_blank")); editMarkBlank->setIcon(QIcon::fromTheme(QStringLiteral("markasblank"))); editMarkBlank->setText(i18n("&Mark as Blank")); actionCollection()->setDefaultShortcut(editMarkBlank, QKeySequence(Qt::CTRL + Qt::Key_M)); editMarkBlank->setWhatsThis(i18n("Marks the current or selected word as a blank for Fill-in-the-blank")); editMarkBlank->setToolTip(editMarkBlank->whatsThis()); editMarkBlank->setStatusTip(editMarkBlank->whatsThis()); connect(editMarkBlank, &QAction::triggered, this, &KWordQuizApp::slotEditMarkBlank); editUnmarkBlank = actionCollection()->addAction(QStringLiteral("edit_unmark_blank")); editUnmarkBlank->setIcon(QIcon::fromTheme(QStringLiteral("unmarkasblank"))); editUnmarkBlank->setText(i18n("&Unmark Blanks")); editUnmarkBlank->setWhatsThis(i18n("Removes blanks from the current or selected word")); editUnmarkBlank->setToolTip(editUnmarkBlank->whatsThis()); editUnmarkBlank->setStatusTip(editUnmarkBlank->whatsThis()); connect(editUnmarkBlank, &QAction::triggered, this, &KWordQuizApp::slotEditUnmarkBlank); vocabLanguages = actionCollection()->addAction(QStringLiteral("vocab_languages")); vocabLanguages->setIcon(QIcon::fromTheme(QStringLiteral("languages"))); vocabLanguages->setText(i18n("&Column Settings...")); actionCollection()->setDefaultShortcut(vocabLanguages, QKeySequence(Qt::CTRL + Qt::Key_L)); vocabLanguages->setWhatsThis(i18n("Defines the column settings for the active vocabulary")); vocabLanguages->setToolTip(vocabLanguages->whatsThis()); vocabLanguages->setStatusTip(vocabLanguages->whatsThis()); connect(vocabLanguages, &QAction::triggered, this, &KWordQuizApp::slotVocabLanguages); vocabFont = actionCollection()->addAction(QStringLiteral("vocab_font")); vocabFont->setIcon(QIcon::fromTheme(QStringLiteral("preferences-desktop-font"))); vocabFont->setText(i18n("&Font...")); vocabFont->setWhatsThis(i18n("Defines the font used by the editor")); vocabFont->setToolTip(vocabFont->whatsThis()); vocabFont->setStatusTip(vocabFont->whatsThis()); connect(vocabFont, &QAction::triggered, this, &KWordQuizApp::slotVocabFont); a = actionCollection()->addAction(QStringLiteral("vocab_image")); a->setIcon(QIcon::fromTheme(QStringLiteral("image-x-generic"))); a->setText(i18n("Link &Image...")); a->setWhatsThis(i18n("Links an image with the current entry")); a->setToolTip(a->whatsThis()); a->setStatusTip(a->whatsThis()); connect(a, &QAction::triggered, this, &KWordQuizApp::slotVocabImage); a = actionCollection()->addAction(QStringLiteral("vocab_sound")); a->setIcon(QIcon::fromTheme(QStringLiteral("audio-x-generic"))); a->setText(i18n("Link &Sound...")); a->setWhatsThis(i18n("Links a sound with the current entry")); a->setToolTip(a->whatsThis()); a->setStatusTip(a->whatsThis()); connect(a, &QAction::triggered, this, &KWordQuizApp::slotVocabSound); vocabAdjustRows = actionCollection()->addAction(QStringLiteral("vocab_adjust_rows")); //vocabAdjustRows->setIcon(QIcon::fromTheme()); vocabAdjustRows->setText(i18n("&Adjust Row Heights")); vocabAdjustRows->setWhatsThis(i18n("Automatically adjusts the height of selected rows")); vocabAdjustRows->setToolTip(vocabAdjustRows->whatsThis()); vocabAdjustRows->setStatusTip(vocabAdjustRows->whatsThis()); connect(vocabAdjustRows, &QAction::triggered, this, &KWordQuizApp::slotVocabAdjustRows); vocabShuffle = actionCollection()->addAction(QStringLiteral("vocab_shuffle")); vocabShuffle->setIcon(QIcon::fromTheme(QStringLiteral("shuffle"))); vocabShuffle->setText(i18n("Sh&uffle")); vocabShuffle->setWhatsThis(i18n("Shuffles the entries of the active vocabulary")); vocabShuffle->setToolTip(vocabShuffle->whatsThis()); vocabShuffle->setStatusTip(vocabShuffle->whatsThis()); connect(vocabShuffle, &QAction::triggered, this, &KWordQuizApp::slotVocabShuffle); vocabLayouts = actionCollection()->addAction(QStringLiteral("vocab_layouts")); vocabLayouts->setText(i18n("&Keyboard Layout")); vocabLayouts->setWhatsThis(i18n("Shows available keyboard layouts")); vocabLayouts->setToolTip(vocabLayouts->whatsThis()); vocabLayouts->setStatusTip(vocabLayouts->whatsThis()); QMenu *m = new QMenu(this); vocabLayouts->setMenu(m); m_layoutActionGroup = new QActionGroup(this); connect(m_layoutActionGroup, &QActionGroup::triggered, this, &KWordQuizApp::slotLayoutActionGroupTriggered); m_modeActionMenu = actionCollection()->add(QStringLiteral("mode_0")); m_modeActionMenu->setIcon(QIcon::fromTheme(QStringLiteral("mode1"))); m_modeActionMenu->setText(i18n("Change Mode")); m_modeActionMenu->setIconText(i18n("Mode")); m_modeActionMenu->setWhatsThis(i18n("Changes the mode used in quiz sessions")); m_modeActionMenu->setToolTip(m_modeActionMenu->whatsThis()); m_modeActionMenu->setStatusTip(m_modeActionMenu->whatsThis()); connect(m_modeActionMenu, &QAction::triggered, this, &KWordQuizApp::slotModeChange); m_modeActionGroup = new QActionGroup(this); connect(m_modeActionGroup, &QActionGroup::triggered, this, &KWordQuizApp::slotModeActionGroupTriggered); for (int i = 1; i <=5; ++i) { a = actionCollection()->addAction(QStringLiteral("mode_%1").arg(QString::number(i))); a->setData(i); a->setCheckable(true); a->setIcon(QIcon::fromTheme(QStringLiteral("mode%1").arg(QString::number(i)))); a->setWhatsThis(i18n("Selects this mode")); a->setToolTip(a->whatsThis()); a->setStatusTip(a->whatsThis()); m_modeActionMenu->addAction(a); m_modeActionGroup->addAction(a); } quizEditor = actionCollection()->addAction(QStringLiteral("quiz_editor")); quizEditor->setIcon(QIcon::fromTheme(QStringLiteral("editor"))); quizEditor->setText(i18nc("@item:inlistbox activate vocabulary editor", "&Editor")); actionCollection()->setDefaultShortcut(quizEditor, QKeySequence(Qt::Key_F6)); quizEditor->setWhatsThis(i18n("Activates the vocabulary editor")); quizEditor->setToolTip(quizEditor->whatsThis()); quizEditor->setStatusTip(quizEditor->whatsThis()); connect(quizEditor, &QAction::triggered, this, &KWordQuizApp::slotQuizEditor); quizFlash = actionCollection()->addAction(QStringLiteral("quiz_flash")); quizFlash->setIcon(QIcon::fromTheme(QStringLiteral("flash"))); quizFlash->setText(i18n("&Flashcard")); actionCollection()->setDefaultShortcut(quizFlash, QKeySequence(Qt::Key_F7)); quizFlash->setWhatsThis(i18n("Starts a flashcard session using the active vocabulary")); quizFlash->setToolTip(quizFlash->whatsThis()); quizFlash->setStatusTip(quizFlash->whatsThis()); connect(quizFlash, &QAction::triggered, this, &KWordQuizApp::slotQuizFlash); quizMultiple = actionCollection()->addAction(QStringLiteral("quiz_multiple")); quizMultiple->setIcon(QIcon::fromTheme(QStringLiteral("multiple"))); quizMultiple->setText(i18n("&Multiple Choice")); actionCollection()->setDefaultShortcut(quizMultiple, QKeySequence(Qt::Key_F8)); quizMultiple->setWhatsThis(i18n("Starts a multiple choice session using the active vocabulary")); quizMultiple->setToolTip(quizMultiple->whatsThis()); quizMultiple->setStatusTip(quizMultiple->whatsThis()); connect(quizMultiple, &QAction::triggered, this, &KWordQuizApp::slotQuizMultiple); quizQA = actionCollection()->addAction(QStringLiteral("quiz_qa")); quizQA->setIcon(QIcon::fromTheme(QStringLiteral("qa"))); quizQA->setText(i18n("&Question and Answer")); quizQA->setIconText(i18n("Q&&A")); actionCollection()->setDefaultShortcut(quizQA, QKeySequence(Qt::Key_F9)); quizQA->setWhatsThis(i18n("Starts a question and answer session using the active vocabulary")); quizQA->setToolTip(quizQA->whatsThis()); quizQA->setStatusTip(quizQA->whatsThis()); connect(quizQA, &QAction::triggered, this, &KWordQuizApp::slotQuizQA); quizCheck = actionCollection()->addAction(QStringLiteral("quiz_check")); quizCheck->setIcon(QIcon::fromTheme(QStringLiteral("answer-correct"))); quizCheck->setText(i18n("&Check")); actionCollection()->setDefaultShortcut(quizCheck, QKeySequence(Qt::Key_Return)); quizCheck->setWhatsThis(i18n("Checks your answer to this question")); quizCheck->setToolTip(quizCheck->whatsThis()); quizCheck->setStatusTip(quizCheck->whatsThis()); quizOpt1 = actionCollection()->addAction(QStringLiteral("quiz_Opt1")); quizOpt1->setText(i18n("Choose Option &1")); actionCollection()->setDefaultShortcut(quizOpt1, QKeySequence(Qt::Key_1)); quizOpt2 = actionCollection()->addAction(QStringLiteral("quiz_Opt2")); quizOpt2->setText(i18n("Choose Option &2")); actionCollection()->setDefaultShortcut(quizOpt2, QKeySequence(Qt::Key_2)); quizOpt3 = actionCollection()->addAction(QStringLiteral("quiz_Opt3")); quizOpt3->setText(i18n("Choose Option &3")); actionCollection()->setDefaultShortcut(quizOpt3, QKeySequence(Qt::Key_3)); flashKnow = actionCollection()->addAction(QStringLiteral("flash_know")); flashKnow->setIcon(QIcon::fromTheme(QStringLiteral("know"))); flashKnow->setText(i18n("I &Know")); actionCollection()->setDefaultShortcut(flashKnow, QKeySequence(Qt::Key_K)); flashKnow->setWhatsThis(i18n("Counts this card as correct and shows the next card")); flashKnow->setToolTip(flashKnow->whatsThis()); flashKnow->setStatusTip(flashKnow->whatsThis()); flashDontKnow = actionCollection()->addAction(QStringLiteral("flash_dont_know")); flashDontKnow->setIcon(QIcon::fromTheme(QStringLiteral("dontknow"))); flashDontKnow->setText(i18n("I &Do Not Know")); actionCollection()->setDefaultShortcut(flashDontKnow, QKeySequence(Qt::Key_D)); flashDontKnow->setWhatsThis(i18n("Counts this card as incorrect and shows the next card")); flashDontKnow->setToolTip(flashDontKnow->whatsThis()); flashDontKnow->setStatusTip(flashDontKnow->whatsThis()); qaHint = actionCollection()->addAction(QStringLiteral("qa_hint")); qaHint->setIcon(QIcon::fromTheme(QStringLiteral("hint"))); qaHint->setText(i18n("&Hint")); actionCollection()->setDefaultShortcut(qaHint, QKeySequence(Qt::CTRL + Qt::Key_H)); qaHint->setWhatsThis(i18n("Gets the next correct letter of the answer")); qaHint->setToolTip(qaHint->whatsThis()); qaHint->setStatusTip(qaHint->whatsThis()); qaMarkLastCorrect = actionCollection()->addAction(QStringLiteral("qa_mark_last_correct")); qaMarkLastCorrect->setIcon(QIcon::fromTheme(QStringLiteral("answer-correct"))); qaMarkLastCorrect->setText(i18n("Mark Last Correct")); actionCollection()->setDefaultShortcut(qaMarkLastCorrect, QKeySequence(Qt::SHIFT + Qt::Key_Return)); qaMarkLastCorrect->setWhatsThis(i18n("Marks last answer as correct")); qaMarkLastCorrect->setToolTip(qaMarkLastCorrect->whatsThis()); qaMarkLastCorrect->setStatusTip(qaMarkLastCorrect->whatsThis()); quizRestart = actionCollection()->addAction(QStringLiteral("quiz_restart")); quizRestart->setIcon(QIcon::fromTheme(QStringLiteral("start-over"))); quizRestart->setText(i18n("&Restart")); actionCollection()->setDefaultShortcut(quizRestart, QKeySequence(Qt::CTRL + Qt::Key_R)); quizRestart->setWhatsThis(i18n("Restarts the quiz session from the beginning")); quizRestart->setToolTip(quizRestart->whatsThis()); quizRestart->setStatusTip(quizRestart->whatsThis()); a = actionCollection()->addAction(QStringLiteral("quiz_audio_play")); a->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-start"))); a->setText(i18n("&Play Audio")); actionCollection()->setDefaultShortcut(a, QKeySequence(Qt::CTRL + Qt::Key_B)); a->setWhatsThis(i18n("Play associated audio")); a->setToolTip(a->whatsThis()); a->setStatusTip(a->whatsThis()); quizRepeatErrors = actionCollection()->addAction(QStringLiteral("quiz_repeat_errors")); quizRepeatErrors->setIcon(QIcon::fromTheme(QStringLiteral("repeat"))); quizRepeatErrors->setText(i18n("Repeat &Errors")); actionCollection()->setDefaultShortcut(quizRepeatErrors, QKeySequence(Qt::CTRL + Qt::Key_E)); quizRepeatErrors->setWhatsThis(i18n("Repeats all incorrectly answered questions")); quizRepeatErrors->setToolTip(quizRepeatErrors->whatsThis()); quizRepeatErrors->setStatusTip(quizRepeatErrors->whatsThis()); quizExportErrors = actionCollection()->addAction(QStringLiteral("quiz_export_errors")); quizExportErrors->setIcon(KStandardGuiItem::saveAs().icon()); quizExportErrors->setText(i18n("Export Errors &As...")); quizExportErrors->setWhatsThis(i18n("Exports all errors as a new vocabulary document")); quizExportErrors->setToolTip(quizExportErrors->whatsThis()); quizExportErrors->setStatusTip(quizExportErrors->whatsThis()); connect(quizExportErrors, &QAction::triggered, this, &KWordQuizApp::slotCreateErrorListDocument); configShowSearchBar = actionCollection()->add(QStringLiteral("config_show_search")); configShowSearchBar->setText(i18n("Show Se&arch")); connect(configShowSearchBar, &QAction::triggered, this, &KWordQuizApp::slotConfigShowSearch); configShowSearchBar->setWhatsThis(i18n("Toggle display of the search bar")); configShowSearchBar->setToolTip(configShowSearchBar->whatsThis()); configShowSearchBar->setStatusTip(configShowSearchBar->whatsThis()); configNotifications = KStandardAction::configureNotifications(this, SLOT(slotConfigureNotifications()), actionCollection()); configNotifications->setWhatsThis(i18n("Configures sound and other notifications for certain events")); configNotifications->setToolTip(configNotifications->whatsThis()); configNotifications->setStatusTip(configNotifications->whatsThis()); configApp = KStandardAction::preferences(this, SLOT(slotConfigure()), actionCollection()); configApp->setWhatsThis(i18n("Specifies preferences for the vocabulary editor and quiz sessions")); configApp->setToolTip(configApp->whatsThis()); configApp->setStatusTip(configApp->whatsThis()); for (int i = 1; i <=9; ++i) { a = actionCollection()->addAction(QStringLiteral("char_%1").arg(QString::number(i))); a->setText(i18n("Special Character %1", i)); actionCollection()->setDefaultShortcut(a, QKeySequence(QStringLiteral("Ctrl+%1").arg(QString::number(i)))); connect(a, &QAction::triggered, this, [this, i] () { slotInsertChar(i); }); } updateSpecialCharIcons(); resize( QSize(650, 450).expandedTo(minimumSizeHint())); setupGUI(ToolBar | Keys | StatusBar | Create); setAutoSaveSettings(); configToolbar = actionCollection()->action(QStringLiteral("options_configure_toolbars")); configToolbar->setWhatsThis(i18n("Toggles display of the toolbars")); configToolbar->setToolTip(configToolbar->whatsThis()); configToolbar->setStatusTip(configToolbar->whatsThis()); } void KWordQuizApp::initStatusBar() { m_statusLabel = new QLabel(statusBar()); statusBar()->insertPermanentWidget(0, m_statusLabel); //statusBar()->setItemFixed(1, 250); } void KWordQuizApp::initDocument() { m_doc = new KEduVocDocument(this); m_doc->setGenerator(QStringLiteral("kwordquiz %1").arg(KWORDQUIZ_VERSION_STRING)); ///@todo New kvtml documents have a locale setting which should contain the language they are written in. /* it would be nice to support that somehow. get hot new stuff for KHangman and KAnagram already uses this. */ m_doc->appendIdentifier(); m_doc->identifier(0).setName(i18n("Column 1")); // m_doc->identifier(0).setLocale("en"); m_doc->appendIdentifier(); m_doc->identifier(1).setName(i18n("Column 2")); // m_doc->identifier(1).setLocale("en"); for (int i=0; i<20; i++) { m_doc->lesson()->appendEntry(new KEduVocExpression()); } } void KWordQuizApp::initModel() { m_tableModel = new KWQTableModel(this); m_tableModel->setDocument(m_doc); m_tableModel->setHeaderData(0, Qt::Horizontal, QSize(250, 25), Qt::SizeHintRole); m_tableModel->setHeaderData(1, Qt::Horizontal, QSize(250, 25), Qt::SizeHintRole); m_sortFilterModel = new KWQSortFilterModel(this); m_sortFilterModel->setTableModel(m_tableModel); } void KWordQuizApp::initView() { m_pageWidget = new KPageWidget(this); m_pageWidget->setFaceType( KPageView::List ); setCentralWidget(m_pageWidget); connect(m_pageWidget, SIGNAL(currentPageChanged(KPageWidgetItem*,KPageWidgetItem*)), this, SLOT(slotCurrentPageChanged(KPageWidgetItem*,KPageWidgetItem*))); QVBoxLayout *editorLayout = new QVBoxLayout(); editorLayout->setContentsMargins(0, 0, 0, 0); m_searchLine = new FilterProxySearchLine(this); m_searchLine->setFocusPolicy(Qt::ClickFocus); m_searchLine->setPlaceholderText(i18n("Enter search terms here")); m_searchLine->setFilterProxyModel(m_sortFilterModel); m_tableView = new KWQTableView(m_undoStack, this); editorLayout->addWidget(m_searchLine); editorLayout->addWidget(m_tableView); m_tableView->setFilterModel(m_sortFilterModel); m_tableView->setColumnWidth(0, qvariant_cast(m_tableModel->headerData(0, Qt::Horizontal, Qt::SizeHintRole)).width()); m_tableView->setColumnWidth(1, qvariant_cast(m_tableModel->headerData(1, Qt::Horizontal, Qt::SizeHintRole)).width()); setWindowTitle(m_doc->url().fileName() + "[*]"); setWindowModified(false); m_tableView->setContextMenuPolicy(Qt::CustomContextMenu); connect(m_tableView, &QWidget::customContextMenuRequested, this, &KWordQuizApp::slotTableContextMenuRequested); connect(m_tableModel, &QAbstractItemModel::modelReset, m_tableView, &KWQTableView::slotModelReset); m_searchLine->setVisible(Prefs::showSearch()); configShowSearchBar->setChecked(Prefs::showSearch()); m_editorView = new QWidget(this); m_flashView = new FlashView(this, actionCollection()); m_multipleView = new MultipleView(this, actionCollection()); m_qaView = new QAView(this, actionCollection()); m_editorPage = m_pageWidget->addPage(m_editorView, i18nc("@item:inlistbox vocabulary editor", "Editor")); m_editorPage->setIcon(QIcon::fromTheme(QStringLiteral("editor"))); m_editorPage->setHeader(QLatin1String("")); m_editorPage->widget()->setLayout(editorLayout); m_flashPage = m_pageWidget->addPage(m_flashView, i18n("Flashcard")); m_flashPage->setIcon(QIcon::fromTheme(QStringLiteral("flash"))); m_flashPage->setHeader(QLatin1String("")); m_multiplePage = m_pageWidget->addPage(m_multipleView, i18n("Multiple Choice")); m_multiplePage->setIcon(QIcon::fromTheme(QStringLiteral("multiple"))); m_multiplePage->setHeader(QLatin1String("")); m_qaPage = m_pageWidget->addPage(m_qaView, i18n("Question & Answer")); m_qaPage->setIcon(QIcon::fromTheme(QStringLiteral("qa"))); m_qaPage->setHeader(QLatin1String("")); m_pageWidget->addAction(quizEditor); m_pageWidget->addAction(quizFlash); m_pageWidget->addAction(quizMultiple); m_pageWidget->addAction(quizQA); const QList listOfChildren = m_pageWidget->children(); foreach (QObject *object, listOfChildren) { if(!object->isWidgetType()) continue; QWidget *childWidget = static_cast(object); if (childWidget->inherits("QListView")) childWidget->setFocusPolicy(Qt::NoFocus); } m_pageWidget->setCurrentPage(m_editorPage); m_tableView->setFocus(); updateActions(); } void KWordQuizApp::openUrl(const QUrl &url) { if(!url.isEmpty()) { if (m_dirWatch->contains(url.path())) { KMainWindow* w; if(!memberList().isEmpty()) { for (int i = 0; i < memberList().size(); ++i) { w = memberList().at(i); KWordQuizApp *a =(KWordQuizApp *) w; if(a->document()->url().path() == url.path()) { if (w->isMinimized()) KWindowSystem::unminimizeWindow(w->winId()); w->activateWindow(); w->raise(); break; } } } } else { if (m_tableModel->isEmpty()){ openDocumentFile(url); } else { KWordQuizApp *new_window= new KWordQuizApp(); new_window->show(); new_window->openDocumentFile(url); } } } } void KWordQuizApp::openDocumentFile(const QUrl &url) { slotStatusMsg(i18n("Opening file...")); if (!url.isEmpty()) { int result = m_doc->open(url); if (result == KEduVocDocument::NoError) { while (m_doc->identifierCount() < 2) { //if we opened a TAB-less CSV, there m_doc->appendIdentifier(); //may be 0 or 1 identifiers, we need at least 2 } //m_tableModel->reset(); m_dirWatch->addFile(url.path()); setWindowTitle(m_doc->url().fileName() + "[*]"); setWindowModified(false); fileOpenRecent->addUrl(url); slotModeActionGroupTriggered(m_modeActionGroup->checkedAction()); m_undoStack->clear(); switch (Prefs::startSession()) { case Prefs::EnumStartSession::Flashcard: slotQuizFlash(); break; case Prefs::EnumStartSession::MultipleChoice: slotQuizMultiple(); break; case Prefs::EnumStartSession::QA: slotQuizQA(); break; default: slotQuizEditor(); break; } } else KMessageBox::error(this, KEduVocDocument::errorDescription(result)); } slotStatusMsg(i18nc("@info:status ready", "Ready")); } KEduVocDocument *KWordQuizApp::document() const { return m_doc; } void KWordQuizApp::saveOptions() { fileOpenRecent->saveEntries(KSharedConfig::openConfig()->group( "Recent Files") ); Prefs::self()->save(); } void KWordQuizApp::readOptions() { fileOpenRecent->loadEntries(KSharedConfig::openConfig()->group( "Recent Files") ); } void KWordQuizApp::saveProperties(KConfigGroup &_cfg) { if(!m_doc->url().fileName().isEmpty() && !m_doc->isModified()) { // saving to tempfile not necessary } else { QUrl url = m_doc->url(); _cfg.writeEntry("filename", url.url()); _cfg.writeEntry("modified", m_doc->isModified()); QString tempname = QTemporaryFile().fileName(); QString tempurl = QUrl::toPercentEncoding(tempname); QUrl _url(tempurl); m_doc->saveAs(_url, KEduVocDocument::Automatic); } } void KWordQuizApp::readProperties(const KConfigGroup &_cfg) { QString filename = _cfg.readEntry("filename", ""); QUrl url(filename); bool modified = _cfg.readEntry("modified", false); if(modified) { QTemporaryFile tmpfile(filename); if (tmpfile.open()) { QUrl _url(QUrl::fromLocalFile(tmpfile.fileName())); m_doc->open(_url); m_doc->setModified(); setWindowTitle(_url.fileName() + "[*]"); setWindowModified(true); } } else { if(!filename.isEmpty()) { m_doc->open(url); setWindowTitle(url.fileName() + "[*]"); setWindowModified(false); } } } bool KWordQuizApp::queryClose() { bool completed=true; if(m_doc->isModified()) { int want_save = KMessageBox::warningYesNoCancel(this, i18n("The current document has been modified.\nDo you want to save it?"), QString(), KStandardGuiItem::save(), KStandardGuiItem::discard()); switch(want_save) { case KMessageBox::Cancel: completed = false; break; case KMessageBox::Yes: if (m_doc->url().fileName().isEmpty()) { completed = saveDocAsFileName(m_doc); } else { completed = (m_doc->saveAs(m_doc->url(), KEduVocDocument::Automatic) == KEduVocDocument::NoError); } break; case KMessageBox::No: completed = true; break; default: completed = false; break; } } if (completed) if (m_dirWatch->contains(m_doc->url().toLocalFile())) m_dirWatch->removeFile(m_doc->url().toLocalFile()); saveOptions(); // Close the current document to get rid of its lock file m_doc->close(); return completed; } void KWordQuizApp::slotFileNew() { slotStatusMsg(i18n("Opening a new document window...")); if (!m_tableModel->isEmpty()){ KWordQuizApp *new_window= new KWordQuizApp(); new_window->show(); } slotStatusMsg(i18nc("@info:status ready", "Ready")); } void KWordQuizApp::slotFileOpen() { slotStatusMsg(i18n("Opening file...")); QCheckBox * cb = new QCheckBox(i18n("&Merge selected files with the current document"), 0); cb -> setChecked(false); cb -> setEnabled(false); QString filter = KEduVocDocument::pattern(KEduVocDocument::Reading); QPointer fd = new QFileDialog(this, i18n("Open Vocabulary Document"), QString(), filter); fd->setFileMode(QFileDialog::ExistingFiles); if (fd->exec() == QDialog::Accepted) { QList l = fd->selectedUrls(); bool append = ((cb->isChecked()) && (l.count() >= 1)); if (append) { QList::iterator it; for(it = l.begin(); it != l.end(); ++it) { KEduVocDocument *new_doc = new KEduVocDocument(this); new_doc->open(*it); m_doc->merge(new_doc, false); delete (new_doc); } //m_tableModel->reset(); } else { QList::iterator it; for(it = l.begin(); it != l.end(); ++it) { openUrl(*it); } } } delete (fd); //deletes cb also slotStatusMsg(i18nc("@info:status ready", "Ready")); } void KWordQuizApp::slotFileOpenRecent(const QUrl &url) { slotStatusMsg(i18n("Opening file...")); fileOpenRecent->setCurrentItem(-1); openUrl(url); slotStatusMsg(i18nc("@info:status ready", "Ready")); } void KWordQuizApp::slotFileGHNS() { QPointer getHotNewStuffDialog = new KNS3::DownloadDialog(QStringLiteral("kwordquiz.knsrc"), this); getHotNewStuffDialog->exec(); KNS3::Entry::List entries = getHotNewStuffDialog->changedEntries(); QMimeDatabase db; // list of changed entries foreach(const KNS3::Entry& entry, entries) { // check mime type and if kvtml, open it foreach(const QString &file, entry.installedFiles()) { QMimeType mimeType = db.mimeTypeForFile(file); if (mimeType.name() == QLatin1String("application/x-kvtml")) { KProcess::startDetached(QStringLiteral("kwordquiz"), QStringList() << file); } } } delete getHotNewStuffDialog; } void KWordQuizApp::slotFileSave() { bool success = false; slotStatusMsg(i18n("Saving file...")); if (m_doc->url().fileName().isEmpty()) { success = saveDocAsFileName(m_doc); } else { int saveStatus = m_doc->saveAs(m_doc->url(), KEduVocDocument::Automatic); if (saveStatus == KEduVocDocument::NoError) success = true; else success = saveDocAsFileName(m_doc); } if (success) m_undoStack->setClean(); //emits cleanChanged() slotStatusMsg(i18nc("@info:status ready", "Ready")); } void KWordQuizApp::slotFileSaveAs() { slotStatusMsg(i18n("Saving file with a new filename...")); bool success = saveDocAsFileName(m_doc); if (success) { m_undoStack->setClean(); //emits cleanChanged() setWindowTitle(m_doc->url().fileName() + "[*]"); //if clean to begin with setWindowModified(m_doc->isModified()); } slotStatusMsg(i18nc("@info:status ready", "Ready")); } bool KWordQuizApp::saveDocAsFileName(KEduVocDocument *document) { bool success = false; int result = KEduVocDocument::Unknown; QString filter = KEduVocDocument::pattern(KEduVocDocument::Writing); filter.append(QStringLiteral(";;")); filter.append(i18n("HTML Document") + QStringLiteral(" (*.html)")); QPointer fd = new QFileDialog(this, i18n("Save Vocabulary Document As"), QString(), filter); fd->setAcceptMode(QFileDialog::AcceptSave); if (fd->exec() == QDialog::Accepted) { QUrl url = fd->selectedUrls().at(0); if (!url.isEmpty()) { QString chosenFilter = fd->selectedNameFilter(); if (!url.fileName().contains('.')) { qDebug() << "Selected name filter is " << chosenFilter; if (chosenFilter == QLatin1String("*.csv")) url = QUrl(url.path().append(".csv")); else if (chosenFilter == QLatin1String("*.kvtml")) url = QUrl(url.path().append(".kvtml")); else if (chosenFilter == QLatin1String("*.html")) url = QUrl(url.path().append(".html")); } if (chosenFilter == QLatin1String("*.html")) { if (m_tableView->doHtmlExport(url)) result = KEduVocDocument::NoError; else result = KEduVocDocument::FileCannotWrite; success = false; //export only, do not consider really saved } else { if (m_dirWatch->contains(document->url().toLocalFile())) m_dirWatch->removeFile(document->url().toLocalFile()); result = document->saveAs(url, KEduVocDocument::Automatic); if (result == KEduVocDocument::NoError) { m_dirWatch->addFile(url.path()); fileOpenRecent->addUrl(url); success = true; } } if (result != KEduVocDocument::NoError) { KMessageBox::error(this, KEduVocDocument::errorDescription(result)); success = false; } } } delete(fd); return success; } void KWordQuizApp::slotFileClose() { slotStatusMsg(i18n("Closing file...")); if (memberList().count() > 1) close(); else if (queryClose()) { delete m_doc; initDocument(); setWindowTitle(m_doc->url().fileName() + "[*]"); setWindowModified(m_doc->isModified()); m_tableModel->setDocument(m_doc); slotQuizEditor(); slotModeActionGroupTriggered(m_modeActionGroup->actions().at(Prefs::mode() - 1)); m_tableView ->selectionModel()->setCurrentIndex(m_sortFilterModel->index(0, 0), QItemSelectionModel::SelectCurrent); m_undoStack->clear(); } slotStatusMsg(i18nc("@info:status ready", "Ready")); } void KWordQuizApp::slotFilePrint() { slotStatusMsg(i18n("Printing...")); m_tableView->doPrint(); slotStatusMsg(i18nc("@info:status ready", "Ready")); } void KWordQuizApp::slotFilePrintPreview() { slotStatusMsg(i18n("Showing Preview...")); m_tableView->doPrintPreview(); slotStatusMsg(i18nc("@info:status ready", "Ready")); } void KWordQuizApp::slotFileQuit() { slotStatusMsg(i18nc("@info:status quitting", "Quitting...")); saveOptions(); // close the first window, the list makes the next one the first again. // This ensures that queryClose() is called on each window to ask for closing KMainWindow* w; if(!memberList().isEmpty()) { for (int i = 0; i < memberList().size(); ++i) { w = memberList().at(i); // only close the window if the closeEvent is accepted. If the user presses Cancel on the saveModified() dialog, // the window and the application stay open. if(!w->close()) break; // Close the corresponding document to remove its lock file static_cast(w)->document()->close(); } } } void KWordQuizApp::slotEditCut() { slotStatusMsg(i18n("Cutting selection...")); m_tableView->doEditCut(); slotStatusMsg(i18nc("@info:status ready", "Ready")); } void KWordQuizApp::slotEditCopy() { slotStatusMsg(i18n("Copying selection to clipboard...")); m_tableView->doEditCopy(); slotStatusMsg(i18nc("@info:status ready", "Ready")); } void KWordQuizApp::slotEditPaste() { slotStatusMsg(i18n("Inserting clipboard contents...")); m_tableView->doEditPaste(); slotStatusMsg(i18nc("@info:status ready", "Ready")); } void KWordQuizApp::slotEditClear() { slotStatusMsg(i18n("Clearing the selected cells...")); m_tableView->doEditClear(); slotStatusMsg(i18nc("@info:status ready", "Ready")); } void KWordQuizApp::slotEditInsert() { slotStatusMsg(i18n("Inserting rows...")); m_tableView->doEditInsert(); slotStatusMsg(i18nc("@info:status ready", "Ready")); } void KWordQuizApp::slotEditDelete() { slotStatusMsg(i18n("Deleting selected rows...")); m_tableView->doEditDelete(); slotStatusMsg(i18nc("@info:status ready", "Ready")); } void KWordQuizApp::slotEditMarkBlank() { slotStatusMsg(i18n("Marking selected text as a blank...")); m_tableView->doEditMarkBlank(); slotStatusMsg(i18nc("@info:status ready", "Ready")); } void KWordQuizApp::slotEditUnmarkBlank() { slotStatusMsg(i18n("Removing blank markings...")); m_tableView->doEditUnmarkBlank(); slotStatusMsg(i18nc("@info:status ready", "Ready")); } void KWordQuizApp::slotVocabLanguages() { slotStatusMsg(i18n("Setting the column titles of the vocabulary...")); DlgLanguage* dlg; dlg = new DlgLanguage(m_tableModel, this); if (dlg->exec() == QDialog::Accepted) { KWQCommandIdentifiers *kwqc = new KWQCommandIdentifiers(m_tableView, dlg->columnData()); m_undoStack->push(kwqc); } slotStatusMsg(i18nc("@info:status ready", "Ready")); } void KWordQuizApp::slotVocabFont() { slotStatusMsg(i18n("Setting the font of the vocabulary...")); QPointer dlg = new QFontDialog(this); dlg->setObjectName(QStringLiteral("dlg_font")); dlg->setFont(Prefs::editorFont()); if (dlg->exec() == QDialog::Accepted) { KWQCommandFont *kwqc = new KWQCommandFont(m_tableView, Prefs::editorFont(), dlg->font()); m_undoStack->push(kwqc); } delete dlg; slotStatusMsg(i18nc("@info:status ready", "Ready")); } void KWordQuizApp::slotVocabImage() { slotStatusMsg(i18n("Linking an image with the current entry...")); m_tableView->doVocabImage(); slotStatusMsg(i18nc("@info:status ready", "Ready")); } void KWordQuizApp::slotVocabSound() { slotStatusMsg(i18n("Linking a sound with the current entry...")); m_tableView->doVocabSound(); slotStatusMsg(i18nc("@info:status ready", "Ready")); } void KWordQuizApp::slotVocabAdjustRows() { slotStatusMsg(i18n("Adjusting row heights...")); foreach(const QModelIndex &index, m_tableView->selectionModel()->selectedIndexes()) m_tableView->adjustRow(index.row()); slotStatusMsg(i18nc("@info:status ready", "Ready")); } void KWordQuizApp::slotVocabShuffle() { slotStatusMsg(i18n("Randomizing the vocabulary...")); m_tableView->doVocabShuffle(); slotStatusMsg(i18nc("@info:status ready", "Ready")); } void KWordQuizApp::slotModeChange() { QString newMode; slotStatusMsg(i18n("Updating mode...")); if (Prefs::mode() < 5) newMode = QStringLiteral("mode_%1").arg(QString::number(Prefs::mode() + 1)); else newMode = QStringLiteral("mode_1"); QAction *a = actionCollection()->action(newMode); a->activate(QAction::Trigger); slotStatusMsg(i18nc("@info:status ready", "Ready")); } void KWordQuizApp::slotQuizEditor() { slotStatusMsg(i18n("Starting editor session...")); m_pageWidget->setCurrentPage(m_editorPage); slotStatusMsg(i18nc("@info:status ready", "Ready")); } void KWordQuizApp::slotQuizFlash() { slotStatusMsg(i18n("Starting flashcard session...")); m_pageWidget->setCurrentPage(m_flashPage); slotStatusMsg(i18nc("@info:status ready", "Ready")); } void KWordQuizApp::slotQuizMultiple() { slotStatusMsg(i18n("Starting multiple choice session...")); m_pageWidget->setCurrentPage(m_multiplePage); slotStatusMsg(i18nc("@info:status ready", "Ready")); } void KWordQuizApp::slotQuizQA() { slotStatusMsg(i18n("Starting question & answer session...")); m_pageWidget->setCurrentPage(m_qaPage); slotStatusMsg(i18nc("@info:status ready", "Ready")); } void KWordQuizApp::slotCurrentPageChanged(KPageWidgetItem *current, KPageWidgetItem *before) { Q_UNUSED(before); delete(m_quiz); m_quiz = 0; disconnect(quizCheck, 0, 0, 0); disconnect(flashKnow, 0, 0, 0); disconnect(flashDontKnow, 0, 0, 0); disconnect(quizRestart, 0, 0, 0); disconnect(actionCollection()->action(QStringLiteral("quiz_audio_play")), 0, 0, 0); disconnect(quizRepeatErrors, 0, 0, 0); disconnect(qaHint, 0, 0, 0); disconnect(qaMarkLastCorrect, 0, 0, 0); if (current == m_editorPage) { m_tableView->setFocus(); m_searchLine->setVisible(Prefs::showSearch()); } else if (current == m_flashPage) { if (Prefs::enableBlanks()) { if (!m_tableModel->checkSyntax()) m_pageWidget->setCurrentPage(m_editorPage); } m_quiz = new KWQQuizModel(this); m_quiz->setFilterModel(m_sortFilterModel); connect(m_quiz, &KWQQuizModel::checkingAnswer, m_tableView, &KWQTableView::slotCheckedAnswer); m_quiz->setQuizType(Prefs::EnumStartSession::Flashcard); m_quiz->setQuizMode(Prefs::mode()); if (m_quiz->init()) { connect(quizCheck, SIGNAL(triggered(bool)), m_flashView, SLOT(slotCheck())); connect(flashKnow, &QAction::triggered, m_flashView, &FlashView::slotKnow); connect(flashDontKnow, &QAction::triggered, m_flashView, &FlashView::slotDontKnow); connect(actionCollection()->action(QStringLiteral("quiz_audio_play")), &QAction::triggered, m_flashView, &KWQQuizView::slotAudioPlay); connect(quizRestart, &QAction::triggered, m_flashView, &KWQQuizView::slotRestart); connect(quizRepeatErrors, &QAction::triggered, m_flashView, &KWQQuizView::slotRepeat); connect(this, SIGNAL(settingsChanged()), m_flashView, SLOT(slotApplySettings())); m_flashView->setQuiz(m_quiz); m_flashView->init(); m_flashView->stackedWidget->setCurrentIndex(0); } else { delete(m_quiz); m_quiz = 0; m_flashView->stackedWidget->setCurrentIndex(1); } } else if (current == m_multiplePage) { if (Prefs::enableBlanks()) { if (!m_tableModel->checkSyntax()) m_pageWidget->setCurrentPage(m_editorPage); } m_quiz = new KWQQuizModel(this); m_quiz->setFilterModel(m_sortFilterModel); connect(m_quiz, &KWQQuizModel::checkingAnswer, m_tableView, &KWQTableView::slotCheckedAnswer); m_quiz->setQuizType(Prefs::EnumStartSession::MultipleChoice); m_quiz->setQuizMode(Prefs::mode()); if (m_quiz->init()) { connect(quizCheck, SIGNAL(triggered(bool)), m_multipleView, SLOT(slotCheck())); connect(quizRestart, &QAction::triggered, m_multipleView, &KWQQuizView::slotRestart); connect(quizRepeatErrors, &QAction::triggered, m_multipleView, &KWQQuizView::slotRepeat); connect(this, SIGNAL(settingsChanged()), m_multipleView, SLOT(slotApplySettings())); m_multipleView->setQuiz(m_quiz); m_multipleView->init(); m_multipleView->stackedWidget->setCurrentIndex(0); } else { delete(m_quiz); m_quiz = 0; m_multipleView->stackedWidget->setCurrentIndex(1); } } else if (current == m_qaPage) { if (Prefs::enableBlanks()) { if (!m_tableModel->checkSyntax()) m_pageWidget->setCurrentPage(m_editorPage); } m_quiz = new KWQQuizModel(this); m_quiz->setFilterModel(m_sortFilterModel); connect(m_quiz, &KWQQuizModel::checkingAnswer, m_tableView, &KWQTableView::slotCheckedAnswer); m_quiz->setQuizType(Prefs::EnumStartSession::QA); m_quiz->setQuizMode(Prefs::mode()); if (m_quiz->init()) { connect(quizCheck, SIGNAL(triggered(bool)), m_qaView, SLOT(slotCheck())); connect(qaHint, &QAction::triggered, m_qaView, &QAView::slotHint); connect(qaMarkLastCorrect, &QAction::triggered, m_qaView, &QAView::slotMarkLastCorrect); connect(quizRestart, &QAction::triggered, m_qaView, &KWQQuizView::slotRestart); connect(actionCollection()->action(QStringLiteral("quiz_audio_play")), &QAction::triggered, m_qaView, &KWQQuizView::slotAudioPlay); connect(quizRepeatErrors, &QAction::triggered, m_qaView, &KWQQuizView::slotRepeat); connect(this, SIGNAL(settingsChanged()), m_qaView, SLOT(slotApplySettings())); m_qaView->setQuiz(m_quiz); m_qaView->init(); m_qaView->stackedWidget->setCurrentIndex(0); } else { delete(m_quiz); m_quiz = 0; m_qaView->stackedWidget->setCurrentIndex(1); } } updateActions(); } /** Configure notifications */ void KWordQuizApp::slotConfigureNotifications( ) { KNotifyConfigWidget::configure(this); } /** Configure kwordquiz */ void KWordQuizApp::slotConfigure() { if (KWordQuizPrefs::showDialog(QStringLiteral("settings"))) return; //KConfigDialog didn't find an instance of this dialog, so lets create it : KWordQuizPrefs* dialog = new KWordQuizPrefs(this, QStringLiteral("settings"), Prefs::self(), actionCollection()); connect(dialog, &KConfigDialog::settingsChanged, this, &KWordQuizApp::slotApplyPreferences); dialog->show(); } void KWordQuizApp::slotApplyPreferences() { editMarkBlank->setEnabled(Prefs::enableBlanks()); editUnmarkBlank->setEnabled(Prefs::enableBlanks()); m_tableView->reset(); updateSpecialCharIcons(); emit settingsChanged(); } void KWordQuizApp::updateSpecialCharIcons() { for (int i = 0; i < 9; i++){ QAction * a = actionCollection()->action(QString("char_" + QString::number(i + 1))); a->setIcon(charIcon(Prefs::specialCharacters()[i])); a->setIconText(i18n("Insert %1", Prefs::specialCharacters()[i])); a->setWhatsThis(i18n("Inserts the character %1", Prefs::specialCharacters()[i])); a->setToolTip(a->whatsThis()); a->setStatusTip(a->whatsThis()); } } QIcon KWordQuizApp::charIcon(const QChar & c) { QRect r(4, 4, 120, 120); ///A font to draw the character with QFont font(QStringLiteral("sans")); font.setPixelSize(100); font.setWeight(QFont::Bold); ///Create the pixmap QPixmap pm(128, 128); pm.fill(Qt::white); QPainter p; p.begin(&pm); p.setFont(font); p.setPen(Qt::blue); p.drawText(r, Qt::AlignCenter, (QString) c); p.end(); ///Create transparency mask QBitmap bm(128, 128); bm.fill(Qt::color0); QPainter b; b.begin(&bm); b.setFont(font); b.setPen(Qt::color1); b.drawText(r, Qt::AlignCenter, (QString) c); b.end(); ///Mask the pixmap pm.setMask(bm); return QIcon(pm); } void KWordQuizApp::slotStatusMsg(const QString &text) { //statusBar()->clearMessage(); statusBar()->showMessage(text); } void KWordQuizApp::slotModeActionGroupTriggered(QAction *act) { if (m_quiz != 0) if (KMessageBox::warningContinueCancel(this, i18n("This will restart your quiz. Do you wish to continue?"), QString(), KStandardGuiItem::cont(), KStandardGuiItem::cancel(), QStringLiteral("askModeQuiz")) != KMessageBox::Continue) { m_modeActionGroup->actions()[0]->setChecked(Prefs::mode() == 1); m_modeActionGroup->actions()[1]->setChecked(Prefs::mode() == 2); m_modeActionGroup->actions()[2]->setChecked(Prefs::mode() == 3); m_modeActionGroup->actions()[3]->setChecked(Prefs::mode() == 4); m_modeActionGroup->actions()[4]->setChecked(Prefs::mode() == 5); return; } act->setChecked(true); QString s1 = m_tableModel->headerData(0, Qt::Horizontal, Qt::DisplayRole).toString(); QString s2 = m_tableModel->headerData(1, Qt::Horizontal, Qt::DisplayRole).toString(); m_modeActionGroup->actions()[0]->setText(i18n("&1 %1 -> %2 In Order", s1, s2)); m_modeActionGroup->actions()[1]->setText(i18n("&2 %1 -> %2 In Order", s2, s1)); m_modeActionGroup->actions()[2]->setText(i18n("&3 %1 -> %2 Randomly", s1, s2)); m_modeActionGroup->actions()[3]->setText(i18n("&4 %1 -> %2 Randomly", s2, s1)); m_modeActionGroup->actions()[4]->setText(i18n("&5 %1 <-> %2 Randomly", s1, s2)); Prefs::setMode(act->data().toInt()); m_modeActionMenu->setIcon(QIcon::fromTheme("mode" + QString::number(Prefs::mode()))); switch (Prefs::mode()){ case 1: m_statusLabel->setText(i18n("%1 -> %2 In Order", s1, s2)); break; case 2: m_statusLabel->setText(i18n("%1 -> %2 In Order", s2, s1)); break; case 3: m_statusLabel->setText(i18n("%1 -> %2 Randomly", s1, s2)); break; case 4: m_statusLabel->setText(i18n("%1 -> %2 Randomly", s2, s1)); break; case 5: m_statusLabel->setText(i18n("%1 <-> %2 Randomly", s1, s2)); break; } if (m_quiz !=0) slotCurrentPageChanged(m_pageWidget->currentPage(), m_pageWidget->currentPage()); } void KWordQuizApp::slotInsertChar( int i ) { if (m_pageWidget->currentPage() == m_qaPage) m_qaView->slotSpecChar(Prefs::specialCharacters()[i - 1]); else if (m_pageWidget->currentPage() == m_editorPage) { m_tableView->slotSpecChar(Prefs::specialCharacters()[i - 1]); } } void KWordQuizApp::updateActions() { bool fEdit = (m_pageWidget->currentPage() == m_editorPage); bool fQuiz = !fEdit && (m_quiz != 0); fileSave->setEnabled(fEdit); fileSaveAs->setEnabled(fEdit); filePrint->setEnabled(fEdit); filePrintPreview->setEnabled(fEdit); editCopy->setEnabled(fEdit); editCut->setEnabled(fEdit); editPaste->setEnabled(fEdit); editClear->setEnabled(fEdit); editInsert->setEnabled(fEdit); editDelete->setEnabled(fEdit); editMarkBlank->setEnabled(fEdit && Prefs::enableBlanks()); editUnmarkBlank->setEnabled(fEdit && Prefs::enableBlanks()); vocabLanguages->setEnabled(fEdit); vocabFont->setEnabled(fEdit); actionCollection()->action(QStringLiteral("vocab_image"))->setEnabled(fEdit); actionCollection()->action(QStringLiteral("vocab_sound"))->setEnabled(fEdit); vocabAdjustRows->setEnabled(fEdit); vocabShuffle->setEnabled(fEdit); quizCheck->setEnabled(fQuiz); quizRestart->setEnabled(fQuiz); quizRepeatErrors->setEnabled(false); quizExportErrors->setEnabled(false); flashKnow->setEnabled((m_pageWidget->currentPage() == m_flashPage) && fQuiz); flashDontKnow->setEnabled((m_pageWidget->currentPage() == m_flashPage) && fQuiz); qaHint->setEnabled((m_pageWidget->currentPage() == m_qaPage) && fQuiz); qaMarkLastCorrect->setVisible((m_pageWidget->currentPage() == m_qaPage) && fQuiz); actionCollection()->action(QStringLiteral("quiz_audio_play"))->setEnabled(false); quizOpt1->setEnabled((m_pageWidget->currentPage() == m_multiplePage) && fQuiz); quizOpt2->setEnabled((m_pageWidget->currentPage() == m_multiplePage) && fQuiz); quizOpt3->setEnabled((m_pageWidget->currentPage() == m_multiplePage) && fQuiz); configShowSearchBar->setEnabled(fEdit); addToolBar(Qt::RightToolBarArea, toolBar(QStringLiteral("quizToolBar"))); toolBar(QStringLiteral("quizToolBar"))->setHidden(fEdit); } void KWordQuizApp::slotConfigShowSearch() { if (m_searchLine) { m_searchLine->setVisible(m_searchLine->isHidden()); Prefs::setShowSearch(m_searchLine->isVisible()); } } void KWordQuizApp::slotCleanChanged(bool clean) { m_doc->setModified(!clean); setWindowTitle(m_doc->url().fileName() + "[*]"); setWindowModified(m_doc->isModified()); } void KWordQuizApp::slotUndoTextChanged(const QString & undoText) { Q_UNUSED(undoText); editUndo->setWhatsThis(editUndo->text()); editUndo->setStatusTip(editUndo->text()); slotModeActionGroupTriggered(m_modeActionGroup->actions().at(Prefs::mode() - 1)); } void KWordQuizApp::slotRedoTextChanged(const QString &redoText) { Q_UNUSED(redoText); editRedo->setWhatsThis(editRedo->text()); editRedo->setStatusTip(editRedo->text()); slotModeActionGroupTriggered(m_modeActionGroup->actions().at(Prefs::mode() - 1)); } void KWordQuizApp::slotCreateErrorListDocument() { if (m_quiz) { KEduVocDocument *errorDoc = new KEduVocDocument(this); errorDoc->appendIdentifier(); errorDoc->identifier(0).setName(m_tableModel->headerData(0, Qt::Horizontal, Qt::DisplayRole).toString()); errorDoc->appendIdentifier(); errorDoc->identifier(1).setName(m_tableModel->headerData(1, Qt::Horizontal, Qt::DisplayRole).toString()); foreach (int item, m_quiz->errorList()) { KEduVocExpression *errorExpr = new KEduVocExpression(); errorDoc->lesson()->appendEntry(errorExpr); errorExpr->setTranslation(0, m_quiz->data(m_quiz->index(item, 0), Qt::DisplayRole).toString()); errorExpr->setTranslation(1, m_quiz->data(m_quiz->index(item, 1), Qt::DisplayRole).toString()); } saveDocAsFileName(errorDoc); if (m_dirWatch->contains(errorDoc->url().toLocalFile())) m_dirWatch->removeFile(errorDoc->url().toLocalFile()); } } void KWordQuizApp::slotTableContextMenuRequested(const QPoint & pos) { QMenu *popup = static_cast(guiFactory()->container(QStringLiteral("editor_popup"),this)); QAction *a; int column = m_tableView->currentIndex().column(); QString currentLayout = QLatin1String(""); currentLayout = m_tableModel->headerData(column, Qt::Horizontal, KWQTableModel::KeyboardLayoutRole).toString(); // keyboard layout // try to talk to kxbk - get a list of keyboard layouts QDBusInterface kxbk(QStringLiteral("org.kde.keyboard"), QStringLiteral("/Layouts"), QStringLiteral("org.kde.KeyboardLayouts")); QDBusReply reply = kxbk.call(QStringLiteral("getLayoutsList")); if (reply.isValid()) { QStringList layouts = reply; //layouts.prepend(QString()); QMenu *m = vocabLayouts->menu(); m->clear(); foreach (const QString &s, layouts) { a = m->addAction(s); a->setData(s); a->setCheckable(true); a->setActionGroup(m_layoutActionGroup); if (s == currentLayout) a->setChecked(true); } } else { qDebug() << "kxkb dbus error"; } popup->exec(m_tableView->viewport()->mapToGlobal(pos)); } void KWordQuizApp::slotLayoutActionGroupTriggered(QAction *act) { int column = m_tableView->currentIndex().column(); m_tableModel->setHeaderData(column, Qt::Horizontal, act->data().toString(), KWQTableModel::KeyboardLayoutRole); }