File indexing completed on 2024-04-28 05:48:42
0001 /* This file is part of the KDE project 0002 SPDX-FileCopyrightText: 2001 Christoph Cullmann <cullmann@kde.org> 0003 SPDX-FileCopyrightText: 2002 Joseph Wenninger <jowenn@kde.org> 0004 SPDX-FileCopyrightText: 2002 Anders Lund <anders.lund@lund.tdcadsl.dk> 0005 SPDX-FileCopyrightText: 2007 Anders Lund <anders@alweb.dk> 0006 SPDX-FileCopyrightText: 2017 Ederag <edera@gmx.fr> 0007 0008 SPDX-License-Identifier: LGPL-2.0-only 0009 */ 0010 0011 #include "kateconsole.h" 0012 0013 #include <KLocalizedString> 0014 #include <ktexteditor/document.h> 0015 #include <ktexteditor/message.h> 0016 #include <ktexteditor/view.h> 0017 0018 #include <KActionCollection> 0019 #include <KShell> 0020 #include <QAction> 0021 #include <kde_terminal_interface.h> 0022 #include <kparts/part.h> 0023 0024 #include <KMessageBox> 0025 0026 #include <QApplication> 0027 #include <QCheckBox> 0028 #include <QFileInfo> 0029 #include <QGroupBox> 0030 #include <QIcon> 0031 #include <QLabel> 0032 #include <QLineEdit> 0033 #include <QPainter> 0034 #include <QPushButton> 0035 #include <QShowEvent> 0036 #include <QStyle> 0037 #include <QTabWidget> 0038 #include <QVBoxLayout> 0039 0040 #include <KAuthorized> 0041 #include <KColorScheme> 0042 #include <KConfigGroup> 0043 #include <KPluginFactory> 0044 #include <KSharedConfig> 0045 #include <KXMLGUIFactory> 0046 0047 K_PLUGIN_FACTORY_WITH_JSON(KateKonsolePluginFactory, "katekonsoleplugin.json", registerPlugin<KateKonsolePlugin>();) 0048 0049 static const QStringList s_escapeExceptions{QStringLiteral("vi"), QStringLiteral("vim"), QStringLiteral("nvim"), QStringLiteral("git")}; 0050 0051 KateKonsolePlugin::KateKonsolePlugin(QObject *parent, const QVariantList &) 0052 : KTextEditor::Plugin(parent) 0053 , m_previousEditorEnv(qgetenv("EDITOR")) 0054 { 0055 if (!KAuthorized::authorize(QStringLiteral("shell_access"))) { 0056 KMessageBox::error(nullptr, i18n("You do not have enough karma to access a shell or terminal emulation")); 0057 } 0058 } 0059 0060 void setEditorEnv(const QByteArray &value) 0061 { 0062 if (value.isNull()) { 0063 qunsetenv("EDITOR"); 0064 } else { 0065 qputenv("EDITOR", value.data()); 0066 } 0067 } 0068 0069 KateKonsolePlugin::~KateKonsolePlugin() 0070 { 0071 setEditorEnv(m_previousEditorEnv); 0072 } 0073 0074 QObject *KateKonsolePlugin::createView(KTextEditor::MainWindow *mainWindow) 0075 { 0076 KateKonsolePluginView *view = new KateKonsolePluginView(this, mainWindow); 0077 return view; 0078 } 0079 0080 KTextEditor::ConfigPage *KateKonsolePlugin::configPage(int number, QWidget *parent) 0081 { 0082 if (number != 0) { 0083 return nullptr; 0084 } 0085 return new KateKonsoleConfigPage(parent, this); 0086 } 0087 0088 void KateKonsolePlugin::readConfig() 0089 { 0090 for (KateKonsolePluginView *view : qAsConst(mViews)) { 0091 view->readConfig(); 0092 } 0093 } 0094 0095 KateKonsolePluginView::KateKonsolePluginView(KateKonsolePlugin *plugin, KTextEditor::MainWindow *mainWindow) 0096 : QObject(mainWindow) 0097 , m_plugin(plugin) 0098 { 0099 // init console 0100 QWidget *toolview = mainWindow->createToolView(plugin, 0101 QStringLiteral("kate_private_plugin_katekonsoleplugin"), 0102 KTextEditor::MainWindow::Bottom, 0103 QIcon::fromTheme(QStringLiteral("dialog-scripts")), 0104 i18n("Terminal")); 0105 m_console = new KateConsole(m_plugin, mainWindow, toolview); 0106 0107 // register this view 0108 m_plugin->mViews.append(this); 0109 } 0110 0111 KateKonsolePluginView::~KateKonsolePluginView() 0112 { 0113 // unregister this view 0114 m_plugin->mViews.removeAll(this); 0115 0116 // cleanup, kill toolview + console 0117 auto toolview = m_console->parent(); 0118 delete m_console; 0119 delete toolview; 0120 } 0121 0122 void KateKonsolePluginView::readConfig() 0123 { 0124 m_console->readConfig(); 0125 } 0126 0127 KateConsole::KateConsole(KateKonsolePlugin *plugin, KTextEditor::MainWindow *mw, QWidget *parent) 0128 : QWidget(parent) 0129 , m_part(nullptr) 0130 , m_mw(mw) 0131 , m_toolView(parent) 0132 , m_plugin(plugin) 0133 { 0134 KXMLGUIClient::setComponentName(QStringLiteral("katekonsole"), i18n("Terminal")); 0135 setXMLFile(QStringLiteral("ui.rc")); 0136 0137 // make sure we have a vertical layout 0138 new QVBoxLayout(this); 0139 layout()->setContentsMargins(0, 1, 0, 0); 0140 0141 QAction *a = actionCollection()->addAction(QStringLiteral("katekonsole_tools_pipe_to_terminal")); 0142 a->setIcon(QIcon::fromTheme(QStringLiteral("dialog-scripts"))); 0143 a->setText(i18nc("@action", "&Pipe to Terminal")); 0144 connect(a, &QAction::triggered, this, &KateConsole::slotPipeToConsole); 0145 0146 a = actionCollection()->addAction(QStringLiteral("katekonsole_tools_sync")); 0147 a->setText(i18nc("@action", "S&ynchronize Terminal with Current Document")); 0148 connect(a, &QAction::triggered, this, &KateConsole::slotManualSync); 0149 0150 a = actionCollection()->addAction(QStringLiteral("katekonsole_tools_run")); 0151 a->setText(i18nc("@action", "Run Current Document")); 0152 connect(a, &QAction::triggered, this, &KateConsole::slotRun); 0153 0154 a = actionCollection()->addAction(QStringLiteral("katekonsole_tools_toggle_visibility")); 0155 a->setIcon(QIcon::fromTheme(QStringLiteral("dialog-scripts"))); 0156 a->setText(i18nc("@action", "S&how Terminal Panel")); 0157 actionCollection()->setDefaultShortcut(a, QKeySequence(Qt::Key_F4)); 0158 connect(a, &QAction::triggered, this, &KateConsole::slotToggleVisibility); 0159 0160 a = actionCollection()->addAction(QStringLiteral("katekonsole_tools_toggle_focus")); 0161 a->setIcon(QIcon::fromTheme(QStringLiteral("swap-panels"))); 0162 a->setText(i18nc("@action", "&Focus Terminal Panel")); 0163 actionCollection()->setDefaultShortcut(a, QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_F4)); 0164 connect(a, &QAction::triggered, this, &KateConsole::slotToggleFocus); 0165 0166 connect(m_mw, &KTextEditor::MainWindow::unhandledShortcutOverride, this, &KateConsole::handleEsc); 0167 0168 m_mw->guiFactory()->addClient(this); 0169 0170 readConfig(); 0171 0172 connect(qApp, &QApplication::focusChanged, this, &KateConsole::focusChanged); 0173 } 0174 0175 KateConsole::~KateConsole() 0176 { 0177 // we unplug our actions below, avoid that we trigger their usage 0178 disconnect(qApp, &QApplication::focusChanged, this, &KateConsole::focusChanged); 0179 0180 m_mw->guiFactory()->removeClient(this); 0181 if (m_part) { 0182 disconnect(m_part, &KParts::ReadOnlyPart::destroyed, this, &KateConsole::slotDestroyed); 0183 } 0184 } 0185 0186 void KateConsole::loadConsoleIfNeeded() 0187 { 0188 if (m_part) { 0189 return; 0190 } 0191 0192 if (!window() || !parent()) { 0193 return; 0194 } 0195 if (!window() || !isVisibleTo(window())) { 0196 return; 0197 } 0198 0199 if (hasKonsole()) { 0200 /** 0201 * get konsole part factory 0202 */ 0203 const QString konsolePart = QStringLiteral("kf6/parts/konsolepart"); 0204 KPluginFactory *factory = KPluginFactory::loadFactory(konsolePart).plugin; 0205 if (!factory) { 0206 return; 0207 } 0208 0209 m_part = factory->create<KParts::ReadOnlyPart>(this); 0210 0211 if (!m_part) { 0212 return; 0213 } 0214 0215 if (auto konsoleTabWidget = qobject_cast<QTabWidget *>(m_part->widget())) { 0216 konsoleTabWidget->setTabBarAutoHide(true); 0217 konsoleTabWidget->installEventFilter(this); 0218 } 0219 layout()->addWidget(m_part->widget()); 0220 0221 // start the terminal 0222 qobject_cast<TerminalInterface *>(m_part)->showShellInDir(QString()); 0223 0224 // KGlobal::locale()->insertCatalog("konsole"); // FIXME KF5: insert catalog 0225 0226 setFocusProxy(m_part->widget()); 0227 0228 connect(m_part, &KParts::ReadOnlyPart::destroyed, this, &KateConsole::slotDestroyed); 0229 // clang-format off 0230 connect(m_part, SIGNAL(overrideShortcut(QKeyEvent*,bool&)), this, SLOT(overrideShortcut(QKeyEvent*,bool&))); 0231 // clang-format on 0232 } 0233 0234 if (KConfigGroup(KSharedConfig::openConfig(), QStringLiteral("Konsole")).readEntry("AutoSyncronize", true)) { 0235 slotSync(); 0236 } 0237 } 0238 0239 static bool isCtrlShiftT(QKeyEvent *ke) 0240 { 0241 return ke->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier) && ke->key() == Qt::Key_T; 0242 } 0243 0244 bool KateConsole::eventFilter(QObject *w, QEvent *e) 0245 { 0246 if (!m_part) { 0247 return QWidget::eventFilter(w, e); 0248 } 0249 0250 if (e->type() == QEvent::KeyPress || e->type() == QEvent::ShortcutOverride) { 0251 QKeyEvent *keyEvent = static_cast<QKeyEvent *>(e); 0252 if (isCtrlShiftT(keyEvent)) { 0253 e->accept(); 0254 QMetaObject::invokeMethod(m_part, "newTab"); 0255 return true; 0256 } 0257 } 0258 0259 return QWidget::eventFilter(w, e); 0260 } 0261 0262 void KateConsole::slotDestroyed() 0263 { 0264 m_part = nullptr; 0265 m_currentPath.clear(); 0266 setFocusProxy(nullptr); 0267 0268 // hide the dockwidget 0269 if (parent()) { 0270 m_mw->hideToolView(m_toolView); 0271 } 0272 } 0273 0274 void KateConsole::overrideShortcut(QKeyEvent *, bool &override) 0275 { 0276 /** 0277 * let konsole handle all shortcuts 0278 */ 0279 override = true; 0280 } 0281 0282 void KateConsole::showEvent(QShowEvent *) 0283 { 0284 if (m_part) { 0285 return; 0286 } 0287 0288 loadConsoleIfNeeded(); 0289 } 0290 0291 void KateConsole::paintEvent(QPaintEvent *e) 0292 { 0293 if (hasKonsole()) { 0294 QWidget::paintEvent(e); 0295 return; 0296 } 0297 QPainter p(this); 0298 p.setPen(QPen(KColorScheme().foreground(KColorScheme::NegativeText), 1)); 0299 p.setBrush(Qt::NoBrush); 0300 p.drawRect(rect().adjusted(1, 1, -1, -1)); 0301 auto font = p.font(); 0302 font.setPixelSize(20); 0303 p.setFont(font); 0304 const QString text = i18n("Konsole not installed. Please install konsole to be able to use the terminal."); 0305 p.drawText(rect(), Qt::AlignCenter | Qt::TextWordWrap, text); 0306 } 0307 0308 static constexpr QLatin1String eolChar() 0309 { 0310 // On windows, if the shell is powershell 0311 // '\r' needs to be sent to trigger enter 0312 #ifdef Q_OS_WIN 0313 return QLatin1String("\r\n"); 0314 #else 0315 return QLatin1String("\n"); 0316 #endif 0317 } 0318 0319 void KateConsole::cd(const QString &path) 0320 { 0321 if (m_currentPath == path) { 0322 return; 0323 } 0324 0325 if (!m_part) { 0326 return; 0327 } 0328 0329 m_currentPath = path; 0330 QString command = QLatin1String(" cd ") + KShell::quoteArg(m_currentPath) + eolChar(); 0331 0332 // special handling for some interpreters 0333 TerminalInterface *t = qobject_cast<TerminalInterface *>(m_part); 0334 if (t) { 0335 // ghci doesn't allow \space dir names, does allow spaces in dir names 0336 // irb can take spaces or \space but doesn't allow " 'path' " 0337 if (t->foregroundProcessName() == QLatin1String("irb")) { 0338 command = QLatin1String("Dir.chdir(\"") + path + QLatin1String("\") \n"); 0339 } else if (t->foregroundProcessName() == QLatin1String("ghc")) { 0340 command = QLatin1String(":cd ") + path + QLatin1Char('\n'); 0341 } else if (!t->foregroundProcessName().isEmpty()) { 0342 // If something is running, dont try to cd anywhere 0343 return; 0344 } 0345 } 0346 0347 #ifndef Q_OS_WIN // Doesnt work with PS or cmd.exe on windows 0348 // Send prior Ctrl-E, Ctrl-U to ensure the line is empty 0349 sendInput(QStringLiteral("\x05\x15")); 0350 #endif 0351 sendInput(command); 0352 } 0353 0354 void KateConsole::sendInput(const QString &text) 0355 { 0356 loadConsoleIfNeeded(); 0357 0358 if (!m_part) { 0359 return; 0360 } 0361 0362 if (TerminalInterface *t = qobject_cast<TerminalInterface *>(m_part)) { 0363 t->sendInput(text); 0364 } 0365 } 0366 0367 KPluginFactory *KateConsole::pluginFactory() 0368 { 0369 if (s_pluginFactory) { 0370 return s_pluginFactory; 0371 } 0372 const QString konsolePart = QStringLiteral("kf6/parts/konsolepart"); 0373 return s_pluginFactory = KPluginFactory::loadFactory(konsolePart).plugin; 0374 } 0375 0376 void KateConsole::slotPipeToConsole() 0377 { 0378 if (KMessageBox::warningContinueCancel( 0379 m_mw->window(), 0380 i18n("Do you really want to pipe the text to the console? This will execute any contained commands with your user rights."), 0381 i18n("Pipe to Terminal?"), 0382 KGuiItem(i18n("Pipe to Terminal")), 0383 KStandardGuiItem::cancel(), 0384 QStringLiteral("Pipe To Terminal Warning")) 0385 != KMessageBox::Continue) { 0386 return; 0387 } 0388 0389 KTextEditor::View *v = m_mw->activeView(); 0390 0391 if (!v) { 0392 return; 0393 } 0394 0395 if (v->selection()) { 0396 sendInput(v->selectionText()); 0397 } else { 0398 sendInput(v->document()->text()); 0399 } 0400 } 0401 0402 void KateConsole::slotSync() 0403 { 0404 if (m_mw->activeView()) { 0405 QUrl u = m_mw->activeView()->document()->url(); 0406 if (u.isValid() && u.isLocalFile()) { 0407 QFileInfo fi(u.toLocalFile()); 0408 cd(fi.absolutePath()); 0409 } else if (!u.isEmpty()) { 0410 sendInput(QStringLiteral("### ") + i18n("Sorry, cannot cd into '%1'", u.toLocalFile()) + QLatin1Char('\n')); 0411 } 0412 } 0413 } 0414 0415 void KateConsole::slotViewOrUrlChanged(KTextEditor::View *view) 0416 { 0417 disconnect(m_urlChangedConnection); 0418 if (view) { 0419 KTextEditor::Document *doc = view->document(); 0420 m_urlChangedConnection = connect(doc, &KParts::ReadOnlyPart::urlChanged, this, &KateConsole::slotSync); 0421 } 0422 0423 slotSync(); 0424 } 0425 0426 void KateConsole::slotManualSync() 0427 { 0428 m_currentPath.clear(); 0429 slotSync(); 0430 0431 if (!m_part || !m_part->widget()->isVisible()) { 0432 m_mw->showToolView(qobject_cast<QWidget *>(parent())); 0433 } 0434 } 0435 0436 void KateConsole::slotRun() 0437 { 0438 KTextEditor::View *view = m_mw->activeView(); 0439 if (!view) { 0440 return; 0441 } 0442 0443 KTextEditor::Document *document = view->document(); 0444 const QUrl url = document->url(); 0445 if (!url.isLocalFile()) { 0446 QPointer<KTextEditor::Message> message = new KTextEditor::Message(i18n("Not a local file: '%1'", url.toDisplayString()), KTextEditor::Message::Error); 0447 // auto hide is enabled and set to a sane default value of several seconds. 0448 message->setAutoHide(2000); 0449 message->setAutoHideMode(KTextEditor::Message::Immediate); 0450 document->postMessage(message); 0451 return; 0452 } 0453 // ensure that file is saved 0454 if (document->isModified()) { 0455 document->save(); 0456 } 0457 0458 KConfigGroup cg(KSharedConfig::openConfig(), QStringLiteral("Konsole")); 0459 // The string that should be output to terminal, upon acceptance 0460 QString output_str; 0461 // Set prefix first 0462 QString first_line = document->line(0); 0463 const QLatin1String shebang("#!"); 0464 if (first_line.startsWith(shebang)) { 0465 // If there's a shebang, respect it 0466 output_str += first_line.remove(0, shebang.size()).append(QLatin1Char(' ')); 0467 } else { 0468 output_str += cg.readEntry("RunPrefix", ""); 0469 } 0470 0471 // then filename 0472 QFileInfo fileInfo(url.toLocalFile()); 0473 const bool removeExt = cg.readEntry("RemoveExtension", true); 0474 // append filename without extension (i.e. keep only the basename) 0475 const QString path = fileInfo.absolutePath() + QLatin1Char('/') + (removeExt ? fileInfo.baseName() : fileInfo.fileName()); 0476 output_str += KShell::quoteArg(path); 0477 0478 const QString msg = i18n( 0479 "Do you really want to Run the document ?\n" 0480 "This will execute the following command,\n" 0481 "with your user rights, in the terminal:\n" 0482 "'%1'", 0483 output_str); 0484 const auto result = KMessageBox::warningContinueCancel(m_mw->window(), 0485 msg, 0486 i18n("Run in Terminal?"), 0487 KGuiItem(i18n("Run")), 0488 KStandardGuiItem::cancel(), 0489 QStringLiteral("Konsole: Run in Terminal Warning")); 0490 if (result != KMessageBox::Continue) { 0491 return; 0492 } 0493 // echo to terminal 0494 sendInput(output_str + eolChar()); 0495 } 0496 0497 void KateConsole::slotToggleVisibility() 0498 { 0499 QAction *action = actionCollection()->action(QStringLiteral("katekonsole_tools_toggle_visibility")); 0500 if (!m_part || !m_part->widget()->isVisible()) { 0501 m_mw->showToolView(qobject_cast<QWidget *>(parent())); 0502 action->setText(i18nc("@action", "&Hide Terminal Panel")); 0503 } else { 0504 m_mw->hideToolView(m_toolView); 0505 action->setText(i18nc("@action", "S&how Terminal Panel")); 0506 } 0507 } 0508 0509 void KateConsole::focusChanged(QWidget *, QWidget *now) 0510 { 0511 QAction *action = actionCollection()->action(QStringLiteral("katekonsole_tools_toggle_focus")); 0512 if (m_part && m_part->widget()->isAncestorOf(now)) { 0513 action->setText(i18n("Defocus Terminal Panel")); 0514 } else if (action->text() != i18n("Focus Terminal Panel")) { 0515 action->setText(i18n("Focus Terminal Panel")); 0516 } 0517 } 0518 0519 void KateConsole::slotToggleFocus() 0520 { 0521 if (!m_part) { 0522 m_mw->showToolView(qobject_cast<QWidget *>(parent())); 0523 return; // this shows and focuses the konsole 0524 } 0525 0526 if (m_part->widget()->hasFocus()) { 0527 if (m_mw->activeView()) { 0528 m_mw->activeView()->setFocus(); 0529 } 0530 } else { 0531 // show the view if it is hidden 0532 if (auto p = qobject_cast<QWidget *>(parent()); p->isHidden()) { 0533 m_mw->showToolView(p); 0534 } else { // should focus the widget too! 0535 m_part->widget()->setFocus(Qt::OtherFocusReason); 0536 } 0537 } 0538 } 0539 0540 void KateConsole::readConfig() 0541 { 0542 disconnect(m_mw, &KTextEditor::MainWindow::viewChanged, this, &KateConsole::slotViewOrUrlChanged); 0543 disconnect(m_urlChangedConnection); 0544 0545 if (KConfigGroup(KSharedConfig::openConfig(), QStringLiteral("Konsole")).readEntry("AutoSyncronize", true)) { 0546 connect(m_mw, &KTextEditor::MainWindow::viewChanged, this, &KateConsole::slotViewOrUrlChanged); 0547 } 0548 0549 if (KConfigGroup(KSharedConfig::openConfig(), QStringLiteral("Konsole")).readEntry("SetEditor", false)) { 0550 qputenv("EDITOR", "kate -b"); 0551 } else { 0552 setEditorEnv(m_plugin->previousEditorEnv()); 0553 } 0554 } 0555 0556 void KateConsole::handleEsc(QEvent *e) 0557 { 0558 if (!KConfigGroup(KSharedConfig::openConfig(), QStringLiteral("Konsole")).readEntry("KonsoleEscKeyBehaviour", true)) { 0559 return; 0560 } 0561 0562 QStringList exceptList = KConfigGroup(KSharedConfig::openConfig(), QStringLiteral("Konsole")).readEntry("KonsoleEscKeyExceptions", s_escapeExceptions); 0563 0564 if (!m_mw || !m_toolView || !e) { 0565 return; 0566 } 0567 0568 QKeyEvent *k = static_cast<QKeyEvent *>(e); 0569 if (k->key() == Qt::Key_Escape && k->modifiers() == Qt::NoModifier) { 0570 if (m_part) { 0571 const auto app = qobject_cast<TerminalInterface *>(m_part)->foregroundProcessName(); 0572 if (m_toolView && m_toolView->isVisible() && !exceptList.contains(app)) { 0573 m_mw->hideToolView(m_toolView); 0574 } 0575 } else if (m_toolView && m_toolView->isVisible()) { 0576 m_mw->hideToolView(m_toolView); 0577 } 0578 } 0579 } 0580 0581 KateKonsoleConfigPage::KateKonsoleConfigPage(QWidget *parent, KateKonsolePlugin *plugin) 0582 : KTextEditor::ConfigPage(parent) 0583 , mPlugin(plugin) 0584 { 0585 QVBoxLayout *lo = new QVBoxLayout(this); 0586 lo->setSpacing(QApplication::style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing)); 0587 0588 cbAutoSyncronize = new QCheckBox(i18n("&Automatically synchronize the terminal with the current document when possible"), this); 0589 lo->addWidget(cbAutoSyncronize); 0590 0591 QVBoxLayout *vboxRun = new QVBoxLayout; 0592 QGroupBox *groupRun = new QGroupBox(i18n("Run in terminal"), this); 0593 // Remove extension 0594 cbRemoveExtension = new QCheckBox(i18n("&Remove extension"), this); 0595 vboxRun->addWidget(cbRemoveExtension); 0596 // Prefix 0597 QFrame *framePrefix = new QFrame(this); 0598 QHBoxLayout *hboxPrefix = new QHBoxLayout(framePrefix); 0599 QLabel *label = new QLabel(i18n("Prefix:"), framePrefix); 0600 hboxPrefix->addWidget(label); 0601 lePrefix = new QLineEdit(framePrefix); 0602 hboxPrefix->addWidget(lePrefix); 0603 vboxRun->addWidget(framePrefix); 0604 // show warning next time 0605 QFrame *frameWarn = new QFrame(this); 0606 QHBoxLayout *hboxWarn = new QHBoxLayout(frameWarn); 0607 QPushButton *buttonWarn = new QPushButton(i18n("&Show warning next time"), frameWarn); 0608 buttonWarn->setWhatsThis( 0609 i18n("The next time '%1' is executed, " 0610 "make sure a warning window will pop up, " 0611 "displaying the command to be sent to terminal, " 0612 "for review.", 0613 i18n("Run in terminal"))); 0614 connect(buttonWarn, &QPushButton::pressed, this, &KateKonsoleConfigPage::slotEnableRunWarning); 0615 hboxWarn->addWidget(buttonWarn); 0616 vboxRun->addWidget(frameWarn); 0617 groupRun->setLayout(vboxRun); 0618 lo->addWidget(groupRun); 0619 0620 cbSetEditor = new QCheckBox(i18n("Set &EDITOR environment variable to 'kate -b'"), this); 0621 lo->addWidget(cbSetEditor); 0622 QLabel *tmp = new QLabel(this); 0623 tmp->setText(i18n("Important: The document has to be closed to make the console application continue")); 0624 lo->addWidget(tmp); 0625 0626 cbSetEscHideKonsole = new QCheckBox(i18n("Hide Konsole on pressing 'Esc'")); 0627 lo->addWidget(cbSetEscHideKonsole); 0628 QLabel *hideKonsoleLabel = 0629 new QLabel(i18n("This may cause issues with terminal apps that use Esc key, for e.g., vim. Add these apps in the input below (Comma separated list)"), 0630 this); 0631 hideKonsoleLabel->setWordWrap(true); 0632 lo->addWidget(hideKonsoleLabel); 0633 0634 leEscExceptions = new QLineEdit(this); 0635 lo->addWidget(leEscExceptions); 0636 0637 reset(); 0638 lo->addStretch(); 0639 0640 connect(cbAutoSyncronize, &QCheckBox::stateChanged, this, &KateKonsoleConfigPage::changed); 0641 connect(cbRemoveExtension, &QCheckBox::stateChanged, this, &KTextEditor::ConfigPage::changed); 0642 connect(lePrefix, &QLineEdit::textChanged, this, &KateKonsoleConfigPage::changed); 0643 connect(cbSetEditor, &QCheckBox::stateChanged, this, &KateKonsoleConfigPage::changed); 0644 connect(cbSetEscHideKonsole, &QCheckBox::stateChanged, this, &KateKonsoleConfigPage::changed); 0645 connect(leEscExceptions, &QLineEdit::textChanged, this, &KateKonsoleConfigPage::changed); 0646 } 0647 0648 void KateKonsoleConfigPage::slotEnableRunWarning() 0649 { 0650 KMessageBox::enableMessage(QStringLiteral("Konsole: Run in Terminal Warning")); 0651 } 0652 0653 QString KateKonsoleConfigPage::name() const 0654 { 0655 return i18n("Terminal"); 0656 } 0657 0658 QString KateKonsoleConfigPage::fullName() const 0659 { 0660 return i18n("Terminal Settings"); 0661 } 0662 0663 QIcon KateKonsoleConfigPage::icon() const 0664 { 0665 return QIcon::fromTheme(QStringLiteral("dialog-scripts")); 0666 } 0667 0668 void KateKonsoleConfigPage::apply() 0669 { 0670 KConfigGroup config(KSharedConfig::openConfig(), QStringLiteral("Konsole")); 0671 config.writeEntry("AutoSyncronize", cbAutoSyncronize->isChecked()); 0672 config.writeEntry("RemoveExtension", cbRemoveExtension->isChecked()); 0673 config.writeEntry("RunPrefix", lePrefix->text()); 0674 config.writeEntry("SetEditor", cbSetEditor->isChecked()); 0675 config.writeEntry("KonsoleEscKeyBehaviour", cbSetEscHideKonsole->isChecked()); 0676 config.writeEntry("KonsoleEscKeyExceptions", leEscExceptions->text().split(QLatin1Char(','))); 0677 config.sync(); 0678 mPlugin->readConfig(); 0679 } 0680 0681 void KateKonsoleConfigPage::reset() 0682 { 0683 KConfigGroup config(KSharedConfig::openConfig(), QStringLiteral("Konsole")); 0684 cbAutoSyncronize->setChecked(config.readEntry("AutoSyncronize", true)); 0685 cbRemoveExtension->setChecked(config.readEntry("RemoveExtension", false)); 0686 lePrefix->setText(config.readEntry("RunPrefix", "")); 0687 cbSetEditor->setChecked(config.readEntry("SetEditor", false)); 0688 cbSetEscHideKonsole->setChecked(config.readEntry("KonsoleEscKeyBehaviour", true)); 0689 leEscExceptions->setText(config.readEntry("KonsoleEscKeyExceptions", s_escapeExceptions).join(QLatin1Char(','))); 0690 } 0691 0692 #include "kateconsole.moc" 0693 #include "moc_kateconsole.cpp" 0694 0695 // kate: space-indent on; indent-width 4; replace-tabs on;