diff --git a/src/elisaapplication.cpp b/src/elisaapplication.cpp index 262aa5ee..cbb95158 100644 --- a/src/elisaapplication.cpp +++ b/src/elisaapplication.cpp @@ -1,487 +1,492 @@ /* * Copyright 2017 Matthieu Gallien * Copyright (C) 2012 Aleix Pol Gonzalez * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "elisaapplication.h" #include "musiclistenersmanager.h" #include "models/allalbumsproxymodel.h" #include "models/alltracksproxymodel.h" #include "models/allartistsproxymodel.h" #include "models/singleartistproxymodel.h" #include "models/singlealbumproxymodel.h" #include "models/filebrowserproxymodel.h" #include "mediaplaylist.h" #include "audiowrapper.h" #include "manageaudioplayer.h" #include "managemediaplayercontrol.h" #include "manageheaderbar.h" #include "elisa_settings.h" #include #if defined KF5ConfigWidgets_FOUND && KF5ConfigWidgets_FOUND #include #endif #if defined KF5XmlGui_FOUND && KF5XmlGui_FOUND #include #include #include #include #include #endif #if defined KF5KCMUtils_FOUND && KF5KCMUtils_FOUND #include #endif #include #include #include #include #include #include #include #include #include #include #include #include class ElisaApplicationPrivate { public: explicit ElisaApplicationPrivate(QObject *parent) #if defined KF5XmlGui_FOUND && KF5XmlGui_FOUND : mCollection(parent) #endif { Q_UNUSED(parent) auto configurationFileName = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation); configurationFileName += QStringLiteral("/elisarc"); Elisa::ElisaConfiguration::instance(configurationFileName); Elisa::ElisaConfiguration::self()->load(); Elisa::ElisaConfiguration::self()->save(); } #if defined KF5XmlGui_FOUND && KF5XmlGui_FOUND KActionCollection mCollection; #endif QStringList mArguments; std::unique_ptr mMusicManager; std::unique_ptr mAllAlbumsProxyModel; std::unique_ptr mAllArtistsProxyModel; std::unique_ptr mAllTracksProxyModel; std::unique_ptr mSingleArtistProxyModel; std::unique_ptr mSingleAlbumProxyModel; std::unique_ptr mFileBrowserProxyModel; std::unique_ptr mMediaPlayList; std::unique_ptr mAudioWrapper; std::unique_ptr mAudioControl; std::unique_ptr mPlayerControl; std::unique_ptr mManageHeaderBar; }; ElisaApplication::ElisaApplication(QObject *parent) : QObject(parent), d(std::make_unique(this)) { } ElisaApplication::~ElisaApplication() = default; void ElisaApplication::setupActions(const QString &actionName) { #if defined KF5XmlGui_FOUND && KF5XmlGui_FOUND if (actionName == QStringLiteral("file_quit")) { auto quitAction = KStandardAction::quit(QCoreApplication::instance(), &QCoreApplication::quit, &d->mCollection); d->mCollection.addAction(actionName, quitAction); } if (actionName == QStringLiteral("help_contents") && KAuthorized::authorizeAction(actionName)) { auto handBookAction = KStandardAction::helpContents(this, &ElisaApplication::appHelpActivated, &d->mCollection); d->mCollection.addAction(handBookAction->objectName(), handBookAction); } if (actionName == QStringLiteral("help_report_bug") && KAuthorized::authorizeAction(actionName) && !KAboutData::applicationData().bugAddress().isEmpty()) { auto reportBugAction = KStandardAction::reportBug(this, &ElisaApplication::reportBug, &d->mCollection); d->mCollection.addAction(reportBugAction->objectName(), reportBugAction); } if (actionName == QStringLiteral("help_about_app") && KAuthorized::authorizeAction(actionName)) { auto aboutAppAction = KStandardAction::aboutApp(this, &ElisaApplication::aboutApplication, this); d->mCollection.addAction(aboutAppAction->objectName(), aboutAppAction); } if (actionName == QStringLiteral("options_configure") && KAuthorized::authorizeAction(actionName)) { auto preferencesAction = KStandardAction::preferences(this, &ElisaApplication::configureElisa, this); d->mCollection.addAction(preferencesAction->objectName(), preferencesAction); } if (actionName == QStringLiteral("options_configure_keybinding") && KAuthorized::authorizeAction(actionName)) { auto keyBindingsAction = KStandardAction::keyBindings(this, &ElisaApplication::configureShortcuts, this); d->mCollection.addAction(keyBindingsAction->objectName(), keyBindingsAction); } if (actionName == QStringLiteral("go_back") && KAuthorized::authorizeAction(actionName)) { auto goBackAction = KStandardAction::back(this, &ElisaApplication::goBack, this); d->mCollection.addAction(goBackAction->objectName(), goBackAction); } if (actionName == QStringLiteral("edit_find") && KAuthorized::authorizeAction(actionName)) { auto findAction = KStandardAction::find(this, &ElisaApplication::find, this); d->mCollection.addAction(findAction->objectName(), findAction); } d->mCollection.readSettings(); #endif } void ElisaApplication::setArguments(const QStringList &newArguments) { if (d->mArguments == newArguments) { return; } d->mArguments = checkFileListAndMakeAbsolute(newArguments, QDir::currentPath()); Q_EMIT argumentsChanged(); if (!d->mArguments.isEmpty()) { Q_EMIT enqueue(d->mArguments); } } void ElisaApplication::activateActionRequested(const QString &actionName, const QVariant ¶meter) { Q_UNUSED(actionName) Q_UNUSED(parameter) } void ElisaApplication::activateRequested(const QStringList &arguments, const QString &workingDirectory) { auto realArguments = arguments; if (realArguments.size() > 1) { realArguments.removeFirst(); Q_EMIT enqueue(checkFileListAndMakeAbsolute(realArguments, workingDirectory)); } } void ElisaApplication::openRequested(const QList &uris) { Q_UNUSED(uris) } void ElisaApplication::appHelpActivated() { QDesktopServices::openUrl(QUrl(QStringLiteral("help:/"))); } void ElisaApplication::aboutApplication() { #if defined KF5XmlGui_FOUND && KF5XmlGui_FOUND static QPointer dialog; if (!dialog) { dialog = new KAboutApplicationDialog(KAboutData::applicationData(), nullptr); dialog->setAttribute(Qt::WA_DeleteOnClose); } dialog->show(); #endif } void ElisaApplication::reportBug() { #if defined KF5XmlGui_FOUND && KF5XmlGui_FOUND static QPointer dialog; if (!dialog) { dialog = new KBugReport(KAboutData::applicationData(), nullptr); dialog->setAttribute(Qt::WA_DeleteOnClose); } dialog->show(); #endif } void ElisaApplication::configureShortcuts() { #if defined KF5XmlGui_FOUND && KF5XmlGui_FOUND KShortcutsDialog dlg(KShortcutsEditor::AllActions, KShortcutsEditor::LetterShortcutsAllowed, nullptr); dlg.setModal(true); dlg.addCollection(&d->mCollection); dlg.configure(); #endif } void ElisaApplication::configureElisa() { #if defined KF5KCMUtils_FOUND && KF5KCMUtils_FOUND KCMultiDialog configurationDialog; configurationDialog.addModule(QStringLiteral("kcm_elisa_local_file")); configurationDialog.setModal(true); configurationDialog.exec(); #endif } void ElisaApplication::goBack() {} void ElisaApplication::find() {} QStringList ElisaApplication::checkFileListAndMakeAbsolute(const QStringList &filesList, const QString &workingDirectory) const { QStringList filesToOpen; for (const auto &oneFile : filesList) { auto newFile = QFileInfo(oneFile); if (newFile.isRelative()) { newFile = QFileInfo(workingDirectory + QStringLiteral("/") + oneFile); } if (newFile.exists()) { filesToOpen.push_back(newFile.canonicalFilePath()); } } return filesToOpen; } void ElisaApplication::initialize() { initializeModels(); initializePlayer(); } void ElisaApplication::initializeModels() { d->mMusicManager = std::make_unique(); Q_EMIT musicManagerChanged(); d->mAllAlbumsProxyModel = std::make_unique(); Q_EMIT allAlbumsProxyModelChanged(); d->mAllArtistsProxyModel = std::make_unique(); Q_EMIT allArtistsProxyModelChanged(); d->mAllTracksProxyModel = std::make_unique(); Q_EMIT allTracksProxyModelChanged(); d->mSingleArtistProxyModel = std::make_unique(); Q_EMIT singleArtistProxyModelChanged(); d->mSingleAlbumProxyModel = std::make_unique(); Q_EMIT singleAlbumProxyModelChanged(); d->mFileBrowserProxyModel = std::make_unique(); Q_EMIT fileBrowserProxyModelChanged(); d->mMediaPlayList = std::make_unique(); Q_EMIT mediaPlayListChanged(); d->mMusicManager->setElisaApplication(this); d->mMediaPlayList->setMusicListenersManager(d->mMusicManager.get()); QObject::connect(this, &ElisaApplication::enqueue, d->mMediaPlayList.get(), &MediaPlayList::enqueueAndPlay); d->mAllAlbumsProxyModel->setSourceModel(d->mMusicManager->allAlbumsModel()); d->mAllArtistsProxyModel->setSourceModel(d->mMusicManager->allArtistsModel()); d->mAllTracksProxyModel->setSourceModel(d->mMusicManager->allTracksModel()); d->mSingleArtistProxyModel->setSourceModel(d->mMusicManager->allAlbumsModel()); d->mSingleAlbumProxyModel->setSourceModel(d->mMusicManager->albumModel()); QObject::connect(d->mAllAlbumsProxyModel.get(), &AllAlbumsProxyModel::albumToEnqueue, d->mMediaPlayList.get(), static_cast &, ElisaUtils::PlayListEnqueueMode, ElisaUtils::PlayListEnqueueTriggerPlay)>(&MediaPlayList::enqueue)); QObject::connect(d->mAllArtistsProxyModel.get(), &AllArtistsProxyModel::artistToEnqueue, d->mMediaPlayList.get(), &MediaPlayList::enqueueArtists); QObject::connect(d->mAllTracksProxyModel.get(), &AllTracksProxyModel::trackToEnqueue, d->mMediaPlayList.get(), static_cast &, ElisaUtils::PlayListEnqueueMode, ElisaUtils::PlayListEnqueueTriggerPlay)>(&MediaPlayList::enqueue)); QObject::connect(d->mSingleArtistProxyModel.get(), &SingleArtistProxyModel::albumToEnqueue, d->mMediaPlayList.get(), static_cast &, ElisaUtils::PlayListEnqueueMode, ElisaUtils::PlayListEnqueueTriggerPlay)>(&MediaPlayList::enqueue)); QObject::connect(d->mSingleAlbumProxyModel.get(), &SingleAlbumProxyModel::trackToEnqueue, d->mMediaPlayList.get(), static_cast &, ElisaUtils::PlayListEnqueueMode, ElisaUtils::PlayListEnqueueTriggerPlay)>(&MediaPlayList::enqueue)); + QObject::connect(d->mFileBrowserProxyModel.get(), &FileBrowserProxyModel::filesToEnqueue, + d->mMediaPlayList.get(), static_cast &, + ElisaUtils::PlayListEnqueueMode, + ElisaUtils::PlayListEnqueueTriggerPlay)>(&MediaPlayList::enqueue)); + } void ElisaApplication::initializePlayer() { d->mAudioWrapper = std::make_unique(); Q_EMIT audioPlayerChanged(); d->mAudioControl = std::make_unique(); Q_EMIT audioControlChanged(); d->mPlayerControl = std::make_unique(); Q_EMIT playerControlChanged(); d->mManageHeaderBar = std::make_unique(); Q_EMIT manageHeaderBarChanged(); d->mAudioControl->setAlbumNameRole(MediaPlayList::AlbumRole); d->mAudioControl->setArtistNameRole(MediaPlayList::ArtistRole); d->mAudioControl->setTitleRole(MediaPlayList::TitleRole); d->mAudioControl->setUrlRole(MediaPlayList::ResourceRole); d->mAudioControl->setIsPlayingRole(MediaPlayList::IsPlayingRole); d->mAudioControl->setPlayListModel(d->mMediaPlayList.get()); QObject::connect(d->mAudioControl.get(), &ManageAudioPlayer::playerPlay, d->mAudioWrapper.get(), &AudioWrapper::play); QObject::connect(d->mAudioControl.get(), &ManageAudioPlayer::playerPause, d->mAudioWrapper.get(), &AudioWrapper::pause); QObject::connect(d->mAudioControl.get(), &ManageAudioPlayer::playerStop, d->mAudioWrapper.get(), &AudioWrapper::stop); QObject::connect(d->mAudioControl.get(), &ManageAudioPlayer::seek, d->mAudioWrapper.get(), &AudioWrapper::seek); QObject::connect(d->mAudioControl.get(), &ManageAudioPlayer::skipNextTrack, d->mMediaPlayList.get(), &MediaPlayList::skipNextTrack); QObject::connect(d->mAudioControl.get(), &ManageAudioPlayer::sourceInError, d->mMediaPlayList.get(), &MediaPlayList::trackInError); QObject::connect(d->mAudioControl.get(), &ManageAudioPlayer::sourceInError, d->mMusicManager.get(), &MusicListenersManager::playBackError); QObject::connect(d->mAudioControl.get(), &ManageAudioPlayer::playerSourceChanged, d->mAudioWrapper.get(), &AudioWrapper::setSource); QObject::connect(d->mMediaPlayList.get(), &MediaPlayList::ensurePlay, d->mAudioControl.get(), &ManageAudioPlayer::ensurePlay); QObject::connect(d->mMediaPlayList.get(), &MediaPlayList::playListFinished, d->mAudioControl.get(), &ManageAudioPlayer::playListFinished); QObject::connect(d->mMediaPlayList.get(), &MediaPlayList::currentTrackChanged, d->mAudioControl.get(), &ManageAudioPlayer::setCurrentTrack); QObject::connect(d->mAudioWrapper.get(), &AudioWrapper::playbackStateChanged, d->mAudioControl.get(), &ManageAudioPlayer::setPlayerPlaybackState); QObject::connect(d->mAudioWrapper.get(), &AudioWrapper::statusChanged, d->mAudioControl.get(), &ManageAudioPlayer::setPlayerStatus); QObject::connect(d->mAudioWrapper.get(), &AudioWrapper::errorChanged, d->mAudioControl.get(), &ManageAudioPlayer::setPlayerError); QObject::connect(d->mAudioWrapper.get(), &AudioWrapper::durationChanged, d->mAudioControl.get(), &ManageAudioPlayer::setAudioDuration); QObject::connect(d->mAudioWrapper.get(), &AudioWrapper::seekableChanged, d->mAudioControl.get(), &ManageAudioPlayer::setPlayerIsSeekable); QObject::connect(d->mAudioWrapper.get(), &AudioWrapper::positionChanged, d->mAudioControl.get(), &ManageAudioPlayer::setPlayerPosition); d->mPlayerControl->setPlayListModel(d->mMediaPlayList.get()); QObject::connect(d->mMediaPlayList.get(), &MediaPlayList::currentTrackChanged, d->mPlayerControl.get(), &ManageMediaPlayerControl::setCurrentTrack); QObject::connect(d->mAudioWrapper.get(), &AudioWrapper::playing, d->mPlayerControl.get(), &ManageMediaPlayerControl::playerPlaying); QObject::connect(d->mAudioWrapper.get(), &AudioWrapper::paused, d->mPlayerControl.get(), &ManageMediaPlayerControl::playerPaused); QObject::connect(d->mAudioWrapper.get(), &AudioWrapper::stopped, d->mPlayerControl.get(), &ManageMediaPlayerControl::playerStopped); d->mManageHeaderBar->setTitleRole(MediaPlayList::TitleRole); d->mManageHeaderBar->setAlbumRole(MediaPlayList::AlbumRole); d->mManageHeaderBar->setArtistRole(MediaPlayList::ArtistRole); d->mManageHeaderBar->setImageRole(MediaPlayList::ImageRole); d->mManageHeaderBar->setIsValidRole(MediaPlayList::IsValidRole); d->mManageHeaderBar->setPlayListModel(d->mMediaPlayList.get()); QObject::connect(d->mMediaPlayList.get(), &MediaPlayList::currentTrackChanged, d->mManageHeaderBar.get(), &ManageHeaderBar::setCurrentTrack); if (!d->mArguments.isEmpty()) { Q_EMIT enqueue(d->mArguments); } } QAction * ElisaApplication::action(const QString& name) { #if defined KF5XmlGui_FOUND && KF5XmlGui_FOUND auto resultAction = d->mCollection.action(name); if (!resultAction) { setupActions(name); resultAction = d->mCollection.action(name); } return resultAction; #else Q_UNUSED(name); return new QAction(); #endif } QString ElisaApplication::iconName(const QIcon& icon) { return icon.name(); } const QStringList &ElisaApplication::arguments() const { return d->mArguments; } MusicListenersManager *ElisaApplication::musicManager() const { return d->mMusicManager.get(); } AllAlbumsProxyModel *ElisaApplication::allAlbumsProxyModel() const { return d->mAllAlbumsProxyModel.get(); } AllArtistsProxyModel *ElisaApplication::allArtistsProxyModel() const { return d->mAllArtistsProxyModel.get(); } AllTracksProxyModel *ElisaApplication::allTracksProxyModel() const { return d->mAllTracksProxyModel.get(); } SingleArtistProxyModel *ElisaApplication::singleArtistProxyModel() const { return d->mSingleArtistProxyModel.get(); } SingleAlbumProxyModel *ElisaApplication::singleAlbumProxyModel() const { return d->mSingleAlbumProxyModel.get(); } FileBrowserProxyModel *ElisaApplication::fileBrowserProxyModel() const { return d->mFileBrowserProxyModel.get(); } MediaPlayList *ElisaApplication::mediaPlayList() const { return d->mMediaPlayList.get(); } AudioWrapper *ElisaApplication::audioPlayer() const { return d->mAudioWrapper.get(); } ManageAudioPlayer *ElisaApplication::audioControl() const { return d->mAudioControl.get(); } ManageMediaPlayerControl *ElisaApplication::playerControl() const { return d->mPlayerControl.get(); } ManageHeaderBar *ElisaApplication::manageHeaderBar() const { return d->mManageHeaderBar.get(); } #include "moc_elisaapplication.cpp" diff --git a/src/elisautils.cpp b/src/elisautils.cpp index 94890b8d..f80642dc 100644 --- a/src/elisautils.cpp +++ b/src/elisautils.cpp @@ -1,180 +1,168 @@ /* * Copyright 2017 Matthieu Gallien * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "elisautils.h" #include #include #include #include #include MusicAudioTrack ElisaUtils::scanOneFile(const QUrl &scanFile, const QMimeDatabase &mimeDatabase, const KFileMetaData::ExtractorCollection &allExtractors) { MusicAudioTrack newTrack; auto localFileName = scanFile.toLocalFile(); const auto &fileMimeType = mimeDatabase.mimeTypeForFile(localFileName); if (!fileMimeType.name().startsWith(QStringLiteral("audio/"))) { return newTrack; } QString mimetype = fileMimeType.name(); QList exList = allExtractors.fetchExtractors(mimetype); if (exList.isEmpty()) { return newTrack; } QFileInfo scanFileInfo(localFileName); newTrack.setFileModificationTime(scanFileInfo.fileTime(QFile::FileModificationTime)); newTrack.setResourceURI(scanFile); KFileMetaData::Extractor* ex = exList.first(); KFileMetaData::SimpleExtractionResult result(localFileName, mimetype, KFileMetaData::ExtractionResult::ExtractMetaData); ex->extract(&result); const auto &allProperties = result.properties(); ElisaUtils::scanProperties(localFileName, allProperties, newTrack); return newTrack; } void ElisaUtils::scanProperties(const QString localFileName, const KFileMetaData::PropertyMap &allProperties, MusicAudioTrack &trackData) { auto titleProperty = allProperties.find(KFileMetaData::Property::Title); auto durationProperty = allProperties.find(KFileMetaData::Property::Duration); auto artistProperty = allProperties.find(KFileMetaData::Property::Artist); auto albumProperty = allProperties.find(KFileMetaData::Property::Album); auto albumArtistProperty = allProperties.find(KFileMetaData::Property::AlbumArtist); auto trackNumberProperty = allProperties.find(KFileMetaData::Property::TrackNumber); auto discNumberProperty = allProperties.find(KFileMetaData::Property::DiscNumber); auto genreProperty = allProperties.find(KFileMetaData::Property::Genre); auto yearProperty = allProperties.find(KFileMetaData::Property::ReleaseYear); auto composerProperty = allProperties.find(KFileMetaData::Property::Composer); auto lyricistProperty = allProperties.find(KFileMetaData::Property::Lyricist); auto channelsProperty = allProperties.find(KFileMetaData::Property::Channels); auto bitRateProperty = allProperties.find(KFileMetaData::Property::BitRate); auto sampleRateProperty = allProperties.find(KFileMetaData::Property::SampleRate); auto commentProperty = allProperties.find(KFileMetaData::Property::Comment); #if defined Q_OS_LINUX && !defined Q_OS_ANDROID auto fileData = KFileMetaData::UserMetaData(localFileName); #endif if (albumProperty != allProperties.end()) { trackData.setAlbumName(albumProperty->toString()); } if (artistProperty != allProperties.end()) { trackData.setArtist(artistProperty->toStringList().join(QStringLiteral(", "))); } if (durationProperty != allProperties.end()) { trackData.setDuration(QTime::fromMSecsSinceStartOfDay(int(1000 * durationProperty->toDouble()))); } if (titleProperty != allProperties.end()) { trackData.setTitle(titleProperty->toString()); } if (trackNumberProperty != allProperties.end()) { trackData.setTrackNumber(trackNumberProperty->toInt()); } if (discNumberProperty != allProperties.end()) { trackData.setDiscNumber(discNumberProperty->toInt()); } else { trackData.setDiscNumber(1); } if (albumArtistProperty != allProperties.end()) { trackData.setAlbumArtist(albumArtistProperty->toStringList().join(QStringLiteral(", "))); } if (yearProperty != allProperties.end()) { trackData.setYear(yearProperty->toInt()); } if (channelsProperty != allProperties.end()) { trackData.setChannels(channelsProperty->toInt()); } if (bitRateProperty != allProperties.end()) { trackData.setBitRate(bitRateProperty->toInt()); } if (sampleRateProperty != allProperties.end()) { trackData.setSampleRate(sampleRateProperty->toInt()); } if (genreProperty != allProperties.end()) { trackData.setGenre(genreProperty->toStringList().join(QStringLiteral(", "))); } if (composerProperty != allProperties.end()) { trackData.setComposer(composerProperty->toStringList().join(QStringLiteral(", "))); } if (lyricistProperty != allProperties.end()) { trackData.setLyricist(lyricistProperty->toStringList().join(QStringLiteral(", "))); } if (commentProperty != allProperties.end()) { trackData.setComment(commentProperty->toString()); } if (trackData.artist().isEmpty()) { trackData.setArtist(trackData.albumArtist()); } #if defined Q_OS_LINUX && !defined Q_OS_ANDROID trackData.setRating(fileData.rating()); #else trackData.setRating(0); #endif - if (trackData.title().isEmpty()) { - return; - } - - if (trackData.artist().isEmpty()) { - return; - } - - if (trackData.albumName().isEmpty()) { - return; - } - if (!trackData.duration().isValid()) { return; } trackData.setValid(true); } #include "moc_elisautils.cpp" diff --git a/src/qml/ElisaMainWindow.qml b/src/qml/ElisaMainWindow.qml index 66cfa706..d0442ded 100644 --- a/src/qml/ElisaMainWindow.qml +++ b/src/qml/ElisaMainWindow.qml @@ -1,286 +1,286 @@ /* * Copyright 2016-2018 Matthieu Gallien * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ import QtQuick 2.7 import QtQuick.Controls 2.2 import QtQuick.Controls 1.4 as Controls1 import QtQuick.Layouts 1.1 import QtQuick.Window 2.2 import org.kde.elisa 1.0 import Qt.labs.settings 1.0 ApplicationWindow { id: mainWindow visible: true minimumWidth: 1100 minimumHeight: 600 LayoutMirroring.enabled: Qt.application.layoutDirection == Qt.RightToLeft LayoutMirroring.childrenInherit: true x: persistentSettings.x y: persistentSettings.y width: persistentSettings.width height: persistentSettings.height title: i18n("Elisa") property var goBackAction: elisa.action("go_back") property var findAction: elisa.action("edit_find") Controls1.Action { shortcut: findAction.shortcut onTriggered: { if ( persistentSettings.expandedFilterView == true) { persistentSettings.expandedFilterView = false } else { persistentSettings.expandedFilterView = true } } } Controls1.Action { shortcut: goBackAction.shortcut onTriggered: contentView.goBack() } Controls1.Action { id: applicationMenuAction text: i18nc("open application menu", "Application Menu") iconName: "application-menu" onTriggered: applicationMenu.popup() } ApplicationMenu { id: applicationMenu } SystemPalette { id: myPalette colorGroup: SystemPalette.Active } Theme { id: elisaTheme } Settings { id: persistentSettings property int x property int y property int width : 1100 property int height : 600 property var playListState property var audioPlayerState property double playControlItemVolume : 100.0 property bool playControlItemMuted : false property bool playControlItemRepeat : false property bool playControlItemShuffle : false property bool expandedFilterView: false } Connections { target: Qt.application onAboutToQuit: { persistentSettings.x = mainWindow.x; persistentSettings.y = mainWindow.y; persistentSettings.width = mainWindow.width; persistentSettings.height = mainWindow.height; persistentSettings.playListState = elisa.mediaPlayList.persistentState; persistentSettings.audioPlayerState = elisa.audioControl.persistentState persistentSettings.playControlItemVolume = headerBar.playerControl.volume persistentSettings.playControlItemMuted = headerBar.playerControl.muted persistentSettings.playControlItemRepeat = headerBar.playerControl.repeat persistentSettings.playControlItemShuffle = headerBar.playerControl.shuffle } } Loader { id: mprisloader active: false sourceComponent: PlatformIntegration { id: platformInterface playListModel: elisa.mediaPlayList audioPlayerManager: elisa.audioControl player: elisa.audioPlayer headerBarManager: elisa.manageHeaderBar manageMediaPlayerControl: elisa.playerControl onRaisePlayer: { mainWindow.show() mainWindow.raise() mainWindow.requestActivate() } } } Connections { target: elisa.audioPlayer onVolumeChanged: headerBar.playerControl.volume = elisa.audioPlayer.volume onMutedChanged: headerBar.playerControl.muted = elisa.audioPlayer.muted } Connections { target: elisa.mediaPlayList onPlayListLoadFailed: { messageNotification.showNotification(i18nc("message of passive notification when playlist load failed", "Load of playlist failed"), 3000) } } PassiveNotification { id: messageNotification } Rectangle { color: myPalette.base anchors.fill: parent ColumnLayout { anchors.fill: parent spacing: 0 Item { Layout.preferredHeight: mainWindow.height * 0.2 + elisaTheme.mediaPlayerControlHeight Layout.minimumHeight: mainWindow.height * 0.2 + elisaTheme.mediaPlayerControlHeight Layout.maximumHeight: mainWindow.height * 0.2 + elisaTheme.mediaPlayerControlHeight Layout.fillWidth: true HeaderBar { id: headerBar focus: true anchors.fill: parent tracksCount: elisa.manageHeaderBar.remainingTracks album: elisa.manageHeaderBar.album title: elisa.manageHeaderBar.title artist: elisa.manageHeaderBar.artist image: elisa.manageHeaderBar.image ratingVisible: false playerControl.duration: elisa.audioPlayer.duration playerControl.seekable: elisa.audioPlayer.seekable playerControl.volume: persistentSettings.playControlItemVolume playerControl.muted: persistentSettings.playControlItemMuted playerControl.position: elisa.audioPlayer.position playerControl.skipBackwardEnabled: elisa.playerControl.skipBackwardControlEnabled playerControl.skipForwardEnabled: elisa.playerControl.skipForwardControlEnabled playerControl.playEnabled: elisa.playerControl.playControlEnabled playerControl.isPlaying: elisa.playerControl.musicPlaying playerControl.repeat: persistentSettings.playControlItemRepeat playerControl.shuffle: persistentSettings.playControlItemShuffle playerControl.onSeek: elisa.audioPlayer.seek(position) playerControl.onPlay: elisa.audioControl.playPause() playerControl.onPause: elisa.audioControl.playPause() playerControl.onPlayPrevious: elisa.mediaPlayList.skipPreviousTrack() playerControl.onPlayNext: elisa.mediaPlayList.skipNextTrack() TrackImportNotification { id: importedTracksCountNotification anchors { right: headerBar.right top: headerBar.top rightMargin: elisaTheme.layoutHorizontalMargin * 1.75 topMargin: elisaTheme.layoutHorizontalMargin * 3 } } Binding { target: importedTracksCountNotification property: 'musicManager' value: elisa.musicManager when: elisa.musicManager !== undefined } Loader { sourceComponent: Binding { target: importedTracksCountNotification property: 'indexingRunning' value: elisa.musicManager.indexingRunning } active: elisa.musicManager !== undefined } Loader { sourceComponent: Binding { target: importedTracksCountNotification property: 'importedTracksCount' value: elisa.musicManager.importedTracksCount } active: elisa.musicManager !== undefined } } } ContentView { id: contentView Layout.fillHeight: true Layout.fillWidth: true } } } Component.onCompleted: { elisa.initialize() - elisa.mediaPlayList.randomPlay = Qt.binding(function() { return contentView.playList.randomPlayChecked }) - elisa.mediaPlayList.repeatPlay = Qt.binding(function() { return contentView.playList.repeatPlayChecked }) - elisa.playerControl.randomOrContinuePlay = Qt.binding(function() { return contentView.playList.randomPlayChecked || contentView.playList.repeatPlayChecked }) + elisa.mediaPlayList.randomPlay = Qt.binding(function() { return headerBar.playerControl.shuffle }) + elisa.mediaPlayList.repeatPlay = Qt.binding(function() { return headerBar.playerControl.repeat }) + elisa.playerControl.randomOrContinuePlay = Qt.binding(function() { return headerBar.playerControl.shuffle || headerBar.playerControl.repeat}) if (persistentSettings.playListState) { elisa.mediaPlayList.persistentState = persistentSettings.playListState } if (persistentSettings.audioPlayerState) { elisa.audioControl.persistentState = persistentSettings.audioPlayerState } elisa.audioPlayer.muted = Qt.binding(function() { return headerBar.playerControl.muted }) elisa.audioPlayer.volume = Qt.binding(function() { return headerBar.playerControl.volume }) mprisloader.active = true } } diff --git a/src/trackdatahelper.cpp b/src/trackdatahelper.cpp index 8d79f018..f11c1e6f 100644 --- a/src/trackdatahelper.cpp +++ b/src/trackdatahelper.cpp @@ -1,169 +1,183 @@ /* * Copyright 2018 Alexander Stippich * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "trackdatahelper.h" TrackDataHelper::TrackDataHelper(QObject *parent) : QObject(parent) { } TrackDataHelper::~TrackDataHelper() = default; const MusicAudioTrack &TrackDataHelper::trackData() const { return *this; } void TrackDataHelper::setTrackData(const MusicAudioTrack &track) { MusicAudioTrack::operator=(track); Q_EMIT trackDataChanged(); } +QString TrackDataHelper::title() const +{ + if (MusicAudioTrack::title().isEmpty()) { + return fileName(); + } else { + return MusicAudioTrack::title(); + } +} + QString TrackDataHelper::trackNumber() const { return QString::number(MusicAudioTrack::trackNumber()); } QString TrackDataHelper::discNumber() const { return QString::number(MusicAudioTrack::discNumber()); } QString TrackDataHelper::channels() const { return QString::number(MusicAudioTrack::channels()); } QString TrackDataHelper::bitRate() const { return QString::number(MusicAudioTrack::bitRate()/1000); } QString TrackDataHelper::sampleRate() const { return QString::number(MusicAudioTrack::sampleRate()); } QString TrackDataHelper::year() const { return QString::number(MusicAudioTrack::year()); } QString TrackDataHelper::duration() const { QString result; const QTime &trackDuration = MusicAudioTrack::duration(); if (trackDuration.hour() == 0) { result = trackDuration.toString(QStringLiteral("mm:ss")); } else { result = trackDuration.toString(QStringLiteral("h:mm:ss")); } return result; } QString TrackDataHelper::resourceURI() const { return MusicAudioTrack::resourceURI().toString(); } +QString TrackDataHelper::fileName() const +{ + return MusicAudioTrack::resourceURI().fileName(); +} + bool TrackDataHelper::hasValidTrackNumber() const { return MusicAudioTrack::trackNumber() > -1; } bool TrackDataHelper::hasValidDiscNumber() const { return MusicAudioTrack::discNumber() > -1; } bool TrackDataHelper::hasValidChannels() const { return MusicAudioTrack::channels() > -1; } bool TrackDataHelper::hasValidBitRate() const { return MusicAudioTrack::bitRate() > -1; } bool TrackDataHelper::hasValidSampleRate() const { return MusicAudioTrack::sampleRate() > -1; } bool TrackDataHelper::hasValidYear() const { return MusicAudioTrack::year() != 0; } bool TrackDataHelper::hasValidRating() const { return MusicAudioTrack::rating() > -1; } bool TrackDataHelper::hasValidTitle() const { return !MusicAudioTrack::title().isEmpty(); } bool TrackDataHelper::hasValidArtist() const { return !MusicAudioTrack::artist().isEmpty(); } bool TrackDataHelper::hasValidAlbumArtist() const { return !MusicAudioTrack::albumArtist().isEmpty(); } bool TrackDataHelper::hasValidAlbumName() const { return !MusicAudioTrack::albumName().isEmpty(); } bool TrackDataHelper::hasValidGenre() const { return !MusicAudioTrack::genre().isEmpty(); } bool TrackDataHelper::hasValidComposer() const { return !MusicAudioTrack::composer().isEmpty(); } bool TrackDataHelper::hasValidLyricist() const { return !MusicAudioTrack::lyricist().isEmpty(); } bool TrackDataHelper::hasValidComment() const { return !MusicAudioTrack::comment().isEmpty(); } bool TrackDataHelper::hasValidAlbumCover() const { return !MusicAudioTrack::albumCover().isEmpty(); } #include "moc_trackdatahelper.cpp" diff --git a/src/trackdatahelper.h b/src/trackdatahelper.h index 24d497d3..b58bb4fe 100644 --- a/src/trackdatahelper.h +++ b/src/trackdatahelper.h @@ -1,181 +1,189 @@ /* * Copyright 2018 Alexander Stippich * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef TRACKDATAHELPER_H #define TRACKDATAHELPER_H #include "elisaLib_export.h" #include #include "musicaudiotrack.h" class ELISALIB_EXPORT TrackDataHelper : public QObject, public MusicAudioTrack { Q_OBJECT Q_PROPERTY(MusicAudioTrack trackData READ trackData WRITE setTrackData NOTIFY trackDataChanged) Q_PROPERTY(QString title READ title NOTIFY trackDataChanged) Q_PROPERTY(QString artist READ artist NOTIFY trackDataChanged) Q_PROPERTY(QString albumName READ albumName NOTIFY trackDataChanged) Q_PROPERTY(QString albumArtist READ albumArtist NOTIFY trackDataChanged) Q_PROPERTY(QString genre READ genre NOTIFY trackDataChanged) Q_PROPERTY(QString composer READ composer NOTIFY trackDataChanged) Q_PROPERTY(QString lyricist READ lyricist NOTIFY trackDataChanged) Q_PROPERTY(QString comment READ comment NOTIFY trackDataChanged) Q_PROPERTY(QString year READ year NOTIFY trackDataChanged) Q_PROPERTY(QString trackNumber READ trackNumber NOTIFY trackDataChanged) Q_PROPERTY(QString discNumber READ discNumber NOTIFY trackDataChanged) Q_PROPERTY(QString channels READ channels NOTIFY trackDataChanged) Q_PROPERTY(QString bitRate READ bitRate NOTIFY trackDataChanged) Q_PROPERTY(QString sampleRate READ sampleRate NOTIFY trackDataChanged) Q_PROPERTY(QString resourceURI READ resourceURI NOTIFY trackDataChanged) + Q_PROPERTY(QString fileName + READ fileName + NOTIFY trackDataChanged) + Q_PROPERTY(QString duration READ duration NOTIFY trackDataChanged) Q_PROPERTY(int rating READ rating NOTIFY trackDataChanged) Q_PROPERTY(QUrl albumCover READ albumCover NOTIFY trackDataChanged) Q_PROPERTY(qulonglong databaseId READ databaseId NOTIFY trackDataChanged) public: explicit TrackDataHelper(QObject *parent = nullptr); ~TrackDataHelper() override; + QString title() const; + QString trackNumber() const; QString discNumber() const; QString channels() const; QString bitRate() const; QString sampleRate() const; QString year() const; QString duration() const; QString resourceURI() const; + QString fileName() const; + const MusicAudioTrack& trackData() const; void setTrackData(const MusicAudioTrack &track); Q_SIGNALS: void trackDataChanged(); public: Q_INVOKABLE bool hasValidTitle() const; Q_INVOKABLE bool hasValidArtist() const; Q_INVOKABLE bool hasValidAlbumName() const; Q_INVOKABLE bool hasValidAlbumArtist() const; Q_INVOKABLE bool hasValidGenre() const; Q_INVOKABLE bool hasValidComposer() const; Q_INVOKABLE bool hasValidLyricist() const; Q_INVOKABLE bool hasValidComment() const; Q_INVOKABLE bool hasValidTrackNumber() const; Q_INVOKABLE bool hasValidDiscNumber() const; Q_INVOKABLE bool hasValidChannels() const; Q_INVOKABLE bool hasValidRating() const; Q_INVOKABLE bool hasValidBitRate() const; Q_INVOKABLE bool hasValidSampleRate() const; Q_INVOKABLE bool hasValidYear() const; Q_INVOKABLE bool hasValidAlbumCover() const; }; #endif // TRACKDATAHELPER_H