diff --git a/Desktop/analysis/analysis.cpp b/Desktop/analysis/analysis.cpp
index c5fad62046..583cda81fd 100644
--- a/Desktop/analysis/analysis.cpp
+++ b/Desktop/analysis/analysis.cpp
@@ -27,6 +27,7 @@
#include "utilities/qutils.h"
#include "utilities/settings.h"
#include "utilities/reporter.h"
+#include "utilities/helpmodel.h"
#include "gui/preferencesmodel.h"
#include "results/resultsjsinterface.h"
#include "utilities/messageforwarder.h"
@@ -357,7 +358,8 @@ void Analysis::createForm(QQuickItem* parentItem)
connect(this, &Analysis::titleChanged, _analysisForm, &AnalysisForm::titleChanged );
connect(this, &Analysis::needsRefreshChanged, _analysisForm, &AnalysisForm::needsRefreshChanged );
connect(this, &Analysis::needsRefreshChanged, _analysisForm, &AnalysisForm::rSyntaxTextChanged );
- connect(this, &Analysis::boundValuesChanged, this, &Analysis::setRSyntaxTextInResult, Qt::QueuedConnection );
+ connect(this, &Analysis::boundValuesChanged, this, &Analysis::setRSyntaxTextInResult, Qt::QueuedConnection );
+ connect(_analysisForm, &AnalysisForm::helpJumpToAnchor, this, &Analysis::helpJumpToAnchor, Qt::QueuedConnection );
setRSyntaxTextInResult();
_analysisForm->setShowRButton(_moduleData->hasWrapper());
@@ -1086,6 +1088,11 @@ void Analysis::onUsedVariablesChanged()
DataSetPackage::pkg()->checkComputedColumnDependenciesForAnalysis(this);
}
+void Analysis::helpJumpToAnchor(const QString &anchor)
+{
+ HelpModel::singleton()->jumpToAnchor(anchor);
+}
+
void Analysis::checkForRSources()
{
if(!_results.isMember(".meta"))
diff --git a/Desktop/analysis/analysis.h b/Desktop/analysis/analysis.h
index bc8847f9c9..f9be79ac51 100644
--- a/Desktop/analysis/analysis.h
+++ b/Desktop/analysis/analysis.h
@@ -198,6 +198,7 @@ public slots:
void setRSyntaxTextInResult();
void filterByNameDone(const QString &name, const QString &error);
void onUsedVariablesChanged() override;
+ void helpJumpToAnchor(const QString & anchor);
protected:
void abort();
diff --git a/Desktop/utilities/helpmodel.cpp b/Desktop/utilities/helpmodel.cpp
index 979afd684a..90fd6db61b 100644
--- a/Desktop/utilities/helpmodel.cpp
+++ b/Desktop/utilities/helpmodel.cpp
@@ -7,8 +7,13 @@
#include "gui/preferencesmodel.h"
#include "log.h"
+HelpModel * HelpModel::_singleton = nullptr;
+
HelpModel::HelpModel(QObject * parent) : QObject(parent)
{
+ assert(!_singleton);
+ _singleton = this;
+
setPagePath("index");
connect(this, &HelpModel::pagePathChanged, this, &HelpModel::generateJavascript);
connect(PreferencesModel::prefs(), &PreferencesModel::currentThemeNameChanged, this, &HelpModel::setThemeCss, Qt::QueuedConnection);
@@ -33,6 +38,8 @@ void HelpModel::runJavaScript(QString renderFunc, QString content)
runJavaScriptSignal(renderFunc + "(\"" + content + "\");");
}
+
+
void HelpModel::setVisible(bool visible)
{
if (_visible == visible)
@@ -58,7 +65,7 @@ void HelpModel::loadingSucceeded()
generateJavascript();
}
-void HelpModel::setMarkdown(QString markdown)
+void HelpModel::setMarkdown(const QString & markdown)
{
if (_markdown == markdown)
return;
@@ -76,8 +83,12 @@ void HelpModel::setMarkdown(QString markdown)
void HelpModel::setPagePath(QString pagePath)
{
- _pagePath = pagePath;
- emit pagePathChanged(_pagePath);
+ if(_pagePath != pagePath)
+ _anchorName = "";
+
+ _pagePath = pagePath;
+
+ emit pagePathChanged(HelpModel::pagePath());
}
QString HelpModel::indexURL()
@@ -157,6 +168,8 @@ void HelpModel::showOrToggleParticularPageForAnalysis(Analysis * analysis, QStri
if(analysis == _analysis && pagePath == _pagePath && _visible)
{
setVisible(false);
+ _anchorName = "";
+
return;
}
else
@@ -205,7 +218,7 @@ void HelpModel::setFont()
}
///Temporary function for https://github.com/jasp-stats/INTERNAL-jasp/issues/1215
-bool HelpModel::pageExists(QString pagePath)
+bool HelpModel::pageExists(const QString & pagePath)
{
QString renderFunc, content;
@@ -214,6 +227,26 @@ bool HelpModel::pageExists(QString pagePath)
return loadHelpContent(pagePath, false, renderFunc, content) || loadHelpContent(pagePath, true, renderFunc, content);
}
+void HelpModel::jumpToAnchor(const QString &anchorName)
+{
+ _anchorName = anchorName;
+
+ emit pagePathChanged(pagePath());
+
+ jumpToSelectedAnchor();
+}
+
+void HelpModel::jumpToSelectedAnchor()
+{
+ if(!_anchorName.isEmpty())
+ emit runJavaScriptSignal(QString("document.getElementById('%1').scrollIntoView()").arg(_anchorName));
+}
+
+QString HelpModel::pagePath() const
+{
+ return _anchorName.isEmpty() ? _pagePath : _pagePath + "#" + _anchorName;
+}
+
bool HelpModel::loadHelpContent(const QString & pagePath, bool ignorelanguage, QString &renderFunc, QString &content)
{
@@ -262,12 +295,14 @@ bool HelpModel::loadHelpContent(const QString & pagePath, bool ignorelanguage, Q
return found;
}
-void HelpModel::loadMarkdown(QString md)
+void HelpModel::loadMarkdown(const QString & md)
{
//Log::log() << "loadMarkdown got:\n" << md << std::endl;
setVisible(true);
runJavaScript("window.render", md);
+
+ jumpToSelectedAnchor();
}
void HelpModel::setAnalysis(Analysis *newAnalysis)
diff --git a/Desktop/utilities/helpmodel.h b/Desktop/utilities/helpmodel.h
index 551f6ba340..fefe15279d 100644
--- a/Desktop/utilities/helpmodel.h
+++ b/Desktop/utilities/helpmodel.h
@@ -24,9 +24,11 @@ class HelpModel : public QObject
void runJavaScript(QString renderFunc, QString content);
bool visible() const { return _visible; }
- QString pagePath() const { return _pagePath; }
+ QString pagePath() const;
QString markdown() const { return _markdown; }
Analysis * analysis() const { return _analysis; }
+
+ static HelpModel * singleton() { return _singleton; }
public slots:
void setVisible(bool visible);
@@ -42,9 +44,11 @@ public slots:
void setThemeCss(QString themeName);
void setFont();
void loadingSucceeded();
- void setMarkdown(QString markdown);
- void loadMarkdown(QString md);
- bool pageExists(QString pagePath);
+ void setMarkdown( const QString & markdown);
+ void loadMarkdown( const QString & md);
+ bool pageExists( const QString & pagePath);
+ void jumpToAnchor( const QString & anchorName);
+ void jumpToSelectedAnchor();
signals:
void renderCode(QString javascript);
@@ -61,8 +65,11 @@ public slots:
private:
bool _visible = false;
QString _pagePath = "",
- _markdown = "";
+ _markdown = "",
+ _anchorName = "";
Analysis * _analysis = nullptr;
+
+ static HelpModel * _singleton;
};
#endif // HELPMODEL_H
diff --git a/QMLComponents/analysisform.cpp b/QMLComponents/analysisform.cpp
index a1f71eacf5..cc45e030f5 100644
--- a/QMLComponents/analysisform.cpp
+++ b/QMLComponents/analysisform.cpp
@@ -334,7 +334,9 @@ void AnalysisForm::_setUp()
for (JASPControl* control : controls)
{
_dependsOrderedCtrls.push_back(control);
- connect(control, &JASPControl::helpMDChanged, this, &AnalysisForm::helpMDChanged);
+ connect(control, &JASPControl::helpMDChanged, this, &AnalysisForm::helpMDChanged);
+ connect(control, &JASPControl::helpJumpToAnchor, this, &AnalysisForm::helpJumpToAnchor);
+
}
_rSyntax->setUp();
diff --git a/QMLComponents/analysisform.h b/QMLComponents/analysisform.h
index 091c4770cc..535cf7e885 100644
--- a/QMLComponents/analysisform.h
+++ b/QMLComponents/analysisform.h
@@ -118,6 +118,7 @@ public slots:
void infoChanged();
void infoBottomChanged();
void helpMDChanged();
+ void helpJumpToAnchor(const QString & anchor);
void errorsChanged();
void warningsChanged();
void analysisChanged();
diff --git a/QMLComponents/controls/comboboxbase.cpp b/QMLComponents/controls/comboboxbase.cpp
index 2c85dacc24..d97514d7c9 100644
--- a/QMLComponents/controls/comboboxbase.cpp
+++ b/QMLComponents/controls/comboboxbase.cpp
@@ -310,8 +310,9 @@ QString ComboBoxBase::generateMDHelp(int depth) const
{
QStringList markdown;
- markdown << printLabelMD(depth);
- markdown << info();
+ markdown << markdownAnchor()
+ << printLabelMD(depth)
+ << info();
// If one of the option has an info property, then display the options as an unordered list
if (_hasOptionInfo())
diff --git a/QMLComponents/controls/jaspcontrol.cpp b/QMLComponents/controls/jaspcontrol.cpp
index e0bb5b1918..693b7bac03 100644
--- a/QMLComponents/controls/jaspcontrol.cpp
+++ b/QMLComponents/controls/jaspcontrol.cpp
@@ -60,6 +60,7 @@ JASPControl::JASPControl(QQuickItem *parent) : QQuickItem(parent)
connect(this, &JASPControl::debugChanged, [this] () { _setBackgroundColor(); _setVisible(); } );
connect(this, &JASPControl::parentDebugChanged, [this] () { _setBackgroundColor(); _setVisible(); } );
connect(this, &JASPControl::boundValueChanged, this, &JASPControl::_resetBindingValue);
+ connect(this, &JASPControl::activeFocusChanged, this, &JASPControl::_handleActiveFocusChanged);
connect(this, &JASPControl::activeFocusChanged, this, &JASPControl::_setFocus);
connect(this, &JASPControl::activeFocusChanged, this, &JASPControl::_notifyFormOfActiveFocus);
@@ -496,6 +497,12 @@ void JASPControl::_checkControlName()
{
checkOptionName(_name);
}
+
+void JASPControl::_handleActiveFocusChanged()
+{
+ if(hasActiveFocus() && name() != "")
+ emit helpJumpToAnchor(markdownAnchor(false));
+ }
bool JASPControl::checkOptionName(const QString &name)
{
@@ -631,12 +638,28 @@ JASPControls JASPControl::getMDSubItems(const QQuickItem* parentItem) const
return MDSubItems;
}
+
+QString JASPControl::markdownAnchor(bool includeHtml) const
+{
+ if(_name == "")
+ return "";
+
+ const QString anchorName = "qml_" + name();
+ if(!includeHtml)
+ return anchorName;
+
+ return QString("").arg(anchorName);
+}
QString JASPControl::generateMDHelp(int depth) const
{
- JASPControls MDSubItems = getMDSubItems();
- QStringList markdown;
- markdown << printLabelMD(depth) << info() << "\n";
+ JASPControls MDSubItems = getMDSubItems();
+ QStringList markdown;
+
+ markdown << markdownAnchor()
+ << printLabelMD(depth)
+ << info()
+ << "\n";
if (MDSubItems.size() > 0)
{
@@ -698,6 +721,7 @@ void JASPControl::setName(const QString &name)
{
_name = name;
emit nameChanged();
+ emit helpMDChanged();
}
}
diff --git a/QMLComponents/controls/jaspcontrol.h b/QMLComponents/controls/jaspcontrol.h
index 573da192e9..d5f0581c62 100644
--- a/QMLComponents/controls/jaspcontrol.h
+++ b/QMLComponents/controls/jaspcontrol.h
@@ -119,6 +119,7 @@ class JASPControl : public QQuickItem
virtual bool infoLabelItalic() const { return false; }
QString toolTip() const { return _toolTip; }
+ QString markdownAnchor(bool includeHtml=true) const; ///