diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 8fd8b9afa..b7779d32b 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -205,6 +205,7 @@ set(SOURCES
ui/screensaver.cpp
ui/settingsdialog.cpp
ui/systemtrayicon.cpp
+ ui/windows7thumbbar.cpp
widgets/autoexpandingtreeview.cpp
widgets/busyindicator.cpp
@@ -377,6 +378,7 @@ set(HEADERS
ui/qtsystemtrayicon.h
ui/settingsdialog.h
ui/systemtrayicon.h
+ ui/windows7thumbbar.h
widgets/autoexpandingtreeview.h
widgets/busyindicator.h
diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp
index 598fa4eee..2604e0638 100644
--- a/src/ui/mainwindow.cpp
+++ b/src/ui/mainwindow.cpp
@@ -15,10 +15,6 @@
along with Clementine. If not, see .
*/
-#ifdef Q_OS_WIN32
-# define _WIN32_WINNT 0x0600
-#endif
-
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "core/backgroundstreams.h"
@@ -81,6 +77,7 @@
#include "ui/qtsystemtrayicon.h"
#include "ui/settingsdialog.h"
#include "ui/systemtrayicon.h"
+#include "ui/windows7thumbbar.h"
#include "widgets/errordialog.h"
#include "widgets/fileview.h"
#include "widgets/multiloadingindicator.h"
@@ -123,9 +120,6 @@
#ifdef Q_OS_WIN32
# include
-# include
-# include
-# include
#endif
@@ -156,6 +150,7 @@ MainWindow::MainWindow(
QWidget* parent)
: QMainWindow(parent),
ui_(new Ui_MainWindow),
+ thumbbar_(new Windows7ThumbBar(this)),
tray_icon_(tray_icon),
osd_(osd),
task_manager_(task_manager),
@@ -191,8 +186,7 @@ MainWindow::MainWindow(
playlist_menu_(new QMenu(this)),
library_sort_model_(new QSortFilterProxyModel(this)),
track_position_timer_(new QTimer(this)),
- was_maximized_(false),
- taskbar_list_(NULL)
+ was_maximized_(false)
{
// Create some objects in the database thread
playlist_backend_ = new PlaylistBackend;
@@ -499,6 +493,16 @@ MainWindow::MainWindow(
connect(tray_icon_, SIGNAL(ShowHide()), SLOT(ToggleShowHide()));
connect(tray_icon_, SIGNAL(ChangeVolume(int)), SLOT(VolumeWheelEvent(int)));
+ // Windows 7 thumbbar buttons
+ thumbbar_->SetActions(QList()
+ << ui_->action_previous_track
+ << ui_->action_play_pause
+ << ui_->action_stop
+ << ui_->action_next_track
+ << NULL // spacer
+ << ui_->action_love
+ << ui_->action_ban);
+
#if (defined(Q_OS_DARWIN) && defined(HAVE_SPARKLE)) || defined(Q_OS_WIN32)
// Add check for updates item to application menu.
QAction* check_updates = ui_->menu_tools->addAction(tr("Check for updates..."));
@@ -1651,51 +1655,8 @@ void MainWindow::ShowScriptDialog() {
}
#ifdef Q_OS_WIN32
-static const int kTaskbarIconSize = 16;
-
-static void SetButton(const QIcon& icon, const QString& tooltip, uint id,
- THUMBBUTTON* button) {
- button->dwMask = THUMBBUTTONMASK(THB_ICON | THB_TOOLTIP | THB_FLAGS);
- button->iId = id;
- button->dwFlags = THBF_ENABLED;
- button->hIcon = icon.pixmap(kTaskbarIconSize).toWinHICON();
- tooltip.toWCharArray(button->szTip);
-}
-
-bool MainWindow::winEvent(MSG* m, long* result) {
- static UINT sTaskbarButtonCreated = WM_NULL;
-
- if (sTaskbarButtonCreated == WM_NULL) {
- // Compute the value for the TaskbarButtonCreated message
- sTaskbarButtonCreated = RegisterWindowMessage("TaskbarButtonCreated");
- }
-
- if (m->message == sTaskbarButtonCreated) {
- if (!taskbar_list_) {
- // Get the interface
- if (CoCreateInstance(CLSID_ITaskbarList, NULL, CLSCTX_ALL,
- IID_ITaskbarList3, (void**) &taskbar_list_)) {
- qWarning() << "Error creating the ITaskbarList3 interface";
- return false;
- }
-
- ITaskbarList3* taskbar_list = reinterpret_cast(taskbar_list_);
- if (taskbar_list->HrInit()) {
- taskbar_list->Release();
- taskbar_list_ = NULL;
- return false;
- }
-
- // Add the playback control buttons
- THUMBBUTTON buttons[4] = {};
- SetButton(IconLoader::Load("media-skip-backward"), tr("Previous track"), 0, &buttons[0]);
- SetButton(IconLoader::Load("media-playback-start"), tr("Pause"), 1, &buttons[1]);
- SetButton(IconLoader::Load("media-playback-stop"), tr("Stop"), 2, &buttons[2]);
- SetButton(IconLoader::Load("media-skip-forward"), tr("Next track"), 3, &buttons[3]);
-
- taskbar_list->ThumbBarAddButtons(winId(), 4, buttons);
- }
- }
+bool MainWindow::winEvent(MSG* msg, long*) {
+ thumbbar_->HandleWinEvent(msg);
return false;
}
#endif // Q_OS_WIN32
diff --git a/src/ui/mainwindow.h b/src/ui/mainwindow.h
index 9b9d1e2ed..4bbdb83ba 100644
--- a/src/ui/mainwindow.h
+++ b/src/ui/mainwindow.h
@@ -67,6 +67,7 @@ class TaskManager;
class TranscodeDialog;
class VisualisationContainer;
class WiimotedevShortcuts;
+class Windows7ThumbBar;
class Ui_MainWindow;
class QSortFilterProxyModel;
@@ -216,6 +217,7 @@ class MainWindow : public QMainWindow, public PlatformInterface {
private:
Ui_MainWindow* ui_;
+ Windows7ThumbBar* thumbbar_;
SystemTrayIcon* tray_icon_;
OSD* osd_;
@@ -284,9 +286,6 @@ class MainWindow : public QMainWindow, public PlatformInterface {
bool autoclear_playlist_;
BackgroundStreams* background_streams_;
-
- // Really an ITaskbarList3* but I don't want to have to include windows.h here
- void* taskbar_list_;
};
#endif // MAINWINDOW_H
diff --git a/src/ui/windows7thumbbar.cpp b/src/ui/windows7thumbbar.cpp
new file mode 100644
index 000000000..fd14e3ca9
--- /dev/null
+++ b/src/ui/windows7thumbbar.cpp
@@ -0,0 +1,140 @@
+/* This file is part of Clementine.
+ Copyright 2010, David Sansome
+
+ Clementine 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.
+
+ Clementine 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 Clementine. If not, see .
+*/
+
+#include "windows7thumbbar.h"
+
+#include
+#include
+
+#ifdef Q_OS_WIN32
+# define _WIN32_WINNT 0x0600
+# include
+# include
+# include
+#endif // Q_OS_WIN32
+
+
+const int Windows7ThumbBar::kIconSize = 16;
+const int Windows7ThumbBar::kMaxButtonCount = 7;
+
+
+Windows7ThumbBar::Windows7ThumbBar(QWidget* widget)
+ : QObject(widget),
+ widget_(widget),
+ button_created_message_id_(0),
+ taskbar_list_(NULL)
+{
+}
+
+void Windows7ThumbBar::SetActions(const QList& actions) {
+#ifdef Q_OS_WIN32
+ Q_ASSERT(actions.count() <= kMaxButtonCount);
+
+ actions_ = actions;
+ foreach (QAction* action, actions) {
+ if (action) {
+ connect(action, SIGNAL(changed()), SLOT(ActionChanged()));
+ }
+ }
+
+#endif // Q_OS_WIN32
+}
+
+#ifdef Q_OS_WIN32
+static void SetupButton(const QAction* action, THUMBBUTTON* button) {
+ if (action) {
+ button->hIcon = action->icon().pixmap(Windows7ThumbBar::kIconSize).toWinHICON();
+ button->dwFlags = action->isEnabled() ? THBF_ENABLED : THBF_DISABLED;
+ action->text().toWCharArray(button->szTip);
+ button->szTip[action->text().count()] = '\0';
+
+ if (!action->isVisible()) {
+ button->dwFlags = THUMBBUTTONFLAGS(button->dwFlags | THBF_HIDDEN);
+ }
+ } else {
+ button->hIcon = 0;
+ button->szTip[0] = '\0';
+ button->dwFlags = THBF_NOBACKGROUND;
+ }
+}
+#endif // Q_OS_WIN32
+
+void Windows7ThumbBar::HandleWinEvent(MSG* msg) {
+#ifdef Q_OS_WIN32
+ if (button_created_message_id_ == 0) {
+ // Compute the value for the TaskbarButtonCreated message
+ button_created_message_id_ = RegisterWindowMessage("TaskbarButtonCreated");
+ }
+
+ if (msg->message == button_created_message_id_) {
+ if (!taskbar_list_) {
+ // Create the taskbar list for the first time
+ if (CoCreateInstance(CLSID_ITaskbarList, NULL, CLSCTX_ALL,
+ IID_ITaskbarList3, (void**) &taskbar_list_)) {
+ qWarning() << "Error creating the ITaskbarList3 interface";
+ return;
+ }
+
+ ITaskbarList3* taskbar_list = reinterpret_cast(taskbar_list_);
+ if (taskbar_list->HrInit()) {
+ taskbar_list->Release();
+ taskbar_list_ = NULL;
+ return;
+ }
+
+ // Add the buttons
+ THUMBBUTTON buttons[kMaxButtonCount];
+ for (int i=0 ; idwMask = THUMBBUTTONMASK(THB_ICON | THB_TOOLTIP | THB_FLAGS);
+ button->iId = i;
+ SetupButton(action, button);
+ }
+
+ taskbar_list->ThumbBarAddButtons(widget_->winId(), actions_.count(), buttons);
+ }
+ } else if (msg->message == WM_COMMAND) {
+ const int button_id = LOWORD(msg->wParam);
+
+ if (button_id >= 0 && button_id < actions_.count()) {
+ actions_[button_id]->activate(QAction::Trigger);
+ }
+ }
+#endif // Q_OS_WIN32
+}
+
+void Windows7ThumbBar::ActionChanged() {
+#ifdef Q_OS_WIN32
+ if (!taskbar_list_)
+ return;
+ ITaskbarList3* taskbar_list = reinterpret_cast(taskbar_list_);
+
+ THUMBBUTTON buttons[kMaxButtonCount];
+ for (int i=0 ; idwMask = THUMBBUTTONMASK(THB_ICON | THB_TOOLTIP | THB_FLAGS);
+ button->iId = i;
+ SetupButton(action, button);
+ }
+
+ taskbar_list->ThumbBarUpdateButtons(widget_->winId(), actions_.count(), buttons);
+#endif // Q_OS_WIN32
+}
diff --git a/src/ui/windows7thumbbar.h b/src/ui/windows7thumbbar.h
new file mode 100644
index 000000000..70b7f03bc
--- /dev/null
+++ b/src/ui/windows7thumbbar.h
@@ -0,0 +1,59 @@
+/* This file is part of Clementine.
+ Copyright 2010, David Sansome
+
+ Clementine 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.
+
+ Clementine 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 Clementine. If not, see .
+*/
+
+#ifndef WINDOWS7THUMBBAR_H
+#define WINDOWS7THUMBBAR_H
+
+#include
+#include
+
+#ifndef Q_OS_WIN32
+ typedef void MSG;
+#endif // Q_OS_WIN32
+
+class Windows7ThumbBar : public QObject {
+ Q_OBJECT
+
+public:
+ // Creates a list of buttons in the taskbar icon for this window. Does
+ // nothing and is safe to use on other operating systems too.
+ Windows7ThumbBar(QWidget* widget = 0);
+
+ static const int kIconSize;
+ static const int kMaxButtonCount;
+
+ // You must call this in the parent widget's constructor before returning
+ // to the event loop. If an action is NULL it becomes a spacer.
+ void SetActions(const QList& actions);
+
+ // Call this from the parent's winEvent() function.
+ void HandleWinEvent(MSG* msg);
+
+private slots:
+ void ActionChanged();
+
+private:
+ QWidget* widget_;
+ QList actions_;
+
+ unsigned int button_created_message_id_;
+
+ // Really an ITaskbarList3* but I don't want to have to include windows.h here
+ void* taskbar_list_;
+};
+
+#endif // WINDOWS7THUMBBAR_H