]> git.sur5r.net Git - minitube/blobdiff - src/mainwindow.cpp
Views refactoring, don't use RTTI
[minitube] / src / mainwindow.cpp
index c427d91f9aa7fc8c9571d4d3d3867d5d0c2917b6..a77ac272e2a470fc95249bf544350a38dadcb4bc 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"
 #include "downloadview.h"
 #include "spacer.h"
 #include "constants.h"
-#include "iconloader/qticonloader.h"
+#include "iconutils.h"
 #include "global.h"
 #include "videodefinition.h"
 #include "fontutils.h"
 #include "globalshortcuts.h"
-#ifdef Q_WS_X11
+#include "searchparams.h"
+#include "videosource.h"
+#include "ytsearch.h"
+#ifdef APP_LINUX
 #include "gnomeglobalshortcutbackend.h"
 #endif
-#ifdef Q_WS_MAC
+#ifdef Q_OS_MAC
 #include "mac_startup.h"
 #include "macfullscreen.h"
 #include "macsupport.h"
 #include "macutils.h"
 #endif
 #include "downloadmanager.h"
-#include "youtubesuggest.h"
+#include "ytsuggester.h"
 #include "updatechecker.h"
 #include "temporary.h"
-#ifdef APP_MAC
+#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 <iostream>
-#ifndef Q_WS_X11
+#ifdef APP_EXTRA
 #include "extra.h"
 #include "updatedialog.h"
 #endif
 #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 "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;
 }
 
 MainWindow::MainWindow() :
-        updateChecker(0),
-        aboutView(0),
-        downloadView(0),
-        mediaObject(0),
-        audioOutput(0),
-        m_fullscreen(false) {
+    updateChecker(0),
+    aboutView(0),
+    downloadView(0),
+    regionsView(0),
+    mainToolBar(0),
+    #ifdef APP_PHONON
+    mediaObject(0),
+    audioOutput(0),
+    #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);
+
+    messageLabel = new QLabel();
+    messageLabel->setWindowFlags(Qt::ToolTip | Qt::FramelessWindowHint);
+    messageLabel->setStyleSheet("padding:5px;border:1px solid #808080;background:palette(window)");
+    messageLabel->hide();
+    adjustMessageLabelPosition();
+    messageTimer = new QTimer(this);
+    messageTimer->setInterval(5000);
+    messageTimer->setSingleShot(true);
+    connect(messageTimer, SIGNAL(timeout()), messageLabel, SLOT(hide()));
+    connect(messageTimer, SIGNAL(timeout()), messageLabel, SLOT(clear()));
 
     // views
-    homeView = new HomeView(this);
+    homeView = new HomeView();
     views->addWidget(homeView);
 
     // TODO make this lazy
-    mediaView = new MediaView(this);
+    mediaView = MediaView::instance();
     mediaView->setEnabled(false);
     views->addWidget(mediaView);
 
@@ -76,16 +136,9 @@ MainWindow::MainWindow() :
     createToolBars();
     createStatusBar();
 
-    initPhonon();
-    mediaView->setSlider(seekSlider);
-    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);
 
@@ -95,12 +148,12 @@ 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);
 
+    views->show();
+
     // show the initial view
     showHome(false);
 
@@ -109,15 +162,43 @@ MainWindow::MainWindow() :
         showActivationView(false);
 #endif
 
-    setCentralWidget(views);
+    QTimer::singleShot(0, 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 APP_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()));
@@ -138,35 +219,42 @@ MainWindow::MainWindow() :
     mouseTimer->setSingleShot(true);
     connect(mouseTimer, SIGNAL(timeout()), SLOT(hideMouse()));
 
-    QTimer::singleShot(0, this, SLOT(checkForUpdate()));
+    JsFunctions::instance();
 
-}
+    checkForUpdate();
 
-MainWindow::~MainWindow() {
-    delete history;
+    // Hack to give focus to searchlineedit
+    QMetaObject::invokeMethod(views->currentWidget(), "appear");
+    View* view = qobject_cast<View *> (views->currentWidget());
+    QString desc = view->metadata().value("description").toString();
+    if (!desc.isEmpty()) showMessage(desc);
+
+    ChannelAggregator::instance()->start();
 }
 
-void MainWindow::changeEvent(QEvent* event) {
+void MainWindow::changeEvent(QEvent *e) {
 #ifdef APP_MAC
-    if (event->type() == QEvent::WindowStateChange) {
+    if (e->type() == QEvent::WindowStateChange) {
         The::globalActions()->value("minimize")->setEnabled(!isMinimized());
     }
 #endif
-    QMainWindow::changeEvent(event);
+    QMainWindow::changeEvent(e);
 }
 
-bool MainWindow::eventFilter(QObject *obj, QEvent *event) {
+bool MainWindow::eventFilter(QObject *obj, QEvent *e) {
 
-    if (m_fullscreen && event->type() == QEvent::MouseMove) {
+    if (m_fullscreen && e->type() == QEvent::MouseMove) {
 
-        QMouseEvent *mouseEvent = static_cast<QMouseEvent*> (event);
+        QMouseEvent *mouseEvent = static_cast<QMouseEvent*> (e);
         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);
@@ -188,52 +276,49 @@ bool MainWindow::eventFilter(QObject *obj, QEvent *event) {
 
     }
 
-    if (event->type() == QEvent::ToolTip) {
+    if (e->type() == QEvent::ToolTip) {
         // kill tooltips
         return true;
     }
     // standard event processing
-    return QMainWindow::eventFilter(obj, event);
+    return QMainWindow::eventFilter(obj, e);
 }
 
 void MainWindow::createActions() {
 
-    QMap<QString, QAction*> *actions = The::globalActions();
+    QHash<QString, QAction*> *actions = The::globalActions();
 
-    stopAct = new QAction(QtIconLoader::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(
-                QtIconLoader::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(QtIconLoader::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(QtIconLoader::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(QtIconLoader::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
@@ -243,9 +328,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()));
 
@@ -369,15 +452,20 @@ void MainWindow::createActions() {
     addAction(volumeDownAct);
 
     volumeMuteAct = new QAction(this);
-    volumeMuteAct->setIcon(QtIconLoader::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(QtIconLoader::icon("video-display"));
+#ifdef APP_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);
@@ -392,9 +480,9 @@ void MainWindow::createActions() {
 
     QAction *action;
 
-    action = new QAction(QtIconLoader::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);
@@ -403,50 +491,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(QtIconLoader::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(QtIconLoader::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()));
 
@@ -460,12 +558,17 @@ void MainWindow::createActions() {
     actions->insert("restore", action);
     connect(action, SIGNAL(triggered()), SLOT(restore()));
 
-    action = new QAction(QtIconLoader::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(QtIconLoader::icon("media-playback-stop"), tr("&Stop After This Video"), this);
+    action = new QAction(tr("&Adjust Window Size"), this);
+    action->setCheckable(true);
+    actions->insert("adjustwindowsize", action);
+    connect(action, SIGNAL(toggled(bool)), SLOT(adjustWindowSizeChanged(bool)));
+
+    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);
@@ -477,39 +580,55 @@ void MainWindow::createActions() {
     connect(action, SIGNAL(triggered()), SLOT(reportIssue()));
 
     action = new QAction(tr("&Refine Search..."), this);
-    action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_R));
+    action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_E));
     action->setCheckable(true);
+    action->setEnabled(false);
     actions->insert("refine-search", action);
 
+    action = new QAction(YTRegions::worldwideRegion().name, this);
+    actions->insert("worldwide-region", action);
+
+    action = new QAction(YTRegions::localRegion().name, this);
+    actions->insert("local-region", action);
+
+    action = new QAction(tr("More..."), this);
+    actions->insert("more-region", action);
+
+    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
@@ -550,21 +669,27 @@ void MainWindow::createMenus() {
 
     QMenu* videoMenu = menuBar()->addMenu(tr("&Video"));
     menus->insert("video", videoMenu);
+    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);
     viewMenu->addAction(fullscreenAct);
     viewMenu->addAction(compactViewAct);
     viewMenu->addSeparator();
+    viewMenu->addAction(The::globalActions()->value("adjustwindowsize"));
+    viewMenu->addSeparator();
     viewMenu->addAction(The::globalActions()->value("ontop"));
 
     QMenu* shareMenu = menuBar()->addMenu(tr("&Share"));
@@ -588,21 +713,75 @@ 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() {
 
-    setUnifiedTitleAndToolBarOnMac(true);
+    // Create widgets
 
-    mainToolBar = new QToolBar(this);
-#if QT_VERSION < 0x040600 | defined(APP_MAC)
-    mainToolBar->setToolButtonStyle(Qt::ToolButtonIconOnly);
+    currentTime = new QLabel("00:00");
+    currentTime->setFont(FontUtils::small());
+
+#ifdef APP_PHONON_SEEK
+    seekSlider = new Phonon::SeekSlider();
+    seekSlider->setTracking(true);
+    seekSlider->setIconVisible(false);
+    seekSlider->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
+#else
+    slider = new SeekSlider(this);
+    slider->setEnabled(false);
+    slider->setTracking(false);
+    slider->setMaximum(1000);
+    slider->setOrientation(Qt::Horizontal);
+    slider->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
+#endif
+
+#ifdef APP_PHONON
+    volumeSlider = new Phonon::VolumeSlider();
+    volumeSlider->setMuteVisible(false);
+    // qDebug() << volumeSlider->children();
+    // status tip for the volume slider
+    QSlider* volumeQSlider = volumeSlider->findChild<QSlider*>();
+    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)));
+    // this makes the volume slider smaller
+    volumeSlider->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+#endif
+
+#if defined(APP_MAC_SEARCHFIELD) && !defined(APP_MAC_QMACTOOLBAR)
+    SearchWrapper* searchWrapper = new SearchWrapper(this);
+    toolbarSearch = searchWrapper->getSearchLineEdit();
 #else
-    mainToolBar->setToolButtonStyle(Qt::ToolButtonFollowStyle);
+    toolbarSearch = new SearchLineEdit(this);
+    qDebug() << "Qt SearchLineEdit" << toolbarSearch;
+#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());
+
+    // Add widgets to toolbar
+
+#ifdef APP_MAC_QMACTOOLBAR
+    currentTime->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)
     mainToolBar->setIconSize(QSize(32, 32));
 #endif
@@ -610,95 +789,83 @@ 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();
-    currentTime = new QLabel(mainToolBar);
-    currentTime->setFont(smallerFont);
     mainToolBar->addWidget(currentTime);
-
     mainToolBar->addWidget(new Spacer());
-
-    seekSlider = new Phonon::SeekSlider(this);
-    seekSlider->setIconVisible(false);
-    seekSlider->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
+#ifdef APP_PHONON_SEEK
     mainToolBar->addWidget(seekSlider);
-
-/*
-    mainToolBar->addWidget(new Spacer());
-    slider = new QSlider(this);
-    slider->setOrientation(Qt::Horizontal);
-    slider->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
+#else
     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_LINUX
+    QToolButton *volumeMuteButton = qobject_cast<QToolButton *>(mainToolBar->widgetForAction(volumeMuteAct));
+    volumeMuteButton->setIcon(volumeMuteButton->icon().pixmap(16));
+#endif
 
-    volumeSlider = new Phonon::VolumeSlider(this);
-    volumeSlider->setMuteVisible(false);
-    // qDebug() << volumeSlider->children();
-    // status tip for the volume slider
-    QSlider* volumeQSlider = volumeSlider->findChild<QSlider*>();
-    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)));
-    // this makes the volume slider smaller
-    volumeSlider->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+#ifdef APP_PHONON
     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 YouTubeSuggest(this));
-    connect(toolbarSearch, SIGNAL(search(const QString&)), this, SLOT(startToolbarSearch(const QString&)));
-    connect(toolbarSearch, SIGNAL(suggestionAccepted(const QString&)), SLOT(startToolbarSearch(const QString&)));
-    toolbarSearch->setStatusTip(searchFocusAct->statusTip());
-#ifdef APP_MAC
+#if defined(APP_MAC_SEARCHFIELD) && !defined(APP_MAC_QMACTOOLBAR)
     mainToolBar->addWidget(searchWrapper);
 #else
     mainToolBar->addWidget(toolbarSearch);
-    Spacer* spacer = new Spacer();
-    // spacer->setWidth(4);
-    mainToolBar->addWidget(spacer);
+    mainToolBar->addWidget(new Spacer());
 #endif
 
     addToolBar(mainToolBar);
 }
 
 void MainWindow::createStatusBar() {
-    QToolBar* toolBar = new QToolBar(this);
-    statusToolBar = toolBar;
-    toolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
-    toolBar->setIconSize(QSize(16, 16));
-    toolBar->addAction(The::globalActions()->value("downloads"));
-    toolBar->addAction(The::globalActions()->value("definition"));
-    statusBar()->addPermanentWidget(toolBar);
-    statusBar()->show();
+    statusToolBar = new QToolBar(this);
+    statusToolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+    statusToolBar->setIconSize(QSize(16, 16));
+    // statusToolBar->addAction(The::globalActions()->value("downloads"));
+
+    regionAction = new QAction(this);
+    regionAction->setStatusTip(tr("Choose your content location"));
+
+    QAction *localAction = The::globalActions()->value("local-region");
+    if (!localAction->text().isEmpty()) {
+        QMenu *regionMenu = new QMenu(this);
+        regionMenu->addAction(The::globalActions()->value("worldwide-region"));
+        regionMenu->addAction(localAction);
+        regionMenu->addSeparator();
+        QAction *moreRegionsAction = The::globalActions()->value("more-region");
+        regionMenu->addAction(moreRegionsAction);
+        connect(moreRegionsAction, SIGNAL(triggered()), SLOT(showRegionsView()));
+        regionAction->setMenu(regionMenu);
+    } else {
+        connect(regionAction, SIGNAL(triggered()), SLOT(showRegionsView()));
+    }
+
+    /* Stupid code that generates the QRC items
+    foreach(YTRegion r, YTRegions::list())
+        qDebug() << QString("<file>flags/%1.png</file>").arg(r.id.toLower());
+    */
+
+    statusBar()->addPermanentWidget(statusToolBar);
 }
 
 void MainWindow::showStopAfterThisInStatusBar(bool show) {
@@ -707,27 +874,54 @@ 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);
+        if (statusBar()->isHidden() && !m_fullscreen)
+            setStatusBarVisibility(true);
     } else {
         statusToolBar->removeAction(action);
+        if (statusBar()->isVisible() && !needStatusBar())
+            if (m_fullscreen && views->currentWidget() == mediaView)
+                setStatusBarVisibility(false);
     }
 }
 
+void MainWindow::setStatusBarVisibility(bool show) {
+    statusBar()->setVisible(show);
+    if (views->currentWidget() == mediaView)
+        QTimer::singleShot(0, mediaView, SLOT(maybeAdjustWindowSize()));
+}
+
+void MainWindow::adjustStatusBarVisibility() {
+    setStatusBarVisibility(needStatusBar());
+}
+
 void MainWindow::readSettings() {
     QSettings settings;
     if (settings.contains("geometry")) {
         restoreGeometry(settings.value("geometry").toByteArray());
 #ifdef APP_MAC
-    MacSupport::fixGeometry(this);
+        MacSupport::fixGeometry(this);
 #endif
     } else {
-        setGeometry(100, 100, 1000, 500);
+        const QRect desktopSize = qApp->desktop()->availableGeometry();
+        int w = qMin(2000, desktopSize.width());
+        int h = qMin(w / 3, desktopSize.height());
+        setGeometry(
+                    QStyle::alignedRect(
+                        Qt::LeftToRight,
+                        Qt::AlignTop,
+                        QSize(w, h),
+                        desktopSize)
+                    );
     }
-    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());
+    The::globalActions()->value("adjustwindowsize")->setChecked(settings.value("adjustWindowSize", true).toBool());
 }
 
 void MainWindow::writeSettings() {
@@ -736,8 +930,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());
 }
 
@@ -750,59 +948,27 @@ void MainWindow::goBack() {
 }
 
 void MainWindow::showWidget(QWidget* widget, bool transition) {
+    Q_UNUSED(transition);
 
     if (compactViewAct->isChecked())
         compactViewAct->toggle();
 
-    setUpdatesEnabled(false);
-
     // call hide method on the current view
-    View* oldView = dynamic_cast<View *> (views->currentWidget());
+    View* oldView = qobject_cast<View *> (views->currentWidget());
     if (oldView) {
         oldView->disappear();
         views->currentWidget()->setEnabled(false);
     } else qDebug() << "Cannot cast view";
 
-    // call show method on the new view
-    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 += " - ";
-        setWindowTitle(title + Constants::NAME);
-        QString desc = metadata.value("description").toString();
-        if (!desc.isEmpty()) showMessage(desc);
-    }
-
     const bool isMediaView = widget == mediaView;
 
     stopAct->setEnabled(isMediaView);
     compactViewAct->setEnabled(isMediaView);
-    webPageAct->setEnabled(isMediaView);
-    copyPageAct->setEnabled(isMediaView);
-    copyLinkAct->setEnabled(isMediaView);
-    findVideoPartsAct->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);
@@ -810,9 +976,34 @@ void MainWindow::showWidget(QWidget* widget, bool transition) {
     views->setCurrentWidget(widget);
     widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
 
-#ifndef Q_WS_X11
-    if (transition) Extra::fadeInWidget(oldWidget, widget);
-#endif
+    // call show method on the new view
+    View* newView = qobject_cast<View *> (widget);
+    if (newView) {
+        widget->setEnabled(true);
+        QHash<QString,QVariant> metadata = newView->metadata();
+
+        QString title = metadata.value("title").toString();
+        if (title.isEmpty()) title = Constants::NAME;
+        else title += QLatin1String(" - ") + Constants::NAME;
+        setWindowTitle(title);
+
+        // dynamic view actions
+        foreach (QAction* action, viewActions)
+            showActionInStatusBar(action, false);
+        viewActions = newView->getViewActions();
+        foreach (QAction* action, viewActions)
+            showActionInStatusBar(action, true);
+
+        newView->appear();
+
+        adjustStatusBarVisibility();
+        messageLabel->hide();
+
+        /*
+        QString desc = metadata.value("description").toString();
+        if (!desc.isEmpty()) showMessage(desc);
+        */
+    }
 
     history->push(widget);
 }
@@ -827,13 +1018,13 @@ void MainWindow::about() {
 
 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())));
+    showMessage(QString(tr("Opening %1").arg(url.toString())));
     QDesktopServices::openUrl(url);
 }
 
@@ -852,21 +1043,33 @@ void MainWindow::quit() {
     if (!m_fullscreen && !compactViewAct->isChecked()) {
         writeSettings();
     }
+    // mediaView->stop();
     Temporary::deleteAll();
+    ChannelAggregator::instance()->stop();
+    ChannelAggregator::instance()->cleanup();
+    Database::shutdown();
     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
 }
 
@@ -895,14 +1098,20 @@ bool MainWindow::confirmQuit() {
 void MainWindow::showHome(bool transition) {
     showWidget(homeView, transition);
     currentTime->clear();
-    totalTime->clear();
+    // totalTime->clear();
 }
 
 void MainWindow::showMedia(SearchParams *searchParams) {
+    showWidget(mediaView);
     mediaView->search(searchParams);
+}
+
+void MainWindow::showMedia(VideoSource *videoSource) {
     showWidget(mediaView);
+    mediaView->setVideoSource(videoSource);
 }
 
+#ifdef APP_PHONON
 void MainWindow::stateChanged(Phonon::State newState, Phonon::State /* oldState */) {
 
     // qDebug() << "Phonon state: " << newState;
@@ -913,53 +1122,64 @@ void MainWindow::stateChanged(Phonon::State newState, Phonon::State /* oldState
         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()));
+            // showMessage(tr("Fatal error: %1").arg(mediaObject->errorString()));
         } else {
-            statusBar()->showMessage(tr("Error: %1").arg(mediaObject->errorString()));
+            showMessage(tr("Error: %1").arg(mediaObject->errorString()));
         }
         break;
 
-         case Phonon::PlayingState:
+    case Phonon::PlayingState:
         pauseAct->setEnabled(true);
-        pauseAct->setIcon(QtIconLoader::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);
         break;
 
-         case Phonon::StoppedState:
+    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:
+    case Phonon::PausedState:
         pauseAct->setEnabled(true);
-        pauseAct->setIcon(QtIconLoader::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:
-         case Phonon::LoadingState:
+    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;
 
-         default:
+    default:
         ;
     }
 }
+#endif
 
 void MainWindow::stop() {
-    mediaView->stop();
     showHome();
+    mediaView->stop();
 }
 
-void MainWindow::resizeEvent(QResizeEvent*) {
-#ifdef Q_WS_MAC
+void MainWindow::resizeEvent(QResizeEvent*e) {
+    Q_UNUSED(e);
+#ifdef APP_MAC
     if (mac::CanGoFullScreen(winId())) {
         bool isFullscreen = mac::IsFullScreen(winId());
         if (isFullscreen != m_fullscreen) {
@@ -972,6 +1192,15 @@ void MainWindow::resizeEvent(QResizeEvent*) {
         }
     }
 #endif
+#ifdef APP_MAC_QMACTOOLBAR
+    toolbarSearch->move(width() - toolbarSearch->width() - 13, -38);
+#endif
+    adjustMessageLabelPosition();
+}
+
+void MainWindow::moveEvent(QMoveEvent *e) {
+    Q_UNUSED(e);
+    adjustMessageLabelPosition();
 }
 
 void MainWindow::fullscreen() {
@@ -979,17 +1208,17 @@ void MainWindow::fullscreen() {
     if (compactViewAct->isChecked())
         compactViewAct->toggle();
 
-#ifdef Q_WS_MAC
+    m_fullscreen = !m_fullscreen;
+
+#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;
-
     if (m_fullscreen) {
         // Enter full screen
 
@@ -999,20 +1228,20 @@ void MainWindow::fullscreen() {
         // geometry won't be saved
         writeSettings();
 
-#ifdef Q_WS_MAC
+#ifdef APP_MAC
         MacSupport::enterFullScreen(this, views);
 #else
-        mainToolBar->hide();
+        if (mainToolBar) mainToolBar->hide();
         showFullScreen();
 #endif
 
     } else {
         // Exit full screen
 
-#ifdef Q_WS_MAC
+#ifdef APP_MAC
         MacSupport::exitFullScreen(this, views);
 #else
-        mainToolBar->show();
+        if (mainToolBar) mainToolBar->show();
         if (m_maximized) showMaximized();
         else showNormal();
 #endif
@@ -1036,9 +1265,14 @@ void MainWindow::updateUIForFullscreen() {
         fullscreenAct->setShortcuts(QList<QKeySequence>(fsShortcuts)
                                     << QKeySequence(Qt::Key_Escape));
         fullscreenAct->setText(tr("Leave &Full Screen"));
+        fullscreenAct->setIcon(IconUtils::icon("view-restore"));
+        setStatusBarVisibility(false);
     } else {
         fullscreenAct->setShortcuts(fsShortcuts);
         fullscreenAct->setText(fsText);
+        fullscreenAct->setIcon(IconUtils::icon("view-fullscreen"));
+
+        if (needStatusBar()) setStatusBarVisibility(true);
     }
 
     // No compact view action when in full screen
@@ -1047,7 +1281,7 @@ void MainWindow::updateUIForFullscreen() {
 
     // Hide anything but the video
     mediaView->setPlaylistVisible(!m_fullscreen);
-    statusBar()->setVisible(!m_fullscreen);
+    if (mainToolBar) mainToolBar->setVisible(!m_fullscreen);
 
 #ifndef APP_MAC
     menuBar()->setVisible(!m_fullscreen);
@@ -1059,7 +1293,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
 
@@ -1074,7 +1308,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;
@@ -1087,8 +1332,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();
@@ -1096,11 +1341,15 @@ void MainWindow::compactView(bool enable) {
         if (settings.contains(key))
             restoreGeometry(settings.value(key).toByteArray());
         else
-            resize(320, 240);
+            resize(320, 180);
 
+#ifdef APP_MAC_QMACTOOLBAR
+        mac::showToolBar(winId(), !enable);
+#else
         mainToolBar->setVisible(!enable);
+#endif
         mediaView->setPlaylistVisible(!enable);
-        statusBar()->setVisible(!enable);
+        statusBar()->hide();
 
         compactShortcuts = compactViewAct->shortcuts();
         stopShortcuts = stopAct->shortcuts();
@@ -1117,13 +1366,18 @@ 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());
+#ifdef APP_MAC_QMACTOOLBAR
+        mac::showToolBar(winId(), !enable);
+#else
         mainToolBar->setVisible(!enable);
+#endif
         mediaView->setPlaylistVisible(!enable);
-        statusBar()->setVisible(!enable);
+        if (needStatusBar()) setStatusBarVisibility(true);
+
         readSettings();
 
         compactViewAct->setShortcuts(compactShortcuts);
@@ -1131,7 +1385,11 @@ void MainWindow::compactView(bool enable) {
     }
 
     // auto float on top
-    floatOnTop(enable);
+    floatOnTop(enable, false);
+
+#ifdef Q_OS_MAC
+    mac::compactMode(winId(), enable);
+#endif
 }
 
 void MainWindow::searchFocus() {
@@ -1139,6 +1397,7 @@ void MainWindow::searchFocus() {
     toolbarSearch->setFocus();
 }
 
+#ifdef APP_PHONON
 void MainWindow::initPhonon() {
     // Phonon initialization
     if (mediaObject) delete mediaObject;
@@ -1146,121 +1405,173 @@ 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) {
-        // 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;
+    const QString s = formatTime(time);
+    if (s != currentTime->text()) {
+        currentTime->setText(s);
+        emit currentTimeChanged(s);
     }
 
-    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);
     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
 }
 
 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);
-    statusBar()->showMessage(tr("Volume at %1%").arg((int)(newVolume*100)));
+    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
+    showMessage(tr("Volume at %1%").arg((int)(newVolume*100)));
 }
 
 void MainWindow::volumeMutedChanged(bool muted) {
     if (muted) {
-        volumeMuteAct->setIcon(QtIconLoader::icon("audio-volume-muted"));
-        statusBar()->showMessage(tr("Volume is muted"));
+        volumeMuteAct->setIcon(IconUtils::icon("audio-volume-muted"));
+        showMessage(tr("Volume is muted"));
     } else {
-        volumeMuteAct->setIcon(QtIconLoader::icon("audio-volume-high"));
-        statusBar()->showMessage(tr("Volume is unmuted"));
+        volumeMuteAct->setIcon(IconUtils::icon("audio-volume-high"));
+        showMessage(tr("Volume is unmuted"));
     }
+#ifdef APP_LINUX
+    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())
                                 + " (" +  definitionAct->shortcut().toString(QKeySequence::NativeText) + ")");
-    statusBar()->showMessage(definitionAct->statusTip());
+    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;
+    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;
     }
-    QString nextDefinition = definitionNames.at(nextIndex);
-    setDefinitionMode(nextDefinition);
+
+    int index = definitions.indexOf(currentDefinition);
+    if (index != definitions.size() - 1) {
+        index++;
+    } else {
+        index = 0;
+    }
+    // TODO: pass a VideoDefinition instead of QString.
+    setDefinitionMode(definitions.at(index).getName());
 }
 
 void MainWindow::showFullscreenToolbar(bool show) {
@@ -1282,6 +1593,8 @@ void MainWindow::clearRecentKeywords() {
         searchView->updateRecentKeywords();
         searchView->updateRecentChannels();
     }
+    QAbstractNetworkCache *cache = The::networkAccessManager()->cache();
+    if (cache) cache->clear();
     showMessage(tr("Your privacy is now safe"));
 }
 
@@ -1291,13 +1604,13 @@ 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);
 }
 
 void MainWindow::downloadsFinished() {
     The::globalActions()->value("downloads")->setText(tr("&Downloads"));
-    statusBar()->showMessage(tr("Downloads complete"));
+    showMessage(tr("Downloads complete"));
 }
 
 void MainWindow::toggleDownloads(bool show) {
@@ -1305,11 +1618,11 @@ void MainWindow::toggleDownloads(bool show) {
     if (show) {
         stopAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::Key_MediaStop));
         The::globalActions()->value("downloads")->setShortcuts(
-                QList<QKeySequence>() << QKeySequence(Qt::CTRL + Qt::Key_J)
-                << QKeySequence(Qt::Key_Escape));
+                    QList<QKeySequence>() << QKeySequence(Qt::CTRL + Qt::Key_J)
+                    << QKeySequence(Qt::Key_Escape));
     } else {
         The::globalActions()->value("downloads")->setShortcuts(
-                QList<QKeySequence>() << QKeySequence(Qt::CTRL + Qt::Key_J));
+                    QList<QKeySequence>() << QKeySequence(Qt::CTRL + Qt::Key_J));
         stopAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::Key_Escape) << QKeySequence(Qt::Key_MediaStop));
     }
 
@@ -1321,40 +1634,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;
+void MainWindow::dragEnterEvent(QDragEnterEvent *e) {
+    if (e->mimeData()->hasFormat("text/uri-list")) {
+        QList<QUrl> urls = e->mimeData()->urls();
+        if (urls.isEmpty()) return;
         QUrl url = urls.first();
-        QString videoId = YouTubeSearch::videoIdFromUrl(url.toString());
-        if (!videoId.isNull())
-            event->acceptProposedAction();
+        QString videoId = YTSearch::videoIdFromUrl(url.toString());
+        if (!videoId.isEmpty())
+            e->acceptProposedAction();
     }
 }
 
-void MainWindow::dropEvent(QDropEvent *event) {
-    QList<QUrl> urls = event->mimeData()->urls();
+void MainWindow::dropEvent(QDropEvent *e) {
+    if (!toolbarSearch->isEnabled()) return;
+
+    QList<QUrl> urls = e->mimeData()->urls();
     if (urls.isEmpty())
         return;
     QUrl url = urls.first();
-    QString videoId = YouTubeSearch::videoIdFromUrl(url.toString());
-    if (!videoId.isNull()) {
+    QString videoId = YTSearch::videoIdFromUrl(url.toString());
+    if (!videoId.isEmpty()) {
         setWindowTitle(url.toString());
         SearchParams *searchParams = new SearchParams();
         searchParams->setKeywords(videoId);
@@ -1382,7 +1693,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;
@@ -1392,16 +1703,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")
@@ -1420,8 +1732,19 @@ void MainWindow::simpleUpdateDialog(QString version) {
     if (msgBox.clickedButton() == updateButton) visitSite();
 }
 
-void MainWindow::floatOnTop(bool onTop) {
-    showActionInStatusBar(The::globalActions()->value("ontop"), onTop);
+bool MainWindow::needStatusBar() {
+    return !statusToolBar->actions().isEmpty();
+}
+
+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, bool showAction) {
+    if (showAction) showActionInStatusBar(The::globalActions()->value("ontop"), onTop);
 #ifdef APP_MAC
     mac::floatOnTop(winId(), onTop);
     return;
@@ -1435,6 +1758,13 @@ void MainWindow::floatOnTop(bool onTop) {
     }
 }
 
+void MainWindow::adjustWindowSizeChanged(bool enabled) {
+    QSettings settings;
+    settings.setValue("adjustWindowSize", enabled);
+    if (enabled && views->currentWidget() == mediaView)
+        mediaView->adjustWindowSize();
+}
+
 void MainWindow::restore() {
 #ifdef APP_MAC
     mac::uncloseWindow(window()->winId());
@@ -1442,12 +1772,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()) {
@@ -1465,6 +1797,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";
@@ -1475,11 +1815,25 @@ 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) {
-    statusBar()->showMessage(message, 60000);
+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 {
+        messageLabel->setText(message);
+        messageLabel->resize(messageLabel->sizeHint());
+        adjustMessageLabelPosition();
+        messageLabel->show();
+        messageTimer->start();
+    }
 }
 
 #ifdef APP_ACTIVATION
@@ -1507,3 +1861,13 @@ void MainWindow::hideBuyAction() {
     action->setEnabled(false);
 }
 #endif
+
+void MainWindow::showRegionsView() {
+    if (!regionsView) {
+        regionsView = new RegionsView(this);
+        connect(regionsView, SIGNAL(regionChanged()),
+                homeView->getStandardFeedsView(), SLOT(load()));
+        views->addWidget(regionsView);
+    }
+    showWidget(regionsView);
+}