From f7c488d128bfa0b38382ed8119e36ea3d0a63dd8 Mon Sep 17 00:00:00 2001 From: boutinb Date: Tue, 14 Jan 2025 21:30:54 +0100 Subject: [PATCH] Use CommanData in QML Components --- CommonData/filter.cpp | 11 --- CommonData/filter.h | 21 +++-- Desktop/mainwindow.cpp | 32 -------- QMLComponents/CMakeLists.txt | 5 +- .../models/listmodelfiltereddataentry.cpp | 82 +++++++------------ .../models/listmodelfiltereddataentry.h | 12 +-- .../utilities/desktopcommunicator.cpp | 53 ------------ QMLComponents/utilities/desktopcommunicator.h | 23 ------ QMLComponents/variableinfo.cpp | 14 ++++ QMLComponents/variableinfo.h | 1 + 10 files changed, 58 insertions(+), 196 deletions(-) diff --git a/CommonData/filter.cpp b/CommonData/filter.cpp index 2f447a10c9..439fe4cbbc 100644 --- a/CommonData/filter.cpp +++ b/CommonData/filter.cpp @@ -3,8 +3,6 @@ #include "dataset.h" #include "databaseinterface.h" -std::map _filterMap; - Filter::Filter(DataSet * data) : DataSetBaseNode(dataSetBaseNodeType::filter, data), _data(data) { } @@ -17,8 +15,6 @@ Filter::Filter(DataSet * data, const std::string & name, bool createIfMissing) if(db().filterGetId(_name) > -1) dbLoad(); else if(createIfMissing) dbCreate(); else throw std::runtime_error("Filter by name '" + _name + "' but it doesnt exist and createIfMissing=false!\nAre you sure this filter should exist?"); - - _filterMap[name] = this; } void Filter::dbCreate() @@ -140,8 +136,6 @@ void Filter::dbDelete() db().filterDelete(_id); _id = -1; - - _filterMap.erase(_name); } void Filter::incRevision() @@ -181,11 +175,6 @@ bool Filter::filterNameIsFree(const std::string &filterName) return -1 == DatabaseInterface::singleton()->filterGetId(filterName); } -Filter* Filter::getFilterFromName(const std::string & filterName) -{ - return _filterMap[filterName]; -} - void Filter::reset() { if(!_data->writeBatchedToDB()) diff --git a/CommonData/filter.h b/CommonData/filter.h index ce11a194db..3ea7225634 100644 --- a/CommonData/filter.h +++ b/CommonData/filter.h @@ -24,16 +24,16 @@ class Filter : public DataSetBaseNode Filter(DataSet * data); Filter(DataSet * data, const std::string & name, bool createIfMissing = true); - DataSet * data() const { return _data; } - int id() const { return _id; } - const std::string & name() const { return _name; } - const std::string & rFilter() const { return _rFilter; } - const std::string & generatedFilter() const { return _generatedFilter; } - const std::string & constructorJson() const { return _constructorJson; } - const std::string & constructorR() const { return _constructorR; } - const std::string & errorMsg() const { return _errorMsg; } - const std::vector & filtered() const { return _filtered; } - int filteredRowCount() const { return _filteredRowCount; } + DataSet * data() const { return _data; } + int id() const { return _id; } + const std::string & name() const { return _name; } + const std::string & rFilter() const { return _rFilter; } + const std::string & generatedFilter() const { return _generatedFilter; } + const std::string & constructorJson() const { return _constructorJson; } + const std::string & constructorR() const { return _constructorR; } + const std::string & errorMsg() const { return _errorMsg; } + const std::vector & filtered() const { return _filtered; } + int filteredRowCount() const { return _filteredRowCount; } void setRFilter( const std::string & rFilter) { _rFilter = rFilter; dbUpdate(); } void setGeneratedFilter( const std::string & generatedFilter) { _generatedFilter = generatedFilter; dbUpdate(); } @@ -56,7 +56,6 @@ class Filter : public DataSetBaseNode bool checkForUpdates(); static bool filterNameIsFree(const std::string & filterName); - static Filter* getFilterFromName(const std::string & filterName); void reset(); diff --git a/Desktop/mainwindow.cpp b/Desktop/mainwindow.cpp index 6426ce2a25..ef5e06e808 100644 --- a/Desktop/mainwindow.cpp +++ b/Desktop/mainwindow.cpp @@ -77,7 +77,6 @@ MainWindow * MainWindow::_singleton = nullptr; MainWindow::MainWindow(QApplication * application) : QObject(application), _application(application) { std::cout << "MainWindow constructor started" << std::endl; - connect(this, &MainWindow::exitSignal, this, &QApplication::exit, Qt::QueuedConnection); assert(!_singleton); @@ -491,37 +490,6 @@ void MainWindow::makeConnections() Column::setAutoSortByValuesByDefault(PreferencesModel::prefs()->orderByValueByDefault()); auto * dCSingleton = DesktopCommunicator::singleton(); - // For Audit analyses, the Filter object is needed. As the QML objects should not have direct access to the data objects, the needed functions are set as callbacks. - dCSingleton->setFilterFunctions( - [](const std::string& name) { - new Filter(DataSetPackage::pkg()->dataSet(), name, true); - }, - [](const std::string& name) { - Filter* filter = Filter::getFilterFromName(name); - if (filter) - filter->dbDelete(); - }, - [](const std::string& name, const std::string& rFilter) { - Filter* filter = Filter::getFilterFromName(name); - if (filter) - filter->setRFilter(rFilter); - }, - [](const std::string& name) { - Filter* filter = Filter::getFilterFromName(name); - return filter ? filter->checkForUpdates() : false; - }, - [](const std::string& name) { - Filter* filter = Filter::getFilterFromName(name); - return filter ? filter->filtered() : std::vector(); - }, - [](const std::string& name) { - Filter* filter = Filter::getFilterFromName(name); - return filter ? filter->filteredRowCount() : 0; - }, - [](const std::string& name) { - return Filter::filterNameIsFree(name); - } - ); //Needed to allow for a hard split between Desktop/QMLComps: connect(_preferences, &PreferencesModel::uiScaleChanged, dCSingleton, &DesktopCommunicator::uiScaleChanged ); diff --git a/QMLComponents/CMakeLists.txt b/QMLComponents/CMakeLists.txt index 1393cecbf7..0c47ea4185 100644 --- a/QMLComponents/CMakeLists.txt +++ b/QMLComponents/CMakeLists.txt @@ -8,10 +8,9 @@ file(GLOB_RECURSE QML_FILES RELATIVE "${CMAKE_CURRENT_LIST_DIR}" "components/JAS qt_add_qml_module(QMLComponents URI JASP.Controls - #STATIC OUTPUT_DIRECTORY "JASP/Controls" RESOURCE_PREFIX /jasp-stats.org/imports - #PLUGIN_TARGET QMLComponents + #PLUGIN_TARGET QMLComponentsPlugin DEPENDENCIES QtQuick #NO_PLUGIN_OPTIONAL NO_GENERATE_PLUGIN_SOURCE @@ -39,6 +38,7 @@ target_include_directories( QMLComponents PUBLIC # JASP ${PROJECT_SOURCE_DIR}/Common + ${PROJECT_SOURCE_DIR}/CommonData ${PROJECT_SOURCE_DIR}/Common/jaspColumnEncoder ${CMAKE_CURRENT_LIST_DIR}/controls ${CMAKE_CURRENT_LIST_DIR}/rsyntax @@ -50,6 +50,7 @@ target_link_libraries( QMLComponents PUBLIC Common + CommonData Qt::Core Qt::Gui Qt::Widgets diff --git a/QMLComponents/models/listmodelfiltereddataentry.cpp b/QMLComponents/models/listmodelfiltereddataentry.cpp index d7c170f0a2..04fc2e1127 100644 --- a/QMLComponents/models/listmodelfiltereddataentry.cpp +++ b/QMLComponents/models/listmodelfiltereddataentry.cpp @@ -3,8 +3,7 @@ #include "utilities/qutils.h" #include "log.h" #include "controls/jaspcontrol.h" -#include "utilities/desktopcommunicator.h" - +#include "filter.h" ListModelFilteredDataEntry::ListModelFilteredDataEntry(TableViewBase * parent) : ListModelTableViewBase(parent) @@ -16,19 +15,23 @@ ListModelFilteredDataEntry::ListModelFilteredDataEntry(TableViewBase * parent) connect(_tableView, SIGNAL(colNameSignal(QString)), this, SLOT(setColName(QString)) ); connect(_tableView, SIGNAL(extraColSignal(QString)), this, SLOT(setExtraCol(QString)) ); + DataSet* dataSet = VariableInfo::info()->dataSet(); static int counter = 0; do { _filterName = "ListModelFilteredDataEntry_" + std::to_string(counter++); } - while(!filterNameIsFree(_filterName)); + while(!Filter::filterNameIsFree(_filterName)); connect(VariableInfo::info(), &VariableInfo::dataSetChanged, this, &ListModelFilteredDataEntry::dataSetChangedHandler); } ListModelFilteredDataEntry::~ListModelFilteredDataEntry() { - filterDelete(); + if(_filter) + _filter->dbDelete(); + delete _filter; + _filter = nullptr; } void ListModelFilteredDataEntry::dataSetChangedHandler() @@ -49,14 +52,18 @@ void ListModelFilteredDataEntry::setFilter(QString filter) _tableTerms.filter = filter; emit filterChanged(_tableTerms.filter); - filterSetRScript("filterResult <- {" + filter.toStdString() + "};" "\n" + if(_filter) + _filter->setRFilter("filterResult <- {" + filter.toStdString() + "};" "\n" "if(!is.logical(filterResult)) filterResult <- rep(TRUE, rowcount);" "\n" " return(filterResult);" "\n"); } void ListModelFilteredDataEntry::runFilter() { - runFilterByName(tq(_filterName)); + if(!_filter) //prob still need to bind + return; + + runFilterByName(tq(_filter->name())); } void ListModelFilteredDataEntry::filterDoneHandler(const QString &name, const QString & error) @@ -66,16 +73,16 @@ void ListModelFilteredDataEntry::filterDoneHandler(const QString &name, const QS Log::log() << "ListModelFilteredDataEntry::filterDoneHandler for " << name << " and error '" << error << "'" << std::endl; - filterCheckForUpdate(); + _filter->checkForUpdates(); - setAcceptedRows(filtered()); + setAcceptedRows(_filter->filtered()); if(!error.isEmpty()) _tableView->addControlWarning(tr("Filter had error '%1'").arg(error)); else _tableView->clearControlError(); - if(filteredRowCount() == 0) + if(_filter->filteredRowCount() == 0) runFilter(); else informDataSetOfInitialValues(); @@ -167,12 +174,16 @@ void ListModelFilteredDataEntry::initTableTerms(const TableTerms& terms) Log::log() << "Too many values in ListModelFilteredDataEntry" << std::endl; if(terms.filterName.isEmpty()) + { //We dont apparently have a previous filterName, so this is a fresh one, we need a new filter! - assert(!_filterName.empty()); - else if(_filterName.empty()) + assert(!_filter && !_filterName.empty()); + _filter = new Filter(VariableInfo::info()->dataSet(), _filterName, true); + } + else if(!_filter) + { _filterName = fq(terms.filterName); - - filterBuild(); + _filter = new Filter(VariableInfo::info()->dataSet(), _filterName, true); + } if (terms.colName.isEmpty()) { @@ -187,7 +198,7 @@ void ListModelFilteredDataEntry::initTableTerms(const TableTerms& terms) setColName( _tableTerms.colName ); setExtraCol(_tableTerms.extraCol); - _acceptedRows = filtered(); + _acceptedRows = _filter->filtered(); _dataColumns = _tableTerms.colNames; @@ -212,9 +223,10 @@ void ListModelFilteredDataEntry::fillTable() _tableTerms.rowNames.clear(); _tableTerms.values.clear(); - filterCheckForUpdate(); + if (_filter) + _filter->checkForUpdates(); - size_t dataRows = filtered().size() > 0 ? filtered().size() : getDataSetRowCount(); + size_t dataRows = _filter && _filter->filtered().size() > 0 ? _filter->filtered().size() : getDataSetRowCount(); if (_acceptedRows.size() != dataRows) _acceptedRows = std::vector(dataRows, true); @@ -427,41 +439,3 @@ void ListModelFilteredDataEntry::refreshModel() ListModel::refresh(); } -bool ListModelFilteredDataEntry::filterNameIsFree(const std::string& name) -{ - return DesktopCommunicator::singleton()->filterNameIsFree(name); -} - -void ListModelFilteredDataEntry::filterBuild() -{ - if (!_filterName.empty()) - DesktopCommunicator::singleton()->filterBuild(_filterName); -} - -void ListModelFilteredDataEntry::filterDelete() -{ - if (!_filterName.empty()) - DesktopCommunicator::singleton()->filterDelete(_filterName); -} - -void ListModelFilteredDataEntry::filterSetRScript(const std::string& script) -{ - if (!_filterName.empty()) - DesktopCommunicator::singleton()->filterSetRScript(_filterName, script); -} - -bool ListModelFilteredDataEntry::filterCheckForUpdate() -{ - return !_filterName.empty() ? DesktopCommunicator::singleton()->filterCheckForUpdate(_filterName) : false; -} - -std::vector ListModelFilteredDataEntry::filtered() -{ - return !_filterName.empty() ? DesktopCommunicator::singleton()->filtered(_filterName) : std::vector(); -} - -int ListModelFilteredDataEntry::filteredRowCount() -{ - return !_filterName.empty() ? DesktopCommunicator::singleton()->filteredRowCount(_filterName) : 0; -} - diff --git a/QMLComponents/models/listmodelfiltereddataentry.h b/QMLComponents/models/listmodelfiltereddataentry.h index 71ca457a62..663bbeb349 100644 --- a/QMLComponents/models/listmodelfiltereddataentry.h +++ b/QMLComponents/models/listmodelfiltereddataentry.h @@ -22,6 +22,7 @@ #include "listmodeltableviewbase.h" +class Filter; class ListModelFilteredDataEntry : public ListModelTableViewBase { Q_OBJECT @@ -74,16 +75,6 @@ private slots: size_t getDataSetRowCount() const; void fillTable(); - bool filterNameIsFree(const std::string& name); - void filterBuild(); - void filterDelete(); - void filterSetRScript(const std::string& script); - bool filterCheckForUpdate(); - std::vector filtered(); - int filteredRowCount(); - - - private: boolvec _acceptedRows; @@ -94,6 +85,7 @@ private slots: QStringList _dataColumns, _extraColsStr; std::string _filterName; + Filter * _filter = nullptr; bool _informOnce = false; }; diff --git a/QMLComponents/utilities/desktopcommunicator.cpp b/QMLComponents/utilities/desktopcommunicator.cpp index 8dfc3188a7..cc3536d6da 100644 --- a/QMLComponents/utilities/desktopcommunicator.cpp +++ b/QMLComponents/utilities/desktopcommunicator.cpp @@ -16,59 +16,6 @@ DesktopCommunicator *DesktopCommunicator::singleton() return _singleton; } -void DesktopCommunicator::setFilterFunctions( - std::function _builderFunc, - std::function _deleteFunc, - std::function _setRFilterFunc, - std::function _checkForUpdateFunc, - std::function(const std::string&)> _filteredFunc, - std::function _filteredRowCountFunc, - std::function _filterExistFunc) -{ - _filterBuilderFunc = _builderFunc; - _filterDeleteFunc = _deleteFunc; - _filterSetRFilterFunc = _setRFilterFunc; - _filterCheckForUpdateFunc = _checkForUpdateFunc; - _filterFilteredFunc = _filteredFunc; - _filterFilteredRowCountFunc = _filteredRowCountFunc; - _filterNameExistFunc = _filterExistFunc; -} - -void DesktopCommunicator::filterBuild(const std::string &name) -{ - _filterBuilderFunc(name); -} - -void DesktopCommunicator::filterDelete(const std::string& name) -{ - _filterDeleteFunc(name); -} - -void DesktopCommunicator::filterSetRScript(const std::string& name, const std::string& rFilter) -{ - _filterSetRFilterFunc(name, rFilter); -} - -bool DesktopCommunicator::filterCheckForUpdate(const std::string& name) -{ - return _filterCheckForUpdateFunc(name); -} - -std::vector DesktopCommunicator::filtered(const std::string& name) -{ - return _filterFilteredFunc(name); -} - -int DesktopCommunicator::filteredRowCount(const std::string& name) -{ - return _filterFilteredRowCountFunc(name); -} - -bool DesktopCommunicator::filterNameIsFree(const std::string &name) -{ - return _filterNameExistFunc(name); -} - bool DesktopCommunicator::useNativeFileDialog() { #ifdef BUILDING_JASP diff --git a/QMLComponents/utilities/desktopcommunicator.h b/QMLComponents/utilities/desktopcommunicator.h index 0b79f7d36d..3e8873bd6b 100644 --- a/QMLComponents/utilities/desktopcommunicator.h +++ b/QMLComponents/utilities/desktopcommunicator.h @@ -14,21 +14,6 @@ class DesktopCommunicator : public QObject static DesktopCommunicator * singleton(); bool useNativeFileDialog(); - void setFilterFunctions( - std::function _builderFunc, - std::function _deleteFunc, - std::function _setRFilterFunc, - std::function _checkForUpdateFunc, - std::function(const std::string&)> _filteredFunc, - std::function _filteredRowCountFunc, - std::function _filterExistFunc); - void filterBuild(const std::string& name); - void filterDelete(const std::string& name); - void filterSetRScript(const std::string& name, const std::string& rFilter); - bool filterCheckForUpdate(const std::string& name); - std::vector filtered(const std::string& name); - int filteredRowCount(const std::string& name); - bool filterNameIsFree(const std::string& name); signals: void currentJaspThemeChanged(); @@ -38,14 +23,6 @@ class DesktopCommunicator : public QObject private: static DesktopCommunicator * _singleton; - - std::function _filterBuilderFunc; - std::function _filterDeleteFunc; - std::function _filterSetRFilterFunc; - std::function _filterCheckForUpdateFunc; - std::function(const std::string&)> _filterFilteredFunc; - std::function _filterFilteredRowCountFunc; - std::function _filterNameExistFunc; }; #endif // DESKTOPCOMMUNICATOR_H diff --git a/QMLComponents/variableinfo.cpp b/QMLComponents/variableinfo.cpp index 331f000246..ac30e55936 100644 --- a/QMLComponents/variableinfo.cpp +++ b/QMLComponents/variableinfo.cpp @@ -2,6 +2,8 @@ #include "jasptheme.h" #include "QQmlContext" #include "QTimer" +#include "databaseinterface.h" +#include "dataset.h" VariableInfo* VariableInfo::_singleton = nullptr; @@ -65,3 +67,15 @@ bool VariableInfo::dataAvailable() { return _provider ? _provider->provideInfo(VariableInfo::DataAvailable).toBool() : false; } + +DataSet *VariableInfo::dataSet() +{ + static DataSet* singleDataSet = nullptr; + + if (!singleDataSet) + { + DatabaseInterface* db = new DatabaseInterface(false); + singleDataSet = new DataSet(db->dataSetGetId()); + } + return singleDataSet; +} diff --git a/QMLComponents/variableinfo.h b/QMLComponents/variableinfo.h index 2158c6880b..166da51068 100644 --- a/QMLComponents/variableinfo.h +++ b/QMLComponents/variableinfo.h @@ -55,6 +55,7 @@ class VariableInfo : public QObject int rowCount(); bool dataAvailable(); + DataSet * dataSet(); signals: void namesChanged( QMap changedNames);