diff --git a/configwizard.cpp b/configwizard.cpp index c00a8b1..2b2e309 100644 --- a/configwizard.cpp +++ b/configwizard.cpp @@ -1,150 +1,148 @@ /*************************************************************************** * Copyright (C) 2002 by Gunnar Schmi Dt * * * * 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. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "configwizard.h" -#include -#include #include #include #include #include #include #include "texttospeechconfigurationwidget.h" #include "phrasebook/initialphrasebookwidget.h" #include "wordcompletion/wordcompletion.h" #include "wordcompletion/dictionarycreationwizard.h" ConfigWizard::ConfigWizard(QWidget *parent) : QWizard(parent) { setWindowTitle(i18n("Initial Configuration - KMouth")); initCommandPage(); initBookPage(); initCompletion(); connect(this, &QDialog::accepted, this, &ConfigWizard::saveConfig); } ConfigWizard::~ConfigWizard() { } void ConfigWizard::initCommandPage() { KConfigGroup cg(KSharedConfig::openConfig(), QStringLiteral("TTS System")); bool displayCommand = false; if (!cg.hasKey("StdIn")) displayCommand = true; if (!cg.hasKey("Codec")) displayCommand = true; if (displayCommand) { commandWidget = new TextToSpeechConfigurationWidget(this, QStringLiteral("ttsPage")); commandWidget->readOptions(QStringLiteral("TTS System")); commandWidget->setTitle(i18n("Text-to-Speech Configuration")); addPage(commandWidget); commandWidget->setFinalPage(true); } else commandWidget = nullptr; } void ConfigWizard::initBookPage() { QString standardBook = QStandardPaths::locate(QStandardPaths::DataLocation, QStringLiteral("standard.phrasebook")); bool displayBook = (standardBook.isNull() || standardBook.isEmpty()); if (displayBook) { bookWidget = new InitialPhraseBookWidget(this, "pbPage"); bookWidget->setTitle(i18n("Initial Phrase Book")); addPage(bookWidget); bookWidget->setFinalPage(true); if (commandWidget != nullptr) commandWidget->setFinalPage(false); } else bookWidget = nullptr; } void ConfigWizard::initCompletion() { if (!WordCompletion::isConfigured()) { QString dictionaryFile = QStandardPaths::locate(QStandardPaths::DataLocation, QStringLiteral("dictionary.txt")); QFile file(dictionaryFile); if (file.exists()) { // If there is a word completion dictionary but no entry in the // configuration file, we need to add it there. KConfigGroup cg(KSharedConfig::openConfig() , "Dictionary 0"); cg.writeEntry("Filename", "dictionary.txt"); cg.writeEntry("Name", "Default"); cg.writeEntry("Language", QString()); cg.sync(); } } if (KSharedConfig::openConfig()->hasGroup("Completion")) { completionWidget = nullptr; return; } if (!WordCompletion::isConfigured()) { completionWidget = new CompletionWizardWidget(this, "completionPage"); completionWidget->setTitle(i18n("Word Completion")); addPage(completionWidget); completionWidget->setFinalPage(true); if (commandWidget != nullptr) commandWidget->setFinalPage(false); if (bookWidget != nullptr) bookWidget->setFinalPage(false); } else completionWidget = nullptr; } void ConfigWizard::saveConfig() { if (commandWidget != nullptr) { commandWidget->ok(); commandWidget->saveOptions(QStringLiteral("TTS System")); } if (bookWidget != nullptr) bookWidget->createBook(); if (completionWidget != nullptr) completionWidget->ok(); } bool ConfigWizard::requestConfiguration() { if (commandWidget != nullptr || bookWidget != nullptr || completionWidget != nullptr) return (exec() == QDialog::Accepted); else return false; } bool ConfigWizard::configurationNeeded() { return (commandWidget != nullptr || bookWidget != nullptr || completionWidget != nullptr); } void ConfigWizard::help() { KHelpClient::invokeHelp(QStringLiteral("Wizard")); } diff --git a/kmouth.cpp b/kmouth.cpp index c6a34fd..1204bf5 100644 --- a/kmouth.cpp +++ b/kmouth.cpp @@ -1,527 +1,525 @@ /*************************************************************************** * Copyright (C) 2002 by Gunnar Schmi Dt * * * * 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. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ // application specific includes #include "kmouth.h" // include files for Qt -#include #include #include -#include #include #include #include // include files for KDE #include #include #include #include #include #include #include #include #include #include "phraselist.h" #include "phrasebook/phrasebook.h" #include "phrasebook/phrasebookdialog.h" #include "optionsdialog.h" #include "configwizard.h" KMouthApp::KMouthApp(QWidget* , const QString& name): KXmlGuiWindow(nullptr) { setWindowIcon(QIcon::fromTheme(QStringLiteral("kmouth"))); setObjectName(name); isConfigured = false; /////////////////////////////////////////////////////////////////// // call inits to invoke all other construction parts initStatusBar(); initPhraseList(); initActions(); optionsDialog = new OptionsDialog(this); connect(optionsDialog, &OptionsDialog::configurationChanged, this, &KMouthApp::slotConfigurationChanged); connect(optionsDialog, &OptionsDialog::configurationChanged, phraseList, &PhraseList::configureCompletion); phrases = new KActionCollection(static_cast(this)); readOptions(); ConfigWizard *wizard = new ConfigWizard(this); if (wizard->configurationNeeded()) { if (wizard->requestConfiguration()) { isConfigured = true; saveOptions(); wizard->saveConfig(); readOptions(); } else isConfigured = false; } else isConfigured = true; delete wizard; if (isConfigured) { phraseList->configureCompletion(); } /////////////////////////////////////////////////////////////////// // disable actions at startup fileSaveAs->setEnabled(false); filePrint->setEnabled(false); printer = nullptr; } KMouthApp::~KMouthApp() { delete printer; } bool KMouthApp::configured() { return isConfigured; } void KMouthApp::initActions() { // The "File" menu fileOpen = actionCollection()->addAction(QStringLiteral("file_open")); fileOpen->setIcon(QIcon::fromTheme(QStringLiteral("document-open"))); fileOpen->setText(i18n("&Open as History...")); actionCollection()->setDefaultShortcuts(fileOpen, KStandardShortcut::open()); connect(fileOpen, &QAction::triggered, this, &KMouthApp::slotFileOpen); fileOpen->setToolTip(i18n("Opens an existing file as history")); fileOpen->setWhatsThis(i18n("Opens an existing file as history")); fileSaveAs = actionCollection()->addAction(QStringLiteral("file_save_as")); fileSaveAs->setIcon(QIcon::fromTheme(QStringLiteral("document-save"))); fileSaveAs->setText(i18n("Save &History As...")); actionCollection()->setDefaultShortcuts(fileSaveAs, KStandardShortcut::save()); connect(fileSaveAs, &QAction::triggered, this, &KMouthApp::slotFileSaveAs); fileSaveAs->setToolTip(i18n("Saves the actual history as...")); fileSaveAs->setWhatsThis(i18n("Saves the actual history as...")); filePrint = actionCollection()->addAction(QStringLiteral("file_print")); filePrint->setIcon(QIcon::fromTheme(QStringLiteral("document-print"))); filePrint->setText(i18n("&Print History...")); actionCollection()->setDefaultShortcuts(filePrint, KStandardShortcut::print()); connect(filePrint, &QAction::triggered, this, &KMouthApp::slotFilePrint); filePrint->setToolTip(i18n("Prints out the actual history")); filePrint->setWhatsThis(i18n("Prints out the actual history")); fileQuit = KStandardAction::quit(this, SLOT(slotFileQuit()), actionCollection()); fileQuit->setToolTip(i18n("Quits the application")); fileQuit->setWhatsThis(i18n("Quits the application")); // The "Edit" menu editCut = KStandardAction::cut(phraseList, SLOT(cut()), actionCollection()); editCut->setToolTip(i18n("Cuts the selected section and puts it to the clipboard")); editCut->setWhatsThis(i18n("Cuts the selected section and puts it to the clipboard. If there is some text selected in the edit field it is placed it on the clipboard. Otherwise the selected sentences in the history (if any) are placed on the clipboard.")); editCopy = KStandardAction::copy(phraseList, SLOT(copy()), actionCollection()); editCopy->setToolTip(i18n("Copies the selected section to the clipboard")); editCopy->setWhatsThis(i18n("Copies the selected section to the clipboard. If there is some text selected in the edit field it is copied to the clipboard. Otherwise the selected sentences in the history (if any) are copied to the clipboard.")); editPaste = KStandardAction::paste(phraseList, SLOT(paste()), actionCollection()); editPaste->setToolTip(i18n("Pastes the clipboard contents to current position")); editPaste->setWhatsThis(i18n("Pastes the clipboard contents at the current cursor position into the edit field.")); editSpeak = actionCollection()->addAction(QStringLiteral("edit_speak")); editSpeak->setIcon(QIcon::fromTheme(QStringLiteral("text-speak"))); editSpeak->setText(i18nc("Start speaking", "&Speak")); connect(editSpeak, &QAction::triggered, phraseList, &PhraseList::speak); editSpeak->setToolTip(i18n("Speaks the currently active sentence(s)")); editSpeak->setWhatsThis(i18n("Speaks the currently active sentence(s). If there is some text in the edit field it is spoken. Otherwise the selected sentences in the history (if any) are spoken.")); // The "Phrase book" menu phrasebookEdit = actionCollection()->addAction(QStringLiteral("phrasebook_edit")); phrasebookEdit->setText(i18n("&Edit...")); connect(phrasebookEdit, &QAction::triggered, this, &KMouthApp::slotEditPhrasebook); // The "Options" menu viewMenuBar = KStandardAction::showMenubar(this, SLOT(slotViewMenuBar()), actionCollection()); // FIXME: Disable so it will compile. // viewToolBar = KStandardAction::showToolbar(this, SLOT(slotViewToolBar()), actionCollection()); // viewToolBar->setToolTip(i18n("Enables/disables the toolbar")); // viewToolBar->setWhatsThis (i18n("Enables/disables the toolbar")); viewPhrasebookBar = actionCollection()->add(QStringLiteral("showPhrasebookBar")); viewPhrasebookBar->setText(i18n("Show P&hrasebook Bar")); connect(viewPhrasebookBar, &QAction::triggered, this, &KMouthApp::slotViewPhrasebookBar); viewPhrasebookBar->setToolTip(i18n("Enables/disables the phrasebook bar")); viewPhrasebookBar->setWhatsThis(i18n("Enables/disables the phrasebook bar")); viewStatusBar = KStandardAction::showStatusbar(this, SLOT(slotViewStatusBar()), actionCollection()); viewStatusBar->setToolTip(i18n("Enables/disables the statusbar")); viewStatusBar->setWhatsThis(i18n("Enables/disables the statusbar")); configureTTS = actionCollection()->addAction(QStringLiteral("configureTTS")); configureTTS->setIcon(QIcon::fromTheme(QStringLiteral("configure"))); configureTTS->setText(i18n("&Configure KMouth...")); connect(configureTTS, &QAction::triggered, this, &KMouthApp::slotConfigureTTS); configureTTS->setToolTip(i18n("Opens the configuration dialog")); configureTTS->setWhatsThis(i18n("Opens the configuration dialog")); // The "Help" menu // The "Help" menu will automatically get created. // The popup menu of the list of spoken sentences phraseListSpeak = actionCollection()->addAction(QStringLiteral("phraselist_speak")); phraseListSpeak->setIcon(QIcon::fromTheme(QStringLiteral("text-speak"))); phraseListSpeak->setText(i18n("&Speak")); phraseListSpeak->setToolTip(i18n("Speaks the currently selected phrases in the history")); connect(phraseListSpeak, &QAction::triggered, phraseList, &PhraseList::speakListSelection); phraseListSpeak->setWhatsThis(i18n("Speaks the currently selected phrases in the history")); phraseListRemove = actionCollection()->addAction(QStringLiteral("phraselist_remove")); phraseListRemove->setIcon(QIcon::fromTheme(QStringLiteral("edit-delete"))); phraseListRemove->setText(i18n("&Delete")); connect(phraseListRemove, &QAction::triggered, phraseList, &PhraseList::removeListSelection); phraseListRemove->setToolTip(i18n("Deletes the currently selected phrases from the history")); phraseListRemove->setWhatsThis(i18n("Deletes the currently selected phrases from the history")); phraseListCut = actionCollection()->addAction(QStringLiteral("phraselist_cut")); phraseListCut->setIcon(QIcon::fromTheme(QStringLiteral("edit-cut"))); phraseListCut->setText(i18n("Cu&t")); connect(phraseListCut, &QAction::triggered, phraseList, &PhraseList::cutListSelection); phraseListCut->setToolTip(i18n("Cuts the currently selected phrases from the history and puts them to the clipboard")); phraseListCut->setWhatsThis(i18n("Cuts the currently selected phrases from the history and puts them to the clipboard")); phraseListCopy = actionCollection()->addAction(QStringLiteral("phraselist_copy")); phraseListCopy->setIcon(QIcon::fromTheme(QStringLiteral("edit-copy"))); phraseListCopy->setText(i18n("&Copy")); connect(phraseListCopy, &QAction::triggered, phraseList, &PhraseList::copyListSelection); phraseListCut->setToolTip(i18n("Copies the currently selected phrases from the history to the clipboard")); phraseListCut->setWhatsThis(i18n("Copies the currently selected phrases from the history to the clipboard")); phraselistSelectAll = actionCollection()->addAction(QStringLiteral("phraselist_select_all")); phraselistSelectAll->setText(i18n("Select &All Entries")); connect(phraselistSelectAll, &QAction::triggered, phraseList, &PhraseList::selectAllEntries); phraselistSelectAll->setToolTip(i18n("Selects all phrases in the history")); phraselistSelectAll->setWhatsThis(i18n("Selects all phrases in the history")); phraselistDeselectAll = actionCollection()->addAction(QStringLiteral("phraselist_deselect_all")); phraselistDeselectAll->setText(i18n("D&eselect All Entries")); connect(phraselistDeselectAll, &QAction::triggered, phraseList, &PhraseList::deselectAllEntries); phraselistDeselectAll->setToolTip(i18n("Deselects all phrases in the history")); phraselistDeselectAll->setWhatsThis(i18n("Deselects all phrases in the history")); // The popup menu of the edit field // The popup menu of the edit field will automatically get created. // use the absolute path to your kmouthui.rc file for testing purpose in createGUI(); createGUI(); } void KMouthApp::initStatusBar() { /////////////////////////////////////////////////////////////////// // STATUSBAR // TODO: add your own items you need for displaying current application status. m_statusLabel = new QLabel(i18nc("The job is done", "Ready.")); statusBar()->addPermanentWidget(m_statusLabel); } void KMouthApp::initPhraseList() { //////////////////////////////////////////////////////////////////// // create the main widget here that is managed by KTMainWindow's view-region and // connect the widget to your document to display document contents. phraseList = new PhraseList(this); setCentralWidget(phraseList); } void KMouthApp::openDocumentFile(const QUrl &url) { slotStatusMsg(i18n("Opening file...")); phraseList->open(url); slotStatusMsg(i18nc("The job is done", "Ready.")); } void KMouthApp::saveOptions() { if (isConfigured) { KConfigGroup cg(KSharedConfig::openConfig(), "General Options"); cg.writeEntry("Geometry", size()); cg.writeEntry("Show Menubar", viewMenuBar->isChecked()); // FIXME: Toolbar disabled so it will compile. // cg.writeEntry("Show Toolbar", viewToolBar->isChecked()); cg.writeEntry("Show Phrasebook Bar", viewPhrasebookBar->isChecked()); cg.writeEntry("Show Statusbar", viewStatusBar->isChecked()); // FIXME: KToolBar no longer has barPos() method. // cg.writeEntry("ToolBarPos", (int) toolBar("mainToolBar")->barPos()); if (phraseList != nullptr) phraseList->saveCompletionOptions(); optionsDialog->saveOptions(); KConfigGroup cg2(KSharedConfig::openConfig(), "mainToolBar"); toolBar(QStringLiteral("mainToolBar"))->saveSettings(cg2); KConfigGroup cg3(KSharedConfig::openConfig(), "phrasebookBar"); toolBar(QStringLiteral("phrasebookBar"))->saveSettings(cg); } } void KMouthApp::readOptions() { KConfigGroup cg(KSharedConfig::openConfig(), "General Options"); // bar status settings bool bViewMenubar = cg.readEntry("Show Menubar", true); viewMenuBar->setChecked(bViewMenubar); slotViewMenuBar(); // FIXME: Toolbar disabled so it will compile. // bool bViewToolbar = cg.readEntry("Show Toolbar", QVariant(true)).toBool(); // viewToolBar->setChecked(bViewToolbar); // slotViewToolBar(); bool bViewPhrasebookbar = cg.readEntry("Show Phrasebook Bar", true); viewPhrasebookBar->setChecked(bViewPhrasebookbar); bool bViewStatusbar = cg.readEntry("Show Statusbar", true); viewStatusBar->setChecked(bViewStatusbar); slotViewStatusBar(); // bar position settings // FIXME: // KToolBar::BarPosition toolBarPos; // toolBarPos=(KToolBar::BarPosition) cg.readEntry("ToolBarPos", int(KToolBar::Top)); // toolBar("mainToolBar")->setBarPos(toolBarPos); QSize size = cg.readEntry("Geometry", QSize()); if (!size.isEmpty()) { resize(size); } optionsDialog->readOptions(); toolBar(QStringLiteral("mainToolBar"))->applySettings(KSharedConfig::openConfig()->group("mainToolBar")); toolBar(QStringLiteral("phrasebookBar"))->applySettings(KSharedConfig::openConfig()->group("phrasebookBar")); slotPhrasebookConfirmed(); if (phraseList != nullptr) phraseList->readCompletionOptions(); } bool KMouthApp::queryClose() { saveOptions(); return true; } void KMouthApp::enableMenuEntries(bool existSelectedEntries, bool existDeselectedEntries) { bool existEntries = existSelectedEntries | existDeselectedEntries; fileSaveAs->setEnabled(existEntries); filePrint->setEnabled(existEntries); phraselistSelectAll->setEnabled(existDeselectedEntries); phraselistDeselectAll->setEnabled(existSelectedEntries); phraseListSpeak->setEnabled(existSelectedEntries); phraseListRemove->setEnabled(existSelectedEntries); phraseListCut->setEnabled(existSelectedEntries); phraseListCopy->setEnabled(existSelectedEntries); } ///////////////////////////////////////////////////////////////////// // SLOT IMPLEMENTATION ///////////////////////////////////////////////////////////////////// void KMouthApp::slotFileOpen() { slotStatusMsg(i18n("Opening file...")); phraseList->open(); slotStatusMsg(i18nc("The job is done", "Ready.")); } void KMouthApp::slotFileSaveAs() { slotStatusMsg(i18n("Saving history with a new filename...")); phraseList->save(); slotStatusMsg(i18nc("The job is done", "Ready.")); } void KMouthApp::slotFilePrint() { slotStatusMsg(i18n("Printing...")); if (printer == nullptr) { printer = new QPrinter(); } QPrintDialog *printDialog = new QPrintDialog(printer, nullptr); if (printDialog->exec()) { phraseList->print(printer); } slotStatusMsg(i18nc("The job is done", "Ready.")); } void KMouthApp::slotFileQuit() { slotStatusMsg(i18nc("Shutting down the application", "Exiting...")); 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) { // 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. w = memberList().at(i); if (!w->close()) break; #ifdef __GNUC__ #warning "kde4: how remove it ?.???" #endif //memberList()->removeRef(w); } } } void KMouthApp::slotEditPhrasebook() { PhraseBookDialog *phraseBookDialog = PhraseBookDialog::get(); // As we do not know whether the we are already connected to the slot, // we first disconnect and then connect again. disconnect(phraseBookDialog, &PhraseBookDialog::phrasebookConfirmed, this, &KMouthApp::slotPhrasebookConfirmed); connect(phraseBookDialog, &PhraseBookDialog::phrasebookConfirmed, this, &KMouthApp::slotPhrasebookConfirmed); // As we do not know whether the phrase book edit window is already open, // we first open and then raise it, so that it is surely the top window. phraseBookDialog->show(); phraseBookDialog->raise(); } void KMouthApp::slotViewMenuBar() { slotStatusMsg(i18n("Toggling menubar...")); if (!viewMenuBar->isChecked()) menuBar()->hide(); else menuBar()->show(); slotStatusMsg(i18nc("The job is done", "Ready.")); } void KMouthApp::slotViewToolBar() { slotStatusMsg(i18n("Toggling toolbar...")); /////////////////////////////////////////////////////////////////// // turn Toolbar on or off if (!viewToolBar->isChecked()) { toolBar(QStringLiteral("mainToolBar"))->hide(); } else { toolBar(QStringLiteral("mainToolBar"))->show(); } slotStatusMsg(i18nc("The job is done", "Ready.")); } void KMouthApp::slotViewPhrasebookBar() { slotStatusMsg(i18n("Toggling phrasebook bar...")); /////////////////////////////////////////////////////////////////// // turn Toolbar on or off if (!viewPhrasebookBar->isChecked()) { toolBar(QStringLiteral("phrasebookBar"))->hide(); } else { toolBar(QStringLiteral("phrasebookBar"))->show(); } slotStatusMsg(i18nc("The job is done", "Ready.")); } void KMouthApp::slotViewStatusBar() { slotStatusMsg(i18n("Toggle the statusbar...")); /////////////////////////////////////////////////////////////////// //turn Statusbar on or off if (!viewStatusBar->isChecked()) { statusBar()->hide(); } else { statusBar()->show(); } slotStatusMsg(i18nc("The job is done", "Ready.")); } void KMouthApp::slotConfigureTTS() { phraseList->saveWordCompletion(); optionsDialog->show(); } void KMouthApp::slotStatusMsg(const QString &text) { /////////////////////////////////////////////////////////////////// // change status message permanently m_statusLabel->setText(text); } void KMouthApp::slotPhrasebookConfirmed() { QString standardBook = QStandardPaths::locate(QStandardPaths::DataLocation, QStringLiteral("standard.phrasebook")); if (!standardBook.isEmpty()) { PhraseBook book; book.open(QUrl::fromLocalFile(standardBook)); QString name = QStringLiteral("phrasebooks"); QMenu *popup = (QMenu *)factory()->container(name, this); KToolBar *toolbar = toolBar(QStringLiteral("phrasebookBar")); delete phrases; phrases = new KActionCollection(actionCollection()); book.addToGUI(popup, toolbar, phrases, this, SLOT(slotPhraseSelected(QString))); } } void KMouthApp::slotConfigurationChanged() { optionsDialog->saveOptions(); } void KMouthApp::slotPhraseSelected(const QString &phrase) { phraseList->insert(phrase); if (optionsDialog->isSpeakImmediately()) phraseList->speak(); } TextToSpeechSystem *KMouthApp::getTTSSystem() const { return optionsDialog->getTTSSystem(); } diff --git a/main.cpp b/main.cpp index 9deee30..ce7503f 100644 --- a/main.cpp +++ b/main.cpp @@ -1,79 +1,78 @@ /*************************************************************************** * Copyright (C) 2002 by Gunnar Schmi Dt * * * * 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. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include #include -#include #include #include #include #include "kmouth.h" #include "version.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); KLocalizedString::setApplicationDomain("kmouth"); QApplication::setApplicationDisplayName(i18n("KMouth")); KAboutData aboutData(QStringLiteral("kmouth"), i18n("KMouth"), QStringLiteral(KMOUTH_VERSION), i18n("A type-and-say front end for speech synthesizers"), KAboutLicense::GPL, i18n("(c) 2002/2003, Gunnar Schmi Dt"), QString(), QStringLiteral("https://www.kde.org/applications/utilities/kmouth/"), QStringLiteral("kmouth@schmi-dt.de")); aboutData.addAuthor(i18n("Gunnar Schmi Dt"), i18n("Original Author"), QStringLiteral("kmouth@schmi-dt.de")); aboutData.addAuthor(i18n("Jeremy Whiting"), i18n("Current Maintainer"), QStringLiteral("jpwhiting@kde.org")); aboutData.addCredit(i18n("Olaf Schmidt"), i18n("Tips, extended phrase books")); aboutData.setOrganizationDomain(QByteArray("kde.org")); QCommandLineParser parser; KAboutData::setApplicationData(aboutData); parser.addPositionalArgument(QStringLiteral("[File]"), i18n("History file to open")); aboutData.setupCommandLine(&parser); parser.process(app); aboutData.processCommandLine(&parser); if (app.isSessionRestored()) { RESTORE(KMouthApp); } else { KMouthApp *kmouth = new KMouthApp(); if (!kmouth->configured()) return 0; kmouth->show(); if (!parser.positionalArguments().isEmpty()) { const QUrl url = QUrl::fromUserInput(parser.positionalArguments().at(0), QDir::currentPath()); kmouth->openDocumentFile(url); } } return app.exec(); } diff --git a/optionsdialog.cpp b/optionsdialog.cpp index 46d3e47..a651bd0 100644 --- a/optionsdialog.cpp +++ b/optionsdialog.cpp @@ -1,223 +1,221 @@ /*************************************************************************** * Copyright (C) 2002 by Gunnar Schmi Dt * * * * 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. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "optionsdialog.h" #include #include #include -#include #include #include #include #include #include -#include #include #include "speech.h" #include "texttospeechconfigurationwidget.h" #include "wordcompletion/wordcompletionwidget.h" PreferencesWidget::PreferencesWidget(QWidget *parent, const QString &name) : QWidget(parent) { setObjectName(name); setupUi(this); speakCombo->setCurrentIndex(1); speak = false; closeCombo->setCurrentIndex(2); save = 2; } PreferencesWidget::~PreferencesWidget() { } void PreferencesWidget::cancel() { if (speak) speakCombo->setCurrentIndex(0); else speakCombo->setCurrentIndex(1); closeCombo->setCurrentIndex(save); } void PreferencesWidget::ok() { speak = speakCombo->currentIndex() == 0; save = closeCombo->currentIndex(); } void PreferencesWidget::readOptions() { KConfigGroup cg(KSharedConfig::openConfig(), "Preferences"); if (cg.hasKey("AutomaticSpeak")) if (cg.readEntry("AutomaticSpeak") == QLatin1String("Yes")) speak = true; else speak = false; else speak = false; KConfigGroup cg2(KSharedConfig::openConfig() , "Notification Messages"); if (cg2.hasKey("AutomaticSave")) if (cg2.readEntry("AutomaticSave") == QLatin1String("Yes")) save = 0; else save = 1; else save = 2; if (speak) speakCombo->setCurrentIndex(0); else speakCombo->setCurrentIndex(1); closeCombo->setCurrentIndex(save); } void PreferencesWidget::saveOptions() { KConfigGroup cg(KSharedConfig::openConfig(), "Preferences"); if (speak) cg.writeEntry("AutomaticSpeak", "Yes"); else cg.writeEntry("AutomaticSpeak", "No"); KConfigGroup cg2(KSharedConfig::openConfig(), "Notification Messages"); if (save == 0) cg2.writeEntry("AutomaticSave", "Yes"); else if (save == 1) cg2.writeEntry("AutomaticSave", "No"); else cg2.deleteEntry("AutomaticSave"); } bool PreferencesWidget::isSpeakImmediately() { return speak; } /***************************************************************************/ OptionsDialog::OptionsDialog(QWidget *parent) : KPageDialog(parent) { setWindowTitle(i18n("Configuration")); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::Apply); QWidget *mainWidget = new QWidget(this); QVBoxLayout *mainLayout = new QVBoxLayout; setLayout(mainLayout); mainLayout->addWidget(mainWidget); QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok); okButton->setDefault(true); okButton->setShortcut(Qt::CTRL | Qt::Key_Return); connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); //PORTING SCRIPT: WARNING mainLayout->addWidget(buttonBox) must be last item in layout. Please move it. mainLayout->addWidget(buttonBox); setFaceType(KPageDialog::List); //setHelp(QLatin1String("config-dialog")); //addGridPage (1, Qt::Horizontal, i18n("General Options"), QString(), iconGeneral); tabCtl = new QTabWidget(); tabCtl->setObjectName(QStringLiteral("general")); behaviourWidget = new PreferencesWidget(tabCtl, QStringLiteral("prefPage")); tabCtl->addTab(behaviourWidget, i18n("&Preferences")); commandWidget = new TextToSpeechConfigurationWidget(tabCtl, QStringLiteral("ttsTab")); tabCtl->addTab(commandWidget, i18n("&Text-to-Speech")); KPageWidgetItem *pageGeneral = new KPageWidgetItem(tabCtl, i18n("General Options")); pageGeneral->setHeader(i18n("General Options")); pageGeneral->setIcon(QIcon::fromTheme(QStringLiteral("configure"))); addPage(pageGeneral); completionWidget = new WordCompletionWidget(nullptr, "Word Completion widget"); KPageWidgetItem *pageCompletion = new KPageWidgetItem(completionWidget, i18n("Word Completion")); pageCompletion->setHeader(i18n("Word Completion")); pageCompletion->setIcon(QIcon::fromTheme(QStringLiteral("keyboard"))); addPage(pageCompletion); buttonBox->button(QDialogButtonBox::Cancel)->setDefault(true); connect(okButton, &QAbstractButton::clicked, this, &OptionsDialog::slotOk); connect(buttonBox->button(QDialogButtonBox::Cancel), &QAbstractButton::clicked, this, &OptionsDialog::slotCancel); connect(buttonBox->button(QDialogButtonBox::Apply), &QAbstractButton::clicked, this, &OptionsDialog::slotApply); } OptionsDialog::~OptionsDialog() { } void OptionsDialog::slotCancel() { // QDialog::slotCancel(); commandWidget->cancel(); behaviourWidget->cancel(); completionWidget->load(); } void OptionsDialog::slotOk() { // QDialog::slotOk(); commandWidget->ok(); behaviourWidget->ok(); completionWidget->save(); emit configurationChanged(); } void OptionsDialog::slotApply() { // QDialog::slotApply(); commandWidget->ok(); behaviourWidget->ok(); completionWidget->save(); emit configurationChanged(); } TextToSpeechSystem *OptionsDialog::getTTSSystem() const { return commandWidget->getTTSSystem(); } void OptionsDialog::readOptions() { commandWidget->readOptions(QStringLiteral("TTS System")); behaviourWidget->readOptions(); } void OptionsDialog::saveOptions() { commandWidget->saveOptions(QStringLiteral("TTS System")); behaviourWidget->saveOptions(); KSharedConfig::openConfig()->sync(); } bool OptionsDialog::isSpeakImmediately() { return behaviourWidget->isSpeakImmediately(); } diff --git a/phrasebook/initialphrasebookwidget.cpp b/phrasebook/initialphrasebookwidget.cpp index 91a373f..1ebc49d 100644 --- a/phrasebook/initialphrasebookwidget.cpp +++ b/phrasebook/initialphrasebookwidget.cpp @@ -1,145 +1,144 @@ /*************************************************************************** * Copyright (C) 2002 by Gunnar Schmi Dt * * * * 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. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "initialphrasebookwidget.h" // include files for Qt #include #include #include #include #include #include #include // include files for KDE #include #include #include #include -#include InitialPhraseBookWidget::InitialPhraseBookWidget(QWidget *parent, const char *name) : QWizardPage(parent) { setObjectName(QLatin1String(name)); QVBoxLayout *mainLayout = new QVBoxLayout(this); //TODO PORT QT5 mainLayout->setSpacing(QDialog::spacingHint()); QLabel *label = new QLabel(i18n("Please decide which phrase books you need:"), this); label->setObjectName(QStringLiteral("booksTitle")); mainLayout->addWidget(label); m_model = new QStandardItemModel(0, 1, this); m_model->setHeaderData(0, Qt::Horizontal, i18n("Book")); QTreeView *view = new QTreeView(this); view->setSortingEnabled(false); //books->setItemsMovable (false); view->setDragEnabled(false); view->setRootIsDecorated(true); view->setSelectionMode(QAbstractItemView::MultiSelection); view->setModel(m_model); mainLayout->addWidget(view); initStandardPhraseBooks(); connect(m_model, &QStandardItemModel::itemChanged, this, &InitialPhraseBookWidget::slotItemChanged); } InitialPhraseBookWidget::~InitialPhraseBookWidget() { } void InitialPhraseBookWidget::slotItemChanged(QStandardItem *item) { if (item->hasChildren()) { for (int i = 0; i < item->rowCount(); ++i) { QStandardItem *child = item->child(i); child->setCheckState(item->checkState()); } } } void InitialPhraseBookWidget::initStandardPhraseBooks() { StandardBookList bookPaths = PhraseBook::standardPhraseBooks(); QStandardItem *parent = m_model->invisibleRootItem(); QStringList currentNamePath; currentNamePath << QLatin1String(""); QStack stack; StandardBookList::iterator it; for (it = bookPaths.begin(); it != bookPaths.end(); ++it) { QString namePath = (*it).path; QStringList dirs = namePath.split(QLatin1Char('/')); QStringList::iterator it1 = currentNamePath.begin(); QStringList::iterator it2 = dirs.begin(); for (; (it1 != currentNamePath.end()) && (it2 != dirs.end()) && (*it1 == *it2); ++it1, ++it2); for (; it1 != currentNamePath.end(); ++it1) { parent = stack.pop(); } for (; it2 != dirs.end(); ++it2) { stack.push(parent); QStandardItem *newParent = new QStandardItem(*it2); newParent->setCheckable(true); parent->appendRow(newParent); parent = newParent; } currentNamePath = dirs; QStandardItem *book; book = new QStandardItem((*it).name); book->setData((*it).filename); book->setCheckable(true); parent->appendRow(book); } } void InitialPhraseBookWidget::createBook() { PhraseBook book; QStandardItem *item = m_model->invisibleRootItem(); addChildrenToBook(book, item); QString bookLocation = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QLatin1Char('/'); if (!bookLocation.isNull() && !bookLocation.isEmpty()) { QDir().mkpath(bookLocation); qDebug() << "creating book at location " << bookLocation; book.save(QUrl::fromLocalFile(bookLocation + QStringLiteral("standard.phrasebook"))); } } void InitialPhraseBookWidget::addChildrenToBook(PhraseBook &book, QStandardItem *item) { for (int i = 0; i < item->rowCount(); ++i) { QStandardItem *child = item->child(i); if (child->checkState() != Qt::Unchecked) { PhraseBook localBook; if (localBook.open(QUrl::fromLocalFile(child->data().toString()))) { book += localBook; } } if (child->hasChildren()) addChildrenToBook(book, child); } } diff --git a/phrasebook/phrasebook.cpp b/phrasebook/phrasebook.cpp index 4979548..766a667 100644 --- a/phrasebook/phrasebook.cpp +++ b/phrasebook/phrasebook.cpp @@ -1,512 +1,510 @@ /*************************************************************************** * Copyright (C) 2002 by Gunnar Schmi Dt * * * * 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. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "phrasebook.h" #include "phrasebookparser.h" #include #include #include #include #include #include #include #include -#include #include #include #include #include #include #include #include #include #include #include #include #include -#include Phrase::Phrase() { this->phrase.clear(); this->shortcut.clear(); } Phrase::Phrase(const QString &phrase) { this->phrase = phrase; this->shortcut.clear(); } Phrase::Phrase(const QString &phrase, const QString &shortcut) { this->phrase = phrase; this->shortcut = shortcut; } QString Phrase::getPhrase() const { return phrase; } QString Phrase::getShortcut() const { return shortcut; } void Phrase::setPhrase(const QString &phrase) { this->phrase = phrase; } void Phrase::setShortcut(const QString &shortcut) { this->shortcut = shortcut; } // *************************************************************************** PhraseBookEntry::PhraseBookEntry() { phrase = Phrase(); level = 1; isPhraseValue = false; } PhraseBookEntry::PhraseBookEntry(const Phrase &phrase, int level, bool isPhrase) { this->phrase = phrase; this->level = level; isPhraseValue = isPhrase; } bool PhraseBookEntry::isPhrase() const { return isPhraseValue; } Phrase PhraseBookEntry::getPhrase() const { return phrase; } int PhraseBookEntry::getLevel() const { return level; } // *************************************************************************** void PhraseBook::print(QPrinter *pPrinter) { QPainter printpainter; printpainter.begin(pPrinter); QRect size = printpainter.viewport(); int x = size.x(); int y = size.y(); int w = size.width(); printpainter.setFont(QFont(QFontDatabase::systemFont(QFontDatabase::GeneralFont).family(), 12)); QFontMetrics metrics = printpainter.fontMetrics(); PhraseBookEntryList::iterator it; for (it = begin(); it != end(); ++it) { QRect rect = metrics.boundingRect(x + 16 * (*it).getLevel(), y, w - 16 * (*it).getLevel(), 0, Qt::AlignJustify | Qt::TextWordWrap, (*it).getPhrase().getPhrase()); if (y + rect.height() > size.height()) { pPrinter->newPage(); y = 0; } printpainter.drawText(x + 16 * (*it).getLevel(), y, w - 16 * (*it).getLevel(), rect.height(), Qt::AlignJustify | Qt::TextWordWrap, (*it).getPhrase().getPhrase()); y += rect.height(); } printpainter.end(); } bool PhraseBook::decode(const QString &xml) { QXmlInputSource source; source.setData(xml); return decode(source); } bool PhraseBook::decode(QXmlInputSource &source) { PhraseBookParser parser; QXmlSimpleReader reader; reader.setFeature(QStringLiteral("http://trolltech.com/xml/features/report-start-end-entity"), true); reader.setContentHandler(&parser); if (reader.parse(source)) { PhraseBookEntryList::clear(); *(PhraseBookEntryList *)this += parser.getPhraseList(); return true; } else return false; } QByteArray encodeString(const QString &str) { QByteArray res = ""; for (int i = 0; i < (int)str.length(); i++) { QChar ch = str.at(i); ushort uc = ch.unicode(); QByteArray number; number.setNum(uc); if ((uc > 127) || (uc < 32) || (ch == QLatin1Char('<')) || (ch == QLatin1Char('>')) || (ch == QLatin1Char('&')) || (ch == QLatin1Char(';'))) res = res + "&#" + number + ';'; else res = res + (char)uc; } return res; } QString PhraseBook::encode() { QString result; result = QStringLiteral("\n"); result += QLatin1String("\n"); result += QLatin1String("\n"); PhraseBookEntryList::iterator it; int level = 0; for (it = begin(); it != end(); ++it) { int newLevel = (*it).getLevel(); while (level < newLevel) { result += QLatin1String("\n"); level++; } while (level > newLevel) { result += QLatin1String("\n"); level--; } if ((*it).isPhrase()) { Phrase phrase = (*it).getPhrase(); result += QStringLiteral("") + QLatin1String(encodeString(phrase.getPhrase())) + QStringLiteral("\n"); } else { Phrase phrase = (*it).getPhrase(); result += QStringLiteral("\n"); level++; } } while (level > 0) { result += QLatin1String("\n"); level--; } result += QLatin1String(""); return result; } QStringList PhraseBook::toStringList() { QStringList result; PhraseBook::iterator it; for (it = begin(); it != end(); ++it) { if ((*it).isPhrase()) result += (*it).getPhrase().getPhrase(); } return result; } bool PhraseBook::save(const QUrl &url) { QRegExp pattern(QStringLiteral("*.phrasebook"), Qt::CaseSensitive, QRegExp::Wildcard); return save(url, pattern.exactMatch(url.fileName())); } void PhraseBook::save(QTextStream &stream, bool asPhrasebook) { if (asPhrasebook) stream << encode(); else stream << toStringList().join(QStringLiteral("\n")); } bool PhraseBook::save(const QUrl &url, bool asPhrasebook) { if (url.isLocalFile()) { QFile file(url.path()); if (!file.open(QIODevice::WriteOnly)) return false; QTextStream stream(&file); save(stream, asPhrasebook); file.close(); if (file.error() != QFile::NoError) return false; else return true; } else { QByteArray data; QTextStream ts(&data); save(ts, asPhrasebook); ts.flush(); KIO::StoredTransferJob *uploadJob = KIO::storedPut(data, url, -1); return uploadJob->exec(); } } int PhraseBook::save(QWidget *parent, const QString &title, QUrl &url, bool phrasebookFirst) { // KFileDialog::getSaveUrl(...) is not useful here as we need // to know the requested file type. QString filters; if (phrasebookFirst) filters = i18n("Phrase Books (*.phrasebook);;Plain Text Files (*.txt);;All Files (*)"); else filters = i18n("Plain Text Files (*.txt);;Phrase Books (*.phrasebook);;All Files (*)"); QFileDialog fdlg(parent, title, QString(), filters); fdlg.setAcceptMode(QFileDialog::AcceptSave); if (fdlg.exec() != QDialog::Accepted || fdlg.selectedUrls().size() < 1) { return 0; } url = fdlg.selectedUrls().at(0); if (url.isEmpty() || !url.isValid()) { return -1; } if (QFile::exists(url.toLocalFile())) { if (KMessageBox::warningContinueCancel(nullptr, QStringLiteral("%1").arg(i18n("The file %1 already exists. " "Do you want to overwrite it?", url.url())), i18n("File Exists"), KGuiItem(i18n("&Overwrite"))) == KMessageBox::Cancel) { return 0; } } bool result; if (fdlg.selectedNameFilter() == QLatin1String("*.phrasebook")) { if (url.fileName(nullptr).contains(QLatin1Char('.')) == 0) { url = url.adjusted(QUrl::RemoveFilename); url.setPath(url.path() + url.fileName(nullptr) + QStringLiteral(".phrasebook")); } else if (url.fileName(nullptr).rightRef(11).contains(QLatin1String(".phrasebook"), Qt::CaseInsensitive) == 0) { int filetype = KMessageBox::questionYesNoCancel(nullptr, QStringLiteral("%1").arg(i18n("Your chosen filename %1 has a different extension than .phrasebook. " "Do you wish to add .phrasebook to the filename?", url.fileName())), i18n("File Extension"), KGuiItem(i18n("Add")), KGuiItem(i18n("Do Not Add"))); if (filetype == KMessageBox::Cancel) { return 0; } if (filetype == KMessageBox::Yes) { url = url.adjusted(QUrl::RemoveFilename); url.setPath(url.path() + url.fileName(nullptr) + QStringLiteral(".phrasebook")); } } result = save(url, true); } else if (fdlg.selectedNameFilter() == QLatin1String("*.txt")) { if (url.fileName(nullptr).rightRef(11).contains(QLatin1String(".phrasebook"), Qt::CaseInsensitive) == 0) { result = save(url, false); } else { int filetype = KMessageBox::questionYesNoCancel(nullptr, QStringLiteral("%1").arg(i18n("Your chosen filename %1 has the extension .phrasebook. " "Do you wish to save in phrasebook format?", url.fileName())), i18n("File Extension"), KGuiItem(i18n("As Phrasebook")), KGuiItem(i18n("As Plain Text"))); if (filetype == KMessageBox::Cancel) { return 0; } if (filetype == KMessageBox::Yes) { result = save(url, true); } else { result = save(url, false); } } } else // file format "All files" requested, so decide by extension result = save(url); if (result) return 1; else return -1; } bool PhraseBook::open(const QUrl &url) { KIO::StoredTransferJob *downloadJob = KIO::storedGet(url); if (downloadJob->exec()) { // First: try to load it as a normal phrase book QBuffer fileBuffer; fileBuffer.setData(downloadJob->data()); QXmlInputSource source(&fileBuffer); bool error = !decode(source); // Second: if the file does not contain a phrase book, load it as // a plain text file if (error) { // Load each line of the plain text file as a new phrase QTextStream stream(&fileBuffer); while (!stream.atEnd()) { QString s = stream.readLine(); if (!(s.isNull() || s.isEmpty())) *this += PhraseBookEntry(Phrase(s, QLatin1String("")), 0, true); } error = false; } return !error; } return false; } StandardBookList PhraseBook::standardPhraseBooks() { // Get all the standard phrasebook filenames in bookPaths. QStringList bookPaths; const QStringList dirs = QStandardPaths::locateAll(QStandardPaths::AppDataLocation, QStringLiteral("books"), QStandardPaths::LocateDirectory); Q_FOREACH (const QString &dir, dirs) { const QStringList locales = QDir(dir).entryList(QDir::Dirs | QDir::NoDotAndDotDot); Q_FOREACH (const QString &locale, locales) { const QStringList fileNames = QDir(dir + QLatin1Char('/') + locale).entryList(QStringList() << QStringLiteral("*.phrasebook")); Q_FOREACH (const QString &file, fileNames) { bookPaths.append(dir + QLatin1Char('/') + locale + QLatin1Char('/') + file); } } } QStringList bookNames; QMap bookMap; QStringList::iterator it; // Iterate over all books creating a phrasebook for each, creating a StandardBook of each. for (it = bookPaths.begin(); it != bookPaths.end(); ++it) { PhraseBook pbook; // Open the phrasebook. if (pbook.open(QUrl::fromLocalFile(*it))) { StandardBook book; book.name = (*pbook.begin()).getPhrase().getPhrase(); book.path = displayPath(*it); book.filename = *it; bookNames += book.path + QLatin1Char('/') + book.name; bookMap [book.path + QLatin1Char('/') + book.name] = book; } } bookNames.sort(); StandardBookList result; for (it = bookNames.begin(); it != bookNames.end(); ++it) result += bookMap [*it]; return result; } QString PhraseBook::displayPath(const QString &filename) { QFileInfo file(filename); QString path = file.path(); QString dispPath; int position = path.indexOf(QLatin1String("/kmouth/books/")) + QStringLiteral("/kmouth/books/").length(); while (path.length() > position) { file.setFile(path); KDesktopFile *dirDesc = new KDesktopFile(QStandardPaths::GenericDataLocation, path + QStringLiteral("/.directory")); QString name = dirDesc->readName(); delete dirDesc; if (name.isNull() || name.isEmpty()) dispPath += QLatin1Char('/') + file.fileName(); else dispPath += QLatin1Char('/') + name; path = file.path(); } return dispPath; } void PhraseBook::addToGUI(QMenu *popup, KToolBar *toolbar, KActionCollection *phrases, QObject *receiver, const char *slot) const { if ((popup != nullptr) || (toolbar != nullptr)) { QStack stack; QWidget *parent = popup; int level = 0; QList::ConstIterator it; for (it = begin(); it != end(); ++it) { int newLevel = (*it).getLevel(); while (newLevel > level) { KActionMenu *menu = phrases->add(QStringLiteral("phrasebook")); menu->setDelayed(false); if (parent == popup) toolbar->addAction(menu); if (parent != nullptr) { parent->addAction(menu); stack.push(parent); } parent = menu->menu(); level++; } while (newLevel < level && (parent != popup)) { parent = stack.pop(); level--; } if ((*it).isPhrase()) { Phrase phrase = (*it).getPhrase(); QAction *action = new PhraseAction(phrase.getPhrase(), phrase.getShortcut(), receiver, slot, phrases); if (parent == popup) toolbar->addAction(action); if (parent != nullptr) parent->addAction(action); } else { Phrase phrase = (*it).getPhrase(); KActionMenu *menu = phrases->add(QStringLiteral("phrasebook")); menu->setText(phrase.getPhrase()); menu->setDelayed(false); if (parent == popup) toolbar->addAction(menu); parent->addAction(menu); stack.push(parent); parent = menu->menu(); level++; } } } } void PhraseBook::insert(const QString &name, const PhraseBook &book) { *this += PhraseBookEntry(Phrase(name), 0, false); QList::ConstIterator it; for (it = book.begin(); it != book.end(); ++it) { *this += PhraseBookEntry((*it).getPhrase(), (*it).getLevel() + 1, (*it).isPhrase()); } } diff --git a/phrasebook/phrasebookdialog.cpp b/phrasebook/phrasebookdialog.cpp index 3b5177e..9f457d7 100644 --- a/phrasebook/phrasebookdialog.cpp +++ b/phrasebook/phrasebookdialog.cpp @@ -1,704 +1,703 @@ /*************************************************************************** * Copyright (C) 2002 by Gunnar Schmi Dt * * * * 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. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "phrasebookdialog.h" // include files for Qt #include #include #include #include #include // include files for KDE #include #include #include #include #include "phrasebook.h" #include -#include const int kTextColumn = 0; const int kShortcutColumn = 1; const QString kName = QStringLiteral("name"); const QString kShortcut = QStringLiteral("shortcut"); const QString kPhraseBook = QStringLiteral("phrasebook"); const QString kPhrase = QStringLiteral("phrase"); const QString kPhraseBookXML = QStringLiteral("\n%2\n"); const QString kPhraseXML = QStringLiteral("%1\n"); const QString kWholeBookXML = QStringLiteral("\n" "\n" "\n%1" ""); const QIcon kPhraseBookIcon = QIcon::fromTheme(kPhraseBook); const QIcon kPhraseIcon = QIcon::fromTheme(kPhrase); StandardPhraseBookInsertAction::StandardPhraseBookInsertAction(const QUrl &url, const QString& name, const QObject* receiver, const char* slot, KActionCollection* parent) : QAction(QIcon::fromTheme(QStringLiteral("phrasebook")), name, parent) { this->url = url; connect(this, SIGNAL(triggered(bool)), this, SLOT(slotActivated())); connect(this, SIGNAL(slotActivated(const QUrl &)), receiver, slot); parent->addAction(name, this); } StandardPhraseBookInsertAction::~StandardPhraseBookInsertAction() { } void StandardPhraseBookInsertAction::slotActivated() { emit slotActivated(url); } namespace PhraseBookPrivate { PhraseBookDialog *instance = nullptr; } PhraseBookDialog::PhraseBookDialog() : KXmlGuiWindow(nullptr) { // Create model with 2 columns and no rows m_bookModel = new QStandardItemModel(0, 2, this); m_rootItem = m_bookModel->invisibleRootItem(); m_bookModel->setHeaderData(kTextColumn, Qt::Horizontal, i18n("Phrase")); m_bookModel->setHeaderData(kShortcutColumn, Qt::Horizontal, i18n("Shortcut")); setObjectName(QStringLiteral("phraseEditDialog")); setWindowTitle(i18n("Phrase Book")); initGUI(); initActions(); initStandardPhraseBooks(); QString standardBook = QStandardPaths::locate(QStandardPaths::DataLocation, QStringLiteral("standard.phrasebook")); if (!standardBook.isNull() && !standardBook.isEmpty()) { QFile file(standardBook); file.open(QIODevice::ReadOnly); QDomDocument document; document.setContent(&file); const QDomNodeList nodes = document.documentElement().childNodes(); for (int i = 0; i < nodes.count(); ++i) { deserializeBook(nodes.at(i), m_rootItem); } selectionChanged(); phrasebookChanged = false; fileSave->setEnabled(false); } // Watch any changes in the model. connect(m_bookModel, &QAbstractItemModel::dataChanged, this, &PhraseBookDialog::slotModelChanged); connect(m_bookModel, &QAbstractItemModel::rowsInserted, this, &PhraseBookDialog::slotModelChanged); connect(m_bookModel, &QAbstractItemModel::rowsMoved, this, &PhraseBookDialog::slotModelChanged); connect(m_bookModel, &QAbstractItemModel::rowsRemoved, this, &PhraseBookDialog::slotModelChanged); //printer = 0; // i18n("Edit Phrase Book") } PhraseBookDialog *PhraseBookDialog::get() { if (PhraseBookPrivate::instance == nullptr) PhraseBookPrivate::instance = new PhraseBookDialog(); return PhraseBookPrivate::instance; } PhraseBookDialog::~PhraseBookDialog() { PhraseBookPrivate::instance = nullptr; //delete printer; } QStandardItem* PhraseBookDialog::deserializeBook(const QDomNode &node, QStandardItem *parent) { QString text; QString shortcut; bool isBook = (node.nodeName() == kPhraseBook); text = isBook ? node.attributes().namedItem(kName).nodeValue() : node.lastChild().nodeValue(); shortcut = isBook ? QString() : node.attributes().namedItem(kShortcut).nodeValue(); QStandardItem *item = isBook ? new QStandardItem(kPhraseBookIcon, text) : new QStandardItem(kPhraseIcon, text); QStandardItem *shortcutItem = new QStandardItem(shortcut); if (!isBook) { item->setDropEnabled(false); shortcutItem->setDropEnabled(false); } QList items; items << item << shortcutItem; if (parent) parent->appendRow(items); else m_bookModel->appendRow(items); if (isBook) { // Iterate over the document creating QStandardItems as needed const QDomNodeList childNodes = node.childNodes(); for (int i = 0; i < childNodes.count(); ++i) { const QDomNode child = childNodes.at(i); deserializeBook(child, item); } } return item; } QString PhraseBookDialog::serializeBook(const QModelIndex &index) { QString value; if (index.isValid()) { QStandardItem *item = m_bookModel->itemFromIndex(index); QStandardItem *shortcutItem = m_bookModel->itemFromIndex(index.sibling(index.row(), kShortcutColumn)); bool isBook = item->isDropEnabled(); // We know it's a book if it's drop enabled if (isBook) { QString childrenText; for (int i = 0; i < item->rowCount(); ++i) { childrenText += serializeBook(index.child(i, 0)); } value = kPhraseBookXML.arg(item->text()).arg(childrenText); } else { value = kPhraseXML.arg(item->text()).arg(shortcutItem->text()); } } else { // Do the whole model, inside a tag. int rows = m_bookModel->rowCount(QModelIndex()); QString childrenText; for (int i = 0; i < rows; ++i) { childrenText += serializeBook(m_bookModel->index(i, 0)); } value = kWholeBookXML.arg(childrenText); } return value; } void PhraseBookDialog::initGUI() { QWidget *page = new QWidget(this); m_ui = new Ui::PhraseBookDialog(); m_ui->setupUi(page); setCentralWidget(page); m_ui->treeView->setModel(m_bookModel); connect(m_ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &PhraseBookDialog::selectionChanged); connect(m_ui->treeView, &QWidget::customContextMenuRequested, this, &PhraseBookDialog::contextMenuRequested); connectEditor(); } void PhraseBookDialog::slotModelChanged() { phrasebookChanged = true; fileSave->setEnabled(true); } void PhraseBookDialog::initActions() { // The file menu fileNewPhrase = actionCollection()->addAction(QStringLiteral("file_new_phrase")); fileNewPhrase->setIcon(QIcon::fromTheme(QStringLiteral("document-new"))); fileNewPhrase->setText(i18n("&New Phrase")); connect(fileNewPhrase, &QAction::triggered, this, &PhraseBookDialog::slotAddPhrase); fileNewPhrase->setToolTip(i18n("Adds a new phrase")); fileNewPhrase->setWhatsThis(i18n("Adds a new phrase")); fileNewBook = actionCollection()->addAction(QStringLiteral("file_new_book")); fileNewBook->setIcon(QIcon::fromTheme(QStringLiteral("document-new"))); fileNewBook->setText(i18n("New Phrase &Book")); connect(fileNewBook, &QAction::triggered, this, &PhraseBookDialog::slotAddPhrasebook); fileNewBook->setToolTip(i18n("Adds a new phrase book into which other books and phrases can be placed")); fileNewBook->setWhatsThis(i18n("Adds a new phrase book into which other books and phrases can be placed")); fileSave = KStandardAction::save(this, SLOT(slotSave()), actionCollection()); fileSave->setToolTip(i18n("Saves the phrase book onto the hard disk")); fileSave->setWhatsThis(i18n("Saves the phrase book onto the hard disk")); fileImport = actionCollection()->addAction(QStringLiteral("file_import")); fileImport->setIcon(QIcon::fromTheme(QStringLiteral("document-open"))); fileImport->setText(i18n("&Import...")); connect(fileImport, SIGNAL(triggered(bool)), this, SLOT(slotImportPhrasebook())); fileImport->setToolTip(i18n("Imports a file and adds its contents to the phrase book")); fileImport->setWhatsThis(i18n("Imports a file and adds its contents to the phrase book")); toolbarImport = new KToolBarPopupAction(QIcon::fromTheme(QStringLiteral("document-open")), i18n("&Import..."), this); actionCollection()->addAction(QStringLiteral("toolbar_import"), toolbarImport); connect(toolbarImport, SIGNAL(triggered(bool)), this, SLOT(slotImportPhrasebook())); toolbarImport->setToolTip(i18n("Imports a file and adds its contents to the phrase book")); toolbarImport->setWhatsThis(i18n("Imports a file and adds its contents to the phrase book")); fileImportStandardBook = actionCollection()->add(QStringLiteral("file_import_standard_book")); fileImportStandardBook->setIcon(QIcon::fromTheme(QStringLiteral("document-open"))); fileImportStandardBook->setText(i18n("I&mport Standard Phrase Book")); fileImportStandardBook->setToolTip(i18n("Imports a standard phrase book and adds its contents to the phrase book")); fileImportStandardBook->setWhatsThis(i18n("Imports a standard phrase book and adds its contents to the phrase book")); fileExport = actionCollection()->addAction(QStringLiteral("file_export")); fileExport->setIcon(QIcon::fromTheme(QStringLiteral("document-save"))); fileExport->setText(i18n("&Export...")); connect(fileExport, &QAction::triggered, this, &PhraseBookDialog::slotExportPhrasebook); fileExport->setToolTip(i18n("Exports the currently selected phrase(s) or phrase book(s) into a file")); fileExport->setWhatsThis(i18n("Exports the currently selected phrase(s) or phrase book(s) into a file")); //filePrint = KStandardAction::print(this, SLOT(slotPrint()), actionCollection()); //filePrint->setToolTip(i18n("Prints the currently selected phrase(s) or phrase book(s)")); //filePrint->setWhatsThis (i18n("Prints the currently selected phrase(s) or phrase book(s)")); fileClose = KStandardAction::close(this, SLOT(close()), actionCollection()); fileClose->setToolTip(i18n("Closes the window")); fileClose->setWhatsThis(i18n("Closes the window")); // The edit menu editCut = KStandardAction::cut(this, SLOT(slotCut()), actionCollection()); editCut->setToolTip(i18n("Cuts the currently selected entries from the phrase book and puts it to the clipboard")); editCut->setWhatsThis(i18n("Cuts the currently selected entries from the phrase book and puts it to the clipboard")); editCopy = KStandardAction::copy(this, SLOT(slotCopy()), actionCollection()); editCopy->setToolTip(i18n("Copies the currently selected entry from the phrase book to the clipboard")); editCopy->setWhatsThis(i18n("Copies the currently selected entry from the phrase book to the clipboard")); editPaste = KStandardAction::paste(this, SLOT(slotPaste()), actionCollection()); editPaste->setToolTip(i18n("Pastes the clipboard contents to current position")); editPaste->setWhatsThis(i18n("Pastes the clipboard contents at the current cursor position into the edit field.")); editDelete = actionCollection()->addAction(QStringLiteral("edit_delete")); editDelete->setIcon(QIcon::fromTheme(QStringLiteral("edit-delete"))); editDelete->setText(i18n("&Delete")); connect(editDelete, &QAction::triggered, this, &PhraseBookDialog::slotRemove); editDelete->setToolTip(i18n("Deletes the selected entries from the phrase book")); editDelete->setWhatsThis(i18n("Deletes the selected entries from the phrase book")); // use the absolute path to your kmouthui.rc file for testing purpose in createGUI(); createGUI(QStringLiteral("phrasebookdialogui.rc")); } void PhraseBookDialog::initStandardPhraseBooks() { StandardBookList bookPaths = PhraseBook::standardPhraseBooks(); KActionMenu *parent = fileImportStandardBook; QStringList currentNamePath; currentNamePath << QStringLiteral("x"); QStack stack; StandardBookList::iterator it; for (it = bookPaths.begin(); it != bookPaths.end(); ++it) { QUrl url = QUrl::fromLocalFile((*it).filename); QString namePath = QStringLiteral("x") + (*it).path; QStringList dirs = namePath.split(QLatin1Char('/')); QStringList::iterator it1 = currentNamePath.begin(); QStringList::iterator it2 = dirs.begin(); for (; (it1 != currentNamePath.end()) && (it2 != dirs.end()) && (*it1 == *it2); ++it1, ++it2); for (; it1 != currentNamePath.end(); ++it1) parent = stack.pop(); for (; it2 != dirs.end(); ++it2) { stack.push(parent); KActionMenu *newParent = actionCollection()->add(*it2); newParent->setText(*it2); parent->addAction(newParent); if (parent == fileImportStandardBook) toolbarImport->menu()->addAction(newParent); parent = newParent; } currentNamePath = dirs; QAction *book = new StandardPhraseBookInsertAction( url, (*it).name, this, SLOT(slotImportPhrasebook(QUrl)), actionCollection()); parent->addAction(book); if (parent == fileImportStandardBook) toolbarImport->menu()->addAction(book); } } void PhraseBookDialog::connectEditor() { connect(m_ui->lineEdit, &QLineEdit::textChanged, this, &PhraseBookDialog::slotTextChanged); connect(m_ui->noKey, &QAbstractButton::clicked, this, &PhraseBookDialog::slotNoKey); connect(m_ui->customKey, &QAbstractButton::clicked, this, &PhraseBookDialog::slotCustomKey); connect(m_ui->keyButton, &KKeySequenceWidget::keySequenceChanged, this, &PhraseBookDialog::slotKeySequenceChanged); } void PhraseBookDialog::disconnectEditor() { disconnect(m_ui->lineEdit, &QLineEdit::textChanged, this, &PhraseBookDialog::slotTextChanged); disconnect(m_ui->noKey, &QAbstractButton::clicked, this, &PhraseBookDialog::slotNoKey); disconnect(m_ui->customKey, &QAbstractButton::clicked, this, &PhraseBookDialog::slotCustomKey); disconnect(m_ui->keyButton, &KKeySequenceWidget::keySequenceChanged, this, &PhraseBookDialog::slotKeySequenceChanged); } void PhraseBookDialog::selectionChanged() { disconnectEditor(); bool modified = phrasebookChanged; QModelIndex selected = m_ui->treeView->selectionModel()->currentIndex(); QModelIndex shortcutIndex = selected.sibling(selected.row(), 1); QStandardItem *item = m_bookModel->itemFromIndex(selected); if (!m_ui->treeView->selectionModel()->hasSelection()) { m_ui->textLabel->setText(i18n("Text of the &phrase:")); m_ui->textLabel->setEnabled(false); m_ui->phrasebox->setEnabled(false); m_ui->lineEdit->setText(QLatin1String("")); m_ui->lineEdit->setEnabled(false); m_ui->shortcutLabel->setEnabled(false); m_ui->keyButton->clearKeySequence(); m_ui->keyButton->setEnabled(false); m_ui->noKey->setChecked(false); m_ui->noKey->setEnabled(false); m_ui->customKey->setChecked(false); m_ui->customKey->setEnabled(false); } else if (!item->isDropEnabled()) { // It's a phrase, since drop isn't enabled m_ui->textLabel->setText(i18n("Text of the &phrase:")); m_ui->textLabel->setEnabled(true); m_ui->phrasebox->setEnabled(true); m_ui->lineEdit->setText(m_bookModel->data(selected, Qt::DisplayRole).toString()); m_ui->lineEdit->setEnabled(true); m_ui->shortcutLabel->setEnabled(true); QString shortcut = m_bookModel->data(shortcutIndex, Qt::DisplayRole).toString(); m_ui->keyButton->setKeySequence(QKeySequence(shortcut)); if (shortcut.isEmpty() || shortcut.isNull()) { m_ui->noKey->setChecked(true); } else { m_ui->customKey->setChecked(true); } m_ui->keyButton->setEnabled(true); m_ui->noKey->setEnabled(true); m_ui->customKey->setEnabled(true); } else { // It's a book since drop is enabled m_ui->textLabel->setText(i18n("Name of the &phrase book:")); m_ui->textLabel->setEnabled(true); m_ui->phrasebox->setEnabled(true); m_ui->lineEdit->setText(m_bookModel->data(selected, Qt::DisplayRole).toString()); m_ui->lineEdit->setEnabled(true); m_ui->shortcutLabel->setEnabled(false); m_ui->keyButton->clearKeySequence(); // Can't have a shortcut for a book m_ui->keyButton->setEnabled(false); m_ui->noKey->setChecked(false); m_ui->noKey->setEnabled(false); m_ui->customKey->setChecked(false); m_ui->customKey->setEnabled(false); } connectEditor(); phrasebookChanged = modified; } bool PhraseBookDialog::queryClose() { if (phrasebookChanged) { int answer = KMessageBox::questionYesNoCancel(this, i18n("There are unsaved changes.
Do you want to apply the changes before closing the \"phrase book\" window or discard the changes?
"), i18n("Closing \"Phrase Book\" Window"), KStandardGuiItem::apply(), KStandardGuiItem::discard(), KStandardGuiItem::cancel(), QStringLiteral("AutomaticSave")); if (answer == KMessageBox::Yes) { slotSave(); return true; } return (answer == KMessageBox::No); } return true; } void PhraseBookDialog::slotTextChanged(const QString &s) { QModelIndex selected = m_ui->treeView->selectionModel()->currentIndex(); QModelIndex textIndex = selected.sibling(selected.row(), kTextColumn); if (textIndex.isValid()) { m_bookModel->setData(textIndex, s); } } void PhraseBookDialog::slotNoKey() { m_ui->noKey->setChecked(true); m_ui->customKey->setChecked(false); // This shouldn't be needed because of the groupbox... FIXME QModelIndex selected = m_ui->treeView->selectionModel()->currentIndex(); QModelIndex shortcutIndex = selected.sibling(selected.row(), kShortcutColumn); if (shortcutIndex.isValid()) m_bookModel->setData(shortcutIndex, QString()); m_ui->keyButton->clearKeySequence(); } void PhraseBookDialog::slotCustomKey() { m_ui->keyButton->captureKeySequence(); } void PhraseBookDialog::slotKeySequenceChanged(const QKeySequence& sequence) { if (sequence.isEmpty()) { slotNoKey(); } else setShortcut(sequence); } void PhraseBookDialog::setShortcut(const QKeySequence& sequence) { // Check whether the shortcut is valid // const QList cutList = cut.toList(); // for (int i = 0; i < cutList.count(); i++) { // const QKeySequence& seq = cutList[i]; // //const KKey& key = seq.key(0); //#ifdef __GNUC__ //#warning "kde 4 port it"; //#endif //#if 0 // if (key.modFlags() == 0 && key.sym() < 0x3000 // && QChar(key.sym()).isLetterOrNumber()) // { // QString s = i18n("In order to use the '%1' key as a shortcut, " // "it must be combined with the " // "Win, Alt, Ctrl, and/or Shift keys.", QChar(key.sym())); // KMessageBox::sorry( this, s, i18n("Invalid Shortcut Key") ); // return; // } //#endif // } QModelIndex selected = m_ui->treeView->selectionModel()->currentIndex(); QModelIndex shortcutIndex = selected.sibling(selected.row(), kShortcutColumn); if (shortcutIndex.isValid()) m_bookModel->setData(shortcutIndex, sequence.toString()); //// If key isn't already in use, // // Update display m_ui->noKey->setChecked(false); m_ui->customKey->setChecked(true); m_ui->keyButton->setKeySequence(sequence); } void PhraseBookDialog::contextMenuRequested(const QPoint &pos) { QString name; if (m_ui->treeView->selectionModel()->hasSelection()) name = QStringLiteral("phrasebook_popup_sel"); else name = QStringLiteral("phrasebook_popup_nosel"); QMenu *popup = (QMenu *)factory()->container(name, this); if (popup != nullptr) { popup->popup(m_ui->treeView->mapToGlobal(pos), nullptr); } } void PhraseBookDialog::slotRemove() { if (m_ui->treeView->selectionModel()->hasSelection()) { QList selected = m_ui->treeView->selectionModel()->selectedRows(); qSort(selected.begin(), selected.end()); // Iterate over the rows backwards so we don't modify the .row of any indexes in selected. for (int i = selected.size() - 1; i >= 0; --i) { QModelIndex index = selected.at(i); m_bookModel->removeRows(index.row(), 1, index.parent()); } } } void PhraseBookDialog::slotCut() { slotCopy(); slotRemove(); } void PhraseBookDialog::slotCopy() { QList selected = m_ui->treeView->selectionModel()->selectedRows(); QString xml; foreach (const QModelIndex index, selected) { xml += serializeBook(index); } QMimeData *data = new QMimeData(); data->setText(xml); QApplication::clipboard()->setMimeData(data); } void PhraseBookDialog::slotPaste() { const QMimeData *data = QApplication::clipboard()->mimeData(); QModelIndex index = m_ui->treeView->selectionModel()->currentIndex(); QStandardItem *item = m_bookModel->itemFromIndex(index); while (item != nullptr && !item->isDropEnabled()) item = item->parent(); QDomDocument document; document.setContent(data->text()); QDomNode node = document.documentElement(); deserializeBook(node, item); } QModelIndex PhraseBookDialog::getCurrentParent() { QModelIndex currentIndex = m_ui->treeView->currentIndex(); QStandardItem *item = m_bookModel->itemFromIndex(currentIndex); if (item != nullptr && !item->isDropEnabled()) // If it's not a book currentIndex = currentIndex.parent(); return currentIndex; } void PhraseBookDialog::focusNewItem(const QModelIndex &parent, QStandardItem *item) { m_ui->treeView->expand(parent); QModelIndex newIndex = m_bookModel->indexFromItem(item); m_ui->treeView->setCurrentIndex(newIndex); m_ui->lineEdit->selectAll(); m_ui->lineEdit->setFocus(); } void PhraseBookDialog::slotAddPhrasebook() { QModelIndex parentIndex = getCurrentParent(); QStandardItem *parent = m_bookModel->itemFromIndex(parentIndex); QStandardItem *item = new QStandardItem(kPhraseBookIcon, i18n("(New Phrase Book)")); QStandardItem *shortcutItem = new QStandardItem(); QList items; items << item << shortcutItem; if (parent) parent->appendRow(items); else m_bookModel->appendRow(items); focusNewItem(parentIndex, item); } void PhraseBookDialog::slotAddPhrase() { QModelIndex parentIndex = getCurrentParent(); QStandardItem *parent = m_bookModel->itemFromIndex(parentIndex); QStandardItem *item = new QStandardItem(kPhraseIcon, i18n("(New Phrase)")); QStandardItem *shortcutItem = new QStandardItem(); item->setDropEnabled(false); shortcutItem->setDropEnabled(false); QList items; items << item << shortcutItem; if (parent) parent->appendRow(items); else m_bookModel->appendRow(items); focusNewItem(parentIndex, item); } void PhraseBookDialog::slotSave() { QString standardBook = QStandardPaths::locate(QStandardPaths::DataLocation, QStringLiteral("standard.phrasebook")); if (!standardBook.isNull() && !standardBook.isEmpty()) { QFile file(standardBook); file.open(QIODevice::WriteOnly); file.write(serializeBook(QModelIndex()).toUtf8()); file.close(); emit phrasebookConfirmed(); phrasebookChanged = false; fileSave->setEnabled(false); } } void PhraseBookDialog::slotImportPhrasebook() { QUrl url = QFileDialog::getOpenFileUrl(this, i18n("Import Phrasebook"), QUrl(), i18n("Phrase Books (*.phrasebook);Plain Text Files (*.txt);All Files (*)")); slotImportPhrasebook(url); } void PhraseBookDialog::slotImportPhrasebook(const QUrl &url) { if (!url.isEmpty()) { QModelIndex parentIndex = getCurrentParent(); QStandardItem *parentItem = m_bookModel->itemFromIndex(parentIndex); QFile file(url.toLocalFile()); if (file.open(QIODevice::ReadOnly)) { QDomDocument document; document.setContent(&file); QDomNode node = document.documentElement(); QStandardItem *item = nullptr; if (node.hasAttributes()) { // It has attributes, so add it directly item = deserializeBook(node, parentItem); } else { // It has no attributes, so add all it's children QDomNodeList nodes = node.childNodes(); for (int i = 0; i < nodes.count(); ++i) { QDomNode child = nodes.at(i); item = deserializeBook(child, parentItem); } } focusNewItem(parentIndex, item); } else { qDebug() << "Unable to open file " << url.toLocalFile(); KMessageBox::sorry(this, i18n("There was an error loading file\n%1", url.toLocalFile())); } } } void PhraseBookDialog::slotExportPhrasebook() { // Get the current book or if a phrase is selected get it's parent book to export. QModelIndex parentIndex = getCurrentParent(); QString content = kWholeBookXML.arg(serializeBook(parentIndex)); QUrl url = QFileDialog::getSaveFileUrl(this, i18n("Export Phrase Book"), QUrl(), i18n("Phrase Books (*.phrasebook)")); QFile file(url.toLocalFile()); if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { QTextStream out(&file); out << content; file.close(); } else { KMessageBox::sorry(this, i18n("There was an error saving file\n%1", url.toLocalFile())); } } //void PhraseBookDialog::slotPrint() //{ // if (printer == 0) { // printer = new QPrinter(); // } // QPrintDialog *printDialog = KdePrint::createPrintDialog(printer, this); // if (printDialog->exec()) { // PhraseBook book; // //treeView->fillBook (&book, treeView->hasSelectedItems()); // book.print(printer); // } // delete printDialog; //} diff --git a/phrasebook/phrasebookdialog.h b/phrasebook/phrasebookdialog.h index 9e8e898..023d097 100644 --- a/phrasebook/phrasebookdialog.h +++ b/phrasebook/phrasebookdialog.h @@ -1,164 +1,163 @@ /*************************************************************************** * Copyright (C) 2002 by Gunnar Schmi Dt * * * * 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. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef PHRASEBOOKDIALOG_H #define PHRASEBOOKDIALOG_H #include #include #include -#include #include #include //#include "phrasebook.h" #include "ui_phrasebookdialog.h" class KActionMenu; class KToolBarPopupAction; /** * The class StandardPhraseBookInsertAction implements an Action for * inserting a standard phrase book. * @author Gunnar Schmi Dt */ class StandardPhraseBookInsertAction : public QAction { Q_OBJECT public: StandardPhraseBookInsertAction(const QUrl &url, const QString& name, const QObject* receiver, const char* slot, KActionCollection* parent); ~StandardPhraseBookInsertAction(); public Q_SLOTS: void slotActivated(); Q_SIGNALS: void slotActivated(const QUrl &url); private: QUrl url; }; /** * The class PhraseBookDialog implements a dialog for editing phrase books. * @author Gunnar Schmi Dt */ class PhraseBookDialog : public KXmlGuiWindow { friend class InitialPhraseBookWidget; Q_OBJECT private: /** Constructor. It is private because this class implements the singleton * pattern. For creating the instance of the dialog, use the get() method. */ PhraseBookDialog(); public: /** Returns a pointer to the instance of this dialog. As a part off the * singleton pattern it will make sure that there is at most one instance * of the dialog at a given time. */ static PhraseBookDialog *get(); /** Destructor. */ ~PhraseBookDialog(); bool queryClose() override; public Q_SLOTS: void slotTextChanged(const QString &s); void slotNoKey(); void slotCustomKey(); void slotKeySequenceChanged(const QKeySequence& sequence); void selectionChanged(); void contextMenuRequested(const QPoint &pos); void slotRemove(); void slotCut(); void slotCopy(); void slotPaste(); void slotAddPhrasebook(); void slotAddPhrase(); void slotSave(); void slotImportPhrasebook(); void slotImportPhrasebook(const QUrl &url); void slotExportPhrasebook(); //void slotPrint (); void slotModelChanged(); Q_SIGNALS: void phrasebookConfirmed(); private: void initGUI(); /** initializes the KActions of the window */ void initActions(); /** initializes the list of standard phrase books */ void initStandardPhraseBooks(); void connectEditor(); void disconnectEditor(); // Deserialize the book from the given QDomNode and under the given parent // Return the new QStandardItem so it can get focused. QStandardItem* deserializeBook(const QDomNode &node, QStandardItem *parent); // Return a serialized string of the book or phrase at the given index. QString serializeBook(const QModelIndex &index); // Get the current parent, if the current index is not a book, get it's parent. QModelIndex getCurrentParent(); // Expand to, select and focus a new item from the given parameters void focusNewItem(const QModelIndex &parent, QStandardItem *item); void setShortcut(const QKeySequence &sequence); bool phrasebookChanged; QAction* fileNewPhrase; QAction* fileNewBook; QAction* fileSave; QAction* fileImport; KToolBarPopupAction* toolbarImport; KActionMenu* fileImportStandardBook; QAction* fileExport; //QAction* filePrint; QAction* fileClose; QAction* editCut; QAction* editCopy; QAction* editPaste; QAction* editDelete; QStandardItemModel* m_bookModel; QStandardItem *m_rootItem; // Keep QPrinter so settings persist //QPrinter *printer; Ui::PhraseBookDialog *m_ui; }; #endif diff --git a/wordcompletion/dictionarycreationwizard.cpp b/wordcompletion/dictionarycreationwizard.cpp index cb0e489..9e85df1 100644 --- a/wordcompletion/dictionarycreationwizard.cpp +++ b/wordcompletion/dictionarycreationwizard.cpp @@ -1,341 +1,339 @@ /*************************************************************************** * Copyright (C) 2002 by Gunnar Schmi Dt * * * * 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. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "dictionarycreationwizard.h" #include "wordlist.h" #include #include #include #include -#include #include #include #include -#include #include #include #include int CreationSourceWidget::nextId() const { int nextPage = -1; if (fileButton->isChecked()) { nextPage = DictionaryCreationWizard::FilePage; } else if (directoryButton->isChecked()) { nextPage = DictionaryCreationWizard::DirPage; } else if (kdeDocButton->isChecked()) { nextPage = DictionaryCreationWizard::KDEDocPage; } else if (mergeButton->isChecked()) { nextPage = DictionaryCreationWizard::MergePage; } return nextPage; } void CreationSourceWidget::emptyToggled(bool checked) { setFinalPage(checked); } DictionaryCreationWizard::DictionaryCreationWizard(QWidget *parent, const char *name, const QStringList &dictionaryNames, const QStringList &dictionaryFiles, const QStringList &dictionaryLanguages) : QWizard(parent) { buildCodecList(); creationSource = new CreationSourceWidget(this, QStringLiteral("source page")); creationSource->setTitle(i18n("Source of New Dictionary (1)")); setPage(CreationSourcePage, creationSource); setOption(QWizard::HaveHelpButton, false); //setFinishEnabled (creationSource, false); fileWidget = new CreationSourceDetailsWidget(this, QStringLiteral("file source page")); fileWidget->setTitle(i18n("Source of New Dictionary (2)")); fileWidget->setFinalPage(true); setPage(FilePage, fileWidget); buildCodecCombo(fileWidget->encodingCombo); dirWidget = new CreationSourceDetailsWidget(this, QStringLiteral("directory source page")); dirWidget->setTitle(i18n("Source of New Dictionary (2)")); dirWidget->setFinalPage(true); setPage(DirPage, dirWidget); dirWidget->urlLabel->setText(i18nc("In which directory is the file located?", "&Directory:")); dirWidget->urlLabel->setWhatsThis(i18n("With this input field you specify which directory you want to load for creating the new dictionary.")); dirWidget->url->setMode(KFile::Directory); dirWidget->url->setWhatsThis(i18n("With this input field you specify which directory you want to load for creating the new dictionary.")); buildCodecCombo(dirWidget->encodingCombo); kdeDocWidget = new KDEDocSourceWidget(this, "KDE documentation source page"); kdeDocWidget->setTitle(i18n("Source of New Dictionary (2)")); kdeDocWidget->setFinalPage(true); setPage(KDEDocPage, kdeDocWidget); kdeDocWidget->languageButton->showLanguageCodes(true); kdeDocWidget->languageButton->loadAllLanguages(); mergeWidget = new MergeWidget(this, "merge source page", dictionaryNames, dictionaryFiles, dictionaryLanguages); mergeWidget->setTitle(i18n("Source of New Dictionary (2)")); mergeWidget->setFinalPage(true); setPage(MergePage, mergeWidget); } DictionaryCreationWizard::~DictionaryCreationWizard() { delete codecList; } void DictionaryCreationWizard::buildCodecList() { codecList = new QList; QList availableCodecs = QTextCodec::availableCodecs(); for (int i = 0; i < availableCodecs.count(); ++i) { QTextCodec *codec = QTextCodec::codecForName(availableCodecs[i]); codecList->append(codec); } } void DictionaryCreationWizard::buildCodecCombo(KComboBox *combo) { QString local = i18nc("Local characterset", "Local") + QStringLiteral(" ("); local += QLatin1String(QTextCodec::codecForLocale()->name()) + QLatin1Char(')'); combo->addItem(local, 0); combo->addItem(i18nc("Latin characterset", "Latin1"), 1); combo->addItem(i18n("Unicode"), 2); for (int i = 0; i < codecList->count(); i++) combo->addItem(QLatin1String(codecList->at(i)->name()), i + 3); } QString DictionaryCreationWizard::createDictionary() { WordList::WordMap map; QString dicFile; QProgressDialog *pdlg = WordList::progressDialog(); if (creationSource->mergeButton->isChecked()) { map = WordList::mergeFiles(mergeWidget->mergeParameters(), pdlg); dicFile.clear(); } else if (creationSource->emptyButton->isChecked()) { dicFile.clear(); } else if (creationSource->fileButton->isChecked()) { QString filename = fileWidget->url->url().path(); int encoding = fileWidget->encodingCombo->currentIndex(); if (fileWidget->spellCheckBox->isChecked()) dicFile = fileWidget->ooDictURL->url().path(); switch (encoding) { case 0: map = WordList::parseFile(filename, QTextCodec::codecForLocale(), pdlg); break; case 1: map = WordList::parseFile(filename, QTextCodec::codecForName("ISO-8859-1"), pdlg); break; case 2: map = WordList::parseFile(filename, QTextCodec::codecForName("UTF-16"), pdlg); break; default: map = WordList::parseFile(filename, codecList->at(encoding - 3), pdlg); } } else if (creationSource->directoryButton->isChecked()) { QString directory = dirWidget->url->url().path(); int encoding = dirWidget->encodingCombo->currentIndex(); if (dirWidget->spellCheckBox->isChecked()) dicFile = dirWidget->ooDictURL->url().path(); switch (encoding) { case 0: map = WordList::parseDir(directory, QTextCodec::codecForLocale(), pdlg); break; case 1: map = WordList::parseDir(directory, QTextCodec::codecForName("ISO-8859-1"), pdlg); break; case 2: map = WordList::parseDir(directory, QTextCodec::codecForName("UTF-16"), pdlg); break; default: map = WordList::parseDir(directory, codecList->at(encoding - 3), pdlg); } } else { // creationSource->kdeDocButton must be checked QString language = kdeDocWidget->languageButton->current(); if (kdeDocWidget->spellCheckBox->isChecked()) dicFile = kdeDocWidget->ooDictURL->url().path(); map = WordList::parseKDEDoc(language, pdlg); } if (!dicFile.isEmpty() && !dicFile.isNull()) map = WordList::spellCheck(map, dicFile, pdlg); pdlg->close(); delete pdlg; int dictnumber = 0; QString filename; QString dictionaryFile; do { dictnumber++; filename = QStringLiteral("wordcompletion%1.dict").arg(dictnumber); dictionaryFile = QStandardPaths::locate(QStandardPaths::DataLocation, filename); } while (QFile::exists(dictionaryFile)); dictionaryFile = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') + QStringLiteral("/") + filename; if (WordList::saveWordList(map, dictionaryFile)) return filename; else return QLatin1String(""); } QString DictionaryCreationWizard::name() { if (creationSource->mergeButton->isChecked()) { return i18n("Merge result"); } else if (creationSource->emptyButton->isChecked()) { return i18nc("In the sense of a blank word list", "Empty list"); } else if (creationSource->fileButton->isChecked()) { return fileWidget->url->url().path(); } else if (creationSource->directoryButton->isChecked()) { return dirWidget->url->url().path(); } else { // creationSource->kdeDocButton must be checked return i18n("KDE Documentation"); } } QString DictionaryCreationWizard::language() { if (creationSource->mergeButton->isChecked()) { return mergeWidget->language(); } else if (creationSource->emptyButton->isChecked()) { return QLocale::languageToString(QLocale::system().language()); } else if (creationSource->fileButton->isChecked()) { return fileWidget->languageButton->current(); } else if (creationSource->directoryButton->isChecked()) { return dirWidget->languageButton->current(); } else { // creationSource->kdeDocButton must be checked return kdeDocWidget->languageButton->current(); } } /***************************************************************************/ MergeWidget::MergeWidget(QWidget *parent, const char *name, const QStringList &dictionaryNames, const QStringList &dictionaryFiles, const QStringList &dictionaryLanguages) : QWizardPage(parent) { QGridLayout *layout = new QGridLayout(this); layout->setColumnStretch(0, 0); layout->setColumnStretch(1, 1); int row = 0; QStringList::ConstIterator nIt = dictionaryNames.begin(); QStringList::ConstIterator fIt = dictionaryFiles.begin(); QStringList::ConstIterator lIt = dictionaryLanguages.begin(); for (; nIt != dictionaryNames.end(); ++nIt, ++fIt, ++lIt) { QCheckBox *checkbox = new QCheckBox(*nIt, this); QSpinBox *spinBox = new QSpinBox(this); layout->addWidget(checkbox, row, 0); layout->addWidget(spinBox, row, 1); checkbox->setChecked(true); spinBox->setRange(1, 100); spinBox->setSingleStep(10); spinBox->setValue(100); connect(checkbox, &QAbstractButton::toggled, spinBox, &QWidget::setEnabled); dictionaries.insert(*fIt, checkbox); weights.insert(*fIt, spinBox); languages [*fIt] = *lIt; row++; } setLayout(layout); } MergeWidget::~MergeWidget() { } QMap MergeWidget::mergeParameters() { QMap files; QHashIterator it(dictionaries); while (it.hasNext()) { it.next(); if (it.value()->isChecked()) { QString name = it.key(); QString dictionaryFile = QStandardPaths::locate(QStandardPaths::DataLocation, name); files[dictionaryFile] = weights.value(name)->value(); } } return files; } QString MergeWidget::language() { QHashIterator it(dictionaries); while (it.hasNext()) { it.next(); if (it.value()->isChecked()) { return languages [it.key()]; } } return QString(); } /***************************************************************************/ CompletionWizardWidget::CompletionWizardWidget(QWidget *parent, const char *name) : QWizardPage(parent) { setupUi(this); setObjectName(QLatin1String(name)); } CompletionWizardWidget::~CompletionWizardWidget() { } void CompletionWizardWidget::ok() { WordList::WordMap map; QProgressDialog *pdlg = WordList::progressDialog(); QString language = languageButton->current(); map = WordList::parseKDEDoc(language, pdlg); if (spellCheckBox->isChecked()) map = WordList::spellCheck(map, ooDictURL->url().path(), pdlg); pdlg->close(); delete pdlg; QString filename; QString dictionaryFile; dictionaryFile = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') + QStringLiteral("/"); qDebug() << "dictionaryFile is " << dictionaryFile; if (WordList::saveWordList(map, dictionaryFile)) { KConfigGroup cg(KSharedConfig::openConfig(), "Dictionary 0"); cg.writeEntry("Filename", "wordcompletion1.dict"); cg.writeEntry("Name", i18nc("Default dictionary", "Default")); cg.writeEntry("Language", language); cg.sync(); } } diff --git a/wordcompletion/wordcompletionwidget.cpp b/wordcompletion/wordcompletionwidget.cpp index f22ad76..5afc44a 100644 --- a/wordcompletion/wordcompletionwidget.cpp +++ b/wordcompletion/wordcompletionwidget.cpp @@ -1,275 +1,273 @@ /*************************************************************************** * Copyright (C) 2002 by Gunnar Schmi Dt * * * * 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. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "wordcompletionwidget.h" #include #include #include #include -#include #include -#include #include #include #include #include #include "dictionarycreationwizard.h" #include "wordcompletion.h" WordCompletionWidget::WordCompletionWidget(QWidget *parent, const char *name) : QWidget(parent) { setupUi(this); setObjectName(QLatin1String(name)); model = new QStandardItemModel(0, 2, this); dictionaryView->setModel(model); languageButton->showLanguageCodes(true); languageButton->loadAllLanguages(); // Connect the signals from hte KCMKTTSDWidget to this class connect(addButton, &QAbstractButton::clicked, this, &WordCompletionWidget::addDictionary); connect(deleteButton, &QAbstractButton::clicked, this, &WordCompletionWidget::deleteDictionary); connect(moveUpButton, &QAbstractButton::clicked, this, &WordCompletionWidget::moveUp); connect(moveDownButton, &QAbstractButton::clicked, this, &WordCompletionWidget::moveDown); connect(exportButton, &QAbstractButton::clicked, this, &WordCompletionWidget::exportDictionary); connect(dictionaryView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &WordCompletionWidget::selectionChanged); connect(dictionaryName, &QLineEdit::textChanged, this, &WordCompletionWidget::nameChanged); connect(languageButton, &KLanguageButton::activated, this, &WordCompletionWidget::languageSelected); // Load the configuration from the file load(); } /** * Destructor */ WordCompletionWidget::~WordCompletionWidget() { } /***************************************************************************/ void WordCompletionWidget::load() { model->clear(); QStringList labels; labels << i18n("Dictionary") << i18n("Language"); model->setHorizontalHeaderLabels(labels); // Set the group general for the configuration of kttsd itself (no plug ins) const QStringList groups = KSharedConfig::openConfig()->groupList(); for (QStringList::const_iterator it = groups.constBegin(); it != groups.constEnd(); ++it) if ((*it).startsWith(QLatin1String("Dictionary "))) { KConfigGroup cg(KSharedConfig::openConfig(), *it); QString filename = cg.readEntry("Filename"); QString languageTag = cg.readEntry("Language"); QStandardItem *nameItem = new QStandardItem(cg.readEntry("Name")); nameItem->setData(filename); QStandardItem *languageItem = new QStandardItem(languageTag); QList items; items.append(nameItem); items.append(languageItem); model->appendRow(items); if (!languageButton->contains(languageTag)) languageButton->insertLanguage(languageTag, i18n("without name")); } // Clean up disc space for (QStringList::const_iterator it = newDictionaryFiles.constBegin(); it != newDictionaryFiles.constEnd(); ++it) { QString filename = QStandardPaths::locate(QStandardPaths::DataLocation, *it); if (!filename.isEmpty() && !filename.isNull()) QFile::remove(filename); } newDictionaryFiles.clear(); } void WordCompletionWidget::save() { const QStringList groups = KSharedConfig::openConfig()->groupList(); for (QStringList::const_iterator it = groups.constBegin(); it != groups.constEnd(); ++it) if ((*it).startsWith(QLatin1String("Dictionary "))) KSharedConfig::openConfig()->deleteGroup(*it); int row = 0; for (int row = 0; row < model->rowCount(); ++row) { const QStandardItem *nameItem = model->item(row, 0); const QStandardItem *languageItem = model->item(row, 1); KConfigGroup cg(KSharedConfig::openConfig(), QStringLiteral("Dictionary %1").arg(row)); cg.writeEntry("Filename", nameItem->data().toString()); cg.writeEntry("Name", nameItem->text()); cg.writeEntry("Language", languageItem->text()); } KSharedConfig::openConfig()->sync(); // Clean up disc space for (QStringList::const_iterator it = removedDictionaryFiles.constBegin(); it != removedDictionaryFiles.constEnd(); ++it) { QString filename = QStandardPaths::locate(QStandardPaths::DataLocation, *it); if (!filename.isEmpty() && !filename.isNull()) QFile::remove(filename); } removedDictionaryFiles.clear(); } /***************************************************************************/ void WordCompletionWidget::addDictionary() { QStringList dictionaryNames; QStringList dictionaryFiles; QStringList dictionaryLanguages; for (int row = 0; row < model->rowCount(); ++row) { const QStandardItem *nameItem = model->item(row, 0); const QStandardItem *languageItem = model->item(row, 1); dictionaryNames += nameItem->text(); dictionaryFiles += nameItem->data().toString(); dictionaryLanguages += languageItem->text(); } DictionaryCreationWizard *wizard = new DictionaryCreationWizard(this, "Dictionary creation wizard", dictionaryNames, dictionaryFiles, dictionaryLanguages); if (wizard->exec() == QDialog::Accepted) { QString filename = wizard->createDictionary(); newDictionaryFiles += filename; QString languageTag = wizard->language(); if (!languageButton->contains(languageTag)) { languageButton->insertLanguage(languageTag, i18n("without name")); } QStandardItem *nameItem = new QStandardItem(wizard->name()); nameItem->setData(filename); QStandardItem *languageItem = new QStandardItem(languageTag); QList items; items.append(nameItem); items.append(languageItem); model->appendRow(items); } delete wizard; } void WordCompletionWidget::deleteDictionary() { int row = dictionaryView->currentIndex().row(); const QStandardItem *nameItem = model->item(row, 0); if (nameItem != nullptr) { removedDictionaryFiles += nameItem->data().toString(); qDeleteAll(model->takeRow(row)); } } void WordCompletionWidget::moveUp() { int row = dictionaryView->currentIndex().row(); if (row > 0) { QList items = model->takeRow(row); model->insertRow(row - 1, items); dictionaryView->setCurrentIndex(model->index(row - 1, 0)); } } void WordCompletionWidget::moveDown() { int row = dictionaryView->currentIndex().row(); if (row < model->rowCount() - 1) { QList items = model->takeRow(row); model->insertRow(row + 1, items); dictionaryView->setCurrentIndex(model->index(row + 1, 0)); } } void WordCompletionWidget::exportDictionary() { const QStandardItem *nameItem = model->item(dictionaryView->currentIndex().row(), 0); if (nameItem != nullptr) { QUrl url = QFileDialog::getSaveFileUrl(this, i18n("Export Dictionary")); if (url.isEmpty() || !url.isValid()) return; if (url.isLocalFile() && QFile::exists(url.toLocalFile())) { if (KMessageBox::warningContinueCancel(nullptr, QStringLiteral("%1").arg(i18n("The file %1 already exists. " "Do you want to overwrite it?", url.url())), i18n("File Exists"), KGuiItem(i18n("&Overwrite"))) == KMessageBox::Cancel) { return; } } QUrl src; src.setPath(QStandardPaths::locate(QStandardPaths::DataLocation, nameItem->data().toString())); KIO::FileCopyJob *job = KIO::file_copy(src, url); job->exec(); } } void WordCompletionWidget::selectionChanged() { QModelIndex current = dictionaryView->currentIndex(); deleteButton->setEnabled(current.isValid()); exportButton->setEnabled(current.isValid()); selectedDictionaryDetails->setEnabled(current.isValid()); moveUpButton->setEnabled(current.isValid() && current.row() > 0); moveDownButton->setEnabled(current.isValid() && current.row() < model->rowCount() - 1); if (current.isValid()) { const QStandardItem *nameItem = model->item(current.row(), 0); const QStandardItem *languageItem = model->item(current.row(), 1); dictionaryName->setText(nameItem->text()); languageButton->setCurrentItem(languageItem->text()); } else { dictionaryName->clear(); } } void WordCompletionWidget::nameChanged(const QString &text) { const QStandardItem *nameItem = model->item(dictionaryView->currentIndex().row(), 0); if (nameItem != nullptr) { QString old = nameItem->text(); if (old != text) { QStandardItem *newItem = new QStandardItem(text); newItem->setData(nameItem->data()); model->setItem(dictionaryView->currentIndex().row(), 0, newItem); emit changed(true); } } } void WordCompletionWidget::languageSelected() { const QStandardItem *languageItem = model->item(dictionaryView->currentIndex().row(), 1); if (languageItem != nullptr) { QString old = languageItem->text(); QString text = languageButton->current(); if (old != text) { QStandardItem *newItem = new QStandardItem(text); model->setItem(dictionaryView->currentIndex().row(), 1, newItem); emit changed(true); } } }