/***************************************************************************** * Eliot * Copyright (C) 2008-2012 Olivier Teulière * Authors: Olivier Teulière * * 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 St, Fifth Floor, Boston, MA 02110-1301 USA *****************************************************************************/ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include "dic_tools_widget.h" #include "custom_popup.h" #include "validator_factory.h" #include "qtcommon.h" #include "dic.h" #include "header.h" #include "listdic.h" #include "encoding.h" #include "dic_exception.h" using namespace std; INIT_LOGGER(qt, DicToolsWidget); DicToolsWidget::DicToolsWidget(QWidget *parent) : QWidget(parent), m_dic(NULL) { setupUi(this); redPalette = labelCheck->palette(); redPalette.setColor(QPalette::Foreground, Qt::red); darkYellowPalette = labelCheck->palette(); darkYellowPalette.setColor(QPalette::Foreground, Qt::darkYellow); greenPalette = labelCheck->palette(); greenPalette.setColor(QPalette::Foreground, Qt::darkGreen); labelLimitReached->hide(); // Create connections QObject::connect(lineEditCheck, SIGNAL(textChanged(const QString&)), this, SLOT(refreshCheck())); QObject::connect(lineEditPlus1, SIGNAL(textChanged(const QString&)), this, SLOT(enableSearchPlus1())); QObject::connect(lineEditPlus1, SIGNAL(returnPressed()), this, SLOT(refreshPlus1())); QObject::connect(buttonSearchPlus1, SIGNAL(clicked()), this, SLOT(refreshPlus1())); QObject::connect(lineEditRegexp, SIGNAL(textChanged(const QString&)), this, SLOT(enableSearchRegexp())); QObject::connect(lineEditRegexp, SIGNAL(returnPressed()), this, SLOT(refreshRegexp())); QObject::connect(buttonSearchRegexp, SIGNAL(clicked()), this, SLOT(refreshRegexp())); QObject::connect(buttonSaveRegexp, SIGNAL(clicked()), this, SLOT(saveRegexpResults())); QObject::connect(buttonSaveWords, SIGNAL(clicked()), this, SLOT(exportWordsList())); // Add context menus for the results m_customPopupPlus1 = new CustomPopup(treeViewPlus1); QObject::connect(m_customPopupPlus1, SIGNAL(popupCreated(QMenu&, const QPoint&)), this, SLOT(populateMenuPlus1(QMenu&, const QPoint&))); QObject::connect(m_customPopupPlus1, SIGNAL(requestDefinition(QString)), this, SIGNAL(requestDefinition(QString))); m_customPopupRegexp = new CustomPopup(treeViewRegexp); QObject::connect(m_customPopupRegexp, SIGNAL(popupCreated(QMenu&, const QPoint&)), this, SLOT(populateMenuRegexp(QMenu&, const QPoint&))); QObject::connect(m_customPopupRegexp, SIGNAL(requestDefinition(QString)), this, SIGNAL(requestDefinition(QString))); // Create models m_plus1Model = new QStandardItemModel(this); treeViewPlus1->setModel(m_plus1Model); m_plus1Model->setColumnCount(1); m_plus1Model->setHeaderData(0, Qt::Horizontal, _q("Rack:"), Qt::DisplayRole); m_regexpModel = new QStandardItemModel(this); treeViewRegexp->setModel(m_regexpModel); m_regexpModel->setColumnCount(1); m_regexpModel->setHeaderData(0, Qt::Horizontal, _q("Rack:"), Qt::DisplayRole); m_dicInfoModel = new QStandardItemModel(this); treeViewDicLetters->setModel(m_dicInfoModel); m_dicInfoModel->setColumnCount(6); m_dicInfoModel->setHeaderData(0, Qt::Horizontal, _q("Letter"), Qt::DisplayRole); m_dicInfoModel->setHeaderData(1, Qt::Horizontal, _q("Points"), Qt::DisplayRole); m_dicInfoModel->setHeaderData(2, Qt::Horizontal, _q("Frequency"), Qt::DisplayRole); m_dicInfoModel->setHeaderData(3, Qt::Horizontal, _q("Vowel?"), Qt::DisplayRole); m_dicInfoModel->setHeaderData(4, Qt::Horizontal, _q("Consonant?"), Qt::DisplayRole); m_dicInfoModel->setHeaderData(5, Qt::Horizontal, _q("Alternative inputs"), Qt::DisplayRole); } void DicToolsWidget::setDic(const Dictionary *iDic) { if (m_dic != iDic) { m_dic = iDic; // Reset the letters lineEditCheck->clear(); lineEditPlus1->clear(); lineEditRegexp->clear(); // Create new validators lineEditCheck->setValidator(ValidatorFactory::newDicRackValidator(this, m_dic)); lineEditPlus1->setValidator(ValidatorFactory::newDicRackValidator(this, m_dic, true)); lineEditRegexp->setValidator(ValidatorFactory::newRegexpValidator(this, m_dic)); // Refresh refreshCheck(); refreshPlus1(); refreshRegexp(); refreshDicInfo(); } } void DicToolsWidget::setPlus1Rack(const QString &iRack) { lineEditPlus1->setText(iRack); refreshPlus1(); } void DicToolsWidget::refreshCheck() { QLineEdit *rack = lineEditCheck; if (m_dic == NULL) { labelCheck->setText(_q("Please select a dictionary")); return; } if (rack->text() == "") labelCheck->setText(""); else { if (!rack->hasAcceptableInput()) { labelCheck->setText(_q("Invalid or incomplete letters")); labelCheck->setPalette(darkYellowPalette); return; } wstring input = m_dic->convertFromInput(wfq(rack->text())); bool res = m_dic->searchWord(input); // Convert the input to uppercase input = toUpper(input); const wdstring &dispStr = m_dic->convertToDisplay(input); if (res) { labelCheck->setText(_q("The word '%1' exists").arg(qfw(dispStr))); labelCheck->setPalette(greenPalette); } else { labelCheck->setText(_q("The word '%1' does not exist").arg(qfw(dispStr))); labelCheck->setPalette(redPalette); } } } void DicToolsWidget::enableSearchPlus1() { buttonSearchPlus1->setEnabled(lineEditPlus1->text() != ""); } void DicToolsWidget::refreshPlus1() { QStandardItemModel *model = m_plus1Model; QTreeView *treeView = treeViewPlus1; QLineEdit *rack = lineEditPlus1; model->removeRows(0, model->rowCount()); if (m_dic == NULL) { model->setHeaderData(0, Qt::Horizontal, _q("Please select a dictionary"), Qt::DisplayRole); return; } const wstring &input = m_dic->convertFromInput(wfq(rack->text().toUpper())); const wdstring &disp = m_dic->convertToDisplay(input); model->setHeaderData(0, Qt::Horizontal, _q("Rack: %1").arg(qfw(disp)), Qt::DisplayRole); if (input != L"") { map > wordList; m_dic->search7pl1(input, wordList, true); int rowNum = 0; map >::const_iterator it; for (it = wordList.begin(); it != wordList.end(); it++) { // Create the header line model->insertRow(rowNum); const QModelIndex &index = model->index(rowNum, 0); if (it->first != 0) model->setData(index, qfw(m_dic->getHeader().getDisplayStr(it->first))); else model->setData(index, _q("Anagrams")); treeView->setExpanded(index, true); ++rowNum; // Create the result lines model->insertColumn(0, index); model->insertRows(0, it->second.size(), index); const vector &results = it->second; for (unsigned i = 0; i < results.size(); ++i) { model->setData(model->index(i, 0, index), qfw(results[i])); } } } } void DicToolsWidget::enableSearchRegexp() { bool hasText = lineEditRegexp->text() != ""; buttonSearchRegexp->setEnabled(hasText); buttonSaveRegexp->setEnabled(m_dic != NULL && hasText); } void DicToolsWidget::refreshRegexp() { QStandardItemModel *model = m_regexpModel; QLineEdit *rack = lineEditRegexp; model->removeRows(0, model->rowCount()); if (m_dic == NULL) { model->setHeaderData(0, Qt::Horizontal, _q("Please select a dictionary"), Qt::DisplayRole); return; } const wstring &input = m_dic->convertFromInput(wfq(rack->text().toUpper())); const wdstring &disp = m_dic->convertToDisplay(input); model->setHeaderData(0, Qt::Horizontal, _q("Regular expression: %1").arg(qfw(disp)), Qt::DisplayRole); if (input != L"") { unsigned lmin = spinBoxMinLength->value(); unsigned lmax = spinBoxMaxLength->value(); // FIXME: this value should not be hardcoded, // or a warning should appear when it is reached unsigned limit = 1000; vector wordList; bool res = true; int rowNum = 0; try { res = m_dic->searchRegExp(input, wordList, lmin, lmax, limit); } catch (InvalidRegexpException &e) { model->insertRow(rowNum); model->setData(model->index(rowNum, 0), _q("Invalid regular expression: %1").arg(qfl(e.what()))); model->setData(model->index(rowNum, 0), QBrush(Qt::red), Qt::ForegroundRole); } vector::const_iterator it; for (it = wordList.begin(); it != wordList.end(); it++) { model->insertRow(rowNum); model->setData(model->index(rowNum, 0), qfw(*it)); ++rowNum; } if (res) labelLimitReached->hide(); else labelLimitReached->show(); } } void DicToolsWidget::saveRegexpResults() { if (m_dic == NULL) return; QString fileName = QFileDialog::getSaveFileName(this, _q("Save words list")); if (fileName != "") { const wstring &input = m_dic->convertFromInput(wfq(lineEditRegexp->text().toUpper())); unsigned lmin = spinBoxMinLength->value(); unsigned lmax = spinBoxMaxLength->value(); vector wordList; try { m_dic->searchRegExp(input, wordList, lmin, lmax, 0); } catch (InvalidRegexpException &e) { QMessageBox::warning(this, _q("Eliot - Error"), _q("Invalid regular expression: %1").arg(qfl(e.what()))); return; } try { ofstream file(lfq(fileName).c_str()); foreach (const wstring &word, wordList) { file << lfw(word) << endl; } QMessageBox::information(this, _q("Save words list"), _q("File '%1' successfully saved").arg(fileName)); } catch (std::exception &e) { QMessageBox::warning(this, _q("Eliot - Error"), _q("Cannot save the words list: %1").arg(e.what())); } } } void DicToolsWidget::refreshDicInfo() { if (m_dic == NULL) { lineEditName->setText(""); lineEditLetters->setText(""); spinBoxWords->setValue(0); m_dicInfoModel->clear(); } else { const Header &header = m_dic->getHeader(); lineEditName->setText(qfw(header.getName())); lineEditLetters->setText(qfw(m_dic->convertToDisplay(header.getLetters()))); spinBoxWords->setValue(header.getNbWords()); QStandardItemModel *model = m_dicInfoModel; model->removeRows(0, model->rowCount()); const vector &allTiles = m_dic->getAllTiles(); vector::const_iterator it; int rowNum = 0; for (it = allTiles.begin(); it != allTiles.end(); ++it) { model->insertRow(rowNum); model->setData(model->index(rowNum, 0), qfw(it->getDisplayStr())); model->setData(model->index(rowNum, 1), it->getPoints()); model->setData(model->index(rowNum, 2), it->maxNumber()); model->setData(model->index(rowNum, 3), it->isVowel() ? _q("Yes") : _q("No")); model->setData(model->index(rowNum, 4), it->isConsonant() ? _q("Yes") : _q("No")); const vector &inputVect = it->getInputStr(); wstring tmp; for (unsigned int i = 1; i < inputVect.size(); ++i) { tmp += inputVect[i] + L" "; } model->setData(model->index(rowNum, 5), qfw(tmp)); // Center the text in the column for (int col = 0; col < 5; ++col) { model->item(rowNum, col)->setTextAlignment(Qt::AlignCenter); } ++rowNum; } treeViewDicLetters->resizeColumnToContents(0); treeViewDicLetters->resizeColumnToContents(1); treeViewDicLetters->resizeColumnToContents(2); treeViewDicLetters->resizeColumnToContents(3); treeViewDicLetters->resizeColumnToContents(4); } } void DicToolsWidget::exportWordsList() { if (m_dic == NULL) return; QString fileName = QFileDialog::getSaveFileName(this, _q("Save words list")); if (fileName != "") { try { ofstream file(lfq(fileName).c_str()); ListDic::printWords(file, *m_dic); QMessageBox::information(this, _q("Save words list"), _q("File '%1' successfully saved").arg(fileName)); } catch (std::exception &e) { QMessageBox::warning(this, _q("Eliot - Error"), _q("Cannot save the words list: %1").arg(e.what())); } } } void DicToolsWidget::populateMenuPlus1(QMenu &iMenu, const QPoint &iPoint) { const QModelIndex &index = treeViewPlus1->indexAt(iPoint); if (!index.isValid() || !index.parent().isValid()) return; // Find the selected word const QModelIndex &wordIndex = m_plus1Model->index(index.row(), 0, index.parent()); QString selectedWord = m_plus1Model->data(wordIndex).toString(); iMenu.addAction(m_customPopupPlus1->getShowDefinitionEntry(selectedWord)); } void DicToolsWidget::populateMenuRegexp(QMenu &iMenu, const QPoint &iPoint) { const QModelIndex &index = treeViewRegexp->indexAt(iPoint); if (!index.isValid()) return; // Find the selected word const QModelIndex &wordIndex = m_regexpModel->index(index.row(), 0); QString selectedWord = m_regexpModel->data(wordIndex).toString(); iMenu.addAction(m_customPopupRegexp->getShowDefinitionEntry(selectedWord)); }