juk.cpp 13.8 KB
Newer Older
1 2 3 4 5
/***************************************************************************
                          juk.cpp  -  description
                             -------------------
    begin                : Mon Feb  4 23:40:41 EST 2002
    copyright            : (C) 2002 by Scott Wheeler
6
    email                : wheeler@kde.org
7
***************************************************************************/
8 9 10 11 12 13 14 15 16 17

/***************************************************************************
 *                                                                         *
 *   This program 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 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

18 19
#include <config.h>

20 21 22 23
#include <kcmdlineargs.h>
#include <kstatusbar.h>
#include <kdebug.h>
#include <kmessagebox.h>
Scott Wheeler's avatar
Scott Wheeler committed
24
#include <kiconloader.h>
25
#include <kapplication.h>
26 27 28

#include <qslider.h>

29 30 31 32 33 34 35
#include "juk.h"
#include "slideraction.h"
#include "statuslabel.h"
#include "splashscreen.h"
#include "systemtray.h"
#include "keydialog.h"
#include "tagguesserconfigdlg.h"
36
#include "filerenamerconfigdlg.h"
37
#include "actioncollection.h"
38
#include "cache.h"
39 40
#include "playlistsplitter.h"
#include "collectionlist.h"
41

42 43
using namespace ActionCollection;

44 45 46 47
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////

Scott Wheeler's avatar
Scott Wheeler committed
48
JuK::JuK(QWidget *parent, const char *name) :
Scott Wheeler's avatar
Scott Wheeler committed
49
    KMainWindow(parent, name, WDestructiveClose),
50
    m_player(PlayerManager::instance()),
51
    m_shuttingDown(false)
52
{
53 54
    // Expect segfaults if you change this order.

55
    readSettings();
56

57
    if(m_showSplash && !m_startDocked) {
58 59 60 61
	SplashScreen::instance()->show();
	kapp->processEvents();
    }

62
    setupActions();
63
    setupLayout();
64
    createGUI();
65
    readConfig();
66
    setupSystemTray();
67
    setupGlobalAccels();
68
    processArgs();
69

70
    SplashScreen::finishedLoading();
Scott Wheeler's avatar
Scott Wheeler committed
71
    QTimer::singleShot(0, CollectionList::instance(), SLOT(slotCheckCache()));
72 73

    m_sliderAction->slotUpdateOrientation();
74 75 76 77
}

JuK::~JuK()
{
78

79 80
}

81 82 83 84 85
KActionCollection *JuK::actionCollection() const
{
    return ActionCollection::actions();
}

86 87 88 89
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////

90 91
void JuK::setupLayout()
{
92 93
    m_splitter = new PlaylistSplitter(this, "playlistSplitter");
    setCentralWidget(m_splitter);
94

95 96
    m_statusLabel = new StatusLabel(m_splitter->playlist(), statusBar());
    statusBar()->addWidget(m_statusLabel, 1);
97 98
    PlayerManager::instance()->setStatusLabel(m_statusLabel);

99
    m_splitter->setFocus();
100
    resize(750, 500);
101 102
}

103 104
void JuK::setupActions()
{
105 106 107 108 109 110
    KStdAction::quit(this, SLOT(slotQuit()), actions());
    KStdAction::cut(kapp,   SLOT(cut()),   actions());
    KStdAction::copy(kapp,  SLOT(copy()),  actions());
    KStdAction::paste(kapp, SLOT(paste()), actions());
    KStdAction::clear(kapp, SLOT(clear()), actions());
    KStdAction::selectAll(kapp, SLOT(selectAll()), actions());
111

112 113
    m_showHistoryAction = new KToggleAction(i18n("Show &History"),    "history",  0, actions(), "showHistory");
    m_randomPlayAction =  new KToggleAction(i18n("&Random Play"),                 0, actions(), "randomPlay");
114

Stephan Binner's avatar
Stephan Binner committed
115
    m_showHistoryAction->setCheckedState(i18n("Hide &History"));
116

117 118 119
    new KAction(i18n("&Play"),  "player_play",  0, m_player, SLOT(play()),  actions(), "play");
    new KAction(i18n("P&ause"), "player_pause", 0, m_player, SLOT(pause()), actions(), "pause");
    new KAction(i18n("&Stop"),  "player_stop",  0, m_player, SLOT(stop()),  actions(), "stop");
Scott Wheeler's avatar
Scott Wheeler committed
120

121 122 123
    // m_backAction = new KToolBarPopupAction(i18n("Previous &Track"), "player_start", 0,
    //                                        this, SLOT(back()), actions(), "back");
    // TODO: switch this back to being a popup action
124

125
    new KAction(i18n("Previous &Track"), "player_start", 0, m_player, SLOT(back()),    actions(), "back");
126
    new KAction(i18n("&Next Track"),     "player_end",   0, m_player, SLOT(forward()), actions(), "forward");
127

128 129 130
    new KToggleAction(i18n("&Loop Playlist"), 0, 0, actions(), "loopPlaylist");

    // the following are not visible by default
131

132 133 134 135 136 137
    new KAction(i18n("Mute"),         "mute",        0, m_player, SLOT(mute()),        actions(), "mute");
    new KAction(i18n("Volume Up"),    "volumeUp",    0, m_player, SLOT(volumeUp()),    actions(), "volumeUp");
    new KAction(i18n("Volume Down"),  "volumeDown",  0, m_player, SLOT(volumeDown()),  actions(), "volumeDown");
    new KAction(i18n("Play / Pause"), "playPause",   0, m_player, SLOT(playPause()),   actions(), "playPause");
    new KAction(i18n("Seek Forward"), "seekForward", 0, m_player, SLOT(seekForward()), actions(), "seekForward");
    new KAction(i18n("Seek Back"),    "seekBack",    0, m_player, SLOT(seekBack()),    actions(), "seekBack");
Stephan Binner's avatar
Stephan Binner committed
138

139

140
    //////////////////////////////////////////////////
141
    // settings menu
142 143
    //////////////////////////////////////////////////

144
    setStandardToolBarMenuEnabled(true);
145

Scott Wheeler's avatar
Scott Wheeler committed
146
    m_toggleSplashAction =
147
	new KToggleAction(i18n("Show Splash Screen on Startup"),
Scott Wheeler's avatar
Scott Wheeler committed
148
			  KShortcut(), actions(), "showSplashScreen");
Stephan Binner's avatar
Stephan Binner committed
149
    m_toggleSplashAction->setCheckedState(i18n("Hide Splash Screen on Startup"));
Scott Wheeler's avatar
Scott Wheeler committed
150 151 152
    m_toggleSystemTrayAction =
	new KToggleAction(i18n("&Dock in System Tray"),
			  KShortcut(), actions(), "toggleSystemTray");
Stephan Binner's avatar
Stephan Binner committed
153
    m_toggleDockOnCloseAction =
Scott Wheeler's avatar
Scott Wheeler committed
154 155 156
	new KToggleAction(i18n("&Stay in System Tray on Close"),
			  KShortcut(), actions(), "dockOnClose");
    m_togglePopupsAction =
157
	new KToggleAction(i18n("Popup &Track Announcement"),
Scott Wheeler's avatar
Scott Wheeler committed
158
			  KShortcut(), this, 0, actions(), "togglePopups");
159

Scott Wheeler's avatar
Scott Wheeler committed
160 161
    connect(m_toggleSystemTrayAction, SIGNAL(toggled(bool)),
	    this, SLOT(slotToggleSystemTray(bool)));
162

Scott Wheeler's avatar
Scott Wheeler committed
163

164
    m_outputSelectAction = PlayerManager::playerSelectAction(actions());
165

166
    if(m_outputSelectAction)
167
        m_outputSelectAction->setCurrentItem(0);
168

Scott Wheeler's avatar
Scott Wheeler committed
169
    new KAction(i18n("&Tag Guesser..."), 0, 0, this, SLOT(slotConfigureTagGuesser()),
170
		actions(), "tagGuesserConfig");
171

172
    new KAction(i18n("&File Renamer..."), 0, 0, this, SLOT(slotConfigureFileRenamer()),
173
		actions(), "fileRenamerConfig");
174

175
    KStdAction::keyBindings(this, SLOT(slotEditKeys()), actions());
176

177
    //////////////////////////////////////////////////
178
    // just in the toolbar
179 180
    //////////////////////////////////////////////////

181
    m_sliderAction = new SliderAction(i18n("Track Position"), actions(),
Scott Wheeler's avatar
Scott Wheeler committed
182
				      "trackPositionAction");
183 184
}

185
void JuK::setupSystemTray()
186
{
187
    if(m_toggleSystemTrayAction && m_toggleSystemTrayAction->isChecked()) {
Scott Wheeler's avatar
Scott Wheeler committed
188 189
	m_systemTray = new SystemTray(this, "systemTray");
	m_systemTray->show();
190

Scott Wheeler's avatar
Scott Wheeler committed
191
	m_toggleDockOnCloseAction->setEnabled(true);
192
	m_togglePopupsAction->setEnabled(true);
193

Scott Wheeler's avatar
Scott Wheeler committed
194
	connect(m_systemTray, SIGNAL(quitSelected()), this, SLOT(slotQuit()));
195
    }
196
    else {
Scott Wheeler's avatar
Scott Wheeler committed
197 198
	m_systemTray = 0;
	m_toggleDockOnCloseAction->setEnabled(false);
199
	m_togglePopupsAction->setEnabled(false);
200
    }
201 202
}

203 204 205
void JuK::setupGlobalAccels()
{
    m_accel = new KGlobalAccel(this);
206

207 208 209 210 211 212 213 214 215
    KeyDialog::insert(m_accel, "PlayPause",   i18n("Play / Pause"), action("playPause"),   SLOT(activate()));
    KeyDialog::insert(m_accel, "Stop",        i18n("Stop Playing"), action("stop"),        SLOT(activate()));
    KeyDialog::insert(m_accel, "Back",        i18n("Back"),         action("back"),        SLOT(activate()));
    KeyDialog::insert(m_accel, "Forward",     i18n("Forward"),      action("forward"),     SLOT(activate()));
    KeyDialog::insert(m_accel, "SeekBack",    i18n("Seek Back"),    action("seekBack"),    SLOT(activate()));
    KeyDialog::insert(m_accel, "SeekForward", i18n("Seek Forward"), action("seekForward"), SLOT(activate()));
    KeyDialog::insert(m_accel, "VolumeUp",    i18n("Volume Up"),    action("volumeUp"),    SLOT(activate()));
    KeyDialog::insert(m_accel, "VolumeDown",  i18n("Volume Down"),  action("volumeDown"),  SLOT(activate()));
    KeyDialog::insert(m_accel, "Mute",        i18n("Mute"),         action("mute"),        SLOT(activate()));
216
    KeyDialog::insert(m_accel, "ShowHide",    i18n("Show / Hide"),  this,                  SLOT(slotShowHide()));
217

218 219 220 221 222
    m_accel->setConfigGroup("Shortcuts");
    m_accel->readSettings();
    m_accel->updateConnections();
}

223 224 225 226
void JuK::processArgs()
{
    KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
    QStringList files;
227

228
    for(int i = 0; i < args->count(); i++)
229
        files.append(args->arg(i));
230

231 232
    // TODO: make this work again
    // m_splitter->open(files);
233 234
}

235 236 237
void JuK::keyPressEvent(QKeyEvent *e)
{
    if (e->key() >= Qt::Key_Back && e->key() <= Qt::Key_MediaLast)
238
        e->accept();
239 240 241
    KMainWindow::keyPressEvent(e);
}

242 243 244 245 246 247 248 249 250
/**
 * These are settings that need to be know before setting up the GUI.
 */

void JuK::readSettings()
{
    KConfig *config = KGlobal::config();
    { // general settings
        KConfigGroupSaver saver(config, "Settings");
251
        m_showSplash = config->readBoolEntry("ShowSplashScreen", true);
252
        m_startDocked = config->readBoolEntry("StartDocked", false);
253 254 255
    }
}

256 257
void JuK::readConfig()
{
258
    // Automagically save and m_restore many window settings.
259 260
    setAutoSaveSettings();

261
    KConfig *config = KGlobal::config();
262
    { // player settings
263
        KConfigGroupSaver saver(config, "Player");
264 265
        if(m_sliderAction->volumeSlider()) {
	    int maxVolume = m_sliderAction->volumeSlider()->maxValue();
Scott Wheeler's avatar
Scott Wheeler committed
266
	    int volume = config->readNumEntry("Volume", maxVolume);
267
            m_sliderAction->volumeSlider()->setVolume(volume);
268
        }
269 270
        bool randomPlay = config->readBoolEntry("RandomPlay", false);
        m_randomPlayAction->setChecked(randomPlay);
271

272
        bool loopPlaylist = config->readBoolEntry("LoopPlaylist", false);
273
        ActionCollection::action<KToggleAction>("loopPlaylist")->setChecked(loopPlaylist);
274
    }
275
    { // view settings
276
        KConfigGroupSaver saver(config, "View");
277

278 279 280
	// The history list will actually be created by the playlist restoration
	// code, but we want to remember the checkbox's setting and hope that
	// it's in synch with the code that does the real work.
281

282 283
	bool showHistory = config->readBoolEntry("ShowHistory", false);
	m_showHistoryAction->setChecked(showHistory);
284
    }
285 286
    { // general settings
        KConfigGroupSaver saver(config, "Settings");
287

288 289
        bool dockInSystemTray = config->readBoolEntry("DockInSystemTray", true);
        m_toggleSystemTrayAction->setChecked(dockInSystemTray);
290

291 292
        bool dockOnClose = config->readBoolEntry("DockOnClose", true);
        m_toggleDockOnCloseAction->setChecked(dockOnClose);
293

294 295
        bool showPopups = config->readBoolEntry("TrackPopup", false);
        m_togglePopupsAction->setChecked(showPopups);
296

297 298
        if(m_outputSelectAction)
            m_outputSelectAction->setCurrentItem(config->readNumEntry("MediaSystem", 0));
299
    }
300

301
    m_toggleSplashAction->setChecked(m_showSplash);
302 303 304 305
}

void JuK::saveConfig()
{
306
    KConfig *config = KGlobal::config();
307
    { // player settings
308
        KConfigGroupSaver saver(config, "Player");
309
	config->writeEntry("Volume", m_sliderAction->volumeSlider()->volume());
310 311 312 313
	config->writeEntry("RandomPlay", m_randomPlayAction->isChecked());

	KToggleAction *a = ActionCollection::action<KToggleAction>("loopPlaylist");
	config->writeEntry("LoopPlaylist", a->isChecked());
314
    }
315 316
    { // view settings
        KConfigGroupSaver saver(config, "View");
317
	config->writeEntry("ShowHistory", m_showHistoryAction->isChecked());
318
    }
319 320
    { // general settings
        KConfigGroupSaver saver(config, "Settings");
321
        config->writeEntry("ShowSplashScreen", m_toggleSplashAction->isChecked());
322
        config->writeEntry("StartDocked", m_startDocked);
323 324 325 326 327
        config->writeEntry("DockInSystemTray", m_toggleSystemTrayAction->isChecked());
        config->writeEntry("DockOnClose", m_toggleDockOnCloseAction->isChecked());
        config->writeEntry("TrackPopup", m_togglePopupsAction->isChecked());
        if(m_outputSelectAction)
            config->writeEntry("MediaSystem", m_outputSelectAction->currentItem());
328
    }
329
    config->sync();
330 331
}

332
bool JuK::queryExit()
333
{
334 335
    m_startDocked = !isVisible();

336
    hide();
337
    action("stop")->activate();
338 339 340
    delete m_systemTray;
    m_systemTray = 0;

341
    Cache::instance()->save();
342
    saveConfig();
343
    delete m_splitter;
344
    return true;
345 346
}

347 348
bool JuK::queryClose()
{
349 350 351 352 353
    if(!m_shuttingDown &&
       !kapp->sessionSaving() &&
       m_systemTray &&
       m_toggleDockOnCloseAction->isChecked())
    {
354
	KMessageBox::information(this,
Scott Wheeler's avatar
Scott Wheeler committed
355 356 357
	    i18n("<qt>Closing the main window will keep JuK running in the system tray. "
		 "Use Quit from the File menu to quit the application.</qt>"),
	    i18n("Docking in System Tray"), "hideOnCloseInfo");
358 359 360 361 362 363 364
	hide();
	return false;
    }
    else
	return true;
}

365 366 367 368
////////////////////////////////////////////////////////////////////////////////
// private slot definitions
////////////////////////////////////////////////////////////////////////////////

369 370 371 372 373
void JuK::slotShowHide()
{
    setShown(!isShown());
}

374 375 376 377 378
void JuK::slotQuit()
{
    kapp->quit();
}

379 380 381 382
////////////////////////////////////////////////////////////////////////////////
// settings menu
////////////////////////////////////////////////////////////////////////////////

383
void JuK::slotToggleSystemTray(bool enabled)
384
{
385
    if(enabled && !m_systemTray)
386
	setupSystemTray();
387 388 389
    else if(!enabled && m_systemTray) {
	delete m_systemTray;
	m_systemTray = 0;
390
	m_toggleDockOnCloseAction->setEnabled(false);
391
	m_togglePopupsAction->setEnabled(false);
392 393 394
    }
}

395 396
void JuK::slotEditKeys()
{
397
    KeyDialog::configure(m_accel, actions(), this);
398 399
}

400 401
void JuK::slotConfigureTagGuesser()
{
402
    TagGuesserConfigDlg(this).exec();
403 404
}

405 406
void JuK::slotConfigureFileRenamer()
{
407
    FileRenamerConfigDlg(this).exec();
408 409
}

410
#include "juk.moc"