diff --git a/src/collection/containermodel.cpp b/src/collection/containermodel.cpp index a9379c7f..a95ca690 100644 --- a/src/collection/containermodel.cpp +++ b/src/collection/containermodel.cpp @@ -1,389 +1,389 @@ /*************************************************************************** Copyright 2007-2008 Frederik Gladhorn ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "containermodel.h" #include "containermimedata.h" #include "vocabularymimedata.h" #include #include #include #include #include #include /** @file * Implementation of ContainerModel. * Functions to create the model from the lessons of the vocabulary document. */ ContainerModel::ContainerModel(KEduVocContainer::EnumContainerType type, QObject * parent) : ReadonlyContainerModel(type, parent) { m_type = type; m_doc = 0; } QModelIndex ContainerModel::appendContainer(const QModelIndex& parent, const QString & containerName) { KEduVocContainer* parentContainer; if (parent.isValid()) { parentContainer = static_cast(parent.internalPointer()); } else { return QModelIndex(); } beginInsertRows(parent, parentContainer->childContainerCount(), parentContainer->childContainerCount()); switch (m_type) { case (KEduVocContainer::Lesson): parentContainer->appendChildContainer(new KEduVocLesson(containerName, static_cast(parentContainer))); break; case (KEduVocContainer::WordType): { KEduVocWordType* parentWordType = static_cast(parentContainer); KEduVocWordType* wordTypeContainer = new KEduVocWordType(containerName, parentWordType); wordTypeContainer->setWordType(parentWordType->wordType()); parentContainer->appendChildContainer(wordTypeContainer); break; } default: break; } endInsertRows(); return index(parentContainer->childContainerCount() - 1, 0, parent); } QVariant ContainerModel::data(const QModelIndex & index, int role) const { if (!index.isValid()) { return QVariant(); } KEduVocContainer *container = static_cast(index.internalPointer()); switch (index.column()) { case ContainerNameColumn: if (role == Qt::DisplayRole || role == Qt::EditRole) { return container->name(); } // if (role == Qt::DecorationRole) { // return QIcon::fromTheme("favorites"); // } if (role == Qt::TextAlignmentRole) { return Qt::AlignLeft; } break; case TotalCountColumn: if (role == Qt::DisplayRole) { return container->entryCount(KEduVocContainer::Recursive); } if (role == Qt::TextAlignmentRole) { return Qt::AlignRight; } break; default: if (role == Qt::TextAlignmentRole) { return Qt::AlignRight; } } return QVariant(); } bool ContainerModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (!index.isValid()) { return false; } if (index.column() == ContainerNameColumn) { KEduVocContainer *container = static_cast(index.internalPointer()); // rename a lesson if (role == Qt::EditRole) { container->setName(value.toString()); emit dataChanged(index, index); emit documentModified(); return true; } // checkboxes if (role == Qt::CheckStateRole) { bool newState = value.toBool(); for (int i = 0; i < rowCount(index); i++) { - setData(index.child(i, 0), newState, Qt::CheckStateRole); + setData(index.model()->index(i, 0, index), newState, Qt::CheckStateRole); } container->setInPractice(newState); emit dataChanged(index, index); emit documentModified(); return true; } } return false; } Qt::ItemFlags ContainerModel::flags(const QModelIndex &index) const { if (index.isValid()) { // the root element, not editable for now if (index.parent() == QModelIndex()) { return (Qt::ItemIsEnabled | Qt::ItemIsSelectable); } // the name column if (index.column() == ContainerNameColumn) { return (Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); } else { // every other element return (Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); } } return Qt::ItemIsDropEnabled; } QVariant ContainerModel::headerData(int section, Qt::Orientation orientation, int role) const { // statically two columns for now if (orientation == Qt::Horizontal) { switch (section) { case ContainerNameColumn: if (role == Qt::DisplayRole) { return i18n("Unit"); } break; case TotalCountColumn: if (role == Qt::DisplayRole) { return QVariant(); } if (role == Qt::ToolTipRole) { return i18n("Number of entries in this lesson."); } break; } } return QVariant(); } int ContainerModel::columnCount(const QModelIndex & parent) const { Q_UNUSED(parent); if (!m_doc) { return FirstDataColumn; } // for now one grade per language return FirstDataColumn; // + m_doc->identifierCount(); } void ContainerModel::deleteContainer(const QModelIndex & containerIndex) { KEduVocContainer* container = static_cast(containerIndex.internalPointer()); KEduVocContainer* parent = container->parent(); if (!parent) { // never delete the root container return; } beginRemoveRows(containerIndex.parent(), containerIndex.row(), containerIndex.row()); parent->deleteChildContainer(container->row()); endRemoveRows(); } Qt::DropActions ContainerModel::supportedDropActions() const { return Qt::MoveAction | Qt::CopyAction; } QStringList ContainerModel::mimeTypes() const { return QStringList() << QStringLiteral("text/plain"); } QMimeData * ContainerModel::mimeData(const QModelIndexList &indexes) const { ContainerMimeData *mimeData = new ContainerMimeData(); // QByteArray encodedData; foreach(const QModelIndex & index, indexes) { mimeData->addContainer(static_cast(index.internalPointer())); } mimeData->setText(QStringLiteral("Parley lesson")); // QDataStream stream(&encodedData, QIODevice::WriteOnly); // stream << "Parley lesson"; // foreach (const QModelIndex &index, indexes) { // if (index.isValid()) { // QString text = data(index, Qt::DisplayRole).toString(); // stream << text; // } // } // // qDebug() << "mimeData:" << encodedData; // mimeData->setData("text/plain", encodedData); return mimeData; } bool ContainerModel::dropMimeData(const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent) { Q_UNUSED(column) if (action == Qt::IgnoreAction) { return true; } // if it's internal, get the pointers const ContainerMimeData * containerData = qobject_cast(data); if (containerData) { foreach(KEduVocContainer * container, containerData->containerList()) { // no way to move a word type to a lesson for now if (container->containerType() != m_type) { return false; } if (action == Qt::MoveAction || action == Qt::CopyAction) { qDebug() << "Move container: " << container->name(); KEduVocContainer* parentContainer = 0; if (parent.isValid()) { parentContainer = static_cast(parent.internalPointer()); } if (!parentContainer) { // drop into root parentContainer = rootContainer(); } else { //make sure a container cannot be dropped into one of its child containers! KEduVocContainer* childTest = parentContainer; while (childTest != 0) { if (childTest == container) { qDebug() << "Cannot drop a container into one of its child containers!"; return false; } childTest = childTest->parent(); } } QModelIndex oldParent = index(container->parent()); beginRemoveRows(oldParent, container->row(), container->row()); container->parent()->removeChildContainer(container->row()); endRemoveRows(); // if we get to choose, append seems sane. if (row < 0) { row = parentContainer->childContainerCount(); } // use index because we sometimes reparent to the root container instead of dropping into nowhere beginInsertRows(index(parentContainer), row, row); parentContainer->insertChildContainer(row, container); endInsertRows(); return true; } } } // if it's a translation, get the pointers const VocabularyMimeData * translationData = qobject_cast(data); if (translationData) { if (!parent.isValid()) { return false; } if (containerType() == KEduVocContainer::Lesson) { // Create a list of the entries associated with the translations being copied. This prevents duplicates if they highlighted several columns. QList entries; foreach(KEduVocTranslation * translation, translationData->translationList()) { if (!entries.contains(translation->entry())) { entries << translation->entry(); } } foreach(KEduVocExpression * entry, entries) { static_cast(parent.internalPointer())->appendEntry(new KEduVocExpression(*entry)); } } if (containerType() == KEduVocContainer::WordType) { foreach(KEduVocTranslation * translation, translationData->translationList()) { translation->setWordType( static_cast(parent.internalPointer())); } } return false; } qDebug() << data->formats(); /* if (data->hasText()) { if (action == Qt::CopyAction | action == Qt::MoveAction) { QString name; name = data->text(); qDebug() << "Copy lesson " << name; appendLesson(parent, name); return true; } }*/ return false; } Qt::DropActions ContainerModel::supportedDragActions() const { return (Qt::CopyAction | Qt::MoveAction); } /* bool ContainerModel::removeRows(int row, int count, const QModelIndex & parent) { // BIG FAT WARNING this code works, but it gets called by the drag and drop implementation automatically, so either this gets used or the other (dropMimeData) to remove the containers. If both are active, containers get deleted without warning or visible signs. KEduVocContainer* parentContainer; if (!parent.internalPointer()) { parentContainer = m_container; } else { parentContainer = static_cast(parent.internalPointer()); } qDebug() << "removeRows from " << parentContainer->name() << " row " << row << "count" << count; beginRemoveRows ( parent, row, row+count ); for (int i = 0; iremoveChildContainer(row); } endRemoveRows(); return true; } */ diff --git a/src/collection/vocabularymodel.cpp b/src/collection/vocabularymodel.cpp index bddb92b7..8cf84364 100644 --- a/src/collection/vocabularymodel.cpp +++ b/src/collection/vocabularymodel.cpp @@ -1,409 +1,409 @@ /*************************************************************************** Copyright 2007 Frederik Gladhorn ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "vocabularymodel.h" #include "parleydocument.h" #include "prefs.h" #include "languagesettings.h" #include #include #include "vocabularymimedata.h" #include #include #include #include #include #include VocabularyModel::VocabularyModel(QObject *parent) : QAbstractTableModel(parent), m_container(0), m_document(0) { m_recursive = Prefs::showSublessonentries() ? KEduVocContainer::Recursive : KEduVocContainer::NotRecursive; qRegisterMetaType("KEduVocTranslationPointer"); } VocabularyModel::~VocabularyModel() { } void VocabularyModel::setDocument(KEduVocDocument * doc) { beginResetModel(); m_document = doc; m_container = 0; m_lesson = 0; if (m_document) { showContainer(m_document->lesson()); } else { showContainer(0); } endResetModel(); } void VocabularyModel::showContainer(KEduVocContainer * container) { // use remove and insert rows. using reset resets all table headers too. if (rowCount(QModelIndex()) > 0) { beginRemoveRows(QModelIndex(), 0, rowCount(QModelIndex()) - 1); m_container = 0; endRemoveRows(); } if (container) { if (container->entryCount(m_recursive) > 0) { beginInsertRows(QModelIndex(), 0, container->entryCount(m_recursive) - 1); m_container = container; endInsertRows(); } else { m_container = container; } } } void VocabularyModel::setLesson(KEduVocLesson * lessonContainer) { m_lesson = lessonContainer; } KEduVocLesson * VocabularyModel::lesson() { return m_lesson; } int VocabularyModel::rowCount(const QModelIndex &index) const { // no lesson set - zarro rows if (!m_container) { return 0; } // only the root index has children because we have no hierarchical model. if (index == QModelIndex()) { return m_container->entryCount(m_recursive); } return 0; } int VocabularyModel::columnCount(const QModelIndex &) const { if (!m_document) { return 0; } return m_document->identifierCount() * EntryColumnsMAX; } QVariant VocabularyModel::data(const QModelIndex & index, int role) const { if (!m_document || !m_container) { return QVariant(); } int translationId = translation(index.column()); int entryColumn = columnType(index.column()); switch (role) { case Qt::DisplayRole: switch (entryColumn) { case Translation: return QVariant(m_container->entry(index.row(), m_recursive)->translation(translationId)->text()); case Pronunciation: return QVariant(m_container->entry(index.row(), m_recursive)->translation(translationId)->pronunciation()); case WordClass: // if no word type is set, we get a null pointer if (m_container->entry(index.row(), m_recursive)->translation(translationId)->wordType()) { return QVariant(m_container->entry(index.row(), m_recursive)->translation(translationId)->wordType()->name()); } return QVariant(QString()); case Synonym: { QStringList displayElements; foreach(KEduVocTranslation * synonym, m_container->entry(index.row(), m_recursive)->translation(translationId)->synonyms()) { displayElements.append(synonym->text()); } return QVariant(displayElements.join(QStringLiteral("; "))); } case Antonym: { QStringList displayElements; foreach(KEduVocTranslation * antonym, m_container->entry(index.row(), m_recursive)->translation(translationId)->antonyms()) { displayElements.append(antonym->text()); } return QVariant(displayElements.join(QStringLiteral("; "))); } case Example: { QString example = m_container->entry(index.row(), m_recursive)->translation(translationId)->example(); /*QString word = m_container->entry(index.row(), m_recursive)->translation(translationId)->text(); int pos = 0; QString start = ""; QString end = ""; while ((pos = example.indexOf(word, pos)) >= 0) { example.insert(pos, start); example.insert(pos+word.length()+start.length(), end); pos += word.length()+start.length()+end.length(); }*/ return QVariant(example); } case Comment: return QVariant(m_container->entry(index.row(), m_recursive)->translation(translationId)->comment()); case Paraphrase: return QVariant(m_container->entry(index.row(), m_recursive)->translation(translationId)->paraphrase()); default: return QVariant(); } break; case Qt::FontRole: if (entryColumn == Translation) { QString locale = m_document->identifier(translationId).locale(); LanguageSettings ls(locale); ls.load(); return ls.editorFont(); } return QVariant(); case LocaleRole: return QVariant(m_document->identifier(translationId).locale()); case AudioRole: return QVariant(m_container->entry(index.row(), m_recursive)->translation(translationId)->soundUrl()); case ImageRole: return QVariant(m_container->entry(index.row(), m_recursive)->translation(translationId)->imageUrl()); case EntryRole: { QVariant v; v.setValue(m_container->entry(index.row(), m_recursive)); return v; } case Qt::ToolTipRole: { ///@todo more tooltips? switch (entryColumn) { case WordClass: return i18n("You can drag and drop words onto their word type."); case Synonym: return i18n("Enable the synonym view to edit synonyms."); case Antonym: return i18n("Enable the antonym view to edit antonyms."); } } } return QVariant(); } bool VocabularyModel::setData(const QModelIndex &index, const QVariant &value, int role) { if ((!index.isValid()) || (role != Qt::EditRole)) { return false; } int translationId = translation(index.column()); int column = columnType(index.column()); switch (column) { case Translation: m_container->entry(index.row(), m_recursive)->translation(translationId)->setText(value.toString()); break; case Pronunciation: m_container->entry(index.row(), m_recursive)->translation(translationId)->setPronunciation(value.toString()); break; case WordClass: break; case Example: m_container->entry(index.row(), m_recursive)->translation(translationId)->setExample(value.toString()); break; case Comment: m_container->entry(index.row(), m_recursive)->translation(translationId)->setComment(value.toString()); break; case Paraphrase: m_container->entry(index.row(), m_recursive)->translation(translationId)->setParaphrase(value.toString()); break; default: return false; } emit(dataChanged(index, index)); ///@todo trust dirty bit m_document->setModified(); return true; } Qt::ItemFlags VocabularyModel::flags(const QModelIndex & index) const { if (!index.isValid()) { return Qt::ItemIsDropEnabled; } switch (columnType(index.column())) { case Translation: return QAbstractItemModel::flags(index) | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; case WordClass: return QAbstractItemModel::flags(index) | Qt::ItemIsEditable; case Synonym: case Antonym: return QAbstractItemModel::flags(index) | Qt::ItemIsDropEnabled; default: return QAbstractItemModel::flags(index) | Qt::ItemIsEditable | Qt::ItemIsDropEnabled; } } QVariant VocabularyModel::headerData(int section, Qt::Orientation orientation, int role) const { if (!m_document) { return QVariant(); } if (orientation == Qt::Horizontal) { int translationId = section / EntryColumnsMAX; int entryColumn = section % EntryColumnsMAX; switch (role) { case Qt::DisplayRole: return VocabularyModel::columnTitle(m_document, translationId, entryColumn, /*addLocaleSuffix*/ true); break; } // switch role } // if horizontal return QVariant(); } QString VocabularyModel::columnTitle(KEduVocDocument *document, int translation, int column, bool addLocaleSuffix) { const QString localeSuffix = document->identifier(translation).locale(); switch (column) { case Translation: if (document->identifierCount() - 1 < translation) { return QString(); } return document->identifier(translation).name(); //returns "English", "German", etc case Pronunciation: return addLocaleSuffix ? i18n("Pronunciation (%1)", localeSuffix) : i18n("Pronunciation"); case WordClass: return addLocaleSuffix ? i18n("Word Type (%1)", localeSuffix) : i18n("Word Type"); case Synonym: return addLocaleSuffix ? i18n("Synonym (%1)", localeSuffix) : i18n("Synonym"); case Antonym: return addLocaleSuffix ? i18n("Antonym (%1)", localeSuffix) : i18n("Antonym"); case Example: return addLocaleSuffix ? i18n("Example (%1)", localeSuffix) : i18n("Example"); case Comment: return addLocaleSuffix ? i18n("Comment (%1)", localeSuffix) : i18n("Comment"); case Paraphrase: return addLocaleSuffix ? i18n("Paraphrase (%1)", localeSuffix) : i18n("Paraphrase"); } return QString(); } int VocabularyModel::translation(int column) { return column / EntryColumnsMAX; } int VocabularyModel::columnType(int column) { return column % EntryColumnsMAX; } QModelIndex VocabularyModel::appendEntry(KEduVocExpression *expression) { if (m_document->identifierCount() == 0) { KMessageBox::information(0, i18n("Please use Edit -> Languages to set up your document."), i18n("No Languages Defined")); return QModelIndex(); } if (!m_lesson || !m_lesson->parent()) { KMessageBox::information(0, i18n("Select a unit before adding vocabulary."), i18n("No Unit Selected")); delete expression; return QModelIndex(); } beginInsertRows(QModelIndex(), rowCount(QModelIndex()), rowCount(QModelIndex())); if (!expression) { expression = new KEduVocExpression; } m_lesson->appendEntry(expression); endInsertRows(); return index(rowCount(QModelIndex()) - 1, 0, QModelIndex()); } bool VocabularyModel::removeRows(int row, int count, const QModelIndex & parent) { Q_UNUSED(parent); if (count < 1 || row < 0 || row + count > m_container->entryCount(m_recursive)) { return false; } int bottomRow = row + count - 1; beginRemoveRows(QModelIndex(), row, bottomRow); for (int i = bottomRow; i >= row; i--) { delete m_container->entry(i, m_recursive); } endRemoveRows(); return true; } QStringList VocabularyModel::mimeTypes() const { return QStringList() << QStringLiteral("text/plain"); } QMimeData * VocabularyModel::mimeData(const QModelIndexList & indexes) const { VocabularyMimeData *mimeData = new VocabularyMimeData(); QModelIndexList sortedIndexes = indexes; - qSort(sortedIndexes); + std::sort(sortedIndexes.begin(), sortedIndexes.end()); qDebug() << "mimeData for " << indexes.count() << "indexes"; QList translations; foreach(const QModelIndex & index, sortedIndexes) { // only add if it's a translation. other cells like word type are being ignored for now. if (columnType(index.column()) == Translation) { translations.append(m_container->entry(index.row(), m_recursive)->translation(translation(index.column()))); } } mimeData->setTranslations(translations); return mimeData; } void VocabularyModel::showEntriesOfSubcontainers(bool show) { beginResetModel(); Prefs::setShowSublessonentries(show); if (show) { m_recursive = KEduVocContainer::Recursive; } else { m_recursive = KEduVocContainer::NotRecursive; } endResetModel(); } void VocabularyModel::resetLanguages() { // play it save - this happens seldom enough to warrant a reload setDocument(m_document); } void VocabularyModel::automaticTranslation(bool enabled) { qDebug() << "auto trans enabled: " << enabled; Prefs::setAutomaticTranslation(true); } diff --git a/src/dashboard/dashboard.cpp b/src/dashboard/dashboard.cpp index a0ece2c7..ecddb385 100644 --- a/src/dashboard/dashboard.cpp +++ b/src/dashboard/dashboard.cpp @@ -1,382 +1,372 @@ /*************************************************************************** Copyright 2014 Inge Wallin ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "dashboard.h" #include #include #include #include -#include #include //#include #include #include "../utils.h" #include "buttondelegate.h" #include "parleymainwindow.h" #include "parleydocument.h" #include "practice/themedbackgroundrenderer.h" #include "practice/imagewidget.h" #include "statistics/statisticsmainwindow.h" #include "statistics/statisticsmodel.h" #include "collection.h" #include "collectionwidget.h" #include "gradereferencewidget.h" // ================================================================ // class Dashboard int ROWSIZE = 4; // Number of collection widgets (+ 1 initial spacerItem) per row Dashboard::Dashboard(ParleyMainWindow *parent) : KXmlGuiWindow(parent) , m_mainWindow(parent) { // KXmlGui setXMLFile(QStringLiteral("dashboardui.rc")); setObjectName(QStringLiteral("Dashboard")); m_widget = new Practice::ImageWidget(this); m_widget->setScalingEnabled(false, false); m_widget->setKeepAspectRatio(Qt::IgnoreAspectRatio); m_widget->setFadingEnabled(false); m_ui = new Ui::Dashboard(); m_ui->setupUi(m_widget); setCentralWidget(m_widget); - m_practiceSignalMapper = new QSignalMapper(this); - m_removeSignalMapper = new QSignalMapper(this); QTime time = QTime::currentTime(); qsrand((uint)time.msec()); QFont font = m_ui->recentLabel->font(); font.setBold(true); m_ui->recentLabel->setFont(font); font = m_ui->completedLabel->font(); font.setBold(true); m_ui->completedLabel->setFont(font); m_ui->newButton->setIcon(QIcon::fromTheme(QStringLiteral("document-new"))); m_ui->openButton->setIcon(QIcon::fromTheme(QStringLiteral("document-open"))); m_ui->ghnsButton->setIcon(QIcon::fromTheme(QStringLiteral("get-hot-new-stuff"))); GradeReferenceWidget *gradeReferenceWidget = new GradeReferenceWidget(); gradeReferenceWidget->setMinimumSize(m_widget->width(), 50); m_ui->gridLayout->addWidget(gradeReferenceWidget, 1, 0, 1, ROWSIZE, Qt::AlignCenter); m_subGridLayout = new QGridLayout(); m_subGridLayout->setHorizontalSpacing(50); m_subGridLayout->setVerticalSpacing(30); m_ui->gridLayout_2->addLayout(m_subGridLayout, 2, 0, 1, 1); m_completedGridLayout = new QGridLayout(); m_completedGridLayout->setHorizontalSpacing(50); m_completedGridLayout->setVerticalSpacing(30); m_ui->gridLayout_2->addLayout(m_completedGridLayout, 6, 0, 1, 1); populateMap(); populateGrid(); // Signals from the main buttons. ParleyDocument* doc = m_mainWindow->parleyDocument(); connect(m_ui->newButton, &QAbstractButton::clicked, m_mainWindow, &ParleyMainWindow::slotFileNew); connect(m_ui->openButton, &QAbstractButton::clicked, doc, &ParleyDocument::slotFileOpen); connect(m_ui->ghnsButton, &QAbstractButton::clicked, doc, &ParleyDocument::slotGHNS); - // Signals FROM the signal mappers. The ones TO the signal mappers are - // handled below. - connect(m_practiceSignalMapper, SIGNAL(mapped(QString)), - this, SLOT(slotPracticeButtonClicked(QString))); - connect(m_removeSignalMapper, SIGNAL(mapped(QString)), - this, SLOT(slotRemoveButtonClicked(QString))); - KConfigGroup cfg(KSharedConfig::openConfig(QStringLiteral("parleyrc")), objectName()); applyMainWindowSettings(cfg); m_themedBackgroundRenderer = new Practice::ThemedBackgroundRenderer(this, QStringLiteral("startpagethemecache.bin")); // Set theme and prepare for future theme changes. connect(Prefs::self(), &KCoreConfigSkeleton::configChanged, this, &Dashboard::setTheme); setTheme(); connect(m_themedBackgroundRenderer, &Practice::ThemedBackgroundRenderer::backgroundChanged, this, &Dashboard::backgroundChanged); connect(m_widget, &Practice::ImageWidget::sizeChanged, this, &Dashboard::updateBackground); QAction *updateAction = new QAction(this); updateAction->connect(updateAction, &QAction::triggered, this, &Dashboard::updateWidgets); actionCollection()->addAction(QStringLiteral("update_dashboard"), updateAction); actionCollection()->setDefaultShortcut(updateAction, QKeySequence(Qt::Key_F5)); } Dashboard::~Dashboard() { KConfigGroup cfg(KSharedConfig::openConfig(QStringLiteral("parleyrc")), objectName()); saveMainWindowSettings(cfg); } void Dashboard::clearGrid() { remove(m_subGridLayout, m_subGridLayout->rowCount() - 1, m_subGridLayout->columnCount() - 1, true); remove(m_completedGridLayout, m_completedGridLayout->rowCount() - 1, m_completedGridLayout->columnCount() - 1, true); } /** * Helper function. Removes all layout items within the given @a layout * which either span the given @a row or @a column. If @a deleteWidgets * is true, all concerned child widgets become not only removed from the * layout, but also deleted. */ void Dashboard::remove(QGridLayout *layout, int row, int column, bool deleteWidgets) { // We avoid usage of QGridLayout::itemAtPosition() here to improve performance. for (int i = layout->count() - 1; i >= 0; i--) { int r, c, rs, cs; layout->getItemPosition(i, &r, &c, &rs, &cs); if ((r + rs - 1 <= row) || (c + cs - 1 <= column)) { // This layout item is subject to deletion. QLayoutItem *item = layout->takeAt(i); if (deleteWidgets) { deleteChildWidgets(item); } delete item; } } } /** * Helper function. Deletes all child widgets of the given layout @a item. */ void Dashboard::deleteChildWidgets(QLayoutItem *item) { if (item->layout()) { // Process all child items recursively. for (int i = 0; i < item->layout()->count(); i++) { deleteChildWidgets(item->layout()->itemAt(i)); } } delete item->widget(); } void Dashboard::populateMap() { KConfig parleyConfig(QStringLiteral("parleyrc")); KConfigGroup recentFilesGroup(&parleyConfig, "Recent Files"); for (int i = recentFilesGroup.keyList().count() / 2; i > 0 ; i--) { QString urlString = recentFilesGroup.readPathEntry("File" + QString::number(i), QString()); QString nameString = recentFilesGroup.readEntry("Name" + QString::number(i), QString()); m_recentFilesMap.insert(urlString, nameString); } } void Dashboard::populateGrid() { int j = 0, k = 0, jc = 0, kc = 0; QMapIterator it(m_recentFilesMap); while (it.hasNext()) { it.next(); QString urlString = it.key(); QString titleString = it.value(); QUrl url(QUrl::fromLocalFile(urlString)); Collection *collection = new Collection(&url, this); WordCount dueWords; int percentageCompleted = dueWords.percentageCompleted(); m_urlArray[k] = url; if (percentageCompleted != 100) { if (j % ROWSIZE == 0) { m_subGridLayout->addItem(new QSpacerItem(50, 1), j / ROWSIZE, 0); j++; } } else { if (jc % ROWSIZE == 0) { m_completedGridLayout->addItem(new QSpacerItem(50,1), jc / ROWSIZE, 0); jc++; } } CollectionWidget* backWidget = new CollectionWidget(collection, &dueWords, this); m_collectionWidgets.append(backWidget); if (percentageCompleted != 100) { backWidget->setFixedSize(COLLWIDTH, COLLHEIGHT1); backWidget->setMinimumSize(COLLWIDTH, COLLHEIGHT1); m_subGridLayout->addWidget(backWidget, j / ROWSIZE, j % ROWSIZE); } else { backWidget->setFixedSize(COLLWIDTH, COLLHEIGHT2); backWidget->setMinimumSize(COLLWIDTH, COLLHEIGHT2); m_completedGridLayout->addWidget(backWidget, jc / ROWSIZE, jc % ROWSIZE); } - m_practiceSignalMapper->setMapping(backWidget, urlString); - connect(backWidget, SIGNAL(practiceButtonClicked()), m_practiceSignalMapper, SLOT(map())); - m_removeSignalMapper->setMapping(backWidget, urlString); - connect(backWidget, SIGNAL(removeButtonClicked()), m_removeSignalMapper, SLOT(map())); + connect(backWidget, &CollectionWidget::practiceButtonClicked, + this, [=] {slotPracticeButtonClicked(urlString);}); + connect(backWidget, &CollectionWidget::removeButtonClicked, + this, [=] {slotRemoveButtonClicked(urlString);}); if (percentageCompleted != 100) { j++; } else { jc++; kc++; } k++; } m_count = k; m_completedGridLayout->addItem(new QSpacerItem(50, 1, QSizePolicy::Expanding, QSizePolicy::Fixed), m_completedGridLayout->rowCount() - 1, m_completedGridLayout->columnCount()); m_subGridLayout->addItem(new QSpacerItem(50,1,QSizePolicy::Expanding, QSizePolicy::Fixed), m_subGridLayout->rowCount() - 1, m_subGridLayout->columnCount()); if (k - kc) { m_ui->recentLabel->setText(i18n("Active Collections")); } else { m_ui->recentLabel->clear(); } if (kc) { m_ui->completedLabel->setText(i18n("Completed Collections")); } else { m_ui->completedLabel->clear(); } } void Dashboard::statisticsHandler(const QUrl &url) { #if 1 Q_UNUSED(url); #else if (!m_mainWindow->parleyDocument()->open(url)) { return; } // Find due words. TODO find a better way. m_mainWindow->m_sessionManager.setDocument(m_mainWindow->parleyDocument()->document()); qDebug()<<"Session Manager, allEntryCount="<m_sessionManager.allDueEntryCount(); statisticsWidget->setDocument(m_mainWindow->parleyDocument()->document()); // Find the percentage completion, to categorize as active or completed collection. QModelIndex index = statisticsWidget->statisticsModel()->index(0, 2, QModelIndex()); qDebug() << "Percentage:" << index.data(StatisticsModel::TotalPercent).toInt(); #endif } void Dashboard::slotOpenUrl(const QUrl& url) { if (!m_mainWindow->parleyDocument()->open(url)) { return; } m_mainWindow->showEditor(); } void Dashboard::slotPracticeButtonClicked(const QString& urlString) { //qDebug() << urlString; QUrl url( QUrl::fromLocalFile(urlString) ); m_openUrl = url; QTimer::singleShot(0, this, &Dashboard::slotDoubleClickOpen); } void Dashboard::slotRemoveButtonClicked(const QString& urlString) { qDebug() << urlString; QMessageBox::StandardButton reply; reply = QMessageBox::question(this, i18n("Remove"), i18n("Are you sure you want to remove this collection?"), QMessageBox::Yes | QMessageBox::No); if (reply == QMessageBox::Yes) { m_recentFilesMap.remove(urlString); m_mainWindow->removeRecentFile(QUrl::fromLocalFile(urlString )); clearGrid(); populateGrid(); } } void Dashboard::slotDoubleClickOpen() { slotPracticeUrl(m_openUrl); } void Dashboard::slotPracticeUrl(const QUrl & url) { if (!m_mainWindow->parleyDocument()->open(url)) { return; } // This used to go to the practice configuration but both I and //some users wanted to go directly to the practice so I'm testing //out this for a while. m_mainWindow->showPracticeConfiguration(); //m_mainWindow->showPractice(); } void Dashboard::backgroundChanged(const QPixmap &pixmap) { m_widget->setPixmap(pixmap); } void Dashboard::setTheme() { m_themedBackgroundRenderer->setTheme(Prefs::theme()); updateFontColors(); updateBackground(); m_widget->setContentsMargins(m_themedBackgroundRenderer->contentMargins()); } void Dashboard::updateWidgets() { foreach (CollectionWidget *cw, m_collectionWidgets) { cw->updateDue(); } } void Dashboard::updateFontColors() { QPalette p(QApplication::palette()); QColor c = m_themedBackgroundRenderer->fontColor(QStringLiteral("Start"), p.color(QPalette::Active, QPalette::WindowText)); p.setColor(QPalette::Base, Qt::transparent); p.setColor(QPalette::Text, c); p.setColor(QPalette::WindowText, c); m_widget->setPalette(p); } void Dashboard::updateBackground() { m_themedBackgroundRenderer->clearRects(); m_themedBackgroundRenderer->addRect(QStringLiteral("startbackground"), QRect(QPoint(), m_widget->size())); QPixmap pixmap = m_themedBackgroundRenderer->getScaledBackground(); if (!pixmap.isNull()) { m_widget->setPixmap(pixmap); } m_themedBackgroundRenderer->updateBackground(); } diff --git a/src/dashboard/dashboard.h b/src/dashboard/dashboard.h index 6d160b8e..fbcf711c 100644 --- a/src/dashboard/dashboard.h +++ b/src/dashboard/dashboard.h @@ -1,89 +1,85 @@ /*************************************************************************** Copyright 2008-2010 Daniel Laidig ***************************************************************************/ /*************************************************************************** * * * 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. * * * ***************************************************************************/ #ifndef DASHBOARD_H #define DASHBOARD_H #include "ui_dashboard.h" #include "statistics/statisticsmainwindow.h" #include -#include #include static const int N = 50; class ParleyMainWindow; namespace Practice { class ThemedBackgroundRenderer; class ImageWidget; } class CollectionWidget; class RemoveButton; class Dashboard : public KXmlGuiWindow { Q_OBJECT public: explicit Dashboard(ParleyMainWindow *parent); ~Dashboard(); public slots: void slotOpenUrl(const QUrl& url); void slotPracticeUrl(const QUrl& url); //void slotDoubleClicked(const QModelIndex& index); void slotDoubleClickOpen(); //void updateRecentFilesModel(); void populateGrid(); void populateMap(); void clearGrid(); void slotPracticeButtonClicked(const QString& urlString); void slotRemoveButtonClicked(const QString& urlString); void statisticsHandler(const QUrl &url); void remove(QGridLayout *layout, int row, int column, bool deleteWidgets); void deleteChildWidgets(QLayoutItem *item); private slots: void setTheme(); void updateWidgets(); void backgroundChanged(const QPixmap& pixmap); void updateFontColors(); void updateBackground(); private: Ui::Dashboard *m_ui; ParleyMainWindow *m_mainWindow; StatisticsMainWindow *m_statisticsWidget; Practice::ThemedBackgroundRenderer *m_themedBackgroundRenderer; Practice::ImageWidget* m_widget; QMap m_recentFilesMap; // url, name QUrl m_openUrl; QGridLayout *m_subGridLayout; QGridLayout *m_completedGridLayout; QList m_collectionWidgets; // List of the widgets in the dashboard. // The parts of the collections QUrl m_urlArray[N]; - QSignalMapper *m_practiceSignalMapper; // For the practice buttons - QSignalMapper *m_removeSignalMapper; // For the remove buttons - int m_count; }; #endif diff --git a/src/editor/editor.cpp b/src/editor/editor.cpp index 843cd701..b355760f 100644 --- a/src/editor/editor.cpp +++ b/src/editor/editor.cpp @@ -1,524 +1,521 @@ /*************************************************************************** Copyright 1999-2001 Ewald Arnold Copyright 2004-2007 Peter Hedlund Copyright 2007-2009 Frederik Gladhorn Copyright 2008 Daniel Laidig ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "editor.h" #include // Qt models on top of the KEduVocDocument #include "containermodel.h" #include "lessonmodel.h" #include "vocabularymodel.h" #include "vocabularyfilter.h" #include "wordclassmodel.h" // Views #include "vocabularyview.h" #include "containerview.h" #include "lessonview.h" #include "wordtypeview.h" #include "multiplechoicewidget.h" #include "comparisonwidget.h" #include "inflectionwidget.h" #include "imagechooserwidget.h" #include "audiowidget.h" #include "browserwidget.h" #include "synonymwidget.h" #include "summarywordwidget.h" #include "latexwidget.h" #include "settings/parleyprefs.h" #include "prefs.h" #include "scripts/scriptdialog.h" #include "scripts/translator.h" #include "parleyactions.h" #include "parleyadaptor.h" #include #include #include #include #include -#include #include #include #include #include #include using namespace Editor; EditorWindow::EditorWindow(ParleyMainWindow* parent) : KXmlGuiWindow(parent), m_mainWindow(parent) { // KXmlGui setXMLFile(QStringLiteral("editorui.rc")); setObjectName(QStringLiteral("Editor")); setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea); setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea); setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea); setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea); initView(); initModel(); initDockWidgets(); initActions(); KConfigGroup cfg(KSharedConfig::openConfig(QStringLiteral("parleyrc")), objectName()); applyMainWindowSettings(cfg); connect(parent->parleyDocument(), &ParleyDocument::documentChanged, this, &EditorWindow::updateDocument); connect(parent->parleyDocument(), &ParleyDocument::languagesChanged, this, &EditorWindow::slotLanguagesChanged); connect(parent->parleyDocument(), SIGNAL(statesNeedSaving()), this, SLOT(saveState())); connect(parent, &ParleyMainWindow::preferencesChanged, this, &EditorWindow::applyPrefs); QTimer::singleShot(0, this, &EditorWindow::initScripts); } EditorWindow::~EditorWindow() { saveState(); KConfigGroup cfg(KSharedConfig::openConfig(QStringLiteral("parleyrc")), objectName()); saveMainWindowSettings(cfg); } void EditorWindow::updateDocument(KEduVocDocument *doc) { m_vocabularyView->setDocument(doc); m_vocabularyModel->setDocument(doc); m_lessonModel->setDocument(doc); m_wordTypeModel->setDocument(doc); m_summaryWordWidget->slotDocumentChanged(doc); m_inflectionWidget->setDocument(doc); m_comparisonWidget->setDocument(doc); m_synonymWidget->setDocument(doc); m_antonymWidget->setDocument(doc); m_falseFriendWidget->setDocument(doc); if (!m_mainWindow->parleyDocument()->document()) { return; } if (!doc) { return; } // expand the root items m_lessonView->expandToDepth(0); m_wordTypeView->expandToDepth(0); connect(m_vocabularyView->selectionModel(), &QItemSelectionModel::selectionChanged, m_summaryWordWidget, &SummaryWordWidget::slotSelectionChanged); connect(m_vocabularyView->selectionModel(), &QItemSelectionModel::selectionChanged, m_latexWidget, &LatexWidget::slotSelectionChanged); m_spellCheckMenu->menu()->clear(); for (int i = 0; i < doc->identifierCount(); ++i) { QAction* languageSpellCheck = new QAction(doc->identifier(i).name(), m_spellCheckMenu->menu()); m_spellCheckMenu->menu()->addAction(languageSpellCheck); - m_spellCheckMapper->setMapping(languageSpellCheck, i); - connect(languageSpellCheck, SIGNAL(triggered()), m_spellCheckMapper, SLOT(map())); + connect(languageSpellCheck, &QAction::triggered, + this, [=] {m_vocabularyView->checkSpelling(i);}); } } void EditorWindow::initDockWidgets() { // Lesson dockwidget QDockWidget *lessonDockWidget = new QDockWidget(i18n("Units"), this); lessonDockWidget->setObjectName(QStringLiteral("LessonDock")); m_lessonView = new LessonView(this); lessonDockWidget->setWidget(m_lessonView); addDockWidget(Qt::LeftDockWidgetArea, lessonDockWidget); m_dockWidgets.append(lessonDockWidget); actionCollection()->addAction(QStringLiteral("show_units_dock"), lessonDockWidget->toggleViewAction()); m_lessonModel = new LessonModel(this); m_lessonView->setModel(m_lessonModel); m_lessonView->setToolTip(i18n("Right click to add, delete, or rename units. \n" "With the checkboxes you can select which units you want to practice. \n" "Only checked units [x] will be asked in the practice!")); connect(m_lessonView, &LessonView::selectedLessonChanged, m_vocabularyModel, &VocabularyModel::setLesson); connect(m_lessonView, &LessonView::signalShowContainer, m_vocabularyModel, &VocabularyModel::showContainer); connect(m_vocabularyView, &VocabularyView::translationChanged, m_lessonView, &LessonView::setTranslation); // Word classes dock widget QDockWidget* wordTypeDockWidget = new QDockWidget(i18n("Word Types"), this); wordTypeDockWidget->setObjectName(QStringLiteral("WordTypeDock")); m_wordTypeView = new WordTypeView(this); wordTypeDockWidget->setWidget(m_wordTypeView); addDockWidget(Qt::LeftDockWidgetArea, wordTypeDockWidget); m_dockWidgets.append(wordTypeDockWidget); m_wordTypeModel = new WordClassModel(this); wordTypeDockWidget->setVisible(false); actionCollection()->addAction(QStringLiteral("show_wordtype_dock"), wordTypeDockWidget->toggleViewAction()); ///@todo test, should be fixed with the lesson one though ///@todo remove before release // new ModelTest(m_wordTypeModel, this); m_wordTypeView->setModel(m_wordTypeModel); connect(m_vocabularyView, &VocabularyView::translationChanged, m_wordTypeView, &WordTypeView::setTranslation); // Inflections QDockWidget *inflectionDock = new QDockWidget(i18n("Inflection (verbs, adjectives, nouns)"), this); inflectionDock->setObjectName(QStringLiteral("InflectionDock")); m_inflectionWidget = new InflectionWidget(this); QScrollArea *inflectionScrollArea = new QScrollArea(this); inflectionScrollArea->setWidgetResizable(true); inflectionScrollArea->setWidget(m_inflectionWidget); inflectionDock->setWidget(inflectionScrollArea); addDockWidget(Qt::RightDockWidgetArea, inflectionDock); m_dockWidgets.append(inflectionDock); actionCollection()->addAction(QStringLiteral("show_inflection_dock"), inflectionDock->toggleViewAction()); connect(m_mainWindow->parleyDocument(), &ParleyDocument::documentChanged, m_inflectionWidget, &InflectionWidget::setDocument); connect(m_vocabularyView, &VocabularyView::translationChanged, m_inflectionWidget, &InflectionWidget::setTranslation); // Comparison forms QDockWidget *comparisonDock = new QDockWidget(i18n("Comparison forms"), this); comparisonDock->setObjectName(QStringLiteral("ComparisonDock")); m_comparisonWidget = new ComparisonWidget(this); QScrollArea *comparisonScrollArea = new QScrollArea(this); comparisonScrollArea->setWidgetResizable(true); comparisonScrollArea->setWidget(m_comparisonWidget); comparisonDock->setWidget(comparisonScrollArea); addDockWidget(Qt::RightDockWidgetArea, comparisonDock); m_dockWidgets.append(comparisonDock); actionCollection()->addAction(QStringLiteral("show_comparison_dock"), comparisonDock->toggleViewAction()); comparisonDock->setVisible(false); connect(m_vocabularyView, &VocabularyView::translationChanged, m_comparisonWidget, &ComparisonWidget::setTranslation); tabifyDockWidget(comparisonDock,inflectionDock); // Multiple choice QDockWidget *multipleChoiceDock = new QDockWidget(i18n("Multiple Choice"), this); multipleChoiceDock->setObjectName(QStringLiteral("MultipleChoiceDock")); MultipleChoiceWidget *multipleChoiceWidget = new MultipleChoiceWidget(this); QScrollArea *multipleChoiceScrollArea = new QScrollArea(this); multipleChoiceScrollArea->setWidgetResizable(true); multipleChoiceScrollArea->setWidget(multipleChoiceWidget); multipleChoiceDock->setWidget(multipleChoiceScrollArea); addDockWidget(Qt::RightDockWidgetArea, multipleChoiceDock); m_dockWidgets.append(multipleChoiceDock); actionCollection()->addAction(QStringLiteral("show_multiplechoice_dock"), multipleChoiceDock->toggleViewAction()); multipleChoiceDock->setVisible(false); connect(m_vocabularyView, &VocabularyView::translationChanged, multipleChoiceWidget, &MultipleChoiceWidget::setTranslation); // Synonym (and the same for antonym and false friends) QDockWidget *synonymDock = new QDockWidget(i18n("Synonyms"), this); synonymDock->setObjectName(QStringLiteral("SynonymDock")); m_synonymWidget = new SynonymWidget(SynonymWidget::Synonym, this); QScrollArea *synonymScrollArea = new QScrollArea(this); synonymScrollArea->setWidgetResizable(true); synonymScrollArea->setWidget(m_synonymWidget); synonymDock->setWidget(synonymScrollArea); addDockWidget(Qt::RightDockWidgetArea, synonymDock); m_dockWidgets.append(synonymDock); actionCollection()->addAction(QStringLiteral("show_synonym_dock"), synonymDock->toggleViewAction()); synonymDock->setVisible(false); connect(m_vocabularyView, &VocabularyView::translationChanged, m_synonymWidget, &SynonymWidget::setTranslation); QDockWidget *antonymDock = new QDockWidget(i18n("Antonyms"), this); antonymDock->setObjectName(QStringLiteral("AntonymDock")); m_antonymWidget = new SynonymWidget(SynonymWidget::Antonym, this); QScrollArea *antonymScrollArea = new QScrollArea(this); antonymScrollArea->setWidgetResizable(true); antonymScrollArea->setWidget(m_antonymWidget); antonymDock->setWidget(antonymScrollArea); addDockWidget(Qt::RightDockWidgetArea, antonymDock); m_dockWidgets.append(antonymDock); actionCollection()->addAction(QStringLiteral("show_antonym_dock"), antonymDock->toggleViewAction()); antonymDock->setVisible(false); connect(m_vocabularyView, &VocabularyView::translationChanged, m_antonymWidget, &SynonymWidget::setTranslation); tabifyDockWidget(synonymDock,antonymDock); QDockWidget *falseFriendDock = new QDockWidget(i18n("False Friends"), this); falseFriendDock->setObjectName(QStringLiteral("FalseFriendDock")); m_falseFriendWidget = new SynonymWidget(SynonymWidget::FalseFriend, this); QScrollArea *falseFriendScrollArea = new QScrollArea(this); falseFriendScrollArea->setWidgetResizable(true); falseFriendScrollArea->setWidget(m_falseFriendWidget); falseFriendDock->setWidget(falseFriendScrollArea); addDockWidget(Qt::RightDockWidgetArea, falseFriendDock); m_dockWidgets.append(falseFriendDock); actionCollection()->addAction(QStringLiteral("show_falsefriend_dock"), falseFriendDock->toggleViewAction()); falseFriendDock->setVisible(false); connect(m_vocabularyView, &VocabularyView::translationChanged, m_falseFriendWidget, &SynonymWidget::setTranslation); tabifyDockWidget(antonymDock,falseFriendDock); // Pronunciation symbols - Use KCharSelect QDockWidget *charSelectDock = new QDockWidget(i18n("Phonetic Symbols"), this); charSelectDock->setObjectName(QStringLiteral("IPADock")); KCharSelect *charSelectWidget = new KCharSelect(this, 0, KCharSelect::SearchLine | KCharSelect::BlockCombos | KCharSelect::CharacterTable); charSelectWidget->setCurrentChar(0x0250); QScrollArea *charSelectScrollArea = new QScrollArea(this); charSelectScrollArea->setWidgetResizable(true); charSelectScrollArea->setWidget(charSelectWidget); charSelectDock->setWidget(charSelectScrollArea); addDockWidget(Qt::BottomDockWidgetArea, charSelectDock); m_dockWidgets.append(charSelectDock); actionCollection()->addAction(QStringLiteral("show_pronunciation_dock"), charSelectDock->toggleViewAction()); charSelectDock->setVisible(false); connect(charSelectWidget, &KCharSelect::charSelected, m_vocabularyView, &VocabularyView::appendChar); // Image QDockWidget *imageDock = new QDockWidget(i18n("Image"), this); imageDock->setObjectName(QStringLiteral("ImageDock")); ImageChooserWidget *imageChooserWidget = new ImageChooserWidget(this); QScrollArea *imageScrollArea = new QScrollArea(this); imageScrollArea->setWidgetResizable(true); imageScrollArea->setWidget(imageChooserWidget); imageDock->setWidget(imageScrollArea); addDockWidget(Qt::RightDockWidgetArea, imageDock); m_dockWidgets.append(imageDock); actionCollection()->addAction(QStringLiteral("show_image_dock"), imageDock->toggleViewAction()); imageDock->setVisible(false); connect(m_vocabularyView, &VocabularyView::translationChanged, imageChooserWidget, &ImageChooserWidget::setTranslation); tabifyDockWidget(multipleChoiceDock,imageDock); // Summary word QDockWidget *summaryDock = new QDockWidget(i18n("Summary"), this); summaryDock->setObjectName(QStringLiteral("SummaryDock")); m_summaryWordWidget = new SummaryWordWidget(m_vocabularyFilter, m_mainWindow->parleyDocument()->document(), this); QScrollArea *summaryScrollArea = new QScrollArea(this); summaryScrollArea->setWidgetResizable(true); summaryScrollArea->setWidget(m_summaryWordWidget); summaryDock->setWidget(summaryScrollArea); addDockWidget(Qt::BottomDockWidgetArea, summaryDock); actionCollection()->addAction(QStringLiteral("show_summary_dock"), summaryDock->toggleViewAction()); summaryDock->setVisible(false); m_dockWidgets.append(summaryDock); connect(m_vocabularyView, &VocabularyView::translationChanged, m_summaryWordWidget, &SummaryWordWidget::setTranslation); // Sound QDockWidget *audioDock = new QDockWidget(i18n("Sound"), this); audioDock->setObjectName(QStringLiteral("AudioDock")); AudioWidget *audioWidget = new AudioWidget(this); QScrollArea *audioScrollArea = new QScrollArea(this); audioScrollArea->setWidgetResizable(true); audioScrollArea->setWidget(audioWidget); audioDock->setWidget(audioScrollArea); addDockWidget(Qt::RightDockWidgetArea, audioDock); m_dockWidgets.append(audioDock); actionCollection()->addAction(QStringLiteral("show_audio_dock"), audioDock->toggleViewAction()); audioDock->setVisible(false); connect(m_vocabularyView, &VocabularyView::translationChanged, audioWidget, &AudioWidget::setTranslation); tabifyDockWidget(imageDock,audioDock); // browser QDockWidget *browserDock = new QDockWidget(i18n("Internet"), this); browserDock->setObjectName(QStringLiteral("BrowserDock")); BrowserWidget *htmlPart = new BrowserWidget(browserDock); QScrollArea *browserScrollArea = new QScrollArea(this); browserScrollArea->setWidgetResizable(true); browserScrollArea->setWidget(htmlPart); browserDock->setWidget(browserScrollArea); addDockWidget(Qt::BottomDockWidgetArea, browserDock); m_dockWidgets.append(browserDock); actionCollection()->addAction(QStringLiteral("show_browser_dock"), browserDock->toggleViewAction()); browserDock->setVisible(false); connect(m_vocabularyView, &VocabularyView::translationChanged, htmlPart, &BrowserWidget::setTranslation); tabifyDockWidget(summaryDock,browserDock); // LaTeX QDockWidget *latexDock = new QDockWidget(i18n("LaTeX"), this); latexDock->setObjectName(QStringLiteral("LatexDock")); m_latexWidget = new LatexWidget(m_vocabularyFilter, m_mainWindow->parleyDocument()->document(), this); QScrollArea *latexScrollArea = new QScrollArea(this); latexScrollArea->setWidgetResizable(true); latexScrollArea->setWidget(m_latexWidget); latexDock->setWidget(latexScrollArea); addDockWidget(Qt::RightDockWidgetArea, latexDock); actionCollection()->addAction(QStringLiteral("show_latex_dock"), latexDock->toggleViewAction()); latexDock->setVisible(false); m_dockWidgets.append(latexDock); connect(m_vocabularyView, &VocabularyView::translationChanged, m_latexWidget, &LatexWidget::setTranslation); tabifyDockWidget(audioDock,latexDock); // Grades // QDockWidget *gradeDock = new QDockWidget(i18n("Grade"), this); // gradeDock->setObjectName("gradeDock"); // QLabel *gradeWidget = new QLabel("grade placeholder", this); // gradeDock->setWidget(gradeWidget); // addDockWidget(Qt::RightDockWidgetArea, gradeDock); // connect(this, SIGNAL(signalSetData(KEduVocTranslation*)), m_declensionWidget, SLOT(setTranslation(KEduVocTranslation*))); } void EditorWindow::initActions() { ParleyActions::create(ParleyActions::RemoveGrades, this, SLOT(removeGrades()), actionCollection()); m_spellCheckMenu = ParleyActions::create(ParleyActions::CheckSpelling, 0, "", actionCollection()); m_spellCheckMenu->setMenu(new QMenu(this)); - m_spellCheckMapper = new QSignalMapper(this); - connect(m_spellCheckMapper, SIGNAL(mapped(int)), m_vocabularyView, SLOT(checkSpelling(int))); ParleyActions::create(ParleyActions::ToggleShowSublessons, m_vocabularyModel, SLOT(showEntriesOfSubcontainers(bool)), actionCollection()); ParleyActions::create(ParleyActions::AutomaticTranslation, m_vocabularyModel, SLOT(automaticTranslation(bool)), actionCollection()); ParleyActions::create(ParleyActions::StartPractice, m_mainWindow, SLOT(showPracticeConfiguration()), actionCollection()); actionCollection()->action(QStringLiteral("practice_start"))->setText(i18n("Practice")); actionCollection()->action(QStringLiteral("practice_start"))->setToolTip(i18n("Practice")); ParleyActions::create(ParleyActions::ConfigurePractice, m_mainWindow, SLOT(configurePractice()), actionCollection()); ParleyActions::create(ParleyActions::ToggleSearchBar, this, SLOT(slotConfigShowSearch()), actionCollection()); ParleyActions::create(ParleyActions::SearchVocabulary, this, SLOT(startSearch()), actionCollection()); ParleyActions::create(ParleyActions::ShowScriptManager, this, SLOT(slotShowScriptManager()), actionCollection()); ParleyActions::create(ParleyActions::LanguagesProperties, m_mainWindow->parleyDocument(), SLOT(languageProperties()), actionCollection()); ParleyActions::createUploadAction(m_mainWindow->parleyDocument(), SLOT(uploadFile()), actionCollection()); new EditorWindowAdaptor(this); QDBusConnection dbus = QDBusConnection::sessionBus(); dbus.registerObject(QStringLiteral("/AddWithTranslation"), this); } void EditorWindow::addWordWithTranslation(const QStringList &w) { KEduVocExpression *kexpr = new KEduVocExpression(w); m_vocabularyModel->appendEntry(kexpr); } void EditorWindow::initModel() { m_vocabularyModel = new VocabularyModel(this); m_vocabularyFilter = new VocabularyFilter(this); m_vocabularyFilter->setSourceModel(m_vocabularyModel); m_vocabularyView->setFilter(m_vocabularyFilter); // connect(m_mainWindow->parleyDocument(), SIGNAL(documentChanged(KEduVocDocument*)), m_vocabularyModel, SLOT(setDocument(KEduVocDocument*))); // connect(m_mainWindow->parleyDocument(), SIGNAL(documentChanged(KEduVocDocument*)), m_vocabularyView, SLOT(setDocument(KEduVocDocument*))); connect(m_searchLine, &QLineEdit::textChanged, m_vocabularyFilter, &VocabularyFilter::setSearchString); } /** * This initializes the main widgets and table. */ void EditorWindow::initView() { QWidget *mainWidget = new QWidget(this); setCentralWidget(mainWidget); QVBoxLayout *topLayout = new QVBoxLayout(mainWidget); m_searchLine = new QLineEdit(this); m_searchLine->show(); m_searchLine->setFocusPolicy(Qt::ClickFocus); m_searchLine->setClearButtonEnabled(true); m_searchLine->setPlaceholderText(i18n("Enter search terms here")); m_searchLine->setToolTip(i18n("Search your vocabulary")); QLabel *label = new QLabel(i18n("S&earch:"), this); label->setBuddy(m_searchLine); label->show(); m_searchWidget = new QWidget(this); QHBoxLayout* layout = new QHBoxLayout(m_searchWidget); layout->setContentsMargins(0, 0, 0, 0); layout->addWidget(label); layout->addWidget(m_searchLine); ///@todo centralWidget()-> delete layout QVBoxLayout * rightLayout = new QVBoxLayout(); rightLayout->setContentsMargins(0, 0, 0, 0); rightLayout->addWidget(m_searchWidget); m_searchWidget->setVisible(Prefs::showSearch()); m_vocabularyView = new VocabularyView(this); rightLayout->addWidget(m_vocabularyView, 1, 0); topLayout->addLayout(rightLayout); } void EditorWindow::slotConfigShowSearch() { m_searchWidget->setVisible(m_searchWidget->isHidden()); Prefs::setShowSearch(m_searchWidget->isVisible()); } void EditorWindow::startSearch() { m_searchWidget->setVisible(true); m_searchLine->setFocus(); } void EditorWindow::slotShowScriptManager() { ScriptDialog * dialog = new ScriptDialog(m_scriptManager); dialog->show(); } void EditorWindow::applyPrefs() { m_vocabularyView->reset(); } void EditorWindow::removeGrades() { m_mainWindow->parleyDocument()->document()->lesson()->resetGrades(-1, KEduVocContainer::Recursive); } void EditorWindow::initScripts() { m_scriptManager = new ScriptManager(this); m_vocabularyView->setTranslator(m_scriptManager->translator()); //Load scripts m_scriptManager->loadScripts(); } void EditorWindow::saveState() { m_vocabularyView->saveColumnVisibility(); } void EditorWindow::slotLanguagesChanged() { m_vocabularyModel->resetLanguages(); } diff --git a/src/editor/editor.h b/src/editor/editor.h index 9124dd8b..ee545b47 100644 --- a/src/editor/editor.h +++ b/src/editor/editor.h @@ -1,166 +1,164 @@ /*************************************************************************** Copyright 1999-2001 Ewald Arnold Copyright 2004-2007 Peter Hedlund Copyright 2007-2009 Frederik Gladhorn Copyright 2008 Daniel Laidig ***************************************************************************/ /*************************************************************************** * * * 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. * * * ***************************************************************************/ #ifndef EDITOR_H #define EDITOR_H #include "parleydocument.h" #include "scripts/scripting/parley.h" #include -class QSignalMapper; class QLineEdit; class ScriptManager; ///@brief contains objects for the editor main window // Models around the Collection / KEduVocDocument class LessonModel; class VocabularyModel; class VocabularyFilter; class WordClassModel; namespace Editor { class VocabularyView; class LessonView; class WordTypeView; class InflectionWidget; class ComparisonWidget; class SummaryWordWidget; class LatexWidget; class SynonymWidget; class EditorWindow : public KXmlGuiWindow { Q_OBJECT public: explicit EditorWindow(ParleyMainWindow* parent); ~EditorWindow(); /** * setup the action (menus etc) */ void initActions(); /** setup the main model*/ void initModel(); /** setup the main view*/ void initView(); void initDockWidgets(); /** This will look at the lesson list and also the combo box to determine what should be displayed in the table. */ void updateTableFilter(); public slots: /** * Load enabled scripts (from configuration parleyrc) */ void initScripts(); /** * Edit languages contained in the document. * This includes adding/removing languages, * editing articles, personal pronouns and tenses. */ void slotLanguagesChanged(); void slotConfigShowSearch(); /** * Display script manager (open a new window / or Settings window) */ void slotShowScriptManager(); void applyPrefs(); /** * Removes all grading information from the current document */ void removeGrades(); /** when closing the application, save the editor's state */ void saveState(); /** * Set the current doc (after creating a new one or opening a file) */ void updateDocument(KEduVocDocument *doc); /** * DBus method for adding words by external apps */ void addWordWithTranslation(const QStringList &w); private slots: /** Make the search bar visible and focus it */ void startSearch(); signals: void signalSetData(const QList& entries, int currentTranslation); private: ParleyMainWindow *m_mainWindow; QAction* m_vocabShowSearchBarAction; VocabularyModel *m_vocabularyModel; VocabularyView *m_vocabularyView; VocabularyFilter *m_vocabularyFilter; QLineEdit *m_searchLine; QWidget *m_searchWidget; QAction *m_spellCheckMenu; - QSignalMapper *m_spellCheckMapper; /** Show a single conjugation and let the user edit it */ InflectionWidget *m_inflectionWidget; SummaryWordWidget *m_summaryWordWidget; ComparisonWidget *m_comparisonWidget; LatexWidget *m_latexWidget; SynonymWidget *m_synonymWidget; SynonymWidget *m_antonymWidget; SynonymWidget *m_falseFriendWidget; /// dock widgets to display lessons, word types, ... LessonView *m_lessonView; LessonModel *m_lessonModel; WordClassModel *m_wordTypeModel; WordTypeView *m_wordTypeView; ScriptManager* m_scriptManager; ///stores all the translations of a vocabulary word Translator* m_translator; QList m_dockWidgets; QList m_dockWidgetVisibility; friend class ::ParleyDocument; friend class Scripting::Parley; friend class ::ScriptManager; }; } #endif // EDITOR_H diff --git a/src/editor/summarywordwidget.cpp b/src/editor/summarywordwidget.cpp index 68bd4d21..7728a85a 100644 --- a/src/editor/summarywordwidget.cpp +++ b/src/editor/summarywordwidget.cpp @@ -1,227 +1,228 @@ /*************************************************************************** Copyright 2007 Frederik Gladhorn Copyright 2008 Javier Goday ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "summarywordwidget.h" #include "languagesettings.h" #include "lessonmodel.h" #include "vocabularymodel.h" #include "vocabularyfilter.h" #include "wordclassmodel.h" // Qt headers #include #include #include #include #include #include // KEduVocDocument #include #include #include #include using namespace Editor; SummaryWordWidget::SummaryWordWidget(VocabularyFilter *model, KEduVocDocument *doc, QWidget *parent) : QWidget(parent) , m_doc(doc) , m_wordTypeModel(0) , m_wordTypeView(0) , m_entry(0) , m_translationId(0) { Q_ASSERT(model); Q_ASSERT(m_doc); m_model = model; setupUi(this); slotDocumentChanged(m_doc); m_mapper = new QDataWidgetMapper(this); m_mapper->setModel(model); m_mapper->setItemDelegate(new SummaryWordDelegate(this)); - connect(wordTypeComboBox, static_cast(&KComboBox::currentIndexChanged), this, &SummaryWordWidget::wordTypeSelected); + connect(wordTypeComboBox, QOverload::of(&KComboBox::currentTextChanged), + this, &SummaryWordWidget::wordTypeSelected); } void SummaryWordWidget::setTranslation(KEduVocExpression *entry, int translation) { if (entry) { // we need to map the widgets relative to the translation (each translation has 9 columns) m_mapper->clearMapping(); m_mapper->addMapping(wordEntry, VocabularyModel::EntryColumnsMAX * translation + VocabularyModel::Translation); //m_mapper->addMapping(wordTypeComboBox, // VocabularyModel::EntryColumnsMAX * translation + VocabularyModel::WordType); m_mapper->addMapping(pronunciationEntry, VocabularyModel::EntryColumnsMAX * translation + VocabularyModel::Pronunciation); m_mapper->addMapping(exampleEntry, VocabularyModel::EntryColumnsMAX * translation + VocabularyModel::Example); m_mapper->addMapping(paraphraseEntry, VocabularyModel::EntryColumnsMAX * translation + VocabularyModel::Paraphrase); m_mapper->addMapping(commentEntry, VocabularyModel::EntryColumnsMAX * translation + VocabularyModel::Comment); languageLabel->setText("" + m_doc->identifier(translation).name() + ""); lessonLabel->setText(entry->lesson()->name()); setCurrentWordType(entry, translation); } else { clear(); } m_entry = entry; m_translationId = translation; } void SummaryWordWidget::slotDocumentChanged(KEduVocDocument *doc) { m_doc = doc; if (!m_doc) { qDebug() << "Set invalid document"; delete m_wordTypeModel; m_wordTypeModel = 0; } else { delete m_wordTypeView; if (!m_wordTypeModel) { qDebug() << "Create word type model for summary view"; m_wordTypeModel = new WordClassModel(this); } m_wordTypeModel->setDocument(m_doc); m_wordTypeView = new QTreeView(this); m_wordTypeView->setModel(m_wordTypeModel); wordTypeComboBox->setModel(m_wordTypeModel); wordTypeComboBox->setView(m_wordTypeView); m_wordTypeView->setColumnHidden(1, true); m_wordTypeView->header()->setVisible(false); m_wordTypeView->setRootIsDecorated(true); m_wordTypeView->expandAll(); } } void SummaryWordWidget::slotSelectionChanged(const QItemSelection &itemSelected, const QItemSelection &itemDeselected) { Q_UNUSED(itemDeselected) if (itemSelected.indexes().size() >= 1) { // the selected index belongs to VocabularyFilter, when we need it from the vocabulary model QModelIndex index = m_model->index(itemSelected.indexes().at(0).row(), itemSelected.indexes().at(0).column()); m_mapper->setCurrentModelIndex(index); } } /* void SummaryWordWidget::populateLessonList(KEduVocExpression *entry) { lessonComboBox->clear(); LessonModel *basicLessonModel = new LessonModel(this); lessonComboBox->setModel(basicLessonModel); QTreeView *view = new QTreeView(this); view->setModel(basicLessonModel); lessonComboBox->setView(view); basicLessonModel->setDocument(m_doc); view->header()->setVisible(false); view->setRootIsDecorated(true); view->expandAll(); view->setCurrentIndex(basicLessonModel->index(entry->lesson())); } */ void SummaryWordWidget::setCurrentWordType(KEduVocExpression *entry, int translation) { if (entry && entry->translation(translation)->wordType()) { qDebug() << "Set current word type: " << entry->translation(translation)->wordType()->name(); // select the right word type m_wordTypeView->setCurrentIndex(m_wordTypeModel->index(entry->translation(translation)->wordType())); } else { wordTypeComboBox->setCurrentIndex(-1); } } void SummaryWordWidget::clear() { qDebug() << "Clear summary widget"; languageLabel->setText(QString()); wordEntry->setText(QString()); // lessonComboBox->clear(); lessonLabel->setText(QString()); pronunciationEntry->setText(QString()); exampleEntry->setText(QString()); paraphraseEntry->setText(QString()); commentEntry->setText(QString()); } SummaryWordDelegate::SummaryWordDelegate(QObject *parent) : QItemDelegate(parent) { } void SummaryWordDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { if (!index.isValid()) { return; } if (editor) { switch (VocabularyModel::columnType(index.column())) { case VocabularyModel::WordClass: break; case VocabularyModel::Comment: case VocabularyModel::Pronunciation: case VocabularyModel::Translation: case VocabularyModel::Example: case VocabularyModel::Paraphrase: QLineEdit *entry = static_cast (editor); if (entry) { entry->setText(index.model()->data(index).toString()); } break; } } } void SummaryWordWidget::wordTypeSelected(const QString& wordTypeName) { if (!m_doc || !m_entry) { return; } KEduVocContainer* container = m_doc->wordTypeContainer()->childContainer(wordTypeName); if (container) { KEduVocWordType *wordType = static_cast(container); if (wordType) { m_entry->translation(m_translationId)->setWordType(wordType); } } } diff --git a/src/editor/vocabularyview.cpp b/src/editor/vocabularyview.cpp index eb539d9c..e330f00a 100644 --- a/src/editor/vocabularyview.cpp +++ b/src/editor/vocabularyview.cpp @@ -1,465 +1,465 @@ /*************************************************************************** Copyright 2006, 2007 Peter Hedlund Copyright 2007-2008 Frederik Gladhorn ***************************************************************************/ /*************************************************************************** * * * 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. * * * ***************************************************************************/ ///@file vocabularyview.cpp #include "vocabularyview.h" #include "vocabularyheaderview.h" #include "vocabularymodel.h" #include "vocabularyfilter.h" #include "vocabularydelegate.h" #include "vocabularymimedata.h" #include "editor/editor.h" #include "prefs.h" #include "vocabularycolumnsdialog.h" #include "documentsettings.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace Editor; VocabularyView::VocabularyView(EditorWindow * parent) : QTableView(parent), m_model(0), m_doc(0), m_spellChecker(0), m_spellDialog(0) { installEventFilter(this); setHorizontalHeader(new VocabularyHeaderView(Qt::Horizontal, this)); horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive); horizontalHeader()->setSectionsMovable(true); setEditTriggers(QAbstractItemView::AnyKeyPressed | QAbstractItemView::EditKeyPressed | QAbstractItemView::DoubleClicked); setSortingEnabled(true); setTabKeyNavigation(true); m_vocabularyDelegate = new VocabularyDelegate(this); setItemDelegate(m_vocabularyDelegate); setFrameStyle(QFrame::NoFrame); setAlternatingRowColors(true); // Enable context menus setContextMenuPolicy(Qt::ActionsContextMenu); horizontalHeader()->setContextMenuPolicy(Qt::ActionsContextMenu); setWordWrap(true); setDragEnabled(true); // smooth scrolling horizontally, otherwise it tries to jump from item to item. setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel); m_appendEntryAction = new QAction(this); parent->actionCollection()->addAction(QStringLiteral("edit_append"), m_appendEntryAction); parent->actionCollection()->setDefaultShortcut( m_appendEntryAction, QKeySequence(Qt::Key_Insert)); m_appendEntryAction->setIcon(QIcon::fromTheme(QStringLiteral("list-add-card"))); m_appendEntryAction->setText(i18n("&Add New Entry")); connect(m_appendEntryAction, &QAction::triggered, this, &VocabularyView::appendEntry); m_appendEntryAction->setShortcut(QKeySequence(Qt::Key_Insert)); m_appendEntryAction->setWhatsThis(i18n("Append a new row to the vocabulary")); m_appendEntryAction->setToolTip(m_appendEntryAction->whatsThis()); m_appendEntryAction->setStatusTip(m_appendEntryAction->whatsThis()); addAction(m_appendEntryAction); m_deleteEntriesAction = new QAction(this); parent->actionCollection()->addAction(QStringLiteral("edit_remove_selected_area"), m_deleteEntriesAction); parent->actionCollection()->setDefaultShortcut( m_deleteEntriesAction, QKeySequence::Delete); m_deleteEntriesAction->setIcon(QIcon::fromTheme(QStringLiteral("list-remove-card"))); m_deleteEntriesAction->setText(i18n("&Delete Entry")); connect(m_deleteEntriesAction, &QAction::triggered, this, &VocabularyView::deleteSelectedEntries); m_deleteEntriesAction->setShortcut(QKeySequence::Delete); m_deleteEntriesAction->setWhatsThis(i18n("Delete the selected rows")); m_deleteEntriesAction->setToolTip(m_deleteEntriesAction->whatsThis()); m_deleteEntriesAction->setStatusTip(m_deleteEntriesAction->whatsThis()); addAction(m_deleteEntriesAction); QAction* separator = new QAction(this); separator->setSeparator(true); addAction(separator); m_copyAction = KStandardAction::copy(this, SLOT(slotEditCopy()), parent->actionCollection()); parent->actionCollection()->setDefaultShortcut( m_copyAction, QKeySequence::Copy); m_copyAction->setWhatsThis(i18n("Copy")); m_copyAction->setToolTip(m_copyAction->whatsThis()); m_copyAction->setStatusTip(m_copyAction->whatsThis()); addAction(m_copyAction); m_cutAction = KStandardAction::cut(this, SLOT(slotCutEntry()), parent->actionCollection()); parent->actionCollection()->setDefaultShortcut( m_cutAction, QKeySequence::Cut); m_cutAction->setWhatsThis(i18n("Cut")); m_cutAction->setToolTip(m_cutAction->whatsThis()); m_cutAction->setStatusTip(m_cutAction->whatsThis()); addAction(m_cutAction); m_pasteAction = KStandardAction::paste(this, SLOT(slotEditPaste()), parent->actionCollection()); parent->actionCollection()->setDefaultShortcut( m_pasteAction, QKeySequence::Paste); m_pasteAction->setWhatsThis(i18n("Paste")); m_pasteAction->setToolTip(m_pasteAction->whatsThis()); m_pasteAction->setStatusTip(m_pasteAction->whatsThis()); addAction(m_pasteAction); m_selectAllAction = KStandardAction::selectAll(this, SLOT(selectAll()), parent->actionCollection()); parent->actionCollection()->setDefaultShortcut( m_selectAllAction, QKeySequence::SelectAll); m_selectAllAction->setWhatsThis(i18n("Select all rows")); m_selectAllAction->setToolTip(m_selectAllAction->whatsThis()); m_selectAllAction->setStatusTip(m_selectAllAction->whatsThis()); m_clearSelectionAction = KStandardAction::deselect(this, SLOT(clearSelection()), parent->actionCollection()); parent->actionCollection()->setDefaultShortcut( m_clearSelectionAction, QKeySequence::Deselect); m_clearSelectionAction->setWhatsThis(i18n("Deselect all rows")); m_clearSelectionAction->setToolTip(m_clearSelectionAction->whatsThis()); m_clearSelectionAction->setStatusTip(m_clearSelectionAction->whatsThis()); // vocabulary columns dialog QAction *vocabularyColumnsDialogAction = new QAction(this); parent->actionCollection()->addAction(QStringLiteral("show_vocabulary_columns_dialog"), vocabularyColumnsDialogAction); vocabularyColumnsDialogAction->setIcon(QIcon::fromTheme(QStringLiteral("view-file-columns"))); vocabularyColumnsDialogAction->setText(i18n("Vocabulary Columns...")); vocabularyColumnsDialogAction->setWhatsThis(i18n("Toggle display of individual vocabulary columns")); vocabularyColumnsDialogAction->setToolTip(vocabularyColumnsDialogAction->whatsThis()); vocabularyColumnsDialogAction->setStatusTip(vocabularyColumnsDialogAction->whatsThis()); horizontalHeader()->addAction(vocabularyColumnsDialogAction); addAction(vocabularyColumnsDialogAction); connect(vocabularyColumnsDialogAction, &QAction::triggered, this, &VocabularyView::slotShowVocabularyColumnsDialog); } void VocabularyView::setFilter(VocabularyFilter * model) { QTableView::setModel(model); m_model = model; connect(selectionModel(), &QItemSelectionModel::currentChanged, this, &VocabularyView::slotCurrentChanged); connect(selectionModel(), &QItemSelectionModel::selectionChanged, this, &VocabularyView::slotSelectionChanged); slotSelectionChanged(QItemSelection(), QItemSelection()); } void VocabularyView::slotCurrentChanged(const QModelIndex & current, const QModelIndex & previous) { Q_UNUSED(previous); KEduVocExpression* entry = 0; if (current.isValid()) { entry = model()->data(current, VocabularyModel::EntryRole).value(); } emit translationChanged(entry, VocabularyModel::translation(current.column())); } void VocabularyView::reset() { QTableView::reset(); emit translationChanged(0, 0); QList visibleColumns; if (m_doc) { DocumentSettings ds(m_doc->url().url()); ds.load(); visibleColumns = ds.visibleColumns(); KConfig parleyConfig(QStringLiteral("parleyrc")); KConfigGroup documentGroup(&parleyConfig, "Document " + m_doc->url().url()); QByteArray state = documentGroup.readEntry("VocabularyColumns", QByteArray()); if (!horizontalHeader()->restoreState(state)) { resizeColumnsToContents(); } } horizontalHeader()->setSectionsMovable(true); for (int i = 0; i < model()->columnCount(QModelIndex()); i++) { if (i < visibleColumns.size()) { setColumnHidden(i, !visibleColumns.value(i)); } else { if (VocabularyModel::columnType(i) != VocabularyModel::Translation) { setColumnHidden(i, true); } } } } void VocabularyView::saveColumnVisibility() const { if (!m_doc) { return; } // Generate a QList for saving QList visibleList; for (int i = 0; i < m_model->columnCount(); ++i) { visibleList.append(static_cast(!isColumnHidden(i))); } DocumentSettings ds(m_doc->url().url()); ds.setVisibleColumns(visibleList); ds.save(); QByteArray saveState = horizontalHeader()->saveState(); KConfig parleyConfig(QStringLiteral("parleyrc")); KConfigGroup documentGroup(&parleyConfig, "Document " + m_doc->url().url()); documentGroup.writeEntry("VocabularyColumns", horizontalHeader()->saveState()); } void VocabularyView::appendEntry() { QModelIndex newIndex = m_model->appendEntry(); scrollTo(newIndex); selectionModel()->clear(); // otherwise proxy mapping gets screwed for some reason selectionModel()->select(newIndex, QItemSelectionModel::ClearAndSelect); selectionModel()->setCurrentIndex(newIndex, QItemSelectionModel::ClearAndSelect); edit(newIndex); } void VocabularyView::appendChar(const QChar &c) { const QModelIndex &index = selectionModel()->currentIndex(); m_model->setData(index, QString(m_model->data(index).toString() + c)); } void VocabularyView::deleteSelectedEntries(bool askConfirmation) { QSet rows; foreach(const QModelIndex & index, selectionModel()->selectedIndexes()) { rows.insert(index.row()); } bool del = true; if (askConfirmation) { del = KMessageBox::Continue == KMessageBox::warningContinueCancel(this, i18np("Do you really want to delete the selected entry?", "Do you really want to delete the selected %1 entries?", rows.count()), i18n("Delete"), KStandardGuiItem::del()); } if (del) { emit translationChanged(0, 0); while (!selectionModel()->selectedIndexes().isEmpty()) { m_model->removeRows(selectionModel()->selectedIndexes()[0].row(), 1, QModelIndex()); } } } void VocabularyView::slotEditCopy() { QModelIndexList sortedIndexes = selectionModel()->selectedIndexes(); - qSort(sortedIndexes); + std::sort(sortedIndexes.begin(), sortedIndexes.end()); QMimeData *mimeData = m_model->mimeData(sortedIndexes); QClipboard *clipboard = QApplication::clipboard(); clipboard->setMimeData(mimeData); } void VocabularyView::slotEditPaste() { QClipboard *clipboard = QApplication::clipboard(); const QMimeData *mimeData = clipboard->mimeData(); const VocabularyMimeData *vocMimeData = qobject_cast(mimeData); if (vocMimeData) { qDebug() << "Clipboard contains vocabulary mime data."; foreach(const VocabularyMimeData::MimeExpression & mimeEntry, vocMimeData->expressionList()) { KEduVocExpression *pasteExpression = new KEduVocExpression(mimeEntry.expression); m_model->appendEntry(pasteExpression); // find word type (create if not found) KEduVocWordType *type = m_doc->wordTypeContainer(); foreach(int translation, mimeEntry.wordTypes.keys()) { // append if needed foreach(const QString & typeName, mimeEntry.wordTypes.value(translation).wordType) { qDebug() << mimeEntry.wordTypes.value(translation).wordType; KEduVocContainer *childType = type->childContainer(typeName); if (!childType) { // the doc does not contain the right word type - create it childType = new KEduVocWordType(typeName); type->appendChildContainer(childType); } type = static_cast(childType); } pasteExpression->translation(translation)->setWordType(type); // check for special type stuff if (type->wordType() != mimeEntry.wordTypes.value(translation).grammarType) { if (type->wordType() == KEduVocWordFlag::NoInformation) { type->setWordType(mimeEntry.wordTypes.value(translation).grammarType); } } } } } else if (mimeData->hasText()) { qDebug() << "Clipboard contains text data."; // split at newline QStringList lines = clipboard->text().split('\n'); foreach(QString line, lines) { // split at tabs or semicolon: m_model->appendEntry(new KEduVocExpression(line.split(QRegExp(QStringLiteral("[\t;]")), QString::KeepEmptyParts))); } } } void VocabularyView::slotCutEntry() { slotEditCopy(); deleteSelectedEntries(false); } void VocabularyView::slotSelectionChanged(const QItemSelection &, const QItemSelection &) { bool hasSelection = selectionModel()->hasSelection(); m_deleteEntriesAction->setEnabled(hasSelection); m_clearSelectionAction->setEnabled(hasSelection); m_copyAction->setEnabled(hasSelection); m_cutAction->setEnabled(hasSelection); } void VocabularyView::setDocument(KEduVocDocument * doc) { m_doc = doc; m_vocabularyDelegate->setDocument(doc); QTimer::singleShot(0, this, SLOT(reset())); } /** * Set the translator to be used by the delegate * @param translator */ void VocabularyView::setTranslator(Translator* translator) { m_vocabularyDelegate->setTranslator(translator); } void VocabularyView::slotShowVocabularyColumnsDialog() { VocabularyColumnsDialog *dialog = new VocabularyColumnsDialog(m_doc, this); if (dialog->exec() == QDialog::Accepted) { reset(); } } void VocabularyView::checkSpelling(int language) { if (!m_model->rowCount()) { KMessageBox::information(this, i18n("Nothing to spell check.")); return; } if (!m_spellChecker) { m_spellChecker = new Sonnet::BackgroundChecker(this); m_spellDialog = new Sonnet::Dialog(m_spellChecker, this); connect(m_spellDialog, SIGNAL(done(QString)), this, SLOT(continueSpelling())); connect(m_spellDialog, &Sonnet::Dialog::misspelling, this, &VocabularyView::misspelling); connect(m_spellDialog, &Sonnet::Dialog::replace, this, &VocabularyView::spellingReplace); } m_spellColumn = language * VocabularyModel::EntryColumnsMAX; m_spellRow = -1; if (m_spellColumn < 0) { return; } QString locale = m_doc->identifier(language).locale(); LanguageSettings settings(locale); QString spellCode = settings.spellChecker().isEmpty() ? locale : settings.spellChecker(); m_spellChecker->changeLanguage(spellCode); if (!m_spellChecker->speller().isValid()) { qDebug() << "Invalid Language, popup here!"; KNotification::event(KNotification::Warning, i18nc("@title of a popup", "No Spell Checker Available"), i18nc("@popupmessage", "Either the language set up is incorrect or no spellchecker was installed for this locale: %1.", locale)); } m_spellDialog->show(); continueSpelling(); } void VocabularyView::continueSpelling() { qDebug() << "Check spelling: " << m_spellRow << m_spellColumn; ++m_spellRow; while (m_spellRow < m_model->rowCount()) { QModelIndex index = m_model->index(m_spellRow, m_spellColumn); qDebug() << " " << m_model->data(index).toString(); if (!m_model->data(index).toString().isEmpty()) { m_spellDialog->setBuffer(m_model->data(index).toString()); break; } else { ++m_spellRow; } } } void VocabularyView::selectIndex(const QModelIndex &newIndex) { selectionModel()->select(newIndex, QItemSelectionModel::ClearAndSelect); selectionModel()->setCurrentIndex(newIndex, QItemSelectionModel::ClearAndSelect); scrollTo(newIndex); } bool VocabularyView::eventFilter(QObject* obj, QEvent* event) { if (event->type() == QEvent::KeyPress && Prefs::smartAppend()) { QKeyEvent *keyEvent = static_cast(event); if (keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) { if (selectionModel()->currentIndex().row() == m_model->rowCount() - 1) { appendEntry(); } } } // standard event processing return QObject::eventFilter(obj, event); } void VocabularyView::misspelling(const QString & word, int start) { Q_UNUSED(word) Q_UNUSED(start) QModelIndex index = m_model->index(m_spellRow, m_spellColumn); selectIndex(index); } void VocabularyView::spellingReplace(const QString & oldWord, int start, const QString & newWord) { qDebug() << oldWord << start << newWord; QModelIndex index = m_model->index(m_spellRow, m_spellColumn); QString data = index.data().toString(); QString newData = data.replace(start, oldWord.length(), newWord); qDebug() << "Changing " << data << " to " << newData; m_model->setData(index, newData); } QModelIndexList VocabularyView::getSelectedIndexes() const { return selectionModel()->selectedIndexes(); } diff --git a/src/practice/practicesummarycomponent.cpp b/src/practice/practicesummarycomponent.cpp index 0958cf69..6cb87dc2 100644 --- a/src/practice/practicesummarycomponent.cpp +++ b/src/practice/practicesummarycomponent.cpp @@ -1,201 +1,201 @@ /*************************************************************************** Copyright 2007-2009 Frederik Gladhorn *************************************************************************** *************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "practicesummarycomponent.h" #include "prefs.h" #include "parleyactions.h" #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace Practice; class PracticeSummaryComponent::SortedAttemptTableWidgetItem: public QTableWidgetItem { bool operator<(const QTableWidgetItem &other) const Q_DECL_OVERRIDE { if (data(Qt::DisplayRole).toInt() == other.data(Qt::DisplayRole).toInt()) { return data(Qt::UserRole).toInt() < other.data(Qt::UserRole).toInt(); } return data(Qt::DisplayRole).toInt() < other.data(Qt::DisplayRole).toInt(); } }; PracticeSummaryComponent::PracticeSummaryComponent(SessionManagerBase* sessionManager, QWidget* parent) : KXmlGuiWindow(parent) , m_sessionManager(sessionManager) { // KXmlGui setXMLFile(QStringLiteral("practicesummaryui.rc")); setObjectName(QStringLiteral("Statistics")); QWidget *mainWidget = new QWidget(this); setupUi(mainWidget); setCentralWidget(mainWidget); initActions(parent); setupDetailsTable(); summaryBar->setStatistics(m_sessionManager->statisticTotalCorrectFirstAttempt(), m_sessionManager->statisticTotalWrong(), m_sessionManager->statisticTotalUnanswered()); int total = m_sessionManager->statisticTotalCorrectFirstAttempt() + m_sessionManager->statisticTotalWrong(); int minutes = m_sessionManager->totalTime() / 60; int seconds = m_sessionManager->totalTime() % 60; testSummaryLabel->setText(i18nc("number of words, minutes, seconds", "You practiced %1 in %2 and %3.", i18np("one word", "%1 words", total), i18np("one minute", "%1 minutes", minutes), i18np("one second", "%1 seconds", seconds))); KConfigGroup cfg(KSharedConfig::openConfig(QStringLiteral("parleyrc")), objectName()); applyMainWindowSettings(cfg); } PracticeSummaryComponent::~PracticeSummaryComponent() { KConfigGroup cfg(KSharedConfig::openConfig(QStringLiteral("parleyrc")), objectName()); saveMainWindowSettings(cfg); } void PracticeSummaryComponent::initActions(QWidget* parleyMainWindow) { ParleyActions::create(ParleyActions::EnterEditMode, parleyMainWindow, SLOT(showEditor()), actionCollection()); ParleyActions::create(ParleyActions::StartPractice, parleyMainWindow, SLOT(showPracticeConfiguration()), actionCollection()); ParleyActions::create(ParleyActions::ExportPracticeResults, this, SLOT(exportResults()), actionCollection()); actionCollection()->action(QStringLiteral("practice_start"))->setText(i18n("Practice Overview")); actionCollection()->action(QStringLiteral("practice_start"))->setToolTip(i18n("Switch to the Practice Overview page")); } void PracticeSummaryComponent::setupDetailsTable() { tableWidget->setRowCount(m_sessionManager->allEntryCount()); tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); Qt::ItemFlags flags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); KColorScheme scheme(QPalette::Active); QPalette correctPalette = QApplication::palette(); correctPalette.setColor(QPalette::WindowText, scheme.foreground(KColorScheme::PositiveText).color()); correctPalette.setColor(QPalette::Text, scheme.foreground(KColorScheme::PositiveText).color()); QPalette wrongPalette = QApplication::palette(); wrongPalette.setColor(QPalette::WindowText, scheme.foreground(KColorScheme::NegativeText).color()); wrongPalette.setColor(QPalette::Text, scheme.foreground(KColorScheme::NegativeText).color()); int i = 0; // TODO headers with languages // TODO some colors, maybe an indicator icon whether the word was right/wrong foreach(TestEntry * entry, m_sessionManager->allTestEntries()) { QTableWidgetItem* itemFrom = new QTableWidgetItem( entry->entry()->translation(entry->TestEntry::languageFrom())->text()); QTableWidgetItem* itemTo = new QTableWidgetItem( entry->entry()->translation(entry->languageTo())->text()); if (entry->statisticGoodCount() > 0) { - itemTo->setForeground(correctPalette.foreground()); + itemTo->setForeground(correctPalette.windowText()); } QTableWidgetItem* itemUserAnswer = new QTableWidgetItem( entry->userAnswers().join(QStringLiteral("; "))); - itemUserAnswer->setForeground(wrongPalette.foreground()); + itemUserAnswer->setForeground(wrongPalette.windowText()); SortedAttemptTableWidgetItem* itemAttempts = new SortedAttemptTableWidgetItem(); itemAttempts->setData(Qt::DisplayRole, entry->statisticCount()); itemAttempts->setData(Qt::UserRole, entry->statisticBadCount()); itemAttempts->setTextAlignment(Qt::AlignRight); itemFrom->setFlags(flags); itemTo->setFlags(flags); itemUserAnswer->setFlags(flags); itemAttempts->setFlags(flags); if (entry->correctAtFirstAttempt()) { itemUserAnswer->setIcon(QIcon::fromTheme(QStringLiteral("dialog-ok-apply"))); } else if (entry->statisticGoodCount() > 0) { itemUserAnswer->setIcon(QIcon::fromTheme(QStringLiteral("task-attempt"))); } else if (entry->statisticCount() > 0) { itemUserAnswer->setIcon(QIcon::fromTheme(QStringLiteral("dialog-error"))); } else { itemUserAnswer->setIcon(QIcon::fromTheme(QStringLiteral("task-attempt"))); } tableWidget->setItem(i, 0, itemAttempts); tableWidget->setItem(i, 1, itemFrom); tableWidget->setItem(i, 2, itemTo); tableWidget->setItem(i, 3, itemUserAnswer); ++i; } tableWidget->horizontalHeader()->resizeSections(QHeaderView::ResizeToContents); tableWidget->setSortingEnabled(true); tableWidget->sortItems(0, Qt::DescendingOrder); } void PracticeSummaryComponent::exportResults() { QString filter = i18n("HTML Files") + " (*.html);;" + i18n("OpenDocument text files") + " (*.odt)" ; QString caption; QString startingdir(QStringLiteral("kfiledialog:///practice_export")); QString fileName = QFileDialog::getSaveFileName(0, caption, startingdir , filter); if (fileName.isEmpty()) { return; } QTextDocument doc; doc.setHtml("" + i18n("Practice results") + ""); QTextCursor cursor(&doc); cursor.insertHtml("

" + m_sessionManager->title() + "


"); cursor.insertText(i18n("Answered questions: %1\n", m_sessionManager->allEntryCount())); cursor.insertText(i18n("Correct answers: %1\n", m_sessionManager->statisticTotalCorrectFirstAttempt())); cursor.insertText(i18n("Wrong answers: %1\n", m_sessionManager->statisticTotalWrong())); QTextTableFormat tableFormat; tableFormat.setBorderStyle(QTextFrameFormat::BorderStyle_Solid); tableFormat.setCellPadding(1); tableFormat.setAlignment(Qt::AlignLeft); QTextTable *table = cursor.insertTable(1, 4, tableFormat); table->cellAt(0, 0).firstCursorPosition().insertHtml(i18n("Attempts")); table->cellAt(0, 1).firstCursorPosition().insertHtml(i18n("Question")); table->cellAt(0, 2).firstCursorPosition().insertHtml(i18n("Correct answer")); table->cellAt(0, 3).firstCursorPosition().insertHtml(i18n("Your errors")); foreach(TestEntry * entry, m_sessionManager->allTestEntries()) { table->appendRows(1); int newRow = table->rows() - 1; table->cellAt(newRow, 0).firstCursorPosition().insertText(QString::number(entry->statisticCount())); table->cellAt(newRow, 1).firstCursorPosition().insertText(entry->entry()->translation(entry->languageFrom())->text()); table->cellAt(newRow, 2).firstCursorPosition().insertText(entry->entry()->translation(entry->languageTo())->text()); table->cellAt(newRow, 3).firstCursorPosition().insertText(entry->userAnswers().join(QStringLiteral("; "))); } QTextDocumentWriter writer(fileName); if (!writer.write(&doc)) { KMessageBox::error(this, i18n("Could not write to %1", fileName), i18n("Could not write file")); return; } } diff --git a/src/settings/languagepropertiespage.cpp b/src/settings/languagepropertiespage.cpp index a87c21d5..22ae8af9 100644 --- a/src/settings/languagepropertiespage.cpp +++ b/src/settings/languagepropertiespage.cpp @@ -1,428 +1,429 @@ /*************************************************************************** Copyright 2008 Frederik Gladhorn ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "languagepropertiespage.h" #include "languagesettings.h" #include "documentproperties.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define TENSE_TAG ". " LanguagePropertiesPage::LanguagePropertiesPage(KEduVocDocument *doc, int identifierIndex, QWidget *parent) : QWidget(parent), m_doc(doc), m_identifierIndex(identifierIndex) { setupUi(this); - connect(localeComboBox, static_cast(&KComboBox::currentIndexChanged), this, &LanguagePropertiesPage::localeChanged); + connect(localeComboBox, QOverload::of(&KComboBox::currentTextChanged), + this, &LanguagePropertiesPage::localeChanged); connect(downloadGrammarButton, &QPushButton::clicked, this, &LanguagePropertiesPage::downloadGrammar); // qmap automatically sorts by keys QMap languageCodeMap = DocumentProperties::localeLangsMap(); // add the language, but also it's code as data foreach(const QString & language, languageCodeMap.keys()) { localeComboBox->addItem(language, languageCodeMap.value(language)); } if (m_identifierIndex < m_doc->identifierCount()) { localeComboBox->setCurrentIndex(localeComboBox->findData( m_doc->identifier(m_identifierIndex).locale())); identifierNameLineEdit->setText(m_doc->identifier(m_identifierIndex).name()); } int index = (m_identifierIndex < m_doc->identifierCount() ? m_identifierIndex : 0); LanguageSettings settings(m_doc->identifier(index).locale()); settings.load(); // fonts editorFont->setFont(settings.editorFont()); practiceFont->setFont(settings.practiceFont()); // keyboard layout // try to talk to kxbk - get a list of keyboard layouts QDBusInterface kxbk(QStringLiteral("org.kde.keyboard"), QStringLiteral("/Layouts"), QStringLiteral("org.kde.KeyboardLayouts")); QDBusReply reply = kxbk.call(QStringLiteral("getLayoutsList")); if (reply.isValid()) { QStringList layouts = reply; layouts.prepend(QString()); keyboardLayoutComboBox->clear(); keyboardLayoutComboBox->addItems(layouts); keyboardLayoutComboBox->setEnabled(true); QDBusReply currentLayout = kxbk.call(QStringLiteral("getCurrentLayout")); keyboardLayoutComboBox->setCurrentIndex(keyboardLayoutComboBox->findText(currentLayout)); if (m_identifierIndex < m_doc->identifierCount()) { if (!settings.keyboardLayout().isEmpty()) { keyboardLayoutComboBox->setCurrentIndex(keyboardLayoutComboBox->findText(settings.keyboardLayout())); } } } else { qDebug() << "kxkb dbus error"; keyboardLayoutComboBox->setEnabled(false); keyboardLayoutComboBox->addItem(i18n("No KDE keyboard selector found.")); } Sonnet::Speller speller; QMap dicts = speller.availableDictionaries(); QMap::const_iterator iter = dicts.constBegin(); while (iter != dicts.constEnd()) { spellcheckerComboBox->addItem(iter.key(), iter.value()); ++iter; } spellcheckerComboBox->model()->sort(0); spellcheckerComboBox->setCurrentIndex(spellcheckerComboBox->findData(settings.spellChecker())); loadGrammarFromDocument(); } void LanguagePropertiesPage::setLanguageIdentifierIndex(int newIndex) { m_identifierIndex = newIndex; } namespace DocumentHelper { void fetchGrammar(KEduVocDocument* doc, int languageIndex); } void LanguagePropertiesPage::downloadGrammar() { DocumentHelper::fetchGrammar(m_doc, m_identifierIndex); loadGrammarFromDocument(); } void LanguagePropertiesPage::loadGrammarFromDocument() { if (m_identifierIndex < m_doc->identifierCount()) { // articles KEduVocArticle articles = m_doc->identifier(m_identifierIndex).article(); def_male->setText(articles.article(KEduVocWordFlag::Singular | KEduVocWordFlag::Definite | KEduVocWordFlag::Masculine)); indef_male->setText(articles.article(KEduVocWordFlag::Singular | KEduVocWordFlag::Indefinite | KEduVocWordFlag::Masculine)); def_female->setText(articles.article(KEduVocWordFlag::Singular | KEduVocWordFlag::Definite | KEduVocWordFlag::Feminine)); indef_female->setText(articles.article(KEduVocWordFlag::Singular | KEduVocWordFlag::Indefinite | KEduVocWordFlag::Feminine)); def_natural->setText(articles.article(KEduVocWordFlag::Singular | KEduVocWordFlag::Definite | KEduVocWordFlag::Neuter)); indef_natural->setText(articles.article(KEduVocWordFlag::Singular | KEduVocWordFlag::Indefinite | KEduVocWordFlag::Neuter)); def_male_plural->setText(articles.article(KEduVocWordFlag::Plural | KEduVocWordFlag::Definite | KEduVocWordFlag::Masculine)); indef_male_plural->setText(articles.article(KEduVocWordFlag::Plural | KEduVocWordFlag::Indefinite | KEduVocWordFlag::Masculine)); def_female_plural->setText(articles.article(KEduVocWordFlag::Plural | KEduVocWordFlag::Definite | KEduVocWordFlag::Feminine)); indef_female_plural->setText(articles.article(KEduVocWordFlag::Plural | KEduVocWordFlag::Indefinite | KEduVocWordFlag::Feminine)); def_natural_plural->setText(articles.article(KEduVocWordFlag::Plural | KEduVocWordFlag::Definite | KEduVocWordFlag::Neuter)); indef_natural_plural->setText(articles.article(KEduVocWordFlag::Plural | KEduVocWordFlag::Indefinite | KEduVocWordFlag::Neuter)); // personal pronouns const KEduVocWordFlags numS = KEduVocWordFlag::Singular; const KEduVocWordFlags numD = KEduVocWordFlag::Dual; const KEduVocWordFlags numP = KEduVocWordFlag::Plural; KEduVocPersonalPronoun pronoun = m_doc->identifier(m_identifierIndex).personalPronouns(); first_singular->setText(pronoun.personalPronoun(KEduVocWordFlag::First | numS)); second_singular->setText(pronoun.personalPronoun(KEduVocWordFlag::Second | numS)); thirdM_singular->setText(pronoun.personalPronoun(KEduVocWordFlag::Third | KEduVocWordFlag::Masculine | numS)); thirdF_singular->setText(pronoun.personalPronoun(KEduVocWordFlag::Third | KEduVocWordFlag::Feminine | numS)); thirdN_singular->setText(pronoun.personalPronoun(KEduVocWordFlag::Third | KEduVocWordFlag::Neuter | numS)); dualFirstLineEdit->setText(pronoun.personalPronoun(KEduVocWordFlag::First | numD)); dualSecondLineEdit->setText(pronoun.personalPronoun(KEduVocWordFlag::Second | numD)); dualThirdMaleLineEdit->setText(pronoun.personalPronoun(KEduVocWordFlag::Third | KEduVocWordFlag::Masculine | numD)); dualThirdFemaleLineEdit->setText(pronoun.personalPronoun(KEduVocWordFlag::Third | KEduVocWordFlag::Feminine | numD)); dualThirdNeutralLineEdit->setText(pronoun.personalPronoun(KEduVocWordFlag::Third | KEduVocWordFlag::Neuter | numD)); first_plural->setText(pronoun.personalPronoun(KEduVocWordFlag::First | numP)); second_plural->setText(pronoun.personalPronoun(KEduVocWordFlag::Second | numP)); thirdM_plural->setText(pronoun.personalPronoun(KEduVocWordFlag::Third | KEduVocWordFlag::Masculine | numP)); thirdF_plural->setText(pronoun.personalPronoun(KEduVocWordFlag::Third | KEduVocWordFlag::Feminine | numP)); thirdN_plural->setText(pronoun.personalPronoun(KEduVocWordFlag::Third | KEduVocWordFlag::Neuter | numP)); maleFemaleDifferCheckBox->setChecked(pronoun.maleFemaleDifferent()); neutralCheckBox->setChecked(pronoun.neutralExists()); dualCheckBox->setChecked(pronoun.dualExists()); } // update shown labels etc... updateCheckBoxes(); connect(maleFemaleDifferCheckBox, &QCheckBox::toggled, this, &LanguagePropertiesPage::updateCheckBoxes); connect(neutralCheckBox, &QCheckBox::toggled, this, &LanguagePropertiesPage::updateCheckBoxes); connect(dualCheckBox, &QCheckBox::toggled, this, &LanguagePropertiesPage::updateCheckBoxes); // tenses connect(tenseList, &QListWidget::currentRowChanged, this, &LanguagePropertiesPage::slotTenseChosen); connect(deleteButton, &QPushButton::clicked, this, &LanguagePropertiesPage::slotDeleteTense); connect(modifyButton, &QPushButton::clicked, this, &LanguagePropertiesPage::slotModifyTense); connect(newButton, &QPushButton::clicked, this, &LanguagePropertiesPage::slotNewTense); if (m_identifierIndex < m_doc->identifierCount()) { int i = 1; foreach(const QString & tenseName, m_doc->identifier(m_identifierIndex).tenseList()) { tenseList->addItem(QStringLiteral("%1").arg(i++, 2).append(TENSE_TAG).append(tenseName)); tenseIndex.append(i); } } m_currentTense = 0; if (tenseList->count() > 0) { tenseList->setCurrentRow(m_currentTense); } modifyButton->setEnabled(tenseList->count() > 0); deleteButton->setEnabled(tenseList->count() > 0); tenseList->setFocus(); } void LanguagePropertiesPage::accept() { if (!isEnabled()) { // disabled pages are deleted languages return; } // general QString locale = localeComboBox->itemData(localeComboBox->currentIndex()).toString(); // if no locales are found (kdebase not installed?) at least fall back to using the language name as locale. if (locale.isEmpty()) { locale = identifierNameLineEdit->text(); } m_doc->identifier(m_identifierIndex).setLocale(locale); m_doc->identifier(m_identifierIndex).setName(identifierNameLineEdit->text()); LanguageSettings settings(locale); settings.setEditorFont(editorFont->font()); settings.setPracticeFont(practiceFont->font()); if (keyboardLayoutComboBox->isEnabled()) { settings.setKeyboardLayout(keyboardLayoutComboBox->currentText()); } int index = spellcheckerComboBox->currentIndex(); settings.setSpellChecker(spellcheckerComboBox->itemData(index).toString()); settings.save(); // articles const KEduVocWordFlag::Flags artSing = KEduVocWordFlag::Singular; // const KEduVocWordFlag::Flags artDual = KEduVocWordFlag::Dual; const KEduVocWordFlag::Flags artPlur = KEduVocWordFlag::Plural; const KEduVocWordFlag::Flags artDef = KEduVocWordFlag::Definite; const KEduVocWordFlag::Flags artIndef = KEduVocWordFlag::Indefinite; KEduVocArticle article; article.setArticle(def_male->text(), artSing | artDef | KEduVocWordFlag::Masculine); article.setArticle(indef_male->text(), artSing | artIndef | KEduVocWordFlag::Masculine); article.setArticle(def_female->text(), artSing | artDef | KEduVocWordFlag::Feminine); article.setArticle(indef_female->text(), artSing | artIndef | KEduVocWordFlag::Feminine); article.setArticle(def_natural->text(), artSing | artDef | KEduVocWordFlag::Neuter); article.setArticle(indef_natural->text(), artSing | artIndef | KEduVocWordFlag::Neuter); article.setArticle(def_male_plural->text(), artPlur | artDef | KEduVocWordFlag::Masculine); article.setArticle(indef_male_plural->text(), artPlur | artIndef | KEduVocWordFlag::Masculine); article.setArticle(def_female_plural->text(), artPlur | artDef | KEduVocWordFlag::Feminine); article.setArticle(indef_female_plural->text(), artPlur | artIndef | KEduVocWordFlag::Feminine); article.setArticle(def_natural_plural->text(), artPlur | artDef | KEduVocWordFlag::Neuter); article.setArticle(indef_natural_plural->text(), artPlur | artIndef | KEduVocWordFlag::Neuter); m_doc->identifier(m_identifierIndex).setArticle(article); // personal pronouns KEduVocPersonalPronoun pronoun; const KEduVocWordFlags numS = KEduVocWordFlag::Singular; const KEduVocWordFlags numD = KEduVocWordFlag::Dual; const KEduVocWordFlags numP = KEduVocWordFlag::Plural; pronoun.setPersonalPronoun(first_singular->text(), KEduVocWordFlag::First | numS); pronoun.setPersonalPronoun(second_singular->text(), KEduVocWordFlag::Second | numS); pronoun.setPersonalPronoun(thirdM_singular->text(), KEduVocWordFlag::Third | KEduVocWordFlag::Masculine | numS); pronoun.setPersonalPronoun(thirdF_singular->text(), KEduVocWordFlag::Third | KEduVocWordFlag::Feminine | numS); pronoun.setPersonalPronoun(thirdN_singular->text(), KEduVocWordFlag::Third | KEduVocWordFlag::Neuter | numS); pronoun.setPersonalPronoun(dualFirstLineEdit->text(), KEduVocWordFlag::First | numD); pronoun.setPersonalPronoun(dualSecondLineEdit->text(), KEduVocWordFlag::Second | numD); pronoun.setPersonalPronoun(dualThirdMaleLineEdit->text(), KEduVocWordFlag::Third | KEduVocWordFlag::Masculine | numD); pronoun.setPersonalPronoun(dualThirdFemaleLineEdit->text(), KEduVocWordFlag::Third | KEduVocWordFlag::Feminine | numD); pronoun.setPersonalPronoun(dualThirdNeutralLineEdit->text(), KEduVocWordFlag::Third | KEduVocWordFlag::Neuter | numD); pronoun.setPersonalPronoun(first_plural->text(), KEduVocWordFlag::First | numP); pronoun.setPersonalPronoun(second_plural->text(), KEduVocWordFlag::Second | numP); pronoun.setPersonalPronoun(thirdM_plural->text(), KEduVocWordFlag::Third | KEduVocWordFlag::Masculine | numP); pronoun.setPersonalPronoun(thirdF_plural->text(), KEduVocWordFlag::Third | KEduVocWordFlag::Feminine | numP); pronoun.setPersonalPronoun(thirdN_plural->text(), KEduVocWordFlag::Third | KEduVocWordFlag::Neuter | numP); pronoun.setMaleFemaleDifferent(maleFemaleDifferCheckBox->isChecked()); pronoun.setNeutralExists(neutralCheckBox->isChecked()); pronoun.setDualExists(dualCheckBox->isChecked()); m_doc->identifier(m_identifierIndex).setPersonalPronouns(pronoun); // tenses QList tenseIndex; QStringList tenses; QString str; for (int i = 0; i < (int) tenseList->count(); i++) { str = tenseList->item(i)->text(); tenses.append(str.mid(str.indexOf(TENSE_TAG) + QStringLiteral(TENSE_TAG).length())); } m_doc->identifier(m_identifierIndex).setTenseList(tenses); } void LanguagePropertiesPage::updateCheckBoxes() { bool maleFemale = maleFemaleDifferCheckBox->isChecked(); bool neutral = neutralCheckBox->isChecked(); bool dual = dualCheckBox->isChecked(); neutralCheckBox->setVisible(maleFemale); male_c_label->setVisible(maleFemale); female_c_label->setVisible(maleFemale); thirdM_singular->setVisible(maleFemale); thirdF_singular->setVisible(maleFemale); thirdM_plural->setVisible(maleFemale); thirdF_plural->setVisible(maleFemale); dualLabel->setVisible(dual); dualFirstLineEdit->setVisible(dual); dualSecondLineEdit->setVisible(dual); dualThirdMaleLineEdit->setVisible(dual && maleFemale); dualThirdFemaleLineEdit->setVisible(dual && maleFemale); if (!maleFemale) { natural_c_label->setVisible(false); thirdN_singular->setVisible(true); thirdN_plural->setVisible(true); dualThirdNeutralLineEdit->setVisible(dual); } else { natural_c_label->setVisible(neutral); thirdN_singular->setVisible(neutral); thirdN_plural->setVisible(neutral); dualThirdNeutralLineEdit->setVisible(dual && neutral); } } void LanguagePropertiesPage::localeChanged(const QString & locale) { identifierNameLineEdit->setText(locale); } // ************** TENSES ********************* void LanguagePropertiesPage::slotTenseChosen(int index) { m_currentTense = index; } void LanguagePropertiesPage::slotNewTense() { bool ok; QString getTense = QInputDialog::getText(this, i18n("Tense Name"), i18n("Enter name of tense:"), QLineEdit::Normal, QString(), &ok); if (!ok) return; QString str; int i = tenseList->count() + 1; tenseList->addItem(QStringLiteral("%1").arg(i, 2).append(TENSE_TAG).append(getTense.simplified())); tenseIndex.append(-(i - 1)); m_currentTense = tenseList->count(); tenseList->setCurrentRow(i - 1); modifyButton->setEnabled(true); deleteButton->setEnabled(true); } void LanguagePropertiesPage::slotModifyTense() { if (tenseList->count() != 0 && (int) tenseList->count() > m_currentTense) { QString str = tenseList->item(m_currentTense)->text(); str = str.mid(str.indexOf(TENSE_TAG) + QStringLiteral(TENSE_TAG).length()); bool ok; QString getTense = QInputDialog::getText(this, i18n("Tense Name"), i18n("Enter name of tense:"), QLineEdit::Normal, str, &ok); if (!ok) return; int i = m_currentTense + 1; tenseList->item(m_currentTense)->setText(QStringLiteral("%1").arg(i, 2).append(TENSE_TAG).append(getTense.simplified())); } } void LanguagePropertiesPage::updateListBox(int start) { QString str; for (int i = start; i < (int) tenseList->count(); i++) { str = tenseList->item(i)->text(); str = str.mid(str.indexOf(TENSE_TAG) + QStringLiteral(TENSE_TAG).length()); tenseList->item(i)->setText(QStringLiteral("%1").arg(i + 1, 2).append(TENSE_TAG).append(str)); } } void LanguagePropertiesPage::slotDeleteTense() { int act = m_currentTense; if (tenseList->count() > 0 && (int) tenseList->count() > act) { QString t = tenseList->item(act)->text(); foreach(KEduVocExpression * exp, m_doc->lesson()->entries(KEduVocLesson::Recursive)) { for (int lang = 0; lang < m_doc->identifierCount(); lang++) { if (exp->translation(lang)->conjugationTenses().contains(t)) { KMessageBox::information(this, i18n("The selected user defined tense could not be deleted\nbecause it is in use."), i18n("Deleting Tense Description")); return; } } } delete tenseList->takeItem(act); tenseIndex.erase(tenseIndex.begin() + act); if ((int) tenseList->count() <= act) act = tenseList->count() - 1; else updateListBox(act); // update items after current if (act >= 0) tenseList->setCurrentRow(act); } modifyButton->setEnabled(tenseList->count() > 0); deleteButton->setEnabled(tenseList->count() > 0); } diff --git a/src/statistics/statisticsmainwindow.cpp b/src/statistics/statisticsmainwindow.cpp index d7cf3c29..016b1297 100644 --- a/src/statistics/statisticsmainwindow.cpp +++ b/src/statistics/statisticsmainwindow.cpp @@ -1,338 +1,335 @@ /*************************************************************************** Copyright 2008-2010 Frederik Gladhorn Copyright 2008 Daniel Laidig *************************************************************************** *************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "statisticsmainwindow.h" #include -#include #include #include #include #include #include "practice/configure/configurepracticedialog.h" #include "lessonstatisticsview.h" #include "statisticsmodel.h" #include "parleymainwindow.h" #include "parleyactions.h" #include "prefs.h" #include "ui_statisticsmainwindow.h" #include "conjugationoptions.h" StatisticsMainWindow::StatisticsMainWindow(KEduVocDocument *doc, ParleyMainWindow *parent) : KXmlGuiWindow(parent) , m_mainWindow(parent) , m_doc(doc) , m_ui(new Ui::StatisticsMainWindow) , m_conjugationOptions(0) { // KXmlGui setXMLFile(QStringLiteral("statisticsui.rc")); setObjectName(QStringLiteral("Statistics")); QWidget *mainWidget = new QWidget(this); setCentralWidget(mainWidget); m_ui->setupUi(mainWidget); //m_ui->caption->setText(i18nc("caption for an overview of the confidence levels for a document" // "Statistics for \"%1\"", m_doc->title())); m_statisticsModel = new StatisticsModel(this); setDocument(doc); initActions(); initPracticeModeSelection(); initLanguages(); initPracticeMode(); KConfigGroup cfg(KSharedConfig::openConfig(QStringLiteral("parleyrc")), objectName()); applyMainWindowSettings(cfg); } StatisticsMainWindow::~StatisticsMainWindow() { if (m_conjugationOptions) { m_conjugationOptions->updateSettings(); } KConfigGroup cfg(KSharedConfig::openConfig(QStringLiteral("parleyrc")), objectName()); saveMainWindowSettings(cfg); delete m_ui; } void StatisticsMainWindow::syncConfig() { //qDebug() << "save tenses"; if (m_conjugationOptions) { m_conjugationOptions->updateSettings(); } } void StatisticsMainWindow::setDocument(KEduVocDocument* doc) { m_doc = doc; m_statisticsModel->setDocument(doc); m_ui->lessonStatistics->setModel(m_statisticsModel); m_ui->lessonStatistics->restoreExpandedStatus(); m_ui->lessonStatistics->resizeColumnToContents(0); } void StatisticsMainWindow::initActions() { ParleyActions::create(ParleyActions::EnterEditMode, m_mainWindow, SLOT(showEditor()), actionCollection()); ParleyActions::create(ParleyActions::StartPractice, m_mainWindow, SLOT(startPractice()), actionCollection()); ParleyActions::create(ParleyActions::ConfigurePractice, m_mainWindow, SLOT(configurePractice()), actionCollection()); } void StatisticsMainWindow::initPracticeModeSelection() { switch (Prefs::practiceMode()) { case Prefs::EnumPracticeMode::FlashCardsPractice: m_ui->flashCard->setChecked(true); break; case Prefs::EnumPracticeMode::MixedLettersPractice: m_ui->mixedLetters->setChecked(true); break; case Prefs::EnumPracticeMode::MultipleChoicePractice: m_ui->multipleChoice->setChecked(true); break; case Prefs::EnumPracticeMode::WrittenPractice: m_ui->written->setChecked(true); break; case Prefs::EnumPracticeMode::ExampleSentencesPractice: m_ui->exampleSentence->setChecked(true); break; case Prefs::EnumPracticeMode::GenderPractice: m_ui->gender->setChecked(true); break; case Prefs::EnumPracticeMode::ComparisonPractice: m_ui->comparisonForms->setChecked(true); break; case Prefs::EnumPracticeMode::ConjugationPractice: m_ui->conjugations->setChecked(true); showConjugationOptions(); break; default: break; } - QSignalMapper* mapper = new QSignalMapper(this); - mapper->setMapping(m_ui->flashCard, Prefs::EnumPracticeMode::FlashCardsPractice); - mapper->setMapping(m_ui->mixedLetters, Prefs::EnumPracticeMode::MixedLettersPractice); - mapper->setMapping(m_ui->multipleChoice, Prefs::EnumPracticeMode::MultipleChoicePractice); - mapper->setMapping(m_ui->written, Prefs::EnumPracticeMode::WrittenPractice); - mapper->setMapping(m_ui->exampleSentence, Prefs::EnumPracticeMode::ExampleSentencesPractice); - mapper->setMapping(m_ui->gender, Prefs::EnumPracticeMode::GenderPractice); - mapper->setMapping(m_ui->comparisonForms, Prefs::EnumPracticeMode::ComparisonPractice); - mapper->setMapping(m_ui->conjugations, Prefs::EnumPracticeMode::ConjugationPractice); - connect(m_ui->flashCard, SIGNAL(clicked(bool)), mapper, SLOT(map())); - connect(m_ui->mixedLetters, SIGNAL(clicked(bool)), mapper, SLOT(map())); - connect(m_ui->multipleChoice, SIGNAL(clicked(bool)), mapper, SLOT(map())); - connect(m_ui->written, SIGNAL(clicked(bool)), mapper, SLOT(map())); - connect(m_ui->exampleSentence, SIGNAL(clicked(bool)), mapper, SLOT(map())); - connect(m_ui->gender, SIGNAL(clicked(bool)), mapper, SLOT(map())); - connect(m_ui->comparisonForms, SIGNAL(clicked(bool)), mapper, SLOT(map())); - connect(m_ui->conjugations, SIGNAL(clicked(bool)), mapper, SLOT(map())); - connect(mapper, SIGNAL(mapped(int)), this, SLOT(practiceModeSelected(int))); + connect(m_ui->flashCard, &QRadioButton::clicked, + this, [=] {practiceModeSelected(Prefs::EnumPracticeMode::FlashCardsPractice);}); + connect(m_ui->mixedLetters, &QRadioButton::clicked, + this, [=] {practiceModeSelected(Prefs::EnumPracticeMode::MixedLettersPractice);}); + connect(m_ui->multipleChoice, &QRadioButton::clicked, + this, [=] {practiceModeSelected(Prefs::EnumPracticeMode::MultipleChoicePractice);}); + connect(m_ui->written, &QRadioButton::clicked, + this, [=] {practiceModeSelected(Prefs::EnumPracticeMode::WrittenPractice);}); + connect(m_ui->exampleSentence, &QRadioButton::clicked, + this, [=] {practiceModeSelected(Prefs::EnumPracticeMode::ExampleSentencesPractice);}); + connect(m_ui->gender, &QRadioButton::clicked, + this, [=] {practiceModeSelected(Prefs::EnumPracticeMode::GenderPractice);}); + connect(m_ui->comparisonForms, &QRadioButton::clicked, + this, [=] {practiceModeSelected(Prefs::EnumPracticeMode::ComparisonPractice);}); + connect(m_ui->conjugations, &QRadioButton::clicked, + this, [=] {practiceModeSelected(Prefs::EnumPracticeMode::ConjugationPractice);}); } void StatisticsMainWindow::initLanguages() { //qDebug() << "init languages: " << Prefs::learningLanguage() << Prefs::knownLanguage(); const int totalNumLanguages = m_doc->identifierCount(); if ( Prefs::knownLanguage() < 0 || totalNumLanguages <= Prefs::knownLanguage() ) { Prefs::setKnownLanguage(0); } if ( Prefs::learningLanguage() < 0 || totalNumLanguages <= Prefs::learningLanguage() ) { Prefs::setLearningLanguage(0); } if (Prefs::knownLanguage() >= totalNumLanguages || Prefs::learningLanguage() >= totalNumLanguages || Prefs::learningLanguage() == Prefs::knownLanguage()) { Prefs::setKnownLanguage(0); Prefs::setLearningLanguage(1); //qDebug() << "Invalid language selection."; } // Insert data into the comboboxes. for (int i = 0; i < totalNumLanguages; ++i) { m_ui->learnedLanguage->insertItem(i, m_doc->identifier(i).name()); m_ui->knownLanguage->insertItem(i, m_doc->identifier(i).name()); } m_ui->learnedLanguage->setCurrentIndex(Prefs::learningLanguage()); m_ui->knownLanguage->setCurrentIndex(Prefs::knownLanguage()); connect(m_ui->learnedLanguage, SIGNAL(currentIndexChanged(int)), SLOT(languagesChanged())); connect(m_ui->knownLanguage, SIGNAL(currentIndexChanged(int)), SLOT(languagesChanged())); languagesChanged(); } void StatisticsMainWindow::languagesChanged() { int knownLanguage = m_ui->knownLanguage->currentIndex(); int learningLanguage = m_ui->learnedLanguage->currentIndex(); Prefs::setLearningLanguage(learningLanguage); Prefs::setKnownLanguage(knownLanguage); emit languagesChanged(knownLanguage, learningLanguage); updateVisibleColumns(); updateModelSettings(); } void StatisticsMainWindow::initPracticeMode() { m_ui->practiceDirection->insertItem(0, i18n("Known to Learning")); m_ui->practiceDirection->insertItem(1, i18n("Learning to Known")); m_ui->practiceDirection->insertItem(2, i18n("Mixed Directions")); //m_ui->practiceDirection->insertItem(3, i18n("Mixed Directions with Sound")); int practiceDirection(Prefs::rememberPracticeDirection() ? practiceDirectionForPracticeMode(Prefs::practiceMode()) : Prefs::practiceDirection()); if (practiceDirection < 0 || 3 < practiceDirection) Prefs::setPracticeDirection(Prefs::EnumPracticeDirection::MixedDirectionsWordsOnly); m_ui->practiceDirection->setCurrentIndex(practiceDirection); connect(m_ui->practiceDirection, static_cast(&QComboBox::currentIndexChanged), this, &StatisticsMainWindow::practiceDirectionChanged); m_ui->rememberPracticeDirection->setChecked(Prefs::rememberPracticeDirection()); connect(m_ui->rememberPracticeDirection, &QCheckBox::toggled, this, &StatisticsMainWindow::rememberPracticeDirectionChanged); } void StatisticsMainWindow::practiceModeSelected(int mode) { int previousPracticeMode = Prefs::practiceMode(); Prefs::setPracticeMode(static_cast(mode)); //qDebug() << "mode: " << mode << Prefs::practiceMode(); showConjugationOptions(mode == Prefs::EnumPracticeMode::ConjugationPractice); if (Prefs::rememberPracticeDirection()) { setPracticeDirectionForPracticeMode(Prefs::practiceDirection(), previousPracticeMode); m_ui->practiceDirection->setCurrentIndex(practiceDirectionForPracticeMode(mode)); } updateModelSettings(); } void StatisticsMainWindow::practiceDirectionChanged(int mode) { //qDebug() << "new practice direction:" << mode; Prefs::setPracticeDirection(static_cast(mode)); if (Prefs::rememberPracticeDirection()) { setPracticeDirectionForPracticeMode(mode, Prefs::practiceMode()); } updateVisibleColumns(); updateModelSettings(); } void StatisticsMainWindow::rememberPracticeDirectionChanged(bool checked) { // qDebug() << "remember practice direction changed to: " << checked; Prefs::setRememberPracticeDirection(checked); if (checked) { setPracticeDirectionForPracticeMode(Prefs::practiceDirection(), Prefs::practiceMode()); } } void StatisticsMainWindow::updateVisibleColumns() { bool isHidden; for (int i = ContainerModel::FirstDataColumn; i < m_ui->lessonStatistics->header()->count(); i++) { int iLang = i - ContainerModel::FirstDataColumn; switch (Prefs::practiceDirection()) { case Prefs::EnumPracticeDirection::LearningToKnown: isHidden = iLang != Prefs::knownLanguage(); break; case Prefs::EnumPracticeDirection::MixedDirectionsWordsOnly: case Prefs::EnumPracticeDirection::MixedDirectionsWithSound: isHidden = iLang != Prefs::knownLanguage() && iLang != Prefs::learningLanguage(); break; case Prefs::EnumPracticeDirection::KnownToLearning: // Use KnownToLearning as default. default: isHidden = iLang != Prefs::learningLanguage(); break; } m_ui->lessonStatistics->setColumnHidden(i, isHidden); m_ui->lessonStatistics->adjustColumnWidths(); } } void StatisticsMainWindow::showConjugationOptions(bool visible) { if (!m_conjugationOptions && !visible) { return; } if (!m_conjugationOptions) { m_conjugationOptions = new ConjugationOptions(m_doc, m_ui->modeSpecificOptions); QHBoxLayout* layout = new QHBoxLayout(m_ui->modeSpecificOptions); layout->setContentsMargins(0, 0, 0, 0); layout->addWidget(m_conjugationOptions); connect(this, QOverload::of(&StatisticsMainWindow::languagesChanged), m_conjugationOptions, &ConjugationOptions::setLanguages); m_conjugationOptions->setLanguages(Prefs::knownLanguage(), Prefs::learningLanguage()); connect(m_conjugationOptions, &ConjugationOptions::checkBoxChanged, this, &StatisticsMainWindow::updateModelSettings); } m_conjugationOptions->setVisible(visible); } void StatisticsMainWindow::configurePractice() { ConfigurePracticeDialog dialog(m_doc, this, QStringLiteral("practice settings"), Prefs::self()); dialog.exec(); } int StatisticsMainWindow::practiceDirectionForPracticeMode(int mode) const { int direction = Prefs::practiceDirectionsByPracticeMode().value(mode, Prefs::practiceDirection()); if ((direction < 0) || (direction > Prefs::EnumPracticeDirection::MixedDirectionsWordsOnly)) { direction = Prefs::EnumPracticeDirection::MixedDirectionsWordsOnly; } return direction; } void StatisticsMainWindow::setPracticeDirectionForPracticeMode(int direction, int mode) { QList directions = Prefs::practiceDirectionsByPracticeMode(); // Expand list if fields not used before for (int i = directions.size() - 1; i < mode; ++i) { directions.append(Prefs::practiceDirection()); } directions[mode] = direction; Prefs::setPracticeDirectionsByPracticeMode(directions); } void StatisticsMainWindow::updateModelSettings() { m_ui->lessonStatistics->saveExpandedStatus(); m_statisticsModel->updateDocumentSettings(); m_ui->lessonStatistics->restoreExpandedStatus(); }