File indexing completed on 2024-05-19 05:54:13
0001 /* This file was part of the KDE libraries 0002 0003 SPDX-FileCopyrightText: 2021 Tomaz Canabrava <tcanabrava@kde.org> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "sshmanagerplugin.h" 0009 0010 #include "sshmanagermodel.h" 0011 #include "sshmanagerpluginwidget.h" 0012 0013 #include "ProcessInfo.h" 0014 #include "konsoledebug.h" 0015 #include "session/SessionController.h" 0016 0017 #include <QDockWidget> 0018 #include <QListView> 0019 #include <QMainWindow> 0020 #include <QMenuBar> 0021 #include <QSortFilterProxyModel> 0022 #include <QStandardItemModel> 0023 #include <QTimer> 0024 0025 #include <KActionCollection> 0026 #include <KCommandBar> 0027 #include <KCrash> 0028 #include <KLocalizedString> 0029 #include <KMessageBox> 0030 #include <QSettings> 0031 #include <kcommandbar.h> 0032 0033 #include "MainWindow.h" 0034 #include "terminalDisplay/TerminalDisplay.h" 0035 0036 K_PLUGIN_CLASS_WITH_JSON(SSHManagerPlugin, "konsole_sshmanager.json") 0037 0038 struct SSHManagerPluginPrivate { 0039 SSHManagerModel model; 0040 0041 QMap<Konsole::MainWindow *, SSHManagerTreeWidget *> widgetForWindow; 0042 QMap<Konsole::MainWindow *, QDockWidget *> dockForWindow; 0043 QAction *showQuickAccess = nullptr; 0044 }; 0045 0046 SSHManagerPlugin::SSHManagerPlugin(QObject *object, const QVariantList &args) 0047 : Konsole::IKonsolePlugin(object, args) 0048 , d(std::make_unique<SSHManagerPluginPrivate>()) 0049 { 0050 d->showQuickAccess = new QAction(); 0051 0052 setName(QStringLiteral("SshManager")); 0053 KCrash::initialize(); 0054 } 0055 0056 SSHManagerPlugin::~SSHManagerPlugin() 0057 { 0058 } 0059 0060 void SSHManagerPlugin::createWidgetsForMainWindow(Konsole::MainWindow *mainWindow) 0061 { 0062 auto *sshDockWidget = new QDockWidget(mainWindow); 0063 auto *managerWidget = new SSHManagerTreeWidget(); 0064 managerWidget->setModel(&d->model); 0065 sshDockWidget->setWidget(managerWidget); 0066 sshDockWidget->setWindowTitle(i18n("SSH Manager")); 0067 sshDockWidget->setObjectName(QStringLiteral("SSHManagerDock")); 0068 sshDockWidget->setVisible(false); 0069 sshDockWidget->setAllowedAreas(Qt::DockWidgetArea::LeftDockWidgetArea | Qt::DockWidgetArea::RightDockWidgetArea); 0070 0071 mainWindow->addDockWidget(Qt::LeftDockWidgetArea, sshDockWidget); 0072 0073 d->widgetForWindow[mainWindow] = managerWidget; 0074 d->dockForWindow[mainWindow] = sshDockWidget; 0075 0076 connect(managerWidget, &SSHManagerTreeWidget::requestNewTab, this, [mainWindow] { 0077 mainWindow->newTab(); 0078 }); 0079 0080 connect(managerWidget, &SSHManagerTreeWidget::quickAccessShortcutChanged, this, [this, mainWindow](QKeySequence s) { 0081 mainWindow->actionCollection()->setDefaultShortcut(d->showQuickAccess, s); 0082 0083 QString sequenceText = s.toString(); 0084 QSettings settings; 0085 settings.beginGroup(QStringLiteral("plugins")); 0086 settings.beginGroup(QStringLiteral("sshplugin")); 0087 settings.setValue(QStringLiteral("ssh_shortcut"), sequenceText); 0088 settings.sync(); 0089 }); 0090 } 0091 0092 QList<QAction *> SSHManagerPlugin::menuBarActions(Konsole::MainWindow *mainWindow) const 0093 { 0094 Q_UNUSED(mainWindow) 0095 0096 QAction *toggleVisibilityAction = new QAction(i18n("Show SSH Manager"), mainWindow); 0097 toggleVisibilityAction->setCheckable(true); 0098 mainWindow->actionCollection()->setDefaultShortcut(toggleVisibilityAction, QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_F2)); 0099 connect(toggleVisibilityAction, &QAction::triggered, d->dockForWindow[mainWindow], &QDockWidget::setVisible); 0100 connect(d->dockForWindow[mainWindow], &QDockWidget::visibilityChanged, toggleVisibilityAction, &QAction::setChecked); 0101 0102 return {toggleVisibilityAction}; 0103 } 0104 0105 #include <iostream> 0106 0107 void SSHManagerPlugin::activeViewChanged(Konsole::SessionController *controller, Konsole::MainWindow *mainWindow) 0108 { 0109 Q_ASSERT(controller); 0110 Q_ASSERT(mainWindow); 0111 0112 auto terminalDisplay = controller->view(); 0113 0114 d->showQuickAccess->deleteLater(); 0115 d->showQuickAccess = new QAction(i18n("Show Quick Access for SSH Actions")); 0116 0117 QSettings settings; 0118 settings.beginGroup(QStringLiteral("plugins")); 0119 settings.beginGroup(QStringLiteral("sshplugin")); 0120 0121 const QKeySequence def(Qt::CTRL | Qt::ALT | Qt::Key_H); 0122 const QString defText = def.toString(); 0123 const QString entry = settings.value(QStringLiteral("ssh_shortcut"), defText).toString(); 0124 const QKeySequence shortcutEntry(entry); 0125 0126 mainWindow->actionCollection()->setDefaultShortcut(d->showQuickAccess, shortcutEntry); 0127 terminalDisplay->addAction(d->showQuickAccess); 0128 0129 connect(d->showQuickAccess, &QAction::triggered, this, [this, terminalDisplay, controller] { 0130 auto bar = new KCommandBar(terminalDisplay->topLevelWidget()); 0131 QList<QAction *> actions; 0132 for (int i = 0; i < d->model.rowCount(); i++) { 0133 QModelIndex folder = d->model.index(i, 0); 0134 for (int e = 0; e < d->model.rowCount(folder); e++) { 0135 QModelIndex idx = d->model.index(e, 0, folder); 0136 QAction *act = new QAction(idx.data().toString()); 0137 connect(act, &QAction::triggered, this, [this, idx, controller] { 0138 requestConnection(nullptr, &d->model, controller, idx); 0139 }); 0140 actions.append(act); 0141 } 0142 } 0143 0144 if (actions.isEmpty()) // no ssh config found, must give feedback to the user about that 0145 { 0146 const QString feedbackMessage = i18n("No saved SSH config found. You can add one on Plugins -> SSH Manager"); 0147 const QString feedbackTitle = i18n("Plugins - SSH Manager"); 0148 KMessageBox::error(terminalDisplay->topLevelWidget(), feedbackMessage, feedbackTitle); 0149 return; 0150 } 0151 0152 QVector<KCommandBar::ActionGroup> groups; 0153 groups.push_back(KCommandBar::ActionGroup{i18n("SSH Entries"), actions}); 0154 bar->setActions(groups); 0155 bar->show(); 0156 }); 0157 0158 if (mainWindow) { 0159 d->widgetForWindow[mainWindow]->setCurrentController(controller); 0160 } 0161 } 0162 0163 void SSHManagerPlugin::requestConnection(QSortFilterProxyModel *filterModel, 0164 QStandardItemModel *model, 0165 Konsole::SessionController *controller, 0166 const QModelIndex &idx) 0167 { 0168 if (!controller) { 0169 return; 0170 } 0171 0172 auto sourceIdx = filterModel ? filterModel->mapToSource(idx) : idx; 0173 if (sourceIdx.parent() == model->invisibleRootItem()->index()) { 0174 return; 0175 } 0176 0177 #ifndef Q_OS_WIN 0178 Konsole::ProcessInfo *info = controller->session()->getProcessInfo(); 0179 bool ok = false; 0180 QString processName = info->name(&ok); 0181 if (!ok) { 0182 KMessageBox::error(nullptr, i18n("Could not get the process name, assume that we can't request a connection"), i18n("Error issuing SSH Command")); 0183 return; 0184 } 0185 0186 if (!QVector<QString>({QStringLiteral("fish"), 0187 QStringLiteral("bash"), 0188 QStringLiteral("dash"), 0189 QStringLiteral("sh"), 0190 QStringLiteral("csh"), 0191 QStringLiteral("ksh"), 0192 QStringLiteral("zsh")}) 0193 .contains(processName)) { 0194 KMessageBox::error(nullptr, i18n("Can't issue SSH command outside the shell application (eg, bash, zsh, sh)"), i18n("Error issuing SSH Command")); 0195 return; 0196 } 0197 #else 0198 // FIXME: Can we do this on windows? 0199 #endif 0200 0201 auto item = model->itemFromIndex(sourceIdx); 0202 auto data = item->data(SSHManagerModel::SSHRole).value<SSHConfigurationData>(); 0203 0204 QString sshCommand = QStringLiteral("ssh "); 0205 if (!data.useSshConfig) { 0206 if (data.sshKey.length()) { 0207 sshCommand += QStringLiteral("-i %1 ").arg(data.sshKey); 0208 } 0209 0210 if (data.port.length()) { 0211 sshCommand += QStringLiteral("-p %1 ").arg(data.port); 0212 } 0213 0214 if (!data.username.isEmpty()) { 0215 sshCommand += data.username + QLatin1Char('@'); 0216 } 0217 } 0218 0219 if (!data.host.isEmpty()) { 0220 sshCommand += data.host; 0221 } 0222 0223 controller->session()->sendTextToTerminal(sshCommand, QLatin1Char('\r')); 0224 if (controller->session()->views().count()) { 0225 controller->session()->views().at(0)->setFocus(); 0226 } 0227 } 0228 0229 #include "moc_sshmanagerplugin.cpp" 0230 #include "sshmanagerplugin.moc"