mainwindow.cpp 11.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
/* This file is part of the KDE project
   Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
   Copyright (C) 2013 Amandeep Singh <aman.dedman@gmail.com>

   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.
*/
#include "mainwindow.h"
11
#include "invitationsrfbserver.h"
12 13 14 15

#include "krfbconfig.h"
#include "ui_configtcp.h"
#include "ui_configsecurity.h"
16
#include "ui_configframebuffer.h"
17 18

#include <KConfigDialog>
19
#include <KLocalizedString>
20
#include <KMessageBox>
21
#include <KMessageWidget>
22 23
#include <KStandardAction>
#include <KActionCollection>
Amandeep Singh's avatar
Amandeep Singh committed
24
#include <KNewPasswordDialog>
25 26
#include <KPluginLoader>
#include <KPluginMetaData>
27

28
#include <QIcon>
Jeremy Whiting's avatar
Jeremy Whiting committed
29
#include <QWidget>
30 31
#include <QLineEdit>
#include <QComboBox>
Jeremy Whiting's avatar
Jeremy Whiting committed
32
#include <QSizePolicy>
33 34
#include <QVector>
#include <QSet>
35
#include <QNetworkInterface>
36
#include <QHostInfo>
37

38

39 40 41
class TCP: public QWidget, public Ui::TCP
{
public:
42
    TCP(QWidget *parent = nullptr) : QWidget(parent) {
43 44 45 46 47 48 49
        setupUi(this);
    }
};

class Security: public QWidget, public Ui::Security
{
public:
50
    Security(QWidget *parent = nullptr) : QWidget(parent) {
51
        setupUi(this);
52 53 54 55 56 57 58
        walletWarning = new KMessageWidget(this);
        walletWarning->setText(i18n("Storing passwords in config file is insecure!"));
        walletWarning->setCloseButtonVisible(false);
        walletWarning->setMessageType(KMessageWidget::Warning);
        walletWarning->hide();
        vboxLayout->addWidget(walletWarning);

59
        // show warning when "noWallet" checkbox is checked
60
        QObject::connect(kcfg_noWallet, &QCheckBox::toggled, this, [this] (bool checked) {
61
            walletWarning->setVisible(checked);
62
        });
63
    }
64 65

    KMessageWidget *walletWarning = nullptr;
66 67
};

68 69 70
class ConfigFramebuffer: public QWidget, public Ui::Framebuffer
{
public:
71
    ConfigFramebuffer(QWidget *parent = nullptr) : QWidget(parent) {
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
        setupUi(this);
        // hide the line edit with framebuffer string
        kcfg_preferredFrameBufferPlugin->hide();
        // fill drop-down combo with a list of real existing plugins
        this->fillFrameBuffersCombo();
        // initialize combo with currently configured framebuffer plugin
        cb_preferredFrameBufferPlugin->setCurrentText(KrfbConfig::preferredFrameBufferPlugin());
        // connect signals between combo<->lineedit
        // if we change selection in combo, lineedit is updated
        QObject::connect(cb_preferredFrameBufferPlugin, &QComboBox::currentTextChanged,
                         kcfg_preferredFrameBufferPlugin, &QLineEdit::setText);
    }

    void fillFrameBuffersCombo() {
        const QVector<KPluginMetaData> plugins = KPluginLoader::findPlugins(
                    QStringLiteral("krfb"), [](const KPluginMetaData & md) {
            return md.serviceTypes().contains(QStringLiteral("krfb/framebuffer"));
        });
        QSet<QString> unique;
        QVectorIterator<KPluginMetaData> i(plugins);
        i.toBack();
        while (i.hasPrevious()) {
            const KPluginMetaData &metadata = i.previous();
            if (unique.contains(metadata.pluginId())) continue;
            cb_preferredFrameBufferPlugin->addItem(metadata.pluginId());
            unique.insert(metadata.pluginId());
        }
    }
};

102 103 104 105 106 107 108

MainWindow::MainWindow(QWidget *parent)
    : KXmlGuiWindow(parent)
{
    setAttribute(Qt::WA_DeleteOnClose, false);

    m_passwordEditable = false;
109
    m_passwordLineEdit = new QLineEdit(this);
110 111 112 113 114
    m_passwordLineEdit->setVisible(false);
    m_passwordLineEdit->setAlignment(Qt::AlignHCenter);

    QWidget *mainWidget = new QWidget;
    m_ui.setupUi(mainWidget);
115
    m_ui.krfbIconLabel->setPixmap(QIcon::fromTheme(QStringLiteral("krfb")).pixmap(128));
116 117 118
    m_ui.enableUnattendedCheckBox->setChecked(
            InvitationsRfbServer::instance->allowUnattendedAccess());

119 120
    setCentralWidget(mainWidget);

Albert Astals Cid's avatar
Albert Astals Cid committed
121 122 123 124 125 126 127 128 129 130 131 132 133 134
    connect(m_ui.passwordEditButton, &QToolButton::clicked,
            this, &MainWindow::editPassword);
    connect(m_ui.enableSharingCheckBox, &QCheckBox::toggled,
            this, &MainWindow::toggleDesktopSharing);
    connect(m_ui.enableUnattendedCheckBox, &QCheckBox::toggled,
            InvitationsRfbServer::instance, &InvitationsRfbServer::toggleUnattendedAccess);
    connect(m_ui.unattendedPasswordButton, &QPushButton::clicked,
            this, &MainWindow::editUnattendedPassword);
    connect(m_ui.addressAboutButton, &QToolButton::clicked,
            this, &MainWindow::aboutConnectionAddress);
    connect(m_ui.unattendedAboutButton, &QToolButton::clicked,
            this, &MainWindow::aboutUnattendedMode);
    connect(InvitationsRfbServer::instance, &InvitationsRfbServer::passwordChanged,
            this, &MainWindow::passwordChanged);
135 136 137

    // Figure out the address
    int port = KrfbConfig::port();
138 139
    const QList<QNetworkInterface> interfaceList = QNetworkInterface::allInterfaces();
    for (const QNetworkInterface& interface : interfaceList) {
140 141 142 143
        if(interface.flags() & QNetworkInterface::IsLoopBack)
            continue;

        if(interface.flags() & QNetworkInterface::IsRunning &&
144 145
                !interface.addressEntries().isEmpty()) {
            const QString hostName = QHostInfo::localHostName();
146
            const QString ipAddress = interface.addressEntries().constFirst().ip().toString();
147 148 149 150 151
            const QString addressLabelText = hostName.isEmpty()
                ? QStringLiteral("%1 : %2").arg(ipAddress).arg(port)
                : QStringLiteral("%1 (%2) : %3").arg(hostName, ipAddress).arg(port);
            m_ui.addressDisplayLabel->setText(addressLabelText);
        }
152 153 154
    }

    //Figure out the password
155 156
    m_ui.passwordDisplayLabel->setText(
            InvitationsRfbServer::instance->desktopPassword());
157 158 159 160 161

    KStandardAction::quit(QCoreApplication::instance(), SLOT(quit()), actionCollection());
    KStandardAction::preferences(this, SLOT(showConfiguration()), actionCollection());

    setupGUI();
162

163 164 165 166
    if (KrfbConfig::allowDesktopControl()) {
      m_ui.enableSharingCheckBox->setChecked(true);
    }

167
    setAutoSaveSettings();
168 169 170 171 172 173 174 175 176 177
}

MainWindow::~MainWindow()
{
}

void MainWindow::editPassword()
{
    if(m_passwordEditable) {
        m_passwordEditable = false;
178
        m_ui.passwordEditButton->setIcon(QIcon::fromTheme(QStringLiteral("document-properties")));
179
        m_ui.passwordGridLayout->removeWidget(m_passwordLineEdit);
180 181 182 183 184
        InvitationsRfbServer::instance->setDesktopPassword(
                m_passwordLineEdit->text());
        m_ui.passwordDisplayLabel->setText(
                InvitationsRfbServer::instance->desktopPassword());
        m_passwordLineEdit->setVisible(false);
185 186
    } else {
        m_passwordEditable = true;
187
        m_ui.passwordEditButton->setIcon(QIcon::fromTheme(QStringLiteral("document-save")));
188
        m_ui.passwordGridLayout->addWidget(m_passwordLineEdit,0,0);
189 190 191 192
        m_passwordLineEdit->setText(
                InvitationsRfbServer::instance->desktopPassword());
        m_passwordLineEdit->setVisible(true);
        m_passwordLineEdit->setFocus(Qt::MouseFocusReason);
193 194 195
    }
}

Amandeep Singh's avatar
Amandeep Singh committed
196 197 198 199 200 201 202 203 204
void MainWindow::editUnattendedPassword()
{
    KNewPasswordDialog dialog(this);
    dialog.setPrompt(i18n("Enter a new password for Unattended Access"));
    if(dialog.exec()) {
        InvitationsRfbServer::instance->setUnattendedPassword(dialog.password());
    }
}

205 206 207
void MainWindow::toggleDesktopSharing(bool enable)
{
    if(enable) {
208
        if(!InvitationsRfbServer::instance->start()) {
209
            KMessageBox::error(this,
210 211 212 213
                    i18n("Failed to start the krfb server. Desktop sharing "
                        "will not work. Try setting another port in the settings "
                        "and restart krfb."));
        }
214
    } else {
215
        InvitationsRfbServer::instance->stop();
216 217 218
        if(m_passwordEditable) {
            m_passwordEditable = false;
            m_passwordLineEdit->setVisible(false);
219
            m_ui.passwordEditButton->setIcon(QIcon::fromTheme(QStringLiteral("document-properties")));
220 221 222 223
        }
    }
}

224 225 226 227 228 229
void MainWindow::passwordChanged(const QString& password)
{
    m_passwordLineEdit->setText(password);
    m_ui.passwordDisplayLabel->setText(password);
}

Amandeep Singh's avatar
Amandeep Singh committed
230 231 232 233 234 235 236 237 238 239 240 241 242 243
void MainWindow::aboutConnectionAddress()
{
    KMessageBox::about(this,
            i18n("This field contains the address of your computer and the port number, separated by a colon.\n\nThe address is just a hint - you can use any address that can reach your computer.\n\nDesktop Sharing tries to guess your address from your network configuration, but does not always succeed in doing so.\n\nIf your computer is behind a firewall it may have a different address or be unreachable for other computers."),
            i18n("KDE Desktop Sharing"));
}

void MainWindow::aboutUnattendedMode()
{
    KMessageBox::about(this,
            i18n("Any remote user with normal desktop sharing password will have to be authenticated.\n\nIf unattended access is on, and the remote user provides unattended mode password, desktop sharing access will be granted without explicit confirmation."),
            i18n("KDE Desktop Sharing"));
}

244 245
void MainWindow::showConfiguration()
{
246
    static QString s_prevFramebufferPlugin;
247
    static bool s_prevNoWallet;
248 249 250 251
    // ^^ needs to be static, because lambda will be called long time
    //    after showConfiguration() ends, so auto variable would go out of scope
    // save previously selected framebuffer plugin config
    s_prevFramebufferPlugin = KrfbConfig::preferredFrameBufferPlugin();
252
    s_prevNoWallet = KrfbConfig::noWallet();
253

254
    if (KConfigDialog::showDialog(QStringLiteral("settings"))) {
255 256 257
        return;
    }

258 259 260 261
    KConfigDialog *dialog = new KConfigDialog(this, QStringLiteral("settings"), KrfbConfig::self());
    dialog->addPage(new TCP, i18n("Network"), QStringLiteral("network-wired"));
    dialog->addPage(new Security, i18n("Security"), QStringLiteral("security-high"));
    dialog->addPage(new ConfigFramebuffer, i18n("Screen capture"), QStringLiteral("video-display"));
262
    dialog->show();
263
    connect(dialog, &KConfigDialog::settingsChanged, this, [this] () {
264 265 266 267 268
        // check if framebuffer plugin config has changed
        if (s_prevFramebufferPlugin != KrfbConfig::preferredFrameBufferPlugin()) {
            KMessageBox::information(this, i18n("To apply framebuffer plugin setting, "
                                                "you need to restart the program."));
        }
269 270 271 272 273 274 275 276 277 278 279 280 281
        // check if kwallet config has changed
        if (s_prevNoWallet != KrfbConfig::noWallet()) {
            // try to apply settings immediately
            if (KrfbConfig::noWallet()) {
                InvitationsRfbServer::instance->closeKWallet();
            } else {
                InvitationsRfbServer::instance->openKWallet();
                // erase stored passwords from krfbconfig file
                KConfigGroup securityConfigGroup(KSharedConfig::openConfig(), "Security");
                securityConfigGroup.deleteEntry("desktopPassword");
                securityConfigGroup.deleteEntry("unattendedPassword");
            }
        }
282
    });
283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
}

void MainWindow::readProperties(const KConfigGroup& group)
{
    if (group.readEntry("Visible", true)) {
        show();
    }
    KMainWindow::readProperties(group);
}

void MainWindow::saveProperties(KConfigGroup& group)
{
    group.writeEntry("Visible", isVisible());
    KMainWindow::saveProperties(group);
}