[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: [elisa] /: introduce elisa_local_file kcm module to configure path for elisa music indexer
From: Matthieu Gallien <null () kde ! org>
Date: 2017-07-31 21:34:17
Message-ID: E1dcIKP-0005Nl-8y () code ! kde ! org
[Download RAW message or body]
Git commit f47e0047fde2ee1cbcd34a24547d7ab70e67264a by Matthieu Gallien.
Committed on 31/07/2017 at 21:33.
Pushed by mgallien into branch 'master'.
introduce elisa_local_file kcm module to configure path for elisa music indexer
allow to configure the paths searched by elisa local music files indexer
M +2 -2 CMakeLists.txt
M +38 -8 autotests/CMakeLists.txt
M +0 -4 config-upnp-qt.h.cmake
M +10 -14 src/CMakeLists.txt
M +10 -1 src/MediaServer.qml
M +18 -6 src/abstractfile/abstractfilelistener.cpp
M +10 -2 src/abstractfile/abstractfilelistener.h
M +5 -0 src/abstractfile/abstractfilelisting.cpp
M +6 -2 src/abstractfile/abstractfilelisting.h
M +5 -0 src/allalbumsmodel.cpp
M +2 -0 src/allalbumsmodel.h
M +4 -1 src/baloo/baloolistener.cpp
M +2 -0 src/baloo/localbaloofilelisting.cpp
M +164 -57 src/databaseinterface.cpp
M +4 -0 src/databaseinterface.h
M +19 -7 src/elisaapplication.cpp
M +6 -0 src/elisaapplication.h
M +14 -1 src/file/filelistener.cpp
M +5 -2 src/file/filelistener.h
M +8 -7 src/file/localfilelisting.cpp
M +2 -0 src/file/localfilelisting.h
A +31 -0 src/localFileConfiguration/CMakeLists.txt
A +13 -0 src/localFileConfiguration/kcm_elisa_local_file.desktop
A +117 -0 src/localFileConfiguration/localfileconfiguration.cpp [License: \
LGPL (v3+)] C +23 -22 src/localFileConfiguration/localfileconfiguration.h [from: \
src/file/localfilelisting.h - 057% similarity] A +154 -0 \
src/localFileConfiguration/package/contents/ui/main.qml [License: LGPL (v3+)] A \
+16 -0 src/localFileConfiguration/package/metadata.desktop M +108 -28 \
src/musiclistenersmanager.cpp M +8 -0 src/musiclistenersmanager.h
M +7 -0 src/upnpControl.cpp
https://commits.kde.org/elisa/f47e0047fde2ee1cbcd34a24547d7ab70e67264a
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 523ff0c..c8ce6d6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -27,10 +27,10 @@ find_package(KF5Baloo ${REQUIRED_KF5_VERSION} CONFIG QUIET)
find_package(KF5FileMetaData ${REQUIRED_KF5_VERSION} CONFIG QUIET)
find_package(KF5DocTools ${REQUIRED_KF5_VERSION} CONFIG QUIET)
find_package(KF5XmlGui ${REQUIRED_KF5_VERSION} CONFIG QUIET)
-find_package(KF5ConfigWidgets ${REQUIRED_KF5_VERSION} CONFIG QUIET)
-find_package(KF5Config ${REQUIRED_KF5_VERSION} CONFIG QUIET)
+find_package(KF5Config ${REQUIRED_KF5_VERSION} CONFIG REQUIRED QUIET)
find_package(KF5Crash ${REQUIRED_KF5_VERSION} CONFIG QUIET)
find_package(KF5DBusAddons ${REQUIRED_KF5_VERSION} CONFIG QUIET)
+find_package(KF5KCMUtils ${REQUIRED_KF5_VERSION} CONFIG REQUIRED QUIET)
find_package(UPNPQT CONFIG QUIET)
set_package_properties(UPNPQT PROPERTIES
diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt
index 453c6cb..d41e359 100644
--- a/autotests/CMakeLists.txt
+++ b/autotests/CMakeLists.txt
@@ -1,6 +1,7 @@
enable_testing()
include_directories(${elisa_BINARY_DIR})
+include_directories(${elisa_BINARY_DIR}/src)
set(databaseInterfaceTest_SOURCES
../src/databaseinterface.cpp
@@ -60,9 +61,15 @@ if (KF5FileMetaData_FOUND)
)
endif()
+kconfig_add_kcfg_files(playListControlerTest_SOURCES ../src/elisa_settings.kcfgc )
+set(playListControlerTest_SOURCES
+ ${playListControlerTest_SOURCES}
+ ../src/elisa_core.kcfg
+)
+
add_executable(playListControlerTest ${playListControlerTest_SOURCES})
-target_link_libraries(playListControlerTest Qt5::Test Qt5::Core Qt5::Sql KF5::I18n)
+target_link_libraries(playListControlerTest Qt5::Test Qt5::Core Qt5::Sql KF5::I18n \
KF5::ConfigCore KF5::ConfigGui) if (KF5Baloo_FOUND)
target_link_libraries(playListControlerTest KF5::Baloo Qt5::DBus)
endif()
@@ -121,9 +128,15 @@ if (KF5FileMetaData_FOUND)
)
endif()
+kconfig_add_kcfg_files(managemediaplayercontrolTest_SOURCES \
../src/elisa_settings.kcfgc ) +set(managemediaplayercontrolTest_SOURCES
+ ${managemediaplayercontrolTest_SOURCES}
+ ../src/elisa_core.kcfg
+)
+
add_executable(managemediaplayercontrolTest ${managemediaplayercontrolTest_SOURCES})
-target_link_libraries(managemediaplayercontrolTest Qt5::Test Qt5::Core Qt5::Sql \
KF5::I18n) +target_link_libraries(managemediaplayercontrolTest Qt5::Test Qt5::Core \
Qt5::Sql KF5::I18n KF5::ConfigCore KF5::ConfigGui) if (KF5Baloo_FOUND)
target_link_libraries(managemediaplayercontrolTest KF5::Baloo Qt5::DBus)
endif()
@@ -183,9 +196,15 @@ if (KF5FileMetaData_FOUND)
)
endif()
+kconfig_add_kcfg_files(manageheaderbarTest_SOURCES ../src/elisa_settings.kcfgc )
+set(manageheaderbarTest_SOURCES
+ ${manageheaderbarTest_SOURCES}
+ ../src/elisa_core.kcfg
+)
+
add_executable(manageheaderbarTest ${manageheaderbarTest_SOURCES})
-target_link_libraries(manageheaderbarTest Qt5::Test Qt5::Core Qt5::Sql Qt5::Gui \
KF5::I18n) +target_link_libraries(manageheaderbarTest Qt5::Test Qt5::Core Qt5::Sql \
Qt5::Gui KF5::I18n KF5::ConfigCore KF5::ConfigGui) if (KF5Baloo_FOUND)
target_link_libraries(manageheaderbarTest KF5::Baloo Qt5::DBus)
endif()
@@ -253,9 +272,15 @@ if (KF5FileMetaData_FOUND)
)
endif()
+kconfig_add_kcfg_files(mediaplaylistTest_SOURCES ../src/elisa_settings.kcfgc )
+set(mediaplaylistTest_SOURCES
+ ${mediaplaylistTest_SOURCES}
+ ../src/elisa_core.kcfg
+)
+
add_executable(mediaplaylistTest ${mediaplaylistTest_SOURCES})
-target_link_libraries(mediaplaylistTest Qt5::Test Qt5::Core Qt5::Sql Qt5::Gui \
KF5::I18n) +target_link_libraries(mediaplaylistTest Qt5::Test Qt5::Core Qt5::Sql \
Qt5::Gui KF5::I18n KF5::ConfigCore KF5::ConfigGui) if (KF5Baloo_FOUND)
target_link_libraries(mediaplaylistTest KF5::Baloo Qt5::DBus)
endif()
@@ -333,11 +358,16 @@ if (KF5FileMetaData_FOUND)
localfilelistingtest.cpp
)
+ kconfig_add_kcfg_files(localfilelistingtest_SOURCES ../src/elisa_settings.kcfgc \
) + set(localfilelistingtest_SOURCES
+ ${localfilelistingtest_SOURCES}
+ ../src/elisa_core.kcfg
+ )
+
add_executable(localfilelistingtest ${localfilelistingtest_SOURCES})
- target_link_libraries(localfilelistingtest Qt5::Test Qt5::Core Qt5::Sql \
KF5::I18n)
- if (KF5FileMetaData_FOUND)
- target_link_libraries(localfilelistingtest KF5::FileMetaData)
- endif()
+ target_link_libraries(localfilelistingtest Qt5::Test Qt5::Core Qt5::Sql \
KF5::I18n KF5::ConfigCore KF5::ConfigGui KF5::FileMetaData) +
target_include_directories(localfilelistingtest PRIVATE ${CMAKE_SOURCE_DIR}/src)
add_test(localfilelistingtest localfilelistingtest)
+
endif()
diff --git a/config-upnp-qt.h.cmake b/config-upnp-qt.h.cmake
index 6628774..80316c5 100644
--- a/config-upnp-qt.h.cmake
+++ b/config-upnp-qt.h.cmake
@@ -8,10 +8,6 @@
#cmakedefine01 KF5XmlGui_FOUND
-#cmakedefine01 KF5ConfigWidgets_FOUND
-
-#cmakedefine01 KF5Config_FOUND
-
#cmakedefine01 KF5Crash_FOUND
#cmakedefine01 KF5FileMetaData_FOUND
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 6f21bfd..aec7d54 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -101,6 +101,12 @@ if (Qt5Quick_FOUND AND Qt5Widgets_FOUND)
)
endif()
+ kconfig_add_kcfg_files(elisa_SOURCES elisa_settings.kcfgc)
+ set(elisa_SOURCES
+ ${elisa_SOURCES}
+ elisa_core.kcfg
+ )
+
qt5_add_resources(elisa_SOURCES upnpControl.qrc)
add_executable(elisa ${elisa_SOURCES})
@@ -119,6 +125,8 @@ if (Qt5Quick_FOUND AND Qt5Widgets_FOUND)
Qt5::Xml
Qt5::Sql
KF5::I18n
+ KF5::ConfigCore
+ KF5::KCMUtils
)
if (Qt5DBus_FOUND)
@@ -170,20 +178,6 @@ if (Qt5Quick_FOUND AND Qt5Widgets_FOUND)
)
endif()
- if (KF5ConfigWidgets_FOUND)
- target_link_libraries(elisa
- LINK_PRIVATE
- KF5::ConfigWidgets
- )
- endif()
-
- if (KF5Config_FOUND)
- target_link_libraries(elisa
- LINK_PRIVATE
- KF5::ConfigCore
- )
- endif()
-
if (KF5Crash_FOUND)
target_link_libraries(elisa
LINK_PRIVATE
@@ -208,3 +202,5 @@ if (Qt5Quick_FOUND AND Qt5Widgets_FOUND)
endif()
install(TARGETS elisa ${INSTALL_TARGETS_DEFAULT_ARGS})
+
+add_subdirectory(localFileConfiguration)
diff --git a/src/MediaServer.qml b/src/MediaServer.qml
index b7caf65..7eb98f0 100644
--- a/src/MediaServer.qml
+++ b/src/MediaServer.qml
@@ -46,6 +46,7 @@ ApplicationWindow {
property var reportBugAction: elisa.action("help_report_bug")
property var aboutAppAction: elisa.action("help_about_app")
property var configureShortcutsAction: \
elisa.action("options_configure_keybinding") + property var configureAction: \
elisa.action("options_configure")
SystemPalette {
id: myPalette
@@ -328,6 +329,14 @@ ApplicationWindow {
}
MenuItem {
+ text: configureAction.text
+ shortcut: configureAction.shortcut
+ iconName: 'configure'
+ onTriggered: configureAction.trigger()
+ visible: configureAction.text !== ""
+ }
+
+ MenuItem {
text: configureShortcutsAction.text
shortcut: configureShortcutsAction.shortcut
iconName: elisa.iconName(configureShortcutsAction.icon)
@@ -336,7 +345,7 @@ ApplicationWindow {
}
MenuSeparator {
- visible: configureShortcutsAction.text !== ""
+ visible: configureAction.text !== "" || configureShortcutsAction.text \
!== "" }
MenuItem {
diff --git a/src/abstractfile/abstractfilelistener.cpp \
b/src/abstractfile/abstractfilelistener.cpp index a4cc4b5..132c5ef 100644
--- a/src/abstractfile/abstractfilelistener.cpp
+++ b/src/abstractfile/abstractfilelistener.cpp
@@ -28,25 +28,23 @@ class AbstractFileListenerPrivate
{
public:
- explicit AbstractFileListenerPrivate(AbstractFileListing *aFileListing) : \
mFileListing(aFileListing) + explicit AbstractFileListenerPrivate()
{
}
QThread mFileQueryThread;
- AbstractFileListing *mFileListing;
+ AbstractFileListing *mFileListing = nullptr;
};
-AbstractFileListener::AbstractFileListener(AbstractFileListing *aFileListing, \
QObject *parent) : QObject(parent), d(new AbstractFileListenerPrivate(aFileListing)) \
+AbstractFileListener::AbstractFileListener(QObject *parent) + : QObject(parent), \
d(new AbstractFileListenerPrivate) {
- d->mFileQueryThread.start();
- d->mFileListing->moveToThread(&d->mFileQueryThread);
}
AbstractFileListener::~AbstractFileListener()
{
- delete d->mFileListing;
delete d;
}
@@ -78,10 +76,24 @@ void AbstractFileListener::applicationAboutToQuit()
d->mFileQueryThread.wait();
}
+void AbstractFileListener::setFileListing(AbstractFileListing *fileIndexer)
+{
+ d->mFileListing = fileIndexer;
+ d->mFileQueryThread.start();
+ d->mFileListing->moveToThread(&d->mFileQueryThread);
+ connect(fileIndexer, &AbstractFileListing::indexingFinished,
+ this, &AbstractFileListener::indexingFinished);
+}
+
AbstractFileListing *AbstractFileListener::fileListing() const
{
return d->mFileListing;
}
+void AbstractFileListener::performInitialScan()
+{
+ d->mFileListing->refreshContent();
+}
+
#include "moc_abstractfilelistener.cpp"
diff --git a/src/abstractfile/abstractfilelistener.h \
b/src/abstractfile/abstractfilelistener.h index d033084..aa34a24 100644
--- a/src/abstractfile/abstractfilelistener.h
+++ b/src/abstractfile/abstractfilelistener.h
@@ -39,12 +39,14 @@ class AbstractFileListener : public QObject
NOTIFY databaseInterfaceChanged)
public:
- explicit AbstractFileListener(AbstractFileListing *aFileListing, QObject *parent \
= 0); + explicit AbstractFileListener(QObject *parent = 0);
virtual ~AbstractFileListener();
DatabaseInterface* databaseInterface() const;
+ AbstractFileListing* fileListing() const;
+
Q_SIGNALS:
void databaseInterfaceChanged();
@@ -53,15 +55,21 @@ Q_SIGNALS:
void newTrackFile(const MusicAudioTrack &newTrack);
+ void indexingFinished();
+
+ void configurationChanged();
+
public Q_SLOTS:
+ void performInitialScan();
+
void setDatabaseInterface(DatabaseInterface* databaseInterface);
void applicationAboutToQuit();
protected:
- AbstractFileListing* fileListing() const;
+ void setFileListing(AbstractFileListing *fileIndexer);
private:
diff --git a/src/abstractfile/abstractfilelisting.cpp \
b/src/abstractfile/abstractfilelisting.cpp index e0ee14f..d768edc 100644
--- a/src/abstractfile/abstractfilelisting.cpp
+++ b/src/abstractfile/abstractfilelisting.cpp
@@ -428,5 +428,10 @@ void AbstractFileListing::removeFile(const QUrl \
&oneRemovedTrack, QList<QUrl> &a }
}
+void AbstractFileListing::setSourceName(const QString &name)
+{
+ d->mSourceName = name;
+}
+
#include "moc_abstractfilelisting.cpp"
diff --git a/src/abstractfile/abstractfilelisting.h \
b/src/abstractfile/abstractfilelisting.h index 9ba4344..4b2561a 100644
--- a/src/abstractfile/abstractfilelisting.h
+++ b/src/abstractfile/abstractfilelisting.h
@@ -44,6 +44,8 @@ public:
virtual void applicationAboutToQuit();
+ const QString &sourceName() const;
+
Q_SIGNALS:
void tracksList(const QList<MusicAudioTrack> &tracks, const QHash<QString, QUrl> \
&covers, const QString &musicSource); @@ -52,6 +54,8 @@ Q_SIGNALS:
void modifyTracksList(const QList<MusicAudioTrack> &modifiedTracks, const \
QHash<QString, QUrl> &covers);
+ void indexingFinished();
+
public Q_SLOTS:
void refreshContent();
@@ -76,8 +80,6 @@ protected:
void scanDirectory(QList<MusicAudioTrack> &newFiles, const QUrl &path);
- const QString &sourceName() const;
-
virtual MusicAudioTrack scanOneFile(const QUrl &scanFile);
void watchPath(const QString &pathName);
@@ -96,6 +98,8 @@ protected:
void removeFile(const QUrl &oneRemovedTrack, QList<QUrl> &allRemovedFiles);
+ void setSourceName(const QString &name);
+
private:
std::unique_ptr<AbstractFileListingPrivate> d;
diff --git a/src/allalbumsmodel.cpp b/src/allalbumsmodel.cpp
index 39e4fbc..fc28181 100644
--- a/src/allalbumsmodel.cpp
+++ b/src/allalbumsmodel.cpp
@@ -51,6 +51,11 @@ AllAlbumsModel::~AllAlbumsModel()
delete d;
}
+int AllAlbumsModel::albumCount() const
+{
+ return rowCount({});
+}
+
int AllAlbumsModel::rowCount(const QModelIndex &parent) const
{
auto albumCount = 0;
diff --git a/src/allalbumsmodel.h b/src/allalbumsmodel.h
index 62f2a42..c29e13b 100644
--- a/src/allalbumsmodel.h
+++ b/src/allalbumsmodel.h
@@ -58,6 +58,8 @@ public:
virtual ~AllAlbumsModel();
+ Q_INVOKABLE int albumCount() const;
+
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QHash<int, QByteArray> roleNames() const override;
diff --git a/src/baloo/baloolistener.cpp b/src/baloo/baloolistener.cpp
index be8d878..4d54bdd 100644
--- a/src/baloo/baloolistener.cpp
+++ b/src/baloo/baloolistener.cpp
@@ -28,10 +28,13 @@ class BalooListenerPrivate
{
public:
+ LocalBalooFileListing mBalooFileIndexer;
+
};
-BalooListener::BalooListener(QObject *parent) : AbstractFileListener(new \
LocalBalooFileListing, parent), d(new BalooListenerPrivate) \
+BalooListener::BalooListener(QObject *parent) : AbstractFileListener(parent), d(new \
BalooListenerPrivate) {
+ setFileListing(&d->mBalooFileIndexer);
}
BalooListener::~BalooListener()
diff --git a/src/baloo/localbaloofilelisting.cpp \
b/src/baloo/localbaloofilelisting.cpp index 9288238..a93d429 100644
--- a/src/baloo/localbaloofilelisting.cpp
+++ b/src/baloo/localbaloofilelisting.cpp
@@ -126,6 +126,8 @@ void LocalBalooFileListing::triggerRefreshOfContent()
if (!newFiles.isEmpty() && d->mStopRequest == 0) {
emitNewFiles(newFiles);
}
+
+ Q_EMIT indexingFinished();
}
MusicAudioTrack LocalBalooFileListing::scanOneFile(const QUrl &scanFile)
diff --git a/src/databaseinterface.cpp b/src/databaseinterface.cpp
index ab19e50..45f738f 100644
--- a/src/databaseinterface.cpp
+++ b/src/databaseinterface.cpp
@@ -57,7 +57,8 @@ public:
mInitialUpdateTracksValidity(mTracksDatabase), \
mUpdateTrackMapping(mTracksDatabase),
mSelectTracksMapping(mTracksDatabase), \
mSelectTracksMappingPriority(mTracksDatabase),
mUpdateAlbumArtUriFromAlbumIdQuery(mTracksDatabase), \
mUpdateAlbumArtistFromAlbumIdQuery(mTracksDatabase),
- mInsertAlbumWithoutArtistQuery(mTracksDatabase), \
mSelectTracksMappingPriorityByTrackId(mTracksDatabase) + \
mInsertAlbumWithoutArtistQuery(mTracksDatabase), \
mSelectTracksMappingPriorityByTrackId(mTracksDatabase), + \
mSelectAllTrackFilesFromSourceQuery(mTracksDatabase) {
}
@@ -137,6 +138,8 @@ public:
QSqlQuery mSelectTracksMappingPriorityByTrackId;
+ QSqlQuery mSelectAllTrackFilesFromSourceQuery;
+
qulonglong mAlbumId = 1;
qulonglong mArtistId = 1;
@@ -273,6 +276,13 @@ QList<MusicAudioTrack> \
DatabaseInterface::allTracksFromSource(const QString &mus
qDebug() << "DatabaseInterface::allAlbums" << \
d->mSelectAllTracksFromSourceQuery.boundValues();
qDebug() << "DatabaseInterface::allAlbums" << \
d->mSelectAllTracksFromSourceQuery.lastError();
+ d->mSelectAllTracksFromSourceQuery.finish();
+
+ transactionResult = finishTransaction();
+ if (!transactionResult) {
+ return result;
+ }
+
return result;
}
@@ -586,6 +596,81 @@ void DatabaseInterface::applicationAboutToQuit()
d->mStopRequest = 1;
}
+void DatabaseInterface::removeAllTracksFromSource(const QString &sourceName)
+{
+ auto transactionResult = startTransaction();
+ if (!transactionResult) {
+ return;
+ }
+
+ d->mSelectMusicSource.bindValue(QStringLiteral(":name"), sourceName);
+
+ auto queryResult = d->mSelectMusicSource.exec();
+
+ if (!queryResult || !d->mSelectMusicSource.isSelect() || \
!d->mSelectMusicSource.isActive()) { + qDebug() << \
"DatabaseInterface::insertMusicSource" << d->mSelectMusicSource.lastQuery(); + \
qDebug() << "DatabaseInterface::insertMusicSource" << \
d->mSelectMusicSource.boundValues(); + qDebug() << \
"DatabaseInterface::insertMusicSource" << d->mSelectMusicSource.lastError(); +
+ d->mSelectMusicSource.finish();
+
+ transactionResult = finishTransaction();
+ if (!transactionResult) {
+ return;
+ }
+
+ return;
+ }
+
+ if (!d->mSelectMusicSource.next()) {
+ transactionResult = finishTransaction();
+ if (!transactionResult) {
+ return;
+ }
+
+ return;
+ }
+
+ qulonglong sourceId = d->mSelectMusicSource.record().value(0).toULongLong();
+
+ d->mSelectMusicSource.finish();
+
+ d->mSelectAllTrackFilesFromSourceQuery.bindValue(QStringLiteral(":discoverId"), \
sourceId); +
+ queryResult = d->mSelectAllTrackFilesFromSourceQuery.exec();
+
+ if (!queryResult || !d->mSelectAllTrackFilesFromSourceQuery.isSelect() || \
!d->mSelectAllTrackFilesFromSourceQuery.isActive()) { + qDebug() << \
"DatabaseInterface::insertMusicSource" << \
d->mSelectAllTrackFilesFromSourceQuery.lastQuery(); + qDebug() << \
"DatabaseInterface::insertMusicSource" << \
d->mSelectAllTrackFilesFromSourceQuery.boundValues(); + qDebug() << \
"DatabaseInterface::insertMusicSource" << \
d->mSelectAllTrackFilesFromSourceQuery.lastError(); +
+ d->mSelectAllTrackFilesFromSourceQuery.finish();
+
+ transactionResult = finishTransaction();
+ if (!transactionResult) {
+ return;
+ }
+
+ return;
+ }
+
+ QList<QUrl> allFileNames;
+
+ while(d->mSelectAllTrackFilesFromSourceQuery.next()) {
+ auto fileName = \
d->mSelectAllTrackFilesFromSourceQuery.record().value(0).toUrl(); + \
allFileNames.push_back(fileName); + }
+
+ d->mSelectAllTrackFilesFromSourceQuery.finish();
+
+ internalRemoveTracksList(allFileNames);
+
+ transactionResult = finishTransaction();
+ if (!transactionResult) {
+ return;
+ }
+}
+
void DatabaseInterface::insertTracksList(const QList<MusicAudioTrack> &tracks, const \
QHash<QString, QUrl> &covers, const QString &musicSource) {
if (d->mStopRequest == 1) {
@@ -668,62 +753,7 @@ void DatabaseInterface::removeTracksList(const QList<QUrl> \
&removedTracks) return;
}
- QList<MusicAudioTrack> willRemoveTrack;
-
- for (const auto &removedTrackFileName : removedTracks) {
- d->mSelectTrackFromFilePathQuery.bindValue(QStringLiteral(":filePath"), \
removedTrackFileName.toString());
-
- auto result = d->mSelectTrackFromFilePathQuery.exec();
-
- if (!result || !d->mSelectTrackFromFilePathQuery.isSelect() || \
!d->mSelectTrackFromFilePathQuery.isActive()) {
- qDebug() << "DatabaseInterface::removeTracksList" << \
d->mSelectTrackFromFilePathQuery.lastQuery();
- qDebug() << "DatabaseInterface::removeTracksList" << \
d->mSelectTrackFromFilePathQuery.boundValues();
- qDebug() << "DatabaseInterface::removeTracksList" << \
d->mSelectTrackFromFilePathQuery.lastError();
-
- continue;
- }
-
- while (d->mSelectTrackFromFilePathQuery.next()) {
- const auto ¤tRecord = d->mSelectTrackFromFilePathQuery.record();
-
- willRemoveTrack.push_back(buildTrackFromDatabaseRecord(currentRecord));
- }
-
- d->mSelectTrackFromFilePathQuery.finish();
- }
-
- QSet<qulonglong> modifiedAlbums;
-
- for (const auto &oneRemovedTrack : willRemoveTrack) {
- removeTrackInDatabase(oneRemovedTrack.databaseId());
- Q_EMIT trackRemoved(oneRemovedTrack.databaseId());
-
- const auto &modifiedAlbumId = \
internalAlbumIdFromTitle(oneRemovedTrack.albumName());
- const auto &allArtistTracks = \
internalTracksFromAuthor(oneRemovedTrack.artist());
- const auto &removedArtistId = \
internalArtistIdFromName(oneRemovedTrack.artist());
- const auto &removedArtist = internalArtistFromId(removedArtistId);
-
- if (updateTracksCount(modifiedAlbumId)) {
- modifiedAlbums.insert(modifiedAlbumId);
- }
- updateAlbumFromId(modifiedAlbumId, oneRemovedTrack.albumCover(), \
oneRemovedTrack);
-
- if (allArtistTracks.isEmpty()) {
- removeArtistInDatabase(removedArtistId);
- Q_EMIT artistRemoved(removedArtist);
- }
- }
-
- for (auto modifiedAlbumId : modifiedAlbums) {
- auto modifiedAlbum = internalAlbumFromId(modifiedAlbumId);
-
- if (modifiedAlbum.isValid() && !modifiedAlbum.isEmpty()) {
- Q_EMIT albumModified(modifiedAlbum, modifiedAlbumId);
- } else {
- removeAlbumInDatabase(modifiedAlbum.databaseId());
- Q_EMIT albumRemoved(modifiedAlbum, modifiedAlbumId);
- }
- }
+ internalRemoveTracksList(removedTracks);
transactionResult = finishTransaction();
if (!transactionResult) {
@@ -1400,6 +1430,21 @@ void DatabaseInterface::initRequest()
}
{
+ auto selectAllTrackFilesFromSourceQueryText = QStringLiteral("SELECT "
+ \
"tracksMapping.`FileName` " + \
"FROM " + \
"`TracksMapping` tracksMapping " + \
"WHERE " + \
"tracksMapping.`DiscoverID` = :discoverId"); +
+ auto result = \
d->mSelectAllTrackFilesFromSourceQuery.prepare(selectAllTrackFilesFromSourceQueryText);
+
+ if (!result) {
+ qDebug() << "DatabaseInterface::initRequest" << \
d->mSelectAllTrackFilesFromSourceQuery.lastError(); + }
+ }
+
+ {
auto insertMusicSourceQueryText = QStringLiteral("INSERT OR IGNORE INTO \
`DiscoverSource` (`ID`, `Name`) "
"VALUES (:discoverId, :name)");
@@ -2052,6 +2097,68 @@ MusicAudioTrack \
DatabaseInterface::buildTrackFromDatabaseRecord(const QSqlRecord return result;
}
+void DatabaseInterface::internalRemoveTracksList(const QList<QUrl> &removedTracks)
+{
+ QList<MusicAudioTrack> willRemoveTrack;
+
+ qDebug() << "DatabaseInterface::internalRemoveTracksList" << removedTracks;
+
+ for (const auto &removedTrackFileName : removedTracks) {
+ d->mSelectTrackFromFilePathQuery.bindValue(QStringLiteral(":filePath"), \
removedTrackFileName.toString()); +
+ auto result = d->mSelectTrackFromFilePathQuery.exec();
+
+ if (!result || !d->mSelectTrackFromFilePathQuery.isSelect() || \
!d->mSelectTrackFromFilePathQuery.isActive()) { + qDebug() << \
"DatabaseInterface::removeTracksList" << \
d->mSelectTrackFromFilePathQuery.lastQuery(); + qDebug() << \
"DatabaseInterface::removeTracksList" << \
d->mSelectTrackFromFilePathQuery.boundValues(); + qDebug() << \
"DatabaseInterface::removeTracksList" << \
d->mSelectTrackFromFilePathQuery.lastError(); +
+ continue;
+ }
+
+ while (d->mSelectTrackFromFilePathQuery.next()) {
+ const auto ¤tRecord = d->mSelectTrackFromFilePathQuery.record();
+
+ willRemoveTrack.push_back(buildTrackFromDatabaseRecord(currentRecord));
+ }
+
+ d->mSelectTrackFromFilePathQuery.finish();
+ }
+
+ QSet<qulonglong> modifiedAlbums;
+
+ for (const auto &oneRemovedTrack : willRemoveTrack) {
+ removeTrackInDatabase(oneRemovedTrack.databaseId());
+ Q_EMIT trackRemoved(oneRemovedTrack.databaseId());
+
+ const auto &modifiedAlbumId = \
internalAlbumIdFromTitle(oneRemovedTrack.albumName()); + const auto \
&allArtistTracks = internalTracksFromAuthor(oneRemovedTrack.artist()); + const \
auto &removedArtistId = internalArtistIdFromName(oneRemovedTrack.artist()); + \
const auto &removedArtist = internalArtistFromId(removedArtistId); +
+ if (updateTracksCount(modifiedAlbumId)) {
+ modifiedAlbums.insert(modifiedAlbumId);
+ }
+ updateAlbumFromId(modifiedAlbumId, oneRemovedTrack.albumCover(), \
oneRemovedTrack); +
+ if (allArtistTracks.isEmpty()) {
+ removeArtistInDatabase(removedArtistId);
+ Q_EMIT artistRemoved(removedArtist);
+ }
+ }
+
+ for (auto modifiedAlbumId : modifiedAlbums) {
+ auto modifiedAlbum = internalAlbumFromId(modifiedAlbumId);
+
+ if (modifiedAlbum.isValid() && !modifiedAlbum.isEmpty()) {
+ Q_EMIT albumModified(modifiedAlbum, modifiedAlbumId);
+ } else {
+ removeAlbumInDatabase(modifiedAlbum.databaseId());
+ Q_EMIT albumRemoved(modifiedAlbum, modifiedAlbumId);
+ }
+ }
+}
+
qulonglong DatabaseInterface::internalArtistIdFromName(const QString &name)
{
auto result = qulonglong(0);
diff --git a/src/databaseinterface.h b/src/databaseinterface.h
index cbc7947..0498a83 100644
--- a/src/databaseinterface.h
+++ b/src/databaseinterface.h
@@ -75,6 +75,8 @@ public:
void applicationAboutToQuit();
+ void removeAllTracksFromSource(const QString &sourceName);
+
Q_SIGNALS:
void artistAdded(const MusicArtist &newArtist);
@@ -169,6 +171,8 @@ private:
MusicAudioTrack buildTrackFromDatabaseRecord(const QSqlRecord &trackRecord) \
const;
+ void internalRemoveTracksList(const QList<QUrl> &removedTracks);
+
DatabaseInterfacePrivate *d;
};
diff --git a/src/elisaapplication.cpp b/src/elisaapplication.cpp
index 1725c5e..9f06881 100644
--- a/src/elisaapplication.cpp
+++ b/src/elisaapplication.cpp
@@ -20,6 +20,8 @@
#include "elisaapplication.h"
+#include "elisa_settings.h"
+
#if defined KF5XmlGui_FOUND && KF5XmlGui_FOUND
#include <KXmlGui/KAboutApplicationDialog>
#include <KXmlGui/KHelpMenu>
@@ -27,13 +29,8 @@
#include <KXmlGui/KShortcutsDialog>
#endif
-#if defined KF5ConfigWidgets_FOUND && KF5ConfigWidgets_FOUND
#include <KConfigWidgets/KStandardAction>
-#endif
-
-#if defined KF5Config_FOUND && KF5Config_FOUND
#include <KConfigCore/KAuthorized>
-#endif
#if defined KF5CoreAddons_FOUND && KF5CoreAddons_FOUND
#include <KCoreAddons/KAboutData>
@@ -55,6 +52,8 @@ ElisaApplication::ElisaApplication(QObject *parent) : \
QObject(parent) #endif
{
setupActions();
+
+ mConfigurationDialog.addModule(QStringLiteral("kcm_elisa_local_file"));
}
void ElisaApplication::setupActions()
@@ -78,8 +77,15 @@ void ElisaApplication::setupActions()
mCollection.addAction(mAboutAppAction->objectName(), mAboutAppAction);
}
- auto mKeyBindignsAction = KStandardAction::keyBindings(this, \
&ElisaApplication::configureShortcuts, this);
- mCollection.addAction(mKeyBindignsAction->objectName(), mKeyBindignsAction);
+ if (KAuthorized::authorizeAction(QStringLiteral("options_configure"))) {
+ auto mPreferencesAction = KStandardAction::preferences(this, \
&ElisaApplication::configureElisa, this); + \
mCollection.addAction(mPreferencesAction->objectName(), mPreferencesAction); + }
+
+ if (KAuthorized::authorizeAction(QStringLiteral("options_configure_keybinding"))) \
{ + auto mKeyBindignsAction = KStandardAction::keyBindings(this, \
&ElisaApplication::configureShortcuts, this); + \
mCollection.addAction(mKeyBindignsAction->objectName(), mKeyBindignsAction); + }
mCollection.readSettings();
#endif
@@ -124,6 +130,12 @@ void ElisaApplication::configureShortcuts()
#endif
}
+void ElisaApplication::configureElisa()
+{
+ mConfigurationDialog.setModal(true);
+ mConfigurationDialog.show();
+}
+
QAction * ElisaApplication::action(const QString& name)
{
#if defined KF5XmlGui_FOUND && KF5XmlGui_FOUND
diff --git a/src/elisaapplication.h b/src/elisaapplication.h
index 46c06b2..81610ba 100644
--- a/src/elisaapplication.h
+++ b/src/elisaapplication.h
@@ -26,6 +26,8 @@
#include <KXmlGui/KActionCollection>
#endif
+#include <KCMultiDialog>
+
#include <QObject>
#include <QString>
@@ -56,12 +58,16 @@ public Q_SLOTS:
void configureShortcuts();
+ void configureElisa();
+
private:
#if defined KF5XmlGui_FOUND && KF5XmlGui_FOUND
KActionCollection mCollection;
#endif
+ KCMultiDialog mConfigurationDialog;
+
};
#endif // ELISAAPPLICATION_H
diff --git a/src/file/filelistener.cpp b/src/file/filelistener.cpp
index cabcbe2..a8ba8e3 100644
--- a/src/file/filelistener.cpp
+++ b/src/file/filelistener.cpp
@@ -28,10 +28,13 @@ class FileListenerPrivate
{
public:
+ LocalFileListing mLocalFileIndexer;
+
};
-FileListener::FileListener(QObject *parent) : AbstractFileListener(new \
LocalFileListing, parent), d(new FileListenerPrivate) \
+FileListener::FileListener(QObject *parent) : AbstractFileListener(parent), d(new \
FileListenerPrivate) {
+ setFileListing(&d->mLocalFileIndexer);
}
FileListener::~FileListener()
@@ -39,5 +42,15 @@ FileListener::~FileListener()
delete d;
}
+const LocalFileListing& FileListener::localFileIndexer() const
+{
+ return d->mLocalFileIndexer;
+}
+
+void FileListener::setRootPath(const QString &rootPath)
+{
+ d->mLocalFileIndexer.setRootPath(rootPath);
+}
+
#include "moc_filelistener.cpp"
diff --git a/src/file/filelistener.h b/src/file/filelistener.h
index c5e4fa7..47a4a31 100644
--- a/src/file/filelistener.h
+++ b/src/file/filelistener.h
@@ -27,8 +27,7 @@
#include <QString>
class FileListenerPrivate;
-class DatabaseInterface;
-class MusicAudioTrack;
+class LocalFileListing;
class FileListener : public AbstractFileListener
{
@@ -39,10 +38,14 @@ public:
virtual ~FileListener();
+ const LocalFileListing& localFileIndexer() const;
+
Q_SIGNALS:
public Q_SLOTS:
+ void setRootPath(const QString &rootPath);
+
private:
FileListenerPrivate *d = nullptr;
diff --git a/src/file/localfilelisting.cpp b/src/file/localfilelisting.cpp
index 92a7692..7553717 100644
--- a/src/file/localfilelisting.cpp
+++ b/src/file/localfilelisting.cpp
@@ -49,13 +49,6 @@ public:
LocalFileListing::LocalFileListing(QObject *parent) : \
AbstractFileListing(QStringLiteral("local"), parent), d(new LocalFileListingPrivate) \
{
- const auto &musicLocations(QStandardPaths::standardLocations(QStandardPaths::MusicLocation));
-
- if (musicLocations.isEmpty()) {
- return;
- }
-
- d->mRootPath = musicLocations.first();
}
LocalFileListing::~LocalFileListing()
@@ -75,11 +68,19 @@ void LocalFileListing::setRootPath(const QString &rootPath)
d->mRootPath = rootPath;
Q_EMIT rootPathChanged();
+
+ setSourceName(rootPath);
+}
+
+void LocalFileListing::executeInit()
+{
}
void LocalFileListing::triggerRefreshOfContent()
{
scanDirectoryTree(d->mRootPath);
+
+ Q_EMIT indexingFinished();
}
diff --git a/src/file/localfilelisting.h b/src/file/localfilelisting.h
index 0fb59cb..fe68ccd 100644
--- a/src/file/localfilelisting.h
+++ b/src/file/localfilelisting.h
@@ -56,6 +56,8 @@ public Q_SLOTS:
private:
+ void executeInit() override;
+
void triggerRefreshOfContent() override;
std::unique_ptr<LocalFileListingPrivate> d;
diff --git a/src/localFileConfiguration/CMakeLists.txt \
b/src/localFileConfiguration/CMakeLists.txt new file mode 100644
index 0000000..468cc89
--- /dev/null
+++ b/src/localFileConfiguration/CMakeLists.txt
@@ -0,0 +1,31 @@
+set(KCM_ELISA_LOCAL_FILE_SRCS
+ localfileconfiguration.cpp
+ kcm_elisa_local_file.desktop
+ package/contents/ui/main.qml
+ package/metadata.desktop
+)
+
+kconfig_add_kcfg_files(KCM_ELISA_LOCAL_FILE_SRCS ../elisa_settings.kcfgc )
+set(KCM_ELISA_LOCAL_FILE_SRCS
+ ${KCM_ELISA_LOCAL_FILE_SRCS}
+ ../elisa_core.kcfg
+)
+
+add_library(kcm_elisa_local_file MODULE ${KCM_ELISA_LOCAL_FILE_SRCS})
+
+target_link_libraries(kcm_elisa_local_file
+ KF5::ConfigCore
+ KF5::CoreAddons
+ KF5::Declarative
+ KF5::I18n
+ KF5::QuickAddons
+ KF5::ConfigWidgets
+)
+
+kcoreaddons_desktop_to_json(kcm_elisa_local_file "kcm_elisa_local_file.desktop")
+
+install(FILES kcm_elisa_local_file.desktop DESTINATION ${SERVICES_INSTALL_DIR})
+install(TARGETS kcm_elisa_local_file DESTINATION ${PLUGIN_INSTALL_DIR}/kcms)
+
+kpackage_install_package(package kcm_elisa_local_file kcms)
+
diff --git a/src/localFileConfiguration/kcm_elisa_local_file.desktop \
b/src/localFileConfiguration/kcm_elisa_local_file.desktop new file mode 100644
index 0000000..fdb3b90
--- /dev/null
+++ b/src/localFileConfiguration/kcm_elisa_local_file.desktop
@@ -0,0 +1,13 @@
+[Desktop Entry]
+Type=Service
+Icon=alarm
+Exec=kcmshell5 kcm_elisa_local_file
+
+X-KDE-Library=kcm_elisa_local_file
+X-KDE-ServiceTypes=KCModule
+X-KDE-ParentComponents=elisa
+X-KDE-PluginKeyword=kcm_elisa_local_file
+
+Name=Elisa Local Files Indexer
+Comment=A configuration tool for Elisa music player local files indexer
+X-KDE-Keywords=Elisa
diff --git a/src/localFileConfiguration/localfileconfiguration.cpp \
b/src/localFileConfiguration/localfileconfiguration.cpp new file mode 100644
index 0000000..508e78a
--- /dev/null
+++ b/src/localFileConfiguration/localfileconfiguration.cpp
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2017 Matthieu Gallien <matthieu_gallien@yahoo.fr>
+ *
+ * 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 "localfileconfiguration.h"
+
+#include "elisa_settings.h"
+
+#include <KPluginFactory>
+#include <KAboutData>
+#include <KLocalizedString>
+
+#include <QStandardPaths>
+
+K_PLUGIN_FACTORY_WITH_JSON(KCMElisaLocalFileFactory,
+ "kcm_elisa_local_file.json",
+ registerPlugin<KCMElisaLocalFile>();)
+
+KCMElisaLocalFile::KCMElisaLocalFile(QObject* parent, const QVariantList &args)
+ : ConfigModule(parent, args)
+{
+ KAboutData *about = new KAboutData(QStringLiteral("kcm_elisa_local_file"),
+ i18n("Elisa Local Files Indexer \
Configuration"), + QStringLiteral("0.1"), {}, \
KAboutLicense::LGPL_V3, + i18n("Copyright 20017 \
Matthieu Gallien <matthieu_gallien@yahoo.fr>")); +
+ about->addAuthor(i18n("Matthieu Gallien"),i18n("Author"), \
QStringLiteral("mgallien@mgallien.fr")); + setAboutData(about);
+
+ auto configurationFileName = \
QStandardPaths::writableLocation(QStandardPaths::ConfigLocation); + \
configurationFileName += QStringLiteral("/elisarc"); + \
Elisa::ElisaConfiguration::instance(configurationFileName); +
+ connect(Elisa::ElisaConfiguration::self(), \
&Elisa::ElisaConfiguration::configChanged, + this, \
&KCMElisaLocalFile::configChanged); +
+ setRootPath(Elisa::ElisaConfiguration::rootPath());
+ Elisa::ElisaConfiguration::setRootPath(mRootPath);
+ Elisa::ElisaConfiguration::self()->save();
+}
+
+KCMElisaLocalFile::~KCMElisaLocalFile()
+{
+}
+
+QStringList KCMElisaLocalFile::rootPath() const
+{
+ return mRootPath;
+}
+
+void KCMElisaLocalFile::defaults()
+{
+ setRootPath(QStandardPaths::standardLocations(QStandardPaths::MusicLocation));
+}
+
+void KCMElisaLocalFile::load()
+{
+ setRootPath(Elisa::ElisaConfiguration::rootPath());
+}
+
+void KCMElisaLocalFile::save()
+{
+ Elisa::ElisaConfiguration::setRootPath(mRootPath);
+ Elisa::ElisaConfiguration::self()->save();
+}
+
+void KCMElisaLocalFile::setRootPath(QStringList rootPath)
+{
+ if (mRootPath == rootPath) {
+ return;
+ }
+
+ mRootPath.clear();
+ for (const auto &onePath : rootPath) {
+ if (onePath.startsWith(QStringLiteral("file:///"))) {
+ mRootPath.push_back(onePath.mid(7));
+ } else if (onePath.startsWith(QStringLiteral("file:/"))) {
+ mRootPath.push_back(onePath.mid(5));
+ } else {
+ mRootPath.push_back(onePath);
+ }
+ }
+
+ if (mRootPath.isEmpty()) {
+ for (const auto &musicPath : \
QStandardPaths::standardLocations(QStandardPaths::MusicLocation)) { + \
mRootPath.push_back(musicPath); + }
+ }
+
+ Q_EMIT rootPathChanged(mRootPath);
+
+ setNeedsSave(true);
+ Q_EMIT needsSaveChanged();
+}
+
+void KCMElisaLocalFile::configChanged()
+{
+ setRootPath(Elisa::ElisaConfiguration::rootPath());
+}
+
+
+#include "localfileconfiguration.moc"
diff --git a/src/file/localfilelisting.h \
b/src/localFileConfiguration/localfileconfiguration.h similarity index 57%
copy from src/file/localfilelisting.h
copy to src/localFileConfiguration/localfileconfiguration.h
index 0fb59cb..878d26d 100644
--- a/src/file/localfilelisting.h
+++ b/src/localFileConfiguration/localfileconfiguration.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2016-2017 Matthieu Gallien <matthieu_gallien@yahoo.fr>
+ * Copyright 2017 Matthieu Gallien <matthieu_gallien@yahoo.fr>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -17,51 +17,52 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef LOCALFILELISTING_H
-#define LOCALFILELISTING_H
+#if !defined LOCALFILECONFIGURATION_H_
+#define LOCALFILECONFIGURATION_H_
-#include "../abstractfile/abstractfilelisting.h"
+#include <KQuickAddons/ConfigModule>
+#include <QStringList>
-#include <QString>
-
-#include <memory>
-
-class LocalFileListingPrivate;
-
-class LocalFileListing : public AbstractFileListing
+class KCMElisaLocalFile : public KQuickAddons::ConfigModule
{
Q_OBJECT
- Q_PROPERTY(QString rootPath
+ Q_PROPERTY(QStringList rootPath
READ rootPath
WRITE setRootPath
NOTIFY rootPathChanged)
public:
- explicit LocalFileListing(QObject *parent = 0);
+ explicit KCMElisaLocalFile(QObject *parent, const QVariantList &args);
- virtual ~LocalFileListing();
+ virtual ~KCMElisaLocalFile();
- QString rootPath() const;
+ QStringList rootPath() const;
Q_SIGNALS:
- void rootPathChanged();
+ void rootPathChanged(QStringList rootPath);
public Q_SLOTS:
- void setRootPath(const QString &rootPath);
+ void defaults() override final;
-private:
+ void load() override final;
- void triggerRefreshOfContent() override;
+ void save() override final;
- std::unique_ptr<LocalFileListingPrivate> d;
+ void setRootPath(QStringList rootPath);
-};
+private Q_SLOTS:
+ void configChanged();
+private:
+
+ QStringList mRootPath;
+
+};
-#endif // LOCALFILELISTING_H
+#endif
diff --git a/src/localFileConfiguration/package/contents/ui/main.qml \
b/src/localFileConfiguration/package/contents/ui/main.qml new file mode 100644
index 0000000..5d09733
--- /dev/null
+++ b/src/localFileConfiguration/package/contents/ui/main.qml
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2017 Matthieu Gallien <matthieu_gallien@yahoo.fr>
+ *
+ * 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 1.4
+import QtQuick.Layouts 1.3
+import QtQuick.Dialogs 1.2
+import QtQml.Models 2.3
+import org.kde.kcm 1.0
+import org.kde.plasma.core 2.0 as PlasmaCore
+
+Item {
+ //implicitWidth and implicitHeight will be used as initial size
+ //when loaded in kcmshell5
+ implicitWidth: units.gridUnit * 20
+ implicitHeight: units.gridUnit * 20
+
+ ConfigModule.buttons: ConfigModule.Help|ConfigModule.Apply
+
+ SystemPalette {
+ id: myPalette
+ colorGroup: SystemPalette.Active
+ }
+
+ Component {
+ id: highlightBar
+
+ Rectangle {
+ width: 200; height: 50
+ color: myPalette.highlight
+ }
+ }
+
+ Component {
+ id: pathDelegate
+
+ Item {
+ id: delegateItem
+
+ height: 3 * units.gridUnit
+
+ width: pathList.width
+
+ Rectangle {
+ anchors.fill: parent
+ anchors.margins: 0.1 * units.gridUnit
+
+ color: myPalette.base
+
+ MouseArea {
+ anchors.fill: parent
+
+ hoverEnabled: true
+
+ onEntered: pathList.currentIndex = \
delegateItem.DelegateModel.itemsIndex +
+ Label {
+ text: modelData
+
+ anchors.centerIn: parent
+ }
+
+ ToolButton {
+ iconName: 'list-remove'
+
+ anchors.top: parent.top
+ anchors.right: parent.right
+
+ onClicked:
+ {
+ var oldPaths = kcm.rootPath
+ oldPaths.splice(delegateItem.DelegateModel.itemsIndex, \
1) + kcm.rootPath = oldPaths
+ }
+ }
+ }
+ }
+ }
+ }
+
+ RowLayout {
+ spacing: 0
+
+ anchors.fill: parent
+
+ ScrollView {
+ flickableItem.boundsBehavior: Flickable.StopAtBounds
+
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+
+ ListView {
+ id:pathList
+
+ anchors.fill: parent
+
+ model: DelegateModel {
+ model: kcm.rootPath
+
+ delegate: pathDelegate
+ }
+
+ highlight: highlightBar
+ }
+ }
+
+ ColumnLayout {
+ Layout.fillHeight: true
+ Layout.leftMargin: 0.3 * units.gridUnit
+
+ Button {
+ text: 'Add new path'
+ onClicked: fileDialog.open()
+
+ Layout.alignment: Qt.AlignTop | Qt.AlignLeft
+
+ FileDialog {
+ id: fileDialog
+ title: "Please choose a file"
+ folder: shortcuts.home
+ selectFolder: true
+
+ visible: false
+
+ onAccepted: {
+ var oldPaths = kcm.rootPath
+ oldPaths.push(fileDialog.fileUrls)
+ kcm.rootPath = oldPaths
+ }
+ }
+ }
+
+ Item {
+ Layout.fillHeight: true
+ }
+ }
+ }
+}
diff --git a/src/localFileConfiguration/package/metadata.desktop \
b/src/localFileConfiguration/package/metadata.desktop new file mode 100644
index 0000000..7ffb54b
--- /dev/null
+++ b/src/localFileConfiguration/package/metadata.desktop
@@ -0,0 +1,16 @@
+[Desktop Entry]
+Name=Elisa
+Comment=Configure Local Files Indexer of Elisa Music Player
+Icon=elisa
+Type=Service
+X-KDE-ParentApp=
+X-KDE-PluginInfo-Author=Matthieu Gallien
+X-KDE-PluginInfo-Email=matthieu_gallien@yahoo.fr
+X-KDE-PluginInfo-License=LGPLv3
+X-KDE-PluginInfo-Name=kcm_elisa_local_file
+X-KDE-PluginInfo-Version=
+X-KDE-PluginInfo-Website=
+X-KDE-ServiceTypes=Plasma/Generic
+
+X-Plasma-MainScript=ui/main.qml
+X-Plasma-RemoteLocation=
diff --git a/src/musiclistenersmanager.cpp b/src/musiclistenersmanager.cpp
index 1f82789..69483ea 100644
--- a/src/musiclistenersmanager.cpp
+++ b/src/musiclistenersmanager.cpp
@@ -32,13 +32,19 @@
#include "databaseinterface.h"
#include "mediaplaylist.h"
#include "file/filelistener.h"
+#include "file/localfilelisting.h"
#include "trackslistener.h"
+#include "elisa_settings.h"
#include <QThread>
#include <QMutex>
#include <QStandardPaths>
#include <QDir>
#include <QCoreApplication>
+#include <QList>
+#include <QScopedPointer>
+#include <QPointer>
+#include <QFileSystemWatcher>
class MusicListenersManagerPrivate
{
@@ -51,15 +57,17 @@ public:
#endif
#if defined KF5Baloo_FOUND && KF5Baloo_FOUND
- BalooListener mBalooListener;
+ QScopedPointer<BalooListener> mBalooListener;
#endif
-#if (!defined KF5Baloo_FOUND || !KF5Baloo_FOUND) && defined KF5FileMetaData_FOUND && \
KF5FileMetaData_FOUND
- FileListener mFileListener;
+#if defined KF5FileMetaData_FOUND && KF5FileMetaData_FOUND
+ QList<QPointer<FileListener>> mFileListener;
#endif
DatabaseInterface mDatabaseInterface;
+ QFileSystemWatcher mConfigFileWatcher;
+
};
MusicListenersManager::MusicListenersManager(QObject *parent)
@@ -106,6 +114,24 @@ MusicListenersManager::MusicListenersManager(QObject *parent)
connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit,
this, &MusicListenersManager::applicationAboutToQuit);
+
+ connect(Elisa::ElisaConfiguration::self(), \
&Elisa::ElisaConfiguration::configChanged, + this, \
&MusicListenersManager::configChanged); +
+ connect(&d->mConfigFileWatcher, &QFileSystemWatcher::fileChanged,
+ this, &MusicListenersManager::configChanged);
+
+ auto initialRootPath = Elisa::ElisaConfiguration::rootPath();
+ if (initialRootPath.isEmpty()) {
+ for (const auto &musicPath : \
QStandardPaths::standardLocations(QStandardPaths::MusicLocation)) { + \
initialRootPath.push_back(musicPath); + }
+
+ Elisa::ElisaConfiguration::setRootPath(initialRootPath);
+ Elisa::ElisaConfiguration::self()->save();
+ }
+
+ d->mConfigFileWatcher.addPath(Elisa::ElisaConfiguration::self()->config()->name());
}
MusicListenersManager::~MusicListenersManager()
@@ -137,31 +163,7 @@ void MusicListenersManager::subscribeForTracks(MediaPlayList \
*client)
void MusicListenersManager::databaseReady()
{
-#if defined KF5Baloo_FOUND && KF5Baloo_FOUND
- d->mBalooListener.setDatabaseInterface(&d->mDatabaseInterface);
- d->mBalooListener.moveToThread(&d->mDatabaseThread);
- connect(this, &MusicListenersManager::applicationIsTerminating,
- &d->mBalooListener, &BalooListener::applicationAboutToQuit, \
Qt::BlockingQueuedConnection);
- connect(this, &MusicListenersManager::databaseIsReady,
- &d->mBalooListener, &BalooListener::databaseReady);
-#endif
-#if defined UPNPQT_FOUND && UPNPQT_FOUND
- d->mUpnpListener.setDatabaseInterface(&d->mDatabaseInterface);
- d->mUpnpListener.moveToThread(&d->mDatabaseThread);
- connect(this, &MusicListenersManager::applicationIsTerminating,
- &d->mUpnpListener, &UpnpListener::applicationAboutToQuit, \
Qt::BlockingQueuedConnection);
- connect(this, &MusicListenersManager::databaseIsReady,
- &d->mUpnpListener, &UpnpListener::databaseReady);
-#endif
-
-#if (!defined KF5Baloo_FOUND || !KF5Baloo_FOUND) && defined KF5FileMetaData_FOUND && \
KF5FileMetaData_FOUND
- d->mFileListener.setDatabaseInterface(&d->mDatabaseInterface);
- d->mFileListener.moveToThread(&d->mDatabaseThread);
- connect(this, &MusicListenersManager::applicationIsTerminating,
- &d->mFileListener, &FileListener::applicationAboutToQuit, \
Qt::BlockingQueuedConnection);
- connect(this, &MusicListenersManager::databaseIsReady,
- &d->mFileListener, &FileListener::databaseReady);
-#endif
+ configChanged();
Q_EMIT databaseIsReady();
}
@@ -176,5 +178,83 @@ void MusicListenersManager::applicationAboutToQuit()
d->mDatabaseThread.wait();
}
+void MusicListenersManager::showConfiguration()
+{
+}
+
+void MusicListenersManager::configChanged()
+{
+ auto currentConfiguration = Elisa::ElisaConfiguration::self();
+
+ d->mConfigFileWatcher.addPath(currentConfiguration->config()->name());
+
+ currentConfiguration->load();
+
+#if defined KF5Baloo_FOUND && KF5Baloo_FOUND
+ if (currentConfiguration->balooIndexer() && !d->mBalooListener) {
+ d->mBalooListener.reset(new BalooListener);
+ d->mBalooListener->setDatabaseInterface(&d->mDatabaseInterface);
+ d->mBalooListener->moveToThread(&d->mDatabaseThread);
+ connect(this, &MusicListenersManager::applicationIsTerminating,
+ d->mBalooListener.data(), &BalooListener::applicationAboutToQuit, \
Qt::BlockingQueuedConnection); + connect(this, \
&MusicListenersManager::databaseIsReady, + d->mBalooListener.data(), \
&BalooListener::databaseReady); + connect(d->mBalooListener.data(), \
&BalooListener::indexingFinished, + this, \
&MusicListenersManager::indexingFinished); + } else if \
(!currentConfiguration->balooIndexer() && d->mBalooListener) { + \
d->mBalooListener.reset(); + }
+#endif
+#if defined UPNPQT_FOUND && UPNPQT_FOUND
+ d->mUpnpListener.setDatabaseInterface(&d->mDatabaseInterface);
+ d->mUpnpListener.moveToThread(&d->mDatabaseThread);
+ connect(this, &MusicListenersManager::applicationIsTerminating,
+ &d->mUpnpListener, &UpnpListener::applicationAboutToQuit, \
Qt::BlockingQueuedConnection); + connect(this, \
&MusicListenersManager::databaseIsReady, + &d->mUpnpListener, \
&UpnpListener::databaseReady); +#endif
+
+#if defined KF5FileMetaData_FOUND && KF5FileMetaData_FOUND
+ if (currentConfiguration->elisaFilesIndexer())
+ {
+ const auto &allRootPaths = currentConfiguration->rootPath();
+ for (auto itFileListener = d->mFileListener.begin(); itFileListener != \
d->mFileListener.end(); ) { + const auto ¤tRootPath = \
(*itFileListener)->localFileIndexer().rootPath(); + auto itPath = \
std::find(allRootPaths.begin(), allRootPaths.end(), currentRootPath); +
+ if (itPath == allRootPaths.end()) {
+ d->mDatabaseInterface.removeAllTracksFromSource((*itFileListener)->fileListing()->sourceName());
+ itFileListener = d->mFileListener.erase(itFileListener);
+ } else {
+ ++itFileListener;
+ }
+ }
+
+ for (const auto &oneRootPath : allRootPaths) {
+ auto itPath = std::find_if(d->mFileListener.begin(), \
d->mFileListener.end(), + [&oneRootPath](auto \
value)->bool {return value->localFileIndexer().rootPath() == oneRootPath;}); + \
if (itPath == d->mFileListener.end()) { + auto newFileIndexer = new \
FileListener; +
+ newFileIndexer->setDatabaseInterface(&d->mDatabaseInterface);
+ newFileIndexer->moveToThread(&d->mDatabaseThread);
+ connect(this, &MusicListenersManager::applicationIsTerminating,
+ newFileIndexer, &FileListener::applicationAboutToQuit, \
Qt::BlockingQueuedConnection); + connect(this, \
&MusicListenersManager::databaseIsReady, + newFileIndexer, \
&FileListener::databaseReady); + connect(newFileIndexer, \
&FileListener::indexingFinished, + this, \
&MusicListenersManager::indexingFinished); +
+ newFileIndexer->setRootPath(oneRootPath);
+
+ d->mFileListener.push_back({newFileIndexer});
+
+ newFileIndexer->performInitialScan();
+ }
+ }
+ }
+#endif
+}
+
#include "moc_musiclistenersmanager.cpp"
diff --git a/src/musiclistenersmanager.h b/src/musiclistenersmanager.h
index 668f770..796ba45 100644
--- a/src/musiclistenersmanager.h
+++ b/src/musiclistenersmanager.h
@@ -77,12 +77,20 @@ Q_SIGNALS:
void databaseIsReady();
+ void indexingFinished();
+
public Q_SLOTS:
void databaseReady();
void applicationAboutToQuit();
+ void showConfiguration();
+
+private Q_SLOTS:
+
+ void configChanged();
+
private:
MusicListenersManagerPrivate *d;
diff --git a/src/upnpControl.cpp b/src/upnpControl.cpp
index ec0c39f..65c9e11 100644
--- a/src/upnpControl.cpp
+++ b/src/upnpControl.cpp
@@ -53,6 +53,7 @@
#include "elisaapplication.h"
#include "audiowrapper.h"
#include "alltracksmodel.h"
+#include "elisa_settings.h"
#if defined Qt5DBus_FOUND && Qt5DBus_FOUND
#include "mpris2/mpris2.h"
@@ -214,6 +215,12 @@ int main(int argc, char *argv[])
QtAndroid::androidContext().object());
#endif
+ auto configurationFileName = \
QStandardPaths::writableLocation(QStandardPaths::ConfigLocation); + \
configurationFileName += QStringLiteral("/elisarc"); + \
Elisa::ElisaConfiguration::instance(configurationFileName); + \
Elisa::ElisaConfiguration::self()->load(); + \
Elisa::ElisaConfiguration::self()->save(); +
QQmlApplicationEngine engine;
engine.addImportPath(QStringLiteral("qrc:/imports"));
QQmlFileSelector selector(&engine);
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic