Index: src/view/katestatusbar.h =================================================================== --- src/view/katestatusbar.h +++ src/view/katestatusbar.h @@ -84,6 +84,8 @@ void configChanged(); + void dictionaryChanged(QAction *action); + protected: bool eventFilter(QObject *obj, QEvent *event) override; void contextMenuEvent(QContextMenuEvent *event) override; @@ -97,6 +99,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; Index: src/view/katestatusbar.cpp =================================================================== --- src/view/katestatusbar.cpp +++ 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 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::dictionaryChanged); + /** + * allow to change indentation configuration + */ m_tabsIndent = new StatusBarButton(this); topLayout->addWidget(m_tabsIndent); @@ -178,6 +204,8 @@ 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::cursorPositionChanged); + connect(m_view->doc(), &KTextEditor::DocumentPrivate::dictionaryRangesPresent, this, &KateStatusBar::cursorPositionChanged); updateStatus(); toggleWordCount(KateViewConfig::global()->showWordCount()); @@ -248,8 +276,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,12 +288,52 @@ , QLocale().toString(position.column() + 1) ); } - if (m_wordCounter) { text.append(QStringLiteral(", ") + m_wordCount); } - m_cursorPosition->setText(text); + + // Update dictionary button + QString newDict; + // Check if at the current cursor position is a different dictionary to use + const QList > dictRanges = m_view->doc()->dictionaryRanges(); + for (auto rangeDictPair : dictRanges) { + if (rangeDictPair.first->contains(position)) { + newDict = rangeDictPair.second; + break; + } + } + // Check if the default dictionary is in use + if (newDict.isEmpty()) { + newDict = m_view->doc()->defaultDictionary(); // May return an empty string, it's for me a BUG + if (newDict.isEmpty()) { // This code should be part of KTextEditor::DocumentPrivate + 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; + m_dictionary->setText(newDict); + // 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() @@ -464,3 +532,16 @@ { toggleWordCount(m_view->config()->showWordCount()); } + +void KateStatusBar::dictionaryChanged(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); + } +}