diff --git a/Desktop/modules/analysisentry.cpp b/Desktop/modules/analysisentry.cpp index 95d5598aff..fdfcbbe6e2 100644 --- a/Desktop/modules/analysisentry.cpp +++ b/Desktop/modules/analysisentry.cpp @@ -23,8 +23,8 @@ namespace Modules { -AnalysisEntry::AnalysisEntry(std::function specialFunc, std::string internalTitle, std::string menuTitle, bool requiresData, std::string icon) - : _title(internalTitle), _function(internalTitle), _menu(menuTitle), _isSeparator(false), _isGroupTitle(!specialFunc), _requiresData(requiresData), _icon(icon), _specialFunc(specialFunc) +AnalysisEntry::AnalysisEntry(std::function specialFunc, std::string internalTitle, std::function menuTitleF, bool requiresData, std::string icon) + : _title(internalTitle), _function(internalTitle), _menuF(menuTitleF), _isSeparator(false), _isGroupTitle(!specialFunc), _requiresData(requiresData), _icon(icon), _specialFunc(specialFunc) {} AnalysisEntry::AnalysisEntry(std::string menuTitle, std::string icon, bool smallIcon) diff --git a/Desktop/modules/analysisentry.h b/Desktop/modules/analysisentry.h index cc773ebf2e..3545861925 100644 --- a/Desktop/modules/analysisentry.h +++ b/Desktop/modules/analysisentry.h @@ -39,12 +39,12 @@ class AnalysisEntry { friend EntryBase; public: - AnalysisEntry(std::function specialFunc, std::string internalTitle, std::string menuTitle, bool requiresData=true, std::string icon = ""); ///< AnalysisEntry with a callbackfunction to JASP, if !specialFunc then a grouptitle + AnalysisEntry(std::function specialFunc, std::string internalTitle, std::function menuTitleF, bool requiresData=true, std::string icon = ""); ///< AnalysisEntry with a callbackfunction to JASP, if !specialFunc then a grouptitle AnalysisEntry(std::string menuTitle, std::string icon = "", bool small=false); ///< AnalysisEntry grouptitle AnalysisEntry(Json::Value & analysisEntry, DynamicModule * dynamicModule, bool defaultRequiresData = true); ///< AnalysisEntry from a modules Description.qml AnalysisEntry(); ///< AnalysisEntry separator - std::string menu() const { return _menu; } + std::string menu() const { return _menuF ? _menuF() : _menu; } std::string title() const { return _title; } std::string function() const { return _function; } std::string qml() const { return _qml != "" ? _qml : _function + ".qml"; } @@ -75,20 +75,21 @@ class AnalysisEntry static bool requiresDataEntries(const AnalysisEntries & entries); private: - std::string _title = "???" , - _function = "???" , - _qml = "???" , - _menu = "???" , - _icon = "" ; - DynamicModule* _dynamicModule = nullptr ; - bool _isSeparator = true , - _isGroupTitle = false , - _isAnalysis = false , - _isEnabled = true , - _requiresData = true , - _hasWrapper = false , - _smallIcon = false ; - std::function _specialFunc = nullptr ; + std::string _title = "???" , + _function = "???" , + _qml = "???" , + _menu = "???" , + _icon = "" ; + DynamicModule* _dynamicModule = nullptr ; + bool _isSeparator = true , + _isGroupTitle = false , + _isAnalysis = false , + _isEnabled = true , + _requiresData = true , + _hasWrapper = false , + _smallIcon = false ; + std::function _specialFunc = nullptr ; + std::function _menuF = nullptr ; //To make it translatable }; } diff --git a/Desktop/modules/ribbonbutton.cpp b/Desktop/modules/ribbonbutton.cpp index ed9c558c7a..1d8ccdca65 100644 --- a/Desktop/modules/ribbonbutton.cpp +++ b/Desktop/modules/ribbonbutton.cpp @@ -17,7 +17,6 @@ // #include "ribbonbutton.h" -#include "enginedefinitions.h" #include "modules/dynamicmodule.h" #include "modules/analysisentry.h" #include "utilities/qutils.h" @@ -49,14 +48,14 @@ RibbonButton::RibbonButton(QObject *parent, DynamicModule * module) : QObject(p bindYourself(); } -RibbonButton::RibbonButton(QObject *parent, std::string name, std::string title, std::string icon, bool requiresData, std::function justThisFunction, std::string toolTip, bool enabled, bool remember, bool defaultActiveBinding) +RibbonButton::RibbonButton(QObject *parent, std::string name, std::function titleF, std::string icon, bool requiresData, std::function justThisFunction, std::function toolTipF, bool enabled, bool remember, bool defaultActiveBinding) : QObject(parent), _enabled(enabled), _defaultActiveBinding(defaultActiveBinding), _remember(remember), _special(true), _module(nullptr), _specialButtonFunc(justThisFunction) { _menuModel = new MenuModel(this); setModuleName(name); - setTitle(title); - setToolTip(tq(toolTip)); + _titleF = titleF; + _toolTipF = toolTipF; setIconSource(tq(icon)); setRequiresData(requiresData); //setRequiresData because setMenu changes it based on the menu entries, but that doesnt work for this special dummy @@ -64,16 +63,16 @@ RibbonButton::RibbonButton(QObject *parent, std::string name, std::string title, bindYourself(); } -RibbonButton::RibbonButton(QObject *parent, std::string name, std::string title, std::string icon, Modules::AnalysisEntries * funcEntries, std::string toolTip, bool enabled, bool remember, bool defaultActiveBinding) +RibbonButton::RibbonButton(QObject *parent, std::string name, std::function titleF, std::string icon, Modules::AnalysisEntries * funcEntries, std::function toolTipF, bool enabled, bool remember, bool defaultActiveBinding) : QObject(parent), _enabled(enabled), _defaultActiveBinding(defaultActiveBinding), _remember(remember), _special(true), _module(nullptr) { _menuModel = new MenuModel(this, funcEntries); setRequiresData(AnalysisEntry::requiresDataEntries(*funcEntries)); setModuleName(name); - setTitle(title); + _titleF = titleF; + _toolTipF = toolTipF; setIconSource(tq(icon)); - setToolTip(tq(toolTip)); bindYourself(); } @@ -150,8 +149,6 @@ void RibbonButton::setReady(bool ready) setEnabled(true); } - - RibbonButton::~RibbonButton() { @@ -291,6 +288,15 @@ void RibbonButton::setToolTip(QString toolTip) emit toolTipChanged(_toolTip); } +void RibbonButton::setToolTipF(std::function toolTipF) +{ + if ((!_toolTipF && !toolTipF) || (_toolTipF && toolTipF && _toolTipF() == toolTipF())) + return; + + _toolTipF = toolTipF; + emit toolTipChanged(_toolTipF()); +} + bool RibbonButton::separator() const { return _separator; diff --git a/Desktop/modules/ribbonbutton.h b/Desktop/modules/ribbonbutton.h index c168e21f74..6c90bcab19 100644 --- a/Desktop/modules/ribbonbutton.h +++ b/Desktop/modules/ribbonbutton.h @@ -56,15 +56,15 @@ class RibbonButton : public QObject RibbonButton(QObject *parent); RibbonButton(QObject *parent, Modules::DynamicModule * module); - RibbonButton(QObject *parent, std::string name, std::string title, std::string icon, bool requiresData, std::function justThisFunction, std::string toolTip = "", bool enabled = true, bool remember = false, bool defaultActiveBinding = true); - RibbonButton(QObject *parent, std::string name, std::string title, std::string icon, Modules::AnalysisEntries * funcEntries, std::string toolTip = "", bool enabled = true, bool remember = false, bool defaultActiveBinding = true); + RibbonButton(QObject *parent, std::string name, std::function titleF, std::string icon, bool requiresData, std::function justThisFunction, std::function toolTipF = [](){return "";}, bool enabled = true, bool remember = false, bool defaultActiveBinding = true); + RibbonButton(QObject *parent, std::string name, std::function titleF, std::string icon, Modules::AnalysisEntries * funcEntries, std::function toolTipF = [](){return "";}, bool enabled = true, bool remember = false, bool defaultActiveBinding = true); ~RibbonButton(); bool requiresData() const { return _requiresData; } bool isCommon() const { return _isCommonModule; } - std::string title() const { return _title; } - QString titleQ() const { return QString::fromStdString(_title); } + std::string title() const { return _titleF ? _titleF() : _title; } + QString titleQ() const { return QString::fromStdString(title()); } QString iconSource() const { return _iconSource; } bool enabled() const { return _enabled; } std::string name() const { return _name; } @@ -75,7 +75,7 @@ class RibbonButton : public QObject stringvec getAllEntries() const; bool dataLoaded() const { return Modules::DynamicModules::dynMods() && Modules::DynamicModules::dynMods()->dataLoaded(); } bool active() const { return _active; } - QString toolTip() const { return _toolTip; } + QString toolTip() const { return _toolTipF ? _toolTipF() : _toolTip; } bool isBundled() const { return _module && _module->isBundled(); } QString version() const { return !_module ? "?" : _module->versionQ(); } bool ready() const { return _ready; } @@ -83,31 +83,31 @@ class RibbonButton : public QObject bool remember() const { return _remember; } bool isSpecial() const { return _special; } - static QString getJsonDescriptionFilename(); + static QString getJsonDescriptionFilename(); bool separator() const; void setSeparator(bool newSeparator); + public slots: - void setDynamicModule(Modules::DynamicModule * module); - void setRequiresData(bool requiresData); - void setIsCommon(bool isCommonModule); - void setTitle(std::string title); - void setTitleQ(QString title) { setTitle(title.toStdString()); } - void setIconSource(QString iconSource); - void setEnabled(bool enabled); - void setModuleName(std::string moduleName); - void setModuleNameQ(QString moduleName) { setModuleName(moduleName.toStdString()); } - void somePropertyChanged() { emit iChanged(this); } - void setToolTip(QString toolTip); - void setReady(bool ready); - void setError(bool error); - void setRemember(bool remember); - void setActive(bool active); - - - void runSpecial(QString func);; - void reloadDynamicModule(Modules::DynamicModule * dynMod); + void setDynamicModule( Modules::DynamicModule * module); + void setRequiresData( bool requiresData); + void setIsCommon( bool isCommonModule); + void setTitle( std::string title); + void setTitleQ( QString title) { setTitle(title.toStdString()); } + void setIconSource( QString iconSource); + void setEnabled( bool enabled); + void setModuleName( std::string moduleName); + void setModuleNameQ( QString moduleName) { setModuleName(moduleName.toStdString()); } + void somePropertyChanged() { emit iChanged(this); } + void setToolTip( QString toolTip); + void setToolTipF( std::function toolTipF); + void setReady( bool ready); + void setError( bool error); + void setRemember( bool remember); + void setActive( bool active); + void runSpecial( QString func); + void reloadDynamicModule( Modules::DynamicModule * dynMod); signals: @@ -152,6 +152,8 @@ public slots: QString _iconSource, _toolTip; std::function _specialButtonFunc = nullptr; + std::function _titleF = nullptr; + std::function _toolTipF = nullptr; }; diff --git a/Desktop/modules/ribbonmodel.cpp b/Desktop/modules/ribbonmodel.cpp index be7cba2e13..22db4f3a7f 100644 --- a/Desktop/modules/ribbonmodel.cpp +++ b/Desktop/modules/ribbonmodel.cpp @@ -38,6 +38,7 @@ RibbonModel::RibbonModel() : QAbstractListModel(DynamicModules::dynMods()) connect(DynamicModules::dynMods(), &DynamicModules::dynamicModuleUninstalled, this, &RibbonModel::removeDynamicRibbonButtonModel ); connect(DynamicModules::dynMods(), &DynamicModules::dynamicModuleReplaced, this, &RibbonModel::dynamicModuleReplaced ); connect(DynamicModules::dynMods(), &DynamicModules::dynamicModuleChanged, this, &RibbonModel::dynamicModuleChanged ); + connect(PreferencesModel::prefs(), &PreferencesModel::languageCodeChanged, this, &RibbonModel::refreshButtons ); } void RibbonModel::loadModules(std::vector commonModulesToLoad, std::vector extraModulesToLoad) @@ -120,42 +121,41 @@ void RibbonModel::addSpecialRibbonButtonsEarly() //_entriesInsert and _entriesDelete are destroyed by the menumodel destructor when the button gets destroyed. _entriesInsert = new AnalysisEntries( { - new AnalysisEntry([&](){ emit this->dataInsertRowBefore( -1); }, "insert-row-before", fq(tr("Insert row above")), true, "menu-row-insert-before"), - new AnalysisEntry([&](){ emit this->dataInsertRowAfter( -1); }, "insert-row-after", fq(tr("Insert row below")), true, "menu-row-insert-after"), + new AnalysisEntry([&](){ emit this->dataInsertRowBefore( -1); }, "insert-row-before", [&](){ return fq(tr("Insert row above"));}, true, "menu-row-insert-before"), + new AnalysisEntry([&](){ emit this->dataInsertRowAfter( -1); }, "insert-row-after", [&](){ return fq(tr("Insert row below"));}, true, "menu-row-insert-after"), new AnalysisEntry(), - new AnalysisEntry([&](){ emit this->dataInsertColumnBefore( -1,false,false); }, "insert-column-before", fq(tr("Insert column before")), true, "menu-column-insert-before"), - new AnalysisEntry([&](){ emit this->dataInsertColumnAfter( -1,false,false); }, "insert-column-after", fq(tr("Insert column after")), true, "menu-column-insert-after"), + new AnalysisEntry([&](){ emit this->dataInsertColumnBefore( -1,false,false); }, "insert-column-before", [&](){ return fq(tr("Insert column before"));}, true, "menu-column-insert-before"), + new AnalysisEntry([&](){ emit this->dataInsertColumnAfter( -1,false,false); }, "insert-column-after", [&](){ return fq(tr("Insert column after"));}, true, "menu-column-insert-after"), new AnalysisEntry(), - new AnalysisEntry([&](){ emit this->dataInsertColumnBefore( -1,true ,false); }, "insert-c-column-before", fq(tr("Insert constructor column before")), true, "menu-column-insert-before"), - new AnalysisEntry([&](){ emit this->dataInsertColumnAfter( -1,true ,false); }, "insert-c-column-after", fq(tr("Insert constructor column after")), true, "menu-column-insert-after"), - new AnalysisEntry([&](){ emit this->dataInsertColumnBefore( -1,true ,true); }, "insert-r-column-before", fq(tr("Insert R column before")), true, "menu-column-insert-before"), - new AnalysisEntry([&](){ emit this->dataInsertColumnAfter( -1,true ,true); }, "insert-r-column-after", fq(tr("Insert R column after")), true, "menu-column-insert-after"), + new AnalysisEntry([&](){ emit this->dataInsertColumnBefore( -1,true ,false); }, "insert-c-column-before", [&](){ return fq(tr("Insert constructor column before"));}, true, "menu-column-insert-before"), + new AnalysisEntry([&](){ emit this->dataInsertColumnAfter( -1,true ,false); }, "insert-c-column-after", [&](){ return fq(tr("Insert constructor column after"));}, true, "menu-column-insert-after"), + new AnalysisEntry([&](){ emit this->dataInsertColumnBefore( -1,true ,true); }, "insert-r-column-before", [&](){ return fq(tr("Insert R column before"));}, true, "menu-column-insert-before"), + new AnalysisEntry([&](){ emit this->dataInsertColumnAfter( -1,true ,true); }, "insert-r-column-after", [&](){ return fq(tr("Insert R column after"));}, true, "menu-column-insert-after"), }); _entriesDelete = new AnalysisEntries( { - new AnalysisEntry([&](){ emit this->dataRemoveColumn(); }, "delete-column", fq(tr("Delete column")), true, "menu-column-remove"), - new AnalysisEntry([&](){ emit this->dataRemoveRow(); }, "delete-row", fq(tr("Delete row")), true, "menu-row-remove"), - new AnalysisEntry([&](){ emit this->cellsClear(); }, "clear-cells", fq(tr("Clear cells")), true, "menu-cells-clear") + new AnalysisEntry([&](){ emit this->dataRemoveColumn(); }, "delete-column", [&](){ return fq(tr("Delete column"));}, true, "menu-column-remove"), + new AnalysisEntry([&](){ emit this->dataRemoveRow(); }, "delete-row", [&](){ return fq(tr("Delete row"));}, true, "menu-row-remove"), + new AnalysisEntry([&](){ emit this->cellsClear(); }, "clear-cells", [&](){ return fq(tr("Clear cells"));}, true, "menu-cells-clear") }); _entriesSynchOn = new AnalysisEntries( { - new AnalysisEntry([&]() { MainWindow::singleton()->startDataEditorHandler(); }, "open-datafile", fq(tr("Open datafile with default spreadsheet editor")), true, ""), - new AnalysisEntry([&]() { emit setDataSynchronisation(false); }, "stop-externaledit", fq(tr("Turn external data synchronisation off")), true, "") + new AnalysisEntry([&]() { MainWindow::singleton()->startDataEditorHandler(); }, "open-datafile", [](){ return fq(tr("Open datafile with default spreadsheet editor"));}, true, ""), + new AnalysisEntry([&]() { emit setDataSynchronisation(false); }, "stop-externaledit", [](){ return fq(tr("Turn external data synchronisation off"));}, true, "") }); - _analysesButton = new RibbonButton(this, "Analyses", fq(tr("Analyses")), "JASP_logo_green.svg", false, [&](){ emit finishCurrentEdit(); emit showStatistics(); }, fq(tr("Switch JASP to analyses mode")), true); - _dataSwitchButton = new RibbonButton(this, "Data", fq(tr("Edit Data")), "data-button.svg", false, [&](){ emit showData(); }, fq(tr("Switch JASP to data editing mode")), false, false, false); - _dataNewButton = new RibbonButton(this, "Data-New", fq(tr("New Data")), "data-button-new.svg", false, [&](){ emit showNewData(); }, fq(tr("Open a workspace without data")), true, false, false); - _dataResizeButton = new RibbonButton(this, "Data-Resize", fq(tr("Resize Data")), "data-button-resize.svg", false, [&](){ emit resizeData(); }, fq(tr("Resize your dataset")), false); - _insertButton = new RibbonButton(this, "Data-Insert", fq(tr("Insert")), "data-button-insert.svg", _entriesInsert, fq(tr("Insert empty columns or rows"))); - _removeButton = new RibbonButton(this, "Data-Remove", fq(tr("Remove")), "data-button-erase.svg", _entriesDelete, fq(tr("Remove columns or rows"))); - _synchroniseOnButton = new RibbonButton(this, "Data-Synch-On", fq(tr("Synchronisation")), "data-button-sync-off.svg", true, [&](){ emit setDataSynchronisation(true); }, fq(tr("Turn external data synchronisation on")), false); - _synchroniseOffButton = new RibbonButton(this, "Data-Synch-Off", fq(tr("Synchronisation")), "data-button-sync-on.svg", _entriesSynchOn, fq(tr("Turn external data synchronisation off")), true); - - _undoButton = new RibbonButton(this, "Data-Undo", fq(tr("Undo")), "menu-undo.svg", true, [&](){ emit dataUndo(); }, fq(tr("Undo changes, %1+Z").arg(getShortCutKey())), true, false, false); - _redoButton = new RibbonButton(this, "Data-Redo", fq(tr("Redo")), "menu-redo.svg", true, [&](){ emit dataRedo(); }, fq(tr("Redo changes, %1+shift+Z or %1+Y").arg(getShortCutKey())), true, false, false); + _analysesButton = new RibbonButton(this, "Analyses", [&](){ return fq(tr("Analyses"));}, "JASP_logo_green.svg", false, [&](){ emit finishCurrentEdit(); emit showStatistics(); }, [&](){return tr("Switch JASP to analyses mode");}, true); + _dataSwitchButton = new RibbonButton(this, "Data", [&](){ return fq(tr("Edit Data"));}, "data-button.svg", false, [&](){ emit showData(); }, [&](){return tr("Switch JASP to data editing mode");}, false, false, false); + _dataNewButton = new RibbonButton(this, "Data-New", [&](){ return fq(tr("New Data"));}, "data-button-new.svg", false, [&](){ emit showNewData(); }, [&](){return tr("Open a workspace without data");}, true, false, false); + _dataResizeButton = new RibbonButton(this, "Data-Resize", [&](){ return fq(tr("Resize Data"));}, "data-button-resize.svg", false, [&](){ emit resizeData(); }, [&](){return tr("Resize your dataset");}, false); + _insertButton = new RibbonButton(this, "Data-Insert", [&](){ return fq(tr("Insert"));}, "data-button-insert.svg", _entriesInsert, [&](){return tr("Insert empty columns or rows");}); + _removeButton = new RibbonButton(this, "Data-Remove", [&](){ return fq(tr("Remove"));}, "data-button-erase.svg", _entriesDelete, [&](){return tr("Remove columns or rows");}); + _synchroniseOnButton = new RibbonButton(this, "Data-Synch-On", [&](){ return fq(tr("Synchronisation"));}, "data-button-sync-off.svg", true, [&](){ emit setDataSynchronisation(true); }, [&](){return tr("Turn external data synchronisation on");}, false); + _synchroniseOffButton = new RibbonButton(this, "Data-Synch-Off", [&](){ return fq(tr("Synchronisation"));}, "data-button-sync-on.svg", _entriesSynchOn, [&](){return tr("Turn external data synchronisation off");}, true); + _undoButton = new RibbonButton(this, "Data-Undo", [&](){ return fq(tr("Undo"));}, "menu-undo.svg", true, [&](){ emit dataUndo(); }, [&](){return tr("Undo changes, %1+Z").arg(getShortCutKey());}, true, false, false); + _redoButton = new RibbonButton(this, "Data-Redo", [&](){ return fq(tr("Redo"));}, "menu-redo.svg", true, [&](){ emit dataRedo(); }, [&](){return tr("Redo changes, %1+shift+Z or %1+Y").arg(getShortCutKey());}, true, false, false); _dataNewButton->setActive(true); connect(this, &RibbonModel::dataLoadedChanged, _dataSwitchButton, [=](bool loaded) { _dataSwitchButton ->setEnabled(loaded); }); @@ -173,14 +173,11 @@ void RibbonModel::addSpecialRibbonButtonsEarly() auto setUnAndRedoButtonLambda = [&,view]() { - QString undoText = view->undoText(), - redoText = view->redoText(); - - _undoButton->setActive(!undoText.isEmpty()); - _redoButton->setActive(!redoText.isEmpty()); + _undoButton->setActive(!view->undoText().isEmpty()); + _redoButton->setActive(!view->redoText().isEmpty()); - _undoButton->setToolTip(tr("Undo %2 (%1+Z)") .arg(getShortCutKey()).arg(undoText)); - _redoButton->setToolTip(tr("Redo %2 (%1+shift+Z or %1+Y)") .arg(getShortCutKey()).arg(redoText)); + _undoButton->setToolTipF([&,view](){return tr("Undo %2 (%1+Z)") .arg(getShortCutKey()).arg(view->undoText());}); + _redoButton->setToolTipF([&,view](){return tr("Redo %2 (%1+shift+Z or %1+Y)") .arg(getShortCutKey()).arg(view->redoText());}); }; @@ -207,7 +204,7 @@ void RibbonModel::addSpecialRibbonButtonsEarly() void RibbonModel::addSpecialRibbonButtonsLate() { - addRibbonButtonModel(new RibbonButton(this, "R", fq(tr("R console")), "Rlogo.svg", false, [&](){ emit showRCommander(); }, fq(tr("Execute R code in a console")), false, true), size_t(RowType::Analyses)); + addRibbonButtonModel(new RibbonButton(this, "R", [&](){return fq(tr("R console")); }, "Rlogo.svg", false, [&](){ emit showRCommander(); }, [&](){ return tr("Execute R code in a console");}, false, true), size_t(RowType::Analyses)); } void RibbonModel::setDataMode(bool data) @@ -455,3 +452,9 @@ void RibbonModel::ribbonButtonModelChanged(RibbonButton* model) if(row > -1) emit dataChanged(index(row), index(row)); } + +void RibbonModel::refreshButtons() +{ + beginResetModel(); + endResetModel(); +} diff --git a/Desktop/modules/ribbonmodel.h b/Desktop/modules/ribbonmodel.h index c4634b86da..e37c6369bf 100644 --- a/Desktop/modules/ribbonmodel.h +++ b/Desktop/modules/ribbonmodel.h @@ -130,7 +130,7 @@ public slots: void setHighlightedModuleIndex(int highlightedModuleIndex); void analysisClicked(QString analysisFunction, QString analysisQML, QString analysisTitle, QString module); void setCurrentRow(int currentRow); - + void refreshButtons(); private slots: void dynamicModuleChanged( Modules::DynamicModule * module);