File indexing completed on 2022-08-11 17:17:09
0001 /** 0002 * Copyright (C) 2002-2004 Scott Wheeler <wheeler@kde.org> 0003 * Copyright (C) 2008, 2009, 2017 Michael Pyne <mpyne@kde.org> 0004 * 0005 * This program is free software; you can redistribute it and/or modify it under 0006 * the terms of the GNU General Public License as published by the Free Software 0007 * Foundation; either version 2 of the License, or (at your option) any later 0008 * version. 0009 * 0010 * This program is distributed in the hope that it will be useful, but WITHOUT ANY 0011 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 0012 * PARTICULAR PURPOSE. See the GNU General Public License for more details. 0013 * 0014 * You should have received a copy of the GNU General Public License along with 0015 * this program. If not, see <http://www.gnu.org/licenses/>. 0016 */ 0017 0018 #include "juk.h" 0019 0020 #include <KSharedConfig> 0021 #include <kaboutdata.h> 0022 #include <kactioncollection.h> 0023 #include <kactionmenu.h> 0024 #include <kconfiggroup.h> 0025 #include <kglobalaccel.h> 0026 #include <kmessagebox.h> 0027 #include <knotification.h> 0028 #include <kstandardaction.h> 0029 #include <ktoggleaction.h> 0030 #include <ktoolbarpopupaction.h> 0031 0032 #include <QAction> 0033 #include <QCoreApplication> 0034 #include <QDBusInterface> 0035 #include <QDBusMessage> 0036 #include <QDBusReply> 0037 #include <QDir> 0038 #include <QDirIterator> 0039 #include <QIcon> 0040 #include <QKeyEvent> 0041 #include <QMenuBar> 0042 #include <QMetaType> 0043 #include <QScreen> 0044 #include <QStatusBar> 0045 #include <QTime> 0046 #include <QTimer> 0047 0048 #include "actioncollection.h" 0049 #include "cache.h" 0050 #include "collectionlist.h" 0051 #include "covermanager.h" 0052 #include "filerenamerconfigdlg.h" 0053 #include "iconsupport.h" 0054 #include "keydialog.h" 0055 #include "playermanager.h" 0056 #include "playlistsplitter.h" 0057 #include "scrobbleconfigdlg.h" 0058 #include "scrobbler.h" 0059 #include "slideraction.h" 0060 #include "statuslabel.h" 0061 #include "systemtray.h" 0062 #include "tagguesserconfigdlg.h" 0063 #include "tagtransactionmanager.h" 0064 0065 #include "juk_debug.h" 0066 0067 using namespace ActionCollection; // ""_act and others 0068 using namespace IconSupport; // ""_icon 0069 0070 JuK* JuK::m_instance; 0071 0072 template<class T> 0073 void deleteAndClear(T *&ptr) 0074 { 0075 delete ptr; 0076 ptr = 0; 0077 } 0078 0079 //////////////////////////////////////////////////////////////////////////////// 0080 // public members 0081 //////////////////////////////////////////////////////////////////////////////// 0082 0083 JuK::JuK(const QStringList &filesToOpen, QWidget *parent) 0084 : KXmlGuiWindow(parent, Qt::WindowFlags(Qt::WA_DeleteOnClose)) 0085 , m_player(new PlayerManager) 0086 , m_filesToOpen(filesToOpen) 0087 { 0088 // Expect segfaults if you change this order. 0089 0090 // Allow to be passed across threads 0091 qRegisterMetaType<FileHandle>(); 0092 qRegisterMetaType<FileHandleList>(); 0093 0094 m_instance = this; 0095 0096 Cache::ensureAppDataStorageExists(); 0097 0098 setupActions(); 0099 setupLayout(); // Creates PlaylistSplitter and therefore CollectionList 0100 0101 bool firstRun = !KSharedConfig::openConfig()->hasGroup("MainWindow"); 0102 0103 if(firstRun) { 0104 KConfigGroup mainWindowConfig(KSharedConfig::openConfig(), "MainWindow"); 0105 KConfigGroup playToolBarConfig(&mainWindowConfig, "Toolbar playToolBar"); 0106 playToolBarConfig.writeEntry("ToolButtonStyle", "IconOnly"); 0107 } 0108 0109 QSize defaultSize(800, 480); 0110 0111 if(QApplication::isRightToLeft()) 0112 setupGUI(defaultSize, ToolBar | Save | Create, "jukui-rtl.rc"); 0113 else 0114 setupGUI(defaultSize, ToolBar | Save | Create); 0115 0116 // Center the GUI if this is our first run ever. 0117 0118 if(firstRun) { 0119 QRect r = rect(); 0120 const QRect screenCenter = QApplication::primaryScreen()->availableGeometry(); 0121 r.moveCenter(screenCenter.center()); 0122 move(r.topLeft()); 0123 } 0124 0125 connect(m_splitter, SIGNAL(guiReady()), SLOT(slotSetupSystemTray())); 0126 readConfig(); 0127 setupGlobalAccels(); 0128 activateScrobblerIfEnabled(); 0129 0130 QDBusInterface *pmInterface = new QDBusInterface(QStringLiteral("org.kde.Solid.PowerManagement"), 0131 QStringLiteral("/org/freedesktop/PowerManagement/Inhibit"), 0132 QStringLiteral("org.freedesktop.PowerManagement.Inhibit"), 0133 QDBusConnection::sessionBus()); 0134 0135 connect(m_player, &PlayerManager::signalPlay, pmInterface, [=] () { 0136 QDBusReply<uint> reply; 0137 if(pmInterface->isValid() && (m_pmToken == 0)) { 0138 reply = pmInterface->call(QStringLiteral("Inhibit"), 0139 KAboutData::applicationData().componentName(), 0140 QStringLiteral("playing audio")); 0141 if(reply.isValid()) { 0142 m_pmToken = reply.value(); 0143 } 0144 } 0145 }); 0146 0147 auto uninhibitPowerManagement = [=] () { 0148 QDBusMessage reply; 0149 if(pmInterface->isValid() && (m_pmToken != 0)) { 0150 reply = pmInterface->call(QStringLiteral("UnInhibit"), m_pmToken); 0151 if(reply.errorName().isEmpty()) { 0152 m_pmToken = 0; 0153 } 0154 } 0155 }; 0156 0157 connect(m_player, &PlayerManager::signalPause, uninhibitPowerManagement); 0158 connect(m_player, &PlayerManager::signalStop, uninhibitPowerManagement); 0159 0160 // KMainWindow will close the window on this signal, but we need the visible state 0161 // of it in saveConfig() 0162 disconnect(qApp, &QGuiApplication::commitDataRequest, nullptr, nullptr); 0163 0164 connect(qApp, &QGuiApplication::commitDataRequest, this, [this]() { saveConfig(); }, 0165 Qt::DirectConnection); 0166 0167 // slotCheckCache loads the cached entries first to populate the collection list 0168 0169 QTimer::singleShot(0, this, SLOT(slotClearOldCovers())); 0170 QTimer::singleShot(0, CollectionList::instance(), SLOT(startLoadingCachedItems())); 0171 QTimer::singleShot(0, this, SLOT(slotProcessArgs())); 0172 } 0173 0174 JuK::~JuK() 0175 { 0176 if(!m_shuttingDown) 0177 slotQuit(); 0178 0179 // Some items need to be deleted before others, though I haven't looked 0180 // at this in some time so refinement is probably possible. 0181 delete m_systemTray; 0182 delete m_splitter; 0183 delete m_player; 0184 delete m_statusLabel; 0185 0186 // Sometimes KMainWindow doesn't actually call QCoreApplication::quit 0187 // after queryClose, even if not in a session shutdown, so make sure to 0188 // do so ourselves when closing the main window. 0189 QTimer::singleShot(0, qApp, &QCoreApplication::quit); 0190 } 0191 0192 JuK* JuK::JuKInstance() 0193 { 0194 return m_instance; 0195 } 0196 0197 PlayerManager *JuK::playerManager() const 0198 { 0199 return m_player; 0200 } 0201 0202 void JuK::coverDownloaded(const QPixmap &cover) 0203 { 0204 QString event(cover.isNull() ? "coverFailed" : "coverDownloaded"); 0205 KNotification *notification = new KNotification(event); 0206 notification->setWidget(this); 0207 notification->setPixmap(cover); 0208 notification->setFlags(KNotification::CloseOnTimeout); 0209 0210 if(cover.isNull()) 0211 notification->setText(i18n("Your album art failed to download.")); 0212 else 0213 notification->setText(i18n("Your album art has finished downloading.")); 0214 0215 notification->sendEvent(); 0216 } 0217 0218 //////////////////////////////////////////////////////////////////////////////// 0219 // private members 0220 //////////////////////////////////////////////////////////////////////////////// 0221 0222 void JuK::setupLayout() 0223 { 0224 m_splitter = new PlaylistSplitter(m_player, this); 0225 setCentralWidget(m_splitter); 0226 0227 m_statusLabel = new StatusLabel(*m_splitter->playlist(), statusBar()); 0228 statusBar()->addWidget(m_statusLabel, 1); 0229 connect(m_player, &PlayerManager::tick, m_statusLabel, 0230 &StatusLabel::setItemCurrentTime); 0231 connect(m_player, &PlayerManager::totalTimeChanged, 0232 m_statusLabel, &StatusLabel::setItemTotalTime); 0233 connect(m_splitter, &PlaylistSplitter::currentPlaylistChanged, 0234 m_statusLabel, &StatusLabel::slotCurrentPlaylistHasChanged); 0235 0236 m_splitter->setFocus(); 0237 } 0238 0239 void JuK::setupActions() 0240 { 0241 KActionCollection *collection = ActionCollection::actions(); 0242 0243 // Setup KDE standard actions that JuK uses. 0244 0245 KStandardAction::quit(this, SLOT(slotQuit()), collection); 0246 KStandardAction::undo(this, SLOT(slotUndo()), collection); 0247 KStandardAction::cut(collection); 0248 KStandardAction::copy(collection); 0249 KStandardAction::paste(collection); 0250 QAction *clear = KStandardAction::clear(collection); 0251 KStandardAction::selectAll(collection); 0252 KStandardAction::keyBindings(this, SLOT(slotEditKeys()), collection); 0253 KStandardAction::showMenubar(menuBar(), SLOT(setVisible(bool)), collection); 0254 0255 // Setup the menu which handles the random play options. 0256 KActionMenu *actionMenu = collection->add<KActionMenu>("actionMenu"); 0257 actionMenu->setText(i18n("&Random Play")); 0258 actionMenu->setIcon("media-playlist-shuffle"_icon); 0259 actionMenu->setPopupMode(QToolButton::InstantPopup); 0260 0261 QActionGroup* randomPlayGroup = new QActionGroup(this); 0262 0263 QAction *act = collection->add<KToggleAction>("disableRandomPlay"); 0264 act->setText(i18n("&Disable Random Play")); 0265 act->setIcon("go-down"_icon); 0266 act->setActionGroup(randomPlayGroup); 0267 actionMenu->addAction(act); 0268 0269 m_randomPlayAction = collection->add<KToggleAction>("randomPlay"); 0270 m_randomPlayAction->setText(i18n("Use &Random Play")); 0271 m_randomPlayAction->setIcon("media-playlist-shuffle"_icon); 0272 m_randomPlayAction->setActionGroup(randomPlayGroup); 0273 actionMenu->addAction(m_randomPlayAction); 0274 0275 act = collection->add<KToggleAction>("albumRandomPlay"); 0276 act->setText(i18n("Use &Album Random Play")); 0277 act->setIcon("media-playlist-shuffle"_icon); 0278 act->setActionGroup(randomPlayGroup); 0279 connect(act, &QAction::toggled, 0280 this, &JuK::slotCheckAlbumNextAction); 0281 actionMenu->addAction(act); 0282 0283 act = collection->addAction("removeFromPlaylist", clear, SLOT(clear())); 0284 act->setText(i18n("Remove From Playlist")); 0285 act->setIcon("list-remove"_icon); 0286 0287 act = collection->addAction("play", m_player, SLOT(play())); 0288 act->setText(i18n("&Play")); 0289 act->setIcon("media-playback-start"_icon); 0290 0291 act = collection->addAction("pause", m_player, SLOT(pause())); 0292 act->setEnabled(false); 0293 act->setText(i18n("P&ause")); 0294 act->setIcon("media-playback-pause"_icon); 0295 0296 act = collection->addAction("stop", m_player, SLOT(stop())); 0297 act->setEnabled(false); 0298 act->setText(i18n("&Stop")); 0299 act->setIcon("media-playback-stop"_icon); 0300 0301 act = new KToolBarPopupAction("media-skip-backward"_icon, i18nc("previous track", "Previous" ), collection); 0302 act->setEnabled(false); 0303 collection->addAction("back", act); 0304 connect(act, SIGNAL(triggered(bool)), m_player, SLOT(back())); 0305 0306 act = collection->addAction("forward", m_player, SLOT(forward())); 0307 act->setEnabled(false); 0308 act->setText(i18nc("next track", "&Next")); 0309 act->setIcon("media-skip-forward"_icon); 0310 0311 act = collection->addAction("loopPlaylist"); 0312 act->setText(i18n("&Loop Playlist")); 0313 act->setCheckable(true); 0314 0315 act = collection->add<KToggleAction>("resizeColumnsManually"); 0316 act->setText(i18n("&Resize Playlist Columns Manually")); 0317 0318 // the following are not visible by default 0319 0320 act = collection->addAction("mute", m_player, SLOT(mute())); 0321 act->setText(i18nc("silence playback", "Mute")); 0322 act->setIcon("audio-volume-muted"_icon); 0323 0324 act = collection->addAction("volumeUp", m_player, SLOT(volumeUp())); 0325 act->setText(i18n("Volume Up")); 0326 act->setIcon("audio-volume-high"_icon); 0327 0328 act = collection->addAction("volumeDown", m_player, SLOT(volumeDown())); 0329 act->setText(i18n("Volume Down")); 0330 act->setIcon("audio-volume-low"_icon); 0331 0332 act = collection->addAction("playPause", m_player, SLOT(playPause())); 0333 act->setText(i18n("Play / Pause")); 0334 act->setIcon("media-playback-start"_icon); 0335 0336 act = collection->addAction("seekForward", m_player, SLOT(seekForward())); 0337 act->setText(i18n("Seek Forward")); 0338 act->setIcon("media-seek-forward"_icon); 0339 0340 act = collection->addAction("seekBack", m_player, SLOT(seekBack())); 0341 act->setText(i18n("Seek Back")); 0342 act->setIcon("media-seek-backward"_icon); 0343 0344 act = collection->addAction("showHide", this, SLOT(slotShowHide())); 0345 act->setText(i18n("Show / Hide")); 0346 0347 ////////////////////////////////////////////////// 0348 // settings menu 0349 ////////////////////////////////////////////////// 0350 0351 m_toggleSystemTrayAction = collection->add<KToggleAction>("toggleSystemTray"); 0352 m_toggleSystemTrayAction->setText(i18n("&Dock in System Tray")); 0353 connect(m_toggleSystemTrayAction, SIGNAL(triggered(bool)), SLOT(slotToggleSystemTray(bool))); 0354 0355 m_toggleDockOnCloseAction = collection->add<KToggleAction>("dockOnClose"); 0356 m_toggleDockOnCloseAction->setText(i18n("&Stay in System Tray on Close")); 0357 0358 m_togglePopupsAction = collection->add<KToggleAction>("togglePopups"); 0359 m_togglePopupsAction->setText(i18n("Popup &Track Announcement")); 0360 0361 act = collection->add<KToggleAction>("saveUpcomingTracks"); 0362 act->setText(i18n("Save &Play Queue on Exit")); 0363 0364 act = collection->addAction("tagGuesserConfig", this, SLOT(slotConfigureTagGuesser())); 0365 act->setText(i18n("&Tag Guesser...")); 0366 0367 act = collection->addAction("fileRenamerConfig", this, SLOT(slotConfigureFileRenamer())); 0368 act->setText(i18n("&File Renamer...")); 0369 0370 act = collection->addAction("scrobblerConfig", this, SLOT(slotConfigureScrobbling())); 0371 act->setText(i18n("&Configure scrobbling...")); 0372 0373 ////////////////////////////////////////////////// 0374 // just in the toolbar 0375 ////////////////////////////////////////////////// 0376 0377 collection->addAction("trackPositionAction", 0378 new TrackPositionAction(i18n("Track Position"), this)); 0379 collection->addAction("volumeAction", 0380 new VolumeAction(i18n("Volume"), this)); 0381 0382 ActionCollection::actions()->addAssociatedWidget(this); 0383 foreach (QAction* action, ActionCollection::actions()->actions()) 0384 action->setShortcutContext(Qt::WidgetWithChildrenShortcut); 0385 } 0386 0387 void JuK::slotSetupSystemTray() 0388 { 0389 if(m_toggleSystemTrayAction && m_toggleSystemTrayAction->isChecked()) { 0390 m_systemTray = new SystemTray(m_player, this); 0391 m_systemTray->setObjectName(QStringLiteral("systemTray")); 0392 0393 m_toggleDockOnCloseAction->setEnabled(true); 0394 m_togglePopupsAction->setEnabled(true); 0395 0396 // since we need the information if the main window is visible 0397 // when quit was selected, we need to reroute the signal to our slot 0398 QAction *quitAction = m_systemTray->action(QStringLiteral("quit")); 0399 if (quitAction) { 0400 quitAction->disconnect(); 0401 connect(quitAction, &QAction::triggered, this, &JuK::slotQuit); 0402 } 0403 0404 // If this flag gets set then JuK will quit if you click the cover on 0405 // the track announcement popup when JuK is only in the system tray 0406 // (the systray has no widget). 0407 0408 qGuiApp->setQuitOnLastWindowClosed(false); 0409 } 0410 else { 0411 m_systemTray = nullptr; 0412 m_toggleDockOnCloseAction->setEnabled(false); 0413 m_togglePopupsAction->setEnabled(false); 0414 } 0415 } 0416 0417 void JuK::setupGlobalAccels() 0418 { 0419 KeyDialog::setupActionShortcut("play"); 0420 KeyDialog::setupActionShortcut("playPause"); 0421 KeyDialog::setupActionShortcut("stop"); 0422 KeyDialog::setupActionShortcut("back"); 0423 KeyDialog::setupActionShortcut("forward"); 0424 KeyDialog::setupActionShortcut("seekBack"); 0425 KeyDialog::setupActionShortcut("seekForward"); 0426 KeyDialog::setupActionShortcut("volumeUp"); 0427 KeyDialog::setupActionShortcut("volumeDown"); 0428 KeyDialog::setupActionShortcut("mute"); 0429 KeyDialog::setupActionShortcut("showHide"); 0430 KeyDialog::setupActionShortcut("forwardAlbum"); 0431 } 0432 0433 void JuK::slotProcessArgs() 0434 { 0435 CollectionList::instance()->addFiles(m_filesToOpen); 0436 } 0437 0438 void JuK::slotClearOldCovers() 0439 { 0440 // Find all saved covers from the previous run of JuK and clear them out, in case 0441 // we find our tracks in a different order this run, which would cause old saved 0442 // covers to be wrong. 0443 // See mpris2/mediaplayer2player.cpp 0444 QString tmpDir = QStandardPaths::writableLocation(QStandardPaths::TempLocation); 0445 QStringList nameFilters; 0446 0447 nameFilters << QStringLiteral("juk-cover-*.png"); 0448 QDirIterator jukCoverIter(tmpDir, nameFilters); 0449 while (jukCoverIter.hasNext()) { 0450 QFile::remove(jukCoverIter.next()); 0451 } 0452 } 0453 0454 void JuK::keyPressEvent(QKeyEvent *e) 0455 { 0456 if (e->key() >= Qt::Key_Back && e->key() <= Qt::Key_MediaLast) 0457 e->accept(); 0458 KXmlGuiWindow::keyPressEvent(e); 0459 } 0460 0461 void JuK::readConfig() 0462 { 0463 // player settings 0464 0465 KConfigGroup playerConfig(KSharedConfig::openConfig(), "Player"); 0466 0467 if(m_player) 0468 { 0469 const int maxVolume = 100; 0470 const int volume = playerConfig.readEntry("Volume", maxVolume); 0471 m_player->setVolume(volume * 0.01); 0472 0473 //bool enableCrossfade = playerConfig.readEntry("CrossfadeTracks", true); 0474 //m_player->setCrossfadeEnabled(enableCrossfade); 0475 //ActionCollection::action<QAction>("crossfadeTracks")->setChecked(enableCrossfade); 0476 } 0477 0478 // Default to no random play 0479 0480 ActionCollection::action<KToggleAction>("disableRandomPlay")->setChecked(true); 0481 0482 QString randomPlayMode = playerConfig.readEntry("RandomPlay", "Disabled"); 0483 if(randomPlayMode == "true" || randomPlayMode == "Normal") 0484 m_randomPlayAction->setChecked(true); 0485 else if(randomPlayMode == "AlbumRandomPlay") 0486 ActionCollection::action<QAction>("albumRandomPlay")->setChecked(true); 0487 0488 bool loopPlaylist = playerConfig.readEntry("LoopPlaylist", false); 0489 ActionCollection::action<QAction>("loopPlaylist")->setChecked(loopPlaylist); 0490 0491 // general settings 0492 0493 KConfigGroup settingsConfig(KSharedConfig::openConfig(), "Settings"); 0494 0495 bool dockInSystemTray = settingsConfig.readEntry("DockInSystemTray", true); 0496 m_toggleSystemTrayAction->setChecked(dockInSystemTray); 0497 0498 bool dockOnClose = settingsConfig.readEntry("DockOnClose", true); 0499 m_toggleDockOnCloseAction->setChecked(dockOnClose); 0500 0501 bool showPopups = settingsConfig.readEntry("TrackPopup", false); 0502 m_togglePopupsAction->setChecked(showPopups); 0503 } 0504 0505 void JuK::saveConfig() 0506 { 0507 // player settings 0508 0509 KConfigGroup playerConfig(KSharedConfig::openConfig(), "Player"); 0510 0511 if (m_player) 0512 { 0513 playerConfig.writeEntry("Volume", static_cast<int>(100.0 * m_player->volume())); 0514 } 0515 0516 playerConfig.writeEntry("RandomPlay", m_randomPlayAction->isChecked()); 0517 0518 QAction *a = ActionCollection::action<QAction>("loopPlaylist"); 0519 playerConfig.writeEntry("LoopPlaylist", a->isChecked()); 0520 0521 playerConfig.writeEntry("CrossfadeTracks", false); // TODO bring back 0522 0523 a = ActionCollection::action<QAction>("albumRandomPlay"); 0524 if(a->isChecked()) 0525 playerConfig.writeEntry("RandomPlay", "AlbumRandomPlay"); 0526 else if(m_randomPlayAction->isChecked()) 0527 playerConfig.writeEntry("RandomPlay", "Normal"); 0528 else 0529 playerConfig.writeEntry("RandomPlay", "Disabled"); 0530 0531 // general settings 0532 0533 KConfigGroup settingsConfig(KSharedConfig::openConfig(), "Settings"); 0534 settingsConfig.writeEntry("StartDocked", !isVisible() && m_toggleDockOnCloseAction->isChecked()); 0535 settingsConfig.writeEntry("DockInSystemTray", m_toggleSystemTrayAction->isChecked()); 0536 settingsConfig.writeEntry("DockOnClose", m_toggleDockOnCloseAction->isChecked()); 0537 settingsConfig.writeEntry("TrackPopup", m_togglePopupsAction->isChecked()); 0538 0539 KSharedConfig::openConfig()->sync(); 0540 } 0541 0542 bool JuK::queryClose() 0543 { 0544 if(!m_shuttingDown && 0545 !qApp->isSavingSession() && 0546 m_systemTray && 0547 m_toggleDockOnCloseAction->isChecked()) 0548 { 0549 KMessageBox::information(this, 0550 i18n("<qt>Closing the main window will keep JuK running in the system tray. " 0551 "Use Quit from the File menu to quit the application.</qt>"), 0552 i18n("Docking in System Tray"), "hideOnCloseInfo"); 0553 hide(); 0554 return false; 0555 } 0556 0557 return true; 0558 } 0559 0560 //////////////////////////////////////////////////////////////////////////////// 0561 // private slot definitions 0562 //////////////////////////////////////////////////////////////////////////////// 0563 0564 void JuK::slotShowHide() 0565 { 0566 setHidden(!isHidden()); 0567 } 0568 0569 void JuK::slotQuit() 0570 { 0571 m_shuttingDown = true; 0572 0573 // Some phonon backends will crash on shutdown unless we've stopped 0574 // playback. 0575 if(m_player->playing()) { 0576 m_player->stop(); 0577 } 0578 0579 saveConfig(); 0580 0581 // this will start chain of events causing PlaylistCollection (in 0582 // guise of PlaylistBox) and CollectionList (as first Playlist child) 0583 // to save themselves and then quit the application when this widget 0584 // closes. 0585 delete m_statusLabel; 0586 m_statusLabel = nullptr; 0587 0588 delete m_splitter; 0589 m_splitter = nullptr; 0590 0591 close(); 0592 } 0593 0594 //////////////////////////////////////////////////////////////////////////////// 0595 // settings menu 0596 //////////////////////////////////////////////////////////////////////////////// 0597 0598 void JuK::slotToggleSystemTray(bool enabled) 0599 { 0600 if(enabled && !m_systemTray) 0601 slotSetupSystemTray(); 0602 else if(!enabled && m_systemTray) { 0603 delete m_systemTray; 0604 m_systemTray = nullptr; 0605 m_toggleDockOnCloseAction->setEnabled(false); 0606 m_togglePopupsAction->setEnabled(false); 0607 0608 qGuiApp->setQuitOnLastWindowClosed(true); 0609 } 0610 } 0611 0612 void JuK::slotEditKeys() 0613 { 0614 KeyDialog(ActionCollection::actions(), this).configure(); 0615 } 0616 0617 void JuK::slotConfigureTagGuesser() 0618 { 0619 TagGuesserConfigDlg(this).exec(); 0620 } 0621 0622 void JuK::slotConfigureFileRenamer() 0623 { 0624 FileRenamerConfigDlg(this).exec(); 0625 } 0626 0627 void JuK::slotConfigureScrobbling() 0628 { 0629 ScrobbleConfigDlg(this).exec(); 0630 activateScrobblerIfEnabled(); 0631 } 0632 0633 void JuK::activateScrobblerIfEnabled() 0634 { 0635 bool isScrobbling = Scrobbler::isScrobblingEnabled(); 0636 0637 if (!m_scrobbler && isScrobbling) { 0638 m_scrobbler = new Scrobbler(this); 0639 connect (m_player, SIGNAL(signalItemChanged(FileHandle)), 0640 m_scrobbler, SLOT(nowPlaying(FileHandle))); 0641 } 0642 else if (m_scrobbler && !isScrobbling) { 0643 delete m_scrobbler; 0644 m_scrobbler = 0; 0645 } 0646 } 0647 0648 void JuK::slotUndo() 0649 { 0650 TagTransactionManager::instance()->undo(); 0651 } 0652 0653 void JuK::slotCheckAlbumNextAction(bool albumRandomEnabled) 0654 { 0655 action("forwardAlbum")->setEnabled(m_player->playing() && albumRandomEnabled); 0656 } 0657 0658 // vim: set et sw=4 tw=0 sta: