From 0b870d85f4a521163f35bc15a19b29a0a2dff470 Mon Sep 17 00:00:00 2001 From: 0xFEEDC0DE64 Date: Sat, 4 Mar 2023 20:19:10 +0100 Subject: [PATCH] Preset steps can be added/removed --- DeviceTypesSettingsPage.qml | 64 +++++++++--- DevicesSettingsPage.qml | 10 +- PresetsSettingsPage.qml | 54 ++++++++-- dmxcontroller.h | 3 + presetstepsmodel.cpp | 190 +++++++++++++++++++++++++++++++++--- presetstepsmodel.h | 7 ++ 6 files changed, 289 insertions(+), 39 deletions(-) diff --git a/DeviceTypesSettingsPage.qml b/DeviceTypesSettingsPage.qml index 47a87a0..1dde322 100644 --- a/DeviceTypesSettingsPage.qml +++ b/DeviceTypesSettingsPage.qml @@ -45,7 +45,7 @@ ColumnLayout { modal: true title: qsTr('Confirmation') - onAccepted: deviceTypesModel.removeRow(index) + onAccepted: if (!deviceTypesModel.removeRow(index)) console.warn('failed'); Label { id: textContainer @@ -62,6 +62,8 @@ ColumnLayout { } ColumnLayout { + Layout.preferredWidth: 300 + Layout.maximumWidth: 300 Layout.fillHeight: true enabled: deviceTypesListView.currentIndex !== -1 @@ -77,6 +79,7 @@ ColumnLayout { } Label { text: qsTr("Name:") } TextField { + Layout.fillWidth: true text: deviceTypesListView.currentData ? deviceTypesListView.currentData.name : '' onTextEdited: if (deviceTypesListView.currentData) deviceTypesListView.currentData.name = text; else console.warn('discarded'); } @@ -109,34 +112,61 @@ ColumnLayout { } } - Pane { + EditableListView { + id: registersListView + Layout.preferredWidth: 300 + Layout.maximumWidth: 300 Layout.fillHeight: true enabled: deviceTypesListView.currentIndex !== -1 - Material.elevation: 6 + textRole: 'registerTypeName' - EditableListView { - id: registersListView - anchors.fill: parent + model: DeviceTypeRegistersModel { + id: registersModel + controller: __controller - textRole: 'registerTypeName' + deviceTypeId: deviceTypesListView.currentData ? deviceTypesListView.currentData.id : -1 + } - model: DeviceTypeRegistersModel { - id: registersModel - controller: __controller + onAddClicked: (index) => { const newIndex = index < 0 ? 0 : index + 1; if (registersModel.insertRow(newIndex)) currentIndex = newIndex; else console.warn('failed'); } + onRemoveClicked: (index) => { + const dialog = dialogComponent2.createObject(Overlay.overlay); + dialog.index = index; + dialog.open(); + } - deviceTypeId: deviceTypesListView.currentData ? deviceTypesListView.currentData.id : -1 + Component { + id: dialogComponent2 + + Dialog { + property int index + + anchors.centerIn: parent + standardButtons: DialogButtonBox.Yes | DialogButtonBox.Cancel + modal: true + title: qsTr('Confirmation') + + onAccepted: if (!registersModel.removeRow(index)) console.warn('failed'); + + Label { + id: textContainer + + anchors.fill: parent + + horizontalAlignment: Qt.AlignLeft + verticalAlignment: Qt.AlignTop + + text: qsTr('Are you sure you want to remove row %0').arg(index) + } } - - onAddClicked: (index) => { const newIndex = index < 0 ? 0 : index + 1; if (registersModel.insertRow(newIndex)) currentIndex = newIndex; else console.warn('failed'); } - onRemoveClicked: (index) => registersModel.removeRow(index) } } ColumnLayout { - //Layout.fillWidth: true + Layout.preferredWidth: 300 + Layout.maximumWidth: 300 Layout.fillHeight: true enabled: registersListView.currentIndex >= 0 @@ -163,5 +193,9 @@ ColumnLayout { Layout.fillHeight: true } } + + Item { + Layout.fillWidth: true + } } } diff --git a/DevicesSettingsPage.qml b/DevicesSettingsPage.qml index 424e889..95235a1 100644 --- a/DevicesSettingsPage.qml +++ b/DevicesSettingsPage.qml @@ -48,7 +48,7 @@ ColumnLayout { modal: true title: qsTr('Confirmation') - onAccepted: model.removeRow(index) + onAccepted: if (!model.removeRow(index)) console.warn('failed'); Label { id: textContainer @@ -82,13 +82,13 @@ ColumnLayout { enabled: false Layout.fillWidth: true value: listView.currentData ? listView.currentData.id : -1 - onValueModified: listView.currentData.id = value + onValueModified: if (listView.currentData) listView.currentData.id = value; else console.warn('discarded'); } Label { text: qsTr("Name:") } TextField { Layout.fillWidth: true text: listView.currentData ? listView.currentData.name : '' - onTextEdited: listView.currentData.name = text + onTextEdited: if (listView.currentData) listView.currentData.name = text; else console.warn('discarded'); } Label { text: qsTr("DeviceType:") } IconComboBox { @@ -112,7 +112,7 @@ ColumnLayout { to: 512 Layout.fillWidth: true value: listView.currentData ? listView.currentData.address : -1 - onValueModified: listView.currentData.address = value + onValueModified: if (listView.currentData) listView.currentData.address = value; else console.warn('discarded'); } Label { Layout.alignment: Qt.AlignTop | Qt.AlignLeft @@ -121,7 +121,7 @@ ColumnLayout { Vector3DField { id: positionField Layout.fillWidth: true - onValueModified: listView.currentData.position = value; + onValueModified: if (listView.currentData) listView.currentData.position = value; else console.warn('discarded'); // TODO solve without onCurrentDataChanged } } diff --git a/PresetsSettingsPage.qml b/PresetsSettingsPage.qml index eb5d698..2bb2f45 100644 --- a/PresetsSettingsPage.qml +++ b/PresetsSettingsPage.qml @@ -44,7 +44,7 @@ ColumnLayout { modal: true title: qsTr('Confirmation') - onAccepted: presetsModel.removeRow(index) + onAccepted: if (!presetsModel.removeRow(index)) console.warn('failed'); Label { id: textContainer @@ -61,6 +61,8 @@ ColumnLayout { } ColumnLayout { + Layout.preferredWidth: 300 + Layout.maximumWidth: 300 Layout.fillHeight: true enabled: presetsListView.currentIndex !== -1 @@ -76,6 +78,7 @@ ColumnLayout { } Label { text: qsTr("Name:") } TextField { + Layout.fillWidth: true text: presetsListView.currentData ? presetsListView.currentData.name : '' onTextEdited: if (presetsListView.currentData) presetsListView.currentData.name = text; else console.warn('discarded'); } @@ -86,24 +89,61 @@ ColumnLayout { } } - PresetModel { - id: presetModel - controller: __controller - presetId: presetsListView.currentData ? presetsListView.currentData.id : -1 - } - EditableListView { + Layout.fillWidth: true + enabled: presetsListView.currentIndex !== -1 model: PresetStepsModel { + id: presetStepsModel + controller: __controller presetId: presetsListView.currentData ? presetsListView.currentData.id : -1 } + + onAddClicked: (index) => { const newIndex = index < 0 ? 0 : index + 1; if (presetStepsModel.insertRow(newIndex)) currentIndex = newIndex; else console.warn('failed'); } + onRemoveClicked: (index) => { + const dialog = dialogComponent2.createObject(Overlay.overlay); + dialog.index = index; + dialog.open(); + } + + Component { + id: dialogComponent2 + + Dialog { + property int index + + anchors.centerIn: parent + standardButtons: DialogButtonBox.Yes | DialogButtonBox.Cancel + modal: true + title: qsTr('Confirmation') + + onAccepted: if (!presetStepsModel.removeRow(index)) console.warn('failed'); + + Label { + id: textContainer + + anchors.fill: parent + + horizontalAlignment: Qt.AlignLeft + verticalAlignment: Qt.AlignTop + + text: qsTr('Are you sure you want to remove row %0').arg(index) + } + } + } } ColumnLayout { Layout.fillWidth: true + PresetModel { + id: presetModel + controller: __controller + presetId: presetsListView.currentData ? presetsListView.currentData.id : -1 + } + RowLayout { Button { text: qsTr('Auf Schieberegler\nunten kopieren'); diff --git a/dmxcontroller.h b/dmxcontroller.h index 71fa8d8..a2cdc2d 100644 --- a/dmxcontroller.h +++ b/dmxcontroller.h @@ -74,6 +74,9 @@ signals: void presetRemoved(int first, int last); void presetNameChanged(int row, const QString &name); + void presetStepInserted(const PresetConfig &preset, int first, int last); + void presetStepRemoved(const PresetConfig &preset, int first, int last); + void sliderStatesChanged(const sliders_state_t &sliderStates); protected: diff --git a/presetstepsmodel.cpp b/presetstepsmodel.cpp index 458adad..712ceb0 100644 --- a/presetstepsmodel.cpp +++ b/presetstepsmodel.cpp @@ -11,24 +11,24 @@ void PresetStepsModel::setController(DmxController *controller) if (m_controller) { -// disconnect(m_controller, &DmxController::presetRegisterInserted, -// this, &PresetStepsModel::otherPresetRegisterInserted); -// disconnect(m_controller, &DmxController::presetRegisterRemoved, -// this, &PresetStepsModel::otherPresetRegisterRemoved); -// disconnect(m_controller, &DmxController::presetRegisterTypeChanged, -// this, &PresetStepsModel::otherPresetRegisterTypeChanged); + disconnect(m_controller, &DmxController::presetStepInserted, + this, &PresetStepsModel::otherPresetStepInserted); + disconnect(m_controller, &DmxController::presetStepRemoved, + this, &PresetStepsModel::otherPresetStepRemoved); +// disconnect(m_controller, &DmxController::presetStepTypeChanged, +// this, &PresetStepsModel::otherPresetStepTypeChanged); } m_controller = controller; if (m_controller) { -// connect(m_controller, &DmxController::presetRegisterInserted, -// this, &PresetStepsModel::otherPresetRegisterInserted); -// connect(m_controller, &DmxController::presetRegisterRemoved, -// this, &PresetStepsModel::otherPresetRegisterRemoved); -// connect(m_controller, &DmxController::presetRegisterTypeChanged, -// this, &PresetStepsModel::otherPresetRegisterTypeChanged); + connect(m_controller, &DmxController::presetStepInserted, + this, &PresetStepsModel::otherPresetStepInserted); + connect(m_controller, &DmxController::presetStepRemoved, + this, &PresetStepsModel::otherPresetStepRemoved); +// connect(m_controller, &DmxController::presetStepTypeChanged, +// this, &PresetStepsModel::otherPresetStepTypeChanged); } endResetModel(); @@ -184,3 +184,169 @@ QHash PresetStepsModel::roleNames() const { Qt::DisplayRole, "name" }, }; } + +bool PresetStepsModel::insertRows(int row, int count, const QModelIndex &parent) +{ + if (parent.isValid()) + { + qWarning() << "hilfe" << __LINE__; + return false; + } + + if (!m_controller) + { + qWarning() << "hilfe" << __LINE__; + return false; + } + + if (m_presetId == -1) + { + qWarning() << "hilfe" << __LINE__; + return false; + } + + auto &presets = m_controller->lightProject().presets; + auto presetPtr = presets.findById(m_presetId); + if (!presetPtr) + { + qWarning() << "hilfe" << __LINE__; + return false; + } + + auto &preset = *presetPtr; + + if (row < 0) + { + qWarning() << "hilfe" << __LINE__; + return false; + } + + auto &steps = preset.steps; + + beginInsertRows({}, row, row+count-1); + { + QMutexLocker locker{&m_controller->mutex()}; + auto iter = std::begin(steps) + row; + for (auto i = 0; i < count; i++) + iter = steps.insert(iter, PresetStepConfig{}) + 1; + } + endInsertRows(); + + disconnect(m_controller, &DmxController::presetStepInserted, + this, &PresetStepsModel::otherPresetStepInserted); + emit m_controller->presetStepInserted(preset, row, row+count-1); + connect(m_controller, &DmxController::presetStepInserted, + this, &PresetStepsModel::otherPresetStepInserted); + + return true; +} + +bool PresetStepsModel::removeRows(int row, int count, const QModelIndex &parent) +{ + if (parent.isValid()) + { + qWarning() << "hilfe" << __LINE__; + return false; + } + + if (!m_controller) + { + qWarning() << "hilfe" << __LINE__; + return false; + } + + if (m_presetId == -1) + { + qWarning() << "hilfe" << __LINE__; + return false; + } + + auto &presets = m_controller->lightProject().presets; + auto presetPtr = presets.findById(m_presetId); + if (!presetPtr) + { + qWarning() << "hilfe" << __LINE__; + return false; + } + + auto &preset = *presetPtr; + + if (row < 0) + { + qWarning() << "hilfe" << __LINE__; + return false; + } + + auto &steps = preset.steps; + + if (row >= steps.size()) + { + qWarning() << "hilfe" << __LINE__; + return false; + } + + if (row + count > steps.size()) + { + qWarning() << "hilfe" << __LINE__; + return false; + } + + beginRemoveRows({}, row, row+count-1); + { + QMutexLocker locker{&m_controller->mutex()}; + auto begin = std::begin(steps) + row; + auto end = begin + count; + steps.erase(begin, end); + } + endRemoveRows(); + + disconnect(m_controller, &DmxController::presetStepRemoved, + this, &PresetStepsModel::otherPresetStepRemoved); + emit m_controller->presetStepRemoved(preset, row, row+count-1); + connect(m_controller, &DmxController::presetStepRemoved, + this, &PresetStepsModel::otherPresetStepRemoved); + + return true; +} + +void PresetStepsModel::otherPresetStepInserted(const PresetConfig &preset, int first, int last) +{ + if (!m_controller) + { + qWarning() << "hilfe" << __LINE__; + return; + } + + if (m_presetId == -1) + { + qWarning() << "hilfe" << __LINE__; + return; + } + + if (m_presetId != preset.id) + return; + + beginInsertRows({}, first, last); + endInsertRows(); +} + +void PresetStepsModel::otherPresetStepRemoved(const PresetConfig &preset, int first, int last) +{ + if (!m_controller) + { + qWarning() << "hilfe" << __LINE__; + return; + } + + if (m_presetId == -1) + { + qWarning() << "hilfe" << __LINE__; + return; + } + + if (m_presetId != preset.id) + return; + + beginRemoveRows({}, first, last); + endRemoveRows(); +} diff --git a/presetstepsmodel.h b/presetstepsmodel.h index 47c228c..1a2ece7 100644 --- a/presetstepsmodel.h +++ b/presetstepsmodel.h @@ -27,10 +27,17 @@ public: QMap itemData(const QModelIndex &index) const override; QHash roleNames() const override; + bool insertRows(int row, int count, const QModelIndex &parent) override; + bool removeRows(int row, int count, const QModelIndex &parent) override; + signals: void controllerChanged(DmxController *controller); void presetIdChanged(int presetId); +private slots: + void otherPresetStepInserted(const PresetConfig &preset, int first, int last); + void otherPresetStepRemoved(const PresetConfig &preset, int first, int last); + private: DmxController *m_controller{}; int m_presetId{-1};