X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fmainwindow.cpp;h=8b001ac0864d24e98fc67ddce7d113973c82eaa2;hb=9337294c49c89c5cb01db726835da60af566821f;hp=b03d59a8e5ced29be72f7a5bfca84fd7310a04b6;hpb=5ecc9c04fb173c5693bcded5191d29816304d12c;p=minitube diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index b03d59a..8b001ac 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -19,22 +19,25 @@ along with Minitube. If not, see . $END_LICENSE */ #include "mainwindow.h" -#include "homeview.h" -#include "searchview.h" -#include "mediaview.h" + #include "aboutview.h" #include "downloadview.h" -#include "spacer.h" +#include "homeview.h" +#include "mediaview.h" +#include "regionsview.h" +#include "searchview.h" +#include "standardfeedsview.h" + #include "constants.h" -#include "iconutils.h" -#include "global.h" -#include "videodefinition.h" #include "fontutils.h" #include "globalshortcuts.h" +#include "iconutils.h" #include "searchparams.h" +#include "spacer.h" +#include "videodefinition.h" #include "videosource.h" #include "ytsearch.h" -#ifdef Q_OS_LINUX +#ifdef APP_LINUX #include "gnomeglobalshortcutbackend.h" #endif #ifdef Q_OS_MAC @@ -44,62 +47,89 @@ $END_LICENSE */ #include "macutils.h" #endif #include "downloadmanager.h" -#include "ytsuggester.h" -#include "updatechecker.h" #include "temporary.h" -#ifdef APP_MAC +#include "ytsuggester.h" +#if defined(APP_MAC_SEARCHFIELD) && !defined(APP_MAC_QMACTOOLBAR) #include "searchlineedit_mac.h" #else #include "searchlineedit.h" #endif +#ifdef APP_MAC_QMACTOOLBAR +#include "mactoolbar.h" +#endif #include #ifdef APP_EXTRA +#include "compositefader.h" #include "extra.h" #include "updatedialog.h" #endif #ifdef APP_ACTIVATION #include "activation.h" #include "activationview.h" -#include "activationdialog.h" #endif -#include "ytregions.h" -#include "regionsview.h" -#include "standardfeedsview.h" #include "channelaggregator.h" #include "database.h" -#include "videoareawidget.h" +#include "httputils.h" #include "jsfunctions.h" #include "seekslider.h" +#include "sidebarwidget.h" +#include "toolbarmenu.h" +#include "videoarea.h" +#include "yt3.h" +#include "ytregions.h" + +#include "invidious.h" +#include "js.h" +#include "videoapi.h" -static MainWindow *singleton = 0; +#ifdef MEDIA_QTAV +#include "mediaqtav.h" +#endif +#ifdef MEDIA_MPV +#include "mediampv.h" +#endif -MainWindow* MainWindow::instance() { - if (!singleton) singleton = new MainWindow(); - return singleton; +#ifdef UPDATER +#include "updater.h" +#endif + +#include "subscriptionimportview.h" + +namespace { +MainWindow *mainWindowInstance; } -MainWindow::MainWindow() : - updateChecker(0), - aboutView(0), - downloadView(0), - regionsView(0), - #ifdef APP_PHONON - mediaObject(0), - audioOutput(0), - #endif - m_fullscreen(false), - m_compact(false) { +MainWindow *MainWindow::instance() { + return mainWindowInstance; +} - singleton = this; +MainWindow::MainWindow() + : aboutView(nullptr), downloadView(nullptr), regionsView(nullptr), mainToolBar(nullptr), + fullScreenActive(false), compactModeActive(false), initialized(false), toolbarMenu(nullptr), + media(nullptr) { + mainWindowInstance = this; // views mechanism - history = new QStack(); views = new QStackedWidget(); - views->hide(); setCentralWidget(views); +#ifdef APP_EXTRA + Extra::windowSetup(this); +#endif + + messageLabel = new QLabel(this); + messageLabel->setWordWrap(false); + messageLabel->setStyleSheet("padding:5px;border:0;background:palette(window)"); + messageLabel->setAlignment(Qt::AlignCenter); + messageLabel->hide(); + adjustMessageLabelPosition(); + messageTimer = new QTimer(this); + messageTimer->setInterval(5000); + messageTimer->setSingleShot(true); + connect(messageTimer, SIGNAL(timeout()), SLOT(hideMessage())); + // views - homeView = new HomeView(); + homeView = new HomeView(this); views->addWidget(homeView); // TODO make this lazy @@ -110,7 +140,8 @@ MainWindow::MainWindow() : // build ui createActions(); createMenus(); - createToolBars(); + createToolBar(); + hideToolbar(); createStatusBar(); // remove that useless menu/toolbar context menu @@ -129,36 +160,30 @@ MainWindow::MainWindow() : views->widget(i)->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); setMinimumWidth(0); - // show the initial view - showHome(false); - #ifdef APP_ACTIVATION - if (!Activation::instance().isActivated()) - showActivationView(false); -#endif - - views->show(); - -#ifdef APP_EXTRA - Extra::windowSetup(this); + Activation::instance().initialCheck(); +#else + showHome(); #endif - qApp->processEvents(); - QTimer::singleShot(50, this, SLOT(lazyInit())); -} + if (VideoAPI::impl() == VideoAPI::IV) { + Invidious::instance().initServers(); + } else if (VideoAPI::impl() == VideoAPI::YT3) { + YT3::instance().initApiKeys(); + } else if (VideoAPI::impl() == VideoAPI::JS) { + JS::instance().getNamFactory().setRequestHeaders( + {{"User-Agent", HttpUtils::stealthUserAgent()}}); + JS::instance().initialize(QUrl(QLatin1String(Constants::WEBSITE) + "-ws/bundle2.js")); + /// JS::instance().initialize(QUrl("http://localhost:8000/bundle-test.js")); + Invidious::instance().initServers(); + } -MainWindow::~MainWindow() { - delete history; + QTimer::singleShot(100, this, &MainWindow::lazyInit); } void MainWindow::lazyInit() { -#ifdef APP_PHONON - initPhonon(); -#endif mediaView->initialize(); -#ifdef APP_PHONON - mediaView->setMediaObject(mediaObject); -#endif + initMedia(); qApp->processEvents(); // CLI @@ -172,11 +197,12 @@ void MainWindow::lazyInit() { searchParams->setKeywords(query); showMedia(searchParams); } - } + } else + showMessage(tr("Make yourself comfortable")); // Global shortcuts GlobalShortcuts &shortcuts = GlobalShortcuts::instance(); -#ifdef Q_OS_LINUX +#ifdef APP_LINUX if (GnomeGlobalShortcutBackend::IsGsdAvailable()) shortcuts.setBackend(new GnomeGlobalShortcutBackend(&shortcuts)); #endif @@ -187,114 +213,171 @@ void MainWindow::lazyInit() { connect(&shortcuts, SIGNAL(Stop()), this, SLOT(stop())); connect(&shortcuts, SIGNAL(Next()), skipAct, SLOT(trigger())); connect(&shortcuts, SIGNAL(Previous()), skipBackwardAct, SLOT(trigger())); - // connect(&shortcuts, SIGNAL(StopAfter()), The::globalActions()->value("stopafterthis"), SLOT(toggle())); + // connect(&shortcuts, SIGNAL(StopAfter()), getAction("stopafterthis"), SLOT(toggle())); connect(DownloadManager::instance(), SIGNAL(statusMessageChanged(QString)), SLOT(updateDownloadMessage(QString))); - connect(DownloadManager::instance(), SIGNAL(finished()), - SLOT(downloadsFinished())); + connect(DownloadManager::instance(), SIGNAL(finished()), SLOT(downloadsFinished())); setAcceptDrops(true); - mouseTimer = new QTimer(this); - mouseTimer->setInterval(5000); - mouseTimer->setSingleShot(true); - connect(mouseTimer, SIGNAL(timeout()), SLOT(hideMouse())); + fullscreenTimer = new QTimer(this); + fullscreenTimer->setInterval(3000); + fullscreenTimer->setSingleShot(true); + connect(fullscreenTimer, SIGNAL(timeout()), SLOT(hideFullscreenUI())); JsFunctions::instance(); - checkForUpdate(); + // Hack to give focus to searchlineedit + View *view = qobject_cast(views->currentWidget()); + if (view == homeView) { + QMetaObject::invokeMethod(views->currentWidget(), "appear"); + const QString &desc = view->getDescription(); + if (!desc.isEmpty()) showMessage(desc); + } ChannelAggregator::instance()->start(); + +#ifdef UPDATER + Updater::instance().checkWithoutUI(); +#endif + + initialized = true; } -void MainWindow::changeEvent(QEvent* event) { +void MainWindow::changeEvent(QEvent *e) { #ifdef APP_MAC - if (event->type() == QEvent::WindowStateChange) { - The::globalActions()->value("minimize")->setEnabled(!isMinimized()); + if (e->type() == QEvent::WindowStateChange) { + getAction("minimize")->setEnabled(!isMinimized()); } #endif - QMainWindow::changeEvent(event); + if (messageLabel->isVisible()) { + if (e->type() == QEvent::ActivationChange || e->type() == QEvent::WindowStateChange || + e->type() == QEvent::WindowDeactivate || e->type() == QEvent::ApplicationStateChange) { + hideMessage(); + } + } + QMainWindow::changeEvent(e); } -bool MainWindow::eventFilter(QObject *obj, QEvent *event) { +bool MainWindow::eventFilter(QObject *obj, QEvent *e) { + const QEvent::Type t = e->type(); - if (m_fullscreen && event->type() == QEvent::MouseMove) { +#ifndef APP_MAC + static bool altPressed = false; + if (t == QEvent::KeyRelease && altPressed) { + altPressed = false; + QKeyEvent *ke = static_cast(e); + if (ke->key() == Qt::Key_Alt) { + toggleMenuVisibility(); + return true; + } + } else if (t == QEvent::KeyPress) { + QKeyEvent *ke = static_cast(e); + altPressed = ke->key() == Qt::Key_Alt; + } +#endif - QMouseEvent *mouseEvent = static_cast (event); - const int x = mouseEvent->pos().x(); - const QString className = QString(obj->metaObject()->className()); - const bool isHoveringVideo = - (className == QLatin1String("QGLWidget")) || - (className == QLatin1String("VideoAreaWidget")); + if (fullScreenActive && views->currentWidget() == mediaView && t == QEvent::MouseMove && + obj->isWidgetType() && qobject_cast(obj)->window() == this) { + QMouseEvent *mouseEvent = static_cast(e); - // qDebug() << obj << mouseEvent->pos() << isHoveringVideo << mediaView->isPlaylistVisible(); + bool toolBarVisible = mainToolBar && mainToolBar->isVisible(); + bool sidebarVisible = mediaView->isSidebarVisible(); - if (mediaView->isPlaylistVisible()) { - if (isHoveringVideo && x > 5) mediaView->setPlaylistVisible(false); - } else { - if (isHoveringVideo && x >= 0 && x < 5) mediaView->setPlaylistVisible(true); + if (!sidebarVisible && !toolBarVisible) { + const int x = mouseEvent->pos().x(); + if (x >= 0 && x < 5) { +#ifndef APP_MAC + SidebarWidget *sidebar = mediaView->getSidebar(); + sidebar->resize(sidebar->width(), height()); +#endif + mediaView->setSidebarVisibility(true); + sidebarVisible = true; + } } #ifndef APP_MAC - const int y = mouseEvent->pos().y(); - if (mainToolBar->isVisible()) { - if (isHoveringVideo && y > 5) mainToolBar->setVisible(false); - } else { - if (isHoveringVideo && y >= 0 && y < 5) mainToolBar->setVisible(true); + if (!toolBarVisible && !sidebarVisible) { + const int y = mouseEvent->pos().y(); + if (y >= 0 && y < 5) { + mainToolBar->resize(width(), mainToolBar->sizeHint().height()); + mainToolBar->setVisible(true); + } } #endif // show the normal cursor unsetCursor(); // then hide it again after a few seconds - mouseTimer->start(); - + fullscreenTimer->start(); } - if (event->type() == QEvent::ToolTip) { + if (t == QEvent::ToolTip) { // kill tooltips return true; } + + if (t == QEvent::Show && obj == toolbarMenu) { +#ifdef APP_MAC + int x = width() - toolbarMenu->sizeHint().width(); + int y = views->y(); +#else + int x = toolbarMenuButton->x() + toolbarMenuButton->width() - + toolbarMenu->sizeHint().width(); + int y = toolbarMenuButton->y() + toolbarMenuButton->height(); +#endif + QPoint p(x, y); + toolbarMenu->move(mapToGlobal(p)); + } + + if (obj == this && t == QEvent::StyleChange) { + qDebug() << "Style change detected"; + qApp->paletteChanged(qApp->palette()); + return false; + } + // standard event processing - return QMainWindow::eventFilter(obj, event); + return QMainWindow::eventFilter(obj, e); } void MainWindow::createActions() { - - QHash *actions = The::globalActions(); - - stopAct = new QAction(IconUtils::icon("media-playback-stop"), tr("&Stop"), this); + stopAct = new QAction(tr("&Stop"), this); + IconUtils::setIcon(stopAct, "media-playback-stop"); stopAct->setStatusTip(tr("Stop playback and go back to the search view")); - stopAct->setShortcuts(QList() << QKeySequence(Qt::Key_Escape) << QKeySequence(Qt::Key_MediaStop)); + stopAct->setShortcuts(QList() + << QKeySequence(Qt::Key_Escape) << QKeySequence(Qt::Key_MediaStop)); stopAct->setEnabled(false); - actions->insert("stop", stopAct); + actionMap.insert("stop", stopAct); connect(stopAct, SIGNAL(triggered()), SLOT(stop())); - skipBackwardAct = new QAction( - IconUtils::icon("media-skip-backward"), - tr("P&revious"), this); + skipBackwardAct = new QAction(tr("P&revious"), this); skipBackwardAct->setStatusTip(tr("Go back to the previous track")); skipBackwardAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Left)); skipBackwardAct->setEnabled(false); - actions->insert("previous", skipBackwardAct); + actionMap.insert("previous", skipBackwardAct); connect(skipBackwardAct, SIGNAL(triggered()), mediaView, SLOT(skipBackward())); - skipAct = new QAction(IconUtils::icon("media-skip-forward"), tr("S&kip"), this); + skipAct = new QAction(tr("S&kip"), this); + IconUtils::setIcon(skipAct, "media-skip-forward"); skipAct->setStatusTip(tr("Skip to the next video")); - skipAct->setShortcuts(QList() << QKeySequence(Qt::CTRL + Qt::Key_Right) << QKeySequence(Qt::Key_MediaNext)); + skipAct->setShortcuts(QList() << QKeySequence(Qt::CTRL + Qt::Key_Right) + << QKeySequence(Qt::Key_MediaNext)); skipAct->setEnabled(false); - actions->insert("skip", skipAct); + actionMap.insert("skip", skipAct); connect(skipAct, SIGNAL(triggered()), mediaView, SLOT(skip())); - pauseAct = new QAction(IconUtils::icon("media-playback-start"), tr("&Play"), this); + pauseAct = new QAction(tr("&Play"), this); + IconUtils::setIcon(pauseAct, "media-playback-start"); pauseAct->setStatusTip(tr("Resume playback")); - pauseAct->setShortcuts(QList() << QKeySequence(Qt::Key_Space) << QKeySequence(Qt::Key_MediaPlay)); + pauseAct->setShortcuts(QList() + << QKeySequence(Qt::Key_Space) << QKeySequence(Qt::Key_MediaPlay)); pauseAct->setEnabled(false); - actions->insert("pause", pauseAct); + actionMap.insert("pause", pauseAct); connect(pauseAct, SIGNAL(triggered()), mediaView, SLOT(pause())); - fullscreenAct = new QAction(IconUtils::icon("view-fullscreen"), tr("&Full Screen"), this); + fullscreenAct = new QAction(tr("&Full Screen"), this); + IconUtils::setIcon(fullscreenAct, "view-fullscreen"); fullscreenAct->setStatusTip(tr("Go full screen")); QList fsShortcuts; #ifdef APP_MAC @@ -305,41 +388,38 @@ void MainWindow::createActions() { fullscreenAct->setShortcuts(fsShortcuts); fullscreenAct->setShortcutContext(Qt::ApplicationShortcut); fullscreenAct->setPriority(QAction::LowPriority); - actions->insert("fullscreen", fullscreenAct); - connect(fullscreenAct, SIGNAL(triggered()), this, SLOT(fullscreen())); + actionMap.insert("fullscreen", fullscreenAct); + connect(fullscreenAct, SIGNAL(triggered()), SLOT(toggleFullscreen())); compactViewAct = new QAction(tr("&Compact Mode"), this); compactViewAct->setStatusTip(tr("Hide the playlist and the toolbar")); -#ifdef APP_MAC - compactViewAct->setShortcut(QKeySequence(Qt::CTRL + Qt::META + Qt::Key_C)); -#else compactViewAct->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_C)); -#endif compactViewAct->setCheckable(true); compactViewAct->setChecked(false); compactViewAct->setEnabled(false); - actions->insert("compactView", compactViewAct); + actionMap.insert("compactView", compactViewAct); connect(compactViewAct, SIGNAL(toggled(bool)), this, SLOT(compactView(bool))); webPageAct = new QAction(tr("Open the &YouTube Page"), this); webPageAct->setStatusTip(tr("Go to the YouTube video page and pause playback")); webPageAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Y)); webPageAct->setEnabled(false); - actions->insert("webpage", webPageAct); + actionMap.insert("webpage", webPageAct); connect(webPageAct, SIGNAL(triggered()), mediaView, SLOT(openWebPage())); copyPageAct = new QAction(tr("Copy the YouTube &Link"), this); + IconUtils::setIcon(copyPageAct, "link"); copyPageAct->setStatusTip(tr("Copy the current video YouTube link to the clipboard")); copyPageAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_L)); copyPageAct->setEnabled(false); - actions->insert("pagelink", copyPageAct); + actionMap.insert("pagelink", copyPageAct); connect(copyPageAct, SIGNAL(triggered()), mediaView, SLOT(copyWebPage())); copyLinkAct = new QAction(tr("Copy the Video Stream &URL"), this); copyLinkAct->setStatusTip(tr("Copy the current video stream URL to the clipboard")); copyLinkAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_U)); copyLinkAct->setEnabled(false); - actions->insert("videolink", copyLinkAct); + actionMap.insert("videolink", copyLinkAct); connect(copyLinkAct, SIGNAL(triggered()), mediaView, SLOT(copyVideoLink())); findVideoPartsAct = new QAction(tr("Find Video &Parts"), this); @@ -347,27 +427,28 @@ void MainWindow::createActions() { findVideoPartsAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_P)); findVideoPartsAct->setEnabled(false); connect(findVideoPartsAct, SIGNAL(triggered()), mediaView, SLOT(findVideoParts())); - actions->insert("findVideoParts", findVideoPartsAct); + actionMap.insert("findVideoParts", findVideoPartsAct); removeAct = new QAction(tr("&Remove"), this); removeAct->setStatusTip(tr("Remove the selected videos from the playlist")); - removeAct->setShortcuts(QList() << QKeySequence("Del") << QKeySequence("Backspace")); + removeAct->setShortcuts(QList() + << QKeySequence("Del") << QKeySequence("Backspace")); removeAct->setEnabled(false); - actions->insert("remove", removeAct); + actionMap.insert("remove", removeAct); connect(removeAct, SIGNAL(triggered()), mediaView, SLOT(removeSelected())); moveUpAct = new QAction(tr("Move &Up"), this); moveUpAct->setStatusTip(tr("Move up the selected videos in the playlist")); moveUpAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Up)); moveUpAct->setEnabled(false); - actions->insert("moveUp", moveUpAct); + actionMap.insert("moveUp", moveUpAct); connect(moveUpAct, SIGNAL(triggered()), mediaView, SLOT(moveUpSelected())); moveDownAct = new QAction(tr("Move &Down"), this); moveDownAct->setStatusTip(tr("Move down the selected videos in the playlist")); moveDownAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Down)); moveDownAct->setEnabled(false); - actions->insert("moveDown", moveDownAct); + actionMap.insert("moveDown", moveDownAct); connect(moveDownAct, SIGNAL(triggered()), mediaView, SLOT(moveDownSelected())); clearAct = new QAction(tr("&Clear Recent Searches"), this); @@ -377,33 +458,34 @@ void MainWindow::createActions() { << QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Backspace)); clearAct->setStatusTip(tr("Clear the search history. Cannot be undone.")); clearAct->setEnabled(true); - actions->insert("clearRecentKeywords", clearAct); + actionMap.insert("clearRecentKeywords", clearAct); connect(clearAct, SIGNAL(triggered()), SLOT(clearRecentKeywords())); quitAct = new QAction(tr("&Quit"), this); quitAct->setMenuRole(QAction::QuitRole); quitAct->setShortcut(QKeySequence(QKeySequence::Quit)); quitAct->setStatusTip(tr("Bye")); - actions->insert("quit", quitAct); + actionMap.insert("quit", quitAct); connect(quitAct, SIGNAL(triggered()), SLOT(quit())); siteAct = new QAction(tr("&Website"), this); siteAct->setShortcut(QKeySequence::HelpContents); siteAct->setStatusTip(tr("%1 on the Web").arg(Constants::NAME)); - actions->insert("site", siteAct); + actionMap.insert("site", siteAct); connect(siteAct, SIGNAL(triggered()), this, SLOT(visitSite())); #if !defined(APP_MAC) && !defined(APP_WIN) donateAct = new QAction(tr("Make a &Donation"), this); - donateAct->setStatusTip(tr("Please support the continued development of %1").arg(Constants::NAME)); - actions->insert("donate", donateAct); + donateAct->setStatusTip( + tr("Please support the continued development of %1").arg(Constants::NAME)); + actionMap.insert("donate", donateAct); connect(donateAct, SIGNAL(triggered()), this, SLOT(donate())); #endif aboutAct = new QAction(tr("&About"), this); aboutAct->setMenuRole(QAction::AboutRole); aboutAct->setStatusTip(tr("Info about %1").arg(Constants::NAME)); - actions->insert("about", aboutAct); + actionMap.insert("about", aboutAct); connect(aboutAct, SIGNAL(triggered()), this, SLOT(about())); // Invisible actions @@ -411,82 +493,93 @@ void MainWindow::createActions() { searchFocusAct = new QAction(this); searchFocusAct->setShortcut(QKeySequence::Find); searchFocusAct->setStatusTip(tr("Search")); - actions->insert("search", searchFocusAct); + actionMap.insert("search", searchFocusAct); connect(searchFocusAct, SIGNAL(triggered()), this, SLOT(searchFocus())); addAction(searchFocusAct); volumeUpAct = new QAction(this); volumeUpAct->setShortcuts(QList() << QKeySequence(Qt::CTRL + Qt::Key_Plus)); - actions->insert("volume-up", volumeUpAct); + actionMap.insert("volumeUp", volumeUpAct); connect(volumeUpAct, SIGNAL(triggered()), this, SLOT(volumeUp())); addAction(volumeUpAct); volumeDownAct = new QAction(this); volumeDownAct->setShortcuts(QList() << QKeySequence(Qt::CTRL + Qt::Key_Minus)); - actions->insert("volume-down", volumeDownAct); + actionMap.insert("volumeDown", volumeDownAct); connect(volumeDownAct, SIGNAL(triggered()), this, SLOT(volumeDown())); addAction(volumeDownAct); volumeMuteAct = new QAction(this); - volumeMuteAct->setIcon(IconUtils::icon("audio-volume-high")); + IconUtils::setIcon(volumeMuteAct, "audio-volume-high"); volumeMuteAct->setStatusTip(tr("Mute volume")); - volumeMuteAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_K)); - actions->insert("volume-mute", volumeMuteAct); - connect(volumeMuteAct, SIGNAL(triggered()), SLOT(volumeMute())); + volumeMuteAct->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_M)); + actionMap.insert("volumeMute", volumeMuteAct); + connect(volumeMuteAct, SIGNAL(triggered()), SLOT(toggleVolumeMute())); addAction(volumeMuteAct); - QAction *definitionAct = new QAction(this); -#ifdef Q_OS_LINUX - definitionAct->setIcon(IconUtils::tintedIcon("video-display", QColor(0, 0, 0), - QList() << QSize(16, 16))); -#else - definitionAct->setIcon(IconUtils::icon("video-display")); -#endif - definitionAct->setShortcuts(QList() << QKeySequence(Qt::CTRL + Qt::Key_D)); - /* + QToolButton *definitionButton = new QToolButton(this); + definitionButton->setText(YT3::instance().maxVideoDefinition().getName()); + IconUtils::setIcon(definitionButton, "video-display"); + definitionButton->setIconSize(QSize(16, 16)); + definitionButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + definitionButton->setPopupMode(QToolButton::InstantPopup); QMenu *definitionMenu = new QMenu(this); - foreach (QString definition, VideoDefinition::getDefinitionNames()) { - definitionMenu->addAction(definition); + QActionGroup *group = new QActionGroup(this); + for (auto &defName : VideoDefinition::getDefinitionNames()) { + QAction *a = new QAction(defName); + a->setCheckable(true); + a->setActionGroup(group); + a->setChecked(defName == YT3::instance().maxVideoDefinition().getName()); + connect(a, &QAction::triggered, this, [this, defName, definitionButton] { + setDefinitionMode(defName); + definitionButton->setText(defName); + }); + connect(&YT3::instance(), &YT3::maxVideoDefinitionChanged, this, + [defName, definitionButton](const QString &name) { + if (defName == name) definitionButton->setChecked(true); + }); + definitionMenu->addAction(a); } - definitionAct->setMenu(definitionMenu); - */ - actions->insert("definition", definitionAct); - connect(definitionAct, SIGNAL(triggered()), SLOT(toggleDefinitionMode())); + definitionButton->setMenu(definitionMenu); + QWidgetAction *definitionAct = new QWidgetAction(this); + definitionAct->setDefaultWidget(definitionButton); + definitionAct->setShortcuts(QList() << QKeySequence(Qt::CTRL + Qt::Key_D)); + actionMap.insert("definition", definitionAct); addAction(definitionAct); QAction *action; - action = new QAction(IconUtils::icon("media-playback-start"), tr("&Manually Start Playing"), this); + action = new QAction(tr("&Manually Start Playing"), this); + IconUtils::setIcon(action, "media-playback-start"); action->setStatusTip(tr("Manually start playing videos")); action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_T)); action->setCheckable(true); connect(action, SIGNAL(toggled(bool)), SLOT(setManualPlay(bool))); - actions->insert("manualplay", action); + actionMap.insert("manualplay", action); action = new QAction(tr("&Downloads"), this); + IconUtils::setIcon(action, "document-save"); action->setStatusTip(tr("Show details about video downloads")); action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_J)); action->setCheckable(true); - action->setIcon(IconUtils::icon("document-save")); - action->setVisible(false); connect(action, SIGNAL(toggled(bool)), SLOT(toggleDownloads(bool))); - actions->insert("downloads", action); + actionMap.insert("downloads", action); action = new QAction(tr("&Download"), this); + IconUtils::setIcon(action, "document-save"); action->setStatusTip(tr("Download the current video")); action->setShortcut(QKeySequence::Save); - action->setIcon(IconUtils::icon("document-save")); action->setEnabled(false); action->setVisible(false); action->setPriority(QAction::LowPriority); connect(action, SIGNAL(triggered()), mediaView, SLOT(downloadVideo())); - actions->insert("download", action); + actionMap.insert("download", action); #ifdef APP_SNAPSHOT action = new QAction(tr("Take &Snapshot"), this); action->setShortcut(QKeySequence(Qt::Key_F9)); action->setEnabled(false); - actions->insert("snapshot", action); + actionMap.insert("snapshot", action); connect(action, SIGNAL(triggered()), mediaView, SLOT(snapshot())); #endif @@ -495,116 +588,141 @@ void MainWindow::createActions() { action->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_S)); action->setEnabled(false); connect(action, SIGNAL(triggered()), mediaView, SLOT(toggleSubscription())); - actions->insert("subscribe-channel", action); - mediaView->updateSubscriptionAction(0, false); + actionMap.insert("subscribeChannel", action); + mediaView->updateSubscriptionActionForVideo(0, false); QString shareTip = tr("Share the current video using %1"); action = new QAction("&Twitter", this); + IconUtils::setIcon(action, "twitter"); action->setStatusTip(shareTip.arg("Twitter")); action->setEnabled(false); - actions->insert("twitter", action); + actionMap.insert("twitter", action); connect(action, SIGNAL(triggered()), mediaView, SLOT(shareViaTwitter())); action = new QAction("&Facebook", this); + IconUtils::setIcon(action, "facebook"); action->setStatusTip(shareTip.arg("Facebook")); action->setEnabled(false); - actions->insert("facebook", action); + actionMap.insert("facebook", action); connect(action, SIGNAL(triggered()), mediaView, SLOT(shareViaFacebook())); - action = new QAction("&Buffer", this); - action->setStatusTip(shareTip.arg("Buffer")); - action->setEnabled(false); - actions->insert("buffer", action); - connect(action, SIGNAL(triggered()), mediaView, SLOT(shareViaBuffer())); - action = new QAction(tr("&Email"), this); + IconUtils::setIcon(action, "email"); action->setStatusTip(shareTip.arg(tr("Email"))); action->setEnabled(false); - actions->insert("email", action); + actionMap.insert("email", action); connect(action, SIGNAL(triggered()), mediaView, SLOT(shareViaEmail())); action = new QAction(tr("&Close"), this); action->setShortcut(QKeySequence(QKeySequence::Close)); - actions->insert("close", action); + actionMap.insert("close", action); connect(action, SIGNAL(triggered()), SLOT(close())); action = new QAction(Constants::NAME, this); action->setShortcut(QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_1)); - actions->insert("restore", action); + actionMap.insert("restore", action); connect(action, SIGNAL(triggered()), SLOT(restore())); - action = new QAction(IconUtils::icon("go-top"), tr("&Float on Top"), this); + action = new QAction(tr("&Float on Top"), this); + IconUtils::setIcon(action, "go-top"); action->setCheckable(true); - actions->insert("ontop", action); + actionMap.insert("ontop", action); connect(action, SIGNAL(toggled(bool)), SLOT(floatOnTop(bool))); - action = new QAction(IconUtils::icon("media-playback-stop"), tr("&Stop After This Video"), this); + action = new QAction(tr("&Stop After This Video"), this); + IconUtils::setIcon(action, "media-playback-stop"); action->setShortcut(QKeySequence(Qt::SHIFT + Qt::Key_Escape)); action->setCheckable(true); action->setEnabled(false); - actions->insert("stopafterthis", action); + actionMap.insert("stopafterthis", action); connect(action, SIGNAL(toggled(bool)), SLOT(showStopAfterThisInStatusBar(bool))); action = new QAction(tr("&Report an Issue..."), this); - actions->insert("report-issue", action); + actionMap.insert("reportIssue", action); connect(action, SIGNAL(triggered()), SLOT(reportIssue())); action = new QAction(tr("&Refine Search..."), this); action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_E)); action->setCheckable(true); action->setEnabled(false); - actions->insert("refine-search", action); + actionMap.insert("refineSearch", action); action = new QAction(YTRegions::worldwideRegion().name, this); - actions->insert("worldwide-region", action); + actionMap.insert("worldwideRegion", action); action = new QAction(YTRegions::localRegion().name, this); - actions->insert("local-region", action); + actionMap.insert("localRegion", action); action = new QAction(tr("More..."), this); - actions->insert("more-region", action); + actionMap.insert("moreRegion", action); - action = new QAction(IconUtils::icon("view-list"), tr("&Related Videos"), this); + action = new QAction(tr("&Related Videos"), this); + IconUtils::setIcon(action, "view-list"); action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_R)); action->setStatusTip(tr("Watch videos related to the current one")); action->setEnabled(false); action->setPriority(QAction::LowPriority); connect(action, SIGNAL(triggered()), mediaView, SLOT(relatedVideos())); - actions->insert("related-videos", action); + actionMap.insert("relatedVideos", action); action = new QAction(tr("Open in &Browser..."), this); action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_B)); action->setEnabled(false); - actions->insert("open-in-browser", action); + actionMap.insert("openInBrowser", action); connect(action, SIGNAL(triggered()), mediaView, SLOT(openInBrowser())); + action = new QAction(tr("Restricted Mode"), this); + IconUtils::setIcon(action, "safesearch"); + action->setStatusTip(tr("Hide videos that may contain inappropriate content")); + action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_K)); + action->setCheckable(true); + action->setVisible(VideoAPI::impl() != VideoAPI::IV); + actionMap.insert("safeSearch", action); + + action = new QAction(tr("Toggle &Menu Bar"), this); + connect(action, SIGNAL(triggered()), SLOT(toggleMenuVisibilityWithMessage())); + actionMap.insert("toggleMenu", action); + + action = new QAction(tr("Menu"), this); + IconUtils::setIcon(action, "open-menu"); + connect(action, SIGNAL(triggered()), SLOT(toggleToolbarMenu())); + actionMap.insert("toolbarMenu", action); + + action = new QAction(tr("Import Subscriptions..."), this); + action->setMenuRole(QAction::ApplicationSpecificRole); + connect(action, &QAction::triggered, this, [this] { + if (!subscriptionImportView) { + subscriptionImportView = new SubscriptionImportView(this); + views->addWidget(subscriptionImportView); + } + showView(subscriptionImportView); + }); + actionMap.insert("importSubscriptions", action); + #ifdef APP_MAC_STORE action = new QAction(tr("&Love %1? Rate it!").arg(Constants::NAME), this); - actions->insert("app-store", action); + actionMap.insert("appStore", action); connect(action, SIGNAL(triggered()), SLOT(rateOnAppStore())); #endif #ifdef APP_ACTIVATION - Extra::createActivationAction(tr("Buy %1...").arg(Constants::NAME)); + ActivationView::createActivationAction(tr("Buy %1...").arg(Constants::NAME)); #endif // common action properties - foreach (QAction *action, actions->values()) { + for (QAction *action : qAsConst(actionMap)) { // add actions to the MainWindow so that they work // when the menu is hidden addAction(action); - IconUtils::setupAction(action); + setupAction(action); } } void MainWindow::createMenus() { - - QHash *menus = The::globalMenus(); - fileMenu = menuBar()->addMenu(tr("&Application")); #ifdef APP_ACTIVATION - QAction *buyAction = The::globalActions()->value("buy"); + QAction *buyAction = getAction("buy"); if (buyAction) fileMenu->addAction(buyAction); #ifndef APP_MAC fileMenu->addSeparator(); @@ -616,99 +734,142 @@ void MainWindow::createMenus() { #endif fileMenu->addAction(quitAct); - QMenu* playbackMenu = menuBar()->addMenu(tr("&Playback")); - menus->insert("playback", playbackMenu); + QMenu *playbackMenu = menuBar()->addMenu(tr("&Playback")); + menuMap.insert("playback", playbackMenu); playbackMenu->addAction(pauseAct); playbackMenu->addAction(stopAct); - playbackMenu->addAction(The::globalActions()->value("stopafterthis")); + playbackMenu->addAction(getAction("stopafterthis")); playbackMenu->addSeparator(); playbackMenu->addAction(skipAct); playbackMenu->addAction(skipBackwardAct); playbackMenu->addSeparator(); - playbackMenu->addAction(The::globalActions()->value("manualplay")); + playbackMenu->addAction(getAction("manualplay")); #ifdef APP_MAC MacSupport::dockMenu(playbackMenu); #endif playlistMenu = menuBar()->addMenu(tr("&Playlist")); - menus->insert("playlist", playlistMenu); + menuMap.insert("playlist", playlistMenu); playlistMenu->addAction(removeAct); playlistMenu->addSeparator(); playlistMenu->addAction(moveUpAct); playlistMenu->addAction(moveDownAct); playlistMenu->addSeparator(); - playlistMenu->addAction(The::globalActions()->value("refine-search")); + playlistMenu->addAction(getAction("refineSearch")); - QMenu* videoMenu = menuBar()->addMenu(tr("&Video")); - menus->insert("video", videoMenu); - videoMenu->addAction(The::globalActions()->value("related-videos")); + QMenu *videoMenu = menuBar()->addMenu(tr("&Video")); + menuMap.insert("video", videoMenu); + videoMenu->addAction(getAction("relatedVideos")); videoMenu->addAction(findVideoPartsAct); videoMenu->addSeparator(); - videoMenu->addAction(The::globalActions()->value("subscribe-channel")); + videoMenu->addAction(getAction("subscribeChannel")); #ifdef APP_SNAPSHOT videoMenu->addSeparator(); - videoMenu->addAction(The::globalActions()->value("snapshot")); + videoMenu->addAction(getAction("snapshot")); #endif videoMenu->addSeparator(); videoMenu->addAction(webPageAct); videoMenu->addAction(copyLinkAct); - videoMenu->addAction(The::globalActions()->value("open-in-browser")); - videoMenu->addAction(The::globalActions()->value("download")); + videoMenu->addAction(getAction("openInBrowser")); + videoMenu->addAction(getAction("download")); - QMenu* viewMenu = menuBar()->addMenu(tr("&View")); - menus->insert("view", viewMenu); - viewMenu->addAction(fullscreenAct); - viewMenu->addAction(compactViewAct); - viewMenu->addSeparator(); - viewMenu->addAction(The::globalActions()->value("ontop")); - - QMenu* shareMenu = menuBar()->addMenu(tr("&Share")); - menus->insert("share", shareMenu); + QMenu *shareMenu = menuBar()->addMenu(tr("&Share")); + menuMap.insert("share", shareMenu); shareMenu->addAction(copyPageAct); shareMenu->addSeparator(); - shareMenu->addAction(The::globalActions()->value("twitter")); - shareMenu->addAction(The::globalActions()->value("facebook")); - shareMenu->addAction(The::globalActions()->value("buffer")); + shareMenu->addAction(getAction("twitter")); + shareMenu->addAction(getAction("facebook")); shareMenu->addSeparator(); - shareMenu->addAction(The::globalActions()->value("email")); + shareMenu->addAction(getAction("email")); + + QMenu *viewMenu = menuBar()->addMenu(tr("&View")); + menuMap.insert("view", viewMenu); + viewMenu->addAction(getAction("ontop")); + viewMenu->addAction(compactViewAct); + viewMenu->addSeparator(); + viewMenu->addAction(fullscreenAct); +#ifndef APP_MAC + viewMenu->addSeparator(); + viewMenu->addAction(getAction("toggleMenu")); +#endif #ifdef APP_MAC MacSupport::windowMenu(this); #endif helpMenu = menuBar()->addMenu(tr("&Help")); + menuMap.insert("help", helpMenu); helpMenu->addAction(siteAct); #if !defined(APP_MAC) && !defined(APP_WIN) helpMenu->addAction(donateAct); #endif - helpMenu->addAction(The::globalActions()->value("report-issue")); + helpMenu->addAction(getAction("reportIssue")); helpMenu->addAction(aboutAct); +#ifdef UPDATER + helpMenu->addAction(Updater::instance().getAction()); +#endif #ifdef APP_MAC_STORE helpMenu->addSeparator(); - helpMenu->addAction(The::globalActions()->value("app-store")); + helpMenu->addAction(getAction("appStore")); #endif } -void MainWindow::createToolBars() { +void MainWindow::createToolBar() { + // Create widgets + currentTimeLabel = new QLabel("00:00", this); + + seekSlider = new SeekSlider(this); + seekSlider->setEnabled(false); + seekSlider->setTracking(false); + seekSlider->setMaximum(1000); + volumeSlider = new SeekSlider(this); + volumeSlider->setValue(volumeSlider->maximum()); + +#if defined(APP_MAC_SEARCHFIELD) && !defined(APP_MAC_QMACTOOLBAR) + SearchWrapper *searchWrapper = new SearchWrapper(this); + toolbarSearch = searchWrapper->getSearchLineEdit(); +#else + toolbarSearch = new SearchLineEdit(this); +#endif + toolbarSearch->setMinimumWidth(toolbarSearch->fontInfo().pixelSize() * 15); + toolbarSearch->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + toolbarSearch->setSuggester(new YTSuggester(this)); + connect(toolbarSearch, SIGNAL(search(const QString &)), SLOT(search(const QString &))); + connect(toolbarSearch, SIGNAL(suggestionAccepted(Suggestion *)), + SLOT(suggestionAccepted(Suggestion *))); + toolbarSearch->setStatusTip(searchFocusAct->statusTip()); + + // Add widgets to toolbar - setUnifiedTitleAndToolBarOnMac(true); +#ifdef APP_MAC_QMACTOOLBAR + currentTimeLabel->hide(); + toolbarSearch->hide(); + volumeSlider->hide(); + seekSlider->hide(); + MacToolbar::instance().createToolbar(this); + return; +#endif mainToolBar = new QToolBar(this); mainToolBar->setToolButtonStyle(Qt::ToolButtonIconOnly); mainToolBar->setFloatable(false); mainToolBar->setMovable(false); - -#if defined(APP_MAC) | defined(APP_WIN) +#ifndef APP_LINUX mainToolBar->setIconSize(QSize(32, 32)); #endif - mainToolBar->addAction(stopAct); + QToolButton *stopToolButton = + qobject_cast(mainToolBar->widgetForAction(stopAct)); + if (stopToolButton) { + QMenu *stopMenu = new QMenu(this); + stopMenu->addAction(getAction("stopafterthis")); + stopToolButton->setMenu(stopMenu); + stopToolButton->setPopupMode(QToolButton::DelayedPopup); + } mainToolBar->addAction(pauseAct); mainToolBar->addAction(skipAct); - - mainToolBar->addAction(The::globalActions()->value("related-videos")); - mainToolBar->addAction(The::globalActions()->value("download")); + mainToolBar->addAction(getAction("relatedVideos")); bool addFullScreenAct = true; #ifdef Q_OS_MAC @@ -718,229 +879,246 @@ void MainWindow::createToolBars() { mainToolBar->addWidget(new Spacer()); - QFont smallerFont = FontUtils::small(); - currentTime = new QLabel(mainToolBar); - currentTime->setFont(smallerFont); - mainToolBar->addWidget(currentTime); + currentTimeLabel->setFont(FontUtils::small()); + currentTimeLabel->setMinimumWidth(currentTimeLabel->fontInfo().pixelSize() * 4); + currentTimeLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter); + mainToolBar->addWidget(currentTimeLabel); - mainToolBar->addWidget(new Spacer()); +#ifdef APP_WIN + mainToolBar->addWidget(new Spacer(nullptr, 10)); +#endif -#ifdef APP_PHONON_SEEK - seekSlider = new Phonon::SeekSlider(this); - seekSlider->setTracking(true); - seekSlider->setIconVisible(false); - seekSlider->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); + seekSlider->setOrientation(Qt::Horizontal); + seekSlider->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); + seekSlider->setFocusPolicy(Qt::NoFocus); mainToolBar->addWidget(seekSlider); -#else - slider = new SeekSlider(this); - slider->setEnabled(false); - slider->setTracking(false); - slider->setMaximum(1000); - slider->setOrientation(Qt::Horizontal); - slider->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); - mainToolBar->addWidget(slider); -#endif - /* mainToolBar->addWidget(new Spacer()); - totalTime = new QLabel(mainToolBar); - totalTime->setFont(smallerFont); - mainToolBar->addWidget(totalTime); - */ - mainToolBar->addWidget(new Spacer()); mainToolBar->addAction(volumeMuteAct); - -#ifdef APP_PHONON - volumeSlider = new Phonon::VolumeSlider(this); - volumeSlider->setMuteVisible(false); - // qDebug() << volumeSlider->children(); - // status tip for the volume slider - QSlider* volumeQSlider = volumeSlider->findChild(); - if (volumeQSlider) - volumeQSlider->setStatusTip(tr("Press %1 to raise the volume, %2 to lower it").arg( - volumeUpAct->shortcut().toString(QKeySequence::NativeText), volumeDownAct->shortcut().toString(QKeySequence::NativeText))); +#ifndef APP_MAC_QMACTOOLBAR + QToolButton *volumeMuteButton = + qobject_cast(mainToolBar->widgetForAction(volumeMuteAct)); + volumeMuteButton->setIconSize(QSize(16, 16)); + auto fixVolumeMuteIconSize = [volumeMuteButton] { + volumeMuteButton->setIcon(volumeMuteButton->icon().pixmap(16)); + }; + fixVolumeMuteIconSize(); + volumeMuteButton->connect(volumeMuteAct, &QAction::changed, volumeMuteButton, + fixVolumeMuteIconSize); +#endif + + volumeSlider->setStatusTip( + tr("Press %1 to raise the volume, %2 to lower it") + .arg(volumeUpAct->shortcut().toString(QKeySequence::NativeText), + volumeDownAct->shortcut().toString(QKeySequence::NativeText))); + + volumeSlider->setOrientation(Qt::Horizontal); // this makes the volume slider smaller volumeSlider->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + volumeSlider->setFocusPolicy(Qt::NoFocus); mainToolBar->addWidget(volumeSlider); -#endif mainToolBar->addWidget(new Spacer()); -#ifdef APP_MAC - SearchWrapper* searchWrapper = new SearchWrapper(this); - toolbarSearch = searchWrapper->getSearchLineEdit(); -#else - toolbarSearch = new SearchLineEdit(this); -#endif - toolbarSearch->setMinimumWidth(toolbarSearch->fontInfo().pixelSize()*15); - toolbarSearch->setSuggester(new YTSuggester(this)); - connect(toolbarSearch, SIGNAL(search(const QString&)), SLOT(search(const QString&))); - connect(toolbarSearch, SIGNAL(suggestionAccepted(Suggestion*)), SLOT(suggestionAccepted(Suggestion*))); - toolbarSearch->setStatusTip(searchFocusAct->statusTip()); -#ifdef APP_MAC +#if defined(APP_MAC_SEARCHFIELD) && !defined(APP_MAC_QMACTOOLBAR) mainToolBar->addWidget(searchWrapper); #else mainToolBar->addWidget(toolbarSearch); - mainToolBar->addWidget(new Spacer()); + mainToolBar->addWidget(new Spacer(this, toolbarSearch->height() / 2)); + + QAction *toolbarMenuAction = getAction("toolbarMenu"); + mainToolBar->addAction(toolbarMenuAction); + toolbarMenuButton = + qobject_cast(mainToolBar->widgetForAction(toolbarMenuAction)); #endif addToolBar(mainToolBar); } void MainWindow::createStatusBar() { - statusToolBar = new QToolBar(this); + statusToolBar = new QToolBar(statusBar()); statusToolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); statusToolBar->setIconSize(QSize(16, 16)); - statusToolBar->addAction(The::globalActions()->value("downloads")); - regionButton = new QToolButton(this); - regionButton->setStatusTip(tr("Choose your content location")); - regionButton->setIconSize(QSize(16, 16)); - regionButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - regionAction = statusToolBar->addWidget(regionButton); - regionAction->setVisible(false); + regionAction = new QAction(this); + regionAction->setStatusTip(tr("Choose your content location")); - QAction *localAction = The::globalActions()->value("local-region"); + QAction *localAction = getAction("localRegion"); if (!localAction->text().isEmpty()) { - regionButton->setPopupMode(QToolButton::InstantPopup); QMenu *regionMenu = new QMenu(this); - regionMenu->addAction(The::globalActions()->value("worldwide-region")); + regionMenu->addAction(getAction("worldwideRegion")); regionMenu->addAction(localAction); regionMenu->addSeparator(); - QAction *moreRegionsAction = The::globalActions()->value("more-region"); + QAction *moreRegionsAction = getAction("moreRegion"); regionMenu->addAction(moreRegionsAction); connect(moreRegionsAction, SIGNAL(triggered()), SLOT(showRegionsView())); - regionButton->setMenu(regionMenu); - } else { - connect(regionButton, SIGNAL(clicked()), SLOT(showRegionsView())); + regionAction->setMenu(regionMenu); } + connect(regionAction, SIGNAL(triggered()), SLOT(showRegionsView())); /* Stupid code that generates the QRC items foreach(YTRegion r, YTRegions::list()) qDebug() << QString("flags/%1.png").arg(r.id.toLower()); */ - statusToolBar->addAction(The::globalActions()->value("definition")); - statusBar()->addPermanentWidget(statusToolBar); - statusBar()->show(); + statusBar()->hide(); } void MainWindow::showStopAfterThisInStatusBar(bool show) { - QAction* action = The::globalActions()->value("stopafterthis"); - showActionInStatusBar(action, show); + QAction *action = getAction("stopafterthis"); + showActionsInStatusBar({action}, show); } -void MainWindow::showActionInStatusBar(QAction* action, bool show) { +void MainWindow::showActionsInStatusBar(const QVector &actions, bool show) { #ifdef APP_EXTRA Extra::fadeInWidget(statusBar(), statusBar()); #endif + for (auto action : actions) { + if (show) { + if (statusToolBar->actions().contains(action)) continue; + if (statusToolBar->actions().isEmpty()) { + statusToolBar->addAction(action); + } else { + statusToolBar->insertAction(statusToolBar->actions().at(0), action); + } + } else { + statusToolBar->removeAction(action); + } + } + if (show) { - statusToolBar->insertAction(statusToolBar->actions().first(), action); + if (statusBar()->isHidden() && !fullScreenActive) setStatusBarVisibility(true); } else { - statusToolBar->removeAction(action); + if (statusBar()->isVisible() && !needStatusBar()) setStatusBarVisibility(false); } } -void MainWindow::readSettings() { - QSettings settings; - if (settings.contains("geometry")) { - restoreGeometry(settings.value("geometry").toByteArray()); +void MainWindow::setStatusBarVisibility(bool show) { + if (statusBar()->isVisible() != show) { + statusBar()->setVisible(show); + if (views->currentWidget() == mediaView) + QTimer::singleShot(0, mediaView, SLOT(adjustWindowSize())); + } +} + +void MainWindow::adjustStatusBarVisibility() { + setStatusBarVisibility(needStatusBar()); +} + +void MainWindow::hideToolbar() { +#ifdef APP_MAC + mac::showToolBar(winId(), false); +#else + mainToolBar->hide(); +#endif +} + +void MainWindow::showToolbar() { #ifdef APP_MAC - MacSupport::fixGeometry(this); + mac::showToolBar(winId(), true); +#else + mainToolBar->show(); #endif +} + +void MainWindow::readSettings() { + QSettings settings; + QByteArray geometrySettings = settings.value("geometry").toByteArray(); + if (!geometrySettings.isEmpty()) { + restoreGeometry(geometrySettings); } else { - setGeometry(100, 100, 1000, 500); + const QRect desktopSize = QGuiApplication::primaryScreen()->availableGeometry(); + int w = desktopSize.width() * .9; + int h = qMin(w / 2, desktopSize.height()); + setGeometry( + QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter, QSize(w, h), desktopSize)); } - setDefinitionMode(settings.value("definition", VideoDefinition::getDefinitionNames().first()).toString()); - The::globalActions()->value("manualplay")->setChecked(settings.value("manualplay", false).toBool()); + setDefinitionMode(settings.value("definition", YT3::instance().maxVideoDefinition().getName()) + .toString()); + getAction("manualplay")->setChecked(settings.value("manualplay", false).toBool()); + getAction("safeSearch")->setChecked(settings.value("safeSearch", false).toBool()); +#ifndef APP_MAC + menuBar()->setVisible(settings.value("menuBar", false).toBool()); +#endif } void MainWindow::writeSettings() { QSettings settings; - settings.setValue("geometry", saveGeometry()); - mediaView->saveSplitterState(); + if (!isReallyFullScreen()) { + settings.setValue("geometry", saveGeometry()); + if (mediaView) mediaView->saveSplitterState(); + } -#ifdef APP_PHONON - if (audioOutput->volume() > 0.1) - settings.setValue("volume", audioOutput->volume()); - // settings.setValue("volumeMute", audioOutput->isMuted()); + settings.setValue("manualplay", getAction("manualplay")->isChecked()); + settings.setValue("safeSearch", getAction("safeSearch")->isChecked()); +#ifndef APP_MAC + settings.setValue("menuBar", menuBar()->isVisible()); #endif - - settings.setValue("manualplay", The::globalActions()->value("manualplay")->isChecked()); } void MainWindow::goBack() { - if ( history->size() > 1 ) { - history->pop(); - QWidget *widget = history->pop(); - showWidget(widget); + if (history.size() > 1) { + history.pop(); + showView(history.pop()); } } -void MainWindow::showWidget(QWidget* widget, bool transition) { +void MainWindow::showView(View *view, bool transition) { + if (!history.isEmpty() && view == history.top()) { + qDebug() << "Attempting to show same view" << view; + return; + } - if (compactViewAct->isChecked()) - compactViewAct->toggle(); +#ifdef APP_MAC + if (transition && !history.isEmpty()) CompositeFader::go(this, this->grab()); +#endif - setUpdatesEnabled(false); + if (compactViewAct->isChecked()) compactViewAct->toggle(); // call hide method on the current view - View* oldView = dynamic_cast (views->currentWidget()); + View *oldView = qobject_cast(views->currentWidget()); if (oldView) { + oldView->willDisappear(); oldView->disappear(); - views->currentWidget()->setEnabled(false); - } else qDebug() << "Cannot cast view"; - - // call show method on the new view - View* newView = dynamic_cast (widget); - if (newView) { - widget->setEnabled(true); - QHash metadata = newView->metadata(); - QString title = metadata.value("title").toString(); - if (title.isEmpty()) title = Constants::NAME; - else title += QLatin1String(" - ") + Constants::NAME; - setWindowTitle(title); - QString desc = metadata.value("description").toString(); - if (!desc.isEmpty()) showMessage(desc); - newView->appear(); - - // dynamic view actions - foreach (QAction* action, viewActions) - showActionInStatusBar(action, false); - viewActions = newView->getViewActions(); - foreach (QAction* action, viewActions) - showActionInStatusBar(action, true); - - } - - const bool isMediaView = widget == mediaView; + oldView->setEnabled(false); + oldView->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); + } else + qDebug() << "Cannot cast old view"; + + view->willAppear(); + view->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + view->setEnabled(true); + views->setCurrentWidget(view); + view->appear(); + view->didAppear(); + if (oldView) oldView->didDisappear(); + + QString title = view->getTitle(); + if (title.isEmpty()) + title = Constants::NAME; + else + title += QLatin1String(" - ") + Constants::NAME; + setWindowTitle(title); + const bool isMediaView = view == mediaView; stopAct->setEnabled(isMediaView); compactViewAct->setEnabled(isMediaView); - toolbarSearch->setEnabled(widget == homeView || isMediaView || widget == downloadView); - - aboutAct->setEnabled(widget != aboutView); - The::globalActions()->value("downloads")->setChecked(widget == downloadView); - - QWidget *oldWidget = views->currentWidget(); - if (oldWidget) - oldWidget->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); - - views->setCurrentWidget(widget); - widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - - setUpdatesEnabled(true); - -#ifdef APP_EXTRA - // if (transition && (oldWidget != mediaView || !mediaView->getVideoArea()->isVideoShown())) - if (transition) - Extra::fadeInWidget(oldWidget, widget); -#endif + toolbarSearch->setEnabled(isMediaView); + aboutAct->setEnabled(view != aboutView); + getAction("downloads")->setChecked(view == downloadView); + + // dynamic view actions + /* Not currently used by any view + showActionsInStatusBar(viewActions, false); + viewActions = newView->getViewActions(); + showActionsInStatusBar(viewActions, true); + */ - history->push(widget); + history.push(view); + emit viewChanged(); } void MainWindow::about() { @@ -948,23 +1126,23 @@ void MainWindow::about() { aboutView = new AboutView(this); views->addWidget(aboutView); } - showWidget(aboutView); + showView(aboutView); } void MainWindow::visitSite() { QUrl url(Constants::WEBSITE); - statusBar()->showMessage(QString(tr("Opening %1").arg(url.toString()))); + showMessage(QString(tr("Opening %1").arg(url.toString()))); QDesktopServices::openUrl(url); } void MainWindow::donate() { - QUrl url(QString(Constants::WEBSITE) + "#donate"); - statusBar()->showMessage(QString(tr("Opening %1").arg(url.toString()))); + QUrl url("https://" + QLatin1String(Constants::ORG_DOMAIN) + "/donate"); + showMessage(QString(tr("Opening %1").arg(url.toString()))); QDesktopServices::openUrl(url); } void MainWindow::reportIssue() { - QUrl url("http://flavio.tordini.org/forums/forum/minitube-forums/minitube-troubleshooting"); + QUrl url("https://flavio.tordini.org/forums/forum/minitube-forums/minitube-troubleshooting"); QDesktopServices::openUrl(url); } @@ -975,10 +1153,13 @@ void MainWindow::quit() { } #endif // do not save geometry when in full screen or in compact mode - if (!m_fullscreen && !compactViewAct->isChecked()) { + if (!fullScreenActive && !compactViewAct->isChecked()) { +#ifdef APP_MAC + hideToolbar(); +#endif writeSettings(); } - mediaView->stop(); + // mediaView->stop(); Temporary::deleteAll(); ChannelAggregator::instance()->stop(); ChannelAggregator::instance()->cleanup(); @@ -986,32 +1167,43 @@ void MainWindow::quit() { qApp->quit(); } -void MainWindow::closeEvent(QCloseEvent *event) { +void MainWindow::closeEvent(QCloseEvent *e) { #ifdef APP_MAC mac::closeWindow(winId()); - event->ignore(); + e->ignore(); #else if (!confirmQuit()) { - event->ignore(); + e->ignore(); return; } - QWidget::closeEvent(event); + QWidget::closeEvent(e); quit(); +#endif + messageLabel->hide(); +} + +void MainWindow::showEvent(QShowEvent *e) { + QWidget::showEvent(e); +#ifdef APP_MAC + restore(); #endif } bool MainWindow::confirmQuit() { if (DownloadManager::instance()->activeItems() > 0) { QMessageBox msgBox(this); - msgBox.setIconPixmap(QPixmap(":/images/app.png").scaled(64, 64, Qt::KeepAspectRatio, Qt::SmoothTransformation)); - msgBox.setText(tr("Do you want to exit %1 with a download in progress?").arg(Constants::NAME)); - msgBox.setInformativeText(tr("If you close %1 now, this download will be cancelled.").arg(Constants::NAME)); + msgBox.setIconPixmap(IconUtils::pixmap(":/images/64x64/app.png", devicePixelRatioF())); + msgBox.setText( + tr("Do you want to exit %1 with a download in progress?").arg(Constants::NAME)); + msgBox.setInformativeText( + tr("If you close %1 now, this download will be cancelled.").arg(Constants::NAME)); msgBox.setModal(true); // make it a "sheet" on the Mac msgBox.setWindowModality(Qt::WindowModal); msgBox.addButton(tr("Close and cancel download"), QMessageBox::RejectRole); - QPushButton *waitButton = msgBox.addButton(tr("Wait for download to finish"), QMessageBox::ActionRole); + QPushButton *waitButton = + msgBox.addButton(tr("Wait for download to finish"), QMessageBox::ActionRole); msgBox.exec(); @@ -1022,202 +1214,230 @@ bool MainWindow::confirmQuit() { return true; } -void MainWindow::showHome(bool transition) { - showWidget(homeView, transition); - currentTime->clear(); - // totalTime->clear(); +void MainWindow::showHome() { + showView(homeView); + currentTimeLabel->clear(); + seekSlider->setValue(0); } void MainWindow::showMedia(SearchParams *searchParams) { - showWidget(mediaView); + showView(mediaView); + if (getAction("safeSearch")->isChecked()) + searchParams->setSafeSearch(SearchParams::Strict); + else + searchParams->setSafeSearch(SearchParams::None); mediaView->search(searchParams); } void MainWindow::showMedia(VideoSource *videoSource) { - showWidget(mediaView); + showView(mediaView); mediaView->setVideoSource(videoSource); } -#ifdef APP_PHONON -void MainWindow::stateChanged(Phonon::State newState, Phonon::State /* oldState */) { +void MainWindow::stateChanged(Media::State newState) { + qDebug() << newState; - // qDebug() << "Phonon state: " << newState; + seekSlider->setEnabled(newState != Media::StoppedState); switch (newState) { - - case Phonon::ErrorState: - if (mediaObject->errorType() == Phonon::FatalError) { - // Do not display because we try to play incomplete video files and sometimes trigger this - // We retry automatically (in MediaView) so no need to show it - // statusBar()->showMessage(tr("Fatal error: %1").arg(mediaObject->errorString())); - } else { - statusBar()->showMessage(tr("Error: %1").arg(mediaObject->errorString())); - } + case Media::ErrorState: + showMessage(tr("Error: %1").arg(media->errorString())); break; - case Phonon::PlayingState: + case Media::PlayingState: pauseAct->setEnabled(true); pauseAct->setIcon(IconUtils::icon("media-playback-pause")); pauseAct->setText(tr("&Pause")); - pauseAct->setStatusTip(tr("Pause playback") + " (" + pauseAct->shortcut().toString(QKeySequence::NativeText) + ")"); - // stopAct->setEnabled(true); + pauseAct->setStatusTip(tr("Pause playback") + " (" + + pauseAct->shortcut().toString(QKeySequence::NativeText) + ")"); break; - case Phonon::StoppedState: + case Media::StoppedState: pauseAct->setEnabled(false); pauseAct->setIcon(IconUtils::icon("media-playback-start")); pauseAct->setText(tr("&Play")); - pauseAct->setStatusTip(tr("Resume playback") + " (" + pauseAct->shortcut().toString(QKeySequence::NativeText) + ")"); - // stopAct->setEnabled(false); + pauseAct->setStatusTip(tr("Resume playback") + " (" + + pauseAct->shortcut().toString(QKeySequence::NativeText) + ")"); break; - case Phonon::PausedState: + case Media::PausedState: pauseAct->setEnabled(true); pauseAct->setIcon(IconUtils::icon("media-playback-start")); pauseAct->setText(tr("&Play")); - pauseAct->setStatusTip(tr("Resume playback") + " (" + pauseAct->shortcut().toString(QKeySequence::NativeText) + ")"); - // stopAct->setEnabled(true); + pauseAct->setStatusTip(tr("Resume playback") + " (" + + pauseAct->shortcut().toString(QKeySequence::NativeText) + ")"); break; - case Phonon::BufferingState: + case Media::BufferingState: pauseAct->setEnabled(false); pauseAct->setIcon(IconUtils::icon("content-loading")); pauseAct->setText(tr("&Loading...")); pauseAct->setStatusTip(QString()); break; - case Phonon::LoadingState: + case Media::LoadingState: pauseAct->setEnabled(false); - currentTime->clear(); - // totalTime->clear(); - // stopAct->setEnabled(true); + currentTimeLabel->clear(); break; - default: - ; + default:; } } -#endif void MainWindow::stop() { showHome(); mediaView->stop(); } -void MainWindow::resizeEvent(QResizeEvent*) { -#ifdef Q_OS_MAC - if (mac::CanGoFullScreen(winId())) { +void MainWindow::resizeEvent(QResizeEvent *e) { + Q_UNUSED(e); +#ifdef APP_MAC + if (initialized && mac::CanGoFullScreen(winId())) { bool isFullscreen = mac::IsFullScreen(winId()); - if (isFullscreen != m_fullscreen) { + if (isFullscreen != fullScreenActive) { if (compactViewAct->isChecked()) { compactViewAct->setChecked(false); compactView(false); } - m_fullscreen = isFullscreen; + fullScreenActive = isFullscreen; updateUIForFullscreen(); } } #endif +#ifdef APP_MAC_QMACTOOLBAR + int moreButtonWidth = 40; + toolbarSearch->move(width() - toolbarSearch->width() - moreButtonWidth - 7, -34); +#endif + hideMessage(); } -void MainWindow::fullscreen() { +void MainWindow::enterEvent(QEvent *e) { + Q_UNUSED(e); +#ifdef APP_MAC + // Workaround cursor bug on macOS + unsetCursor(); +#endif +} - if (compactViewAct->isChecked()) - compactViewAct->toggle(); +void MainWindow::leaveEvent(QEvent *e) { + Q_UNUSED(e); + if (fullScreenActive) hideFullscreenUI(); +} -#ifdef Q_OS_MAC +void MainWindow::toggleFullscreen() { + if (compactViewAct->isChecked()) compactViewAct->toggle(); + +#ifdef APP_MAC WId handle = winId(); if (mac::CanGoFullScreen(handle)) { - mainToolBar->setVisible(true); + if (mainToolBar) mainToolBar->setVisible(true); mac::ToggleFullScreen(handle); return; } #endif - m_fullscreen = !m_fullscreen; + fullScreenActive = !fullScreenActive; - if (m_fullscreen) { + if (fullScreenActive) { // Enter full screen - m_maximized = isMaximized(); + maximizedBeforeFullScreen = isMaximized(); // save geometry now, if the user quits when in full screen // geometry won't be saved writeSettings(); -#ifdef Q_OS_MAC +#ifdef APP_MAC MacSupport::enterFullScreen(this, views); #else - mainToolBar->hide(); + menuVisibleBeforeFullScreen = menuBar()->isVisible(); + menuBar()->hide(); + if (mainToolBar) mainToolBar->hide(); showFullScreen(); #endif } else { // Exit full screen -#ifdef Q_OS_MAC +#ifdef APP_MAC MacSupport::exitFullScreen(this, views); #else - mainToolBar->show(); - if (m_maximized) showMaximized(); - else showNormal(); + menuBar()->setVisible(menuVisibleBeforeFullScreen); + if (mainToolBar) mainToolBar->setVisible(views->currentWidget() == mediaView); + if (maximizedBeforeFullScreen) + showMaximized(); + else + showNormal(); #endif // Make sure the window has focus activateWindow(); - } + qApp->processEvents(); updateUIForFullscreen(); - } void MainWindow::updateUIForFullscreen() { static QList fsShortcuts; static QString fsText; - if (m_fullscreen) { + if (fullScreenActive) { fsShortcuts = fullscreenAct->shortcuts(); fsText = fullscreenAct->text(); + if (fsText.isEmpty()) qDebug() << "[taking Empty!]"; fullscreenAct->setShortcuts(QList(fsShortcuts) << QKeySequence(Qt::Key_Escape)); fullscreenAct->setText(tr("Leave &Full Screen")); fullscreenAct->setIcon(IconUtils::icon("view-restore")); + setStatusBarVisibility(false); + + if (mainToolBar) { + removeToolBar(mainToolBar); + mainToolBar->move(0, 0); + } + + mediaView->removeSidebar(); + } else { fullscreenAct->setShortcuts(fsShortcuts); + if (fsText.isEmpty()) fsText = "[Empty!]"; fullscreenAct->setText(fsText); fullscreenAct->setIcon(IconUtils::icon("view-fullscreen")); + + if (needStatusBar()) setStatusBarVisibility(true); + + if (mainToolBar) { + addToolBar(mainToolBar); + } + + mediaView->restoreSidebar(); } // No compact view action when in full screen - compactViewAct->setVisible(!m_fullscreen); + compactViewAct->setVisible(!fullScreenActive); compactViewAct->setChecked(false); // Hide anything but the video - mediaView->setPlaylistVisible(!m_fullscreen); - statusBar()->setVisible(!m_fullscreen); + mediaView->setSidebarVisibility(!fullScreenActive); -#ifndef APP_MAC - menuBar()->setVisible(!m_fullscreen); -#endif - - if (m_fullscreen) { + if (fullScreenActive) { stopAct->setShortcuts(QList() << QKeySequence(Qt::Key_MediaStop)); } else { - stopAct->setShortcuts(QList() << QKeySequence(Qt::Key_Escape) << QKeySequence(Qt::Key_MediaStop)); + stopAct->setShortcuts(QList() + << QKeySequence(Qt::Key_Escape) << QKeySequence(Qt::Key_MediaStop)); } #ifdef Q_OS_MAC - MacSupport::fullScreenActions(The::globalActions()->values(), m_fullscreen); + MacSupport::fullScreenActions(actionMap, fullScreenActive); #endif - if (views->currentWidget() == mediaView) - mediaView->setFocus(); + if (views->currentWidget() == mediaView) mediaView->setFocus(); - if (m_fullscreen) { - hideMouse(); + if (fullScreenActive) { + if (views->currentWidget() == mediaView) hideFullscreenUI(); } else { - mouseTimer->stop(); + fullscreenTimer->stop(); unsetCursor(); } } @@ -1225,26 +1445,65 @@ void MainWindow::updateUIForFullscreen() { bool MainWindow::isReallyFullScreen() { #ifdef Q_OS_MAC WId handle = winId(); - if (mac::CanGoFullScreen(handle)) return mac::IsFullScreen(handle); - else return isFullScreen(); + if (mac::CanGoFullScreen(handle)) + return mac::IsFullScreen(handle); + else + return isFullScreen(); #else return isFullScreen(); #endif } +void MainWindow::missingKeyWarning() { + static bool shown = false; + if (shown) return; + shown = true; + QMessageBox msgBox(this); + msgBox.setIconPixmap(IconUtils::pixmap(":/images/64x64/app.png", devicePixelRatioF())); + msgBox.setText(QString("%1 was built without a Google API key.").arg(Constants::NAME)); + msgBox.setInformativeText(QString("It won't work unless you enter one." + "

In alternative you can get %1 from the developer site.") + .arg(Constants::NAME)); + msgBox.setModal(true); + msgBox.setWindowModality(Qt::WindowModal); + msgBox.addButton(QMessageBox::Close); + QPushButton *enterKeyButton = + msgBox.addButton(QString("Enter API key..."), QMessageBox::AcceptRole); + QPushButton *devButton = msgBox.addButton(QString("Get from %1").arg(Constants::WEBSITE), + QMessageBox::AcceptRole); + QPushButton *helpButton = msgBox.addButton(QMessageBox::Help); + + msgBox.exec(); + + if (msgBox.clickedButton() == helpButton) { + QDesktopServices::openUrl(QUrl("https://github.com/flaviotordini/minitube/blob/master/" + "README.md#google-api-key")); + } else if (msgBox.clickedButton() == enterKeyButton) { + bool ok; + QString text = QInputDialog::getText(this, QString(), "Google API key:", QLineEdit::Normal, + QString(), &ok); + if (ok && !text.isEmpty()) { + QSettings settings; + settings.setValue("googleApiKey", text); + YT3::instance().initApiKeys(); + } + } else if (msgBox.clickedButton() == devButton) { + QDesktopServices::openUrl(QUrl(Constants::WEBSITE)); + } + shown = false; +} + void MainWindow::compactView(bool enable) { - m_compact = enable; + setUpdatesEnabled(false); + + compactModeActive = enable; static QList compactShortcuts; static QList stopShortcuts; - const static QString key = "compactGeometry"; + const QString key = "compactGeometry"; QSettings settings; -#ifndef APP_MAC - menuBar()->setVisible(!enable); -#endif - if (enable) { setMinimumSize(320, 180); #ifdef Q_OS_MAC @@ -1255,11 +1514,15 @@ void MainWindow::compactView(bool enable) { if (settings.contains(key)) restoreGeometry(settings.value(key).toByteArray()); else - resize(320, 180); + resize(480, 270); +#ifdef APP_MAC_QMACTOOLBAR + mac::showToolBar(winId(), !enable); +#else mainToolBar->setVisible(!enable); - mediaView->setPlaylistVisible(!enable); - statusBar()->setVisible(!enable); +#endif + mediaView->setSidebarVisibility(!enable); + statusBar()->hide(); compactShortcuts = compactViewAct->shortcuts(); stopShortcuts = stopAct->shortcuts(); @@ -1267,22 +1530,30 @@ void MainWindow::compactView(bool enable) { QList newStopShortcuts(stopShortcuts); newStopShortcuts.removeAll(QKeySequence(Qt::Key_Escape)); stopAct->setShortcuts(newStopShortcuts); - compactViewAct->setShortcuts(QList(compactShortcuts) << QKeySequence(Qt::Key_Escape)); + compactViewAct->setShortcuts(QList(compactShortcuts) + << QKeySequence(Qt::Key_Escape)); // ensure focus does not end up to the search box // as it would steal the Space shortcut mediaView->setFocus(); } else { + settings.setValue(key, saveGeometry()); + // unset minimum size setMinimumSize(0, 0); + #ifdef Q_OS_MAC mac::SetupFullScreenWindow(winId()); #endif - settings.setValue(key, saveGeometry()); +#ifdef APP_MAC_QMACTOOLBAR + mac::showToolBar(winId(), !enable); +#else mainToolBar->setVisible(!enable); - mediaView->setPlaylistVisible(!enable); - statusBar()->setVisible(!enable); +#endif + mediaView->setSidebarVisibility(!enable); + if (needStatusBar()) setStatusBarVisibility(true); + readSettings(); compactViewAct->setShortcuts(compactShortcuts); @@ -1290,11 +1561,28 @@ void MainWindow::compactView(bool enable) { } // auto float on top - floatOnTop(enable); + floatOnTop(enable, false); -#ifdef Q_OS_MAC +#ifdef APP_MAC mac::compactMode(winId(), enable); +#else + if (enable) { + menuVisibleBeforeCompactMode = menuBar()->isVisible(); + menuBar()->hide(); + } else { + menuBar()->setVisible(menuVisibleBeforeCompactMode); + } #endif + + setUpdatesEnabled(true); +} + +void MainWindow::toggleToolbarMenu() { + if (!toolbarMenu) toolbarMenu = new ToolbarMenu(this); + if (toolbarMenu->isVisible()) + toolbarMenu->hide(); + else + toolbarMenu->show(); } void MainWindow::searchFocus() { @@ -1302,174 +1590,155 @@ void MainWindow::searchFocus() { toolbarSearch->setFocus(); } -#ifdef APP_PHONON -void MainWindow::initPhonon() { - // Phonon initialization - if (mediaObject) delete mediaObject; - if (audioOutput) delete audioOutput; - mediaObject = new Phonon::MediaObject(this); - mediaObject->setTickInterval(100); - connect(mediaObject, SIGNAL(stateChanged(Phonon::State, Phonon::State)), - this, SLOT(stateChanged(Phonon::State, Phonon::State))); - connect(mediaObject, SIGNAL(tick(qint64)), this, SLOT(tick(qint64))); - connect(mediaObject, SIGNAL(totalTimeChanged(qint64)), this, SLOT(totalTimeChanged(qint64))); -#ifdef APP_PHONON_SEEK - seekSlider->setMediaObject(mediaObject); -#endif - audioOutput = new Phonon::AudioOutput(Phonon::VideoCategory, this); - connect(audioOutput, SIGNAL(volumeChanged(qreal)), this, SLOT(volumeChanged(qreal))); - connect(audioOutput, SIGNAL(mutedChanged(bool)), this, SLOT(volumeMutedChanged(bool))); - volumeSlider->setAudioOutput(audioOutput); - Phonon::createPath(mediaObject, audioOutput); +void MainWindow::initMedia() { +#ifdef MEDIA_QTAV + qFatal("QtAV has a showstopper bug. Audio stops randomly. See bug " + "https://github.com/wang-bin/QtAV/issues/1184"); + media = new MediaQtAV(this); +#elif defined MEDIA_MPV + media = new MediaMPV(); +#else + qFatal("No media backend defined"); +#endif + media->init(); + media->setUserAgent(HttpUtils::stealthUserAgent()); + QSettings settings; - audioOutput->setVolume(settings.value("volume", 1).toDouble()); - // audioOutput->setMuted(settings.value("volumeMute").toBool()); + qreal volume = settings.value("volume", 1.).toReal(); + media->setVolume(volume); + + connect(media, &Media::error, this, &MainWindow::handleError); + connect(media, &Media::stateChanged, this, &MainWindow::stateChanged); + connect(media, &Media::positionChanged, this, &MainWindow::tick); + + connect(seekSlider, &QSlider::sliderMoved, this, [this](int value) { + // value : maxValue = posit ion : duration + qint64 ms = (value * media->duration()) / seekSlider->maximum(); + qDebug() << "Seeking to" << ms; + media->seek(ms); + if (media->state() == Media::PausedState) media->play(); + }); + connect(seekSlider, &QSlider::sliderPressed, this, [this]() { + // value : maxValue = position : duration + qint64 ms = (seekSlider->value() * media->duration()) / seekSlider->maximum(); + media->seek(ms); + if (media->state() == Media::PausedState) media->play(); + }); + connect(media, &Media::started, this, [this]() { seekSlider->setValue(0); }); + + connect(media, &Media::volumeChanged, this, &MainWindow::volumeChanged); + connect(media, &Media::volumeMutedChanged, this, &MainWindow::volumeMutedChanged); + connect(volumeSlider, &QSlider::sliderMoved, this, [this](int value) { + qreal volume = (qreal)value / volumeSlider->maximum(); + media->setVolume(volume); + }); + connect(volumeSlider, &QSlider::sliderPressed, this, [this]() { + qreal volume = (qreal)volumeSlider->value() / volumeSlider->maximum(); + media->setVolume(volume); + }); + + mediaView->setMedia(media); } -#endif void MainWindow::tick(qint64 time) { - if (time <= 0) { - // the "if" is important because tick is continually called - // and we don't want to paint the toolbar every 100ms - if (!currentTime->text().isEmpty()) currentTime->clear(); - return; +#ifdef APP_MAC + bool isDown = seekSlider->property("down").isValid(); +#else + bool isDown = seekSlider->isSliderDown(); +#endif + if (!isDown && media->state() == Media::PlayingState) { + // value : maxValue = position : duration + qint64 duration = media->duration(); + if (duration <= 0) return; + int value = (seekSlider->maximum() * media->position()) / duration; + seekSlider->setValue(value); } - currentTime->setText(formatTime(time)); - - // remaining time -#ifdef APP_PHONON - const qint64 remainingTime = mediaObject->remainingTime(); - currentTime->setStatusTip(tr("Remaining time: %1").arg(formatTime(remainingTime))); + const QString s = formatTime(time); + if (s != currentTimeLabel->text()) { + currentTimeLabel->setText(s); + emit currentTimeChanged(s); -#ifndef APP_PHONON_SEEK - const qint64 totalTime = mediaObject->totalTime(); - slider->blockSignals(true); - // qWarning() << totalTime << time << time * 100 / totalTime; - if (totalTime > 0 && time > 0 && !slider->isSliderDown() && mediaObject->state() == Phonon::PlayingState) - slider->setValue(time * slider->maximum() / totalTime); - slider->blockSignals(false); -#endif - -#endif -} - -void MainWindow::totalTimeChanged(qint64 time) { - if (time <= 0) { - // totalTime->clear(); - return; + // remaining time + const qint64 remainingTime = media->remainingTime(); + currentTimeLabel->setStatusTip(tr("Remaining time: %1").arg(formatTime(remainingTime))); } - // totalTime->setText(formatTime(time)); - - /* - slider->blockSignals(true); - slider->setMaximum(time/1000); - slider->blockSignals(false); - */ - } -QString MainWindow::formatTime(qint64 time) { - QTime displayTime; - displayTime = displayTime.addMSecs(time); - QString timeString; - // 60 * 60 * 1000 = 3600000 - if (time > 3600000) - timeString = displayTime.toString("h:mm:ss"); - else - timeString = displayTime.toString("m:ss"); - return timeString; +QString MainWindow::formatTime(qint64 duration) { + duration /= 1000; + QString res; + int seconds = (int)(duration % 60); + duration /= 60; + int minutes = (int)(duration % 60); + duration /= 60; + int hours = (int)(duration % 24); + if (hours == 0) return res.sprintf("%02d:%02d", minutes, seconds); + return res.sprintf("%02d:%02d:%02d", hours, minutes, seconds); } void MainWindow::volumeUp() { -#ifdef APP_PHONON - qreal newVolume = volumeSlider->audioOutput()->volume() + .1; - if (newVolume > volumeSlider->maximumVolume()) - newVolume = volumeSlider->maximumVolume(); - volumeSlider->audioOutput()->setVolume(newVolume); -#endif + qreal newVolume = media->volume() + .1; + if (newVolume > 1.) newVolume = 1.; + media->setVolume(newVolume); } void MainWindow::volumeDown() { -#ifdef APP_PHONON - qreal newVolume = volumeSlider->audioOutput()->volume() - .1; - if (newVolume < 0.) - newVolume = 0.; - volumeSlider->audioOutput()->setVolume(newVolume); -#endif + qreal newVolume = media->volume() - .1; + if (newVolume < 0) newVolume = 0; + media->setVolume(newVolume); } -void MainWindow::volumeMute() { -#ifdef APP_PHONON - volumeSlider->audioOutput()->setMuted(!volumeSlider->audioOutput()->isMuted()); -#endif +void MainWindow::toggleVolumeMute() { + bool muted = media->volumeMuted(); + media->setVolumeMuted(!muted); } void MainWindow::volumeChanged(qreal newVolume) { -#ifdef APP_PHONON // automatically unmute when volume changes - if (volumeSlider->audioOutput()->isMuted()) - volumeSlider->audioOutput()->setMuted(false); - - bool isZero = volumeSlider->property("zero").toBool(); - bool styleChanged = false; - if (newVolume == 0. && !isZero) { - volumeSlider->setProperty("zero", true); - styleChanged = true; - } else if (newVolume > 0. && isZero) { - volumeSlider->setProperty("zero", false); - styleChanged = true; - } - if (styleChanged) { - QSlider* volumeQSlider = volumeSlider->findChild(); - style()->unpolish(volumeQSlider); - style()->polish(volumeQSlider); - } -#endif - statusBar()->showMessage(tr("Volume at %1%").arg((int)(newVolume*100))); + if (media->volumeMuted()) media->setVolumeMuted(false); + showMessage(tr("Volume at %1%").arg((int)(newVolume * 100))); + // newVolume : 1.0 = x : 1000 + int value = newVolume * volumeSlider->maximum(); + volumeSlider->blockSignals(true); + volumeSlider->setValue(value); + volumeSlider->blockSignals(false); } void MainWindow::volumeMutedChanged(bool muted) { if (muted) { volumeMuteAct->setIcon(IconUtils::icon("audio-volume-muted")); - statusBar()->showMessage(tr("Volume is muted")); + showMessage(tr("Volume is muted")); } else { volumeMuteAct->setIcon(IconUtils::icon("audio-volume-high")); - statusBar()->showMessage(tr("Volume is unmuted")); + showMessage(tr("Volume is unmuted")); } } -void MainWindow::setDefinitionMode(QString definitionName) { - QAction *definitionAct = The::globalActions()->value("definition"); +void MainWindow::setDefinitionMode(const QString &definitionName) { + QAction *definitionAct = getAction("definition"); definitionAct->setText(definitionName); - definitionAct->setStatusTip(tr("Maximum video definition set to %1").arg(definitionAct->text()) - + " (" + definitionAct->shortcut().toString(QKeySequence::NativeText) + ")"); - statusBar()->showMessage(definitionAct->statusTip()); - QSettings settings; - settings.setValue("definition", definitionName); -} - -void MainWindow::toggleDefinitionMode() { - QSettings settings; - QString currentDefinition = settings.value("definition").toString(); - QStringList definitionNames = VideoDefinition::getDefinitionNames(); - int currentIndex = definitionNames.indexOf(currentDefinition); - int nextIndex = 0; - if (currentIndex != definitionNames.size() - 1) { - nextIndex = currentIndex + 1; + definitionAct->setStatusTip( + tr("Maximum video definition set to %1").arg(definitionAct->text()) + " (" + + definitionAct->shortcut().toString(QKeySequence::NativeText) + ")"); + showMessage(definitionAct->statusTip()); + YT3::instance().setMaxVideoDefinition(definitionName); + if (views->currentWidget() == mediaView) { + mediaView->reloadCurrentVideo(); } - QString nextDefinition = definitionNames.at(nextIndex); - setDefinitionMode(nextDefinition); } -void MainWindow::showFullscreenToolbar(bool show) { - if (!m_fullscreen) return; - mainToolBar->setVisible(show); -} +void MainWindow::toggleDefinitionMode() { + const QVector &definitions = VideoDefinition::getDefinitions(); + const VideoDefinition ¤tDefinition = YT3::instance().maxVideoDefinition(); -void MainWindow::showFullscreenPlaylist(bool show) { - if (!m_fullscreen) return; - mediaView->setPlaylistVisible(show); + int index = definitions.indexOf(currentDefinition); + if (index != definitions.size() - 1) { + index++; + } else { + index = 0; + } + setDefinitionMode(definitions.at(index).getName()); } void MainWindow::clearRecentKeywords() { @@ -1481,45 +1750,49 @@ void MainWindow::clearRecentKeywords() { searchView->updateRecentKeywords(); searchView->updateRecentChannels(); } - QAbstractNetworkCache *cache = The::networkAccessManager()->cache(); - if (cache) cache->clear(); + HttpUtils::clearCaches(); showMessage(tr("Your privacy is now safe")); } void MainWindow::setManualPlay(bool enabled) { QSettings settings; settings.setValue("manualplay", QVariant::fromValue(enabled)); - showActionInStatusBar(The::globalActions()->value("manualplay"), enabled); + if (views->currentWidget() == homeView && + homeView->currentWidget() == homeView->getSearchView()) + return; + showActionsInStatusBar({getAction("manualplay")}, enabled); } -void MainWindow::updateDownloadMessage(QString message) { - The::globalActions()->value("downloads")->setText(message); +void MainWindow::updateDownloadMessage(const QString &message) { + getAction("downloads")->setText(message); } void MainWindow::downloadsFinished() { - The::globalActions()->value("downloads")->setText(tr("&Downloads")); - statusBar()->showMessage(tr("Downloads complete")); + getAction("downloads")->setText(tr("&Downloads")); + showMessage(tr("Downloads complete")); } void MainWindow::toggleDownloads(bool show) { - if (show) { stopAct->setShortcuts(QList() << QKeySequence(Qt::Key_MediaStop)); - The::globalActions()->value("downloads")->setShortcuts( - QList() << QKeySequence(Qt::CTRL + Qt::Key_J) - << QKeySequence(Qt::Key_Escape)); + getAction("downloads") + ->setShortcuts(QList() << QKeySequence(Qt::CTRL + Qt::Key_J) + << QKeySequence(Qt::Key_Escape)); } else { - The::globalActions()->value("downloads")->setShortcuts( - QList() << QKeySequence(Qt::CTRL + Qt::Key_J)); - stopAct->setShortcuts(QList() << QKeySequence(Qt::Key_Escape) << QKeySequence(Qt::Key_MediaStop)); + getAction("downloads") + ->setShortcuts(QList() << QKeySequence(Qt::CTRL + Qt::Key_J)); + stopAct->setShortcuts(QList() + << QKeySequence(Qt::Key_Escape) << QKeySequence(Qt::Key_MediaStop)); } if (!downloadView) { downloadView = new DownloadView(this); views->addWidget(downloadView); } - if (show) showWidget(downloadView); - else goBack(); + if (show) + showView(downloadView); + else + goBack(); } void MainWindow::suggestionAccepted(Suggestion *suggestion) { @@ -1527,31 +1800,29 @@ void MainWindow::suggestionAccepted(Suggestion *suggestion) { } void MainWindow::search(const QString &query) { - QString q = query.trimmed(); - if (q.length() == 0) return; + QString q = query.simplified(); + if (q.isEmpty()) return; SearchParams *searchParams = new SearchParams(); searchParams->setKeywords(q); showMedia(searchParams); } -void MainWindow::dragEnterEvent(QDragEnterEvent *event) { - if (event->mimeData()->hasFormat("text/uri-list")) { - QList urls = event->mimeData()->urls(); +void MainWindow::dragEnterEvent(QDragEnterEvent *e) { + if (e->mimeData()->hasFormat("text/uri-list")) { + QList urls = e->mimeData()->urls(); if (urls.isEmpty()) return; - QUrl url = urls.first(); + const QUrl &url = urls.at(0); QString videoId = YTSearch::videoIdFromUrl(url.toString()); - if (!videoId.isEmpty()) - event->acceptProposedAction(); + if (!videoId.isEmpty()) e->acceptProposedAction(); } } -void MainWindow::dropEvent(QDropEvent *event) { +void MainWindow::dropEvent(QDropEvent *e) { if (!toolbarSearch->isEnabled()) return; - QList urls = event->mimeData()->urls(); - if (urls.isEmpty()) - return; - QUrl url = urls.first(); + QList urls = e->mimeData()->urls(); + if (urls.isEmpty()) return; + const QUrl &url = urls.at(0); QString videoId = YTSearch::videoIdFromUrl(url.toString()); if (!videoId.isEmpty()) { setWindowTitle(url.toString()); @@ -1561,69 +1832,22 @@ void MainWindow::dropEvent(QDropEvent *event) { } } -void MainWindow::checkForUpdate() { - static const QString updateCheckKey = "updateCheck"; - - // check every 24h - QSettings settings; - uint unixTime = QDateTime::currentDateTime().toTime_t(); - int lastCheck = settings.value(updateCheckKey).toInt(); - int secondsSinceLastCheck = unixTime - lastCheck; - // qDebug() << "secondsSinceLastCheck" << unixTime << lastCheck << secondsSinceLastCheck; - if (secondsSinceLastCheck < 86400) return; - - // check it out - if (updateChecker) delete updateChecker; - updateChecker = new UpdateChecker(); - connect(updateChecker, SIGNAL(newVersion(QString)), - this, SLOT(gotNewVersion(QString))); - updateChecker->checkForUpdate(); - settings.setValue(updateCheckKey, unixTime); -} - -void MainWindow::gotNewVersion(QString version) { - if (updateChecker) { - delete updateChecker; - updateChecker = 0; - } - - QSettings settings; - QString checkedVersion = settings.value("checkedVersion").toString(); - if (checkedVersion == version) return; - -#ifdef APP_SIMPLEUPDATE - simpleUpdateDialog(version); -#elif defined(APP_ACTIVATION) && !defined(APP_MAC) - UpdateDialog *dialog = new UpdateDialog(version, this); - dialog->show(); -#endif +bool MainWindow::needStatusBar() { + return !statusToolBar->actions().isEmpty(); } -void MainWindow::simpleUpdateDialog(QString version) { - QMessageBox msgBox(this); - msgBox.setIconPixmap( - QPixmap(":/images/app.png") - .scaled(64, 64, Qt::KeepAspectRatio, Qt::SmoothTransformation)); - msgBox.setText(tr("%1 version %2 is now available.").arg(Constants::NAME, version)); - msgBox.setModal(true); - msgBox.setWindowModality(Qt::WindowModal); - msgBox.addButton(QMessageBox::Close); - QPushButton* laterButton = msgBox.addButton(tr("Remind me later"), QMessageBox::RejectRole); - QPushButton* updateButton = msgBox.addButton(tr("Update"), QMessageBox::AcceptRole); - msgBox.exec(); - if (msgBox.clickedButton() != laterButton) { - QSettings settings; - settings.setValue("checkedVersion", version); - } - if (msgBox.clickedButton() == updateButton) visitSite(); +void MainWindow::adjustMessageLabelPosition() { + if (messageLabel->parent() == this) + messageLabel->move(0, height() - messageLabel->height()); + else + messageLabel->move(mapToGlobal(QPoint(0, height() - messageLabel->height()))); } -void MainWindow::floatOnTop(bool onTop) { - showActionInStatusBar(The::globalActions()->value("ontop"), onTop); +void MainWindow::floatOnTop(bool onTop, bool showAction) { + if (showAction) showActionsInStatusBar({getAction("ontop")}, onTop); #ifdef APP_MAC mac::floatOnTop(winId(), onTop); - return; -#endif +#else if (onTop) { setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint); show(); @@ -1631,11 +1855,12 @@ void MainWindow::floatOnTop(bool onTop) { setWindowFlags(windowFlags() ^ Qt::WindowStaysOnTopHint); show(); } +#endif } void MainWindow::restore() { #ifdef APP_MAC - mac::uncloseWindow(window()->winId()); + mac::uncloseWindow(winId()); #endif } @@ -1647,8 +1872,8 @@ void MainWindow::messageReceived(const QString &message) { } else if (message == QLatin1String("--previous")) { if (skipBackwardAct->isEnabled()) skipBackwardAct->trigger(); } else if (message == QLatin1String("--stop-after-this")) { - The::globalActions()->value("stopafterthis")->toggle(); - } else if (message.startsWith("--")) { + getAction("stopafterthis")->toggle(); + } else if (message.startsWith("--")) { MainWindow::printHelp(); } else if (!message.isEmpty()) { SearchParams *searchParams = new SearchParams(); @@ -1657,14 +1882,39 @@ void MainWindow::messageReceived(const QString &message) { } } -void MainWindow::hideMouse() { +void MainWindow::hideFullscreenUI() { + if (views->currentWidget() != mediaView) return; setCursor(Qt::BlankCursor); - mediaView->setPlaylistVisible(false); + + QPoint p = mapFromGlobal(QCursor::pos()); + const int x = p.x(); + + if (x > mediaView->getSidebar()->width()) mediaView->setSidebarVisibility(false); + #ifndef APP_MAC - mainToolBar->setVisible(false); + const int y = p.y(); + bool shouldHideToolbar = !toolbarSearch->hasFocus() && y > mainToolBar->height(); + if (shouldHideToolbar) mainToolBar->setVisible(false); #endif } +void MainWindow::toggleMenuVisibility() { + bool show = !menuBar()->isVisible(); + menuBar()->setVisible(show); +} + +void MainWindow::toggleMenuVisibilityWithMessage() { + bool show = !menuBar()->isVisible(); + menuBar()->setVisible(show); + if (!show) { + QMessageBox msgBox(this); + msgBox.setText(tr("You can still access the menu bar by pressing the ALT key")); + msgBox.setModal(true); + msgBox.setWindowModality(Qt::WindowModal); + msgBox.exec(); + } +} + #ifdef APP_MAC_STORE void MainWindow::rateOnAppStore() { QDesktopServices::openUrl(QUrl("macappstore://userpub.itunes.apple.com" @@ -1688,42 +1938,82 @@ void MainWindow::printHelp() { std::cout << msg.toLocal8Bit().data(); } -void MainWindow::showMessage(QString message) { - statusBar()->showMessage(message, 60000); +void MainWindow::setupAction(QAction *action) { + // never autorepeat. + // unexperienced users tend to keep keys pressed for a "long" time + action->setAutoRepeat(false); + + // show keyboard shortcuts in the status bar + if (!action->shortcut().isEmpty()) + action->setStatusTip(action->statusTip() + QLatin1String(" (") + + action->shortcut().toString(QKeySequence::NativeText) + + QLatin1String(")")); } -#ifdef APP_ACTIVATION -void MainWindow::showActivationView(bool transition) { - QWidget *activationView = ActivationView::instance(); - if (views->currentWidget() == activationView) { - buy(); - return; +QAction *MainWindow::getAction(const char *name) { + return actionMap.value(QByteArray::fromRawData(name, strlen(name))); +} + +void MainWindow::addNamedAction(const QByteArray &name, QAction *action) { + actionMap.insert(name, action); +} + +QMenu *MainWindow::getMenu(const char *name) { + return menuMap.value(QByteArray::fromRawData(name, strlen(name))); +} + +void MainWindow::showMessage(const QString &message) { + if (!isVisible()) return; +#ifdef APP_MAC + if (!mac::isVisible(winId())) return; +#endif + if (statusBar()->isVisible()) + statusBar()->showMessage(message, 60000); + else if (isActiveWindow()) { + messageLabel->setText(message); + QSize size = messageLabel->sizeHint(); + // round width to avoid flicker with fast changing messages (e.g. volume + // changes) + int w = size.width() + 10; + const int multiple = 15; + w = w + multiple / 2; + w -= w % multiple; + size.setWidth(w); + messageLabel->resize(size); + if (messageLabel->isHidden()) { + adjustMessageLabelPosition(); + messageLabel->show(); + } + messageTimer->start(); } - views->addWidget(activationView); - showWidget(activationView, transition); } -void MainWindow::showActivationDialog() { - QTimer::singleShot(0, new ActivationDialog(this), SLOT(show())); +void MainWindow::hideMessage() { + if (messageLabel->isVisible()) { + messageLabel->hide(); + messageLabel->clear(); + } } -void MainWindow::buy() { - Extra::buy(); +void MainWindow::handleError(const QString &message) { + qWarning() << message; + showMessage(message); } -void MainWindow::hideBuyAction() { - QAction *action = The::globalActions()->value("buy"); - action->setVisible(false); - action->setEnabled(false); +#ifdef APP_ACTIVATION +void MainWindow::showActivationView() { + View *activationView = ActivationView::instance(); + views->addWidget(activationView); + if (views->currentWidget() != activationView) showView(activationView); } #endif void MainWindow::showRegionsView() { if (!regionsView) { regionsView = new RegionsView(this); - connect(regionsView, SIGNAL(regionChanged()), - homeView->getStandardFeedsView(), SLOT(load())); + connect(regionsView, SIGNAL(regionChanged()), homeView->getStandardFeedsView(), + SLOT(load())); views->addWidget(regionsView); } - showWidget(regionsView); + showView(regionsView); }