juk.cpp 23.5 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 20 21 22 23 24
#include <kcmdlineargs.h>
#include <kstatusbar.h>
#include <kdebug.h>
#include <kmessagebox.h>

#include <qslider.h>

25 26 27 28 29 30 31
#include "juk.h"
#include "slideraction.h"
#include "statuslabel.h"
#include "splashscreen.h"
#include "systemtray.h"
#include "keydialog.h"
#include "tagguesserconfigdlg.h"
32
#include "filerenamerconfigdlg.h"
33
#include "actioncollection.h"
34

35 36
using namespace ActionCollection;

37 38 39 40
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////

Scott Wheeler's avatar
Scott Wheeler committed
41 42
JuK::JuK(QWidget *parent, const char *name) :
    KMainWindow(parent, name, WDestructiveClose),
43 44 45
    m_player(PlayerManager::instance()),
    m_shuttingDown(false),
    m_muted(false)
46
{
47 48
    // Expect segfaults if you change this order.

49
    readSettings();
50

51
    if(m_showSplash && !m_startDocked) {
52 53 54 55
	SplashScreen::instance()->show();
	kapp->processEvents();
    }

56
    setupActions();
57 58
    setupLayout();
    setupSplitterConnections();
59
    slotPlaylistChanged();
60
    readConfig();
61
    setupSystemTray();
62
    setupGlobalAccels();
63
    processArgs();
64

65 66
    m_player->setPlaylistInterface(m_splitter);

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

JuK::~JuK()
{
73

74 75
}

76 77 78 79 80
KActionCollection *JuK::actionCollection() const
{
    return ActionCollection::actions();
}

81 82 83 84 85 86
////////////////////////////////////////////////////////////////////////////////
// public slots
////////////////////////////////////////////////////////////////////////////////

void JuK::setVolume(float volume)
{
87 88
    if(m_sliderAction->volumeSlider()->maxValue() > 0 &&
       volume >= 0 && m_sliderAction->volumeSlider()->maxValue() >= volume)
89
    {
90
	int v = int(volume / 100 * m_sliderAction->volumeSlider()->maxValue());
91
	m_player->slotSetVolume(v);
92
	m_sliderAction->volumeSlider()->setValue(v);
93 94 95
    }
}

96 97 98 99 100
void JuK::setTime(int time)
{
    m_player->seek(time);
}

101
void JuK::slotGuessTagInfoFromFile()
102
{
103 104 105 106 107 108
    m_splitter->slotGuessTagInfo(TagGuesser::FileName);
}

void JuK::slotGuessTagInfoFromInternet()
{
    m_splitter->slotGuessTagInfo(TagGuesser::MusicBrainz);
109 110
}

111 112 113 114 115 116 117 118 119 120
void JuK::back(int howMany)
{
    for(--howMany; howMany > 0; --howMany)
        m_splitter->playPreviousFile(m_randomPlayAction->isChecked());

    play(m_splitter->playPreviousFile(m_randomPlayAction->isChecked()));
}

void JuK::slotPopulateBackMenu()
{
Scott Wheeler's avatar
Scott Wheeler committed
121 122
    m_splitter->populatePlayHistoryMenu(m_backAction->popupMenu(),
					m_randomPlayAction->isChecked());
123 124 125 126
}

void JuK::forward()
{
127
    m_player->forward();
128 129 130 131
}

void JuK::seekBack()
{
132 133 134
    int position = m_sliderAction->trackPositionSlider()->value();
    position = QMAX(m_sliderAction->trackPositionSlider()->minValue(), position - 10);
    emit m_sliderAction->trackPositionSlider()->setValue(position);
135 136 137 138
}

void JuK::seekForward()
{
139 140 141
    int position = m_sliderAction->trackPositionSlider()->value();
    position = QMIN(m_sliderAction->trackPositionSlider()->maxValue(), position + 10);
    emit m_sliderAction->trackPositionSlider()->setValue(position);
142 143 144 145 146
}

void JuK::playPause()
{
    if(m_player->playing())
147
	action("pause")->activate();
148
    else
149
	action("play")->activate();
150 151 152 153
}

void JuK::volumeUp()
{
154 155 156
    if(m_sliderAction && m_sliderAction->volumeSlider()) {
	int volume = m_sliderAction->volumeSlider()->value() +
	    m_sliderAction->volumeSlider()->maxValue() / 25; // 4% up
157
	m_player->slotSetVolume(volume);
158
	m_sliderAction->volumeSlider()->setValue(volume);
159 160 161 162 163
    }
}

void JuK::volumeDown()
{
164 165 166
    if(m_sliderAction && m_sliderAction->volumeSlider()) {
	int volume = m_sliderAction->volumeSlider()->value() -
	    m_sliderAction->volumeSlider()->maxValue() / 25; // 4% down
167
	m_player->slotSetVolume(volume);
168
	m_sliderAction->volumeSlider()->setValue(volume);
169 170 171 172 173
    }
}

void JuK::volumeMute()
{
174
    if(m_sliderAction && m_sliderAction->volumeSlider()) {
175
	if(m_muted)
176
	    m_player->slotSetVolume(m_sliderAction->volumeSlider()->value());
177
	else
178
	    m_player->slotSetVolume(0);
179 180 181 182 183 184 185 186 187
	    m_muted = !m_muted;
    }
}

void JuK::openFile(const QString &file)
{
    m_splitter->open(file);
}

188 189 190 191 192 193
void JuK::openFile(const QStringList &files)
{
    for(QStringList::ConstIterator it = files.begin(); it != files.end(); ++it)
	openFile(*it);
}

194 195 196 197
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////

198 199
void JuK::setupLayout()
{
200
    m_splitter = new PlaylistSplitter(this, "playlistSplitter");
201
    setCentralWidget(m_splitter);
202 203

    // playlist item activation connection
Scott Wheeler's avatar
Scott Wheeler committed
204
    connect(m_splitter, SIGNAL(signalActivated()),
205
	    this, SLOT(slotPlayCurrent()));
Scott Wheeler's avatar
Scott Wheeler committed
206
    connect(m_splitter, SIGNAL(signalListBoxDoubleClicked()),
207
	    this, SLOT(slotPlayCurrent()));
208

209
    // create status bar
210

211
    m_statusLabel = new StatusLabel(statusBar());
212

213
    statusBar()->addWidget(m_statusLabel, 1);
214

Scott Wheeler's avatar
Scott Wheeler committed
215 216
    connect(m_splitter, SIGNAL(signalSelectedPlaylistCountChanged(int)),
	    m_statusLabel, SLOT(setPlaylistCount(int)));
217 218
    connect(m_splitter, SIGNAL(signalSelectedPlaylistTimeChanged(int)),
	    m_statusLabel, SLOT(setPlaylistTime(int)));
Scott Wheeler's avatar
Scott Wheeler committed
219 220
    connect(m_statusLabel, SIGNAL(jumpButtonClicked()),
	    m_splitter, SLOT(slotSelectPlaying()));
221

222 223
    PlayerManager::instance()->setStatusLabel(m_statusLabel);

224 225
    // Needs to be here because m_splitter is not called before setupActions
    // (because PlaylistSplitter itself accesses the actionCollection)
226

227 228 229
    new KAction(i18n("&Rename File"), 0, "CTRL+r", m_splitter, SLOT(slotRenameFile()),
                actionCollection(), "renameFile"); // 4

230
    m_splitter->setFocus();
231

232
    resize(750, 500);
233 234
}

235 236
void JuK::setupActions()
{
237
    //////////////////////////////////////////////////
238
    // file menu
239
    //////////////////////////////////////////////////
240

Scott Wheeler's avatar
Scott Wheeler committed
241 242 243
    KActionMenu *newMenu = new KActionMenu(i18n("&New"), "filenew",
					   actionCollection(), "file_new");

244 245 246 247 248 249
    // This connection will call the
    // PlaylistSplitter::slotCreatePlaylist(const QString &) slot - this is
    // possible because the QString parameter has a default value, so the
    // slot can be called without arguments (as required by the signal's
    // signature).

Scott Wheeler's avatar
Scott Wheeler committed
250 251 252
    newMenu->insert(createSplitterAction(i18n("Empty Playlist..."),
					 SLOT(slotCreatePlaylist()), 0, 0, 0));

253
    newMenu->insert(createSplitterAction(i18n("Playlist From Folder..."),
Scott Wheeler's avatar
Scott Wheeler committed
254 255 256 257 258
					 SLOT(slotCreatePlaylistFromDir()), 0, 0, 0));

    createSplitterAction(
	i18n("Open..."), SLOT(slotOpen()), "file_open", "fileopen", "CTRL+o");
    createSplitterAction(
259
	i18n("Open &Folder..."), SLOT(slotOpenDirectory()), "openDirectory", "fileopen");
Scott Wheeler's avatar
Scott Wheeler committed
260 261 262 263 264 265 266 267 268 269 270 271
    createSplitterAction(
	i18n("&Rename..."), SLOT(slotRenamePlaylist()), "renamePlaylist");
    createSplitterAction(
	i18n("D&uplicate..."), SLOT(slotDuplicatePlaylist()), "duplicatePlaylist");
    createSplitterAction(
	i18n("Save"), SLOT(slotSavePlaylist()), "file_save", "filesave", "CTRL+s");
    createSplitterAction(
	i18n("Save As..."), SLOT(slotSaveAsPlaylist()), "file_save_as", "filesaveas");
    createSplitterAction(
	i18n("R&emove"), SLOT(slotDeletePlaylist()), "deleteItemPlaylist", "edittrash");
    createSplitterAction(
	i18n("Reload"), SLOT(slotReloadPlaylist()), "reloadPlaylist", "reload");
272

273
    KStdAction::quit(this, SLOT(slotQuit()), actionCollection());
274

275
    //////////////////////////////////////////////////
276
    // edit menu
277 278
    //////////////////////////////////////////////////

279 280 281 282
    KStdAction::cut(kapp,   SLOT(cut()),   actionCollection());
    KStdAction::copy(kapp,  SLOT(copy()),  actionCollection());
    KStdAction::paste(kapp, SLOT(paste()), actionCollection());
    KStdAction::clear(kapp, SLOT(clear()), actionCollection());
283

284
    KStdAction::selectAll(kapp, SLOT(selectAll()), actionCollection());
285

286
    createSplitterAction(
287
	i18n("Advanced Search"), SLOT(slotAdvancedSearch()), "advancedSearch", "find", "s");
288

289
    //////////////////////////////////////////////////
290
    // view menu
291
    //////////////////////////////////////////////////
292

Scott Wheeler's avatar
Scott Wheeler committed
293 294 295 296
    m_showSearchAction = new KToggleAction(i18n("Show &Search Bar"), "filefind",
					   0, actionCollection(), "showSearch");
    m_showEditorAction = new KToggleAction(i18n("Show &Tag Editor"), "edit",
					   0, actionCollection(), "showEditor");
297
    m_showHistoryAction = new KToggleAction(i18n("Show &History"), "history",
298
					   0, actionCollection(), "showHistory");
299

300
    createSplitterAction(i18n("Refresh Items"), SLOT(slotRefresh()), "refresh", "reload");
301

302
    //////////////////////////////////////////////////
303
    // play menu
304 305
    //////////////////////////////////////////////////

Scott Wheeler's avatar
Scott Wheeler committed
306 307 308
    m_randomPlayAction = new KToggleAction(i18n("&Random Play"), 0,
					   actionCollection(), "randomPlay");

309
    new KAction(i18n("&Play"),  "player_play",  0, m_player, SLOT(play()),
Scott Wheeler's avatar
Scott Wheeler committed
310 311
		actionCollection(), "play");

312
    new KAction(i18n("P&ause"), "player_pause", 0, m_player, SLOT(pause()),
Scott Wheeler's avatar
Scott Wheeler committed
313 314
		actionCollection(), "pause");

315
    new KAction(i18n("&Stop"),  "player_stop",  0, m_player, SLOT(stop()),
Scott Wheeler's avatar
Scott Wheeler committed
316 317
		actionCollection(), "stop");

318
    m_backAction = new KToolBarPopupAction(i18n("Previous &Track"), "player_start", 0,
Scott Wheeler's avatar
Scott Wheeler committed
319
					   this, SLOT(back()), actionCollection(), "back");
320

Scott Wheeler's avatar
Scott Wheeler committed
321 322
    connect(m_backAction->popupMenu(), SIGNAL(aboutToShow()),
	    this, SLOT(slotPopulateBackMenu()));
323

Scott Wheeler's avatar
Scott Wheeler committed
324 325
    connect(m_backAction->popupMenu(), SIGNAL(activated(int)),
	    this, SLOT(back(int)));
326

327
    new KAction(i18n("&Next Track"), "player_end", 0, this, SLOT(forward()),
Scott Wheeler's avatar
Scott Wheeler committed
328
		actionCollection(), "forward");
329

Scott Wheeler's avatar
Scott Wheeler committed
330 331
    m_loopPlaylistAction = new KToggleAction(i18n("&Loop Playlist"), 0, 0,
					     actionCollection(), "loopPlaylist");
332

333
    //////////////////////////////////////////////////
334
    // tagger menu
335 336
    //////////////////////////////////////////////////

337
    createSplitterAction(i18n("&Save"), SLOT(slotSaveTag()),
Scott Wheeler's avatar
Scott Wheeler committed
338 339 340
			 "saveItem",   "filesave", "CTRL+t");
    createSplitterAction(i18n("&Delete"), SLOT(slotDeleteSelectedItems()),
			 "removeItem", "editdelete");
341

342
    m_guessMenu = new KActionMenu(i18n("&Guess Tag Information"),
Scott Wheeler's avatar
Scott Wheeler committed
343 344
					     QString::null, actionCollection(),
					     "guessTag");
345

Scott Wheeler's avatar
Scott Wheeler committed
346
    KAction *a;
347

348 349
    a = new KAction(i18n("From &Filename"), 0, "CTRL+f", this, SLOT(slotGuessTagInfoFromFile()),
                actionCollection(), "guessTagFile");
350
    m_guessMenu->insert(a);
351
#if HAVE_MUSICBRAINZ
352 353
    a = new KAction(i18n("From &Internet"), 0, "CTRL+i", this, SLOT(slotGuessTagInfoFromInternet()),
                actionCollection(), "guessTagInternet");
354
    m_guessMenu->insert(a);
355
#endif
Scott Wheeler's avatar
Scott Wheeler committed
356

357
    //////////////////////////////////////////////////
358
    // settings menu
359 360
    //////////////////////////////////////////////////

361
    setStandardToolBarMenuEnabled(true);
362

Stephan Binner's avatar
Stephan Binner committed
363
    m_toggleSplashAction = new KToggleAction(i18n("Show Splash Screen on Startup"),
Scott Wheeler's avatar
Scott Wheeler committed
364 365 366 367 368 369 370
					     0, actionCollection(), "showSplashScreen");

    m_toggleSystemTrayAction = new KToggleAction(i18n("&Dock in System Tray"),
						 0, actionCollection(), "toggleSystemTray");

    m_toggleDockOnCloseAction = new KToggleAction(i18n("&Stay in System Tray on Close"),
						  0, actionCollection(), "dockOnClose");
371

372
    m_togglePopupsAction = new KToggleAction(i18n("Popup &Track Announcement"),
Scott Wheeler's avatar
Scott Wheeler committed
373
					     0, this, 0, actionCollection(), "togglePopups");
374

Scott Wheeler's avatar
Scott Wheeler committed
375 376
    connect(m_toggleSystemTrayAction, SIGNAL(toggled(bool)),
	    this, SLOT(slotToggleSystemTray(bool)));
377

Scott Wheeler's avatar
Scott Wheeler committed
378

379
    m_outputSelectAction = Player::playerSelectAction(actionCollection());
380

381
    if(m_outputSelectAction)
382
        m_outputSelectAction->setCurrentItem(0);
383

Scott Wheeler's avatar
Scott Wheeler committed
384 385
    new KAction(i18n("&Tag Guesser..."), 0, 0, this, SLOT(slotConfigureTagGuesser()),
		actionCollection(), "tagGuesserConfig");
386

387 388 389
    new KAction(i18n("&File Renamer..."), 0, 0, this, SLOT(slotConfigureFileRenamer()),
		actionCollection(), "fileRenamerConfig");

390 391
    KStdAction::keyBindings(this, SLOT(slotEditKeys()), actionCollection());

392
    //////////////////////////////////////////////////
393
    // just in the toolbar
394 395
    //////////////////////////////////////////////////

Scott Wheeler's avatar
Scott Wheeler committed
396 397
    m_sliderAction = new SliderAction(i18n("Track Position"), actionCollection(),
				      "trackPositionAction");
398 399

    createGUI();
400 401

    // set the slider to the proper orientation and make it stay that way
402
    m_sliderAction->slotUpdateOrientation();
403 404
}

405 406 407 408 409 410
void JuK::setupSplitterConnections()
{
    QValueListConstIterator<SplitterConnection> it = m_splitterConnections.begin();
    for(; it != m_splitterConnections.end(); ++it)
        connect((*it).first, SIGNAL(activated()), m_splitter, (*it).second);

Scott Wheeler's avatar
Scott Wheeler committed
411 412 413 414
    connect(m_showSearchAction, SIGNAL(toggled(bool)),
	    m_splitter, SLOT(slotSetSearchVisible(bool)));
    connect(m_showEditorAction, SIGNAL(toggled(bool)),
	    m_splitter, SLOT(slotSetEditorVisible(bool)));
415 416
    connect(m_showHistoryAction, SIGNAL(toggled(bool)),
	    m_splitter, SLOT(slotSetHistoryVisible(bool)));
417
    connect(this, SIGNAL(dockWindowPositionChanged(QDockWindow *)),
Scott Wheeler's avatar
Scott Wheeler committed
418 419 420
	    m_sliderAction, SLOT(slotUpdateOrientation(QDockWindow *)));
    connect(m_splitter, SIGNAL(signalPlaylistChanged()),
	    this, SLOT(slotPlaylistChanged()));
421 422
}

423
void JuK::setupSystemTray()
424
{
425
    if(m_toggleSystemTrayAction && m_toggleSystemTrayAction->isChecked()) {
426 427
        m_systemTray = new SystemTray(this, "systemTray");
        m_systemTray->show();
428

429
        connect(this, SIGNAL(signalNewSong(const QString&)),
Scott Wheeler's avatar
Scott Wheeler committed
430
		m_systemTray, SLOT(slotNewSong(const QString&)));
431

432
        m_toggleDockOnCloseAction->setEnabled(true);
433
	m_togglePopupsAction->setEnabled(true);
434

435
        connect(m_systemTray, SIGNAL(quitSelected()), this, SLOT(slotQuit()));
436
    }
437
    else {
438 439
        m_systemTray = 0;
        m_toggleDockOnCloseAction->setEnabled(false);
440
	m_togglePopupsAction->setEnabled(false);
441
    }
442 443
}

444 445 446
void JuK::setupGlobalAccels()
{
    m_accel = new KGlobalAccel(this);
447
    KeyDialog::insert(m_accel, "PlayPause",   i18n("Play/Pause"),   this, SLOT(playPause()));
448
    KeyDialog::insert(m_accel, "Stop",        i18n("Stop Playing"), action("stop"), SLOT(activate()));
449 450 451 452 453 454 455
    KeyDialog::insert(m_accel, "Back",        i18n("Back"),         this, SLOT(back()));
    KeyDialog::insert(m_accel, "Forward",     i18n("Forward"),      this, SLOT(forward()));
    KeyDialog::insert(m_accel, "SeekBack",    i18n("Seek Back"),    this, SLOT(seekBack()));
    KeyDialog::insert(m_accel, "SeekForward", i18n("Seek Forward"), this, SLOT(seekForward()));
    KeyDialog::insert(m_accel, "VolumeUp",    i18n("Volume Up"),    this, SLOT(volumeUp()));
    KeyDialog::insert(m_accel, "VolumeDown",  i18n("Volume Down"),  this, SLOT(volumeDown()));
    KeyDialog::insert(m_accel, "Mute",        i18n("Mute"),         this, SLOT(volumeMute()));
456

457 458 459 460 461
    m_accel->setConfigGroup("Shortcuts");
    m_accel->readSettings();
    m_accel->updateConnections();
}

462 463 464 465
void JuK::processArgs()
{
    KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
    QStringList files;
466

467
    for(int i = 0; i < args->count(); i++)
468
        files.append(args->arg(i));
469

470
    m_splitter->open(files);
471 472
}

473 474 475
void JuK::keyPressEvent(QKeyEvent *e)
{
    if (e->key() >= Qt::Key_Back && e->key() <= Qt::Key_MediaLast)
476
        e->accept();
477 478 479
    KMainWindow::keyPressEvent(e);
}

480 481 482 483 484 485 486 487 488
/**
 * 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");
489
        m_showSplash = config->readBoolEntry("ShowSplashScreen", true);
490
        m_startDocked = config->readBoolEntry("StartDocked", false);
491 492 493
    }
}

494 495
void JuK::readConfig()
{
496
    // Automagically save and m_restore many window settings.
497 498
    setAutoSaveSettings();

499
    KConfig *config = KGlobal::config();
500
    { // player settings
501
        KConfigGroupSaver saver(config, "Player");
502 503
        if(m_sliderAction->volumeSlider()) {
	    int maxVolume = m_sliderAction->volumeSlider()->maxValue();
Scott Wheeler's avatar
Scott Wheeler committed
504
	    int volume = config->readNumEntry("Volume", maxVolume);
505
            m_sliderAction->volumeSlider()->setValue(volume);
506
        }
507 508
        bool randomPlay = config->readBoolEntry("RandomPlay", false);
        m_randomPlayAction->setChecked(randomPlay);
509

510 511
        bool loopPlaylist = config->readBoolEntry("LoopPlaylist", false);
        m_loopPlaylistAction->setChecked(loopPlaylist);
512
    }
513
    { // view settings
514
        KConfigGroupSaver saver(config, "View");
515 516 517 518 519

        bool showSearch = config->readBoolEntry("ShowSearch", true);
        m_showSearchAction->setChecked(showSearch);
        m_splitter->slotSetSearchVisible(showSearch);

520 521 522
        bool showEditor = config->readBoolEntry("ShowEditor", false);
        m_showEditorAction->setChecked(showEditor);
        m_splitter->slotSetEditorVisible(showEditor);
523

524 525 526
	// 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.
527

528 529
	bool showHistory = config->readBoolEntry("ShowHistory", false);
	m_showHistoryAction->setChecked(showHistory);
530
    }
531 532
    { // general settings
        KConfigGroupSaver saver(config, "Settings");
533

534 535
        bool dockInSystemTray = config->readBoolEntry("DockInSystemTray", true);
        m_toggleSystemTrayAction->setChecked(dockInSystemTray);
536

537 538
        bool dockOnClose = config->readBoolEntry("DockOnClose", true);
        m_toggleDockOnCloseAction->setChecked(dockOnClose);
539

540 541
        bool showPopups = config->readBoolEntry("TrackPopup", false);
        m_togglePopupsAction->setChecked(showPopups);
542

543 544
        if(m_outputSelectAction)
            m_outputSelectAction->setCurrentItem(config->readNumEntry("MediaSystem", 0));
545
    }
546

547
    m_toggleSplashAction->setChecked(m_showSplash);
548 549 550 551
}

void JuK::saveConfig()
{
552
    KConfig *config = KGlobal::config();
553
    { // player settings
554
        KConfigGroupSaver saver(config, "Player");
555 556
        if(m_sliderAction && m_sliderAction->volumeSlider())
            config->writeEntry("Volume", m_sliderAction->volumeSlider()->value());
557 558 559 560
        if(m_randomPlayAction)
            config->writeEntry("RandomPlay", m_randomPlayAction->isChecked());
        if(m_loopPlaylistAction)
            config->writeEntry("LoopPlaylist", m_loopPlaylistAction->isChecked());
561
    }
562 563
    { // view settings
        KConfigGroupSaver saver(config, "View");
564

565
        config->writeEntry("ShowEditor", m_showEditorAction->isChecked());
566
        config->writeEntry("ShowSearch", m_showSearchAction->isChecked());
567
	config->writeEntry("ShowHistory", m_showHistoryAction->isChecked());
568
    }
569 570
    { // general settings
        KConfigGroupSaver saver(config, "Settings");
571
        config->writeEntry("ShowSplashScreen", m_toggleSplashAction->isChecked());
572
        config->writeEntry("StartDocked", m_startDocked);
573 574 575 576 577
        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());
578
    }
579
    config->sync();
580 581
}

582
bool JuK::queryExit()
583
{
584 585
    m_startDocked = !isVisible();

586 587 588 589
    hide();
    delete m_systemTray;
    m_systemTray = 0;

590
    Cache::instance()->save();
591
    saveConfig();
592
    delete m_splitter;
593
    return true;
594 595
}

596 597
bool JuK::queryClose()
{
598 599 600 601 602
    if(!m_shuttingDown &&
       !kapp->sessionSaving() &&
       m_systemTray &&
       m_toggleDockOnCloseAction->isChecked())
    {
603
	KMessageBox::information(this,
Scott Wheeler's avatar
Scott Wheeler committed
604 605 606
	    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");
607 608 609 610 611 612 613
	hide();
	return false;
    }
    else
	return true;
}

614 615 616
QString JuK::playingString() const
{
    QString s;
617 618
    if(!m_player->playing() && !m_player->paused())
	return i18n("No song playing");
619

620 621 622 623
    if(!m_splitter->playingArtist().isEmpty())
	s = m_splitter->playingArtist().simplifyWhiteSpace() + " - ";

    s += m_splitter->playingTrack().simplifyWhiteSpace();
624 625 626 627

    return s;
}

628 629
void JuK::updatePlaylistInfo()
{
Scott Wheeler's avatar
Scott Wheeler committed
630
    m_statusLabel->setPlaylistInfo(m_splitter->visiblePlaylistName(),
631 632
				   m_splitter->selectedPlaylistCount(),
				   m_splitter->selectedPlaylistTotalTime());
633 634 635 636
}

void JuK::play(const QString &file)
{
637
    m_player->play(file);
638
    emit signalNewSong(playingString());
639 640
}

Scott Wheeler's avatar
Scott Wheeler committed
641 642 643
KAction *JuK::createSplitterAction(const QString &text, const char *slot,
				   const char *name, const QString &pix,
				   const KShortcut &shortcut)
644 645 646 647 648 649 650 651 652
{
    KAction *action;

    if(pix.isNull())
	action = new KAction(text, shortcut, actionCollection(), name);
    else
	action = new KAction(text, pix, shortcut, actionCollection(), name);

    m_splitterConnections.append(SplitterConnection(action, slot));
653

654 655 656
    return action;
}

657 658 659 660
////////////////////////////////////////////////////////////////////////////////
// private slot definitions
////////////////////////////////////////////////////////////////////////////////

661
void JuK::slotPlaylistChanged()
662
{
663 664 665 666
    if(m_splitter->collectionListSelected() ||
       !m_splitter->hasListSelected() ||
       m_splitter->readOnlyListSelected())
    {
667 668 669 670 671
        action("file_save")->setEnabled(false);
        action("file_save_as")->setEnabled(false);
        action("renamePlaylist")->setEnabled(false);
        action("reloadPlaylist")->setEnabled(false);
        action("deleteItemPlaylist")->setEnabled(false);
672 673
    }
    else {
674 675 676 677
        action("file_save")->setEnabled(true);
        action("file_save_as")->setEnabled(true);
        action("renamePlaylist")->setEnabled(true);
        action("deleteItemPlaylist")->setEnabled(true);
678 679

	if(m_splitter->fileBasedListSelected() || m_splitter->dynamicListSelected())
680
	    action("reloadPlaylist")->setEnabled(true);
681
	else
682
	    action("reloadPlaylist")->setEnabled(false);
683
    }
684
    if(m_splitter->hasListSelected())
685
        action("duplicatePlaylist")->setEnabled(true);
686
    else
687
        action("duplicatePlaylist")->setEnabled(false);
688

689 690 691
    updatePlaylistInfo();
}

692 693 694 695 696
void JuK::slotQuit()
{
    kapp->quit();
}

697 698 699 700
////////////////////////////////////////////////////////////////////////////////
// settings menu
////////////////////////////////////////////////////////////////////////////////

701
void JuK::slotToggleSystemTray(bool enabled)
702
{
703
    if(enabled && !m_systemTray)
704
	setupSystemTray();
705 706 707
    else if(!enabled && m_systemTray) {
	delete m_systemTray;
	m_systemTray = 0;
708
	m_toggleDockOnCloseAction->setEnabled(false);
709
	m_togglePopupsAction->setEnabled(false);
710 711 712
    }
}

713 714 715 716 717
void JuK::slotEditKeys()
{
    KeyDialog::configure(m_accel, actionCollection(), this);
}

718
////////////////////////////////////////////////////////////////////////////////
719
// additional player slots
720 721
////////////////////////////////////////////////////////////////////////////////

722
void JuK::slotPlayCurrent()
723
{
724 725
    m_player->stop();
    action("play")->activate();
726 727
}

728 729
void JuK::slotConfigureTagGuesser()
{
730
    TagGuesserConfigDlg(this).exec();
731 732
}

733 734
void JuK::slotConfigureFileRenamer()
{
735
    FileRenamerConfigDlg(this).exec();
736 737
}

738
#include "juk.moc"