Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Sign in
Toggle navigation
L
Lichtsteuerung
Project overview
Project overview
Details
Activity
Releases
Cycle Analytics
Insights
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Locked Files
Issues
23
Issues
23
List
Boards
Labels
Milestones
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Security & Compliance
Security & Compliance
Dependency List
Packages
Packages
Container Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Leander Schulten
Lichtsteuerung
Commits
d5bf91ba
Commit
d5bf91ba
authored
Oct 28, 2019
by
Leander Schulten
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' into windows-release
parents
e1bd3e6f
6487111d
Pipeline
#199378
passed with stages
in 7 minutes and 20 seconds
Changes
15
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
422 additions
and
33 deletions
+422
-33
Dockerfile
Dockerfile
+1
-0
src/Lichtsteuerung.pro
src/Lichtsteuerung.pro
+7
-0
src/applicationdata.cpp
src/applicationdata.cpp
+11
-1
src/audio/systemvolume.cpp
src/audio/systemvolume.cpp
+102
-15
src/audio/systemvolume.h
src/audio/systemvolume.h
+23
-4
src/main.cpp
src/main.cpp
+26
-5
src/qml/SettingsView.qml
src/qml/SettingsView.qml
+46
-4
src/qml/components/TextInputField.qml
src/qml/components/TextInputField.qml
+2
-2
src/qml/components/TextUnderline.qml
src/qml/components/TextUnderline.qml
+3
-2
src/qml/main.qml
src/qml/main.qml
+80
-0
src/settings.cpp
src/settings.cpp
+14
-0
src/settings.h
src/settings.h
+26
-0
src/settingsfilewrapper.cpp
src/settingsfilewrapper.cpp
+43
-0
src/settingsfilewrapper.h
src/settingsfilewrapper.h
+37
-0
src/usermanagment.h
src/usermanagment.h
+1
-0
No files found.
Dockerfile
View file @
d5bf91ba
...
...
@@ -151,6 +151,7 @@ RUN make qtnetworkauth
RUN
make qtquickcontrols2
RUN
make qtserialport
RUN
make qttools
RUN
make qtwebsockets
#set path to mxe compiler
RUN
export
PATH
=
/usr/src/mxe/usr/bin:
$PATH
src/Lichtsteuerung.pro
View file @
d5bf91ba
...
...
@@ -53,6 +53,7 @@ SOURCES += \
modules/dmxconsumer.cpp \
modules/ledconsumer.cpp \
scanner.cpp \
settingsfilewrapper.cpp \
slideshow.cpp \
system_error_handler.cpp \
test/testloopprogramm.cpp \
...
...
@@ -125,6 +126,7 @@ HEADERS += \
modules/ledconsumer.h \
modules/scanner.hpp \
scanner.h \
settingsfilewrapper.h \
slideshow.h \
system_error_handler.h \
updater.h \
...
...
@@ -287,3 +289,8 @@ win32-msvc{
INCLUDEPATH
+=
$$
PWD
/
lib
/
RtAudio
/
include
LIBS
+=
-
L
$$
PWD
/
lib
/
RtAudio
/
lib
-
lrtaudio
win32
:
LIBS
+=
-
lole32
-
lwinmm
-
lksuser
-
lmfplat
-
lmfuuid
-
lwmcodecdspuuid
macx
{
#
Needed
by
the
SystemVolume
class
LIBS
+=
-
framework
CoreAudio
}
src/applicationdata.cpp
View file @
d5bf91ba
...
...
@@ -90,7 +90,17 @@ std::pair<std::function<void()>, QString> loadData(const QByteArray &data) {
QJsonParseError
error
{};
auto
doc
=
QJsonDocument
::
fromJson
(
data
,
&
error
);
if
(
error
.
error
!=
QJsonParseError
::
NoError
)
{
return
{{},
"Failed to parse settings file: "
+
error
.
errorString
()
+
" at position "
+
QString
::
number
(
error
.
offset
)};
// compute line and column
int
line
=
1
;
auto
lastNewLine
=
data
.
cbegin
();
for
(
auto
i
=
data
.
cbegin
();
i
!=
data
.
cbegin
()
+
error
.
offset
;
++
i
)
{
if
(
*
i
==
'\n'
)
{
++
line
;
lastNewLine
=
i
;
}
}
int
column
=
QString
::
fromUtf8
(
lastNewLine
,
data
.
cbegin
()
+
error
.
offset
-
lastNewLine
).
length
();
return
{{},
"Failed to parse settings file: "
+
error
.
errorString
()
+
" at position "
+
QString
::
number
(
error
.
offset
)
+
", Ln "
+
QString
::
number
(
line
)
+
", Col "
+
QString
::
number
(
column
)};
}
const
auto
o
=
doc
.
object
();
for
(
const
auto
e
:
o
[
QStringLiteral
(
"DevicePrototypes"
)].
toArray
())
{
...
...
src/audio/systemvolume.cpp
View file @
d5bf91ba
#include "systemvolume.h"
#include <QtDebug>
#ifdef Q_OS_MAC
OSStatus
callback
(
AudioObjectID
inObjectID
,
UInt32
inNumberAddresses
,
const
AudioObjectPropertyAddress
*
inAddresses
,
void
*
/*inClientData*/
)
{
for
(
UInt32
i
=
0
;
i
<
inNumberAddresses
;
++
i
)
{
const
auto
&
cur
=
inAddresses
[
i
];
if
(
cur
.
mScope
==
kAudioDevicePropertyScopeOutput
&&
cur
.
mSelector
==
kAudioDevicePropertyVolumeScalar
&&
cur
.
mElement
==
1
/*LEFT_CHANNEL*/
)
{
AudioObjectPropertyAddress
volumePropertyAddress
=
{
kAudioDevicePropertyVolumeScalar
,
kAudioDevicePropertyScopeOutput
,
1
/*LEFT_CHANNEL*/
};
Float32
volume
;
UInt32
volumedataSize
=
sizeof
(
volume
);
auto
result
=
AudioObjectGetPropertyData
(
inObjectID
,
&
volumePropertyAddress
,
0
,
nullptr
,
&
volumedataSize
,
&
volume
);
if
(
result
==
kAudioHardwareNoError
)
{
SystemVolume
::
get
().
setVolume
(
static_cast
<
double
>
(
volume
));
}
break
;
}
}
return
noErr
;
}
#endif
#ifdef Q_OS_WIN
HRESULT
Callback
::
OnNotify
(
AUDIO_VOLUME_NOTIFICATION_DATA
*
pNotify
)
{
SystemVolume
::
get
().
setVolume
(
static_cast
<
double
>
(
pNotify
->
fMasterVolume
));
return
S_OK
;
}
Callback
::~
Callback
()
{
if
(
counter
!=
0
)
{
qWarning
()
<<
"SystemVolume::Callback: Releasing object with ref count > 0"
;
}
}
HRESULT
Callback
::
QueryInterface
(
const
IID
&
/*riid*/
,
void
**
/*ppvObject*/
)
{
qWarning
()
<<
"SystemVolume::Callback: What do they want from me?"
;
return
E_NOINTERFACE
;
}
#endif
SystemVolume
::
SystemVolume
()
{
#ifdef Q_OS_WIN
...
...
@@ -21,28 +62,52 @@ SystemVolume::SystemVolume() {
if
(
hr
<
0
)
{
return
;
}
hr
=
endpointVolume
->
RegisterControlChangeNotify
(
&
callback
);
if
(
hr
<
0
)
{
return
;
}
// query initial volume
FLOAT
v
;
hr
=
endpointVolume
->
GetMasterVolumeLevelScalar
(
&
v
);
if
(
hr
<
0
)
{
return
;
}
volume
=
static_cast
<
double
>
(
v
);
emit
volumeChanged
();
#endif
startTimer
(
SystemVolumeUpdateRateInMs
);
timerEvent
(
nullptr
);
}
#ifdef Q_OS_MAC
AudioObjectPropertyAddress
getDefaultOutputDevicePropertyAddress
=
{
kAudioHardwarePropertyDefaultOutputDevice
,
kAudioObjectPropertyScopeGlobal
,
kAudioObjectPropertyElementMaster
};
void
SystemVolume
::
timerEvent
(
QTimerEvent
*
/*event*/
)
{
#ifdef Q_OS_WIN
if
(
endpointVolume
)
{
float
vol
;
auto
hr
=
endpointVolume
->
GetMasterVolumeLevelScalar
(
&
vol
);
if
(
hr
>=
0
/* success */
)
{
auto
v
=
static_cast
<
double
>
(
vol
);
if
(
volume
!=
v
)
{
volume
=
v
;
emit
volumeChanged
();
}
}
UInt32
outputDeviceSize
=
sizeof
(
defaultOutputDeviceID
);
OSStatus
result
=
AudioObjectGetPropertyData
(
kAudioObjectSystemObject
,
&
getDefaultOutputDevicePropertyAddress
,
0
,
nullptr
,
&
outputDeviceSize
,
&
defaultOutputDeviceID
);
if
(
kAudioHardwareNoError
!=
result
)
{
qWarning
()
<<
"Failed to get the default output device"
;
}
// register a listener so that we get an event when the volume changed
AudioObjectPropertyAddress
volumePropertyAddress
=
{
kAudioDevicePropertyVolumeScalar
,
kAudioDevicePropertyScopeOutput
,
1
/*LEFT_CHANNEL*/
};
result
=
AudioObjectAddPropertyListener
(
defaultOutputDeviceID
,
&
volumePropertyAddress
,
&
callback
,
nullptr
);
if
(
result
!=
kAudioHardwareNoError
)
{
qWarning
()
<<
"Registration of Audio Listener Failed"
;
}
// get initial volume
Float32
volume
;
UInt32
volumedataSize
=
sizeof
(
volume
);
result
=
AudioObjectGetPropertyData
(
defaultOutputDeviceID
,
&
volumePropertyAddress
,
0
,
nullptr
,
&
volumedataSize
,
&
volume
);
if
(
result
==
kAudioHardwareNoError
)
{
this
->
volume
=
static_cast
<
double
>
(
volume
);
emit
volumeChanged
();
}
#endif
}
SystemVolume
::~
SystemVolume
()
{
#ifdef Q_OS_WIN
if
(
pEnumerator
)
{
pEnumerator
->
Release
();
}
...
...
@@ -50,12 +115,14 @@ SystemVolume::~SystemVolume() {
pDevice
->
Release
();
}
if
(
endpointVolume
)
{
endpointVolume
->
UnregisterControlChangeNotify
(
&
callback
);
endpointVolume
->
Release
();
}
if
(
client
)
{
client
->
Release
();
}
CoUninitialize
();
#endif
}
void
SystemVolume
::
setVolume
(
double
volume
)
{
...
...
@@ -67,6 +134,26 @@ void SystemVolume::setVolume(double volume) {
if
(
endpointVolume
)
{
endpointVolume
->
SetMasterVolumeLevelScalar
(
static_cast
<
float
>
(
volume
),
nullptr
);
}
#endif
#ifdef Q_OS_MAC
if
(
defaultOutputDeviceID
!=
kAudioDeviceUnknown
)
{
AudioObjectPropertyAddress
volumePropertyAddress
=
{
kAudioDevicePropertyVolumeScalar
,
kAudioDevicePropertyScopeOutput
,
1
/*LEFT_CHANNEL*/
};
Float32
volume
=
static_cast
<
Float32
>
(
this
->
volume
);
auto
result
=
AudioObjectSetPropertyData
(
defaultOutputDeviceID
,
&
volumePropertyAddress
,
0
,
nullptr
,
sizeof
(
volume
),
&
volume
);
if
(
result
!=
kAudioHardwareNoError
)
{
qWarning
()
<<
"Can not set system volume"
;
}
else
{
// setting right channel
volumePropertyAddress
.
mElement
=
2
/*RIGHT_CHANNEL*/
;
result
=
AudioObjectSetPropertyData
(
defaultOutputDeviceID
,
&
volumePropertyAddress
,
0
,
nullptr
,
sizeof
(
volume
),
&
volume
);
if
(
result
!=
kAudioHardwareNoError
)
{
qWarning
()
<<
"Can not set system volume of right channel"
;
}
}
}
#endif
}
}
src/audio/systemvolume.h
View file @
d5bf91ba
...
...
@@ -14,6 +14,25 @@
#include <windows.h>
#endif
#ifdef Q_OS_MAC
#include <CoreAudio/CoreAudio.h>
#endif
#ifdef Q_OS_WIN
class
Callback
:
public
IAudioEndpointVolumeCallback
{
ULONG
counter
=
0
;
HRESULT
OnNotify
(
AUDIO_VOLUME_NOTIFICATION_DATA
*
pNotify
)
override
;
public:
~
Callback
();
HRESULT
QueryInterface
(
REFIID
/*riid*/
,
void
**
/*ppvObject*/
)
override
;
ULONG
AddRef
()
override
{
return
++
counter
;
}
ULONG
Release
()
override
{
return
--
counter
;
}
};
#endif
class
SystemVolume
:
public
QObject
{
Q_OBJECT
#ifdef Q_OS_WIN
...
...
@@ -22,15 +41,15 @@ class SystemVolume : public QObject {
IAudioEndpointVolume
*
endpointVolume
=
nullptr
;
WAVEFORMATEX
*
wformat
=
nullptr
;
IAudioClient
*
client
=
nullptr
;
Callback
callback
;
#endif
#ifdef Q_OS_MAC
AudioDeviceID
defaultOutputDeviceID
=
kAudioDeviceUnknown
;
#endif
double
volume
=
-
1
;
Q_PROPERTY
(
double
volume
READ
getVolume
WRITE
setVolume
NOTIFY
volumeChanged
)
SystemVolume
();
static
constexpr
int
SystemVolumeUpdateRateInMs
=
10'000
;
protected:
void
timerEvent
(
QTimerEvent
*
event
)
override
;
public:
static
SystemVolume
&
get
()
{
...
...
src/main.cpp
View file @
d5bf91ba
...
...
@@ -3,6 +3,7 @@
#include "errornotifier.h"
#include "modelmanager.h"
#include "settings.h"
#include "settingsfilewrapper.h"
#include "slideshow.h"
#include "sortedmodelview.h"
#include "updater.h"
...
...
@@ -250,8 +251,9 @@ int main(int argc, char *argv[]) {
qmlRegisterType
<
Settings
>
(
"custom.licht"
,
1
,
0
,
"PopupBackground"
);
qRegisterMetaType
<
DMXChannelFilter
::
Operation
>
(
"Operation"
);
qmlRegisterUncreatableType
<
UserManagment
>
(
"custom.licht"
,
1
,
0
,
"Permission"
,
QStringLiteral
(
"Singletone in c++"
));
qmlRegisterUncreatableMetaObject
(
Updater
::
staticMetaObject
,
"custom.licht"
,
1
,
0
,
"UpdaterState"
,
QStringLiteral
(
"Enum in c++"
));
qmlRegisterUncreatableMetaObject
(
ControlItemData
::
staticMetaObject
,
"custom.licht"
,
1
,
0
,
"ControlType"
,
QStringLiteral
(
"Enum in c++"
));
qmlRegisterUncreatableMetaObject
(
Updater
::
staticMetaObject
,
"custom.licht"
,
1
,
0
,
"UpdaterState"
,
QStringLiteral
(
"Enum in c++"
));
qmlRegisterUncreatableMetaObject
(
ControlItemData
::
staticMetaObject
,
"custom.licht"
,
1
,
0
,
"ControlType"
,
QStringLiteral
(
"Enum in c++"
));
qmlRegisterUncreatableType
<
SettingsFileWrapper
>
(
"custom.licht"
,
1
,
0
,
"SettingsFileStatus"
,
QStringLiteral
(
"Enum in c++"
));
qRegisterMetaType
<
UserManagment
::
Permission
>
(
"Permission"
);
qRegisterMetaType
<
Modules
::
detail
::
PropertyInformation
::
Type
>
(
"Type"
);
qRegisterMetaType
<
Modules
::
ValueType
>
(
"ValueType"
);
...
...
@@ -266,7 +268,13 @@ int main(int argc, char *argv[]) {
// Load Settings and ApplicationData
Settings
::
setLocalSettingFile
(
QFileInfo
(
QStringLiteral
(
"settings.ini"
)));
Settings
settings
;
SettingsFileWrapper
settingsFileWrapper
(
settings
);
RemoteVolume
remoteVolume
(
settings
);
if
(
settings
.
isStartupVolumeEnabled
())
{
SystemVolume
::
get
().
setVolume
(
settings
.
getStartupVolume
());
}
QString
file
(
settings
.
getJsonSettingsFilePath
());
if
(
!
QFile
::
exists
(
file
))
{
file
=
QStringLiteral
(
"QTJSONFile.json"
);
...
...
@@ -278,11 +286,15 @@ int main(int argc, char *argv[]) {
QString
error
;
std
::
tie
(
after
,
error
)
=
ApplicationData
::
loadData
(
file
);
if
(
!
error
.
isEmpty
())
{
ErrorNotifier
::
showError
(
error
);
settingsFileWrapper
.
setErrorMessage
(
error
);
settingsFileWrapper
.
setStatus
(
SettingsFileWrapper
::
LoadingFailed
);
}
else
{
settingsFileWrapper
.
setStatus
(
SettingsFileWrapper
::
Loaded
);
}
}
else
{
ErrorNotifier
::
showError
(
QStringLiteral
(
"No settings file found! The Lichtsteuerung starts wihout content."
));
settingsFileWrapper
.
setStatus
(
SettingsFileWrapper
::
NoFile
);
}
// nachdem die Benutzer geladen wurden, auto login durchführen
UserManagment
::
get
()
->
autoLoginUser
();
...
...
@@ -324,7 +336,10 @@ int main(int argc, char *argv[]) {
CatchingErrorApplication
::
connect
(
&
app
,
&
QGuiApplication
::
aboutToQuit
,
[
&
]()
{
Modules
::
ModuleManager
::
singletone
()
->
controller
().
stop
();
Audio
::
AudioCaptureManager
::
get
().
stopCapturingAndWait
();
ApplicationData
::
saveData
(
settings
.
getJsonSettingsFileSavePath
());
// if status is not SettingsFileWrapper::Loaded, the loading of the data failed and we should not write back an emtpy file
if
(
settingsFileWrapper
.
getStatus
()
==
SettingsFileWrapper
::
Loaded
)
{
ApplicationData
::
saveData
(
settings
.
getJsonSettingsFileSavePath
());
}
Driver
::
stopAndUnloadDriver
();
if
(
updater
.
getState
()
==
Updater
::
ReadyToInstall
)
{
updater
.
runUpdateInstaller
();
...
...
@@ -339,7 +354,12 @@ int main(int argc, char *argv[]) {
Driver
::
getCurrentDriver
()
->
setWaitTime
(
std
::
chrono
::
milliseconds
(
settings
.
getUpdatePauseInMs
()));
}
});
Settings
::
connect
(
&
settings
,
&
Settings
::
saveAs
,
[
&
](
const
auto
&
path
)
{
ApplicationData
::
saveData
(
path
);
});
Settings
::
connect
(
&
settings
,
&
Settings
::
saveAs
,
[
&
](
const
auto
&
path
)
{
// if status is not SettingsFileWrapper::Loaded, the loading of the data failed and we should not write back an emtpy file
if
(
settingsFileWrapper
.
getStatus
()
==
SettingsFileWrapper
::
Loaded
)
{
ApplicationData
::
saveData
(
path
);
}
});
Modules
::
ModuleManager
::
singletone
()
->
loadAllModulesInDir
(
settings
.
getModuleDirPath
());
Settings
::
connect
(
&
settings
,
&
Settings
::
moduleDirPathChanged
,
[
&
]()
{
Modules
::
ModuleManager
::
singletone
()
->
loadAllModulesInDir
(
settings
.
getModuleDirPath
());
});
...
...
@@ -367,6 +387,7 @@ int main(int argc, char *argv[]) {
engine
.
rootContext
()
->
setContextProperty
(
QStringLiteral
(
"dmxOutputValues"
),
&
Driver
::
dmxValueModel
);
engine
.
rootContext
()
->
setContextProperty
(
QStringLiteral
(
"AudioManager"
),
&
Audio
::
AudioCaptureManager
::
get
());
engine
.
rootContext
()
->
setContextProperty
(
QStringLiteral
(
"SlideShow"
),
&
SlideShow
::
get
());
engine
.
rootContext
()
->
setContextProperty
(
QStringLiteral
(
"SettingsFile"
),
&
settingsFileWrapper
);
engine
.
rootContext
()
->
setContextProperty
(
QStringLiteral
(
"System"
),
&
SystemVolume
::
get
());
engine
.
load
(
QUrl
(
QStringLiteral
(
"qrc:/qml/main.qml"
)));
engine
.
load
(
QUrl
(
QStringLiteral
(
"qrc:/qml/SlideShowWindow.qml"
)));
...
...
src/qml/SettingsView.qml
View file @
d5bf91ba
...
...
@@ -6,10 +6,21 @@ import QtQuick.Window 2.12
import
custom
.
licht
1.0
import
"
components
"
Pane
{
property
bool
visibleForUser
:
SwipeView
.
isCurrentItem
onVisibleForUserChanged
:
fileDialogLoader
.
load
();
ScrollView
{
property
bool
visibleForUser
:
SwipeView
.
isCurrentItem
onVisibleForUserChanged
:
{
if
(
visibleForUser
)
{
fileDialogLoader
.
load
();
// show the scroll bar for a short time so that the user can see that you can scroll here
ScrollBar
.
vertical
.
active
=
true
;
ScrollBar
.
vertical
.
active
=
false
;
}
}
contentHeight
:
layout
.
implicitHeight
contentWidth
:
Math
.
max
(
600
,
width
-
2
*
padding
)
padding
:
10
GridLayout
{
id
:
layout
anchors.left
:
parent
.
left
anchors.right
:
parent
.
right
rowSpacing
:
4
...
...
@@ -19,7 +30,7 @@ Pane{
}
RowLayout
{
id
:
root
//
enabled: UserManagment.currentUser.havePermission(Permission.CHANGE_SETTINGS_FILE_PATH)
enabled
:
UserManagment
.
currentUser
.
havePermission
(
Permission
.
CHANGE_SETTINGS_FILE_PATH
)
Item
{
Layout.fillWidth
:
true
Layout.preferredWidth
:
inputSettingsPath
.
implicitWidth
...
...
@@ -282,6 +293,36 @@ Pane{
}
Label
{
text
:
"
Startup Volume
"
}
RowLayout
{
Layout.topMargin
:
-
10
Layout.bottomMargin
:
-
10
Layout.leftMargin
:
-
7
enabled
:
UserManagment
.
currentUser
.
havePermission
(
Permission
.
CHANGE_STARTUP_VOLUME
)
CheckBox
{
text
:
"
enabled
"
checked
:
Settings
.
isStartupVolumeEnabled
onCheckedChanged
:
Settings
.
isStartupVolumeEnabled
=
checked
}
Label
{
visible
:
Settings
.
isStartupVolumeEnabled
Layout.leftMargin
:
10
Layout.preferredWidth
:
100
text
:
"
Volume:
"
+
(
Settings
.
startupVolume
*
100
).
toFixed
(
0
)
+
"
%
"
}
Slider
{
visible
:
Settings
.
isStartupVolumeEnabled
from
:
0
to
:
1
Layout.preferredWidth
:
200
value
:
Settings
.
startupVolume
onValueChanged
:
Settings
.
startupVolume
=
value
;
}
}
}
Loader
{
...
...
@@ -322,3 +363,4 @@ Pane{
}
}
src/qml/components/TextInputField.qml
View file @
d5bf91ba
...
...
@@ -7,11 +7,11 @@ TextInput{
color
:
Material
.
foreground
selectByMouse
:
true
font.pixelSize
:
15
selectionColor
:
"
lightgreen
"
selectionColor
:
Material
.
textSelectionColor
property
alias
underlineColor
:
underline
.
color
property
alias
underline
:
underline
cursorDelegate
:
Rectangle
{
color
:
"
lightgreen
"
color
:
Material
.
accentColor
x
:
parent
.
cursorRectangle
.
x
y
:
parent
.
cursorRectangle
.
y
width
:
parent
.
cursorRectangle
.
width
+
1
...
...
src/qml/components/TextUnderline.qml
View file @
d5bf91ba
import
QtQuick
2.2
import
QtQuick
2.12
import
QtQuick
.
Controls
.
Material
2.12
Rectangle
{
id
:
underline
...
...
@@ -9,7 +10,7 @@ Rectangle{
width
:
parent
.
contentWidth
+
extendetWidth
height
:
2
radius
:
1
color
:
parent
.
enabled
?
"
lightgreen
"
:
"
lightgrey
"
color
:
parent
.
enabled
?
Material
.
accentColor
:
Material
.
hintTextColor
//property bool hasFocus
Behavior
on
width
{
NumberAnimation
{
easing.type
:
Easing
.
OutExpo
;
easing.amplitude
:
5.0
;
easing.period
:
2.0
;
duration
:
800
}
...
...
src/qml/main.qml
View file @
d5bf91ba
...
...
@@ -314,4 +314,84 @@ ApplicationWindow {
visible
:
ErrorNotifier
.
errorMessage
.
length
!==
0
}
Popup
{
Overlay.modal
:
ModalPopupBackground
{}
closePolicy
:
Popup
.
NoAutoClose
y
:
70
x
:
(
parent
.
width
-
width
)
/
2
modal
:
true
visible
:
SettingsFile
.
status
===
SettingsFileStatus
.
LoadingFailed
onVisibleChanged
:
{
if
(
visible
)
{
fileDialogLoader
.
source
=
"
components/SystemFileDialog.qml
"
}
}
contentItem
:
ColumnLayout
{
Label
{
font.pointSize
:
15
font.bold
:
true
text
:
"
Failed to load settings file
"
}
Label
{
id
:
fontReference
text
:
SettingsFile
.
errorMessage
Layout.bottomMargin
:
5
Layout.maximumWidth
:
500
wrapMode
:
Text
.
WrapAtWordBoundaryOrAnywhere
}
TextInput
{
Layout.fillWidth
:
true
Layout.maximumWidth
:
500
Layout.leftMargin
:
1
Layout.rightMargin
:
2
clip
:
true
color
:
Material
.
foreground
selectionColor
:
Material
.
textSelectionColor
font
:
fontReference
.
font
text
:
Settings
.
jsonSettingsFilePath
selectByMouse
:
true
readOnly
:
true
}
GridLayout
{
columns
:
2
rowSpacing
:
-
5
Button
{
text
:
"
Open file in default editor
"
Layout.fillWidth
:
true
flat
:
true
onClicked
:
SettingsFile
.
openFileInDefaultEditor
();
}
Button
{
text
:
"
Open folder where file is
"
Layout.fillWidth
:
true
flat
:
true
onClicked
:
SettingsFile
.
openFileExplorerAtFile
();
}
Button
{
text
:
"
Reload selected settings file
"
Layout.fillWidth
:
true
onClicked
:
SettingsFile
.
reload
();
}
Button
{
text
:
"
Load an other settings file
"
Layout.fillWidth
:
true
onClicked
:
fileDialogLoader
.
item
.
openAt
(
Settings
.
jsonSettingsFilePath
,
false
)
}
}
}
Loader
{
asynchronous
:
true
id
:
fileDialogLoader
onStatusChanged
:
{
if
(
status
===
Loader
.
Ready
)
{
item
.
callback
=
path
=>
{
SettingsFile
.
loadFile
(
path
);
};
}
}
}
}
}
src/settings.cpp
View file @
d5bf91ba
...
...
@@ -57,6 +57,20 @@ void Settings::remoteVolumeControl(bool enable) {
}
}
void
Settings
::
setStartupVolumeEnabled
(
bool
enabled
)
{
if
(
enabled
!=
isStartupVolumeEnabled
())
{
setValue
(
QStringLiteral
(
"isStartupVolumeEnabled"
),
enabled
);
emit
isStartupVolumeEnabledChanged
();
}
}
void
Settings
::
setStartupVolume
(
double
volume
)
{
if
(
volume
!=
getStartupVolume
())
{
setValue
(
QStringLiteral
(
"StartupVolume"
),
volume
);
emit
startupVolumeChanged
();
}
}
void
Settings
::
setValue
(
const
QString
&
key
,
const
QVariant
&
value
){
if
(
localSettings
)
{
if
(
localSettings
->
contains
(
key
))
{
...
...
src/settings.h
View file @
d5bf91ba
...
...
@@ -59,6 +59,8 @@ class Settings : public QObject {
Q_PROPERTY
(
QString
includePath
READ
getIncludePath
WRITE
setIncludePath
NOTIFY
includePathChanged
)
Q_PROPERTY
(
QString
computerName
READ
getComputerName
WRITE
setComputerName
NOTIFY
computerNameChanged
)
Q_PROPERTY
(
bool
remoteVolumeControl
READ
remoteVolumeControl
WRITE
remoteVolumeControl
NOTIFY
remoteVolumeControlChanged
)
Q_PROPERTY
(
bool
isStartupVolumeEnabled
READ
isStartupVolumeEnabled
WRITE
setStartupVolumeEnabled
NOTIFY
isStartupVolumeEnabledChanged
)
Q_PROPERTY
(
double
startupVolume
READ
getStartupVolume
WRITE
setStartupVolume
NOTIFY
startupVolumeChanged
)
Q_PROPERTY
(
int
theme
READ
getTheme
WRITE
setTheme
NOTIFY
themeChanged
)
Q_PROPERTY
(
unsigned
int
updatePauseInMs
READ
getUpdatePauseInMs
WRITE
setUpdatePauseInMs
NOTIFY
updatePauseInMsChanged
)
static
inline
QFileInfo
localSettingsFile
;
...
...
@@ -187,6 +189,28 @@ public:
void
remoteVolumeControl
(
bool
enable
);
[[
nodiscard
]]
bool
remoteVolumeControl
()
const
{
return
value
(
QStringLiteral
(
"remoteVolumeControl"
),
false
).
toBool
();
}
/**
* @brief setStartupVolumeEnabled enables or disables the functionality described here: isStartupVolumeEnabled()
* @param enabled true if enabled, false if disabled
*/
void
setStartupVolumeEnabled
(
bool
enabled
);
/**
* @brief isStartupVolumeEnabled if true, the system volume should be set to getStartupVolume() when the Lichtsteuerung starts
* @return true if should set, false otherwise
*/
[[
nodiscard
]]
bool
isStartupVolumeEnabled
()
const
{
return
value
(
QStringLiteral
(
"isStartupVolumeEnabled"
),
false
).
toBool
();
}
/**
* @brief setStartupVolume sets the system volume that should be set when the Lichtsteuerung starts, valid values: 0.0 - 1.0
* @param volume the new startup volume
*/
void
setStartupVolume
(
double
volume
);
/**
* @brief getStartupVolume the system volume that should be set when the Lichtsteuerung starts, valid values: 0.0 - 1.0
* @return the startup volume, 0.0 - 1.0
*/
[[
nodiscard
]]
double
getStartupVolume
()
const
{
return
value
(
QStringLiteral
(
"StartupVolume"
),
-
.5
).
toDouble
();
}
void
setTheme
(
int
theme
)
{
if
(
theme
!=
getTheme
())
{
setValue
(
QStringLiteral
(
"theme"
),
theme
);
...
...
@@ -236,6 +260,8 @@ signals:
void
saveAs
(
QString
path
);
void
computerNameChanged
();
void
remoteVolumeControlChanged
();
void
isStartupVolumeEnabledChanged
();
void
startupVolumeChanged
();
public
slots
:
};
...
...
src/settingsfilewrapper.cpp
0 → 100644
View file @
d5bf91ba
#include "settingsfilewrapper.h"
#include "applicationdata.h"
#include "errornotifier.h"
#include "usermanagment.h"
#include <QDesktopServices>
#include <QUrl>
void
SettingsFileWrapper
::
setStatus
(
SettingsFileWrapper
::
Status
status
)
{
if
(
this
->
status
!=
status
)
{
this
->
status
=
status
;
emit
statusChanged
();
}
}
void
SettingsFileWrapper
::
setErrorMessage
(
const
QString
&
errorMessage
)
{
if
(
this
->
errorMessage
!=
errorMessage
)
{
this
->
errorMessage
=
errorMessage
;
emit
errorMessageChanged
();
}
}
void
SettingsFileWrapper
::
loadFile
(
const
QString
&
filepath
)
{
Q_ASSERT
(
status
!=
Loaded
);
settings
.
setJsonSettingsFilePath
(
filepath
);
auto
[
after
,
error
]
=
ApplicationData
::
loadData
(
filepath
);
if
(
error
.
isEmpty
())
{
after
();
UserManagment
::
get
()
->
autoLoginUser
();
setStatus
(
Loaded
);
}
else
{
setErrorMessage
(
error
);
setStatus
(
LoadingFailed
);
}
}
bool
SettingsFileWrapper
::
openFileInDefaultEditor
()
{
return
QDesktopServices
::
openUrl
(
QUrl
::
fromLocalFile
(
settings
.
getJsonSettingsFilePath
()));
}
void
SettingsFileWrapper
::
openFileExplorerAtFile
()
{
QDesktopServices
::
openUrl
(
QUrl
::
fromLocalFile
(
QFileInfo
(
settings
.
getJsonSettingsFilePath
()).
path
()));
}
src/settingsfilewrapper.h
0 → 100644
View file @
d5bf91ba
#ifndef SETTINGSFILEWRAPPER_H
#define SETTINGSFILEWRAPPER_H
#include "settings.h"
#include <QObject>
/**
* @brief The SettingsFileWrapper class wrapps the status of the settings file for QML
*/
class
SettingsFileWrapper
:
public
QObject
{
Q_OBJECT
public:
enum
Status
{
Loaded
,
NoFile
,
LoadingFailed
,
NotLoaded
};
Q_ENUM
(
Status
)
private:
Settings
&
settings
;
QString
errorMessage
;
Q_PROPERTY
(
QString
errorMessage
READ
getErrorMessage
NOTIFY
errorMessageChanged
)
Q_PROPERTY
(
Status
status
READ
getStatus
NOTIFY
statusChanged
)
Status
status
=
NotLoaded
;
public:
explicit
SettingsFileWrapper
(
Settings
&
settings
)
:
settings
(
settings
)
{}
[[
nodiscard
]]
Status
getStatus
()
const
{
return
status
;
}
void
setStatus
(
Status
status
);
[[
nodiscard
]]
QString
getErrorMessage
()
const
{
return
errorMessage
;
}
void
setErrorMessage
(
const
QString
&
errorMessage
);
Q_INVOKABLE
void
loadFile
(
const
QString
&
filepath
);
Q_INVOKABLE
void
reload
()
{
loadFile
(
settings
.
getJsonSettingsFilePath
());
}
Q_INVOKABLE
bool
openFileInDefaultEditor
();
Q_INVOKABLE
void
openFileExplorerAtFile
();
signals:
void
statusChanged
();
void
errorMessageChanged
();
};
#endif // SETTINGSFILEWRAPPER_H
src/usermanagment.h
View file @
d5bf91ba
...
...
@@ -82,6 +82,7 @@ public:
SAVE_SLIDE_SHOW_SETTINGS
=
28
,
CHANGE_SYSTEM_VOLUME
=
29
,
ENABLE_REMOTE_VOLUME_CONTROL
=
30
,
CHANGE_STARTUP_VOLUME
=
31
,
};
Q_ENUM
(
Permission
)
/**
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment