NEW: Using axis's tick label formating properties to format values in data-tooltips (e.g. dates will appear formated as such)

This commit is contained in:
jkriege2 2024-02-14 13:59:59 +01:00
parent e152e984f6
commit bcc626172e
4 changed files with 60 additions and 21 deletions

View File

@ -69,6 +69,7 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
<li>IMPROVED: QT6-compatibility by removing deprecated warnings</li>
<li>IMPROVED: added missing override declarations</li>
<li>IMPROVED: JKQTPlotter::jkqtp_RESIZE_DELAY is thread-safe now (atomic)</li>
<li>IMPROVED: Using axis's tick label formating properties to format values in data-tooltips (e.g. dates will appear formated as such)</li>
<li>IMPROVED/REWORKED: reworked JKQTPErrorPlotstyle and error indicator plotting so error-inidcators can be specified as ORed combination of flags from JKQTPErrorPlotstyleElements, added additional error indicator styles (half-bars, arrows...)</li>
<li>IMPROVED/REWORKED: reworked JKQTPCADrawMode and coordinate axis drawing so the draw mide can be specified as ORed combination of flags from JKQTPCADrawModeElements, added flags to draw arrows at the end of the axis line</li>
<li>IMPROVED/REWORKED: coordinate axis code was refactored</li>
@ -155,7 +156,7 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
<li>IMPROVED: rendering of sqrt</li>
<li>IMPROVED: rendering and size calculation of decorations</li>
<li>IMPROVED: tokenizing and parsing of text in text-mode: now a lot of accents with commands like \c \\\"a, \c \\'e and variants (e.g. \c {\\\"a}, \c \\\"{a}, ...) are supported now</li>
<li>IMPROVED: all fucntions in JKQTMathText are re-entrant + diverse speed improvements for parallel use-cases (via caches)</li>
<li>IMPROVED: all functions in JKQTMathText are re-entrant + diverse speed improvements for parallel use-cases (via caches)</li>
<li>IMPROVED/BREAKING: refactored symbol node JKQTMathTextSymbolNode and changed font-lookup!</li>
<li>IMPROVED/NEW/BREAKING: refactored whitespace-processing node JKQTMathTextWhitespaceNode, now all major LaTeX whitespace commands are supported properly</li>
<li>IMPROVED/NEW/BREAKING: refactored LaTeX parser in JKQTMathText</li>

View File

@ -491,6 +491,12 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPCoordinateAxis: public QObject {
/** \brief calls x2p() of the other axis (or returns \c NAN if the other axis does not exist */
virtual double parentOtherAxisX2P(double x) const =0;
/** \brief convert a float to a tick label string */
QString floattolabel(double data) const;
/** \brief convert a float to a tick label string with a given precision */
QString floattolabel(double data, int past_comma) const;
public Q_SLOTS:
/** \brief set range of plot axis */
void setRange(double amin, double amax);
@ -741,11 +747,6 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPCoordinateAxis: public QObject {
const JKQTMathText* getParentMathText() const;
/** \brief convert a float to a tick label string */
QString floattolabel(double data) const;
/** \brief convert a float to a tick label string with a given precision */
QString floattolabel(double data, int past_comma) const;
/** \brief parent plotter class */
JKQTBasePlotter* parent;
/** \brief current view: minimum of axis */

View File

@ -152,7 +152,7 @@ void JKQTPPlotElement::drawOutside(JKQTPEnhancedPainter& /*painter*/, QRect /*le
}
QString JKQTPPlotElement::formatHitTestDefaultLabel(double x, double y, int index, JKQTPDatastore* datastore) const {
QString JKQTPPlotElement::formatHitTestDefaultLabel(double x, double y, int index, const JKQTPDatastore* datastore) const {
const JKQTPXGraphErrorData* errgx=dynamic_cast<const JKQTPXGraphErrorData*>(this);
QString xerrstr;
// retrieve x-error data
@ -160,11 +160,11 @@ QString JKQTPPlotElement::formatHitTestDefaultLabel(double x, double y, int inde
if (errgx->getXErrorColumn()>=0) {
if (errgx->getXErrorColumnLower()>=0) {
xerrstr=QString("\\:+%1\\:-%2")
.arg(jkqtp_floattolatexqstr(datastore->get(errgx->getXErrorColumn(),static_cast<size_t>(index)), 3))
.arg(jkqtp_floattolatexqstr(datastore->get(errgx->getXErrorColumnLower(),static_cast<size_t>(index)), 3));
.arg(xFloatToString(datastore->get(errgx->getXErrorColumn(),static_cast<size_t>(index))))
.arg(xFloatToString(datastore->get(errgx->getXErrorColumnLower(),static_cast<size_t>(index))));
} else {
xerrstr=QString("{\\:}{\\pm}%1")
.arg(jkqtp_floattolatexqstr(datastore->get(errgx->getXErrorColumn(),static_cast<size_t>(index)), 3));
.arg(xFloatToString(datastore->get(errgx->getXErrorColumn(),static_cast<size_t>(index))));
}
}
}
@ -176,18 +176,30 @@ QString JKQTPPlotElement::formatHitTestDefaultLabel(double x, double y, int inde
if (errgy->getYErrorColumn()>=0) {
if (errgy->getYErrorColumnLower()>=0) {
yerrstr=QString("\\:+%1\\:-%2")
.arg(jkqtp_floattolatexqstr(datastore->get(errgy->getYErrorColumn(),static_cast<size_t>(index)), 3))
.arg(jkqtp_floattolatexqstr(datastore->get(errgy->getYErrorColumnLower(),static_cast<size_t>(index)), 3));
.arg(yFloatToString(datastore->get(errgy->getYErrorColumn(),static_cast<size_t>(index))))
.arg(yFloatToString(datastore->get(errgy->getYErrorColumnLower(),static_cast<size_t>(index))));
} else {
yerrstr=QString("{\\:}{\\pm}%1")
.arg(jkqtp_floattolatexqstr(datastore->get(errgy->getYErrorColumn(),static_cast<size_t>(index)), 3));
.arg(yFloatToString(datastore->get(errgy->getYErrorColumn(),static_cast<size_t>(index))));
}
}
}
return QString("\\ensuremath{\\left[{\\:}%1%3{\\;},{\\;}%2%4{\\:}\\right]}").arg(jkqtp_floattolatexqstr(x, 3)).arg(jkqtp_floattolatexqstr(y, 3)).arg(xerrstr).arg(yerrstr);
return QString("\\ensuremath{\\left[{\\:}%1%3{\\;},{\\;}%2%4{\\:}\\right]}").arg(xFloatToString(x)).arg(yFloatToString(y)).arg(xerrstr).arg(yerrstr);
}
QString JKQTPPlotElement::xFloatToString(double v, int past_comma) const
{
if (past_comma<0) return getXAxis()->floattolabel(v);
else return getXAxis()->floattolabel(v, past_comma);
}
QString JKQTPPlotElement::yFloatToString(double v, int past_comma) const
{
if (past_comma<0) return getYAxis()->floattolabel(v);
else return getYAxis()->floattolabel(v, past_comma);
}
double JKQTPPlotElement::hitTest(const QPointF & posSystem, QPointF* closestSpotSystem, QString* label, HitTestMode mode) const
{
if (parent==nullptr) return JKQTP_NAN;
@ -522,7 +534,7 @@ double JKQTPXYGraph::hitTest(const QPointF &posSystem, QPointF *closestSpotSyste
}
}
if (closest>=0) {
if (label) *label=formatHitTestDefaultLabel(closestPos.x(), closestPos.y(), closest);
if (label) *label=formatHitTestDefaultLabel(closestPos.x(), closestPos.y(), closest, datastore);
if (closestSpotSystem) *closestSpotSystem=closestPos;
return closedist;
} else {
@ -831,7 +843,7 @@ double JKQTPXYYGraph::hitTest(const QPointF &posSystem, QPointF *closestSpotSyst
}
}
if (closest>=0) {
if (label) *label=formatHitTestDefaultLabel(closestPos.x(), closestPos.y(), closest);
if (label) *label=formatHitTestDefaultLabel(closestPos.x(), closestPos.y(), closest, datastore);
if (closestSpotSystem) *closestSpotSystem=closestPos;
return closedist;
} else {
@ -994,7 +1006,7 @@ double JKQTPXXYGraph::hitTest(const QPointF &posSystem, QPointF *closestSpotSyst
}
}
if (closest>=0) {
if (label) *label=formatHitTestDefaultLabel(closestPos.x(), closestPos.y(), closest);
if (label) *label=formatHitTestDefaultLabel(closestPos.x(), closestPos.y(), closest, datastore);
if (closestSpotSystem) *closestSpotSystem=closestPos;
return closedist;
} else {
@ -1223,6 +1235,26 @@ double JKQTPXYAndVectorGraph::hitTest(const QPointF &posSystem, QPointF *closest
return JKQTPXYGraph::hitTest(posSystem, closestSpotSystem, label, mode);
}
QString JKQTPXYAndVectorGraph::formatHitTestDefaultLabel(double x, double y, int i, const JKQTPDatastore *datastore) const
{
QString vec="\\mbox{no vector data}";
if (datastore) {
switch(vectorDataLayout) {
case DeltaXDeltaYLayout: {
const double dx=datastore->get(static_cast<size_t>(dxColumn),static_cast<size_t>(i));
const double dy=datastore->get(static_cast<size_t>(dyColumn),static_cast<size_t>(i));
vec="\\vec{\\mbox{\\delta}}=("+jkqtp_floattolatexqstr(dx, 3)+"{\\;},{\\;}"+jkqtp_floattolatexqstr(dy, 3)+")";
} break;
case AngleAndLengthLayout: {
const double a=datastore->get(static_cast<size_t>(angleColumn),static_cast<size_t>(i));
const double l=(lengthColumn<0) ? 1.0 : datastore->get(static_cast<size_t>(lengthColumn),static_cast<size_t>(i));
vec= "\\angle="+jkqtp_floattolatexqstr(a/M_PI*180.0, 1)+"\\degree{\\;},{\\;}l="+jkqtp_floattolatexqstr(l, 3);
} break;
}
}
return QString("\\ensuremath{\\left|\\stackrel{x=({\\:}%1{\\;},{\\;}%2{\\:}),}{ %3 }\\right.").arg(jkqtp_floattolatexqstr(x, 3)).arg(jkqtp_floattolatexqstr(y, 3)).arg(vec);
}
void JKQTPXYAndVectorGraph::setDxColumn(int col)
{
dxColumn=col;

View File

@ -337,7 +337,7 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPPlotElement: public QObject {
*
* \see hitTest(), clearHitTestData(), m_hitTestData, HitTestLocation, reserveHitTestData()
*/
inline void addHitTestData(double x_, double y_, int index_=-1, JKQTPDatastore* datastore=nullptr) { addHitTestData(HitTestLocation(x_,y_,formatHitTestDefaultLabel(x_,y_, index_, datastore))); }
inline void addHitTestData(double x_, double y_, int index_=-1, const JKQTPDatastore* datastore=nullptr) { addHitTestData(HitTestLocation(x_,y_,formatHitTestDefaultLabel(x_,y_, index_, datastore))); }
/** \brief clear the internal datastore for hitTest(),
* this variant uses formatHitTestDefaultLabel() to auto-generate the label
*
@ -347,7 +347,7 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPPlotElement: public QObject {
*
* \see hitTest(), clearHitTestData(), m_hitTestData, HitTestLocation, reserveHitTestData()
*/
inline void addHitTestData(const QPointF& pos_, int index_=-1, JKQTPDatastore* datastore=nullptr) { addHitTestData(HitTestLocation(pos_,formatHitTestDefaultLabel(pos_.x(), pos_.y(), index_, datastore))); }
inline void addHitTestData(const QPointF& pos_, int index_=-1, const JKQTPDatastore* datastore=nullptr) { addHitTestData(HitTestLocation(pos_,formatHitTestDefaultLabel(pos_.x(), pos_.y(), index_, datastore))); }
/** \brief clear the internal datastore for hitTest()
*
* \param x_ x-position of the graph point in system coordinates
@ -377,8 +377,11 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPPlotElement: public QObject {
* \param datastore The datastore to read error data from (optional!)
* \returns a LaTeX formatted label
*/
virtual QString formatHitTestDefaultLabel(double x, double y, int index=-1, JKQTPDatastore *datastore=nullptr) const;
virtual QString formatHitTestDefaultLabel(double x, double y, int index=-1, const JKQTPDatastore *datastore=nullptr) const;
/** \brief converts a x-value \a v into a string, taking into account the type of x-axis */
QString xFloatToString(double v, int past_comma=-1) const;
/** \brief converts a x-value \a v into a string, taking into account the type of x-axis */
QString yFloatToString(double v, int past_comma=-1) const;
/** \brief the plotter object this object belongs to */
JKQTBasePlotter* parent;
@ -999,6 +1002,8 @@ public:
/** \copydoc JKQTPXYGraph::hitTest() */
virtual double hitTest(const QPointF &posSystem, QPointF* closestSpotSystem=nullptr, QString* label=nullptr, HitTestMode mode=HitTestXY) const override;
/** \copydoc JKQTPXYGraph::formatHitTestDefaultLabel() */
virtual QString formatHitTestDefaultLabel(double x, double y, int index=-1, const JKQTPDatastore *datastore=nullptr) const override;
Q_PROPERTY(VectorDataLayout vectorDataLayout READ getVectorDataLayout)
Q_PROPERTY(int dxColumn READ getDxColumn WRITE setDxColumn)