diff --git a/CommonData/column.cpp b/CommonData/column.cpp index 4bd1d1f89a..8b87103c82 100644 --- a/CommonData/column.cpp +++ b/CommonData/column.cpp @@ -799,9 +799,10 @@ void Column::labelsTempReset() _labelsTempRevision = -1; _labelsTempMaxWidth = 0; _labelsTempNumerics = 0; + _labelsFilterCountTemp = 0; } -int Column::labelsTempCount() +int Column::labelsTempCount(bool onlyFiltered) { if(_revision != _labelsTempRevision) { @@ -819,6 +820,8 @@ int Column::labelsTempCount() if(!std::isnan(*_labelsTempDbls.rbegin())) _labelsTempNumerics++; + if(_labels[r]->filterAllows()) + _labelsFilterCountTemp++; } doubleset dblset; @@ -843,6 +846,8 @@ int Column::labelsTempCount() _labelsTempToIndex[doubleLabel] = _labelsTemp.size()-1; _labelsTempMaxWidth = std::max(_labelsTempMaxWidth, qsizetype(_labelsTemp[_labelsTemp.size()-1].size())); _labelsTempNumerics ++; + _labelsFilterCountTemp ++; + } } @@ -850,7 +855,7 @@ int Column::labelsTempCount() _labelsTempRevision = _revision; } - return _labelsTemp.size(); + return onlyFiltered ? _labelsFilterCountTemp : _labelsTemp.size(); } int Column::labelsTempNumerics() @@ -934,6 +939,14 @@ int Column::labelsDoubleValueIsTempLabelRow(double dbl) return -1; } +void Column::labelsFilterCountUpdate(bool increase) +{ + if(increase) + _labelsFilterCountTemp++; + else if(_labelsFilterCountTemp > 0) + _labelsFilterCountTemp--; +} + void Column::_resetLabelValueMap() { _labelByIntsIdMap.clear(); diff --git a/CommonData/column.h b/CommonData/column.h index 10b8fc8202..f01b5b8afa 100644 --- a/CommonData/column.h +++ b/CommonData/column.h @@ -118,7 +118,7 @@ class Column : public DataSetBaseNode strintmap labelsResetValues( int & maxValue); void labelsRemoveBeyond( size_t indexToStartRemoving); - int labelsTempCount(); ///< Generates the labelsTemp also! + int labelsTempCount(bool onlyFiltered = false); ///< Generates the labelsTemp also! int labelsTempNumerics(); ///< Also calls labelsTempCount() to be sure it has some info const stringvec & labelsTemp(); void labelsTempReset(); @@ -127,6 +127,7 @@ class Column : public DataSetBaseNode double labelsTempValueDouble( size_t tempLabelIndex); int labelsDoubleValueIsTempLabelRow(double dbl); Label * labelDoubleDummy() { return _doubleDummy; } + void labelsFilterCountUpdate(bool increase); std::set labelsMoveRows(std::vector rows, bool up); void labelsReverse(); @@ -252,6 +253,7 @@ class Column : public DataSetBaseNode _labelsTempNumerics = 0; ///< Use the labelsTemp step to calculate the amount of numeric labels qsizetype _labelsTempMaxWidth = 0; stringvec _labelsTemp; ///< Contains displaystring for labels. Used to allow people to edit "double" labels. Initialized when necessary + int _labelsFilterCountTemp; doublevec _labelsTempDbls; strintmap _labelsTempToIndex; bool _invalidated = false, diff --git a/Desktop/data/columnsmodel.cpp b/Desktop/data/columnsmodel.cpp index dce82372ce..a853f571c5 100644 --- a/Desktop/data/columnsmodel.cpp +++ b/Desktop/data/columnsmodel.cpp @@ -16,6 +16,7 @@ ColumnsModel::ColumnsModel(DataSetTableModel *tableModel) connect(_tableModel, &DataSetTableModel::columnTypeChanged, this, [&](QString col, int) { emit columnTypeChanged(col); }); connect(_tableModel, &DataSetTableModel::labelChanged, this, [&](QString col, QString orgLabel, QString newLabel) { emit labelsChanged(col, {std::make_pair(orgLabel, newLabel) }); } ); connect(_tableModel, &DataSetTableModel::labelsReordered, this, &ColumnsModel::labelsReordered ); + connect(_tableModel, &DataSetTableModel::labelFilterChanged, this, &ColumnsModel::labelFilterChanged ); auto * info = new VariableInfo(_singleton); @@ -24,6 +25,7 @@ ColumnsModel::ColumnsModel(DataSetTableModel *tableModel) connect(this, &ColumnsModel::columnTypeChanged, info, &VariableInfo::columnTypeChanged ); connect(this, &ColumnsModel::labelsChanged, info, &VariableInfo::labelsChanged ); connect(this, &ColumnsModel::labelsReordered, info, &VariableInfo::labelsReordered ); + connect(this, &ColumnsModel::labelFilterChanged, info, &VariableInfo::labelFilterChanged ); connect(this, &QTransposeProxyModel::columnsInserted, info, &VariableInfo::rowCountChanged ); connect(this, &QTransposeProxyModel::columnsRemoved, info, &VariableInfo::rowCountChanged ); connect(this, &QTransposeProxyModel::modelReset, info, &VariableInfo::rowCountChanged ); diff --git a/Desktop/data/columnsmodel.h b/Desktop/data/columnsmodel.h index 70718bb2ee..109d7cf440 100644 --- a/Desktop/data/columnsmodel.h +++ b/Desktop/data/columnsmodel.h @@ -44,6 +44,7 @@ public slots: void columnTypeChanged( QString colName); void labelsChanged( QString columnName, QMap changedLabels); void labelsReordered( QString columnName); + void labelFilterChanged(QString columnName); private: QVariant _getLabels(int colId) const; diff --git a/Desktop/data/datasetpackage.cpp b/Desktop/data/datasetpackage.cpp index 60bf062f0b..3bd085c03e 100644 --- a/Desktop/data/datasetpackage.cpp +++ b/Desktop/data/datasetpackage.cpp @@ -518,7 +518,7 @@ QVariant DataSetPackage::data(const QModelIndex &index, int role) const case int(specialRoles::filter): return getRowFilter(index.row()); case int(specialRoles::columnType): return int(column->type()); case int(specialRoles::totalNumericValues): return column->labelsTempNumerics(); - case int(specialRoles::totalLevels): return int(column->labelsTemp().size()); + case int(specialRoles::totalLevels): return int(column->labelsTempCount(true)); case int(specialRoles::computedColumnType): return int(column->codeType()); case int(specialRoles::columnPkgIndex): return index.column(); case int(specialRoles::lines): @@ -718,7 +718,7 @@ bool DataSetPackage::setData(const QModelIndex &index, const QVariant &value, in if(column->hasFilter()) { - emit labelFilterChanged(); + emit labelFilterChanged(tq(column->name())); emit runFilter(); } } @@ -814,7 +814,7 @@ void DataSetPackage::resetFilterAllows(size_t columnIndex) _dataSet->column(columnIndex)->resetFilter(); - emit labelFilterChanged(); + emit labelFilterChanged(tq(_dataSet->column(columnIndex)->name())); QModelIndex parentModel = indexForSubNode(_dataSet->dataNode()); emit dataChanged(DataSetPackage::index(0, columnIndex, parentModel), DataSetPackage::index(rowCount() - 1, columnIndex, parentModel), {int(specialRoles::filter)} ); @@ -865,6 +865,7 @@ bool DataSetPackage::setLabelDisplay(const QModelIndex &index, const QString &ne aChange = true; } + QString oldLabel = tq(label->label()); if(label->setLabel(newLabel.toStdString())) { aChange = true; @@ -877,6 +878,9 @@ bool DataSetPackage::setLabelDisplay(const QModelIndex &index, const QString &ne changedCols = {column->name()}; endSynchingDataChangedColumns(changedCols, false, false); + + if(aChange) + emit labelChanged(tq(column->name()), oldLabel, tq(label->label())); if(setManual) setManualEdits(true); @@ -1011,12 +1015,14 @@ bool DataSetPackage::setLabelAllowFilter(const QModelIndex & index, bool newAllo int col = column->data()->columnIndex(column); bool before = column->hasFilter(); - labels[row]->setFilterAllows(newAllowValue); + + if (labels[row]->setFilterAllows(newAllowValue)) + column->labelsFilterCountUpdate(newAllowValue); if(before != column->hasFilter()) notifyColumnFilterStatusChanged(col); //basically resetModel now - emit labelFilterChanged(); + emit labelFilterChanged(tq(column->name())); QModelIndex columnParentNode = indexForSubNode(column); emit dataChanged(DataSetPackage::index(row, 0, columnParentNode), DataSetPackage::index(row, columnCount(columnParentNode), columnParentNode), { int(specialRoles::filter) }); emit filteredOutChanged(col); diff --git a/Desktop/data/datasetpackage.h b/Desktop/data/datasetpackage.h index 897205b943..7e8e72af2c 100644 --- a/Desktop/data/datasetpackage.h +++ b/Desktop/data/datasetpackage.h @@ -283,7 +283,7 @@ class DataSetPackage : public QAbstractItemModel //Not QAbstractTableModel becau void runFilter(); void badDataEntered(const QModelIndex index); void allFiltersReset(); - void labelFilterChanged(); + void labelFilterChanged( QString columnName); void labelChanged( QString columnName, QString originalLabel, QString newLabel); void columnDataTypeChanged( QString columnName); void labelsReordered( QString columnName); diff --git a/Desktop/data/datasettablemodel.cpp b/Desktop/data/datasettablemodel.cpp index 483defb406..005e388881 100644 --- a/Desktop/data/datasettablemodel.cpp +++ b/Desktop/data/datasettablemodel.cpp @@ -28,6 +28,7 @@ DataSetTableModel::DataSetTableModel(bool showInactive) connect(DataSetPackage::pkg(), &DataSetPackage::columnDataTypeChanged, this, [&](QString colName) { emit columnTypeChanged(colName, int(DataSetPackage::pkg()->getColumnType(colName))); }, Qt::QueuedConnection); connect(DataSetPackage::pkg(), &DataSetPackage::labelChanged, this, &DataSetTableModel::labelChanged ); connect(DataSetPackage::pkg(), &DataSetPackage::labelsReordered, this, &DataSetTableModel::labelsReordered ); + connect(DataSetPackage::pkg(), &DataSetPackage::labelFilterChanged, this, &DataSetTableModel::labelFilterChanged ); //connect(this, &DataSetTableModel::dataChanged, this, &DataSetTableModel::onDataChanged, Qt::QueuedConnection); setFilterRole(int(DataSetPackage::specialRoles::filter)); diff --git a/Desktop/data/datasettablemodel.h b/Desktop/data/datasettablemodel.h index 753735e8f0..65a3fa09f4 100644 --- a/Desktop/data/datasettablemodel.h +++ b/Desktop/data/datasettablemodel.h @@ -57,6 +57,7 @@ class DataSetTableModel : public DataSetTableProxy void columnTypeChanged(QString colName, int colType); void labelChanged(QString columnName, QString originalLabel, QString newLabel); void labelsReordered(QString columnName); + void labelFilterChanged(QString columnName); void renameColumnDialog(int columnIndex); diff --git a/Engine/rbridge.cpp b/Engine/rbridge.cpp index b61f820270..4ce5369ab9 100644 --- a/Engine/rbridge.cpp +++ b/Engine/rbridge.cpp @@ -712,7 +712,7 @@ std::vector rbridge_applyFilter(const std::string & filterCode, const std: jaspRCPP_freeArrayPointer(&arrayPointer); if(!atLeastOneRow) - throw filterException("Filtered out all data.."); + throw filterException("Filtered out all data."); if(arrayLength != rowCount) { diff --git a/QMLComponents/controls/sourceitem.cpp b/QMLComponents/controls/sourceitem.cpp index d8a5b7d8cc..73aebdd710 100644 --- a/QMLComponents/controls/sourceitem.cpp +++ b/QMLComponents/controls/sourceitem.cpp @@ -133,6 +133,7 @@ void SourceItem::connectModels() } ); connect(variableInfo, &VariableInfo::labelsChanged, controlModel, &ListModel::sourceLabelsChanged ); connect(variableInfo, &VariableInfo::labelsReordered, controlModel, &ListModel::sourceLabelsReordered ); + connect(variableInfo, &VariableInfo::labelFilterChanged, controlModel, &ListModel::sourceLabelFilterChanged ); connect(variableInfo, &VariableInfo::columnsChanged, controlModel, &ListModel::sourceColumnsChanged ); } @@ -142,6 +143,7 @@ void SourceItem::connectModels() connect(_sourceListModel, &ListModel::columnTypeChanged, controlModel, &ListModel::sourceColumnTypeChanged); connect(_sourceListModel, &ListModel::labelsChanged, controlModel, &ListModel::sourceLabelsChanged ); connect(_sourceListModel, &ListModel::labelsReordered, controlModel, &ListModel::sourceLabelsReordered ); + connect(_sourceListModel, &ListModel::labelFilterChanged, controlModel, &ListModel::sourceLabelFilterChanged ); connect(_sourceListModel, &ListModel::columnsChanged, controlModel, &ListModel::sourceColumnsChanged ); } diff --git a/QMLComponents/controls/variableslistbase.cpp b/QMLComponents/controls/variableslistbase.cpp index 540cd63cc5..3829288a71 100644 --- a/QMLComponents/controls/variableslistbase.cpp +++ b/QMLComponents/controls/variableslistbase.cpp @@ -88,7 +88,12 @@ void VariablesListBase::setUp() //We use macros here because the signals come from QML QQuickItem::connect(this, SIGNAL(itemDoubleClicked(int)), this, SLOT(itemDoubleClickedHandler(int))); QQuickItem::connect(this, SIGNAL(itemsDropped(QVariant, QVariant, int)), this, SLOT(itemsDroppedHandler(QVariant, QVariant, int))); - connect(this, &VariablesListBase::allowedColumnsChanged, this, &VariablesListBase::_setAllowedVariables); + connect(this, &VariablesListBase::allowedColumnsChanged, this, &VariablesListBase::_setAllowedVariables ); + connect(_draggableModel, &ListModelDraggable::labelFilterChanged, this, &VariablesListBase::checkLevelsConstraints ); + connect(this, &VariablesListBase::maxLevelsChanged, this, &VariablesListBase::checkLevelsConstraints ); + connect(this, &VariablesListBase::minLevelsChanged, this, &VariablesListBase::checkLevelsConstraints ); + connect(this, &VariablesListBase::maxNumericLevelsChanged, this, &VariablesListBase::checkLevelsConstraints ); + connect(this, &VariablesListBase::minNumericLevelsChanged, this, &VariablesListBase::checkLevelsConstraints ); } void VariablesListBase::_setInitialized(const Json::Value &value) @@ -326,11 +331,8 @@ void VariablesListBase::setVariableType(int index, int type) model()->setVariableType(index, columnType(type)); } -void VariablesListBase::termsChangedHandler() +void VariablesListBase::checkLevelsConstraints() { - setColumnsTypes(model()->termsTypes()); - setColumnsNames(model()->terms().asQList()); - bool noScaleAllowed = !_allowedTypesModel->hasType(columnType::scale); if (_minLevels >= 0 || _maxLevels >= 0 || _minNumericLevels >= 0 || _maxNumericLevels >= 0 || noScaleAllowed) @@ -387,6 +389,14 @@ void VariablesListBase::termsChangedHandler() if (!hasError) clearControlError(); } +} + +void VariablesListBase::termsChangedHandler() +{ + setColumnsTypes(model()->termsTypes()); + setColumnsNames(model()->terms().asQList()); + + checkLevelsConstraints(); if (_boundControl) _boundControl->resetBoundValue(); else JASPListControl::termsChangedHandler(); diff --git a/QMLComponents/controls/variableslistbase.h b/QMLComponents/controls/variableslistbase.h index 9b630c1126..fab4c6aca8 100644 --- a/QMLComponents/controls/variableslistbase.h +++ b/QMLComponents/controls/variableslistbase.h @@ -110,6 +110,7 @@ protected slots: void itemDoubleClickedHandler(int index); void itemsDroppedHandler(QVariant indexes, QVariant vdropList, int dropItemIndex); void interactionHighOrderHandler(JASPControl* checkBoxControl); + void checkLevelsConstraints(); protected: GENERIC_SET_FUNCTION(ListViewType, _listViewType, listViewTypeChanged, ListViewType ) diff --git a/QMLComponents/models/listmodel.cpp b/QMLComponents/models/listmodel.cpp index 8984edfecc..0911e25e29 100644 --- a/QMLComponents/models/listmodel.cpp +++ b/QMLComponents/models/listmodel.cpp @@ -685,6 +685,15 @@ bool ListModel::sourceLabelsReordered(QString columnName) return change; } +bool ListModel::sourceLabelFilterChanged(QString columnName) +{ + bool change = terms().contains(columnName); + if (change) + emit labelFilterChanged(columnName); + + return change; +} + void ListModel::sourceColumnsChanged(QStringList columns) { QStringList changedColumns; diff --git a/QMLComponents/models/listmodel.h b/QMLComponents/models/listmodel.h index 71ba96e572..2d608e1879 100644 --- a/QMLComponents/models/listmodel.h +++ b/QMLComponents/models/listmodel.h @@ -107,6 +107,7 @@ class ListModel : public QAbstractTableModel, public VariableInfoConsumer void columnTypeChanged(Term term); void labelsChanged(QString columnName, QMap = {}); void labelsReordered(QString columnName); + void labelFilterChanged(QString columnName); void columnsChanged(QStringList columns); void selectedItemsChanged(); void oneTermChanged(const QString& oldName, const QString& newName); @@ -117,6 +118,7 @@ public slots: virtual int sourceColumnTypeChanged(Term sourceTerm); virtual bool sourceLabelsChanged(QString columnName, QMap changedLabels = {}); virtual bool sourceLabelsReordered(QString columnName); + virtual bool sourceLabelFilterChanged(QString columnName); virtual void sourceColumnsChanged(QStringList columns); void dataChangedHandler(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector &roles = QVector()); diff --git a/QMLComponents/models/listmodelavailableinterface.cpp b/QMLComponents/models/listmodelavailableinterface.cpp index eb6277485c..9faa508e73 100644 --- a/QMLComponents/models/listmodelavailableinterface.cpp +++ b/QMLComponents/models/listmodelavailableinterface.cpp @@ -169,6 +169,16 @@ bool ListModelAvailableInterface::sourceLabelsChanged(QString columnName, QMaplistView(), &JASPListControl::setContainsVariables ); connect(listView(), &JASPListControl::containsInteractionsChanged, assignedModel->listView(), &JASPListControl::setContainsInteractions ); } diff --git a/QMLComponents/models/listmodelavailableinterface.h b/QMLComponents/models/listmodelavailableinterface.h index 60fb1c8d88..0d37d181d3 100644 --- a/QMLComponents/models/listmodelavailableinterface.h +++ b/QMLComponents/models/listmodelavailableinterface.h @@ -55,6 +55,7 @@ public slots: int sourceColumnTypeChanged(Term name) override; bool sourceLabelsChanged(QString columnName, QMap = {}) override; bool sourceLabelsReordered(QString columnName) override; + bool sourceLabelFilterChanged(QString columnName) override; void removeAssignedModel(ListModelAssignedInterface *assignedModel); void clearAssignedModels() { _assignedModels.clear(); } diff --git a/QMLComponents/variableinfo.h b/QMLComponents/variableinfo.h index 86b5b292ca..5093645bd3 100644 --- a/QMLComponents/variableinfo.h +++ b/QMLComponents/variableinfo.h @@ -61,6 +61,7 @@ class VariableInfo : public QObject void columnTypeChanged(QString colName); void labelsChanged(QString columnName, QMap changedLabels); void labelsReordered(QString columnName); + void labelFilterChanged(QString columnName); void rowCountChanged(); void dataAvailableChanged();