File indexing completed on 2024-04-28 15:30:55
0001 /* 0002 SPDX-FileCopyrightText: 2001-2010 Christoph Cullmann <cullmann@kde.org> 0003 SPDX-FileCopyrightText: 2009 Erlend Hamberg <ehamberg@gmail.com> 0004 0005 For the addScrollablePage original 0006 SPDX-FileCopyrightText: 2003 Benjamin C Meyer <ben+kdelibs at meyerhome dot net> 0007 SPDX-FileCopyrightText: 2003 Waldo Bastian <bastian@kde.org> 0008 SPDX-FileCopyrightText: 2004 Michael Brade <brade@kde.org> 0009 SPDX-FileCopyrightText: 2021 Ahmad Samir <a.samirh78@gmail.com> 0010 0011 SPDX-License-Identifier: LGPL-2.0-or-later 0012 */ 0013 0014 #include "kateglobal.h" 0015 #include "config.h" 0016 0017 #include <ktexteditor_version.h> 0018 0019 #include "katebuffer.h" 0020 #include "katecmd.h" 0021 #include "katecmds.h" 0022 #include "kateconfig.h" 0023 #include "katedialogs.h" 0024 #include "katedocument.h" 0025 #include "katehighlightingcmds.h" 0026 #include "katekeywordcompletion.h" 0027 #include "katemodemanager.h" 0028 #include "katescriptmanager.h" 0029 #include "katesedcmd.h" 0030 #include "katesyntaxmanager.h" 0031 #include "katethemeconfig.h" 0032 #include "katevariableexpansionmanager.h" 0033 #include "kateview.h" 0034 #include "katewordcompletion.h" 0035 #include "spellcheck/spellcheck.h" 0036 0037 #include "katenormalinputmodefactory.h" 0038 #include "kateviinputmodefactory.h" 0039 0040 #include <KConfigGroup> 0041 #include <KDirWatch> 0042 #include <KLocalizedString> 0043 #include <KPageDialog> 0044 0045 #include <QApplication> 0046 #include <QBoxLayout> 0047 #include <QClipboard> 0048 #include <QFrame> 0049 #include <QPushButton> 0050 #include <QScreen> 0051 #include <QScrollArea> 0052 #include <QScrollBar> 0053 #include <QStringListModel> 0054 #include <QTimer> 0055 0056 // BEGIN unit test mode 0057 static bool kateUnitTestMode = false; 0058 0059 void KTextEditor::EditorPrivate::enableUnitTestMode() 0060 { 0061 kateUnitTestMode = true; 0062 } 0063 0064 bool KTextEditor::EditorPrivate::unitTestMode() 0065 { 0066 return kateUnitTestMode; 0067 } 0068 // END unit test mode 0069 0070 KTextEditor::EditorPrivate::EditorPrivate(QPointer<KTextEditor::EditorPrivate> &staticInstance) 0071 : KTextEditor::Editor(this) 0072 , m_aboutData(QStringLiteral("katepart"), 0073 i18n("Kate Part"), 0074 QStringLiteral(KTEXTEDITOR_VERSION_STRING), 0075 i18n("Embeddable editor component"), 0076 KAboutLicense::LGPL_V2, 0077 i18n("(c) 2000-2022 The Kate Authors"), 0078 QString(), 0079 QStringLiteral("https://kate-editor.org")) 0080 , m_dummyApplication(nullptr) 0081 , m_application(&m_dummyApplication) 0082 , m_dummyMainWindow(nullptr) 0083 , m_searchHistoryModel(nullptr) 0084 , m_replaceHistoryModel(nullptr) 0085 { 0086 // remember this 0087 staticInstance = this; 0088 0089 // register some datatypes 0090 qRegisterMetaType<KTextEditor::Cursor>("KTextEditor::Cursor"); 0091 qRegisterMetaType<KTextEditor::Document *>("KTextEditor::Document*"); 0092 qRegisterMetaType<KTextEditor::View *>("KTextEditor::View*"); 0093 0094 // 0095 // fill about data 0096 // 0097 m_aboutData.addAuthor(i18n("Christoph Cullmann"), i18n("Maintainer"), QStringLiteral("cullmann@kde.org"), QStringLiteral("https://cullmann.io")); 0098 m_aboutData.addAuthor(i18n("Dominik Haumann"), i18n("Core Developer"), QStringLiteral("dhaumann@kde.org")); 0099 m_aboutData.addAuthor(i18n("Milian Wolff"), i18n("Core Developer"), QStringLiteral("mail@milianw.de"), QStringLiteral("https://milianw.de/")); 0100 m_aboutData.addAuthor(i18n("Joseph Wenninger"), 0101 i18n("Core Developer"), 0102 QStringLiteral("jowenn@kde.org"), 0103 QStringLiteral("http://stud3.tuwien.ac.at/~e9925371")); 0104 m_aboutData.addAuthor(i18n("Erlend Hamberg"), i18n("Vi Input Mode"), QStringLiteral("ehamberg@gmail.com"), QStringLiteral("https://hamberg.no/erlend")); 0105 m_aboutData.addAuthor(i18n("Bernhard Beschow"), 0106 i18n("Developer"), 0107 QStringLiteral("bbeschow@cs.tu-berlin.de"), 0108 QStringLiteral("https://user.cs.tu-berlin.de/~bbeschow")); 0109 m_aboutData.addAuthor(i18n("Anders Lund"), i18n("Core Developer"), QStringLiteral("anders@alweb.dk"), QStringLiteral("https://alweb.dk")); 0110 m_aboutData.addAuthor(i18n("Michel Ludwig"), i18n("On-the-fly spell checking"), QStringLiteral("michel.ludwig@kdemail.net")); 0111 m_aboutData.addAuthor(i18n("Pascal Létourneau"), i18n("Large scale bug fixing"), QStringLiteral("pascal.letourneau@gmail.com")); 0112 m_aboutData.addAuthor(i18n("Hamish Rodda"), i18n("Core Developer"), QStringLiteral("rodda@kde.org")); 0113 m_aboutData.addAuthor(i18n("Waldo Bastian"), i18n("The cool buffersystem"), QStringLiteral("bastian@kde.org")); 0114 m_aboutData.addAuthor(i18n("Charles Samuels"), i18n("The Editing Commands"), QStringLiteral("charles@kde.org")); 0115 m_aboutData.addAuthor(i18n("Matt Newell"), i18n("Testing, ..."), QStringLiteral("newellm@proaxis.com")); 0116 m_aboutData.addAuthor(i18n("Michael Bartl"), i18n("Former Core Developer"), QStringLiteral("michael.bartl1@chello.at")); 0117 m_aboutData.addAuthor(i18n("Michael McCallum"), i18n("Core Developer"), QStringLiteral("gholam@xtra.co.nz")); 0118 m_aboutData.addAuthor(i18n("Michael Koch"), i18n("KWrite port to KParts"), QStringLiteral("koch@kde.org")); 0119 m_aboutData.addAuthor(i18n("Christian Gebauer"), QString(), QStringLiteral("gebauer@kde.org")); 0120 m_aboutData.addAuthor(i18n("Simon Hausmann"), QString(), QStringLiteral("hausmann@kde.org")); 0121 m_aboutData.addAuthor(i18n("Glen Parker"), i18n("KWrite Undo History, Kspell integration"), QStringLiteral("glenebob@nwlink.com")); 0122 m_aboutData.addAuthor(i18n("Scott Manson"), i18n("KWrite XML Syntax highlighting support"), QStringLiteral("sdmanson@alltel.net")); 0123 m_aboutData.addAuthor(i18n("John Firebaugh"), i18n("Patches and more"), QStringLiteral("jfirebaugh@kde.org")); 0124 m_aboutData.addAuthor(i18n("Andreas Kling"), i18n("Developer"), QStringLiteral("kling@impul.se")); 0125 m_aboutData.addAuthor(i18n("Mirko Stocker"), i18n("Various bugfixes"), QStringLiteral("me@misto.ch"), QStringLiteral("https://misto.ch/")); 0126 m_aboutData.addAuthor(i18n("Matthew Woehlke"), i18n("Selection, KColorScheme integration"), QStringLiteral("mw_triad@users.sourceforge.net")); 0127 m_aboutData.addAuthor(i18n("Sebastian Pipping"), 0128 i18n("Search bar back- and front-end"), 0129 QStringLiteral("webmaster@hartwork.org"), 0130 QStringLiteral("https://hartwork.org/")); 0131 m_aboutData.addAuthor(i18n("Jochen Wilhelmy"), i18n("Original KWrite Author"), QStringLiteral("digisnap@cs.tu-berlin.de")); 0132 m_aboutData.addAuthor(i18n("Gerald Senarclens de Grancy"), 0133 i18n("QA and Scripting"), 0134 QStringLiteral("oss@senarclens.eu"), 0135 QStringLiteral("http://find-santa.eu/")); 0136 0137 m_aboutData.addCredit(i18n("Matteo Merli"), i18n("Highlighting for RPM Spec-Files, Perl, Diff and more"), QStringLiteral("merlim@libero.it")); 0138 m_aboutData.addCredit(i18n("Rocky Scaletta"), i18n("Highlighting for VHDL"), QStringLiteral("rocky@purdue.edu")); 0139 m_aboutData.addCredit(i18n("Yury Lebedev"), i18n("Highlighting for SQL"), QString()); 0140 m_aboutData.addCredit(i18n("Chris Ross"), i18n("Highlighting for Ferite"), QString()); 0141 m_aboutData.addCredit(i18n("Nick Roux"), i18n("Highlighting for ILERPG"), QString()); 0142 m_aboutData.addCredit(i18n("Carsten Niehaus"), i18n("Highlighting for LaTeX"), QString()); 0143 m_aboutData.addCredit(i18n("Per Wigren"), i18n("Highlighting for Makefiles, Python"), QString()); 0144 m_aboutData.addCredit(i18n("Jan Fritz"), i18n("Highlighting for Python"), QString()); 0145 m_aboutData.addCredit(i18n("Daniel Naber")); 0146 m_aboutData.addCredit(i18n("Roland Pabel"), i18n("Highlighting for Scheme"), QString()); 0147 m_aboutData.addCredit(i18n("Cristi Dumitrescu"), i18n("PHP Keyword/Datatype list"), QString()); 0148 m_aboutData.addCredit(i18n("Carsten Pfeiffer"), i18n("Very nice help"), QString()); 0149 m_aboutData.addCredit(i18n("Bruno Massa"), i18n("Highlighting for Lua"), QStringLiteral("brmassa@gmail.com")); 0150 0151 m_aboutData.addCredit(i18n("All people who have contributed and I have forgotten to mention")); 0152 0153 m_aboutData.setTranslator(i18nc("NAME OF TRANSLATORS", "Your names"), i18nc("EMAIL OF TRANSLATORS", "Your emails")); 0154 0155 // set proper Kate icon for our about dialog 0156 m_aboutData.setProgramLogo(QIcon(QStringLiteral(":/ktexteditor/kate.svg"))); 0157 0158 // 0159 // dir watch 0160 // 0161 m_dirWatch = new KDirWatch(); 0162 0163 // 0164 // command manager 0165 // 0166 m_cmdManager = new KateCmd(); 0167 0168 // 0169 // variable expansion manager 0170 // 0171 m_variableExpansionManager = new KateVariableExpansionManager(this); 0172 0173 // 0174 // hl manager 0175 // 0176 m_hlManager = new KateHlManager(); 0177 0178 // 0179 // mode man 0180 // 0181 m_modeManager = new KateModeManager(); 0182 0183 // 0184 // input mode factories 0185 // 0186 Q_ASSERT(m_inputModeFactories.size() == KTextEditor::View::ViInputMode + 1); 0187 m_inputModeFactories[KTextEditor::View::NormalInputMode].reset(new KateNormalInputModeFactory()); 0188 m_inputModeFactories[KTextEditor::View::ViInputMode].reset(new KateViInputModeFactory()); 0189 0190 // 0191 // spell check manager 0192 // 0193 m_spellCheckManager = new KateSpellCheckManager(); 0194 0195 // config objects 0196 m_globalConfig = new KateGlobalConfig(); 0197 m_documentConfig = new KateDocumentConfig(); 0198 m_viewConfig = new KateViewConfig(); 0199 m_rendererConfig = new KateRendererConfig(); 0200 0201 // create script manager (search scripts) 0202 m_scriptManager = KateScriptManager::self(); 0203 0204 // 0205 // init the cmds 0206 // 0207 m_cmds.push_back(KateCommands::CoreCommands::self()); 0208 m_cmds.push_back(KateCommands::Character::self()); 0209 m_cmds.push_back(KateCommands::Date::self()); 0210 m_cmds.push_back(KateCommands::SedReplace::self()); 0211 m_cmds.push_back(KateCommands::Highlighting::self()); 0212 0213 // global word completion model 0214 m_wordCompletionModel = new KateWordCompletionModel(this); 0215 0216 // global keyword completion model 0217 m_keywordCompletionModel = new KateKeywordCompletionModel(this); 0218 0219 // tap to QApplication object for color palette changes 0220 qApp->installEventFilter(this); 0221 } 0222 0223 KTextEditor::EditorPrivate::~EditorPrivate() 0224 { 0225 delete m_globalConfig; 0226 delete m_documentConfig; 0227 delete m_viewConfig; 0228 delete m_rendererConfig; 0229 0230 delete m_modeManager; 0231 0232 delete m_dirWatch; 0233 0234 // cu managers 0235 delete m_scriptManager; 0236 delete m_hlManager; 0237 0238 delete m_spellCheckManager; 0239 0240 // cu model 0241 delete m_wordCompletionModel; 0242 0243 // delete variable expansion manager 0244 delete m_variableExpansionManager; 0245 m_variableExpansionManager = nullptr; 0246 0247 // delete the commands before we delete the cmd manager 0248 qDeleteAll(m_cmds); 0249 delete m_cmdManager; 0250 } 0251 0252 KTextEditor::Document *KTextEditor::EditorPrivate::createDocument(QObject *parent) 0253 { 0254 KTextEditor::DocumentPrivate *doc = new KTextEditor::DocumentPrivate(false, false, nullptr, parent); 0255 0256 Q_EMIT documentCreated(this, doc); 0257 0258 return doc; 0259 } 0260 0261 // END KTextEditor::Editor config stuff 0262 0263 // config dialog with improved sizing and that allows scrolling 0264 class KTextEditorConfigDialog : public KPageDialog 0265 { 0266 public: 0267 QList<KTextEditor::ConfigPage *> editorPages; 0268 0269 KTextEditorConfigDialog(KTextEditor::EditorPrivate *editor, QWidget *parent) 0270 : KPageDialog(parent) 0271 { 0272 setWindowTitle(i18n("Configure")); 0273 setFaceType(KPageDialog::List); 0274 setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Apply | QDialogButtonBox::Help); 0275 0276 // create pages already in construct to have proper layout for sizeHint 0277 editorPages.reserve(editor->configPages()); 0278 for (int i = 0; i < editor->configPages(); ++i) { 0279 KTextEditor::ConfigPage *page = editor->configPage(i, this); 0280 KPageWidgetItem *item = addScrollablePage(page, page->name()); 0281 item->setHeader(page->fullName()); 0282 item->setIcon(page->icon()); 0283 0284 connect(button(QDialogButtonBox::Apply), &QPushButton::clicked, page, &KTextEditor::ConfigPage::apply); 0285 editorPages.append(page); 0286 } 0287 } 0288 0289 QSize sizeHint() const override 0290 { 0291 // start with a bit enlarged default size hint to minimize changes of useless scrollbars 0292 QSize size = KPageDialog::sizeHint() * 1.3; 0293 0294 // enlarge it to half of the main window size, if that is larger 0295 if (parentWidget() && parentWidget()->window()) { 0296 size = size.expandedTo(parentWidget()->window()->size() * 0.5); 0297 } 0298 0299 // return bounded size to available real screen space 0300 return size.boundedTo(screen()->availableSize() * 0.9); 0301 } 0302 0303 KPageWidgetItem *addScrollablePage(QWidget *page, const QString &itemName) 0304 { 0305 // inspired by KPageWidgetItem *KConfigDialogPrivate::addPageInternal(QWidget *page, const QString &itemName, const QString &pixmapName, const QString 0306 // &header) 0307 QWidget *frame = new QWidget; 0308 QVBoxLayout *boxLayout = new QVBoxLayout(frame); 0309 boxLayout->setContentsMargins(0, 0, 0, 0); 0310 boxLayout->setContentsMargins(0, 0, 0, 0); 0311 0312 QScrollArea *scroll = new QScrollArea; 0313 scroll->setFrameShape(QFrame::NoFrame); 0314 scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); 0315 scroll->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); 0316 scroll->setWidget(page); 0317 scroll->setWidgetResizable(true); 0318 scroll->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); 0319 0320 if (page->minimumSizeHint().height() > scroll->sizeHint().height() - 2) { 0321 if (page->sizeHint().width() < scroll->sizeHint().width() + 2) { 0322 // QScrollArea is planning only a vertical scroll bar, 0323 // try to avoid the horizontal one by reserving space for the vertical one. 0324 // Currently KPageViewPrivate::_k_modelChanged() queries the minimumSizeHint(). 0325 // We can only set the minimumSize(), so this approach relies on QStackedWidget size calculation. 0326 scroll->setMinimumWidth(scroll->sizeHint().width() + qBound(0, scroll->verticalScrollBar()->sizeHint().width(), 200) + 4); 0327 } 0328 } 0329 0330 boxLayout->addWidget(scroll); 0331 return addPage(frame, itemName); 0332 } 0333 }; 0334 0335 void KTextEditor::EditorPrivate::configDialog(QWidget *parent) 0336 { 0337 QPointer<KTextEditorConfigDialog> kd = new KTextEditorConfigDialog(this, parent); 0338 if (kd->exec() && kd) { 0339 KateGlobalConfig::global()->configStart(); 0340 KateDocumentConfig::global()->configStart(); 0341 KateViewConfig::global()->configStart(); 0342 KateRendererConfig::global()->configStart(); 0343 0344 for (int i = 0; i < kd->editorPages.count(); ++i) { 0345 kd->editorPages.at(i)->apply(); 0346 } 0347 0348 KateGlobalConfig::global()->configEnd(); 0349 KateDocumentConfig::global()->configEnd(); 0350 KateViewConfig::global()->configEnd(); 0351 KateRendererConfig::global()->configEnd(); 0352 } 0353 delete kd; 0354 } 0355 0356 int KTextEditor::EditorPrivate::configPages() const 0357 { 0358 return 4; 0359 } 0360 0361 KTextEditor::ConfigPage *KTextEditor::EditorPrivate::configPage(int number, QWidget *parent) 0362 { 0363 switch (number) { 0364 case 0: 0365 return new KateViewDefaultsConfig(parent); 0366 0367 case 1: 0368 return new KateThemeConfigPage(parent); 0369 0370 case 2: 0371 return new KateEditConfigTab(parent); 0372 0373 case 3: 0374 return new KateSaveConfigTab(parent); 0375 0376 default: 0377 break; 0378 } 0379 0380 return nullptr; 0381 } 0382 0383 /** 0384 * Cleanup the KTextEditor::EditorPrivate during QCoreApplication shutdown 0385 */ 0386 static void cleanupGlobal() 0387 { 0388 // delete if there 0389 delete KTextEditor::EditorPrivate::self(); 0390 } 0391 0392 KTextEditor::EditorPrivate *KTextEditor::EditorPrivate::self() 0393 { 0394 // remember the static instance in a QPointer 0395 static bool inited = false; 0396 static QPointer<KTextEditor::EditorPrivate> staticInstance; 0397 0398 // just return it, if already inited 0399 if (inited) { 0400 return staticInstance.data(); 0401 } 0402 0403 // start init process 0404 inited = true; 0405 0406 // now create the object and store it 0407 new KTextEditor::EditorPrivate(staticInstance); 0408 0409 // register cleanup 0410 // let use be deleted during QCoreApplication shutdown 0411 qAddPostRoutine(cleanupGlobal); 0412 0413 // return instance 0414 return staticInstance.data(); 0415 } 0416 0417 void KTextEditor::EditorPrivate::registerDocument(KTextEditor::DocumentPrivate *doc) 0418 { 0419 Q_ASSERT(!m_documents.contains(doc)); 0420 m_documents.insert(doc, doc); 0421 } 0422 0423 void KTextEditor::EditorPrivate::deregisterDocument(KTextEditor::DocumentPrivate *doc) 0424 { 0425 Q_ASSERT(m_documents.contains(doc)); 0426 m_documents.remove(doc); 0427 } 0428 0429 void KTextEditor::EditorPrivate::registerView(KTextEditor::ViewPrivate *view) 0430 { 0431 Q_ASSERT(!m_views.contains(view)); 0432 m_views.insert(view); 0433 } 0434 0435 void KTextEditor::EditorPrivate::deregisterView(KTextEditor::ViewPrivate *view) 0436 { 0437 Q_ASSERT(m_views.contains(view)); 0438 m_views.remove(view); 0439 } 0440 0441 KTextEditor::Command *KTextEditor::EditorPrivate::queryCommand(const QString &cmd) const 0442 { 0443 return m_cmdManager->queryCommand(cmd); 0444 } 0445 0446 QList<KTextEditor::Command *> KTextEditor::EditorPrivate::commands() const 0447 { 0448 return m_cmdManager->commands(); 0449 } 0450 0451 QStringList KTextEditor::EditorPrivate::commandList() const 0452 { 0453 return m_cmdManager->commandList(); 0454 } 0455 0456 KateVariableExpansionManager *KTextEditor::EditorPrivate::variableExpansionManager() 0457 { 0458 return m_variableExpansionManager; 0459 } 0460 0461 void KTextEditor::EditorPrivate::updateColorPalette() 0462 { 0463 // reload the global schema (triggers reload for every view as well) 0464 // might trigger selection of better matching theme for new palette 0465 m_rendererConfig->reloadSchema(); 0466 0467 // force full update of all view caches and colors 0468 m_rendererConfig->updateConfig(); 0469 } 0470 0471 void KTextEditor::EditorPrivate::copyToClipboard(const QString &text, const QString &fileName) 0472 { 0473 // empty => nop 0474 if (text.isEmpty()) { 0475 return; 0476 } 0477 0478 // move to clipboard 0479 QApplication::clipboard()->setText(text, QClipboard::Clipboard); 0480 0481 // LRU, kill potential duplicated, move new entry to top 0482 // cut after X entries 0483 auto entry = ClipboardEntry{text, fileName}; 0484 m_clipboardHistory.removeOne(entry); 0485 m_clipboardHistory.prepend(entry); 0486 if (m_clipboardHistory.size() > m_viewConfig->clipboardHistoryEntries()) { 0487 m_clipboardHistory.removeLast(); 0488 } 0489 0490 // notify about change 0491 Q_EMIT clipboardHistoryChanged(); 0492 } 0493 0494 bool KTextEditor::EditorPrivate::eventFilter(QObject *obj, QEvent *event) 0495 { 0496 if (obj == qApp && event->type() == QEvent::ApplicationPaletteChange) { 0497 // only update the color once for the event that belongs to the qApp 0498 updateColorPalette(); 0499 } 0500 0501 return false; // always continue processing 0502 } 0503 0504 QStringListModel *KTextEditor::EditorPrivate::searchHistoryModel() 0505 { 0506 if (!m_searchHistoryModel) { 0507 KConfigGroup cg(KSharedConfig::openConfig(), "KTextEditor::Search"); 0508 const QStringList history = cg.readEntry(QStringLiteral("Search History"), QStringList()); 0509 m_searchHistoryModel = new QStringListModel(history, this); 0510 } 0511 return m_searchHistoryModel; 0512 } 0513 0514 QStringListModel *KTextEditor::EditorPrivate::replaceHistoryModel() 0515 { 0516 if (!m_replaceHistoryModel) { 0517 KConfigGroup cg(KSharedConfig::openConfig(), "KTextEditor::Search"); 0518 const QStringList history = cg.readEntry(QStringLiteral("Replace History"), QStringList()); 0519 m_replaceHistoryModel = new QStringListModel(history, this); 0520 } 0521 return m_replaceHistoryModel; 0522 } 0523 0524 void KTextEditor::EditorPrivate::saveSearchReplaceHistoryModels() 0525 { 0526 KConfigGroup cg(KSharedConfig::openConfig(), "KTextEditor::Search"); 0527 if (m_searchHistoryModel) { 0528 cg.writeEntry(QStringLiteral("Search History"), m_searchHistoryModel->stringList()); 0529 } 0530 if (m_replaceHistoryModel) { 0531 cg.writeEntry(QStringLiteral("Replace History"), m_replaceHistoryModel->stringList()); 0532 } 0533 } 0534 0535 KSharedConfigPtr KTextEditor::EditorPrivate::config() 0536 { 0537 // use dummy config for unit tests! 0538 if (KTextEditor::EditorPrivate::unitTestMode()) { 0539 return KSharedConfig::openConfig(QStringLiteral("katepartrc-unittest"), KConfig::SimpleConfig, QStandardPaths::TempLocation); 0540 } 0541 0542 // else: use application configuration, but try to transfer global settings on first use 0543 auto applicationConfig = KSharedConfig::openConfig(); 0544 if (!KConfigGroup(applicationConfig, QStringLiteral("KTextEditor Editor")).exists()) { 0545 auto globalConfig = KSharedConfig::openConfig(QStringLiteral("katepartrc")); 0546 for (const auto &group : {QStringLiteral("Editor"), QStringLiteral("Document"), QStringLiteral("View"), QStringLiteral("Renderer")}) { 0547 KConfigGroup origin(globalConfig, group); 0548 KConfigGroup destination(applicationConfig, QStringLiteral("KTextEditor ") + group); 0549 origin.copyTo(&destination); 0550 } 0551 } 0552 return applicationConfig; 0553 } 0554 0555 void KTextEditor::EditorPrivate::triggerConfigChanged() 0556 { 0557 // trigger delayed emission, will collapse multiple events to one signal emission 0558 m_configWasChanged = true; 0559 QTimer::singleShot(0, this, &KTextEditor::EditorPrivate::emitConfigChanged); 0560 } 0561 0562 void KTextEditor::EditorPrivate::emitConfigChanged() 0563 { 0564 // emit only once, if still needed 0565 if (m_configWasChanged) { 0566 m_configWasChanged = false; 0567 Q_EMIT configChanged(this); 0568 } 0569 } 0570 0571 void KTextEditor::EditorPrivate::copyToMulticursorClipboard(const QStringList &texts) 0572 { 0573 if (texts.size() == 1) { 0574 qWarning() << "Unexpected size 1 of multicursorClipboard. It should either be empty or greater than 1"; 0575 m_multicursorClipboard = QStringList(); 0576 Q_ASSERT(false); 0577 return; 0578 } 0579 m_multicursorClipboard = texts; 0580 } 0581 0582 QStringList KTextEditor::EditorPrivate::multicursorClipboard() const 0583 { 0584 return m_multicursorClipboard; 0585 } 0586 0587 #include "moc_kateglobal.cpp"