~ubuntu-branches/ubuntu/trusty/tomahawk/trusty-proposed

« back to all changes in this revision

Viewing changes to src/TomahawkWindow.cpp

  • Committer: Package Import Robot
  • Author(s): Harald Sitter
  • Date: 2013-03-07 21:50:13 UTC
  • Revision ID: package-import@ubuntu.com-20130307215013-6gdjkdds7i9uenvs
Tags: upstream-0.6.0+dfsg
ImportĀ upstreamĀ versionĀ 0.6.0+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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-2012, Leo Franchi <lfranchi@kde.org>
 
5
 *   Copyright 2010-2012, Jeff Mitchell <jeff@tomahawk-player.org>
 
6
 *   Copyright 2012,      Teo Mrnjavac <teo@kde.org>
 
7
 *
 
8
 *   Tomahawk is free software: you can redistribute it and/or modify
 
9
 *   it under the terms of the GNU General Public License as published by
 
10
 *   the Free Software Foundation, either version 3 of the License, or
 
11
 *   (at your option) any later version.
 
12
 *
 
13
 *   Tomahawk is distributed in the hope that it will be useful,
 
14
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 
16
 *   GNU General Public License for more details.
 
17
 *
 
18
 *   You should have received a copy of the GNU General Public License
 
19
 *   along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
 
20
 */
 
21
 
 
22
#include "TomahawkWindow.h"
 
23
#include "ui_TomahawkWindow.h"
 
24
 
 
25
#include <QAction>
 
26
#include <QCloseEvent>
 
27
#include <QDesktopServices>
 
28
#include <QShowEvent>
 
29
#include <QHideEvent>
 
30
#include <QInputDialog>
 
31
#include <QPixmap>
 
32
#include <QPropertyAnimation>
 
33
#include <QLineEdit>
 
34
#include <QMessageBox>
 
35
#include <QNetworkAccessManager>
 
36
#include <QNetworkReply>
 
37
#include <QTimer>
 
38
#include <QToolBar>
 
39
#include <QToolButton>
 
40
 
 
41
#include "accounts/AccountManager.h"
 
42
#include "sourcetree/SourceTreeView.h"
 
43
#include "network/Servent.h"
 
44
#include "utils/TomahawkUtilsGui.h"
 
45
#include "utils/ProxyStyle.h"
 
46
#include "utils/WidgetDragFilter.h"
 
47
#include "widgets/AccountsToolButton.h"
 
48
#include "widgets/AnimatedSplitter.h"
 
49
#include "widgets/NewPlaylistWidget.h"
 
50
#include "widgets/SearchWidget.h"
 
51
#include "widgets/PlaylistTypeSelectorDialog.h"
 
52
#include "widgets/ContainedMenuButton.h"
 
53
#include "thirdparty/Qocoa/qsearchfield.h"
 
54
#include "playlist/dynamic/GeneratorInterface.h"
 
55
#include "playlist/PlaylistModel.h"
 
56
#include "playlist/PlaylistView.h"
 
57
#include "playlist/QueueView.h"
 
58
#include "jobview/JobStatusView.h"
 
59
#include "jobview/JobStatusModel.h"
 
60
#include "jobview/ErrorStatusMessage.h"
 
61
#include "jobview/JobStatusModel.h"
 
62
#include "sip/SipPlugin.h"
 
63
#include "filemetadata/ScanManager.h"
 
64
 
 
65
#include "Playlist.h"
 
66
#include "Query.h"
 
67
#include "Artist.h"
 
68
#include "ViewManager.h"
 
69
#include "ActionCollection.h"
 
70
#include "AudioControls.h"
 
71
#include "SettingsDialog.h"
 
72
#include "DiagnosticsDialog.h"
 
73
#include "TomahawkSettings.h"
 
74
#include "SourceList.h"
 
75
#include "TomahawkTrayIcon.h"
 
76
#include "TomahawkApp.h"
 
77
#include "LoadXSPFDialog.h"
 
78
#include "utils/ImageRegistry.h"
 
79
#include "utils/Logger.h"
 
80
 
 
81
#include "config.h"
 
82
 
 
83
#if defined( Q_WS_WIN )
 
84
    #if defined ( WITH_QtSparkle )
 
85
        #include <qtsparkle/Updater>
 
86
    #endif
 
87
 
 
88
    #include <windows.h>
 
89
    #include <shellapi.h>
 
90
 
 
91
    #ifndef THBN_CLICKED
 
92
        #define THBN_CLICKED    0x1800
 
93
    #endif
 
94
#endif
 
95
 
 
96
using namespace Tomahawk;
 
97
using namespace Accounts;
 
98
 
 
99
 
 
100
TomahawkWindow::TomahawkWindow( QWidget* parent )
 
101
    : QMainWindow( parent )
 
102
#ifdef Q_OS_WIN
 
103
    , m_buttonCreatedID( RegisterWindowMessage( L"TaskbarButtonCreated" ) )
 
104
  #ifdef HAVE_THUMBBUTTON
 
105
    , m_taskbarList( 0 )
 
106
  #endif
 
107
#endif
 
108
    , ui( new Ui::TomahawkWindow )
 
109
    , m_searchWidget( 0 )
 
110
    , m_audioControls( new AudioControls( this ) )
 
111
    , m_trayIcon( new TomahawkTrayIcon( this ) )
 
112
    , m_settingsDialog( 0 )
 
113
    , m_audioRetryCounter( 0 )
 
114
{
 
115
    setWindowIcon( QIcon( RESPATH "icons/tomahawk-icon-128x128.png" ) );
 
116
 
 
117
    ViewManager* vm = new ViewManager( this );
 
118
    connect( vm, SIGNAL( showQueueRequested() ), SLOT( showQueue() ) );
 
119
    connect( vm, SIGNAL( hideQueueRequested() ), SLOT( hideQueue() ) );
 
120
    connect( APP, SIGNAL( tomahawkLoaded() ), vm, SLOT( setTomahawkLoaded() ) ); // Pass loaded signal into libtomahawk so components in there can connect to ViewManager
 
121
 
 
122
#ifdef Q_OS_WIN
 
123
    connect( AudioEngine::instance(), SIGNAL( stateChanged( AudioState, AudioState) ), SLOT( audioStateChanged( AudioState, AudioState) ) );
 
124
#endif
 
125
    ui->setupUi( this );
 
126
 
 
127
    applyPlatformTweaks();
 
128
 
 
129
    ui->centralWidget->setContentsMargins( 0, 0, 0, 0 );
 
130
    TomahawkUtils::unmarginLayout( ui->centralWidget->layout() );
 
131
 
 
132
    setupMenuBar();
 
133
    setupToolBar();
 
134
    setupSideBar();
 
135
    statusBar()->addPermanentWidget( m_audioControls, 1 );
 
136
 
 
137
    setupUpdateCheck();
 
138
    loadSettings();
 
139
    setupSignals();
 
140
 
 
141
    if ( qApp->arguments().contains( "--debug" ) )
 
142
    {
 
143
        connect( ActionCollection::instance()->getAction( "crashNow" ), SIGNAL( triggered() ), SLOT( crashNow() ) );
 
144
    }
 
145
 
 
146
    // set initial state
 
147
    audioStopped();
 
148
 
 
149
    vm->setQueue( m_queueView );
 
150
    vm->showWelcomePage();
 
151
 
 
152
    if ( TomahawkSettings::instance()->fullscreenEnabled() )
 
153
    {
 
154
        // Window must be fully constructed to toggle fullscreen mode. Queue it up.
 
155
        QTimer::singleShot( 0, this, SLOT( toggleFullscreen() ) );
 
156
    }
 
157
}
 
158
 
 
159
 
 
160
TomahawkWindow::~TomahawkWindow()
 
161
{
 
162
    saveSettings();
 
163
    delete ui;
 
164
}
 
165
 
 
166
 
 
167
void
 
168
TomahawkWindow::loadSettings()
 
169
{
 
170
    TomahawkSettings* s = TomahawkSettings::instance();
 
171
 
 
172
    // Workaround for broken window geometry restoring on Qt Cocoa when setUnifiedTitleAndToolBarOnMac is true.
 
173
    // See http://bugreports.qt.nokia.com/browse/QTBUG-3116 and
 
174
    // http://lists.qt.nokia.com/pipermail/qt-interest/2009-August/011491.html
 
175
    // for the 'fix'
 
176
#ifdef QT_MAC_USE_COCOA
 
177
     bool workaround = isVisible();
 
178
     if ( workaround )
 
179
     {
 
180
       // make "invisible"
 
181
       setWindowOpacity( 0 );
 
182
       // let Qt update its frameStruts
 
183
       show();
 
184
     }
 
185
#endif
 
186
 
 
187
    if ( !s->mainWindowGeometry().isEmpty() )
 
188
        restoreGeometry( s->mainWindowGeometry() );
 
189
    if ( !s->mainWindowState().isEmpty() )
 
190
        restoreState( s->mainWindowState() );
 
191
    if ( !s->mainWindowSplitterState().isEmpty() )
 
192
        ui->splitter->restoreState( s->mainWindowSplitterState() );
 
193
 
 
194
    // Always set stretch factor. If user hasn't manually set splitter sizes,
 
195
    // this will ensure a sane default on all startups. If the user has, the manual
 
196
    // size will override the default stretching
 
197
    ui->splitter->setStretchFactor( 0, 0 );
 
198
    ui->splitter->setStretchFactor( 1, 1 );
 
199
 
 
200
#ifdef QT_MAC_USE_COCOA
 
201
     if ( workaround )
 
202
     {
 
203
       // Make it visible again
 
204
       setWindowOpacity( 1 );
 
205
     }
 
206
#endif
 
207
 
 
208
#ifndef Q_OS_MAC
 
209
    bool mbVisible = s->menuBarVisible();
 
210
    menuBar()->setVisible( mbVisible );
 
211
    m_compactMenuAction->setVisible( !mbVisible );
 
212
    ActionCollection::instance()->getAction( "toggleMenuBar" )->setText( mbVisible ? tr( "Hide Menu Bar" ) : tr( "Show Menu Bar" ) );
 
213
#endif
 
214
}
 
215
 
 
216
 
 
217
void
 
218
TomahawkWindow::saveSettings()
 
219
{
 
220
    TomahawkSettings* s = TomahawkSettings::instance();
 
221
    s->setMainWindowGeometry( saveGeometry() );
 
222
    s->setMainWindowState( saveState() );
 
223
    s->setMainWindowSplitterState( ui->splitter->saveState() );
 
224
    s->setMenuBarVisible( menuBar()->isVisible() );
 
225
}
 
226
 
 
227
 
 
228
void
 
229
TomahawkWindow::applyPlatformTweaks()
 
230
{
 
231
    // HACK: QtCurve causes an infinite loop on startup. This is because
 
232
    //       setStyle calls setPalette, which calls ensureBaseStyle, which loads
 
233
    //       QtCurve. QtCurve calls setPalette, which creates an infinite loop.
 
234
    //       We could simply not use ProxyStyle under QtCurve, but that would
 
235
    //       make the whole UI look like crap.
 
236
    //       Instead, we tell ProxyStyle that it's running under QtCurve, so it
 
237
    //       can intercept QStyle::polish (which in the base implementation does
 
238
    //       nothing and in QtCurve does evil things), and avoid forwarding it
 
239
    //       to QtCurve.
 
240
    bool isQtCurve = false;
 
241
    if ( QString( qApp->style()->metaObject()->className() ).toLower().contains( "qtcurve" ) )
 
242
        isQtCurve = true;
 
243
    qApp->setStyle( new ProxyStyle( isQtCurve ) );
 
244
 
 
245
#ifdef Q_OS_MAC
 
246
    setUnifiedTitleAndToolBarOnMac( true );
 
247
    delete ui->hline1;
 
248
    delete ui->hline2;
 
249
#else
 
250
    ui->hline1->setStyleSheet( "border: 1px solid gray;" );
 
251
    ui->hline2->setStyleSheet( "border: 1px solid gray;" );
 
252
#endif
 
253
}
 
254
 
 
255
 
 
256
void
 
257
TomahawkWindow::setupToolBar()
 
258
{
 
259
    m_toolbar = addToolBar( "TomahawkToolbar" );
 
260
    m_toolbar->setObjectName( "TomahawkToolbar" );
 
261
    m_toolbar->setMovable( false );
 
262
    m_toolbar->setFloatable( false );
 
263
    m_toolbar->setIconSize( QSize( 22, 22 ) );
 
264
    m_toolbar->setToolButtonStyle( Qt::ToolButtonIconOnly );
 
265
    m_toolbar->setStyleSheet( "border-bottom: 0px" );
 
266
    // If the toolbar is hidden accidentally it causes trouble on Unity because the user can't
 
267
    // easily bring it back (TWK-1046). So we just prevent the user from hiding the toolbar.
 
268
    // This should not affect Mac users.
 
269
    m_toolbar->setContextMenuPolicy( Qt::PreventContextMenu );
 
270
 
 
271
#ifdef Q_OS_MAC
 
272
    m_toolbar->installEventFilter( new WidgetDragFilter( m_toolbar ) );
 
273
#endif
 
274
 
 
275
    m_backAction = m_toolbar->addAction( ImageRegistry::instance()->icon( RESPATH "images/back.svg" ), tr( "Back" ), ViewManager::instance(), SLOT( historyBack() ) );
 
276
    m_backAction->setToolTip( tr( "Go back one page" ) );
 
277
    m_forwardAction = m_toolbar->addAction( ImageRegistry::instance()->icon( RESPATH "images/forward.svg" ), tr( "Forward" ), ViewManager::instance(), SLOT( historyForward() ) );
 
278
    m_forwardAction->setToolTip( tr( "Go forward one page" ) );
 
279
 
 
280
    m_toolbarLeftBalancer = new QWidget( this );
 
281
    m_toolbarLeftBalancer->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Preferred );
 
282
    m_toolbarLeftBalancer->setFixedWidth( 0 );
 
283
    m_toolbar->addWidget( m_toolbarLeftBalancer )->setProperty( "kind", QString( "spacer" ) );
 
284
 
 
285
    QWidget* toolbarLeftSpacer = new QWidget( this );
 
286
    toolbarLeftSpacer->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred );
 
287
    m_toolbar->addWidget( toolbarLeftSpacer )->setProperty( "kind", QString( "spacer" ) );
 
288
 
 
289
    m_searchWidget = new QSearchField( this );
 
290
    m_searchWidget->setPlaceholderText( tr( "Search for any artist, album or song..." ) );
 
291
    m_searchWidget->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Preferred );
 
292
    m_searchWidget->setFixedWidth( 340 );
 
293
    connect( m_searchWidget, SIGNAL( returnPressed() ), this, SLOT( onFilterEdited() ) );
 
294
 
 
295
    m_toolbar->addWidget( m_searchWidget )->setProperty( "kind", QString( "search" ) );
 
296
 
 
297
    QWidget* rightSpacer = new QWidget( this );
 
298
    rightSpacer->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred );
 
299
    m_toolbar->addWidget( rightSpacer )->setProperty( "kind", QString( "spacer" ) );
 
300
 
 
301
    m_toolbarRightBalancer = new QWidget( this );
 
302
    m_toolbarRightBalancer->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Preferred );
 
303
    m_toolbarRightBalancer->setFixedWidth( 0 );
 
304
    m_toolbar->addWidget( m_toolbarRightBalancer )->setProperty( "kind", QString( "spacer" ) );
 
305
 
 
306
    m_accountsButton = new AccountsToolButton( m_toolbar );
 
307
    m_toolbar->addWidget( m_accountsButton );
 
308
    connect( m_accountsButton, SIGNAL( widthChanged() ),
 
309
             this, SLOT( balanceToolbar() ) );
 
310
 
 
311
#ifndef Q_OS_MAC
 
312
    ContainedMenuButton* compactMenuButton = new ContainedMenuButton( m_toolbar );
 
313
    compactMenuButton->setIcon( ImageRegistry::instance()->icon( RESPATH "images/configure.svg" ) );
 
314
    compactMenuButton->setText( tr( "&Main Menu" ) );
 
315
    compactMenuButton->setMenu( m_compactMainMenu );
 
316
    compactMenuButton->setToolButtonStyle( Qt::ToolButtonIconOnly );
 
317
    m_compactMenuAction = m_toolbar->addWidget( compactMenuButton );
 
318
    //HACK: adding the toggle action to the window, otherwise the shortcut keys
 
319
    //      won't be picked up when the menu is hidden.
 
320
    //      This must be done for all menu bar actions that have shortcut keys :(
 
321
    //      Does not apply to Mac which always shows the menu bar.
 
322
    addAction( ActionCollection::instance()->getAction( "playPause" ) );
 
323
    addAction( ActionCollection::instance()->getAction( "toggleMenuBar" ) );
 
324
    addAction( ActionCollection::instance()->getAction( "quit" ) );
 
325
#endif
 
326
    balanceToolbar();
 
327
}
 
328
 
 
329
 
 
330
void
 
331
TomahawkWindow::balanceToolbar()
 
332
{
 
333
    int leftActionsWidth = 0;
 
334
    int rightActionsWidth = 0;
 
335
    bool flip = false;
 
336
    foreach ( QAction* action, m_toolbar->actions() )
 
337
    {
 
338
        if ( action->property( "kind" ) == QString( "spacer" ) ||
 
339
            !action->isVisible() )
 
340
            continue;
 
341
        else if ( action->property( "kind" ) == QString( "search" ) )
 
342
        {
 
343
            flip = true;
 
344
            continue;
 
345
        }
 
346
 
 
347
        QWidget* widget = m_toolbar->widgetForAction( action );
 
348
 
 
349
        if ( !flip ) //we accumulate on the left
 
350
        {
 
351
            leftActionsWidth += widget->sizeHint().width()
 
352
                             +  m_toolbar->layout()->spacing();
 
353
        }
 
354
        else //then, on the right
 
355
        {
 
356
            rightActionsWidth += widget->sizeHint().width()
 
357
                              +  m_toolbar->layout()->spacing();
 
358
        }
 
359
    }
 
360
 
 
361
    if ( leftActionsWidth > rightActionsWidth )
 
362
    {
 
363
        m_toolbarLeftBalancer->setFixedWidth( 0 );
 
364
        m_toolbarRightBalancer->setFixedWidth( leftActionsWidth - rightActionsWidth );
 
365
    }
 
366
    else
 
367
    {
 
368
        m_toolbarLeftBalancer->setFixedWidth( rightActionsWidth - leftActionsWidth );
 
369
        m_toolbarRightBalancer->setFixedWidth( 0 );
 
370
    }
 
371
}
 
372
 
 
373
 
 
374
void
 
375
TomahawkWindow::setupSideBar()
 
376
{
 
377
    // Delete fake designer widgets
 
378
    delete ui->sidebarWidget;
 
379
    delete ui->playlistWidget;
 
380
 
 
381
    QWidget* sidebarWidget = new QWidget();
 
382
    sidebarWidget->setLayout( new QVBoxLayout() );
 
383
 
 
384
    m_sidebar = new AnimatedSplitter();
 
385
    m_sidebar->setOrientation( Qt::Vertical );
 
386
    m_sidebar->setChildrenCollapsible( false );
 
387
 
 
388
    m_sourcetree = new SourceTreeView( this );
 
389
    JobStatusView* jobsView = new JobStatusView( m_sidebar );
 
390
    JobStatusModel* sourceModel = new JobStatusModel( jobsView );
 
391
    m_jobsModel = new JobStatusSortModel( jobsView );
 
392
    m_jobsModel->setJobModel( sourceModel );
 
393
    jobsView->setModel( m_jobsModel );
 
394
 
 
395
    m_queueView = new QueueView( m_sidebar );
 
396
    AudioEngine::instance()->setQueue( m_queueView->queue()->proxyModel()->playlistInterface() );
 
397
 
 
398
    m_sidebar->addWidget( m_sourcetree );
 
399
    m_sidebar->addWidget( jobsView );
 
400
    m_sidebar->addWidget( m_queueView );
 
401
 
 
402
//    m_sidebar->setGreedyWidget( 1 );
 
403
    m_sidebar->hide( 1, false );
 
404
    m_sidebar->hide( 2, false );
 
405
    m_sidebar->hide( 3, false );
 
406
 
 
407
    sidebarWidget->layout()->addWidget( m_sidebar );
 
408
    sidebarWidget->setContentsMargins( 0, 0, 0, 0 );
 
409
    sidebarWidget->layout()->setContentsMargins( 0, 0, 0, 0 );
 
410
    sidebarWidget->layout()->setMargin( 0 );
 
411
 
 
412
#ifndef Q_OS_MAC
 
413
    sidebarWidget->layout()->setSpacing( 0 );
 
414
#endif
 
415
 
 
416
    ui->splitter->addWidget( sidebarWidget );
 
417
    ui->splitter->addWidget( ViewManager::instance()->widget() );
 
418
    ui->splitter->setCollapsible( 1, false );
 
419
 
 
420
    ActionCollection::instance()->getAction( "showOfflineSources" )
 
421
            ->setChecked( TomahawkSettings::instance()->showOfflineSources() );
 
422
}
 
423
 
 
424
 
 
425
void
 
426
TomahawkWindow::setupUpdateCheck()
 
427
{
 
428
#if defined( Q_OS_MAC ) && defined( HAVE_SPARKLE )
 
429
    connect( ActionCollection::instance()->getAction( "checkForUpdates" ), SIGNAL( triggered( bool ) ),
 
430
             SLOT( checkForUpdates() ) );
 
431
    #elif defined( Q_WS_WIN ) && defined( WITH_QtSparkle )
 
432
    QUrl updaterUrl;
 
433
 
 
434
    if ( qApp->arguments().contains( "--debug" ) )
 
435
        updaterUrl.setUrl( "http://download.tomahawk-player.org/sparklewin-debug" );
 
436
    else
 
437
        updaterUrl.setUrl( "http://download.tomahawk-player.org/sparklewin" );
 
438
 
 
439
    qtsparkle::Updater* updater = new qtsparkle::Updater( updaterUrl, this );
 
440
    Q_ASSERT( TomahawkUtils::nam() != 0 );
 
441
    updater->SetNetworkAccessManager( TomahawkUtils::nam() );
 
442
    updater->SetVersion( TomahawkUtils::appFriendlyVersion() );
 
443
 
 
444
    connect( ActionCollection::instance()->getAction( "checkForUpdates" ), SIGNAL( triggered() ),
 
445
             updater, SLOT( CheckNow() ) );
 
446
#endif
 
447
}
 
448
 
 
449
 
 
450
#ifdef Q_OS_WIN
 
451
bool
 
452
TomahawkWindow::setupWindowsButtons()
 
453
{
 
454
#ifdef HAVE_THUMBBUTTON
 
455
    const GUID IID_ITaskbarList3 = { 0xea1afb91,0x9e28,0x4b86, { 0x90,0xe9,0x9e,0x9f,0x8a,0x5e,0xef,0xaf } };
 
456
    HRESULT hr = S_OK;
 
457
 
 
458
    THUMBBUTTONMASK dwMask = THUMBBUTTONMASK( THB_ICON | THB_TOOLTIP | THB_FLAGS );
 
459
    m_thumbButtons[TP_PREVIOUS].dwMask = dwMask;
 
460
    m_thumbButtons[TP_PREVIOUS].iId = TP_PREVIOUS;
 
461
    m_thumbButtons[TP_PREVIOUS].hIcon = thumbIcon(TomahawkUtils::PrevButton);
 
462
    m_thumbButtons[TP_PREVIOUS].dwFlags = THBF_ENABLED;
 
463
    m_thumbButtons[TP_PREVIOUS].szTip[ tr( "Back" ).toWCharArray( m_thumbButtons[TP_PREVIOUS].szTip ) ] = 0;
 
464
 
 
465
    m_thumbButtons[TP_PLAY_PAUSE].dwMask = dwMask;
 
466
    m_thumbButtons[TP_PLAY_PAUSE].iId = TP_PLAY_PAUSE;
 
467
    m_thumbButtons[TP_PLAY_PAUSE].hIcon = thumbIcon(TomahawkUtils::PlayButton);
 
468
    m_thumbButtons[TP_PLAY_PAUSE].dwFlags = THBF_ENABLED;
 
469
    m_thumbButtons[TP_PLAY_PAUSE].szTip[ tr( "Play" ).toWCharArray( m_thumbButtons[TP_PLAY_PAUSE].szTip ) ] = 0;
 
470
 
 
471
    m_thumbButtons[TP_NEXT].dwMask = dwMask;
 
472
    m_thumbButtons[TP_NEXT].iId = TP_NEXT;
 
473
    m_thumbButtons[TP_NEXT].hIcon = thumbIcon(TomahawkUtils::NextButton);
 
474
    m_thumbButtons[TP_NEXT].dwFlags = THBF_ENABLED;
 
475
    m_thumbButtons[TP_NEXT].szTip[ tr( "Next" ).toWCharArray( m_thumbButtons[TP_NEXT].szTip ) ] = 0;
 
476
 
 
477
    m_thumbButtons[3].dwMask = dwMask;
 
478
    m_thumbButtons[3].iId = -1;
 
479
    m_thumbButtons[3].hIcon = 0;
 
480
    m_thumbButtons[3].dwFlags = THBF_NOBACKGROUND | THBF_DISABLED;
 
481
    m_thumbButtons[3].szTip[0] = 0;
 
482
 
 
483
    m_thumbButtons[TP_LOVE].dwMask = dwMask;
 
484
    m_thumbButtons[TP_LOVE].iId = TP_LOVE;
 
485
    m_thumbButtons[TP_LOVE].hIcon = thumbIcon(TomahawkUtils::NotLoved);
 
486
    m_thumbButtons[TP_LOVE].dwFlags = THBF_DISABLED;
 
487
    m_thumbButtons[TP_LOVE].szTip[ tr( "Love" ).toWCharArray( m_thumbButtons[TP_LOVE].szTip ) ] = 0;
 
488
 
 
489
    if ( S_OK == CoCreateInstance( CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (void **)&m_taskbarList ) )
 
490
    {
 
491
        hr = m_taskbarList->HrInit();
 
492
        if ( SUCCEEDED( hr ) )
 
493
        {
 
494
            hr = m_taskbarList->ThumbBarAddButtons( winId(), ARRAYSIZE( m_thumbButtons ), m_thumbButtons );
 
495
        }
 
496
        else
 
497
        {
 
498
            m_taskbarList->Release();
 
499
            m_taskbarList = 0;
 
500
        }
 
501
    }
 
502
 
 
503
    return SUCCEEDED( hr );
 
504
#else // HAVE_THUMBBUTTON
 
505
    return false;
 
506
#endif
 
507
}
 
508
 
 
509
 
 
510
HICON
 
511
TomahawkWindow::thumbIcon(TomahawkUtils::ImageType type)
 
512
{
 
513
    static QMap<TomahawkUtils::ImageType,HICON> thumbIcons;
 
514
    if (!thumbIcons.contains( type ) )
 
515
    {
 
516
        QPixmap pix ( TomahawkUtils::defaultPixmap(type , TomahawkUtils::Original, QSize( 20, 20 ) ) );
 
517
        thumbIcons[type] = pix.toWinHICON();
 
518
    }
 
519
    return thumbIcons[type];
 
520
}
 
521
#endif
 
522
 
 
523
 
 
524
void
 
525
TomahawkWindow::setupSignals()
 
526
{
 
527
    // <From AudioEngine>
 
528
    connect( AudioEngine::instance(), SIGNAL( error( AudioEngine::AudioErrorCode ) ), SLOT( onAudioEngineError( AudioEngine::AudioErrorCode ) ) );
 
529
    connect( AudioEngine::instance(), SIGNAL( loading( const Tomahawk::result_ptr& ) ), SLOT( onPlaybackLoading( const Tomahawk::result_ptr& ) ) );
 
530
    connect( AudioEngine::instance(), SIGNAL( started( Tomahawk::result_ptr ) ), SLOT( audioStarted() ) );
 
531
    connect( AudioEngine::instance(), SIGNAL( finished( Tomahawk::result_ptr ) ), SLOT( audioFinished() ) );
 
532
    connect( AudioEngine::instance(), SIGNAL( resumed() ), SLOT( audioStarted() ) );
 
533
    connect( AudioEngine::instance(), SIGNAL( paused() ), SLOT( audioPaused() ) );
 
534
    connect( AudioEngine::instance(), SIGNAL( stopped() ), SLOT( audioStopped() ) );
 
535
 
 
536
    // <Menu Items>
 
537
    ActionCollection *ac = ActionCollection::instance();
 
538
    //    connect( ui->actionAddPeerManually, SIGNAL( triggered() ), SLOT( addPeerManually() ) );
 
539
    connect( ac->getAction( "preferences" ), SIGNAL( triggered() ), SLOT( showSettingsDialog() ) );
 
540
    connect( ac->getAction( "diagnostics" ), SIGNAL( triggered() ), SLOT( showDiagnosticsDialog() ) );
 
541
    connect( ac->getAction( "legalInfo" ), SIGNAL( triggered() ), SLOT( legalInfo() ) );
 
542
    connect( ac->getAction( "openLogfile" ), SIGNAL( triggered() ), SLOT( openLogfile() ) );
 
543
    connect( ac->getAction( "updateCollection" ), SIGNAL( triggered() ), SLOT( updateCollectionManually() ) );
 
544
    connect( ac->getAction( "rescanCollection" ), SIGNAL( triggered() ), SLOT( rescanCollectionManually() ) );
 
545
    connect( ac->getAction( "loadXSPF" ), SIGNAL( triggered() ), SLOT( loadSpiff() ) );
 
546
    connect( ac->getAction( "aboutTomahawk" ), SIGNAL( triggered() ), SLOT( showAboutTomahawk() ) );
 
547
    connect( ac->getAction( "quit" ), SIGNAL( triggered() ), qApp, SLOT( quit() ) );
 
548
    connect( ac->getAction( "showOfflineSources" ), SIGNAL( triggered() ), SLOT( showOfflineSources() ) );
 
549
 
 
550
#if defined( Q_OS_MAC )
 
551
    connect( ac->getAction( "minimize" ), SIGNAL( triggered() ), SLOT( minimize() ) );
 
552
    connect( ac->getAction( "zoom" ), SIGNAL( triggered() ), SLOT( maximize() ) );
 
553
    connect( ac->getAction( "fullscreen" ), SIGNAL( triggered() ), SLOT( toggleFullscreen() ) );
 
554
#else
 
555
    connect( ac->getAction( "toggleMenuBar" ), SIGNAL( triggered() ), SLOT( toggleMenuBar() ) );
 
556
#endif
 
557
 
 
558
    // <AccountHandler>
 
559
    connect( AccountManager::instance(), SIGNAL( authError( Tomahawk::Accounts::Account* ) ), SLOT( onAccountError() ) );
 
560
 
 
561
    connect( ViewManager::instance(), SIGNAL( historyBackAvailable( bool ) ), SLOT( onHistoryBackAvailable( bool ) ) );
 
562
    connect( ViewManager::instance(), SIGNAL( historyForwardAvailable( bool ) ), SLOT( onHistoryForwardAvailable( bool ) ) );
 
563
}
 
564
 
 
565
 
 
566
void
 
567
TomahawkWindow::setupMenuBar()
 
568
{
 
569
    // Always create a menubar, but only create a compactMenu on Windows and X11
 
570
    m_menuBar = ActionCollection::instance()->createMenuBar( this );
 
571
    setMenuBar( m_menuBar );
 
572
#ifndef Q_OS_MAC
 
573
    m_compactMainMenu = ActionCollection::instance()->createCompactMenu( this );
 
574
#endif
 
575
}
 
576
 
 
577
 
 
578
void
 
579
TomahawkWindow::changeEvent( QEvent* e )
 
580
{
 
581
    QMainWindow::changeEvent( e );
 
582
 
 
583
    switch ( e->type() )
 
584
    {
 
585
        case QEvent::LanguageChange:
 
586
            ui->retranslateUi( this );
 
587
            break;
 
588
 
 
589
        default:
 
590
            break;
 
591
    }
 
592
}
 
593
 
 
594
 
 
595
void
 
596
TomahawkWindow::closeEvent( QCloseEvent* e )
 
597
{
 
598
#ifndef Q_OS_MAC
 
599
    if ( e->spontaneous() && QSystemTrayIcon::isSystemTrayAvailable() )
 
600
    {
 
601
        hide();
 
602
        e->ignore();
 
603
        return;
 
604
    }
 
605
#else
 
606
    m_trayIcon->setShowHideWindow( false );
 
607
#endif
 
608
 
 
609
    e->accept();
 
610
}
 
611
 
 
612
 
 
613
void
 
614
TomahawkWindow::showEvent( QShowEvent* e )
 
615
{
 
616
    QMainWindow::showEvent( e );
 
617
 
 
618
#if defined( Q_OS_MAC )
 
619
    ActionCollection::instance()->getAction( "minimize" )->setDisabled( false );
 
620
    ActionCollection::instance()->getAction( "zoom" )->setDisabled( false );
 
621
#endif
 
622
}
 
623
 
 
624
 
 
625
void
 
626
TomahawkWindow::hideEvent( QHideEvent* e )
 
627
{
 
628
    QMainWindow::hideEvent( e );
 
629
 
 
630
#if defined( Q_OS_MAC )
 
631
    ActionCollection::instance()->getAction( "minimize" )->setDisabled( true );
 
632
    ActionCollection::instance()->getAction( "zoom" )->setDisabled( true );
 
633
#endif
 
634
}
 
635
 
 
636
 
 
637
void
 
638
TomahawkWindow::keyPressEvent( QKeyEvent* e )
 
639
{
 
640
    bool accept = true;
 
641
 
 
642
#if ! defined ( Q_OS_MAC )
 
643
#define KEY_PRESSED Q_FUNC_INFO << "Multimedia Key Pressed:"
 
644
    switch ( e->key() )
 
645
    {
 
646
        case Qt::Key_MediaPlay:
 
647
            tLog() << KEY_PRESSED << "Play";
 
648
            AudioEngine::instance()->playPause();
 
649
            break;
 
650
        case Qt::Key_MediaStop:
 
651
            tLog() << KEY_PRESSED << "Stop";
 
652
            AudioEngine::instance()->stop();
 
653
            break;
 
654
        case Qt::Key_MediaPrevious:
 
655
            tLog() << KEY_PRESSED << "Previous";
 
656
            AudioEngine::instance()->previous();
 
657
            break;
 
658
        case Qt::Key_MediaNext:
 
659
            tLog() << KEY_PRESSED << "Next";
 
660
            AudioEngine::instance()->next();
 
661
            break;
 
662
        case Qt::Key_MediaPause:
 
663
            tLog() << KEY_PRESSED << "Pause";
 
664
            AudioEngine::instance()->pause();
 
665
            break;
 
666
        case Qt::Key_MediaTogglePlayPause:
 
667
            tLog() << KEY_PRESSED << "PlayPause";
 
668
            AudioEngine::instance()->playPause();
 
669
            break;
 
670
        case Qt::Key_MediaRecord:
 
671
        default:
 
672
            accept = false;
 
673
    }
 
674
#else
 
675
    accept = false;
 
676
#endif
 
677
 
 
678
    if ( accept )
 
679
        e->accept();
 
680
 
 
681
    QMainWindow::keyPressEvent( e );
 
682
}
 
683
 
 
684
 
 
685
#ifdef Q_OS_WIN
 
686
bool
 
687
TomahawkWindow::winEvent( MSG* msg, long* result )
 
688
{
 
689
    #define TB_PRESSED Q_FUNC_INFO << "Taskbar Button Pressed:"
 
690
 
 
691
    switch ( msg->message )
 
692
    {
 
693
    case WM_COMMAND:
 
694
        if ( HIWORD( msg->wParam ) == THBN_CLICKED )
 
695
        {
 
696
            switch ( TB_STATES( LOWORD( msg->wParam ) ) )
 
697
            {
 
698
            case TP_PREVIOUS:
 
699
                tLog() << TB_PRESSED << "Previous";
 
700
                AudioEngine::instance()->previous();
 
701
                break;
 
702
            case TP_PLAY_PAUSE:
 
703
                tLog() << TB_PRESSED << "Play/Pause";
 
704
                AudioEngine::instance()->playPause();
 
705
                break;
 
706
            case TP_NEXT:
 
707
                tLog() << TB_PRESSED << "Next";
 
708
                AudioEngine::instance()->next();
 
709
                break;
 
710
            case TP_LOVE:
 
711
                tLog() << TB_PRESSED << "Love";
 
712
                if ( !AudioEngine::instance()->currentTrack().isNull() )
 
713
                {
 
714
                    AudioEngine::instance()->currentTrack()->toQuery()->setLoved( !AudioEngine::instance()->currentTrack()->toQuery()->loved() );
 
715
                    updateWindowsLoveButton();
 
716
                }
 
717
                break;
 
718
            }
 
719
            return true;
 
720
        }
 
721
        break;
 
722
    }
 
723
 
 
724
    if ( msg->message == m_buttonCreatedID )
 
725
        return setupWindowsButtons();
 
726
 
 
727
    return false;
 
728
}
 
729
 
 
730
 
 
731
#endif // Q_OS_WIN
 
732
 
 
733
void
 
734
TomahawkWindow::audioStateChanged( AudioState newState, AudioState oldState )
 
735
{
 
736
#ifdef HAVE_THUMBBUTTON
 
737
    if ( m_taskbarList == 0 )
 
738
        return;
 
739
    switch ( newState )
 
740
    {
 
741
    case AudioEngine::Playing:
 
742
    {
 
743
        m_thumbButtons[TP_PLAY_PAUSE].hIcon = thumbIcon(TomahawkUtils::PauseButton);
 
744
        m_thumbButtons[TP_PLAY_PAUSE].szTip[ tr( "Pause" ).toWCharArray( m_thumbButtons[TP_PLAY_PAUSE].szTip ) ] = 0;
 
745
        updateWindowsLoveButton();
 
746
 
 
747
    }
 
748
        break;
 
749
 
 
750
    case AudioEngine::Paused:
 
751
    {
 
752
        m_thumbButtons[TP_PLAY_PAUSE].hIcon = thumbIcon(TomahawkUtils::PlayButton);
 
753
        m_thumbButtons[TP_PLAY_PAUSE].szTip[ tr( "Play" ).toWCharArray( m_thumbButtons[TP_PLAY_PAUSE].szTip ) ] = 0;
 
754
    }
 
755
        break;
 
756
 
 
757
    case AudioEngine::Stopped:
 
758
    {
 
759
        if ( !AudioEngine::instance()->currentTrack().isNull() )
 
760
        {
 
761
            disconnect( AudioEngine::instance()->currentTrack()->toQuery().data(), SIGNAL( socialActionsLoaded() ), this, SLOT( updateWindowsLoveButton() ) );
 
762
        }
 
763
 
 
764
        m_thumbButtons[TP_PLAY_PAUSE].hIcon = thumbIcon(TomahawkUtils::PlayButton);
 
765
        m_thumbButtons[TP_PLAY_PAUSE].szTip[ tr( "Play" ).toWCharArray( m_thumbButtons[TP_PLAY_PAUSE].szTip ) ] = 0;
 
766
 
 
767
        m_thumbButtons[TP_LOVE].hIcon = thumbIcon(TomahawkUtils::NotLoved);
 
768
        m_thumbButtons[TP_LOVE].dwFlags = THBF_DISABLED;
 
769
    }
 
770
        break;
 
771
 
 
772
    default:
 
773
        return;
 
774
    }
 
775
 
 
776
    m_taskbarList->ThumbBarUpdateButtons( winId(), ARRAYSIZE( m_thumbButtons ), m_thumbButtons );
 
777
#else
 
778
    Q_UNUSED( newState );
 
779
    Q_UNUSED( oldState );
 
780
#endif // HAVE_THUMBBUTTON
 
781
}
 
782
 
 
783
 
 
784
void
 
785
TomahawkWindow::updateWindowsLoveButton()
 
786
{
 
787
#ifdef HAVE_THUMBBUTTON
 
788
    if ( m_taskbarList == 0 )
 
789
        return;
 
790
    if ( !AudioEngine::instance()->currentTrack().isNull() && AudioEngine::instance()->currentTrack()->toQuery()->loved() )
 
791
    {
 
792
        m_thumbButtons[TP_LOVE].hIcon = thumbIcon(TomahawkUtils::Loved);
 
793
        m_thumbButtons[TP_LOVE].szTip[ tr( "Unlove" ).toWCharArray( m_thumbButtons[TP_LOVE].szTip ) ] = 0;
 
794
    }
 
795
    else
 
796
    {
 
797
        m_thumbButtons[TP_LOVE].hIcon = thumbIcon(TomahawkUtils::NotLoved);
 
798
        m_thumbButtons[TP_LOVE].szTip[ tr( "Love" ).toWCharArray( m_thumbButtons[TP_LOVE].szTip ) ] = 0;
 
799
    }
 
800
 
 
801
    m_thumbButtons[TP_LOVE].dwFlags = THBF_ENABLED;
 
802
    m_taskbarList->ThumbBarUpdateButtons( winId(), ARRAYSIZE( m_thumbButtons ), m_thumbButtons );
 
803
#endif // HAVE_THUMBBUTTON
 
804
}
 
805
 
 
806
 
 
807
void
 
808
TomahawkWindow::onHistoryBackAvailable( bool avail )
 
809
{
 
810
    m_backAction->setEnabled( avail );
 
811
}
 
812
 
 
813
 
 
814
void
 
815
TomahawkWindow::onHistoryForwardAvailable( bool avail )
 
816
{
 
817
    m_forwardAction->setEnabled( avail );
 
818
}
 
819
 
 
820
 
 
821
void
 
822
TomahawkWindow::showSettingsDialog()
 
823
{
 
824
    if ( !m_settingsDialog )
 
825
        m_settingsDialog = new SettingsDialog;
 
826
 
 
827
    m_settingsDialog->show();
 
828
}
 
829
 
 
830
 
 
831
void
 
832
TomahawkWindow::showDiagnosticsDialog()
 
833
{
 
834
    DiagnosticsDialog win;
 
835
    win.exec();
 
836
}
 
837
 
 
838
 
 
839
void
 
840
TomahawkWindow::legalInfo()
 
841
{
 
842
    QDesktopServices::openUrl( QUrl( "http://www.tomahawk-player.org/legal.html" ) );
 
843
}
 
844
 
 
845
 
 
846
void
 
847
TomahawkWindow::openLogfile()
 
848
{
 
849
#ifdef WIN32
 
850
    ShellExecuteW( 0, 0, (LPCWSTR)Logger::logFile().utf16(), 0, 0, SW_SHOWNORMAL );
 
851
#else
 
852
    QDesktopServices::openUrl( QUrl::fromLocalFile( Logger::logFile() ) );
 
853
#endif
 
854
}
 
855
 
 
856
 
 
857
void
 
858
TomahawkWindow::updateCollectionManually()
 
859
{
 
860
    if ( TomahawkSettings::instance()->hasScannerPaths() )
 
861
        ScanManager::instance()->runNormalScan();
 
862
}
 
863
 
 
864
 
 
865
void
 
866
TomahawkWindow::rescanCollectionManually()
 
867
{
 
868
    if ( TomahawkSettings::instance()->hasScannerPaths() )
 
869
        ScanManager::instance()->runFullRescan();
 
870
}
 
871
 
 
872
 
 
873
void
 
874
TomahawkWindow::addPeerManually()
 
875
{
 
876
    TomahawkSettings* s = TomahawkSettings::instance();
 
877
    bool ok;
 
878
    QString addr = QInputDialog::getText( this, tr( "Connect To Peer" ),
 
879
                                                tr( "Enter peer address:" ), QLineEdit::Normal,
 
880
                                                s->value( "connip" ).toString(), &ok ); // FIXME
 
881
    if ( !ok )
 
882
        return;
 
883
 
 
884
    s->setValue( "connip", addr );
 
885
    QString ports = QInputDialog::getText( this, tr( "Connect To Peer" ),
 
886
                                                 tr( "Enter peer port:" ), QLineEdit::Normal,
 
887
                                                 s->value( "connport", "50210" ).toString(), &ok );
 
888
    if ( !ok )
 
889
        return;
 
890
 
 
891
    s->setValue( "connport", ports );
 
892
    int port = ports.toInt();
 
893
    QString key = QInputDialog::getText( this, tr( "Connect To Peer" ),
 
894
                                               tr( "Enter peer key:" ), QLineEdit::Normal,
 
895
                                               "whitelist", &ok );
 
896
    if ( !ok )
 
897
        return;
 
898
 
 
899
    qDebug() << "Attempting to connect to" << addr;
 
900
    Servent::instance()->connectToPeer( addr, port, key );
 
901
}
 
902
 
 
903
 
 
904
void
 
905
TomahawkWindow::showOfflineSources()
 
906
{
 
907
    m_sourcetree->showOfflineSources(
 
908
        ActionCollection::instance()->getAction( "showOfflineSources" )->isChecked() );
 
909
    TomahawkSettings::instance()->setShowOfflineSources(
 
910
        ActionCollection::instance()->getAction( "showOfflineSources" )->isChecked() );
 
911
}
 
912
 
 
913
 
 
914
void
 
915
TomahawkWindow::fullScreenEntered()
 
916
{
 
917
    TomahawkSettings::instance()->setFullscreenEnabled( true );
 
918
    statusBar()->setSizeGripEnabled( false );
 
919
 
 
920
#if defined( Q_WS_MAC )
 
921
    ActionCollection::instance()->getAction( "fullscreen" )->setText( tr( "Exit Full Screen" ) );
 
922
#endif
 
923
}
 
924
 
 
925
 
 
926
void
 
927
TomahawkWindow::fullScreenExited()
 
928
{
 
929
    TomahawkSettings::instance()->setFullscreenEnabled( false );
 
930
    statusBar()->setSizeGripEnabled( true );
 
931
 
 
932
#if defined( Q_WS_MAC )
 
933
    ActionCollection::instance()->getAction( "fullscreen" )->setText( tr( "Enter Full Screen" ) );
 
934
#endif
 
935
}
 
936
 
 
937
 
 
938
void
 
939
TomahawkWindow::loadSpiff()
 
940
{
 
941
    LoadXSPFDialog* diag = new LoadXSPFDialog( this, Qt::Sheet );
 
942
#ifdef Q_OS_MAC
 
943
    connect( diag, SIGNAL( finished( int ) ), this, SLOT( loadXspfFinished( int ) ) );
 
944
    diag->show();
 
945
#else
 
946
    QWeakPointer< LoadXSPFDialog > safe( diag );
 
947
 
 
948
    int ret = diag->exec();
 
949
    if ( !safe.isNull() && ret == QDialog::Accepted )
 
950
    {
 
951
        QUrl url = QUrl::fromUserInput( safe.data()->xspfUrl() );
 
952
        bool autoUpdate = safe.data()->autoUpdate();
 
953
 
 
954
        XSPFLoader* loader = new XSPFLoader( true, autoUpdate );
 
955
        connect( loader, SIGNAL( error( XSPFLoader::XSPFErrorCode ) ), SLOT( onXSPFError( XSPFLoader::XSPFErrorCode ) ) );
 
956
        connect( loader, SIGNAL( ok( Tomahawk::playlist_ptr ) ), SLOT( onXSPFOk( Tomahawk::playlist_ptr ) ) );
 
957
        loader->load( url );
 
958
    }
 
959
#endif
 
960
}
 
961
 
 
962
 
 
963
void
 
964
TomahawkWindow::loadXspfFinished( int ret )
 
965
{
 
966
    LoadXSPFDialog* d = qobject_cast< LoadXSPFDialog* >( sender() );
 
967
    Q_ASSERT( d );
 
968
    if ( ret == QDialog::Accepted )
 
969
    {
 
970
        QUrl url = QUrl::fromUserInput( d->xspfUrl() );
 
971
        bool autoUpdate = d->autoUpdate();
 
972
 
 
973
        XSPFLoader* loader = new XSPFLoader( true, autoUpdate );
 
974
        connect( loader, SIGNAL( error( XSPFLoader::XSPFErrorCode ) ), SLOT( onXSPFError( XSPFLoader::XSPFErrorCode ) ) );
 
975
        connect( loader, SIGNAL( ok( Tomahawk::playlist_ptr ) ), SLOT( onXSPFOk( Tomahawk::playlist_ptr ) ) );
 
976
        loader->load( url );
 
977
    }
 
978
    d->deleteLater();
 
979
}
 
980
 
 
981
 
 
982
void
 
983
TomahawkWindow::onXSPFOk( const Tomahawk::playlist_ptr& pl )
 
984
{
 
985
    ViewManager::instance()->show( pl );
 
986
}
 
987
 
 
988
 
 
989
void
 
990
TomahawkWindow::onXSPFError( XSPFLoader::XSPFErrorCode error )
 
991
{
 
992
    switch ( error )
 
993
    {
 
994
        case XSPFLoader::ParseError:
 
995
            QMessageBox::critical( this, tr( "XSPF Error" ), tr( "This is not a valid XSPF playlist." ) );
 
996
            break;
 
997
 
 
998
        case XSPFLoader::InvalidTrackError:
 
999
            QMessageBox::warning( this, tr( "Failed to save tracks" ), tr( "Some tracks in the playlist do not contain an artist and a title. They will be ignored." ), QMessageBox::Ok );
 
1000
            break;
 
1001
        default:
 
1002
            //FIXME: This includes FetchError
 
1003
            break;
 
1004
    }
 
1005
}
 
1006
 
 
1007
 
 
1008
void
 
1009
TomahawkWindow::onAudioEngineError( AudioEngine::AudioErrorCode /* error */ )
 
1010
{
 
1011
    QString msg;
 
1012
#ifdef Q_WS_X11
 
1013
    msg = tr( "Sorry, there is a problem accessing your audio device or the desired track, current track will be skipped. Make sure you have a suitable Phonon backend and required plugins installed." );
 
1014
#else
 
1015
    msg = tr( "Sorry, there is a problem accessing your audio device or the desired track, current track will be skipped." );
 
1016
#endif
 
1017
    JobStatusView::instance()->model()->addJob( new ErrorStatusMessage( msg, 15 ) );
 
1018
 
 
1019
    if ( m_audioRetryCounter < 3 )
 
1020
        AudioEngine::instance()->play();
 
1021
    m_audioRetryCounter++;
 
1022
}
 
1023
 
 
1024
 
 
1025
void
 
1026
TomahawkWindow::createAutomaticPlaylist( QString playlistName )
 
1027
{
 
1028
    if ( playlistName.isEmpty() )
 
1029
        return;
 
1030
 
 
1031
    source_ptr author = SourceList::instance()->getLocal();
 
1032
    QString id = uuid();
 
1033
    QString info  = ""; // FIXME
 
1034
    QString creator = "someone"; // FIXME
 
1035
 
 
1036
    dynplaylist_ptr playlist = DynamicPlaylist::create( author, id, playlistName, info, creator, Static, false );
 
1037
    playlist->setMode( Static );
 
1038
    playlist->createNewRevision( uuid(), playlist->currentrevision(), playlist->type(), playlist->generator()->controls(), playlist->entries() );
 
1039
 
 
1040
    ViewManager::instance()->show( playlist );
 
1041
}
 
1042
 
 
1043
 
 
1044
void
 
1045
TomahawkWindow::createStation()
 
1046
{
 
1047
    QString title = tr( "Station" );
 
1048
    bool ok;
 
1049
    QString playlistName = QInputDialog( this, Qt::Sheet ).getText( this, tr( "Create New Station" ), tr( "Name:" ), QLineEdit::Normal, title, &ok );
 
1050
    if ( !ok )
 
1051
        return;
 
1052
 
 
1053
    if ( playlistName.isEmpty() || playlistName == title )
 
1054
    {
 
1055
        QList< dynplaylist_ptr > pls = SourceList::instance()->getLocal()->collection()->stations();
 
1056
        QStringList titles;
 
1057
        foreach ( const playlist_ptr& pl, pls )
 
1058
            titles << pl->title();
 
1059
 
 
1060
        playlistName = title;
 
1061
        int i = 2;
 
1062
        while ( titles.contains( playlistName ) )
 
1063
        {
 
1064
            playlistName = QString( "%1 (%2)" ).arg( title ).arg( i++ );
 
1065
        }
 
1066
    }
 
1067
 
 
1068
    source_ptr author = SourceList::instance()->getLocal();
 
1069
    QString id = uuid();
 
1070
    QString info  = ""; // FIXME
 
1071
    QString creator = "someone"; // FIXME
 
1072
 
 
1073
    dynplaylist_ptr playlist = DynamicPlaylist::create( author, id, playlistName, info, creator, OnDemand, false );
 
1074
    playlist->setMode( OnDemand );
 
1075
    playlist->createNewRevision( uuid(), playlist->currentrevision(), playlist->type(), playlist->generator()->controls() );
 
1076
 
 
1077
    ViewManager::instance()->show( playlist );
 
1078
}
 
1079
 
 
1080
 
 
1081
void
 
1082
TomahawkWindow::createPlaylist()
 
1083
{
 
1084
    PlaylistTypeSelectorDlg* playlistSelectorDlg = new PlaylistTypeSelectorDlg( TomahawkApp::instance()->mainWindow(), Qt::Sheet );
 
1085
 
 
1086
#ifndef Q_OS_MAC
 
1087
    playlistSelectorDlg->setModal( true );
 
1088
#endif
 
1089
 
 
1090
    connect( playlistSelectorDlg, SIGNAL( finished( int ) ), SLOT( playlistCreateDialogFinished( int ) ) );
 
1091
    playlistSelectorDlg->show();
 
1092
}
 
1093
 
 
1094
 
 
1095
void
 
1096
TomahawkWindow::playlistCreateDialogFinished( int ret )
 
1097
{
 
1098
    PlaylistTypeSelectorDlg* playlistSelectorDlg = qobject_cast< PlaylistTypeSelectorDlg* >( sender() );
 
1099
    Q_ASSERT( playlistSelectorDlg );
 
1100
 
 
1101
    QString playlistName = playlistSelectorDlg->playlistName();
 
1102
 
 
1103
    if ( !playlistSelectorDlg->playlistTypeIsAuto() && ret )
 
1104
    {
 
1105
        if ( playlistName.isEmpty() )
 
1106
        {
 
1107
            QList< playlist_ptr > pls = SourceList::instance()->getLocal()->collection()->playlists();
 
1108
            QStringList titles;
 
1109
            foreach ( const playlist_ptr& pl, pls )
 
1110
                titles << pl->title();
 
1111
 
 
1112
            QString title = tr( "Playlist" );
 
1113
            playlistName = title;
 
1114
            int i = 2;
 
1115
            while ( titles.contains( playlistName ) )
 
1116
            {
 
1117
                playlistName = QString( "%1 (%2)" ).arg( title ).arg( i++ );
 
1118
            }
 
1119
        }
 
1120
 
 
1121
        playlist_ptr playlist = Tomahawk::Playlist::create( SourceList::instance()->getLocal(), uuid(), playlistName, "", "", false, QList< query_ptr>() );
 
1122
        ViewManager::instance()->show( playlist );
 
1123
    }
 
1124
    else if ( playlistSelectorDlg->playlistTypeIsAuto() && ret )
 
1125
    {
 
1126
       // create Auto Playlist
 
1127
        if ( playlistName.isEmpty() )
 
1128
        {
 
1129
            QList< dynplaylist_ptr > pls = SourceList::instance()->getLocal()->collection()->autoPlaylists();
 
1130
            QStringList titles;
 
1131
            foreach ( const dynplaylist_ptr& pl, pls )
 
1132
                titles << pl->title();
 
1133
 
 
1134
            QString title = tr( "Automatic Playlist" );
 
1135
            playlistName = title;
 
1136
            int i = 2;
 
1137
            while ( titles.contains( playlistName ) )
 
1138
            {
 
1139
                playlistName = QString( "%1 (%2)" ).arg( title ).arg( i++ );
 
1140
            }
 
1141
        }
 
1142
 
 
1143
       createAutomaticPlaylist( playlistName );
 
1144
    }
 
1145
 
 
1146
    playlistSelectorDlg->deleteLater();
 
1147
}
 
1148
 
 
1149
 
 
1150
void
 
1151
TomahawkWindow::audioStarted()
 
1152
{
 
1153
    m_audioRetryCounter = 0;
 
1154
 
 
1155
    ActionCollection::instance()->getAction( "playPause" )->setIcon( ImageRegistry::instance()->icon( RESPATH "images/pause-rest.svg" ) );
 
1156
    ActionCollection::instance()->getAction( "playPause" )->setText( tr( "Pause" ) );
 
1157
    ActionCollection::instance()->getAction( "stop" )->setEnabled( true );
 
1158
 
 
1159
#ifdef Q_OS_WIN
 
1160
    connect( AudioEngine::instance()->currentTrack()->toQuery().data(), SIGNAL( socialActionsLoaded() ), SLOT( updateWindowsLoveButton() ) );
 
1161
#endif
 
1162
}
 
1163
 
 
1164
 
 
1165
void
 
1166
TomahawkWindow::audioFinished()
 
1167
{
 
1168
#ifdef Q_OS_WIN
 
1169
    disconnect( AudioEngine::instance()->currentTrack()->toQuery().data(), SIGNAL( socialActionsLoaded() ), this, SLOT( updateWindowsLoveButton() ) );
 
1170
#endif
 
1171
}
 
1172
 
 
1173
 
 
1174
void
 
1175
TomahawkWindow::audioPaused()
 
1176
{
 
1177
    ActionCollection::instance()->getAction( "playPause" )->setIcon( ImageRegistry::instance()->icon( RESPATH "images/play-rest.svg" ) );
 
1178
    ActionCollection::instance()->getAction( "playPause" )->setText( tr( "&Play" ) );
 
1179
}
 
1180
 
 
1181
 
 
1182
void
 
1183
TomahawkWindow::audioStopped()
 
1184
{
 
1185
    audioPaused();
 
1186
    ActionCollection::instance()->getAction( "stop" )->setEnabled( false );
 
1187
 
 
1188
    m_currentTrack = result_ptr();
 
1189
    setWindowTitle( m_windowTitle );
 
1190
}
 
1191
 
 
1192
 
 
1193
void
 
1194
TomahawkWindow::onPlaybackLoading( const Tomahawk::result_ptr& result )
 
1195
{
 
1196
    m_currentTrack = result;
 
1197
    setWindowTitle( m_windowTitle );
 
1198
}
 
1199
 
 
1200
 
 
1201
void
 
1202
TomahawkWindow::onAccountError()
 
1203
{
 
1204
    // TODO fix.
 
1205
//     onAccountDisconnected();
 
1206
 
 
1207
    // TODO real error message from plugin kthxbbq
 
1208
    QMessageBox::warning( this,
 
1209
                          tr( "Authentication Error" ),
 
1210
                          tr( "Error connecting to SIP: Authentication failed!" ),
 
1211
                          QMessageBox::Ok );
 
1212
}
 
1213
 
 
1214
 
 
1215
void
 
1216
TomahawkWindow::setWindowTitle( const QString& title )
 
1217
{
 
1218
    m_windowTitle = title;
 
1219
 
 
1220
    if ( m_currentTrack.isNull() )
 
1221
        QMainWindow::setWindowTitle( title );
 
1222
    else
 
1223
    {
 
1224
        QString s = tr( "%1 by %2", "track, artist name" ).arg( m_currentTrack->track(), m_currentTrack->artist()->name() );
 
1225
        QMainWindow::setWindowTitle( tr( "%1 - %2", "current track, some window title" ).arg( s, title ) );
 
1226
    }
 
1227
}
 
1228
 
 
1229
 
 
1230
void
 
1231
TomahawkWindow::showAboutTomahawk()
 
1232
{
 
1233
    QString head, desc;
 
1234
 
 
1235
#ifdef DEBUG_BUILD
 
1236
    head = tr( "<h2><b>Tomahawk %1<br/>(%2)</h2>" )
 
1237
         .arg( TomahawkUtils::appFriendlyVersion() )
 
1238
         .arg( qApp->applicationVersion() );
 
1239
#else
 
1240
    head = tr( "<h2><b>Tomahawk %1</h2>" )
 
1241
         .arg( TomahawkUtils::appFriendlyVersion() );
 
1242
#endif
 
1243
 
 
1244
    const QString copyright( tr( "Copyright 2010 - 2013" ) );
 
1245
    const QString thanksto( tr( "Thanks to:" ) );
 
1246
 
 
1247
    desc = QString( "%1<br/>Christian Muehlhaeuser &lt;muesli@tomahawk-player.org&gt;<br/><br/>"
 
1248
    "%2 Leo Franchi, Jeff Mitchell, Dominik Schmidt, Jason Herskowitz, Alejandro Wainzinger, Hugo Lindstr&ouml;m, Syd Lawrence, Michael Zanetti, Teo Mrnjavac, Christopher Reichert, Harald Sitter" )
 
1249
              .arg( copyright )
 
1250
              .arg( thanksto );
 
1251
 
 
1252
    QMessageBox::about( this, tr( "About Tomahawk" ), head + desc );
 
1253
}
 
1254
 
 
1255
 
 
1256
void
 
1257
TomahawkWindow::checkForUpdates()
 
1258
{
 
1259
#ifdef Q_OS_MAC
 
1260
    Tomahawk::checkForUpdates();
 
1261
#endif
 
1262
}
 
1263
 
 
1264
 
 
1265
void
 
1266
TomahawkWindow::onSearch( const QString& search )
 
1267
{
 
1268
    if ( !search.trimmed().isEmpty() )
 
1269
        ViewManager::instance()->show( new SearchWidget( search, this ) );
 
1270
}
 
1271
 
 
1272
 
 
1273
void
 
1274
TomahawkWindow::onFilterEdited()
 
1275
{
 
1276
    onSearch( m_searchWidget->text() );
 
1277
    m_searchWidget->clear();
 
1278
}
 
1279
 
 
1280
 
 
1281
void
 
1282
TomahawkWindow::showQueue()
 
1283
{
 
1284
    if ( QThread::currentThread() != thread() )
 
1285
    {
 
1286
        qDebug() << "Reinvoking in correct thread:" << Q_FUNC_INFO;
 
1287
        QMetaObject::invokeMethod( this, "showQueue", Qt::QueuedConnection );
 
1288
        return;
 
1289
    }
 
1290
 
 
1291
    m_queueView->show();
 
1292
}
 
1293
 
 
1294
 
 
1295
void
 
1296
TomahawkWindow::hideQueue()
 
1297
{
 
1298
    if ( QThread::currentThread() != thread() )
 
1299
    {
 
1300
        qDebug() << "Reinvoking in correct thread:" << Q_FUNC_INFO;
 
1301
        QMetaObject::invokeMethod( this, "hideQueue", Qt::QueuedConnection );
 
1302
        return;
 
1303
    }
 
1304
 
 
1305
    m_queueView->hide();
 
1306
}
 
1307
 
 
1308
 
 
1309
void
 
1310
TomahawkWindow::minimize()
 
1311
{
 
1312
    if ( isMinimized() )
 
1313
    {
 
1314
        showNormal();
 
1315
    }
 
1316
    else
 
1317
    {
 
1318
        showMinimized();
 
1319
    }
 
1320
}
 
1321
 
 
1322
 
 
1323
void
 
1324
TomahawkWindow::maximize()
 
1325
{
 
1326
    if ( isMaximized() )
 
1327
    {
 
1328
        showNormal();
 
1329
    }
 
1330
    else
 
1331
    {
 
1332
        showMaximized();
 
1333
    }
 
1334
}
 
1335
 
 
1336
 
 
1337
void
 
1338
TomahawkWindow::toggleFullscreen()
 
1339
{
 
1340
    tDebug() << Q_FUNC_INFO;
 
1341
 
 
1342
#if defined( Q_WS_MAC )
 
1343
   Tomahawk::toggleFullscreen();
 
1344
#endif
 
1345
}
 
1346
 
 
1347
 
 
1348
void
 
1349
TomahawkWindow::crashNow()
 
1350
{
 
1351
    TomahawkUtils::crash();
 
1352
}
 
1353
 
 
1354
 
 
1355
void
 
1356
TomahawkWindow::toggleMenuBar() //SLOT
 
1357
{
 
1358
#ifndef Q_OS_MAC
 
1359
    if ( menuBar()->isVisible() )
 
1360
    {
 
1361
        menuBar()->setVisible( false );
 
1362
        ActionCollection::instance()->getAction( "toggleMenuBar" )->setText( tr( "Show Menu Bar" ) );
 
1363
        m_compactMenuAction->setVisible( true );
 
1364
    }
 
1365
    else
 
1366
    {
 
1367
        m_compactMenuAction->setVisible( false );
 
1368
        ActionCollection::instance()->getAction( "toggleMenuBar" )->setText( tr( "Hide Menu Bar" ) );
 
1369
        menuBar()->setVisible( true );
 
1370
    }
 
1371
    balanceToolbar();
 
1372
    saveSettings();
 
1373
#endif
 
1374
}
 
1375
 
 
1376
 
 
1377
AudioControls*
 
1378
TomahawkWindow::audioControls()
 
1379
{
 
1380
    return m_audioControls;
 
1381
}
 
1382
 
 
1383
 
 
1384
SourceTreeView*
 
1385
TomahawkWindow::sourceTreeView() const
 
1386
{
 
1387
    return m_sourcetree;
 
1388
}