diff --git a/config/hostpreferenceslist.cpp b/config/hostpreferenceslist.cpp index d284825..60e84d6 100644 --- a/config/hostpreferenceslist.cpp +++ b/config/hostpreferenceslist.cpp @@ -1,145 +1,145 @@ /**************************************************************************** ** ** Copyright (C) 2007 Urs Wolfer ** ** This file is part of KDE. ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; see the file COPYING. If not, write to ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ** Boston, MA 02110-1301, USA. ** ****************************************************************************/ #include "hostpreferenceslist.h" #include "hostpreferences.h" #include "krdc_debug.h" #include #include #include #include #include #include HostPreferencesList::HostPreferencesList(QWidget *parent, MainWindow *mainWindow, KConfigGroup hostPrefsConfig) : QWidget(parent) , m_hostPrefsConfig(hostPrefsConfig) , m_mainWindow(mainWindow) { hostList = new QListWidget(this); connect(hostList, SIGNAL(itemSelectionChanged()), SLOT(selectionChanged())); connect(hostList, SIGNAL(itemDoubleClicked(QListWidgetItem*)), SLOT(configureHost())); configureButton = new QPushButton(this); configureButton->setEnabled(false); configureButton->setText(i18n("Configure...")); configureButton->setIcon(QIcon::fromTheme(QLatin1String("configure"))); connect(configureButton, SIGNAL(clicked()), SLOT(configureHost())); removeButton = new QPushButton(this); removeButton->setEnabled(false); removeButton->setText(i18n("Remove")); removeButton->setIcon(QIcon::fromTheme(QLatin1String("list-remove"))); connect(removeButton, SIGNAL(clicked()), SLOT(removeHost())); QVBoxLayout *buttonLayout = new QVBoxLayout; buttonLayout->addWidget(configureButton); buttonLayout->addWidget(removeButton); buttonLayout->addStretch(); QHBoxLayout *mainLayout = new QHBoxLayout(this); mainLayout->addWidget(hostList); mainLayout->addLayout(buttonLayout); setLayout(mainLayout); readConfig(); } HostPreferencesList::~HostPreferencesList() { } void HostPreferencesList::readConfig() { QStringList urls = m_hostPrefsConfig.groupList(); for (int i = 0; i < urls.size(); ++i) hostList->addItem(new QListWidgetItem(urls.at(i))); } void HostPreferencesList::saveSettings() { m_hostPrefsConfig.sync(); } void HostPreferencesList::configureHost() { QList selectedItems = hostList->selectedItems(); foreach(QListWidgetItem *selectedItem, selectedItems) { const QString urlString = selectedItem->text(); const QUrl url = QUrl(urlString); qCDebug(KRDC) << "Configure host: " << urlString; - HostPreferences* prefs = 0; + HostPreferences* prefs = nullptr; const QList remoteViewFactories(m_mainWindow->remoteViewFactoriesList()); foreach(RemoteViewFactory *factory, remoteViewFactories) { if (factory->supportsUrl(url)) { prefs = factory->createHostPreferences(m_hostPrefsConfig.group(urlString), this); if (prefs) { qCDebug(KRDC) << "Found plugin to handle url (" << urlString << "): " << prefs->metaObject()->className(); } else { qCDebug(KRDC) << "Found plugin to handle url (" << urlString << "), but plugin does not provide preferences"; } } } if (prefs) { prefs->showDialog(this); delete prefs; } else { KMessageBox::error(this, i18n("The selected host cannot be handled."), i18n("Unusable URL")); } } } void HostPreferencesList::removeHost() { const QList selectedItems = hostList->selectedItems(); foreach(QListWidgetItem *selectedItem, selectedItems) { qCDebug(KRDC) << "Remove host: " << selectedItem->text(); m_hostPrefsConfig.deleteGroup(selectedItem->text()); delete(selectedItem); } saveSettings(); hostList->clearSelection(); } void HostPreferencesList::selectionChanged() { const bool enabled = hostList->selectedItems().isEmpty() ? false : true; configureButton->setEnabled(enabled); removeButton->setEnabled(enabled); } diff --git a/connectiondelegate.h b/connectiondelegate.h index b064c15..fdfd11e 100644 --- a/connectiondelegate.h +++ b/connectiondelegate.h @@ -1,39 +1,39 @@ /**************************************************************************** ** ** Copyright (C) 2009 Tony Murray ** ** This file is part of KDE. ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; see the file COPYING. If not, write to ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ** Boston, MA 02110-1301, USA. ** ****************************************************************************/ #ifndef CONNECTIONDELEGATE_H #define CONNECTIONDELEGATE_H #include class ConnectionDelegate : public QStyledItemDelegate { Q_OBJECT public: - explicit ConnectionDelegate(QObject *parent = 0); + explicit ConnectionDelegate(QObject *parent = nullptr); QString displayText(const QVariant &value, const QLocale& locale) const override; void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; }; #endif // CONNECTIONDELEGATE_H diff --git a/core/hostpreferences.cpp b/core/hostpreferences.cpp index 0b5ce15..15d123f 100644 --- a/core/hostpreferences.cpp +++ b/core/hostpreferences.cpp @@ -1,230 +1,230 @@ /**************************************************************************** ** ** Copyright (C) 2007 - 2010 Urs Wolfer ** ** This file is part of KDE. ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; see the file COPYING. If not, write to ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ** Boston, MA 02110-1301, USA. ** ****************************************************************************/ #include "hostpreferences.h" #include "krdc_debug.h" #include "settings.h" #include #include #include #include #include #include #include #include HostPreferences::HostPreferences(KConfigGroup configGroup, QObject *parent) : QObject(parent), m_configGroup(configGroup), m_connected(false), - showAgainCheckBox(0), - walletSupportCheckBox(0) + showAgainCheckBox(nullptr), + walletSupportCheckBox(nullptr) { m_hostConfigured = m_configGroup.hasKey("showConfigAgain"); } HostPreferences::~HostPreferences() { } KConfigGroup HostPreferences::configGroup() { return m_configGroup; } void HostPreferences::acceptConfig() { setShowConfigAgain(showAgainCheckBox->isChecked()); setWalletSupport(walletSupportCheckBox->isChecked()); } bool HostPreferences::hostConfigured() { return m_hostConfigured; } void HostPreferences::setShowConfigAgain(bool show) { m_configGroup.writeEntry("showConfigAgain", show); } bool HostPreferences::showConfigAgain() { return m_configGroup.readEntry("showConfigAgain", true); } void HostPreferences::setWalletSupport(bool walletSupport) { m_configGroup.writeEntry("walletSupport", walletSupport); } bool HostPreferences::walletSupport() { return m_configGroup.readEntry("walletSupport", true); } void HostPreferences::setHeight(int height) { if (height >= 0) m_configGroup.writeEntry("height", height); } int HostPreferences::height() { return m_configGroup.readEntry("height", Settings::height()); } void HostPreferences::setWidth(int width) { if (width >= 0) m_configGroup.writeEntry("width", width); } int HostPreferences::width() { return m_configGroup.readEntry("width", Settings::width()); } bool HostPreferences::fullscreenScale() { return m_configGroup.readEntry("fullscreenScale", false); } void HostPreferences::setFullscreenScale(bool scale) { m_configGroup.writeEntry("fullscreenScale", scale); } bool HostPreferences::windowedScale() { return m_configGroup.readEntry("windowedScale", false); } void HostPreferences::setWindowedScale(bool scale) { m_configGroup.writeEntry("windowedScale", scale); } bool HostPreferences::grabAllKeys() { return m_configGroup.readEntry("grabAllKeys", false); } void HostPreferences::setGrabAllKeys(bool grab) { m_configGroup.writeEntry("grabAllKeys", grab); } bool HostPreferences::showLocalCursor() { return m_configGroup.readEntry("showLocalCursor", false); } void HostPreferences::setShowLocalCursor(bool show) { m_configGroup.writeEntry("showLocalCursor", show); } bool HostPreferences::viewOnly() { return m_configGroup.readEntry("viewOnly", false); } void HostPreferences::setViewOnly(bool view) { m_configGroup.writeEntry("viewOnly", view); } bool HostPreferences::showDialogIfNeeded(QWidget *parent) { if (hostConfigured()) { if (showConfigAgain()) { qCDebug(KRDC) << "Show config dialog again"; return showDialog(parent); } else return true; // no changes, no need to save } else { qCDebug(KRDC) << "No config found, create new"; if (Settings::showPreferencesForNewConnections()) return showDialog(parent); else return true; } } bool HostPreferences::showDialog(QWidget *parent) { // Prepare dialog KPageDialog *dialog = new KPageDialog(parent); dialog->setWindowTitle(i18n("Host Configuration")); QWidget *mainWidget = new QWidget(parent); QVBoxLayout *layout = new QVBoxLayout(mainWidget); dialog->addPage(mainWidget, i18n("Host Configuration")); if (m_connected) { const QString noteText = i18n("Note that settings might only apply when you connect next time to this host."); const QString format = QLatin1String("%1"); QLabel *commentLabel = new QLabel(format.arg(noteText), mainWidget); layout->addWidget(commentLabel); } QWidget* widget = createProtocolSpecificConfigPage(); if (widget) { if (widget->layout()) widget->layout()->setMargin(0); layout->addWidget(widget); } showAgainCheckBox = new QCheckBox(mainWidget); showAgainCheckBox->setText(i18n("Show this dialog again for this host")); showAgainCheckBox->setChecked(showConfigAgain()); walletSupportCheckBox = new QCheckBox(mainWidget); walletSupportCheckBox->setText(i18n("Remember password (KWallet)")); walletSupportCheckBox->setChecked(walletSupport()); layout->addWidget(showAgainCheckBox); layout->addWidget(walletSupportCheckBox); layout->addStretch(1); // Show dialog if (dialog->exec() == QDialog::Accepted) { qCDebug(KRDC) << "HostPreferences config dialog accepted"; acceptConfig(); return true; } else { return false; } } void HostPreferences::setShownWhileConnected(bool connected) { m_connected = connected; } diff --git a/core/remoteview.cpp b/core/remoteview.cpp index 3d982c0..c95e672 100644 --- a/core/remoteview.cpp +++ b/core/remoteview.cpp @@ -1,285 +1,285 @@ /**************************************************************************** ** ** Copyright (C) 2002-2003 Tim Jansen ** Copyright (C) 2007-2008 Urs Wolfer ** ** This file is part of KDE. ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; see the file COPYING. If not, write to ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ** Boston, MA 02110-1301, USA. ** ****************************************************************************/ #include "remoteview.h" #include "krdc_debug.h" #include #include #include RemoteView::RemoteView(QWidget *parent) : QWidget(parent), m_status(Disconnected), m_host(QString()), m_port(0), m_viewOnly(false), m_grabAllKeys(false), m_scale(false), m_keyboardIsGrabbed(false), #ifndef QTONLY - m_wallet(0), + m_wallet(nullptr), #endif m_dotCursorState(CursorOff) { resize(0, 0); } RemoteView::~RemoteView() { #ifndef QTONLY delete m_wallet; #endif } RemoteView::RemoteStatus RemoteView::status() { return m_status; } void RemoteView::setStatus(RemoteView::RemoteStatus s) { if (m_status == s) return; if (((1+ m_status) != s) && (s != Disconnected)) { // follow state transition rules if (s == Disconnecting) { if (m_status == Disconnected) return; } else { Q_ASSERT(((int) s) >= 0); if (m_status > s) { m_status = Disconnected; emit statusChanged(Disconnected); } // smooth state transition RemoteStatus origState = m_status; for (int i = origState; i < s; ++i) { m_status = (RemoteStatus) i; emit statusChanged((RemoteStatus) i); } } } m_status = s; emit statusChanged(m_status); } bool RemoteView::supportsScaling() const { return false; } bool RemoteView::supportsLocalCursor() const { return false; } bool RemoteView::supportsViewOnly() const { return false; } QString RemoteView::host() { return m_host; } QSize RemoteView::framebufferSize() { return QSize(0, 0); } void RemoteView::startQuitting() { } bool RemoteView::isQuitting() { return false; } int RemoteView::port() { return m_port; } void RemoteView::updateConfiguration() { } void RemoteView::keyEvent(QKeyEvent *) { } bool RemoteView::viewOnly() { return m_viewOnly; } void RemoteView::setViewOnly(bool viewOnly) { m_viewOnly = viewOnly; } bool RemoteView::grabAllKeys() { return m_grabAllKeys; } void RemoteView::setGrabAllKeys(bool grabAllKeys) { m_grabAllKeys = grabAllKeys; if (grabAllKeys) { m_keyboardIsGrabbed = true; grabKeyboard(); } else if (m_keyboardIsGrabbed) { releaseKeyboard(); } } QPixmap RemoteView::takeScreenshot() { return grab(); } void RemoteView::showDotCursor(DotCursorState state) { m_dotCursorState = state; } RemoteView::DotCursorState RemoteView::dotCursorState() const { return m_dotCursorState; } bool RemoteView::scaling() const { return m_scale; } void RemoteView::enableScaling(bool scale) { m_scale = scale; } void RemoteView::switchFullscreen(bool) { } void RemoteView::scaleResize(int, int) { } QUrl RemoteView::url() { return m_url; } #ifndef QTONLY QString RemoteView::readWalletPassword(bool fromUserNameOnly) { const QString KRDCFOLDER = QLatin1String("KRDC"); window()->setDisabled(true); // WORKAROUND: disable inputs so users cannot close the current tab (see #181230) m_wallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), window()->winId(), KWallet::Wallet::OpenType::Synchronous); window()->setDisabled(false); if (m_wallet) { bool walletOK = m_wallet->hasFolder(KRDCFOLDER); if (!walletOK) { walletOK = m_wallet->createFolder(KRDCFOLDER); qCDebug(KRDC) << "Wallet folder created"; } if (walletOK) { qCDebug(KRDC) << "Wallet OK"; m_wallet->setFolder(KRDCFOLDER); QString password; QString key; if (fromUserNameOnly) key = m_url.userName(); else key = m_url.toDisplayString(QUrl::StripTrailingSlash); if (m_wallet->hasEntry(key) && !m_wallet->readPassword(key, password)) { qCDebug(KRDC) << "Password read OK"; return password; } } } return QString(); } void RemoteView::saveWalletPassword(const QString &password, bool fromUserNameOnly) { QString key; if (fromUserNameOnly) key = m_url.userName(); else key = m_url.toDisplayString(QUrl::StripTrailingSlash); if (m_wallet && m_wallet->isOpen()) { qCDebug(KRDC) << "Write wallet password"; m_wallet->writePassword(key, password); } } #endif QCursor RemoteView::localDotCursor() const { QString cursorBitmapPath = QStandardPaths::locate(QStandardPaths::DataLocation, QLatin1String("pics/pointcursor.png")); QBitmap cursorBitmap = QBitmap(); cursorBitmap.load(cursorBitmapPath); QString cursorMaskPath = QStandardPaths::locate(QStandardPaths::DataLocation, QLatin1String("pics/pointcursormask.png")); QBitmap cursorMask = QBitmap(); cursorMask.load(cursorMaskPath); return QCursor(cursorBitmap, cursorMask); } void RemoteView::focusInEvent(QFocusEvent *event) { if (m_grabAllKeys) { m_keyboardIsGrabbed = true; grabKeyboard(); } QWidget::focusInEvent(event); } void RemoteView::focusOutEvent(QFocusEvent *event) { if (m_grabAllKeys || m_keyboardIsGrabbed) { m_keyboardIsGrabbed = false; releaseKeyboard(); } QWidget::focusOutEvent(event); } #include "moc_remoteview.cpp" diff --git a/core/remoteview.h b/core/remoteview.h index 1f2fbd0..9ee8904 100644 --- a/core/remoteview.h +++ b/core/remoteview.h @@ -1,423 +1,423 @@ /**************************************************************************** ** ** Copyright (C) 2002-2003 Tim Jansen ** Copyright (C) 2007-2008 Urs Wolfer ** ** This file is part of KDE. ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; see the file COPYING. If not, write to ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ** Boston, MA 02110-1301, USA. ** ****************************************************************************/ #ifndef REMOTEVIEW_H #define REMOTEVIEW_H #ifndef QTONLY #include #include "krdccore_export.h" #else #define KRDCCORE_EXPORT #endif #include #include class HostPreferences; /** * Generic widget that displays a remote framebuffer. * Implement this if you want to add another backend. * * Things to take care of: * @li The RemoteView is responsible for its size. In * non-scaling mode, set the fixed size of the widget * to the remote resolution. In scaling mode, set the * maximum size to the remote size and minimum size to the * smallest resolution that your scaler can handle. * @li if you override mouseMoveEvent() * you must ignore the QEvent, because the KRDC widget will * need it for stuff like toolbar auto-hide and bump * scrolling. If you use x11Event(), make sure that * MotionNotify events will be forwarded. * */ class KRDCCORE_EXPORT RemoteView : public QWidget { Q_OBJECT public: Q_ENUMS(Quality) enum Quality { Unknown, High, Medium, Low }; /** * Describes the state of a local cursor, if there is such a concept in the backend. * With local cursors, there are two cursors: the cursor on the local machine (client), * and the cursor on the remote machine (server). Because there is usually some lag, * some backends show both cursors simultanously. In the VNC backend the local cursor * is a dot and the remote cursor is the 'real' cursor, usually an arrow. */ Q_ENUMS(DotCursorState) enum DotCursorState { CursorOn, ///< Always show local cursor (and the remote one). CursorOff, ///< Never show local cursor, only the remote one. /// Try to measure the lag and enable the local cursor if the latency is too high. CursorAuto }; /** * State of the connection. The state of the connection is returned * by @ref RemoteView::status(). * * Not every state transition is allowed. You are only allowed to transition * a state to the following state, with three exceptions: * @li You can move from every state directly to Disconnected * @li You can move from every state except Disconnected to * Disconnecting * @li You can move from Disconnected to Connecting * * @ref RemoteView::setStatus() will follow this rules for you. * (If you add/remove a state here, you must adapt it) */ Q_ENUMS(RemoteStatus) enum RemoteStatus { Connecting = 0, Authenticating = 1, Preparing = 2, Connected = 3, Disconnecting = -1, Disconnected = -2 }; Q_ENUMS(ErrorCode) enum ErrorCode { None = 0, Internal, Connection, Protocol, IO, Name, NoServer, ServerBlocked, Authentication }; ~RemoteView() override; /** * Checks whether the backend supports scaling. The * default implementation returns false. * @return true if scaling is supported * @see scaling() */ virtual bool supportsScaling() const; /** * Checks whether the widget is in scale mode. The * default implementation always returns false. * @return true if scaling is activated. Must always be * false if @ref supportsScaling() returns false * @see supportsScaling() */ virtual bool scaling() const; /** * Checks whether the backend supports the concept of local cursors. The * default implementation returns false. * @return true if local cursors are supported/known * @see DotCursorState * @see showDotCursor() * @see dotCursorState() */ virtual bool supportsLocalCursor() const; /** * Sets the state of the dot cursor, if supported by the backend. * The default implementation does nothing. * @param state the new state (CursorOn, CursorOff or * CursorAuto) * @see dotCursorState() * @see supportsLocalCursor() */ virtual void showDotCursor(DotCursorState state); /** * Returns the state of the local cursor. The default implementation returns * always CursorOff. * @return true if local cursors are supported/known * @see showDotCursor() * @see supportsLocalCursor() */ virtual DotCursorState dotCursorState() const; /** * Checks whether the backend supports the view only mode. The * default implementation returns false. * @return true if view-only mode is supported * @see DotCursorState * @see showDotCursor() * @see dotCursorState() */ virtual bool supportsViewOnly() const; /** * Checks whether the view is in view-only mode. This means * that all input is ignored. */ virtual bool viewOnly(); /** * Checks whether grabbing all possible keys is enabled. */ virtual bool grabAllKeys(); /** * Returns the resolution of the remote framebuffer. * It should return a null @ref QSize when the size * is not known. * The backend must also emit a @ref framebufferSizeChanged() * when the size of the framebuffer becomes available * for the first time or the size changed. * @return the remote framebuffer size, a null QSize * if unknown */ virtual QSize framebufferSize(); /** * Initiate the disconnection. This doesn't need to happen * immediately. The call must not block. * @see isQuitting() */ virtual void startQuitting(); /** * Checks whether the view is currently quitting. * @return true if it is quitting * @see startQuitting() * @see setStatus() */ virtual bool isQuitting(); /** * @return the host the view is connected to */ virtual QString host(); /** * @return the port the view is connected to */ virtual int port(); /** * Initialize the view (for example by showing configuration * dialogs to the user) and start connecting. Should not block * without running the event loop (so displaying a dialog is ok). * When the view starts connecting the application must call * @ref setStatus() with the status Connecting. * @return true if successful (so far), false * otherwise * @see connected() * @see disconnected() * @see disconnectedError() * @see statusChanged() */ virtual bool start() = 0; /** * Called when the configuration is changed. * The default implementation does nothing. */ virtual void updateConfiguration(); /** * @return screenshot of the view */ virtual QPixmap takeScreenshot(); #ifndef QTONLY /** * Returns the current host preferences of this view. */ virtual HostPreferences* hostPreferences() = 0; #endif /** * Returns the current status of the connection. * @return the status of the connection * @see setStatus() */ RemoteStatus status(); /** * @return the current url */ QUrl url(); public Q_SLOTS: /** * Called to enable or disable scaling. * Ignored if @ref supportsScaling() is false. * The default implementation does nothing. * @param s true to enable, false to disable. * @see supportsScaling() * @see scaling() */ virtual void enableScaling(bool scale); /** * Enables/disables the view-only mode. * Ignored if @ref supportsScaling() is false. * The default implementation does nothing. * @param viewOnly true to enable, false to disable. * @see supportsScaling() * @see viewOnly() */ virtual void setViewOnly(bool viewOnly); /** * Enables/disables grabbing all possible keys. * @param grabAllKeys true to enable, false to disable. * Default is false. * @see grabAllKeys() */ virtual void setGrabAllKeys(bool grabAllKeys); /** * Called to let the backend know it when * we switch from/to fullscreen. * @param on true when switching to fullscreen, * false when switching from fullscreen. */ virtual void switchFullscreen(bool on); /** * Sends a QKeyEvent to the remote server. * @param event the key to send */ virtual void keyEvent(QKeyEvent *event); /** * Called when the visible place changed so remote * view can resize itself. */ virtual void scaleResize(int w, int h); Q_SIGNALS: /** * Emitted when the size of the remote screen changes. Also * called when the size is known for the first time. * @param x the width of the screen * @param y the height of the screen */ void framebufferSizeChanged(int w, int h); /** * Emitted when the view connected successfully. */ void connected(); /** * Emitted when the view disconnected without error. */ void disconnected(); /** * Emitted when the view disconnected with error. */ void disconnectedError(); /** * Emitted when the view has a specific error. */ void errorMessage(const QString &title, const QString &message); /** * Emitted when the status of the view changed. * @param s the new status */ void statusChanged(RemoteView::RemoteStatus s); /** * Emitted when the password dialog is shown or hidden. * @param b true when the dialog is shown, false when it has been hidden */ void showingPasswordDialog(bool b); /** * Emitted when the mouse on the remote side has been moved. * @param x the new x coordinate * @param y the new y coordinate * @param buttonMask the mask of mouse buttons (bit 0 for first mouse * button, 1 for second button etc)a */ void mouseStateChanged(int x, int y, int buttonMask); protected: - RemoteView(QWidget *parent = 0); + RemoteView(QWidget *parent = nullptr); void focusInEvent(QFocusEvent *event) override; void focusOutEvent(QFocusEvent *event) override; /** * The status of the remote view. */ RemoteStatus m_status; /** * Set the status of the connection. * Emits a statusChanged() signal. * Note that the states need to be set in a certain order, * see @ref Status. setStatus() will try to do this * transition automatically, so if you are in Connecting * and call setStatus(Preparing), setStatus() will * emit a Authenticating and then Preparing. * If you transition backwards, it will emit a * Disconnected before doing the transition. * @param s the new status */ virtual void setStatus(RemoteStatus s); QCursor localDotCursor() const; QString m_host; int m_port; bool m_viewOnly; bool m_grabAllKeys; bool m_scale; bool m_keyboardIsGrabbed; QUrl m_url; #ifndef QTONLY QString readWalletPassword(bool fromUserNameOnly = false); void saveWalletPassword(const QString &password, bool fromUserNameOnly = false); KWallet::Wallet *m_wallet; #endif DotCursorState m_dotCursorState; }; #endif diff --git a/core/remoteviewfactory.h b/core/remoteviewfactory.h index b4af2da..be0e3dc 100644 --- a/core/remoteviewfactory.h +++ b/core/remoteviewfactory.h @@ -1,92 +1,92 @@ /**************************************************************************** ** ** Copyright (C) 2008 Urs Wolfer ** ** This file is part of KDE. ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; see the file COPYING. If not, write to ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ** Boston, MA 02110-1301, USA. ** ****************************************************************************/ #ifndef REMOTEVIEWFACTORY_H #define REMOTEVIEWFACTORY_H #include "remoteview.h" #include "krdccore_export.h" #include #include #include /** * Factory to be implemented by any plugin. */ class KRDCCORE_EXPORT RemoteViewFactory : public QObject { Q_OBJECT public: /** * Deconstructor. */ ~RemoteViewFactory() override; /** * Returns true if the provided @p url is supported by the current plugin. */ virtual bool supportsUrl(const QUrl &url) const = 0; /** * Returns a new RemoteView implementing object. */ virtual RemoteView *createView(QWidget *parent, const QUrl &url, KConfigGroup configGroup) = 0; /** * Returns a new HostPreferences implementing object or 0 if no settings are available. */ virtual HostPreferences *createHostPreferences(KConfigGroup configGroup, QWidget *parent) = 0; /** * Returns the supported scheme. * @see QUrl::scheme() */ virtual QString scheme() const = 0; /** * Returns the text of the action in the file menu (by default). */ virtual QString connectActionText() const = 0; /** * Returns the text of the connect button on the startscreen. */ virtual QString connectButtonText() const = 0; /** * Returns the tooltip next to the url navigator when the user presses * the connect action. */ virtual QString connectToolTipText() const = 0; protected: /** * Protected constructor so it cannot be instantiated. */ - RemoteViewFactory(QObject *parent = 0); + RemoteViewFactory(QObject *parent = nullptr); }; #endif // REMOTEVIEWFACTORY_H diff --git a/floatingtoolbar.cpp b/floatingtoolbar.cpp index fd851fd..39a927f 100644 --- a/floatingtoolbar.cpp +++ b/floatingtoolbar.cpp @@ -1,483 +1,483 @@ /**************************************************************************** ** ** Copyright (C) 2007-2008 Urs Wolfer ** Parts of this file have been take from okular: ** Copyright (C) 2004-2005 Enrico Ros ** ** This file is part of KDE. ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; see the file COPYING. If not, write to ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ** Boston, MA 02110-1301, USA. ** ****************************************************************************/ #include "floatingtoolbar.h" #include "krdc_debug.h" #include #include #include #include #include #include static const int actionIconSize = 22; static const int toolBarRBMargin = 2; static const double toolBarOpacity = 0.8; static const int visiblePixelWhenAutoHidden = 6; static const int autoHideTimeout = 500; static const int initialAutoHideTimeout = 2000; /** * Denotes the verious states of the animation. */ enum AnimState { Hiding, Showing, Still }; class FloatingToolBarPrivate { public: FloatingToolBarPrivate(FloatingToolBar *qq) : q(qq) , anchorSide(FloatingToolBar::Left) , offsetPlaceHolder(new QWidget(qq)) , animState(Still) , toDelete(false) , visible(false) , sticky(false) , opacity(toolBarOpacity) // set queuedShow to true so we show the toolbar if we get a resize event on the anchorWidget , queuedShow(true) { } // rebuild contents and reposition then widget void buildToolBar(); void reposition(); // compute the visible and hidden positions along current side QPoint getInnerPoint() const; QPoint getOuterPoint() const; FloatingToolBar *q; QWidget *anchorWidget; FloatingToolBar::Side anchorSide; QWidget *offsetPlaceHolder; QTimer *animTimer; QTimer *autoHideTimer; QPoint currentPosition; QPoint endPosition; AnimState animState; bool toDelete; bool visible; bool sticky; qreal opacity; bool queuedShow; QPixmap backgroundPixmap; }; FloatingToolBar::FloatingToolBar(QWidget *parent, QWidget *anchorWidget) : QToolBar(parent), d(new FloatingToolBarPrivate(this)) { ; addWidget(d->offsetPlaceHolder); setMouseTracking(true); setIconSize(QSize(actionIconSize, actionIconSize)); d->anchorWidget = anchorWidget; d->animTimer = new QTimer(this); connect(d->animTimer, SIGNAL(timeout()), this, SLOT(animate())); d->autoHideTimer = new QTimer(this); connect(d->autoHideTimer, SIGNAL(timeout()), this, SLOT(hide())); // apply a filter to get notified when anchor changes geometry d->anchorWidget->installEventFilter(this); } FloatingToolBar::~FloatingToolBar() { delete d; } void FloatingToolBar::addAction(QAction *action) { QToolBar::addAction(action); // rebuild toolbar shape and contents only if the toolbar is already visible, // otherwise it will be done in showAndAnimate() if (isVisible()) d->reposition(); } void FloatingToolBar::setSide(Side side) { d->anchorSide = side; if (isVisible()) d->reposition(); } void FloatingToolBar::setSticky(bool sticky) { d->sticky = sticky; if (sticky) d->autoHideTimer->stop(); } void FloatingToolBar::showAndAnimate() { if (d->animState == Showing) return; d->animState = Showing; show(); // force update for case when toolbar has not been built yet d->reposition(); // start scrolling in d->animTimer->start(20); // This permits to show the toolbar for a while when going full screen. if (!d->sticky) d->autoHideTimer->start(initialAutoHideTimeout); } void FloatingToolBar::hideAndDestroy() { if (d->animState == Hiding) return; // set parameters for sliding out d->animState = Hiding; d->toDelete = true; d->endPosition = d->getOuterPoint(); // start scrolling out d->animTimer->start(20); } void FloatingToolBar::hide() { if (underMouse()) return; if (d->visible) { QPoint diff; switch (d->anchorSide) { case Left: diff = QPoint(visiblePixelWhenAutoHidden, 0); break; case Right: diff = QPoint(-visiblePixelWhenAutoHidden, 0); break; case Top: diff = QPoint(0, visiblePixelWhenAutoHidden); break; case Bottom: diff = QPoint(0, -visiblePixelWhenAutoHidden); break; } d->animState = Hiding; d->endPosition = d->getOuterPoint() + diff; // start scrolling out d->animTimer->start(20); } } bool FloatingToolBar::eventFilter(QObject *obj, QEvent *e) { if (obj == d->anchorWidget && e->type() == QEvent::Resize) { if (d->queuedShow) { // if the toolbar is not visible yet, try to show it if the anchor widget is in fullscreen already d->queuedShow = false; showAndAnimate(); return true; } // if anchorWidget changed geometry reposition toolbar d->animTimer->stop(); if ((d->animState == Hiding || !d->visible) && d->toDelete) deleteLater(); else d->reposition(); } return QToolBar::eventFilter(obj, e); } void FloatingToolBar::paintEvent(QPaintEvent *e) { QToolBar::paintEvent(e); // paint the internal pixmap over the widget QPainter p(this); p.setOpacity(d->opacity); p.drawImage(e->rect().topLeft(), d->backgroundPixmap.toImage(), e->rect()); } void FloatingToolBar::mousePressEvent(QMouseEvent *e) { if (e->button() == Qt::LeftButton) setCursor(Qt::SizeAllCursor); QToolBar::mousePressEvent(e); } void FloatingToolBar::mouseMoveEvent(QMouseEvent *e) { // show the toolbar again when it is auto-hidden if (!d->visible) { showAndAnimate(); return; } if ((QApplication::mouseButtons() & Qt::LeftButton) != Qt::LeftButton) return; // compute the nearest side to attach the widget to const QPoint parentPos = mapToParent(e->pos()); const float nX = (float)parentPos.x() / (float)d->anchorWidget->width(); const float nY = (float)parentPos.y() / (float)d->anchorWidget->height(); if (nX > 0.3 && nX < 0.7 && nY > 0.3 && nY < 0.7) return; bool LT = nX < (1.0 - nY); bool LB = nX < (nY); Side side = LT ? (LB ? Left : Top) : (LB ? Bottom : Right); // check if side changed if (side == d->anchorSide) return; d->anchorSide = side; d->reposition(); emit orientationChanged((int)side); QToolBar::mouseMoveEvent(e); } void FloatingToolBar::enterEvent(QEvent *e) { // Stop the autohide timer while the mouse is inside d->autoHideTimer->stop(); if (!d->visible) showAndAnimate(); QToolBar::enterEvent(e); } void FloatingToolBar::leaveEvent(QEvent *e) { if (!d->sticky) d->autoHideTimer->start(autoHideTimeout); QToolBar::leaveEvent(e); } void FloatingToolBar::mouseReleaseEvent(QMouseEvent *e) { if (e->button() == Qt::LeftButton) setCursor(Qt::ArrowCursor); QToolBar::mouseReleaseEvent(e); } void FloatingToolBar::wheelEvent(QWheelEvent *e) { e->accept(); const qreal diff = e->delta() / 100.0 / 15.0; // qCDebug(KRDC) << diff; if (((d->opacity <= 1) && (diff > 0)) || ((d->opacity >= 0) && (diff < 0))) d->opacity += diff; update(); QToolBar::wheelEvent(e); } void FloatingToolBarPrivate::buildToolBar() { const bool prevUpdates = q->updatesEnabled(); q->setUpdatesEnabled(false); // 1. init numbers we are going to use const bool topLeft = anchorSide == FloatingToolBar::Left || anchorSide == FloatingToolBar::Top; const bool vertical = anchorSide == FloatingToolBar::Left || anchorSide == FloatingToolBar::Right; if (vertical) { offsetPlaceHolder->setFixedSize(1, 7); q->setOrientation(Qt::Vertical); } else { offsetPlaceHolder->setFixedSize(7, 1); q->setOrientation(Qt::Horizontal); } // 2. compute widget size const int myWidth = q->sizeHint().width() - 1; const int myHeight = q->sizeHint().height() - 1; // 3. resize pixmap, mask and widget QBitmap mask(myWidth + 1, myHeight + 1); backgroundPixmap = QPixmap(myWidth + 1, myHeight + 1); backgroundPixmap.fill(Qt::transparent); q->resize(myWidth + 1, myHeight + 1); // 4. create and set transparency mask QPainter maskPainter(&mask); mask.fill(Qt::white); maskPainter.setBrush(Qt::black); if (vertical) maskPainter.drawRoundRect(topLeft ? -10 : 0, 0, myWidth + 10, myHeight, 2000 / (myWidth + 10), 2000 / myHeight); else maskPainter.drawRoundRect(0, topLeft ? -10 : 0, myWidth, myHeight + 10, 2000 / myWidth, 2000 / (myHeight + 10)); maskPainter.end(); q->setMask(mask); // 5. draw background QPainter bufferPainter(&backgroundPixmap); bufferPainter.translate(0.5, 0.5); QPalette pal = q->palette(); // 5.1. draw horizontal/vertical gradient QLinearGradient grad; switch (anchorSide) { case FloatingToolBar::Left: grad = QLinearGradient(0, 1, myWidth + 1, 1); break; case FloatingToolBar::Right: grad = QLinearGradient(myWidth + 1, 1, 0, 1); break; case FloatingToolBar::Top: grad = QLinearGradient(1, 0, 1, myHeight + 1); break; case FloatingToolBar::Bottom: grad = QLinearGradient(1, myHeight + 1, 0, 1); break; } grad.setColorAt(0, pal.color(QPalette::Active, QPalette::Button)); grad.setColorAt(1, pal.color(QPalette::Active, QPalette::Light)); bufferPainter.setBrush(QBrush(grad)); // 5.2. draw rounded border bufferPainter.setPen( pal.color(QPalette::Active, QPalette::Dark).lighter(40)); bufferPainter.setRenderHints(QPainter::Antialiasing); if (vertical) bufferPainter.drawRoundRect(topLeft ? -10 : 0, 0, myWidth + 10, myHeight, 2000 / (myWidth + 10), 2000 / myHeight); else bufferPainter.drawRoundRect(0, topLeft ? -10 : 0, myWidth, myHeight + 10, 2000 / myWidth, 2000 / (myHeight + 10)); // 5.3. draw handle bufferPainter.translate(-0.5, -0.5); bufferPainter.setPen(pal.color(QPalette::Active, QPalette::Mid)); if (vertical) { int dx = anchorSide == FloatingToolBar::Left ? 2 : 4; bufferPainter.drawLine(dx, 6, dx + myWidth - 8, 6); bufferPainter.drawLine(dx, 9, dx + myWidth - 8, 9); bufferPainter.setPen(pal.color(QPalette::Active, QPalette::Light)); bufferPainter.drawLine(dx + 1, 7, dx + myWidth - 7, 7); bufferPainter.drawLine(dx + 1, 10, dx + myWidth - 7, 10); } else { int dy = anchorSide == FloatingToolBar::Top ? 2 : 4; bufferPainter.drawLine(6, dy, 6, dy + myHeight - 8); bufferPainter.drawLine(9, dy, 9, dy + myHeight - 8); bufferPainter.setPen(pal.color(QPalette::Active, QPalette::Light)); bufferPainter.drawLine(7, dy + 1, 7, dy + myHeight - 7); bufferPainter.drawLine(10, dy + 1, 10, dy + myHeight - 7); } q->setUpdatesEnabled(prevUpdates); } void FloatingToolBarPrivate::reposition() { // note: hiding widget here will gives better gfx, but ends drag operation // rebuild widget and move it to its final place buildToolBar(); if (!visible) { currentPosition = getOuterPoint(); endPosition = getInnerPoint(); } else { currentPosition = getInnerPoint(); endPosition = getOuterPoint(); } q->move(currentPosition); } QPoint FloatingToolBarPrivate::getInnerPoint() const { // returns the final position of the widget if (anchorSide == FloatingToolBar::Left) return QPoint(0, (anchorWidget->height() - q->height()) / 2); if (anchorSide == FloatingToolBar::Top) return QPoint((anchorWidget->width() - q->width()) / 2, 0); if (anchorSide == FloatingToolBar::Right) return QPoint(anchorWidget->width() - q->width() + toolBarRBMargin, (anchorWidget->height() - q->height()) / 2); return QPoint((anchorWidget->width() - q->width()) / 2, anchorWidget->height() - q->height() + toolBarRBMargin); } QPoint FloatingToolBarPrivate::getOuterPoint() const { // returns the point from which the transition starts if (anchorSide == FloatingToolBar::Left) return QPoint(-q->width(), (anchorWidget->height() - q->height()) / 2); if (anchorSide == FloatingToolBar::Top) return QPoint((anchorWidget->width() - q->width()) / 2, -q->height()); if (anchorSide == FloatingToolBar::Right) return QPoint(anchorWidget->width() + toolBarRBMargin, (anchorWidget->height() - q->height()) / 2); return QPoint((anchorWidget->width() - q->width()) / 2, anchorWidget->height() + toolBarRBMargin); } void FloatingToolBar::animate() { - if (style()->styleHint(QStyle::SH_Widget_Animate, 0, this)) { + if (style()->styleHint(QStyle::SH_Widget_Animate, nullptr, this)) { // move currentPosition towards endPosition int dX = d->endPosition.x() - d->currentPosition.x(); int dY = d->endPosition.y() - d->currentPosition.y(); dX = dX / 6 + qMax(-1, qMin(1, dX)); dY = dY / 6 + qMax(-1, qMin(1, dY)); d->currentPosition.setX(d->currentPosition.x() + dX); d->currentPosition.setY(d->currentPosition.y() + dY); } else { d->currentPosition = d->endPosition; } move(d->currentPosition); // handle arrival to the end if (d->currentPosition == d->endPosition) { d->animTimer->stop(); switch (d->animState) { case Hiding: d->visible = false; d->animState = Still; if (d->toDelete) deleteLater(); break; case Showing: d->visible = true; d->animState = Still; break; default: qCDebug(KRDC) << "Illegal state"; } } } diff --git a/mainwindow.cpp b/mainwindow.cpp index ebcba2d..c1c577d 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -1,1215 +1,1215 @@ /**************************************************************************** ** ** Copyright (C) 2007 - 2013 Urs Wolfer ** Copyright (C) 2009 - 2010 Tony Murray ** ** This file is part of KDE. ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; see the file COPYING. If not, write to ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ** Boston, MA 02110-1301, USA. ** ****************************************************************************/ #include "mainwindow.h" #include "krdc_debug.h" #include "remoteview.h" #include "settings.h" #include "config/preferencesdialog.h" #include "floatingtoolbar.h" #include "bookmarkmanager.h" #include "connectiondelegate.h" #include "remotedesktopsmodel.h" #include "systemtrayicon.h" #include "tabbedviewwidget.h" #include "hostpreferences.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include MainWindow::MainWindow(QWidget *parent) : KXmlGuiWindow(parent), - m_fullscreenWindow(0), - m_protocolInput(0), - m_addressInput(0), - m_toolBar(0), + m_fullscreenWindow(nullptr), + m_protocolInput(nullptr), + m_addressInput(nullptr), + m_toolBar(nullptr), m_currentRemoteView(-1), - m_systemTrayIcon(0), - m_dockWidgetTableView(0), - m_newConnectionTableView(0), - m_newConnectionWidget(0) + m_systemTrayIcon(nullptr), + m_dockWidgetTableView(nullptr), + m_newConnectionTableView(nullptr), + m_newConnectionWidget(nullptr) { loadAllPlugins(); setupActions(); setStandardToolBarMenuEnabled(true); m_tabWidget = new TabbedViewWidget(this); m_tabWidget->setAutoFillBackground(true); m_tabWidget->setMovable(true); m_tabWidget->setTabPosition((QTabWidget::TabPosition) Settings::tabPosition()); m_tabWidget->setTabsClosable(Settings::tabCloseButton()); connect(m_tabWidget, SIGNAL(tabCloseRequested(int)), SLOT(closeTab(int))); if (Settings::tabMiddleClick()) connect(m_tabWidget, SIGNAL(mouseMiddleClick(int)), SLOT(closeTab(int))); connect(m_tabWidget, SIGNAL(tabBarDoubleClicked(int)), SLOT(openTabSettings(int))); m_tabWidget->tabBar()->setContextMenuPolicy(Qt::CustomContextMenu); connect(m_tabWidget->tabBar(), SIGNAL(customContextMenuRequested(QPoint)), SLOT(tabContextMenu(QPoint))); m_tabWidget->setMinimumSize(600, 400); setCentralWidget(m_tabWidget); createDockWidget(); setupGUI(ToolBar | Keys | Save | Create); if (Settings::systemTrayIcon()) { m_systemTrayIcon = new SystemTrayIcon(this); if(m_fullscreenWindow) m_systemTrayIcon->setAssociatedWidget(m_fullscreenWindow); } connect(m_tabWidget, SIGNAL(currentChanged(int)), SLOT(tabChanged(int))); if (Settings::showStatusBar()) statusBar()->showMessage(i18n("KDE Remote Desktop Client started")); updateActionStatus(); // disable remote view actions if (Settings::openSessions().count() == 0) // just create a new connection tab if there are no open sessions m_tabWidget->addTab(newConnectionWidget(), i18n("New Connection")); if (Settings::rememberSessions()) // give some time to create and show the window first QTimer::singleShot(100, this, SLOT(restoreOpenSessions())); } MainWindow::~MainWindow() { } void MainWindow::setupActions() { QAction *connectionAction = actionCollection()->addAction(QStringLiteral("new_connection")); connectionAction->setText(i18n("New Connection")); connectionAction->setIcon(QIcon::fromTheme(QStringLiteral("network-connect"))); connect(connectionAction, SIGNAL(triggered()), SLOT(newConnectionPage())); QAction *screenshotAction = actionCollection()->addAction(QStringLiteral("take_screenshot")); screenshotAction->setText(i18n("Copy Screenshot to Clipboard")); screenshotAction->setIconText(i18n("Screenshot")); screenshotAction->setIcon(QIcon::fromTheme(QStringLiteral("ksnapshot"))); connect(screenshotAction, SIGNAL(triggered()), SLOT(takeScreenshot())); QAction *fullscreenAction = actionCollection()->addAction(QStringLiteral("switch_fullscreen")); // note: please do not switch to KStandardShortcut unless you know what you are doing (see history of this file) fullscreenAction->setText(i18n("Switch to Full Screen Mode")); fullscreenAction->setIconText(i18n("Full Screen")); fullscreenAction->setIcon(QIcon::fromTheme(QStringLiteral("view-fullscreen"))); actionCollection()->setDefaultShortcuts(fullscreenAction, KStandardShortcut::fullScreen()); connect(fullscreenAction, SIGNAL(triggered()), SLOT(switchFullscreen())); QAction *viewOnlyAction = actionCollection()->addAction(QStringLiteral("view_only")); viewOnlyAction->setCheckable(true); viewOnlyAction->setText(i18n("View Only")); viewOnlyAction->setIcon(QIcon::fromTheme(QStringLiteral("document-preview"))); connect(viewOnlyAction, SIGNAL(triggered(bool)), SLOT(viewOnly(bool))); QAction *disconnectAction = actionCollection()->addAction(QStringLiteral("disconnect")); disconnectAction->setText(i18n("Disconnect")); disconnectAction->setIcon(QIcon::fromTheme(QStringLiteral("network-disconnect"))); actionCollection()->setDefaultShortcuts(disconnectAction, KStandardShortcut::close()); connect(disconnectAction, SIGNAL(triggered()), SLOT(disconnectHost())); QAction *showLocalCursorAction = actionCollection()->addAction(QStringLiteral("show_local_cursor")); showLocalCursorAction->setCheckable(true); showLocalCursorAction->setIcon(QIcon::fromTheme(QStringLiteral("input-mouse"))); showLocalCursorAction->setText(i18n("Show Local Cursor")); showLocalCursorAction->setIconText(i18n("Local Cursor")); connect(showLocalCursorAction, SIGNAL(triggered(bool)), SLOT(showLocalCursor(bool))); QAction *grabAllKeysAction = actionCollection()->addAction(QStringLiteral("grab_all_keys")); grabAllKeysAction->setCheckable(true); grabAllKeysAction->setIcon(QIcon::fromTheme(QStringLiteral("configure-shortcuts"))); grabAllKeysAction->setText(i18n("Grab All Possible Keys")); grabAllKeysAction->setIconText(i18n("Grab Keys")); connect(grabAllKeysAction, SIGNAL(triggered(bool)), SLOT(grabAllKeys(bool))); QAction *scaleAction = actionCollection()->addAction(QStringLiteral("scale")); scaleAction->setCheckable(true); scaleAction->setIcon(QIcon::fromTheme(QStringLiteral("zoom-fit-best"))); scaleAction->setText(i18n("Scale Remote Screen to Fit Window Size")); scaleAction->setIconText(i18n("Scale")); connect(scaleAction, SIGNAL(triggered(bool)), SLOT(scale(bool))); KStandardAction::quit(this, SLOT(quit()), actionCollection()); KStandardAction::preferences(this, SLOT(preferences()), actionCollection()); QAction *configNotifyAction = KStandardAction::configureNotifications(this, SLOT(configureNotifications()), actionCollection()); configNotifyAction->setVisible(false); m_menubarAction = KStandardAction::showMenubar(this, SLOT(showMenubar()), actionCollection()); m_menubarAction->setChecked(!menuBar()->isHidden()); KActionMenu *bookmarkMenu = new KActionMenu(i18n("Bookmarks"), actionCollection()); m_bookmarkManager = new BookmarkManager(actionCollection(), bookmarkMenu->menu(), this); actionCollection()->addAction(QStringLiteral("bookmark") , bookmarkMenu); connect(m_bookmarkManager, SIGNAL(openUrl(QUrl)), SLOT(newConnection(QUrl))); } void MainWindow::loadAllPlugins() { const KPluginInfo::List offers = KPluginTrader::self()->query(QStringLiteral("krdc")); const KConfigGroup conf = KSharedConfig::openConfig()->group(QStringLiteral("Plugins")); qCDebug(KRDC) << "Loading Plugins "; for (int i = 0; i < offers.size(); i++) { KPluginInfo info = offers[i]; info.load(conf); const bool enabled = info.isPluginEnabled(); if (enabled) { RemoteViewFactory *component = createPluginFromInfo(info); - if (component != 0) { + if (component != nullptr) { const int sorting = info.property(QStringLiteral("X-KDE-KRDC-Sorting")).toInt(); m_remoteViewFactories.insert(sorting, component); } else { qCDebug(KRDC) << "Error loading KRDC plugin (" << info.pluginName() << ')'; } } else { qCDebug(KRDC) << "# Plugin " << info.name() << " found, however it's not activated, skipping..."; continue; } } } RemoteViewFactory *MainWindow::createPluginFromInfo(const KPluginInfo &info) { - RemoteViewFactory *plugin = 0; + RemoteViewFactory *plugin = nullptr; KPluginLoader loader(info.libraryPath()); KPluginFactory *factory = loader.factory(); if (factory) { plugin = factory->create(); } return plugin; } void MainWindow::restoreOpenSessions() { const QStringList list = Settings::openSessions(); QListIterator it(list); while (it.hasNext()) { newConnection(QUrl(it.next())); } } QUrl MainWindow::getInputUrl() { QString userInput = m_addressInput->text(); qCDebug(KRDC) << "input url " << userInput; // percent encode usernames so QUrl can parse it int lastAtIndex = userInput.indexOf(QRegExp(QStringLiteral("@[^@]+$"))); if (lastAtIndex >0) { userInput = QString::fromLatin1(QUrl::toPercentEncoding(userInput.left(lastAtIndex))) + userInput.mid(lastAtIndex); qCDebug(KRDC) << "input url " << userInput; } return QUrl(m_protocolInput->currentText() + QStringLiteral("://") + userInput); } void MainWindow::newConnection(const QUrl &newUrl, bool switchFullscreenWhenConnected, const QString &tabName) { m_switchFullscreenWhenConnected = switchFullscreenWhenConnected; const QUrl url = newUrl.isEmpty() ? getInputUrl() : newUrl; if (!url.isValid() || (url.host().isEmpty() && url.port() < 0) || (!url.path().isEmpty() && url.path() != QStringLiteral("/"))) { KMessageBox::error(this, i18n("The entered address does not have the required form.\n Syntax: [username@]host[:port]"), i18n("Malformed URL")); return; } if (m_protocolInput && m_addressInput) { int index = m_protocolInput->findText(url.scheme()); if (index>=0) m_protocolInput->setCurrentIndex(index); m_addressInput->setText(url.authority()); } - RemoteView *view = 0; + RemoteView *view = nullptr; KConfigGroup configGroup = Settings::self()->config()->group(QStringLiteral("hostpreferences")).group(url.toDisplayString(QUrl::StripTrailingSlash)); foreach(RemoteViewFactory *factory, m_remoteViewFactories) { if (factory->supportsUrl(url)) { view = factory->createView(this, url, configGroup); qCDebug(KRDC) << "Found plugin to handle url (" << url.url() << "): " << view->metaObject()->className(); break; } } if (!view) { KMessageBox::error(this, i18n("The entered address cannot be handled."), i18n("Unusable URL")); return; } // Configure the view HostPreferences* prefs = view->hostPreferences(); // if the user press cancel if (! prefs->showDialogIfNeeded(this)) return; view->showDotCursor(prefs->showLocalCursor() ? RemoteView::CursorOn : RemoteView::CursorOff); view->setViewOnly(prefs->viewOnly()); if (! switchFullscreenWhenConnected) view->enableScaling(prefs->windowedScale()); connect(view, SIGNAL(framebufferSizeChanged(int,int)), this, SLOT(resizeTabWidget(int,int))); connect(view, SIGNAL(statusChanged(RemoteView::RemoteStatus)), this, SLOT(statusChanged(RemoteView::RemoteStatus))); connect(view, SIGNAL(disconnected()), this, SLOT(disconnectHost())); view->winId(); // native widget workaround for bug 253365 QScrollArea *scrollArea = createScrollArea(m_tabWidget, view); const int indexOfNewConnectionWidget = m_tabWidget->indexOf(m_newConnectionWidget); if (indexOfNewConnectionWidget >= 0) m_tabWidget->removeTab(indexOfNewConnectionWidget); const int newIndex = m_tabWidget->addTab(scrollArea, QIcon::fromTheme(QStringLiteral("krdc")), tabName.isEmpty() ? url.toDisplayString(QUrl::StripTrailingSlash) : tabName); m_tabWidget->setCurrentIndex(newIndex); m_remoteViewMap.insert(m_tabWidget->widget(newIndex), view); tabChanged(newIndex); // force to update m_currentRemoteView (tabChanged is not emitted when start page has been disabled) view->start(); } void MainWindow::openFromRemoteDesktopsModel(const QModelIndex &index) { const QString urlString = index.data(10001).toString(); const QString nameString = index.data(10003).toString(); if (!urlString.isEmpty()) { const QUrl url(urlString); // first check if url has already been opened; in case show the tab foreach (QWidget *widget, m_remoteViewMap.keys()) { if (m_remoteViewMap.value(widget)->url() == url) { m_tabWidget->setCurrentWidget(widget); return; } } newConnection(url, false, nameString); } } void MainWindow::selectFromRemoteDesktopsModel(const QModelIndex &index) { const QString urlString = index.data(10001).toString(); if (!urlString.isEmpty() && m_protocolInput && m_addressInput) { const QUrl url(urlString); m_addressInput->setText(url.authority()); int index = m_protocolInput->findText(url.scheme()); if (index>=0) m_protocolInput->setCurrentIndex(index); } } void MainWindow::resizeTabWidget(int w, int h) { qCDebug(KRDC) << "tabwidget resize, view size: w: " << w << ", h: " << h; if (m_fullscreenWindow) { qCDebug(KRDC) << "in fullscreen mode, refusing to resize"; return; } const QSize viewSize = QSize(w,h); QDesktopWidget *desktop = QApplication::desktop(); if (Settings::fullscreenOnConnect()) { int currentScreen = desktop->screenNumber(this); const QSize screenSize = desktop->screenGeometry(currentScreen).size(); if (screenSize == viewSize) { qCDebug(KRDC) << "screen size equal to target view size -> switch to fullscreen mode"; switchFullscreen(); return; } } if (Settings::resizeOnConnect()) { QWidget* currentWidget = m_tabWidget->currentWidget(); const QSize newWindowSize = size() - currentWidget->frameSize() + viewSize; const QSize desktopSize = desktop->availableGeometry().size(); qCDebug(KRDC) << "new window size: " << newWindowSize << " available space:" << desktopSize; if ((newWindowSize.width() >= desktopSize.width()) || (newWindowSize.height() >= desktopSize.height())) { qCDebug(KRDC) << "remote desktop needs more space than available -> show window maximized"; setWindowState(windowState() | Qt::WindowMaximized); return; } setWindowState(windowState() & ~ Qt::WindowMaximized); resize(newWindowSize); } } void MainWindow::statusChanged(RemoteView::RemoteStatus status) { qCDebug(KRDC) << status; // the remoteview is already deleted, so don't show it; otherwise it would crash if (status == RemoteView::Disconnecting || status == RemoteView::Disconnected) return; RemoteView *view = qobject_cast(QObject::sender()); const QString host = view->host(); QString iconName = QStringLiteral("krdc"); QString message; switch (status) { case RemoteView::Connecting: iconName = QStringLiteral("network-connect"); message = i18n("Connecting to %1", host); break; case RemoteView::Authenticating: iconName = QStringLiteral("dialog-password"); message = i18n("Authenticating at %1", host); break; case RemoteView::Preparing: iconName = QStringLiteral("view-history"); message = i18n("Preparing connection to %1", host); break; case RemoteView::Connected: iconName = QStringLiteral("krdc"); message = i18n("Connected to %1", host); if (view->grabAllKeys() != view->hostPreferences()->grabAllKeys()) { view->setGrabAllKeys(view->hostPreferences()->grabAllKeys()); updateActionStatus(); } // when started with command line fullscreen argument if (m_switchFullscreenWhenConnected) { m_switchFullscreenWhenConnected = false; switchFullscreen(); } if (Settings::rememberHistory()) { m_bookmarkManager->addHistoryBookmark(view); } break; default: break; } m_tabWidget->setTabIcon(m_tabWidget->indexOf(view), QIcon::fromTheme(iconName)); if (Settings::showStatusBar()) statusBar()->showMessage(message); } void MainWindow::takeScreenshot() { const QPixmap snapshot = currentRemoteView()->takeScreenshot(); QApplication::clipboard()->setPixmap(snapshot); } void MainWindow::switchFullscreen() { qCDebug(KRDC); if (m_fullscreenWindow) { // Leaving full screen mode - m_fullscreenWindow->setWindowState(0); + m_fullscreenWindow->setWindowState(nullptr); m_fullscreenWindow->hide(); m_tabWidget->tabBar()->setHidden(m_tabWidget->count() <= 1 && !Settings::showTabBar()); m_tabWidget->setDocumentMode(false); setCentralWidget(m_tabWidget); show(); restoreGeometry(m_mainWindowGeometry); if (m_systemTrayIcon) m_systemTrayIcon->setAssociatedWidget(this); foreach (RemoteView * view, m_remoteViewMap.values()) { view->enableScaling(view->hostPreferences()->windowedScale()); } if (m_toolBar) { m_toolBar->hideAndDestroy(); m_toolBar->deleteLater(); - m_toolBar = 0; + m_toolBar = nullptr; } actionCollection()->action(QStringLiteral("switch_fullscreen"))->setIcon(QIcon::fromTheme(QStringLiteral("view-fullscreen"))); actionCollection()->action(QStringLiteral("switch_fullscreen"))->setText(i18n("Switch to Full Screen Mode")); actionCollection()->action(QStringLiteral("switch_fullscreen"))->setIconText(i18n("Full Screen")); m_fullscreenWindow->deleteLater(); - m_fullscreenWindow = 0; + m_fullscreenWindow = nullptr; } else { // Entering full screen mode m_fullscreenWindow = new QWidget(this, Qt::Window); m_fullscreenWindow->setWindowTitle(i18nc("window title when in full screen mode (for example displayed in tasklist)", "KDE Remote Desktop Client (Full Screen)")); m_mainWindowGeometry = saveGeometry(); m_tabWidget->tabBar()->hide(); m_tabWidget->setDocumentMode(true); foreach(RemoteView *currentView, m_remoteViewMap) { currentView->enableScaling(currentView->hostPreferences()->fullscreenScale()); } QVBoxLayout *fullscreenLayout = new QVBoxLayout(m_fullscreenWindow); fullscreenLayout->setContentsMargins(QMargins(0, 0, 0, 0)); fullscreenLayout->addWidget(m_tabWidget); KToggleFullScreenAction::setFullScreen(m_fullscreenWindow, true); MinimizePixel *minimizePixel = new MinimizePixel(m_fullscreenWindow); minimizePixel->winId(); // force it to be a native widget (prevents problem with QX11EmbedContainer) connect(minimizePixel, SIGNAL(rightClicked()), m_fullscreenWindow, SLOT(showMinimized())); m_fullscreenWindow->installEventFilter(this); m_fullscreenWindow->show(); hide(); // hide after showing the new window so it stays on the same screen if (m_systemTrayIcon) m_systemTrayIcon->setAssociatedWidget(m_fullscreenWindow); actionCollection()->action(QStringLiteral("switch_fullscreen"))->setIcon(QIcon::fromTheme(QStringLiteral("view-restore"))); actionCollection()->action(QStringLiteral("switch_fullscreen"))->setText(i18n("Switch to Window Mode")); actionCollection()->action(QStringLiteral("switch_fullscreen"))->setIconText(i18n("Window Mode")); showRemoteViewToolbar(); } if (m_tabWidget->currentWidget() == m_newConnectionWidget) { m_addressInput->setFocus(); } } QScrollArea *MainWindow::createScrollArea(QWidget *parent, RemoteView *remoteView) { RemoteViewScrollArea *scrollArea = new RemoteViewScrollArea(parent); scrollArea->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); connect(scrollArea, SIGNAL(resized(int,int)), remoteView, SLOT(scaleResize(int,int))); QPalette palette = scrollArea->palette(); palette.setColor(QPalette::Background, Settings::backgroundColor()); scrollArea->setPalette(palette); scrollArea->setFrameStyle(QFrame::NoFrame); scrollArea->setAutoFillBackground(true); scrollArea->setWidget(remoteView); return scrollArea; } void MainWindow::disconnectHost() { qCDebug(KRDC); RemoteView *view = qobject_cast(QObject::sender()); QWidget *widgetToDelete; if (view) { widgetToDelete = (QWidget*) view->parent()->parent(); m_remoteViewMap.remove(m_remoteViewMap.key(view)); } else { widgetToDelete = m_tabWidget->currentWidget(); view = currentRemoteView(); m_remoteViewMap.remove(m_remoteViewMap.key(view)); } saveHostPrefs(view); view->startQuitting(); // some deconstructors can't properly quit, so quit early m_tabWidget->removePage(widgetToDelete); widgetToDelete->deleteLater(); // if closing the last connection, create new connection tab if (m_tabWidget->count() == 0) { newConnectionPage(false); } // if the newConnectionWidget is the only tab and we are fullscreen, switch to window mode if (m_fullscreenWindow && m_tabWidget->count() == 1 && m_tabWidget->currentWidget() == m_newConnectionWidget) { switchFullscreen(); } } void MainWindow::closeTab(int index) { if (index == -1) { return; } QWidget *widget = m_tabWidget->widget(index); bool isNewConnectionPage = widget == m_newConnectionWidget; if (!isNewConnectionPage) { RemoteView *view = m_remoteViewMap.value(widget); m_remoteViewMap.remove(m_remoteViewMap.key(view)); view->startQuitting(); widget->deleteLater(); } m_tabWidget->removePage(widget); // if closing the last connection, create new connection tab if (m_tabWidget->count() == 0) { newConnectionPage(false); } // if the newConnectionWidget is the only tab and we are fullscreen, switch to window mode if (m_fullscreenWindow && m_tabWidget->count() == 1 && m_tabWidget->currentWidget() == m_newConnectionWidget) { switchFullscreen(); } } void MainWindow::openTabSettings(int index) { if (index == -1) { newConnectionPage(); return; } QWidget *widget = m_tabWidget->widget(index); RemoteViewScrollArea *scrollArea = qobject_cast(widget); if (!scrollArea) return; RemoteView *view = qobject_cast(scrollArea->widget()); if (!view) return; const QString url = view->url().url(); qCDebug(KRDC) << url; showSettingsDialog(url); } void MainWindow::showSettingsDialog(const QString &url) { - HostPreferences *prefs = 0; + HostPreferences *prefs = nullptr; foreach(RemoteViewFactory *factory, remoteViewFactoriesList()) { if (factory->supportsUrl(QUrl(url))) { prefs = factory->createHostPreferences(Settings::self()->config()->group(QStringLiteral("hostpreferences")).group(url), this); if (prefs) { qCDebug(KRDC) << "Found plugin to handle url (" << url << "): " << prefs->metaObject()->className(); } else { qCDebug(KRDC) << "Found plugin to handle url (" << url << "), but plugin does not provide preferences"; } } } if (prefs) { prefs->setShownWhileConnected(true); prefs->showDialog(this); } else { KMessageBox::error(this, i18n("The selected host cannot be handled."), i18n("Unusable URL")); } } void MainWindow::showConnectionContextMenu(const QPoint &pos) { // QTableView does not take headers into account when it does mapToGlobal(), so calculate the offset QPoint offset = QPoint(m_newConnectionTableView->verticalHeader()->size().width(), m_newConnectionTableView->horizontalHeader()->size().height()); QModelIndex index = m_newConnectionTableView->indexAt(pos); if (!index.isValid()) return; const QString url = index.data(10001).toString(); const QString title = index.model()->index(index.row(), RemoteDesktopsModel::Title).data(Qt::DisplayRole).toString(); const QString source = index.model()->index(index.row(), RemoteDesktopsModel::Source).data(Qt::DisplayRole).toString(); QMenu *menu = new QMenu(url, m_newConnectionTableView); QAction *connectAction = menu->addAction(QIcon::fromTheme(QStringLiteral("network-connect")), i18n("Connect")); QAction *renameAction = menu->addAction(QIcon::fromTheme(QStringLiteral("edit-rename")), i18n("Rename")); QAction *settingsAction = menu->addAction(QIcon::fromTheme(QStringLiteral("configure")), i18n("Settings")); QAction *deleteAction = menu->addAction(QIcon::fromTheme(QStringLiteral("edit-delete")), i18n("Delete")); // not very clean, but it works, if (!(source == i18nc("Where each displayed link comes from", "Bookmarks") || source == i18nc("Where each displayed link comes from", "History"))) { renameAction->setEnabled(false); deleteAction->setEnabled(false); } QAction *selectedAction = menu->exec(m_newConnectionTableView->mapToGlobal(pos + offset)); if (selectedAction == connectAction) { openFromRemoteDesktopsModel(index); } else if (selectedAction == renameAction) { //TODO: use inline editor if possible bool ok = false; const QString newTitle = QInputDialog::getText(this, i18n("Rename %1", title), i18n("Rename %1 to", title), QLineEdit::EchoMode::Normal, title, &ok); if (ok && !newTitle.isEmpty()) { BookmarkManager::updateTitle(m_bookmarkManager->getManager(), url, newTitle); } } else if (selectedAction == settingsAction) { showSettingsDialog(url); } else if (selectedAction == deleteAction) { if (KMessageBox::warningContinueCancel(this, i18n("Are you sure you want to delete %1?", url), i18n("Delete %1", title), KStandardGuiItem::del()) == KMessageBox::Continue) { BookmarkManager::removeByUrl(m_bookmarkManager->getManager(), url); } } menu->deleteLater(); } void MainWindow::tabContextMenu(const QPoint &point) { int index = m_tabWidget->tabBar()->tabAt(point); QWidget *widget = m_tabWidget->widget(index); RemoteViewScrollArea *scrollArea = qobject_cast(widget); if (!scrollArea) return; RemoteView *view = qobject_cast(scrollArea->widget()); if (!view) return; const QString url = view->url().toDisplayString(QUrl::StripTrailingSlash); qCDebug(KRDC) << url; QMenu *menu = new QMenu(url, this); QAction *bookmarkAction = menu->addAction(QIcon::fromTheme(QStringLiteral("bookmark-new")), i18n("Add Bookmark")); QAction *closeAction = menu->addAction(QIcon::fromTheme(QStringLiteral("tab-close")), i18n("Close Tab")); QAction *selectedAction = menu->exec(QCursor::pos()); if (selectedAction) { if (selectedAction == closeAction) { closeTab(m_tabWidget->indexOf(widget)); } else if (selectedAction == bookmarkAction) { m_bookmarkManager->addManualBookmark(view->url(), url); } } menu->deleteLater(); } void MainWindow::showLocalCursor(bool showLocalCursor) { qCDebug(KRDC) << showLocalCursor; RemoteView* view = currentRemoteView(); view->showDotCursor(showLocalCursor ? RemoteView::CursorOn : RemoteView::CursorOff); view->hostPreferences()->setShowLocalCursor(showLocalCursor); saveHostPrefs(view); } void MainWindow::viewOnly(bool viewOnly) { qCDebug(KRDC) << viewOnly; RemoteView* view = currentRemoteView(); view->setViewOnly(viewOnly); view->hostPreferences()->setViewOnly(viewOnly); saveHostPrefs(view); } void MainWindow::grabAllKeys(bool grabAllKeys) { qCDebug(KRDC); RemoteView* view = currentRemoteView(); view->setGrabAllKeys(grabAllKeys); view->hostPreferences()->setGrabAllKeys(grabAllKeys); saveHostPrefs(view); } void MainWindow::scale(bool scale) { qCDebug(KRDC); RemoteView* view = currentRemoteView(); view->enableScaling(scale); if (m_fullscreenWindow) view->hostPreferences()->setFullscreenScale(scale); else view->hostPreferences()->setWindowedScale(scale); saveHostPrefs(view); } void MainWindow::showRemoteViewToolbar() { qCDebug(KRDC); if (!m_toolBar) { m_toolBar = new FloatingToolBar(m_fullscreenWindow, m_fullscreenWindow); m_toolBar->winId(); // force it to be a native widget (prevents problem with QX11EmbedContainer) m_toolBar->setSide(FloatingToolBar::Top); KComboBox *sessionComboBox = new KComboBox(m_toolBar); sessionComboBox->setStyleSheet(QStringLiteral("QComboBox:!editable{background:transparent;}")); sessionComboBox->setModel(m_tabWidget->getModel()); sessionComboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents); sessionComboBox->setCurrentIndex(m_tabWidget->currentIndex()); connect(sessionComboBox, SIGNAL(activated(int)), m_tabWidget, SLOT(setCurrentIndex(int))); connect(m_tabWidget, SIGNAL(currentChanged(int)), sessionComboBox, SLOT(setCurrentIndex(int))); m_toolBar->addWidget(sessionComboBox); QToolBar *buttonBox = new QToolBar(m_toolBar); buttonBox->addAction(actionCollection()->action(QStringLiteral("new_connection"))); buttonBox->addAction(actionCollection()->action(QStringLiteral("switch_fullscreen"))); QAction *minimizeAction = new QAction(m_toolBar); minimizeAction->setIcon(QIcon::fromTheme(QStringLiteral("go-down"))); minimizeAction->setText(i18n("Minimize Full Screen Window")); connect(minimizeAction, SIGNAL(triggered()), m_fullscreenWindow, SLOT(showMinimized())); buttonBox->addAction(minimizeAction); buttonBox->addAction(actionCollection()->action(QStringLiteral("take_screenshot"))); buttonBox->addAction(actionCollection()->action(QStringLiteral("view_only"))); buttonBox->addAction(actionCollection()->action(QStringLiteral("show_local_cursor"))); buttonBox->addAction(actionCollection()->action(QStringLiteral("grab_all_keys"))); buttonBox->addAction(actionCollection()->action(QStringLiteral("scale"))); buttonBox->addAction(actionCollection()->action(QStringLiteral("disconnect"))); buttonBox->addAction(actionCollection()->action(QStringLiteral("file_quit"))); QAction *stickToolBarAction = new QAction(m_toolBar); stickToolBarAction->setCheckable(true); stickToolBarAction->setIcon(QIcon::fromTheme(QStringLiteral("object-locked"))); stickToolBarAction->setText(i18n("Stick Toolbar")); connect(stickToolBarAction, SIGNAL(triggered(bool)), m_toolBar, SLOT(setSticky(bool))); buttonBox->addAction(stickToolBarAction); m_toolBar->addWidget(buttonBox); } } void setActionStatus(QAction* action, bool enabled, bool visible, bool checked) { action->setEnabled(enabled); action->setVisible(visible); action->setChecked(checked); } void MainWindow::updateActionStatus() { qCDebug(KRDC) << m_tabWidget->currentIndex(); bool enabled = true; if (m_tabWidget->currentWidget() == m_newConnectionWidget) enabled = false; - RemoteView* view = (m_currentRemoteView >= 0 && enabled) ? currentRemoteView() : 0; + RemoteView* view = (m_currentRemoteView >= 0 && enabled) ? currentRemoteView() : nullptr; actionCollection()->action(QStringLiteral("take_screenshot"))->setEnabled(enabled); actionCollection()->action(QStringLiteral("disconnect"))->setEnabled(enabled); setActionStatus(actionCollection()->action(QStringLiteral("view_only")), enabled, view ? view->supportsViewOnly() : false, view ? view->viewOnly() : false); setActionStatus(actionCollection()->action(QStringLiteral("show_local_cursor")), enabled, view ? view->supportsLocalCursor() : false, view ? view->dotCursorState() == RemoteView::CursorOn : false); setActionStatus(actionCollection()->action(QStringLiteral("scale")), enabled, view ? view->supportsScaling() : false, view ? view->scaling() : false); setActionStatus(actionCollection()->action(QStringLiteral("grab_all_keys")), enabled, enabled, view ? view->grabAllKeys() : false); } void MainWindow::preferences() { // An instance of your dialog could be already created and could be // cached, in which case you want to display the cached dialog // instead of creating another one if (PreferencesDialog::showDialog(QStringLiteral("preferences"))) return; // KConfigDialog didn't find an instance of this dialog, so lets // create it: PreferencesDialog *dialog = new PreferencesDialog(this, Settings::self()); // User edited the configuration - update your local copies of the // configuration data connect(dialog, SIGNAL(settingsChanged(QString)), this, SLOT(updateConfiguration())); dialog->show(); } void MainWindow::updateConfiguration() { if (!Settings::showStatusBar()) statusBar()->deleteLater(); else statusBar()->showMessage(QStringLiteral("")); // force creation of statusbar m_tabWidget->tabBar()->setHidden((m_tabWidget->count() <= 1 && !Settings::showTabBar()) || m_fullscreenWindow); m_tabWidget->setTabPosition((QTabWidget::TabPosition) Settings::tabPosition()); m_tabWidget->setTabsClosable(Settings::tabCloseButton()); disconnect(m_tabWidget, SIGNAL(mouseMiddleClick(int)), this, SLOT(closeTab(int))); // just be sure it is not connected twice if (Settings::tabMiddleClick()) connect(m_tabWidget, SIGNAL(mouseMiddleClick(int)), SLOT(closeTab(int))); if (Settings::systemTrayIcon() && !m_systemTrayIcon) { m_systemTrayIcon = new SystemTrayIcon(this); if(m_fullscreenWindow) m_systemTrayIcon->setAssociatedWidget(m_fullscreenWindow); } else if (m_systemTrayIcon) { delete m_systemTrayIcon; - m_systemTrayIcon = 0; + m_systemTrayIcon = nullptr; } // update the scroll areas background color for (int i = 0; i < m_tabWidget->count(); ++i) { QPalette palette = m_tabWidget->widget(i)->palette(); palette.setColor(QPalette::Dark, Settings::backgroundColor()); m_tabWidget->widget(i)->setPalette(palette); } // Send update configuration message to all views foreach (RemoteView *view, m_remoteViewMap.values()) { view->updateConfiguration(); } } void MainWindow::quit(bool systemEvent) { const bool haveRemoteConnections = !m_remoteViewMap.isEmpty(); if (systemEvent || !haveRemoteConnections || KMessageBox::warningContinueCancel(this, i18n("Are you sure you want to quit the KDE Remote Desktop Client?"), i18n("Confirm Quit"), KStandardGuiItem::quit(), KStandardGuiItem::cancel(), QStringLiteral("DoNotAskBeforeExit")) == KMessageBox::Continue) { if (Settings::rememberSessions()) { // remember open remote views for next startup QStringList list; foreach (RemoteView *view, m_remoteViewMap.values()) { qCDebug(KRDC) << view->url(); list.append(view->url().toDisplayString(QUrl::StripTrailingSlash)); } Settings::setOpenSessions(list); } saveHostPrefs(); foreach (RemoteView *view, m_remoteViewMap.values()) { view->startQuitting(); } Settings::self()->save(); qApp->quit(); } } void MainWindow::configureNotifications() { KNotifyConfigWidget::configure(this); } void MainWindow::showMenubar() { if (m_menubarAction->isChecked()) menuBar()->show(); else menuBar()->hide(); } bool MainWindow::eventFilter(QObject *obj, QEvent *event) { // check for close events from the fullscreen window. if (obj == m_fullscreenWindow && event->type() == QEvent::Close) { quit(true); } // allow other events to pass through. return QObject::eventFilter(obj, event); } void MainWindow::closeEvent(QCloseEvent *event) { if (event->spontaneous()) { // Returns true if the event originated outside the application (a system event); otherwise returns false. event->ignore(); if (Settings::systemTrayIcon()) { hide(); // just hide the mainwindow, keep it in systemtray } else { quit(); } } else { quit(true); } } void MainWindow::saveProperties(KConfigGroup &group) { qCDebug(KRDC); KMainWindow::saveProperties(group); saveHostPrefs(); } void MainWindow::saveHostPrefs() { foreach (RemoteView *view, m_remoteViewMap.values()) { saveHostPrefs(view); } } void MainWindow::saveHostPrefs(RemoteView* view) { // should saving this be a user option? if (view && view->scaling()) { QSize viewSize = m_tabWidget->currentWidget()->size(); qCDebug(KRDC) << "saving window size:" << viewSize; view->hostPreferences()->setWidth(viewSize.width()); view->hostPreferences()->setHeight(viewSize.height()); } Settings::self()->config()->sync(); } void MainWindow::tabChanged(int index) { qCDebug(KRDC) << index; m_tabWidget->tabBar()->setHidden((m_tabWidget->count() <= 1 && !Settings::showTabBar()) || m_fullscreenWindow); m_currentRemoteView = index; if (m_tabWidget->currentWidget() == m_newConnectionWidget) { m_currentRemoteView = -1; if(m_addressInput) m_addressInput->setFocus(); } const QString tabTitle = m_tabWidget->tabText(index).remove(QLatin1Char('&')); setCaption(tabTitle == i18n("New Connection") ? QString() : tabTitle); updateActionStatus(); } QWidget* MainWindow::newConnectionWidget() { if (m_newConnectionWidget) return m_newConnectionWidget; m_newConnectionWidget = new QWidget(this); QVBoxLayout *startLayout = new QVBoxLayout(m_newConnectionWidget); startLayout->setContentsMargins(QMargins(8, 12, 8, 4)); QLabel *headerLabel = new QLabel(m_newConnectionWidget); headerLabel->setText(i18n("

KDE Remote Desktop Client


Enter or select the address of the desktop you would like to connect to.")); QLabel *headerIconLabel = new QLabel(m_newConnectionWidget); headerIconLabel->setPixmap(QIcon::fromTheme(QStringLiteral("krdc")).pixmap(80)); QHBoxLayout *headerLayout = new QHBoxLayout; headerLayout->addWidget(headerLabel, 1, Qt::AlignTop); headerLayout->addWidget(headerIconLabel); startLayout->addLayout(headerLayout); QSortFilterProxyModel *remoteDesktopsModelProxy = new QSortFilterProxyModel(this); remoteDesktopsModelProxy->setSourceModel(m_remoteDesktopsModel); remoteDesktopsModelProxy->setFilterCaseSensitivity(Qt::CaseInsensitive); remoteDesktopsModelProxy->setFilterRole(10002); { QHBoxLayout *connectLayout = new QHBoxLayout; QLabel *addressLabel = new QLabel(i18n("Connect to:"), m_newConnectionWidget); m_protocolInput = new KComboBox(m_newConnectionWidget); m_addressInput = new KLineEdit(m_newConnectionWidget); m_addressInput->setClearButtonShown(true); m_addressInput->setPlaceholderText(i18n("Type here to connect to an address and filter the list.")); connect(m_addressInput, SIGNAL(textChanged(QString)), remoteDesktopsModelProxy, SLOT(setFilterFixedString(QString))); foreach(RemoteViewFactory *factory, m_remoteViewFactories) { m_protocolInput->addItem(factory->scheme()); } connect(m_addressInput, SIGNAL(returnPressed()), SLOT(newConnection())); m_addressInput->setToolTip(i18n("Type an IP or DNS Name here. Clear the line to get a list of connection methods.")); QPushButton *connectButton = new QPushButton(m_newConnectionWidget); connectButton->setToolTip(i18n("Goto Address")); connectButton->setIcon(QIcon::fromTheme(QStringLiteral("go-jump-locationbar"))); connect(connectButton, SIGNAL(clicked()), SLOT(newConnection())); connectLayout->addWidget(addressLabel); connectLayout->addWidget(m_protocolInput); connectLayout->addWidget(m_addressInput, 1); connectLayout->addWidget(connectButton); connectLayout->setContentsMargins(QMargins(0, 6, 0, 10)); startLayout->addLayout(connectLayout); } { m_newConnectionTableView = new QTableView(m_newConnectionWidget); m_newConnectionTableView->setModel(remoteDesktopsModelProxy); // set up the view so it looks nice m_newConnectionTableView->setItemDelegate(new ConnectionDelegate(m_newConnectionTableView)); m_newConnectionTableView->setShowGrid(false); m_newConnectionTableView->setSelectionMode(QAbstractItemView::NoSelection); m_newConnectionTableView->verticalHeader()->hide(); m_newConnectionTableView->verticalHeader()->setDefaultSectionSize( m_newConnectionTableView->fontMetrics().height() + 3); m_newConnectionTableView->horizontalHeader()->setStretchLastSection(true); m_newConnectionTableView->setAlternatingRowColors(true); // set up sorting and actions (double click open, right click custom menu) m_newConnectionTableView->setSortingEnabled(true); m_newConnectionTableView->sortByColumn(Settings::connectionListSortColumn(), Qt::SortOrder(Settings::connectionListSortOrder())); m_newConnectionTableView->resizeColumnsToContents(); connect(m_newConnectionTableView->horizontalHeader(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), SLOT(saveConnectionListSort(int,Qt::SortOrder))); connect(m_newConnectionTableView, SIGNAL(doubleClicked(QModelIndex)), SLOT(openFromRemoteDesktopsModel(QModelIndex))); // useful to edit similar address connect(m_newConnectionTableView, SIGNAL(clicked(QModelIndex)), SLOT(selectFromRemoteDesktopsModel(QModelIndex))); m_newConnectionTableView->setContextMenuPolicy(Qt::CustomContextMenu); connect(m_newConnectionTableView, SIGNAL(customContextMenuRequested(QPoint)), SLOT(showConnectionContextMenu(QPoint))); startLayout->addWidget(m_newConnectionTableView); } return m_newConnectionWidget; } void MainWindow::saveConnectionListSort(const int logicalindex, const Qt::SortOrder order) { Settings::setConnectionListSortColumn(logicalindex); Settings::setConnectionListSortOrder(order); Settings::self()->save(); } void MainWindow::newConnectionPage(bool clearInput) { const int indexOfNewConnectionWidget = m_tabWidget->indexOf(m_newConnectionWidget); if (indexOfNewConnectionWidget >= 0) m_tabWidget->setCurrentIndex(indexOfNewConnectionWidget); else { const int index = m_tabWidget->addTab(newConnectionWidget(), i18n("New Connection")); m_tabWidget->setCurrentIndex(index); } if(clearInput) { m_addressInput->clear(); } else { m_addressInput->selectAll(); } m_addressInput->setFocus(); } QMap MainWindow::remoteViewList() const { return m_remoteViewMap; } QList MainWindow::remoteViewFactoriesList() const { return m_remoteViewFactories.values(); } RemoteView* MainWindow::currentRemoteView() const { if (m_currentRemoteView >= 0) { return m_remoteViewMap.value(m_tabWidget->widget(m_currentRemoteView)); } else { - return 0; + return nullptr; } } void MainWindow::createDockWidget() { QDockWidget *remoteDesktopsDockWidget = new QDockWidget(this); QWidget *remoteDesktopsDockLayoutWidget = new QWidget(remoteDesktopsDockWidget); QVBoxLayout *remoteDesktopsDockLayout = new QVBoxLayout(remoteDesktopsDockLayoutWidget); remoteDesktopsDockWidget->setObjectName(QStringLiteral("remoteDesktopsDockWidget")); // required for saving position / state remoteDesktopsDockWidget->setWindowTitle(i18n("Remote Desktops")); QFontMetrics fontMetrics(remoteDesktopsDockWidget->font()); remoteDesktopsDockWidget->setMinimumWidth(fontMetrics.width(QStringLiteral("vnc://192.168.100.100:6000"))); actionCollection()->addAction(QStringLiteral("remote_desktop_dockwidget"), remoteDesktopsDockWidget->toggleViewAction()); m_dockWidgetTableView = new QTableView(remoteDesktopsDockLayoutWidget); m_remoteDesktopsModel = new RemoteDesktopsModel(this, m_bookmarkManager->getManager()); QSortFilterProxyModel *remoteDesktopsModelProxy = new QSortFilterProxyModel(this); remoteDesktopsModelProxy->setSourceModel(m_remoteDesktopsModel); remoteDesktopsModelProxy->setFilterCaseSensitivity(Qt::CaseInsensitive); remoteDesktopsModelProxy->setFilterRole(10002); m_dockWidgetTableView->setModel(remoteDesktopsModelProxy); m_dockWidgetTableView->setShowGrid(false); m_dockWidgetTableView->verticalHeader()->hide(); m_dockWidgetTableView->verticalHeader()->setDefaultSectionSize( m_dockWidgetTableView->fontMetrics().height() + 2); m_dockWidgetTableView->horizontalHeader()->hide(); m_dockWidgetTableView->horizontalHeader()->setStretchLastSection(true); // hide all columns, then show the one we want for (int i=0; i < remoteDesktopsModelProxy->columnCount(); i++) { m_dockWidgetTableView->hideColumn(i); } m_dockWidgetTableView->showColumn(RemoteDesktopsModel::Title); m_dockWidgetTableView->sortByColumn(RemoteDesktopsModel::Title, Qt::AscendingOrder); connect(m_dockWidgetTableView, SIGNAL(doubleClicked(QModelIndex)), SLOT(openFromRemoteDesktopsModel(QModelIndex))); KLineEdit *filterLineEdit = new KLineEdit(remoteDesktopsDockLayoutWidget); filterLineEdit->setPlaceholderText(i18n("Filter")); filterLineEdit->setClearButtonShown(true); connect(filterLineEdit, SIGNAL(textChanged(QString)), remoteDesktopsModelProxy, SLOT(setFilterFixedString(QString))); remoteDesktopsDockLayout->addWidget(filterLineEdit); remoteDesktopsDockLayout->addWidget(m_dockWidgetTableView); remoteDesktopsDockWidget->setWidget(remoteDesktopsDockLayoutWidget); addDockWidget(Qt::LeftDockWidgetArea, remoteDesktopsDockWidget); } diff --git a/mainwindow.h b/mainwindow.h index 00fce1f..411f5a4 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -1,183 +1,183 @@ /**************************************************************************** ** ** Copyright (C) 2007 - 2013 Urs Wolfer ** Copyright (C) 2009 - 2010 Tony Murray ** ** This file is part of KDE. ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; see the file COPYING. If not, write to ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ** Boston, MA 02110-1301, USA. ** ****************************************************************************/ #ifndef MAINWINDOW_H #define MAINWINDOW_H #include "remoteview.h" #include "remoteviewfactory.h" #include #include class KComboBox; class KLineEdit; class KPushButton; class KToggleAction; class KTabWidget; class BookmarkManager; class FloatingToolBar; class RemoteDesktopsModel; class RemoteView; class SystemTrayIcon; class TabbedViewWidget; class QScrollArea; class QModelIndex; class QTableView; #ifdef TELEPATHY_SUPPORT class TubesManager; #endif class MainWindow : public KXmlGuiWindow { Q_OBJECT public: - explicit MainWindow(QWidget *parent = 0); + explicit MainWindow(QWidget *parent = nullptr); ~MainWindow() override; QMap remoteViewList() const; QList remoteViewFactoriesList() const; RemoteView* currentRemoteView() const; public Q_SLOTS: void newConnection(const QUrl &newUrl = QUrl(), bool switchFullscreenWhenConnected = false, const QString &tabName = QString()); protected: void closeEvent(QCloseEvent *event) override; bool eventFilter(QObject *obj, QEvent *event) override; // checks for close events on fs window void saveProperties(KConfigGroup &group) override; void saveHostPrefs(); void saveHostPrefs(RemoteView *view); private Q_SLOTS: void restoreOpenSessions(); void quit(bool systemEvent = false); void preferences(); void configureNotifications(); void showMenubar(); void resizeTabWidget(int w, int h); void statusChanged(RemoteView::RemoteStatus status); void showRemoteViewToolbar(); void takeScreenshot(); void switchFullscreen(); void disconnectHost(); void closeTab(int index); void openTabSettings(int index); void tabContextMenu(const QPoint &point); void viewOnly(bool viewOnly); void showLocalCursor(bool showLocalCursor); void grabAllKeys(bool grabAllKeys); void scale(bool scale); void updateActionStatus(); void updateConfiguration(); void tabChanged(int index); QWidget* newConnectionWidget(); void newConnectionPage(bool clearInput = true); void openFromRemoteDesktopsModel(const QModelIndex &index); void selectFromRemoteDesktopsModel(const QModelIndex &index); void createDockWidget(); void showConnectionContextMenu(const QPoint &pos); void saveConnectionListSort(const int logicalindex, const Qt::SortOrder order); private: void setupActions(); void loadAllPlugins(); RemoteViewFactory *createPluginFromInfo(const KPluginInfo &info); void showSettingsDialog(const QString &url); QScrollArea *createScrollArea(QWidget *parent, RemoteView *remoteView); QUrl getInputUrl(); QWidget *m_fullscreenWindow; QByteArray m_mainWindowGeometry; KToggleAction *m_menubarAction; TabbedViewWidget *m_tabWidget; KComboBox *m_protocolInput; KLineEdit *m_addressInput; FloatingToolBar *m_toolBar; BookmarkManager *m_bookmarkManager; QMap m_remoteViewMap; QMap m_remoteViewFactories; int m_currentRemoteView; bool m_switchFullscreenWhenConnected; SystemTrayIcon *m_systemTrayIcon; QTableView *m_dockWidgetTableView; QTableView *m_newConnectionTableView; RemoteDesktopsModel *m_remoteDesktopsModel; QWidget *m_newConnectionWidget; }; #include #include #include class MinimizePixel : public QWidget { Q_OBJECT public: explicit MinimizePixel(QWidget *parent) : QWidget(parent) { setFixedSize(1, 1); move(QApplication::desktop()->screenGeometry().width() - 1, 0); } Q_SIGNALS: void rightClicked(); protected: void mousePressEvent(QMouseEvent *event) override { if (event->button() == Qt::RightButton) emit rightClicked(); } }; #include class RemoteViewScrollArea : public QScrollArea { Q_OBJECT public: explicit RemoteViewScrollArea(QWidget *parent) : QScrollArea(parent) { } Q_SIGNALS: void resized(int w, int h); protected: void resizeEvent(QResizeEvent *event) override { QScrollArea::resizeEvent(event); emit resized(width() - 2*frameWidth(), height() - 2*frameWidth()); } }; #endif diff --git a/rdp/rdphostpreferences.h b/rdp/rdphostpreferences.h index 87c0c94..dff3d89 100644 --- a/rdp/rdphostpreferences.h +++ b/rdp/rdphostpreferences.h @@ -1,72 +1,72 @@ /**************************************************************************** ** ** Copyright (C) 2007 - 2012 Urs Wolfer ** Copyright (C) 2012 AceLan Kao ** ** This file is part of KDE. ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; see the file COPYING. If not, write to ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ** Boston, MA 02110-1301, USA. ** ****************************************************************************/ #ifndef RDPHOSTPREFERENCES_H #define RDPHOSTPREFERENCES_H #include "hostpreferences.h" #include "ui_rdppreferences.h" class RdpHostPreferences : public HostPreferences { Q_OBJECT public: - explicit RdpHostPreferences(KConfigGroup configGroup, QObject *parent = 0); + explicit RdpHostPreferences(KConfigGroup configGroup, QObject *parent = nullptr); ~RdpHostPreferences() override; void setResolution(int resolution); int resolution() const; void setColorDepth(int colorDepth); int colorDepth() const; void setKeyboardLayout(const QString &keyboardLayout); QString keyboardLayout() const; void setSound(int sound); int sound() const; void setSoundSystem(int sound); int soundSystem() const; void setConsole(bool console); bool console() const; void setExtraOptions(const QString &extraOptions); QString extraOptions() const; void setRemoteFX(bool remoteFX); bool remoteFX() const; void setPerformance(int performance); int performance() const; void setShareMedia(const QString &shareMedia); QString shareMedia() const; protected: QWidget* createProtocolSpecificConfigPage() override; void acceptConfig() override; private: Ui::RdpPreferences rdpUi; private Q_SLOTS: void updateWidthHeight(int index); void updateSoundSystem(int index); }; #endif diff --git a/rdp/rdppreferences.h b/rdp/rdppreferences.h index 5a7ac27..92d74e9 100644 --- a/rdp/rdppreferences.h +++ b/rdp/rdppreferences.h @@ -1,44 +1,44 @@ /**************************************************************************** ** ** Copyright (C) 2008 Urs Wolfer ** ** This file is part of KDE. ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; see the file COPYING. If not, write to ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ** Boston, MA 02110-1301, USA. ** ****************************************************************************/ #ifndef RDPPREFERENCES_H #define RDPPREFERENCES_H #include "rdphostpreferences.h" #include class RdpPreferences : public KCModule { Q_OBJECT public: - explicit RdpPreferences(QWidget *parent = 0, const QVariantList &args = QVariantList()); + explicit RdpPreferences(QWidget *parent = nullptr, const QVariantList &args = QVariantList()); ~RdpPreferences() override; void save() override; void load() override; }; #endif // RDPPREFERENCES_H diff --git a/rdp/rdpview.cpp b/rdp/rdpview.cpp index a284f60..bc96021 100644 --- a/rdp/rdpview.cpp +++ b/rdp/rdpview.cpp @@ -1,676 +1,676 @@ /**************************************************************************** ** ** Copyright (C) 2002 Arend van Beelen jr. ** Copyright (C) 2007 - 2012 Urs Wolfer ** Copyright (C) 2012 AceLan Kao ** ** This file is part of KDE. ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; see the file COPYING. If not, write to ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ** Boston, MA 02110-1301, USA. ** ****************************************************************************/ #include "rdpview.h" #include "settings.h" #include "krdc_debug.h" #include #include #include #include #include #include RdpView::RdpView(QWidget *parent, const QUrl &url, KConfigGroup configGroup, const QString &user, const QString &password) : RemoteView(parent), m_user(user), m_password(password), m_quitFlag(false), - m_process(NULL) + m_process(nullptr) { m_url = url; m_host = url.host(); m_port = url.port(); if (m_port <= 0) { m_port = TCP_PORT_RDP; } m_container = new QWindow(); m_containerWidget = QWidget::createWindowContainer(m_container, this); m_container->installEventFilter(this); m_hostPreferences = new RdpHostPreferences(configGroup, this); } RdpView::~RdpView() { startQuitting(); } // filter out key and mouse events to the container if we are view only //FIXME: X11 events are passed to the app before getting caught in the Qt event processing bool RdpView::eventFilter(QObject *obj, QEvent *event) { if (m_viewOnly) { if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease || event->type() == QEvent::MouseButtonDblClick || event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease || event->type() == QEvent::MouseMove) return true; } return RemoteView::eventFilter(obj, event); } QSize RdpView::framebufferSize() { return m_containerWidget->minimumSize(); } QSize RdpView::sizeHint() const { return maximumSize(); } void RdpView::startQuitting() { qCDebug(KRDC) << "About to quit"; m_quitFlag = true; if (m_process) { m_process->terminate(); m_process->waitForFinished(1000); m_container->destroy(); } } bool RdpView::isQuitting() { return m_quitFlag; } bool RdpView::start() { m_containerWidget->show(); if (m_url.userName().isEmpty()) { QString userName; bool ok = false; userName = QInputDialog::getText(this, i18n("Enter Username"), i18n("Please enter the username you would like to use for login."), QLineEdit::Normal, Settings::defaultRdpUserName(), &ok); if (ok) { m_url.setUserName(userName); } } if (!m_url.userName().isEmpty()) { const bool useLdapLogin = Settings::recognizeLdapLogins() && m_url.userName().contains(QLatin1Char('\\')); qCDebug(KRDC) << "Is LDAP login:" << useLdapLogin << m_url.userName(); QString walletPassword = QString(); if (m_hostPreferences->walletSupport()) { walletPassword = readWalletPassword(useLdapLogin); } if (!walletPassword.isNull()) { m_url.setPassword(walletPassword); } else { KPasswordDialog dialog(this); dialog.setPrompt(i18n("Access to the system requires a password.")); if (dialog.exec() == KPasswordDialog::Accepted) { m_url.setPassword(dialog.password()); if (m_hostPreferences->walletSupport()) { saveWalletPassword(dialog.password(), useLdapLogin); } } } } // Check the version of FreeRDP so we can use pre-1.1 switches if needed QProcess *xfreeRDPVersionCheck = new QProcess(this); xfreeRDPVersionCheck->start(QStringLiteral("xfreerdp"), QStringList(QStringLiteral("--version"))); xfreeRDPVersionCheck->waitForFinished(); QString versionOutput = QString::fromUtf8(xfreeRDPVersionCheck->readAllStandardOutput().constData()); xfreeRDPVersionCheck->deleteLater(); m_process = new QProcess(m_container); QStringList arguments; int width, height; if (m_hostPreferences->width() > 0) { width = m_hostPreferences->width(); height = m_hostPreferences->height(); } else { width = this->parentWidget()->size().width(); height = this->parentWidget()->size().height(); } m_containerWidget->setFixedWidth(width); m_containerWidget->setFixedHeight(height); setMaximumSize(width, height); if (versionOutput.contains(QLatin1String(" 1.0"))) { qCDebug(KRDC) << "Use FreeRDP 1.0 compatible arguments"; arguments << QStringLiteral("-g") << QString::number(width) + QLatin1Char('x') + QString::number(height); arguments << QStringLiteral("-k") << keymapToXfreerdp(m_hostPreferences->keyboardLayout()); if (!m_url.userName().isEmpty()) { // if username contains a domain, it needs to be set with another parameter if (m_url.userName().contains(QLatin1Char('\\'))) { const QStringList splittedName = m_url.userName().split(QLatin1Char('\\')); arguments << QStringLiteral("-d") << splittedName.at(0); arguments << QStringLiteral("-u") << splittedName.at(1); } else { arguments << QStringLiteral("-u") << m_url.userName(); } } else { arguments << QStringLiteral("-u") << QStringLiteral(""); } arguments << QStringLiteral("-D"); // request the window has no decorations arguments << QStringLiteral("-X") << QString::number(m_container->winId()); arguments << QStringLiteral("-a") << QString::number((m_hostPreferences->colorDepth() + 1) * 8); switch (m_hostPreferences->sound()) { case 1: arguments << QStringLiteral("-o"); break; case 0: arguments << QStringLiteral("--plugin") << QStringLiteral("rdpsnd"); break; case 2: default: break; } if (!m_hostPreferences->shareMedia().isEmpty()) { QStringList shareMedia; shareMedia << QStringLiteral("--plugin") << QStringLiteral("rdpdr") << QStringLiteral("--data") << QStringLiteral("disk:media:") + m_hostPreferences->shareMedia() << QStringLiteral("--"); arguments += shareMedia; } QString performance; switch (m_hostPreferences->performance()) { case 0: performance = QLatin1Char('m'); break; case 1: performance = QLatin1Char('b'); break; case 2: performance = QLatin1Char('l'); break; default: break; } arguments << QStringLiteral("-x") << performance; if (m_hostPreferences->console()) { arguments << QStringLiteral("-0"); } if (m_hostPreferences->remoteFX()) { arguments << QStringLiteral("--rfx"); } if (!m_hostPreferences->extraOptions().isEmpty()) { const QStringList additionalArguments = KShell::splitArgs(m_hostPreferences->extraOptions()); arguments += additionalArguments; } // krdc has no support for certificate management yet; it would not be possbile to connect to any host: // "The host key for example.com has changed" ... // "Add correct host key in ~/.freerdp/known_hosts to get rid of this message." arguments << QStringLiteral("--ignore-certificate"); // clipboard sharing is activated in KRDC; user can disable it at runtime arguments << QStringLiteral("--plugin") << QStringLiteral("cliprdr"); arguments << QStringLiteral("-t") << QString::number(m_port); arguments << m_host; qCDebug(KRDC) << "Starting xfreerdp with arguments: " << arguments.join(QStringLiteral(" ")); arguments.removeLast(); // host must be last, remove and re-add it after the password if (!m_url.password().isNull()) arguments << QStringLiteral("-p") << m_url.password(); arguments << m_host; } else { qCDebug(KRDC) << "Use FreeRDP 1.1+ compatible arguments"; arguments << QStringLiteral("-decorations"); arguments << QStringLiteral("/w:") + QString::number(width); arguments << QStringLiteral("/h:") + QString::number(height); arguments << QStringLiteral("/kbd:") + keymapToXfreerdp(m_hostPreferences->keyboardLayout()); if (!m_url.userName().isEmpty()) { // if username contains a domain, it needs to be set with another parameter if (m_url.userName().contains(QLatin1Char('\\'))) { const QStringList splittedName = m_url.userName().split(QLatin1Char('\\')); arguments << QStringLiteral("/d:") + splittedName.at(0); arguments << QStringLiteral("/u:") + splittedName.at(1); } else { arguments << QStringLiteral("/u:") + m_url.userName(); } } else { arguments << QStringLiteral("/u:"); } arguments << QStringLiteral("/parent-window:") + QString::number(m_container->winId()); arguments << QStringLiteral("/bpp:") + QString::number((m_hostPreferences->colorDepth() + 1) * 8); arguments << QStringLiteral("/audio-mode:") + QString::number(m_hostPreferences->sound()); switch (m_hostPreferences->soundSystem()) { case 0: arguments << QStringLiteral("/sound:sys:alsa"); break; case 1: arguments << QStringLiteral("/sound:sys:pulse"); break; default: break; } if (!m_hostPreferences->shareMedia().isEmpty()) { QStringList shareMedia; shareMedia << QStringLiteral("/drive:media,") + m_hostPreferences->shareMedia(); arguments += shareMedia; } QString performance; switch (m_hostPreferences->performance()) { case 0: performance = QStringLiteral("modem"); break; case 1: performance = QStringLiteral("broadband"); break; case 2: performance = QStringLiteral("lan"); break; default: break; } arguments << QStringLiteral("/network:") + performance; if (m_hostPreferences->console()) { arguments << QStringLiteral("/admin"); } if (m_hostPreferences->remoteFX()) { arguments << QStringLiteral("/rfx"); } if (!m_hostPreferences->extraOptions().isEmpty()) { const QStringList additionalArguments = KShell::splitArgs(m_hostPreferences->extraOptions()); arguments += additionalArguments; } // krdc has no support for certificate management yet; it would not be possbile to connect to any host: // "The host key for example.com has changed" ... // "Add correct host key in ~/.freerdp/known_hosts to get rid of this message." arguments << QStringLiteral("/cert-ignore"); // clipboard sharing is activated in KRDC; user can disable it at runtime arguments << QStringLiteral("+clipboard"); arguments << QStringLiteral("/port:") + QString::number(m_port); arguments << QStringLiteral("/v:") + m_host; qCDebug(KRDC) << "Starting xfreerdp with arguments: " << arguments.join(QStringLiteral(" ")); //avoid printing the password in debug if (!m_url.password().isNull()) { arguments << QStringLiteral("/p:") + m_url.password(); } } setStatus(Connecting); connect(m_process, SIGNAL(error(QProcess::ProcessError)), SLOT(processError(QProcess::ProcessError))); connect(m_process, SIGNAL(readyReadStandardError()), SLOT(receivedStandardError())); connect(m_process, SIGNAL(readyReadStandardOutput()), SLOT(receivedStandardOutput())); connect(m_process, SIGNAL(finished(int, QProcess::ExitStatus)), SLOT(connectionClosed())); connect(m_process, SIGNAL(started()), SLOT(connectionOpened())); m_process->start(QStringLiteral("xfreerdp"), arguments); return true; } HostPreferences* RdpView::hostPreferences() { return m_hostPreferences; } void RdpView::switchFullscreen(bool on) { if (on == true) { m_container->setKeyboardGrabEnabled(true); } } void RdpView::connectionOpened() { qCDebug(KRDC) << "Connection opened"; const QSize size = QSize(m_container->width(), m_container->height()); qCDebug(KRDC) << "Size hint: " << size.width() << " " << size.height(); setStatus(Connected); setFixedSize(size); resize(size); m_containerWidget->setFixedSize(size); emit framebufferSizeChanged(size.width(), size.height()); emit connected(); setFocus(); } QPixmap RdpView::takeScreenshot() { return QPixmap::grabWindow(m_container->winId()); } void RdpView::connectionClosed() { connectionClosed(NormalClose); } void RdpView::connectionClosed(CloseType closeType) { if (m_quitFlag && closeType != ForceClose) { return; } emit disconnected(); setStatus(Disconnected); m_quitFlag = true; } void RdpView::connectionError(const QString &text, const QString &caption) { m_quitFlag = true; - KMessageBox::error(0, text, caption); + KMessageBox::error(nullptr, text, caption); emit disconnectedError(); connectionClosed(ForceClose); } void RdpView::processError(QProcess::ProcessError error) { qCDebug(KRDC) << error; if (m_quitFlag) // do not try to show error messages while quitting (prevent crashes) return; if (m_status == Connecting) { if (error == QProcess::FailedToStart) { connectionError(i18n("Could not start \"xfreerdp\"; make sure xfreerdp is properly installed."), i18n("RDP Failure")); return; } } } void RdpView::receivedStandardError() { const QString output = QString::fromUtf8(m_process->readAllStandardError().constData()); qCDebug(KRDC) << output; QString line; int i = 0; while (!(line = output.section(QLatin1Char('\n'), i, i)).isEmpty()) { // the following error is issued by freerdp because of a bug in freerdp 1.0.1 and below; // see: https://github.com/FreeRDP/FreeRDP/pull/576 //"X Error of failed request: BadWindow (invalid Window parameter) // Major opcode of failed request: 7 (X_ReparentWindow) // Resource id in failed request: 0x71303348 // Serial number of failed request: 36 // Current serial number in output stream: 36" if (line.contains(QLatin1String("X_ReparentWindow"))) { connectionError(i18n("The version of \"xfreerdp\" you are using is too old.\n" "xfreerdp 1.0.2 or greater is required."), i18n("RDP Failure")); return; } else if(line.contains(QLatin1String("connection failure"))) { - KMessageBox::error(0, i18n("Connection failed. You might have passed a wrong address or username."), + KMessageBox::error(nullptr, i18n("Connection failed. You might have passed a wrong address or username."), i18n("RDP Failure")); return; } i++; } } void RdpView::receivedStandardOutput() { const QString output = QString::fromUtf8(m_process->readAllStandardOutput().constData()); qCDebug(KRDC) << output; QStringList splittedOutput = output.split(QLatin1Char('\n')); Q_FOREACH (const QString &line, splittedOutput) { // full xfreerdp message: "transport_connect: getaddrinfo (Name or service not known)" if (line.contains(QLatin1String("Name or service not known"))) { connectionError(i18n("Name or service not known."), i18n("Connection Failure")); return; // full xfreerdp message: "unable to connect to example.com:3389" } else if (line.contains(QLatin1String("unable to connect to"))) { connectionError(i18n("Connection attempt to host failed."), i18n("Connection Failure")); return; } else if (line.contains(QLatin1String("Authentication failure, check credentials"))) { connectionError(i18n("Authentication failure, check credentials."), i18n("Connection Failure")); return; // looks like some generic xfreerdp error message, handle it if nothing was handled: // "Error: protocol security negotiation failure" } else if (line.contains(QLatin1String("Error: protocol security negotiation failure")) || // xfreerdp 1.0 line.contains(QLatin1String("Error: protocol security negotiation or connection failure"))) { // xfreerdp 1.2 connectionError(i18n("Connection attempt to host failed. Security negotiation or connection failure."), i18n("Connection Failure")); return; } } } void RdpView::setGrabAllKeys(bool grabAllKeys) { Q_UNUSED(grabAllKeys); // do nothing.. grabKeyboard seems not to be supported in QX11EmbedContainer } QString RdpView::keymapToXfreerdp(const QString &keyboadLayout) { if (keymapToXfreerdpHash.isEmpty()) { keymapToXfreerdpHash = initKeymapToXfreerdp(); } return keymapToXfreerdpHash[keyboadLayout]; } // list of xfreerdp --kbd-list // this is a mapping for rdesktop comptibilty (old settings will still work) // needs to be completed (when not in message freeze; needs new localization) QHash RdpView::initKeymapToXfreerdp() { QHash keymapToXfreerdpHash; // Keyboard Layouts keymapToXfreerdpHash[QStringLiteral("ar")] = QStringLiteral("0x00000401"); // Arabic (101) // keymapToXfreerdpHash[""] = "0x00000402"; // Bulgarian // keymapToXfreerdpHash[""] = "0x00000404"; // Chinese (Traditional) - US Keyboard keymapToXfreerdpHash[QStringLiteral("cs")] = QStringLiteral("0x00000405"); // Czech keymapToXfreerdpHash[QStringLiteral("da")] = QStringLiteral("0x00000406"); // Danish keymapToXfreerdpHash[QStringLiteral("fo")] = QStringLiteral("0x00000406"); // Danish, Faroese; legacy for rdesktop keymapToXfreerdpHash[QStringLiteral("de")] = QStringLiteral("0x00000407"); // German // keymapToXfreerdpHash[""] = "0x00000408"; // Greek keymapToXfreerdpHash[QStringLiteral("en-us")] = QStringLiteral("0x00000409"); // US keymapToXfreerdpHash[QStringLiteral("es")] = QStringLiteral("0x0000040A"); // Spanish keymapToXfreerdpHash[QStringLiteral("fi")] = QStringLiteral("0x0000040B"); // Finnish keymapToXfreerdpHash[QStringLiteral("fr")] = QStringLiteral("0x0000040C"); // French keymapToXfreerdpHash[QStringLiteral("he")] = QStringLiteral("0x0000040D"); // Hebrew keymapToXfreerdpHash[QStringLiteral("hu")] = QStringLiteral("0x0000040E"); // Hungarian keymapToXfreerdpHash[QStringLiteral("is")] = QStringLiteral("0x0000040F"); // Icelandic keymapToXfreerdpHash[QStringLiteral("it")] = QStringLiteral("0x00000410"); // Italian keymapToXfreerdpHash[QStringLiteral("ja")] = QStringLiteral("0x00000411"); // Japanese keymapToXfreerdpHash[QStringLiteral("ko")] = QStringLiteral("0x00000412"); // Korean keymapToXfreerdpHash[QStringLiteral("nl")] = QStringLiteral("0x00000413"); // Dutch keymapToXfreerdpHash[QStringLiteral("no")] = QStringLiteral("0x00000414"); // Norwegian keymapToXfreerdpHash[QStringLiteral("pl")] = QStringLiteral("0x00000415"); // Polish (Programmers) keymapToXfreerdpHash[QStringLiteral("pt-br")] = QStringLiteral("0x00000416"); // Portuguese (Brazilian ABNT) // keymapToXfreerdpHash[""] = "0x00000418"; // Romanian keymapToXfreerdpHash[QStringLiteral("ru")] = QStringLiteral("0x00000419"); // Russian keymapToXfreerdpHash[QStringLiteral("hr")] = QStringLiteral("0x0000041A"); // Croatian // keymapToXfreerdpHash[""] = "0x0000041B"; // Slovak // keymapToXfreerdpHash[""] = "0x0000041C"; // Albanian keymapToXfreerdpHash[QStringLiteral("sv")] = QStringLiteral("0x0000041D"); // Swedish keymapToXfreerdpHash[QStringLiteral("th")] = QStringLiteral("0x0000041E"); // Thai Kedmanee keymapToXfreerdpHash[QStringLiteral("tr")] = QStringLiteral("0x0000041F"); // Turkish Q // keymapToXfreerdpHash[""] = "0x00000420"; // Urdu // keymapToXfreerdpHash[""] = "0x00000422"; // Ukrainian // keymapToXfreerdpHash[""] = "0x00000423"; // Belarusian keymapToXfreerdpHash[QStringLiteral("sl")] = QStringLiteral("0x00000424"); // Slovenian keymapToXfreerdpHash[QStringLiteral("et")] = QStringLiteral("0x00000425"); // Estonian keymapToXfreerdpHash[QStringLiteral("lv")] = QStringLiteral("0x00000426"); // Latvian keymapToXfreerdpHash[QStringLiteral("lt")] = QStringLiteral("0x00000427"); // Lithuanian IBM // keymapToXfreerdpHash[""] = "0x00000429"; // Farsi // keymapToXfreerdpHash[""] = "0x0000042A"; // Vietnamese // keymapToXfreerdpHash[""] = "0x0000042B"; // Armenian Eastern // keymapToXfreerdpHash[""] = "0x0000042C"; // Azeri Latin keymapToXfreerdpHash[QStringLiteral("mk")] = QStringLiteral("0x0000042F"); // FYRO Macedonian // keymapToXfreerdpHash[""] = "0x00000437"; // Georgian // keymapToXfreerdpHash[""] = "0x00000438"; // Faeroese // keymapToXfreerdpHash[""] = "0x00000439"; // Devanagari - INSCRIPT // keymapToXfreerdpHash[""] = "0x0000043A"; // Maltese 47-key // keymapToXfreerdpHash[""] = "0x0000043B"; // Norwegian with Sami // keymapToXfreerdpHash[""] = "0x0000043F"; // Kazakh // keymapToXfreerdpHash[""] = "0x00000440"; // Kyrgyz Cyrillic // keymapToXfreerdpHash[""] = "0x00000444"; // Tatar // keymapToXfreerdpHash[""] = "0x00000445"; // Bengali // keymapToXfreerdpHash[""] = "0x00000446"; // Punjabi // keymapToXfreerdpHash[""] = "0x00000447"; // Gujarati // keymapToXfreerdpHash[""] = "0x00000449"; // Tamil // keymapToXfreerdpHash[""] = "0x0000044A"; // Telugu // keymapToXfreerdpHash[""] = "0x0000044B"; // Kannada // keymapToXfreerdpHash[""] = "0x0000044C"; // Malayalam // keymapToXfreerdpHash[""] = "0x0000044E"; // Marathi // keymapToXfreerdpHash[""] = "0x00000450"; // Mongolian Cyrillic // keymapToXfreerdpHash[""] = "0x00000452"; // United Kingdom Extended // keymapToXfreerdpHash[""] = "0x0000045A"; // Syriac // keymapToXfreerdpHash[""] = "0x00000461"; // Nepali // keymapToXfreerdpHash[""] = "0x00000463"; // Pashto // keymapToXfreerdpHash[""] = "0x00000465"; // Divehi Phonetic // keymapToXfreerdpHash[""] = "0x0000046E"; // Luxembourgish // keymapToXfreerdpHash[""] = "0x00000481"; // Maori // keymapToXfreerdpHash[""] = "0x00000804"; // Chinese (Simplified) - US Keyboard keymapToXfreerdpHash[QStringLiteral("de-ch")] = QStringLiteral("0x00000807"); // Swiss German keymapToXfreerdpHash[QStringLiteral("en-gb")] = QStringLiteral("0x00000809"); // United Kingdom // keymapToXfreerdpHash[""] = "0x0000080A"; // Latin American keymapToXfreerdpHash[QStringLiteral("fr-be")] = QStringLiteral("0x0000080C"); // Belgian French keymapToXfreerdpHash[QStringLiteral("nl-be")] = QStringLiteral("0x00000813"); // Belgian (Period) keymapToXfreerdpHash[QStringLiteral("pt")] = QStringLiteral("0x00000816"); // Portuguese // keymapToXfreerdpHash[""] = "0x0000081A"; // Serbian (Latin) // keymapToXfreerdpHash[""] = "0x0000082C"; // Azeri Cyrillic // keymapToXfreerdpHash[""] = "0x0000083B"; // Swedish with Sami // keymapToXfreerdpHash[""] = "0x00000843"; // Uzbek Cyrillic // keymapToXfreerdpHash[""] = "0x0000085D"; // Inuktitut Latin // keymapToXfreerdpHash[""] = "0x00000C0C"; // Canadian French (legacy) // keymapToXfreerdpHash[""] = "0x00000C1A"; // Serbian (Cyrillic) keymapToXfreerdpHash[QStringLiteral("fr-ca")] = QStringLiteral("0x00001009"); // Canadian French keymapToXfreerdpHash[QStringLiteral("fr-ch")] = QStringLiteral("0x0000100C"); // Swiss French // keymapToXfreerdpHash[""] = "0x0000141A"; // Bosnian // keymapToXfreerdpHash[""] = "0x00001809"; // Irish // keymapToXfreerdpHash[""] = "0x0000201A"; // Bosnian Cyrillic // Keyboard Layout Variants // keymapToXfreerdpHash[""] = "0x00010401"; // Arabic (102) // keymapToXfreerdpHash[""] = "0x00010402"; // Bulgarian (Latin) // keymapToXfreerdpHash[""] = "0x00010405"; // Czech (QWERTY) // keymapToXfreerdpHash[""] = "0x00010407"; // German (IBM) // keymapToXfreerdpHash[""] = "0x00010408"; // Greek (220) keymapToXfreerdpHash[QStringLiteral("en-dv")] = QStringLiteral("0x00010409"); // United States-Dvorak // keymapToXfreerdpHash[""] = "0x0001040A"; // Spanish Variation // keymapToXfreerdpHash[""] = "0x0001040E"; // Hungarian 101-key // keymapToXfreerdpHash[""] = "0x00010410"; // Italian (142) // keymapToXfreerdpHash[""] = "0x00010415"; // Polish (214) // keymapToXfreerdpHash[""] = "0x00010416"; // Portuguese (Brazilian ABNT2) // keymapToXfreerdpHash[""] = "0x00010419"; // Russian (Typewriter) // keymapToXfreerdpHash[""] = "0x0001041B"; // Slovak (QWERTY) // keymapToXfreerdpHash[""] = "0x0001041E"; // Thai Pattachote // keymapToXfreerdpHash[""] = "0x0001041F"; // Turkish F // keymapToXfreerdpHash[""] = "0x00010426"; // Latvian (QWERTY) // keymapToXfreerdpHash[""] = "0x00010427"; // Lithuanian // keymapToXfreerdpHash[""] = "0x0001042B"; // Armenian Western // keymapToXfreerdpHash[""] = "0x00010439"; // Hindi Traditional // keymapToXfreerdpHash[""] = "0x0001043A"; // Maltese 48-key // keymapToXfreerdpHash[""] = "0x0001043B"; // Sami Extended Norway // keymapToXfreerdpHash[""] = "0x00010445"; // Bengali (Inscript) // keymapToXfreerdpHash[""] = "0x0001045A"; // Syriac Phonetic // keymapToXfreerdpHash[""] = "0x00010465"; // Divehi Typewriter // keymapToXfreerdpHash[""] = "0x0001080C"; // Belgian (Comma) // keymapToXfreerdpHash[""] = "0x0001083B"; // Finnish with Sami // keymapToXfreerdpHash[""] = "0x00011009"; // Canadian Multilingual Standard // keymapToXfreerdpHash[""] = "0x00011809"; // Gaelic // keymapToXfreerdpHash[""] = "0x00020401"; // Arabic (102) AZERTY // keymapToXfreerdpHash[""] = "0x00020405"; // Czech Programmers // keymapToXfreerdpHash[""] = "0x00020408"; // Greek (319) // keymapToXfreerdpHash[""] = "0x00020409"; // United States-International // keymapToXfreerdpHash[""] = "0x0002041E"; // Thai Kedmanee (non-ShiftLock) // keymapToXfreerdpHash[""] = "0x0002083B"; // Sami Extended Finland-Sweden // keymapToXfreerdpHash[""] = "0x00030408"; // Greek (220) Latin // keymapToXfreerdpHash[""] = "0x00030409"; // United States-Dvorak for left hand // keymapToXfreerdpHash[""] = "0x0003041E"; // Thai Pattachote (non-ShiftLock) // keymapToXfreerdpHash[""] = "0x00040408"; // Greek (319) Latin // keymapToXfreerdpHash[""] = "0x00040409"; // United States-Dvorak for right hand // keymapToXfreerdpHash[""] = "0x00050408"; // Greek Latin // keymapToXfreerdpHash[""] = "0x00050409"; // US English Table for IBM Arabic 238_L // keymapToXfreerdpHash[""] = "0x00060408"; // Greek Polytonic // keymapToXfreerdpHash[""] = "0xB0000407"; // German Neo // Keyboard Input Method Editors (IMEs) // keymapToXfreerdpHash[""] = "0xE0010404"; // Chinese (Traditional) - Phonetic // keymapToXfreerdpHash[""] = "0xE0010411"; // Japanese Input System (MS-IME2002) // keymapToXfreerdpHash[""] = "0xE0010412"; // Korean Input System (IME 2000) // keymapToXfreerdpHash[""] = "0xE0010804"; // Chinese (Simplified) - QuanPin // keymapToXfreerdpHash[""] = "0xE0020404"; // Chinese (Traditional) - ChangJie // keymapToXfreerdpHash[""] = "0xE0020804"; // Chinese (Simplified) - ShuangPin // keymapToXfreerdpHash[""] = "0xE0030404"; // Chinese (Traditional) - Quick // keymapToXfreerdpHash[""] = "0xE0030804"; // Chinese (Simplified) - ZhengMa // keymapToXfreerdpHash[""] = "0xE0040404"; // Chinese (Traditional) - Big5 Code // keymapToXfreerdpHash[""] = "0xE0050404"; // Chinese (Traditional) - Array // keymapToXfreerdpHash[""] = "0xE0050804"; // Chinese (Simplified) - NeiMa // keymapToXfreerdpHash[""] = "0xE0060404"; // Chinese (Traditional) - DaYi // keymapToXfreerdpHash[""] = "0xE0070404"; // Chinese (Traditional) - Unicode // keymapToXfreerdpHash[""] = "0xE0080404"; // Chinese (Traditional) - New Phonetic // keymapToXfreerdpHash[""] = "0xE0090404"; // Chinese (Traditional) - New ChangJie // keymapToXfreerdpHash[""] = "0xE00E0804"; // Chinese (Traditional) - Microsoft Pinyin IME 3.0 // keymapToXfreerdpHash[""] = "0xE00F0404"; // Chinese (Traditional) - Alphanumeric return keymapToXfreerdpHash; } diff --git a/rdp/rdpview.h b/rdp/rdpview.h index 04d5942..1e4ec9c 100644 --- a/rdp/rdpview.h +++ b/rdp/rdpview.h @@ -1,109 +1,109 @@ /**************************************************************************** ** ** Copyright (C) 2002 Arend van Beelen jr. ** Copyright (C) 2007 Urs Wolfer ** ** This file is part of KDE. ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; see the file COPYING. If not, write to ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ** Boston, MA 02110-1301, USA. ** ****************************************************************************/ #ifndef RDPVIEW_H #define RDPVIEW_H #include "remoteview.h" #include "rdphostpreferences.h" #include #include #define TCP_PORT_RDP 3389 class RdpView; class QX11EmbedContainer; class RdpView : public RemoteView { Q_OBJECT public: - explicit RdpView(QWidget *parent = 0, + explicit RdpView(QWidget *parent = nullptr, const QUrl &url = QUrl(), KConfigGroup configGroup = KConfigGroup(), const QString &user = QString(), const QString &password = QString()); ~RdpView() override; // functions regarding the window QSize framebufferSize() override; // returns the size of the remote view QSize sizeHint() const override; // returns the suggested size // functions regarding the connection void startQuitting() override; // start closing the connection bool isQuitting() override; // are we currently closing the connection? bool start() override; // open a connection void setGrabAllKeys(bool grabAllKeys) override; HostPreferences* hostPreferences() override; QPixmap takeScreenshot() override; public Q_SLOTS: void switchFullscreen(bool on) override; protected: bool eventFilter(QObject *obj, QEvent *event) override; private: // Marks if connectionClosed should close the connection if m_quitFlag is true. enum CloseType { NormalClose, ForceClose, }; void connectionError(const QString &text, const QString &caption); // called if xfreerdp quits with error void connectionClosed(CloseType closeType); // Signals the connection closed if not quiting or it is forced QString keymapToXfreerdp(const QString &keyboadLayout); QHash initKeymapToXfreerdp(); QString m_name; QString m_user; QString m_password; bool m_quitFlag; QWindow *m_container; // container for the xfreerdp window QWidget *m_containerWidget; // Widget to contain the xfreerdp window. QProcess *m_process; // xfreerdp process RdpHostPreferences *m_hostPreferences; private Q_SLOTS: void connectionOpened(); // called if xfreerdp started void connectionClosed(); // called if xfreerdp quits void processError(QProcess::ProcessError error); // called if xfreerdp dies void receivedStandardError(); // catches xfreerdp debug output void receivedStandardOutput(); // catches xfreerdp output }; static QHash keymapToXfreerdpHash; #endif diff --git a/remotedesktopsmodel.cpp b/remotedesktopsmodel.cpp index ad62380..cce37e0 100644 --- a/remotedesktopsmodel.cpp +++ b/remotedesktopsmodel.cpp @@ -1,306 +1,306 @@ /**************************************************************************** ** ** Copyright (C) 2008 Urs Wolfer ** Copyright (C) 2009 Tony Murray ** ** This file is part of KDE. ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; see the file COPYING. If not, write to ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ** Boston, MA 02110-1301, USA. ** ****************************************************************************/ #include "remotedesktopsmodel.h" #include "krdc_debug.h" #include #include #include #include #include #include #include RemoteDesktopsModel::RemoteDesktopsModel(QObject *parent, KBookmarkManager *manager) : QAbstractTableModel(parent) { m_manager = manager; m_manager->setUpdate(true); connect(m_manager, SIGNAL(changed(QString,QString)), SLOT(bookmarksChanged())); buildModelFromBookmarkGroup(m_manager->root()); #ifdef BUILD_ZEROCONF // Add RDP and NX if they start announcing via Zeroconf: m_protocols[QLatin1String("_rfb._tcp")] = QLatin1String("vnc"); zeroconfBrowser = new KDNSSD::ServiceBrowser(QLatin1String("_rfb._tcp"), true); connect(zeroconfBrowser, SIGNAL(finished()), this, SLOT(servicesChanged())); zeroconfBrowser->startBrowse(); qCDebug(KRDC) << "Browsing for zeroconf hosts."; #endif } RemoteDesktopsModel::~RemoteDesktopsModel() { } int RemoteDesktopsModel::columnCount(const QModelIndex &) const { return 6; // same as count of RemoteDesktopsModel::DisplayItems enum } int RemoteDesktopsModel::rowCount(const QModelIndex &) const { return remoteDesktops.size(); } Qt::ItemFlags RemoteDesktopsModel::flags(const QModelIndex &index) const { if (!index.isValid()) - return 0; + return nullptr; if (index.column() == RemoteDesktopsModel::Favorite) { return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable; } return Qt::ItemIsEnabled; } bool RemoteDesktopsModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (index.isValid() && role == Qt::CheckStateRole && index.column() == RemoteDesktopsModel::Favorite) { bool checked = (Qt::CheckState)value.toUInt() == Qt::Checked; remoteDesktops[index.row()].favorite = checked; RemoteDesktop rd = remoteDesktops.at(index.row()); if (checked) { KBookmarkGroup root = m_manager->root(); root.addBookmark(rd.title, QUrl(rd.url), QString()); m_manager->emitChanged(root); } else { BookmarkManager::removeByUrl(m_manager, rd.url, true, rd.title); } return true; } return false; } QVariant RemoteDesktopsModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant(); RemoteDesktop item = remoteDesktops.at(index.row()); switch (role) { case Qt::DisplayRole: switch (index.column()) { case RemoteDesktopsModel::Favorite: return item.favorite; case RemoteDesktopsModel::Title: return item.title; case RemoteDesktopsModel::LastConnected: return QVariant(item.lastConnected); case RemoteDesktopsModel::VisitCount: return item.visits; case RemoteDesktopsModel::Created: if (item.created.isNull()) return QVariant(); return QLocale().toString(item.created.toLocalTime(), QLocale::FormatType::ShortFormat); case RemoteDesktopsModel::Source: switch (item.source) { case RemoteDesktop::Bookmarks: return i18nc("Where each displayed link comes from", "Bookmarks"); case RemoteDesktop::History: return i18nc("Where each displayed link comes from", "History"); case RemoteDesktop::Zeroconf: return i18nc("Where each displayed link comes from", "Zeroconf"); case RemoteDesktop::None: return i18nc("Where each displayed link comes from", "None"); } default: return QVariant(); } case Qt::CheckStateRole: if (index.column() == RemoteDesktopsModel::Favorite) return item.favorite ? Qt::Checked : Qt::Unchecked; return QVariant(); case Qt::ToolTipRole: switch(index.column()) { case RemoteDesktopsModel::Favorite: if (item.favorite) { return i18nc("Remove the selected url from the bookarks menu", "Remove the bookmark for %1.", item.title); } else { return i18nc("Add the selected url to the bookmarks menu", "Bookmark %1.", item.title); } case RemoteDesktopsModel::LastConnected: if (!item.lastConnected.isNull()) { return QLocale().toString(item.lastConnected.toLocalTime(), QLocale::FormatType::LongFormat); } break; // else show default tooltip case RemoteDesktopsModel::Created: if (!item.created.isNull()) { return QLocale().toString(item.lastConnected.toLocalTime(), QLocale::FormatType::LongFormat); } break; // else show default tooltip default: break; } return item.url; //use the url for the tooltip case 10001: //url for dockwidget return item.url; case 10002: //filter return QUrl::fromPercentEncoding(QString(item.url + item.title).toUtf8()); // return both user visible title and url data, percent encoded case 10003: //title for dockwidget return item.title; default: return QVariant(); } } QVariant RemoteDesktopsModel::headerData(int section, Qt::Orientation orientation, int role) const { if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { switch (section) { case RemoteDesktopsModel::Favorite: return QVariant(); // the favorite column is to small for a header case RemoteDesktopsModel::Title: return i18nc("Header of the connections list, title/url for remote connection", "Remote Desktop"); case RemoteDesktopsModel::LastConnected: return i18nc("Header of the connections list, the last time this connection was initiated", "Last Connected"); case RemoteDesktopsModel::VisitCount: return i18nc("Header of the connections list, the number of times this connection has been visited", "Visits"); case RemoteDesktopsModel::Created: return i18nc("Header of the connections list, the time when this entry was created", "Created"); case RemoteDesktopsModel::Source: return i18nc("Header of the connections list, where this entry comes from", "Source"); } } return QVariant(); } // does not trigger view update, you must do this by hand after using this function void RemoteDesktopsModel::removeAllItemsFromSources(RemoteDesktop::Sources sources) { QMutableListIterator iter(remoteDesktops); while (iter.hasNext()) { iter.next(); // if it matches any of the specified sources, remove it if ((iter.value().source & sources) > 0) iter.remove(); } } void RemoteDesktopsModel::bookmarksChanged() { removeAllItemsFromSources(RemoteDesktop::Bookmarks | RemoteDesktop::History); buildModelFromBookmarkGroup(m_manager->root()); beginResetModel(); endResetModel(); } // Danger Will Roobinson, confusing code ahead! void RemoteDesktopsModel::buildModelFromBookmarkGroup(const KBookmarkGroup &group) { KBookmark bm = group.first(); while (!bm.isNull()) { if (bm.isGroup()) { // recurse subfolders and treat it special if it is the history folder buildModelFromBookmarkGroup(bm.toGroup()); } else { // not a group RemoteDesktop item; item.title = bm.fullText(); item.url = bm.url().url(); int index = remoteDesktops.indexOf(item); //search for this url to see if we need to update it bool newItem = index < 0; // do we need to create a new item? // we want to merge all copies of a url into one link, so if the item exists, update it if (group.metaDataItem(QLatin1String("krdc-history")) == QLatin1String("historyfolder")) { // set source and favorite (will override later if needed) item.source = RemoteDesktop::History; item.favorite = false; // since we are in the history folder collect statitics and add them QDateTime connected = QDateTime(); QDateTime created = QDateTime(); bool ok = false; // first the created datetime created.setTime_t(bm.metaDataItem(QLatin1String("time_added")).toLongLong(&ok)); if (ok) (newItem ? item : remoteDesktops[index]).created = created; // then the last visited datetime ok = false; connected.setTime_t(bm.metaDataItem(QLatin1String("time_visited")).toLongLong(&ok)); if (ok) (newItem ? item : remoteDesktops[index]).lastConnected = connected; // finally the visited count ok = false; int visits = bm.metaDataItem(QLatin1String("visit_count")).toInt(&ok); if (ok) (newItem ? item : remoteDesktops[index]).visits = visits; } else { if (newItem) { // if this is a new item, just add the rest of the required data item.lastConnected = QDateTime(); item.created = QDateTime(); item.visits = 0; item.favorite = true; item.source = RemoteDesktop::Bookmarks; } else { // otherwise override these fields with the info from the bookmark remoteDesktops[index].title = bm.fullText(); remoteDesktops[index].favorite = true; remoteDesktops[index].source = RemoteDesktop::Bookmarks; } } // if we have a new item, add it if (newItem) remoteDesktops.append(item); } bm = group.next(bm); // next item in the group } } #ifdef BUILD_ZEROCONF void RemoteDesktopsModel::servicesChanged() { //redo list because it is easier than finding and removing one that disappeared QList services = zeroconfBrowser->services(); QUrl url; removeAllItemsFromSources(RemoteDesktop::Zeroconf); foreach(KDNSSD::RemoteService::Ptr service, services) { url.setScheme(m_protocols[service->type()].toLower()); url.setHost(service->hostName()); url.setPort(service->port()); RemoteDesktop item; item.url = url.url(); if (!remoteDesktops.contains(item)) { item.title = service->serviceName(); item.source = RemoteDesktop::Zeroconf; item.created = QDateTime::currentDateTime(); item.favorite = false; item.visits = 0; remoteDesktops.append(item); } } beginResetModel(); endResetModel(); } #endif diff --git a/tabbedviewwidget.h b/tabbedviewwidget.h index 5a4bbd2..b3cab71 100644 --- a/tabbedviewwidget.h +++ b/tabbedviewwidget.h @@ -1,82 +1,82 @@ /**************************************************************************** ** ** Copyright (C) 2009 Tony Murray ** ** This file is part of KDE. ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; see the file COPYING. If not, write to ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ** Boston, MA 02110-1301, USA. ** ****************************************************************************/ #ifndef TABBEDVIEWWIDGET_H #define TABBEDVIEWWIDGET_H #include #include #include class TabbedViewWidgetModel : public QAbstractItemModel { friend class TabbedViewWidget; Q_OBJECT public: explicit TabbedViewWidgetModel(QTabWidget *modelTarget); QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; QModelIndex parent(const QModelIndex &index) const override; int rowCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; Qt::ItemFlags flags(const QModelIndex &index) const override; bool setData(const QModelIndex &index, const QVariant &value, int role) override; QVariant data(const QModelIndex &index, int role) const override; protected: void emitLayoutAboutToBeChanged(); void emitLayoutChanged(); void emitDataChanged(int index); private: QTabWidget *m_tabWidget; }; class TabbedViewWidget : public QTabWidget { Q_OBJECT public: - explicit TabbedViewWidget(QWidget *parent = 0); + explicit TabbedViewWidget(QWidget *parent = nullptr); ~TabbedViewWidget() override; TabbedViewWidgetModel* getModel(); int addTab(QWidget *page, const QString &label); int addTab(QWidget *page, const QIcon &icon, const QString &label); int insertTab(int index, QWidget *page, const QString &label); int insertTab(int index, QWidget *page, const QIcon &icon, const QString &label); void removeTab(int index); void removePage(QWidget *page); void moveTab(int from, int to); void setTabText(int index, const QString &label); Q_SIGNALS: void mouseMiddleClick(int index); protected: void mouseDoubleClickEvent(QMouseEvent * event) Q_DECL_OVERRIDE; void mouseReleaseEvent(QMouseEvent *) Q_DECL_OVERRIDE; private: TabbedViewWidgetModel *m_model; bool isEmptyTabbarSpace(const QPoint &point) const; }; #endif // FULLSCREENWINDOW_H diff --git a/test/testview.h b/test/testview.h index 4c8154e..576bb5e 100644 --- a/test/testview.h +++ b/test/testview.h @@ -1,75 +1,75 @@ /**************************************************************************** ** ** Copyright (C) 2008 Urs Wolfer ** ** This file is part of KDE. ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; see the file COPYING. If not, write to ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ** Boston, MA 02110-1301, USA. ** ****************************************************************************/ #ifndef TESTVIEW_H #define TESTVIEW_H #include "remoteview.h" #include "hostpreferences.h" #include class TestHostPreferences; class TestView : public RemoteView { Q_OBJECT public: - explicit TestView(QWidget *parent = 0, const QUrl &url = QUrl(), KConfigGroup configGroup = KConfigGroup()); + explicit TestView(QWidget *parent = nullptr, const QUrl &url = QUrl(), KConfigGroup configGroup = KConfigGroup()); ~TestView() override; QSize framebufferSize() override; QSize sizeHint() const override; bool isQuitting() override; bool start() override; HostPreferences* hostPreferences() override; public Q_SLOTS: void switchFullscreen(bool on) override; protected: bool eventFilter(QObject *obj, QEvent *event) override; private: TestHostPreferences *m_hostPreferences; private Q_SLOTS: void asyncConnect(); }; class TestHostPreferences : public HostPreferences { Q_OBJECT public: - explicit TestHostPreferences(KConfigGroup configGroup, QObject *parent = 0) + explicit TestHostPreferences(KConfigGroup configGroup, QObject *parent = nullptr) : HostPreferences(configGroup, parent) {} protected: - QWidget* createProtocolSpecificConfigPage() override { return 0; }; + QWidget* createProtocolSpecificConfigPage() override { return nullptr; }; }; #endif // TESTVIEW_H diff --git a/test/testviewfactory.cpp b/test/testviewfactory.cpp index 043e9d3..93d6ac8 100644 --- a/test/testviewfactory.cpp +++ b/test/testviewfactory.cpp @@ -1,81 +1,81 @@ /**************************************************************************** ** ** Copyright (C) 2008 Urs Wolfer ** ** This file is part of KDE. ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; see the file COPYING. If not, write to ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ** Boston, MA 02110-1301, USA. ** ****************************************************************************/ #include "testviewfactory.h" #include K_PLUGIN_FACTORY_WITH_JSON(KrdcFactory, "krdc_test.json", registerPlugin();) TestViewFactory::TestViewFactory(QObject *parent, const QVariantList &args) : RemoteViewFactory(parent) { Q_UNUSED(args); KLocalizedString::setApplicationDomain("krdc"); } TestViewFactory::~TestViewFactory() { } bool TestViewFactory::supportsUrl(const QUrl &url) const { return (url.scheme().compare(QLatin1String("test"), Qt::CaseInsensitive) == 0); } RemoteView *TestViewFactory::createView(QWidget *parent, const QUrl &url, KConfigGroup configGroup) { return new TestView(parent, url, configGroup); } HostPreferences *TestViewFactory::createHostPreferences(KConfigGroup configGroup, QWidget *parent) { Q_UNUSED(configGroup); Q_UNUSED(parent); - return 0; + return nullptr; } QString TestViewFactory::scheme() const { return QLatin1String("test"); } QString TestViewFactory::connectActionText() const { return QLatin1String("New Test Connection..."); // no i18n required, just internal test plugin! } QString TestViewFactory::connectButtonText() const { return QLatin1String("KRDC Test Connection"); // no i18n required, just internal test plugin! } QString TestViewFactory::connectToolTipText() const { return QLatin1String("Enter the address here. Port is optional.
" "Example: testserver (host)"); // no i18n required, just internal test plugin! } #include "testviewfactory.moc"