Commit 0bbfb0fb authored by Leander Schulten's avatar Leander Schulten

Merge branch 'master' into windows-release

parents 54dfc045 24dc8b2f
Pipeline #206258 passed with stages
in 6 minutes and 37 seconds
......@@ -10,6 +10,9 @@ RESOURCES += qml.qrc
DEFINES += CONVERT_FROM_SPOTIFY_OBJECTS
# we always want to have context information in log messages.
DEFINES += QT_MESSAGELOGCONTEXT
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
......
#include "remotevolume.h"
#include "systemvolume.h"
#include <QTimerEvent>
#include <QtDebug>
RemoteVolume::RemoteVolume(Settings &settings) : settings(settings) {
QObject::connect(&settings, &Settings::computerNameChanged, [this]() {
......@@ -14,12 +16,33 @@ RemoteVolume::RemoteVolume(Settings &settings) : settings(settings) {
}
} else {
webSocket.close();
// if we were in reconnection mode, stop the timer
if (reconnectTimerId >= 0) {
killTimer(reconnectTimerId);
reconnectTimerId = -1;
}
}
});
QObject::connect(&webSocket, qOverload<QAbstractSocket::SocketError>(&QWebSocket::error), [this](const auto error) { qWarning() << "Remote Volume: WebSocket connection error: " << error << " : " << webSocket.errorString(); });
QObject::connect(&webSocket, &QWebSocket::disconnected, [this]() {
emit isConnectedChanged();
// if we lost the connection, but don't want that, wait some time and reconnect then
if (this->settings.remoteVolumeControl()) {
if (reconnectTimerId == -1) {
startTimer(WAIT_FOR_RECONNECT_MS);
}
}
});
QObject::connect(&webSocket, &QWebSocket::connected, [this]() {
webSocket.sendTextMessage("Name:" + this->settings.getComputerName());
webSocket.sendTextMessage("Value:" + QString::number(SystemVolume::get().getVolume()));
emit isConnectedChanged();
// if we were in reconnection mode, stop the timer
if (reconnectTimerId >= 0) {
killTimer(reconnectTimerId);
reconnectTimerId = -1;
}
});
QObject::connect(&webSocket, &QWebSocket::textMessageReceived, [](const QString &message) {
bool ok;
......@@ -41,3 +64,10 @@ RemoteVolume::RemoteVolume(Settings &settings) : settings(settings) {
void RemoteVolume::connect() {
webSocket.open(QUrl(QStringLiteral("wss://orga.symposion.hilton.rwth-aachen.de/volumeClient")));
}
void RemoteVolume::timerEvent(QTimerEvent *event) {
if (event->timerId() == reconnectTimerId) {
event->accept();
connect();
}
}
#ifndef REMOTEVOLUME_H
#define REMOTEVOLUME_H
#include <QObject>
#include <QWebSocket>
#include <settings.h>
class RemoteVolume
{
class RemoteVolume : public QObject {
Q_OBJECT
QWebSocket webSocket;
Settings &settings;
int reconnectTimerId = -1;
static constexpr int WAIT_FOR_RECONNECT_MS = 5 * 1000;
Q_PROPERTY(bool isConnected READ isConnected NOTIFY isConnectedChanged)
public:
RemoteVolume(Settings &settings);
explicit RemoteVolume(Settings &settings);
void connect();
[[nodiscard]] bool isConnected() const { return webSocket.isValid(); }
protected:
void timerEvent(QTimerEvent *event) override;
signals:
void isConnectedChanged();
};
#endif // REMOTEVOLUME_H
......@@ -739,7 +739,6 @@ int CodeEditorHelper::countSpaces(int startPos) {
}
void CodeEditorHelper::contentsChange(int from, int charsRemoved, int charsAdded){
qDebug() << "pos " << from << " removed : " << charsRemoved << " added : " << charsAdded;
// remove all markups thats gets modified and move the others
const int lineDiff = document->lineCount() - lastLineCount;
for(auto i = codeMarkups.cbegin(); i != codeMarkups.cend();++i){
......
......@@ -134,7 +134,6 @@ public:
if(_document != documentWrapper){
documentWrapper = _document;
emit documentChanged();
qDebug() << "add connection";
if(documentWrapper){
QObject::connect(documentWrapper->textDocument(),&QTextDocument::contentsChange,this,&CodeEditorHelper::contentsChange);
document = documentWrapper->textDocument();
......
......@@ -12,7 +12,6 @@ std::pair<Polygon *,Polygon *> generateBar(){
auto addRightFixTop = [=](Polygon::Point::number_type startX, Polygon::Point::number_type startY){
return [=](Polygon::Point::number_type width, Polygon::Point::number_type height)mutable{
p->addRectangle(startX,startX+width,startY,startY+height);
qDebug() << startX << ", " << startX+width << ", " << startY << ", " << startY+height;
startX += width;
};
};
......
......@@ -76,6 +76,16 @@ extern "C" void signal_handler(int /*sig*/) {
}
#endif
QFile logOutput;
QtMessageHandler defaultMessageHandler = nullptr;
void toFileMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) {
logOutput.write(qFormatLogMessage(type, context, msg).replace(QLatin1String("file://"), "").toUtf8());
logOutput.write("\n");
logOutput.flush();
defaultMessageHandler(type, context, msg);
}
int main(int argc, char *argv[]) {
QSharedMemory mem(QStringLiteral("Lichteuerung Leander Schulten"));
{ // check if the app is alreandy running or should be restarted
......@@ -119,15 +129,21 @@ int main(int argc, char *argv[]) {
std::signal(SIGABRT, signal_handler);
std::signal(SIGFPE, signal_handler);
#endif
// set logging pattern: https://doc.qt.io/qt-5/qtglobal.html#qSetMessagePattern
qSetMessagePattern(QStringLiteral("[%{time h:mm:ss.zzz}] %{type} %{if-category}%{category}: %{endif}file://%{file}:%{line} (%{function}): %{message}"));
// init DrMinGW and file logger base path
const auto basePath = QStandardPaths::writableLocation(QStandardPaths::QStandardPaths::AppDataLocation) + QStringLiteral("/Lichtsteuerung");
if (!QDir().mkpath(basePath)) {
qWarning() << "Error creating dirs : " << basePath;
} else {
logOutput.setFileName(basePath + "/log_" + QDateTime::currentDateTime().toString(QStringLiteral("dd.MM.yyyy HH.mm.ss")) + ".txt");
if (logOutput.open(QFile::WriteOnly)) {
defaultMessageHandler = qInstallMessageHandler(toFileMessageHandler);
}
}
#ifdef DrMinGW
ExcHndlInit();
auto path = QStandardPaths::writableLocation(QStandardPaths::QStandardPaths::AppDataLocation);
path += QLatin1String("/Lichtsteuerung");
QDir dir(path);
if(!dir.mkpath(path)){
qWarning() << "Error creating dirs : " << path;
}
path += QLatin1String("/crash_dump_");
auto path = basePath + QStringLiteral("/crash_dump_");
path += QDateTime::currentDateTime().toString(QStringLiteral("dd.MM.yyyy HH.mm.ss"));
path += QLatin1String(".txt");
qDebug() << "The crash report file is : " << path;
......@@ -144,7 +160,7 @@ int main(int argc, char *argv[]) {
});
#ifdef DrMinGW
// send crash reports
auto files = dir.entryInfoList(QDir::Filter::Files);
auto files = QDir(basePath).entryInfoList(QDir::Filter::Files);
for(auto & file : files){
if(file.fileName().startsWith(QLatin1String("crash_dump"))){
auto newFileName = file.absolutePath() + "/sended_" +file.fileName();
......
......@@ -184,7 +184,6 @@ typedef Modules::Program* (*CreateProgramm)(unsigned int index);
if(!QLibrary::isLibrary(name))
return;
qDebug()<<"load lib : " << name;
QLibrary lib(name);
if(lib.load()){
Have_Func f = reinterpret_cast<Have_Func>(lib.resolve("have"));
......@@ -274,7 +273,6 @@ typedef Modules::Program* (*CreateProgramm)(unsigned int index);
loadedLibraryMap.emplace_back(lib.fileName(),LibInfo{lastLibraryIdentifier,supportAudioFunc});
qDebug() << lib.errorString();
}else{
#ifdef Q_OS_WIN
if(lib.errorString().endsWith("Unknown error 0x000000c1.")){
......@@ -285,32 +283,21 @@ typedef Modules::Program* (*CreateProgramm)(unsigned int index);
}
}
void ModuleManager::loadAllModulesInDir(QDir dir){
qDebug() << dir;
for(auto s : dir.entryInfoList(QDir::Files)){
if(s.suffix() == "old"){
void ModuleManager::loadAllModulesInDir(const QDir &dir) {
for (const auto &s : dir.entryInfoList(QDir::Files)) {
if (s.suffix() == QLatin1String("old")) {
QFile::remove(s.filePath());
}
if(QLibrary::isLibrary(s.fileName())){
if (QLibrary::isLibrary(s.fileName())) {
loadModule(s.absoluteFilePath());
}
//qDebug()<<"found : " << s;
}
for(auto s : dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)){
for (const auto &s : dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) {
loadAllModulesInDir(s);
}
for(const auto & m : getProgrammModules())
qDebug() << m.name().c_str();
for(const auto & m : getFilterModules())
qDebug() << m.name().c_str();
for(const auto & m : getConsumerModules())
qDebug() << m.name().c_str();
}
ModuleManager::SupportAudioFunc ModuleManager::loadAudio(QLibrary & lib, Modules::FFTOutputView<float> * fftOutputView){
ModuleManager::SupportAudioFunc ModuleManager::loadAudio(QLibrary &lib, Modules::FFTOutputView<float> *fftOutputView) {
//typedef void (*SupportAudioFunc )(bool);
typedef void (*SetFFTOutputViewFunc )(Modules::FFTOutputView<float>*);
//using SupportAudioFunc = unsigned int (bool);
......@@ -325,6 +312,4 @@ typedef Modules::Program* (*CreateProgramm)(unsigned int index);
supportAudioFunc(Audio::AudioCaptureManager::get().isCapturing());
return supportAudioFunc;
}
}
} // namespace Modules
......@@ -39,9 +39,9 @@ namespace detail {
Q_PROPERTY(QString name READ getName WRITE setName NOTIFY nameChanged)
Q_PROPERTY(QString description READ getDescription WRITE setDescription NOTIFY descriptionChanged)
Q_PROPERTY(Type type READ getType WRITE setType NOTIFY typeChanged)
Q_PROPERTY(int minValue MEMBER min)
Q_PROPERTY(int maxValue MEMBER max)
Q_PROPERTY(int defaultValue MEMBER defaultValue)
Q_PROPERTY(int minValue MEMBER min NOTIFY minChanged)
Q_PROPERTY(int maxValue MEMBER max NOTIFY maxChanged)
Q_PROPERTY(int defaultValue MEMBER defaultValue NOTIFY defaultChanged)
PropertyInformation() = default;
PropertyInformation(const QJsonObject &o);
void writeJsonObject(QJsonObject &o)const;
......@@ -79,6 +79,9 @@ namespace detail {
void nameChanged();
void descriptionChanged();
void typeChanged();
void minChanged();
void maxChanged();
void defaultChanged();
};
}
......@@ -307,7 +310,7 @@ signals:
* @param replaceOldModulesInProgramBlocks if new programs/filters/consumers are loaded old programs/filters/consumers can be replaced, but they can now have another name, so you have to provide a function that maps new names to the old names to replace them. If no function is provided, no modules gets replaced
*/
void loadModule(QString fileNamePath, std::function<std::string(const std::string&)> replaceOldModulesInProgramBlocks = std::function<std::string(const std::string&)>());
void loadAllModulesInDir(QDir name);
void loadAllModulesInDir(const QDir &name);
ModelVector<Module*>* getModules(){return &modules;}
const ProgrammModuleContainer & getProgrammModules(){return programms;}
const FilterModuleContainer & getFilterModules(){return filter;}
......
......@@ -212,7 +212,10 @@ ControlPanel{
property DimmerGroupControl dimmerControl: null
property DimmerGroupControl programControl: null
property DimmerGroupControl control: null
helpButton.anchors.right: programm.left
Component.onCompleted: {
helpButton.anchors.left = parent.left;
helpButton.anchors.bottom = parent.bottom;
}
enableAnimations: false
tooltipText: "Control Pane Explanation"
onStart: {
......
......@@ -125,6 +125,9 @@ ModelView{
property int currentDMXChannel: deviceModelView.currentModelData ? deviceModelView.currentModelData.startDMXChannel : -1
onCurrentDMXChannelChanged: {
let v = currentDMXChannel;
if (v === -1) {
return;
}
for(let i = 8; i >= 0; --i){
const expo = Math.pow(2,i);
visibleChildren[i + 1].on = v >= expo;
......
......@@ -7,7 +7,7 @@ import "../components"
ModelView{
model:programmModel
id:modelView
rows: 9
rows: 10
rowSpacing: 2
addButton.text: "Add Programm"
removeButton.text: "Remove Programm"
......@@ -74,17 +74,16 @@ ModelView{
anchors.top: topTD.top
anchors.bottom: endTD.bottom
anchors.right: beginTD.left
color: "lightgreen"
color: Material.accentColor
width: 2
anchors.margins: 2
anchors.leftMargin: 6
Layout.preferredHeight: 0
}
ListView{
clip:true
Layout.column: 2
Layout.columnSpan: 2
Layout.row: 7
Layout.fillHeight: true
Layout.fillWidth: true
......@@ -151,8 +150,6 @@ ModelView{
RowLayout{
Layout.row: 8
Layout.column: 2
Layout.columnSpan: 2
Layout.fillWidth: true
Button{
......@@ -187,6 +184,7 @@ ModelView{
id:device
model: deviceModel
textRole: "display"
currentIndex: 0
}
......
......@@ -9,8 +9,6 @@ RoundButton {
ToolTip.text: tooltipText
ToolTip.delay: 500
anchors.right: parent.right
anchors.bottom: parent.bottom
opacity: hovered ? 1 : defaultOpacity
hoverEnabled: true
Behavior on opacity{
......
......@@ -122,11 +122,11 @@ Item{
RoundButton{
id: button_startStop
icon.source: programEditor.programBlock.status === 1 ? "qrc:icons/stop.svg" : programEditor.programBlock.status === 0 ? "qrc:icons/play.svg":"qrc:icons/replay.svg"
icon.source: programEditor.programBlock ? programEditor.programBlock.status === 1 ? "qrc:icons/stop.svg" : programEditor.programBlock.status === 0 ? "qrc:icons/play.svg":"qrc:icons/replay.svg" : ""
anchors.bottom: parent.bottom
anchors.leftMargin: 15
anchors.left: parent.left
checked: programEditor.programBlock.status === 1
checked: programEditor.programBlock ? programEditor.programBlock.status === 1 : false
onClicked: {
if(programEditor.programBlock.status === 0){
programEditor.programBlock.start();
......@@ -138,13 +138,13 @@ Item{
}
ToolTip.visible: hovered
ToolTip.delay: 1000
ToolTip.text: programEditor.programBlock.status === 1 ? "Stop" : programEditor.programBlock.status === 0 ? "Play":"Replay"
ToolTip.text: !programEditor.programBlock ? "null" : programEditor.programBlock.status === 1 ? "Stop" : programEditor.programBlock.status === 0 ? "Play":"Replay"
}
RoundButton{
id: button_pauseResume
icon.source: programEditor.programBlock.status === 1 ? "qrc:icons/pause.svg" : "qrc:icons/resume.png"
visible: programEditor.programBlock.status !== 0;
checked: programEditor.programBlock.status === 1
icon.source: programEditor.programBlock && programEditor.programBlock.status === 1 ? "qrc:icons/pause.svg" : "qrc:icons/resume.png"
visible: programEditor.programBlock && programEditor.programBlock.status !== 0;
checked: programEditor.programBlock && programEditor.programBlock.status === 1
anchors.bottom: parent.bottom
anchors.leftMargin: 15
anchors.left: button_startStop.right
......@@ -157,7 +157,7 @@ Item{
}
ToolTip.visible: hovered
ToolTip.delay: 1000
ToolTip.text: programEditor.programBlock.status === 1 ? "Pause" : "Resume"
ToolTip.text: programEditor.programBlock && programEditor.programBlock.status === 1 ? "Pause" : "Resume"
}
RoundButton{
......
......@@ -604,7 +604,7 @@ Item{
leftPadding: header.leftPadding
rightPadding: footer.rightPadding
bottomPadding: 0
x: (Window.window.width-width)/2;
x: (Overlay.overlay.width-width)/2;
y: (root.height-height)/2;
property alias text: dialogText.text
onAboutToShow: {
......@@ -652,7 +652,7 @@ Item{
TextInputField{
id:name
Layout.fillWidth: true
text:dialog.prop.name
text: dialog.prop ? dialog.prop.name : "Error"
validator: RegExpValidator{
regExp: /[a-z][a-z_0-9]*$/i
}
......@@ -663,13 +663,13 @@ Item{
TextInputField{
id:besch
Layout.fillWidth: true
text:dialog.prop.description
text: dialog.prop ? dialog.prop.description : "Error"
}
Label{
text:"Typ"
}
ComboBox{
currentIndex: dialog.prop.type
currentIndex: dialog.prop ? dialog.prop.type : -1
id:type
model: modolePropertyTypeList
Layout.fillWidth: true
......@@ -687,7 +687,7 @@ Item{
Layout.fillWidth: true
id: minVal
validator: IntValidator{}
text:type.currentIndex === 4 ? "0" : type.currentIndex === 5 ? "" : dialog.prop.minValue
text: type.currentIndex === 4 ? "0" : type.currentIndex === 5 ? "" : (dialog.prop ? dialog.prop.minValue : "0")
}
Label{
......@@ -697,14 +697,14 @@ Item{
Layout.fillWidth: true
id:maxVal
validator: IntValidator{}
text:type.currentIndex === 4 ? "1" : type.currentIndex === 5 ? "" : dialog.prop.maxValue
text: type.currentIndex === 4 ? "1" : type.currentIndex === 5 ? "" : (dialog.prop ? dialog.prop.maxValue : "")
}
Label{
text:"default value"
}
TextInputField{
text: type.currentIndex !== 5 ? dialog.prop.defaultValue : ""
text: type.currentIndex !== 5 && dialog.prop ? dialog.prop.defaultValue : ""
Layout.fillWidth: true
id:defaultVal
enabled: type.currentIndex !== 5
......
......@@ -221,18 +221,21 @@ ScrollView{
ToolTip.text: "The order in which the images are displayed"
}
TextFieldFileChooser{
MouseArea {
Layout.fillWidth: true
folder: true
path: SlideShow.path
onPathChanged: SlideShow.path = path;
fileChooser: fileDialogLoader.item
MouseArea{
Layout.fillHeight: true
acceptedButtons: Qt.NoButton
hoverEnabled: true
ToolTip.visible: containsMouse
ToolTip.text: "The path to the folder with the images"
TextFieldFileChooser {
anchors.fill: parent
acceptedButtons: Qt.NoButton
hoverEnabled: true
ToolTip.visible: containsMouse
ToolTip.text: "The path to the folder with the images"
folder: true
path: SlideShow.path
onPathChanged: SlideShow.path = path;
fileChooser: fileDialogLoader.item
id: shouldBeParent
}
}
}
......
......@@ -134,8 +134,10 @@ ApplicationWindow {
text: qsTr("Audio Events")
}
Help{
helpButton.anchors.left: parent.left
helpButton.anchors.right: undefined
Component.onCompleted: {
helpButton.anchors.left = parent.left;
helpButton.anchors.bottom = parent.bottom;
}
tooltipText: "Tab Explanation"
enableAnimations: false
HelpEntry{
......
......@@ -191,7 +191,10 @@ void SlideShow::scanDirectory(const QString &path, bool recursive) {
}
void SlideShow::scanForNewFiles() {
watcher.removePaths(watcher.directories());
const auto dirs = watcher.directories();
if (!dirs.empty()) {
watcher.removePaths(dirs);
}
if (path.isEmpty()) {
return;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment