PageRenderTime 417ms CodeModel.GetById 60ms app.highlight 248ms RepoModel.GetById 95ms app.codeStats 1ms

/src/tomahawktrayicon.cpp

http://github.com/tomahawk-player/tomahawk
C++ | 351 lines | 249 code | 70 blank | 32 comment | 16 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
 20#include "TomahawkTrayIcon.h"
 21
 22#include "Artist.h"
 23#include "audio/AudioEngine.h"
 24#include "TomahawkApp.h"
 25#include "TomahawkWindow.h"
 26#include "Query.h"
 27#include "Source.h"
 28#include "Collection.h"
 29#include "ActionCollection.h"
 30#include "utils/Logger.h"
 31#include "utils/TomahawkUtilsGui.h"
 32
 33#include <QWheelEvent>
 34
 35TomahawkTrayIcon::TomahawkTrayIcon( QObject* parent )
 36    : QSystemTrayIcon( parent )
 37    , m_currentAnimationFrame( 0 )
 38    , m_showWindowAction( 0 )
 39    , m_stopContinueAfterTrackAction( 0 )
 40    , m_loveTrackAction( 0 )
 41{
 42#ifdef Q_WS_MAC
 43    QIcon icon( RESPATH "icons/tomahawk-icon-128x128-grayscale.png" );
 44#else
 45    QIcon icon( RESPATH "icons/tomahawk-icon-128x128.png" );
 46#endif
 47
 48    setIcon( icon );
 49
 50    refreshToolTip();
 51
 52    m_contextMenu = new QMenu();
 53    setContextMenu( m_contextMenu );
 54
 55    m_loveTrackAction = new QAction( this );
 56    m_stopContinueAfterTrackAction = new QAction( this );
 57
 58    ActionCollection *ac = ActionCollection::instance();
 59    m_contextMenu->addAction( ac->getAction( "playPause" ) );
 60    m_contextMenu->addAction( ac->getAction( "stop" ) );
 61    m_contextMenu->addSeparator();
 62    m_contextMenu->addAction( m_loveTrackAction );
 63    m_contextMenu->addAction( m_stopContinueAfterTrackAction );
 64    m_contextMenu->addSeparator();
 65    m_contextMenu->addAction( ac->getAction( "previousTrack" ) );
 66    m_contextMenu->addAction( ac->getAction( "nextTrack" ) );
 67    m_contextMenu->addSeparator();
 68    m_contextMenu->addAction( ActionCollection::instance()->getAction( "togglePrivacy" ) );
 69
 70#ifdef Q_WS_MAC
 71    // On mac you can close the windows while leaving the app open. We then need a way to show the main window again
 72    m_contextMenu->addSeparator();
 73    m_showWindowAction = m_contextMenu->addAction( tr( "Hide Tomahawk Window" ) );
 74    m_showWindowAction->setData( true );
 75    connect( m_showWindowAction, SIGNAL( triggered() ), this, SLOT( showWindow() ) );
 76
 77    connect( m_contextMenu, SIGNAL( aboutToShow() ), this, SLOT( menuAboutToShow() ) );
 78#endif
 79
 80    m_contextMenu->addSeparator();
 81    m_contextMenu->addAction( ac->getAction( "quit" ) );
 82
 83    connect( m_loveTrackAction, SIGNAL( triggered() ), SLOT( loveTrackTriggered() ) );
 84    connect( m_stopContinueAfterTrackAction, SIGNAL( triggered() ), SLOT( stopContinueAfterTrackActionTriggered() ) );
 85
 86    connect( AudioEngine::instance(), SIGNAL( loading( Tomahawk::result_ptr ) ), SLOT( setResult( Tomahawk::result_ptr ) ) );
 87    connect( AudioEngine::instance(), SIGNAL( started( Tomahawk::result_ptr ) ), SLOT( onPlay() ) );
 88    connect( AudioEngine::instance(), SIGNAL( resumed() ), SLOT( onResume() ) );
 89    connect( AudioEngine::instance(), SIGNAL( stopped() ), SLOT( onStop() ) );
 90    connect( AudioEngine::instance(), SIGNAL( paused() ),  SLOT( onPause() ) );
 91    connect( AudioEngine::instance(), SIGNAL( stopAfterTrackChanged() ), SLOT( onStopContinueAfterTrackChanged() ) );
 92
 93    connect( &m_animationTimer, SIGNAL( timeout() ), SLOT( onAnimationTimer() ) );
 94    connect( this, SIGNAL( activated( QSystemTrayIcon::ActivationReason ) ), SLOT( onActivated( QSystemTrayIcon::ActivationReason ) ) );
 95
 96    onStop();
 97    show();
 98}
 99
100
101TomahawkTrayIcon::~TomahawkTrayIcon()
102{
103    delete m_contextMenu;
104}
105
106
107void
108TomahawkTrayIcon::setShowHideWindow( bool show )
109{
110    if ( show )
111    {
112        m_showWindowAction->setText( tr( "Hide Tomahawk Window" ) );
113        m_showWindowAction->setData( show );
114    }
115    else
116    {
117        m_showWindowAction->setText( tr( "Show Tomahawk Window" ) );
118    }
119
120    m_showWindowAction->setData( show );
121}
122
123
124void
125TomahawkTrayIcon::showWindow()
126{
127    if( !m_showWindowAction->data().toBool() )
128    {
129        APP->mainWindow()->show();
130        APP->mainWindow()->raise();
131
132        setShowHideWindow( true );
133    }
134    else
135    {
136        APP->mainWindow()->hide();
137
138        setShowHideWindow( false );
139    }
140}
141
142
143void
144TomahawkTrayIcon::menuAboutToShow()
145{
146    // When using Cmd-H on mac to hide a window, it is an OS-level hide that is different from QWidget::hide().
147    // Qt returns isVisible() == true for windows that are hidden with Cmd-H, which is weird. isActiveWindow() returns
148    // the proper information though.
149    setShowHideWindow( APP->mainWindow()->isActiveWindow() );
150}
151
152
153void
154TomahawkTrayIcon::setResult( const Tomahawk::result_ptr& result )
155{
156    if ( m_currentTrack )
157    {
158        disconnect( m_currentTrack->toQuery().data(), SIGNAL( socialActionsLoaded() ), this, SLOT( onSocialActionsLoaded() ) );
159    }
160
161    m_currentTrack = result;
162    refreshToolTip();
163
164    if ( result )
165        connect( result->toQuery().data(), SIGNAL( socialActionsLoaded() ), SLOT( onSocialActionsLoaded() ), Qt::UniqueConnection );
166
167    onSocialActionsLoaded();
168    onStopContinueAfterTrackChanged();
169}
170
171
172void
173TomahawkTrayIcon::onStopContinueAfterTrackChanged()
174{
175    if ( m_currentTrack && m_currentTrack->toQuery()->equals( AudioEngine::instance()->stopAfterTrack() ) )
176        m_stopContinueAfterTrackAction->setText( tr( "&Continue Playback after current Track" ) );
177    else
178        m_stopContinueAfterTrackAction->setText( tr( "&Stop Playback after current Track" ) );
179}
180
181
182void
183TomahawkTrayIcon::refreshToolTip()
184{
185    #ifdef Q_WS_MAC
186    // causes issues with OS X menubar, also none
187    // of the other OS X menubar icons have a tooltip
188    return;
189    #endif
190
191    QString tip;
192    if ( !m_currentTrack.isNull() )
193    {
194        tip = m_currentTrack->artist()->name() + " " + QChar( 8211 ) /*en dash*/ + " " + m_currentTrack->track();
195    }
196    else
197    {
198        tip = tr( "Currently not playing." );
199    }
200
201    #ifdef Q_WS_WIN
202        // Good old crappy Win32
203        tip.replace( "&", "&&&" );
204    #endif
205
206    setToolTip( tip );
207}
208
209
210void
211TomahawkTrayIcon::onAnimationTimer()
212{
213/*    m_currentAnimationFrame++;
214    if( m_currentAnimationFrame >= m_animationPixmaps.count() )
215        m_currentAnimationFrame = 0;
216
217    setIcon( m_animationPixmaps.at( m_currentAnimationFrame ) );*/
218}
219
220
221void
222TomahawkTrayIcon::onActivated( QSystemTrayIcon::ActivationReason reason )
223{
224#ifdef Q_WS_MAC
225    return;
226#endif
227
228    switch( reason )
229    {
230        case QSystemTrayIcon::Trigger:
231        {
232            TomahawkWindow* mainwindow = APP->mainWindow();
233            if (mainwindow->isActiveWindow())
234            {
235                mainwindow->hide();
236            }
237            else
238            {
239                TomahawkUtils::bringToFront();
240            }
241        }
242        break;
243
244        case QSystemTrayIcon::MiddleClick:
245        {
246            AudioEngine::instance()->playPause();
247        }
248        break;
249
250        default:
251            break;
252    }
253}
254
255
256void
257TomahawkTrayIcon::onPause()
258{
259    ActionCollection::instance()->getAction( "playPause" )->setText( tr( "Play" ) );
260}
261
262
263void
264TomahawkTrayIcon::onPlay()
265{
266    m_loveTrackAction->setEnabled( true );
267    m_stopContinueAfterTrackAction->setEnabled( true );
268
269    onResume();
270}
271
272
273void
274TomahawkTrayIcon::onStop()
275{
276    m_loveTrackAction->setEnabled( false );
277    m_stopContinueAfterTrackAction->setEnabled( false );
278
279    setResult( Tomahawk::result_ptr() );
280    onPause();
281}
282
283
284void
285TomahawkTrayIcon::onResume()
286{
287    ActionCollection::instance()->getAction( "playPause" )->setText( tr( "Pause" ) );
288}
289
290
291void
292TomahawkTrayIcon::loveTrackTriggered()
293{
294    if ( !m_currentTrack )
295        return;
296
297    m_currentTrack->toQuery()->setLoved( !m_currentTrack->toQuery()->loved() );
298}
299
300
301void
302TomahawkTrayIcon::stopContinueAfterTrackActionTriggered()
303{
304    if ( !m_currentTrack )
305        return;
306
307    if ( !m_currentTrack->toQuery()->equals( AudioEngine::instance()->stopAfterTrack() ) )
308        AudioEngine::instance()->setStopAfterTrack( m_currentTrack->toQuery() );
309    else
310        AudioEngine::instance()->setStopAfterTrack( Tomahawk::query_ptr() );
311}
312
313
314void
315TomahawkTrayIcon::onSocialActionsLoaded()
316{
317    m_loveTrackAction->setText( tr( "&Love" ) );
318    m_loveTrackAction->setIcon( QIcon( RESPATH "images/loved.png" ) );
319
320    if ( !m_currentTrack )
321        return;
322
323    if ( m_currentTrack->toQuery()->loved() )
324    {
325        m_loveTrackAction->setText( tr( "Un-&Love" ) );
326        m_loveTrackAction->setIcon( QIcon( RESPATH "images/not-loved.png" ) );
327    }
328}
329
330
331bool
332TomahawkTrayIcon::event( QEvent* e )
333{
334    // Beginning with Qt 4.3, QSystemTrayIcon supports wheel events, but only
335    // on X11. Let's make it adjust the volume.
336    if ( e->type() == QEvent::Wheel )
337    {
338        if ( ((QWheelEvent*)e)->delta() > 0 )
339        {
340            AudioEngine::instance()->raiseVolume();
341        }
342        else
343        {
344            AudioEngine::instance()->lowerVolume();
345        }
346
347        return true;
348    }
349
350    return QSystemTrayIcon::event( e );
351}