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