diff --git a/qmlui/inputoutputmanager.cpp b/qmlui/inputoutputmanager.cpp index 83809a3e5f..f338fe9722 100644 --- a/qmlui/inputoutputmanager.cpp +++ b/qmlui/inputoutputmanager.cpp @@ -29,6 +29,7 @@ #include "outputpatch.h" #include "inputpatch.h" #include "universe.h" +#include "qlcfile.h" #include "tardis.h" #include "doc.h" @@ -560,33 +561,9 @@ int InputOutputManager::outputPatchesCount(int universe) const * Input Profiles *********************************************************************/ -QVariant InputOutputManager::universeInputProfiles(int universe) +QString InputOutputManager::profileUserFolder() { - QVariantList profilesList; - QStringList profileNames = m_ioMap->profileNames(); - profileNames.sort(); - QDir pSysPath = m_ioMap->systemProfileDirectory(); - - foreach (QString name, profileNames) - { - QLCInputProfile *ip = m_ioMap->profile(name); - if (ip != nullptr) - { - QString type = ip->typeToString(ip->type()); - QVariantMap profileMap; - profileMap.insert("universe", universe); - profileMap.insert("name", name); - profileMap.insert("line", name); - profileMap.insert("plugin", type); - if (ip->path().startsWith(pSysPath.absolutePath())) - profileMap.insert("isUser", false); - else - profileMap.insert("isUser", true); - profilesList.append(profileMap); - } - } - - return QVariant::fromValue(profilesList); + return m_ioMap->userProfileDirectory().absolutePath(); } void InputOutputManager::createInputProfile() @@ -626,6 +603,23 @@ bool InputOutputManager::editInputProfile(QString name) return true; } +bool InputOutputManager::saveInputProfile() +{ + if (m_editProfile == nullptr) + return false; + + QDir dir(InputOutputMap::userProfileDirectory()); + QString absPath = QString("%1/%2-%3%4").arg(dir.absolutePath()) + .arg(m_editProfile->manufacturer()) + .arg(m_editProfile->model()) + .arg(KExtInputProfile); + + m_editProfile->saveXML(absPath); + m_profileEditor->setModified(false); + + return true; +} + void InputOutputManager::finishInputProfile() { if (m_editProfile != nullptr) @@ -641,6 +635,35 @@ void InputOutputManager::finishInputProfile() } } +QVariant InputOutputManager::universeInputProfiles(int universe) +{ + QVariantList profilesList; + QStringList profileNames = m_ioMap->profileNames(); + profileNames.sort(); + QDir pSysPath = m_ioMap->systemProfileDirectory(); + + foreach (QString name, profileNames) + { + QLCInputProfile *ip = m_ioMap->profile(name); + if (ip != nullptr) + { + QString type = ip->typeToString(ip->type()); + QVariantMap profileMap; + profileMap.insert("universe", universe); + profileMap.insert("name", name); + profileMap.insert("line", name); + profileMap.insert("plugin", type); + if (ip->path().startsWith(pSysPath.absolutePath())) + profileMap.insert("isUser", false); + else + profileMap.insert("isUser", true); + profilesList.append(profileMap); + } + } + + return QVariant::fromValue(profilesList); +} + /********************************************************************* * Beats *********************************************************************/ diff --git a/qmlui/inputoutputmanager.h b/qmlui/inputoutputmanager.h index c51745d504..3c11c60cd5 100644 --- a/qmlui/inputoutputmanager.h +++ b/qmlui/inputoutputmanager.h @@ -53,6 +53,8 @@ class InputOutputManager : public PreviewContext Q_PROPERTY(QString beatType READ beatType WRITE setBeatType NOTIFY beatTypeChanged) Q_PROPERTY(int bpmNumber READ bpmNumber WRITE setBpmNumber NOTIFY bpmNumberChanged) + Q_PROPERTY(QString profileUserFolder READ profileUserFolder CONSTANT) + public: InputOutputManager(QQuickView *view, Doc *doc, QObject *parent = 0); @@ -147,10 +149,13 @@ protected slots: * Input Profiles *********************************************************************/ public: - Q_INVOKABLE QVariant universeInputProfiles(int universe); + QString profileUserFolder(); + Q_INVOKABLE void createInputProfile(); Q_INVOKABLE bool editInputProfile(QString name); + Q_INVOKABLE bool saveInputProfile(); Q_INVOKABLE void finishInputProfile(); + Q_INVOKABLE QVariant universeInputProfiles(int universe); private: InputProfileEditor *m_profileEditor; diff --git a/qmlui/inputprofileeditor.cpp b/qmlui/inputprofileeditor.cpp index 5a5edb21e0..59404a11ea 100644 --- a/qmlui/inputprofileeditor.cpp +++ b/qmlui/inputprofileeditor.cpp @@ -60,7 +60,7 @@ QString InputProfileEditor::manufacturer() const void InputProfileEditor::setManufacturer(const QString &newManufacturer) { - if (m_profile == nullptr) + if (m_profile == nullptr || m_profile->manufacturer() == newManufacturer) return; m_profile->setManufacturer(newManufacturer); @@ -75,7 +75,7 @@ QString InputProfileEditor::model() const void InputProfileEditor::setModel(const QString &newModel) { - if (m_profile == nullptr) + if (m_profile == nullptr || m_profile->model() == newModel) return; m_profile->setModel(newModel); @@ -90,7 +90,7 @@ int InputProfileEditor::type() void InputProfileEditor::setType(const int &newType) { - if (m_profile == nullptr) + if (m_profile == nullptr || m_profile->type() == newType) return; m_profile->setType(QLCInputProfile::Type(newType)); diff --git a/qmlui/qml/fixtureeditor/qmldir b/qmlui/qml/fixtureeditor/qmldir index dda90f89dd..1696a64b84 100644 --- a/qmlui/qml/fixtureeditor/qmldir +++ b/qmlui/qml/fixtureeditor/qmldir @@ -7,6 +7,7 @@ ColorToolFull 0.1 ../ColorToolFull.qml ContextMenuEntry 0.1 ../ContextMenuEntry.qml CustomCheckBox 0.1 ../CustomCheckBox.qml CustomComboBox 0.1 ../CustomComboBox.qml +CustomPopupDialog 0.1 ../popup/CustomPopupDialog.qml CustomScrollBar 0.1 ../CustomScrollBar.qml CustomSpinBox 0.1 ../CustomSpinBox.qml CustomTextEdit 0.1 ../CustomTextEdit.qml diff --git a/qmlui/qml/inputoutput/InputProfileEditor.qml b/qmlui/qml/inputoutput/InputProfileEditor.qml index 02a07a6a80..088fa4b495 100644 --- a/qmlui/qml/inputoutput/InputProfileEditor.qml +++ b/qmlui/qml/inputoutput/InputProfileEditor.qml @@ -29,6 +29,49 @@ ColumnLayout { id: peContainer + property bool isEditing: false + + function showWarning() + { + messagePopup.message = qsTr("You are trying to edit a bundled input profile.
" + + "If you modify and save it, a new file will be stored in
" + + ioManager.profileUserFolder + "
and will override the bundled file.") + messagePopup.standardButtons = Dialog.Ok + messagePopup.open() + } + + function showSaveFirst() + { + messagePopup.message = qsTr("Do you wish to save the current profile first?\nChanges will be lost if you don't save them.") + messagePopup.standardButtons = Dialog.Yes | Dialog.No | Dialog.Cancel + messagePopup.open() + } + + CustomPopupDialog + { + id: messagePopup + standardButtons: Dialog.Ok + title: qsTr("!! Warning !!") + + onClicked: + { + if (role === Dialog.Yes) + { + // todo save + } + else if (role === Dialog.No) + { + ioManager.finishInputProfile() + isEditing = false + close() + } + else if (role === Dialog.Ok || role === Dialog.Cancel) + { + close() + } + } + } + Rectangle { implicitWidth: peContainer.width diff --git a/qmlui/qml/inputoutput/ProfilesList.qml b/qmlui/qml/inputoutput/ProfilesList.qml index 0120e490d4..f0c7f148c0 100644 --- a/qmlui/qml/inputoutput/ProfilesList.qml +++ b/qmlui/qml/inputoutput/ProfilesList.qml @@ -31,7 +31,6 @@ Rectangle color: "transparent" property int universeIndex: 0 - property bool isEditing: false onUniverseIndexChanged: { @@ -72,26 +71,26 @@ Rectangle { width: height height: topBar.height - 2 - visible: isEditing - enabled: isEditing && profileEditor.modified + visible: profEditor.isEditing + enabled: profEditor.isEditing && profileEditor.modified imgSource: "qrc:/filesave.svg" tooltip: qsTr("Save this profile") - onClicked: { } + onClicked: ioManager.saveInputProfile() } IconButton { width: height height: topBar.height - 2 - visible: isEditing + visible: profEditor.isEditing checkable: true imgSource: "qrc:/wizard.svg" tooltip: qsTr("Toggle the automatic detection procedure") onToggled: { - if (isEditing) + if (profEditor.isEditing) profileEditor.toggleDetection() } } @@ -101,18 +100,18 @@ Rectangle width: height height: topBar.height - 2 imgSource: "qrc:/add.svg" - tooltip: isEditing ? qsTr("Add a new channel") : qsTr("Create a new input profile") + tooltip: profEditor.isEditing ? qsTr("Add a new channel") : qsTr("Create a new input profile") onClicked: { - if (isEditing) + if (profEditor.isEditing) { } else { ioManager.createInputProfile() - isEditing = true + profEditor.isEditing = true } } } @@ -122,19 +121,21 @@ Rectangle width: height height: topBar.height - 2 imgSource: "qrc:/edit.svg" - tooltip: isEditing ? qsTr("Edit the selected channel") : qsTr("Edit the selected input profile") + tooltip: profEditor.isEditing ? qsTr("Edit the selected channel") : qsTr("Edit the selected input profile") enabled: profListView.selectedIndex >= 0 onClicked: { - if (isEditing) + if (profEditor.isEditing) { } else { ioManager.editInputProfile(profListView.selectedName) - isEditing = true + profEditor.isEditing = true + if (profListView.selectedIsUser == false) + profEditor.showWarning() } } } @@ -144,8 +145,8 @@ Rectangle width: height height: topBar.height - 2 imgSource: "qrc:/remove.svg" - tooltip: isEditing ? qsTr("Delete the selected channel") : qsTr("Delete the selected input profile(s)") - enabled: profListView.selectedIndex >= 0 + tooltip: profEditor.isEditing ? qsTr("Delete the selected channel") : qsTr("Delete the selected input profile(s)") + enabled: profListView.selectedIndex >= 0 && profListView.selectedIsUser onClicked: { } } @@ -156,15 +157,21 @@ Rectangle { width: height height: topBar.height - 2 - visible: isEditing + visible: profEditor.isEditing border.color: UISettings.bgMedium useFontawesome: true label: FontAwesome.fa_times onClicked: { - // todo popup for unsaved changes - ioManager.finishInputProfile() - isEditing = false + if (profileEditor.modified) + { + profEditor.showSaveFirst() + } + else + { + ioManager.finishInputProfile() + profEditor.isEditing = false + } } } } @@ -177,10 +184,11 @@ Rectangle Layout.fillHeight: true z: 1 boundsBehavior: Flickable.StopAtBounds - visible: !isEditing + visible: !profEditor.isEditing property int selectedIndex: -1 property string selectedName + property bool selectedIsUser: false delegate: Item @@ -202,6 +210,7 @@ Rectangle { profListView.selectedIndex = index profListView.selectedName = profileItem.lineName + profListView.selectedIsUser = modelData.isUser } onReleased: @@ -269,6 +278,7 @@ Rectangle InputProfileEditor { + id: profEditor width: profilesContainer.width Layout.fillHeight: true visible: isEditing diff --git a/qmlui/qml/inputoutput/qmldir b/qmlui/qml/inputoutput/qmldir index 27225cf5d4..9043f321ba 100644 --- a/qmlui/qml/inputoutput/qmldir +++ b/qmlui/qml/inputoutput/qmldir @@ -4,6 +4,7 @@ singleton FontAwesome 1.0 ../FontAwesomeVariables.qml ContextMenuEntry 0.1 ../ContextMenuEntry.qml CustomCheckBox 0.1 ../CustomCheckBox.qml CustomComboBox 0.1 ../CustomComboBox.qml +CustomPopupDialog 0.1 ../popup/CustomPopupDialog.qml CustomSpinBox 0.1 ../CustomSpinBox.qml CustomScrollBar 0.1 ../CustomScrollBar.qml CustomTextEdit 0.1 ../CustomTextEdit.qml