File indexing completed on 2024-04-28 04:50:49
0001 /* 0002 * mainwindow.cpp 0003 * 0004 * Copyright (C) 2007-2011 Christoph Pfister <christophpfister@gmail.com> 0005 * 0006 * This program is free software; you can redistribute it and/or modify 0007 * it under the terms of the GNU General Public License as published by 0008 * the Free Software Foundation; either version 2 of the License, or 0009 * (at your option) any later version. 0010 * 0011 * This program is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0014 * GNU General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU General Public License along 0017 * with this program; if not, write to the Free Software Foundation, Inc., 0018 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 0019 */ 0020 0021 #include "log.h" 0022 0023 #include <KAboutData> 0024 #include <KActionCollection> 0025 #include <KConfigGroup> 0026 #include <KHelpMenu> 0027 #include <kio/deletejob.h> 0028 #include <KRecentFilesAction> 0029 #include <KSharedConfig> 0030 #include <KShortcutsDialog> 0031 #include <QApplication> 0032 #include <QCommandLineOption> 0033 #include <QDBusConnection> 0034 #include <QDesktopWidget> 0035 #include <QFileDialog> 0036 #include <QHoverEvent> 0037 #include <QInputDialog> 0038 #include <QLoggingCategory> 0039 #include <QMainWindow> 0040 #include <QMenu> 0041 #include <QMenuBar> 0042 #include <QSettings> 0043 #include <QStackedLayout> 0044 #include <QTabBar> 0045 #include <QToolBar> 0046 0047 #include "configuration.h" 0048 #include "configurationdialog.h" 0049 #include "dbusobjects.h" 0050 #include "dvb/dvbtab.h" 0051 #include "mainwindow.h" 0052 #include "playlist/playlisttab.h" 0053 0054 // log categories. Should match log.h 0055 0056 Q_LOGGING_CATEGORY(logCam, "kaffeine.cam") 0057 Q_LOGGING_CATEGORY(logDev, "kaffeine.dev") 0058 Q_LOGGING_CATEGORY(logDvb, "kaffeine.dvb") 0059 Q_LOGGING_CATEGORY(logDvbSi, "kaffeine.dvbsi") 0060 Q_LOGGING_CATEGORY(logEpg, "kaffeine.epg") 0061 0062 Q_LOGGING_CATEGORY(logConfig, "kaffeine.config") 0063 Q_LOGGING_CATEGORY(logMediaWidget, "kaffeine.mediawidget") 0064 Q_LOGGING_CATEGORY(logPlaylist, "kaffeine.playlist") 0065 Q_LOGGING_CATEGORY(logSql, "kaffeine.sql") 0066 Q_LOGGING_CATEGORY(logVlc, "kaffeine.vlc") 0067 0068 #define FILTER_RULE "kaffeine.*.debug=true" 0069 0070 #define CATEGORIES "cam, dev, dvb, dvbsi, epg, config, mediawidget, playlist, sql, vlc" 0071 0072 class StackedLayout : public QStackedLayout 0073 { 0074 public: 0075 explicit StackedLayout(QWidget *parent) : QStackedLayout(parent) { } 0076 ~StackedLayout() { } 0077 0078 QSize minimumSize() const override 0079 { 0080 QWidget *widget = currentWidget(); 0081 0082 if (widget != NULL) { 0083 return widget->minimumSizeHint(); 0084 } 0085 0086 return QSize(); 0087 } 0088 }; 0089 0090 class StartTab : public TabBase 0091 { 0092 public: 0093 explicit StartTab(MainWindow *mainWindow); 0094 ~StartTab() { } 0095 0096 private: 0097 void activate() override { } 0098 0099 QAbstractButton *addShortcut(const QString &name, const QIcon &icon, QWidget *parent); 0100 }; 0101 0102 StartTab::StartTab(MainWindow *mainWindow) 0103 { 0104 setBackgroundRole(QPalette::Base); 0105 setAutoFillBackground(true); 0106 0107 QGridLayout *gridLayout = new QGridLayout(this); 0108 gridLayout->setAlignment(Qt::AlignCenter); 0109 gridLayout->setMargin(10); 0110 gridLayout->setSpacing(15); 0111 0112 QAbstractButton *button = 0113 addShortcut(i18n("&1 Play File"), QIcon::fromTheme(QLatin1String("video-x-generic"), QIcon(":video-x-generic")), this); 0114 button->setShortcut(Qt::Key_1); 0115 button->setWhatsThis(i18n("Open dialog to play a file")); 0116 connect(button, SIGNAL(clicked()), mainWindow, SLOT(open())); 0117 gridLayout->addWidget(button, 0, 0); 0118 0119 button = addShortcut(i18n("&2 Play Audio CD"), QIcon::fromTheme(QLatin1String("media-optical-audio"), QIcon(":media-optical-audio")), this); 0120 button->setShortcut(Qt::Key_2); 0121 button->setWhatsThis(i18n("Start playing an audio CD. It assumes that the CD is already there at the CD drive")); 0122 connect(button, SIGNAL(clicked()), mainWindow, SLOT(openAudioCd())); 0123 gridLayout->addWidget(button, 0, 1); 0124 0125 button = addShortcut(i18n("&3 Play Video CD"), QIcon::fromTheme(QLatin1String("media-optical"), QIcon(":media-optical-video")), this); 0126 button->setShortcut(Qt::Key_3); 0127 button->setWhatsThis(i18n("Start playing a Video CD. It assumes that the CD is already there at the CD drive")); 0128 connect(button, SIGNAL(clicked()), mainWindow, SLOT(openVideoCd())); 0129 gridLayout->addWidget(button, 0, 2); 0130 0131 button = addShortcut(i18n("&4 Play DVD"), QIcon::fromTheme(QLatin1String("media-optical"), QIcon(":media-optical")), this); 0132 button->setShortcut(Qt::Key_4); 0133 button->setWhatsThis(i18n("Start playing a DVD. It assumes that the DVD is already there at the DVD drive")); 0134 connect(button, SIGNAL(clicked()), mainWindow, SLOT(openDvd())); 0135 gridLayout->addWidget(button, 1, 0); 0136 0137 #if HAVE_DVB == 1 0138 button = addShortcut(i18n("&5 Digital TV"), QIcon::fromTheme(QLatin1String("video-television"), QIcon(":video-television")), this); 0139 button->setShortcut(Qt::Key_5); 0140 button->setWhatsThis("Open the Digital TV live view window. If the TV channels are already scanned, it will start playing the last channel"); 0141 connect(button, SIGNAL(clicked()), mainWindow, SLOT(playDvb())); 0142 gridLayout->addWidget(button, 1, 1); 0143 #endif /* HAVE_DVB == 1 */ 0144 } 0145 0146 QAbstractButton *StartTab::addShortcut(const QString &name, const QIcon &icon, QWidget *parent) 0147 { 0148 // QPushButton has visual problems with big icons 0149 QToolButton *button = new QToolButton(parent); 0150 button->setText(name); 0151 button->setIcon(icon); 0152 button->setFocusPolicy(Qt::NoFocus); 0153 button->setIconSize(QSize(48, 48)); 0154 button->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); 0155 button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); 0156 return button; 0157 } 0158 0159 class PlayerTab : public TabBase 0160 { 0161 public: 0162 explicit PlayerTab(MediaWidget *mediaWidget_); 0163 ~PlayerTab() { } 0164 0165 void activate() override 0166 { 0167 layout()->addWidget(mediaWidget); 0168 mediaWidget->setFocus(); 0169 } 0170 0171 private: 0172 MediaWidget *mediaWidget; 0173 }; 0174 0175 PlayerTab::PlayerTab(MediaWidget *mediaWidget_) : mediaWidget(mediaWidget_) 0176 { 0177 QHBoxLayout *layout = new QHBoxLayout(this); 0178 layout->setMargin(0); 0179 } 0180 0181 void MainWindow::run() 0182 { 0183 // Allow the user to enable or disable debugging 0184 // We handle this before the other parameters, as it may affect some 0185 // early debug messages 0186 // 0187 // --debug enables all debugging categories. It is possible to enable 0188 // each category individually by calling Kaffeine with: 0189 // QT_LOGGING_RULES="epg.debug=true" kaffeine 0190 0191 if (parser->isSet("debug")) { 0192 QLoggingCategory::defaultCategory()->setEnabled(QtDebugMsg, true); 0193 QLoggingCategory::setFilterRules(QStringLiteral(FILTER_RULE)); 0194 } else { 0195 QLoggingCategory::setFilterRules(QStringLiteral("kaffeine.*.debug=false")); 0196 } 0197 0198 readSettings(); 0199 0200 setAttribute(Qt::WA_DeleteOnClose, true); 0201 0202 // menu structure 0203 0204 QMenuBar *menuBar = QMainWindow::menuBar(); 0205 collection = new KActionCollection(this); 0206 0207 QMenu *menu = new QMenu(i18n("&File"), this); 0208 menuBar->addMenu(menu); 0209 0210 QAction *action = KStandardAction::open(this, SLOT(open()), collection); 0211 menu->addAction(collection->addAction(QLatin1String("file_open"), action)); 0212 0213 action = new QAction(QIcon::fromTheme(QLatin1String("text-html"), QIcon(":text-html")), 0214 i18nc("@action:inmenu", "Open URL..."), collection); 0215 action->setShortcut(Qt::CTRL | Qt::Key_U); 0216 connect(action, SIGNAL(triggered(bool)), this, SLOT(openUrl())); 0217 menu->addAction(collection->addAction(QLatin1String("file_open_url"), action)); 0218 0219 actionOpenRecent = KStandardAction::openRecent(this, SLOT(openUrl(QUrl)), collection); 0220 actionOpenRecent->loadEntries(KSharedConfig::openConfig()->group("Recent Files")); 0221 menu->addAction(collection->addAction(QLatin1String("file_open_recent"), actionOpenRecent)); 0222 0223 menu->addSeparator(); 0224 0225 action = new QAction(QIcon::fromTheme(QLatin1String("media-optical-audio"), QIcon(":media-optical-audio")), i18n("Play Audio CD"), collection); 0226 connect(action, SIGNAL(triggered(bool)), this, SLOT(openAudioCd())); 0227 menu->addAction(collection->addAction(QLatin1String("file_play_audiocd"), action)); 0228 0229 action = new QAction(QIcon::fromTheme(QLatin1String("media-optical"), QIcon(":media-optical-video")), i18n("Play Video CD"), collection); 0230 connect(action, SIGNAL(triggered(bool)), this, SLOT(openVideoCd())); 0231 menu->addAction(collection->addAction(QLatin1String("file_play_videocd"), action)); 0232 0233 action = new QAction(QIcon::fromTheme(QLatin1String("media-optical"), QIcon(":media-optical")), i18n("Play DVD"), collection); 0234 connect(action, SIGNAL(triggered(bool)), this, SLOT(openDvd())); 0235 menu->addAction(collection->addAction(QLatin1String("file_play_dvd"), action)); 0236 0237 action = new QAction(QIcon::fromTheme(QLatin1String("media-optical"), QIcon(":media-optical")), i18nc("@action:inmenu", "Play DVD Folder"), 0238 collection); 0239 connect(action, SIGNAL(triggered()), this, SLOT(playDvdFolder())); 0240 menu->addAction(collection->addAction(QLatin1String("file_play_dvd_folder"), action)); 0241 0242 menu->addSeparator(); 0243 0244 action = KStandardAction::quit(this, SLOT(close()), collection); 0245 menu->addAction(collection->addAction(QLatin1String("file_quit"), action)); 0246 0247 QMenu *playerMenu = new QMenu(i18n("&Playback"), this); 0248 menuBar->addMenu(playerMenu); 0249 0250 QMenu *playlistMenu = new QMenu(i18nc("menu bar", "Play&list"), this); 0251 menuBar->addMenu(playlistMenu); 0252 0253 #if HAVE_DVB == 1 0254 QMenu *dvbMenu = new QMenu(i18n("&Television"), this); 0255 menuBar->addMenu(dvbMenu); 0256 #endif /* HAVE_DVB == 1 */ 0257 0258 menu = new QMenu(i18n("&Settings"), this); 0259 menuBar->addMenu(menu); 0260 0261 action = KStandardAction::keyBindings(this, SLOT(configureKeys()), collection); 0262 menu->addAction(collection->addAction(QLatin1String("settings_keys"), action)); 0263 0264 action = KStandardAction::preferences(this, SLOT(configureKaffeine()), collection); 0265 menu->addAction(collection->addAction(QLatin1String("settings_kaffeine"), action)); 0266 0267 menuBar->addSeparator(); 0268 KHelpMenu *helpMenu = new KHelpMenu(this, *aboutData); 0269 menuBar->addMenu(helpMenu->menu()); 0270 0271 // navigation bar - keep in sync with TabIndex enum! 0272 0273 navigationBar = new QToolBar(QLatin1String("navigation_bar")); 0274 this->addToolBar(Qt::LeftToolBarArea, navigationBar); 0275 connect(navigationBar, SIGNAL(orientationChanged(Qt::Orientation)), 0276 this, SLOT(navigationBarOrientationChanged(Qt::Orientation))); 0277 0278 tabBar = new QTabBar(navigationBar); 0279 tabBar->addTab(QIcon::fromTheme(QLatin1String("start-here-kde"), QIcon(":start-here-kde")), i18n("Start")); 0280 tabBar->addTab(QIcon::fromTheme(QLatin1String("kaffeine"), QIcon(":kaffeine")), i18n("Playback")); 0281 tabBar->addTab(QIcon::fromTheme(QLatin1String("view-media-playlist"), QIcon(":view-media-playlist")), i18n("Playlist")); 0282 #if HAVE_DVB == 1 0283 tabBar->addTab(QIcon::fromTheme(QLatin1String("video-television"), QIcon(":video-television")), i18n("Television")); 0284 #endif /* HAVE_DVB == 1 */ 0285 tabBar->setShape(QTabBar::RoundedWest); 0286 tabBar->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); 0287 connect(tabBar, SIGNAL(currentChanged(int)), this, SLOT(activateTab(int))); 0288 navigationBar->addWidget(tabBar); 0289 0290 // control bar 0291 0292 controlBar = new QToolBar(QLatin1String("control_bar"), this); 0293 this->addToolBar(Qt::BottomToolBarArea, controlBar); 0294 0295 controlBar->setToolButtonStyle(Qt::ToolButtonIconOnly); 0296 0297 autoHideControlBar = false; 0298 cursorHideTimer = new QTimer(this); 0299 cursorHideTimer->setInterval(1500); 0300 cursorHideTimer->setSingleShot(true); 0301 connect(cursorHideTimer, SIGNAL(timeout()), this, SLOT(hideCursor())); 0302 0303 // main area 0304 0305 QWidget *widget = new QWidget(this); 0306 stackedLayout = new StackedLayout(widget); 0307 setCentralWidget(widget); 0308 0309 mediaWidget = new MediaWidget(playerMenu, controlBar, collection, widget); 0310 connect(mediaWidget, SIGNAL(displayModeChanged()), this, SLOT(displayModeChanged())); 0311 connect(mediaWidget, SIGNAL(changeCaption(QString)), this, SLOT(setWindowTitle(QString))); 0312 0313 // tabs - keep in sync with TabIndex enum! 0314 0315 TabBase *startTab = new StartTab(this); 0316 tabs.append(startTab); 0317 stackedLayout->addWidget(startTab); 0318 0319 playerTab = new PlayerTab(mediaWidget); 0320 playerTab->activate(); 0321 tabs.append(playerTab); 0322 stackedLayout->addWidget(playerTab); 0323 0324 playlistTab = new PlaylistTab(playlistMenu, collection, mediaWidget); 0325 tabs.append(playlistTab); 0326 stackedLayout->addWidget(playlistTab); 0327 0328 #if HAVE_DVB == 1 0329 dvbTab = new DvbTab(dvbMenu, collection, mediaWidget); 0330 connect(this, SIGNAL(mayCloseApplication(bool*,QWidget*)), 0331 dvbTab, SLOT(mayCloseApplication(bool*,QWidget*))); 0332 tabs.append(dvbTab); 0333 stackedLayout->addWidget(dvbTab); 0334 #endif /* HAVE_DVB == 1 */ 0335 0336 currentTabIndex = StartTabId; 0337 0338 // actions also have to work if the menu bar is hidden (fullscreen) 0339 collection->addAssociatedWidget(this); 0340 0341 // restore custom key bindings 0342 collection->readSettings(); 0343 0344 // Tray menu 0345 menu = new QMenu(i18n("Kaffeine"), this); 0346 0347 action = new QAction(i18n("Play &File"), this); 0348 connect(action, SIGNAL(triggered(bool)), this, SLOT(open())); 0349 menu->addAction(action); 0350 0351 action = new QAction(i18n("Play &Audio CD"), this); 0352 connect(action, SIGNAL(triggered(bool)), this, SLOT(openAudioCd())); 0353 menu->addAction(action); 0354 0355 action = new QAction(i18n("Play &Video CD"), this); 0356 connect(action, SIGNAL(triggered(bool)), this, SLOT(openVideoCd())); 0357 menu->addAction(action); 0358 0359 action = new QAction(i18n("Play &DVD"), this); 0360 connect(action, SIGNAL(triggered(bool)), this, SLOT(openDvd())); 0361 menu->addAction(action); 0362 0363 #if HAVE_DVB == 1 0364 action = new QAction(i18n("&Watch Digital TV"), this); 0365 connect(action, SIGNAL(triggered(bool)), this, SLOT(playDvb())); 0366 menu->addAction(action); 0367 #endif 0368 action = new QAction(i18n("&Quit"), this); 0369 connect(action, SIGNAL(triggered(bool)), this, SLOT(close())); 0370 menu->addAction(action); 0371 0372 // Tray Icon and its menu 0373 QMenu *trayMenu = new QMenu(this); 0374 trayIcon = new QSystemTrayIcon(this); 0375 trayIcon->setContextMenu(trayMenu); 0376 trayIcon->setIcon(QIcon::fromTheme(QLatin1String("kaffeine"), QIcon(":kaffeine"))); 0377 trayIcon->setToolTip(i18n("Kaffeine")); 0378 trayIcon->setContextMenu(menu); 0379 connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(trayShowHide(QSystemTrayIcon::ActivationReason)) ); 0380 0381 // make sure that the bars are visible (fullscreen -> quit -> restore -> hidden) 0382 menuBar->show(); 0383 navigationBar->show(); 0384 controlBar->show(); 0385 trayIcon->show(); 0386 0387 // workaround setAutoSaveSettings() which doesn't accept "IconOnly" as initial state 0388 controlBar->setToolButtonStyle(Qt::ToolButtonIconOnly); 0389 0390 #if QT_VERSION < 0x050a00 0391 // initialize random number generator 0392 qsrand(QTime(0, 0, 0).msecsTo(QTime::currentTime())); 0393 #endif 0394 0395 // initialize dbus objects 0396 QDBusConnection::sessionBus().registerObject(QLatin1String("/"), new MprisRootObject(this), 0397 QDBusConnection::ExportAllContents); 0398 QDBusConnection::sessionBus().registerObject(QLatin1String("/Player"), 0399 new MprisPlayerObject(this, mediaWidget, playlistTab, this), 0400 QDBusConnection::ExportAllContents); 0401 QDBusConnection::sessionBus().registerObject(QLatin1String("/TrackList"), 0402 new MprisTrackListObject(playlistTab, this), QDBusConnection::ExportAllContents); 0403 #if HAVE_DVB == 1 0404 QDBusConnection::sessionBus().registerObject(QLatin1String("/Television"), 0405 new DBusTelevisionObject(dvbTab, this), QDBusConnection::ExportAllContents); 0406 #endif /* HAVE_DVB == 1 */ 0407 QDBusConnection::sessionBus().registerService(QLatin1String("org.mpris.kaffeine")); 0408 0409 parseArgs(); 0410 show(); 0411 } 0412 0413 MainWindow::~MainWindow() 0414 { 0415 actionOpenRecent->saveEntries(KSharedConfig::openConfig()->group("Recent Files")); 0416 0417 if (!temporaryUrls.isEmpty()) { 0418 KIO::del(temporaryUrls); 0419 } 0420 0421 int value = 0; 0422 0423 switch (mediaWidget->getDisplayMode()) { 0424 case MediaWidget::NormalMode: value = 0; break; 0425 case MediaWidget::MinimalMode: value = 1; break; 0426 case MediaWidget::FullScreenMode: value = 2; break; 0427 case MediaWidget::FullScreenReturnToMinimalMode: value = 2; break; 0428 } 0429 0430 KSharedConfig::openConfig()->group("MainWindow").writeEntry("DisplayMode", value); 0431 } 0432 0433 void MainWindow::close() 0434 { 0435 bool ok = true; 0436 0437 #if HAVE_DVB == 1 0438 dvbTab->mayCloseApplication(&ok, mediaWidget); 0439 #endif /* HAVE_DVB == 1 */ 0440 0441 if (ok) { 0442 writeSettings(); 0443 mediaWidget->stop(); 0444 QMainWindow::close(); 0445 Configuration::detach(); 0446 QCoreApplication::exit(0); 0447 } 0448 } 0449 0450 void MainWindow::readSettings() 0451 { 0452 QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName()); 0453 const QByteArray geometry = settings.value("geometry", QByteArray()).toByteArray(); 0454 if (geometry.isEmpty()) { 0455 const QRect availableGeometry = QApplication::desktop()->availableGeometry(this); 0456 resize(availableGeometry.width() / 3, availableGeometry.height() / 2); 0457 move((availableGeometry.width() - width()) / 2, 0458 (availableGeometry.height() - height()) / 2); 0459 } else { 0460 restoreGeometry(geometry); 0461 } 0462 } 0463 0464 void MainWindow::writeSettings() 0465 { 0466 QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName()); 0467 settings.setValue("geometry", saveGeometry()); 0468 } 0469 0470 MainWindow::MainWindow(KAboutData *aboutData, QCommandLineParser *parser) 0471 { 0472 this->aboutData = aboutData; 0473 this->parser = parser; 0474 0475 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))); 0476 parser->addOption(QCommandLineOption(QStringList() << QLatin1String("tempfile"), i18n("The files/URLs opened by the application will be deleted after use"))); 0477 parser->addOption(QCommandLineOption(QStringList() << QLatin1String("f") << QLatin1String("fullscreen"), i18n("Start in full screen mode"))); 0478 parser->addOption(QCommandLineOption(QStringList() << QLatin1String("m") << QLatin1String("minimal"), i18n("Start in minimal mode"))); 0479 parser->addOption(QCommandLineOption(QStringList() << QLatin1String("t") << QLatin1String("alwaysontop"), i18n("Start with always on top"))); 0480 parser->addOption(QCommandLineOption(QStringList() << QLatin1String("audiocd"), i18n("Play Audio CD"))); 0481 parser->addOption(QCommandLineOption(QStringList() << QLatin1String("videocd"), i18n("Play Video CD"))); 0482 parser->addOption(QCommandLineOption(QStringList() << QLatin1String("dvd"), i18n("Play DVD"))); 0483 parser->addOption(QCommandLineOption(QStringList() << QLatin1String("aspectratio"), "Force starting with an specific aspect ratio", QLatin1String("aspect ratio"))); 0484 0485 #if HAVE_DVB == 1 0486 parser->addOption(QCommandLineOption(QStringList() << QLatin1String("dumpdvb"), i18nc("command line option", "Dump dvb data (debug option)"))); 0487 parser->addOption(QCommandLineOption(QStringList() << QLatin1String("channel"), i18nc("command line option", "Play TV channel"), QLatin1String("name / number"))); 0488 parser->addOption(QCommandLineOption(QStringList() << QLatin1String("tv"), i18nc("command line option", "(deprecated option)"), QLatin1String("channel"))); 0489 parser->addOption(QCommandLineOption(QStringList() << QLatin1String("lastchannel"), i18nc("command line option", "Play last tuned TV channel"))); 0490 #endif 0491 parser->addPositionalArgument(QLatin1String("[file]"), i18n("Files or URLs to play")); 0492 } 0493 0494 void MainWindow::parseArgs(const QString workingDirectory) 0495 { 0496 /* Parse first arguments that aren't mutually exclusive */ 0497 0498 if (parser->isSet("alwaysontop")) { 0499 Qt::WindowFlags flags = this->windowFlags(); 0500 flags |= Qt::WindowStaysOnTopHint; 0501 this->setWindowFlags(flags); 0502 } 0503 0504 if (parser->isSet("fullscreen")) { 0505 mediaWidget->setDisplayMode(MediaWidget::FullScreenMode); 0506 } else if (parser->isSet("minimal")) { 0507 mediaWidget->setDisplayMode(MediaWidget::MinimalMode); 0508 } else { 0509 // set display mode 0510 switch (Configuration::instance()->getStartupDisplayMode()) { 0511 case Configuration::StartupNormalMode: 0512 // nothing to do 0513 break; 0514 case Configuration::StartupMinimalMode: 0515 mediaWidget->setDisplayMode(MediaWidget::MinimalMode); 0516 break; 0517 case Configuration::StartupFullScreenMode: 0518 mediaWidget->setDisplayMode(MediaWidget::FullScreenMode); 0519 break; 0520 case Configuration::StartupRememberLastSetting: { 0521 int value = KSharedConfig::openConfig()->group("MainWindow").readEntry("DisplayMode", 0); 0522 0523 switch (value) { 0524 case 0: 0525 // nothing to do 0526 break; 0527 case 1: 0528 mediaWidget->setDisplayMode(MediaWidget::MinimalMode); 0529 break; 0530 case 2: 0531 mediaWidget->setDisplayMode(MediaWidget::FullScreenMode); 0532 break; 0533 } 0534 0535 break; 0536 } /* case */ 0537 } /* switch */ 0538 } 0539 0540 if (parser->isSet("aspectratio")) { 0541 MediaWidget::AspectRatio aspectRatio = MediaWidget::AspectRatioAuto; 0542 QString aspect; 0543 0544 aspect = parser->value("aspectratio"); 0545 0546 if (aspect == "1:1") 0547 aspectRatio = MediaWidget::AspectRatio1_1; 0548 else if (aspect == "4:3") 0549 aspectRatio = MediaWidget::AspectRatio4_3; 0550 else if (aspect == "5:4") 0551 aspectRatio = MediaWidget::AspectRatio5_4; 0552 else if (aspect == "16:9") 0553 aspectRatio = MediaWidget::AspectRatio16_9; 0554 else if (aspect == "16:10") 0555 aspectRatio = MediaWidget::AspectRatio16_10; 0556 else if (aspect == "2.21:1") 0557 aspectRatio = MediaWidget::AspectRatio221_100; 0558 else if (aspect == "2.35:1") 0559 aspectRatio = MediaWidget::AspectRatio235_100; 0560 else if (aspect == "2.39:1") 0561 aspectRatio = MediaWidget::AspectRatio239_100; 0562 0563 mediaWidget->setAspectRatio(aspectRatio); 0564 } 0565 0566 0567 #if HAVE_DVB == 1 0568 if (parser->isSet("dumpdvb")) { 0569 dvbTab->enableDvbDump(); 0570 } 0571 #endif 0572 0573 /* 0574 * Now, parse arguments that are mutually exclusive 0575 */ 0576 0577 #if HAVE_DVB == 1 0578 QString channel; 0579 0580 channel = parser->value("channel"); 0581 0582 if (!channel.isEmpty()) { 0583 activateTab(DvbTabId); 0584 dvbTab->playChannel(channel); 0585 0586 return; 0587 } 0588 0589 channel = parser->value("tv"); 0590 if (!channel.isEmpty()) { 0591 activateTab(DvbTabId); 0592 dvbTab->playChannel(channel); 0593 0594 return; 0595 } 0596 0597 if (parser->isSet("lastchannel")) { 0598 activateTab(DvbTabId); 0599 dvbTab->playLastChannel(); 0600 0601 return; 0602 } 0603 #endif /* HAVE_DVB == 1 */ 0604 0605 if (parser->isSet("audiocd")) { 0606 if (parser->positionalArguments().count() > 0) { 0607 openAudioCd(parser->positionalArguments().first()); 0608 } else { 0609 openAudioCd(); 0610 } 0611 return; 0612 } 0613 0614 if (parser->isSet("videocd")) { 0615 if (parser->positionalArguments().count() > 0) { 0616 openVideoCd(parser->positionalArguments().first()); 0617 } else { 0618 openVideoCd(); 0619 } 0620 return; 0621 } 0622 0623 if (parser->isSet("dvd")) { 0624 if (parser->positionalArguments().count() > 0) { 0625 openDvd(parser->positionalArguments().first()); 0626 } else { 0627 openDvd(); 0628 } 0629 return; 0630 } 0631 0632 if (parser->positionalArguments().count() > 0) { 0633 QList<QUrl> urls; 0634 0635 for (int i = 0; i < parser->positionalArguments().count(); ++i) { 0636 QUrl url = QUrl::fromUserInput(parser->positionalArguments().at(i), workingDirectory); 0637 0638 if (url.isValid()) { 0639 urls.append(url); 0640 } 0641 } 0642 0643 if (parser->isSet("tempfile")) { 0644 temporaryUrls.append(urls); 0645 } 0646 0647 if (urls.size() >= 2) { 0648 activateTab(PlaylistTabId); 0649 playlistTab->appendToVisiblePlaylist(urls, true); 0650 } else if (!urls.isEmpty()) { 0651 openUrl(urls.at(0)); 0652 } 0653 return; 0654 } 0655 } 0656 0657 void MainWindow::displayModeChanged() 0658 { 0659 MediaWidget::DisplayMode displayMode = mediaWidget->getDisplayMode(); 0660 0661 switch (displayMode) { 0662 case MediaWidget::FullScreenMode: 0663 case MediaWidget::FullScreenReturnToMinimalMode: 0664 setWindowState(windowState() | Qt::WindowFullScreen); 0665 break; 0666 case MediaWidget::MinimalMode: 0667 case MediaWidget::NormalMode: 0668 setWindowState(windowState() & (~Qt::WindowFullScreen)); 0669 break; 0670 } 0671 0672 switch (displayMode) { 0673 case MediaWidget::FullScreenMode: 0674 case MediaWidget::FullScreenReturnToMinimalMode: 0675 case MediaWidget::MinimalMode: 0676 menuBar()->hide(); 0677 navigationBar->hide(); 0678 controlBar->hide(); 0679 autoHideControlBar = true; 0680 cursorHideTimer->start(); 0681 break; 0682 case MediaWidget::NormalMode: 0683 menuBar()->show(); 0684 navigationBar->show(); 0685 controlBar->show(); 0686 autoHideControlBar = false; 0687 cursorHideTimer->stop(); 0688 unsetCursor(); 0689 break; 0690 } 0691 tabs.at(currentTabIndex)->toggleDisplayMode(displayMode); 0692 } 0693 0694 void MainWindow::trayShowHide(QSystemTrayIcon::ActivationReason reason) 0695 { 0696 if (reason != QSystemTrayIcon::DoubleClick) 0697 return; 0698 0699 if (isVisible()) 0700 hide(); 0701 else { 0702 show(); 0703 raise(); 0704 setFocus(); 0705 } 0706 } 0707 0708 void MainWindow::open() 0709 { 0710 if (isMinimized()) 0711 showNormal(); 0712 0713 QList<QUrl> urls = QFileDialog::getOpenFileUrls(this, i18nc("@title:window", "Open files"), QUrl(), MediaWidget::extensionFilter()); 0714 0715 // trayIcon->showMessage("Open", "Opening file(s)"); 0716 if (urls.size() >= 2) { 0717 activateTab(PlaylistTabId); 0718 playlistTab->appendToVisiblePlaylist(urls, true); 0719 } else if (!urls.isEmpty()) { 0720 openUrl(urls.at(0)); 0721 } 0722 } 0723 0724 void MainWindow::openUrl() 0725 { 0726 openUrl(QInputDialog::getText(this, i18nc("@title:window", "Open URL"), i18n("Enter a URL:"))); 0727 } 0728 0729 void MainWindow::openUrl(const QUrl &url) 0730 { 0731 if (!url.isValid()) { 0732 return; 0733 } 0734 0735 // we need to copy "url" because addUrl() may invalidate it 0736 QUrl copy(url); 0737 actionOpenRecent->addUrl(copy); // moves the url to the top of the list 0738 0739 if (currentTabIndex != PlaylistTabId) { 0740 activateTab(PlayerTabId); 0741 } 0742 0743 playlistTab->appendToVisiblePlaylist(QList<QUrl>() << copy, true); 0744 } 0745 0746 void MainWindow::openAudioCd(const QString &device) 0747 { 0748 if (isMinimized()) 0749 showNormal(); 0750 0751 activateTab(PlayerTabId); 0752 mediaWidget->playAudioCd(device); 0753 } 0754 0755 void MainWindow::openVideoCd(const QString &device) 0756 { 0757 if (isMinimized()) 0758 showNormal(); 0759 0760 activateTab(PlayerTabId); 0761 mediaWidget->playVideoCd(device); 0762 } 0763 0764 void MainWindow::openDvd(const QString &device) 0765 { 0766 if (isMinimized()) 0767 showNormal(); 0768 0769 activateTab(PlayerTabId); 0770 mediaWidget->playDvd(device); 0771 } 0772 0773 void MainWindow::playDvdFolder() 0774 { 0775 QString folder = QFileDialog::getExistingDirectory(this, QString()); 0776 0777 if (!folder.isEmpty()) { 0778 openDvd(folder); 0779 } 0780 } 0781 0782 void MainWindow::playDvb() 0783 { 0784 if (isMinimized()) 0785 showNormal(); 0786 0787 activateTab(DvbTabId); 0788 dvbTab->playLastChannel(); 0789 } 0790 0791 void MainWindow::configureKeys() 0792 { 0793 KShortcutsDialog::configure(collection); 0794 } 0795 0796 void MainWindow::configureKaffeine() 0797 { 0798 QDialog *dialog = new ConfigurationDialog(this); 0799 dialog->setAttribute(Qt::WA_DeleteOnClose, true); 0800 dialog->setModal(true); 0801 dialog->show(); 0802 } 0803 0804 void MainWindow::navigationBarOrientationChanged(Qt::Orientation orientation) 0805 { 0806 if (orientation == Qt::Horizontal) { 0807 tabBar->setShape(QTabBar::RoundedNorth); 0808 } else { 0809 tabBar->setShape(QTabBar::RoundedWest); 0810 } 0811 } 0812 0813 void MainWindow::activateTab(int tabIndex) 0814 { 0815 currentTabIndex = tabIndex; 0816 tabBar->setCurrentIndex(tabIndex); 0817 0818 /* 0819 * Ensure that menus and timers will be properly shown, 0820 * according with the selected display mode. 0821 */ 0822 stackedLayout->setCurrentIndex(currentTabIndex); 0823 tabs.at(currentTabIndex)->activate(); 0824 0825 emit displayModeChanged(); 0826 } 0827 0828 void MainWindow::hideCursor() 0829 { 0830 setCursor(Qt::BlankCursor); 0831 } 0832 0833 void MainWindow::closeEvent(QCloseEvent *event) 0834 { 0835 bool ok = true; 0836 emit mayCloseApplication(&ok, this); 0837 0838 if (!ok) { 0839 event->ignore(); 0840 } else { 0841 MainWindow::close(); 0842 } 0843 } 0844 0845 bool MainWindow::event(QEvent *event) 0846 { 0847 bool retVal = QMainWindow::event(event); // this has to be done before calling setVisible() 0848 0849 // FIXME we depend on QEvent::HoverMove (instead of QEvent::MouseMove) 0850 // but the latter depends on mouse tracking being enabled on this widget 0851 // and all its children (especially the video widget) ... 0852 0853 switch (event->type()) { 0854 case QEvent::HoverMove: { 0855 int x = reinterpret_cast<QHoverEvent *> (event)->pos().x(); 0856 int y = reinterpret_cast<QHoverEvent *> (event)->pos().y(); 0857 0858 if ((y < 0) || (y >= height()) || 0859 (x < 0) || (x >= width())) { 0860 // QHoverEvent sometimes reports quite strange coordinates - ignore them 0861 return retVal; 0862 } 0863 0864 if (autoHideControlBar) { 0865 cursorHideTimer->stop(); 0866 unsetCursor(); 0867 0868 switch (toolBarArea(controlBar)) { 0869 case Qt::TopToolBarArea: 0870 controlBar->setVisible(y < 60); 0871 break; 0872 case Qt::BottomToolBarArea: 0873 controlBar->setVisible(y >= (height() - 60)); 0874 menuBar()->setVisible(y < 60); 0875 break; 0876 default: 0877 break; 0878 } 0879 0880 if (controlBar->isHidden() || menuBar()->isHidden()) { 0881 cursorHideTimer->start(); 0882 } 0883 } 0884 0885 tabs.at(currentTabIndex)->mouse_move(x, y); 0886 break; 0887 } 0888 default: 0889 break; 0890 } 0891 0892 return retVal; 0893 } 0894 0895 void MainWindow::keyPressEvent(QKeyEvent *event) 0896 { 0897 if (event->key() == Qt::Key_Escape) { 0898 mediaWidget->setDisplayMode(MediaWidget::NormalMode); 0899 } 0900 0901 QMainWindow::keyPressEvent(event); 0902 } 0903 0904 void MainWindow::leaveEvent(QEvent *event) 0905 { 0906 if (autoHideControlBar) { 0907 menuBar()->setVisible(false); 0908 controlBar->setVisible(false); 0909 tabs.at(currentTabIndex)->mouse_move(-1, -1); 0910 } 0911 0912 QMainWindow::leaveEvent(event); 0913 } 0914 0915 #include "moc_mainwindow.cpp"