File indexing completed on 2024-04-21 03:57:51
0001 /* 0002 SPDX-FileCopyrightText: 2013 Dominik Haumann <dhaumann@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "katestatusbar.h" 0008 0009 #include "kateabstractinputmode.h" 0010 #include "kateconfig.h" 0011 #include "katedocument.h" 0012 #include "kateglobal.h" 0013 #include "katemodemanager.h" 0014 #include "katemodemenulist.h" 0015 #include "katerenderer.h" 0016 #include "kateview.h" 0017 #include "wordcounter.h" 0018 0019 #include <KAcceleratorManager> 0020 #include <KActionCollection> 0021 #include <KIconUtils> 0022 #include <Sonnet/Speller> 0023 0024 #include <QActionGroup> 0025 #include <QHBoxLayout> 0026 #include <QInputDialog> 0027 #include <QStylePainter> 0028 0029 // BEGIN menu 0030 KateStatusBarOpenUpMenu::KateStatusBarOpenUpMenu(QWidget *parent) 0031 : QMenu(parent) 0032 { 0033 } 0034 0035 void KateStatusBarOpenUpMenu::setVisible(bool visibility) 0036 { 0037 if (visibility) { 0038 QRect geo = geometry(); 0039 QPoint pos = parentWidget()->mapToGlobal(QPoint(0, 0)); 0040 geo.moveTopLeft(QPoint(pos.x(), pos.y() - geo.height())); 0041 if (geo.top() < 0) { 0042 geo.moveTop(0); 0043 } 0044 setGeometry(geo); 0045 } 0046 0047 QMenu::setVisible(visibility); 0048 } 0049 // END menu 0050 0051 // BEGIN StatusBarButton 0052 StatusBarButton::StatusBarButton(KateStatusBar *parent, const QString &text /*= QString()*/) 0053 : QPushButton(text, parent) 0054 { 0055 setFlat(true); 0056 setFocusProxy(parent->m_view); 0057 setMinimumSize(QSize(1, minimumSizeHint().height())); 0058 } 0059 0060 void StatusBarButton::paintEvent(QPaintEvent *) 0061 { 0062 QStylePainter p(this); 0063 QStyleOptionButton opt; 0064 initStyleOption(&opt); 0065 opt.features &= (~QStyleOptionButton::HasMenu); 0066 p.drawControl(QStyle::CE_PushButton, opt); 0067 } 0068 0069 QSize StatusBarButton::sizeHint() const 0070 { 0071 return minimumSizeHint(); 0072 } 0073 0074 QSize StatusBarButton::minimumSizeHint() const 0075 { 0076 const auto fm = QFontMetrics(font()); 0077 const int h = fm.lineSpacing(); 0078 QSize size = QPushButton::sizeHint(); 0079 const int vMmargin = style()->pixelMetric(QStyle::PM_FocusFrameVMargin) * 2; 0080 size.setHeight(h + vMmargin); 0081 0082 const int w = fm.horizontalAdvance(text()); 0083 const int bm = style()->pixelMetric(QStyle::PM_ButtonMargin) * 2; 0084 const int hMargin = style()->pixelMetric(QStyle::PM_FocusFrameHMargin) * 2; 0085 size.setWidth(w + bm + hMargin); 0086 0087 return size; 0088 } 0089 0090 // END StatusBarButton 0091 0092 KateStatusBar::KateStatusBar(KTextEditor::ViewPrivate *view) 0093 : KateViewBarWidget(false) 0094 , m_view(view) 0095 , m_selectionMode(-1) 0096 , m_wordCounter(nullptr) 0097 { 0098 KAcceleratorManager::setNoAccel(this); 0099 setFocusProxy(m_view); 0100 0101 // just add our status bar to central widget, full sized 0102 QHBoxLayout *topLayout = new QHBoxLayout(centralWidget()); 0103 topLayout->setContentsMargins(0, 0, 0, 0); 0104 topLayout->setSpacing(0); 0105 0106 // ensure all elements of the status bar are right aligned 0107 // for Kate this is nice, as on the left side are the tool view buttons 0108 // for KWrite this makes it more consistent with Kate 0109 topLayout->addStretch(1); 0110 0111 // show Line XXX, Column XXX 0112 m_cursorPosition = new StatusBarButton(this); 0113 topLayout->addWidget(m_cursorPosition); 0114 m_cursorPosition->setWhatsThis(i18n("Current cursor position. Click to go to a specific line.")); 0115 connect(m_cursorPosition, &StatusBarButton::clicked, m_view, &KTextEditor::ViewPrivate::gotoLine); 0116 0117 // show the zoom level of the text 0118 m_zoomLevel = new StatusBarButton(this); 0119 topLayout->addWidget(m_zoomLevel); 0120 connect(m_zoomLevel, &StatusBarButton::clicked, [this] { 0121 m_view->renderer()->resetFontSizes(); 0122 }); 0123 0124 // show the current mode, like INSERT, OVERWRITE, VI + modifiers like [BLOCK] 0125 m_inputMode = new StatusBarButton(this); 0126 topLayout->addWidget(m_inputMode); 0127 m_inputMode->setWhatsThis(i18n("Insert mode and VI input mode indicator. Click to change the mode.")); 0128 connect(m_inputMode, &StatusBarButton::clicked, [this] { 0129 m_view->currentInputMode()->toggleInsert(); 0130 }); 0131 0132 // Add dictionary button which allows user to switch dictionary of the document 0133 m_dictionary = new StatusBarButton(this); 0134 topLayout->addWidget(m_dictionary, 0); 0135 m_dictionary->setWhatsThis(i18n("Change dictionary")); 0136 m_dictionaryMenu = new KateStatusBarOpenUpMenu(m_dictionary); 0137 m_dictionaryMenu->addAction(m_view->action(QStringLiteral("tools_change_dictionary"))); 0138 m_dictionaryMenu->addAction(m_view->action(QStringLiteral("tools_clear_dictionary_ranges"))); 0139 m_dictionaryMenu->addAction(m_view->action(QStringLiteral("tools_toggle_automatic_spell_checking"))); 0140 m_dictionaryMenu->addAction(m_view->action(QStringLiteral("tools_spelling_from_cursor"))); 0141 m_dictionaryMenu->addAction(m_view->action(QStringLiteral("tools_spelling"))); 0142 m_dictionaryMenu->addSeparator(); 0143 m_dictionaryGroup = new QActionGroup(m_dictionaryMenu); 0144 QMapIterator<QString, QString> i(Sonnet::Speller().preferredDictionaries()); 0145 while (i.hasNext()) { 0146 i.next(); 0147 QAction *action = m_dictionaryGroup->addAction(i.key()); 0148 action->setData(i.value()); 0149 action->setToolTip(i.key()); 0150 action->setCheckable(true); 0151 m_dictionaryMenu->addAction(action); 0152 } 0153 m_dictionary->setMenu(m_dictionaryMenu); 0154 connect(m_dictionaryGroup, &QActionGroup::triggered, this, &KateStatusBar::changeDictionary); 0155 0156 // allow to change indentation configuration 0157 m_tabsIndent = new StatusBarButton(this); 0158 topLayout->addWidget(m_tabsIndent); 0159 0160 m_indentSettingsMenu = new KateStatusBarOpenUpMenu(m_tabsIndent); 0161 m_indentSettingsMenu->addSection(i18n("Tab Width")); 0162 m_tabGroup = new QActionGroup(this); 0163 addNumberAction(m_tabGroup, m_indentSettingsMenu, -1); 0164 addNumberAction(m_tabGroup, m_indentSettingsMenu, 8); 0165 addNumberAction(m_tabGroup, m_indentSettingsMenu, 4); 0166 addNumberAction(m_tabGroup, m_indentSettingsMenu, 2); 0167 connect(m_tabGroup, &QActionGroup::triggered, this, &KateStatusBar::slotTabGroup); 0168 0169 m_indentSettingsMenu->addSection(i18n("Indentation Width")); 0170 m_indentGroup = new QActionGroup(this); 0171 addNumberAction(m_indentGroup, m_indentSettingsMenu, -1); 0172 addNumberAction(m_indentGroup, m_indentSettingsMenu, 8); 0173 addNumberAction(m_indentGroup, m_indentSettingsMenu, 4); 0174 addNumberAction(m_indentGroup, m_indentSettingsMenu, 2); 0175 connect(m_indentGroup, &QActionGroup::triggered, this, &KateStatusBar::slotIndentGroup); 0176 0177 m_indentSettingsMenu->addSection(i18n("Indentation Mode")); 0178 QActionGroup *radioGroup = new QActionGroup(m_indentSettingsMenu); 0179 m_mixedAction = m_indentSettingsMenu->addAction(i18n("Tabulators && Spaces")); 0180 m_mixedAction->setCheckable(true); 0181 m_mixedAction->setActionGroup(radioGroup); 0182 m_hardAction = m_indentSettingsMenu->addAction(i18n("Tabulators")); 0183 m_hardAction->setCheckable(true); 0184 m_hardAction->setActionGroup(radioGroup); 0185 m_softAction = m_indentSettingsMenu->addAction(i18n("Spaces")); 0186 m_softAction->setCheckable(true); 0187 m_softAction->setActionGroup(radioGroup); 0188 connect(radioGroup, &QActionGroup::triggered, this, &KateStatusBar::slotIndentTabMode); 0189 0190 m_tabsIndent->setMenu(m_indentSettingsMenu); 0191 0192 // add encoding button which allows user to switch encoding of document 0193 // this will reuse the encoding action menu of the view 0194 m_encoding = new StatusBarButton(this); 0195 topLayout->addWidget(m_encoding); 0196 m_encoding->setMenu(m_view->encodingAction()->menu()); 0197 m_encoding->setWhatsThis(i18n("Encoding")); 0198 0199 m_eol = new StatusBarButton(this); 0200 m_eol->setWhatsThis(i18n("End of line type")); 0201 m_eol->setToolTip(i18n("End of line type")); 0202 m_eol->setMenu(m_view->getEolMenu()); 0203 topLayout->addWidget(m_eol); 0204 0205 // load the mode menu, which contains a scrollable list + search bar. 0206 // This is an alternative menu to the mode action menu of the view. 0207 m_modeMenuList = new KateModeMenuList(i18n("Mode"), this); 0208 m_modeMenuList->setWhatsThis(i18n( 0209 "Here you can choose which mode should be used for the current document. This will influence the highlighting and folding being used, for example.")); 0210 m_modeMenuList->updateMenu(m_view->doc()); 0211 // add mode button which allows user to switch mode of document 0212 m_mode = new StatusBarButton(this); 0213 topLayout->addWidget(m_mode); 0214 m_modeMenuList->setButton(m_mode, KateModeMenuList::AlignHInverse, KateModeMenuList::AlignTop, KateModeMenuList::AutoUpdateTextButton(false)); 0215 m_mode->setMenu(m_modeMenuList); 0216 m_mode->setWhatsThis(i18n("Syntax highlighting")); 0217 0218 // signals for the statusbar 0219 connect(m_view, &KTextEditor::View::cursorPositionChanged, this, &KateStatusBar::cursorPositionChanged); 0220 connect(m_view, &KTextEditor::View::viewModeChanged, this, &KateStatusBar::viewModeChanged); 0221 connect(m_view, &KTextEditor::View::selectionChanged, this, &KateStatusBar::selectionChanged); 0222 connect(m_view->doc(), &KTextEditor::Document::configChanged, this, &KateStatusBar::documentConfigChanged); 0223 connect(m_view->document(), &KTextEditor::DocumentPrivate::modeChanged, this, &KateStatusBar::modeChanged); 0224 connect(m_view, &KTextEditor::View::configChanged, this, &KateStatusBar::configChanged); 0225 connect(m_view->doc(), &KTextEditor::DocumentPrivate::defaultDictionaryChanged, this, &KateStatusBar::updateDictionary); 0226 connect(m_view->doc(), &KTextEditor::DocumentPrivate::dictionaryRangesPresent, this, &KateStatusBar::updateDictionary); 0227 connect(m_view, &KTextEditor::ViewPrivate::caretChangedRange, this, &KateStatusBar::updateDictionary); 0228 0229 updateStatus(); 0230 toggleWordCount(KateViewConfig::global()->showWordCount()); 0231 } 0232 0233 bool KateStatusBar::eventFilter(QObject *obj, QEvent *event) 0234 { 0235 return KateViewBarWidget::eventFilter(obj, event); 0236 } 0237 0238 void KateStatusBar::contextMenuEvent(QContextMenuEvent *event) 0239 { 0240 // TODO Add option "Show Statusbar" and options to show/hide buttons of the status bar 0241 QMenu menu(this); 0242 0243 if (childAt(event->pos()) == m_inputMode) { 0244 if (QAction *inputModesAction = m_view->actionCollection()->action(QStringLiteral("view_input_modes"))) { 0245 if (QMenu *inputModesMenu = inputModesAction->menu()) { 0246 const auto actions = inputModesMenu->actions(); 0247 for (int i = 0; i < actions.count(); ++i) { 0248 menu.addAction(actions.at(i)); 0249 } 0250 menu.addSeparator(); 0251 } 0252 } 0253 } 0254 0255 QAction *showLines = menu.addAction(i18n("Show line count"), this, &KateStatusBar::toggleShowLines); 0256 showLines->setCheckable(true); 0257 showLines->setChecked(KateViewConfig::global()->showLineCount()); 0258 QAction *showWords = menu.addAction(i18n("Show word count"), this, &KateStatusBar::toggleShowWords); 0259 showWords->setCheckable(true); 0260 showWords->setChecked(KateViewConfig::global()->showWordCount()); 0261 auto a = menu.addAction(i18n("Line/Column compact mode"), this, [](bool checked) { 0262 KateViewConfig::global()->setValue(KateViewConfig::StatusbarLineColumnCompact, checked); 0263 }); 0264 a->setCheckable(true); 0265 a->setChecked(KateViewConfig::global()->value(KateViewConfig::StatusbarLineColumnCompact).toBool()); 0266 menu.exec(event->globalPos()); 0267 } 0268 0269 void KateStatusBar::toggleShowLines(bool checked) 0270 { 0271 KateViewConfig::global()->setValue(KateViewConfig::ShowLineCount, checked); 0272 } 0273 0274 void KateStatusBar::toggleShowWords(bool checked) 0275 { 0276 KateViewConfig::global()->setShowWordCount(checked); 0277 } 0278 0279 void KateStatusBar::updateStatus() 0280 { 0281 selectionChanged(); 0282 viewModeChanged(); 0283 cursorPositionChanged(); 0284 documentConfigChanged(); 0285 modeChanged(); 0286 updateDictionary(); 0287 updateEOL(); 0288 } 0289 0290 void KateStatusBar::selectionChanged() 0291 { 0292 const unsigned int newSelectionMode = m_view->blockSelection(); 0293 if (newSelectionMode == m_selectionMode) { 0294 return; 0295 } 0296 0297 // remember new mode and update info 0298 m_selectionMode = newSelectionMode; 0299 viewModeChanged(); 0300 } 0301 0302 void KateStatusBar::viewModeChanged() 0303 { 0304 // prepend BLOCK for block selection mode 0305 QString text = m_view->viewModeHuman(); 0306 if (m_view->blockSelection()) { 0307 text = i18n("[BLOCK] %1", text); 0308 } 0309 0310 m_inputMode->setText(text); 0311 } 0312 0313 void KateStatusBar::cursorPositionChanged() 0314 { 0315 KTextEditor::Cursor position(m_view->cursorPositionVirtual()); 0316 const int l = position.line() + 1; 0317 const int c = position.column() + 1; 0318 0319 // Update line/column label 0320 QString text; 0321 if (KateViewConfig::global()->value(KateViewConfig::StatusbarLineColumnCompact).toBool()) { 0322 if (KateViewConfig::global()->showLineCount()) { 0323 text = i18n("%1/%2:%3", QLocale().toString(l), QLocale().toString(m_view->doc()->lines()), QLocale().toString(c)); 0324 } else { 0325 text = i18n("%1:%2", QLocale().toString(l), QLocale().toString(c)); 0326 } 0327 } else { 0328 if (KateViewConfig::global()->showLineCount()) { 0329 text = i18n("Line %1 of %2, Column %3", QLocale().toString(l), QLocale().toString(m_view->doc()->lines()), QLocale().toString(c)); 0330 } else { 0331 text = i18n("Line %1, Column %2", QLocale().toString(l), QLocale().toString(c)); 0332 } 0333 } 0334 if (m_wordCounter) { 0335 text.append(QLatin1String(", ") + m_wordCount); 0336 } 0337 m_cursorPosition->setText(text); 0338 } 0339 0340 void KateStatusBar::updateDictionary() 0341 { 0342 const auto spellchecker = Sonnet::Speller(); 0343 const auto availableDictionaries = spellchecker.availableDictionaries(); 0344 // No dictionaries available? => hide 0345 if (availableDictionaries.isEmpty()) { 0346 m_dictionary->hide(); 0347 return; 0348 } 0349 0350 QString newDict; 0351 // Check if at the current cursor position is a special dictionary in use 0352 KTextEditor::Cursor position(m_view->cursorPositionVirtual()); 0353 const QList<QPair<KTextEditor::MovingRange *, QString>> dictRanges = m_view->doc()->dictionaryRanges(); 0354 for (const auto &rangeDictPair : dictRanges) { 0355 const KTextEditor::MovingRange *range = rangeDictPair.first; 0356 if (range->contains(position) || range->end() == position) { 0357 newDict = rangeDictPair.second; 0358 break; 0359 } 0360 } 0361 // Check if the default dictionary is in use 0362 if (newDict.isEmpty()) { 0363 newDict = m_view->doc()->defaultDictionary(); 0364 if (newDict.isEmpty()) { 0365 newDict = spellchecker.defaultLanguage(); 0366 } 0367 } 0368 // Update button and menu only on a changed dictionary 0369 if (!m_dictionaryGroup->checkedAction() || (m_dictionaryGroup->checkedAction()->data().toString() != newDict) || m_dictionary->text().isEmpty()) { 0370 bool found = false; 0371 // Remove "-w_accents -variant_0" and such from dict-code to keep it small and clean 0372 m_dictionary->setText(newDict.section(QLatin1Char('-'), 0, 0)); 0373 // For maximum user clearness, change the checked menu option 0374 m_dictionaryGroup->blockSignals(true); 0375 const auto acts = m_dictionaryGroup->actions(); 0376 for (auto a : acts) { 0377 if (a->data().toString() == newDict) { 0378 a->setChecked(true); 0379 found = true; 0380 break; 0381 } 0382 } 0383 if (!found) { 0384 // User has chose some other dictionary from combo box, we need to add that 0385 QString dictName = availableDictionaries.key(newDict); 0386 if (!dictName.isEmpty()) { 0387 QAction *action = m_dictionaryGroup->addAction(dictName); 0388 action->setData(newDict); 0389 action->setCheckable(true); 0390 action->setChecked(true); 0391 m_dictionaryMenu->addAction(action); 0392 } 0393 } 0394 m_dictionaryGroup->blockSignals(false); 0395 } 0396 } 0397 0398 void KateStatusBar::documentConfigChanged() 0399 { 0400 m_encoding->setText(m_view->document()->encoding()); 0401 KateDocumentConfig *config = ((KTextEditor::DocumentPrivate *)m_view->document())->config(); 0402 int tabWidth = config->tabWidth(); 0403 int indentationWidth = config->indentationWidth(); 0404 bool replaceTabsDyn = config->replaceTabsDyn(); 0405 0406 static const KLocalizedString spacesOnly = ki18n("Soft Tabs: %1"); 0407 static const KLocalizedString spacesOnlyShowTabs = ki18n("Soft Tabs: %1 (%2)"); 0408 static const KLocalizedString tabsOnly = ki18n("Tab Size: %1"); 0409 static const KLocalizedString tabSpacesMixed = ki18n("Indent/Tab: %1/%2"); 0410 0411 if (!replaceTabsDyn) { 0412 if (tabWidth == indentationWidth) { 0413 m_tabsIndent->setText(tabsOnly.subs(tabWidth).toString()); 0414 m_tabGroup->setEnabled(false); 0415 m_hardAction->setChecked(true); 0416 } else { 0417 m_tabsIndent->setText(tabSpacesMixed.subs(indentationWidth).subs(tabWidth).toString()); 0418 m_tabGroup->setEnabled(true); 0419 m_mixedAction->setChecked(true); 0420 } 0421 } else { 0422 if (tabWidth == indentationWidth) { 0423 m_tabsIndent->setText(spacesOnly.subs(indentationWidth).toString()); 0424 m_tabGroup->setEnabled(true); 0425 m_softAction->setChecked(true); 0426 } else { 0427 m_tabsIndent->setText(spacesOnlyShowTabs.subs(indentationWidth).subs(tabWidth).toString()); 0428 m_tabGroup->setEnabled(true); 0429 m_softAction->setChecked(true); 0430 } 0431 } 0432 0433 updateGroup(m_tabGroup, tabWidth); 0434 updateGroup(m_indentGroup, indentationWidth); 0435 updateEOL(); 0436 } 0437 0438 void KateStatusBar::modeChanged() 0439 { 0440 m_mode->setText(KTextEditor::EditorPrivate::self()->modeManager()->fileType(m_view->document()->mode()).nameTranslated()); 0441 } 0442 0443 void KateStatusBar::addNumberAction(QActionGroup *group, QMenu *menu, int data) 0444 { 0445 QAction *a; 0446 if (data != -1) { 0447 a = menu->addAction(QStringLiteral("%1").arg(data)); 0448 } else { 0449 a = menu->addAction(i18n("Other...")); 0450 } 0451 a->setData(data); 0452 a->setCheckable(true); 0453 a->setActionGroup(group); 0454 } 0455 0456 void KateStatusBar::updateGroup(QActionGroup *group, int w) 0457 { 0458 QAction *m1 = nullptr; 0459 bool found = false; 0460 // linear search should be fast enough here, no additional hash 0461 const auto acts = group->actions(); 0462 for (QAction *action : acts) { 0463 int val = action->data().toInt(); 0464 if (val == -1) { 0465 m1 = action; 0466 } 0467 if (val == w) { 0468 found = true; 0469 action->setChecked(true); 0470 } 0471 } 0472 0473 if (m1) { 0474 if (found) { 0475 m1->setText(i18n("Other...")); 0476 } else { 0477 m1->setText(i18np("Other (%1)", "Other (%1)", w)); 0478 m1->setChecked(true); 0479 } 0480 } 0481 } 0482 0483 void KateStatusBar::slotTabGroup(QAction *a) 0484 { 0485 int val = a->data().toInt(); 0486 bool ok; 0487 KateDocumentConfig *config = ((KTextEditor::DocumentPrivate *)m_view->document())->config(); 0488 if (val == -1) { 0489 val = QInputDialog::getInt(this, i18n("Tab Width"), i18n("Please specify the wanted tab width:"), config->tabWidth(), 1, 200, 1, &ok); 0490 if (!ok) { 0491 val = config->tabWidth(); 0492 } 0493 } 0494 config->setTabWidth(val); 0495 } 0496 0497 void KateStatusBar::slotIndentGroup(QAction *a) 0498 { 0499 int val = a->data().toInt(); 0500 bool ok; 0501 KateDocumentConfig *config = ((KTextEditor::DocumentPrivate *)m_view->document())->config(); 0502 if (val == -1) { 0503 val = QInputDialog::getInt(this, 0504 i18n("Indentation Width"), 0505 i18n("Please specify the wanted indentation width:"), 0506 config->indentationWidth(), 0507 1, 0508 200, 0509 1, 0510 &ok); 0511 if (!ok) { 0512 val = config->indentationWidth(); 0513 } 0514 } 0515 config->configStart(); 0516 config->setIndentationWidth(val); 0517 if (m_hardAction->isChecked()) { 0518 config->setTabWidth(val); 0519 } 0520 config->configEnd(); 0521 } 0522 0523 void KateStatusBar::slotIndentTabMode(QAction *a) 0524 { 0525 KateDocumentConfig *config = ((KTextEditor::DocumentPrivate *)m_view->document())->config(); 0526 if (a == m_softAction) { 0527 config->setReplaceTabsDyn(true); 0528 } else if (a == m_mixedAction) { 0529 if (config->replaceTabsDyn()) { 0530 config->setReplaceTabsDyn(false); 0531 } 0532 m_tabGroup->setEnabled(true); 0533 } else if (a == m_hardAction) { 0534 if (config->replaceTabsDyn()) { 0535 config->configStart(); 0536 config->setReplaceTabsDyn(false); 0537 config->setTabWidth(config->indentationWidth()); 0538 config->configEnd(); 0539 } else { 0540 config->setTabWidth(config->indentationWidth()); 0541 } 0542 m_tabGroup->setEnabled(false); 0543 } 0544 } 0545 0546 void KateStatusBar::toggleWordCount(bool on) 0547 { 0548 if ((m_wordCounter != nullptr) == on) { 0549 return; 0550 } 0551 0552 if (on) { 0553 m_wordCounter = new WordCounter(m_view); 0554 connect(m_wordCounter, &WordCounter::changed, this, &KateStatusBar::wordCountChanged); 0555 } else { 0556 delete m_wordCounter; 0557 m_wordCounter = nullptr; 0558 } 0559 0560 wordCountChanged(0, 0, 0, 0); 0561 } 0562 0563 void KateStatusBar::wordCountChanged(int wordsInDocument, int wordsInSelection, int charsInDocument, int charsInSelection) 0564 { 0565 if (m_wordCounter) { 0566 if (charsInSelection > 0) { 0567 m_wordCount = i18nc("%1 and %3 are the selected words/chars count, %2 and %4 are the total words/chars count.", 0568 "Words %1/%2, Chars %3/%4", 0569 wordsInSelection, 0570 wordsInDocument, 0571 charsInSelection, 0572 charsInDocument); 0573 } else { 0574 m_wordCount = i18nc("%1 and %2 are the total words/chars count.", "Words %1, Chars %2", wordsInDocument, charsInDocument); 0575 } 0576 } else { 0577 m_wordCount.clear(); 0578 } 0579 0580 cursorPositionChanged(); 0581 } 0582 0583 void KateStatusBar::configChanged() 0584 { 0585 toggleWordCount(m_view->config()->showWordCount()); 0586 const int zoom = m_view->rendererConfig()->baseFont().pointSizeF() / KateRendererConfig::global()->baseFont().pointSizeF() * 100; 0587 if (zoom != 100) { 0588 m_zoomLevel->setVisible(true); 0589 m_zoomLevel->setText(i18n("Zoom: %1%", zoom)); 0590 } else { 0591 m_zoomLevel->hide(); 0592 } 0593 0594 auto cfg = KateViewConfig::global(); 0595 auto updateButtonVisibility = [cfg](StatusBarButton *b, KateViewConfig::ConfigEntryTypes c) { 0596 bool v = cfg->value(c).toBool(); 0597 if (v != (!b->isHidden())) { 0598 b->setVisible(v); 0599 } 0600 }; 0601 updateButtonVisibility(m_inputMode, KateViewConfig::ShowStatusbarInputMode); 0602 updateButtonVisibility(m_mode, KateViewConfig::ShowStatusbarHighlightingMode); 0603 updateButtonVisibility(m_cursorPosition, KateViewConfig::ShowStatusbarLineColumn); 0604 updateButtonVisibility(m_tabsIndent, KateViewConfig::ShowStatusbarTabSettings); 0605 updateButtonVisibility(m_encoding, KateViewConfig::ShowStatusbarFileEncoding); 0606 updateButtonVisibility(m_eol, KateViewConfig::ShowStatusbarEOL); 0607 0608 bool v = cfg->value(KateViewConfig::ShowStatusbarDictionary).toBool(); 0609 if (v != (!m_dictionary->isHidden()) && !Sonnet::Speller().availableDictionaries().isEmpty()) { 0610 updateButtonVisibility(m_dictionary, KateViewConfig::ShowStatusbarDictionary); 0611 } 0612 } 0613 0614 void KateStatusBar::changeDictionary(QAction *action) 0615 { 0616 const QString dictionary = action->data().toString(); 0617 m_dictionary->setText(dictionary); 0618 // Code stolen from KateDictionaryBar::dictionaryChanged 0619 KTextEditor::Range selection = m_view->selectionRange(); 0620 if (selection.isValid() && !selection.isEmpty()) { 0621 m_view->doc()->setDictionary(dictionary, selection); 0622 } else { 0623 m_view->doc()->setDefaultDictionary(dictionary); 0624 } 0625 } 0626 0627 void KateStatusBar::updateEOL() 0628 { 0629 const int eol = m_view->getEol(); 0630 QString text; 0631 switch (eol) { 0632 case KateDocumentConfig::eolUnix: 0633 text = QStringLiteral("LF"); 0634 break; 0635 case KateDocumentConfig::eolDos: 0636 text = QStringLiteral("CRLF"); 0637 break; 0638 case KateDocumentConfig::eolMac: 0639 text = QStringLiteral("CR"); 0640 break; 0641 } 0642 if (text != m_eol->text()) { 0643 m_eol->setText(text); 0644 } 0645 } 0646 0647 KateModeMenuList *KateStatusBar::modeMenu() const 0648 { 0649 return m_modeMenuList; 0650 } 0651 0652 #include "moc_katestatusbar.cpp"