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