/src/tomahawktrayicon.cpp

http://github.com/tomahawk-player/tomahawk · C++ · 351 lines · 249 code · 70 blank · 32 comment · 17 complexity · d1bdcc49a0b56936676fdd2700283c4d MD5 · raw file

  1. /* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
  2. *
  3. * Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
  4. * Copyright 2010-2011, Jeff Mitchell <jeff@tomahawk-player.org>
  5. *
  6. * Tomahawk is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Tomahawk is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "TomahawkTrayIcon.h"
  20. #include "Artist.h"
  21. #include "audio/AudioEngine.h"
  22. #include "TomahawkApp.h"
  23. #include "TomahawkWindow.h"
  24. #include "Query.h"
  25. #include "Source.h"
  26. #include "Collection.h"
  27. #include "ActionCollection.h"
  28. #include "utils/Logger.h"
  29. #include "utils/TomahawkUtilsGui.h"
  30. #include <QWheelEvent>
  31. TomahawkTrayIcon::TomahawkTrayIcon( QObject* parent )
  32. : QSystemTrayIcon( parent )
  33. , m_currentAnimationFrame( 0 )
  34. , m_showWindowAction( 0 )
  35. , m_stopContinueAfterTrackAction( 0 )
  36. , m_loveTrackAction( 0 )
  37. {
  38. #ifdef Q_WS_MAC
  39. QIcon icon( RESPATH "icons/tomahawk-icon-128x128-grayscale.png" );
  40. #else
  41. QIcon icon( RESPATH "icons/tomahawk-icon-128x128.png" );
  42. #endif
  43. setIcon( icon );
  44. refreshToolTip();
  45. m_contextMenu = new QMenu();
  46. setContextMenu( m_contextMenu );
  47. m_loveTrackAction = new QAction( this );
  48. m_stopContinueAfterTrackAction = new QAction( this );
  49. ActionCollection *ac = ActionCollection::instance();
  50. m_contextMenu->addAction( ac->getAction( "playPause" ) );
  51. m_contextMenu->addAction( ac->getAction( "stop" ) );
  52. m_contextMenu->addSeparator();
  53. m_contextMenu->addAction( m_loveTrackAction );
  54. m_contextMenu->addAction( m_stopContinueAfterTrackAction );
  55. m_contextMenu->addSeparator();
  56. m_contextMenu->addAction( ac->getAction( "previousTrack" ) );
  57. m_contextMenu->addAction( ac->getAction( "nextTrack" ) );
  58. m_contextMenu->addSeparator();
  59. m_contextMenu->addAction( ActionCollection::instance()->getAction( "togglePrivacy" ) );
  60. #ifdef Q_WS_MAC
  61. // On mac you can close the windows while leaving the app open. We then need a way to show the main window again
  62. m_contextMenu->addSeparator();
  63. m_showWindowAction = m_contextMenu->addAction( tr( "Hide Tomahawk Window" ) );
  64. m_showWindowAction->setData( true );
  65. connect( m_showWindowAction, SIGNAL( triggered() ), this, SLOT( showWindow() ) );
  66. connect( m_contextMenu, SIGNAL( aboutToShow() ), this, SLOT( menuAboutToShow() ) );
  67. #endif
  68. m_contextMenu->addSeparator();
  69. m_contextMenu->addAction( ac->getAction( "quit" ) );
  70. connect( m_loveTrackAction, SIGNAL( triggered() ), SLOT( loveTrackTriggered() ) );
  71. connect( m_stopContinueAfterTrackAction, SIGNAL( triggered() ), SLOT( stopContinueAfterTrackActionTriggered() ) );
  72. connect( AudioEngine::instance(), SIGNAL( loading( Tomahawk::result_ptr ) ), SLOT( setResult( Tomahawk::result_ptr ) ) );
  73. connect( AudioEngine::instance(), SIGNAL( started( Tomahawk::result_ptr ) ), SLOT( onPlay() ) );
  74. connect( AudioEngine::instance(), SIGNAL( resumed() ), SLOT( onResume() ) );
  75. connect( AudioEngine::instance(), SIGNAL( stopped() ), SLOT( onStop() ) );
  76. connect( AudioEngine::instance(), SIGNAL( paused() ), SLOT( onPause() ) );
  77. connect( AudioEngine::instance(), SIGNAL( stopAfterTrackChanged() ), SLOT( onStopContinueAfterTrackChanged() ) );
  78. connect( &m_animationTimer, SIGNAL( timeout() ), SLOT( onAnimationTimer() ) );
  79. connect( this, SIGNAL( activated( QSystemTrayIcon::ActivationReason ) ), SLOT( onActivated( QSystemTrayIcon::ActivationReason ) ) );
  80. onStop();
  81. show();
  82. }
  83. TomahawkTrayIcon::~TomahawkTrayIcon()
  84. {
  85. delete m_contextMenu;
  86. }
  87. void
  88. TomahawkTrayIcon::setShowHideWindow( bool show )
  89. {
  90. if ( show )
  91. {
  92. m_showWindowAction->setText( tr( "Hide Tomahawk Window" ) );
  93. m_showWindowAction->setData( show );
  94. }
  95. else
  96. {
  97. m_showWindowAction->setText( tr( "Show Tomahawk Window" ) );
  98. }
  99. m_showWindowAction->setData( show );
  100. }
  101. void
  102. TomahawkTrayIcon::showWindow()
  103. {
  104. if( !m_showWindowAction->data().toBool() )
  105. {
  106. APP->mainWindow()->show();
  107. APP->mainWindow()->raise();
  108. setShowHideWindow( true );
  109. }
  110. else
  111. {
  112. APP->mainWindow()->hide();
  113. setShowHideWindow( false );
  114. }
  115. }
  116. void
  117. TomahawkTrayIcon::menuAboutToShow()
  118. {
  119. // When using Cmd-H on mac to hide a window, it is an OS-level hide that is different from QWidget::hide().
  120. // Qt returns isVisible() == true for windows that are hidden with Cmd-H, which is weird. isActiveWindow() returns
  121. // the proper information though.
  122. setShowHideWindow( APP->mainWindow()->isActiveWindow() );
  123. }
  124. void
  125. TomahawkTrayIcon::setResult( const Tomahawk::result_ptr& result )
  126. {
  127. if ( m_currentTrack )
  128. {
  129. disconnect( m_currentTrack->toQuery().data(), SIGNAL( socialActionsLoaded() ), this, SLOT( onSocialActionsLoaded() ) );
  130. }
  131. m_currentTrack = result;
  132. refreshToolTip();
  133. if ( result )
  134. connect( result->toQuery().data(), SIGNAL( socialActionsLoaded() ), SLOT( onSocialActionsLoaded() ), Qt::UniqueConnection );
  135. onSocialActionsLoaded();
  136. onStopContinueAfterTrackChanged();
  137. }
  138. void
  139. TomahawkTrayIcon::onStopContinueAfterTrackChanged()
  140. {
  141. if ( m_currentTrack && m_currentTrack->toQuery()->equals( AudioEngine::instance()->stopAfterTrack() ) )
  142. m_stopContinueAfterTrackAction->setText( tr( "&Continue Playback after current Track" ) );
  143. else
  144. m_stopContinueAfterTrackAction->setText( tr( "&Stop Playback after current Track" ) );
  145. }
  146. void
  147. TomahawkTrayIcon::refreshToolTip()
  148. {
  149. #ifdef Q_WS_MAC
  150. // causes issues with OS X menubar, also none
  151. // of the other OS X menubar icons have a tooltip
  152. return;
  153. #endif
  154. QString tip;
  155. if ( !m_currentTrack.isNull() )
  156. {
  157. tip = m_currentTrack->artist()->name() + " " + QChar( 8211 ) /*en dash*/ + " " + m_currentTrack->track();
  158. }
  159. else
  160. {
  161. tip = tr( "Currently not playing." );
  162. }
  163. #ifdef Q_WS_WIN
  164. // Good old crappy Win32
  165. tip.replace( "&", "&&&" );
  166. #endif
  167. setToolTip( tip );
  168. }
  169. void
  170. TomahawkTrayIcon::onAnimationTimer()
  171. {
  172. /* m_currentAnimationFrame++;
  173. if( m_currentAnimationFrame >= m_animationPixmaps.count() )
  174. m_currentAnimationFrame = 0;
  175. setIcon( m_animationPixmaps.at( m_currentAnimationFrame ) );*/
  176. }
  177. void
  178. TomahawkTrayIcon::onActivated( QSystemTrayIcon::ActivationReason reason )
  179. {
  180. #ifdef Q_WS_MAC
  181. return;
  182. #endif
  183. switch( reason )
  184. {
  185. case QSystemTrayIcon::Trigger:
  186. {
  187. TomahawkWindow* mainwindow = APP->mainWindow();
  188. if (mainwindow->isActiveWindow())
  189. {
  190. mainwindow->hide();
  191. }
  192. else
  193. {
  194. TomahawkUtils::bringToFront();
  195. }
  196. }
  197. break;
  198. case QSystemTrayIcon::MiddleClick:
  199. {
  200. AudioEngine::instance()->playPause();
  201. }
  202. break;
  203. default:
  204. break;
  205. }
  206. }
  207. void
  208. TomahawkTrayIcon::onPause()
  209. {
  210. ActionCollection::instance()->getAction( "playPause" )->setText( tr( "Play" ) );
  211. }
  212. void
  213. TomahawkTrayIcon::onPlay()
  214. {
  215. m_loveTrackAction->setEnabled( true );
  216. m_stopContinueAfterTrackAction->setEnabled( true );
  217. onResume();
  218. }
  219. void
  220. TomahawkTrayIcon::onStop()
  221. {
  222. m_loveTrackAction->setEnabled( false );
  223. m_stopContinueAfterTrackAction->setEnabled( false );
  224. setResult( Tomahawk::result_ptr() );
  225. onPause();
  226. }
  227. void
  228. TomahawkTrayIcon::onResume()
  229. {
  230. ActionCollection::instance()->getAction( "playPause" )->setText( tr( "Pause" ) );
  231. }
  232. void
  233. TomahawkTrayIcon::loveTrackTriggered()
  234. {
  235. if ( !m_currentTrack )
  236. return;
  237. m_currentTrack->toQuery()->setLoved( !m_currentTrack->toQuery()->loved() );
  238. }
  239. void
  240. TomahawkTrayIcon::stopContinueAfterTrackActionTriggered()
  241. {
  242. if ( !m_currentTrack )
  243. return;
  244. if ( !m_currentTrack->toQuery()->equals( AudioEngine::instance()->stopAfterTrack() ) )
  245. AudioEngine::instance()->setStopAfterTrack( m_currentTrack->toQuery() );
  246. else
  247. AudioEngine::instance()->setStopAfterTrack( Tomahawk::query_ptr() );
  248. }
  249. void
  250. TomahawkTrayIcon::onSocialActionsLoaded()
  251. {
  252. m_loveTrackAction->setText( tr( "&Love" ) );
  253. m_loveTrackAction->setIcon( QIcon( RESPATH "images/loved.png" ) );
  254. if ( !m_currentTrack )
  255. return;
  256. if ( m_currentTrack->toQuery()->loved() )
  257. {
  258. m_loveTrackAction->setText( tr( "Un-&Love" ) );
  259. m_loveTrackAction->setIcon( QIcon( RESPATH "images/not-loved.png" ) );
  260. }
  261. }
  262. bool
  263. TomahawkTrayIcon::event( QEvent* e )
  264. {
  265. // Beginning with Qt 4.3, QSystemTrayIcon supports wheel events, but only
  266. // on X11. Let's make it adjust the volume.
  267. if ( e->type() == QEvent::Wheel )
  268. {
  269. if ( ((QWheelEvent*)e)->delta() > 0 )
  270. {
  271. AudioEngine::instance()->raiseVolume();
  272. }
  273. else
  274. {
  275. AudioEngine::instance()->lowerVolume();
  276. }
  277. return true;
  278. }
  279. return QSystemTrayIcon::event( e );
  280. }