* port dialogs to QFormLayout
[kdenetwork.git] / krdc / mainwindow.cpp
blob851c3ff9de1144a28daa98c354e700bd891a6840
1 /****************************************************************************
2 **
3 ** Copyright (C) 2007 Urs Wolfer <uwolfer @ kde.org>
4 **
5 ** This file is part of KDE.
6 **
7 ** This program is free software; you can redistribute it and/or modify
8 ** it under the terms of the GNU General Public License as published by
9 ** the Free Software Foundation; either version 2 of the License, or
10 ** (at your option) any later version.
12 ** This program is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ** GNU General Public License for more details.
17 ** You should have received a copy of the GNU General Public License
18 ** along with this program; see the file COPYING. If not, write to
19 ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 ** Boston, MA 02110-1301, USA.
22 ****************************************************************************/
24 #include "mainwindow.h"
26 #include "remoteview.h"
27 #include "settings.h"
28 #include "config/preferencesdialog.h"
29 #include "floatingtoolbar.h"
30 #include "bookmarkmanager.h"
31 #include "remotedesktopsmodel.h"
32 #include "systemtrayicon.h"
33 #ifdef BUILD_RDP
34 #include "rdpview.h"
35 #endif
36 #ifdef BUILD_NX
37 #include "nxview.h"
38 #endif
39 #ifdef BUILD_VNC
40 #include "vncview.h"
41 #endif
42 #ifdef BUILD_ZEROCONF
43 #include "zeroconfpage.h"
44 #endif
46 #include <KAction>
47 #include <KActionCollection>
48 #include <KActionMenu>
49 #include <KApplication>
50 #include <KComboBox>
51 #include <KEditToolBar>
52 #include <KIcon>
53 #include <KLocale>
54 #include <KMenuBar>
55 #include <KMessageBox>
56 #include <KNotifyConfigWidget>
57 #include <KPushButton>
58 #include <KShortcut>
59 #include <KShortcutsDialog>
60 #include <KStatusBar>
61 #include <KTabWidget>
62 #include <KToggleAction>
63 #include <KToggleFullScreenAction>
64 #include <KUrlNavigator>
66 #include <QClipboard>
67 #include <QCloseEvent>
68 #include <QDesktopWidget>
69 #include <QDockWidget>
70 #include <QFontMetrics>
71 #include <QHeaderView>
72 #include <QLabel>
73 #include <QLayout>
74 #include <QScrollArea>
75 #include <QTimer>
76 #include <QToolButton>
77 #include <QToolTip>
78 #include <QTreeView>
80 MainWindow::MainWindow(QWidget *parent)
81 : KXmlGuiWindow(parent),
82 m_fullscreenWindow(0),
83 m_toolBar(0),
84 m_topBottomBorder(0),
85 m_leftRightBorder(0),
86 m_currentRemoteView(-1),
87 m_showStartPage(false),
88 m_systemTrayIcon(0),
89 m_zeroconfPage(0)
91 setupActions();
93 setStandardToolBarMenuEnabled(true);
95 m_tabWidget = new KTabWidget(this);
96 m_tabWidget->setCloseButtonEnabled(true);
97 connect(m_tabWidget, SIGNAL(closeRequest(QWidget *)), SLOT(closeTab(QWidget *)));
99 m_tabWidget->setMinimumSize(600, 400);
100 setCentralWidget(m_tabWidget);
102 QDockWidget *remoteDesktopsDockWidget = new QDockWidget(this);
103 remoteDesktopsDockWidget->setObjectName("remoteDesktopsDockWidget"); // required for saving position / state
104 remoteDesktopsDockWidget->setWindowTitle(i18n("Remote desktops"));
105 QFontMetrics fontMetrics(remoteDesktopsDockWidget->font());
106 remoteDesktopsDockWidget->setMinimumWidth(fontMetrics.width("vnc://192.168.100.100:6000"));
107 actionCollection()->addAction("remote_desktop_dockwidget",
108 remoteDesktopsDockWidget->toggleViewAction());
109 QTreeView *remoteDesktopsTreeView = new QTreeView(remoteDesktopsDockWidget);
110 RemoteDesktopsModel *remoteDesktopsModel = new RemoteDesktopsModel(this);
111 connect(remoteDesktopsModel, SIGNAL(modelReset()), remoteDesktopsTreeView, SLOT(expandAll()));
112 remoteDesktopsTreeView->setModel(remoteDesktopsModel);
113 remoteDesktopsTreeView->header()->hide();
114 remoteDesktopsTreeView->expandAll();
115 connect(remoteDesktopsTreeView, SIGNAL(doubleClicked(const QModelIndex &)),
116 SLOT(openFromDockWidget(const QModelIndex &)));
118 remoteDesktopsDockWidget->setWidget(remoteDesktopsTreeView);
119 addDockWidget(Qt::LeftDockWidgetArea, remoteDesktopsDockWidget);
121 createGUI("krdcui.rc");
123 if (Settings::systemTrayIcon()) {
124 m_systemTrayIcon = new SystemTrayIcon(this);
125 m_systemTrayIcon->setVisible(true);
128 connect(m_tabWidget, SIGNAL(currentChanged(int)), SLOT(tabChanged(int)));
130 statusBar()->showMessage(i18n("KDE Remote Desktop Client started"));
132 updateActionStatus(); // disable remote view actions
134 if (Settings::showStartPage())
135 createStartPage();
137 setAutoSaveSettings(); // e.g toolbar position, mainwindow size, ...
139 m_addressNavigator->setFocus();
141 if (Settings::rememberSessions()) // give some time to create and show the window first
142 QTimer::singleShot(100, this, SLOT(restoreOpenSessions()));
145 MainWindow::~MainWindow()
149 void MainWindow::setupActions()
151 QAction *vncConnectionAction = actionCollection()->addAction("new_vnc_connection");
152 vncConnectionAction->setText(i18n("New VNC Connection..."));
153 vncConnectionAction->setIcon(KIcon("network-connect"));
154 connect(vncConnectionAction, SIGNAL(triggered()), SLOT(newVncConnection()));
155 #ifndef BUILD_VNC
156 vncConnectionAction->deleteLater();
157 #endif
159 QAction *nxConnectionAction = actionCollection()->addAction("new_nx_connection");
160 nxConnectionAction->setText(i18n("New NX Connection..."));
161 nxConnectionAction->setIcon(KIcon("network-connect"));
162 connect(nxConnectionAction, SIGNAL(triggered()), SLOT(newNxConnection()));
163 #ifndef BUILD_NX
164 nxConnectionAction->deleteLater();
165 #endif
167 QAction *rdpConnectionAction = actionCollection()->addAction("new_rdp_connection");
168 rdpConnectionAction->setText(i18n("New RDP Connection..."));
169 rdpConnectionAction->setIcon(KIcon("network-connect"));
170 connect(rdpConnectionAction, SIGNAL(triggered()), SLOT(newRdpConnection()));
171 #ifndef BUILD_RDP
172 rdpConnectionAction->deleteLater();
173 #endif
175 QAction *zeroconfAction = actionCollection()->addAction("zeroconf_page");
176 zeroconfAction->setText(i18n("Browse Remote Desktop Services on Local Network..."));
177 zeroconfAction->setIcon(KIcon("network-connect"));
178 connect(zeroconfAction, SIGNAL(triggered()), SLOT(createZeroconfPage()));
179 #ifndef BUILD_ZEROCONF
180 zeroconfAction->setVisible(false);
181 #endif
183 QAction *screenshotAction = actionCollection()->addAction("take_screenshot");
184 screenshotAction->setText(i18n("Copy Screenshot to Clipboard"));
185 screenshotAction->setIcon(KIcon("ksnapshot"));
186 connect(screenshotAction, SIGNAL(triggered()), SLOT(takeScreenshot()));
188 QAction *fullscreenAction = actionCollection()->addAction("switch_fullscreen");
189 fullscreenAction->setText(i18n("Switch to Fullscreen Mode"));
190 fullscreenAction->setIcon(KIcon("view-fullscreen"));
191 connect(fullscreenAction, SIGNAL(triggered()), SLOT(switchFullscreen()));
193 QAction *viewOnlyAction = actionCollection()->addAction("view_only");
194 viewOnlyAction->setCheckable(true);
195 viewOnlyAction->setText(i18n("View Only"));
196 viewOnlyAction->setIcon(KIcon("document-preview"));
197 connect(viewOnlyAction, SIGNAL(triggered(bool)), SLOT(viewOnly(bool)));
199 QAction *logoutAction = actionCollection()->addAction("logout");
200 logoutAction->setText(i18n("Log Out"));
201 logoutAction->setIcon(KIcon("system-log-out"));
202 connect(logoutAction, SIGNAL(triggered()), SLOT(logout()));
204 QAction *showLocalCursorAction = actionCollection()->addAction("show_local_cursor");
205 showLocalCursorAction->setCheckable(true);
206 showLocalCursorAction->setIcon(KIcon("input-mouse"));
207 showLocalCursorAction->setText(i18n("Show Local Cursor"));
208 connect(showLocalCursorAction, SIGNAL(triggered(bool)), SLOT(showLocalCursor(bool)));
210 QAction *grabAllKeysAction = actionCollection()->addAction("grab_all_keys");
211 grabAllKeysAction->setCheckable(true);
212 grabAllKeysAction->setIcon(KIcon("configure-shortcuts"));
213 grabAllKeysAction->setText(i18n("Grab all possible keys"));
214 connect(grabAllKeysAction, SIGNAL(triggered(bool)), SLOT(grabAllKeys(bool)));
216 QAction *scaleAction = actionCollection()->addAction("scale");
217 scaleAction->setCheckable(true);
218 scaleAction->setIcon(KIcon("zoom-fit-best"));
219 scaleAction->setText(i18n("Scale remote screen to fit window size"));
220 connect(scaleAction, SIGNAL(triggered(bool)), SLOT(scale(bool)));
222 QAction *quitAction = KStandardAction::quit(this, SLOT(quit()), actionCollection());
223 actionCollection()->addAction("quit", quitAction);
224 QAction *preferencesAction = KStandardAction::preferences(this, SLOT(preferences()), actionCollection());
225 actionCollection()->addAction("preferences", preferencesAction);
226 QAction *configToolbarAction = KStandardAction::configureToolbars(this, SLOT(configureToolbars()), actionCollection());
227 actionCollection()->addAction("configure_toolbars", configToolbarAction);
228 QAction *keyBindingsAction = KStandardAction::keyBindings(this, SLOT(configureKeys()), actionCollection());
229 actionCollection()->addAction("configure_keys", keyBindingsAction);
230 QAction *cinfigNotifyAction = KStandardAction::configureNotifications(this, SLOT(configureNotifications()), actionCollection());
231 cinfigNotifyAction->setVisible(false);
232 actionCollection()->addAction("configure_notifications", cinfigNotifyAction);
233 m_menubarAction = KStandardAction::showMenubar(this, SLOT(showMenubar()), actionCollection());
234 m_menubarAction->setChecked(!menuBar()->isHidden());
235 actionCollection()->addAction("settings_showmenubar", m_menubarAction);
237 QString initialProtocol;
238 #ifdef BUILD_RDP
239 initialProtocol = "rdp";
240 #endif
241 #ifdef BUILD_NX
242 initialProtocol = "nx";
243 #endif
244 #ifdef BUILD_VNC
245 initialProtocol = "vnc";
246 #endif
248 m_addressNavigator = new KUrlNavigator(0, KUrl(initialProtocol + "://"), this);
249 m_addressNavigator->setCustomProtocols(QStringList()
250 #ifdef BUILD_VNC
251 << "vnc"
252 #endif
253 #ifdef BUILD_NX
254 << "nx"
255 #endif
256 #ifdef BUILD_RDP
257 << "rdp"
258 #endif
260 m_addressNavigator->setUrlEditable(Settings::normalUrlInputLine());
261 connect(m_addressNavigator, SIGNAL(returnPressed()), SLOT(newConnection()));
263 QLabel *addressLabel = new QLabel(i18n("Remote desktop:"), this);
265 QWidget *addressWidget = new QWidget(this);
266 QHBoxLayout *addressLayout = new QHBoxLayout(addressWidget);
267 addressLayout->setMargin(0);
268 addressLayout->addWidget(addressLabel);
269 addressLayout->addWidget(m_addressNavigator, 1);
271 KAction *addressLineAction = new KAction(i18nc("Title for remote address input action", "Address"), this);
272 actionCollection()->addAction("address_line", addressLineAction);
273 addressLineAction->setDefaultWidget(addressWidget);
275 QAction *gotoAction = actionCollection()->addAction("goto_address");
276 gotoAction->setText(i18n("Goto Address"));
277 gotoAction->setIcon(KIcon("go-jump-locationbar"));
278 connect(gotoAction, SIGNAL(triggered()), SLOT(newConnection()));
280 KActionMenu *bookmarkMenu = new KActionMenu(i18n("Bookmarks"), actionCollection());
281 m_bookmarkManager = new BookmarkManager(actionCollection(), bookmarkMenu->menu(), this);
282 actionCollection()->addAction("bookmark" , bookmarkMenu);
283 connect(m_bookmarkManager, SIGNAL(openUrl(KUrl)), SLOT(newConnection(KUrl)));
286 void MainWindow::restoreOpenSessions()
288 QStringList list = Settings::openSessions();
289 QStringList::Iterator it = list.begin();
290 QStringList::Iterator end = list.end();
291 while (it != end) {
292 newConnection(*it);
293 ++it;
297 void MainWindow::newConnection(const KUrl &newUrl, bool switchFullscreenWhenConnected)
299 m_switchFullscreenWhenConnected = switchFullscreenWhenConnected;
301 KUrl url = newUrl.isEmpty() ? m_addressNavigator->uncommittedUrl() : newUrl;
303 if (!url.isValid() || (url.host().isEmpty() && url.port() < 0)
304 || !url.path().isEmpty()) {
305 KMessageBox::error(this,
306 i18n("The entered address does not have the required form."),
307 i18n("Malformed URL"));
308 return;
311 m_addressNavigator->setUrl(KUrl(url.scheme().toLower() + "://"));
313 RemoteView *view = 0;
315 if (url.scheme().toLower() == "vnc") {
316 #ifdef BUILD_VNC
317 view = new VncView(this, url);
318 #endif
319 } else if (url.scheme().toLower() == "nx") {
320 #ifdef BUILD_NX
321 view = new NxView(this, url);
322 #endif
323 } else if (url.scheme().toLower() == "rdp") {
324 #ifdef BUILD_RDP
325 view = new RdpView(this, url);
326 #endif
327 } else
329 KMessageBox::error(this,
330 i18n("The entered address cannot be handled."),
331 i18n("Unusable URL"));
332 return;
335 if (!view) {
336 KMessageBox::error(this, i18n("Support for %1:// has not been enabled during build.",
337 url.scheme().toLower()),
338 i18n("Unusable URL"));
339 return;
342 connect(view, SIGNAL(changeSize(int, int)), this, SLOT(resizeTabWidget(int, int)));
343 connect(view, SIGNAL(statusChanged(RemoteView::RemoteStatus)), this, SLOT(statusChanged(RemoteView::RemoteStatus)));
345 m_remoteViewList.append(view);
347 view->resize(0, 0);
349 int numNonRemoteView = 0;
350 if (m_showStartPage)
351 numNonRemoteView++;
352 if (m_zeroconfPage)
353 numNonRemoteView++;
355 QScrollArea *scrollArea = createScrollArea(m_tabWidget, m_remoteViewList.at(m_remoteViewList.count() - 1));
357 int newIndex = m_tabWidget->addTab(scrollArea, KIcon("krdc"), url.prettyUrl(KUrl::RemoveTrailingSlash));
358 m_tabWidget->setCurrentIndex(newIndex);
359 tabChanged(newIndex); // force to update m_currentRemoteView (tabChanged is not emitted when start page has been disabled)
361 view->start();
364 void MainWindow::openFromDockWidget(const QModelIndex &index)
366 QString data = index.data(Qt::UserRole).toString();
367 if (!data.isEmpty()) {
368 KUrl url(data);
369 // first check if url has already been opened; in case show the tab
370 for (int i = 0; i < m_remoteViewList.count(); i++) {
371 if (m_remoteViewList.at(i)->url() == url) {
372 int numNonRemoteView = 0;
373 if (m_showStartPage)
374 numNonRemoteView++;
375 if (m_zeroconfPage)
376 numNonRemoteView++;
377 m_tabWidget->setCurrentIndex(i + numNonRemoteView);
378 return;
381 newConnection(url);
385 void MainWindow::resizeTabWidget(int w, int h)
387 kDebug(5010) << "tabwidget resize: w: " << w << ", h: " << h;
389 if (m_topBottomBorder == 0) { // the values are not cached yet
390 QScrollArea *tmp = qobject_cast<QScrollArea *>(m_tabWidget->currentWidget());
392 m_leftRightBorder = m_tabWidget->width() - m_tabWidget->currentWidget()->width() + (2 * tmp->frameWidth());
393 m_topBottomBorder = m_tabWidget->height() - m_tabWidget->currentWidget()->height() + (2 * tmp->frameWidth());
395 kDebug(5010) << "tabwidget border: w: " << m_leftRightBorder << ", h: " << m_topBottomBorder;
398 int newTabWidth = w + m_leftRightBorder;
399 int newTabHeight = h + m_topBottomBorder;
401 QSize newWindowSize = size() - m_tabWidget->size() + QSize(newTabWidth, newTabHeight);
403 QSize desktopSize = QSize(QApplication::desktop()->availableGeometry().width(),
404 QApplication::desktop()->availableGeometry().height());
406 if ((newWindowSize.height() >= desktopSize.height()) || (newWindowSize.width() >= desktopSize.width())) {
407 kDebug(5010) << "remote desktop needs more place than available -> show window maximized";
408 setWindowState(windowState() | Qt::WindowMaximized);
409 return;
412 //WORKAROUND: QTabWidget resize problem. Let's see if there is a clean solution for this issue.
413 m_tabWidget->setMinimumSize(newTabWidth, newTabHeight);
414 m_tabWidget->adjustSize();
415 QCoreApplication::processEvents();
416 m_tabWidget->setMinimumSize(500, 400);
419 void MainWindow::statusChanged(RemoteView::RemoteStatus status)
421 kDebug(5010) << status;
423 // the remoteview is already deleted, so don't show it; otherwise it would crash
424 if (status == RemoteView::Disconnecting || status == RemoteView::Disconnected)
425 return;
427 QString host = m_remoteViewList.at(m_currentRemoteView)->host();
429 QString iconName = "krdc";
430 QString message;
432 switch (status) {
433 case RemoteView::Connecting:
434 iconName = "network-connect";
435 message = i18n("Connecting to %1", host);
436 break;
437 case RemoteView::Authenticating:
438 iconName = "dialog-password";
439 message = i18n("Authenticating at %1", host);
440 break;
441 case RemoteView::Preparing:
442 iconName = "view-history";
443 message = i18n("Preparing connection to %1", host);
444 break;
445 case RemoteView::Connected:
446 iconName = "krdc";
447 message = i18n("Connected to %1", host);
449 // when started with command line fullscreen argument
450 if (m_switchFullscreenWhenConnected) {
451 m_switchFullscreenWhenConnected = false;
452 switchFullscreen();
455 m_bookmarkManager->addHistoryBookmark();
457 break;
458 default:
459 break;
462 m_tabWidget->setTabIcon(m_tabWidget->currentIndex(), KIcon(iconName));
463 statusBar()->showMessage(message);
466 void MainWindow::takeScreenshot()
468 QPixmap snapshot = QPixmap::grabWidget(m_remoteViewList.at(m_currentRemoteView));
470 QApplication::clipboard()->setPixmap(snapshot);
473 void MainWindow::switchFullscreen()
475 kDebug(5010);
477 if (m_fullscreenWindow) {
478 show();
479 restoreGeometry(m_mainWindowGeometry);
481 m_fullscreenWindow->setWindowState(0);
482 m_fullscreenWindow->hide();
484 QScrollArea *scrollArea = createScrollArea(m_tabWidget, m_remoteViewList.at(m_currentRemoteView));
486 int currentTab = m_tabWidget->currentIndex();
487 m_tabWidget->insertTab(currentTab, scrollArea, m_tabWidget->tabIcon(currentTab), m_tabWidget->tabText(currentTab));
488 m_tabWidget->removeTab(m_tabWidget->currentIndex());
489 m_tabWidget->setCurrentIndex(currentTab);
491 resizeTabWidget(m_remoteViewList.at(m_currentRemoteView)->sizeHint().width(),
492 m_remoteViewList.at(m_currentRemoteView)->sizeHint().height());
494 if (m_toolBar) {
495 m_toolBar->hideAndDestroy();
496 m_toolBar->deleteLater();
497 m_toolBar = 0;
500 actionCollection()->action("switch_fullscreen")->setIcon(KIcon("view-fullscreen"));
501 actionCollection()->action("switch_fullscreen")->setText(i18n("Switch to Fullscreen Mode"));
503 m_fullscreenWindow->deleteLater();
505 m_fullscreenWindow = 0;
506 } else {
507 m_fullscreenWindow = new QWidget(this, Qt::Window);
508 m_fullscreenWindow->setWindowTitle(i18nc("window title when in fullscreen mode (for example displayed in tasklist)",
509 "KDE Remote Desktop Client (Fullscreen)"));
511 QScrollArea *scrollArea = createScrollArea(m_fullscreenWindow, m_remoteViewList.at(m_currentRemoteView));
512 scrollArea->setFrameShape(QFrame::NoFrame);
514 QVBoxLayout *fullscreenLayout = new QVBoxLayout(m_fullscreenWindow);
515 fullscreenLayout->setMargin(0);
516 fullscreenLayout->addWidget(scrollArea);
518 MinimizePixel *minimizePixel = new MinimizePixel(m_fullscreenWindow);
519 minimizePixel->winId(); // force it to be a native widget (prevents problem with QX11EmbedContainer)
520 connect(minimizePixel, SIGNAL(rightClicked()), m_fullscreenWindow, SLOT(showMinimized()));
522 m_fullscreenWindow->show();
524 KToggleFullScreenAction::setFullScreen(m_fullscreenWindow, true);
526 // show the toolbar after we have switched to fullscreen mode
527 QTimer::singleShot(100, this, SLOT(showRemoteViewToolbar()));
529 m_mainWindowGeometry = saveGeometry();
530 hide();
534 QScrollArea *MainWindow::createScrollArea(QWidget *parent, RemoteView *remoteView)
536 RemoteViewScrollArea *scrollArea = new RemoteViewScrollArea(parent);
537 scrollArea->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
539 connect(scrollArea, SIGNAL(resized(int, int)), remoteView, SLOT(scaleResize(int, int)));
541 QPalette palette = scrollArea->palette();
542 palette.setColor(QPalette::Dark, Settings::backgroundColor());
543 scrollArea->setPalette(palette);
545 scrollArea->setBackgroundRole(QPalette::Dark);
546 scrollArea->setWidget(remoteView);
548 return scrollArea;
551 void MainWindow::logout()
553 kDebug(5010);
555 if (m_fullscreenWindow) { // first close fullscreen view
556 switchFullscreen();
559 QWidget *tmp = m_tabWidget->currentWidget();
561 m_remoteViewList.removeAt(m_currentRemoteView);
563 m_tabWidget->removeTab(m_tabWidget->currentIndex());
565 tmp->deleteLater();
568 void MainWindow::closeTab(QWidget *widget)
570 int index = m_tabWidget->indexOf(widget);
572 kDebug(5010) << index;
574 if (m_showStartPage && index == 0) {
575 KMessageBox::information(this, i18n("The start page cannot be closed. "
576 "If you want to disable it, you can do so in the settings."));
577 return;
580 #ifdef BUILD_ZEROCONF
581 if (widget == m_zeroconfPage) {
582 closeZeroconfPage();
583 return;
585 #endif
587 int numNonRemoteView = 0;
588 if (m_showStartPage)
589 numNonRemoteView++;
590 if (m_zeroconfPage)
591 numNonRemoteView++;
593 if (index - numNonRemoteView >= 0)
594 m_remoteViewList.removeAt(index - numNonRemoteView);
596 m_tabWidget->removeTab(index);
598 widget->deleteLater();
601 void MainWindow::showLocalCursor(bool showLocalCursor)
603 kDebug(5010) << showLocalCursor;
605 m_remoteViewList.at(m_currentRemoteView)->showDotCursor(showLocalCursor ? RemoteView::CursorOn : RemoteView::CursorOff);
608 void MainWindow::viewOnly(bool viewOnly)
610 kDebug(5010) << viewOnly;
612 m_remoteViewList.at(m_currentRemoteView)->setViewOnly(viewOnly);
615 void MainWindow::grabAllKeys(bool grabAllKeys)
617 kDebug(5010);
619 m_remoteViewList.at(m_currentRemoteView)->setGrabAllKeys(grabAllKeys);
622 void MainWindow::scale(bool scale)
624 kDebug(5010);
626 m_remoteViewList.at(m_currentRemoteView)->enableScaling(scale);
629 void MainWindow::showRemoteViewToolbar()
631 kDebug(5010);
633 if (!m_toolBar) {
634 actionCollection()->action("switch_fullscreen")->setIcon(KIcon("view-restore"));
635 actionCollection()->action("switch_fullscreen")->setText(i18n("Switch to Window Mode"));
637 m_toolBar = new FloatingToolBar(m_fullscreenWindow, m_fullscreenWindow);
638 m_toolBar->winId(); // force it to be a native widget (prevents problem with QX11EmbedContainer)
639 m_toolBar->setSide(FloatingToolBar::Top);
641 QLabel *hostLabel = new QLabel(m_remoteViewList.at(m_currentRemoteView)->url().prettyUrl(KUrl::RemoveTrailingSlash), m_toolBar);
642 hostLabel->setMargin(4);
643 QFont font(hostLabel->font());
644 font.setBold(true);
645 hostLabel->setFont(font);
646 m_toolBar->addWidget(hostLabel);
648 #if 0 //TODO: implement functionality
649 KComboBox *sessionComboBox = new KComboBox(m_toolBar);
650 sessionComboBox->setEditable(false);
651 sessionComboBox->addItem(i18n("Switch to..."));
652 for (int i = 0; i < m_remoteViewList.count(); i++) {
653 sessionComboBox->addItem(m_remoteViewList.at(i)->url().prettyUrl(KUrl::RemoveTrailingSlash));
655 sessionComboBox->setVisible(m_remoteViewList.count() > 1); // just show it if there are sessions to switch
656 m_toolBar->addWidget(sessionComboBox);
657 #endif
659 m_toolBar->addAction(actionCollection()->action("switch_fullscreen"));
661 QAction *minimizeAction = new QAction(m_toolBar);
662 minimizeAction->setIcon(KIcon("window-suppressed"));
663 minimizeAction->setText(i18n("Minimize Fullscreen Window"));
664 connect(minimizeAction, SIGNAL(triggered()), m_fullscreenWindow, SLOT(showMinimized()));
665 m_toolBar->addAction(minimizeAction);
667 m_toolBar->addAction(actionCollection()->action("take_screenshot"));
668 m_toolBar->addAction(actionCollection()->action("view_only"));
669 m_toolBar->addAction(actionCollection()->action("show_local_cursor"));
670 m_toolBar->addAction(actionCollection()->action("grab_all_keys"));
671 m_toolBar->addAction(actionCollection()->action("scale"));
672 m_toolBar->addAction(actionCollection()->action("logout"));
674 QAction *stickToolBarAction = new QAction(m_toolBar);
675 stickToolBarAction->setCheckable(true);
676 stickToolBarAction->setIcon(KIcon("object-locked"));
677 stickToolBarAction->setText(i18n("Stick Toolbar"));
678 connect(stickToolBarAction, SIGNAL(triggered(bool)), m_toolBar, SLOT(setSticky(bool)));
679 m_toolBar->addAction(stickToolBarAction);
682 m_toolBar->showAndAnimate();
685 void MainWindow::updateActionStatus()
687 kDebug(5010) << m_tabWidget->currentIndex();
689 bool enabled;
691 if ((m_showStartPage && (m_tabWidget->currentIndex() == 0)) ||
692 #ifdef BUILD_ZEROCONF
693 (m_zeroconfPage && (m_tabWidget->currentIndex() == m_tabWidget->indexOf(m_zeroconfPage))) ||
694 #endif
695 (!m_showStartPage && (m_tabWidget->currentIndex() < 0)))
696 enabled = false;
697 else
698 enabled = true;
700 actionCollection()->action("switch_fullscreen")->setEnabled(enabled);
701 actionCollection()->action("take_screenshot")->setEnabled(enabled);
702 actionCollection()->action("view_only")->setEnabled(enabled);
703 actionCollection()->action("grab_all_keys")->setEnabled(enabled);
704 actionCollection()->action("scale")->setEnabled(enabled);
705 actionCollection()->action("logout")->setEnabled(enabled);
707 bool viewOnlyChecked = false;
708 if (m_currentRemoteView >= 0)
709 viewOnlyChecked = enabled && m_remoteViewList.at(m_currentRemoteView)->viewOnly();
710 actionCollection()->action("view_only")->setChecked(viewOnlyChecked);
712 bool showLocalCursorChecked = false;
713 if (m_currentRemoteView >= 0)
714 showLocalCursorChecked = enabled && m_remoteViewList.at(m_currentRemoteView)->dotCursorState() == RemoteView::CursorOn;
715 actionCollection()->action("show_local_cursor")->setChecked(showLocalCursorChecked);
717 bool showLocalCursorVisible = false;
718 if (m_currentRemoteView >= 0)
719 showLocalCursorVisible = enabled && m_remoteViewList.at(m_currentRemoteView)->supportsLocalCursor();
720 actionCollection()->action("show_local_cursor")->setVisible(showLocalCursorVisible);
722 bool scaleVisible = false;
723 if (m_currentRemoteView >= 0)
724 scaleVisible = enabled && m_remoteViewList.at(m_currentRemoteView)->supportsScaling();
725 actionCollection()->action("scale")->setVisible(scaleVisible);
728 void MainWindow::preferences()
730 // An instance of your dialog could be already created and could be
731 // cached, in which case you want to display the cached dialog
732 // instead of creating another one
733 if (PreferencesDialog::showDialog("preferences"))
734 return;
736 // KConfigDialog didn't find an instance of this dialog, so lets
737 // create it:
738 PreferencesDialog *dialog = new PreferencesDialog(this, Settings::self());
740 // User edited the configuration - update your local copies of the
741 // configuration data
742 connect(dialog, SIGNAL(settingsChanged(const QString&)),
743 this, SLOT(updateConfiguration()));
745 dialog->show();
748 void MainWindow::updateConfiguration()
750 m_addressNavigator->setUrlEditable(Settings::normalUrlInputLine());
752 if (Settings::systemTrayIcon() && !m_systemTrayIcon) {
753 m_systemTrayIcon = new SystemTrayIcon(this);
754 m_systemTrayIcon->setVisible(true);
755 } else if (m_systemTrayIcon) {
756 delete m_systemTrayIcon;
757 m_systemTrayIcon = 0;
760 if (Settings::showStartPage() && !m_showStartPage)
761 createStartPage();
762 else if (!Settings::showStartPage() && m_showStartPage) {
763 m_tabWidget->removeTab(0);
764 m_showStartPage = false;
766 updateActionStatus();
768 // update the scroll areas background color
769 int numNonRemoteView = 0;
770 if (m_showStartPage)
771 numNonRemoteView++;
772 if (m_zeroconfPage)
773 numNonRemoteView++;
774 for (int i = numNonRemoteView; i < m_tabWidget->count(); i++) {
775 QPalette palette = m_tabWidget->widget(i)->palette();
776 palette.setColor(QPalette::Dark, Settings::backgroundColor());
777 m_tabWidget->widget(i)->setPalette(palette);
781 void MainWindow::quit()
783 bool haveRemoteConnections = m_remoteViewList.count();
784 if (!haveRemoteConnections || KMessageBox::warningContinueCancel(this,
785 i18n("Are you sure you want to quit the KDE Remote Desktop Client?"),
786 i18n("Confirm Quit"),
787 KStandardGuiItem::quit(), KStandardGuiItem::cancel(),
788 "DoNotAskBeforeExit") == KMessageBox::Continue) {
790 if (Settings::rememberSessions()) { // remember open remote views for next startup
791 QStringList list;
792 for (int i = 0; i < m_remoteViewList.count(); i++) {
793 kDebug(5010) << m_remoteViewList.at(i)->url();
794 list.append(m_remoteViewList.at(i)->url().prettyUrl(KUrl::RemoveTrailingSlash));
796 Settings::setOpenSessions(list);
799 Settings::self()->writeConfig();
801 qApp->quit();
805 void MainWindow::configureNotifications()
807 KNotifyConfigWidget::configure(this);
810 void MainWindow::configureKeys()
812 KShortcutsDialog::configure(actionCollection());
815 void MainWindow::configureToolbars()
817 KEditToolBar edit(actionCollection());
818 connect(&edit, SIGNAL(newToolbarConfig()), this, SLOT(newToolbarConfig()));
819 edit.exec();
822 void MainWindow::showMenubar()
824 if (m_menubarAction->isChecked())
825 menuBar()->show();
826 else
827 menuBar()->hide();
830 void MainWindow::closeEvent(QCloseEvent *event)
832 event->ignore();
834 if (Settings::systemTrayIcon()) {
835 hide(); // just hide the mainwindow, keep it in systemtray
836 } else {
837 quit();
841 void MainWindow::tabChanged(int index)
843 kDebug(5010) << index;
845 int numNonRemoteView = 0;
846 if (m_showStartPage)
847 numNonRemoteView++;
848 if (m_zeroconfPage)
849 numNonRemoteView++;
851 m_currentRemoteView = index - numNonRemoteView;
853 QString tabTitle = m_tabWidget->tabText(index).remove('&');
855 setCaption(tabTitle == i18n("Start Page") ? QString() : tabTitle);
857 updateActionStatus();
860 void MainWindow::createStartPage()
862 m_showStartPage = true;
864 QWidget *startWidget = new QWidget(this);
865 startWidget->setStyleSheet("QWidget { background-color: palette(base) }");
867 QVBoxLayout *startLayout = new QVBoxLayout(startWidget);
869 QLabel *headerLabel = new QLabel(this);
870 headerLabel->setText(i18n("<h1>KDE Remote Desktop Client</h1><br /><br />What would you like to do?<br />"));
872 QLabel *headerIconLabel = new QLabel(this);
873 headerIconLabel->setPixmap(KIcon("krdc").pixmap(128));
875 QHBoxLayout *headerLayout = new QHBoxLayout;
876 headerLayout->setMargin(20);
877 headerLayout->addWidget(headerLabel, 1, Qt::AlignTop);
878 headerLayout->addWidget(headerIconLabel);
880 KPushButton *vncConnectButton = new KPushButton(this);
881 vncConnectButton->setStyleSheet("KPushButton { padding: 12px; margin: 10px; }");
882 vncConnectButton->setIcon(KIcon(actionCollection()->action("new_vnc_connection")->icon()));
883 vncConnectButton->setText(i18n("Connect to a VNC Remote Desktop"));
884 connect(vncConnectButton, SIGNAL(clicked()), SLOT(newVncConnection()));
885 #ifndef BUILD_VNC
886 vncConnectButton->setVisible(false);
887 #endif
889 KPushButton *nxConnectButton = new KPushButton(this);
890 nxConnectButton->setStyleSheet("KPushButton { padding: 12px; margin: 10px; }");
891 nxConnectButton->setIcon(KIcon(actionCollection()->action("new_nx_connection")->icon()));
892 nxConnectButton->setText(i18n("Connect to a NX Remote Desktop"));
893 connect(nxConnectButton, SIGNAL(clicked()), SLOT(newNxConnection()));
894 #ifndef BUILD_NX
895 nxConnectButton->setVisible(false);
896 #endif
898 KPushButton *rdpConnectButton = new KPushButton(this);
899 rdpConnectButton->setStyleSheet("KPushButton { padding: 12px; margin: 10px; }");
900 rdpConnectButton->setIcon(KIcon(actionCollection()->action("new_rdp_connection")->icon()));
901 rdpConnectButton->setText(i18n("Connect to a Windows Remote Desktop (RDP)"));
902 connect(rdpConnectButton, SIGNAL(clicked()), SLOT(newRdpConnection()));
903 #ifndef BUILD_RDP
904 rdpConnectButton->setVisible(false);
905 #endif
907 KPushButton *zeroconfButton = new KPushButton(this);
908 zeroconfButton->setStyleSheet("KPushButton { padding: 12px; margin: 10px; }");
909 zeroconfButton->setIcon(KIcon(actionCollection()->action("zeroconf_page")->icon()));
910 zeroconfButton->setText(i18n("Browse Remote Desktop Services on Local Network"));
911 connect(zeroconfButton, SIGNAL(clicked()), SLOT(createZeroconfPage()));
912 #ifndef BUILD_ZEROCONF
913 zeroconfButton->setVisible(false);
914 #endif
916 startLayout->addLayout(headerLayout);
917 startLayout->addWidget(vncConnectButton);
918 startLayout->addWidget(nxConnectButton);
919 startLayout->addWidget(rdpConnectButton);
920 startLayout->addWidget(zeroconfButton);
921 startLayout->addStretch();
923 m_tabWidget->insertTab(0, startWidget, KIcon("krdc"), i18n("Start Page"));
926 void MainWindow::newVncConnection()
928 m_addressNavigator->setUrl(KUrl("vnc://"));
929 m_addressNavigator->setFocus();
931 QToolTip::showText(m_addressNavigator->pos() + pos() + QPoint(m_addressNavigator->width(),
932 m_addressNavigator->height() + 20),
933 i18n("<html>Enter the address here.<br />"
934 "<i>Example: vncserver:1 (host:port / screen)</i></html>"), this);
937 void MainWindow::newNxConnection()
939 m_addressNavigator->setUrl(KUrl("nx://"));
940 m_addressNavigator->setFocus();
942 QToolTip::showText(m_addressNavigator->pos() + pos() + QPoint(m_addressNavigator->width(),
943 m_addressNavigator->height() + 20),
944 i18n("<html>Enter the address here.<br />"
945 "<i>Example: nxserver (host)</i></html>"), this);
948 void MainWindow::newRdpConnection()
950 m_addressNavigator->setUrl(KUrl("rdp://"));
951 m_addressNavigator->setFocus();
953 QToolTip::showText(m_addressNavigator->pos() + pos() + QPoint(m_addressNavigator->width(),
954 m_addressNavigator->height() + 20),
955 i18n("<html>Enter the address here. Port is optional.<br />"
956 "<i>Example: rdpserver:3389 (host:port)</i></html>"), this);
959 void MainWindow::createZeroconfPage()
961 #ifdef BUILD_ZEROCONF
962 if (m_zeroconfPage)
963 return;
965 m_zeroconfPage = new ZeroconfPage(this);
966 connect(m_zeroconfPage, SIGNAL(newConnection(const KUrl, bool)), this, SLOT(newConnection(const KUrl, bool)));
967 connect(m_zeroconfPage, SIGNAL(closeZeroconfPage()), this, SLOT(closeZeroconfPage()));
968 int zeroconfTabIndex = m_tabWidget->insertTab(m_showStartPage ? 1 : 0, m_zeroconfPage, KIcon("krdc"), i18n("Browse Local Network"));
969 m_tabWidget->setCurrentIndex(zeroconfTabIndex);
970 #endif
973 void MainWindow::closeZeroconfPage()
975 #ifdef BUILD_ZEROCONF
976 int index = m_tabWidget->indexOf(m_zeroconfPage);
977 m_tabWidget->removeTab(index);
978 m_zeroconfPage->deleteLater();
979 m_zeroconfPage = 0;
980 tabChanged(index); // force update again because m_zeroconfPage was not null before
981 #endif
984 QList<RemoteView *> MainWindow::remoteViewList() const
986 return m_remoteViewList;
989 int MainWindow::currentRemoteView() const
991 return m_currentRemoteView;
994 #include "mainwindow.moc"