diff --git a/src/view/katestatusbar.h b/src/view/katestatusbar.h --- a/src/view/katestatusbar.h +++ b/src/view/katestatusbar.h @@ -70,6 +70,8 @@ void cursorPositionChanged(); + void updateDictionary(); + void selectionChanged(); void modifiedChanged(); @@ -84,6 +86,8 @@ void configChanged(); + void changeDictionary(QAction *action); + protected: bool eventFilter(QObject *obj, QEvent *event) override; void contextMenuEvent(QContextMenuEvent *event) override; @@ -97,6 +101,9 @@ StatusBarButton *m_mode = nullptr; StatusBarButton *m_encoding = nullptr; StatusBarButton *m_tabsIndent = nullptr; + StatusBarButton *m_dictionary = nullptr; + QActionGroup *m_dictionaryGroup = nullptr; + KateStatusBarOpenUpMenu *m_dictionaryMenu = nullptr; QMenu *m_indentSettingsMenu; unsigned int m_modifiedStatus; unsigned int m_selectionMode; diff --git a/src/view/katestatusbar.cpp b/src/view/katestatusbar.cpp --- a/src/view/katestatusbar.cpp +++ b/src/view/katestatusbar.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -113,9 +114,34 @@ connect(m_inputMode, &StatusBarButton::clicked, [=] { m_view->currentInputMode()->toggleInsert(); }); /** - * allow to change indentation configuration + * Add dictionary button which allows user to switch dictionary of the document */ + m_dictionary = new StatusBarButton(this); + topLayout->addWidget(m_dictionary, 0); + m_dictionary->setWhatsThis(i18n("Change dictionary")); + m_dictionaryMenu = new KateStatusBarOpenUpMenu(m_dictionary); + m_dictionaryMenu->addAction(m_view->action("tools_change_dictionary")); + m_dictionaryMenu->addAction(m_view->action("tools_clear_dictionary_ranges")); + m_dictionaryMenu->addAction(m_view->action("tools_toggle_automatic_spell_checking")); + m_dictionaryMenu->addAction(m_view->action("tools_spelling_from_cursor")); + m_dictionaryMenu->addAction(m_view->action("tools_spelling")); + m_dictionaryMenu->addSeparator(); + m_dictionaryGroup = new QActionGroup(m_dictionaryMenu); + QMapIterator i(Sonnet::Speller().preferredDictionaries()); + while (i.hasNext()) { + i.next(); + QAction *action = m_dictionaryGroup->addAction(i.key()); + action->setData(i.value()); + action->setToolTip(i.key()); + action->setCheckable(true); + m_dictionaryMenu->addAction(action); + } + m_dictionary->setMenu(m_dictionaryMenu); + connect(m_dictionaryGroup, &QActionGroup::triggered, this, &KateStatusBar::changeDictionary); + /** + * allow to change indentation configuration + */ m_tabsIndent = new StatusBarButton(this); topLayout->addWidget(m_tabsIndent); @@ -178,6 +204,9 @@ connect(m_view->doc(), &KTextEditor::DocumentPrivate::configChanged, this, &KateStatusBar::documentConfigChanged); connect(m_view->document(), &KTextEditor::DocumentPrivate::modeChanged, this, &KateStatusBar::modeChanged); connect(m_view, &KTextEditor::ViewPrivate::configChanged, this, &KateStatusBar::configChanged); + connect(m_view->doc(), &KTextEditor::DocumentPrivate::defaultDictionaryChanged, this, &KateStatusBar::updateDictionary); + connect(m_view->doc(), &KTextEditor::DocumentPrivate::dictionaryRangesPresent, this, &KateStatusBar::updateDictionary); + connect(m_view, &KTextEditor::ViewPrivate::caretChangedRange, this, &KateStatusBar::updateDictionary); updateStatus(); toggleWordCount(KateViewConfig::global()->showWordCount()); @@ -220,6 +249,7 @@ modifiedChanged(); documentConfigChanged(); modeChanged(); + updateDictionary(); } void KateStatusBar::selectionChanged() @@ -248,8 +278,8 @@ { KTextEditor::Cursor position(m_view->cursorPositionVirtual()); + // Update line/column label QString text; - if (KateViewConfig::global()->showLineCount()) { text = i18n("Line %1 of %2, Column %3", QLocale().toString(position.line() + 1) , QLocale().toString(m_view->doc()->lines()) @@ -260,14 +290,59 @@ , QLocale().toString(position.column() + 1) ); } - if (m_wordCounter) { text.append(QStringLiteral(", ") + m_wordCount); } - m_cursorPosition->setText(text); } +void KateStatusBar::updateDictionary() +{ + QString newDict; + // Check if at the current cursor position is a special dictionary in use + KTextEditor::Cursor position(m_view->cursorPositionVirtual()); + const QList> dictRanges = m_view->doc()->dictionaryRanges(); + for (auto rangeDictPair : dictRanges) { + const KTextEditor::MovingRange *range = rangeDictPair.first; + if (range->contains(position) || range->end() == position) { + newDict = rangeDictPair.second; + break; + } + } + // Check if the default dictionary is in use + if (newDict.isEmpty()) { + newDict = m_view->doc()->defaultDictionary(); + if (newDict.isEmpty()) { + newDict = Sonnet::Speller().defaultLanguage(); + } + } + // Update button and menu only on a changed dictionary + if (!m_dictionaryGroup->checkedAction() || (m_dictionaryGroup->checkedAction()->data().toString() != newDict) || m_dictionary->text().isEmpty()) { + bool found = false; + // Remove "-w_accents -variant_0" and such from dict-code to keep it small and clean + m_dictionary->setText(newDict.section(QLatin1Char('-'), 0, 0)); + // For maximum user clearness, change the checked menu option + m_dictionaryGroup->blockSignals(true); + for (auto a : m_dictionaryGroup->actions()) { + if (a->data().toString() == newDict) { + a->setChecked(true); + found = true; + break; + } + } + if (!found) { + // User has chose some other dictionary from combo box, we need to add that + QString dictName = Sonnet::Speller().availableDictionaries().key(newDict); + QAction *action = m_dictionaryGroup->addAction(dictName); + action->setData(newDict); + action->setCheckable(true); + action->setChecked(true); + m_dictionaryMenu->addAction(action); + } + m_dictionaryGroup->blockSignals(false); + } +} + void KateStatusBar::modifiedChanged() { const bool mod = m_view->doc()->isModified(); @@ -464,3 +539,16 @@ { toggleWordCount(m_view->config()->showWordCount()); } + +void KateStatusBar::changeDictionary(QAction *action) +{ + const QString dictionary = action->data().toString(); + m_dictionary->setText(dictionary); + // Code stolen from KateDictionaryBar::dictionaryChanged + KTextEditor::Range selection = m_view->selectionRange(); + if (selection.isValid() && !selection.isEmpty()) { + m_view->doc()->setDictionary(dictionary, selection); + } else { + m_view->doc()->setDefaultDictionary(dictionary); + } +} diff --git a/src/view/kateview.h b/src/view/kateview.h --- a/src/view/kateview.h +++ b/src/view/kateview.h @@ -886,6 +886,12 @@ */ void delayedUpdateOfView(); + /** + * Emitted whenever the caret enter or leave a range. + * ATM only used by KateStatusBar to update the dict button + */ + void caretChangedRange(KTextEditor::View *); + public: /** * set of ranges which had the mouse inside last time, used for rendering diff --git a/src/view/kateview.cpp b/src/view/kateview.cpp --- a/src/view/kateview.cpp +++ b/src/view/kateview.cpp @@ -3514,6 +3514,7 @@ range->feedback()->mouseEnteredRange(range, this); } else { range->feedback()->caretEnteredRange(range, this); + emit caretChangedRange(this); } } @@ -3537,6 +3538,7 @@ range->feedback()->mouseExitedRange(range, this); } else { range->feedback()->caretExitedRange(range, this); + emit caretChangedRange(this); } } }