diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index d3282b0..066f6f6 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1,928 +1,911 @@ /* * mainwindow.cpp * * Copyright (C) 2007-2011 Christoph Pfister * * 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 "log.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#include #include #include #include #include #include #include #include #include #include #include "configuration.h" #include "configurationdialog.h" #include "dbusobjects.h" #include "dvb/dvbtab.h" #include "mainwindow.h" #include "playlist/playlisttab.h" // log categories. Should match log.h Q_LOGGING_CATEGORY(logCam, "kaffeine.cam") Q_LOGGING_CATEGORY(logDev, "kaffeine.dev") Q_LOGGING_CATEGORY(logDvb, "kaffeine.dvb") Q_LOGGING_CATEGORY(logDvbSi, "kaffeine.dvbsi") Q_LOGGING_CATEGORY(logEpg, "kaffeine.epg") Q_LOGGING_CATEGORY(logConfig, "kaffeine.config") Q_LOGGING_CATEGORY(logMediaWidget, "kaffeine.mediawidget") Q_LOGGING_CATEGORY(logPlaylist, "kaffeine.playlist") Q_LOGGING_CATEGORY(logSql, "kaffeine.sql") Q_LOGGING_CATEGORY(logVlc, "kaffeine.vlc") #define FILTER_RULE "kaffeine.*.debug=true" #define CATEGORIES "cam, dev, dvb, dvbsi, epg, config, mediawidget, playlist, sql, vlc" class StackedLayout : public QStackedLayout { public: explicit StackedLayout(QWidget *parent) : QStackedLayout(parent) { } ~StackedLayout() { } QSize minimumSize() const { QWidget *widget = currentWidget(); if (widget != NULL) { return widget->minimumSizeHint(); } return QSize(); } }; class StartTab : public TabBase { public: explicit StartTab(MainWindow *mainWindow); ~StartTab() { } private: void activate() { } QAbstractButton *addShortcut(const QString &name, const QIcon &icon, QWidget *parent); }; StartTab::StartTab(MainWindow *mainWindow) { setBackgroundRole(QPalette::Base); setAutoFillBackground(true); QGridLayout *gridLayout = new QGridLayout(this); gridLayout->setAlignment(Qt::AlignCenter); gridLayout->setMargin(10); gridLayout->setSpacing(15); QAbstractButton *button = addShortcut(i18n("&1 Play File"), QIcon::fromTheme(QLatin1String("video-x-generic"), QIcon(":video-x-generic")), this); button->setShortcut(Qt::Key_1); button->setWhatsThis(i18n("Open dialog to play a file")); connect(button, SIGNAL(clicked()), mainWindow, SLOT(open())); gridLayout->addWidget(button, 0, 0); button = addShortcut(i18n("&2 Play Audio CD"), QIcon::fromTheme(QLatin1String("media-optical-audio"), QIcon(":media-optical-audio")), this); button->setShortcut(Qt::Key_2); button->setWhatsThis(i18n("Start playing an audio CD. It assumes that the CD is already there at the CD drive")); connect(button, SIGNAL(clicked()), mainWindow, SLOT(openAudioCd())); gridLayout->addWidget(button, 0, 1); button = addShortcut(i18n("&3 Play Video CD"), QIcon::fromTheme(QLatin1String("media-optical"), QIcon(":media-optical-video")), this); button->setShortcut(Qt::Key_3); button->setWhatsThis(i18n("Start playing a Video CD. It assumes that the CD is already there at the CD drive")); connect(button, SIGNAL(clicked()), mainWindow, SLOT(openVideoCd())); gridLayout->addWidget(button, 0, 2); button = addShortcut(i18n("&4 Play DVD"), QIcon::fromTheme(QLatin1String("media-optical"), QIcon(":media-optical")), this); button->setShortcut(Qt::Key_4); button->setWhatsThis(i18n("Start playing a DVD. It assumes that the DVD is already there at the DVD drive")); connect(button, SIGNAL(clicked()), mainWindow, SLOT(openDvd())); gridLayout->addWidget(button, 1, 0); #if HAVE_DVB == 1 button = addShortcut(i18n("&5 Digital TV"), QIcon::fromTheme(QLatin1String("video-television"), QIcon(":video-television")), this); button->setShortcut(Qt::Key_5); button->setWhatsThis("Open the Digital TV live view window. If the TV channels are already scanned, it will start playing the last channel"); connect(button, SIGNAL(clicked()), mainWindow, SLOT(playDvb())); gridLayout->addWidget(button, 1, 1); #endif /* HAVE_DVB == 1 */ } QAbstractButton *StartTab::addShortcut(const QString &name, const QIcon &icon, QWidget *parent) { // QPushButton has visual problems with big icons QToolButton *button = new QToolButton(parent); button->setText(name); button->setIcon(icon); button->setFocusPolicy(Qt::NoFocus); button->setIconSize(QSize(48, 48)); button->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); return button; } class PlayerTab : public TabBase { public: explicit PlayerTab(MediaWidget *mediaWidget_); ~PlayerTab() { } void activate() { layout()->addWidget(mediaWidget); mediaWidget->setFocus(); } private: MediaWidget *mediaWidget; }; PlayerTab::PlayerTab(MediaWidget *mediaWidget_) : mediaWidget(mediaWidget_) { QHBoxLayout *layout = new QHBoxLayout(this); layout->setMargin(0); } void MainWindow::run() { // Allow the user to enable or disable debugging // We handle this before the other parameters, as it may affect some // early debug messages // // --debug enables all debugging categories. It is possible to enable // each category individually by calling Kaffeine with: // QT_LOGGING_RULES="epg.debug=true" kaffeine if (parser->isSet("debug")) { QLoggingCategory::defaultCategory()->setEnabled(QtDebugMsg, true); QLoggingCategory::setFilterRules(QStringLiteral(FILTER_RULE)); } else { QLoggingCategory::setFilterRules(QStringLiteral("kaffeine.*.debug=false")); } readSettings(); setAttribute(Qt::WA_DeleteOnClose, true); // menu structure QMenuBar *menuBar = QMainWindow::menuBar(); collection = new KActionCollection(this); QMenu *menu = new QMenu(i18n("&File"), this); menuBar->addMenu(menu); QAction *action = KStandardAction::open(this, SLOT(open()), collection); menu->addAction(collection->addAction(QLatin1String("file_open"), action)); action = new QAction(QIcon::fromTheme(QLatin1String("text-html"), QIcon(":text-html")), i18nc("@action:inmenu", "Open URL..."), collection); action->setShortcut(Qt::CTRL | Qt::Key_U); connect(action, SIGNAL(triggered(bool)), this, SLOT(openUrl())); menu->addAction(collection->addAction(QLatin1String("file_open_url"), action)); actionOpenRecent = KStandardAction::openRecent(this, SLOT(openUrl(QUrl)), collection); actionOpenRecent->loadEntries(KSharedConfig::openConfig()->group("Recent Files")); menu->addAction(collection->addAction(QLatin1String("file_open_recent"), actionOpenRecent)); menu->addSeparator(); action = new QAction(QIcon::fromTheme(QLatin1String("media-optical-audio"), QIcon(":media-optical-audio")), i18n("Play Audio CD"), collection); connect(action, SIGNAL(triggered(bool)), this, SLOT(openAudioCd())); menu->addAction(collection->addAction(QLatin1String("file_play_audiocd"), action)); action = new QAction(QIcon::fromTheme(QLatin1String("media-optical"), QIcon(":media-optical-video")), i18n("Play Video CD"), collection); connect(action, SIGNAL(triggered(bool)), this, SLOT(openVideoCd())); menu->addAction(collection->addAction(QLatin1String("file_play_videocd"), action)); action = new QAction(QIcon::fromTheme(QLatin1String("media-optical"), QIcon(":media-optical")), i18n("Play DVD"), collection); connect(action, SIGNAL(triggered(bool)), this, SLOT(openDvd())); menu->addAction(collection->addAction(QLatin1String("file_play_dvd"), action)); action = new QAction(QIcon::fromTheme(QLatin1String("media-optical"), QIcon(":media-optical")), i18nc("@action:inmenu", "Play DVD Folder"), collection); connect(action, SIGNAL(triggered()), this, SLOT(playDvdFolder())); menu->addAction(collection->addAction(QLatin1String("file_play_dvd_folder"), action)); menu->addSeparator(); action = KStandardAction::quit(this, SLOT(close()), collection); menu->addAction(collection->addAction(QLatin1String("file_quit"), action)); QMenu *playerMenu = new QMenu(i18n("&Playback"), this); menuBar->addMenu(playerMenu); QMenu *playlistMenu = new QMenu(i18nc("menu bar", "Play&list"), this); menuBar->addMenu(playlistMenu); #if HAVE_DVB == 1 QMenu *dvbMenu = new QMenu(i18n("&Television"), this); menuBar->addMenu(dvbMenu); #endif /* HAVE_DVB == 1 */ menu = new QMenu(i18n("&Settings"), this); menuBar->addMenu(menu); action = KStandardAction::keyBindings(this, SLOT(configureKeys()), collection); menu->addAction(collection->addAction(QLatin1String("settings_keys"), action)); action = KStandardAction::preferences(this, SLOT(configureKaffeine()), collection); menu->addAction(collection->addAction(QLatin1String("settings_kaffeine"), action)); menuBar->addSeparator(); KHelpMenu *helpMenu = new KHelpMenu(this, *aboutData); menuBar->addMenu(helpMenu->menu()); // navigation bar - keep in sync with TabIndex enum! navigationBar = new QToolBar(QLatin1String("navigation_bar")); this->addToolBar(Qt::LeftToolBarArea, navigationBar); connect(navigationBar, SIGNAL(orientationChanged(Qt::Orientation)), this, SLOT(navigationBarOrientationChanged(Qt::Orientation))); tabBar = new QTabBar(navigationBar); tabBar->addTab(QIcon::fromTheme(QLatin1String("start-here-kde"), QIcon(":start-here-kde")), i18n("Start")); tabBar->addTab(QIcon::fromTheme(QLatin1String("kaffeine"), QIcon(":kaffeine")), i18n("Playback")); tabBar->addTab(QIcon::fromTheme(QLatin1String("view-media-playlist"), QIcon(":view-media-playlist")), i18n("Playlist")); #if HAVE_DVB == 1 tabBar->addTab(QIcon::fromTheme(QLatin1String("video-television"), QIcon(":video-television")), i18n("Television")); #endif /* HAVE_DVB == 1 */ tabBar->setShape(QTabBar::RoundedWest); tabBar->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); connect(tabBar, SIGNAL(currentChanged(int)), this, SLOT(activateTab(int))); navigationBar->addWidget(tabBar); // control bar controlBar = new QToolBar(QLatin1String("control_bar"), this); this->addToolBar(Qt::BottomToolBarArea, controlBar); controlBar->setToolButtonStyle(Qt::ToolButtonIconOnly); autoHideControlBar = false; cursorHideTimer = new QTimer(this); cursorHideTimer->setInterval(1500); cursorHideTimer->setSingleShot(true); connect(cursorHideTimer, SIGNAL(timeout()), this, SLOT(hideCursor())); // main area QWidget *widget = new QWidget(this); stackedLayout = new StackedLayout(widget); setCentralWidget(widget); mediaWidget = new MediaWidget(playerMenu, controlBar, collection, widget); connect(mediaWidget, SIGNAL(displayModeChanged()), this, SLOT(displayModeChanged())); connect(mediaWidget, SIGNAL(changeCaption(QString)), this, SLOT(setWindowTitle(QString))); // tabs - keep in sync with TabIndex enum! TabBase *startTab = new StartTab(this); tabs.append(startTab); stackedLayout->addWidget(startTab); playerTab = new PlayerTab(mediaWidget); playerTab->activate(); tabs.append(playerTab); stackedLayout->addWidget(playerTab); playlistTab = new PlaylistTab(playlistMenu, collection, mediaWidget); tabs.append(playlistTab); stackedLayout->addWidget(playlistTab); #if HAVE_DVB == 1 dvbTab = new DvbTab(dvbMenu, collection, mediaWidget); connect(this, SIGNAL(mayCloseApplication(bool*,QWidget*)), dvbTab, SLOT(mayCloseApplication(bool*,QWidget*))); tabs.append(dvbTab); stackedLayout->addWidget(dvbTab); #endif /* HAVE_DVB == 1 */ currentTabIndex = StartTabId; // actions also have to work if the menu bar is hidden (fullscreen) collection->addAssociatedWidget(this); // restore custom key bindings collection->readSettings(); // Tray menu menu = new QMenu(i18n("Kaffeine"), this); action = new QAction(i18n("Play &File"), this); connect(action, SIGNAL(triggered(bool)), this, SLOT(open())); menu->addAction(action); action = new QAction(i18n("Play &Audio CD"), this); connect(action, SIGNAL(triggered(bool)), this, SLOT(openAudioCd())); menu->addAction(action); action = new QAction(i18n("Play &Video CD"), this); connect(action, SIGNAL(triggered(bool)), this, SLOT(openVideoCd())); menu->addAction(action); action = new QAction(i18n("Play &DVD"), this); connect(action, SIGNAL(triggered(bool)), this, SLOT(openDvd())); menu->addAction(action); #if HAVE_DVB == 1 action = new QAction(i18n("&Watch Digital TV"), this); connect(action, SIGNAL(triggered(bool)), this, SLOT(playDvb())); menu->addAction(action); #endif action = new QAction(i18n("&Quit"), this); connect(action, SIGNAL(triggered(bool)), this, SLOT(close())); menu->addAction(action); // Tray Icon and its menu QMenu *trayMenu = new QMenu(this); trayIcon = new QSystemTrayIcon(this); trayIcon->setContextMenu(trayMenu); trayIcon->setIcon(QIcon::fromTheme(QLatin1String("kaffeine"), QIcon(":kaffeine"))); trayIcon->setToolTip(i18n("Kaffeine")); trayIcon->setContextMenu(menu); connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(trayShowHide(QSystemTrayIcon::ActivationReason)) ); // make sure that the bars are visible (fullscreen -> quit -> restore -> hidden) menuBar->show(); navigationBar->show(); controlBar->show(); trayIcon->show(); // workaround setAutoSaveSettings() which doesn't accept "IconOnly" as initial state controlBar->setToolButtonStyle(Qt::ToolButtonIconOnly); // initialize random number generator qsrand(QTime(0, 0, 0).msecsTo(QTime::currentTime())); // initialize dbus objects QDBusConnection::sessionBus().registerObject(QLatin1String("/"), new MprisRootObject(this), QDBusConnection::ExportAllContents); QDBusConnection::sessionBus().registerObject(QLatin1String("/Player"), new MprisPlayerObject(this, mediaWidget, playlistTab, this), QDBusConnection::ExportAllContents); QDBusConnection::sessionBus().registerObject(QLatin1String("/TrackList"), new MprisTrackListObject(playlistTab, this), QDBusConnection::ExportAllContents); #if HAVE_DVB == 1 QDBusConnection::sessionBus().registerObject(QLatin1String("/Television"), new DBusTelevisionObject(dvbTab, this), QDBusConnection::ExportAllContents); #endif /* HAVE_DVB == 1 */ QDBusConnection::sessionBus().registerService(QLatin1String("org.mpris.kaffeine")); parseArgs(); show(); } MainWindow::~MainWindow() { actionOpenRecent->saveEntries(KSharedConfig::openConfig()->group("Recent Files")); if (!temporaryUrls.isEmpty()) { KIO::del(temporaryUrls); } int value = 0; switch (mediaWidget->getDisplayMode()) { case MediaWidget::NormalMode: value = 0; break; case MediaWidget::MinimalMode: value = 1; break; case MediaWidget::FullScreenMode: value = 2; break; case MediaWidget::FullScreenReturnToMinimalMode: value = 2; break; } KSharedConfig::openConfig()->group("MainWindow").writeEntry("DisplayMode", value); } void MainWindow::close() { bool ok = true; #if HAVE_DVB == 1 dvbTab->mayCloseApplication(&ok, mediaWidget); #endif /* HAVE_DVB == 1 */ if (ok) { writeSettings(); mediaWidget->stop(); QMainWindow::close(); Configuration::detach(); QCoreApplication::exit(0); } } void MainWindow::readSettings() { QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName()); const QByteArray geometry = settings.value("geometry", QByteArray()).toByteArray(); if (geometry.isEmpty()) { const QRect availableGeometry = QApplication::desktop()->availableGeometry(this); resize(availableGeometry.width() / 3, availableGeometry.height() / 2); move((availableGeometry.width() - width()) / 2, (availableGeometry.height() - height()) / 2); } else { restoreGeometry(geometry); } } void MainWindow::writeSettings() { QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName()); settings.setValue("geometry", saveGeometry()); } MainWindow::MainWindow(KAboutData *aboutData, QCommandLineParser *parser) { this->aboutData = aboutData; this->parser = parser; 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))); parser->addOption(QCommandLineOption(QStringList() << QLatin1String("tempfile"), i18n("The files/URLs opened by the application will be deleted after use"))); parser->addOption(QCommandLineOption(QStringList() << QLatin1String("f") << QLatin1String("fullscreen"), i18n("Start in full screen mode"))); parser->addOption(QCommandLineOption(QStringList() << QLatin1String("m") << QLatin1String("minimal"), i18n("Start in minimal mode"))); parser->addOption(QCommandLineOption(QStringList() << QLatin1String("t") << QLatin1String("alwaysontop"), i18n("Start with always on top"))); parser->addOption(QCommandLineOption(QStringList() << QLatin1String("audiocd"), i18n("Play Audio CD"))); parser->addOption(QCommandLineOption(QStringList() << QLatin1String("videocd"), i18n("Play Video CD"))); parser->addOption(QCommandLineOption(QStringList() << QLatin1String("dvd"), i18n("Play DVD"))); parser->addOption(QCommandLineOption(QStringList() << QLatin1String("aspectratio"), "Force starting with an specific aspect ratio", QLatin1String("aspect ratio"))); #if HAVE_DVB == 1 parser->addOption(QCommandLineOption(QStringList() << QLatin1String("dumpdvb"), i18nc("command line option", "Dump dvb data (debug option)"))); parser->addOption(QCommandLineOption(QStringList() << QLatin1String("channel"), i18nc("command line option", "Play TV channel"), QLatin1String("name / number"))); parser->addOption(QCommandLineOption(QStringList() << QLatin1String("tv"), i18nc("command line option", "(deprecated option)"), QLatin1String("channel"))); parser->addOption(QCommandLineOption(QStringList() << QLatin1String("lastchannel"), i18nc("command line option", "Play last tuned TV channel"))); #endif parser->addPositionalArgument(QLatin1String("[file]"), i18n("Files or URLs to play")); } void MainWindow::parseArgs(const QString workingDirectory) { /* Parse first arguments that aren't mutually exclusive */ if (parser->isSet("alwaysontop")) { Qt::WindowFlags flags = this->windowFlags(); flags |= Qt::WindowStaysOnTopHint; this->setWindowFlags(flags); } if (parser->isSet("fullscreen")) { mediaWidget->setDisplayMode(MediaWidget::FullScreenMode); } else if (parser->isSet("minimal")) { mediaWidget->setDisplayMode(MediaWidget::MinimalMode); } else { // set display mode switch (Configuration::instance()->getStartupDisplayMode()) { case Configuration::StartupNormalMode: // nothing to do break; case Configuration::StartupMinimalMode: mediaWidget->setDisplayMode(MediaWidget::MinimalMode); break; case Configuration::StartupFullScreenMode: mediaWidget->setDisplayMode(MediaWidget::FullScreenMode); break; case Configuration::StartupRememberLastSetting: { int value = KSharedConfig::openConfig()->group("MainWindow").readEntry("DisplayMode", 0); switch (value) { case 0: // nothing to do break; case 1: mediaWidget->setDisplayMode(MediaWidget::MinimalMode); break; case 2: mediaWidget->setDisplayMode(MediaWidget::FullScreenMode); break; } break; } /* case */ } /* switch */ } if (parser->isSet("aspectratio")) { MediaWidget::AspectRatio aspectRatio = MediaWidget::AspectRatioAuto; QString aspect; aspect = parser->value("aspectratio"); if (aspect == "1:1") aspectRatio = MediaWidget::AspectRatio1_1; else if (aspect == "4:3") aspectRatio = MediaWidget::AspectRatio4_3; else if (aspect == "5:4") aspectRatio = MediaWidget::AspectRatio5_4; else if (aspect == "16:9") aspectRatio = MediaWidget::AspectRatio16_9; else if (aspect == "16:10") aspectRatio = MediaWidget::AspectRatio16_10; else if (aspect == "2.21:1") aspectRatio = MediaWidget::AspectRatio221_100; else if (aspect == "2.35:1") aspectRatio = MediaWidget::AspectRatio235_100; else if (aspect == "2.39:1") aspectRatio = MediaWidget::AspectRatio239_100; mediaWidget->setAspectRatio(aspectRatio); } #if HAVE_DVB == 1 if (parser->isSet("dumpdvb")) { dvbTab->enableDvbDump(); } #endif /* * Now, parse arguments that are mutually exclusive */ #if HAVE_DVB == 1 QString channel; channel = parser->value("channel"); if (!channel.isEmpty()) { activateTab(DvbTabId); dvbTab->playChannel(channel); return; } channel = parser->value("tv"); if (!channel.isEmpty()) { activateTab(DvbTabId); dvbTab->playChannel(channel); return; } if (parser->isSet("lastchannel")) { activateTab(DvbTabId); dvbTab->playLastChannel(); return; } #endif /* HAVE_DVB == 1 */ if (parser->isSet("audiocd")) { if (parser->positionalArguments().count() > 0) { openAudioCd(parser->positionalArguments().first()); } else { openAudioCd(); } return; } if (parser->isSet("videocd")) { if (parser->positionalArguments().count() > 0) { openVideoCd(parser->positionalArguments().first()); } else { openVideoCd(); } return; } if (parser->isSet("dvd")) { if (parser->positionalArguments().count() > 0) { openDvd(parser->positionalArguments().first()); } else { openDvd(); } return; } if (parser->positionalArguments().count() > 0) { QList urls; for (int i = 0; i < parser->positionalArguments().count(); ++i) { QUrl url = QUrl::fromUserInput(parser->positionalArguments().at(i), workingDirectory); if (url.isValid()) { urls.append(url); } } if (parser->isSet("tempfile")) { temporaryUrls.append(urls); } if (urls.size() >= 2) { activateTab(PlaylistTabId); playlistTab->appendToVisiblePlaylist(urls, true); } else if (!urls.isEmpty()) { openUrl(urls.at(0)); } return; } } void MainWindow::displayModeChanged() { MediaWidget::DisplayMode displayMode = mediaWidget->getDisplayMode(); switch (displayMode) { case MediaWidget::FullScreenMode: case MediaWidget::FullScreenReturnToMinimalMode: setWindowState(windowState() | Qt::WindowFullScreen); break; case MediaWidget::MinimalMode: case MediaWidget::NormalMode: setWindowState(windowState() & (~Qt::WindowFullScreen)); break; } switch (displayMode) { case MediaWidget::FullScreenMode: case MediaWidget::FullScreenReturnToMinimalMode: case MediaWidget::MinimalMode: menuBar()->hide(); navigationBar->hide(); controlBar->hide(); autoHideControlBar = true; cursorHideTimer->start(); break; case MediaWidget::NormalMode: menuBar()->show(); navigationBar->show(); controlBar->show(); autoHideControlBar = false; cursorHideTimer->stop(); unsetCursor(); break; } tabs.at(currentTabIndex)->toggleDisplayMode(displayMode); } void MainWindow::trayShowHide(QSystemTrayIcon::ActivationReason reason) { if (reason != QSystemTrayIcon::DoubleClick) return; if (isVisible()) hide(); else { show(); raise(); setFocus(); } } void MainWindow::open() { if (isMinimized()) showNormal(); QList urls = QFileDialog::getOpenFileUrls(this, i18nc("@title:window", "Open files"), QUrl(), MediaWidget::extensionFilter()); // trayIcon->showMessage("Open", "Opening file(s)"); if (urls.size() >= 2) { activateTab(PlaylistTabId); playlistTab->appendToVisiblePlaylist(urls, true); } else if (!urls.isEmpty()) { openUrl(urls.at(0)); } } void MainWindow::openUrl() { openUrl(QInputDialog::getText(this, i18nc("@title:window", "Open URL"), i18n("Enter a URL:"))); } void MainWindow::openUrl(const QUrl &url) { if (!url.isValid()) { return; } // we need to copy "url" because addUrl() may invalidate it QUrl copy(url); actionOpenRecent->addUrl(copy); // moves the url to the top of the list if (currentTabIndex != PlaylistTabId) { activateTab(PlayerTabId); } playlistTab->appendToVisiblePlaylist(QList() << copy, true); } void MainWindow::openAudioCd(const QString &device) { if (isMinimized()) showNormal(); activateTab(PlayerTabId); mediaWidget->playAudioCd(device); } void MainWindow::openVideoCd(const QString &device) { if (isMinimized()) showNormal(); activateTab(PlayerTabId); mediaWidget->playVideoCd(device); } void MainWindow::openDvd(const QString &device) { if (isMinimized()) showNormal(); activateTab(PlayerTabId); mediaWidget->playDvd(device); } void MainWindow::playDvdFolder() { QString folder = QFileDialog::getExistingDirectory(this, QString()); if (!folder.isEmpty()) { openDvd(folder); } } void MainWindow::playDvb() { if (isMinimized()) showNormal(); activateTab(DvbTabId); dvbTab->playLastChannel(); } void MainWindow::configureKeys() { KShortcutsDialog::configure(collection); } void MainWindow::configureKaffeine() { QDialog *dialog = new ConfigurationDialog(this); dialog->setAttribute(Qt::WA_DeleteOnClose, true); dialog->setModal(true); dialog->show(); } void MainWindow::navigationBarOrientationChanged(Qt::Orientation orientation) { if (orientation == Qt::Horizontal) { tabBar->setShape(QTabBar::RoundedNorth); } else { tabBar->setShape(QTabBar::RoundedWest); } } void MainWindow::activateTab(int tabIndex) { currentTabIndex = tabIndex; tabBar->setCurrentIndex(tabIndex); /* * Ensure that menus and timers will be properly shown, * according with the selected display mode. */ stackedLayout->setCurrentIndex(currentTabIndex); tabs.at(currentTabIndex)->activate(); emit displayModeChanged(); } void MainWindow::hideCursor() { setCursor(Qt::BlankCursor); } void MainWindow::closeEvent(QCloseEvent *event) { bool ok = true; emit mayCloseApplication(&ok, this); if (!ok) { event->ignore(); } else { MainWindow::close(); } } bool MainWindow::event(QEvent *event) { bool retVal = QMainWindow::event(event); // this has to be done before calling setVisible() // FIXME we depend on QEvent::HoverMove (instead of QEvent::MouseMove) // but the latter depends on mouse tracking being enabled on this widget // and all its children (especially the video widget) ... switch (event->type()) { - case QEvent::Wheel: { - int delta, y; - - QWheelEvent *wheel = static_cast(event); - - y = wheel->pixelDelta().y(); - if (!y) - y = wheel->angleDelta().y(); - - if (!y) - break; - delta = (y < 0) ? -1 : 1; - - mediaWidget->setVolumeUnderMouse(mediaWidget->getVolume() + delta); - break; - } case QEvent::HoverMove: { int x = reinterpret_cast (event)->pos().x(); int y = reinterpret_cast (event)->pos().y(); if ((y < 0) || (y >= height()) || (x < 0) || (x >= width())) { // QHoverEvent sometimes reports quite strange coordinates - ignore them return retVal; } if (autoHideControlBar) { cursorHideTimer->stop(); unsetCursor(); switch (toolBarArea(controlBar)) { case Qt::TopToolBarArea: controlBar->setVisible(y < 60); break; case Qt::BottomToolBarArea: controlBar->setVisible(y >= (height() - 60)); menuBar()->setVisible(y < 60); break; default: break; } if (controlBar->isHidden() || menuBar()->isHidden()) { cursorHideTimer->start(); } } tabs.at(currentTabIndex)->mouse_move(x, y); break; } default: break; } return retVal; } void MainWindow::keyPressEvent(QKeyEvent *event) { if (event->key() == Qt::Key_Escape) { mediaWidget->setDisplayMode(MediaWidget::NormalMode); } QMainWindow::keyPressEvent(event); } void MainWindow::leaveEvent(QEvent *event) { if (autoHideControlBar) { menuBar()->setVisible(false); controlBar->setVisible(false); tabs.at(currentTabIndex)->mouse_move(-1, -1); } QMainWindow::leaveEvent(event); } diff --git a/src/mediawidget.cpp b/src/mediawidget.cpp index c34e9c5..0ba8773 100644 --- a/src/mediawidget.cpp +++ b/src/mediawidget.cpp @@ -1,1608 +1,1603 @@ /* * mediawidget.cpp * * Copyright (C) 2007-2011 Christoph Pfister * * 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 "log.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "backend-vlc/vlcmediawidget.h" #include "configuration.h" #include "mediawidget.h" #include "mediawidget_p.h" #include "osdwidget.h" MediaWidget::MediaWidget(QMenu *menu_, QToolBar *toolBar, KActionCollection *collection, QWidget *parent) : QWidget(parent), menu(menu_), displayMode(NormalMode), autoResizeFactor(0), blockBackendUpdates(false), muted(false), screenSaverSuspended(false), showElapsedTime(true) { dummySource.reset(new MediaSource()); source = dummySource.data(); QBoxLayout *layout = new QVBoxLayout(this); layout->setMargin(0); QPalette palette = QWidget::palette(); palette.setColor(backgroundRole(), Qt::black); setPalette(palette); setAutoFillBackground(true); setAcceptDrops(true); setFocusPolicy(Qt::StrongFocus); backend = VlcMediaWidget::createVlcMediaWidget(this); if (backend == NULL) { backend = new DummyMediaWidget(this); } backend->connectToMediaWidget(this); layout->addWidget(backend); osdWidget = new OsdWidget(this); actionPrevious = new QWidgetAction(this); actionPrevious->setIcon(QIcon::fromTheme(QLatin1String("media-skip-backward"), QIcon(":media-skip-backward"))); actionPrevious->setText(i18n("Previous")); actionPrevious->setShortcut(Qt::Key_PageUp); connect(actionPrevious, SIGNAL(triggered()), this, SLOT(previous())); toolBar->addAction(collection->addAction(QLatin1String("controls_previous"), actionPrevious)); menu->addAction(actionPrevious); actionPlayPause = new QWidgetAction(this); actionPlayPause->setShortcut(Qt::Key_Space); textPlay = i18n("Play"); textPause = i18n("Pause"); iconPlay = QIcon::fromTheme(QLatin1String("media-playback-start"), QIcon(":media-playback-start")); iconPause = QIcon::fromTheme(QLatin1String("media-playback-pause"), QIcon(":media-playback-pause")); connect(actionPlayPause, SIGNAL(triggered(bool)), this, SLOT(pausedChanged(bool))); toolBar->addAction(collection->addAction(QLatin1String("controls_play_pause"), actionPlayPause)); menu->addAction(actionPlayPause); actionStop = new QWidgetAction(this); actionStop->setIcon(QIcon::fromTheme(QLatin1String("media-playback-stop"), QIcon(":media-playback-stop"))); actionStop->setText(i18n("Stop")); actionStop->setShortcut(Qt::Key_Backspace); connect(actionStop, SIGNAL(triggered()), this, SLOT(stop())); toolBar->addAction(collection->addAction(QLatin1String("controls_stop"), actionStop)); menu->addAction(actionStop); actionNext = new QWidgetAction(this); actionNext->setIcon(QIcon::fromTheme(QLatin1String("media-skip-forward"), QIcon(":media-skip-forward"))); actionNext->setText(i18n("Next")); actionNext->setShortcut(Qt::Key_PageDown); connect(actionNext, SIGNAL(triggered()), this, SLOT(next())); toolBar->addAction(collection->addAction(QLatin1String("controls_next"), actionNext)); menu->addAction(actionNext); menu->addSeparator(); fullScreenAction = new QWidgetAction(this); fullScreenAction->setIcon(QIcon::fromTheme(QLatin1String("view-fullscreen"), QIcon(":view-fullscreen"))); fullScreenAction->setText(i18nc("'Playback' menu", "Full Screen Mode")); fullScreenAction->setShortcut(Qt::Key_F); connect(fullScreenAction, SIGNAL(triggered()), this, SLOT(toggleFullScreen())); menu->addAction(collection->addAction(QLatin1String("view_fullscreen"), fullScreenAction)); minimalModeAction = new QWidgetAction(this); minimalModeAction->setIcon(QIcon::fromTheme(QLatin1String("view-fullscreen"), QIcon(":view-fullscreen"))); minimalModeAction->setText(i18nc("'Playback' menu", "Minimal Mode")); minimalModeAction->setShortcut(Qt::Key_Period); connect(minimalModeAction, SIGNAL(triggered()), this, SLOT(toggleMinimalMode())); menu->addAction(collection->addAction(QLatin1String("view_minimal_mode"), minimalModeAction)); audioStreamBox = new QComboBox(toolBar); connect(audioStreamBox, SIGNAL(currentIndexChanged(int)), this, SLOT(currentAudioStreamChanged(int))); toolBar->addWidget(audioStreamBox); audioStreamModel = new QStringListModel(toolBar); audioStreamBox->setModel(audioStreamModel); QMenu *subtitleMenu = new QMenu(i18nc("'Subtitle' menu", "Subtitle"), this); subtitleBox = new QComboBox(this); QWidgetAction *action = new QWidgetAction(this); action->setDefaultWidget(subtitleBox); textSubtitlesOff = i18nc("subtitle selection entry", "off"); connect(subtitleBox, SIGNAL(currentIndexChanged(int)), this, SLOT(currentSubtitleChanged(int))); subtitleModel = new QStringListModel(toolBar); subtitleBox->setModel(subtitleModel); subtitleMenu->addAction(action); menu->addMenu(subtitleMenu); action = new QWidgetAction(this); action->setText(i18nc("'Subtitle' menu", "Add subtitle file")); action->setIcon(QIcon::fromTheme(QLatin1String("application-x-subrip"), QIcon(":application-x-subrip"))); connect(action, &QWidgetAction::triggered, this, &MediaWidget::openSubtitle); subtitleMenu->addAction(action); menu->addMenu(subtitleMenu); QMenu *audioMenu = new QMenu(i18nc("'Playback' menu", "Audio"), this); action = new QWidgetAction(this); action->setIcon(QIcon::fromTheme(QLatin1String("audio-card"), QIcon(":audio-card"))); action->setText(i18nc("'Audio' menu", "Audio Device")); audioDevMenu = new QMenu(i18nc("'Playback' menu", "Audio Device"), audioMenu); action = new QWidgetAction(this); connect(audioDevMenu, &QMenu::aboutToShow, this, &MediaWidget::getAudioDevices); audioMenu->addMenu(audioDevMenu); action = new QWidgetAction(this); action->setIcon(QIcon::fromTheme(QLatin1String("audio-volume-high"), QIcon(":audio-volume-high"))); action->setText(i18nc("'Audio' menu", "Increase Volume")); action->setShortcut(Qt::Key_Plus); connect(action, SIGNAL(triggered()), this, SLOT(increaseVolume())); audioMenu->addAction(collection->addAction(QLatin1String("controls_increase_volume"), action)); action = new QWidgetAction(this); action->setIcon(QIcon::fromTheme(QLatin1String("audio-volume-low"), QIcon(":audio-volume-low"))); action->setText(i18nc("'Audio' menu", "Decrease Volume")); action->setShortcut(Qt::Key_Minus); connect(action, SIGNAL(triggered()), this, SLOT(decreaseVolume())); audioMenu->addAction(collection->addAction(QLatin1String("controls_decrease_volume"), action)); muteAction = new QWidgetAction(this); muteAction->setText(i18nc("'Audio' menu", "Mute Volume")); mutedIcon = QIcon::fromTheme(QLatin1String("audio-volume-muted"), QIcon(":audio-volume-muted")); unmutedIcon = QIcon::fromTheme(QLatin1String("audio-volume-medium"), QIcon(":audio-volume-medium")); muteAction->setIcon(unmutedIcon); muteAction->setShortcut(Qt::Key_M); connect(muteAction, SIGNAL(triggered()), this, SLOT(mutedChanged())); toolBar->addAction(collection->addAction(QLatin1String("controls_mute_volume"), muteAction)); audioMenu->addAction(muteAction); menu->addMenu(audioMenu); QMenu *videoMenu = new QMenu(i18nc("'Playback' menu", "Video"), this); menu->addMenu(videoMenu); menu->addSeparator(); QMenu *deinterlaceMenu = new QMenu(i18nc("'Video' menu", "Deinterlace"), this); deinterlaceMenu->setIcon(QIcon::fromTheme(QLatin1String("format-justify-center"), QIcon(":format-justify-center"))); QActionGroup *deinterlaceGroup = new QActionGroup(this); connect(deinterlaceMenu, SIGNAL(triggered(QAction*)), this, SLOT(deinterlacingChanged(QAction*))); videoMenu->addMenu(deinterlaceMenu); action = new QWidgetAction(deinterlaceGroup); action->setText(i18nc("'Deinterlace' menu", "disabled")); action->setCheckable(true); action->setShortcut(Qt::Key_D); action->setData(DeinterlaceDisabled); deinterlaceMenu->addAction(collection->addAction(QLatin1String("interlace_disabled"), action)); action = new QWidgetAction(deinterlaceGroup); action->setText(i18nc("'Deinterlace' menu", "discard")); action->setCheckable(true); action->setData(DeinterlaceDiscard); deinterlaceMenu->addAction(collection->addAction(QLatin1String("interlace_discard"), action)); action = new QWidgetAction(deinterlaceGroup); action->setText(i18nc("'Deinterlace' menu", "bob")); action->setCheckable(true); action->setData(DeinterlaceBob); deinterlaceMenu->addAction(collection->addAction(QLatin1String("interlace_bob"), action)); action = new QWidgetAction(deinterlaceGroup); action->setText(i18nc("'Deinterlace' menu", "linear")); action->setCheckable(true); action->setData(DeinterlaceLinear); deinterlaceMenu->addAction(collection->addAction(QLatin1String("interlace_linear"), action)); action = new QWidgetAction(deinterlaceGroup); action->setText(i18nc("'Deinterlace' menu", "yadif")); action->setCheckable(true); action->setData(DeinterlaceYadif); action->setShortcut(Qt::Key_I); deinterlaceMenu->addAction(collection->addAction(QLatin1String("interlace_yadif"), action)); action = new QWidgetAction(deinterlaceGroup); action->setText(i18nc("'Deinterlace' menu", "yadif2x")); action->setCheckable(true); action->setData(DeinterlaceYadif2x); deinterlaceMenu->addAction(collection->addAction(QLatin1String("interlace_yadif2x"), action)); action = new QWidgetAction(deinterlaceGroup); action->setText(i18nc("'Deinterlace' menu", "phosphor")); action->setCheckable(true); action->setData(DeinterlacePhosphor); deinterlaceMenu->addAction(collection->addAction(QLatin1String("interlace_phosphor"), action)); action = new QWidgetAction(deinterlaceGroup); action->setText(i18nc("'Deinterlace' menu", "x")); action->setCheckable(true); action->setData(DeinterlaceX); deinterlaceMenu->addAction(collection->addAction(QLatin1String("interlace_x"), action)); action = new QWidgetAction(deinterlaceGroup); action->setText(i18nc("'Deinterlace' menu", "mean")); action->setCheckable(true); action->setData(DeinterlaceMean); deinterlaceMenu->addAction(collection->addAction(QLatin1String("interlace_mean"), action)); action = new QWidgetAction(deinterlaceGroup); action->setText(i18nc("'Deinterlace' menu", "blend")); action->setCheckable(true); action->setData(DeinterlaceBlend); deinterlaceMenu->addAction(collection->addAction(QLatin1String("interlace_blend"), action)); action = new QWidgetAction(deinterlaceGroup); action->setText(i18nc("'Deinterlace' menu", "Inverse telecine")); action->setCheckable(true); action->setData(DeinterlaceIvtc); deinterlaceMenu->addAction(collection->addAction(QLatin1String("interlace_ivtc"), action)); deinterlaceMode = KSharedConfig::openConfig()->group("MediaObject").readEntry("Deinterlace", 0); if (deinterlaceMode <= DeinterlaceIvtc) { for (int i = 0; i < deinterlaceGroup->actions().size(); i++) { if (deinterlaceGroup->actions().at(i)->data().toInt() == deinterlaceMode) { deinterlaceGroup->actions().at(i)->setChecked(true); break; } } } else { deinterlaceGroup->actions().at(0)->setChecked(true); } backend->setDeinterlacing(static_cast(deinterlaceMode)); QMenu *aspectMenu = new QMenu(i18nc("'Video' menu", "Aspect Ratio"), this); QActionGroup *aspectGroup = new QActionGroup(this); connect(aspectGroup, SIGNAL(triggered(QAction*)), this, SLOT(aspectRatioChanged(QAction*))); videoMenu->addMenu(aspectMenu); action = new QWidgetAction(aspectGroup); action->setText(i18nc("'Aspect Ratio' menu", "Automatic")); action->setCheckable(true); action->setData(AspectRatioAuto); aspectMenu->addAction(collection->addAction(QLatin1String("controls_aspect_auto"), action)); action = new QWidgetAction(aspectGroup); action->setText(i18nc("'Aspect Ratio' menu", "1:1")); action->setCheckable(true); action->setData(AspectRatio1_1); aspectMenu->addAction(collection->addAction(QLatin1String("controls_aspect_1_1"), action)); action = new QWidgetAction(aspectGroup); action->setText(i18nc("'Aspect Ratio' menu", "4:3")); action->setCheckable(true); action->setData(AspectRatio4_3); aspectMenu->addAction(collection->addAction(QLatin1String("controls_aspect_4_3"), action)); action = new QWidgetAction(aspectGroup); action->setText(i18nc("'Aspect Ratio' menu", "5:4")); action->setCheckable(true); action->setData(AspectRatio5_4); aspectMenu->addAction(collection->addAction(QLatin1String("controls_aspect_5_4"), action)); action = new QWidgetAction(aspectGroup); action->setText(i18nc("'Aspect Ratio' menu", "16:9")); action->setCheckable(true); action->setData(AspectRatio16_9); aspectMenu->addAction(collection->addAction(QLatin1String("controls_aspect_16_9"), action)); action = new QWidgetAction(aspectGroup); action->setText(i18nc("'Aspect Ratio' menu", "16:10")); action->setCheckable(true); action->setData(AspectRatio16_10); aspectMenu->addAction(collection->addAction(QLatin1String("controls_aspect_16_10"), action)); action = new QWidgetAction(aspectGroup); action->setText(i18nc("'Aspect Ratio' menu", "2.21:1")); action->setCheckable(true); action->setData(AspectRatio221_100); aspectMenu->addAction(collection->addAction(QLatin1String("controls_aspect_221_100"), action)); action = new QWidgetAction(aspectGroup); action->setText(i18nc("'Aspect Ratio' menu", "2.35:1")); action->setCheckable(true); action->setData(AspectRatio235_100); aspectMenu->addAction(collection->addAction(QLatin1String("controls_aspect_235_100"), action)); action = new QWidgetAction(aspectGroup); action->setText(i18nc("'Aspect Ratio' menu", "2.39:1")); action->setCheckable(true); action->setData(AspectRatio239_100); aspectMenu->addAction(collection->addAction(QLatin1String("controls_aspect_239_100"), action)); QMenu *autoResizeMenu = new QMenu(i18n("Video size"), this); QActionGroup *autoResizeGroup = new QActionGroup(this); // we need an event even if you select the currently selected item autoResizeGroup->setExclusive(false); connect(autoResizeGroup, SIGNAL(triggered(QAction*)), this, SLOT(autoResizeTriggered(QAction*))); action = new QWidgetAction(autoResizeGroup); action->setText(i18nc("Video size", "Automatic")); action->setCheckable(true); action->setData(0); autoResizeMenu->addAction(collection->addAction(QLatin1String("controls_autoresize_off"), action)); action = new QWidgetAction(autoResizeGroup); action->setText(i18nc("Video size", "25%")); action->setCheckable(true); action->setData(25); autoResizeMenu->addAction(collection->addAction(QLatin1String("controls_autoresize_double"), action)); action = new QWidgetAction(autoResizeGroup); action->setText(i18nc("Video size", "50%")); action->setCheckable(true); action->setData(50); autoResizeMenu->addAction(collection->addAction(QLatin1String("controls_autoresize_double"), action)); action = new QWidgetAction(autoResizeGroup); action->setText(i18nc("Video size", "75%")); action->setCheckable(true); action->setData(75); autoResizeMenu->addAction(collection->addAction(QLatin1String("controls_autoresize_double"), action)); action = new QWidgetAction(autoResizeGroup); action->setText(i18nc("Video size", "Original Size")); action->setCheckable(true); action->setData(100); autoResizeMenu->addAction(collection->addAction(QLatin1String("controls_autoresize_original"), action)); action = new QWidgetAction(autoResizeGroup); action->setText(i18nc("Video size", "150%")); action->setCheckable(true); action->setData(150); autoResizeMenu->addAction(collection->addAction(QLatin1String("controls_autoresize_double"), action)); action = new QWidgetAction(autoResizeGroup); action->setText(i18nc("Video size", "200%")); action->setCheckable(true); action->setData(200); autoResizeMenu->addAction(collection->addAction(QLatin1String("controls_autoresize_double"), action)); action = new QWidgetAction(autoResizeGroup); action->setText(i18nc("Video size", "250%")); action->setCheckable(true); action->setData(250); autoResizeMenu->addAction(collection->addAction(QLatin1String("controls_autoresize_double"), action)); action = new QWidgetAction(autoResizeGroup); action->setText(i18nc("Video size", "300%")); action->setCheckable(true); action->setData(300); autoResizeMenu->addAction(collection->addAction(QLatin1String("controls_autoresize_double"), action)); autoResizeFactor = KSharedConfig::openConfig()->group("MediaObject").readEntry("AutoResizeFactor", 0); if (autoResizeFactor <= 300) { for (int i = 0; i < autoResizeGroup->actions().size(); i++) { if (autoResizeGroup->actions().at(i)->data().toInt() == autoResizeFactor) { autoResizeGroup->actions().at(i)->setChecked(true); break; } } } else { autoResizeGroup->actions().at(0)->setChecked(true); } setVideoSize(); videoMenu->addMenu(autoResizeMenu); action = new QWidgetAction(this); action->setText(i18n("Volume Slider")); volumeSlider = new QSlider(toolBar); volumeSlider->setFocusPolicy(Qt::NoFocus); volumeSlider->setOrientation(Qt::Horizontal); volumeSlider->setRange(0, 100); volumeSlider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); volumeSlider->setToolTip(action->text()); volumeSlider->setValue(KSharedConfig::openConfig()->group("MediaObject").readEntry("Volume", 100)); connect(volumeSlider, SIGNAL(valueChanged(int)), this, SLOT(volumeChanged(int))); backend->setVolume(volumeSlider->value()); action->setDefaultWidget(volumeSlider); toolBar->addAction(collection->addAction(QLatin1String("controls_volume_slider"), action)); jumpToPositionAction = new QWidgetAction(this); jumpToPositionAction->setIcon(QIcon::fromTheme(QLatin1String("go-jump"), QIcon(":go-jump"))); jumpToPositionAction->setText(i18nc("@action:inmenu", "Jump to Position...")); jumpToPositionAction->setShortcut(Qt::CTRL + Qt::Key_J); connect(jumpToPositionAction, SIGNAL(triggered()), this, SLOT(jumpToPosition())); menu->addAction(collection->addAction(QLatin1String("controls_jump_to_position"), jumpToPositionAction)); navigationMenu = new QMenu(i18nc("playback menu", "Skip"), this); menu->addMenu(navigationMenu); menu->addSeparator(); int shortSkipDuration = Configuration::instance()->getShortSkipDuration(); int longSkipDuration = Configuration::instance()->getLongSkipDuration(); connect(Configuration::instance(), SIGNAL(shortSkipDurationChanged(int)), this, SLOT(shortSkipDurationChanged(int))); connect(Configuration::instance(), SIGNAL(longSkipDurationChanged(int)), this, SLOT(longSkipDurationChanged(int))); longSkipBackwardAction = new QWidgetAction(this); longSkipBackwardAction->setIcon(QIcon::fromTheme(QLatin1String("media-skip-backward"), QIcon(":media-skip-backward"))); // xgettext:no-c-format longSkipBackwardAction->setText(i18nc("submenu of 'Skip'", "Skip %1s Backward", longSkipDuration)); longSkipBackwardAction->setShortcut(Qt::SHIFT + Qt::Key_Left); connect(longSkipBackwardAction, SIGNAL(triggered()), this, SLOT(longSkipBackward())); navigationMenu->addAction( collection->addAction(QLatin1String("controls_long_skip_backward"), longSkipBackwardAction)); shortSkipBackwardAction = new QWidgetAction(this); shortSkipBackwardAction->setIcon(QIcon::fromTheme(QLatin1String("media-skip-backward"), QIcon(":media-skip-backward"))); // xgettext:no-c-format shortSkipBackwardAction->setText(i18nc("submenu of 'Skip'", "Skip %1s Backward", shortSkipDuration)); shortSkipBackwardAction->setShortcut(Qt::Key_Left); connect(shortSkipBackwardAction, SIGNAL(triggered()), this, SLOT(shortSkipBackward())); navigationMenu->addAction( collection->addAction(QLatin1String("controls_skip_backward"), shortSkipBackwardAction)); shortSkipForwardAction = new QWidgetAction(this); shortSkipForwardAction->setIcon(QIcon::fromTheme(QLatin1String("media-skip-forward"), QIcon(":media-skip-forward"))); // xgettext:no-c-format shortSkipForwardAction->setText(i18nc("submenu of 'Skip'", "Skip %1s Forward", shortSkipDuration)); shortSkipForwardAction->setShortcut(Qt::Key_Right); connect(shortSkipForwardAction, SIGNAL(triggered()), this, SLOT(shortSkipForward())); navigationMenu->addAction( collection->addAction(QLatin1String("controls_skip_forward"), shortSkipForwardAction)); longSkipForwardAction = new QWidgetAction(this); longSkipForwardAction->setIcon(QIcon::fromTheme(QLatin1String("media-skip-forward"), QIcon(":media-skip-forward"))); // xgettext:no-c-format longSkipForwardAction->setText(i18nc("submenu of 'Skip'", "Skip %1s Forward", longSkipDuration)); longSkipForwardAction->setShortcut(Qt::SHIFT + Qt::Key_Right); connect(longSkipForwardAction, SIGNAL(triggered()), this, SLOT(longSkipForward())); navigationMenu->addAction( collection->addAction(QLatin1String("controls_long_skip_forward"), longSkipForwardAction)); toolBar->addAction(QIcon::fromTheme(QLatin1String("player-time"), QIcon(":player-time")), i18n("Seek Slider"))->setEnabled(false); action = new QWidgetAction(this); action->setText(i18n("Seek Slider")); seekSlider = new SeekSlider(toolBar); seekSlider->setFocusPolicy(Qt::NoFocus); seekSlider->setOrientation(Qt::Horizontal); seekSlider->setToolTip(action->text()); connect(seekSlider, SIGNAL(valueChanged(int)), this, SLOT(seek(int))); action->setDefaultWidget(seekSlider); toolBar->addAction(collection->addAction(QLatin1String("controls_position_slider"), action)); menuAction = new QWidgetAction(this); menuAction->setIcon(QIcon::fromTheme(QLatin1String("media-optical-video"), QIcon(":media-optical-video"))); menuAction->setText(i18nc("dvd navigation", "DVD Menu")); connect(menuAction, SIGNAL(triggered()), this, SLOT(toggleMenu())); menu->addAction(collection->addAction(QLatin1String("controls_toggle_menu"), menuAction)); titleMenu = new QMenu(i18nc("dvd navigation", "Title"), this); titleGroup = new QActionGroup(this); connect(titleGroup, SIGNAL(triggered(QAction*)), this, SLOT(currentTitleChanged(QAction*))); menu->addMenu(titleMenu); chapterMenu = new QMenu(i18nc("dvd navigation", "Chapter"), this); chapterGroup = new QActionGroup(this); connect(chapterGroup, SIGNAL(triggered(QAction*)), this, SLOT(currentChapterChanged(QAction*))); menu->addMenu(chapterMenu); angleMenu = new QMenu(i18nc("dvd navigation", "Angle"), this); angleGroup = new QActionGroup(this); connect(angleGroup, SIGNAL(triggered(QAction*)), this, SLOT(currentAngleChanged(QAction*))); menu->addMenu(angleMenu); action = new QWidgetAction(this); action->setText(i18n("Switch between elapsed and remaining time display")); timeButton = new QPushButton(toolBar); timeButton->setFocusPolicy(Qt::NoFocus); timeButton->setToolTip(action->text()); connect(timeButton, SIGNAL(clicked(bool)), this, SLOT(timeButtonClicked())); action->setDefaultWidget(timeButton); toolBar->addAction(collection->addAction(QLatin1String("controls_time_button"), action)); QTimer *timer = new QTimer(this); timer->start(50000); connect(timer, SIGNAL(timeout()), this, SLOT(checkScreenSaver())); // Set the play/pause icons accordingly playbackStatusChanged(); } MediaWidget::~MediaWidget() { KSharedConfig::openConfig()->group("MediaObject").writeEntry("Volume", volumeSlider->value()); KSharedConfig::openConfig()->group("MediaObject").writeEntry("Deinterlace", deinterlaceMode); KSharedConfig::openConfig()->group("MediaObject").writeEntry("AutoResizeFactor", autoResizeFactor); } QString MediaWidget::extensionFilter() { return i18n( "Supported Media Files (" // generated from kaffeine.desktop's mime types "*.3ga *.3gp *.3gpp *.669 *.ac3 *.aif *.aiff *.anim1 *.anim2 *.anim3 *.anim4 " "*.anim5 *.anim6 *.anim7 *.anim8 *.anim9 *.animj *.asf *.asx *.au *.avf *.avi " "*.bdm *.bdmv *.clpi *.cpi *.divx *.dv *.f4a *.f4b *.f4v *.flac *.flc *.fli *.flv " "*.it *.lrv *.m15 *.m2t *.m2ts *.m3u *.m3u8 *.m4a *.m4b *.m4v *.med *.mka *.mkv " "*.mng *.mod *.moov *.mov *.mp+ *.mp2 *.mp3 *.mp4 *.mpc *.mpe *.mpeg *.mpg *.mpga " "*.mpl *.mpls *.mpp *.mtm *.mts *.nsv *.oga *.ogg *.ogm *.ogv *.ogx *.opus *.pls " "*.qt *.qtl *.qtvr *.ra *.ram *.rax *.rm *.rmj *.rmm *.rms *.rmvb *.rmx *.rp *.rv " "*.rvx *.s3m *.shn *.snd *.spl *.stm *.swf *.ts *.tta *.ult *.uni *.vdr *.vlc " "*.vob *.voc *.wav *.wax *.webm *.wma *.wmv *.wmx *.wv *.wvp *.wvx *.xm *.xspf " // manual entries "*.kaffeine *.iso);;" "All Files (*)"); } MediaWidget::DisplayMode MediaWidget::getDisplayMode() const { return displayMode; } void MediaWidget::setDisplayMode(DisplayMode displayMode_) { if (displayMode != displayMode_) { displayMode = displayMode_; switch (displayMode) { case NormalMode: case MinimalMode: fullScreenAction->setIcon(QIcon::fromTheme(QLatin1String("view-fullscreen"), QIcon(":view-fullscreen"))); fullScreenAction->setText(i18nc("'Playback' menu", "Full Screen Mode")); break; case FullScreenMode: case FullScreenReturnToMinimalMode: fullScreenAction->setIcon(QIcon::fromTheme(QLatin1String("view-restore"), QIcon(":view-restore"))); fullScreenAction->setText(i18nc("'Playback' menu", "Exit Full Screen Mode")); break; } switch (displayMode) { case NormalMode: case FullScreenMode: case FullScreenReturnToMinimalMode: minimalModeAction->setIcon(QIcon::fromTheme(QLatin1String("view-restore"), QIcon(":view-restore"))); minimalModeAction->setText(i18nc("'Playback' menu", "Minimal Mode")); break; case MinimalMode: minimalModeAction->setIcon(QIcon::fromTheme(QLatin1String("view-fullscreen"), QIcon(":view-fullscreen"))); minimalModeAction->setText(i18nc("'Playback' menu", "Exit Minimal Mode")); break; } emit displayModeChanged(); } } void MediaWidget::play(MediaSource *source_) { if (source != source_) { source->playbackStatusChanged(Idle); source = source_; if (source == NULL) { source = dummySource.data(); } } source->setMediaWidget(this); backend->play(*source); } void MediaWidget::mediaSourceDestroyed(MediaSource *mediaSource) { if (source == mediaSource) { source = dummySource.data(); } } void MediaWidget::openSubtitle() { QString fname = QFileDialog::getOpenFileName(this, i18nc("@title:window", "Open subtitle"),".", i18n("Subtitles (*.cdg *.idx *.srt " \ "*.sub *.utf *.ass " \ "*.ssa *.aqt " \ "*.jss *.psb " \ "*.rt *.smi *.txt " \ "*.smil *.stl *.usf " \ "*.dks *.pjs *.mpl2 *.mks " \ "*.vtt *.ttml *.dfxp")); setSubtitle(QUrl::fromLocalFile(fname)); } void MediaWidget::setSubtitle(QUrl url) { if (!url.isValid()) { return; } backend->setExternalSubtitle(url); } void MediaWidget::play(const QUrl &url, const QUrl &subtitleUrl) { // FIXME mem-leak play(new MediaSourceUrl(url, subtitleUrl)); } void MediaWidget::playAudioCd(const QString &device) { QUrl devicePath; if (!device.isEmpty()) { devicePath = QUrl::fromLocalFile(device); } else { QList devices = Solid::Device::listFromQuery(QLatin1String("OpticalDisc.availableContent & 'Audio'")); if (!devices.isEmpty()) { Solid::Block *block = devices.first().as(); if (block != NULL) { devicePath = QUrl::fromLocalFile(block->device()); } } } // FIXME mem-leak play(new MediaSourceAudioCd(devicePath)); } void MediaWidget::playVideoCd(const QString &device) { QUrl devicePath; if (!device.isEmpty()) { devicePath = QUrl::fromLocalFile(device); } else { QList devices = Solid::Device::listFromQuery( QLatin1String("OpticalDisc.availableContent & 'VideoCd|SuperVideoCd'")); if (!devices.isEmpty()) { Solid::Block *block = devices.first().as(); if (block != NULL) { devicePath = QUrl::fromLocalFile(block->device()); } } } // FIXME mem-leak play(new MediaSourceVideoCd(devicePath)); } void MediaWidget::playDvd(const QString &device) { QUrl devicePath; if (!device.isEmpty()) { devicePath = QUrl::fromLocalFile(device); } else { QList devices = Solid::Device::listFromQuery(QLatin1String("OpticalDisc.availableContent & 'VideoDvd'")); if (!devices.isEmpty()) { Solid::Block *block = devices.first().as(); if (block != NULL) { devicePath = QUrl::fromLocalFile(block->device()); } } } // FIXME mem-leak play(new MediaSourceDvd(devicePath)); } OsdWidget *MediaWidget::getOsdWidget() { return osdWidget; } MediaWidget::PlaybackStatus MediaWidget::getPlaybackStatus() const { return backend->getPlaybackStatus(); } int MediaWidget::getVolume() const { return volumeSlider->value(); } int MediaWidget::getPosition() const { return backend->getCurrentTime(); } void MediaWidget::play() { source->replay(); } void MediaWidget::togglePause() { actionPlayPause->trigger(); } void MediaWidget::setPosition(int position) { backend->seek(position); } void MediaWidget::setVolume(int volume) { // QSlider ensures that the value is within the range volumeSlider->setValue(volume); } void MediaWidget::setVolumeUnderMouse(int volume) { if (!backend->underMouse()) return; if (volume == 100 || !volume) osdWidget->showText(i18nc("osd", "Volume: %1%", volume), 1500); else setVolume(volume); } void MediaWidget::toggleMuted() { muteAction->trigger(); } void MediaWidget::previous() { if (source->getType() == MediaSource::Url) emit playlistPrevious(); source->previous(); } void MediaWidget::next() { if (source->getType() == MediaSource::Url) emit playlistNext(); source->next(); } void MediaWidget::stop() { switch (backend->getPlaybackStatus()) { case Idle: break; case Playing: case Paused: osdWidget->showText(i18nc("osd", "Stopped"), 1500); break; } backend->stop(); source->playbackStatusChanged(Idle); } void MediaWidget::setAudioCard() { QAction *action = qobject_cast(sender()); backend->setAudioDevice(action->data().toString()); } void MediaWidget::increaseVolume() { // QSlider ensures that the value is within the range volumeSlider->setValue(volumeSlider->value() + 5); } void MediaWidget::decreaseVolume() { // QSlider ensures that the value is within the range volumeSlider->setValue(volumeSlider->value() - 5); } void MediaWidget::checkScreenSaver() { bool suspendScreenSaver = false; switch (backend->getPlaybackStatus()) { case Idle: case Paused: break; case Playing: suspendScreenSaver = isVisible(); break; } if (suspendScreenSaver) { // KDE - Inhibit doesn't inhibit "lock screen after inactivity" QDBusInterface(QLatin1String("org.freedesktop.ScreenSaver"), QLatin1String("/ScreenSaver"), QLatin1String("org.freedesktop.ScreenSaver")).call(QDBus::NoBlock, QLatin1String("SimulateUserActivity")); // GNOME - Inhibit doesn't inhibit power management functions QDBusInterface(QLatin1String("org.gnome.ScreenSaver"), QLatin1String("/"), QLatin1String("org.gnome.ScreenSaver")). call(QDBus::NoBlock, QLatin1String("SimulateUserActivity")); } if (screenSaverSuspended != suspendScreenSaver) { // X11 - needed if none of the above applications is running screenSaverSuspended = suspendScreenSaver; XScreenSaverSuspend(QX11Info::display(), suspendScreenSaver); } } void MediaWidget::mutedChanged() { muted = !muted; backend->setMuted(muted); if (muted) { muteAction->setIcon(mutedIcon); osdWidget->showText(i18nc("osd", "Mute On"), 1500); } else { muteAction->setIcon(unmutedIcon); osdWidget->showText(i18nc("osd", "Mute Off"), 1500); } } void MediaWidget::volumeChanged(int volume) { backend->setVolume(volume); osdWidget->showText(i18nc("osd", "Volume: %1%", volume), 1500); } void MediaWidget::toggleFullScreen() { switch (displayMode) { case NormalMode: setDisplayMode(FullScreenMode); break; case FullScreenMode: setDisplayMode(NormalMode); break; case FullScreenReturnToMinimalMode: setDisplayMode(MinimalMode); break; case MinimalMode: setDisplayMode(FullScreenReturnToMinimalMode); break; } } void MediaWidget::toggleMinimalMode() { switch (displayMode) { case NormalMode: case FullScreenMode: case FullScreenReturnToMinimalMode: setDisplayMode(MinimalMode); break; case MinimalMode: setDisplayMode(NormalMode); break; } } void MediaWidget::seek(int position) { if (blockBackendUpdates) { return; } backend->seek(position); } void MediaWidget::deinterlacingChanged(QAction *action) { bool ok; const char *mode; deinterlaceMode = action->data().toInt(&ok); switch (deinterlaceMode) { case DeinterlaceDiscard: mode = "discard"; break; case DeinterlaceBob: mode = "bob"; break; case DeinterlaceLinear: mode = "linear"; break; case DeinterlaceYadif: mode = "yadif"; break; case DeinterlaceYadif2x: mode = "yadif2x"; break; case DeinterlacePhosphor: mode = "phosphor"; break; case DeinterlaceX: mode = "x"; break; case DeinterlaceMean: mode = "mean"; break; case DeinterlaceBlend: mode = "blend"; break; case DeinterlaceIvtc: mode = "ivtc"; break; case DeinterlaceDisabled: default: mode = "disabled"; } backend->setDeinterlacing(static_cast(deinterlaceMode)); osdWidget->showText(i18nc("osd message", "Deinterlace %1", mode), 1500); } void MediaWidget::aspectRatioChanged(QAction *action) { bool ok; unsigned int aspectRatio_ = action->data().toInt(&ok); if (aspectRatio_ <= AspectRatio239_100) { backend->setAspectRatio(static_cast(aspectRatio_)); setVideoSize(); return; } qCWarning(logMediaWidget, "internal error"); } void MediaWidget::setAspectRatio(MediaWidget::AspectRatio aspectRatio) { backend->setAspectRatio(aspectRatio); } void MediaWidget::setVideoSize() { float scale = autoResizeFactor / 100.0; if (scale > 3.4 || scale < 0) scale = 0; backend->resizeToVideo(scale); } void MediaWidget::autoResizeTriggered(QAction *action) { foreach (QAction *autoResizeAction, action->actionGroup()->actions()) { autoResizeAction->setChecked(autoResizeAction == action); } bool ok = false; autoResizeFactor = action->data().toInt(&ok); if (ok) setVideoSize(); else qCWarning(logMediaWidget, "internal error"); } void MediaWidget::pausedChanged(bool paused) { switch (backend->getPlaybackStatus()) { case Idle: source->replay(); break; case Playing: case Paused: backend->setPaused(paused); break; } } void MediaWidget::timeButtonClicked() { showElapsedTime = !showElapsedTime; currentTotalTimeChanged(); } void MediaWidget::longSkipBackward() { int longSkipDuration = Configuration::instance()->getLongSkipDuration(); int currentTime = (backend->getCurrentTime() - 1000 * longSkipDuration); if (currentTime < 0) { currentTime = 0; } backend->seek(currentTime); } void MediaWidget::shortSkipBackward() { int shortSkipDuration = Configuration::instance()->getShortSkipDuration(); int currentTime = (backend->getCurrentTime() - 1000 * shortSkipDuration); if (currentTime < 0) { currentTime = 0; } backend->seek(currentTime); } void MediaWidget::shortSkipForward() { int shortSkipDuration = Configuration::instance()->getShortSkipDuration(); backend->seek(backend->getCurrentTime() + 1000 * shortSkipDuration); } void MediaWidget::longSkipForward() { int longSkipDuration = Configuration::instance()->getLongSkipDuration(); backend->seek(backend->getCurrentTime() + 1000 * longSkipDuration); } void MediaWidget::jumpToPosition() { QDialog *dialog = new JumpToPositionDialog(this); dialog->setAttribute(Qt::WA_DeleteOnClose, true); dialog->setModal(true); dialog->show(); } void MediaWidget::currentAudioStreamChanged(int currentAudioStream) { if (!blockBackendUpdates) { if (source->overrideAudioStreams()) { source->setCurrentAudioStream(currentAudioStream); return; } source->setCurrentAudioStream(currentAudioStream - backend->getAudioStreams().size()); if (currentAudioStream >= backend->getAudioStreams().size()) { currentAudioStream = -1; } if (backend->getCurrentAudioStream() != currentAudioStream) { backend->setCurrentAudioStream(currentAudioStream); } } audioStreamBox->view()->setMinimumWidth(audioStreamBox->view()->sizeHintForColumn(0)); } void MediaWidget::currentSubtitleChanged(int currentSubtitle) { if (blockBackendUpdates) return; if (source->overrideSubtitles()) { source->setCurrentSubtitle(currentSubtitle - 1); return; } source->setCurrentSubtitle(currentSubtitle - 1 - backend->getSubtitles().size()); backend->setCurrentSubtitle(currentSubtitle); } void MediaWidget::toggleMenu() { backend->showDvdMenu(); } void MediaWidget::currentTitleChanged(QAction *action) { backend->setCurrentTitle(titleGroup->actions().indexOf(action) + 1); } void MediaWidget::currentChapterChanged(QAction *action) { backend->setCurrentChapter(chapterGroup->actions().indexOf(action) + 1); } void MediaWidget::currentAngleChanged(QAction *action) { backend->setCurrentAngle(angleGroup->actions().indexOf(action) + 1); } void MediaWidget::shortSkipDurationChanged(int shortSkipDuration) { // xgettext:no-c-format shortSkipBackwardAction->setText(i18nc("submenu of 'Skip'", "Skip %1s Backward", shortSkipDuration)); // xgettext:no-c-format shortSkipForwardAction->setText(i18nc("submenu of 'Skip'", "Skip %1s Forward", shortSkipDuration)); } void MediaWidget::longSkipDurationChanged(int longSkipDuration) { // xgettext:no-c-format longSkipBackwardAction->setText(i18nc("submenu of 'Skip'", "Skip %1s Backward", longSkipDuration)); // xgettext:no-c-format longSkipForwardAction->setText(i18nc("submenu of 'Skip'", "Skip %1s Forward", longSkipDuration)); } void MediaWidget::getAudioDevices() { foreach(QAction *action, audioDevMenu->actions()) { audioDevMenu->removeAction(action); } foreach(const QString &device, backend->getAudioDevices()) { QAction *action = new QWidgetAction(this); action->setText(device); action->setData(device); connect(action, SIGNAL(triggered()), this, SLOT(setAudioCard())); audioDevMenu->addAction(action); } } void MediaWidget::audioStreamsChanged() { QStringList items; int currentIndex; if (source->overrideAudioStreams()) { items = source->getAudioStreams(); currentIndex = source->getCurrentAudioStream(); } else { items = backend->getAudioStreams(); currentIndex = backend->getCurrentAudioStream(); } blockBackendUpdates = true; if (audioStreamModel->stringList() != items) { audioStreamModel->setStringList(items); } audioStreamBox->setCurrentIndex(currentIndex); audioStreamBox->setEnabled(items.size() > 1); blockBackendUpdates = false; } void MediaWidget::subtitlesChanged() { QStringList items(textSubtitlesOff); int currentIndex = 0; if (source->overrideSubtitles()) { items += source->getSubtitles(); currentIndex = (source->getCurrentSubtitle() + 1); // automatically choose appropriate subtitle int selectedSubtitle = -1; if (currentIndex > 0) { selectedSubtitle = (backend->getSubtitles().size() - 1); } if (backend->getCurrentSubtitle() != selectedSubtitle) { backend->setCurrentSubtitle(selectedSubtitle); } } else { items += backend->getSubtitles(); items += source->getSubtitles(); currentIndex = (backend->getCurrentSubtitle()); int currentSourceIndex = source->getCurrentSubtitle(); if (currentSourceIndex >= 0) { currentIndex = (currentSourceIndex + backend->getSubtitles().size() + 1); } } blockBackendUpdates = true; if (subtitleModel->stringList() != items) { subtitleModel->setStringList(items); } if (currentIndex < 0) currentIndex = 0; subtitleBox->setCurrentIndex(currentIndex); subtitleBox->setEnabled(items.size() > 1); blockBackendUpdates = false; } void MediaWidget::currentTotalTimeChanged() { int currentTime = backend->getCurrentTime(); int totalTime = backend->getTotalTime(); source->trackLengthChanged(totalTime); if (source->getType() == MediaSource::Url) emit playlistTrackLengthChanged(totalTime); // If the player backend doesn't implement currentTime and/or // totalTime, the source can implement such logic source->validateCurrentTotalTime(currentTime, totalTime); blockBackendUpdates = true; seekSlider->setRange(0, totalTime); seekSlider->setValue(currentTime); if (showElapsedTime) { timeButton->setText(QLatin1Char(' ') + QTime(0, 0).addMSecs(currentTime).toString()); } else { int remainingTime = (totalTime - currentTime); timeButton->setText(QLatin1Char('-') + QTime(0, 0).addMSecs(remainingTime).toString()); } blockBackendUpdates = false; } void MediaWidget::seekableChanged() { bool seekable = (backend->isSeekable() && !source->hideCurrentTotalTime()); seekSlider->setEnabled(seekable); navigationMenu->setEnabled(seekable); jumpToPositionAction->setEnabled(seekable); timeButton->setEnabled(seekable); } void MediaWidget::contextMenuEvent(QContextMenuEvent *event) { menu->popup(event->globalPos()); } void MediaWidget::mouseDoubleClickEvent(QMouseEvent *event) { Q_UNUSED(event) emit toggleFullScreen(); } void MediaWidget::dragEnterEvent(QDragEnterEvent *event) { if (event->mimeData()->hasUrls()) { event->acceptProposedAction(); } } void MediaWidget::dropEvent(QDropEvent *event) { const QMimeData *mimeData = event->mimeData(); if (mimeData->hasUrls()) { emit playlistUrlsDropped(mimeData->urls()); event->acceptProposedAction(); } } void MediaWidget::keyPressEvent(QKeyEvent *event) { int key = event->key(); if (backend->hasDvdMenu()) { switch (key){ case Qt::Key_Return: case Qt::Key_Up: case Qt::Key_Down: case Qt::Key_Left: case Qt::Key_Right: backend->dvdNavigate(key); } } if ((key >= Qt::Key_0) && (key <= Qt::Key_9)) { emit osdKeyPressed(key); } else { QWidget::keyPressEvent(event); } } void MediaWidget::resizeEvent(QResizeEvent *event) { osdWidget->resize(event->size()); QWidget::resizeEvent(event); } void MediaWidget::wheelEvent(QWheelEvent *event) { - int shortSkipDuration = Configuration::instance()->getShortSkipDuration(); - int currentTime = - (backend->getCurrentTime() - ((25 * shortSkipDuration * event->delta()) / 3)); - - if (currentTime < 0) { - currentTime = 0; - } + int y = event->delta(); + int delta = (y < 0) ? -1 : 1; - backend->seek(currentTime); + setVolumeUnderMouse(getVolume() + delta); } void MediaWidget::playbackFinished() { if (source->getType() == MediaSource::Url) emit playlistNext(); source->playbackFinished(); } void MediaWidget::playbackStatusChanged() { source->playbackStatusChanged(backend->getPlaybackStatus()); bool playing = true; switch (backend->getPlaybackStatus()) { case Idle: actionPlayPause->setIcon(iconPlay); actionPlayPause->setText(textPlay); playing = false; break; case Playing: actionPlayPause->setIcon(iconPause); actionPlayPause->setText(textPause); osdWidget->showText(i18nc("osd", "Playing"), 1500); break; case Paused: actionPlayPause->setIcon(iconPlay); actionPlayPause->setText(textPlay); osdWidget->showText(i18nc("osd", "Paused"), 1500); break; } actionPlayPause->setCheckable(playing); actionPrevious->setEnabled(playing); actionStop->setEnabled(playing); actionNext->setEnabled(playing); timeButton->setEnabled(playing); } void MediaWidget::metadataChanged() { QMap metadata = backend->getMetadata(); source->metadataChanged(metadata); if (source->getType() == MediaSource::Url) emit playlistTrackMetadataChanged(metadata); if (source->overrideCaption()) { emit changeCaption(source->getDefaultCaption()); return; } QString caption = metadata.value(Title); QString artist = metadata.value(Artist); if (!caption.isEmpty() && !artist.isEmpty()) { caption += QLatin1Char(' '); } if (!artist.isEmpty()) { caption += QLatin1Char('('); caption += artist; caption += QLatin1Char(')'); } if (caption.isEmpty()) { caption = source->getDefaultCaption(); } if (!caption.isEmpty()) { osdWidget->showText(caption, 2500); } emit changeCaption(caption); } void MediaWidget::dvdMenuChanged() { bool hasDvdMenu = backend->hasDvdMenu(); menuAction->setEnabled(hasDvdMenu); // Disable key left/right for DVD, in order to allow its usage // to navigate at DVD's menu. Unfortunately, libVlc doesn't provide // a way to tell if the device is at the DVB menu. if (hasDvdMenu) { shortSkipBackwardAction->setShortcut(Qt::Key_unknown); shortSkipForwardAction->setShortcut(Qt::Key_unknown); } else { shortSkipBackwardAction->setShortcut(Qt::Key_Left); shortSkipForwardAction->setShortcut(Qt::Key_Right); } } void MediaWidget::titlesChanged() { int titleCount = backend->getTitleCount(); int currentTitle = backend->getCurrentTitle(); if (titleCount > 1) { QList actions = titleGroup->actions(); if (actions.count() < titleCount) { int i = actions.count(); actions.clear(); for (; i < titleCount; ++i) { QAction *action = titleGroup->addAction(QString::number(i + 1)); action->setCheckable(true); titleMenu->addAction(action); } actions = titleGroup->actions(); } for (int i = 0; i < actions.size(); ++i) { actions.at(i)->setVisible(i < titleCount); } if ((currentTitle >= 1) && (currentTitle <= titleGroup->actions().count())) { titleGroup->actions().at(currentTitle - 1)->setChecked(true); } else if (titleGroup->checkedAction() != NULL) { titleGroup->checkedAction()->setChecked(false); } titleMenu->setEnabled(true); } else { titleMenu->setEnabled(false); } } void MediaWidget::chaptersChanged() { int chapterCount = backend->getChapterCount(); int currentChapter = backend->getCurrentChapter(); if (chapterCount > 1) { QList actions = chapterGroup->actions(); if (actions.count() < chapterCount) { int i = actions.count(); actions.clear(); for (; i < chapterCount; ++i) { QAction *action = chapterGroup->addAction(QString::number(i + 1)); action->setCheckable(true); chapterMenu->addAction(action); } actions = chapterGroup->actions(); } for (int i = 0; i < actions.size(); ++i) { actions.at(i)->setVisible(i < chapterCount); } if ((currentChapter >= 1) && (currentChapter <= chapterGroup->actions().count())) { chapterGroup->actions().at(currentChapter - 1)->setChecked(true); } else if (chapterGroup->checkedAction() != NULL) { chapterGroup->checkedAction()->setChecked(false); } chapterMenu->setEnabled(true); } else { chapterMenu->setEnabled(false); } } void MediaWidget::anglesChanged() { int angleCount = backend->getAngleCount(); int currentAngle = backend->getCurrentAngle(); if (angleCount > 1) { QList actions = angleGroup->actions(); if (actions.count() < angleCount) { int i = actions.count(); actions.clear(); for (; i < angleCount; ++i) { QAction *action = angleGroup->addAction(QString::number(i + 1)); action->setCheckable(true); angleMenu->addAction(action); } actions = angleGroup->actions(); } for (int i = 0; i < actions.size(); ++i) { actions.at(i)->setVisible(i < angleCount); } if ((currentAngle >= 1) && (currentAngle <= angleGroup->actions().count())) { angleGroup->actions().at(currentAngle - 1)->setChecked(true); } else if (angleGroup->checkedAction() != NULL) { angleGroup->checkedAction()->setChecked(false); } angleMenu->setEnabled(true); } else { angleMenu->setEnabled(false); } } void MediaWidget::videoSizeChanged() { setVideoSize(); } JumpToPositionDialog::JumpToPositionDialog(MediaWidget *mediaWidget_) : QDialog(mediaWidget_), mediaWidget(mediaWidget_) { setWindowTitle(i18nc("@title:window", "Jump to Position")); QWidget *widget = new QWidget(this); QBoxLayout *layout = new QVBoxLayout(widget); layout->addWidget(new QLabel(i18n("Enter a position:"))); timeEdit = new QTimeEdit(this); timeEdit->setDisplayFormat(QLatin1String("hh:mm:ss")); timeEdit->setTime(QTime().addMSecs(mediaWidget->getPosition())); layout->addWidget(timeEdit); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok); timeEdit->setFocus(); QVBoxLayout *mainLayout = new QVBoxLayout; setLayout(mainLayout); mainLayout->addWidget(widget); mainLayout->addWidget(buttonBox); connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); } JumpToPositionDialog::~JumpToPositionDialog() { } void JumpToPositionDialog::accept() { mediaWidget->setPosition(QTime(0, 0, 0).msecsTo(timeEdit->time())); QDialog::accept(); } void SeekSlider::mousePressEvent(QMouseEvent *event) { int buttons = style()->styleHint(QStyle::SH_Slider_AbsoluteSetButtons); Qt::MouseButton button = static_cast(buttons & (~(buttons - 1))); QMouseEvent modifiedEvent(event->type(), event->pos(), event->globalPos(), button, event->buttons() ^ event->button() ^ button, event->modifiers()); QSlider::mousePressEvent(&modifiedEvent); }