• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdenetwork API Reference
  • KDE Home
  • Contact Us
 

krdc

  • sources
  • kde-4.14
  • kdenetwork
  • krdc
mainwindow.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2007 - 2013 Urs Wolfer <uwolfer @ kde.org>
4 ** Copyright (C) 2009 - 2010 Tony Murray <murraytony @ gmail.com>
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.
12 **
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.
17 **
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.
22 **
23 ****************************************************************************/
24 
25 #include "mainwindow.h"
26 
27 #include "remoteview.h"
28 #include "settings.h"
29 #include "config/preferencesdialog.h"
30 #include "floatingtoolbar.h"
31 #include "bookmarkmanager.h"
32 #include "connectiondelegate.h"
33 #include "remotedesktopsmodel.h"
34 #include "systemtrayicon.h"
35 #include "tabbedviewwidget.h"
36 #include "hostpreferences.h"
37 
38 #ifdef TELEPATHY_SUPPORT
39 #include "tubesmanager.h"
40 #endif
41 
42 #include <KAction>
43 #include <KActionCollection>
44 #include <KActionMenu>
45 #include <KComboBox>
46 #include <KIcon>
47 #include <KInputDialog>
48 #include <KLineEdit>
49 #include <KLocale>
50 #include <KMenu>
51 #include <KMenuBar>
52 #include <KMessageBox>
53 #include <KNotifyConfigWidget>
54 #include <KPluginInfo>
55 #include <KPushButton>
56 #include <KStatusBar>
57 #include <KToggleAction>
58 #include <KToggleFullScreenAction>
59 #include <KServiceTypeTrader>
60 
61 #include <QClipboard>
62 #include <QDockWidget>
63 #include <QFontMetrics>
64 #include <QGroupBox>
65 #include <QHBoxLayout>
66 #include <QHeaderView>
67 #include <QLabel>
68 #include <QLayout>
69 #include <QScrollArea>
70 #include <QSortFilterProxyModel>
71 #include <QTableView>
72 #include <QTimer>
73 #include <QToolBar>
74 #include <QVBoxLayout>
75 
76 MainWindow::MainWindow(QWidget *parent)
77  : KXmlGuiWindow(parent),
78  m_fullscreenWindow(0),
79  m_protocolInput(0),
80  m_addressInput(0),
81  m_toolBar(0),
82  m_currentRemoteView(-1),
83  m_systemTrayIcon(0),
84  m_dockWidgetTableView(0),
85  m_newConnectionTableView(0),
86 #ifdef TELEPATHY_SUPPORT
87  m_tubesManager(0),
88 #endif
89  m_newConnectionWidget(0)
90 {
91  loadAllPlugins();
92 
93  setupActions();
94 
95  setStandardToolBarMenuEnabled(true);
96 
97  m_tabWidget = new TabbedViewWidget(this);
98  m_tabWidget->setMovable(true);
99  m_tabWidget->setTabPosition((KTabWidget::TabPosition) Settings::tabPosition());
100 
101 #if QT_VERSION >= 0x040500
102  m_tabWidget->setTabsClosable(Settings::tabCloseButton());
103 #else
104  m_tabWidget->setCloseButtonEnabled(Settings::tabCloseButton());
105 #endif
106 
107  connect(m_tabWidget, SIGNAL(closeRequest(QWidget*)), SLOT(closeTab(QWidget*)));
108 
109  if (Settings::tabMiddleClick())
110  connect(m_tabWidget, SIGNAL(mouseMiddleClick(QWidget*)), SLOT(closeTab(QWidget*)));
111 
112  connect(m_tabWidget, SIGNAL(mouseDoubleClick(QWidget*)), SLOT(openTabSettings(QWidget*)));
113  connect(m_tabWidget, SIGNAL(mouseDoubleClick()), SLOT(newConnectionPage()));
114  connect(m_tabWidget, SIGNAL(contextMenu(QWidget*,QPoint)), SLOT(tabContextMenu(QWidget*,QPoint)));
115 
116  m_tabWidget->setMinimumSize(600, 400);
117  setCentralWidget(m_tabWidget);
118 
119  createDockWidget();
120 
121  setupGUI(ToolBar | Keys | Save | Create);
122 
123  if (Settings::systemTrayIcon()) {
124  m_systemTrayIcon = new SystemTrayIcon(this);
125  if(m_fullscreenWindow) m_systemTrayIcon->setAssociatedWidget(m_fullscreenWindow);
126  }
127 
128  connect(m_tabWidget, SIGNAL(currentChanged(int)), SLOT(tabChanged(int)));
129 
130  if (Settings::showStatusBar())
131  statusBar()->showMessage(i18n("KDE Remote Desktop Client started"));
132 
133  updateActionStatus(); // disable remote view actions
134 
135  if (Settings::openSessions().count() == 0) // just create a new connection tab if there are no open sessions
136  m_tabWidget->addTab(newConnectionWidget(), i18n("New Connection"));
137 
138  if (Settings::rememberSessions()) // give some time to create and show the window first
139  QTimer::singleShot(100, this, SLOT(restoreOpenSessions()));
140 }
141 
142 MainWindow::~MainWindow()
143 {
144 }
145 
146 void MainWindow::setupActions()
147 {
148  QAction *connectionAction = actionCollection()->addAction("new_connection");
149  connectionAction->setText(i18n("New Connection"));
150  connectionAction->setIcon(KIcon("network-connect"));
151  connect(connectionAction, SIGNAL(triggered()), SLOT(newConnectionPage()));
152 
153  QAction *screenshotAction = actionCollection()->addAction("take_screenshot");
154  screenshotAction->setText(i18n("Copy Screenshot to Clipboard"));
155  screenshotAction->setIconText(i18n("Screenshot"));
156  screenshotAction->setIcon(KIcon("ksnapshot"));
157  connect(screenshotAction, SIGNAL(triggered()), SLOT(takeScreenshot()));
158 
159  KAction *fullscreenAction = actionCollection()->addAction("switch_fullscreen"); // note: please do not switch to KStandardShortcut unless you know what you are doing (see history of this file)
160  fullscreenAction->setText(i18n("Switch to Full Screen Mode"));
161  fullscreenAction->setIconText(i18n("Full Screen"));
162  fullscreenAction->setIcon(KIcon("view-fullscreen"));
163  fullscreenAction->setShortcut(KStandardShortcut::fullScreen());
164  connect(fullscreenAction, SIGNAL(triggered()), SLOT(switchFullscreen()));
165 
166  QAction *viewOnlyAction = actionCollection()->addAction("view_only");
167  viewOnlyAction->setCheckable(true);
168  viewOnlyAction->setText(i18n("View Only"));
169  viewOnlyAction->setIcon(KIcon("document-preview"));
170  connect(viewOnlyAction, SIGNAL(triggered(bool)), SLOT(viewOnly(bool)));
171 
172  KAction *disconnectAction = actionCollection()->addAction("disconnect");
173  disconnectAction->setText(i18n("Disconnect"));
174  disconnectAction->setIcon(KIcon("network-disconnect"));
175  disconnectAction->setShortcut(QKeySequence::Close);
176  connect(disconnectAction, SIGNAL(triggered()), SLOT(disconnectHost()));
177 
178  QAction *showLocalCursorAction = actionCollection()->addAction("show_local_cursor");
179  showLocalCursorAction->setCheckable(true);
180  showLocalCursorAction->setIcon(KIcon("input-mouse"));
181  showLocalCursorAction->setText(i18n("Show Local Cursor"));
182  showLocalCursorAction->setIconText(i18n("Local Cursor"));
183  connect(showLocalCursorAction, SIGNAL(triggered(bool)), SLOT(showLocalCursor(bool)));
184 
185  QAction *grabAllKeysAction = actionCollection()->addAction("grab_all_keys");
186  grabAllKeysAction->setCheckable(true);
187  grabAllKeysAction->setIcon(KIcon("configure-shortcuts"));
188  grabAllKeysAction->setText(i18n("Grab All Possible Keys"));
189  grabAllKeysAction->setIconText(i18n("Grab Keys"));
190  connect(grabAllKeysAction, SIGNAL(triggered(bool)), SLOT(grabAllKeys(bool)));
191 
192  QAction *scaleAction = actionCollection()->addAction("scale");
193  scaleAction->setCheckable(true);
194  scaleAction->setIcon(KIcon("zoom-fit-best"));
195  scaleAction->setText(i18n("Scale Remote Screen to Fit Window Size"));
196  scaleAction->setIconText(i18n("Scale"));
197  connect(scaleAction, SIGNAL(triggered(bool)), SLOT(scale(bool)));
198 
199  KStandardAction::quit(this, SLOT(quit()), actionCollection());
200  KStandardAction::preferences(this, SLOT(preferences()), actionCollection());
201  QAction *configNotifyAction = KStandardAction::configureNotifications(this, SLOT(configureNotifications()), actionCollection());
202  configNotifyAction->setVisible(false);
203  m_menubarAction = KStandardAction::showMenubar(this, SLOT(showMenubar()), actionCollection());
204  m_menubarAction->setChecked(!menuBar()->isHidden());
205 
206  KActionMenu *bookmarkMenu = new KActionMenu(i18n("Bookmarks"), actionCollection());
207  m_bookmarkManager = new BookmarkManager(actionCollection(), bookmarkMenu->menu(), this);
208  actionCollection()->addAction("bookmark" , bookmarkMenu);
209  connect(m_bookmarkManager, SIGNAL(openUrl(KUrl)), SLOT(newConnection(KUrl)));
210 }
211 
212 void MainWindow::loadAllPlugins()
213 {
214  const KService::List offers = KServiceTypeTrader::self()->query("KRDC/Plugin");
215 
216  KConfigGroup conf(KGlobal::config(), "Plugins");
217 
218  for (int i = 0; i < offers.size(); i++) {
219  KService::Ptr offer = offers[i];
220 
221  RemoteViewFactory *remoteView;
222 
223  KPluginInfo description(offer);
224  description.load(conf);
225 
226  const bool selected = description.isPluginEnabled();
227 
228  if (selected) {
229  if ((remoteView = createPluginFromService(offer)) != 0) {
230  kDebug(5010) << "### Plugin " + description.name() + " found ###";
231  kDebug(5010) << "# Version:" << description.version();
232  kDebug(5010) << "# Description:" << description.comment();
233  kDebug(5010) << "# Author:" << description.author();
234  const int sorting = offer->property("X-KDE-KRDC-Sorting").toInt();
235  kDebug(5010) << "# Sorting:" << sorting;
236 
237  m_remoteViewFactories.insert(sorting, remoteView);
238  } else {
239  kDebug(5010) << "Error loading KRDC plugin (" << (offers[i])->library() << ')';
240  }
241  } else {
242  kDebug(5010) << "# Plugin " + description.name() + " found, however it's not activated, skipping...";
243  continue;
244  }
245  }
246 
247 #ifdef TELEPATHY_SUPPORT
248  /* Start tube handler */
249  m_tubesManager = new TubesManager(this);
250  connect(m_tubesManager, SIGNAL(newConnection(KUrl)), SLOT(newConnection(KUrl)));
251 #endif
252 }
253 
254 RemoteViewFactory *MainWindow::createPluginFromService(const KService::Ptr &service)
255 {
256  //try to load the specified library
257  KPluginFactory *factory = KPluginLoader(service->library()).factory();
258 
259  if (!factory) {
260  kError(5010) << "KPluginFactory could not load the plugin:" << service->library();
261  return 0;
262  }
263 
264  RemoteViewFactory *plugin = factory->create<RemoteViewFactory>();
265 
266  return plugin;
267 }
268 
269 void MainWindow::restoreOpenSessions()
270 {
271  const QStringList list = Settings::openSessions();
272  QStringList::ConstIterator it = list.begin();
273  QStringList::ConstIterator end = list.end();
274  while (it != end) {
275  newConnection(*it);
276  ++it;
277  }
278 }
279 
280 KUrl MainWindow::getInputUrl()
281 {
282  return KUrl(m_protocolInput->currentText() + "://" + m_addressInput->text());
283 }
284 
285 void MainWindow::newConnection(const KUrl &newUrl, bool switchFullscreenWhenConnected, const QString &tabName)
286 {
287  m_switchFullscreenWhenConnected = switchFullscreenWhenConnected;
288 
289  const KUrl url = newUrl.isEmpty() ? getInputUrl() : newUrl;
290 
291  if (!url.isValid() || (url.host().isEmpty() && url.port() < 0)
292  || (!url.path().isEmpty() && url.path() != QLatin1String("/"))) {
293  KMessageBox::error(this,
294  i18n("The entered address does not have the required form.\n Syntax: [username@]host[:port]"),
295  i18n("Malformed URL"));
296  return;
297  }
298 
299  if (m_protocolInput && m_addressInput) {
300  int index = m_protocolInput->findText(url.protocol());
301  if (index>=0) m_protocolInput->setCurrentIndex(index);
302  m_addressInput->setText(url.authority());
303  }
304 
305  RemoteView *view = 0;
306  KConfigGroup configGroup = Settings::self()->config()->group("hostpreferences").group(url.prettyUrl(KUrl::RemoveTrailingSlash));
307 
308  foreach(RemoteViewFactory *factory, m_remoteViewFactories) {
309  if (factory->supportsUrl(url)) {
310  view = factory->createView(this, url, configGroup);
311  kDebug(5010) << "Found plugin to handle url (" + url.url() + "): " + view->metaObject()->className();
312  break;
313  }
314  }
315 
316  if (!view) {
317  KMessageBox::error(this,
318  i18n("The entered address cannot be handled."),
319  i18n("Unusable URL"));
320  return;
321  }
322 
323  // Configure the view
324  HostPreferences* prefs = view->hostPreferences();
325  if (! prefs->showDialogIfNeeded(this)) {
326  delete view;
327  return;
328  }
329 
330  view->showDotCursor(prefs->showLocalCursor() ? RemoteView::CursorOn : RemoteView::CursorOff);
331  view->setViewOnly(prefs->viewOnly());
332  if (! switchFullscreenWhenConnected) view->enableScaling(prefs->windowedScale());
333 
334  connect(view, SIGNAL(framebufferSizeChanged(int,int)), this, SLOT(resizeTabWidget(int,int)));
335  connect(view, SIGNAL(statusChanged(RemoteView::RemoteStatus)), this, SLOT(statusChanged(RemoteView::RemoteStatus)));
336  connect(view, SIGNAL(disconnected()), this, SLOT(disconnectHost()));
337 
338  view->winId(); // native widget workaround for bug 253365
339  QScrollArea *scrollArea = createScrollArea(m_tabWidget, view);
340 
341  const int indexOfNewConnectionWidget = m_tabWidget->indexOf(m_newConnectionWidget);
342  if (indexOfNewConnectionWidget >= 0)
343  m_tabWidget->removeTab(indexOfNewConnectionWidget);
344 
345  const int newIndex = m_tabWidget->addTab(scrollArea, KIcon("krdc"), tabName.isEmpty() ? url.prettyUrl(KUrl::RemoveTrailingSlash) : tabName);
346  m_tabWidget->setCurrentIndex(newIndex);
347  m_remoteViewMap.insert(m_tabWidget->widget(newIndex), view);
348  tabChanged(newIndex); // force to update m_currentRemoteView (tabChanged is not emitted when start page has been disabled)
349 
350  view->start();
351 }
352 
353 void MainWindow::openFromRemoteDesktopsModel(const QModelIndex &index)
354 {
355  const QString urlString = index.data(10001).toString();
356  const QString nameString = index.data(10003).toString();
357  if (!urlString.isEmpty()) {
358  const KUrl url(urlString);
359  // first check if url has already been opened; in case show the tab
360  foreach (QWidget *widget, m_remoteViewMap.keys()) {
361  if (m_remoteViewMap.value(widget)->url() == url) {
362  m_tabWidget->setCurrentWidget(widget);
363  return;
364  }
365  }
366 
367  newConnection(url, false, nameString);
368  }
369 }
370 
371 void MainWindow::resizeTabWidget(int w, int h)
372 {
373  kDebug(5010) << "tabwidget resize, view size: w: " << w << ", h: " << h;
374  if (m_fullscreenWindow) {
375  kDebug(5010) << "in fullscreen mode, refusing to resize";
376  return;
377  }
378 
379  const QSize viewSize = QSize(w,h);
380  QDesktopWidget *desktop = QApplication::desktop();
381 
382  if (Settings::fullscreenOnConnect()) {
383  int currentScreen = desktop->screenNumber(this);
384  const QSize screenSize = desktop->screenGeometry(currentScreen).size();
385 
386  if (screenSize == viewSize) {
387  kDebug(5010) << "screen size equal to target view size -> switch to fullscreen mode";
388  switchFullscreen();
389  return;
390  }
391  }
392 
393  if (Settings::resizeOnConnect()) {
394  QWidget* currentWidget = m_tabWidget->currentWidget();
395  const QSize newWindowSize = size() - currentWidget->frameSize() + viewSize;
396 
397  const QSize desktopSize = desktop->availableGeometry().size();
398  kDebug(5010) << "new window size: " << newWindowSize << " available space:" << desktopSize;
399 
400  if ((newWindowSize.width() >= desktopSize.width()) || (newWindowSize.height() >= desktopSize.height())) {
401  kDebug(5010) << "remote desktop needs more space than available -> show window maximized";
402  setWindowState(windowState() | Qt::WindowMaximized);
403  return;
404  }
405 
406  resize(newWindowSize);
407  }
408 }
409 
410 void MainWindow::statusChanged(RemoteView::RemoteStatus status)
411 {
412  kDebug(5010) << status;
413 
414  // the remoteview is already deleted, so don't show it; otherwise it would crash
415  if (status == RemoteView::Disconnecting || status == RemoteView::Disconnected)
416  return;
417 
418  RemoteView *view = qobject_cast<RemoteView*>(QObject::sender());
419  const QString host = view->host();
420 
421  QString iconName = "krdc";
422  QString message;
423 
424  switch (status) {
425  case RemoteView::Connecting:
426  iconName = "network-connect";
427  message = i18n("Connecting to %1", host);
428  break;
429  case RemoteView::Authenticating:
430  iconName = "dialog-password";
431  message = i18n("Authenticating at %1", host);
432  break;
433  case RemoteView::Preparing:
434  iconName = "view-history";
435  message = i18n("Preparing connection to %1", host);
436  break;
437  case RemoteView::Connected:
438  iconName = "krdc";
439  message = i18n("Connected to %1", host);
440 
441  if (view->grabAllKeys() != view->hostPreferences()->grabAllKeys()) {
442  view->setGrabAllKeys(view->hostPreferences()->grabAllKeys());
443  updateActionStatus();
444  }
445 
446  // when started with command line fullscreen argument
447  if (m_switchFullscreenWhenConnected) {
448  m_switchFullscreenWhenConnected = false;
449  switchFullscreen();
450  }
451 
452  if (Settings::rememberHistory()) {
453  m_bookmarkManager->addHistoryBookmark(view);
454  }
455 
456  break;
457  default:
458  break;
459  }
460 
461  m_tabWidget->setTabIcon(m_tabWidget->indexOf(view), KIcon(iconName));
462  if (Settings::showStatusBar())
463  statusBar()->showMessage(message);
464 }
465 
466 void MainWindow::takeScreenshot()
467 {
468  const QPixmap snapshot = currentRemoteView()->takeScreenshot();
469 
470  QApplication::clipboard()->setPixmap(snapshot);
471 }
472 
473 void MainWindow::switchFullscreen()
474 {
475  kDebug(5010);
476 
477  if (m_fullscreenWindow) {
478  // Leaving full screen mode
479  m_fullscreenWindow->setWindowState(0);
480  m_fullscreenWindow->hide();
481 
482  m_tabWidget->setTabBarHidden(m_tabWidget->count() <= 1 && !Settings::showTabBar());
483  m_tabWidget->setDocumentMode(false);
484  setCentralWidget(m_tabWidget);
485 
486  show();
487  restoreGeometry(m_mainWindowGeometry);
488  if (m_systemTrayIcon) m_systemTrayIcon->setAssociatedWidget(this);
489 
490  foreach (RemoteView * view, m_remoteViewMap.values()) {
491  view->enableScaling(view->hostPreferences()->windowedScale());
492  }
493 
494  if (m_toolBar) {
495  m_toolBar->hideAndDestroy();
496  m_toolBar->deleteLater();
497  m_toolBar = 0;
498  }
499 
500  actionCollection()->action("switch_fullscreen")->setIcon(KIcon("view-fullscreen"));
501  actionCollection()->action("switch_fullscreen")->setText(i18n("Switch to Full Screen Mode"));
502  actionCollection()->action("switch_fullscreen")->setIconText(i18n("Full Screen"));
503 
504  m_fullscreenWindow->deleteLater();
505  m_fullscreenWindow = 0;
506  } else {
507  // Entering full screen mode
508  m_fullscreenWindow = new QWidget(this, Qt::Window);
509  m_fullscreenWindow->setWindowTitle(i18nc("window title when in full screen mode (for example displayed in tasklist)",
510  "KDE Remote Desktop Client (Full Screen)"));
511 
512  m_mainWindowGeometry = saveGeometry();
513 
514  m_tabWidget->setTabBarHidden(true);
515  m_tabWidget->setDocumentMode(true);
516 
517  foreach(RemoteView *currentView, m_remoteViewMap) {
518  currentView->enableScaling(currentView->hostPreferences()->fullscreenScale());
519  }
520 
521  QVBoxLayout *fullscreenLayout = new QVBoxLayout(m_fullscreenWindow);
522  fullscreenLayout->setContentsMargins(QMargins(0, 0, 0, 0));
523  fullscreenLayout->addWidget(m_tabWidget);
524 
525  KToggleFullScreenAction::setFullScreen(m_fullscreenWindow, true);
526 
527  MinimizePixel *minimizePixel = new MinimizePixel(m_fullscreenWindow);
528  minimizePixel->winId(); // force it to be a native widget (prevents problem with QX11EmbedContainer)
529  connect(minimizePixel, SIGNAL(rightClicked()), m_fullscreenWindow, SLOT(showMinimized()));
530  m_fullscreenWindow->installEventFilter(this);
531 
532  m_fullscreenWindow->show();
533  hide(); // hide after showing the new window so it stays on the same screen
534 
535  if (m_systemTrayIcon) m_systemTrayIcon->setAssociatedWidget(m_fullscreenWindow);
536 
537  actionCollection()->action("switch_fullscreen")->setIcon(KIcon("view-restore"));
538  actionCollection()->action("switch_fullscreen")->setText(i18n("Switch to Window Mode"));
539  actionCollection()->action("switch_fullscreen")->setIconText(i18n("Window Mode"));
540  showRemoteViewToolbar();
541  }
542  if (m_tabWidget->currentWidget() == m_newConnectionWidget) {
543  m_addressInput->setFocus();
544  }
545 }
546 
547 QScrollArea *MainWindow::createScrollArea(QWidget *parent, RemoteView *remoteView)
548 {
549  RemoteViewScrollArea *scrollArea = new RemoteViewScrollArea(parent);
550  scrollArea->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
551 
552  connect(scrollArea, SIGNAL(resized(int,int)), remoteView, SLOT(scaleResize(int,int)));
553 
554  QPalette palette = scrollArea->palette();
555  palette.setColor(QPalette::Dark, Settings::backgroundColor());
556  scrollArea->setPalette(palette);
557 
558  scrollArea->setBackgroundRole(QPalette::Dark);
559  scrollArea->setFrameStyle(QFrame::NoFrame);
560 
561  scrollArea->setWidget(remoteView);
562 
563  return scrollArea;
564 }
565 
566 void MainWindow::disconnectHost()
567 {
568  kDebug(5010);
569 
570  RemoteView *view = qobject_cast<RemoteView*>(QObject::sender());
571 
572  QWidget *widgetToDelete;
573  if (view) {
574  widgetToDelete = (QWidget*) view->parent()->parent();
575  m_remoteViewMap.remove(m_remoteViewMap.key(view));
576  } else {
577  widgetToDelete = m_tabWidget->currentWidget();
578  view = currentRemoteView();
579  m_remoteViewMap.remove(m_remoteViewMap.key(view));
580  }
581 
582  saveHostPrefs(view);
583  view->startQuitting(); // some deconstructors can't properly quit, so quit early
584  m_tabWidget->removePage(widgetToDelete);
585  widgetToDelete->deleteLater();
586 #ifdef TELEPATHY_SUPPORT
587  m_tubesManager->closeTube(view->url());
588 #endif
589 
590  // if closing the last connection, create new connection tab
591  if (m_tabWidget->count() == 0) {
592  newConnectionPage(false);
593  }
594 
595  // if the newConnectionWidget is the only tab and we are fullscreen, switch to window mode
596  if (m_fullscreenWindow && m_tabWidget->count() == 1 && m_tabWidget->currentWidget() == m_newConnectionWidget) {
597  switchFullscreen();
598  }
599 }
600 
601 void MainWindow::closeTab(QWidget *widget)
602 {
603  bool isNewConnectionPage = widget == m_newConnectionWidget;
604 
605  if (!isNewConnectionPage) {
606  RemoteView *view = m_remoteViewMap.value(widget);
607  m_remoteViewMap.remove(m_remoteViewMap.key(view));
608  view->startQuitting();
609 #ifdef TELEPATHY_SUPPORT
610  m_tubesManager->closeTube(view->url());
611 #endif
612  widget->deleteLater();
613  }
614 
615  m_tabWidget->removePage(widget);
616 
617  // if closing the last connection, create new connection tab
618  if (m_tabWidget->count() == 0) {
619  newConnectionPage(false);
620  }
621 
622  // if the newConnectionWidget is the only tab and we are fullscreen, switch to window mode
623  if (m_fullscreenWindow && m_tabWidget->count() == 1 && m_tabWidget->currentWidget() == m_newConnectionWidget) {
624  switchFullscreen();
625  }
626 }
627 
628 void MainWindow::openTabSettings(QWidget *widget)
629 {
630  RemoteViewScrollArea *scrollArea = qobject_cast<RemoteViewScrollArea*>(widget);
631  if (!scrollArea) return;
632  RemoteView *view = qobject_cast<RemoteView*>(scrollArea->widget());
633  if (!view) return;
634 
635  const QString url = view->url().url();
636  kDebug(5010) << url;
637 
638  showSettingsDialog(url);
639 }
640 
641 void MainWindow::showSettingsDialog(const QString &url)
642 {
643  HostPreferences *prefs = 0;
644 
645  foreach(RemoteViewFactory *factory, remoteViewFactoriesList()) {
646  if (factory->supportsUrl(url)) {
647  prefs = factory->createHostPreferences(Settings::self()->config()->group("hostpreferences").group(url), this);
648  if (prefs) {
649  kDebug(5010) << "Found plugin to handle url (" + url + "): " + prefs->metaObject()->className();
650  } else {
651  kDebug(5010) << "Found plugin to handle url (" + url + "), but plugin does not provide preferences";
652  }
653  }
654  }
655 
656  if (prefs) {
657  prefs->setShownWhileConnected(true);
658  prefs->showDialog(this);
659  } else {
660  KMessageBox::error(this,
661  i18n("The selected host cannot be handled."),
662  i18n("Unusable URL"));
663  }
664 }
665 
666 void MainWindow::showConnectionContextMenu(const QPoint &pos)
667 {
668  // QTableView does not take headers into account when it does mapToGlobal(), so calculate the offset
669  QPoint offset = QPoint(m_newConnectionTableView->verticalHeader()->size().width(),
670  m_newConnectionTableView->horizontalHeader()->size().height());
671  QModelIndex index = m_newConnectionTableView->indexAt(pos);
672 
673  if (!index.isValid())
674  return;
675 
676  const QString url = index.data(10001).toString();
677  const QString title = index.model()->index(index.row(), RemoteDesktopsModel::Title).data(Qt::DisplayRole).toString();
678  const QString source = index.model()->index(index.row(), RemoteDesktopsModel::Source).data(Qt::DisplayRole).toString();
679 
680  KMenu *menu = new KMenu(m_newConnectionTableView);
681  menu->addTitle(url);
682 
683  QAction *connectAction = menu->addAction(KIcon("network-connect"), i18n("Connect"));
684  QAction *renameAction = menu->addAction(KIcon("edit-rename"), i18n("Rename"));
685  QAction *settingsAction = menu->addAction(KIcon("configure"), i18n("Settings"));
686  QAction *deleteAction = menu->addAction(KIcon("edit-delete"), i18n("Delete"));
687 
688  // not very clean, but it works,
689  if (!(source == i18nc("Where each displayed link comes from", "Bookmarks") ||
690  source == i18nc("Where each displayed link comes from", "History"))) {
691  renameAction->setEnabled(false);
692  deleteAction->setEnabled(false);
693  }
694 
695  QAction *selectedAction = menu->exec(m_newConnectionTableView->mapToGlobal(pos + offset));
696 
697  if (selectedAction == connectAction) {
698  openFromRemoteDesktopsModel(index);
699  } else if (selectedAction == renameAction) {
700  //TODO: use inline editor if possible
701  bool ok = false;
702  const QString newTitle = KInputDialog::getText(i18n("Rename %1", title), i18n("Rename %1 to", title), title, &ok, this);
703  if (ok && !newTitle.isEmpty()) {
704  BookmarkManager::updateTitle(m_bookmarkManager->getManager(), url, newTitle);
705  }
706  } else if (selectedAction == settingsAction) {
707  showSettingsDialog(url);
708  } else if (selectedAction == deleteAction) {
709 
710  if (KMessageBox::warningContinueCancel(this, i18n("Are you sure you want to delete %1?", url), i18n("Delete %1", title),
711  KStandardGuiItem::del()) == KMessageBox::Continue) {
712  BookmarkManager::removeByUrl(m_bookmarkManager->getManager(), url);
713  }
714  }
715 
716  menu->deleteLater();
717 }
718 
719 void MainWindow::tabContextMenu(QWidget *widget, const QPoint &point)
720 {
721  RemoteViewScrollArea *scrollArea = qobject_cast<RemoteViewScrollArea*>(widget);
722  if (!scrollArea) return;
723  RemoteView *view = qobject_cast<RemoteView*>(scrollArea->widget());
724  if (!view) return;
725 
726  const QString url = view->url().prettyUrl(KUrl::RemoveTrailingSlash);
727  kDebug(5010) << url;
728 
729  KMenu *menu = new KMenu(this);
730  menu->addTitle(url);
731  QAction *bookmarkAction = menu->addAction(KIcon("bookmark-new"), i18n("Add Bookmark"));
732  QAction *closeAction = menu->addAction(KIcon("tab-close"), i18n("Close Tab"));
733  QAction *selectedAction = menu->exec(point);
734  if (selectedAction) {
735  if (selectedAction == closeAction) {
736  closeTab(widget);
737  } else if (selectedAction == bookmarkAction) {
738  m_bookmarkManager->addManualBookmark(url, url);
739  }
740  }
741  menu->deleteLater();
742 }
743 
744 void MainWindow::showLocalCursor(bool showLocalCursor)
745 {
746  kDebug(5010) << showLocalCursor;
747 
748  RemoteView* view = currentRemoteView();
749  view->showDotCursor(showLocalCursor ? RemoteView::CursorOn : RemoteView::CursorOff);
750  view->hostPreferences()->setShowLocalCursor(showLocalCursor);
751  saveHostPrefs(view);
752 }
753 
754 void MainWindow::viewOnly(bool viewOnly)
755 {
756  kDebug(5010) << viewOnly;
757 
758  RemoteView* view = currentRemoteView();
759  view->setViewOnly(viewOnly);
760  view->hostPreferences()->setViewOnly(viewOnly);
761  saveHostPrefs(view);
762 }
763 
764 void MainWindow::grabAllKeys(bool grabAllKeys)
765 {
766  kDebug(5010);
767 
768  RemoteView* view = currentRemoteView();
769  view->setGrabAllKeys(grabAllKeys);
770  view->hostPreferences()->setGrabAllKeys(grabAllKeys);
771  saveHostPrefs(view);
772 }
773 
774 void MainWindow::scale(bool scale)
775 {
776  kDebug(5010);
777 
778  RemoteView* view = currentRemoteView();
779  view->enableScaling(scale);
780  if (m_fullscreenWindow)
781  view->hostPreferences()->setFullscreenScale(scale);
782  else
783  view->hostPreferences()->setWindowedScale(scale);
784 
785  saveHostPrefs(view);
786 }
787 
788 void MainWindow::showRemoteViewToolbar()
789 {
790  kDebug(5010);
791 
792  if (!m_toolBar) {
793  m_toolBar = new FloatingToolBar(m_fullscreenWindow, m_fullscreenWindow);
794  m_toolBar->winId(); // force it to be a native widget (prevents problem with QX11EmbedContainer)
795  m_toolBar->setSide(FloatingToolBar::Top);
796 
797  KComboBox *sessionComboBox = new KComboBox(m_toolBar);
798  sessionComboBox->setStyleSheet("QComboBox:!editable{background:transparent;}");
799  sessionComboBox->setModel(m_tabWidget->getModel());
800  sessionComboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
801  sessionComboBox->setCurrentIndex(m_tabWidget->currentIndex());
802  connect(sessionComboBox, SIGNAL(activated(int)), m_tabWidget, SLOT(setCurrentIndex(int)));
803  connect(m_tabWidget, SIGNAL(currentChanged(int)), sessionComboBox, SLOT(setCurrentIndex(int)));
804  m_toolBar->addWidget(sessionComboBox);
805 
806  QToolBar *buttonBox = new QToolBar(m_toolBar);
807 
808  buttonBox->addAction(actionCollection()->action("new_connection"));
809  buttonBox->addAction(actionCollection()->action("switch_fullscreen"));
810 
811  QAction *minimizeAction = new QAction(m_toolBar);
812  minimizeAction->setIcon(KIcon("go-down"));
813  minimizeAction->setText(i18n("Minimize Full Screen Window"));
814  connect(minimizeAction, SIGNAL(triggered()), m_fullscreenWindow, SLOT(showMinimized()));
815  buttonBox->addAction(minimizeAction);
816 
817  buttonBox->addAction(actionCollection()->action("take_screenshot"));
818  buttonBox->addAction(actionCollection()->action("view_only"));
819  buttonBox->addAction(actionCollection()->action("show_local_cursor"));
820  buttonBox->addAction(actionCollection()->action("grab_all_keys"));
821  buttonBox->addAction(actionCollection()->action("scale"));
822  buttonBox->addAction(actionCollection()->action("disconnect"));
823  buttonBox->addAction(actionCollection()->action("file_quit"));
824 
825  QAction *stickToolBarAction = new QAction(m_toolBar);
826  stickToolBarAction->setCheckable(true);
827  stickToolBarAction->setIcon(KIcon("object-locked"));
828  stickToolBarAction->setText(i18n("Stick Toolbar"));
829  connect(stickToolBarAction, SIGNAL(triggered(bool)), m_toolBar, SLOT(setSticky(bool)));
830  buttonBox->addAction(stickToolBarAction);
831 
832  m_toolBar->addWidget(buttonBox);
833  }
834 }
835 
836 void setActionStatus(QAction* action, bool enabled, bool visible, bool checked)
837 {
838  action->setEnabled(enabled);
839  action->setVisible(visible);
840  action->setChecked(checked);
841 }
842 
843 void MainWindow::updateActionStatus()
844 {
845  kDebug(5010) << m_tabWidget->currentIndex();
846 
847  bool enabled = true;
848 
849  if (m_tabWidget->currentWidget() == m_newConnectionWidget)
850  enabled = false;
851 
852  RemoteView* view = (m_currentRemoteView >= 0 && enabled) ? currentRemoteView() : 0;
853 
854  actionCollection()->action("take_screenshot")->setEnabled(enabled);
855  actionCollection()->action("disconnect")->setEnabled(enabled);
856 
857  setActionStatus(actionCollection()->action("view_only"),
858  enabled,
859  true,
860  view ? view->viewOnly() : false);
861 
862  setActionStatus(actionCollection()->action("show_local_cursor"),
863  enabled,
864  view ? view->supportsLocalCursor() : false,
865  view ? view->dotCursorState() == RemoteView::CursorOn : false);
866 
867  setActionStatus(actionCollection()->action("scale"),
868  enabled,
869  view ? view->supportsScaling() : false,
870  view ? view->scaling() : false);
871 
872  setActionStatus(actionCollection()->action("grab_all_keys"),
873  enabled,
874  enabled,
875  view ? view->grabAllKeys() : false);
876 }
877 
878 void MainWindow::preferences()
879 {
880  // An instance of your dialog could be already created and could be
881  // cached, in which case you want to display the cached dialog
882  // instead of creating another one
883  if (PreferencesDialog::showDialog("preferences"))
884  return;
885 
886  // KConfigDialog didn't find an instance of this dialog, so lets
887  // create it:
888  PreferencesDialog *dialog = new PreferencesDialog(this, Settings::self());
889 
890  // User edited the configuration - update your local copies of the
891  // configuration data
892  connect(dialog, SIGNAL(settingsChanged(QString)),
893  this, SLOT(updateConfiguration()));
894 
895  dialog->show();
896 }
897 
898 void MainWindow::updateConfiguration()
899 {
900  if (!Settings::showStatusBar())
901  statusBar()->deleteLater();
902  else
903  statusBar()->showMessage(""); // force creation of statusbar
904 
905  m_tabWidget->setTabBarHidden((m_tabWidget->count() <= 1 && !Settings::showTabBar()) || m_fullscreenWindow);
906  m_tabWidget->setTabPosition((KTabWidget::TabPosition) Settings::tabPosition());
907 #if QT_VERSION >= 0x040500
908  m_tabWidget->setTabsClosable(Settings::tabCloseButton());
909 #else
910  m_tabWidget->setCloseButtonEnabled(Settings::tabCloseButton());
911 #endif
912  disconnect(m_tabWidget, SIGNAL(mouseMiddleClick(QWidget*)), this, SLOT(closeTab(QWidget*))); // just be sure it is not connected twice
913  if (Settings::tabMiddleClick())
914  connect(m_tabWidget, SIGNAL(mouseMiddleClick(QWidget*)), SLOT(closeTab(QWidget*)));
915 
916  if (Settings::systemTrayIcon() && !m_systemTrayIcon) {
917  m_systemTrayIcon = new SystemTrayIcon(this);
918  if(m_fullscreenWindow) m_systemTrayIcon->setAssociatedWidget(m_fullscreenWindow);
919  } else if (m_systemTrayIcon) {
920  delete m_systemTrayIcon;
921  m_systemTrayIcon = 0;
922  }
923 
924  // update the scroll areas background color
925  for (int i = 0; i < m_tabWidget->count(); ++i) {
926  QPalette palette = m_tabWidget->widget(i)->palette();
927  palette.setColor(QPalette::Dark, Settings::backgroundColor());
928  m_tabWidget->widget(i)->setPalette(palette);
929  }
930 
931  // Send update configuration message to all views
932  foreach (RemoteView *view, m_remoteViewMap.values()) {
933  view->updateConfiguration();
934  }
935 
936 }
937 
938 void MainWindow::quit(bool systemEvent)
939 {
940  const bool haveRemoteConnections = !m_remoteViewMap.isEmpty();
941  if (systemEvent || !haveRemoteConnections || KMessageBox::warningContinueCancel(this,
942  i18n("Are you sure you want to quit the KDE Remote Desktop Client?"),
943  i18n("Confirm Quit"),
944  KStandardGuiItem::quit(), KStandardGuiItem::cancel(),
945  "DoNotAskBeforeExit") == KMessageBox::Continue) {
946 
947  if (Settings::rememberSessions()) { // remember open remote views for next startup
948  QStringList list;
949  foreach (RemoteView *view, m_remoteViewMap.values()) {
950  kDebug(5010) << view->url();
951  list.append(view->url().prettyUrl(KUrl::RemoveTrailingSlash));
952  }
953  Settings::setOpenSessions(list);
954  }
955 
956  saveHostPrefs();
957 
958  foreach (RemoteView *view, m_remoteViewMap.values()) {
959  view->startQuitting();
960  }
961 
962  Settings::self()->writeConfig();
963 
964  qApp->quit();
965  }
966 }
967 
968 void MainWindow::configureNotifications()
969 {
970  KNotifyConfigWidget::configure(this);
971 }
972 
973 void MainWindow::showMenubar()
974 {
975  if (m_menubarAction->isChecked())
976  menuBar()->show();
977  else
978  menuBar()->hide();
979 }
980 
981 bool MainWindow::eventFilter(QObject *obj, QEvent *event)
982 {
983  // check for close events from the fullscreen window.
984  if (obj == m_fullscreenWindow && event->type() == QEvent::Close) {
985  quit(true);
986  }
987  // allow other events to pass through.
988  return QObject::eventFilter(obj, event);
989 }
990 
991 void MainWindow::closeEvent(QCloseEvent *event)
992 {
993  if (event->spontaneous()) { // Returns true if the event originated outside the application (a system event); otherwise returns false.
994  event->ignore();
995  if (Settings::systemTrayIcon()) {
996  hide(); // just hide the mainwindow, keep it in systemtray
997  } else {
998  quit();
999  }
1000  } else {
1001  quit(true);
1002  }
1003 }
1004 
1005 void MainWindow::saveProperties(KConfigGroup &group)
1006 {
1007  kDebug(5010);
1008  KMainWindow::saveProperties(group);
1009  saveHostPrefs();
1010 }
1011 
1012 
1013 void MainWindow::saveHostPrefs()
1014 {
1015  foreach (RemoteView *view, m_remoteViewMap.values()) {
1016  saveHostPrefs(view);
1017  view->startQuitting();
1018  }
1019 }
1020 
1021 void MainWindow::saveHostPrefs(RemoteView* view)
1022 {
1023  // should saving this be a user option?
1024  if (view && view->scaling()) {
1025  QSize viewSize = m_tabWidget->currentWidget()->size();
1026  kDebug(5010) << "saving window size:" << viewSize;
1027  view->hostPreferences()->setWidth(viewSize.width());
1028  view->hostPreferences()->setHeight(viewSize.height());
1029  }
1030 
1031  Settings::self()->config()->sync();
1032 }
1033 
1034 void MainWindow::tabChanged(int index)
1035 {
1036  kDebug(5010) << index;
1037 
1038  m_tabWidget->setTabBarHidden((m_tabWidget->count() <= 1 && !Settings::showTabBar()) || m_fullscreenWindow);
1039 
1040  m_currentRemoteView = index;
1041 
1042  if (m_tabWidget->currentWidget() == m_newConnectionWidget) {
1043  m_currentRemoteView = -1;
1044  if(m_addressInput) m_addressInput->setFocus();
1045  }
1046 
1047  const QString tabTitle = m_tabWidget->tabText(index).remove('&');
1048  setCaption(tabTitle == i18n("New Connection") ? QString() : tabTitle);
1049 
1050  updateActionStatus();
1051 }
1052 
1053 QWidget* MainWindow::newConnectionWidget()
1054 {
1055  if (m_newConnectionWidget)
1056  return m_newConnectionWidget;
1057 
1058  m_newConnectionWidget = new QWidget(this);
1059 
1060  QVBoxLayout *startLayout = new QVBoxLayout(m_newConnectionWidget);
1061  startLayout->setContentsMargins(QMargins(8, 12, 8, 4));
1062 
1063  QLabel *headerLabel = new QLabel(m_newConnectionWidget);
1064  headerLabel->setText(i18n("<h1>KDE Remote Desktop Client</h1><br />Enter or select the address of the desktop you would like to connect to."));
1065 
1066  QLabel *headerIconLabel = new QLabel(m_newConnectionWidget);
1067  headerIconLabel->setPixmap(KIcon("krdc").pixmap(80));
1068 
1069  QHBoxLayout *headerLayout = new QHBoxLayout;
1070  headerLayout->addWidget(headerLabel, 1, Qt::AlignTop);
1071  headerLayout->addWidget(headerIconLabel);
1072  startLayout->addLayout(headerLayout);
1073 
1074  QSortFilterProxyModel *remoteDesktopsModelProxy = new QSortFilterProxyModel(this);
1075  remoteDesktopsModelProxy->setSourceModel(m_remoteDesktopsModel);
1076  remoteDesktopsModelProxy->setFilterCaseSensitivity(Qt::CaseInsensitive);
1077  remoteDesktopsModelProxy->setFilterRole(10002);
1078 
1079  {
1080  QHBoxLayout *connectLayout = new QHBoxLayout;
1081 
1082  QLabel *addressLabel = new QLabel(i18n("Connect to:"), m_newConnectionWidget);
1083  m_protocolInput = new KComboBox(m_newConnectionWidget);
1084  m_addressInput = new KLineEdit(m_newConnectionWidget);
1085  m_addressInput->setClearButtonShown(true);
1086  m_addressInput->setClickMessage(i18n("Type here to connect to an address and filter the list."));
1087  connect(m_addressInput, SIGNAL(textChanged(QString)), remoteDesktopsModelProxy, SLOT(setFilterFixedString(QString)));
1088 
1089  foreach(RemoteViewFactory *factory, m_remoteViewFactories) {
1090  m_protocolInput->addItem(factory->scheme());
1091  }
1092 
1093  connect(m_addressInput, SIGNAL(returnPressed()), SLOT(newConnection()));
1094  m_addressInput->setToolTip(i18n("Type an IP or DNS Name here. Clear the line to get a list of connection methods."));
1095 
1096  KPushButton *connectButton = new KPushButton(m_newConnectionWidget);
1097  connectButton->setToolTip(i18n("Goto Address"));
1098  connectButton->setIcon(KIcon("go-jump-locationbar"));
1099  connect(connectButton, SIGNAL(clicked()), SLOT(newConnection()));
1100 
1101  connectLayout->addWidget(addressLabel);
1102  connectLayout->addWidget(m_protocolInput);
1103  connectLayout->addWidget(m_addressInput, 1);
1104  connectLayout->addWidget(connectButton);
1105  connectLayout->setContentsMargins(QMargins(0, 6, 0, 10));
1106  startLayout->addLayout(connectLayout);
1107  }
1108 
1109  {
1110  m_newConnectionTableView = new QTableView(m_newConnectionWidget);
1111  m_newConnectionTableView->setModel(remoteDesktopsModelProxy);
1112 
1113  // set up the view so it looks nice
1114  m_newConnectionTableView->setItemDelegate(new ConnectionDelegate(m_newConnectionTableView));
1115  m_newConnectionTableView->setShowGrid(false);
1116  m_newConnectionTableView->setSelectionMode(QAbstractItemView::NoSelection);
1117  m_newConnectionTableView->verticalHeader()->hide();
1118  m_newConnectionTableView->verticalHeader()->setDefaultSectionSize(
1119  m_newConnectionTableView->fontMetrics().height() + 3);
1120  m_newConnectionTableView->horizontalHeader()->setStretchLastSection(true);
1121  m_newConnectionTableView->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents);
1122  m_newConnectionTableView->setAlternatingRowColors(true);
1123  // set up sorting and actions (double click open, right click custom menu)
1124  m_newConnectionTableView->setSortingEnabled(true);
1125  m_newConnectionTableView->sortByColumn(Settings::connectionListSortColumn(), Qt::SortOrder(Settings::connectionListSortOrder()));
1126  connect(m_newConnectionTableView->horizontalHeader(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
1127  SLOT(saveConnectionListSort(int,Qt::SortOrder)));
1128  connect(m_newConnectionTableView, SIGNAL(doubleClicked(QModelIndex)),
1129  SLOT(openFromRemoteDesktopsModel(QModelIndex)));
1130  m_newConnectionTableView->setContextMenuPolicy(Qt::CustomContextMenu);
1131  connect(m_newConnectionTableView, SIGNAL(customContextMenuRequested(QPoint)), SLOT(showConnectionContextMenu(QPoint)));
1132 
1133  startLayout->addWidget(m_newConnectionTableView);
1134  }
1135 
1136  return m_newConnectionWidget;
1137 }
1138 
1139 void MainWindow::saveConnectionListSort(const int logicalindex, const Qt::SortOrder order)
1140 {
1141  Settings::setConnectionListSortColumn(logicalindex);
1142  Settings::setConnectionListSortOrder(order);
1143  Settings::self()->writeConfig();
1144 }
1145 
1146 void MainWindow::newConnectionPage(bool clearInput)
1147 {
1148  const int indexOfNewConnectionWidget = m_tabWidget->indexOf(m_newConnectionWidget);
1149  if (indexOfNewConnectionWidget >= 0)
1150  m_tabWidget->setCurrentIndex(indexOfNewConnectionWidget);
1151  else {
1152  const int index = m_tabWidget->addTab(newConnectionWidget(), i18n("New Connection"));
1153  m_tabWidget->setCurrentIndex(index);
1154  }
1155  if(clearInput) {
1156  m_addressInput->clear();
1157  } else {
1158  m_addressInput->selectAll();
1159  }
1160  m_addressInput->setFocus();
1161 }
1162 
1163 QMap<QWidget *, RemoteView *> MainWindow::remoteViewList() const
1164 {
1165  return m_remoteViewMap;
1166 }
1167 
1168 QList<RemoteViewFactory *> MainWindow::remoteViewFactoriesList() const
1169 {
1170  return m_remoteViewFactories.values();
1171 }
1172 
1173 RemoteView* MainWindow::currentRemoteView() const
1174 {
1175  if (m_currentRemoteView >= 0) {
1176  return m_remoteViewMap.value(m_tabWidget->widget(m_currentRemoteView));
1177  } else {
1178  return 0;
1179  }
1180 }
1181 
1182 void MainWindow::createDockWidget()
1183 {
1184  QDockWidget *remoteDesktopsDockWidget = new QDockWidget(this);
1185  QWidget *remoteDesktopsDockLayoutWidget = new QWidget(remoteDesktopsDockWidget);
1186  QVBoxLayout *remoteDesktopsDockLayout = new QVBoxLayout(remoteDesktopsDockLayoutWidget);
1187  remoteDesktopsDockWidget->setObjectName("remoteDesktopsDockWidget"); // required for saving position / state
1188  remoteDesktopsDockWidget->setWindowTitle(i18n("Remote Desktops"));
1189  QFontMetrics fontMetrics(remoteDesktopsDockWidget->font());
1190  remoteDesktopsDockWidget->setMinimumWidth(fontMetrics.width("vnc://192.168.100.100:6000"));
1191  actionCollection()->addAction("remote_desktop_dockwidget",
1192  remoteDesktopsDockWidget->toggleViewAction());
1193 
1194  m_dockWidgetTableView = new QTableView(remoteDesktopsDockLayoutWidget);
1195  m_remoteDesktopsModel = new RemoteDesktopsModel(this);
1196  QSortFilterProxyModel *remoteDesktopsModelProxy = new QSortFilterProxyModel(this);
1197  remoteDesktopsModelProxy->setSourceModel(m_remoteDesktopsModel);
1198  remoteDesktopsModelProxy->setFilterCaseSensitivity(Qt::CaseInsensitive);
1199  remoteDesktopsModelProxy->setFilterRole(10002);
1200  m_dockWidgetTableView->setModel(remoteDesktopsModelProxy);
1201 
1202  m_dockWidgetTableView->setShowGrid(false);
1203  m_dockWidgetTableView->verticalHeader()->hide();
1204  m_dockWidgetTableView->verticalHeader()->setDefaultSectionSize(
1205  m_dockWidgetTableView->fontMetrics().height() + 2);
1206  m_dockWidgetTableView->horizontalHeader()->hide();
1207  m_dockWidgetTableView->horizontalHeader()->setStretchLastSection(true);
1208  // hide all columns, then show the one we want
1209  for (int i=0; i < remoteDesktopsModelProxy->columnCount(); i++) {
1210  m_dockWidgetTableView->hideColumn(i);
1211  }
1212  m_dockWidgetTableView->showColumn(RemoteDesktopsModel::Title);
1213  m_dockWidgetTableView->sortByColumn(RemoteDesktopsModel::Title, Qt::AscendingOrder);
1214 
1215  connect(m_dockWidgetTableView, SIGNAL(doubleClicked(QModelIndex)),
1216  SLOT(openFromRemoteDesktopsModel(QModelIndex)));
1217 
1218  KLineEdit *filterLineEdit = new KLineEdit(remoteDesktopsDockLayoutWidget);
1219  filterLineEdit->setClickMessage(i18n("Filter"));
1220  filterLineEdit->setClearButtonShown(true);
1221  connect(filterLineEdit, SIGNAL(textChanged(QString)), remoteDesktopsModelProxy, SLOT(setFilterFixedString(QString)));
1222  remoteDesktopsDockLayout->addWidget(filterLineEdit);
1223  remoteDesktopsDockLayout->addWidget(m_dockWidgetTableView);
1224  remoteDesktopsDockWidget->setWidget(remoteDesktopsDockLayoutWidget);
1225  addDockWidget(Qt::LeftDockWidgetArea, remoteDesktopsDockWidget);
1226 }
1227 
1228 #include "mainwindow.moc"
HostPreferences::setShownWhileConnected
void setShownWhileConnected(bool connected)
If connected is true, a message is shown that settings might only apply after a reconnect.
Definition: hostpreferences.cpp:234
QAction::setText
void setText(const QString &text)
MainWindow::saveProperties
virtual void saveProperties(KConfigGroup &group)
Definition: mainwindow.cpp:1005
Settings::connectionListSortColumn
static int connectionListSortColumn()
Get ConnectionListSortColumn.
Definition: settings.h:334
TabbedViewWidget::removeTab
void removeTab(int index)
Definition: tabbedviewwidget.cpp:164
RemoteView::takeScreenshot
virtual QPixmap takeScreenshot()
Definition: remoteview.cpp:160
QModelIndex
setActionStatus
void setActionStatus(QAction *action, bool enabled, bool visible, bool checked)
Definition: mainwindow.cpp:836
QEvent
RemoteView::CursorOff
Never show local cursor, only the remote one.
Definition: remoteview.h:86
QWidget
QScrollArea::setWidget
void setWidget(QWidget *widget)
QRect::size
QSize size() const
QDesktopWidget::screenGeometry
const QRect screenGeometry(int screen) const
HostPreferences::windowedScale
bool windowedScale()
Whether scaling is enabled when session is not full screen.
Definition: hostpreferences.cpp:119
QEvent::type
Type type() const
QLayout::setContentsMargins
void setContentsMargins(int left, int top, int right, int bottom)
QWidget::palette
palette
QSortFilterProxyModel::setFilterCaseSensitivity
void setFilterCaseSensitivity(Qt::CaseSensitivity cs)
QWidget::setIcon
void setIcon(const QPixmap &i)
QAbstractItemView::setAlternatingRowColors
void setAlternatingRowColors(bool enable)
RemoteView::RemoteStatus
RemoteStatus
State of the connection.
Definition: remoteview.h:108
QSize::width
int width() const
PreferencesDialog
Definition: preferencesdialog.h:32
FloatingToolBar::Top
Definition: floatingtoolbar.h:46
RemoteView::showDotCursor
virtual void showDotCursor(DotCursorState state)
Sets the state of the dot cursor, if supported by the backend.
Definition: remoteview.cpp:165
QAbstractItemView::setSelectionMode
void setSelectionMode(QAbstractItemView::SelectionMode mode)
QMap::values
QList< T > values() const
MainWindow::saveHostPrefs
void saveHostPrefs()
Definition: mainwindow.cpp:1013
bookmarkmanager.h
QPalette::setColor
void setColor(ColorGroup group, ColorRole role, const QColor &color)
QDockWidget
FloatingToolBar::hideAndDestroy
void hideAndDestroy()
Definition: floatingtoolbar.cpp:168
QHeaderView::setDefaultSectionSize
void setDefaultSectionSize(int size)
HostPreferences::setWindowedScale
void setWindowedScale(bool scale)
Definition: hostpreferences.cpp:124
QSortFilterProxyModel::setSourceModel
virtual void setSourceModel(QAbstractItemModel *sourceModel)
ConnectionDelegate
Definition: connectiondelegate.h:29
hostpreferences.h
QObject::sender
QObject * sender() const
Settings::setConnectionListSortColumn
static void setConnectionListSortColumn(int v)
Set ConnectionListSortColumn.
Definition: settings.h:324
QScrollArea::widget
QWidget * widget() const
QAction::setChecked
void setChecked(bool)
RemoteView::supportsScaling
virtual bool supportsScaling() const
Checks whether the backend supports scaling.
Definition: remoteview.cpp:91
HostPreferences::showDialog
bool showDialog(QWidget *parent)
Show the configuration dialog.
Definition: hostpreferences.cpp:177
QAction::setIconText
void setIconText(const QString &text)
Settings::resizeOnConnect
static bool resizeOnConnect()
Get ResizeOnConnect.
Definition: settings.h:125
Settings::setOpenSessions
static void setOpenSessions(const QStringList &v)
Set Sessions.
Definition: settings.h:58
QLabel::setPixmap
void setPixmap(const QPixmap &)
QWidget::setMinimumWidth
void setMinimumWidth(int minw)
QTableView::sortByColumn
void sortByColumn(int column, Qt::SortOrder order)
QAction::setIcon
void setIcon(const QIcon &icon)
tubesmanager.h
QAction::setVisible
void setVisible(bool)
QMap< QWidget *, RemoteView * >
HostPreferences::grabAllKeys
bool grabAllKeys()
Definition: hostpreferences.cpp:129
MainWindow::closeEvent
virtual void closeEvent(QCloseEvent *event)
Definition: mainwindow.cpp:991
BookmarkManager::getManager
KBookmarkManager * getManager()
Definition: bookmarkmanager.cpp:167
QTableView::setSortingEnabled
void setSortingEnabled(bool enable)
QToolBar::addWidget
QAction * addWidget(QWidget *widget)
QWidget::mapToGlobal
QPoint mapToGlobal(const QPoint &pos) const
QObject::metaObject
virtual const QMetaObject * metaObject() const
QHBoxLayout
QWidget::frameSize
frameSize
Settings::openSessions
static QStringList openSessions()
Get Sessions.
Definition: settings.h:68
QPoint
QFontMetrics
QTableView::verticalHeader
QHeaderView * verticalHeader() const
MainWindow::newConnection
void newConnection(const KUrl &newUrl=KUrl(), bool switchFullscreenWhenConnected=false, const QString &tabName=QString())
Definition: mainwindow.cpp:285
TabbedViewWidget::addTab
int addTab(QWidget *page, const QString &label)
Definition: tabbedviewwidget.cpp:122
QFrame::setFrameStyle
void setFrameStyle(int style)
HostPreferences::fullscreenScale
bool fullscreenScale()
Whether scaling is enabled when session is full screen.
Definition: hostpreferences.cpp:109
Settings::systemTrayIcon
static bool systemTrayIcon()
Get SystemTrayIcon.
Definition: settings.h:201
TubesManager
Definition: tubesmanager.h:32
QDesktopWidget::screenNumber
int screenNumber(const QWidget *widget) const
RemoteDesktopsModel::Title
Definition: remotedesktopsmodel.h:67
RemoteView::CursorOn
Always show local cursor (and the remote one).
Definition: remoteview.h:85
MinimizePixel
Definition: mainwindow.h:145
MainWindow::currentRemoteView
RemoteView * currentRemoteView() const
Definition: mainwindow.cpp:1173
Settings::tabMiddleClick
static bool tabMiddleClick()
Get TabMiddleClick.
Definition: settings.h:258
RemoteView::grabAllKeys
virtual bool grabAllKeys()
Checks whether grabbing all possible keys is enabled.
Definition: remoteview.cpp:143
RemoteView
Generic widget that displays a remote framebuffer.
Definition: remoteview.h:59
RemoteView::scaling
virtual bool scaling() const
Checks whether the widget is in scale mode.
Definition: remoteview.cpp:175
systemtrayicon.h
HostPreferences::setShowLocalCursor
void setShowLocalCursor(bool show)
Definition: hostpreferences.cpp:144
Settings::self
static Settings * self()
Definition: settings.cpp:17
QCloseEvent
QMap::keys
QList< Key > keys() const
floatingtoolbar.h
QWidget::size
size
QWidget::setWindowState
void setWindowState(QFlags< Qt::WindowState > windowState)
QTableView::indexAt
virtual QModelIndex indexAt(const QPoint &pos) const
QSortFilterProxyModel::setFilterRole
void setFilterRole(int role)
QWidget::setEnabled
void setEnabled(bool)
QBoxLayout::addWidget
void addWidget(QWidget *widget, int stretch, QFlags< Qt::AlignmentFlag > alignment)
RemoteView::Disconnecting
Definition: remoteview.h:113
QList::append
void append(const T &value)
QTableView::setModel
virtual void setModel(QAbstractItemModel *model)
RemoteViewFactory::createHostPreferences
virtual HostPreferences * createHostPreferences(KConfigGroup configGroup, QWidget *parent)=0
Returns a new HostPreferences implementing object or 0 if no settings are available.
KXmlGuiWindow
FloatingToolBar
A toolbar widget that slides in from a side.
Definition: floatingtoolbar.h:38
RemoteDesktopsModel
Definition: remotedesktopsmodel.h:59
QClipboard::setPixmap
void setPixmap(const QPixmap &pixmap, Mode mode)
QDesktopWidget
QObject::installEventFilter
void installEventFilter(QObject *filterObj)
QApplication::clipboard
QClipboard * clipboard()
tabbedviewwidget.h
QObject
preferencesdialog.h
QObject::setObjectName
void setObjectName(const QString &name)
QString::isEmpty
bool isEmpty() const
HostPreferences::setGrabAllKeys
void setGrabAllKeys(bool grab)
Definition: hostpreferences.cpp:134
RemoteView::dotCursorState
virtual DotCursorState dotCursorState() const
Returns the state of the local cursor.
Definition: remoteview.cpp:170
QAbstractItemView::setItemDelegate
void setItemDelegate(QAbstractItemDelegate *delegate)
mainwindow.h
MainWindow::MainWindow
MainWindow(QWidget *parent=0)
Definition: mainwindow.cpp:76
QSortFilterProxyModel::columnCount
virtual int columnCount(const QModelIndex &parent) const
QVBoxLayout
RemoteView::hostPreferences
virtual HostPreferences * hostPreferences()=0
Returns the current host preferences of this view.
QEvent::spontaneous
bool spontaneous() const
QScrollArea::setAlignment
void setAlignment(QFlags< Qt::AlignmentFlag >)
HostPreferences::setWidth
void setWidth(int width)
Definition: hostpreferences.cpp:98
RemoteViewFactory::scheme
virtual QString scheme() const =0
Returns the supported scheme.
QObject::eventFilter
virtual bool eventFilter(QObject *watched, QEvent *event)
QWidget::winId
WId winId() const
QObject::deleteLater
void deleteLater()
QLabel::setText
void setText(const QString &)
BookmarkManager::updateTitle
static void updateTitle(KBookmarkManager *manager, const QString &url, const QString &title)
Definition: bookmarkmanager.cpp:209
RemoteView::Connecting
Definition: remoteview.h:109
QString
QList
QTableView::setShowGrid
void setShowGrid(bool show)
QWidget::hide
void hide()
Settings::backgroundColor
static QColor backgroundColor()
Get BackgroundColor.
Definition: settings.h:163
RemoteView::setViewOnly
virtual void setViewOnly(bool viewOnly)
Enables/disables the view-only mode.
Definition: remoteview.cpp:138
RemoteView::setGrabAllKeys
virtual void setGrabAllKeys(bool grabAllKeys)
Enables/disables grabbing all possible keys.
Definition: remoteview.cpp:148
RemoteViewScrollArea
Definition: mainwindow.h:167
RemoteView::url
KUrl url()
Definition: remoteview.cpp:193
QStringList
TabbedViewWidget
Definition: tabbedviewwidget.h:51
QTableView::showColumn
void showColumn(int column)
QPixmap
QList::end
iterator end()
QTableView
BookmarkManager::addManualBookmark
void addManualBookmark(const QString &url, const QString &text)
Definition: bookmarkmanager.cpp:161
TabbedViewWidget::getModel
TabbedViewWidgetModel * getModel()
Definition: tabbedviewwidget.cpp:117
Settings::showTabBar
static bool showTabBar()
Get ShowTabBar.
Definition: settings.h:296
QSize
QSortFilterProxyModel
QWidget::font
font
QWidget::setContextMenuPolicy
void setContextMenuPolicy(Qt::ContextMenuPolicy policy)
remotedesktopsmodel.h
Settings::connectionListSortOrder
static int connectionListSortOrder()
Get ConnectionListSortOrder.
Definition: settings.h:353
QMetaObject::className
const char * className() const
QAction::setCheckable
void setCheckable(bool)
QDockWidget::setWidget
void setWidget(QWidget *widget)
QMap::key
const Key key(const T &value) const
RemoteView::viewOnly
virtual bool viewOnly()
Checks whether the view is in view-only mode.
Definition: remoteview.cpp:133
HostPreferences
Definition: hostpreferences.h:42
QDockWidget::toggleViewAction
QAction * toggleViewAction() const
RemoteView::Authenticating
Definition: remoteview.h:110
Settings::rememberHistory
static bool rememberHistory()
Get RememberHistory.
Definition: settings.h:49
QWidget::fontMetrics
QFontMetrics fontMetrics() const
settings.h
HostPreferences::setFullscreenScale
void setFullscreenScale(bool scale)
Definition: hostpreferences.cpp:114
QModelIndex::data
QVariant data(int role) const
RemoteView::enableScaling
virtual void enableScaling(bool scale)
Called to enable or disable scaling.
Definition: remoteview.cpp:180
SystemTrayIcon
Definition: systemtrayicon.h:31
RemoteView::startQuitting
virtual void startQuitting()
Initiate the disconnection.
Definition: remoteview.cpp:111
RemoteView::updateConfiguration
virtual void updateConfiguration()
Called when the configuration is changed.
Definition: remoteview.cpp:125
QLatin1String
QApplication::desktop
QDesktopWidget * desktop()
Settings::fullscreenOnConnect
static bool fullscreenOnConnect()
Get FullscreenOnConnect.
Definition: settings.h:144
RemoteView::supportsLocalCursor
virtual bool supportsLocalCursor() const
Checks whether the backend supports the concept of local cursors.
Definition: remoteview.cpp:96
HostPreferences::setViewOnly
void setViewOnly(bool view)
Definition: hostpreferences.cpp:154
HostPreferences::viewOnly
bool viewOnly()
Definition: hostpreferences.cpp:149
Settings::tabPosition
static int tabPosition()
Get TabPosition.
Definition: settings.h:277
RemoteView::host
virtual QString host()
Definition: remoteview.cpp:101
QMargins
RemoteViewFactory::supportsUrl
virtual bool supportsUrl(const KUrl &url) const =0
Returns true if the provided url is supported by the current plugin.
QHeaderView::setResizeMode
void setResizeMode(ResizeMode mode)
RemoteView::start
virtual bool start()=0
Initialize the view (for example by showing configuration dialogs to the user) and start connecting...
BookmarkManager::removeByUrl
static void removeByUrl(KBookmarkManager *manager, const QString &url, bool ignoreHistory=false, const QString updateTitle=QString())
Definition: bookmarkmanager.cpp:189
QWidget::setWindowTitle
void setWindowTitle(const QString &)
QAction
Settings::rememberSessions
static bool rememberSessions()
Get RememberSessions.
Definition: settings.h:30
QList::ConstIterator
typedef ConstIterator
QToolBar
QFontMetrics::height
int height() const
QSize::height
int height() const
RemoteDesktopsModel::Source
Definition: remotedesktopsmodel.h:67
remoteview.h
connectiondelegate.h
QDesktopWidget::availableGeometry
const QRect availableGeometry(int screen) const
QMap::insert
iterator insert(const Key &key, const T &value)
MainWindow::~MainWindow
~MainWindow()
Definition: mainwindow.cpp:142
QWidget::show
void show()
QMap::isEmpty
bool isEmpty() const
FloatingToolBar::setSide
void setSide(Side side)
Definition: floatingtoolbar.cpp:132
BookmarkManager::addHistoryBookmark
void addHistoryBookmark(RemoteView *view)
Definition: bookmarkmanager.cpp:66
Settings::showStatusBar
static bool showStatusBar()
Get ShowStatusBar.
Definition: settings.h:315
QWidget::setBackgroundRole
void setBackgroundRole(QPalette::ColorRole role)
QScrollArea
RemoteViewFactory::createView
virtual RemoteView * createView(QWidget *parent, const KUrl &url, KConfigGroup configGroup)=0
Returns a new RemoteView implementing object.
RemoteViewFactory
Factory to be implemented by any plugin.
Definition: remoteviewfactory.h:52
TabbedViewWidget::removePage
void removePage(QWidget *page)
Definition: tabbedviewwidget.cpp:156
QHeaderView::setStretchLastSection
void setStretchLastSection(bool stretch)
QLabel
QObject::parent
QObject * parent() const
HostPreferences::setHeight
void setHeight(int height)
Definition: hostpreferences.cpp:87
RemoteView::Disconnected
Definition: remoteview.h:114
QTableView::horizontalHeader
QHeaderView * horizontalHeader() const
HostPreferences::showDialogIfNeeded
bool showDialogIfNeeded(QWidget *parent)
Show the configuration dialog if needed, ie.
Definition: hostpreferences.cpp:159
MainWindow::remoteViewFactoriesList
QList< RemoteViewFactory * > remoteViewFactoriesList() const
Definition: mainwindow.cpp:1168
QToolBar::addAction
void addAction(QAction *action)
QString::data
QChar * data()
QVariant::toString
QString toString() const
RemoteView::Connected
Definition: remoteview.h:112
MainWindow::eventFilter
bool eventFilter(QObject *obj, QEvent *event)
Definition: mainwindow.cpp:981
HostPreferences::showLocalCursor
bool showLocalCursor()
Definition: hostpreferences.cpp:139
QList::begin
iterator begin()
Settings::setConnectionListSortOrder
static void setConnectionListSortOrder(int v)
Set ConnectionListSortOrder.
Definition: settings.h:343
QAction::setEnabled
void setEnabled(bool)
QPalette
Settings::tabCloseButton
static bool tabCloseButton()
Get TabCloseButton.
Definition: settings.h:239
RemoteView::Preparing
Definition: remoteview.h:111
QBoxLayout::addLayout
void addLayout(QLayout *layout, int stretch)
QMap::value
const T value(const Key &key) const
MainWindow::remoteViewList
QMap< QWidget *, RemoteView * > remoteViewList() const
Definition: mainwindow.cpp:1163
QMap::remove
int remove(const Key &key)
QTimer::singleShot
singleShot
QTableView::hideColumn
void hideColumn(int column)
BookmarkManager
Definition: bookmarkmanager.h:36
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:29:34 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

krdc

Skip menu "krdc"
  • Main Page
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdenetwork API Reference

Skip menu "kdenetwork API Reference"
  • kget
  • kopete
  •   kopete
  •   libkopete
  • krdc
  • krfb

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal