"Fossies" - the Fresh Open Source Software Archive

Member "kaffeine-2.0.18/src/mainwindow.cpp" (14 May 2019, 28178 Bytes) of package /linux/misc/kaffeine-2.0.18.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "mainwindow.cpp" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.0.17_vs_2.0.18.

    1 /*
    2  * mainwindow.cpp
    3  *
    4  * Copyright (C) 2007-2011 Christoph Pfister <christophpfister@gmail.com>
    5  *
    6  * This program is free software; you can redistribute it and/or modify
    7  * it under the terms of the GNU General Public License as published by
    8  * the Free Software Foundation; either version 2 of the License, or
    9  * (at your option) any later version.
   10  *
   11  * This program is distributed in the hope that it will be useful,
   12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14  * GNU General Public License for more details.
   15  *
   16  * You should have received a copy of the GNU General Public License along
   17  * with this program; if not, write to the Free Software Foundation, Inc.,
   18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   19  */
   20 
   21 #include "log.h"
   22 
   23 #include <KAboutData>
   24 #include <KActionCollection>
   25 #include <KConfigGroup>
   26 #include <KHelpMenu>
   27 #include <kio/deletejob.h>
   28 #include <KRecentFilesAction>
   29 #include <KSharedConfig>
   30 #include <KShortcutsDialog>
   31 #include <QApplication>
   32 #include <QCommandLineOption>
   33 #include <QDBusConnection>
   34 #include <QDesktopWidget>
   35 #include <QFileDialog>
   36 #include <QHoverEvent>
   37 #include <QInputDialog>
   38 #include <QLoggingCategory>
   39 #include <QMainWindow>
   40 #include <QMenu>
   41 #include <QMenuBar>
   42 #include <QSettings>
   43 #include <QStackedLayout>
   44 #include <QTabBar>
   45 #include <QToolBar>
   46 
   47 #include "configuration.h"
   48 #include "configurationdialog.h"
   49 #include "dbusobjects.h"
   50 #include "dvb/dvbtab.h"
   51 #include "mainwindow.h"
   52 #include "playlist/playlisttab.h"
   53 
   54 // log categories. Should match log.h
   55 
   56 Q_LOGGING_CATEGORY(logCam, "kaffeine.cam")
   57 Q_LOGGING_CATEGORY(logDev, "kaffeine.dev")
   58 Q_LOGGING_CATEGORY(logDvb, "kaffeine.dvb")
   59 Q_LOGGING_CATEGORY(logDvbSi, "kaffeine.dvbsi")
   60 Q_LOGGING_CATEGORY(logEpg, "kaffeine.epg")
   61 
   62 Q_LOGGING_CATEGORY(logConfig, "kaffeine.config")
   63 Q_LOGGING_CATEGORY(logMediaWidget, "kaffeine.mediawidget")
   64 Q_LOGGING_CATEGORY(logPlaylist, "kaffeine.playlist")
   65 Q_LOGGING_CATEGORY(logSql, "kaffeine.sql")
   66 Q_LOGGING_CATEGORY(logVlc, "kaffeine.vlc")
   67 
   68 #define FILTER_RULE "kaffeine.*.debug=true"
   69 
   70 #define CATEGORIES "cam, dev, dvb, dvbsi, epg, config, mediawidget, playlist, sql, vlc"
   71 
   72 class StackedLayout : public QStackedLayout
   73 {
   74 public:
   75     explicit StackedLayout(QWidget *parent) : QStackedLayout(parent) { }
   76     ~StackedLayout() { }
   77 
   78     QSize minimumSize() const
   79     {
   80         QWidget *widget = currentWidget();
   81 
   82         if (widget != NULL) {
   83             return widget->minimumSizeHint();
   84         }
   85 
   86         return QSize();
   87     }
   88 };
   89 
   90 class StartTab : public TabBase
   91 {
   92 public:
   93     explicit StartTab(MainWindow *mainWindow);
   94     ~StartTab() { }
   95 
   96 private:
   97     void activate() { }
   98 
   99     QAbstractButton *addShortcut(const QString &name, const QIcon &icon, QWidget *parent);
  100 };
  101 
  102 StartTab::StartTab(MainWindow *mainWindow)
  103 {
  104     setBackgroundRole(QPalette::Base);
  105     setAutoFillBackground(true);
  106 
  107     QGridLayout *gridLayout = new QGridLayout(this);
  108     gridLayout->setAlignment(Qt::AlignCenter);
  109     gridLayout->setMargin(10);
  110     gridLayout->setSpacing(15);
  111 
  112     QAbstractButton *button =
  113         addShortcut(i18n("&1 Play File"), QIcon::fromTheme(QLatin1String("video-x-generic"), QIcon(":video-x-generic")), this);
  114     button->setShortcut(Qt::Key_1);
  115     button->setWhatsThis(i18n("Open dialog to play a file"));
  116     connect(button, SIGNAL(clicked()), mainWindow, SLOT(open()));
  117     gridLayout->addWidget(button, 0, 0);
  118 
  119     button = addShortcut(i18n("&2 Play Audio CD"), QIcon::fromTheme(QLatin1String("media-optical-audio"), QIcon(":media-optical-audio")), this);
  120     button->setShortcut(Qt::Key_2);
  121     button->setWhatsThis(i18n("Start playing an audio CD. It assumes that the CD is already there at the CD drive"));
  122     connect(button, SIGNAL(clicked()), mainWindow, SLOT(openAudioCd()));
  123     gridLayout->addWidget(button, 0, 1);
  124 
  125     button = addShortcut(i18n("&3 Play Video CD"), QIcon::fromTheme(QLatin1String("media-optical"), QIcon(":media-optical-video")), this);
  126     button->setShortcut(Qt::Key_3);
  127     button->setWhatsThis(i18n("Start playing a Video CD. It assumes that the CD is already there at the CD drive"));
  128     connect(button, SIGNAL(clicked()), mainWindow, SLOT(openVideoCd()));
  129     gridLayout->addWidget(button, 0, 2);
  130 
  131     button = addShortcut(i18n("&4 Play DVD"), QIcon::fromTheme(QLatin1String("media-optical"), QIcon(":media-optical")), this);
  132     button->setShortcut(Qt::Key_4);
  133     button->setWhatsThis(i18n("Start playing a DVD. It assumes that the DVD is already there at the DVD drive"));
  134     connect(button, SIGNAL(clicked()), mainWindow, SLOT(openDvd()));
  135     gridLayout->addWidget(button, 1, 0);
  136 
  137 #if HAVE_DVB == 1
  138     button = addShortcut(i18n("&5 Digital TV"), QIcon::fromTheme(QLatin1String("video-television"), QIcon(":video-television")), this);
  139     button->setShortcut(Qt::Key_5);
  140     button->setWhatsThis("Open the Digital TV live view window. If the TV channels are already scanned, it will start playing the last channel");
  141     connect(button, SIGNAL(clicked()), mainWindow, SLOT(playDvb()));
  142     gridLayout->addWidget(button, 1, 1);
  143 #endif /* HAVE_DVB == 1 */
  144 }
  145 
  146 QAbstractButton *StartTab::addShortcut(const QString &name, const QIcon &icon, QWidget *parent)
  147 {
  148     // QPushButton has visual problems with big icons
  149     QToolButton *button = new QToolButton(parent);
  150     button->setText(name);
  151     button->setIcon(icon);
  152     button->setFocusPolicy(Qt::NoFocus);
  153     button->setIconSize(QSize(48, 48));
  154     button->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
  155     button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
  156     return button;
  157 }
  158 
  159 class PlayerTab : public TabBase
  160 {
  161 public:
  162     explicit PlayerTab(MediaWidget *mediaWidget_);
  163     ~PlayerTab() { }
  164 
  165     void activate()
  166     {
  167         layout()->addWidget(mediaWidget);
  168         mediaWidget->setFocus();
  169     }
  170 
  171 private:
  172     MediaWidget *mediaWidget;
  173 };
  174 
  175 PlayerTab::PlayerTab(MediaWidget *mediaWidget_) : mediaWidget(mediaWidget_)
  176 {
  177     QHBoxLayout *layout = new QHBoxLayout(this);
  178     layout->setMargin(0);
  179 }
  180 
  181 void MainWindow::run()
  182 {
  183     // Allow the user to enable or disable debugging
  184     // We handle this before the other parameters, as it may affect some
  185     // early debug messages
  186     //
  187     // --debug enables all debugging categories. It is possible to enable
  188     // each category individually by calling Kaffeine with:
  189     //  QT_LOGGING_RULES="epg.debug=true" kaffeine
  190 
  191     if (parser->isSet("debug")) {
  192         QLoggingCategory::defaultCategory()->setEnabled(QtDebugMsg, true);
  193         QLoggingCategory::setFilterRules(QStringLiteral(FILTER_RULE));
  194     } else {
  195         QLoggingCategory::setFilterRules(QStringLiteral("kaffeine.*.debug=false"));
  196     }
  197 
  198     readSettings();
  199 
  200     setAttribute(Qt::WA_DeleteOnClose, true);
  201 
  202     // menu structure
  203 
  204     QMenuBar *menuBar = QMainWindow::menuBar();
  205     collection = new KActionCollection(this);
  206 
  207     QMenu *menu = new QMenu(i18n("&File"), this);
  208     menuBar->addMenu(menu);
  209 
  210     QAction *action = KStandardAction::open(this, SLOT(open()), collection);
  211     menu->addAction(collection->addAction(QLatin1String("file_open"), action));
  212 
  213     action = new QAction(QIcon::fromTheme(QLatin1String("text-html"), QIcon(":text-html")),
  214         i18nc("@action:inmenu", "Open URL..."), collection);
  215     action->setShortcut(Qt::CTRL | Qt::Key_U);
  216     connect(action, SIGNAL(triggered(bool)), this, SLOT(openUrl()));
  217     menu->addAction(collection->addAction(QLatin1String("file_open_url"), action));
  218 
  219     actionOpenRecent = KStandardAction::openRecent(this, SLOT(openUrl(QUrl)), collection);
  220     actionOpenRecent->loadEntries(KSharedConfig::openConfig()->group("Recent Files"));
  221     menu->addAction(collection->addAction(QLatin1String("file_open_recent"), actionOpenRecent));
  222 
  223     menu->addSeparator();
  224 
  225     action = new QAction(QIcon::fromTheme(QLatin1String("media-optical-audio"), QIcon(":media-optical-audio")), i18n("Play Audio CD"), collection);
  226     connect(action, SIGNAL(triggered(bool)), this, SLOT(openAudioCd()));
  227     menu->addAction(collection->addAction(QLatin1String("file_play_audiocd"), action));
  228 
  229     action = new QAction(QIcon::fromTheme(QLatin1String("media-optical"), QIcon(":media-optical-video")), i18n("Play Video CD"), collection);
  230     connect(action, SIGNAL(triggered(bool)), this, SLOT(openVideoCd()));
  231     menu->addAction(collection->addAction(QLatin1String("file_play_videocd"), action));
  232 
  233     action = new QAction(QIcon::fromTheme(QLatin1String("media-optical"), QIcon(":media-optical")), i18n("Play DVD"), collection);
  234     connect(action, SIGNAL(triggered(bool)), this, SLOT(openDvd()));
  235     menu->addAction(collection->addAction(QLatin1String("file_play_dvd"), action));
  236 
  237     action = new QAction(QIcon::fromTheme(QLatin1String("media-optical"), QIcon(":media-optical")), i18nc("@action:inmenu", "Play DVD Folder"),
  238         collection);
  239     connect(action, SIGNAL(triggered()), this, SLOT(playDvdFolder()));
  240     menu->addAction(collection->addAction(QLatin1String("file_play_dvd_folder"), action));
  241 
  242     menu->addSeparator();
  243 
  244     action = KStandardAction::quit(this, SLOT(close()), collection);
  245     menu->addAction(collection->addAction(QLatin1String("file_quit"), action));
  246 
  247     QMenu *playerMenu = new QMenu(i18n("&Playback"), this);
  248     menuBar->addMenu(playerMenu);
  249 
  250     QMenu *playlistMenu = new QMenu(i18nc("menu bar", "Play&list"), this);
  251     menuBar->addMenu(playlistMenu);
  252 
  253 #if HAVE_DVB == 1
  254     QMenu *dvbMenu = new QMenu(i18n("&Television"), this);
  255     menuBar->addMenu(dvbMenu);
  256 #endif /* HAVE_DVB == 1 */
  257 
  258     menu = new QMenu(i18n("&Settings"), this);
  259     menuBar->addMenu(menu);
  260 
  261     action = KStandardAction::keyBindings(this, SLOT(configureKeys()), collection);
  262     menu->addAction(collection->addAction(QLatin1String("settings_keys"), action));
  263 
  264     action = KStandardAction::preferences(this, SLOT(configureKaffeine()), collection);
  265     menu->addAction(collection->addAction(QLatin1String("settings_kaffeine"), action));
  266 
  267     menuBar->addSeparator();
  268     KHelpMenu *helpMenu = new KHelpMenu(this, *aboutData);
  269     menuBar->addMenu(helpMenu->menu());
  270 
  271     // navigation bar - keep in sync with TabIndex enum!
  272 
  273     navigationBar = new QToolBar(QLatin1String("navigation_bar"));
  274     this->addToolBar(Qt::LeftToolBarArea, navigationBar);
  275     connect(navigationBar, SIGNAL(orientationChanged(Qt::Orientation)),
  276         this, SLOT(navigationBarOrientationChanged(Qt::Orientation)));
  277 
  278     tabBar = new QTabBar(navigationBar);
  279     tabBar->addTab(QIcon::fromTheme(QLatin1String("start-here-kde"), QIcon(":start-here-kde")), i18n("Start"));
  280     tabBar->addTab(QIcon::fromTheme(QLatin1String("kaffeine"), QIcon(":kaffeine")), i18n("Playback"));
  281     tabBar->addTab(QIcon::fromTheme(QLatin1String("view-media-playlist"), QIcon(":view-media-playlist")), i18n("Playlist"));
  282 #if HAVE_DVB == 1
  283     tabBar->addTab(QIcon::fromTheme(QLatin1String("video-television"), QIcon(":video-television")), i18n("Television"));
  284 #endif /* HAVE_DVB == 1 */
  285     tabBar->setShape(QTabBar::RoundedWest);
  286     tabBar->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
  287     connect(tabBar, SIGNAL(currentChanged(int)), this, SLOT(activateTab(int)));
  288     navigationBar->addWidget(tabBar);
  289 
  290     // control bar
  291 
  292     controlBar = new QToolBar(QLatin1String("control_bar"), this);
  293     this->addToolBar(Qt::BottomToolBarArea, controlBar);
  294 
  295     controlBar->setToolButtonStyle(Qt::ToolButtonIconOnly);
  296 
  297     autoHideControlBar = false;
  298     cursorHideTimer = new QTimer(this);
  299     cursorHideTimer->setInterval(1500);
  300     cursorHideTimer->setSingleShot(true);
  301     connect(cursorHideTimer, SIGNAL(timeout()), this, SLOT(hideCursor()));
  302 
  303     // main area
  304 
  305     QWidget *widget = new QWidget(this);
  306     stackedLayout = new StackedLayout(widget);
  307     setCentralWidget(widget);
  308 
  309     mediaWidget = new MediaWidget(playerMenu, controlBar, collection, widget);
  310     connect(mediaWidget, SIGNAL(displayModeChanged()), this, SLOT(displayModeChanged()));
  311     connect(mediaWidget, SIGNAL(changeCaption(QString)), this, SLOT(setWindowTitle(QString)));
  312 
  313     // tabs - keep in sync with TabIndex enum!
  314 
  315     TabBase *startTab = new StartTab(this);
  316     tabs.append(startTab);
  317     stackedLayout->addWidget(startTab);
  318 
  319     playerTab = new PlayerTab(mediaWidget);
  320     playerTab->activate();
  321     tabs.append(playerTab);
  322     stackedLayout->addWidget(playerTab);
  323 
  324     playlistTab = new PlaylistTab(playlistMenu, collection, mediaWidget);
  325     tabs.append(playlistTab);
  326     stackedLayout->addWidget(playlistTab);
  327 
  328 #if HAVE_DVB == 1
  329     dvbTab = new DvbTab(dvbMenu, collection, mediaWidget);
  330     connect(this, SIGNAL(mayCloseApplication(bool*,QWidget*)),
  331         dvbTab, SLOT(mayCloseApplication(bool*,QWidget*)));
  332     tabs.append(dvbTab);
  333     stackedLayout->addWidget(dvbTab);
  334 #endif /* HAVE_DVB == 1 */
  335 
  336     currentTabIndex = StartTabId;
  337 
  338     // actions also have to work if the menu bar is hidden (fullscreen)
  339     collection->addAssociatedWidget(this);
  340 
  341     // restore custom key bindings
  342     collection->readSettings();
  343 
  344     // Tray menu
  345     menu = new QMenu(i18n("Kaffeine"), this);
  346 
  347     action = new QAction(i18n("Play &File"), this);
  348     connect(action, SIGNAL(triggered(bool)), this, SLOT(open()));
  349     menu->addAction(action);
  350 
  351     action = new QAction(i18n("Play &Audio CD"), this);
  352     connect(action, SIGNAL(triggered(bool)), this, SLOT(openAudioCd()));
  353     menu->addAction(action);
  354 
  355     action = new QAction(i18n("Play &Video CD"), this);
  356     connect(action, SIGNAL(triggered(bool)), this, SLOT(openVideoCd()));
  357     menu->addAction(action);
  358 
  359     action = new QAction(i18n("Play &DVD"), this);
  360     connect(action, SIGNAL(triggered(bool)), this, SLOT(openDvd()));
  361     menu->addAction(action);
  362 
  363 #if HAVE_DVB == 1
  364     action = new QAction(i18n("&Watch Digital TV"), this);
  365     connect(action, SIGNAL(triggered(bool)), this, SLOT(playDvb()));
  366     menu->addAction(action);
  367 #endif
  368     action = new QAction(i18n("&Quit"), this);
  369     connect(action, SIGNAL(triggered(bool)), this, SLOT(close()));
  370     menu->addAction(action);
  371 
  372     // Tray Icon and its menu
  373     QMenu *trayMenu = new QMenu(this);
  374     trayIcon = new QSystemTrayIcon(this);
  375     trayIcon->setContextMenu(trayMenu);
  376     trayIcon->setIcon(QIcon::fromTheme(QLatin1String("kaffeine"), QIcon(":kaffeine")));
  377     trayIcon->setToolTip(i18n("Kaffeine"));
  378     trayIcon->setContextMenu(menu);
  379     connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(trayShowHide(QSystemTrayIcon::ActivationReason)) );
  380 
  381     // make sure that the bars are visible (fullscreen -> quit -> restore -> hidden)
  382     menuBar->show();
  383     navigationBar->show();
  384     controlBar->show();
  385     trayIcon->show();
  386 
  387     // workaround setAutoSaveSettings() which doesn't accept "IconOnly" as initial state
  388     controlBar->setToolButtonStyle(Qt::ToolButtonIconOnly);
  389 
  390     // initialize random number generator
  391     qsrand(QTime(0, 0, 0).msecsTo(QTime::currentTime()));
  392 
  393     // initialize dbus objects
  394     QDBusConnection::sessionBus().registerObject(QLatin1String("/"), new MprisRootObject(this),
  395         QDBusConnection::ExportAllContents);
  396     QDBusConnection::sessionBus().registerObject(QLatin1String("/Player"),
  397         new MprisPlayerObject(this, mediaWidget, playlistTab, this),
  398         QDBusConnection::ExportAllContents);
  399     QDBusConnection::sessionBus().registerObject(QLatin1String("/TrackList"),
  400         new MprisTrackListObject(playlistTab, this), QDBusConnection::ExportAllContents);
  401 #if HAVE_DVB == 1
  402     QDBusConnection::sessionBus().registerObject(QLatin1String("/Television"),
  403         new DBusTelevisionObject(dvbTab, this), QDBusConnection::ExportAllContents);
  404 #endif /* HAVE_DVB == 1 */
  405     QDBusConnection::sessionBus().registerService(QLatin1String("org.mpris.kaffeine"));
  406 
  407     parseArgs();
  408     show();
  409 }
  410 
  411 MainWindow::~MainWindow()
  412 {
  413     actionOpenRecent->saveEntries(KSharedConfig::openConfig()->group("Recent Files"));
  414 
  415     if (!temporaryUrls.isEmpty()) {
  416         KIO::del(temporaryUrls);
  417     }
  418 
  419     int value = 0;
  420 
  421     switch (mediaWidget->getDisplayMode()) {
  422     case MediaWidget::NormalMode: value = 0; break;
  423     case MediaWidget::MinimalMode: value = 1; break;
  424     case MediaWidget::FullScreenMode: value = 2; break;
  425     case MediaWidget::FullScreenReturnToMinimalMode: value = 2; break;
  426     }
  427 
  428     KSharedConfig::openConfig()->group("MainWindow").writeEntry("DisplayMode", value);
  429 }
  430 
  431 void MainWindow::close()
  432 {
  433     bool ok = true;
  434 
  435 #if HAVE_DVB == 1
  436     dvbTab->mayCloseApplication(&ok, mediaWidget);
  437 #endif /* HAVE_DVB == 1 */
  438 
  439     if (ok) {
  440         writeSettings();
  441         mediaWidget->stop();
  442         QMainWindow::close();
  443         Configuration::detach();
  444         QCoreApplication::exit(0);
  445     }
  446 }
  447 
  448 void MainWindow::readSettings()
  449 {
  450     QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName());
  451     const QByteArray geometry = settings.value("geometry", QByteArray()).toByteArray();
  452     if (geometry.isEmpty()) {
  453         const QRect availableGeometry = QApplication::desktop()->availableGeometry(this);
  454         resize(availableGeometry.width() / 3, availableGeometry.height() / 2);
  455         move((availableGeometry.width() - width()) / 2,
  456              (availableGeometry.height() - height()) / 2);
  457     } else {
  458         restoreGeometry(geometry);
  459     }
  460 }
  461 
  462 void MainWindow::writeSettings()
  463 {
  464     QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName());
  465     settings.setValue("geometry", saveGeometry());
  466 }
  467 
  468 MainWindow::MainWindow(KAboutData *aboutData, QCommandLineParser *parser)
  469 {
  470     this->aboutData = aboutData;
  471     this->parser = parser;
  472 
  473     parser->addOption(QCommandLineOption(QStringList() << QLatin1String("d") << QLatin1String("debug"), i18n("Enable all debug messages. Please notice that Kaffeine also allows enabling debug messages per category, by using the environment var:\nQT_LOGGING_RULES=kaffeine.category.debug=true\nwhere 'category' can be:\n" CATEGORIES)));
  474     parser->addOption(QCommandLineOption(QStringList() << QLatin1String("tempfile"), i18n("The files/URLs opened by the application will be deleted after use")));
  475     parser->addOption(QCommandLineOption(QStringList() << QLatin1String("f") << QLatin1String("fullscreen"), i18n("Start in full screen mode")));
  476     parser->addOption(QCommandLineOption(QStringList() << QLatin1String("m") << QLatin1String("minimal"), i18n("Start in minimal mode")));
  477     parser->addOption(QCommandLineOption(QStringList() << QLatin1String("t") << QLatin1String("alwaysontop"), i18n("Start with always on top")));
  478     parser->addOption(QCommandLineOption(QStringList() << QLatin1String("audiocd"), i18n("Play Audio CD")));
  479     parser->addOption(QCommandLineOption(QStringList() << QLatin1String("videocd"), i18n("Play Video CD")));
  480     parser->addOption(QCommandLineOption(QStringList() << QLatin1String("dvd"), i18n("Play DVD")));
  481     parser->addOption(QCommandLineOption(QStringList() << QLatin1String("aspectratio"), "Force starting with an specific aspect ratio", QLatin1String("aspect ratio")));
  482 
  483 #if HAVE_DVB == 1
  484     parser->addOption(QCommandLineOption(QStringList() << QLatin1String("dumpdvb"), i18nc("command line option", "Dump dvb data (debug option)")));
  485     parser->addOption(QCommandLineOption(QStringList() << QLatin1String("channel"), i18nc("command line option", "Play TV channel"), QLatin1String("name / number")));
  486     parser->addOption(QCommandLineOption(QStringList() << QLatin1String("tv"), i18nc("command line option", "(deprecated option)"), QLatin1String("channel")));
  487     parser->addOption(QCommandLineOption(QStringList() << QLatin1String("lastchannel"), i18nc("command line option", "Play last tuned TV channel")));
  488 #endif
  489     parser->addPositionalArgument(QLatin1String("[file]"), i18n("Files or URLs to play"));
  490 }
  491 
  492 void MainWindow::parseArgs(const QString workingDirectory)
  493 {
  494     /* Parse first arguments that aren't mutually exclusive */
  495 
  496     if (parser->isSet("alwaysontop")) {
  497         Qt::WindowFlags flags = this->windowFlags();
  498         flags |= Qt::WindowStaysOnTopHint;
  499         this->setWindowFlags(flags);
  500     }
  501 
  502     if (parser->isSet("fullscreen")) {
  503         mediaWidget->setDisplayMode(MediaWidget::FullScreenMode);
  504     } else if (parser->isSet("minimal")) {
  505         mediaWidget->setDisplayMode(MediaWidget::MinimalMode);
  506     } else {
  507         // set display mode
  508         switch (Configuration::instance()->getStartupDisplayMode()) {
  509         case Configuration::StartupNormalMode:
  510             // nothing to do
  511             break;
  512         case Configuration::StartupMinimalMode:
  513             mediaWidget->setDisplayMode(MediaWidget::MinimalMode);
  514             break;
  515         case Configuration::StartupFullScreenMode:
  516             mediaWidget->setDisplayMode(MediaWidget::FullScreenMode);
  517             break;
  518         case Configuration::StartupRememberLastSetting: {
  519             int value = KSharedConfig::openConfig()->group("MainWindow").readEntry("DisplayMode", 0);
  520 
  521             switch (value) {
  522             case 0:
  523                 // nothing to do
  524                 break;
  525             case 1:
  526                 mediaWidget->setDisplayMode(MediaWidget::MinimalMode);
  527                 break;
  528             case 2:
  529                 mediaWidget->setDisplayMode(MediaWidget::FullScreenMode);
  530                 break;
  531             }
  532 
  533             break;
  534         } /* case */
  535         } /* switch */
  536     }
  537 
  538     if (parser->isSet("aspectratio")) {
  539         MediaWidget::AspectRatio aspectRatio = MediaWidget::AspectRatioAuto;
  540         QString aspect;
  541 
  542         aspect = parser->value("aspectratio");
  543 
  544         if (aspect == "1:1")
  545             aspectRatio = MediaWidget::AspectRatio1_1;
  546         else if (aspect == "4:3")
  547             aspectRatio = MediaWidget::AspectRatio4_3;
  548         else if (aspect == "5:4")
  549             aspectRatio = MediaWidget::AspectRatio5_4;
  550         else if (aspect == "16:9")
  551             aspectRatio = MediaWidget::AspectRatio16_9;
  552         else if (aspect == "16:10")
  553             aspectRatio = MediaWidget::AspectRatio16_10;
  554         else if (aspect == "2.21:1")
  555             aspectRatio = MediaWidget::AspectRatio221_100;
  556         else if (aspect == "2.35:1")
  557             aspectRatio = MediaWidget::AspectRatio235_100;
  558         else if (aspect == "2.39:1")
  559             aspectRatio = MediaWidget::AspectRatio239_100;
  560 
  561         mediaWidget->setAspectRatio(aspectRatio);
  562     }
  563 
  564 
  565 #if HAVE_DVB == 1
  566     if (parser->isSet("dumpdvb")) {
  567         dvbTab->enableDvbDump();
  568     }
  569 #endif
  570 
  571     /*
  572      * Now, parse arguments that are mutually exclusive
  573      */
  574 
  575 #if HAVE_DVB == 1
  576     QString channel;
  577 
  578     channel = parser->value("channel");
  579 
  580     if (!channel.isEmpty()) {
  581         activateTab(DvbTabId);
  582         dvbTab->playChannel(channel);
  583 
  584         return;
  585     }
  586 
  587     channel = parser->value("tv");
  588     if (!channel.isEmpty()) {
  589         activateTab(DvbTabId);
  590         dvbTab->playChannel(channel);
  591 
  592         return;
  593     }
  594 
  595     if (parser->isSet("lastchannel")) {
  596         activateTab(DvbTabId);
  597         dvbTab->playLastChannel();
  598 
  599         return;
  600     }
  601 #endif /* HAVE_DVB == 1 */
  602 
  603     if (parser->isSet("audiocd")) {
  604         if (parser->positionalArguments().count() > 0) {
  605             openAudioCd(parser->positionalArguments().first());
  606         } else {
  607             openAudioCd();
  608         }
  609         return;
  610     }
  611 
  612     if (parser->isSet("videocd")) {
  613         if (parser->positionalArguments().count() > 0) {
  614             openVideoCd(parser->positionalArguments().first());
  615         } else {
  616             openVideoCd();
  617         }
  618         return;
  619     }
  620 
  621     if (parser->isSet("dvd")) {
  622         if (parser->positionalArguments().count() > 0) {
  623             openDvd(parser->positionalArguments().first());
  624         } else {
  625             openDvd();
  626         }
  627         return;
  628     }
  629 
  630     if (parser->positionalArguments().count() > 0) {
  631         QList<QUrl> urls;
  632 
  633         for (int i = 0; i < parser->positionalArguments().count(); ++i) {
  634             QUrl url = QUrl::fromUserInput(parser->positionalArguments().at(i), workingDirectory);
  635 
  636             if (url.isValid()) {
  637                 urls.append(url);
  638             }
  639         }
  640 
  641         if (parser->isSet("tempfile")) {
  642             temporaryUrls.append(urls);
  643         }
  644 
  645         if (urls.size() >= 2) {
  646             activateTab(PlaylistTabId);
  647             playlistTab->appendToVisiblePlaylist(urls, true);
  648         } else if (!urls.isEmpty()) {
  649             openUrl(urls.at(0));
  650         }
  651         return;
  652     }
  653 }
  654 
  655 void MainWindow::displayModeChanged()
  656 {
  657     MediaWidget::DisplayMode displayMode = mediaWidget->getDisplayMode();
  658 
  659     switch (displayMode) {
  660     case MediaWidget::FullScreenMode:
  661     case MediaWidget::FullScreenReturnToMinimalMode:
  662         setWindowState(windowState() | Qt::WindowFullScreen);
  663         break;
  664     case MediaWidget::MinimalMode:
  665     case MediaWidget::NormalMode:
  666         setWindowState(windowState() & (~Qt::WindowFullScreen));
  667         break;
  668     }
  669 
  670     switch (displayMode) {
  671     case MediaWidget::FullScreenMode:
  672     case MediaWidget::FullScreenReturnToMinimalMode:
  673     case MediaWidget::MinimalMode:
  674         menuBar()->hide();
  675         navigationBar->hide();
  676         controlBar->hide();
  677         autoHideControlBar = true;
  678         cursorHideTimer->start();
  679         break;
  680     case MediaWidget::NormalMode:
  681         menuBar()->show();
  682         navigationBar->show();
  683         controlBar->show();
  684         autoHideControlBar = false;
  685         cursorHideTimer->stop();
  686         unsetCursor();
  687         break;
  688     }
  689     tabs.at(currentTabIndex)->toggleDisplayMode(displayMode);
  690 }
  691 
  692 void MainWindow::trayShowHide(QSystemTrayIcon::ActivationReason reason)
  693 {
  694     if (reason != QSystemTrayIcon::DoubleClick)
  695         return;
  696 
  697     if (isVisible())
  698         hide();
  699     else {
  700         show();
  701         raise();
  702         setFocus();
  703     }
  704 }
  705 
  706 void MainWindow::open()
  707 {
  708     if (isMinimized())
  709         showNormal();
  710 
  711     QList<QUrl> urls = QFileDialog::getOpenFileUrls(this, i18nc("@title:window", "Open files"), QUrl(), MediaWidget::extensionFilter());
  712 
  713 //  trayIcon->showMessage("Open", "Opening file(s)");
  714     if (urls.size() >= 2) {
  715         activateTab(PlaylistTabId);
  716         playlistTab->appendToVisiblePlaylist(urls, true);
  717     } else if (!urls.isEmpty()) {
  718         openUrl(urls.at(0));
  719     }
  720 }
  721 
  722 void MainWindow::openUrl()
  723 {
  724     openUrl(QInputDialog::getText(this, i18nc("@title:window", "Open URL"), i18n("Enter a URL:")));
  725 }
  726 
  727 void MainWindow::openUrl(const QUrl &url)
  728 {
  729     if (!url.isValid()) {
  730         return;
  731     }
  732 
  733     // we need to copy "url" because addUrl() may invalidate it
  734     QUrl copy(url);
  735     actionOpenRecent->addUrl(copy); // moves the url to the top of the list
  736 
  737     if (currentTabIndex != PlaylistTabId) {
  738         activateTab(PlayerTabId);
  739     }
  740 
  741     playlistTab->appendToVisiblePlaylist(QList<QUrl>() << copy, true);
  742 }
  743 
  744 void MainWindow::openAudioCd(const QString &device)
  745 {
  746     if (isMinimized())
  747         showNormal();
  748 
  749     activateTab(PlayerTabId);
  750     mediaWidget->playAudioCd(device);
  751 }
  752 
  753 void MainWindow::openVideoCd(const QString &device)
  754 {
  755     if (isMinimized())
  756         showNormal();
  757 
  758     activateTab(PlayerTabId);
  759     mediaWidget->playVideoCd(device);
  760 }
  761 
  762 void MainWindow::openDvd(const QString &device)
  763 {
  764     if (isMinimized())
  765         showNormal();
  766 
  767     activateTab(PlayerTabId);
  768     mediaWidget->playDvd(device);
  769 }
  770 
  771 void MainWindow::playDvdFolder()
  772 {
  773     QString folder = QFileDialog::getExistingDirectory(this, QString());
  774 
  775     if (!folder.isEmpty()) {
  776         openDvd(folder);
  777     }
  778 }
  779 
  780 void MainWindow::playDvb()
  781 {
  782     if (isMinimized())
  783         showNormal();
  784 
  785     activateTab(DvbTabId);
  786     dvbTab->playLastChannel();
  787 }
  788 
  789 void MainWindow::configureKeys()
  790 {
  791     KShortcutsDialog::configure(collection);
  792 }
  793 
  794 void MainWindow::configureKaffeine()
  795 {
  796     QDialog *dialog = new ConfigurationDialog(this);
  797     dialog->setAttribute(Qt::WA_DeleteOnClose, true);
  798     dialog->setModal(true);
  799     dialog->show();
  800 }
  801 
  802 void MainWindow::navigationBarOrientationChanged(Qt::Orientation orientation)
  803 {
  804     if (orientation == Qt::Horizontal) {
  805         tabBar->setShape(QTabBar::RoundedNorth);
  806     } else {
  807         tabBar->setShape(QTabBar::RoundedWest);
  808     }
  809 }
  810 
  811 void MainWindow::activateTab(int tabIndex)
  812 {
  813     currentTabIndex = tabIndex;
  814     tabBar->setCurrentIndex(tabIndex);
  815 
  816     /*
  817      * Ensure that menus and timers will be properly shown,
  818      * according with the selected display mode.
  819      */
  820     stackedLayout->setCurrentIndex(currentTabIndex);
  821     tabs.at(currentTabIndex)->activate();
  822 
  823     emit displayModeChanged();
  824 }
  825 
  826 void MainWindow::hideCursor()
  827 {
  828     setCursor(Qt::BlankCursor);
  829 }
  830 
  831 void MainWindow::closeEvent(QCloseEvent *event)
  832 {
  833     bool ok = true;
  834     emit mayCloseApplication(&ok, this);
  835 
  836     if (!ok) {
  837         event->ignore();
  838     } else {
  839         MainWindow::close();
  840     }
  841 }
  842 
  843 bool MainWindow::event(QEvent *event)
  844 {
  845     bool retVal = QMainWindow::event(event); // this has to be done before calling setVisible()
  846 
  847     // FIXME we depend on QEvent::HoverMove (instead of QEvent::MouseMove)
  848     // but the latter depends on mouse tracking being enabled on this widget
  849     // and all its children (especially the video widget) ...
  850 
  851     switch (event->type()) {
  852     case QEvent::HoverMove: {
  853         int x = reinterpret_cast<QHoverEvent *> (event)->pos().x();
  854         int y = reinterpret_cast<QHoverEvent *> (event)->pos().y();
  855 
  856         if ((y < 0) || (y >= height()) ||
  857             (x < 0) || (x >= width())) {
  858             // QHoverEvent sometimes reports quite strange coordinates - ignore them
  859             return retVal;
  860         }
  861 
  862         if (autoHideControlBar) {
  863             cursorHideTimer->stop();
  864             unsetCursor();
  865 
  866             switch (toolBarArea(controlBar)) {
  867             case Qt::TopToolBarArea:
  868                 controlBar->setVisible(y < 60);
  869                 break;
  870             case Qt::BottomToolBarArea:
  871                 controlBar->setVisible(y >= (height() - 60));
  872                 menuBar()->setVisible(y < 60);
  873                 break;
  874             default:
  875                 break;
  876             }
  877 
  878             if (controlBar->isHidden() || menuBar()->isHidden()) {
  879                 cursorHideTimer->start();
  880             }
  881         }
  882 
  883         tabs.at(currentTabIndex)->mouse_move(x, y);
  884         break;
  885     }
  886     default:
  887         break;
  888     }
  889 
  890     return retVal;
  891 }
  892 
  893 void MainWindow::keyPressEvent(QKeyEvent *event)
  894 {
  895     if (event->key() == Qt::Key_Escape) {
  896         mediaWidget->setDisplayMode(MediaWidget::NormalMode);
  897     }
  898 
  899     QMainWindow::keyPressEvent(event);
  900 }
  901 
  902 void MainWindow::leaveEvent(QEvent *event)
  903 {
  904     if (autoHideControlBar) {
  905         menuBar()->setVisible(false);
  906         controlBar->setVisible(false);
  907         tabs.at(currentTabIndex)->mouse_move(-1, -1);
  908     }
  909 
  910     QMainWindow::leaveEvent(event);
  911 }