]> git.sur5r.net Git - minitube/blobdiff - src/mainwindow.cpp
More const references everywhere
[minitube] / src / mainwindow.cpp
index a1c5991e7306e98cc45e9813f236bac9de2d0c35..65d3627f63c1dc89379464222a4c070c76a74552 100644 (file)
@@ -1,3 +1,23 @@
+/* $BEGIN_LICENSE
+
+This file is part of Minitube.
+Copyright 2009, Flavio Tordini <flavio.tordini@gmail.com>
+
+Minitube 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 3 of the License, or
+(at your option) any later version.
+
+Minitube 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 Minitube.  If not, see <http://www.gnu.org/licenses/>.
+
+$END_LICENSE */
+
 #include "mainwindow.h"
 #include "homeview.h"
 #include "searchview.h"
@@ -6,7 +26,7 @@
 #include "downloadview.h"
 #include "spacer.h"
 #include "constants.h"
-#include "utils.h"
+#include "iconutils.h"
 #include "global.h"
 #include "videodefinition.h"
 #include "fontutils.h"
 #include "searchparams.h"
 #include "videosource.h"
 #include "ytsearch.h"
-#ifdef Q_WS_X11
+#ifdef Q_OS_LINUX
 #include "gnomeglobalshortcutbackend.h"
 #endif
-#ifdef Q_WS_MAC
+#ifdef Q_OS_MAC
 #include "mac_startup.h"
 #include "macfullscreen.h"
 #include "macsupport.h"
@@ -33,7 +53,7 @@
 #include "searchlineedit.h"
 #endif
 #include <iostream>
-#ifndef Q_WS_X11
+#ifdef APP_EXTRA
 #include "extra.h"
 #include "updatedialog.h"
 #endif
 #include "ytregions.h"
 #include "regionsview.h"
 #include "standardfeedsview.h"
+#include "channelaggregator.h"
+#include "database.h"
+#include "videoareawidget.h"
+#include "jsfunctions.h"
+#include "seekslider.h"
+#ifdef APP_YT3
+#include "yt3.h"
+#endif
 
+namespace {
 static MainWindow *singleton = 0;
+}
 
 MainWindow* MainWindow::instance() {
-    if (!singleton) singleton = new MainWindow();
     return singleton;
 }
 
@@ -58,18 +87,27 @@ MainWindow::MainWindow() :
     aboutView(0),
     downloadView(0),
     regionsView(0),
+    #ifdef APP_PHONON
     mediaObject(0),
     audioOutput(0),
-    m_fullscreen(false) {
+    #endif
+    m_fullscreen(false),
+    m_compact(false) {
 
     singleton = this;
 
+#ifdef APP_EXTRA
+    Extra::windowSetup(this);
+#endif
+
     // views mechanism
     history = new QStack<QWidget*>();
-    views = new QStackedWidget(this);
+    views = new QStackedWidget();
+    views->hide();
+    setCentralWidget(views);
 
     // views
-    homeView = new HomeView(this);
+    homeView = new HomeView();
     views->addWidget(homeView);
 
     // TODO make this lazy
@@ -83,15 +121,9 @@ MainWindow::MainWindow() :
     createToolBars();
     createStatusBar();
 
-    initPhonon();
-    mediaView->setMediaObject(mediaObject);
-
     // remove that useless menu/toolbar context menu
     this->setContextMenuPolicy(Qt::NoContextMenu);
 
-    // mediaView init stuff thats needs actions
-    mediaView->initialize();
-
     // event filter to block ugly toolbar tooltips
     qApp->installEventFilter(this);
 
@@ -101,10 +133,8 @@ MainWindow::MainWindow() :
     readSettings();
 
     // fix stacked widget minimum size
-    for (int i = 0; i < views->count(); i++) {
-        QWidget* view = views->widget(i);
-        if (view) view->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
-    }
+    for (int i = 0; i < views->count(); i++)
+        views->widget(i)->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
     setMinimumWidth(0);
 
     // show the initial view
@@ -115,15 +145,46 @@ MainWindow::MainWindow() :
         showActivationView(false);
 #endif
 
-    setCentralWidget(views);
+    views->show();
+
+    qApp->processEvents();
+    QTimer::singleShot(50, this, SLOT(lazyInit()));
+}
+
+MainWindow::~MainWindow() {
+    delete history;
+}
+
+void MainWindow::lazyInit() {
+#ifdef APP_PHONON
+    initPhonon();
+#endif
+    mediaView->initialize();
+#ifdef APP_PHONON
+    mediaView->setMediaObject(mediaObject);
+#endif
+    qApp->processEvents();
+
+    // CLI
+    if (qApp->arguments().size() > 1) {
+        QString query = qApp->arguments().at(1);
+        if (query.startsWith(QLatin1String("--"))) {
+            messageReceived(query);
+            qApp->quit();
+        } else {
+            SearchParams *searchParams = new SearchParams();
+            searchParams->setKeywords(query);
+            showMedia(searchParams);
+        }
+    }
 
     // Global shortcuts
     GlobalShortcuts &shortcuts = GlobalShortcuts::instance();
-#ifdef Q_WS_X11
+#ifdef Q_OS_LINUX
     if (GnomeGlobalShortcutBackend::IsGsdAvailable())
         shortcuts.setBackend(new GnomeGlobalShortcutBackend(&shortcuts));
 #endif
-#ifdef Q_WS_MAC
+#ifdef Q_OS_MAC
     mac::MacSetup();
 #endif
     connect(&shortcuts, SIGNAL(PlayPause()), pauseAct, SLOT(trigger()));
@@ -144,12 +205,9 @@ MainWindow::MainWindow() :
     mouseTimer->setSingleShot(true);
     connect(mouseTimer, SIGNAL(timeout()), SLOT(hideMouse()));
 
-    QTimer::singleShot(0, this, SLOT(checkForUpdate()));
-
-}
+    JsFunctions::instance();
 
-MainWindow::~MainWindow() {
-    delete history;
+    checkForUpdate();
 }
 
 void MainWindow::changeEvent(QEvent* event) {
@@ -168,11 +226,13 @@ bool MainWindow::eventFilter(QObject *obj, QEvent *event) {
         QMouseEvent *mouseEvent = static_cast<QMouseEvent*> (event);
         const int x = mouseEvent->pos().x();
         const QString className = QString(obj->metaObject()->className());
-        const bool isHoveringVideo = (className == "QGLWidget") || (className == "VideoAreaWidget");
+        const bool isHoveringVideo =
+                (className == QLatin1String("QGLWidget")) ||
+                (className == QLatin1String("VideoAreaWidget"));
 
         // qDebug() << obj << mouseEvent->pos() << isHoveringVideo << mediaView->isPlaylistVisible();
 
-        if (mediaView->isPlaylistVisible()) {
+        if (mediaView && mediaView->isPlaylistVisible()) {
             if (isHoveringVideo && x > 5) mediaView->setPlaylistVisible(false);
         } else {
             if (isHoveringVideo && x >= 0 && x < 5) mediaView->setPlaylistVisible(true);
@@ -204,42 +264,39 @@ bool MainWindow::eventFilter(QObject *obj, QEvent *event) {
 
 void MainWindow::createActions() {
 
-    QMap<QString, QAction*> *actions = The::globalActions();
+    QHash<QString, QAction*> *actions = The::globalActions();
 
-    stopAct = new QAction(Utils::icon("media-playback-stop"), tr("&Stop"), this);
+    stopAct = new QAction(IconUtils::icon("media-playback-stop"), tr("&Stop"), this);
     stopAct->setStatusTip(tr("Stop playback and go back to the search view"));
     stopAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::Key_Escape) << QKeySequence(Qt::Key_MediaStop));
     stopAct->setEnabled(false);
     actions->insert("stop", stopAct);
-    connect(stopAct, SIGNAL(triggered()), this, SLOT(stop()));
+    connect(stopAct, SIGNAL(triggered()), SLOT(stop()));
 
     skipBackwardAct = new QAction(
-                Utils::icon("media-skip-backward"),
+                IconUtils::icon("media-skip-backward"),
                 tr("P&revious"), this);
     skipBackwardAct->setStatusTip(tr("Go back to the previous track"));
     skipBackwardAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Left));
-#if QT_VERSION >= 0x040600
-    skipBackwardAct->setPriority(QAction::LowPriority);
-#endif
     skipBackwardAct->setEnabled(false);
     actions->insert("previous", skipBackwardAct);
     connect(skipBackwardAct, SIGNAL(triggered()), mediaView, SLOT(skipBackward()));
 
-    skipAct = new QAction(Utils::icon("media-skip-forward"), tr("S&kip"), this);
+    skipAct = new QAction(IconUtils::icon("media-skip-forward"), tr("S&kip"), this);
     skipAct->setStatusTip(tr("Skip to the next video"));
     skipAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::CTRL + Qt::Key_Right) << QKeySequence(Qt::Key_MediaNext));
     skipAct->setEnabled(false);
     actions->insert("skip", skipAct);
     connect(skipAct, SIGNAL(triggered()), mediaView, SLOT(skip()));
 
-    pauseAct = new QAction(Utils::icon("media-playback-pause"), tr("&Pause"), this);
-    pauseAct->setStatusTip(tr("Pause playback"));
+    pauseAct = new QAction(IconUtils::icon("media-playback-start"), tr("&Play"), this);
+    pauseAct->setStatusTip(tr("Resume playback"));
     pauseAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::Key_Space) << QKeySequence(Qt::Key_MediaPlay));
     pauseAct->setEnabled(false);
     actions->insert("pause", pauseAct);
     connect(pauseAct, SIGNAL(triggered()), mediaView, SLOT(pause()));
 
-    fullscreenAct = new QAction(Utils::icon("view-fullscreen"), tr("&Full Screen"), this);
+    fullscreenAct = new QAction(IconUtils::icon("view-fullscreen"), tr("&Full Screen"), this);
     fullscreenAct->setStatusTip(tr("Go full screen"));
     QList<QKeySequence> fsShortcuts;
 #ifdef APP_MAC
@@ -249,9 +306,7 @@ void MainWindow::createActions() {
 #endif
     fullscreenAct->setShortcuts(fsShortcuts);
     fullscreenAct->setShortcutContext(Qt::ApplicationShortcut);
-#if QT_VERSION >= 0x040600
     fullscreenAct->setPriority(QAction::LowPriority);
-#endif
     actions->insert("fullscreen", fullscreenAct);
     connect(fullscreenAct, SIGNAL(triggered()), this, SLOT(fullscreen()));
 
@@ -375,15 +430,20 @@ void MainWindow::createActions() {
     addAction(volumeDownAct);
 
     volumeMuteAct = new QAction(this);
-    volumeMuteAct->setIcon(Utils::icon("audio-volume-high"));
+    volumeMuteAct->setIcon(IconUtils::icon("audio-volume-high"));
     volumeMuteAct->setStatusTip(tr("Mute volume"));
-    volumeMuteAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::CTRL + Qt::Key_E));
+    volumeMuteAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_K));
     actions->insert("volume-mute", volumeMuteAct);
     connect(volumeMuteAct, SIGNAL(triggered()), SLOT(volumeMute()));
     addAction(volumeMuteAct);
 
     QAction *definitionAct = new QAction(this);
-    definitionAct->setIcon(Utils::icon("video-display"));
+#ifdef Q_OS_LINUX
+    definitionAct->setIcon(IconUtils::tintedIcon("video-display", QColor(0, 0, 0),
+                                                 QList<QSize>() << QSize(16, 16)));
+#else
+    definitionAct->setIcon(IconUtils::icon("video-display"));
+#endif
     definitionAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::CTRL + Qt::Key_D));
     /*
     QMenu *definitionMenu = new QMenu(this);
@@ -398,9 +458,9 @@ void MainWindow::createActions() {
 
     QAction *action;
 
-    action = new QAction(Utils::icon("media-playback-start"), tr("&Manually Start Playing"), this);
+    action = new QAction(IconUtils::icon("media-playback-start"), tr("&Manually Start Playing"), this);
     action->setStatusTip(tr("Manually start playing videos"));
-    action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_B));
+    action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_T));
     action->setCheckable(true);
     connect(action, SIGNAL(toggled(bool)), SLOT(setManualPlay(bool)));
     actions->insert("manualplay", action);
@@ -409,50 +469,60 @@ void MainWindow::createActions() {
     action->setStatusTip(tr("Show details about video downloads"));
     action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_J));
     action->setCheckable(true);
-    action->setIcon(Utils::icon("go-down"));
+    action->setIcon(IconUtils::icon("document-save"));
     action->setVisible(false);
     connect(action, SIGNAL(toggled(bool)), SLOT(toggleDownloads(bool)));
     actions->insert("downloads", action);
 
     action = new QAction(tr("&Download"), this);
     action->setStatusTip(tr("Download the current video"));
-#ifndef APP_NO_DOWNLOADS
     action->setShortcut(QKeySequence::Save);
-#endif
-    action->setIcon(Utils::icon("go-down"));
+    action->setIcon(IconUtils::icon("document-save"));
     action->setEnabled(false);
-#if QT_VERSION >= 0x040600
+    action->setVisible(false);
     action->setPriority(QAction::LowPriority);
-#endif
     connect(action, SIGNAL(triggered()), mediaView, SLOT(downloadVideo()));
     actions->insert("download", action);
 
-    /*
-    action = new QAction(tr("&Snapshot"), this);
-    action->setShortcut(QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_S));
+#ifdef APP_SNAPSHOT
+    action = new QAction(tr("Take &Snapshot"), this);
+    action->setShortcut(QKeySequence(Qt::Key_F9));
+    action->setEnabled(false);
     actions->insert("snapshot", action);
     connect(action, SIGNAL(triggered()), mediaView, SLOT(snapshot()));
-    */
+#endif
+
+    action = new QAction(tr("&Subscribe to Channel"), this);
+    action->setProperty("originalText", action->text());
+    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);
 
     QString shareTip = tr("Share the current video using %1");
 
     action = new QAction("&Twitter", this);
     action->setStatusTip(shareTip.arg("Twitter"));
+    action->setEnabled(false);
     actions->insert("twitter", action);
     connect(action, SIGNAL(triggered()), mediaView, SLOT(shareViaTwitter()));
 
     action = new QAction("&Facebook", this);
     action->setStatusTip(shareTip.arg("Facebook"));
+    action->setEnabled(false);
     actions->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);
     action->setStatusTip(shareTip.arg(tr("Email")));
+    action->setEnabled(false);
     actions->insert("email", action);
     connect(action, SIGNAL(triggered()), mediaView, SLOT(shareViaEmail()));
 
@@ -466,12 +536,12 @@ void MainWindow::createActions() {
     actions->insert("restore", action);
     connect(action, SIGNAL(triggered()), SLOT(restore()));
 
-    action = new QAction(Utils::icon("go-top"), tr("&Float on Top"), this);
+    action = new QAction(IconUtils::icon("go-top"), tr("&Float on Top"), this);
     action->setCheckable(true);
     actions->insert("ontop", action);
     connect(action, SIGNAL(toggled(bool)), SLOT(floatOnTop(bool)));
 
-    action = new QAction(Utils::icon("media-playback-stop"), tr("&Stop After This Video"), this);
+    action = new QAction(IconUtils::icon("media-playback-stop"), tr("&Stop After This Video"), this);
     action->setShortcut(QKeySequence(Qt::SHIFT + Qt::Key_Escape));
     action->setCheckable(true);
     action->setEnabled(false);
@@ -497,42 +567,42 @@ void MainWindow::createActions() {
     action = new QAction(tr("More..."), this);
     actions->insert("more-region", action);
 
-    action = new QAction(Utils::icon("related-videos"), tr("&Related Videos"), this);
+    action = new QAction(IconUtils::icon("view-list"), tr("&Related Videos"), this);
     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);
 
+    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);
+    connect(action, SIGNAL(triggered()), mediaView, SLOT(openInBrowser()));
+
+#ifdef APP_MAC_STORE
+    action = new QAction(tr("&Love %1? Rate it!").arg(Constants::NAME), this);
+    actions->insert("app-store", action);
+    connect(action, SIGNAL(triggered()), SLOT(rateOnAppStore()));
+#endif
+
 #ifdef APP_ACTIVATION
     Extra::createActivationAction(tr("Buy %1...").arg(Constants::NAME));
 #endif
 
     // common action properties
     foreach (QAction *action, actions->values()) {
-
         // add actions to the MainWindow so that they work
         // when the menu is hidden
         addAction(action);
-
-        // never autorepeat.
-        // unexperienced users tend to keep keys pressed for a "long" time
-        action->setAutoRepeat(false);
-
-        // set to something more meaningful then the toolbar text
-        if (!action->statusTip().isEmpty())
-            action->setToolTip(action->statusTip());
-
-        // show keyboard shortcuts in the status bar
-        if (!action->shortcut().isEmpty())
-            action->setStatusTip(action->statusTip() + " (" + action->shortcut().toString(QKeySequence::NativeText) + ")");
+        IconUtils::setupAction(action);
     }
-
 }
 
 void MainWindow::createMenus() {
 
-    QMap<QString, QMenu*> *menus = The::globalMenus();
+    QHash<QString, QMenu*> *menus = The::globalMenus();
 
     fileMenu = menuBar()->addMenu(tr("&Application"));
 #ifdef APP_ACTIVATION
@@ -576,13 +646,16 @@ void MainWindow::createMenus() {
     videoMenu->addAction(The::globalActions()->value("related-videos"));
     videoMenu->addAction(findVideoPartsAct);
     videoMenu->addSeparator();
-    videoMenu->addAction(webPageAct);
+    videoMenu->addAction(The::globalActions()->value("subscribe-channel"));
+#ifdef APP_SNAPSHOT
     videoMenu->addSeparator();
-#ifndef APP_NO_DOWNLOADS
-    videoMenu->addAction(The::globalActions()->value("download"));
-    // videoMenu->addAction(copyLinkAct);
+    videoMenu->addAction(The::globalActions()->value("snapshot"));
 #endif
-    // videoMenu->addAction(The::globalActions()->value("snapshot"));
+    videoMenu->addSeparator();
+    videoMenu->addAction(webPageAct);
+    videoMenu->addAction(copyLinkAct);
+    videoMenu->addAction(The::globalActions()->value("open-in-browser"));
+    videoMenu->addAction(The::globalActions()->value("download"));
 
     QMenu* viewMenu = menuBar()->addMenu(tr("&View"));
     menus->insert("view", viewMenu);
@@ -612,6 +685,11 @@ void MainWindow::createMenus() {
 #endif
     helpMenu->addAction(The::globalActions()->value("report-issue"));
     helpMenu->addAction(aboutAct);
+
+#ifdef APP_MAC_STORE
+    helpMenu->addSeparator();
+    helpMenu->addAction(The::globalActions()->value("app-store"));
+#endif
 }
 
 void MainWindow::createToolBars() {
@@ -619,11 +697,7 @@ void MainWindow::createToolBars() {
     setUnifiedTitleAndToolBarOnMac(true);
 
     mainToolBar = new QToolBar(this);
-#if QT_VERSION < 0x040600 | defined(APP_MAC)
     mainToolBar->setToolButtonStyle(Qt::ToolButtonIconOnly);
-#else
-    mainToolBar->setToolButtonStyle(Qt::ToolButtonFollowStyle);
-#endif
     mainToolBar->setFloatable(false);
     mainToolBar->setMovable(false);
 
@@ -634,18 +708,16 @@ void MainWindow::createToolBars() {
     mainToolBar->addAction(stopAct);
     mainToolBar->addAction(pauseAct);
     mainToolBar->addAction(skipAct);
+
     mainToolBar->addAction(The::globalActions()->value("related-videos"));
+    mainToolBar->addAction(The::globalActions()->value("download"));
 
     bool addFullScreenAct = true;
-#ifdef Q_WS_MAC
+#ifdef Q_OS_MAC
     addFullScreenAct = !mac::CanGoFullScreen(winId());
 #endif
     if (addFullScreenAct) mainToolBar->addAction(fullscreenAct);
 
-#ifndef APP_NO_DOWNLOADS
-    mainToolBar->addAction(The::globalActions()->value("download"));
-#endif
-
     mainToolBar->addWidget(new Spacer());
 
     QFont smallerFont = FontUtils::small();
@@ -655,29 +727,37 @@ void MainWindow::createToolBars() {
 
     mainToolBar->addWidget(new Spacer());
 
+#ifdef APP_PHONON_SEEK
     seekSlider = new Phonon::SeekSlider(this);
+    seekSlider->setTracking(true);
     seekSlider->setIconVisible(false);
     seekSlider->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
     mainToolBar->addWidget(seekSlider);
-
-    /*
-    mainToolBar->addWidget(new Spacer());
-    slider = new QSlider(this);
+#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 Q_WS_X11
+    QToolButton *volumeMuteButton = qobject_cast<QToolButton *>(mainToolBar->widgetForAction(volumeMuteAct));
+    volumeMuteButton->setIcon(volumeMuteButton->icon().pixmap(16));
+#endif
 
+#ifdef APP_PHONON
     volumeSlider = new Phonon::VolumeSlider(this);
     volumeSlider->setMuteVisible(false);
     // qDebug() << volumeSlider->children();
@@ -689,6 +769,7 @@ void MainWindow::createToolBars() {
     // this makes the volume slider smaller
     volumeSlider->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
     mainToolBar->addWidget(volumeSlider);
+#endif
 
     mainToolBar->addWidget(new Spacer());
 
@@ -700,16 +781,14 @@ void MainWindow::createToolBars() {
 #endif
     toolbarSearch->setMinimumWidth(toolbarSearch->fontInfo().pixelSize()*15);
     toolbarSearch->setSuggester(new YTSuggester(this));
-    connect(toolbarSearch, SIGNAL(search(const QString&)), this, SLOT(startToolbarSearch(const QString&)));
-    connect(toolbarSearch, SIGNAL(suggestionAccepted(const QString&)), SLOT(startToolbarSearch(const QString&)));
+    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
     mainToolBar->addWidget(searchWrapper);
 #else
     mainToolBar->addWidget(toolbarSearch);
-    Spacer* spacer = new Spacer();
-    // spacer->setWidth(4);
-    mainToolBar->addWidget(spacer);
+    mainToolBar->addWidget(new Spacer());
 #endif
 
     addToolBar(mainToolBar);
@@ -723,7 +802,6 @@ void MainWindow::createStatusBar() {
 
     regionButton = new QToolButton(this);
     regionButton->setStatusTip(tr("Choose your content location"));
-    regionButton->setIcon(Utils::icon("go-down"));
     regionButton->setIconSize(QSize(16, 16));
     regionButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
     regionAction = statusToolBar->addWidget(regionButton);
@@ -761,6 +839,9 @@ void MainWindow::showStopAfterThisInStatusBar(bool show) {
 }
 
 void MainWindow::showActionInStatusBar(QAction* action, bool show) {
+#ifdef APP_EXTRA
+    Extra::fadeInWidget(statusBar(), statusBar());
+#endif
     if (show) {
         statusToolBar->insertAction(statusToolBar->actions().first(), action);
     } else {
@@ -778,9 +859,8 @@ void MainWindow::readSettings() {
     } else {
         setGeometry(100, 100, 1000, 500);
     }
-    setDefinitionMode(settings.value("definition", VideoDefinition::getDefinitionNames().first()).toString());
-    audioOutput->setVolume(settings.value("volume", 1).toDouble());
-    audioOutput->setMuted(settings.value("volumeMute").toBool());
+    const VideoDefinition& firstDefinition = VideoDefinition::getDefinitions().first();
+    setDefinitionMode(settings.value("definition", firstDefinition.getName()).toString());
     The::globalActions()->value("manualplay")->setChecked(settings.value("manualplay", false).toBool());
 }
 
@@ -790,8 +870,12 @@ void MainWindow::writeSettings() {
     settings.setValue("geometry", saveGeometry());
     mediaView->saveSplitterState();
 
-    settings.setValue("volume", audioOutput->volume());
-    settings.setValue("volumeMute", audioOutput->isMuted());
+#ifdef APP_PHONON
+    if (audioOutput->volume() > 0.1)
+        settings.setValue("volume", audioOutput->volume());
+    // settings.setValue("volumeMute", audioOutput->isMuted());
+#endif
+
     settings.setValue("manualplay", The::globalActions()->value("manualplay")->isChecked());
 }
 
@@ -804,7 +888,6 @@ void MainWindow::goBack() {
 }
 
 void MainWindow::showWidget(QWidget* widget, bool transition) {
-
     if (compactViewAct->isChecked())
         compactViewAct->toggle();
 
@@ -821,7 +904,6 @@ void MainWindow::showWidget(QWidget* widget, bool transition) {
     View* newView = dynamic_cast<View *> (widget);
     if (newView) {
         widget->setEnabled(true);
-        newView->appear();
         QHash<QString,QVariant> metadata = newView->metadata();
         QString title = metadata.value("title").toString();
         if (title.isEmpty()) title = Constants::NAME;
@@ -829,36 +911,26 @@ void MainWindow::showWidget(QWidget* widget, bool transition) {
         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;
 
     stopAct->setEnabled(isMediaView);
     compactViewAct->setEnabled(isMediaView);
-    webPageAct->setEnabled(isMediaView);
-    copyPageAct->setEnabled(isMediaView);
-    copyLinkAct->setEnabled(isMediaView);
-    findVideoPartsAct->setEnabled(isMediaView);
-    The::globalActions()->value("related-videos")->setEnabled(isMediaView);
     toolbarSearch->setEnabled(widget == homeView || isMediaView || widget == downloadView);
 
-    if (widget == homeView) {
-        skipAct->setEnabled(false);
-        The::globalActions()->value("previous")->setEnabled(false);
-        The::globalActions()->value("download")->setEnabled(false);
-        The::globalActions()->value("stopafterthis")->setEnabled(false);
-    }
-
-    The::globalActions()->value("twitter")->setEnabled(isMediaView);
-    The::globalActions()->value("facebook")->setEnabled(isMediaView);
-    The::globalActions()->value("buffer")->setEnabled(isMediaView);
-    The::globalActions()->value("email")->setEnabled(isMediaView);
-
     aboutAct->setEnabled(widget != aboutView);
     The::globalActions()->value("downloads")->setChecked(widget == downloadView);
 
-    setUpdatesEnabled(true);
-
     QWidget *oldWidget = views->currentWidget();
     if (oldWidget)
         oldWidget->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
@@ -866,9 +938,14 @@ void MainWindow::showWidget(QWidget* widget, bool transition) {
     views->setCurrentWidget(widget);
     widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
 
-#ifndef Q_WS_X11
-    if (transition && oldWidget != mediaView)
+    setUpdatesEnabled(true);
+
+#ifdef APP_EXTRA
+    // if (transition && (oldWidget != mediaView || !mediaView->getVideoArea()->isVideoShown()))
+    if (transition)
         Extra::fadeInWidget(oldWidget, widget);
+#else
+    Q_UNUSED(transition);
 #endif
 
     history->push(widget);
@@ -909,7 +986,11 @@ void MainWindow::quit() {
     if (!m_fullscreen && !compactViewAct->isChecked()) {
         writeSettings();
     }
+    // mediaView->stop();
     Temporary::deleteAll();
+    ChannelAggregator::instance()->stop();
+    ChannelAggregator::instance()->cleanup();
+    Database::shutdown();
     qApp->quit();
 }
 
@@ -952,19 +1033,20 @@ bool MainWindow::confirmQuit() {
 void MainWindow::showHome(bool transition) {
     showWidget(homeView, transition);
     currentTime->clear();
-    totalTime->clear();
+    // totalTime->clear();
 }
 
 void MainWindow::showMedia(SearchParams *searchParams) {
-    mediaView->search(searchParams);
     showWidget(mediaView);
+    mediaView->search(searchParams);
 }
 
 void MainWindow::showMedia(VideoSource *videoSource) {
-    mediaView->setVideoSource(videoSource);
     showWidget(mediaView);
+    mediaView->setVideoSource(videoSource);
 }
 
+#ifdef APP_PHONON
 void MainWindow::stateChanged(Phonon::State newState, Phonon::State /* oldState */) {
 
     // qDebug() << "Phonon state: " << newState;
@@ -983,7 +1065,7 @@ void MainWindow::stateChanged(Phonon::State newState, Phonon::State /* oldState
 
     case Phonon::PlayingState:
         pauseAct->setEnabled(true);
-        pauseAct->setIcon(Utils::icon("media-playback-pause"));
+        pauseAct->setIcon(IconUtils::icon("media-playback-pause"));
         pauseAct->setText(tr("&Pause"));
         pauseAct->setStatusTip(tr("Pause playback") + " (" +  pauseAct->shortcut().toString(QKeySequence::NativeText) + ")");
         // stopAct->setEnabled(true);
@@ -991,22 +1073,31 @@ void MainWindow::stateChanged(Phonon::State newState, Phonon::State /* oldState
 
     case Phonon::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);
         break;
 
     case Phonon::PausedState:
         pauseAct->setEnabled(true);
-        pauseAct->setIcon(Utils::icon("media-playback-start"));
+        pauseAct->setIcon(IconUtils::icon("media-playback-start"));
         pauseAct->setText(tr("&Play"));
         pauseAct->setStatusTip(tr("Resume playback") + " (" +  pauseAct->shortcut().toString(QKeySequence::NativeText) + ")");
         // stopAct->setEnabled(true);
         break;
 
     case Phonon::BufferingState:
+        pauseAct->setEnabled(false);
+        pauseAct->setIcon(IconUtils::icon("content-loading"));
+        pauseAct->setText(tr("&Loading..."));
+        pauseAct->setStatusTip(QString());
+        break;
+
     case Phonon::LoadingState:
         pauseAct->setEnabled(false);
         currentTime->clear();
-        totalTime->clear();
+        // totalTime->clear();
         // stopAct->setEnabled(true);
         break;
 
@@ -1014,14 +1105,15 @@ void MainWindow::stateChanged(Phonon::State newState, Phonon::State /* oldState
         ;
     }
 }
+#endif
 
 void MainWindow::stop() {
-    mediaView->stop();
     showHome();
+    mediaView->stop();
 }
 
 void MainWindow::resizeEvent(QResizeEvent*) {
-#ifdef Q_WS_MAC
+#ifdef Q_OS_MAC
     if (mac::CanGoFullScreen(winId())) {
         bool isFullscreen = mac::IsFullScreen(winId());
         if (isFullscreen != m_fullscreen) {
@@ -1041,7 +1133,7 @@ void MainWindow::fullscreen() {
     if (compactViewAct->isChecked())
         compactViewAct->toggle();
 
-#ifdef Q_WS_MAC
+#ifdef Q_OS_MAC
     WId handle = winId();
     if (mac::CanGoFullScreen(handle)) {
         mainToolBar->setVisible(true);
@@ -1061,7 +1153,7 @@ void MainWindow::fullscreen() {
         // geometry won't be saved
         writeSettings();
 
-#ifdef Q_WS_MAC
+#ifdef Q_OS_MAC
         MacSupport::enterFullScreen(this, views);
 #else
         mainToolBar->hide();
@@ -1071,7 +1163,7 @@ void MainWindow::fullscreen() {
     } else {
         // Exit full screen
 
-#ifdef Q_WS_MAC
+#ifdef Q_OS_MAC
         MacSupport::exitFullScreen(this, views);
 #else
         mainToolBar->show();
@@ -1098,9 +1190,11 @@ void MainWindow::updateUIForFullscreen() {
         fullscreenAct->setShortcuts(QList<QKeySequence>(fsShortcuts)
                                     << QKeySequence(Qt::Key_Escape));
         fullscreenAct->setText(tr("Leave &Full Screen"));
+        fullscreenAct->setIcon(IconUtils::icon("view-restore"));
     } else {
         fullscreenAct->setShortcuts(fsShortcuts);
         fullscreenAct->setText(fsText);
+        fullscreenAct->setIcon(IconUtils::icon("view-fullscreen"));
     }
 
     // No compact view action when in full screen
@@ -1121,7 +1215,7 @@ void MainWindow::updateUIForFullscreen() {
         stopAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::Key_Escape) << QKeySequence(Qt::Key_MediaStop));
     }
 
-#ifdef Q_WS_MAC
+#ifdef Q_OS_MAC
     MacSupport::fullScreenActions(The::globalActions()->values(), m_fullscreen);
 #endif
 
@@ -1136,7 +1230,18 @@ void MainWindow::updateUIForFullscreen() {
     }
 }
 
+bool MainWindow::isReallyFullScreen() {
+#ifdef Q_OS_MAC
+    WId handle = winId();
+    if (mac::CanGoFullScreen(handle)) return mac::IsFullScreen(handle);
+    else return isFullScreen();
+#else
+    return isFullScreen();
+#endif
+}
+
 void MainWindow::compactView(bool enable) {
+    m_compact = enable;
 
     static QList<QKeySequence> compactShortcuts;
     static QList<QKeySequence> stopShortcuts;
@@ -1149,8 +1254,8 @@ void MainWindow::compactView(bool enable) {
 #endif
 
     if (enable) {
-        setMinimumSize(160, 120);
-#ifdef Q_WS_MAC
+        setMinimumSize(320, 180);
+#ifdef Q_OS_MAC
         mac::RemoveFullScreenWindow(winId());
 #endif
         writeSettings();
@@ -1158,7 +1263,7 @@ void MainWindow::compactView(bool enable) {
         if (settings.contains(key))
             restoreGeometry(settings.value(key).toByteArray());
         else
-            resize(320, 240);
+            resize(320, 180);
 
         mainToolBar->setVisible(!enable);
         mediaView->setPlaylistVisible(!enable);
@@ -1179,7 +1284,7 @@ void MainWindow::compactView(bool enable) {
     } else {
         // unset minimum size
         setMinimumSize(0, 0);
-#ifdef Q_WS_MAC
+#ifdef Q_OS_MAC
         mac::SetupFullScreenWindow(winId());
 #endif
         settings.setValue(key, saveGeometry());
@@ -1194,6 +1299,10 @@ void MainWindow::compactView(bool enable) {
 
     // auto float on top
     floatOnTop(enable);
+
+#ifdef Q_OS_MAC
+    mac::compactMode(winId(), enable);
+#endif
 }
 
 void MainWindow::searchFocus() {
@@ -1201,6 +1310,7 @@ void MainWindow::searchFocus() {
     toolbarSearch->setFocus();
 }
 
+#ifdef APP_PHONON
 void MainWindow::initPhonon() {
     // Phonon initialization
     if (mediaObject) delete mediaObject;
@@ -1208,16 +1318,27 @@ void MainWindow::initPhonon() {
     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)));
-    seekSlider->setMediaObject(mediaObject);
+            SLOT(stateChanged(Phonon::State, Phonon::State)));
+    connect(mediaObject, SIGNAL(tick(qint64)), SLOT(tick(qint64)));
+    connect(mediaObject, SIGNAL(totalTimeChanged(qint64)), SLOT(totalTimeChanged(qint64)));
+
     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);
+    connect(audioOutput, SIGNAL(volumeChanged(qreal)), SLOT(volumeChanged(qreal)));
+    connect(audioOutput, SIGNAL(mutedChanged(bool)), SLOT(volumeMutedChanged(bool)));
     Phonon::createPath(mediaObject, audioOutput);
+    volumeSlider->setAudioOutput(audioOutput);
+
+#ifdef APP_PHONON_SEEK
+    seekSlider->setMediaObject(mediaObject);
+#endif
+
+    QSettings settings;
+    audioOutput->setVolume(settings.value("volume", 1.).toReal());
+    // audioOutput->setMuted(settings.value("volumeMute").toBool());
+
+    mediaObject->stop();
 }
+#endif
 
 void MainWindow::tick(qint64 time) {
     if (time <= 0) {
@@ -1230,22 +1351,28 @@ void MainWindow::tick(qint64 time) {
     currentTime->setText(formatTime(time));
 
     // remaining time
+#ifdef APP_PHONON
     const qint64 remainingTime = mediaObject->remainingTime();
     currentTime->setStatusTip(tr("Remaining time: %1").arg(formatTime(remainingTime)));
 
-    /*
+#ifndef APP_PHONON_SEEK
+    const qint64 totalTime = mediaObject->totalTime();
     slider->blockSignals(true);
-    slider->setValue(time/1000);
+    // 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();
+        // totalTime->clear();
         return;
     }
-    totalTime->setText(formatTime(time));
+    // totalTime->setText(formatTime(time));
 
     /*
     slider->blockSignals(true);
@@ -1268,41 +1395,73 @@ QString MainWindow::formatTime(qint64 time) {
 }
 
 void MainWindow::volumeUp() {
+#ifdef APP_PHONON
     qreal newVolume = volumeSlider->audioOutput()->volume() + .1;
     if (newVolume > volumeSlider->maximumVolume())
         newVolume = volumeSlider->maximumVolume();
     volumeSlider->audioOutput()->setVolume(newVolume);
+#endif
 }
 
 void MainWindow::volumeDown() {
+#ifdef APP_PHONON
     qreal newVolume = volumeSlider->audioOutput()->volume() - .1;
-    if (newVolume < 0)
-        newVolume = 0;
+    if (newVolume < 0.)
+        newVolume = 0.;
     volumeSlider->audioOutput()->setVolume(newVolume);
+#endif
 }
 
 void MainWindow::volumeMute() {
-    volumeSlider->audioOutput()->setMuted(!volumeSlider->audioOutput()->isMuted());
+#ifdef APP_PHONON
+    bool muted = volumeSlider->audioOutput()->isMuted();
+    volumeSlider->audioOutput()->setMuted(!muted);
+    qApp->processEvents();
+    if (muted && volumeSlider->audioOutput()->volume() == 0) {
+        volumeSlider->audioOutput()->setVolume(volumeSlider->maximumVolume());
+    }
+    qDebug() << volumeSlider->audioOutput()->isMuted() << volumeSlider->audioOutput()->volume();
+#endif
 }
 
 void MainWindow::volumeChanged(qreal newVolume) {
+#ifdef APP_PHONON
     // automatically unmute when volume changes
-    if (volumeSlider->audioOutput()->isMuted())
-        volumeSlider->audioOutput()->setMuted(false);
+    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<QSlider*>();
+        style()->unpolish(volumeQSlider);
+        style()->polish(volumeQSlider);
+    }
+#endif
     statusBar()->showMessage(tr("Volume at %1%").arg((int)(newVolume*100)));
 }
 
 void MainWindow::volumeMutedChanged(bool muted) {
     if (muted) {
-        volumeMuteAct->setIcon(Utils::icon("audio-volume-muted"));
+        volumeMuteAct->setIcon(IconUtils::icon("audio-volume-muted"));
         statusBar()->showMessage(tr("Volume is muted"));
     } else {
-        volumeMuteAct->setIcon(Utils::icon("audio-volume-high"));
+        volumeMuteAct->setIcon(IconUtils::icon("audio-volume-high"));
         statusBar()->showMessage(tr("Volume is unmuted"));
     }
+#ifdef Q_WS_X11
+    QToolButton *volumeMuteButton = qobject_cast<QToolButton *>(mainToolBar->widgetForAction(volumeMuteAct));
+    volumeMuteButton->setIcon(volumeMuteButton->icon().pixmap(16));
+#endif
 }
 
-void MainWindow::setDefinitionMode(QString definitionName) {
+void MainWindow::setDefinitionMode(const QString &definitionName) {
     QAction *definitionAct = The::globalActions()->value("definition");
     definitionAct->setText(definitionName);
     definitionAct->setStatusTip(tr("Maximum video definition set to %1").arg(definitionAct->text())
@@ -1313,16 +1472,22 @@ void MainWindow::setDefinitionMode(QString 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;
+    const QString definitionName = QSettings().value("definition").toString();
+    const QList<VideoDefinition>& definitions = VideoDefinition::getDefinitions();
+    const VideoDefinition& currentDefinition = VideoDefinition::getDefinitionFor(definitionName);
+    if (currentDefinition.isEmpty()) {
+        setDefinitionMode(definitions.first().getName());
+        return;
+    }
+
+    int index = definitions.indexOf(currentDefinition);
+    if (index != definitions.size() - 1) {
+        index++;
+    } else {
+        index = 0;
     }
-    QString nextDefinition = definitionNames.at(nextIndex);
-    setDefinitionMode(nextDefinition);
+    // TODO: pass a VideoDefinition instead of QString.
+    setDefinitionMode(definitions.at(index).getName());
 }
 
 void MainWindow::showFullscreenToolbar(bool show) {
@@ -1344,6 +1509,8 @@ void MainWindow::clearRecentKeywords() {
         searchView->updateRecentKeywords();
         searchView->updateRecentChannels();
     }
+    QAbstractNetworkCache *cache = The::networkAccessManager()->cache();
+    if (cache) cache->clear();
     showMessage(tr("Your privacy is now safe"));
 }
 
@@ -1353,7 +1520,7 @@ void MainWindow::setManualPlay(bool enabled) {
     showActionInStatusBar(The::globalActions()->value("manualplay"), enabled);
 }
 
-void MainWindow::updateDownloadMessage(QString message) {
+void MainWindow::updateDownloadMessage(const QString &message) {
     The::globalActions()->value("downloads")->setText(message);
 }
 
@@ -1383,40 +1550,38 @@ void MainWindow::toggleDownloads(bool show) {
     else goBack();
 }
 
-void MainWindow::startToolbarSearch(QString query) {
-    query = query.trimmed();
-
-    // check for empty query
-    if (query.length() == 0) {
-        return;
-    }
+void MainWindow::suggestionAccepted(Suggestion *suggestion) {
+    search(suggestion->value);
+}
 
+void MainWindow::search(const QString &query) {
+    QString q = query.trimmed();
+    if (q.length() == 0) return;
     SearchParams *searchParams = new SearchParams();
-    searchParams->setKeywords(query);
-
-    // go!
+    searchParams->setKeywords(q);
     showMedia(searchParams);
 }
 
 void MainWindow::dragEnterEvent(QDragEnterEvent *event) {
     if (event->mimeData()->hasFormat("text/uri-list")) {
         QList<QUrl> urls = event->mimeData()->urls();
-        if (urls.isEmpty())
-            return;
+        if (urls.isEmpty()) return;
         QUrl url = urls.first();
         QString videoId = YTSearch::videoIdFromUrl(url.toString());
-        if (!videoId.isNull())
+        if (!videoId.isEmpty())
             event->acceptProposedAction();
     }
 }
 
 void MainWindow::dropEvent(QDropEvent *event) {
+    if (!toolbarSearch->isEnabled()) return;
+
     QList<QUrl> urls = event->mimeData()->urls();
     if (urls.isEmpty())
         return;
     QUrl url = urls.first();
     QString videoId = YTSearch::videoIdFromUrl(url.toString());
-    if (!videoId.isNull()) {
+    if (!videoId.isEmpty()) {
         setWindowTitle(url.toString());
         SearchParams *searchParams = new SearchParams();
         searchParams->setKeywords(videoId);
@@ -1444,7 +1609,7 @@ void MainWindow::checkForUpdate() {
     settings.setValue(updateCheckKey, unixTime);
 }
 
-void MainWindow::gotNewVersion(QString version) {
+void MainWindow::gotNewVersion(const QString &version) {
     if (updateChecker) {
         delete updateChecker;
         updateChecker = 0;
@@ -1454,16 +1619,17 @@ void MainWindow::gotNewVersion(QString version) {
     QString checkedVersion = settings.value("checkedVersion").toString();
     if (checkedVersion == version) return;
 
-#ifdef APP_SIMPLEUPDATE
-    simpleUpdateDialog(version);
-#endif
-#if defined(APP_ACTIVATION) && !defined(APP_MAC)
+#ifdef APP_EXTRA
+#ifndef APP_MAC
     UpdateDialog *dialog = new UpdateDialog(version, this);
     dialog->show();
 #endif
+#else
+    simpleUpdateDialog(version);
+#endif
 }
 
-void MainWindow::simpleUpdateDialog(QString version) {
+void MainWindow::simpleUpdateDialog(const QString &version) {
     QMessageBox msgBox(this);
     msgBox.setIconPixmap(
                 QPixmap(":/images/app.png")
@@ -1504,12 +1670,14 @@ void MainWindow::restore() {
 }
 
 void MainWindow::messageReceived(const QString &message) {
-    if (message == "--toggle-playing") {
+    if (message == QLatin1String("--toggle-playing")) {
         if (pauseAct->isEnabled()) pauseAct->trigger();
-    } else if (message == "--next") {
+    } else if (message == QLatin1String("--next")) {
         if (skipAct->isEnabled()) skipAct->trigger();
-    } else if (message == "--previous") {
+    } 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("--")) {
         MainWindow::printHelp();
     } else if (!message.isEmpty()) {
@@ -1527,6 +1695,14 @@ void MainWindow::hideMouse() {
 #endif
 }
 
+#ifdef APP_MAC_STORE
+void MainWindow::rateOnAppStore() {
+    QDesktopServices::openUrl(QUrl("macappstore://userpub.itunes.apple.com"
+                                   "/WebObjects/MZUserPublishing.woa/wa/addUserReview"
+                                   "?id=422006190&type=Purple+Software"));
+}
+#endif
+
 void MainWindow::printHelp() {
     QString msg = QString("%1 %2\n\n").arg(Constants::NAME, Constants::VERSION);
     msg += "Usage: minitube [options]\n";
@@ -1537,10 +1713,12 @@ void MainWindow::printHelp() {
     msg += "Skip to the next video.\n";
     msg += "  --previous\t\t";
     msg += "Go back to the previous video.\n";
+    msg += "  --stop-after-this\t";
+    msg += "Stop playback at the end of the video.\n";
     std::cout << msg.toLocal8Bit().data();
 }
 
-void MainWindow::showMessage(QString message) {
+void MainWindow::showMessage(const QString &message) {
     statusBar()->showMessage(message, 60000);
 }