X-Git-Url: http://git.maemo.org/git/?a=blobdiff_plain;f=src%2Fmainwindow.cpp;h=07bcf51ddc441dc4c27372f8801202eb0b294719;hb=7f4b9e15b4ddabb36d6d3471bdd7acdcb38eb7f5;hp=e2a2a7b6e4b7c51d469a405f5f0c2680bb886250;hpb=3c170b953a3d8a9d4e8d4085f96736b1d9436b77;p=presencevnc diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index e2a2a7b..07bcf51 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1,288 +1,432 @@ +/* + Presence VNC + Copyright (C) 2010 Christian Pulvermacher + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#include "connectdialog.h" +#include "keymenu.h" #include "mainwindow.h" #include "preferences.h" +#include "scrollarea.h" #include "vncview.h" +#ifdef Q_WS_MAEMO_5 #include #include +#include + +#include +#include #include #include +#endif -#include -MainWindow::MainWindow(QString url, int quality): - QMainWindow(0), - vnc_view(0), - scroll_area(new QScrollArea(0)) +MainWindow::MainWindow(QString url, int quality, int listen_port, bool view_only): + QMainWindow(0), + vnc_view(0), + scroll_area(new ScrollArea(this)), + input_toolbuttons(new QActionGroup(this)), + key_menu(0) { - setWindowTitle("Presence VNC"); -// swipe_start = QPoint(0,0); - setAttribute(Qt::WA_Maemo5StackedWindow); - QSettings settings; - - //set up toolbar - toolbar = new QToolBar(0); - toolbar->setAttribute(Qt::WA_InputMethodEnabled, true); - toolbar->addAction("Mod", this, SLOT(showModifierMenu())); - toolbar->addAction("Tab", this, SLOT(sendTab())); - toolbar->addAction("Esc", this, SLOT(sendEsc())); - toolbar->addAction("PgUp", this, SLOT(sendPgUp())); - toolbar->addAction("PgDn", this, SLOT(sendPgDn())); -// toolbar->addAction("IM", toolbar, SLOT(setFocus())); //doesn't work - toolbar->addAction(QIcon("/usr/share/icons/hicolor/48x48/hildon/general_fullsize.png"), "", this, SLOT(toggleFullscreen())); - addToolBar(toolbar); - toolbar->setVisible(settings.value("show_toolbar", true).toBool()); - - //set up menu - QMenuBar *menu = new QMenuBar(this); - QAction *connect_action = new QAction("Connect", this); - disconnect_action = new QAction("Disconnect", this); -// menu->addAction(connect_action); -// menu->addAction(disconnect_action); - scaling = new QAction("Fit to Screen", this); - scaling->setCheckable(true); - scaling->setChecked(settings.value("rescale", true).toBool()); - menu->addAction(scaling); - QAction *show_toolbar = new QAction("Show Toolbar", this); - show_toolbar->setCheckable(true); - show_toolbar->setChecked(settings.value("show_toolbar", true).toBool()); - menu->addAction(show_toolbar); - QAction *pref_action = new QAction("Preferences", this); - menu->addAction(pref_action); - QAction *about_action = new QAction("About", this); - menu->addAction(about_action); - - //menu->setAttribute(Qt::WA_Maemo5StackedWindow); - //menu->hide(); - - connect(about_action, SIGNAL(triggered()), - this, SLOT(about())); - connect(pref_action, SIGNAL(triggered()), - this, SLOT(showPreferences())); - connect(connect_action, SIGNAL(triggered()), - this, SLOT(connectDialog())); - connect(disconnect_action, SIGNAL(triggered()), - this, SLOT(disconnectFromHost())); - connect(show_toolbar, SIGNAL(toggled(bool)), - toolbar, SLOT(setVisible(bool))); - connect(show_toolbar, SIGNAL(toggled(bool)), - this, SLOT(forceResizeDelayed())); - - setCentralWidget(scroll_area); - - grabZoomKeys(true); - reloadSettings(); - - connect(QApplication::desktop(), SIGNAL(resized(int)), - this, SLOT(forceResize())); - - if(url.isNull()) { - disconnect_action->setEnabled(false); - toolbar->setEnabled(false); - connectDialog(); - } else { - vnc_view = new VncView(this, url, RemoteView::Quality(quality)); - connect(scaling, SIGNAL(toggled(bool)), - vnc_view, SLOT(enableScaling(bool))); - connect(vnc_view, SIGNAL(statusChanged(RemoteView::RemoteStatus)), - this, SLOT(statusChanged(RemoteView::RemoteStatus))); - scroll_area->setWidget(vnc_view); - vnc_view->start(); - vnc_view->enableScaling(scaling->isChecked()); - } - - if(!vnc_view) //not connected - QTimer::singleShot(100, this, SLOT(close())); + setWindowTitle("Presence VNC"); +#ifdef Q_WS_MAEMO_5 + setContextMenuPolicy(Qt::NoContextMenu); + setAttribute(Qt::WA_Maemo5StackedWindow); +#endif + + migrateConfiguration(); + + //set up toolbar + toolbar = new QToolBar(0); + key_menu_button = input_toolbuttons->addAction(toolbar->addAction(QChar(0x2026), this, SLOT(showKeyMenu()))); //"..." button + key_menu_button->setCheckable(true); //used to indicate wether a modifier key is still pressed + input_toolbuttons->addAction(toolbar->addAction(tr("Tab"), this, SLOT(sendTab()))); + input_toolbuttons->addAction(toolbar->addAction(tr("Esc"), this, SLOT(sendEsc()))); + input_toolbuttons->addAction(toolbar->addAction(tr("PgUp"), this, SLOT(sendPgUp()))); + input_toolbuttons->addAction(toolbar->addAction(tr("PgDn"), this, SLOT(sendPgDn()))); +#ifdef Q_WS_MAEMO_5 + input_toolbuttons->addAction(toolbar->addAction(QIcon("/usr/share/icons/hicolor/48x48/hildon/chat_enter.png"), "", this, SLOT(sendReturn()))); + input_toolbuttons->addAction(toolbar->addAction(QIcon("/usr/share/icons/hicolor/48x48/hildon/control_keyboard.png"), "", this, SLOT(showInputPanel()))); +#endif + + QSettings settings; + zoom_slider = new QSlider(Qt::Horizontal, 0); + zoom_slider->setRange(0, 100); + connect(zoom_slider, SIGNAL(valueChanged(int)), + this, SLOT(setZoomLevel(int))); + connect(zoom_slider, SIGNAL(sliderReleased()), + this, SLOT(zoomSliderReleased())); + zoom_slider->setValue(settings.value("zoomlevel", 95).toInt()); + toolbar->addWidget(zoom_slider); + +#ifdef Q_WS_MAEMO_5 + toolbar->addAction(QIcon("/usr/share/icons/hicolor/48x48/hildon/general_fullsize.png"), "", this, SLOT(toggleFullscreen())); +#else + toolbar->addAction(tr("Toggle Fullscreen"), this, SLOT(toggleFullscreen())); +#endif + addToolBar(toolbar); + toolbar->setVisible(settings.value("show_toolbar", true).toBool()); + toolbar->setEnabled(false); + + //set up menu + QAction *connect_action = new QAction(tr("Connect"), this); + disconnect_action = new QAction(tr("Disconnect"), this); + show_toolbar = new QAction(tr("Show toolbar"), this); + show_toolbar->setCheckable(true); + show_toolbar->setChecked(settings.value("show_toolbar", true).toBool()); + QAction *pref_action = new QAction(tr("Preferences"), this); + QAction *about_action = new QAction(tr("About"), this); + +#ifdef Q_WS_MAEMO_5 + menuBar()->addAction(connect_action); + menuBar()->addAction(disconnect_action); + menuBar()->addAction(show_toolbar); + menuBar()->addAction(pref_action); + menuBar()->addAction(about_action); +#else + QMenu* session_menu = menuBar()->addMenu(tr("&Session")); + session_menu->addAction(connect_action); + session_menu->addAction(disconnect_action); + session_menu->addSeparator(); + session_menu->addAction(pref_action); + session_menu->addSeparator(); + session_menu->addAction(tr("&Quit"), this, SLOT(close())); + + QMenu* view_menu = menuBar()->addMenu(tr("&View")); + view_menu->addAction(show_toolbar); + + QMenu* help_menu = menuBar()->addMenu(tr("&Help")); + help_menu->addAction(about_action); +#endif + + connect(about_action, SIGNAL(triggered()), + this, SLOT(about())); + connect(pref_action, SIGNAL(triggered()), + this, SLOT(showPreferences())); + connect(connect_action, SIGNAL(triggered()), + this, SLOT(showConnectDialog())); + connect(disconnect_action, SIGNAL(triggered()), + this, SLOT(disconnectFromHost())); + connect(show_toolbar, SIGNAL(toggled(bool)), + toolbar, SLOT(setVisible(bool))); + connect(show_toolbar, SIGNAL(toggled(bool)), + this, SLOT(updateScreenSpaceDelayed())); +#ifdef Q_WS_MAEMO_5 + QDBusConnection::systemBus().connect("", MCE_SIGNAL_PATH, MCE_SIGNAL_IF, MCE_DISPLAY_SIG, + this, SLOT(displayStateChanged(QString))); +#endif + + setCentralWidget(scroll_area); + + connect(scroll_area, SIGNAL(fullscreenButtonClicked()), + this, SLOT(toggleFullscreen())); + + grabZoomKeys(true); + reloadSettings(); + + if(url.isEmpty() and listen_port == 0) { + disconnect_action->setEnabled(false); + showConnectDialog(); + } else { + connectToHost(url, quality, listen_port, view_only); + } } void MainWindow::grabZoomKeys(bool grab) { - unsigned long val = (grab)?1:0; - Atom atom = XInternAtom(QX11Info::display(), "_HILDON_ZOOM_KEY_ATOM", False); - if(!atom) { - qWarning("Couldn't get zoom key atom"); - return; - } - XChangeProperty(QX11Info::display(), winId(), atom, XA_INTEGER, - 32, PropModeReplace, reinterpret_cast(&val), 1); +#ifdef Q_WS_MAEMO_5 + unsigned long val = (grab)?1:0; + Atom atom = XInternAtom(QX11Info::display(), "_HILDON_ZOOM_KEY_ATOM", False); + if(!atom) { + qWarning("Couldn't get zoom key atom"); + return; + } + XChangeProperty(QX11Info::display(), winId(), atom, XA_INTEGER, + 32, PropModeReplace, reinterpret_cast(&val), 1); +#endif } -void MainWindow::closeEvent(QCloseEvent*) { - grabZoomKeys(false); +void MainWindow::closeEvent(QCloseEvent*) +{ + grabZoomKeys(false); - QSettings settings; - settings.setValue("show_toolbar", toolbar->isVisible()); - settings.setValue("rescale", scaling->isChecked()); - settings.sync(); + QSettings settings; + settings.setValue("show_toolbar", show_toolbar->isChecked()); + settings.setValue("zoomlevel", zoom_slider->value()); + settings.sync(); - hide(); + hide(); - disconnectFromHost(); + disconnectFromHost(); } -void MainWindow::about() { - QMessageBox::about(this, tr("About Presence VNC"), - tr("

Presence VNC 0.2

\ -A touchscreen friendly VNC client\ -

©2010 Christian Pulvermacher <pulvermacher@gmx.de>

\ -

Based on KRDC, © 2007-2008 Urs Wolfer

\ -

This program is free software; License: GNU GPL 2 or later.

")); +void MainWindow::about() +{ + QMessageBox::about(this, tr("About Presence VNC"), + tr("

Presence VNC 0.8

\ +

A touchscreen friendly VNC client

\ +

http://presencevnc.garage.maemo.org/

\ +

©2010 Christian Pulvermacher <pulvermacher@gmx.de>
\ + Based on KRDC, © 2007-2008 Urs Wolfer
\ + and LibVNCServer, © 2001-2003 Johannes E. Schindelin

\ +

This program is free software; License: GNU GPL 2 or later.

")); } -/* swipe not used, and doesn't work without scaling anyway :/ -virtual bool event(QEvent *event) { - if(event->type() == QEvent::MouseMove) { - QMouseEvent *ev = dynamic_cast(event); - if(!swipe_start.isNull()) { - QPoint diff = swipe_start - ev->pos(); - const int swipe_dist = 60; - if(diff.x() > swipe_dist and diff.y() < swipe_dist and diff.y() > -swipe_dist) { // - menu->show(); - swipe_start = QPoint(0,0); - } - } else if((width() - ev->x()) < 10) { - swipe_start = ev->pos(); - } - std::cout << "mousex: " << width() - ev->x() << "\n"; - //TODO: make scrolling over border result in wheel events? i get weird (out of range) mouse events when that happens - return true; - } else if(event->type() == QEvent::MouseButtonRelease) { - swipe_start = QPoint(0,0); - return true; - } else { -// std::cout << "event " << event->type() << "\n"; - return QScrollArea::event(event); - } +void MainWindow::showConnectDialog() +{ + ConnectDialog *connect_dialog = new ConnectDialog(this); + connect(connect_dialog, SIGNAL(connectToHost(QString, int, int, bool)), + this, SLOT(connectToHost(QString, int, int, bool))); + connect_dialog->exec(); + //ConnectDialog cleans up after itself } -*/ -void MainWindow::connectDialog() +void MainWindow::connectToHost(QString url, int quality, int listen_port, bool view_only) { - QSettings settings; - QString url = QInputDialog::getText(this, "Connect to Host", "VNC Server:", QLineEdit::Normal, settings.value("last_hostname", "").toString()); - if(url.isEmpty()) { //dialog dismissed or nothing entered - return; - } - settings.setValue("last_hostname", url); - url = "vnc://" + url; - - disconnectFromHost(); - - vnc_view = new VncView(this, url, RemoteView::Quality(2)); //TODO: get quality in dialog - scroll_area->setWidget(vnc_view); - - connect(scaling, SIGNAL(toggled(bool)), - vnc_view, SLOT(enableScaling(bool))); - connect(vnc_view, SIGNAL(statusChanged(RemoteView::RemoteStatus)), - this, SLOT(statusChanged(RemoteView::RemoteStatus))); - vnc_view->start(); - vnc_view->enableScaling(scaling->isChecked()); - disconnect_action->setEnabled(true); - toolbar->setEnabled(true); + disconnectFromHost(); + + vnc_view = new VncView(this, url, RemoteView::Quality(quality), listen_port); + vnc_view->setViewOnly(view_only); + + connect(vnc_view, SIGNAL(statusChanged(RemoteView::RemoteStatus)), + this, SLOT(statusChanged(RemoteView::RemoteStatus))); + connect(vnc_view, SIGNAL(errorMessage(QString, QString)), + scroll_area, SLOT(showMessage(QString, QString))); + scroll_area->setWidget(vnc_view); + vnc_view->start(); + setWindowTitle(QString("Presence VNC - %1").arg(vnc_view->host()) + (view_only?tr(" [View Only]"):"")); + + disconnect_action->setEnabled(true); + + //reset key menu + delete key_menu; + key_menu = new KeyMenu(this); } void MainWindow::disconnectFromHost() { - if(!vnc_view) - return; - -//TODO: crashes when deleting vnc_view - no idea why - //vnc_view->startQuitting(); - //scroll_area->setWidget(0); - -// vnc_view->disconnect(); //remove all connections - //delete vnc_view; - //vnc_view = 0; - disconnect_action->setEnabled(false); - toolbar->setEnabled(false); + if(!vnc_view) + return; + + setWindowTitle("Presence VNC"); + disconnect_action->setEnabled(false); + toolbar->setEnabled(false); + scroll_area->setWidget(0); + + delete vnc_view; + vnc_view = 0; } void MainWindow::statusChanged(RemoteView::RemoteStatus status) { - static RemoteView::RemoteStatus old_status = RemoteView::Disconnected; - - switch(status) { - case RemoteView::Connecting: - setAttribute(Qt::WA_Maemo5ShowProgressIndicator, true); - break; - case RemoteView::Connected: - setAttribute(Qt::WA_Maemo5ShowProgressIndicator, false); - break; - case RemoteView::Disconnecting: - if(old_status != RemoteView::Disconnected) { //Disconnecting also occurs while connecting, so check last state - QMaemo5InformationBox::information(this, "Connection lost"); - close(); - } - break; - case RemoteView::Disconnected: - setAttribute(Qt::WA_Maemo5ShowProgressIndicator, false); - if(old_status == RemoteView::Disconnecting) { - scroll_area->setWidget(0); //remove widget - } - break; - } - - old_status = status; + static RemoteView::RemoteStatus old_status = RemoteView::Disconnected; + + switch(status) { + case RemoteView::Connecting: +#ifdef Q_WS_MAEMO_5 + setAttribute(Qt::WA_Maemo5ShowProgressIndicator, true); +#endif + break; + case RemoteView::Connected: +#ifdef Q_WS_MAEMO_5 + setAttribute(Qt::WA_Maemo5ShowProgressIndicator, false); +#endif + toolbar->setEnabled(true); + + //disable key input buttons in view only mode + input_toolbuttons->setEnabled(!vnc_view->viewOnly()); + + vnc_view->setZoomLevel(zoom_slider->value()); + vnc_view->useFastTransformations(false); + vnc_view->update(); + break; + case RemoteView::Disconnecting: + if(old_status == RemoteView::Disconnected) //Disconnecting also occurs while connecting, so check last state + break; + + if(disconnect_action->isEnabled()) //don't show when manually disconnecting + scroll_area->showMessage(tr("Connection lost")); + + //clean up + scroll_area->setWidget(0); + vnc_view = 0; + setWindowTitle("Presence VNC"); + disconnect_action->setEnabled(false); + toolbar->setEnabled(false); + + //exit fullscreen mode + if(windowState() & Qt::WindowFullScreen) + setWindowState(windowState() ^ Qt::WindowFullScreen); + break; + case RemoteView::Disconnected: +#ifdef Q_WS_MAEMO_5 + setAttribute(Qt::WA_Maemo5ShowProgressIndicator, false); +#endif + if(old_status == RemoteView::Disconnecting) { + scroll_area->setWidget(0); //remove widget + } + break; + default: //avoid compiler warnings + break; + } + + old_status = status; } -//when rescaling is enabled, this resizes the widget to use available screen space +//updates available screen space for current zoom level //necessary when rotating, showing fullscreen, etc. -void MainWindow::forceResize() +void MainWindow::updateScreenSpace() { - if(vnc_view and scaling->isChecked()) { - vnc_view->resize(scroll_area->size()); - } -} + if(vnc_view) { + vnc_view->setZoomLevel(); + } +} -void MainWindow::forceResizeDelayed() +void MainWindow::updateScreenSpaceDelayed() { - QTimer::singleShot(500, this, SLOT(forceResize())); + QTimer::singleShot(500, this, SLOT(updateScreenSpace())); } void MainWindow::toggleFullscreen() { - setWindowState(windowState() ^ Qt::WindowFullScreen); - forceResizeDelayed(); + bool in_fullscreen = windowState() & Qt::WindowFullScreen; + + //hide menu/toolbar in fullscreen (new state is !in_fullscreen) + toolbar->setVisible(show_toolbar->isChecked() and in_fullscreen); + +#ifndef Q_WS_MAEMO_5 + //menu bar is invisible by default on maemo + menuBar()->setVisible(in_fullscreen); +#endif + + setWindowState(windowState() ^ Qt::WindowFullScreen); + updateScreenSpaceDelayed(); } -void MainWindow::showModifierMenu() +void MainWindow::showKeyMenu() { - static QMenu *mod_menu = new QMenu(tr("Modifiers"), this); - static QAction *win = mod_menu->addAction(tr("Win")); - static QAction *alt = mod_menu->addAction(tr("Alt")); - win->setCheckable(true); - alt->setCheckable(true); - - //show menu at top-left corner of toolbar - QAction *chosen = mod_menu->exec(toolbar->mapToGlobal(QPoint(0,0))); - if(!chosen) { - return; - } else if(chosen == alt) { - vnc_view->sendKey(Qt::Key_Alt); - } else if(chosen == win) { - vnc_view->sendKey(Qt::Key_Meta); - } else { - std::cout << "unhandled action?\n"; - } + key_menu->exec(); + vnc_view->sendKeySequence(key_menu->getKeySequence()); + key_menu_button->setChecked(key_menu->isAltChecked() or key_menu->isWinChecked()); } void MainWindow::showPreferences() { - Preferences *p = new Preferences(this); - p->exec(); - delete p; + Preferences *p = new Preferences(this); + p->exec(); + delete p; - reloadSettings(); + reloadSettings(); } void MainWindow::reloadSettings() { - QSettings settings; - int rotation = settings.value("screen_rotation", 0).toInt(); - setAttribute(Qt::WA_Maemo5AutoOrientation, rotation == 0); - setAttribute(Qt::WA_Maemo5LandscapeOrientation, rotation == 1); - setAttribute(Qt::WA_Maemo5PortraitOrientation, rotation == 2); - - if(vnc_view) - vnc_view->reloadSettings(); + QSettings settings; + zoom_to_cursor = settings.value("zoom_to_cursor", true).toBool(); + +#ifdef Q_WS_MAEMO_5 + int rotation = settings.value("screen_rotation", 0).toInt(); + setAttribute(Qt::WA_Maemo5AutoOrientation, rotation == 0); + setAttribute(Qt::WA_Maemo5LandscapeOrientation, rotation == 1); + setAttribute(Qt::WA_Maemo5PortraitOrientation, rotation == 2); +#endif + + if(vnc_view) + vnc_view->reloadSettings(); +} + +void MainWindow::resizeEvent(QResizeEvent *event) +{ + QMainWindow::resizeEvent(event); + + updateScreenSpace(); + if(vnc_view) + vnc_view->setZoomLevel(zoom_slider->value()); + +#ifdef Q_WS_MAEMO_5 + //hide zoom slider in portrait mode + zoom_slider->setVisible(height() < width()); +#endif } + +void MainWindow::showInputPanel() +{ +#ifdef Q_WS_MAEMO_5 + //TODO: when hardware keyboard is open, this will only cause the IM to mess up 'real' key events + vnc_view->setAttribute(Qt::WA_InputMethodEnabled, true); + vnc_view->setInputMethodHints(Qt::ImhNoAutoUppercase); //without this, IM starts with caps lock + + QEvent event(QEvent::RequestSoftwareInputPanel); + QApplication::sendEvent(vnc_view, &event); +#endif +} + +void MainWindow::setZoomLevel(int level) +{ + if(!vnc_view) + return; + + const qreal old_factor = vnc_view->zoomFactor(); + QPoint center = vnc_view->visibleRegion().boundingRect().center(); + + vnc_view->setZoomLevel(level); + + const qreal new_factor = vnc_view->zoomFactor(); + + //scroll to center, if zoom level actually changed + if(old_factor != new_factor) { + if(zoom_to_cursor) + center = new_factor * vnc_view->cursorPosition(); + else //zoom to center of visible region + center = center * (double(new_factor)/old_factor); + + scroll_area->ensureVisible(center.x(), center.y(), + vnc_view->visibleRegion().boundingRect().width()/2, + vnc_view->visibleRegion().boundingRect().height()/2); + + vnc_view->useFastTransformations(zoom_slider->isSliderDown()); + vnc_view->update(); + + scroll_area->showMessage(tr("Zoom: %1\%").arg(qRound(100*new_factor))); + } +} + +void MainWindow::zoomSliderReleased() +{ + static QTime time; + if(!time.isNull() and time.elapsed() < 500) //double clicked + zoom_slider->setValue(95); //100% + + time.restart(); + + //stopped zooming, reenable high quality + vnc_view->useFastTransformations(false); +} + +void MainWindow::displayStateChanged(QString state) +{ + const bool display_on = (state != "off"); + if(vnc_view) + vnc_view->setDisplayOff(!display_on); +} + +void MainWindow::sendTab() { vnc_view->sendKey(Qt::Key_Tab); } +void MainWindow::sendEsc() { vnc_view->sendKey(Qt::Key_Escape); } +void MainWindow::sendPgUp() { vnc_view->sendKey(Qt::Key_PageUp); } +void MainWindow::sendPgDn() { vnc_view->sendKey(Qt::Key_PageDown); } +void MainWindow::sendReturn() { vnc_view->sendKey(Qt::Key_Return); }