diff options
Diffstat (limited to 'juk/juk.cpp')
-rw-r--r-- | juk/juk.cpp | 478 |
1 files changed, 478 insertions, 0 deletions
diff --git a/juk/juk.cpp b/juk/juk.cpp new file mode 100644 index 00000000..a3e0988c --- /dev/null +++ b/juk/juk.cpp @@ -0,0 +1,478 @@ +/*************************************************************************** + begin : Mon Feb 4 23:40:41 EST 2002 + copyright : (C) 2002 - 2004 by Scott Wheeler + email : wheeler@kde.org +***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include <config.h> + +#include <kcmdlineargs.h> +#include <kstatusbar.h> +#include <kdebug.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> + + +#include "juk.h" +#include "slideraction.h" +#include "statuslabel.h" +#include "splashscreen.h" +#include "systemtray.h" +#include "keydialog.h" +#include "tagguesserconfigdlg.h" +#include "filerenamerconfigdlg.h" +#include "actioncollection.h" +#include "cache.h" +#include "playlistsplitter.h" +#include "collectionlist.h" +#include "covermanager.h" +#include "tagtransactionmanager.h" + +using namespace ActionCollection; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +JuK::JuK(QWidget *parent, const char *name) : + KMainWindow(parent, name, WDestructiveClose), + m_player(PlayerManager::instance()), + m_shuttingDown(false) +{ + // Expect segfaults if you change this order. + + readSettings(); + + if(m_showSplash && !m_startDocked && Cache::cacheFileExists()) { + SplashScreen::instance()->show(); + kapp->processEvents(); + } + + setupActions(); + setupLayout(); + + if(QApplication::reverseLayout()) + setupGUI(ToolBar | Save | Create, "jukui-rtl.rc"); + else + setupGUI(ToolBar | Save | Create); + + readConfig(); + setupSystemTray(); + setupGlobalAccels(); + createDirs(); + + SplashScreen::finishedLoading(); + QTimer::singleShot(0, CollectionList::instance(), SLOT(slotCheckCache())); + QTimer::singleShot(0, this, SLOT(slotProcessArgs())); + + m_sliderAction->slotUpdateOrientation(); +} + +JuK::~JuK() +{ + kdDebug(65432) << k_funcinfo << endl; +} + +KActionCollection *JuK::actionCollection() const +{ + return ActionCollection::actions(); +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void JuK::setupLayout() +{ + new TagTransactionManager(this); + + m_splitter = new PlaylistSplitter(this, "playlistSplitter"); + setCentralWidget(m_splitter); + + m_statusLabel = new StatusLabel(m_splitter->playlist(), statusBar()); + connect(CollectionList::instance(), SIGNAL(signalCollectionChanged()), + m_statusLabel, SLOT(updateData())); + statusBar()->addWidget(m_statusLabel, 1); + PlayerManager::instance()->setStatusLabel(m_statusLabel); + + m_splitter->setFocus(); + resize(750, 500); +} + +void JuK::setupActions() +{ + ActionCollection::actions()->setWidget(this); + + KStdAction::quit(this, SLOT(slotQuit()), actions()); + KStdAction::undo(this, SLOT(slotUndo()), 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()); + + new KAction(i18n("Remove From Playlist"), "edit_remove", 0, kapp, SLOT(clear()), actions(), "removeFromPlaylist"); + + KActionMenu *actionMenu = new KActionMenu(i18n("&Random Play"), "roll", actions(), "actionMenu"); + actionMenu->setDelayed(false); + + KRadioAction *ka = new KRadioAction(i18n("&Disable Random Play"), "player_playlist", 0, actions(), "disableRandomPlay"); + ka->setExclusiveGroup("randomPlayGroup"); + actionMenu->insert(ka); + + m_randomPlayAction = new KRadioAction(i18n("Use &Random Play"), "roll", 0, actions(), "randomPlay"); + m_randomPlayAction->setExclusiveGroup("randomPlayGroup"); + actionMenu->insert(m_randomPlayAction); + + ka = new KRadioAction(i18n("Use &Album Random Play"), "roll", 0, actions(), "albumRandomPlay"); + ka->setExclusiveGroup("randomPlayGroup"); + connect(ka, SIGNAL(toggled(bool)), SLOT(slotCheckAlbumNextAction(bool))); + actionMenu->insert(ka); + + 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"); + + new KToolBarPopupAction(i18n("previous track", "Previous"), "player_start", KShortcut(), m_player, SLOT(back()), actions(), "back"); + new KAction(i18n("next track", "&Next"), "player_end", KShortcut(), m_player, SLOT(forward()), actions(), "forward"); + new KToggleAction(i18n("&Loop Playlist"), 0, KShortcut(), actions(), "loopPlaylist"); + KToggleAction *resizeColumnAction = + new KToggleAction(i18n("&Resize Playlist Columns Manually"), + KShortcut(), actions(), "resizeColumnsManually"); + resizeColumnAction->setCheckedState(i18n("&Resize Column Headers Automatically")); + + // the following are not visible by default + + 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"); + + ////////////////////////////////////////////////// + // settings menu + ////////////////////////////////////////////////// + + m_toggleSplashAction = + new KToggleAction(i18n("Show Splash Screen on Startup"), + KShortcut(), actions(), "showSplashScreen"); + m_toggleSplashAction->setCheckedState(i18n("Hide Splash Screen on Startup")); + m_toggleSystemTrayAction = + new KToggleAction(i18n("&Dock in System Tray"), + KShortcut(), actions(), "toggleSystemTray"); + m_toggleDockOnCloseAction = + new KToggleAction(i18n("&Stay in System Tray on Close"), + KShortcut(), actions(), "dockOnClose"); + m_togglePopupsAction = + new KToggleAction(i18n("Popup &Track Announcement"), + KShortcut(), this, 0, actions(), "togglePopups"); + new KToggleAction(i18n("Save &Play Queue on Exit"), + KShortcut(), this, 0, actions(), "saveUpcomingTracks"); + + connect(m_toggleSystemTrayAction, SIGNAL(toggled(bool)), + this, SLOT(slotToggleSystemTray(bool))); + + + m_outputSelectAction = PlayerManager::playerSelectAction(actions()); + + if(m_outputSelectAction) + m_outputSelectAction->setCurrentItem(0); + + new KAction(i18n("&Tag Guesser..."), 0, 0, this, SLOT(slotConfigureTagGuesser()), + actions(), "tagGuesserConfig"); + + new KAction(i18n("&File Renamer..."), 0, 0, this, SLOT(slotConfigureFileRenamer()), + actions(), "fileRenamerConfig"); + + KStdAction::keyBindings(this, SLOT(slotEditKeys()), actions()); + + ////////////////////////////////////////////////// + // just in the toolbar + ////////////////////////////////////////////////// + + m_sliderAction = new SliderAction(i18n("Track Position"), actions(), + "trackPositionAction"); +} + +void JuK::setupSystemTray() +{ + if(m_toggleSystemTrayAction && m_toggleSystemTrayAction->isChecked()) { + m_systemTray = new SystemTray(this, "systemTray"); + m_systemTray->show(); + + m_toggleDockOnCloseAction->setEnabled(true); + m_togglePopupsAction->setEnabled(true); + + connect(m_systemTray, SIGNAL(quitSelected()), this, SLOT(slotAboutToQuit())); + } + else { + m_systemTray = 0; + m_toggleDockOnCloseAction->setEnabled(false); + m_togglePopupsAction->setEnabled(false); + } +} + +void JuK::setupGlobalAccels() +{ + m_accel = new KGlobalAccel(this); + + KeyDialog::insert(m_accel, "Play", i18n("Play"), action("play"), SLOT(activate())); + 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())); + KeyDialog::insert(m_accel, "ShowHide", i18n("Show / Hide"), this, SLOT(slotShowHide())); + KeyDialog::insert(m_accel, "ForwardAlbum", i18n("Play Next Album"), action("forwardAlbum"), SLOT(activate())); + + m_accel->setConfigGroup("Shortcuts"); + m_accel->readSettings(); + m_accel->updateConnections(); +} + +void JuK::slotProcessArgs() +{ + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + QStringList files; + + for(int i = 0; i < args->count(); i++) + files.append(args->arg(i)); + + CollectionList::instance()->addFiles(files); +} + +void JuK::createDirs() +{ + QDir dir(KGlobal::dirs()->saveLocation("data", kapp->instanceName() + '/')); + if (!dir.exists("covers", false)) + dir.mkdir("covers", false); + dir.cd("covers"); + if (!dir.exists("large", false)) + dir.mkdir("large", false); +} + +void JuK::keyPressEvent(QKeyEvent *e) +{ + if (e->key() >= Qt::Key_Back && e->key() <= Qt::Key_MediaLast) + e->accept(); + KMainWindow::keyPressEvent(e); +} + +/** + * These are settings that need to be know before setting up the GUI. + */ + +void JuK::readSettings() +{ + KConfigGroup config(KGlobal::config(), "Settings"); + m_showSplash = config.readBoolEntry("ShowSplashScreen", true); + m_startDocked = config.readBoolEntry("StartDocked", false); +} + +void JuK::readConfig() +{ + // player settings + + KConfigGroup playerConfig(KGlobal::config(), "Player"); + + if(m_sliderAction->volumeSlider()) { + int maxVolume = m_sliderAction->volumeSlider()->maxValue(); + int volume = playerConfig.readNumEntry("Volume", maxVolume); + m_sliderAction->volumeSlider()->setVolume(volume); + } + + // Default to no random play + + ActionCollection::action<KToggleAction>("disableRandomPlay")->setChecked(true); + + QString randomPlayMode = playerConfig.readEntry("RandomPlay", "Disabled"); + if(randomPlayMode == "true" || randomPlayMode == "Normal") + m_randomPlayAction->setChecked(true); + else if(randomPlayMode == "AlbumRandomPlay") + ActionCollection::action<KToggleAction>("albumRandomPlay")->setChecked(true); + + bool loopPlaylist = playerConfig.readBoolEntry("LoopPlaylist", false); + ActionCollection::action<KToggleAction>("loopPlaylist")->setChecked(loopPlaylist); + + // general settings + + KConfigGroup settingsConfig(KGlobal::config(), "Settings"); + + bool dockInSystemTray = settingsConfig.readBoolEntry("DockInSystemTray", true); + m_toggleSystemTrayAction->setChecked(dockInSystemTray); + + bool dockOnClose = settingsConfig.readBoolEntry("DockOnClose", true); + m_toggleDockOnCloseAction->setChecked(dockOnClose); + + bool showPopups = settingsConfig.readBoolEntry("TrackPopup", false); + m_togglePopupsAction->setChecked(showPopups); + + if(m_outputSelectAction) + m_outputSelectAction->setCurrentItem(settingsConfig.readNumEntry("MediaSystem", 0)); + + m_toggleSplashAction->setChecked(m_showSplash); +} + +void JuK::saveConfig() +{ + // player settings + + KConfigGroup playerConfig(KGlobal::config(), "Player"); + + if (m_sliderAction->volumeSlider()) + { + playerConfig.writeEntry("Volume", m_sliderAction->volumeSlider()->volume()); + } + + playerConfig.writeEntry("RandomPlay", m_randomPlayAction->isChecked()); + + KToggleAction *a = ActionCollection::action<KToggleAction>("loopPlaylist"); + playerConfig.writeEntry("LoopPlaylist", a->isChecked()); + + a = ActionCollection::action<KToggleAction>("albumRandomPlay"); + if(a->isChecked()) + playerConfig.writeEntry("RandomPlay", "AlbumRandomPlay"); + else if(m_randomPlayAction->isChecked()) + playerConfig.writeEntry("RandomPlay", "Normal"); + else + playerConfig.writeEntry("RandomPlay", "Disabled"); + + // general settings + + KConfigGroup settingsConfig(KGlobal::config(), "Settings"); + settingsConfig.writeEntry("ShowSplashScreen", m_toggleSplashAction->isChecked()); + settingsConfig.writeEntry("StartDocked", m_startDocked); + settingsConfig.writeEntry("DockInSystemTray", m_toggleSystemTrayAction->isChecked()); + settingsConfig.writeEntry("DockOnClose", m_toggleDockOnCloseAction->isChecked()); + settingsConfig.writeEntry("TrackPopup", m_togglePopupsAction->isChecked()); + if(m_outputSelectAction) + settingsConfig.writeEntry("MediaSystem", m_outputSelectAction->currentItem()); + + KGlobal::config()->sync(); +} + +bool JuK::queryExit() +{ + m_startDocked = !isVisible(); + + kdDebug(65432) << k_funcinfo << endl; + + hide(); + + action("stop")->activate(); + delete m_systemTray; + m_systemTray = 0; + + CoverManager::shutdown(); + Cache::instance()->save(); + saveConfig(); + + delete m_splitter; + m_splitter = 0; + return true; +} + +bool JuK::queryClose() +{ + kdDebug(65432) << k_funcinfo << endl; + + if(!m_shuttingDown && + !kapp->sessionSaving() && + m_systemTray && + m_toggleDockOnCloseAction->isChecked()) + { + KMessageBox::information(this, + 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"); + hide(); + return false; + } + else + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// private slot definitions +//////////////////////////////////////////////////////////////////////////////// + +void JuK::slotShowHide() +{ + setShown(!isShown()); +} + +void JuK::slotAboutToQuit() +{ + m_shuttingDown = true; +} + +void JuK::slotQuit() +{ + kdDebug(65432) << k_funcinfo << endl; + m_shuttingDown = true; + + kapp->quit(); +} + +//////////////////////////////////////////////////////////////////////////////// +// settings menu +//////////////////////////////////////////////////////////////////////////////// + +void JuK::slotToggleSystemTray(bool enabled) +{ + if(enabled && !m_systemTray) + setupSystemTray(); + else if(!enabled && m_systemTray) { + delete m_systemTray; + m_systemTray = 0; + m_toggleDockOnCloseAction->setEnabled(false); + m_togglePopupsAction->setEnabled(false); + } +} + +void JuK::slotEditKeys() +{ + KeyDialog::configure(m_accel, actions(), this); +} + +void JuK::slotConfigureTagGuesser() +{ + TagGuesserConfigDlg(this).exec(); +} + +void JuK::slotConfigureFileRenamer() +{ + FileRenamerConfigDlg(this).exec(); +} + +void JuK::slotUndo() +{ + TagTransactionManager::instance()->undo(); +} + +void JuK::slotCheckAlbumNextAction(bool albumRandomEnabled) +{ + // If album random play is enabled, then enable the Play Next Album action + // unless we're not playing right now. + + if(albumRandomEnabled && !m_player->playing()) + albumRandomEnabled = false; + + action("forwardAlbum")->setEnabled(albumRandomEnabled); +} + +#include "juk.moc" |