You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
479 lines
17 KiB
479 lines
17 KiB
/***************************************************************************
|
|
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(TQWidget *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(TQApplication::reverseLayout())
|
|
setupGUI(ToolBar | Save | Create, "jukui-rtl.rc");
|
|
else
|
|
setupGUI(ToolBar | Save | Create);
|
|
|
|
readConfig();
|
|
setupSystemTray();
|
|
setupGlobalAccels();
|
|
createDirs();
|
|
|
|
SplashScreen::finishedLoading();
|
|
TQTimer::singleShot(0, CollectionList::instance(), TQT_SLOT(slotCheckCache()));
|
|
TQTimer::singleShot(0, TQT_TQOBJECT(this), TQT_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(), TQT_SIGNAL(signalCollectionChanged()),
|
|
m_statusLabel, TQT_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(TQT_TQOBJECT(this), TQT_SLOT(slotQuit()), ActionCollection::actions());
|
|
KStdAction::undo(TQT_TQOBJECT(this), TQT_SLOT(slotUndo()), ActionCollection::actions());
|
|
KStdAction::cut(TQT_TQOBJECT(kapp), TQT_SLOT(cut()), ActionCollection::actions());
|
|
KStdAction::copy(TQT_TQOBJECT(kapp), TQT_SLOT(copy()), ActionCollection::actions());
|
|
KStdAction::paste(TQT_TQOBJECT(kapp), TQT_SLOT(paste()), ActionCollection::actions());
|
|
KStdAction::clear(TQT_TQOBJECT(kapp), TQT_SLOT(clear()), ActionCollection::actions());
|
|
KStdAction::selectAll(TQT_TQOBJECT(kapp), TQT_SLOT(selectAll()), ActionCollection::actions());
|
|
|
|
new KAction(i18n("Remove From Playlist"), "edit_remove", 0, TQT_TQOBJECT(kapp), TQT_SLOT(clear()), ActionCollection::actions(), "removeFromPlaylist");
|
|
|
|
KActionMenu *actionMenu = new KActionMenu(i18n("&Random Play"), "roll", ActionCollection::actions(), "actionMenu");
|
|
actionMenu->setDelayed(false);
|
|
|
|
KRadioAction *ka = new KRadioAction(i18n("&Disable Random Play"), "player_playlist", 0, ActionCollection::actions(), "disableRandomPlay");
|
|
ka->setExclusiveGroup("randomPlayGroup");
|
|
actionMenu->insert(ka);
|
|
|
|
m_randomPlayAction = new KRadioAction(i18n("Use &Random Play"), "roll", 0, ActionCollection::actions(), "randomPlay");
|
|
m_randomPlayAction->setExclusiveGroup("randomPlayGroup");
|
|
actionMenu->insert(m_randomPlayAction);
|
|
|
|
ka = new KRadioAction(i18n("Use &Album Random Play"), "roll", 0, ActionCollection::actions(), "albumRandomPlay");
|
|
ka->setExclusiveGroup("randomPlayGroup");
|
|
connect(ka, TQT_SIGNAL(toggled(bool)), TQT_SLOT(slotCheckAlbumNextAction(bool)));
|
|
actionMenu->insert(ka);
|
|
|
|
new KAction(i18n("&Play"), "player_play", 0, TQT_TQOBJECT(m_player), TQT_SLOT(play()), ActionCollection::actions(), "play");
|
|
new KAction(i18n("P&ause"), "player_pause", 0, TQT_TQOBJECT(m_player), TQT_SLOT(pause()), ActionCollection::actions(), "pause");
|
|
new KAction(i18n("&Stop"), "player_stop", 0, TQT_TQOBJECT(m_player), TQT_SLOT(stop()), ActionCollection::actions(), "stop");
|
|
|
|
new KToolBarPopupAction(i18n("previous track", "Previous"), "player_start", KShortcut(), TQT_TQOBJECT(m_player), TQT_SLOT(back()), ActionCollection::actions(), "back");
|
|
new KAction(i18n("next track", "&Next"), "player_end", KShortcut(), TQT_TQOBJECT(m_player), TQT_SLOT(forward()), ActionCollection::actions(), "forward");
|
|
new KToggleAction(i18n("&Loop Playlist"), 0, KShortcut(), ActionCollection::actions(), "loopPlaylist");
|
|
KToggleAction *resizeColumnAction =
|
|
new KToggleAction(i18n("&Resize Playlist Columns Manually"),
|
|
KShortcut(), ActionCollection::actions(), "resizeColumnsManually");
|
|
resizeColumnAction->setCheckedState(i18n("&Resize Column Headers Automatically"));
|
|
|
|
// the following are not visible by default
|
|
|
|
new KAction(i18n("Mute"), "mute", 0, TQT_TQOBJECT(m_player), TQT_SLOT(mute()), ActionCollection::actions(), "mute");
|
|
new KAction(i18n("Volume Up"), "volumeUp", 0, TQT_TQOBJECT(m_player), TQT_SLOT(volumeUp()), ActionCollection::actions(), "volumeUp");
|
|
new KAction(i18n("Volume Down"), "volumeDown", 0, TQT_TQOBJECT(m_player), TQT_SLOT(volumeDown()), ActionCollection::actions(), "volumeDown");
|
|
new KAction(i18n("Play / Pause"), "playPause", 0, TQT_TQOBJECT(m_player), TQT_SLOT(playPause()), ActionCollection::actions(), "playPause");
|
|
new KAction(i18n("Seek Forward"), "seekForward", 0, TQT_TQOBJECT(m_player), TQT_SLOT(seekForward()), ActionCollection::actions(), "seekForward");
|
|
new KAction(i18n("Seek Back"), "seekBack", 0, TQT_TQOBJECT(m_player), TQT_SLOT(seekBack()), ActionCollection::actions(), "seekBack");
|
|
|
|
//////////////////////////////////////////////////
|
|
// settings menu
|
|
//////////////////////////////////////////////////
|
|
|
|
m_toggleSplashAction =
|
|
new KToggleAction(i18n("Show Splash Screen on Startup"),
|
|
KShortcut(), ActionCollection::actions(), "showSplashScreen");
|
|
m_toggleSplashAction->setCheckedState(i18n("Hide Splash Screen on Startup"));
|
|
m_toggleSystemTrayAction =
|
|
new KToggleAction(i18n("&Dock in System Tray"),
|
|
KShortcut(), ActionCollection::actions(), "toggleSystemTray");
|
|
m_toggleDockOnCloseAction =
|
|
new KToggleAction(i18n("&Stay in System Tray on Close"),
|
|
KShortcut(), ActionCollection::actions(), "dockOnClose");
|
|
m_togglePopupsAction =
|
|
new KToggleAction(i18n("Popup &Track Announcement"),
|
|
KShortcut(), TQT_TQOBJECT(this), 0, ActionCollection::actions(), "togglePopups");
|
|
new KToggleAction(i18n("Save &Play Queue on Exit"),
|
|
KShortcut(), TQT_TQOBJECT(this), 0, ActionCollection::actions(), "saveUpcomingTracks");
|
|
|
|
connect(m_toggleSystemTrayAction, TQT_SIGNAL(toggled(bool)),
|
|
this, TQT_SLOT(slotToggleSystemTray(bool)));
|
|
|
|
|
|
m_outputSelectAction = PlayerManager::playerSelectAction(ActionCollection::actions());
|
|
|
|
if(m_outputSelectAction)
|
|
m_outputSelectAction->setCurrentItem(0);
|
|
|
|
new KAction(i18n("&Tag Guesser..."), 0, 0, TQT_TQOBJECT(this), TQT_SLOT(slotConfigureTagGuesser()),
|
|
ActionCollection::actions(), "tagGuesserConfig");
|
|
|
|
new KAction(i18n("&File Renamer..."), 0, 0, TQT_TQOBJECT(this), TQT_SLOT(slotConfigureFileRenamer()),
|
|
ActionCollection::actions(), "fileRenamerConfig");
|
|
|
|
KStdAction::keyBindings(TQT_TQOBJECT(this), TQT_SLOT(slotEditKeys()), ActionCollection::actions());
|
|
|
|
//////////////////////////////////////////////////
|
|
// just in the toolbar
|
|
//////////////////////////////////////////////////
|
|
|
|
m_sliderAction = new SliderAction(i18n("Track Position"), ActionCollection::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, TQT_SIGNAL(quitSelected()), TQT_TQOBJECT(this), TQT_SLOT(slotAboutToQuit()));
|
|
}
|
|
else {
|
|
m_systemTray = 0;
|
|
m_toggleDockOnCloseAction->setEnabled(false);
|
|
m_togglePopupsAction->setEnabled(false);
|
|
}
|
|
}
|
|
|
|
void JuK::setupGlobalAccels()
|
|
{
|
|
m_accel = new KGlobalAccel(TQT_TQOBJECT(this));
|
|
|
|
KeyDialog::insert(m_accel, "Play", i18n("Play"), action("play"), TQT_SLOT(activate()));
|
|
KeyDialog::insert(m_accel, "PlayPause", i18n("Play / Pause"), action("playPause"), TQT_SLOT(activate()));
|
|
KeyDialog::insert(m_accel, "Stop", i18n("Stop Playing"), action("stop"), TQT_SLOT(activate()));
|
|
KeyDialog::insert(m_accel, "Back", i18n("Back"), action("back"), TQT_SLOT(activate()));
|
|
KeyDialog::insert(m_accel, "Forward", i18n("Forward"), action("forward"), TQT_SLOT(activate()));
|
|
KeyDialog::insert(m_accel, "SeekBack", i18n("Seek Back"), action("seekBack"), TQT_SLOT(activate()));
|
|
KeyDialog::insert(m_accel, "SeekForward", i18n("Seek Forward"), action("seekForward"), TQT_SLOT(activate()));
|
|
KeyDialog::insert(m_accel, "VolumeUp", i18n("Volume Up"), action("volumeUp"), TQT_SLOT(activate()));
|
|
KeyDialog::insert(m_accel, "VolumeDown", i18n("Volume Down"), action("volumeDown"), TQT_SLOT(activate()));
|
|
KeyDialog::insert(m_accel, "Mute", i18n("Mute"), action("mute"), TQT_SLOT(activate()));
|
|
KeyDialog::insert(m_accel, "ShowHide", i18n("Show / Hide"), TQT_TQOBJECT(this), TQT_SLOT(slotShowHide()));
|
|
KeyDialog::insert(m_accel, "ForwardAlbum", i18n("Play Next Album"), action("forwardAlbum"), TQT_SLOT(activate()));
|
|
|
|
m_accel->setConfigGroup("Shortcuts");
|
|
m_accel->readSettings();
|
|
m_accel->updateConnections();
|
|
}
|
|
|
|
void JuK::slotProcessArgs()
|
|
{
|
|
KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
|
|
TQStringList files;
|
|
|
|
for(int i = 0; i < args->count(); i++)
|
|
files.append(args->arg(i));
|
|
|
|
CollectionList::instance()->addFiles(files);
|
|
}
|
|
|
|
void JuK::createDirs()
|
|
{
|
|
TQDir 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(TQKeyEvent *e)
|
|
{
|
|
if (e->key() >= TQt::Key_Back && e->key() <= TQt::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);
|
|
|
|
TQString 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, ActionCollection::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"
|