1 /***************************************************************************
2  *   Copyright (C) 2002 by Gunnar Schmi Dt <kmouth@schmi-dt.de             *
3  *             (C) 2015 by Jeremy Whiting <jpwhiting@kde.org>              *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
19  ***************************************************************************/
20 
21 #include "dictionarycreationwizard.h"
22 #include "wordlist.h"
23 
24 #include <QCheckBox>
25 #include <QLocale>
26 #include <QGridLayout>
27 #include <QProgressDialog>
28 #include <QSpinBox>
29 #include <QStandardPaths>
30 #include <QTextCodec>
31 
32 #include <QDebug>
33 
34 #include <KConfigGroup>
35 #include <KSharedConfig>
36 
nextId() const37 int CreationSourceWidget::nextId() const
38 {
39     int nextPage = -1;
40     if (fileButton->isChecked()) {
41         nextPage = DictionaryCreationWizard::FilePage;
42     } else if (directoryButton->isChecked()) {
43         nextPage = DictionaryCreationWizard::DirPage;
44     } else if (kdeDocButton->isChecked()) {
45         nextPage = DictionaryCreationWizard::KDEDocPage;
46     } else if (mergeButton->isChecked()) {
47         nextPage = DictionaryCreationWizard::MergePage;
48     }
49     return nextPage;
50 }
51 
emptyToggled(bool checked)52 void CreationSourceWidget::emptyToggled(bool checked)
53 {
54     setFinalPage(checked);
55 }
56 
DictionaryCreationWizard(QWidget * parent,const QStringList & dictionaryNames,const QStringList & dictionaryFiles,const QStringList & dictionaryLanguages)57 DictionaryCreationWizard::DictionaryCreationWizard(QWidget *parent,
58         const QStringList &dictionaryNames, const QStringList &dictionaryFiles,
59         const QStringList &dictionaryLanguages)
60     : QWizard(parent)
61 {
62     buildCodecList();
63 
64     creationSource = new CreationSourceWidget(this, QStringLiteral("source page"));
65     creationSource->setTitle(i18n("Source of New Dictionary (1)"));
66     setPage(CreationSourcePage, creationSource);
67     setOption(QWizard::HaveHelpButton, false);
68     //setFinishEnabled (creationSource, false);
69 
70     fileWidget = new CreationSourceDetailsWidget(this, QStringLiteral("file source page"));
71     fileWidget->setTitle(i18n("Source of New Dictionary (2)"));
72     fileWidget->setFinalPage(true);
73     setPage(FilePage, fileWidget);
74     buildCodecCombo(fileWidget->encodingCombo);
75 
76     dirWidget = new CreationSourceDetailsWidget(this, QStringLiteral("directory source page"));
77     dirWidget->setTitle(i18n("Source of New Dictionary (2)"));
78     dirWidget->setFinalPage(true);
79     setPage(DirPage, dirWidget);
80     dirWidget->urlLabel->setText(i18nc("In which directory is the file located?", "&Directory:"));
81     dirWidget->urlLabel->setWhatsThis(i18n("With this input field you specify which directory you want to load for creating the new dictionary."));
82     dirWidget->url->setMode(KFile::Directory);
83     dirWidget->url->setWhatsThis(i18n("With this input field you specify which directory you want to load for creating the new dictionary."));
84     buildCodecCombo(dirWidget->encodingCombo);
85 
86     kdeDocWidget = new KDEDocSourceWidget(this, "KDE documentation source page");
87     kdeDocWidget->setTitle(i18n("Source of New Dictionary (2)"));
88     kdeDocWidget->setFinalPage(true);
89     setPage(KDEDocPage, kdeDocWidget);
90     kdeDocWidget->languageButton->showLanguageCodes(true);
91     kdeDocWidget->languageButton->loadAllLanguages();
92 
93     mergeWidget = new MergeWidget(this, "merge source page", dictionaryNames, dictionaryFiles, dictionaryLanguages);
94     mergeWidget->setTitle(i18n("Source of New Dictionary (2)"));
95     mergeWidget->setFinalPage(true);
96     setPage(MergePage, mergeWidget);
97 }
98 
~DictionaryCreationWizard()99 DictionaryCreationWizard::~DictionaryCreationWizard()
100 {
101     delete codecList;
102 }
103 
buildCodecList()104 void DictionaryCreationWizard::buildCodecList()
105 {
106     codecList = new QList<QTextCodec*>;
107     QList<QByteArray> availableCodecs = QTextCodec::availableCodecs();
108     for (int i = 0; i < availableCodecs.count(); ++i) {
109         QTextCodec *codec = QTextCodec::codecForName(availableCodecs[i]);
110         codecList->append(codec);
111     }
112 }
113 
buildCodecCombo(KComboBox * combo)114 void DictionaryCreationWizard::buildCodecCombo(KComboBox *combo)
115 {
116     QString local = i18nc("Local characterset", "Local") + QStringLiteral(" (");
117     local += QLatin1String(QTextCodec::codecForLocale()->name()) + QLatin1Char(')');
118     combo->addItem(local, 0);
119     combo->addItem(i18nc("Latin characterset", "Latin1"), 1);
120     combo->addItem(i18n("Unicode"), 2);
121 
122     for (int i = 0; i < codecList->count(); i++)
123         combo->addItem(QLatin1String(codecList->at(i)->name()), i + 3);
124 }
125 
createDictionary()126 QString DictionaryCreationWizard::createDictionary()
127 {
128     WordList::WordMap map;
129     QString dicFile;
130     QProgressDialog *pdlg = WordList::progressDialog();
131 
132     if (creationSource->mergeButton->isChecked()) {
133         map = WordList::mergeFiles(mergeWidget->mergeParameters(), pdlg);
134         dicFile.clear();
135     } else if (creationSource->emptyButton->isChecked()) {
136         dicFile.clear();
137     } else if (creationSource->fileButton->isChecked()) {
138         QString filename = fileWidget->url->url().path();
139         int encoding = fileWidget->encodingCombo->currentIndex();
140         if (fileWidget->spellCheckBox->isChecked())
141             dicFile = fileWidget->ooDictURL->url().path();
142         switch (encoding) {
143         case 0:
144             map = WordList::parseFile(filename, QTextCodec::codecForLocale(), pdlg);
145             break;
146         case 1:
147             map = WordList::parseFile(filename, QTextCodec::codecForName("ISO-8859-1"), pdlg);
148             break;
149         case 2:
150             map = WordList::parseFile(filename, QTextCodec::codecForName("UTF-16"), pdlg);
151             break;
152         default:
153             map = WordList::parseFile(filename, codecList->at(encoding - 3), pdlg);
154         }
155     } else if (creationSource->directoryButton->isChecked()) {
156         QString directory = dirWidget->url->url().path();
157         int encoding = dirWidget->encodingCombo->currentIndex();
158         if (dirWidget->spellCheckBox->isChecked())
159             dicFile = dirWidget->ooDictURL->url().path();
160         switch (encoding) {
161         case 0:
162             map = WordList::parseDir(directory, QTextCodec::codecForLocale(), pdlg);
163             break;
164         case 1:
165             map = WordList::parseDir(directory, QTextCodec::codecForName("ISO-8859-1"), pdlg);
166             break;
167         case 2:
168             map = WordList::parseDir(directory, QTextCodec::codecForName("UTF-16"), pdlg);
169             break;
170         default:
171             map = WordList::parseDir(directory, codecList->at(encoding - 3), pdlg);
172         }
173     } else { // creationSource->kdeDocButton must be checked
174         QString language = kdeDocWidget->languageButton->current();
175         if (kdeDocWidget->spellCheckBox->isChecked())
176             dicFile = kdeDocWidget->ooDictURL->url().path();
177         map = WordList::parseKDEDoc(language, pdlg);
178     }
179 
180     if (!dicFile.isEmpty() && !dicFile.isNull())
181         map = WordList::spellCheck(map, dicFile, pdlg);
182     pdlg->close();
183     delete pdlg;
184 
185     int dictnumber = 0;
186     QString filename;
187     QString dictionaryFile;
188     do {
189         dictnumber++;
190         filename = QStringLiteral("wordcompletion%1.dict").arg(dictnumber);
191         dictionaryFile = QStandardPaths::locate(QStandardPaths::DataLocation, filename);
192     } while (QFile::exists(dictionaryFile));
193 
194     dictionaryFile = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') + QStringLiteral("/") + filename;
195     if (WordList::saveWordList(map, dictionaryFile))
196         return filename;
197     else
198         return QLatin1String("");
199 }
200 
name()201 QString DictionaryCreationWizard::name()
202 {
203     if (creationSource->mergeButton->isChecked()) {
204         return i18n("Merge result");
205     } else if (creationSource->emptyButton->isChecked()) {
206         return i18nc("In the sense of a blank word list", "Empty list");
207     } else if (creationSource->fileButton->isChecked()) {
208         return fileWidget->url->url().path();
209     } else if (creationSource->directoryButton->isChecked()) {
210         return dirWidget->url->url().path();
211     } else { // creationSource->kdeDocButton must be checked
212         return i18n("KDE Documentation");
213     }
214 }
215 
language()216 QString DictionaryCreationWizard::language()
217 {
218     if (creationSource->mergeButton->isChecked()) {
219         return mergeWidget->language();
220     } else if (creationSource->emptyButton->isChecked()) {
221         return QLocale::languageToString(QLocale::system().language());
222     } else if (creationSource->fileButton->isChecked()) {
223         return fileWidget->languageButton->current();
224     } else if (creationSource->directoryButton->isChecked()) {
225         return dirWidget->languageButton->current();
226     } else { // creationSource->kdeDocButton must be checked
227         return kdeDocWidget->languageButton->current();
228     }
229 }
230 
231 /***************************************************************************/
232 
MergeWidget(QWidget * parent,const char * name,const QStringList & dictionaryNames,const QStringList & dictionaryFiles,const QStringList & dictionaryLanguages)233 MergeWidget::MergeWidget(QWidget *parent, const char *name,
234                          const QStringList &dictionaryNames, const QStringList &dictionaryFiles,
235                          const QStringList &dictionaryLanguages)
236     : QWizardPage(parent)
237 {
238     QGridLayout *layout = new QGridLayout(this);
239     layout->setColumnStretch(0, 0);
240     layout->setColumnStretch(1, 1);
241 
242     int row = 0;
243     QStringList::ConstIterator nIt = dictionaryNames.begin();
244     QStringList::ConstIterator fIt = dictionaryFiles.begin();
245     QStringList::ConstIterator lIt = dictionaryLanguages.begin();
246     for (; nIt != dictionaryNames.end(); ++nIt, ++fIt, ++lIt) {
247         QCheckBox *checkbox = new QCheckBox(*nIt, this);
248         QSpinBox *spinBox = new QSpinBox(this);
249         layout->addWidget(checkbox, row, 0);
250         layout->addWidget(spinBox, row, 1);
251 
252         checkbox->setChecked(true);
253         spinBox->setRange(1, 100);
254         spinBox->setSingleStep(10);
255         spinBox->setValue(100);
256         connect(checkbox, &QAbstractButton::toggled, spinBox, &QWidget::setEnabled);
257 
258         dictionaries.insert(*fIt, checkbox);
259         weights.insert(*fIt, spinBox);
260         languages [*fIt] = *lIt;
261         row++;
262     }
263     setLayout(layout);
264 }
265 
~MergeWidget()266 MergeWidget::~MergeWidget()
267 {
268 }
269 
mergeParameters()270 QMap <QString, int> MergeWidget::mergeParameters()
271 {
272     QMap <QString, int> files;
273     QHashIterator<QString, QCheckBox*> it(dictionaries);
274     while (it.hasNext()) {
275         it.next();
276         if (it.value()->isChecked()) {
277             QString name = it.key();
278             QString dictionaryFile = QStandardPaths::locate(QStandardPaths::DataLocation, name);
279             files[dictionaryFile] = weights.value(name)->value();
280         }
281     }
282 
283     return files;
284 }
285 
language()286 QString MergeWidget::language()
287 {
288     QHashIterator<QString, QCheckBox*> it(dictionaries);
289     while (it.hasNext()) {
290         it.next();
291         if (it.value()->isChecked()) {
292             return languages [it.key()];
293         }
294     }
295 
296     return QString();
297 }
298 
299 /***************************************************************************/
300 
CompletionWizardWidget(QWidget * parent,const char * name)301 CompletionWizardWidget::CompletionWizardWidget(QWidget *parent, const char *name)
302     : QWizardPage(parent)
303 {
304     setupUi(this);
305     setObjectName(QLatin1String(name));
306 }
307 
~CompletionWizardWidget()308 CompletionWizardWidget::~CompletionWizardWidget()
309 {
310 }
311 
ok()312 void CompletionWizardWidget::ok()
313 {
314     WordList::WordMap map;
315     QProgressDialog *pdlg = WordList::progressDialog();
316 
317     QString language = languageButton->current();
318     map = WordList::parseKDEDoc(language, pdlg);
319 
320     if (spellCheckBox->isChecked())
321         map = WordList::spellCheck(map, ooDictURL->url().path(), pdlg);
322 
323     pdlg->close();
324     delete pdlg;
325 
326     QString filename;
327     QString dictionaryFile;
328 
329     dictionaryFile = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') + QStringLiteral("/");
330     qDebug() << "dictionaryFile is " << dictionaryFile;
331     if (WordList::saveWordList(map, dictionaryFile)) {
332         KConfigGroup cg(KSharedConfig::openConfig(), "Dictionary 0");
333         cg.writeEntry("Filename", "wordcompletion1.dict");
334         cg.writeEntry("Name",     i18nc("Default dictionary", "Default"));
335         cg.writeEntry("Language", language);
336         cg.sync();
337     }
338 }
339 
340