Greatly improve experience for LDAP (e.g. MS Active Directory) administrators.
[kdenetwork.git] / krdc / rdp / rdpview.cpp
blob3ce8fa368d2aadb46aa9f23a0002a805a152361b
1 /****************************************************************************
2 **
3 ** Copyright (C) 2002 Arend van Beelen jr. <arend@auton.nl>
4 ** Copyright (C) 2007 Urs Wolfer <uwolfer @ kde.org>
5 **
6 ** This file is part of KDE.
7 **
8 ** This program is free software; you can redistribute it and/or modify
9 ** it under the terms of the GNU General Public License as published by
10 ** the Free Software Foundation; either version 2 of the License, or
11 ** (at your option) any later version.
13 ** This program is distributed in the hope that it will be useful,
14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ** GNU General Public License for more details.
18 ** You should have received a copy of the GNU General Public License
19 ** along with this program; see the file COPYING. If not, write to
20 ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 ** Boston, MA 02110-1301, USA.
23 ****************************************************************************/
25 #include "rdpview.h"
27 #include "settings.h"
29 #include <KInputDialog>
30 #include <KMessageBox>
31 #include <KPasswordDialog>
33 #include <QX11EmbedContainer>
34 #include <QEvent>
36 RdpView::RdpView(QWidget *parent,
37 const KUrl &url,
38 const QString &user, const QString &password,
39 int flags, const QString &domain,
40 const QString &shell, const QString &directory)
41 : RemoteView(parent),
42 m_user(user),
43 m_password(password),
44 m_flags(flags),
45 m_domain(domain),
46 m_shell(shell),
47 m_directory(directory),
48 m_quitFlag(false),
49 m_process(NULL)
51 m_url = url;
52 m_host = url.host();
53 m_port = url.port();
55 if (m_port <= 0) {
56 m_port = TCP_PORT_RDP;
59 m_container = new QX11EmbedContainer(this);
60 m_container->installEventFilter(this);
63 RdpView::~RdpView()
65 startQuitting();
68 // filter out key and mouse events to the container if we are view only
69 //FIXME: X11 events are passed to the app before getting caught in the Qt event processing
70 bool RdpView::eventFilter(QObject *obj, QEvent *event)
72 if (m_viewOnly) {
73 if (event->type() == QEvent::KeyPress ||
74 event->type() == QEvent::KeyRelease ||
75 event->type() == QEvent::MouseButtonDblClick ||
76 event->type() == QEvent::MouseButtonPress ||
77 event->type() == QEvent::MouseButtonRelease ||
78 event->type() == QEvent::MouseMove)
79 return true;
81 return RemoteView::eventFilter(obj, event);
84 QSize RdpView::framebufferSize()
86 return m_container->minimumSizeHint();
89 QSize RdpView::sizeHint() const
91 return maximumSize();
94 void RdpView::startQuitting()
96 kDebug(5012) << "About to quit";
97 m_quitFlag = true;
98 if (m_process) {
99 m_process->terminate();
100 m_process->waitForFinished(1000);
101 m_container->discardClient();
105 bool RdpView::isQuitting()
107 return m_quitFlag;
110 bool RdpView::start()
112 m_hostPreferences = new RdpHostPreferences(m_url.prettyUrl(KUrl::RemoveTrailingSlash), false, this);
114 m_container->show();
116 if (m_hostPreferences->walletSupport()) {
117 if (m_url.userName().isEmpty()) {
118 QString userName;
119 bool ok = true;
121 userName = KInputDialog::getText(i18n("Enter Username"),
122 i18n("Please enter the username you would like to use for login."),
123 Settings::defaultRdpUserName(), &ok, this);
125 if (ok)
126 m_url.setUserName(userName);
129 if (!m_url.userName().isEmpty()) {
130 bool useLdapLogin = Settings::recognizeLdapLogins() && m_url.userName().contains('\\');
131 kDebug(5012) << "Is LDAP login:" << useLdapLogin << m_url.userName();
132 QString walletPassword = readWalletPassword(useLdapLogin);
134 if (!walletPassword.isNull())
135 m_url.setPassword(walletPassword);
136 else {
137 KPasswordDialog dialog(this);
138 dialog.setPrompt(i18n("Access to the system requires a password."));
139 if (dialog.exec() == KPasswordDialog::Accepted) {
140 m_url.setPassword(dialog.password());
142 if (m_hostPreferences->walletSupport())
143 saveWalletPassword(dialog.password(), useLdapLogin);
149 m_process = new QProcess(m_container);
151 QStringList arguments;
152 arguments << "-g" << (QString::number(m_hostPreferences->width()) + 'x' +
153 QString::number(m_hostPreferences->height()));
154 arguments << "-k" << m_hostPreferences->keyboardLayout();
156 if (!m_url.userName().isEmpty())
157 arguments << "-u" << m_url.userName();
158 else
159 arguments << "-u" << "";
161 if (!m_url.password().isNull())
162 arguments << "-p" << m_url.password();
164 arguments << "-X" << QString::number(m_container->winId());
165 arguments << "-a" << QString::number((m_hostPreferences->colorDepth() + 1) * 8);
167 QString sound;
168 switch (m_hostPreferences->sound()) {
169 case 0:
170 sound = "local";
171 break;
172 case 1:
173 sound = "remote";
174 break;
175 case 2:
176 default:
177 sound = "off";
179 arguments << "-r" << "sound:" + sound;
181 if (!m_hostPreferences->extraOptions().isEmpty()) {
182 QStringList additionalArguments = m_hostPreferences->extraOptions().split(' ');
183 arguments += additionalArguments;
186 arguments << (m_host + ':' + QString::number(m_port));
188 kDebug(5012) << arguments;
190 setStatus(Connecting);
192 connect(m_process, SIGNAL(error(QProcess::ProcessError)), SLOT(processError(QProcess::ProcessError)));
193 connect(m_process, SIGNAL(readyReadStandardError()), SLOT(receivedStandardError()));
194 connect(m_container, SIGNAL(clientClosed()), SLOT(connectionClosed()));
195 connect(m_container, SIGNAL(clientIsEmbedded()), SLOT(connectionOpened()));
197 m_process->start("rdesktop", arguments);
199 return true;
202 void RdpView::switchFullscreen(bool on)
204 if (on == true) {
205 m_container->grabKeyboard();
209 void RdpView::connectionOpened()
211 kDebug(5012) << "Connection opened";
212 QSize size = m_container->minimumSizeHint();
213 kDebug(5012) << "Size hint: " << size.width() << " " << size.height();
214 setStatus(Connected);
215 setFixedSize(size);
216 resize(size);
217 m_container->setFixedSize(size);
218 emit changeSize(size.width(), size.height());
219 emit connected();
220 setFocus();
223 void RdpView::connectionClosed()
225 emit disconnected();
226 setStatus(Disconnected);
227 m_quitFlag = true;
230 void RdpView::processError(QProcess::ProcessError error)
232 if (m_quitFlag) // do not try to show error messages while quitting (prevent crashes)
233 return;
235 if (m_status == Connecting) {
236 setStatus(Disconnected);
238 if (error == QProcess::FailedToStart) {
239 KMessageBox::error(0, i18n("Could not start \"rdesktop\"; make sure rdesktop is properly installed."),
240 i18n("RDP Failure"));
241 return;
244 if (m_clientVersion.isEmpty()) {
245 KMessageBox::error(0, i18n("Connection attempt to host failed."),
246 i18n("Connection Failure"));
247 } else {
248 KMessageBox::error(0, i18n("The version of \"rdesktop\" you are using (%1) is too old:\n"
249 "rdesktop 1.3.2 or greater is required.", m_clientVersion),
250 i18n("RDP Failure"));
252 emit disconnectedError();
256 void RdpView::receivedStandardError()
258 QString output(m_process->readAllStandardError());
259 QString line;
260 int i = 0;
261 while (!(line = output.section('\n', i, i)).isEmpty()) {
262 if (line.startsWith("Version ")) {
263 m_clientVersion = line.section(' ', 1, 1);
264 m_clientVersion = m_clientVersion.left(m_clientVersion.length() - 1);
265 return;
266 } else {
267 kDebug(5012) << "Process error output: " << line;
269 i++;
273 #include "rdpview.moc"