From fd6fec87d6f60bbce202cd1784f970b178bf8c6f Mon Sep 17 00:00:00 2001 From: Joris Goosen Date: Mon, 15 Sep 2025 18:10:35 +0200 Subject: [PATCH 1/4] make dataclass and qml for https://support.jasp-services.com/SCG-Chemicals/SCG_Chemicals_Public_Company_Limited/issues/16 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ok the editing isnt working out very well the tabbar should not move with the content.. open the resultsmenu in the right place even when zooming in or out... make the ploteditor tabs a lot better open first tab on show ah the rolenames were messing up the width 🤡 typeselecting works now to get the position entry to work --- Desktop/components/JASP/Widgets/MainPage.qml | 2 +- .../Widgets/PlotEditor/PlotEditTabHead.qml | 60 +++++ .../Widgets/PlotEditor/PlotEditingAxis.qml | 7 +- .../PlotEditor/PlotEditingReferenceLines.qml | 228 ++++++++++++++++ .../JASP/Widgets/PlotEditor/PlotEditor.qml | 234 ++++++----------- Desktop/data/expanddataproxymodel.cpp | 10 + Desktop/data/expanddataproxymodel.h | 1 + Desktop/mainwindow.cpp | 1 + Desktop/results/ploteditormodel.cpp | 41 +-- Desktop/results/ploteditormodel.h | 58 +++-- Desktop/results/ploteditorreferencelines.cpp | 244 ++++++++++++++++++ Desktop/results/ploteditorreferencelines.h | 72 ++++++ .../components/JASP/Controls/DropDown.qml | 2 + QMLComponents/datasetviewbase.cpp | 3 +- 14 files changed, 765 insertions(+), 198 deletions(-) create mode 100644 Desktop/components/JASP/Widgets/PlotEditor/PlotEditTabHead.qml create mode 100644 Desktop/components/JASP/Widgets/PlotEditor/PlotEditingReferenceLines.qml create mode 100644 Desktop/results/ploteditorreferencelines.cpp create mode 100644 Desktop/results/ploteditorreferencelines.h diff --git a/Desktop/components/JASP/Widgets/MainPage.qml b/Desktop/components/JASP/Widgets/MainPage.qml index 18ec3b81b7..7b10daa49b 100644 --- a/Desktop/components/JASP/Widgets/MainPage.qml +++ b/Desktop/components/JASP/Widgets/MainPage.qml @@ -535,7 +535,7 @@ Item "functionCall" : functionCall }; - customMenu.toggle(resultsView, props, (optionsJSON['rXright'] + 10) * preferencesModel.uiScale, optionsJSON['rY'] * preferencesModel.uiScale); + customMenu.toggle(resultsView, props, (optionsJSON['rXright'] + 10 ) * preferencesModel.uiScale, optionsJSON['rY'] ); customMenu.scrollOri = resultsView.scrollPosition; customMenu.menuScroll.x = Qt.binding(function() { return -1 * (resultsView.scrollPosition.x - customMenu.scrollOri.x) / resultsView.zoomFactor; }); diff --git a/Desktop/components/JASP/Widgets/PlotEditor/PlotEditTabHead.qml b/Desktop/components/JASP/Widgets/PlotEditor/PlotEditTabHead.qml new file mode 100644 index 0000000000..afc2b468b0 --- /dev/null +++ b/Desktop/components/JASP/Widgets/PlotEditor/PlotEditTabHead.qml @@ -0,0 +1,60 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import JASP.Widgets as JASPW +import JASP.Theme +import JASP.Controls as JASPC +import JASP.PlotEditor + +TabButton +{ + id: refTab + height: axes.tabBarHeight + 2 + clip: true + + property string buttonText: "Fill me" + + background: Rectangle + { + color: refTab.checked ? jaspTheme.uiBackground : jaspTheme.grayLighter + radius: axes.tabButtonRadius + border.width: 1 + border.color: refTab.checked ? jaspTheme.uiBorder : jaspTheme.borderColor + height: axes.tabBarHeight + axes.tabButtonRadius + + + Rectangle + { + color: jaspTheme.uiBorder + height: 1 + visible: !refTab.checked + anchors + { + left: parent.left + right: parent.right + top: parent.top + topMargin: axes.tabBarHeight + 1 + } + } + } + + contentItem: Text + { + // The bottom of buttons are hidden to remove their bottom line with the radius + // So the text has to be moved higher from the horizontal middle line. + topPadding: -axes.tabButtonRadius * 3/4 + font: jaspTheme.font + color: jaspTheme.black + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + opacity: refTab.checked ? 1 : .6 + text: buttonText + } + + MouseArea + { + anchors.fill : parent + cursorShape : refTab.checked ? Qt.ArrowCursor : Qt.PointingHandCursor + acceptedButtons : Qt.NoButton + } +} diff --git a/Desktop/components/JASP/Widgets/PlotEditor/PlotEditingAxis.qml b/Desktop/components/JASP/Widgets/PlotEditor/PlotEditingAxis.qml index 98f5e24cc4..049119db84 100644 --- a/Desktop/components/JASP/Widgets/PlotEditor/PlotEditingAxis.qml +++ b/Desktop/components/JASP/Widgets/PlotEditor/PlotEditingAxis.qml @@ -25,7 +25,7 @@ import JASP */ -Column +ColumnLayout { id: axis spacing: jaspTheme.columnGroupSpacing @@ -37,6 +37,8 @@ Column label : qsTr("Show title") checked : axisModel.titleType !== AxisModel.TitleNull onClicked : axisModel.titleType = (checked ? AxisModel.TitleCharacter : AxisModel.TitleNull) + + Layout.fillWidth: true JASPC.TextField { @@ -56,6 +58,8 @@ Column checked : axisModel.breaksType !== AxisModel.BreaksNull onClicked : axisModel.breaksType = (checked ? lastBreakType : AxisModel.BreaksNull) columns : 1 + + Layout.fillWidth: true property int lastBreakType: AxisModel.BreaksRange @@ -151,6 +155,7 @@ Column { title : qsTr("Advanced") columns : 1 + Layout.fillWidth: true JASPC.CheckBox { diff --git a/Desktop/components/JASP/Widgets/PlotEditor/PlotEditingReferenceLines.qml b/Desktop/components/JASP/Widgets/PlotEditor/PlotEditingReferenceLines.qml new file mode 100644 index 0000000000..f723376ae9 --- /dev/null +++ b/Desktop/components/JASP/Widgets/PlotEditor/PlotEditingReferenceLines.qml @@ -0,0 +1,228 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import JASP.Widgets as JASPW +import JASP.Theme +import JASP.Controls as JASPC +import JASP.PlotEditor +import JASP + + +JASPW.JASPDataView +{ + id: jaspDataView + model: plotEditorModel.references + + onWidthChanged: plotEditorModel.references.viewWidth = width + + rowNumberDelegate: null + + itemDelegate: Component { Loader + { + + property int rowIdx: rowIndex + property int columnIdx: columnIndex + property string modelText: itemText + property var modelData: itemData + + sourceComponent: columnIndex === 0 ? typeSelector : columnIndex == 1 ? textView : columnIndex == 2 ? valueView : eraseButton; + }} + + + editDelegate: Component { Loader + { + + property int rowIdx: rowIndex + property int columnIdx: columnIndex + property string modelText: itemText + property var modelData: itemData + + sourceComponent: columnIndex != 2 ? textEdit : valueEdit + }} + + Component + { + id: textView + + Text + { + text: modelText == "" ? "..." : modelText; + font: jaspTheme.font; + color: jaspTheme.textEnabled; + MouseArea + { + anchors.fill: parent; + onClicked: jaspDataView.view.edit(rowIdx, columnIdx) + } + + // opacity: rowIdx < jaspDataView.view.rowCount - 1 ? 1.0 : 0.5 + + } + } + + Component + { + id: textEdit + + TextInput + { + id: editItem + text: modelText + color: jaspTheme.textEnabled + font: jaspTheme.font + focus: true + clip: true + //onTextEdited: jaspDataView.view.model.setData(jaspDataView.view.model.index(rowIdx, columnIdx), text) + onEditingFinished: jaspDataView.view.forceActiveFocus(); + Keys.onReturnPressed: jaspDataView.view.forceActiveFocus(); + Component.onCompleted: forceActiveFocus() + onActiveFocusChanged: + { + if(!activeFocus) + { + jaspDataView.view.commitEdit(rowIdx, columnIdx, text); + jaspDataView.view.clearEdit(); + } + } + + //opacity: rowIdx < jaspDataView.view.rowCount - 1 ? 1.0 : 0.5 + } + } + + ListModel + { + id: typeModel + + ListElement { value: 0; name: qsTr("Point") } + ListElement { value: 1; name: qsTr("Horizontal Line") } + ListElement { value: 2; name: qsTr("Vertical Line") } + } + + Component + { + id: typeSelector + + JASPC.DropDown + { + fieldWidth: width + source: typeModel + currentIndex: modelData + onValueChanged: + { + if(modelData != currentIndex) + jaspDataView.view.model.setData(jaspDataView.view.model.index(rowIdx, columnIdx), currentIndex); + } + + //opacity: rowIdx < jaspDataView.view.rowCount - 1 ? 1.0 : 0.5 + } + } + + Component + { + id: valueView + + RowLayout + { + //opacity: rowIdx < jaspDataView.view.rowCount - 1 ? 1.0 : 0.5 + + Text + { + text: modelData && modelData.length > 0 ? modelData[0] : modelText + font: jaspTheme.font; + color: jaspTheme.textEnabled; + + MouseArea + { + anchors.fill: parent; + onClicked: jaspDataView.view.edit(rowIdx, columnIdx); + } + } + + Text + { + text: modelData && modelData.length > 1 ? modelData[1] : "" + font: jaspTheme.font; + color: jaspTheme.textEnabled; + visible: modelData && modelData.length > 1 + + MouseArea + { + anchors.fill: parent; + onClicked: jaspDataView.view.edit(rowIdx, columnIdx); + } + } + + + } + } + + Component + { + id: valueEdit + + RowLayout + { + //opacity: rowIdx < jaspDataView.view.rowCount - 1 ? 1.0 : 0.5 + + property bool has2Fields: modelData && modelData.length > 1 + + TextInput + { + id: editItem0 + text: modelData[0] + color: jaspTheme.textEnabled + font: jaspTheme.font + clip: true + focus: true + onEditingFinished: jaspDataView.view.forceActiveFocus(); + Keys.onReturnPressed: jaspDataView.view.forceActiveFocus(); + Component.onCompleted: forceActiveFocus() + onActiveFocusChanged: + { + if(!activeFocus) + { + jaspDataView.view.commitEdit(rowIdx, columnIdx, has2Fields ? [text, modelData[1]] : [text]); + jaspDataView.view.clearEdit(); + } + } + } + + TextInput + { + id: editItem1 + text: modelData[1] + color: jaspTheme.textEnabled + font: jaspTheme.font + clip: true + visible: has2Fields + enabled: has2Fields + onEditingFinished: jaspDataView.view.forceActiveFocus(); + Keys.onReturnPressed: jaspDataView.view.forceActiveFocus(); + Component.onCompleted: forceActiveFocus() + onActiveFocusChanged: + { + if(!activeFocus) + { + jaspDataView.view.commitEdit(rowIdx, columnIdx, has2Fields ? [modelData[0], text] : [text]); + jaspDataView.view.clearEdit(); + } + } + } + } + } + + + Component + { + id: eraseButton + + + JASPC.RectangularButton + { + text: "X" + onClicked: model.setData(model.index(rowIdx, columnIdx), true); + //visible: rowIdx < jaspDataView.view.rowCount - 1 + } + } + +} diff --git a/Desktop/components/JASP/Widgets/PlotEditor/PlotEditor.qml b/Desktop/components/JASP/Widgets/PlotEditor/PlotEditor.qml index a505a7ef41..b65aeb6c0a 100644 --- a/Desktop/components/JASP/Widgets/PlotEditor/PlotEditor.qml +++ b/Desktop/components/JASP/Widgets/PlotEditor/PlotEditor.qml @@ -163,10 +163,10 @@ Popup Item { - id: axes + id: axes SplitView.preferredWidth: parent.width * .3 - SplitView.minimumWidth: parent.width * .3 - SplitView.maximumWidth: parent.width * .9 + SplitView.minimumWidth: parent.width * .3 + SplitView.maximumWidth: parent.width * .9 property real tabBarHeight: 28 * preferencesModel.uiScale property real tabButtonRadius: 5 * preferencesModel.uiScale @@ -185,165 +185,100 @@ Popup border.width: 1 border.color: jaspTheme.uiBorder color: "transparent" + z: -1 + } + + + TabBar + { + id: tabbar + contentHeight: axes.tabBarHeight + width: axes.axeTitles.length * axes.tabButtonWidth + background: Rectangle { color: jaspTheme.uiBackground } // Per default the background is white + + Repeater + { + model: axes.axeTitles + PlotEditTabHead + { + buttonText: modelData + } + } + + PlotEditTabHead + { + buttonText: qsTr("References") + } + + Component.onCompleted: setCurrentIndex(0); + } + + JASPC.MenuButton + { + id: helpButton + iconSource: jaspTheme.iconPath + "info-button.png" + width: height + radius: height + onClicked: helpModel.showOrTogglePage("other/plotediting"); + toolTip: qsTr("Open Documentation") + anchors + { + top: tabbar.top + left: tabbar.right + bottom: tabbar.bottom + leftMargin: 4 * preferencesModel.uiScale + } + } + + MouseArea + { + id: focusCatcher //Because then people can click away from the axistableview or something + onPressed: { forceActiveFocus(); mouse.accepted = false; } + anchors.fill: axesFlickable + z: -100 + } + + JASPC.JASPScrollBar + { + id: axesScrollbar + flickable: axesFlickable + vertical: true } Flickable { id: axesFlickable - anchors.fill: parent + anchors + { + top: tabbar.bottom + left: parent.left + right: parent.right + bottom: parent.bottom + } clip: true - contentHeight: flickChild.height - contentWidth: flickChild.width flickableDirection: Flickable.VerticalFlick onFlickStarted: forceActiveFocus(); - Item + StackLayout { - id: flickChild - width: axesFlickable.width - height: stack.y + stack.height + jaspTheme.generalAnchorMargin - - MouseArea - { - id: focusCatcher //Because then people can click away from the axistableview or something - onPressed: { forceActiveFocus(); mouse.accepted = false; } - anchors - { - top: parent.top - left: parent.left - right: parent.right - } - height: Math.max(flickChild.height, axesFlickable.height) - z: -100 - } - - TabBar - { - id: tabbar - contentHeight: axes.tabBarHeight + axes.tabButtonRadius - width: axes.axeTitles.length * axes.tabButtonWidth - - background: Rectangle { color: jaspTheme.uiBackground } // Per default the background is white - - Repeater - { - model: axes.axeTitles - TabButton - { - height: tabbar.height - background: Rectangle - { - color: checked ? jaspTheme.uiBackground : jaspTheme.grayLighter - radius: axes.tabButtonRadius - border.width: 1 - border.color: checked ? jaspTheme.uiBorder : jaspTheme.borderColor - } - - contentItem: Text - { - // The bottom of buttons are hidden to remove their bottom line with the radius - // So the text has to be moved higher from the horizontal middle line. - topPadding: -axes.tabButtonRadius * 3/4 - text: modelData - font: jaspTheme.font - color: jaspTheme.black - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - opacity: checked ? 1 : .6 - } - - MouseArea - { - anchors.fill : parent - cursorShape : checked ? Qt.ArrowCursor : Qt.PointingHandCursor - acceptedButtons : Qt.NoButton - } - } - } - } - - Rectangle + id: stack + currentIndex: tabbar.currentIndex + width: axesFlickable.width - (2*jaspTheme.generalAnchorMargin + axesScrollbar.width) + y: jaspTheme.generalAnchorMargin + x: jaspTheme.generalAnchorMargin + + Repeater { - // This hides the bottom border of the buttons (with their radius) - id : roundingHider - width : parent.width - height : axes.tabButtonRadius + 1 - anchors + model: axes.axeModels + PlotEditingAxis { - left: parent.left - right: tabbar.right - top: parent.top - topMargin: axes.tabBarHeight - } - color: jaspTheme.uiBackground - - Rectangle - { - // The Tabbar removes the left border. Redraw it. - anchors.left: parent.left - anchors.top: parent.top - anchors.bottom: parent.bottom - width: 1 - color: jaspTheme.uiBorder - } - } - - Rectangle - { - // Redraw a line below the unchecked tab - anchors - { - top: roundingHider.top - left: parent.left - leftMargin: tabbar.currentIndex === 0 ? axes.tabButtonWidth - 1 : 0 - right: tabbar.right - rightMargin: tabbar.currentIndex === 0 ? 0 : axes.tabButtonWidth - 1 - } - height: 1 - color: jaspTheme.uiBorder - } - - StackLayout - { - id: stack - anchors - { - top : tabbar.bottom - left : parent.left - right : parent.right - margins : jaspTheme.generalAnchorMargin - } - currentIndex: tabbar.currentIndex - - Repeater - { - model: axes.axeModels - PlotEditingAxis - { - axisModel: modelData - width: flickChild.width - } - } - } - - JASPC.MenuButton - { - id: helpButton - iconSource: jaspTheme.iconPath + "info-button.png" - width: height - radius: height - onClicked: helpModel.showOrTogglePage("other/plotediting"); - toolTip: qsTr("Open Documentation") - anchors - { - top: tabbar.top - left: tabbar.right - bottom: roundingHider.top - leftMargin: 4 * preferencesModel.uiScale + axisModel: modelData } } + + PlotEditingReferenceLines {} } } @@ -388,12 +323,7 @@ Popup onClicked: plotEditorModel.undoSomething() } */ - JASPC.JASPScrollBar - { - id: axesScrollbar - flickable: axesFlickable - vertical: true - } + } Item diff --git a/Desktop/data/expanddataproxymodel.cpp b/Desktop/data/expanddataproxymodel.cpp index 32610d1183..776f3b086d 100644 --- a/Desktop/data/expanddataproxymodel.cpp +++ b/Desktop/data/expanddataproxymodel.cpp @@ -277,10 +277,20 @@ void ExpandDataProxyModel::resize(int row, int col, bool onlyExpand, const QStri _undoStack->endMacro(); } +bool ExpandDataProxyModel::useUndoStack() const +{ + return dynamic_cast(_sourceModel); +} + bool ExpandDataProxyModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (!_sourceModel || index.row() < 0 || index.column() < 0) return false; + + if(!useUndoStack()) + { + return _sourceModel->setData(_sourceModel->index(index.row(), index.column()), value, role); + } resize(index.row(), index.column()); _undoStack->endMacro(new SetDataCommand(_sourceModel, index.row(), index.column(), value, role)); diff --git a/Desktop/data/expanddataproxymodel.h b/Desktop/data/expanddataproxymodel.h index 660ca89416..8d269c21b4 100644 --- a/Desktop/data/expanddataproxymodel.h +++ b/Desktop/data/expanddataproxymodel.h @@ -48,6 +48,7 @@ class ExpandDataProxyModel : public QAbstractItemModel QString undoText() { return _undoStack->undoText(); } QString redoText() { return _undoStack->redoText(); } void resize(int row, int col, bool onlyExpand = true, const QString& undoText = QString()); + bool useUndoStack() const; signals: void undoChanged(); diff --git a/Desktop/mainwindow.cpp b/Desktop/mainwindow.cpp index a0789f560d..77d122b95e 100644 --- a/Desktop/mainwindow.cpp +++ b/Desktop/mainwindow.cpp @@ -426,6 +426,7 @@ void MainWindow::makeConnections() qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); + qRegisterMetaType(); connect(_computedColumnsModel, &ComputedColumnModel::sendComputeCode, _engineSync, &EngineSync::computeColumn, Qt::QueuedConnection); connect(_computedColumnsModel, &ComputedColumnModel::dataColumnAdded, _fileMenu, &FileMenu::dataColumnAdded ); diff --git a/Desktop/results/ploteditormodel.cpp b/Desktop/results/ploteditormodel.cpp index c6384bc4d8..b2ffabf53b 100644 --- a/Desktop/results/ploteditormodel.cpp +++ b/Desktop/results/ploteditormodel.cpp @@ -15,15 +15,18 @@ int PlotEditorModel::_editRequest = 0; PlotEditorModel::PlotEditorModel() : QObject(Analyses::analyses()) { - _xAxis = new AxisModel(this, true); - _yAxis = new AxisModel(this, true); - _currentAxis = _xAxis; - _ppi = PreferencesModel::prefs()->plotPPI(); - - connect(_xAxis, &AxisModel::somethingChanged, this, &PlotEditorModel::somethingChanged); - connect(_yAxis, &AxisModel::somethingChanged, this, &PlotEditorModel::somethingChanged); - connect(_xAxis, &AxisModel::addToUndoStack, this, &PlotEditorModel::addToUndoStack); - connect(_yAxis, &AxisModel::addToUndoStack, this, &PlotEditorModel::addToUndoStack); + _xAxis = new AxisModel(this, true); + _yAxis = new AxisModel(this, true); + _currentAxis = _xAxis; + _ppi = PreferencesModel::prefs()->plotPPI(); + _references = new References(this); + + connect(_xAxis, &AxisModel::somethingChanged, this, &PlotEditorModel::somethingChanged); + connect(_yAxis, &AxisModel::somethingChanged, this, &PlotEditorModel::somethingChanged); + connect(_references, &References::somethingChanged, this, &PlotEditorModel::somethingChanged); + connect(_references, &References::addToUndoStack, this, &PlotEditorModel::addToUndoStack); + connect(_xAxis, &AxisModel::addToUndoStack, this, &PlotEditorModel::addToUndoStack); + connect(_yAxis, &AxisModel::addToUndoStack, this, &PlotEditorModel::addToUndoStack); } @@ -79,13 +82,9 @@ void PlotEditorModel::setup() return; } - Json::Value xAxis = editOptions.get( "xAxis", Json::objectValue), - yAxis = editOptions.get( "yAxis", Json::objectValue); - - _xAxis->setAxisData(xAxis); - _yAxis->setAxisData(yAxis); - - //_coordinates.loadCoordinates(editOptions.get("coordinates", Json::objectValue)); // To Do Vincent Pedata: is this the right json object? + _xAxis ->setAxisData( editOptions.get("xAxis", Json::objectValue)); + _yAxis ->setAxisData( editOptions.get("yAxis", Json::objectValue)); + _references ->fromJson( editOptions.get("references", Json::arrayValue)); _originalImgOps = _imgOptions = generateImgOptions(); } @@ -128,8 +127,9 @@ void PlotEditorModel::reset() Json::Value PlotEditorModel::generateImgOptions() const { Json::Value newOptions = _imgOptions; - newOptions["editOptions"]["xAxis"] = _xAxis->getAxisData(); - newOptions["editOptions"]["yAxis"] = _yAxis->getAxisData(); + newOptions["editOptions"]["xAxis"] = _xAxis->getAxisData(); + newOptions["editOptions"]["yAxis"] = _yAxis->getAxisData(); + newOptions["editOptions"]["references"] = _references->toJson(); newOptions["name"] = name().toStdString(); newOptions["data"] = data().toStdString(); @@ -370,4 +370,9 @@ void PlotEditorModel::setLoading(bool loading) emit loadingChanged(_loading); } +References *PlotEditorModel::references() const +{ + return _references; +} + } diff --git a/Desktop/results/ploteditormodel.h b/Desktop/results/ploteditormodel.h index 97e7efecdc..f8641a0a00 100644 --- a/Desktop/results/ploteditormodel.h +++ b/Desktop/results/ploteditormodel.h @@ -2,11 +2,12 @@ #define PLOTEDITORMODEL_H #include +#include #include #include #include "ploteditoraxismodel.h" #include "ploteditorcoordinates.h" -#include +#include "ploteditorreferencelines.h" class Analyses; class Analysis; @@ -38,6 +39,7 @@ class PlotEditorModel : public QObject Q_PROPERTY(bool redoEnabled READ redoEnabled NOTIFY unOrRedoEnabledChanged ) Q_PROPERTY(AxisModel * currentAxis READ currentAxis NOTIFY currentAxisChanged ) Q_PROPERTY(AxisType axisType READ axisType WRITE setAxisType NOTIFY axisTypeChanged ) + Q_PROPERTY(References * references READ references NOTIFY referencesChanged ) public: explicit PlotEditorModel(); @@ -72,6 +74,8 @@ class PlotEditorModel : public QObject void setBlockChanges(bool change) { _blockChanges = change; } bool blockChanges() const { return _blockChanges; } + References *references() const; + signals: void visibleChanged( bool visible ); void nameChanged( QString name ); @@ -91,6 +95,8 @@ class PlotEditorModel : public QObject void currentAxisChanged( AxisModel * currentAxis); void axisTypeChanged( AxisType axisType); + void referencesChanged(); + public slots: void showPlotEditor(int id, QString options); void updateOptions(Analysis* analysis); @@ -103,9 +109,9 @@ public slots: void setHeight( int height ); void setLoading( bool loading ); - void resetDefaults(); - void cancelPlot(); - void savePlot() const; + void resetDefaults(); + void cancelPlot(); + void savePlot() const; void setAxisType( const AxisType axisType ); void somethingChanged(); @@ -126,34 +132,36 @@ public slots: void updatePlot(Json::Value& imageOptions); private: - Analysis * _analysis = nullptr; - AxisModel * _xAxis = nullptr, - * _yAxis = nullptr, - * _currentAxis = nullptr; + Analysis * _analysis = nullptr; + AxisModel * _xAxis = nullptr, + * _yAxis = nullptr, + * _currentAxis = nullptr; + References * _references = nullptr; //Coordinates _coordinates; - Json::Value _imgOptions = Json::nullValue, - _originalImgOps = Json::nullValue; - std::map _editedImgsMap; - QString _name, - _data, - _title; - bool _visible = false, - _goBlank = false, - _loading = false, - _validOptions = false, - _blockChanges = false; - int _width, - _height; - double _ppi; - - static int _editRequest; + Json::Value _imgOptions = Json::nullValue, + _originalImgOps = Json::nullValue; + std::map _editedImgsMap; + QString _name, + _data, + _title; + bool _visible = false, + _goBlank = false, + _loading = false, + _validOptions = false, + _blockChanges = false; + int _width, + _height; + double _ppi; + + static int _editRequest; std::stack _undo, _redo; - AxisType _axisType = AxisType::Xaxis; + AxisType _axisType = AxisType::Xaxis; + }; } diff --git a/Desktop/results/ploteditorreferencelines.cpp b/Desktop/results/ploteditorreferencelines.cpp new file mode 100644 index 0000000000..0a5f1d08ef --- /dev/null +++ b/Desktop/results/ploteditorreferencelines.cpp @@ -0,0 +1,244 @@ +#include "ploteditorreferencelines.h" +#include "data/datasetpackageenums.h" +#include "utilities/qutils.h" +#include "ploteditormodel.h" + +namespace PlotEditor +{ + +References::References(PlotEditorModel * model) + : QAbstractTableModel{model}, _model(model) +{ + +} + +int PlotEditor::References::rowCount(const QModelIndex &parent) const +{ + return _refs.size() + 1; +} + +int PlotEditor::References::columnCount(const QModelIndex &parent) const +{ + return 4; +} + +// I hate the following and fixes for this kind of shenanigans are in a different branch but for now just do this: +QHash PlotEditor::References::roleNames() const +{ + static bool set = false; + static QHash roles = QAbstractItemModel::roleNames (); + + if(!set) + { + for(const auto & enumString : dataPkgRolesToStringMap()) + roles[int(enumString.first)] = tq(enumString.second).toUtf8(); + + set = true; + } + + return roles; +} + +QVariant PlotEditor::References::headerData(int section, Qt::Orientation orientation, int role) const +{ + if(orientation == Qt::Vertical) + return QVariant(); + + switch(role) + { + default: + switch(section) + { + case 0: return tr("Type"); + case 1: return tr("Text"); + case 2: return tr("Position"); + case 3: return tr("Remove"); + }; + break; + + case int(dataPkgRoles::maxColString): + case int(dataPkgRoles::maxRowHeaderString): + case int(dataPkgRoles::maxColumnHeaderString): + return QVariant(); + + case int(dataPkgRoles::columnWidthFallback): + return _widths.size() > section ? _widths[section] : 200; + } + + return QVariant(); +} + +bool References::insertRows(int rows, int count, const QModelIndex &parent) +{ + emit addToUndoStack(); + rows = std::min(rows, int(_refs.size())); + beginInsertRows(QModelIndex(), rows, rows+count-1); + for(int c=0; c _refs.size() || index.column() < 0 || index.column() >= columnCount() ) + return QVariant(); + + if(index.row() == _refs.size()) //Special "add a row"-row + switch(index.column()) + { + case 0: return ReferenceType::Point; + default: return ""; + case 2: return 0; + } + + const Reference & ref = _refs[index.row()]; + + switch(index.column()) + { + case 0: return ref.point ? ReferenceType::Point : ref.horizontal ? ReferenceType::LineHorizontal : ReferenceType::LineVertical; + case 1: return ref.text; + case 2: return ref.point ? QVariantList(ref.x) : QVariantList(ref.x, ref.y); + } + + return QVariant(); +} + +bool References::setData(const QModelIndex &index, const QVariant &value, int role) +{ + if(index.row() < 0 || index.row() > _refs.size() || index.column() < 0 || index.column() >= columnCount() ) + return false; + + if(index.row() == _refs.size()) + { + if(index.column() == 0 && ReferenceType(value.toInt()) == ReferenceType::Point) + return false; + else + insertRows(index.row(), 1); + } + + emit addToUndoStack(); + + Reference & ref = _refs[index.row()]; + + switch(index.column()) + { + default: + return false; + + case 0: + { + ref.point = ReferenceType(value.toInt()) == ReferenceType::Point; + ref.horizontal = ReferenceType(value.toInt()) == ReferenceType::LineHorizontal; + break; + } + case 1: + { + ref.text = value.toString(); + break; + } + case 2: + { + QVariantList values = value.toList(); + double x = values.size() > 0 ? values[0].toDouble() : NAN, + y = values.size() > 1 ? values[1].toDouble() : NAN; + + ref.x = x; + if(ref.point) + ref.y = y; + break; + } + case 3: + removeRows(index.row(), 1); + break; + } + + emit dataChanged(index, index); + emit somethingChanged(); + return true; + +} + +Json::Value PlotEditor::References::toJson() const +{ + Json::Value val = Json::arrayValue; + + for(const Reference & l : _refs) + { + Json::Value obj; + obj["text"] = fq(l.text); + obj["horizontal"] = l.horizontal; + obj["point"] = l.point; + obj["x"] = l.x; + obj["y"] = l.y; + val.append(obj); + } + + return val; +} + +void PlotEditor::References::fromJson(const Json::Value &json) +{ + emit addToUndoStack(); + beginResetModel(); + _refs.clear(); + if(json.type() == Json::arrayValue) + for(const Json::Value & r : json) + _refs.push_back(Reference{ + tq(r.get("text", "???") .asString()), + r.get("horizontal", true) .asBool(), + r.get("point", false) .asBool(), + r.get("x", 0.) .asDouble(), + r.get("y", 0.) .asDouble() + }); + endResetModel(); + emit somethingChanged(); +} + +void References::setColWidth(int index, int width) +{ + if(_widths.size() > index && _widths[index] == width) + return; + + if(_widths.size() <= index) + _widths.resize(index+1); + _widths[index] = width; +} + +int References::viewWidth() const +{ + return _viewWidth; +} + +void References::setViewWidth(int newViewWidth) +{ + if (_viewWidth == newViewWidth) + return; + _viewWidth = newViewWidth; + emit viewWidthChanged(); + + int quarterPounder = newViewWidth / 4; + + beginResetModel(); + for(int i=0; i<4; i++) + setColWidth(i, quarterPounder); + endResetModel(); +} + +} diff --git a/Desktop/results/ploteditorreferencelines.h b/Desktop/results/ploteditorreferencelines.h new file mode 100644 index 0000000000..59694b14b5 --- /dev/null +++ b/Desktop/results/ploteditorreferencelines.h @@ -0,0 +1,72 @@ +#ifndef PLOTEDITORREFERENCELINES_H +#define PLOTEDITORREFERENCELINES_H + +#include +#include +#include +#include "utils.h" + +namespace PlotEditor +{ + +class PlotEditorModel; + + +class References : public QAbstractTableModel +{ + Q_OBJECT + QML_ELEMENT + Q_PROPERTY(int viewWidth READ viewWidth WRITE setViewWidth NOTIFY viewWidthChanged) + +public: + explicit References(PlotEditorModel * model); + + enum ReferenceType { Point, LineHorizontal, LineVertical}; + Q_ENUM(ReferenceType) + + + struct Reference + { + QString text = ""; + bool horizontal = false, + point = true; + double x = 0, + y; + }; + + int rowCount( const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data( const QModelIndex &index, int role = Qt::DisplayRole) const override; + bool setData( const QModelIndex &index, const QVariant &value, int role) override; + QVariant headerData ( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const override; + bool insertRows(int rows, int count, const QModelIndex &parent = QModelIndex()) override; + bool removeRows(int rows, int count, const QModelIndex &parent = QModelIndex()) override; + QHash roleNames() const override; + + Json::Value toJson() const; + void fromJson(const Json::Value & json); + + int viewWidth() const; + void setViewWidth(int newViewWidth); + + +public slots: + void setColWidth(int index, int width); + +signals: + void somethingChanged(); + void addToUndoStack(); + + + void viewWidthChanged(); + +protected: + PlotEditorModel * _model; + std::vector _refs; + intvec _widths; + int _viewWidth; +}; + +} + +#endif // PLOTEDITORREFERENCELINES_H diff --git a/QMLComponents/components/JASP/Controls/DropDown.qml b/QMLComponents/components/JASP/Controls/DropDown.qml index de1804a11d..78a63b8652 100644 --- a/QMLComponents/components/JASP/Controls/DropDown.qml +++ b/QMLComponents/components/JASP/Controls/DropDown.qml @@ -6,6 +6,8 @@ import JASP.Controls ComboBoxBase { id: comboBox + height: implicitHeight + width: implicitWidth implicitHeight: control.height + ((controlLabel.visible && setLabelAbove) ? rectangleLabel.height : 0) implicitWidth: controlLabel.visible ? (setLabelAbove ? Math.max(control.width, rectangleLabel.width) : (rectangleLabel.width + jaspTheme.labelSpacing + control.width)) diff --git a/QMLComponents/datasetviewbase.cpp b/QMLComponents/datasetviewbase.cpp index ff8aee27f5..a7a3a39e6c 100644 --- a/QMLComponents/datasetviewbase.cpp +++ b/QMLComponents/datasetviewbase.cpp @@ -1475,7 +1475,7 @@ void DataSetViewBase::onDataModeChanged(bool dataMode) void DataSetViewBase::commitLastEdit() { Log::log() << "Commit last edit" << std::endl; - if(_prevEditRow != -1 && _prevEditCol != -1 && _editItemContextual && _editItemContextual->item) + if(_prevEditRow != -1 && _prevEditCol != -1 && _editItemContextual && _editItemContextual->item && _editItemContextual->item->property("text").isValid()) commitEdit(_prevEditRow, _prevEditCol, _editItemContextual->item->property("text")); } @@ -1510,6 +1510,7 @@ QQmlContext * DataSetViewBase::setStyleDataItem(QQmlContext * previousContext, b //The first four also get updated in DataSetViewBase::modelDataChanged! //If adding or changes behaviour also do that there previousContext->setContextProperty("itemText", text); + previousContext->setContextProperty("itemData", _model->data(modelIndex)); previousContext->setContextProperty("itemTextEdit", textEdit); previousContext->setContextProperty("itemShadowText", _model->data(modelIndex, getRole("shadowDisplay"))); previousContext->setContextProperty("itemLabel", _model->data(modelIndex, getRole("label"))); From 9a1bfac0f69f1bbdb07a29d21a1dfa72139653eb Mon Sep 17 00:00:00 2001 From: Joris Goosen Date: Fri, 31 Oct 2025 13:52:03 +0100 Subject: [PATCH 2/4] was missing editable flag --- .../PlotEditor/PlotEditingReferenceLines.qml | 14 ++++++++++---- Desktop/results/ploteditorreferencelines.cpp | 7 ++++++- Desktop/results/ploteditorreferencelines.h | 2 ++ 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/Desktop/components/JASP/Widgets/PlotEditor/PlotEditingReferenceLines.qml b/Desktop/components/JASP/Widgets/PlotEditor/PlotEditingReferenceLines.qml index f723376ae9..a5c9763769 100644 --- a/Desktop/components/JASP/Widgets/PlotEditor/PlotEditingReferenceLines.qml +++ b/Desktop/components/JASP/Widgets/PlotEditor/PlotEditingReferenceLines.qml @@ -73,18 +73,24 @@ JASPW.JASPDataView focus: true clip: true //onTextEdited: jaspDataView.view.model.setData(jaspDataView.view.model.index(rowIdx, columnIdx), text) - onEditingFinished: jaspDataView.view.forceActiveFocus(); - Keys.onReturnPressed: jaspDataView.view.forceActiveFocus(); + onEditingFinished: {saveEdit(); jaspDataView.view.forceActiveFocus(); } + Keys.onReturnPressed: {saveEdit(); jaspDataView.view.forceActiveFocus(); } Component.onCompleted: forceActiveFocus() onActiveFocusChanged: { if(!activeFocus) { - jaspDataView.view.commitEdit(rowIdx, columnIdx, text); - jaspDataView.view.clearEdit(); + + text = Qt.binding(function() {return modelText;}); } } + function saveEdit() + { + jaspDataView.view.commitEdit(rowIdx, columnIdx, text); + jaspDataView.view.clearEdit(); + } + //opacity: rowIdx < jaspDataView.view.rowCount - 1 ? 1.0 : 0.5 } } diff --git a/Desktop/results/ploteditorreferencelines.cpp b/Desktop/results/ploteditorreferencelines.cpp index 0a5f1d08ef..ab3f97fa5f 100644 --- a/Desktop/results/ploteditorreferencelines.cpp +++ b/Desktop/results/ploteditorreferencelines.cpp @@ -39,6 +39,11 @@ QHash PlotEditor::References::roleNames() const return roles; } +Qt::ItemFlags References::flags(const QModelIndex &index) const +{ + return QAbstractTableModel::flags(index) | Qt::ItemIsEditable; +} + QVariant PlotEditor::References::headerData(int section, Qt::Orientation orientation, int role) const { if(orientation == Qt::Vertical) @@ -97,7 +102,7 @@ bool References::removeRows(int rows, int count, const QModelIndex &parent) QVariant PlotEditor::References::data(const QModelIndex &index, int role) const { - if(index.row() < 0 || index.row() > _refs.size() || index.column() < 0 || index.column() >= columnCount() ) + if(role != Qt::DisplayRole || index.row() < 0 || index.row() > _refs.size() || index.column() < 0 || index.column() >= columnCount() ) return QVariant(); if(index.row() == _refs.size()) //Special "add a row"-row diff --git a/Desktop/results/ploteditorreferencelines.h b/Desktop/results/ploteditorreferencelines.h index 59694b14b5..32a712607d 100644 --- a/Desktop/results/ploteditorreferencelines.h +++ b/Desktop/results/ploteditorreferencelines.h @@ -42,6 +42,8 @@ class References : public QAbstractTableModel bool insertRows(int rows, int count, const QModelIndex &parent = QModelIndex()) override; bool removeRows(int rows, int count, const QModelIndex &parent = QModelIndex()) override; QHash roleNames() const override; + Qt::ItemFlags flags(const QModelIndex &index) const override; + Json::Value toJson() const; void fromJson(const Json::Value & json); From 0f5f863a44a680475bb651b196a50096e12da045 Mon Sep 17 00:00:00 2001 From: Joris Goosen Date: Fri, 31 Oct 2025 15:32:31 +0100 Subject: [PATCH 3/4] Make interface work --- .../PlotEditor/PlotEditingReferenceLines.qml | 109 ++---------------- Desktop/results/ploteditorreferencelines.cpp | 57 ++++++--- Desktop/results/ploteditorreferencelines.h | 4 + QMLComponents/datasetviewbase.cpp | 6 +- 4 files changed, 58 insertions(+), 118 deletions(-) diff --git a/Desktop/components/JASP/Widgets/PlotEditor/PlotEditingReferenceLines.qml b/Desktop/components/JASP/Widgets/PlotEditor/PlotEditingReferenceLines.qml index a5c9763769..fd1f68f279 100644 --- a/Desktop/components/JASP/Widgets/PlotEditor/PlotEditingReferenceLines.qml +++ b/Desktop/components/JASP/Widgets/PlotEditor/PlotEditingReferenceLines.qml @@ -24,8 +24,9 @@ JASPW.JASPDataView property int columnIdx: columnIndex property string modelText: itemText property var modelData: itemData + property bool modelEnabled: itemEnabled - sourceComponent: columnIndex === 0 ? typeSelector : columnIndex == 1 ? textView : columnIndex == 2 ? valueView : eraseButton; + sourceComponent: columnIndex === 0 ? typeSelector : columnIndex == 4 ? eraseButton : textView; }} @@ -36,8 +37,9 @@ JASPW.JASPDataView property int columnIdx: columnIndex property string modelText: itemText property var modelData: itemData - - sourceComponent: columnIndex != 2 ? textEdit : valueEdit + //property bool modelEnabled: itemEnabled + + sourceComponent: textEdit }} Component @@ -48,7 +50,8 @@ JASPW.JASPDataView { text: modelText == "" ? "..." : modelText; font: jaspTheme.font; - color: jaspTheme.textEnabled; + color: enabled ? jaspTheme.textEnabled : jaspTheme.textDisabled; + enabled: modelEnabled MouseArea { anchors.fill: parent; @@ -68,7 +71,7 @@ JASPW.JASPDataView { id: editItem text: modelText - color: jaspTheme.textEnabled + color: enabled ? jaspTheme.textEnabled : jaspTheme.textDisabled; font: jaspTheme.font focus: true clip: true @@ -76,6 +79,7 @@ JASPW.JASPDataView onEditingFinished: {saveEdit(); jaspDataView.view.forceActiveFocus(); } Keys.onReturnPressed: {saveEdit(); jaspDataView.view.forceActiveFocus(); } Component.onCompleted: forceActiveFocus() + //enabled: modelEnabled onActiveFocusChanged: { if(!activeFocus) @@ -123,101 +127,6 @@ JASPW.JASPDataView } } - Component - { - id: valueView - - RowLayout - { - //opacity: rowIdx < jaspDataView.view.rowCount - 1 ? 1.0 : 0.5 - - Text - { - text: modelData && modelData.length > 0 ? modelData[0] : modelText - font: jaspTheme.font; - color: jaspTheme.textEnabled; - - MouseArea - { - anchors.fill: parent; - onClicked: jaspDataView.view.edit(rowIdx, columnIdx); - } - } - - Text - { - text: modelData && modelData.length > 1 ? modelData[1] : "" - font: jaspTheme.font; - color: jaspTheme.textEnabled; - visible: modelData && modelData.length > 1 - - MouseArea - { - anchors.fill: parent; - onClicked: jaspDataView.view.edit(rowIdx, columnIdx); - } - } - - - } - } - - Component - { - id: valueEdit - - RowLayout - { - //opacity: rowIdx < jaspDataView.view.rowCount - 1 ? 1.0 : 0.5 - - property bool has2Fields: modelData && modelData.length > 1 - - TextInput - { - id: editItem0 - text: modelData[0] - color: jaspTheme.textEnabled - font: jaspTheme.font - clip: true - focus: true - onEditingFinished: jaspDataView.view.forceActiveFocus(); - Keys.onReturnPressed: jaspDataView.view.forceActiveFocus(); - Component.onCompleted: forceActiveFocus() - onActiveFocusChanged: - { - if(!activeFocus) - { - jaspDataView.view.commitEdit(rowIdx, columnIdx, has2Fields ? [text, modelData[1]] : [text]); - jaspDataView.view.clearEdit(); - } - } - } - - TextInput - { - id: editItem1 - text: modelData[1] - color: jaspTheme.textEnabled - font: jaspTheme.font - clip: true - visible: has2Fields - enabled: has2Fields - onEditingFinished: jaspDataView.view.forceActiveFocus(); - Keys.onReturnPressed: jaspDataView.view.forceActiveFocus(); - Component.onCompleted: forceActiveFocus() - onActiveFocusChanged: - { - if(!activeFocus) - { - jaspDataView.view.commitEdit(rowIdx, columnIdx, has2Fields ? [modelData[0], text] : [text]); - jaspDataView.view.clearEdit(); - } - } - } - } - } - - Component { id: eraseButton diff --git a/Desktop/results/ploteditorreferencelines.cpp b/Desktop/results/ploteditorreferencelines.cpp index ab3f97fa5f..f69ea94cfa 100644 --- a/Desktop/results/ploteditorreferencelines.cpp +++ b/Desktop/results/ploteditorreferencelines.cpp @@ -19,7 +19,7 @@ int PlotEditor::References::rowCount(const QModelIndex &parent) const int PlotEditor::References::columnCount(const QModelIndex &parent) const { - return 4; + return 5; } // I hate the following and fixes for this kind of shenanigans are in a different branch but for now just do this: @@ -39,9 +39,29 @@ QHash PlotEditor::References::roleNames() const return roles; } +bool References::indexDisabled(const QModelIndex &index) const +{ + if(index.row() >= rowCount()) + return false; + + if(index.row() >= _refs.size() || _refs[index.row()].point) + return false; + + if(_refs[index.row()].horizontal && index.column() == 3) + return true; + + if(!_refs[index.row()].horizontal && index.column() == 2) + return true; + + return false; +} + Qt::ItemFlags References::flags(const QModelIndex &index) const { - return QAbstractTableModel::flags(index) | Qt::ItemIsEditable; + Qt::ItemFlags flags = QAbstractTableModel::flags(index) | Qt::ItemIsEditable; + if(indexDisabled(index)) + flags &= ~Qt::ItemIsEnabled; + return flags; } QVariant PlotEditor::References::headerData(int section, Qt::Orientation orientation, int role) const @@ -56,8 +76,9 @@ QVariant PlotEditor::References::headerData(int section, Qt::Orientation orienta { case 0: return tr("Type"); case 1: return tr("Text"); - case 2: return tr("Position"); - case 3: return tr("Remove"); + case 2: return tr("Horizontal"); + case 3: return tr("Vertical"); + case 4: return tr("Remove"); }; break; @@ -111,6 +132,7 @@ QVariant PlotEditor::References::data(const QModelIndex &index, int role) const case 0: return ReferenceType::Point; default: return ""; case 2: return 0; + case 3: return 0; } const Reference & ref = _refs[index.row()]; @@ -119,7 +141,8 @@ QVariant PlotEditor::References::data(const QModelIndex &index, int role) const { case 0: return ref.point ? ReferenceType::Point : ref.horizontal ? ReferenceType::LineHorizontal : ReferenceType::LineVertical; case 1: return ref.text; - case 2: return ref.point ? QVariantList(ref.x) : QVariantList(ref.x, ref.y); + case 2: return ref.x; + case 3: return ref.y; } return QVariant(); @@ -140,6 +163,7 @@ bool References::setData(const QModelIndex &index, const QVariant &value, int ro emit addToUndoStack(); + beginResetModel(); Reference & ref = _refs[index.row()]; switch(index.column()) @@ -160,21 +184,20 @@ bool References::setData(const QModelIndex &index, const QVariant &value, int ro } case 2: { - QVariantList values = value.toList(); - double x = values.size() > 0 ? values[0].toDouble() : NAN, - y = values.size() > 1 ? values[1].toDouble() : NAN; - - ref.x = x; - if(ref.point) - ref.y = y; + ref.x = value.toDouble(); break; } case 3: + { + ref.y = value.toDouble(); + break; + } + case 4: removeRows(index.row(), 1); break; } - - emit dataChanged(index, index); + endResetModel(); + //emit dataChanged(References::index(index.row(), 0), References::index(index.row(), columnCount())); emit somethingChanged(); return true; @@ -238,11 +261,11 @@ void References::setViewWidth(int newViewWidth) _viewWidth = newViewWidth; emit viewWidthChanged(); - int quarterPounder = newViewWidth / 4; + int fiver = newViewWidth / 5; beginResetModel(); - for(int i=0; i<4; i++) - setColWidth(i, quarterPounder); + for(int i=0; i<5; i++) + setColWidth(i, fiver); endResetModel(); } diff --git a/Desktop/results/ploteditorreferencelines.h b/Desktop/results/ploteditorreferencelines.h index 32a712607d..66beef2f58 100644 --- a/Desktop/results/ploteditorreferencelines.h +++ b/Desktop/results/ploteditorreferencelines.h @@ -55,6 +55,9 @@ class References : public QAbstractTableModel public slots: void setColWidth(int index, int width); +protected: + bool indexDisabled(const QModelIndex &index) const; + signals: void somethingChanged(); void addToUndoStack(); @@ -67,6 +70,7 @@ public slots: std::vector _refs; intvec _widths; int _viewWidth; + }; } diff --git a/QMLComponents/datasetviewbase.cpp b/QMLComponents/datasetviewbase.cpp index a7a3a39e6c..86dce277c1 100644 --- a/QMLComponents/datasetviewbase.cpp +++ b/QMLComponents/datasetviewbase.cpp @@ -201,6 +201,7 @@ void DataSetViewBase::modelDataChanged(const QModelIndex &topLeft, const QModelI { //Changes here should be considered also for DataSetViewBase::setStyleDataItem: context->setContextProperty("itemText", _model->data(modelIndex)); + context->setContextProperty("itemEnabled", bool(_model->flags(modelIndex) & Qt::ItemIsEnabled)); context->setContextProperty("itemTextEdit", _model->data(modelIndex, getRole("noSepaDisplay"))); context->setContextProperty("itemShadowText", _model->data(modelIndex, getRole("shadowDisplay"))); context->setContextProperty("itemLabel", _model->data(modelIndex, getRole("label"))); @@ -1485,7 +1486,9 @@ QQmlContext * DataSetViewBase::setStyleDataItem(QQmlContext * previousContext, b QModelIndex modelIndex = _model->index(row, col); - bool isEditable(_model->flags(modelIndex) & Qt::ItemIsEditable); + auto flagsModel = _model->flags(modelIndex); + bool isEditable ( flagsModel & Qt::ItemIsEditable), + isEnabled ( flagsModel & Qt::ItemIsEnabled); if(isEditable || _storedDisplayText.count(row) == 0 || _storedDisplayText[row].count(col) == 0) _storedDisplayText[row][col] = _model->data(modelIndex, Qt::DisplayRole).toString(); @@ -1511,6 +1514,7 @@ QQmlContext * DataSetViewBase::setStyleDataItem(QQmlContext * previousContext, b //If adding or changes behaviour also do that there previousContext->setContextProperty("itemText", text); previousContext->setContextProperty("itemData", _model->data(modelIndex)); + previousContext->setContextProperty("itemEnabled", isEnabled); previousContext->setContextProperty("itemTextEdit", textEdit); previousContext->setContextProperty("itemShadowText", _model->data(modelIndex, getRole("shadowDisplay"))); previousContext->setContextProperty("itemLabel", _model->data(modelIndex, getRole("label"))); From aae34bea25a8a65ccd2226c61650f6072980aea9 Mon Sep 17 00:00:00 2001 From: Joris Goosen Date: Fri, 31 Oct 2025 15:47:08 +0100 Subject: [PATCH 4/4] vertical lines have horizontal positions... --- .../JASP/Widgets/PlotEditor/PlotEditingReferenceLines.qml | 1 + Desktop/results/ploteditorreferencelines.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Desktop/components/JASP/Widgets/PlotEditor/PlotEditingReferenceLines.qml b/Desktop/components/JASP/Widgets/PlotEditor/PlotEditingReferenceLines.qml index fd1f68f279..846692de83 100644 --- a/Desktop/components/JASP/Widgets/PlotEditor/PlotEditingReferenceLines.qml +++ b/Desktop/components/JASP/Widgets/PlotEditor/PlotEditingReferenceLines.qml @@ -52,6 +52,7 @@ JASPW.JASPDataView font: jaspTheme.font; color: enabled ? jaspTheme.textEnabled : jaspTheme.textDisabled; enabled: modelEnabled + visible: enabled MouseArea { anchors.fill: parent; diff --git a/Desktop/results/ploteditorreferencelines.cpp b/Desktop/results/ploteditorreferencelines.cpp index f69ea94cfa..2c22c5d52c 100644 --- a/Desktop/results/ploteditorreferencelines.cpp +++ b/Desktop/results/ploteditorreferencelines.cpp @@ -47,10 +47,10 @@ bool References::indexDisabled(const QModelIndex &index) const if(index.row() >= _refs.size() || _refs[index.row()].point) return false; - if(_refs[index.row()].horizontal && index.column() == 3) + if(_refs[index.row()].horizontal && index.column() == 2) return true; - if(!_refs[index.row()].horizontal && index.column() == 2) + if(!_refs[index.row()].horizontal && index.column() == 3) return true; return false;