/* * Copyright (c) 2008 Sander Knopper (sander AT knopper DOT tk) and * Roeland Douma (roeland AT rullzer DOT com) * * This file is part of QtMPC. * * QtMPC 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. * * QtMPC is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with QtMPC. If not, see . */ #include #include #include #include #include #include #include #ifdef ENABLE_KDE_SUPPORT #include #include #include #include #include #include #include #include #include #include #include #endif #include "lyrics.h" #include "covers.h" #include "mainwindow.h" #include "musiclibraryitemsong.h" #include "preferencesdialog.h" #include "lib/mpdconnection.h" #include "lib/mpdstats.h" #include "lib/mpdstatus.h" #include "lib/mpdparseutils.h" #include "settings.h" #include "updatedialog.h" #include "config.h" #include "musiclibraryitemalbum.h" #include "folderpage.h" #include "librarypage.h" #include "lyricspage.h" #include "playlistspage.h" #include "fancytabwidget.h" VolumeSliderEventHandler::VolumeSliderEventHandler(MainWindow *w) : QObject(w), window(w) { } bool VolumeSliderEventHandler::eventFilter(QObject *obj, QEvent *event) { if (event->type() == QEvent::Wheel) { int numDegrees = static_cast(event)->delta() / 8; int numSteps = numDegrees / 15; if (numSteps > 0) { for (int i = 0; i < numSteps; ++i) window->action_Increase_volume->trigger(); } else { for (int i = 0; i > numSteps; --i) window->action_Decrease_volume->trigger(); } return true; } return QObject::eventFilter(obj, event); } VolumeControl::VolumeControl(QWidget *parent) : QMenu(parent) { QFrame *w = new QFrame(this); slider = new QSlider(w); QLabel *increase = new QLabel(QLatin1String("+"), w); QLabel *decrease = new QLabel(QLatin1String("-"), w); increase->setAlignment(Qt::AlignHCenter); decrease->setAlignment(Qt::AlignHCenter); QVBoxLayout *l = new QVBoxLayout(w); l->setMargin(3); l->setSpacing(0); l->addWidget(increase); l->addWidget(slider); l->addWidget(decrease); QHBoxLayout *layout = new QHBoxLayout(this); layout->setMargin(0); layout->addWidget(w); connect(slider, SIGNAL(valueChanged(int)), SIGNAL(valueChanged(int))); slider->setMinimumHeight(192); slider->setMaximumHeight(192); slider->setOrientation(Qt::Vertical); slider->setMinimum(0); slider->setMaximum(100); slider->setPageStep(5); adjustSize(); } VolumeControl::~VolumeControl() { } void VolumeControl::installSliderEventFilter(QObject *filter) { slider->installEventFilter(filter); } void VolumeControl::increaseVolume() { slider->triggerAction(QAbstractSlider::SliderPageStepAdd); } void VolumeControl::decreaseVolume() { slider->triggerAction(QAbstractSlider::SliderPageStepSub); } void VolumeControl::setValue(int v) { slider->setValue(v); } CoverEventHandler::CoverEventHandler(MainWindow *w) : QObject(w), window(w) { } bool CoverEventHandler::eventFilter(QObject *obj, QEvent *event) { switch(event->type()) { case QEvent::MouseButtonPress: if (Qt::LeftButton==static_cast(event)->button()) { pressed=true; } break; case QEvent::MouseButtonRelease: if (pressed && Qt::LeftButton==static_cast(event)->button()) { window->action_Show_playlist->trigger(); } pressed=false; break; default: break; } return QObject::eventFilter(obj, event); } #ifdef ENABLE_KDE_SUPPORT MainWindow::MainWindow(QWidget *parent) : KXmlGuiWindow(parent), #else MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), #endif lastState(MPDStatus::State_Inactive), lastSongId(-1), fetchStatsFactor(0), nowPlayingFactor(0), draggingPositionSlider(false) { loaded=0; updateDialog = 0; trayIcon = 0; lyricsNeedUpdating=false; #ifdef ENABLE_KDE_SUPPORT QWidget *widget = new QWidget(this); setupUi(widget); setCentralWidget(widget); #else setupUi(this); #endif libraryPage = new LibraryPage(this); folderPage = new FolderPage(this); playlistsPage = new PlaylistsPage(this); lyricsPage = new LyricsPage(this); #ifdef ENABLE_KDE_SUPPORT tabWidget->AddTab(libraryPage, QIcon::fromTheme("media-optical-audio"), i18n("Library")); tabWidget->AddTab(folderPage, QIcon::fromTheme("inode-directory"), i18n("Folders")); tabWidget->AddTab(playlistsPage, QIcon::fromTheme("view-media-playlist"), i18n("Playlists")); tabWidget->AddTab(lyricsPage, QIcon::fromTheme("view-media-lyrics"), i18n("Lyrics")); #else tabWidget->AddTab(libraryPage, QIcon::fromTheme("media-optical-audio"), tr("Library")); tabWidget->AddTab(folderPage, QIcon::fromTheme("inode-directory"), tr("Folders")); tabWidget->AddTab(playlistsPage, QIcon::fromTheme("view-media-playlist"), tr("Playlists")); tabWidget->AddTab(lyricsPage, QIcon::fromTheme("view-media-lyrics"), tr("Lyrics")); #endif tabWidget->SetMode(FancyTabWidget::Mode_LargeSidebar); connect(tabWidget, SIGNAL(CurrentChanged(int)), this, SLOT(currentTabChanged(int))); #ifdef ENABLE_KDE_SUPPORT KStandardAction::quit(kapp, SLOT(quit()), actionCollection()); KStandardAction::preferences(this, SLOT(showPreferencesDialog()), actionCollection()); KAction *action_Update_database = actionCollection()->addAction("updatedatabase"); action_Update_database->setText(i18n("Update Database")); action_Prev_track = actionCollection()->addAction("prevtrack"); action_Prev_track->setText(i18n("Previous Track")); action_Prev_track->setGlobalShortcut(KShortcut(Qt::META + Qt::Key_Left)); action_Next_track = actionCollection()->addAction("nexttrack"); action_Next_track->setText(i18n("Next Track")); action_Next_track->setGlobalShortcut(KShortcut(Qt::META + Qt::Key_Right)); action_Play_pause_track = actionCollection()->addAction("playpausetrack"); action_Play_pause_track->setText(i18n("Play/Pause")); action_Play_pause_track->setGlobalShortcut(KShortcut(Qt::META + Qt::Key_C)); action_Stop_track = actionCollection()->addAction("stoptrack"); action_Stop_track->setText(i18n("Stop")); action_Stop_track->setGlobalShortcut(KShortcut(Qt::META + Qt::Key_X)); action_Increase_volume = actionCollection()->addAction("increasevolume"); action_Increase_volume->setText(i18n("Increase Volume")); action_Increase_volume->setGlobalShortcut(KShortcut(Qt::META + Qt::Key_Up)); action_Decrease_volume = actionCollection()->addAction("decreasevolume"); action_Decrease_volume->setText(i18n("Decrease Volume")); action_Decrease_volume->setGlobalShortcut(KShortcut(Qt::META + Qt::Key_Down)); action_Add_to_playlist = actionCollection()->addAction("addtoplaylist"); action_Add_to_playlist->setText(i18n("Add To Playlist")); action_Replace_playlist = actionCollection()->addAction("replaceplaylist"); action_Replace_playlist->setText(i18n("Replace Playlist")); action_Load_playlist = actionCollection()->addAction("loadplaylist"); action_Load_playlist->setText(i18n("Load")); action_Remove_playlist = actionCollection()->addAction("removeplaylist"); action_Remove_playlist->setText(i18n("Remove")); action_Remove_from_playlist = actionCollection()->addAction("removefromplaylist"); action_Remove_from_playlist->setText(i18n("Remove")); action_Remove_from_playlist->setShortcut(QKeySequence::Delete); action_Copy_song_info = actionCollection()->addAction("copysonginfo"); action_Copy_song_info->setText(i18n("Copy Song Info")); action_Crop_playlist = actionCollection()->addAction("cropplaylist"); action_Crop_playlist->setText(i18n("Crop")); action_Shuffle_playlist = actionCollection()->addAction("shuffleplaylist"); action_Shuffle_playlist->setText(i18n("Shuffle")); action_Rename_playlist = actionCollection()->addAction("renameplaylist"); action_Rename_playlist->setText(i18n("Rename")); action_Save_playlist = actionCollection()->addAction("saveplaylist"); action_Save_playlist->setText(i18n("Save As")); action_Clear_playlist = actionCollection()->addAction("clearplaylist"); action_Clear_playlist->setText(i18n("Clear")); action_Show_playlist = actionCollection()->addAction("showplaylist"); action_Show_playlist->setText(i18n("Show Playlist")); action_Random_playlist = actionCollection()->addAction("randomplaylist"); action_Random_playlist->setText(i18n("Random")); action_Repeat_playlist = actionCollection()->addAction("repeatplaylist"); action_Repeat_playlist->setText(i18n("Repeat")); action_Consume_playlist = actionCollection()->addAction("consumeplaylist"); action_Consume_playlist->setText(i18n("Consume")); #else action_Prev_track = new QAction(tr("Previous Track"), this); action_Next_track = new QAction(tr("Next Track"), this); action_Play_pause_track = new QAction(tr("Play/Pause"), this); action_Stop_track = new QAction(tr("Stop"), this); action_Increase_volume = new QAction(tr("Increase Volume"), this); action_Decrease_volume = new QAction(tr("Decrease Volume"), this); action_Add_to_playlist = new QAction(tr("Add To Playlist"), this); action_Replace_playlist = new QAction(tr("Replace Playlist"), this); action_Load_playlist = new QAction(tr("Load"), this); action_Remove_playlist = new QAction(tr("Remove"), this); action_Remove_from_playlist = new QAction(tr("Remove"), this); action_Remove_from_playlist->setShortcut(QKeySequence::Delete); action_Copy_song_info = new QAction(tr("Copy Song Info"), this); action_Copy_song_info->setShortcuts(QKeySequence::Copy); action_Crop_playlist = new QAction(tr("Crop"), this); action_Shuffle_playlist = new QAction(tr("Shuffle"), this); action_Rename_playlist = new QAction(tr("Rename"), this); action_Save_playlist = new QAction(tr("Save As"), this); action_Clear_playlist = new QAction(tr("Clear"), this); action_Show_playlist = new QAction(tr("Show Playlist"), this); action_Random_playlist = new QAction(tr("Random"), this); action_Repeat_playlist = new QAction(tr("Repeat"), this); action_Consume_playlist = new QAction(tr("Consume"), this); #endif setVisible(true); // Setup event handler for volume adjustment volumeSliderEventHandler = new VolumeSliderEventHandler(this); coverEventHandler = new CoverEventHandler(this); volumeControl = new VolumeControl(volumeButton); volumeControl->installSliderEventFilter(volumeSliderEventHandler); volumeButton->installEventFilter(volumeSliderEventHandler); // KDE does this for us //#ifndef ENABLE_KDE_SUPPORT // setWindowIcon(QIcon(":/icons/icon.svg")); //#endif noCover = QIcon::fromTheme("media-optical-audio").pixmap(128, 128).scaled(coverWidget->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); coverWidget->setPixmap(noCover); playbackPlay = QIcon::fromTheme("media-playback-start"); playbackPause = QIcon::fromTheme("media-playback-pause"); // #ifdef ENABLE_KDE_SUPPORT // action_Random_playlist->setIcon(KIcon("media-random-tracks")); // action_Repeat_playlist->setIcon(KIcon("media-repeat-playlist")); // action_Consume_playlist->setIcon(KIcon("media-consume-playlist")); // action_Add_to_playlist->setIcon(KIcon("media-track-add")); // action_Replace_playlist->setIcon(KIcon("media-replace-playlist")); // #else // action_Random_playlist->setIcon(QIcon(":/icons/hi16-action-media-random-tracks.png")); // action_Repeat_playlist->setIcon(QIcon(":/icons/hi16-action-media-repeat-playlist.png")); // action_Consume_playlist->setIcon(QIcon(":/icons/hi16-action-media-consume-playlist.png")); // action_Add_to_playlist->setIcon(QIcon(":/icons/hi16-action-media-track-add.png")); // action_Replace_playlist->setIcon(QIcon(":/icons/hi16-action-media-replace-playlist.png")); // #endif action_Repeat_playlist->setIcon(QIcon::fromTheme("edit-redo")); action_Random_playlist->setIcon(QIcon::fromTheme("roll")); action_Consume_playlist->setIcon(QIcon::fromTheme("format-list-unordered")); action_Add_to_playlist->setIcon(QIcon::fromTheme(Qt::RightToLeft==QApplication::layoutDirection() ? "arrow-left" : "arrow-right")); action_Replace_playlist->setIcon(QIcon::fromTheme(Qt::RightToLeft==QApplication::layoutDirection() ? "arrow-left-double" : "arrow-right-double")); action_Prev_track->setIcon(QIcon::fromTheme("media-skip-backward")); action_Next_track->setIcon(QIcon::fromTheme("media-skip-forward")); action_Play_pause_track->setIcon(playbackPlay); action_Stop_track->setIcon(QIcon::fromTheme("media-playback-stop")); action_Load_playlist->setIcon(QIcon::fromTheme("document-open")); action_Remove_playlist->setIcon(QIcon::fromTheme("edit-delete")); action_Remove_from_playlist->setIcon(QIcon::fromTheme("list-remove")); action_Clear_playlist->setIcon(QIcon::fromTheme("edit-clear-list")); action_Save_playlist->setIcon(QIcon::fromTheme("document-save-as")); action_Clear_playlist->setIcon(QIcon::fromTheme("edit-clear-list")); action_Show_playlist->setIcon(QIcon::fromTheme("view-media-playlist")); action_Update_database->setIcon(QIcon::fromTheme("view-refresh")); volumeButton->setIcon(QIcon::fromTheme("player-volume")); connect(Lyrics::self(), SIGNAL(lyrics(const QString &, const QString &, const QString &)), SLOT(lyrics(const QString &, const QString &, const QString &))); connect(Covers::self(), SIGNAL(cover(const QString &, const QString &, const QImage &)), SLOT(cover(const QString &, const QString &, const QImage &))); connect(Covers::self(), SIGNAL(cover(const QString &, const QString &, const QImage &)), &musicLibraryModel, SLOT(setCover(const QString &, const QString &, const QImage &))); playPauseTrackButton->setDefaultAction(action_Play_pause_track); stopTrackButton->setDefaultAction(action_Stop_track); nextTrackButton->setDefaultAction(action_Next_track); prevTrackButton->setDefaultAction(action_Prev_track); libraryPage->addToPlaylist->setDefaultAction(action_Add_to_playlist); libraryPage->replacePlaylist->setDefaultAction(action_Replace_playlist); folderPage->addToPlaylist->setDefaultAction(action_Add_to_playlist); folderPage->replacePlaylist->setDefaultAction(action_Replace_playlist); savePlaylistPushButton->setDefaultAction(action_Save_playlist); removeAllFromPlaylistPushButton->setDefaultAction(action_Clear_playlist); removeFromPlaylistPushButton->setDefaultAction(action_Remove_from_playlist); playlistsPage->addToPlaylist->setDefaultAction(action_Add_to_playlist); playlistsPage->replacePlaylist->setDefaultAction(action_Load_playlist); playlistsPage->removePlaylist->setDefaultAction(action_Remove_playlist); randomPushButton->setDefaultAction(action_Random_playlist); repeatPushButton->setDefaultAction(action_Repeat_playlist); consumePushButton->setDefaultAction(action_Consume_playlist); libraryPage->libraryUpdate->setDefaultAction(action_Update_database); folderPage->libraryUpdate->setDefaultAction(action_Update_database); playlistsPage->libraryUpdate->setDefaultAction(action_Update_database); action_Show_playlist->setCheckable(true); action_Random_playlist->setCheckable(true); action_Repeat_playlist->setCheckable(true); action_Consume_playlist->setCheckable(true); libraryPage->addToPlaylist->setEnabled(false); libraryPage->replacePlaylist->setEnabled(false); folderPage->addToPlaylist->setEnabled(false); folderPage->replacePlaylist->setEnabled(false); playlistsPage->addToPlaylist->setEnabled(false); playlistsPage->replacePlaylist->setEnabled(false); playlistsPage->removePlaylist->setEnabled(false); #ifdef ENABLE_KDE_SUPPORT libraryPage->search->setPlaceholderText(i18n("Search library...")); folderPage->search->setPlaceholderText(i18n("Search files...")); searchPlaylistLineEdit->setPlaceholderText(i18n("Search playlist...")); #else libraryPage->search->setPlaceholderText(tr("Search library...")); folderPage->search->setPlaceholderText(tr("Search files...")); searchPlaylistLineEdit->setPlaceholderText(tr("Search playlist...")); #endif QList btns; btns << prevTrackButton << stopTrackButton << playPauseTrackButton << nextTrackButton << libraryPage->addToPlaylist << libraryPage->replacePlaylist << folderPage->addToPlaylist << folderPage->replacePlaylist << playlistsPage->addToPlaylist << playlistsPage->replacePlaylist << playlistsPage->removePlaylist << repeatPushButton << randomPushButton << savePlaylistPushButton << removeAllFromPlaylistPushButton << removeFromPlaylistPushButton << consumePushButton << libraryPage->libraryUpdate << folderPage->libraryUpdate << playlistsPage->libraryUpdate << volumeButton; foreach(QToolButton * b, btns) { b->setAutoRaise(true); } #ifdef ENABLE_KDE_SUPPORT trackLabel->setText(i18n("Stopped")); #else trackLabel->setText(tr("Stopped")); #endif artistLabel->setText("..."); playlistsProxyModel.setSourceModel(&playlistsModel); playlistsPage->view->setModel(&playlistsProxyModel); playlistsPage->view->sortByColumn(0, Qt::AscendingOrder); playlistsPage->view->addAction(action_Add_to_playlist); playlistsPage->view->addAction(action_Load_playlist); playlistsPage->view->addAction(action_Remove_playlist); playlistsPage->view->addAction(action_Rename_playlist); libraryPage->view->setHeaderHidden(true); folderPage->view->setHeaderHidden(true); playlistsPage->view->setHeaderHidden(true); action_Show_playlist->setChecked(Settings::self()->showPlaylist()); action_Random_playlist->setChecked(Settings::self()->randomPlaylist()); action_Repeat_playlist->setChecked(Settings::self()->repeatPlaylist()); action_Consume_playlist->setChecked(Settings::self()->consumePlaylist()); mpdDir=Settings::self()->mpdDir(); Lyrics::self()->setMpdDir(mpdDir); Covers::self()->setMpdDir(mpdDir); MusicLibraryItemAlbum::setCoverSize((MusicLibraryItemAlbum::CoverSize)Settings::self()->coverSize()); tabWidget->SetMode((FancyTabWidget::Mode)Settings::self()->sidebar()); if (setupTrayIcon() && Settings::self()->useSystemTray()) trayIcon->show(); // Start connection threads MPDConnection::self()->start(); // Set connection data MPDConnection::self()->setDetails(Settings::self()->connectionHost(), Settings::self()->connectionPort(), Settings::self()->connectionPasswd()); while (!MPDConnection::self()->connectToMPD()) { if (!showPreferencesDialog()) exit(EXIT_FAILURE); MPDConnection::self()->setDetails(Settings::self()->connectionHost(), Settings::self()->connectionPort(), Settings::self()->connectionPasswd()); qWarning("Retrying"); } togglePlaylist(); setRandom(); setRepeat(); setConsume(); #ifdef ENABLE_KDE_SUPPORT setupGUI(KXmlGuiWindow::Keys | KXmlGuiWindow::Save | KXmlGuiWindow::Create); #else QSize sz=Settings::self()->mainWindowSize(); if (!sz.isEmpty()) { resize(sz); } #endif coverWidget->installEventFilter(coverEventHandler); libraryProxyModel.setSourceModel(&musicLibraryModel); libraryPage->view->setModel(&libraryProxyModel); libraryPage->view->addAction(action_Add_to_playlist); libraryPage->view->addAction(action_Replace_playlist); dirProxyModel.setSourceModel(&dirviewModel); folderPage->view->setModel(&dirProxyModel); folderPage->view->addAction(action_Add_to_playlist); folderPage->view->addAction(action_Replace_playlist); connect(&playlistsModel, SIGNAL(playlistLoaded()), this, SLOT(startPlayingSong())); connect(&playlistModel, SIGNAL(filesAddedInPlaylist(const QStringList, const int, const int)), this, SLOT(addFilenamesToPlaylist(const QStringList, const int, const int))); connect(&playlistModel, SIGNAL(moveInPlaylist(const QList, const int, const int)), this, SLOT(movePlaylistItems(const QList, const int, const int))); connect(&playlistModel, SIGNAL(playListStatsUpdated()), this, SLOT(updatePlayListStatus())); playlistProxyModel.setSourceModel(&playlistModel); playlistTableView->setModel(&playlistProxyModel); playlistTableView->setAcceptDrops(true); playlistTableView->setDropIndicatorShown(true); playlistTableView->addAction(action_Remove_from_playlist); playlistTableView->addAction(action_Clear_playlist); playlistTableView->addAction(action_Crop_playlist); playlistTableView->addAction(action_Shuffle_playlist); playlistTableView->addAction(action_Copy_song_info); connect(playlistTableView, SIGNAL(itemsSelected(bool)), SLOT(playlistItemsSelected(bool))); setupPlaylistViewHeader(); setupPlaylistViewMenu(); connect(MPDConnection::self(), SIGNAL(statsUpdated()), this, SLOT(updateStats())); connect(MPDConnection::self(), SIGNAL(statusUpdated()), this, SLOT(updateStatus()), Qt::DirectConnection); connect(MPDConnection::self(), SIGNAL(playlistUpdated(const QList &)), this, SLOT(updatePlaylist(const QList &))); connect(MPDConnection::self(), SIGNAL(currentSongUpdated(const Song &)), this, SLOT(updateCurrentSong(const Song &))); connect(MPDConnection::self(), SIGNAL(mpdConnectionDied()), this, SLOT(mpdConnectionDied())); connect(MPDConnection::self(), SIGNAL(musicLibraryUpdated(MusicLibraryItemRoot *, QDateTime)), &musicLibraryModel, SLOT(updateMusicLibrary(MusicLibraryItemRoot *, QDateTime))); connect(MPDConnection::self(), SIGNAL(dirViewUpdated(DirViewItemRoot *)), &dirviewModel, SLOT(updateDirView(DirViewItemRoot *))); #ifndef ENABLE_KDE_SUPPORT connect(action_Quit, SIGNAL(triggered()), qApp, SLOT(quit())); connect(action_Preferences, SIGNAL(triggered(bool)), this, SLOT(showPreferencesDialog())); connect(action_About, SIGNAL(triggered(bool)), this, SLOT(showAboutDialog())); #endif connect(action_Update_database, SIGNAL(triggered(bool)), this, SLOT(updateDb())); connect(action_Prev_track, SIGNAL(triggered(bool)), this, SLOT(previousTrack())); connect(action_Next_track, SIGNAL(triggered(bool)), this, SLOT(nextTrack())); connect(action_Play_pause_track, SIGNAL(triggered(bool)), this, SLOT(playPauseTrack())); connect(action_Stop_track, SIGNAL(triggered(bool)), this, SLOT(stopTrack())); connect(volumeControl, SIGNAL(valueChanged(int)), SLOT(setVolume(int))); connect(action_Increase_volume, SIGNAL(triggered(bool)), this, SLOT(increaseVolume())); connect(action_Decrease_volume, SIGNAL(triggered(bool)), this, SLOT(decreaseVolume())); connect(action_Increase_volume, SIGNAL(triggered(bool)), volumeControl, SLOT(increaseVolume())); connect(action_Decrease_volume, SIGNAL(triggered(bool)), volumeControl, SLOT(decreaseVolume())); connect(positionSlider, SIGNAL(sliderPressed()), this, SLOT(positionSliderPressed())); connect(positionSlider, SIGNAL(sliderReleased()), this, SLOT(setPosition())); connect(positionSlider, SIGNAL(sliderReleased()), this, SLOT(positionSliderReleased())); connect(action_Random_playlist, SIGNAL(activated()), this, SLOT(setRandom())); connect(action_Repeat_playlist, SIGNAL(activated()), this, SLOT(setRepeat())); connect(action_Consume_playlist, SIGNAL(activated()), this, SLOT(setConsume())); connect(libraryPage->search, SIGNAL(returnPressed()), this, SLOT(searchMusicLibrary())); connect(libraryPage->search, SIGNAL(textChanged(const QString)), this, SLOT(searchMusicLibrary())); connect(libraryPage->genreCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(searchMusicLibrary())); connect(folderPage->search, SIGNAL(returnPressed()), this, SLOT(searchDirView())); connect(folderPage->search, SIGNAL(textChanged(const QString)), this, SLOT(searchDirView())); connect(searchPlaylistLineEdit, SIGNAL(returnPressed()), this, SLOT(searchPlaylist())); connect(searchPlaylistLineEdit, SIGNAL(textChanged(const QString)), this, SLOT(searchPlaylist())); connect(playlistTableView, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(playlistItemActivated(const QModelIndex &))); connect(libraryPage->view, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(libraryItemActivated(const QModelIndex &))); connect(folderPage->view, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(dirViewItemActivated(const QModelIndex &))); connect(action_Add_to_playlist, SIGNAL(activated()), this, SLOT(addToPlaylistItemActivated())); connect(action_Replace_playlist, SIGNAL(activated()), this, SLOT(replacePlaylist())); connect(action_Load_playlist, SIGNAL(activated()), this, SLOT(loadPlaylistPushButtonActivated())); connect(action_Remove_playlist, SIGNAL(activated()), this, SLOT(removePlaylistPushButtonActivated())); connect(action_Save_playlist, SIGNAL(activated()), this, SLOT(savePlaylistPushButtonActivated())); connect(action_Remove_from_playlist, SIGNAL(activated()), this, SLOT(removeFromPlaylist())); connect(action_Rename_playlist, SIGNAL(triggered()), this, SLOT(renamePlaylistActivated())); connect(action_Clear_playlist, SIGNAL(activated()), this, SLOT(clearPlaylist())); connect(action_Copy_song_info, SIGNAL(activated()), this, SLOT(copySongInfo())); connect(action_Crop_playlist, SIGNAL(activated()), this, SLOT(cropPlaylist())); connect(action_Shuffle_playlist, SIGNAL(activated()), MPDConnection::self(), SLOT(shuffle())); connect(action_Show_playlist, SIGNAL(activated()), this, SLOT(togglePlaylist())); connect(&elapsedTimer, SIGNAL(timeout()), this, SLOT(updatePositionSilder())); connect(&musicLibraryModel, SIGNAL(updateGenres(const QStringList &)), this, SLOT(updateGenres(const QStringList &))); connect(libraryPage->view, SIGNAL(itemsSelected(bool)), libraryPage->addToPlaylist, SLOT(setEnabled(bool))); connect(libraryPage->view, SIGNAL(itemsSelected(bool)), libraryPage->replacePlaylist, SLOT(setEnabled(bool))); connect(folderPage->view, SIGNAL(itemsSelected(bool)), folderPage->addToPlaylist, SLOT(setEnabled(bool))); connect(folderPage->view, SIGNAL(itemsSelected(bool)), folderPage->replacePlaylist, SLOT(setEnabled(bool))); connect(playlistsPage->view, SIGNAL(itemsSelected(bool)), playlistsPage->addToPlaylist, SLOT(setEnabled(bool))); connect(playlistsPage->view, SIGNAL(itemsSelected(bool)), playlistsPage->replacePlaylist, SLOT(setEnabled(bool))); connect(playlistsPage->view, SIGNAL(itemsSelected(bool)), playlistsPage->removePlaylist, SLOT(setEnabled(bool))); connect(volumeButton, SIGNAL(clicked()), SLOT(showVolumeControl())); connect(playlistsPage->addToPlaylist, SIGNAL(clicked(bool)), this, SLOT(addPlaylistToPlaylistPushButtonActivated())); connect(playlistsPage->view, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(playlistsViewItemDoubleClicked(const QModelIndex &))); connect(MPDConnection::self(), SIGNAL(storedPlayListUpdated()), this, SLOT(updateStoredPlaylists())); elapsedTimer.setInterval(1000); splitter->restoreState(Settings::self()->splitterState()); connect(MPDConnection::self(), SIGNAL(outputsUpdated(const QList &)), this, SLOT(updateOutpus(const QList &))); #ifdef ENABLE_KDE_SUPPORT QMenu *m = (QMenu *)factory()->container("output_menu", this); connect(m, SIGNAL(triggered(QAction *)), this, SLOT(outputChanged(QAction *))); #else connect(menu_Outputs, SIGNAL(triggered(QAction *)), this, SLOT(outputChanged(QAction *))); #endif MPDConnection::self()->outputs(); MPDConnection::self()->getStatus(); MPDConnection::self()->getStats(); MPDConnection::self()->playListInfo(); currentTabChanged(0); playlistItemsSelected(false); } MainWindow::~MainWindow() { #ifndef ENABLE_KDE_SUPPORT Settings::self()->saveMainWindowSize(size()); #endif Settings::self()->saveConsumePlaylist(action_Consume_playlist->isChecked()); Settings::self()->saveRandomPlaylist(action_Random_playlist->isChecked()); Settings::self()->saveRepeatPlaylist(action_Repeat_playlist->isChecked()); Settings::self()->saveShowPlaylist(action_Show_playlist->isChecked()); Settings::self()->saveSplitterState(splitter->saveState()); Settings::self()->savePlaylistHeaderState(playlistTableViewHeader->saveState()); Settings::self()->saveSidebar((int)(tabWidget->mode())); Settings::self()->save(); } void MainWindow::closeEvent(QCloseEvent *event) { if (trayIcon != NULL && trayIcon->isVisible()) { lastPos=pos(); hide(); } else qApp->quit(); event->ignore(); } void MainWindow::showVolumeControl() { // qWarning() << volumeControl->pos().x() << volumeControl->pos().y() // << volumeButton->pos().x() << volumeButton->pos().y() // << volumeButton->mapToGlobal(volumeButton->pos()).x() << volumeButton->mapToGlobal(volumeButton->pos()).y(); // volumeControl->move(); volumeControl->popup(volumeButton->mapToGlobal(QPoint((volumeButton->width()-volumeControl->width())/2, volumeButton->height()))); } void MainWindow::playlistItemsSelected(bool s) { if (playlistTableView->model()->rowCount()) { playlistTableView->setContextMenuPolicy(Qt::ActionsContextMenu); action_Remove_from_playlist->setEnabled(s); action_Copy_song_info->setEnabled(s); action_Clear_playlist->setEnabled(true); action_Crop_playlist->setEnabled(playlistTableView->haveUnSelectedItems()); action_Shuffle_playlist->setEnabled(true); } } void MainWindow::mpdConnectionDied() { // Stop timer(s) elapsedTimer.stop(); // Reset GUI positionSlider->setValue(0); songTimeElapsedLabel->setText("00:00 / 00:00"); action_Play_pause_track->setIcon(playbackPlay); action_Play_pause_track->setEnabled(true); action_Stop_track->setEnabled(false); // Show warning message #ifdef ENABLE_KDE_SUPPORT KMessageBox::error(this, i18n("The MPD connection died unexpectedly.\nThis error is unrecoverable, please restart %1.").arg(PACKAGE_NAME), i18n("Lost MPD Connection")); #else QMessageBox::critical(this, tr("MPD connection gone"), tr("The MPD connection died unexpectedly. This error is unrecoverable, please restart "PACKAGE_NAME".")); #endif } void MainWindow::updateDb() { MPDConnection::self()->update(); if (!updateDialog) { updateDialog = new UpdateDialog(this); connect(MPDConnection::self(), SIGNAL(databaseUpdated()), updateDialog, SLOT(complete())); } updateDialog->show(); } int MainWindow::showPreferencesDialog() { PreferencesDialog pref(this); if (MPDConnection::self()->isConnected()) { if (trayIcon != NULL) connect(&pref, SIGNAL(systemTraySet(bool)), this, SLOT(toggleTrayIcon(bool))); connect(&pref, SIGNAL(crossfadingChanged(const int)), this, SLOT(crossfadingChanged(const int))); } int rv=pref.exec(); if (rv) { mpdDir=Settings::self()->mpdDir(); if (!mpdDir.endsWith("/")) { mpdDir=mpdDir+"/"; } Lyrics::self()->setMpdDir(mpdDir); Covers::self()->setMpdDir(mpdDir); } return rv; } void MainWindow::toggleTrayIcon(bool enable) { if (enable) { if (!trayIcon) { setupTrayIcon(); } if (trayIcon) { trayIcon->show(); } } else if (trayIcon) { trayIcon->hide(); } } #ifndef ENABLE_KDE_SUPPORT void MainWindow::showAboutDialog() { QMessageBox msgBox; msgBox.setIcon(QMessageBox::Information); msgBox.setWindowTitle(tr("About Cantata")); msgBox.setText(tr("Simple GUI front-end for MPD.
(c) Craig Drummond 2001.
Released under the GPLv2
Based upon QtMPC - (C) 2007-2010 The QtMPC Authors")); msgBox.setStandardButtons(QMessageBox::Ok); msgBox.exec(); } #endif void MainWindow::positionSliderPressed() { draggingPositionSlider = true; } void MainWindow::positionSliderReleased() { draggingPositionSlider = false; } void MainWindow::startPlayingSong() { MPDConnection::self()->startPlayingSong(); } void MainWindow::nextTrack() { MPDConnection::self()->goToNext(); } void MainWindow::stopTrack() { MPDConnection::self()->stopPlaying(); action_Stop_track->setEnabled(false); } void MainWindow::playPauseTrack() { MPDStatus * const status = MPDStatus::self(); if (status->state() == MPDStatus::State_Playing) MPDConnection::self()->setPause(true); else if (status->state() == MPDStatus::State_Paused) MPDConnection::self()->setPause(false); else MPDConnection::self()->startPlayingSong(); } void MainWindow::previousTrack() { MPDConnection::self()->goToPrevious(); } void MainWindow::setPosition() { MPDConnection::self()->setSeekId(MPDStatus::self()->songId(), positionSlider->value()); } void MainWindow::setVolume(int vol) { MPDConnection::self()->setVolume(vol); } void MainWindow::increaseVolume() { volumeControl->sliderWidget()->triggerAction(QAbstractSlider::SliderPageStepAdd); } void MainWindow::decreaseVolume() { volumeControl->sliderWidget()->triggerAction(QAbstractSlider::SliderPageStepSub); } void MainWindow::setRandom() { MPDConnection::self()->setRandom(action_Random_playlist->isChecked()); } void MainWindow::setRepeat() { MPDConnection::self()->setRepeat(action_Repeat_playlist->isChecked()); } void MainWindow::setConsume() { MPDConnection::self()->setConsume(action_Consume_playlist->isChecked()); } void MainWindow::searchMusicLibrary() { libraryProxyModel.setFilterGenre(0==libraryPage->genreCombo->currentIndex() ? QString() : libraryPage->genreCombo->currentText()); if (libraryPage->search->text().isEmpty()) { libraryProxyModel.setFilterRegExp(QString()); return; } libraryProxyModel.setFilterRegExp(libraryPage->search->text()); } void MainWindow::searchDirView() { if (folderPage->search->text().isEmpty()) { dirProxyModel.setFilterRegExp(""); return; } dirProxyModel.setFilterRegExp(folderPage->search->text()); } void MainWindow::searchPlaylist() { if (searchPlaylistLineEdit->text().isEmpty()) { playlistProxyModel.setFilterRegExp(""); return; } playlistProxyModel.setFilterRegExp(searchPlaylistLineEdit->text()); } void MainWindow::updatePlaylist(const QList &songs) { QList selectedSongIds; qint32 firstSelectedSongId = -1; qint32 firstSelectedRow = -1; // remember selected song ids and rownum of smallest selected row in proxymodel (because that represents the visible rows) if (playlistTableView->selectionModel()->hasSelection()) { QModelIndexList items = playlistTableView->selectionModel()->selectedRows(); QModelIndex index; QModelIndex sourceIndex; // find smallest selected rownum for (int i = 0; i < items.size(); i++) { index = items.at(i); sourceIndex = playlistProxyModel.mapToSource(index); selectedSongIds.append(playlistModel.getIdByRow(sourceIndex.row())); if (firstSelectedRow == -1 || index.row() < firstSelectedRow) { firstSelectedRow = index.row(); firstSelectedSongId = playlistModel.getIdByRow(sourceIndex.row()); } } } // refresh playlist playlistModel.updatePlaylist(songs); // reselect song ids or minrow if songids were not found (songs removed) bool found = false; if (selectedSongIds.size() > 0) { qint32 newCurrentRow = playlistModel.getRowById(firstSelectedSongId); QModelIndex newCurrentSourceIndex = playlistModel.index(newCurrentRow, 0); QModelIndex newCurrentIndex = playlistProxyModel.mapFromSource(newCurrentSourceIndex); playlistTableView->setCurrentIndex(newCurrentIndex); qint32 row; QModelIndex sourceIndex; QModelIndex index; for (int i = 0; i < selectedSongIds.size(); i++) { row = playlistModel.getRowById(selectedSongIds.at(i)); if (row >= 0) { found = true; } sourceIndex = playlistModel.index(row, 0); index = playlistProxyModel.mapFromSource(sourceIndex); playlistTableView->selectionModel()->select(index, QItemSelectionModel::Select | QItemSelectionModel::Rows); } if (!found) { // songids which were selected before the playlistupdate were not found anymore (they were removed) -> select firstSelectedRow again (should be the next song after the removed one) // firstSelectedRow contains the selected row of the proxymodel before we did the playlist refresh // check if rowcount of current proxymodel is smaller than that (last row as removed) and adjust firstSelectedRow when needed index = playlistProxyModel.index(firstSelectedRow, 0); if (firstSelectedRow > playlistProxyModel.rowCount(index) - 1) { firstSelectedRow = playlistProxyModel.rowCount(index) - 1; } index = playlistProxyModel.index(firstSelectedRow, 0); playlistTableView->setCurrentIndex(index); playlistTableView->selectionModel()->select(index, QItemSelectionModel::Select | QItemSelectionModel::Rows); } } } void MainWindow::updateCurrentSong(const Song &song) { current=song; // Determine if album cover should be updated const QString &albumArtist=song.albumArtist(); if (coverWidget->property("artist").toString() != albumArtist || coverWidget->property("album").toString() != song.album) { Covers::self()->get(song); coverWidget->setProperty("artist", albumArtist); coverWidget->setProperty("album", song.album); } if (song.title.isEmpty() && albumArtist.isEmpty()) { #ifdef ENABLE_KDE_SUPPORT trackLabel->setText(i18n("Stopped")); #else trackLabel->setText(tr("Stopped")); #endif artistLabel->setText("..."); } else { trackLabel->setText(song.title); artistLabel->setText(song.artist); } playlistModel.updateCurrentSong(song.id); if (3==tabWidget->current_index()) { Lyrics::self()->get(song); } else { lyricsNeedUpdating=true; } if (Settings::self()->showPopups()) { //(trayIcon && trayIcon->isVisible() && isHidden()) { if (!song.title.isEmpty() && !song.artist.isEmpty() && !song.album.isEmpty()) { #ifdef ENABLE_KDE_SUPPORT const QString text(i18n("" "" "" "" "" "" "
Artist:%1
Album:%2
Song:%3
Track:%4
Length:%5
").arg(song.artist).arg(song.album).arg(song.title) .arg(song.track).arg(Song::formattedTime(song.time))); KNotification *notification = new KNotification("CurrentTrackChanged", this); notification->setText(text); notification->sendEvent(); #else const QString text("album: " + song.album + "\n" + "track: " + QString::number(song.track) + "\n" + "length: " + Song::formattedTime(song.time)); trayIcon->showMessage(song.artist + " - " + song.title, text, QSystemTrayIcon::Information, 5000); #endif } } } void MainWindow::updateStats() { MPDStats * const stats = MPDStats::self(); /* * Check if remote db is more recent than local one * Also update the dirview */ if (lastDbUpdate.isValid() && stats->dbUpdate() > lastDbUpdate) { MPDConnection::self()->listAllInfo(stats->dbUpdate()); MPDConnection::self()->listAll(); } lastDbUpdate = stats->dbUpdate(); } void MainWindow::updateStatus() { MPDStatus * const status = MPDStatus::self(); QString timeElapsedFormattedString; if (!draggingPositionSlider) { if (status->state() == MPDStatus::State_Stopped || status->state() == MPDStatus::State_Inactive) { positionSlider->setValue(0); } else { positionSlider->setRange(0, status->timeTotal()); positionSlider->setValue(status->timeElapsed()); } } #ifdef ENABLE_KDE_SUPPORT volumeButton->setToolTip(i18n("Volume %1%").arg(status->volume())); volumeControl->setToolTip(i18n("Volume %1%").arg(status->volume())); #else volumeButton->setToolTip(tr("Volume %1%").arg(status->volume())); volumeControl->setToolTip(tr("Volume %1%").arg(status->volume())); #endif volumeControl->setValue(status->volume()); randomPushButton->setChecked(status->random()); repeatPushButton->setChecked(status->repeat()); consumePushButton->setChecked(status->consume()); if (status->state() == MPDStatus::State_Stopped || status->state() == MPDStatus::State_Inactive) { timeElapsedFormattedString = "00:00 / 00:00"; } else { timeElapsedFormattedString += Song::formattedTime(status->timeElapsed()); timeElapsedFormattedString += " / "; timeElapsedFormattedString += Song::formattedTime(status->timeTotal()); songTime = status->timeTotal(); } songTimeElapsedLabel->setText(timeElapsedFormattedString); switch (status->state()) { case MPDStatus::State_Playing: action_Play_pause_track->setIcon(playbackPause); action_Play_pause_track->setEnabled(true); //playPauseTrackButton->setChecked(false); action_Stop_track->setEnabled(true); elapsedTimer.start(); if (trayIcon != NULL) trayIcon->setIcon(playbackPlay); break; case MPDStatus::State_Inactive: case MPDStatus::State_Stopped: action_Play_pause_track->setIcon(playbackPlay); action_Play_pause_track->setEnabled(true); action_Stop_track->setEnabled(false); #ifdef ENABLE_KDE_SUPPORT trackLabel->setText(i18n("Stopped")); #else trackLabel->setText(tr("Stopped")); #endif artistLabel->setText("..."); if (trayIcon != NULL) trayIcon->setIcon(windowIcon()); elapsedTimer.stop(); break; case MPDStatus::State_Paused: action_Play_pause_track->setIcon(playbackPlay); action_Play_pause_track->setEnabled(true); action_Stop_track->setEnabled(true); if (trayIcon != NULL) trayIcon->setIcon(playbackPause); elapsedTimer.stop(); break; default: qDebug("Invalid state"); break; } // Check if song has changed or we're playing again after being stopped // and update song info if needed if (lastState == MPDStatus::State_Inactive || (lastState == MPDStatus::State_Stopped && status->state() == MPDStatus::State_Playing) || lastSongId != status->songId()) MPDConnection::self()->currentSong(); // Update status info lastState = status->state(); lastSongId = status->songId(); lastPlaylist = status->playlist(); } void MainWindow::playlistItemActivated(const QModelIndex &index) { QModelIndex sourceIndex = playlistProxyModel.mapToSource(index); MPDConnection::self()->startPlayingSongId(playlistModel.getIdByRow(sourceIndex.row())); } void MainWindow::clearPlaylist() { MPDConnection::self()->clear(); searchPlaylistLineEdit->clear(); } void MainWindow::removeFromPlaylist() { const QModelIndexList items = playlistTableView->selectionModel()->selectedRows(); QModelIndex sourceIndex; QList toBeRemoved; if (items.isEmpty()) return; for (int i = 0; i < items.size(); i++) { sourceIndex = playlistProxyModel.mapToSource(items.at(i)); toBeRemoved.append(playlistModel.getIdByRow(sourceIndex.row())); } MPDConnection::self()->removeSongs(toBeRemoved); } void MainWindow::replacePlaylist() { MPDConnection::self()->clear(); MPDConnection::self()->getStatus(); searchPlaylistLineEdit->clear(); if (libraryPage->view->isVisible()) { addSelectionToPlaylist(); } else if (folderPage->view->isVisible()) { addDirViewSelectionToPlaylist(); } } void MainWindow::addSelectionToPlaylist() { QStringList files; MusicLibraryItem *item; MusicLibraryItemSong *songItem; // Get selected view indexes const QModelIndexList selected = libraryPage->view->selectionModel()->selectedIndexes(); int selectionSize = selected.size(); if (selectionSize == 0) { return; } // Loop over the selection. Only add files. for (int selectionPos = 0; selectionPos < selectionSize; selectionPos++) { const QModelIndex current = selected.at(selectionPos); item = static_cast(libraryProxyModel.mapToSource(current).internalPointer()); switch (item->type()) { case MusicLibraryItem::Type_Artist: { for (quint32 i = 0; ; i++) { const QModelIndex album = current.child(i , 0); if (!album.isValid()) break; for (quint32 j = 0; ; j++) { const QModelIndex track = album.child(j, 0); if (!track.isValid()) break; const QModelIndex mappedSongIndex = libraryProxyModel.mapToSource(track); songItem = static_cast(mappedSongIndex.internalPointer()); const QString fileName = songItem->file(); if (!fileName.isEmpty() && !files.contains(fileName)) files.append(fileName); } } break; } case MusicLibraryItem::Type_Album: { for (quint32 i = 0; ; i++) { QModelIndex track = current.child(i, 0); if (!track.isValid()) break; const QModelIndex mappedSongIndex = libraryProxyModel.mapToSource(track); songItem = static_cast(mappedSongIndex.internalPointer()); const QString fileName = songItem->file(); if (!fileName.isEmpty() && !files.contains(fileName)) files.append(fileName); } break; } case MusicLibraryItem::Type_Song: { const QString fileName = static_cast(item)->file(); if (!fileName.isEmpty() && !files.contains(fileName)) files.append(fileName); break; } default: break; } } if (!files.isEmpty()) { MPDConnection::self()->add(files); if (MPDStatus::self()->state() != MPDStatus::State_Playing) MPDConnection::self()->startPlayingSong(); libraryPage->view->selectionModel()->clearSelection(); } } QStringList MainWindow::walkDirView(QModelIndex rootItem) { QStringList files; DirViewItem *item = static_cast(dirProxyModel.mapToSource(rootItem).internalPointer()); if (item->type() == DirViewItem::Type_File) { return QStringList(item->fileName()); } for (int i = 0; ; i++) { QModelIndex current = rootItem.child(i, 0); if (!current.isValid()) return files; QStringList tmp = walkDirView(current); for (int j = 0; j < tmp.size(); j++) { if (!files.contains(tmp.at(j))) files << tmp.at(j); } } return files; } void MainWindow::addDirViewSelectionToPlaylist() { QModelIndex current; QStringList files; DirViewItem *item; // Get selected view indexes const QModelIndexList selected = folderPage->view->selectionModel()->selectedIndexes(); int selectionSize = selected.size(); if (selectionSize == 0) { return; } for (int selectionPos = 0; selectionPos < selectionSize; selectionPos++) { current = selected.at(selectionPos); item = static_cast(dirProxyModel.mapToSource(current).internalPointer()); QStringList tmp; switch (item->type()) { case DirViewItem::Type_Dir: tmp = walkDirView(current); for (int i = 0; i < tmp.size(); i++) { if (!files.contains(tmp.at(i))) files << tmp.at(i); } break; case DirViewItem::Type_File: if (!files.contains(item->fileName())) files << item->fileName(); break; default: break; } } if (!files.isEmpty()) { MPDConnection::self()->add(files); if (MPDStatus::self()->state() != MPDStatus::State_Playing) MPDConnection::self()->startPlayingSong(); folderPage->view->selectionModel()->clearSelection(); } } void MainWindow::libraryItemActivated(const QModelIndex & /*index*/) { MusicLibraryItem *item; const QModelIndexList selected = libraryPage->view->selectionModel()->selectedIndexes(); int selectionSize = selected.size(); if (selectionSize != 1) return; //doubleclick should only have one selected item const QModelIndex current = selected.at(0); item = static_cast(libraryProxyModel.mapToSource(current).internalPointer()); if (item->type() == MusicLibraryItem::Type_Song) { addSelectionToPlaylist(); } } void MainWindow::dirViewItemActivated(const QModelIndex & /*index*/) { DirViewItem *item; const QModelIndexList selected = folderPage->view->selectionModel()->selectedIndexes(); int selectionSize = selected.size(); if (selectionSize != 1) return; //doubleclick should only have one selected item const QModelIndex current = selected.at(0); item = static_cast(dirProxyModel.mapToSource(current).internalPointer()); if (item->type() == DirViewItem::Type_File) { addDirViewSelectionToPlaylist(); } } void MainWindow::addToPlaylistItemActivated() { if (libraryPage->view->isVisible()) { addSelectionToPlaylist(); } else if (folderPage->view->isVisible()) { addDirViewSelectionToPlaylist(); } else if (playlistTableView->isVisible()) { addPlaylistToPlaylistPushButtonActivated(); } } void MainWindow::crossfadingChanged(int seconds) { MPDConnection::self()->setCrossfade(seconds); } void MainWindow::updatePlayListStatus() { MPDStats * const stats = MPDStats::self(); QString status = ""; if (stats->playlistSongs() == 0) { playListStatsLabel->setText(status); return; } #ifdef ENABLE_KDE_SUPPORT status+=i18np("1 Artist, ", "%1 Artists, ", stats->playlistArtists()); status+=i18np("1 Album, ", "%1 Albums, ", stats->playlistAlbums()); status+=i18np("1 Song", "%1 Songs", stats->playlistSongs()); #else status += QString::number(stats->playlistArtists())+QString(1==stats->playlistArtists() ? " Artist, " : "Artists, "); status += QString::number(stats->playlistAlbums())+QString(1==stats->playlistAlbums() ? " Album, " : "Albums, "); status += QString::number(stats->playlistSongs())+QString(1==stats->playlistSongs() ? " Song" : "Songs"); #endif status += " ("; status += MPDParseUtils::seconds2formattedString(stats->playlistTime()); status += ")"; playListStatsLabel->setText(status); } void MainWindow::movePlaylistItems(const QList items, const int row, const int size) { MPDConnection::self()->move(items, row, size); } void MainWindow::addFilenamesToPlaylist(const QStringList filenames, const int row, const int size) { MPDConnection::self()->addid(filenames, row, size); if (MPDStatus::self()->state() != MPDStatus::State_Playing) MPDConnection::self()->startPlayingSong(); } void MainWindow::updatePositionSilder() { QString timeElapsedFormattedString; if (positionSlider->value() != positionSlider->maximum()) { positionSlider->setValue(positionSlider->value() + 1); timeElapsedFormattedString += Song::formattedTime(positionSlider->value()); timeElapsedFormattedString += " / "; timeElapsedFormattedString += Song::formattedTime(songTime); songTimeElapsedLabel->setText(timeElapsedFormattedString); } } void MainWindow::copySongInfo() { const QModelIndexList items = playlistTableView->selectionModel()->selectedRows(); QModelIndex sourceIndex; QString txt = ""; QClipboard *clipboard = QApplication::clipboard(); if (items.isEmpty()) return; for (int i = 0; i < items.size(); i++) { sourceIndex = playlistProxyModel.mapToSource(items.at(i)); Song s = playlistModel.getSongByRow(sourceIndex.row()); if (s.isEmpty()) { if (txt != "") { txt += "\n"; } txt += s.format(); } } clipboard->setText(txt); } void MainWindow::updateOutpus(const QList &outputs) { #ifndef ENABLE_KDE_SUPPORT menu_Outputs->clear(); foreach(const Output &o, outputs) { QAction *a = new QAction(o.name, menu_Outputs); a->setCheckable(true); a->setChecked(o.enabled); a->setData(o.id); menu_Outputs->addAction(a); } #else QList actions; foreach(const Output &o, outputs) { QAction *a = new QAction(o.name, this); a->setCheckable(true); a->setChecked(o.enabled); a->setData(o.id); actions << a; } unplugActionList("outputs_list"); plugActionList("outputs_list", actions); #endif } void MainWindow::outputChanged(QAction *action) { if (action->isChecked()) { MPDConnection::self()->enableOutput(action->data().toInt()); } else { MPDConnection::self()->disableOutput(action->data().toInt()); } } void MainWindow::togglePlaylist() { if (splitter->isVisible()==action_Show_playlist->isChecked()) { return; } static int lastHeight=0; int widthB4=size().width(); bool showing=action_Show_playlist->isChecked(); if (!showing) { lastHeight=size().height(); } else { setMinimumHeight(0); setMaximumHeight(65535); } splitter->setVisible(showing); QApplication::processEvents(); adjustSize(); bool adjustWidth=size().width()setCheckable(true); act->setChecked(true); playlistTableViewMenu->addAction(act); viewActions.append(act); connect(act, SIGNAL(toggled(bool)), this, SLOT(playListTableViewToggleItem(bool))); } //Restore state QByteArray state = Settings::self()->playlistHeaderState(); //Restore if (!state.isEmpty()) { playlistTableViewHeader->restoreState(state); for(int i=3; i<7; ++i) { if (playlistTableViewHeader->isSectionHidden(i) || playlistTableViewHeader->sectionSize(i) == 0) { viewActions.at(i-3)->setChecked(false); playlistTableViewHeader->resizeSection(i, 100); playlistTableViewHeader->setSectionHidden(i, true); } } } } void MainWindow::setupPlaylistViewHeader() { playlistTableViewHeader = playlistTableView->header(); playlistTableViewHeader->setMovable(true); playlistTableViewHeader->setResizeMode(QHeaderView::Interactive); playlistTableViewHeader->setContextMenuPolicy(Qt::CustomContextMenu); connect(playlistTableViewHeader, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(playlistTableViewContextMenuClicked())); } void MainWindow::playlistTableViewContextMenuClicked() { playlistTableViewMenu->exec(QCursor::pos()); } void MainWindow::playListTableViewToggleItem(const bool visible) { QAction *act=qobject_cast(sender()); if (act) { int index=viewActions.indexOf(act); if (-1!=index) { playlistTableViewHeader->setSectionHidden(index+3, !visible); } } } /* * Crop playlist * Do this by taking the set off all song id's and subtracting from that * the set of selected song id's. Feed that list to MPDConnection::self()->removeSongs */ void MainWindow::cropPlaylist() { QSet songs = playlistModel.getSongIdSet(); QSet selected; const QModelIndexList items = playlistTableView->selectionModel()->selectedRows(); QModelIndex sourceIndex; if (items.isEmpty()) return; for(int i = 0; i < items.size(); i++) { sourceIndex = playlistProxyModel.mapToSource(items.at(i)); selected << playlistModel.getIdByRow(sourceIndex.row()); } QList toBeRemoved = (songs - selected).toList(); MPDConnection::self()->removeSongs(toBeRemoved); } // Tray Icon // bool MainWindow::setupTrayIcon() { if (!QSystemTrayIcon::isSystemTrayAvailable()) { trayIcon = NULL; return false; } trayIcon = new QSystemTrayIcon(this); trayIcon->installEventFilter(volumeSliderEventHandler); trayIconMenu = new QMenu(this); #ifdef ENABLE_KDE_SUPPORT quitAction = KStandardAction::quit(kapp, SLOT(quit()), trayIconMenu); #else quitAction = new QAction(tr("&Quit"), trayIconMenu); connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit())); #endif connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(trayIconClicked(QSystemTrayIcon::ActivationReason))); trayIconMenu->addAction(action_Prev_track); trayIconMenu->addAction(action_Next_track); trayIconMenu->addAction(action_Stop_track); trayIconMenu->addAction(action_Play_pause_track); trayIconMenu->addSeparator(); trayIconMenu->addAction(quitAction); trayIcon->setContextMenu(trayIconMenu); trayIcon->setIcon(windowIcon()); #ifdef ENABLE_KDE_SUPPORT trayIcon->setToolTip(i18n("Cantata")); #else trayIcon->setToolTip(tr("Cantata")); #endif return true; } void MainWindow::trayIconClicked(QSystemTrayIcon::ActivationReason reason) { switch (reason) { case QSystemTrayIcon::Trigger: if (isHidden()) { showNormal(); if (!lastPos.isNull()) { move(lastPos); } } else { hide(); } default: break; } } void MainWindow::addPlaylistToPlaylistPushButtonActivated() { const QModelIndexList items = playlistsPage->view->selectionModel()->selectedRows(); if (items.size() == 1) { QModelIndex sourceIndex = playlistsProxyModel.mapToSource(items.first()); QString playlist_name = playlistsModel.data(sourceIndex, Qt::DisplayRole).toString(); playlistsModel.loadPlaylist(playlist_name); } } void MainWindow::loadPlaylistPushButtonActivated() { const QModelIndexList items = playlistsPage->view->selectionModel()->selectedRows(); if (items.size() == 1) { MPDConnection::self()->clear(); MPDConnection::self()->getStatus(); searchPlaylistLineEdit->clear(); QModelIndex sourceIndex = playlistsProxyModel.mapToSource(items.first()); QString playlist_name = playlistsModel.data(sourceIndex, Qt::DisplayRole).toString(); playlistsModel.loadPlaylist(playlist_name); } } void MainWindow::playlistsViewItemDoubleClicked(const QModelIndex &index) { QModelIndex sourceIndex = playlistsProxyModel.mapToSource(index); QString playlist_name = playlistsModel.data(sourceIndex, Qt::DisplayRole).toString(); playlistsModel.loadPlaylist(playlist_name); } void MainWindow::removePlaylistPushButtonActivated() { const QModelIndexList items = playlistsPage->view->selectionModel()->selectedRows(); if (items.size() == 1) { QModelIndex sourceIndex = playlistsProxyModel.mapToSource(items.first()); QString playlist_name = playlistsModel.data(sourceIndex, Qt::DisplayRole).toString(); #ifdef ENABLE_KDE_SUPPORT if (KMessageBox::Yes == KMessageBox::warningYesNo(this, i18n("Are you sure you want to delete playlist: %1?", playlist_name), i18n("Delete Playlist?"))) { playlistsModel.removePlaylist(playlist_name); } #else QMessageBox msgBox; msgBox.setIcon(QMessageBox::Warning); msgBox.setWindowTitle(tr("Delete Playlist?")); msgBox.setText(tr("Are you sure you want to delete playlist: %1?").arg(playlist_name)); msgBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes); msgBox.setDefaultButton(QMessageBox::No); int ret = msgBox.exec(); if (ret == QMessageBox::Yes) { playlistsModel.removePlaylist(playlist_name); } #endif } } void MainWindow::savePlaylistPushButtonActivated() { #ifdef ENABLE_KDE_SUPPORT QString name = QInputDialog::getText(this, i18n("Playlist Name"), i18n("Enter a name for the playlist:")); #else QString name = QInputDialog::getText(this, tr("Playlist Name"), tr("Enter a name for the playlist:")); #endif if (!name.isEmpty()) playlistsModel.savePlaylist(name); } /* * Idle command has returnd that stored_playlist: * "a stored playlist has been modified, renamed, created or deleted" * Update accordingly * * TODO: Implement */ void MainWindow::updateStoredPlaylists() { qDebug() << "Need to update playlist"; playlistsModel.getPlaylists(); } void MainWindow::renamePlaylistActivated() { const QModelIndexList items = playlistsPage->view->selectionModel()->selectedRows(); if (items.size() == 1) { QModelIndex sourceIndex = playlistsProxyModel.mapToSource(items.first()); QString playlist_name = playlistsModel.data(sourceIndex, Qt::DisplayRole).toString(); #ifdef ENABLE_KDE_SUPPORT QString new_name = QInputDialog::getText(this, i18n("Rename Playlist"), i18n("Enter new name for playlist: %1").arg(playlist_name)); #else QString new_name = QInputDialog::getText(this, tr("Rename Playlist"), tr("Enter new name for playlist: %1").arg(playlist_name)); #endif if (!new_name.isEmpty()) { playlistsModel.renamePlaylist(playlist_name, new_name); } } } enum Tabs { TAB_LIBRARY = 0x01, TAB_DIRS = 0x02, TAB_PLAYLISTS = 0x04 }; void MainWindow::currentTabChanged(int index) { switch(index) { case 0: if (!(loaded&TAB_LIBRARY)) { loaded|=TAB_LIBRARY; if (!musicLibraryModel.fromXML(MPDStats::self()->dbUpdate())) { MPDConnection::self()->listAllInfo(MPDStats::self()->dbUpdate()); } } break; case 1: if (!(loaded&TAB_DIRS)) { loaded|=TAB_DIRS; MPDConnection::self()->listAll(); } break; case 2: if (!(loaded&TAB_PLAYLISTS)) { loaded|=TAB_PLAYLISTS; playlistsModel.getPlaylists(); } break; case 3: if (lyricsNeedUpdating) { Lyrics::self()->get(current); lyricsNeedUpdating=false; } break; default: break; } } void MainWindow::lyrics(const QString &artist, const QString &title, const QString &text) { if (artist==current.artist && title==current.title) { lyricsPage->text->setText(text); } } void MainWindow::cover(const QString &artist, const QString &album, const QImage &img) { if (artist==current.albumArtist() && album==current.album) { if (img.isNull()) { coverWidget->setPixmap(noCover); } else { coverWidget->setPixmap(QPixmap::fromImage(img).scaled(coverWidget->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); } } } void MainWindow::updateGenres(const QStringList &genres) { QStringList entries; #ifdef ENABLE_KDE_SUPPORT entries << i18n("All Genres"); #else entries << tr("All Genres"); #endif entries+=genres; bool diff=libraryPage->genreCombo->count() != entries.count(); if (!diff) { // Check items... for (int i=1; igenreCombo->count() && !diff; ++i) { if (libraryPage->genreCombo->itemText(i) != entries.at(i)) { diff=true; } } } if (!diff) { return; } QString currentFilter = libraryPage->genreCombo->currentIndex() ? libraryPage->genreCombo->currentText() : QString(); libraryPage->genreCombo->clear(); if (genres.count()<2) { libraryPage->genreCombo->setCurrentIndex(0); } else { libraryPage->genreCombo->addItems(entries); if (!currentFilter.isEmpty()) { bool found=false; for (int i=1; igenreCombo->count() && !found; ++i) { if (libraryPage->genreCombo->itemText(i) == currentFilter) { libraryPage->genreCombo->setCurrentIndex(i); found=true; } } if (!found) { libraryPage->genreCombo->setCurrentIndex(0); } } } }