added config
This commit is contained in:
parent
893a2990af
commit
f02f439790
7 changed files with 168 additions and 17 deletions
|
|
@ -23,7 +23,7 @@ Item{
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.margins: visible ? container.margins : 0
|
anchors.margins: visible ? container.margins : 0
|
||||||
|
|
||||||
visible: container.height > 500
|
visible: container.height > 500 && uiStateModel.pShowQuitAppButton
|
||||||
diameter: visible ? defaultDiameter : 0
|
diameter: visible ? defaultDiameter : 0
|
||||||
|
|
||||||
imageSource: "qrc:/icon_close"
|
imageSource: "qrc:/icon_close"
|
||||||
|
|
@ -56,6 +56,7 @@ Item{
|
||||||
|
|
||||||
VolumeSlider{
|
VolumeSlider{
|
||||||
id: volumeSlider
|
id: volumeSlider
|
||||||
|
visible: uiStateModel.pShowVolumeControls
|
||||||
anchors{
|
anchors{
|
||||||
right: parent.right
|
right: parent.right
|
||||||
top: closeAppButton.bottom
|
top: closeAppButton.bottom
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ Item {
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.margins: container.margins
|
anchors.margins: container.margins
|
||||||
|
visible: uiStateModel.pShowQuitAppButton
|
||||||
imageSource: "qrc:/icon_close"
|
imageSource: "qrc:/icon_close"
|
||||||
onClicked: {
|
onClicked: {
|
||||||
Qt.quit();
|
Qt.quit();
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,11 @@ void NavigationController::init(const QString &rootPath)
|
||||||
mNavList->setModelItems(mRootItem->getChildren());
|
mNavList->setModelItems(mRootItem->getChildren());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NavigationController::setUiProfile(const QString &profileString)
|
||||||
|
{
|
||||||
|
mUiState->setProfile(profileString);
|
||||||
|
}
|
||||||
|
|
||||||
void NavigationController::setContext(QQmlContext *context)
|
void NavigationController::setContext(QQmlContext *context)
|
||||||
{
|
{
|
||||||
mContext = context;
|
mContext = context;
|
||||||
|
|
|
||||||
|
|
@ -9,19 +9,50 @@ class NavigationListModel;
|
||||||
class UiStateModel;
|
class UiStateModel;
|
||||||
class MusicController;
|
class MusicController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Main controller controlling ui state, navigation and music player.
|
||||||
|
*/
|
||||||
class NavigationController : public QObject
|
class NavigationController : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit NavigationController(QObject *parent = nullptr);
|
explicit NavigationController(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Setup navigation model parsing all directories under rootPath
|
||||||
|
* @param rootPath path to root directory containing music
|
||||||
|
*/
|
||||||
void init(const QString & rootPath);
|
void init(const QString & rootPath);
|
||||||
|
/**
|
||||||
|
* @brief Set ui profile
|
||||||
|
* @param profileString String defining profile
|
||||||
|
* @see UiStateModel::setProfile(const QString& profileString)
|
||||||
|
*/
|
||||||
|
void setUiProfile(const QString& profileString);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief setContext set QML Context and context properties
|
||||||
|
* @param context QmlContext
|
||||||
|
* @see setContextProperties
|
||||||
|
*/
|
||||||
void setContext(QQmlContext* context);
|
void setContext(QQmlContext* context);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/**
|
||||||
|
* @brief Register models in context
|
||||||
|
*/
|
||||||
void setContextProperties();
|
void setContextProperties();
|
||||||
|
/**
|
||||||
|
* @brief Add a directory and its subdirectories to navigation
|
||||||
|
* @param path Path to directory
|
||||||
|
* @param parentItem Parent directory
|
||||||
|
*/
|
||||||
void add(const QString & path, NavigationItemModel* parentItem);
|
void add(const QString & path, NavigationItemModel* parentItem);
|
||||||
|
/**
|
||||||
|
* @brief Check whether directory contains either a subdirectory or flac or mp3 music files
|
||||||
|
* @param path path to directory
|
||||||
|
* @return true if directory is valid
|
||||||
|
*/
|
||||||
bool checkContent(const QString& path);
|
bool checkContent(const QString& path);
|
||||||
|
|
||||||
NavigationItemModel* mRootItem;
|
NavigationItemModel* mRootItem;
|
||||||
|
|
@ -35,6 +66,9 @@ private:
|
||||||
QQmlContext* mContext = nullptr;
|
QQmlContext* mContext = nullptr;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
/**
|
||||||
|
* @brief Either show subdirectories or music player depending on current directory type
|
||||||
|
*/
|
||||||
void onNavigationRequest();
|
void onNavigationRequest();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,34 +1,56 @@
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
#include <QQmlApplicationEngine>
|
#include <QQmlApplicationEngine>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
#include <QCommandLineParser>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QDebug>
|
||||||
#include "controllers/NavigationController.h"
|
#include "controllers/NavigationController.h"
|
||||||
#include "MouseEventSpy.h"
|
#include "MouseEventSpy.h"
|
||||||
#include "EnergySaver.h"
|
#include "EnergySaver.h"
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
* @todo Add command line parser to specify a custom config file
|
|
||||||
* https://doc.qt.io/qt-5/qcommandlineparser.html
|
|
||||||
*/
|
|
||||||
QGuiApplication app(argc, argv);
|
QGuiApplication app(argc, argv);
|
||||||
QQmlApplicationEngine engine;
|
QQmlApplicationEngine engine;
|
||||||
|
|
||||||
/* Read Settings */
|
/* Add command line parser to specify a custom config file
|
||||||
QSettings settings("me", "LenaPi");
|
* https://doc.qt.io/qt-5/qcommandlineparser.html
|
||||||
const auto rootPath = settings.value("rootPath", "/home/ar/source/lenaMusic/").toString(); // path to music files
|
|
||||||
const auto profile = settings.value("profile", "RasPiTouch").toString(); // known modes are "RasPiTouch" and "Desktop"
|
|
||||||
const auto isEnergySavingEnabled = settings.value("enableEnergySaver", true).toBool(); // enable/disable energy saver
|
|
||||||
const auto energySaverTimeout = settings.value("timeout", 60).toInt(); //timeout in seconds
|
|
||||||
const auto shutdownScript = settings.value("shutdownScript", "/usr/local/sbin/do_shutdown.sh").toString();
|
|
||||||
|
|
||||||
/* @todo Hand over profile to UiStateModel via NavigationController
|
|
||||||
* Add properties to UiStateModel for showing volume controls and close button.
|
|
||||||
* Set those properties according to profile and use them to hide/show elements in qml
|
|
||||||
*/
|
*/
|
||||||
|
QCommandLineParser parser;
|
||||||
|
parser.setApplicationDescription("Lena's music app");
|
||||||
|
// Define a custom config file using -c or --config
|
||||||
|
QCommandLineOption configOption(QStringList() << "c" << "config", "Optional: Define custom config file");
|
||||||
|
parser.addOption(configOption);
|
||||||
|
|
||||||
|
// process commandline arguments
|
||||||
|
parser.process(app);
|
||||||
|
|
||||||
|
QSettings* settings = nullptr;
|
||||||
|
if(!parser.value(configOption).isEmpty()){
|
||||||
|
// config was handed over via commandline argument. Use this config if file exists.
|
||||||
|
QString configFilePath = parser.value(configOption);
|
||||||
|
QFileInfo configInfo(configFilePath);
|
||||||
|
if(configInfo.exists()){
|
||||||
|
settings = new QSettings(configFilePath, QSettings::Format::NativeFormat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!settings){
|
||||||
|
// default config
|
||||||
|
settings = new QSettings(QSettings::Scope::UserScope, "MaleyanaSoft", "LenaPi");
|
||||||
|
}
|
||||||
|
/* Read Settings */
|
||||||
|
|
||||||
|
const auto rootPath = settings->value("rootPath", "/home/ar/source/lenaMusic/").toString(); // path to music files
|
||||||
|
const auto profile = settings->value("profile", "RasPiTouch").toString(); // known profiles are "RasPiTouch" and "Desktop"
|
||||||
|
const auto isEnergySavingEnabled = settings->value("enableEnergySaver", true).toBool(); // enable/disable energy saver
|
||||||
|
const auto energySaverTimeout = settings->value("timeout", 60).toInt(); //timeout in seconds
|
||||||
|
const auto shutdownScript = settings->value("shutdownScript", "/usr/local/sbin/do_shutdown.sh").toString();
|
||||||
|
|
||||||
NavigationController navController;
|
NavigationController navController;
|
||||||
navController.setContext(engine.rootContext());
|
navController.setContext(engine.rootContext());
|
||||||
navController.init(rootPath);
|
navController.init(rootPath);
|
||||||
|
navController.setUiProfile(profile);
|
||||||
|
|
||||||
if(isEnergySavingEnabled){
|
if(isEnergySavingEnabled){
|
||||||
/* install MouseEventSpy and energy saver used for auto shut down of device
|
/* install MouseEventSpy and energy saver used for auto shut down of device
|
||||||
|
|
@ -43,6 +65,5 @@ int main(int argc, char *argv[])
|
||||||
// load GUI
|
// load GUI
|
||||||
engine.load(QUrl("qrc:/main.qml"));
|
engine.load(QUrl("qrc:/main.qml"));
|
||||||
|
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,30 @@
|
||||||
#include "UiStateModel.h"
|
#include "UiStateModel.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
UiStateModel::UiStateModel(QObject *parent) : QObject(parent)
|
UiStateModel::UiStateModel(QObject *parent) : QObject(parent)
|
||||||
{
|
{
|
||||||
|
initProfiles();
|
||||||
showNavigation();
|
showNavigation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UiStateModel::setProfile(UiStateModel::EProfile profile)
|
||||||
|
{
|
||||||
|
mProfile = profile;
|
||||||
|
emit profileChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UiStateModel::isShowQuitAppButton() const
|
||||||
|
{
|
||||||
|
const auto & profileInfo = mProfileInfoMap[mProfile];
|
||||||
|
return profileInfo.isShowQuitAppButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UiStateModel::isShowVolumeControls() const
|
||||||
|
{
|
||||||
|
const auto & profileInfo = mProfileInfoMap[mProfile];
|
||||||
|
return profileInfo.isShowVolumeControls;
|
||||||
|
}
|
||||||
|
|
||||||
QUrl UiStateModel::getSource() const
|
QUrl UiStateModel::getSource() const
|
||||||
{
|
{
|
||||||
return mSource;
|
return mSource;
|
||||||
|
|
@ -19,3 +39,32 @@ void UiStateModel::showNavigation(){
|
||||||
mSource = QUrl("Navigation.qml");
|
mSource = QUrl("Navigation.qml");
|
||||||
emit sourceChanged();
|
emit sourceChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UiStateModel::initProfiles()
|
||||||
|
{
|
||||||
|
// Profile_RasPiTouch
|
||||||
|
ProfileInfo rasPiTouchProfile;
|
||||||
|
rasPiTouchProfile.profileType = Profile_RasPiTouch;
|
||||||
|
rasPiTouchProfile.isShowQuitAppButton = false;
|
||||||
|
rasPiTouchProfile.isShowVolumeControls = false;
|
||||||
|
|
||||||
|
mProfileInfoMap.insert(rasPiTouchProfile.profileType, rasPiTouchProfile);
|
||||||
|
|
||||||
|
// Profile_Desktop
|
||||||
|
ProfileInfo desktopProfile;
|
||||||
|
desktopProfile.profileType = Profile_Desktop;
|
||||||
|
desktopProfile.isShowQuitAppButton = true;
|
||||||
|
desktopProfile.isShowVolumeControls = true;
|
||||||
|
|
||||||
|
mProfileInfoMap.insert(desktopProfile.profileType, desktopProfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
UiStateModel::EProfile UiStateModel::getProfileFromString(const QString &profileString)
|
||||||
|
{
|
||||||
|
if(profileString == "Desktop"){
|
||||||
|
return Profile_Desktop;
|
||||||
|
} else if(profileString != "RasPiTouch"){
|
||||||
|
std::cout << "WARNING: Unknown profile\t" << profileString.toStdString() << std::endl;
|
||||||
|
}
|
||||||
|
return Profile_RasPiTouch;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
#include <QHash>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Handles state of UI by providing the qml source.
|
* @brief Handles state of UI by providing the qml source.
|
||||||
|
|
@ -15,9 +16,12 @@ class UiStateModel : public QObject
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
Q_PROPERTY(QUrl pSource READ getSource NOTIFY sourceChanged)
|
Q_PROPERTY(QUrl pSource READ getSource NOTIFY sourceChanged)
|
||||||
|
Q_PROPERTY(bool pShowQuitAppButton READ isShowQuitAppButton NOTIFY profileChanged)
|
||||||
|
Q_PROPERTY(bool pShowVolumeControls READ isShowVolumeControls NOTIFY profileChanged)
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void sourceChanged();
|
void sourceChanged();
|
||||||
|
void profileChanged();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
|
|
@ -37,15 +41,51 @@ public:
|
||||||
*/
|
*/
|
||||||
Profile_Desktop
|
Profile_Desktop
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit UiStateModel(QObject *parent = nullptr);
|
explicit UiStateModel(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief setProfile
|
||||||
|
* @param profileString String identifying profile as read from config.
|
||||||
|
*
|
||||||
|
* Known profile strings are "RasPiTouch" and "Desktop".
|
||||||
|
*/
|
||||||
|
void setProfile(const QString& profileString){ setProfile(getProfileFromString(profileString)); }
|
||||||
|
void setProfile(EProfile profile);
|
||||||
|
|
||||||
|
bool isShowQuitAppButton() const;
|
||||||
|
bool isShowVolumeControls() const;
|
||||||
|
|
||||||
QUrl getSource() const;
|
QUrl getSource() const;
|
||||||
|
|
||||||
void showMusicPlayer();
|
void showMusicPlayer();
|
||||||
void showNavigation();
|
void showNavigation();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/**
|
||||||
|
* @brief Container defining ui state inforamtion for a certain profile
|
||||||
|
*/
|
||||||
|
struct ProfileInfo{
|
||||||
|
EProfile profileType = Profile_RasPiTouch;
|
||||||
|
bool isShowQuitAppButton = false;
|
||||||
|
bool isShowVolumeControls = false;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* @brief Map containing ProfileInfo for each profile
|
||||||
|
*/
|
||||||
|
QHash<EProfile, ProfileInfo> mProfileInfoMap;
|
||||||
|
/**
|
||||||
|
* @brief Init ProfileInfo for all known profiles and init mProfileInfoMap
|
||||||
|
*/
|
||||||
|
void initProfiles();
|
||||||
|
/**
|
||||||
|
* @brief Transform given profile string to enum valie
|
||||||
|
* @param profileString String identifying profile
|
||||||
|
* @return Matching profile. If given string does not match a known profile, Profile_RasPiTouch is used as default.
|
||||||
|
*/
|
||||||
|
static EProfile getProfileFromString(const QString& profileString);
|
||||||
QUrl mSource;
|
QUrl mSource;
|
||||||
|
EProfile mProfile = Profile_RasPiTouch;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // UISTATEMODEL_H
|
#endif // UISTATEMODEL_H
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue