File indexing completed on 2024-12-22 04:17:41
0001 /*************************************************************************** 0002 * * 0003 * copyright : (C) 2007 The University of Toronto * 0004 * netterfield@astro.utoronto.ca * 0005 * * 0006 * This program is free software; you can redistribute it and/or modify * 0007 * it under the terms of the GNU General Public License as published by * 0008 * the Free Software Foundation; either version 2 of the License, or * 0009 * (at your option) any later version. * 0010 * * 0011 ***************************************************************************/ 0012 0013 #include "plotitem.h" 0014 #include "colorsequence.h" 0015 0016 #include "plotitemmanager.h" 0017 #include "plotrenderitem.h" 0018 0019 #include "image.h" 0020 0021 #include "layoutboxitem.h" 0022 #include "viewgridlayout.h" 0023 #include "debug.h" 0024 0025 #include "application.h" 0026 #include "mainwindow.h" 0027 #include "document.h" 0028 #include "tabwidget.h" 0029 #include "labelrenderer.h" 0030 0031 #include "datacollection.h" 0032 #include "cartesianrenderitem.h" 0033 0034 #include "plotitemdialog.h" 0035 #include "dialoglauncher.h" 0036 #include "sharedaxisboxitem.h" 0037 0038 #include "applicationsettings.h" 0039 #include "updatemanager.h" 0040 #include "plotscriptinterface.h" 0041 #include "math_kst.h" 0042 0043 #include "dialogdefaults.h" 0044 0045 #include <QMenu> 0046 #include <QDebug> 0047 #include <QGraphicsSceneMouseEvent> 0048 #include <QClipboard> 0049 0050 // Benchmark drawing 0051 // undefined = None, 1 = PlotItem, 2 = More Details 0052 //#define BENCHMARK 1 0053 0054 static const int PLOT_MAXIMIZED_ZORDER = 1000; 0055 0056 namespace Kst { 0057 0058 PlotItem::PlotItem(View *parent) 0059 : ViewItem(parent), PlotItemInterface(), 0060 _isInSharedAxisBox(false), 0061 _manuallyHideLeftAxisLabel(false), 0062 _manuallyHideRightAxisLabel(false), 0063 _manuallyHideTopAxisLabel(false), 0064 _manuallyHideBottomAxisLabel(false), 0065 _plotRectsDirty(true), 0066 _calculatedLeftLabelMargin(0.0), 0067 _calculatedLeftLabelWidth(0.0), 0068 _calculatedLeftBaseOffset(0.0), 0069 _calculatedRightLabelMargin(0.0), 0070 _calculatedTopLabelMargin(0.0), 0071 _calculatedTopLabelHeight(0.0), 0072 _calculatedBottomLabelMargin(0.0), 0073 _calculatedBottomLabelWidth(0.0), 0074 _calculatedLabelMarginWidth(0.0), 0075 _calculatedLabelMarginHeight(0.0), 0076 _calculatedAxisMarginWidth(0.0), 0077 _calculatedAxisMarginHeight(0.0), 0078 _calculatedAxisMarginVLead(0.0), 0079 _calculatedAxisMarginHLead(0.0), 0080 _calculatedAxisMarginROverflow(0.0), 0081 _calculatedAxisMarginTOverflow(0.0), 0082 _leftPadding(0.0), 0083 _bottomPadding(0.0), 0084 _rightPadding(0.0), 0085 _topPadding(0.0), 0086 _globalFontScale(14.0), 0087 _numberAxisLabelScaleFactor(1.0), 0088 _useNumberAxisLabelScale(true), 0089 _showLegend(false), 0090 _allowUpdates(true), 0091 _legend(0), 0092 _zoomMenu(0), 0093 _filterMenu(0), 0094 _fitMenu(0), 0095 _psdMenu(0), 0096 _histogramMenu(0), 0097 _editMenu(0), 0098 _sharedAxisBoxMenu(0), 0099 _copyMenu(0), 0100 _sharedBox(0), 0101 _axisLabelsDirty(true), 0102 0103 _plotPixmapDirty(true), 0104 _i_per(0) 0105 { 0106 setTypeName(tr("Plot", "a plot of data")); 0107 _initializeShortName(); 0108 0109 setBrush(Qt::white); 0110 0111 setSupportsTiedZoom(true); 0112 0113 _xAxis = new PlotAxis(this, Qt::Horizontal); 0114 _yAxis = new PlotAxis(this, Qt::Vertical); 0115 0116 connect(this, SIGNAL(geometryChanged()), _xAxis, SLOT(setTicksUpdated())); 0117 connect(this, SIGNAL(geometryChanged()), _yAxis, SLOT(setTicksUpdated())); 0118 connect(this, SIGNAL(geometryChanged()), this, SLOT(setPlotRectsDirty())); 0119 0120 _leftLabelDetails = new PlotLabel(this); 0121 _rightLabelDetails = new PlotLabel(this); 0122 _topLabelDetails = new PlotLabel(this); 0123 _bottomLabelDetails = new PlotLabel(this); 0124 _numberLabelDetails = new PlotLabel(this); 0125 0126 //view()->configurePlotFontDefaults(this); 0127 0128 connect(_leftLabelDetails, SIGNAL(labelChanged()), this, SLOT(setPlotBordersDirty())); 0129 connect(_leftLabelDetails, SIGNAL(labelChanged()), this, SLOT(setLeftLabelDirty())); 0130 connect(_rightLabelDetails, SIGNAL(labelChanged()), this, SLOT(setPlotBordersDirty())); 0131 connect(_rightLabelDetails, SIGNAL(labelChanged()), this, SLOT(setRightLabelDirty())); 0132 connect(_topLabelDetails, SIGNAL(labelChanged()), this, SLOT(setPlotBordersDirty())); 0133 connect(_topLabelDetails, SIGNAL(labelChanged()), this, SLOT(setTopLabelDirty())); 0134 connect(_bottomLabelDetails, SIGNAL(labelChanged()), this, SLOT(setPlotBordersDirty())); 0135 connect(_bottomLabelDetails, SIGNAL(labelChanged()), this, SLOT(setBottomLabelDirty())); 0136 connect(_numberLabelDetails, SIGNAL(labelChanged()), this, SLOT(setPlotBordersDirty())); 0137 connect(_numberLabelDetails, SIGNAL(labelChanged()), this, SLOT(setAxisLabelsDirty())); 0138 0139 _undoStack = new QUndoStack(this); 0140 0141 createActions(); 0142 0143 // Set the initial projection. 0144 setProjectionRect(QRectF(QPointF(-0.1, -0.1), QPointF(0.1, 0.1))); 0145 renderItem(PlotRenderItem::Cartesian); 0146 0147 setPlotBordersDirty(true); 0148 connect(this, SIGNAL(triggerRedraw()), this, SLOT(redrawPlot())); 0149 connect(this, SIGNAL(geometryChanged()), this, SLOT(setLabelsDirty())); 0150 connect(this, SIGNAL(updateAxes()), this, SLOT(setPlotPixmapDirty())); 0151 connect(this, SIGNAL(geometryChanged()), this, SLOT(setPlotPixmapDirty())); 0152 0153 applyDefaults(); 0154 applyDialogDefaultsStroke(); 0155 applyDialogDefaultsFill(); 0156 applyDialogDefaultsLockPosToData(); 0157 } 0158 0159 ScriptInterface* PlotItem::createScriptInterface() { 0160 return new PlotSI(this); 0161 } 0162 0163 0164 QColor PlotItem::nextColor() { 0165 ColorSequence::self().setIndex(curveList().count()); 0166 return ColorSequence::self().current(); 0167 } 0168 0169 0170 void PlotItem::applyDefaults() { 0171 QFont font; 0172 0173 // Global Font Settings 0174 QFont globalfont; 0175 globalfont.fromString(dialogDefaults().value(defaultsGroupName()+"/globalFontFamily",globalfont.toString()).toString()); 0176 setGlobalFont(globalfont); 0177 setGlobalFontScale(dialogDefaults().value(defaultsGroupName()+"/globalFontScale", 13).toDouble()); 0178 QColor color; 0179 color = dialogDefaults().value(defaultsGroupName()+"/globalFontColor", QColor(Qt::black)).value<QColor>(); 0180 setGlobalFontColor(color); 0181 0182 // Left Font Settings 0183 leftLabelDetails()->setFontUseGlobal(dialogDefaults().value(defaultsGroupName()+"/leftFontGlobal", true).toBool()); 0184 font.fromString(dialogDefaults().value(defaultsGroupName()+"/leftFontFamily",globalfont.toString()).toString()); 0185 leftLabelDetails()->setFont(font); 0186 leftLabelDetails()->setFontScale(dialogDefaults().value(defaultsGroupName()+"/leftFontScale", 13).toDouble()); 0187 color = dialogDefaults().value(defaultsGroupName()+"/leftFontColor", QColor(Qt::black)).value<QColor>(); 0188 leftLabelDetails()->setFontColor(color); 0189 0190 // right Font Settings 0191 rightLabelDetails()->setFontUseGlobal(dialogDefaults().value(defaultsGroupName()+"/rightFontGlobal", true).toBool()); 0192 font.fromString(dialogDefaults().value(defaultsGroupName()+"/rightFontFamily",globalfont.toString()).toString()); 0193 rightLabelDetails()->setFont(font); 0194 rightLabelDetails()->setFontScale(dialogDefaults().value(defaultsGroupName()+"/rightFontScale", 13).toDouble()); 0195 color = dialogDefaults().value(defaultsGroupName()+"/rightFontColor", QColor(Qt::black)).value<QColor>(); 0196 rightLabelDetails()->setFontColor(color); 0197 0198 // top Font Settings 0199 topLabelDetails()->setFontUseGlobal(dialogDefaults().value(defaultsGroupName()+"/topFontGlobal", true).toBool()); 0200 font.fromString(dialogDefaults().value(defaultsGroupName()+"/topFontFamily",globalfont.toString()).toString()); 0201 topLabelDetails()->setFont(font); 0202 topLabelDetails()->setFontScale(dialogDefaults().value(defaultsGroupName()+"/topFontScale", 13).toDouble()); 0203 color = dialogDefaults().value(defaultsGroupName()+"/topFontColor", QColor(Qt::black)).value<QColor>(); 0204 topLabelDetails()->setFontColor(color); 0205 0206 // bottom Font Settings 0207 bottomLabelDetails()->setFontUseGlobal(dialogDefaults().value(defaultsGroupName()+"/bottomFontGlobal", true).toBool()); 0208 font.fromString(dialogDefaults().value(defaultsGroupName()+"/bottomFontFamily",globalfont.toString()).toString()); 0209 bottomLabelDetails()->setFont(font); 0210 bottomLabelDetails()->setFontScale(dialogDefaults().value(defaultsGroupName()+"/bottomFontScale", 13).toDouble()); 0211 color = dialogDefaults().value(defaultsGroupName()+"/bottomFontColor", QColor(Qt::black)).value<QColor>(); 0212 bottomLabelDetails()->setFontColor(color); 0213 0214 // number Font Settings 0215 numberLabelDetails()->setFontUseGlobal(dialogDefaults().value(defaultsGroupName()+"/numberFontGlobal", true).toBool()); 0216 font.fromString(dialogDefaults().value(defaultsGroupName()+"/numberFontFamily",globalfont.toString()).toString()); 0217 numberLabelDetails()->setFont(font); 0218 numberLabelDetails()->setFontScale(dialogDefaults().value(defaultsGroupName()+"/numberFontScale", 13).toDouble()); 0219 color = dialogDefaults().value(defaultsGroupName()+"/numberFontColor", QColor(Qt::black)).value<QColor>(); 0220 numberLabelDetails()->setFontColor(color); 0221 0222 xAxis()->setAxisVisible(dialogDefaults().value(defaultsGroupName()+"/xAxisVisible", true).toBool()); 0223 xAxis()->setAxisLog(dialogDefaults().value(defaultsGroupName()+"/xAxisLog", false).toBool()); 0224 xAxis()->setAxisReversed(dialogDefaults().value(defaultsGroupName()+"/xAxisReversed", false).toBool()); 0225 xAxis()->setAxisAutoBaseOffset(dialogDefaults().value(defaultsGroupName()+"/xAxisAutoBaseOffset", true).toBool()); 0226 xAxis()->setAxisBaseOffset(dialogDefaults().value(defaultsGroupName()+"/xAxisBaseOffset", false).toBool()); 0227 xAxis()->setAxisForceOffsetMin(dialogDefaults().value(defaultsGroupName()+"/xAxisForceOffsetMin", false).toBool()); 0228 xAxis()->setAxisInterpret(dialogDefaults().value(defaultsGroupName()+"/xAxisInterpret", false).toBool()); 0229 xAxis()->setAxisInterpretation((AxisInterpretationType)dialogDefaults().value(defaultsGroupName()+"/xAxisInterpretation", 1).toInt()); 0230 xAxis()->setAxisDisplay((AxisDisplayType)dialogDefaults().value(defaultsGroupName()+"/xAxisDisplay", 4).toInt()); 0231 xAxis()->setTimezoneName(dialogDefaults().value(defaultsGroupName()+"/xAxisTimezone", "GMT").toString()); 0232 xAxis()->setAxisMajorTickMode((MajorTickMode)dialogDefaults().value(defaultsGroupName()+"/xAxisMajorTickMode", 5).toInt()); 0233 xAxis()->setAxisMinorTickCount(dialogDefaults().value(defaultsGroupName()+"/xAxisMinorTickCount", 5).toInt()); 0234 xAxis()->setAxisAutoMinorTicks(dialogDefaults().value(defaultsGroupName()+"/xAxisautoMinorTickCount", true).toBool()); 0235 xAxis()->setDrawAxisMajorTicks(dialogDefaults().value(defaultsGroupName()+"/xAxisDrawMajorTicks", true).toBool()); 0236 xAxis()->setDrawAxisMinorTicks(dialogDefaults().value(defaultsGroupName()+"/xAxisDrawMinorTicks", true).toBool()); 0237 xAxis()->setDrawAxisMajorGridLines(dialogDefaults().value(defaultsGroupName()+"/xAxisDrawMajorGridLines", true).toBool()); 0238 xAxis()->setDrawAxisMinorGridLines(dialogDefaults().value(defaultsGroupName()+"/xAxisDrawMinorGridLines", false).toBool()); 0239 0240 xAxis()->setAxisMajorGridLineStyle((Qt::PenStyle)dialogDefaults().value(defaultsGroupName()+"/xAxisDrawMajorGridLineStyle", 2).toInt()); 0241 xAxis()->setAxisMajorGridLineWidth(dialogDefaults().value(defaultsGroupName()+"/xAxisDrawMajorGridLineWidth",1).toDouble()); 0242 color = dialogDefaults().value(defaultsGroupName()+"/xAxisDrawMajorGridLineColor", "#a0a0a4").value<QColor>(); 0243 xAxis()->setAxisMajorGridLineColor(color); 0244 0245 xAxis()->setAxisMinorGridLineStyle((Qt::PenStyle)dialogDefaults().value(defaultsGroupName()+"/xAxisDrawMinorGridLineStyle", 2).toInt()); 0246 xAxis()->setAxisMinorGridLineWidth(dialogDefaults().value(defaultsGroupName()+"/xAxisDrawMinorGridLineWidth",1).toDouble()); 0247 color = dialogDefaults().value(defaultsGroupName()+"/xAxisDrawMinorGridLineColor", "#a0a0a4").value<QColor>(); 0248 xAxis()->setAxisMinorGridLineColor(color); 0249 0250 xAxis()->setAxisSignificantDigits(dialogDefaults().value(defaultsGroupName()+"/xAxisSignificantDigits",9).toInt()); 0251 xAxis()->setAxisLabelRotation(dialogDefaults().value(defaultsGroupName()+"/xAxisRotation",0).toDouble()); 0252 0253 0254 yAxis()->setAxisVisible(dialogDefaults().value(defaultsGroupName()+"/yAxisVisible", true).toBool()); 0255 yAxis()->setAxisLog(dialogDefaults().value(defaultsGroupName()+"/yAxisLog", false).toBool()); 0256 yAxis()->setAxisReversed(dialogDefaults().value(defaultsGroupName()+"/yAxisReversed", false).toBool()); 0257 yAxis()->setAxisAutoBaseOffset(dialogDefaults().value(defaultsGroupName()+"/yAxisAutoBaseOffset", true).toBool()); 0258 yAxis()->setAxisBaseOffset(dialogDefaults().value(defaultsGroupName()+"/yAxisBaseOffset", false).toBool()); 0259 yAxis()->setAxisForceOffsetMin(dialogDefaults().value(defaultsGroupName()+"/yAxisForceOffsetMin", false).toBool()); 0260 yAxis()->setAxisInterpret(dialogDefaults().value(defaultsGroupName()+"/yAxisInterpret", false).toBool()); 0261 yAxis()->setAxisInterpretation((AxisInterpretationType)dialogDefaults().value(defaultsGroupName()+"/yAxisInterpretation", 1).toInt()); 0262 yAxis()->setAxisDisplay((AxisDisplayType)dialogDefaults().value(defaultsGroupName()+"/yAxisDisplay", 4).toInt()); 0263 yAxis()->setTimezoneName(dialogDefaults().value(defaultsGroupName()+"/yAxisTimezone", "GMT").toString()); 0264 yAxis()->setAxisMajorTickMode((MajorTickMode)dialogDefaults().value(defaultsGroupName()+"/yAxisMajorTickMode", 5).toInt()); 0265 yAxis()->setAxisMinorTickCount(dialogDefaults().value(defaultsGroupName()+"/yAxisMinorTickCount", 5).toInt()); 0266 yAxis()->setAxisAutoMinorTicks(dialogDefaults().value(defaultsGroupName()+"/yAxisautoMinorTickCount", true).toBool()); 0267 yAxis()->setDrawAxisMajorTicks(dialogDefaults().value(defaultsGroupName()+"/yAxisDrawMajorTicks", true).toBool()); 0268 yAxis()->setDrawAxisMinorTicks(dialogDefaults().value(defaultsGroupName()+"/yAxisDrawMinorTicks", true).toBool()); 0269 yAxis()->setDrawAxisMajorGridLines(dialogDefaults().value(defaultsGroupName()+"/yAxisDrawMajorGridLines", true).toBool()); 0270 yAxis()->setDrawAxisMinorGridLines(dialogDefaults().value(defaultsGroupName()+"/yAxisDrawMinorGridLines", false).toBool()); 0271 0272 yAxis()->setAxisMajorGridLineStyle((Qt::PenStyle)dialogDefaults().value(defaultsGroupName()+"/yAxisDrawMajorGridLineStyle", 2).toInt()); 0273 yAxis()->setAxisMajorGridLineWidth(dialogDefaults().value(defaultsGroupName()+"/yAxisDrawMajorGridLineWidth",1).toDouble()); 0274 color = dialogDefaults().value(defaultsGroupName()+"/yAxisDrawMajorGridLineColor", "#a0a0a4").value<QColor>(); 0275 yAxis()->setAxisMajorGridLineColor(color); 0276 0277 yAxis()->setAxisMinorGridLineStyle((Qt::PenStyle)dialogDefaults().value(defaultsGroupName()+"/yAxisDrawMinorGridLineStyle", 2).toInt()); 0278 yAxis()->setAxisMinorGridLineWidth(dialogDefaults().value(defaultsGroupName()+"/yAxisDrawMinorGridLineWidth",1).toDouble()); 0279 color = dialogDefaults().value(defaultsGroupName()+"/yAxisDrawMinorGridLineColor", "#a0a0a4").value<QColor>(); 0280 yAxis()->setAxisMinorGridLineColor(color); 0281 0282 yAxis()->setAxisSignificantDigits(dialogDefaults().value(defaultsGroupName()+"/yAxisSignificantDigits",9).toInt()); 0283 yAxis()->setAxisLabelRotation(dialogDefaults().value(defaultsGroupName()+"/yAxisRotation",0).toDouble()); 0284 0285 } 0286 0287 0288 PlotItem::~PlotItem() { 0289 delete _xAxis; 0290 delete _yAxis; 0291 delete _leftLabelDetails; 0292 delete _rightLabelDetails; 0293 delete _topLabelDetails; 0294 delete _bottomLabelDetails; 0295 delete _numberLabelDetails; 0296 delete _zoomMenu; 0297 delete _filterMenu; 0298 delete _fitMenu; 0299 delete _editMenu; 0300 0301 if (_sharedAxisBoxMenu) { 0302 delete _sharedAxisBoxMenu; 0303 } 0304 if (_copyMenu) { 0305 delete _copyMenu; 0306 } 0307 0308 } 0309 0310 void PlotItem::_initializeShortName() { 0311 _shortName = 'P'+QString::number(_plotnum); 0312 if (_plotnum>max_plotnum) { 0313 max_plotnum = _plotnum; 0314 } 0315 _plotnum++; 0316 } 0317 0318 QString PlotItem::plotName() const { 0319 return Name(); 0320 } 0321 0322 QString PlotItem::plotCleanedName() const { 0323 return CleanedName(); 0324 } 0325 0326 void PlotItem::save(QXmlStreamWriter &xml) { 0327 if (isVisible()) { 0328 bool plot_maximized = _plotMaximized; 0329 // We don't save 'plot maximized' mode - so un-do it before saving 0330 if (plot_maximized) { 0331 plotMaximize(); 0332 } 0333 xml.writeStartElement("plot"); 0334 xml.writeAttribute("tiedxzoom", QVariant(isXTiedZoom()).toString()); 0335 xml.writeAttribute("tiedyzoom", QVariant(isYTiedZoom()).toString()); 0336 xml.writeAttribute("leftlabelvisible", QVariant(_leftLabelDetails->isVisible()).toString()); 0337 xml.writeAttribute("bottomlabelvisible", QVariant(_bottomLabelDetails->isVisible()).toString()); 0338 xml.writeAttribute("rightlabelvisible", QVariant(_rightLabelDetails->isVisible()).toString()); 0339 xml.writeAttribute("toplabelvisible", QVariant(_topLabelDetails->isVisible()).toString()); 0340 xml.writeAttribute("globalfont", QVariant(_globalFont).toString()); 0341 xml.writeAttribute("globalfontscale", QVariant(_globalFontScale).toString()); 0342 xml.writeAttribute("globalfontcolor", QVariant(_globalFontColor).toString()); 0343 xml.writeAttribute("showlegend", QVariant(_showLegend).toString()); 0344 xml.writeAttribute("hidebottomaxislabel", QVariant(_manuallyHideBottomAxisLabel).toString()); 0345 xml.writeAttribute("hidetopaxislabel", QVariant(_manuallyHideTopAxisLabel).toString()); 0346 xml.writeAttribute("hideleftaxislabel", QVariant(_manuallyHideLeftAxisLabel).toString()); 0347 xml.writeAttribute("hiderightaxislabel", QVariant(_manuallyHideRightAxisLabel).toString()); 0348 xml.writeAttribute("numberaxislabelscale", QVariant(_useNumberAxisLabelScale).toString()); 0349 saveNameInfo(xml, PLOTNUM); 0350 0351 ViewItem::save(xml); 0352 legend()->saveInPlot(xml); 0353 0354 foreach (PlotRenderItem *renderer, renderItems()) { 0355 renderer->saveInPlot(xml); 0356 } 0357 _xAxis->saveInPlot(xml, QString("xaxis")); 0358 _yAxis->saveInPlot(xml, QString("yaxis")); 0359 _leftLabelDetails->saveInPlot(xml, QString("leftlabel")); 0360 _rightLabelDetails->saveInPlot(xml, QString("rightlabel")); 0361 _topLabelDetails->saveInPlot(xml, QString("toplabel")); 0362 _bottomLabelDetails->saveInPlot(xml, QString("bottomlabel")); 0363 _numberLabelDetails->saveInPlot(xml, QString("numberlabel")); 0364 0365 xml.writeStartElement("projectionrect"); 0366 xml.writeAttribute("x", QVariant(projectionRect().x()).toString()); 0367 xml.writeAttribute("y", QVariant(projectionRect().y()).toString()); 0368 xml.writeAttribute("width", QVariant(projectionRect().width()).toString()); 0369 xml.writeAttribute("height", QVariant(projectionRect().height()).toString()); 0370 xml.writeEndElement(); 0371 xml.writeEndElement(); 0372 if (plot_maximized) { 0373 plotMaximize(); // re-maximize it if we just un-maximized it. 0374 } 0375 } 0376 } 0377 0378 0379 void PlotItem::edit(PlotClickEditRegion region) { 0380 PlotItemDialog *editDialog = new PlotItemDialog(this, kstApp->mainWindow()); 0381 if (region == LABEL) { 0382 editDialog->selectLabelsPage(); 0383 } else if (region == XAXIS) { 0384 editDialog->selectXAxisPage(); 0385 } else if (region == YAXIS) { 0386 editDialog->selectYAxisPage(); 0387 } 0388 editDialog->show(); 0389 } 0390 0391 0392 void PlotItem::createActions() { 0393 0394 _createCurve = new QAction(tr("Create Curve"), this); 0395 connect(_createCurve, SIGNAL(triggered()), this, SLOT(showCurveDialog())); 0396 0397 _zoomMaximum = new QAction(tr("Zoom Maximum"), this); 0398 _zoomMaximum->setShortcut(Qt::Key_M); 0399 registerShortcut(_zoomMaximum); 0400 connect(_zoomMaximum, SIGNAL(triggered()), this, SLOT(zoomMaximum())); 0401 0402 _zoomMaxSpikeInsensitive = new QAction(tr("Zoom Max Spike Insensitive"), this); 0403 _zoomMaxSpikeInsensitive->setShortcut(Qt::Key_S); 0404 registerShortcut(_zoomMaxSpikeInsensitive); 0405 connect(_zoomMaxSpikeInsensitive, SIGNAL(triggered()), this, SLOT(zoomMaxSpikeInsensitive())); 0406 0407 _zoomPrevious = _undoStack->createUndoAction(this, tr("Zoom Previous")); 0408 _zoomPrevious->setShortcut(Qt::Key_R); 0409 registerShortcut(_zoomPrevious); 0410 0411 _zoomTied = new QAction(tr("Zoom Tied"), this); 0412 _zoomTied->setShortcut(Qt::Key_T); 0413 _zoomTied->setCheckable(true); 0414 registerShortcut(_zoomTied); 0415 connect(_zoomTied, SIGNAL(triggered()), this, SLOT(zoomTied())); 0416 0417 _zoomOut = new QAction(tr("Zoom Out"), this); 0418 _zoomOut->setShortcut(Qt::Key_Minus); 0419 registerShortcut(_zoomOut); 0420 connect(_zoomOut, SIGNAL(triggered()), this, SLOT(zoomOut())); 0421 0422 _zoomIn = new QAction(tr("Zoom In"), this); 0423 _zoomIn->setShortcut(Qt::Key_Plus); 0424 registerShortcut(_zoomIn); 0425 connect(_zoomIn, SIGNAL(triggered()), this, SLOT(zoomIn())); 0426 0427 _zoomXTied = new QAction(tr("Zoom X Tied"), this); 0428 _zoomXTied->setShortcut(Qt::CTRL+Qt::Key_T); 0429 _zoomXTied->setCheckable(true); 0430 registerShortcut(_zoomXTied); 0431 connect(_zoomXTied, SIGNAL(triggered()), this, SLOT(zoomXTied())); 0432 0433 _zoomYTied = new QAction(tr("Zoom Y Tied"), this); 0434 _zoomYTied->setShortcut(Qt::SHIFT+Qt::Key_T); 0435 _zoomYTied->setCheckable(true); 0436 registerShortcut(_zoomYTied); 0437 connect(_zoomYTied, SIGNAL(triggered()), this, SLOT(zoomYTied())); 0438 0439 _zoomMeanCentered = new QAction(tr("Zoom Mean-centered Y"), this); 0440 _zoomMeanCentered->setShortcut(Qt::Key_A); 0441 registerShortcut(_zoomMeanCentered); 0442 connect(_zoomMeanCentered, SIGNAL(triggered()), this, SLOT(zoomMeanCentered())); 0443 0444 _zoomXMaximum = new QAction(tr("X-Zoom Maximum"), this); 0445 _zoomXMaximum->setShortcut(Qt::CTRL+Qt::Key_M); 0446 registerShortcut(_zoomXMaximum); 0447 connect(_zoomXMaximum, SIGNAL(triggered()), this, SLOT(zoomXMaximum())); 0448 0449 _zoomXAutoBorder = new QAction(tr("X-Zoom Auto Border"), this); 0450 _zoomXAutoBorder->setShortcut(Qt::CTRL+Qt::Key_B); 0451 registerShortcut(_zoomXAutoBorder); 0452 connect(_zoomXAutoBorder, SIGNAL(triggered()), this, SLOT(zoomXAutoBorder())); 0453 0454 _zoomXNoSpike = new QAction(tr("X-Zoom Spike Insensitive"), this); 0455 //_zoomXNoSpike->setShortcut(Qt::CTRL+Qt::Key_S); 0456 registerShortcut(_zoomXNoSpike); 0457 connect(_zoomXNoSpike, SIGNAL(triggered()), this, SLOT(zoomXNoSpike())); 0458 0459 _zoomXRight = new QAction(tr("X-Zoom Right"), this); 0460 _zoomXRight->setShortcut(Qt::Key_Right); 0461 registerShortcut(_zoomXRight); 0462 connect(_zoomXRight, SIGNAL(triggered()), this, SLOT(zoomXRight())); 0463 0464 _zoomXFarRight = new QAction(tr("X-Zoom Right by one screen"), this); 0465 _zoomXFarRight->setShortcut(Qt::CTRL+Qt::Key_Right); 0466 registerShortcut(_zoomXFarRight); 0467 connect(_zoomXFarRight, SIGNAL(triggered()), this, SLOT(zoomXFarRight())); 0468 0469 _zoomXLeft= new QAction(tr("X-Zoom Left"), this); 0470 _zoomXLeft->setShortcut(Qt::Key_Left); 0471 registerShortcut(_zoomXLeft); 0472 connect(_zoomXLeft, SIGNAL(triggered()), this, SLOT(zoomXLeft())); 0473 0474 _zoomXFarLeft= new QAction(tr("X-Zoom Left by one screen"), this); 0475 _zoomXFarLeft->setShortcut(Qt::CTRL+Qt::Key_Left); 0476 registerShortcut(_zoomXFarLeft); 0477 connect(_zoomXFarLeft, SIGNAL(triggered()), this, SLOT(zoomXFarLeft())); 0478 0479 _zoomXOut = new QAction(tr("X-Zoom Out"), this); 0480 _zoomXOut->setShortcut(Qt::SHIFT+Qt::Key_Right); 0481 registerShortcut(_zoomXOut); 0482 connect(_zoomXOut, SIGNAL(triggered()), this, SLOT(zoomXOut())); 0483 0484 _zoomXIn = new QAction(tr("X-Zoom In"), this); 0485 _zoomXIn->setShortcut(Qt::SHIFT+Qt::Key_Left); 0486 registerShortcut(_zoomXIn); 0487 connect(_zoomXIn, SIGNAL(triggered()), this, SLOT(zoomXIn())); 0488 0489 _zoomNormalizeXtoY = new QAction(tr("Normalize X-axis to Y-axis"), this); 0490 _zoomNormalizeXtoY->setShortcut(Qt::Key_N); 0491 registerShortcut(_zoomNormalizeXtoY); 0492 connect(_zoomNormalizeXtoY, SIGNAL(triggered()), this, SLOT(zoomNormalizeXtoY())); 0493 0494 _zoomLogX = new QAction(tr("Log X-axis"), this); 0495 _zoomLogX->setShortcut(Qt::Key_G); 0496 _zoomLogX->setCheckable(true); 0497 registerShortcut(_zoomLogX); 0498 connect(_zoomLogX, SIGNAL(triggered()), this, SLOT(zoomLogX())); 0499 0500 _zoomYLocalMaximum = new QAction(tr("Y-Zoom Local Maximum"), this); 0501 _zoomYLocalMaximum->setShortcut(Qt::SHIFT+Qt::Key_L); 0502 registerShortcut(_zoomYLocalMaximum); 0503 connect(_zoomYLocalMaximum, SIGNAL(triggered()), this, SLOT(zoomYLocalMaximum())); 0504 0505 _zoomYMaximum = new QAction(tr("Y-Zoom Maximum"), this); 0506 _zoomYMaximum->setShortcut(Qt::SHIFT+Qt::Key_M); 0507 registerShortcut(_zoomYMaximum); 0508 connect(_zoomYMaximum, SIGNAL(triggered()), this, SLOT(zoomYMaximum())); 0509 0510 _zoomYAutoBorder = new QAction(tr("Y-Zoom Auto Border"), this); 0511 _zoomYAutoBorder->setShortcut(Qt::SHIFT+Qt::Key_B); 0512 registerShortcut(_zoomYAutoBorder); 0513 connect(_zoomYAutoBorder, SIGNAL(triggered()), this, SLOT(zoomYAutoBorder())); 0514 0515 _zoomYNoSpike = new QAction(tr("Y-Zoom Spike Insensitive"), this); 0516 _zoomYNoSpike->setShortcut(Qt::SHIFT+Qt::Key_S); 0517 registerShortcut(_zoomYNoSpike); 0518 connect(_zoomYNoSpike, SIGNAL(triggered()), this, SLOT(zoomYNoSpike())); 0519 0520 _zoomYUp= new QAction(tr("Y-Zoom Up"), this); 0521 _zoomYUp->setShortcut(Qt::Key_Up); 0522 registerShortcut(_zoomYUp); 0523 connect(_zoomYUp, SIGNAL(triggered()), this, SLOT(zoomYUp())); 0524 0525 _zoomYDown= new QAction(tr("Y-Zoom Down"), this); 0526 _zoomYDown->setShortcut(Qt::Key_Down); 0527 registerShortcut(_zoomYDown); 0528 connect(_zoomYDown, SIGNAL(triggered()), this, SLOT(zoomYDown())); 0529 0530 _zoomYOut = new QAction(tr("Y-Zoom Out"), this); 0531 _zoomYOut->setShortcut(Qt::SHIFT+Qt::Key_Up); 0532 registerShortcut(_zoomYOut); 0533 connect(_zoomYOut, SIGNAL(triggered()), this, SLOT(zoomYOut())); 0534 0535 _zoomYIn = new QAction(tr("Y-Zoom In"), this); 0536 _zoomYIn->setShortcut(Qt::SHIFT+Qt::Key_Down); 0537 registerShortcut(_zoomYIn); 0538 connect(_zoomYIn, SIGNAL(triggered()), this, SLOT(zoomYIn())); 0539 0540 _zoomNormalizeYtoX = new QAction(tr("Normalize Y-axis to X-axis"), this); 0541 _zoomNormalizeYtoX->setShortcut(Qt::SHIFT+Qt::Key_N); 0542 registerShortcut(_zoomNormalizeYtoX); 0543 connect(_zoomNormalizeYtoX, SIGNAL(triggered()), this, SLOT(zoomNormalizeYtoX())); 0544 0545 _zoomLogY = new QAction(tr("Log Y Axis"), this); 0546 _zoomLogY->setShortcut(Qt::Key_L); 0547 _zoomLogY->setCheckable(true); 0548 registerShortcut(_zoomLogY); 0549 connect(_zoomLogY, SIGNAL(triggered()), this, SLOT(zoomLogY())); 0550 0551 _adjustImageColorscale = new QAction(tr("Adjust Image Color Scale"), this); 0552 _adjustImageColorscale->setShortcut(Qt::Key_I); 0553 registerShortcut(_adjustImageColorscale); 0554 connect(_adjustImageColorscale, SIGNAL(triggered()), this, SLOT(adjustImageColorScale())); 0555 0556 createZoomMenu(); 0557 0558 _plotMaximize = new QAction(tr("Maximize Plot"), this); 0559 _plotMaximize->setShortcut(Qt::Key_Z); 0560 _plotMaximize->setCheckable(true); 0561 registerShortcut(_plotMaximize); 0562 connect(_plotMaximize, SIGNAL(triggered()), this, SLOT(plotMaximize())); 0563 0564 0565 _shareBoxShareX = new QAction(tr("Share Plots on X-Axis"), this); 0566 _shareBoxShareX->setCheckable(true); 0567 registerShortcut(_shareBoxShareX); 0568 connect(_shareBoxShareX, SIGNAL(triggered()), this, SIGNAL(shareXAxisTriggered())); 0569 0570 _shareBoxShareY = new QAction(tr("Share Plots on Y-Axis"), this); 0571 _shareBoxShareY->setCheckable(true); 0572 registerShortcut(_shareBoxShareY); 0573 connect(_shareBoxShareY, SIGNAL(triggered()), this, SIGNAL(shareYAxisTriggered())); 0574 0575 _breakSharedBox = new QAction(tr("Break Shared Axis Box"), this); 0576 registerShortcut(_breakSharedBox); 0577 connect(_breakSharedBox, SIGNAL(triggered()), this, SIGNAL(breakShareTriggered())); 0578 0579 _copyStatus = new QAction(tr("Copy Coordinates"), this); 0580 _copyStatus->setShortcut(Qt::CTRL + Qt::Key_C); 0581 registerShortcut(_copyStatus); 0582 connect(_copyStatus, SIGNAL(triggered()), this, SLOT(copyStatus())); 0583 0584 _copyXCoord = new QAction(tr("Copy X Coordinate"), this); 0585 _copyXCoord->setShortcut(Qt::Key_X); 0586 registerShortcut(_copyXCoord); 0587 connect(_copyXCoord, SIGNAL(triggered()), this, SLOT(copyXCoord())); 0588 0589 _copyYCoord = new QAction(tr("Copy Y Coordinate"), this); 0590 _copyYCoord->setShortcut(Qt::Key_Y); 0591 registerShortcut(_copyYCoord); 0592 connect(_copyYCoord, SIGNAL(triggered()), this, SLOT(copyYCoord())); 0593 0594 createCopyMenu(); 0595 0596 referenceMode = new QAction(tr("Place Reference Marker"), this); 0597 referenceMode->setShortcut(Qt::Key_C); 0598 registerShortcut(referenceMode); 0599 0600 referenceModeDisabled = new QAction(tr("Remove Reference Marker"), this); 0601 referenceModeDisabled->setShortcut(Qt::SHIFT + Qt::Key_C); 0602 registerShortcut(referenceModeDisabled); 0603 0604 } 0605 0606 void PlotItem::createCopyMenu() { 0607 if (_copyMenu) { 0608 delete _copyMenu; 0609 } 0610 0611 _copyMenu = new QMenu; 0612 _copyMenu->setTitle(tr("Copy")); 0613 0614 _copyMenu->addAction(_copyStatus); 0615 _copyMenu->addAction(_copyXCoord); 0616 _copyMenu->addAction(_copyYCoord); 0617 0618 } 0619 0620 void PlotItem::createZoomMenu() { 0621 if (_zoomMenu) { 0622 delete _zoomMenu; 0623 } 0624 0625 _zoomMenu = new QMenu; 0626 _zoomMenu->setTitle(tr("Zoom")); 0627 0628 QMenu *xyZoomMenu = _zoomMenu->addMenu(tr("XY Zoom", "menu title: zoom in both axis of a plot")); 0629 QMenu *yZoomMenu = _zoomMenu->addMenu(tr("Y Zoom", "menu title: zoom in the horizontal axis of a plot")); 0630 QMenu *xZoomMenu = _zoomMenu->addMenu(tr("X Zoom", "menu title: zoom in the vertical axis of a plot")); 0631 0632 _zoomMenu->addAction(_zoomPrevious); 0633 _zoomMenu->addAction(_adjustImageColorscale); 0634 0635 xyZoomMenu->addAction(_zoomMaximum); 0636 xyZoomMenu->addAction(_zoomMaxSpikeInsensitive); 0637 xyZoomMenu->addAction(_zoomMeanCentered); 0638 xyZoomMenu->addAction(_zoomTied); 0639 0640 xZoomMenu->addAction(_zoomXTied); 0641 xZoomMenu->addAction(_zoomXMaximum); 0642 xZoomMenu->addAction(_zoomXAutoBorder); 0643 xZoomMenu->addAction(_zoomXNoSpike); 0644 xZoomMenu->addAction(_zoomXRight); 0645 xZoomMenu->addAction(_zoomXLeft); 0646 xZoomMenu->addAction(_zoomXFarRight); 0647 xZoomMenu->addAction(_zoomXFarLeft); 0648 xZoomMenu->addAction(_zoomXOut); 0649 xZoomMenu->addAction(_zoomXIn); 0650 xZoomMenu->addAction(_zoomNormalizeXtoY); 0651 xZoomMenu->addAction(_zoomLogX); 0652 0653 0654 yZoomMenu->addAction(_zoomYTied); 0655 yZoomMenu->addAction(_zoomYLocalMaximum); 0656 yZoomMenu->addAction(_zoomYMaximum); 0657 yZoomMenu->addAction(_zoomYAutoBorder); 0658 yZoomMenu->addAction(_zoomYNoSpike); 0659 yZoomMenu->addAction(_zoomYUp); 0660 yZoomMenu->addAction(_zoomYDown); 0661 yZoomMenu->addAction(_zoomYOut); 0662 yZoomMenu->addAction(_zoomYIn); 0663 yZoomMenu->addAction(_zoomNormalizeYtoX); 0664 yZoomMenu->addAction(_zoomLogY); 0665 } 0666 0667 0668 CurveList PlotItem::curveList() const { 0669 CurveList list; 0670 foreach (PlotRenderItem *renderer, renderItems()) { 0671 foreach (RelationPtr relation, renderer->relationList()) { 0672 if (CurvePtr curve = kst_cast<Curve>(relation)) { 0673 list << curve; 0674 } 0675 } 0676 } 0677 return list; 0678 } 0679 0680 0681 RelationList PlotItem::relationList() const { 0682 RelationList list; 0683 foreach (PlotRenderItem *renderer, renderItems()) { 0684 foreach (RelationPtr relation, renderer->relationList()) { 0685 list << relation; 0686 } 0687 } 0688 0689 return list; 0690 } 0691 0692 0693 void PlotItem::createFilterMenu() { 0694 if (_filterMenu) { 0695 delete _filterMenu; 0696 } 0697 0698 _filterMenu = new QMenu; 0699 _filterMenu->setTitle(tr("Create Filter")); 0700 0701 CurveList curves = curveList(); 0702 foreach (const CurvePtr& curve, curves) { 0703 _filterMenu->addAction(new QAction(curve->Name(), this)); 0704 } 0705 connect(_filterMenu, SIGNAL(triggered(QAction*)), this, SLOT(showFilterDialog(QAction*))); 0706 } 0707 0708 0709 void PlotItem::createEditMenu() { 0710 if (_editMenu) { 0711 delete _editMenu; 0712 } 0713 0714 _editMenu = new QMenu; 0715 0716 int nc = curveList().size(); 0717 int nr = relationList().size(); 0718 if (nc == nr) { 0719 _editMenu->setTitle(tr("Edit Curve")); 0720 } else if (nc == 0) { 0721 _editMenu->setTitle(tr("Edit Image")); 0722 } else { 0723 _editMenu->setTitle(tr("Edit Curve/Image")); 0724 } 0725 0726 RelationList relations = relationList(); 0727 foreach (const RelationPtr& relation, relations) { 0728 _editMenu->addAction(new QAction(relation->Name(), this)); 0729 } 0730 connect(_editMenu, SIGNAL(triggered(QAction*)), this, SLOT(showEditDialog(QAction*))); 0731 } 0732 0733 0734 void PlotItem::createFitMenu() { 0735 if (_fitMenu) { 0736 delete _fitMenu; 0737 } 0738 0739 _fitMenu = new QMenu; 0740 _fitMenu->setTitle(tr("Create Fit")); 0741 0742 CurveList curves = curveList(); 0743 foreach (const CurvePtr& curve, curves) { 0744 _fitMenu->addAction(new QAction(curve->Name(), this)); 0745 } 0746 0747 connect(_fitMenu, SIGNAL(triggered(QAction*)), this, SLOT(showFitDialog(QAction*))); 0748 } 0749 0750 void PlotItem::createPSDMenu() { 0751 if (_psdMenu) { 0752 delete _psdMenu; 0753 } 0754 0755 _psdMenu = new QMenu; 0756 _psdMenu->setTitle(tr("Create Spectrum")); 0757 0758 CurveList curves = curveList(); 0759 foreach (const CurvePtr& curve, curves) { 0760 _psdMenu->addAction(new QAction(curve->Name(), this)); 0761 } 0762 0763 connect(_psdMenu, SIGNAL(triggered(QAction*)), this, SLOT(showPSDDialog(QAction*))); 0764 } 0765 0766 0767 void PlotItem::createHistogramMenu() { 0768 if (_histogramMenu) { 0769 delete _histogramMenu; 0770 } 0771 0772 _histogramMenu = new QMenu; 0773 _histogramMenu->setTitle(tr("Create Histogram")); 0774 0775 CurveList curves = curveList(); 0776 foreach (const CurvePtr& curve, curves) { 0777 _histogramMenu->addAction(new QAction(curve->Name(), this)); 0778 } 0779 0780 connect(_histogramMenu, SIGNAL(triggered(QAction*)), this, SLOT(showHistogramDialog(QAction*))); 0781 } 0782 0783 0784 0785 void PlotItem::createSharedAxisBoxMenu() { 0786 if (_sharedAxisBoxMenu) { 0787 delete _sharedAxisBoxMenu; 0788 } 0789 _sharedAxisBoxMenu = new QMenu; 0790 _sharedAxisBoxMenu->setTitle(tr("Shared Axis Box Settings")); 0791 0792 _sharedAxisBoxMenu->addAction(_shareBoxShareX); 0793 _sharedAxisBoxMenu->addAction(_shareBoxShareY); 0794 } 0795 0796 0797 0798 0799 void PlotItem::addToMenuForContextEvent(QMenu &menu) { 0800 0801 menu.addSeparator(); 0802 menu.addAction(_createCurve); 0803 0804 if (curveList().size()>0) { 0805 if (!DataObject::filterPluginList().empty()) { 0806 createFilterMenu(); 0807 menu.addMenu(_filterMenu); 0808 } 0809 0810 if (!DataObject::fitsPluginList().empty()) { 0811 createFitMenu(); 0812 menu.addMenu(_fitMenu); 0813 } 0814 createPSDMenu(); 0815 menu.addMenu(_psdMenu); 0816 0817 createHistogramMenu(); 0818 menu.addMenu(_histogramMenu); 0819 0820 createEditMenu(); 0821 menu.addMenu(_editMenu); 0822 0823 } else if (relationList().size()>0) { 0824 menu.addSeparator(); 0825 createEditMenu(); 0826 menu.addMenu(_editMenu); 0827 } 0828 0829 if (parentItem() && isInSharedAxisBox() && _sharedBox) { 0830 if (view()->viewMode() == View::Data) { 0831 0832 menu.addSeparator(); 0833 menu.addMenu(_sharedAxisBoxMenu); 0834 0835 menu.addAction(_breakSharedBox); 0836 0837 _shareBoxShareX->setChecked(_sharedBox->isXAxisShared()); 0838 _shareBoxShareY->setChecked(_sharedBox->isYAxisShared()); 0839 } 0840 } 0841 0842 if (view()->viewMode() == View::Data) { 0843 _plotMaximize->setChecked(_plotMaximized); 0844 menu.addSeparator(); 0845 menu.addAction(_plotMaximize); 0846 menu.addAction(referenceMode); 0847 menu.addAction(referenceModeDisabled); 0848 } 0849 0850 _zoomLogX->setChecked(xAxis()->axisLog()); 0851 _zoomLogY->setChecked(yAxis()->axisLog()); 0852 0853 _zoomTied->setChecked(isTiedZoom()); 0854 _zoomXTied->setChecked(isXTiedZoom()); 0855 _zoomYTied->setChecked(isYTiedZoom()); 0856 0857 _zoomPrevious->setVisible(!isInSharedAxisBox()); 0858 menu.addMenu(_zoomMenu); 0859 0860 menu.addMenu(_copyMenu); 0861 0862 } 0863 0864 0865 void PlotItem::showEditDialog(QAction *action) { 0866 RelationList relations = relationList(); 0867 int n = relations.size(); 0868 for (int i = 0; i<n; i++) { 0869 RelationPtr relation = relations.at(i); 0870 if (relation->Name() == action->text()) { 0871 DialogLauncher::self()->showObjectDialog(relation); 0872 } 0873 } 0874 } 0875 0876 0877 void PlotItem::showFitFilterDialog(QAction* action, const QString& plugin) { 0878 CurveList curves = curveList(); 0879 foreach (const CurvePtr& curve, curves) { 0880 if (curve->Name() == action->text()) { 0881 DialogLauncher::self()->showBasicPluginDialog(plugin, 0, curve->xVector(), curve->yVector(), this); 0882 } 0883 } 0884 } 0885 0886 void PlotItem::showPSDDialog(QAction* action) { 0887 CurveList curves = curveList(); 0888 foreach (const CurvePtr& curve, curves) { 0889 if (curve->Name() == action->text()) { 0890 DialogLauncher::self()->showPowerSpectrumDialog(0, curve->yVector()); 0891 } 0892 } 0893 } 0894 0895 void PlotItem::showCurveDialog() { 0896 DialogLauncher::self()->showCurveDialog(0,0,this); 0897 } 0898 0899 0900 void PlotItem::showHistogramDialog(QAction* action) { 0901 CurveList curves = curveList(); 0902 foreach (const CurvePtr& curve, curves) { 0903 if (curve->Name() == action->text()) { 0904 DialogLauncher::self()->showHistogramDialog(0, curve->yVector()); 0905 } 0906 } 0907 } 0908 0909 0910 void PlotItem::showFilterDialog(QAction* action) { 0911 showFitFilterDialog(action, DataObject::filterPluginList().first()); 0912 } 0913 0914 void PlotItem::showFitDialog(QAction* action) { 0915 showFitFilterDialog(action, DataObject::fitsPluginList().first()); 0916 } 0917 0918 void PlotItem::redrawPlot() { 0919 update(); 0920 } 0921 0922 0923 bool PlotItem::handleChangedInputs(qint64 serial) { 0924 if (!_allowUpdates) { 0925 return false; 0926 } 0927 0928 // decide if the inputs have changed 0929 bool no_change = true; 0930 0931 if (_serialOfLastChange==Forced) { 0932 no_change = false; 0933 } else { 0934 foreach (PlotRenderItem *renderer, renderItems()) { 0935 foreach (RelationPtr relation, renderer->relationList()) { 0936 if (relation->serialOfLastChange() > _serialOfLastChange) { 0937 no_change = false; 0938 } 0939 } 0940 } 0941 } 0942 0943 if (no_change) { 0944 return false; 0945 } 0946 0947 _serialOfLastChange = serial; 0948 0949 if (isInSharedAxisBox()) { 0950 // Need to update the box's projectionRect. 0951 sharedAxisBox()->updateZoomForDataUpdate(serial); 0952 } 0953 0954 QRectF compute = computedProjectionRect(); 0955 QRectF newProjectionRec = projectionRect(); 0956 0957 if ((xAxis()->axisZoomMode() == PlotAxis::Auto) || 0958 (xAxis()->axisZoomMode() == PlotAxis::MeanCentered) || 0959 (xAxis()->axisZoomMode() == PlotAxis::AutoBorder) || 0960 (xAxis()->axisZoomMode() == PlotAxis::SpikeInsensitive)) { 0961 0962 newProjectionRec.setWidth(0.1); 0963 newProjectionRec.setLeft(0.0); 0964 newProjectionRec.setLeft(compute.x()); 0965 newProjectionRec.setWidth(compute.width()); 0966 } 0967 0968 if ((yAxis()->axisZoomMode() == PlotAxis::AutoBorder) || 0969 (yAxis()->axisZoomMode() == PlotAxis::Auto) || 0970 (yAxis()->axisZoomMode() == PlotAxis::SpikeInsensitive) || 0971 (yAxis()->axisZoomMode() == PlotAxis::MeanCentered)) { 0972 newProjectionRec.setHeight(0.1); 0973 newProjectionRec.setTop(0.0); 0974 newProjectionRec.setTop(compute.y()); 0975 newProjectionRec.setHeight(compute.height()); 0976 } 0977 0978 setProjectionRect(newProjectionRec); 0979 0980 setLabelsDirty(); 0981 0982 return true; 0983 } 0984 0985 0986 QList<PlotRenderItem*> PlotItem::renderItems() const { 0987 return _renderers.values(); 0988 } 0989 0990 0991 PlotRenderItem *PlotItem::renderItem(PlotRenderItem::RenderType type) { 0992 if ((type == PlotRenderItem::First) && (_renderers.count()>0)) { 0993 return _renderers.values().at(0); 0994 } 0995 if (_renderers.contains(type)) 0996 return _renderers.value(type); 0997 0998 switch (type) { 0999 case PlotRenderItem::Cartesian: 1000 { 1001 CartesianRenderItem *renderItem = new CartesianRenderItem(this); 1002 _renderers.insert(type, renderItem); 1003 return renderItem; 1004 } 1005 case PlotRenderItem::Polar: 1006 case PlotRenderItem::Sinusoidal: 1007 default: 1008 return 0; 1009 } 1010 } 1011 1012 1013 void PlotItem::calculateBorders(QPainter *painter) { 1014 1015 calculateLeftLabelMargin(painter); 1016 calculateRightLabelMargin(painter); 1017 calculateTopLabelMargin(painter); 1018 calculateBottomLabelMargin(painter); 1019 1020 calculateBottomTickLabelBound(painter); 1021 calculateLeftTickLabelBound(painter); 1022 1023 calculateMargins(); 1024 1025 setPlotRectsDirty(); 1026 } 1027 1028 1029 void PlotItem::updatePlotPixmap() { 1030 #if BENCHMARK 1031 QTime bench_time; 1032 bench_time.start(); 1033 #endif 1034 1035 _plotPixmapDirty = false; 1036 if (maskedByMaximization()) { 1037 return; 1038 } 1039 1040 #ifdef QT5 1041 int device_pixel_ratio = view()->devicePixelRatio(); 1042 #else 1043 int device_pixel_ratio = 1; 1044 #endif 1045 1046 QPixmap pixmap(device_pixel_ratio*(rect().width()+1), device_pixel_ratio*(rect().height()+1)); 1047 #ifdef QT5 1048 pixmap.setDevicePixelRatio(device_pixel_ratio); 1049 #endif 1050 1051 pixmap.fill(Qt::transparent); 1052 QPainter pixmapPainter(&pixmap); 1053 1054 //pixmapPainter.setRenderHint(QPainter::Antialiasing, ApplicationSettings::self()->antialiasPlots()); 1055 1056 pixmapPainter.save(); 1057 if (rect().topLeft() != QPointF(0, 0)) { 1058 pixmapPainter.translate(-rect().topLeft()); 1059 } 1060 paintPixmap(&pixmapPainter); 1061 pixmapPainter.restore(); 1062 1063 _plotPixmap = pixmap; 1064 #if BENCHMARK 1065 int i = bench_time.elapsed(); 1066 qDebug() << "Total Time to update plot pixmap " << (void *)this << ": " << i << "ms"; 1067 #endif 1068 } 1069 1070 1071 void PlotItem::paint(QPainter *painter) { 1072 if (maskedByMaximization()) { 1073 return; 1074 } 1075 1076 #if BENCHMARK 1077 QTime bench_time; 1078 bench_time.start(); 1079 #endif 1080 if (view()->isPrinting()) { 1081 paintPixmap(painter); 1082 } else { 1083 if (_plotPixmapDirty && rect().isValid()) { 1084 updatePlotPixmap(); 1085 } 1086 painter->save(); 1087 painter->setPen(Qt::NoPen); 1088 painter->drawRect(rect()); 1089 painter->restore(); 1090 painter->drawPixmap(rect().topLeft(), _plotPixmap); 1091 if (view()->viewMode() == View::Layout) { 1092 painter->save(); 1093 painter->setPen(pen()); 1094 painter->setBrush(Qt::NoBrush); 1095 painter->drawRect(rect()); 1096 painter->restore(); 1097 } 1098 } 1099 #if BENCHMARK 1100 int i = bench_time.elapsed(); 1101 qDebug() << "Total Time to paint " << (void *)this << ": " << i << "ms" << endl; 1102 #endif 1103 } 1104 1105 1106 void PlotItem::paintPixmap(QPainter *painter) { 1107 if ((view()->plotBordersDirty() || (creationState() == ViewItem::InProgress)) && rect().isValid()) { 1108 ViewGridLayout::standardizePlotMargins(this, painter); 1109 setPlotBordersDirty(false); 1110 } 1111 1112 painter->save(); 1113 painter->setPen(Qt::NoPen); 1114 painter->drawRect(rect()); 1115 painter->restore(); 1116 1117 painter->save(); 1118 bool xTicksUpdated = xAxis()->ticksUpdated(); 1119 bool yTicksUpdated = yAxis()->ticksUpdated(); 1120 if (xTicksUpdated ||yTicksUpdated) { 1121 resetScaleAxisLabels(); 1122 } 1123 1124 painter->setFont(numberLabelDetails()->calculatedFont(*painter->device())); 1125 1126 paintLeftLabel(painter); 1127 paintBottomLabel(painter); 1128 paintRightLabel(painter); 1129 1130 paintPlot(painter, xTicksUpdated, yTicksUpdated); 1131 1132 paintTickLabels(painter); 1133 1134 paintPlotMarkers(painter); 1135 1136 paintTopLabel(painter); 1137 1138 painter->restore(); 1139 } 1140 1141 1142 void PlotItem::paintPlot(QPainter *painter, bool xUpdated, bool yUpdated) { 1143 if (xUpdated) { 1144 xAxis()->validateDrawingRegion(painter); 1145 updateXAxisLines(); 1146 updateXAxisLabels(painter); 1147 } 1148 if (yUpdated) { 1149 yAxis()->validateDrawingRegion(painter); 1150 updateYAxisLines(); 1151 updateYAxisLabels(painter); 1152 } 1153 if (isUseAxisScale()) { 1154 QFont font(painter->font()); 1155 qreal pointSize = qMax((font.pointSizeF() * _numberAxisLabelScaleFactor), ApplicationSettings::self()->minimumFontSize()); 1156 1157 font.setPointSizeF(pointSize); 1158 painter->setFont(font); 1159 } 1160 1161 if (_axisLabelsDirty) { 1162 if (!xUpdated) { 1163 updateXAxisLabels(painter); 1164 } 1165 if (!yUpdated) { 1166 updateYAxisLabels(painter); 1167 } 1168 } 1169 #if BENCHMARK > 1 1170 QTime bench_time, benchtmp; 1171 int b_1 = 0, b_2 = 0, b_3 = 0, b_4 = 0, b_5 = 0; 1172 bench_time.start(); 1173 benchtmp.start(); 1174 #endif 1175 paintMajorGridLines(painter); 1176 #if BENCHMARK > 1 1177 b_1 = benchtmp.elapsed(); 1178 #endif 1179 paintMinorGridLines(painter); 1180 #if BENCHMARK > 1 1181 b_2 = benchtmp.elapsed(); 1182 #endif 1183 painter->save(); 1184 painter->setBrush(Qt::NoBrush); 1185 painter->setPen(pen()); 1186 QRectF box(plotRect()); 1187 box.adjust(-1.0, -1.0, 0.0, 0.0); 1188 painter->drawRect(box); 1189 #if BENCHMARK > 1 1190 b_3 = benchtmp.elapsed(); 1191 #endif 1192 1193 paintMajorTicks(painter); 1194 #if BENCHMARK > 1 1195 b_4 = benchtmp.elapsed(); 1196 #endif 1197 paintMinorTicks(painter); 1198 #if BENCHMARK > 1 1199 b_5 = benchtmp.elapsed(); 1200 #endif 1201 painter->restore(); 1202 1203 #if BENCHMARK > 1 1204 int i = bench_time.elapsed(); 1205 qDebug() << "Painting Plot - PaintPlot " << (void *)this << ": " << i << "ms"; 1206 if (b_1 > 0) qDebug() << " Major Lines: " << b_1 << "ms"; 1207 if (b_2 - b_1 > 0) qDebug() << " Minor Lines: " << (b_2 - b_1) << "ms"; 1208 if (b_3 - b_2 > 0) qDebug() << " Rect: " << (b_3 - b_2) << "ms"; 1209 if (b_4 - b_3 > 0) qDebug() << " Major Ticks: " << (b_4 - b_3) << "ms"; 1210 if (b_5 - b_4 > 0) qDebug() << " Minor Ticks: " << (b_5 - b_4) << "ms"; 1211 #endif 1212 } 1213 1214 1215 void PlotItem::updateXAxisLines() { 1216 qreal majorTickLength = qMin(rect().width(), rect().height()) * .02; //two percent 1217 qreal minorTickLength = qMin(rect().width(), rect().height()) * 0.01; //one percent 1218 QRectF rect = plotRect(); 1219 1220 _xMajorGridLines.clear(); 1221 _xMajorTickLines.clear(); 1222 foreach (qreal x, _xAxis->axisMajorTicks()) { 1223 QPointF p1 = QPointF(mapXToPlot(x), rect.bottom()); 1224 QPointF p2 = p1 - QPointF(0, rect.height()); 1225 _xMajorGridLines << QLineF(p1, p2); 1226 1227 p2 = p1 - QPointF(0, majorTickLength); 1228 _xMajorTickLines << QLineF(p1, p2); 1229 1230 p1.setY(rect.top()); 1231 p2 = p1 + QPointF(0, majorTickLength); 1232 _xMajorTickLines << QLineF(p1, p2); 1233 } 1234 _xMinorGridLines.clear(); 1235 _xMinorTickLines.clear(); 1236 foreach (qreal x, _xAxis->axisMinorTicks()) { 1237 QPointF p1 = QPointF(mapXToPlot(x), rect.bottom()); 1238 QPointF p2 = p1 - QPointF(0, rect.height()); 1239 _xMinorGridLines << QLineF(p1, p2); 1240 1241 p2 = p1 - QPointF(0, minorTickLength); 1242 _xMinorTickLines << QLineF(p1, p2); 1243 1244 p1.setY(rect.top()); 1245 p2 = p1 + QPointF(0, minorTickLength); 1246 _xMinorTickLines << QLineF(p1, p2); 1247 } 1248 _xPlotMarkerLines.clear(); 1249 foreach (double x, _xAxis->axisPlotMarkers().markers()) { 1250 double xx = _xAxis->axisLog() ? logXLo(x) : x; 1251 if (xx > _xMin && xx < _xMax) { 1252 QPointF p1 = QPointF(mapXToPlot(x), rect.bottom()); 1253 QPointF p2 = p1 - QPointF(0, rect.height()); 1254 _xPlotMarkerLines << QLineF(p1, p2); 1255 } 1256 } 1257 } 1258 1259 1260 void PlotItem::updateXAxisLabels(QPainter* painter) { 1261 int flags = Qt::TextSingleLine | Qt::AlignCenter; 1262 _xPlotLabels.clear(); 1263 1264 int rotation = _xAxis->axisLabelRotation(); 1265 painter->save(); 1266 QTransform t; 1267 t.rotate(rotation); 1268 1269 QMapIterator<double, QString> xLabelIt(_xAxis->axisLabels()); 1270 while (xLabelIt.hasNext()) { 1271 xLabelIt.next(); 1272 1273 QRectF bound = painter->boundingRect(QRectF(), flags, xLabelIt.value()); 1274 QPointF p; 1275 if (rotation == 0) { 1276 p = QPointF(mapXToPlot(xLabelIt.key()), plotRect().bottom() + bound.height()*0.5 + _calculatedAxisMarginVLead); 1277 bound.moveCenter(p); 1278 } else { 1279 if (rotation < 0) { 1280 qreal theta = (rotation >-30 ? rotation : -30); 1281 qreal right = mapXToPlot(xLabelIt.key()) - bound.height() * (sin(theta*M_PI/180.0)); 1282 bound = t.mapRect(bound); 1283 p = QPointF(right, plotRect().bottom() + _calculatedAxisMarginVLead); 1284 bound.moveTopRight(p); 1285 } else { 1286 qreal theta = (rotation <30 ? rotation : 30); 1287 qreal left = mapXToPlot(xLabelIt.key()) - bound.height() * (sin(theta*M_PI/180.0)); 1288 bound = t.mapRect(bound); 1289 p = QPointF(left, plotRect().bottom() + _calculatedAxisMarginVLead); 1290 bound.moveTopLeft(p); 1291 } 1292 } 1293 1294 if (rect().left() > bound.left()) { 1295 bound.setLeft(rect().left()); 1296 } 1297 1298 if (rect().right() >= bound.right()) { // if no overflow to the right... 1299 CachedPlotLabel label; 1300 label.bound = bound; 1301 label.value = xLabelIt.value(); 1302 _xPlotLabels.append(label); 1303 } 1304 } 1305 painter->restore(); 1306 1307 if (!_xAxis->baseLabel().isEmpty()) { 1308 QRectF bound = painter->boundingRect(QRectF(), flags, _xAxis->baseLabel()); 1309 QPointF p = QPointF(plotRect().left(), plotRect().bottom() + bound.height() * 2.0 + _calculatedAxisMarginVLead); 1310 bound.moveBottomLeft(p); 1311 1312 CachedPlotLabel label; 1313 label.bound = bound; 1314 label.value = _xAxis->baseLabel(); 1315 label.baseLabel = true; 1316 _xPlotLabels.append(label); 1317 } 1318 } 1319 1320 1321 void PlotItem::setPlotRectsDirty() { 1322 _plotRectsDirty = true; 1323 xAxis()->setTicksUpdated(); 1324 yAxis()->setTicksUpdated(); 1325 setPlotPixmapDirty(); 1326 } 1327 1328 1329 void PlotItem::updateYAxisLines() { 1330 qreal majorTickLength = qMin(rect().width(), rect().height()) * .02; //two percent 1331 qreal minorTickLength = qMin(rect().width(), rect().height()) * 0.01; //one percent 1332 QRectF rect = plotRect(); 1333 1334 _yMajorGridLines.clear(); 1335 _yMajorTickLines.clear(); 1336 foreach (qreal y, _yAxis->axisMajorTicks()) { 1337 QPointF p1 = QPointF(rect.left(), mapYToPlot(y)); 1338 QPointF p2 = p1 + QPointF(rect.width(), 0); 1339 _yMajorGridLines << QLineF(p1, p2); 1340 1341 p2 = p1 + QPointF(majorTickLength, 0); 1342 _yMajorTickLines << QLineF(p1, p2); 1343 1344 p1.setX(rect.right()); 1345 p2 = p1 - QPointF(majorTickLength, 0); 1346 _yMajorTickLines << QLineF(p1, p2); 1347 } 1348 1349 _yMinorGridLines.clear(); 1350 _yMinorTickLines.clear(); 1351 foreach (qreal y, _yAxis->axisMinorTicks()) { 1352 QPointF p1 = QPointF(rect.left(), mapYToPlot(y)); 1353 QPointF p2 = p1 + QPointF(rect.width(), 0); 1354 _yMinorGridLines << QLineF(p1, p2); 1355 1356 p2 = p1 + QPointF(minorTickLength, 0); 1357 _yMinorTickLines << QLineF(p1, p2); 1358 1359 p1.setX(rect.right()); 1360 p2 = p1 - QPointF(minorTickLength, 0); 1361 _yMinorTickLines << QLineF(p1, p2); 1362 } 1363 _yPlotMarkerLines.clear(); 1364 foreach (double y, _yAxis->axisPlotMarkers().markers()) { 1365 double yy = _yAxis->axisLog() ? logYLo(y) : y; 1366 if (yy > _yMin && yy < _yMax) { 1367 QPointF p1 = QPointF(rect.left(), mapYToPlot(y)); 1368 QPointF p2 = p1 + QPointF(rect.width(), 0); 1369 _yPlotMarkerLines << QLineF(p1, p2); 1370 } 1371 } 1372 } 1373 1374 1375 void PlotItem::updateYAxisLabels(QPainter* painter) { 1376 int flags = Qt::TextSingleLine | Qt::AlignCenter; 1377 _yPlotLabels.clear(); 1378 1379 int rotation = _yAxis->axisLabelRotation(); 1380 1381 QTransform t; 1382 t.rotate(rotation); 1383 1384 QMapIterator<double, QString> yLabelIt(_yAxis->axisLabels()); 1385 while (yLabelIt.hasNext()) { 1386 yLabelIt.next(); 1387 1388 QRectF bound = painter->boundingRect(QRectF(), flags, yLabelIt.value()); 1389 QPointF p; 1390 if (rotation < 0) { 1391 qreal theta = (rotation >-45.0) ? rotation : -45.0; 1392 qreal top; 1393 if (rotation >-89) { 1394 top = mapYToPlot(yLabelIt.key()) - bound.height()*0.5*cos(theta*2.0*M_PI/180.0); 1395 } else { 1396 top = mapYToPlot(yLabelIt.key()) - bound.width()*0.5; 1397 } 1398 bound = t.mapRect(bound); 1399 bound.moveRight(plotRect().left() - _calculatedAxisMarginHLead); 1400 bound.moveTop(top); 1401 } else if (rotation > 0) { 1402 qreal theta = (rotation <45.0) ? rotation : 45.0; 1403 qreal bottom; 1404 if (rotation < 89) { 1405 bottom = mapYToPlot(yLabelIt.key()) + bound.height()*0.5*cos(theta*2.0*M_PI/180.0); 1406 } else { 1407 bottom = mapYToPlot(yLabelIt.key()) + bound.width()*0.5; 1408 } 1409 bound = t.mapRect(bound); 1410 bound.moveRight(plotRect().left() - _calculatedAxisMarginHLead); 1411 bound.moveBottom(bottom); 1412 } else { // no rotation. 1413 p = QPointF(plotRect().left() - _calculatedAxisMarginHLead, 1414 mapYToPlot(yLabelIt.key()) - bound.height() * 0.5); 1415 bound.moveTopRight(p); 1416 } 1417 1418 if (rect().top() > bound.top()) bound.setTop(rect().top()); 1419 if (rect().bottom() < bound.bottom()) bound.setBottom(rect().bottom()); 1420 1421 CachedPlotLabel label; 1422 label.bound = bound; 1423 label.value = yLabelIt.value(); 1424 _yPlotLabels.append(label); 1425 } 1426 1427 if (!_yAxis->baseLabel().isEmpty()) { 1428 painter->save(); 1429 painter->rotate(-90.0); 1430 1431 QRectF bound = painter->boundingRect(QRectF(), flags, _yAxis->baseLabel()); 1432 bound = QRectF(bound.x(), bound.bottomRight().y() - bound.width(), bound.height(), bound.width()); 1433 QPointF p = QPointF(rect().left() + _calculatedLeftBaseOffset, plotRect().bottom()); 1434 bound.moveBottomLeft(p); 1435 1436 CachedPlotLabel label; 1437 label.bound = bound; 1438 label.value = _yAxis->baseLabel(); 1439 label.baseLabel = true; 1440 _yPlotLabels.append(label); 1441 painter->restore(); 1442 } 1443 } 1444 1445 1446 void PlotItem::paintMajorGridLines(QPainter *painter) { 1447 if (xAxis()->drawAxisMajorGridLines()) { 1448 painter->save(); 1449 painter->setPen(QPen(QBrush(_xAxis->axisMajorGridLineColor()), 1450 Curve::lineDim(painter->window(),_xAxis->axisMajorGridLineWidth()), 1451 _xAxis->axisMajorGridLineStyle())); 1452 painter->setRenderHint(QPainter::Antialiasing, ApplicationSettings::self()->antialiasPlots()); 1453 painter->drawLines(_xMajorGridLines); 1454 painter->restore(); 1455 } 1456 1457 if (yAxis()->drawAxisMajorGridLines()) { 1458 painter->save(); 1459 painter->setPen(QPen(QBrush(_yAxis->axisMajorGridLineColor()), 1460 Curve::lineDim(painter->window(),_yAxis->axisMajorGridLineWidth()), 1461 _yAxis->axisMajorGridLineStyle())); 1462 painter->setRenderHint(QPainter::Antialiasing, ApplicationSettings::self()->antialiasPlots()); 1463 painter->drawLines(_yMajorGridLines); 1464 painter->restore(); 1465 } 1466 } 1467 1468 1469 void PlotItem::paintMinorGridLines(QPainter *painter) { 1470 if (xAxis()->drawAxisMinorGridLines()) { 1471 painter->save(); 1472 painter->setPen(QPen(QBrush(_xAxis->axisMinorGridLineColor()), 1473 Curve::lineDim(painter->window(),_xAxis->axisMinorGridLineWidth()), 1474 _xAxis->axisMinorGridLineStyle())); 1475 painter->setRenderHint(QPainter::Antialiasing, ApplicationSettings::self()->antialiasPlots()); 1476 painter->drawLines(_xMinorGridLines); 1477 painter->restore(); 1478 } 1479 1480 if (yAxis()->drawAxisMinorGridLines()) { 1481 painter->save(); 1482 painter->setPen(QPen(QBrush(_yAxis->axisMinorGridLineColor()), 1483 Curve::lineDim(painter->window(),_yAxis->axisMinorGridLineWidth()), 1484 _yAxis->axisMinorGridLineStyle())); 1485 painter->setRenderHint(QPainter::Antialiasing, ApplicationSettings::self()->antialiasPlots()); 1486 painter->drawLines(_yMinorGridLines); 1487 painter->restore(); 1488 } 1489 } 1490 1491 1492 void PlotItem::paintMajorTicks(QPainter *painter) { 1493 painter->save(); 1494 painter->setRenderHint(QPainter::Antialiasing, ApplicationSettings::self()->antialiasPlots()); 1495 if (xAxis()->drawAxisMajorTicks()) { 1496 painter->drawLines(_xMajorTickLines); 1497 } 1498 1499 if (yAxis()->drawAxisMajorTicks()) { 1500 painter->drawLines(_yMajorTickLines); 1501 } 1502 painter->restore(); 1503 } 1504 1505 1506 void PlotItem::paintMinorTicks(QPainter *painter) { 1507 painter->save(); 1508 painter->setRenderHint(QPainter::Antialiasing, ApplicationSettings::self()->antialiasPlots()); 1509 if (xAxis()->drawAxisMinorTicks()) { 1510 painter->drawLines(_xMinorTickLines); 1511 } 1512 1513 if (yAxis()->drawAxisMinorTicks()) { 1514 painter->drawLines(_yMinorTickLines); 1515 } 1516 painter->restore(); 1517 } 1518 1519 1520 void PlotItem::scaleAxisLabels(qreal scaleFactor) { 1521 _numberAxisLabelScaleFactor = qMin(_numberAxisLabelScaleFactor, scaleFactor); 1522 } 1523 1524 1525 void PlotItem::resetScaleAxisLabels() { 1526 _numberAxisLabelScaleFactor = 1.0; 1527 } 1528 1529 1530 bool PlotItem::isUseAxisScale() const { 1531 return _useNumberAxisLabelScale; 1532 } 1533 1534 1535 void PlotItem::setUseAxisScale(bool useScale) { 1536 if (_useNumberAxisLabelScale != useScale) { 1537 _useNumberAxisLabelScale = useScale; 1538 setPlotPixmapDirty(); 1539 } 1540 } 1541 1542 1543 static void PaintNumber(QPainter *painter, const QRectF rec, int flags, const QString &text) { 1544 const double superscript_scale = 0.60; 1545 const double superscript_raise = 0.44; 1546 QRectF r = rec; 1547 QStringList base_mantisa = text.split('e'); 1548 1549 if (base_mantisa.size()>1) { 1550 if (base_mantisa[1][0].isLetter()) { 1551 base_mantisa.clear(); 1552 base_mantisa.append(text); 1553 } 1554 } 1555 1556 1557 if (base_mantisa.size()<=1) { 1558 painter->drawText(r, flags, text); 1559 } else { 1560 QString base; 1561 if (base_mantisa[0]==QString('x')) { 1562 base = "10"; 1563 base_mantisa[0].clear(); 1564 } else { 1565 base = "x10"; 1566 } 1567 base_mantisa[1].remove('+'); 1568 if (base_mantisa[1].contains(']')) { 1569 base_mantisa[1].remove(']'); 1570 base_mantisa.append(QString(']')); 1571 } 1572 qreal w = painter->fontMetrics().width(base_mantisa[0] + base) + 1573 painter->fontMetrics().width(base_mantisa[1])*superscript_scale; 1574 if (base_mantisa.size()>2) { 1575 w += painter->fontMetrics().width(base_mantisa[2]); 1576 } 1577 if (flags & Qt::AlignRight) { 1578 qreal right = r.right(); 1579 r.setWidth(w); 1580 r.moveRight(right); 1581 } else if (flags & Qt::AlignCenter) { 1582 QPointF center = r.center(); 1583 r.setWidth(w); 1584 r.moveCenter(center); 1585 } 1586 QPointF p = QPointF(r.topLeft().x(), r.center().y()+painter->fontMetrics().boundingRect('0').height()/2); 1587 //painter->drawRect(r); 1588 painter->drawText(p, base_mantisa[0]); 1589 p.setX(p.x() + painter->fontMetrics().width(base_mantisa[0])); 1590 painter->drawText(p,base); 1591 qreal ly = p.y(); 1592 p.setX(p.x() + painter->fontMetrics().width(base)); 1593 p.setY(p.y() - superscript_raise * painter->fontMetrics().height()); 1594 painter->save(); 1595 QFont f = painter->font(); 1596 f.setPointSizeF(f.pointSizeF()*superscript_scale); 1597 painter->setFont(f); 1598 painter->drawText(p,base_mantisa[1]); 1599 p.setX(p.x() + painter->fontMetrics().width(base_mantisa[1])); 1600 painter->restore(); 1601 if (base_mantisa.size()>2) { 1602 p.setY(ly); 1603 painter->drawText(p,base_mantisa[2]); 1604 } 1605 } 1606 } 1607 1608 void PlotItem::paintBottomTickLabels(QPainter *painter) { 1609 int flags = Qt::TextSingleLine/* | Qt::AlignCenter*/; 1610 1611 painter->save(); 1612 painter->setPen(_numberLabelDetails->fontColor()); 1613 1614 int rotation = _xAxis->axisLabelRotation(); 1615 foreach(const CachedPlotLabel &label, _xPlotLabels) { 1616 QRectF bound = label.bound; 1617 if (_numberAxisLabelScaleFactor<0.9999) { 1618 bound.translate( bound.width() *(1.0-_numberAxisLabelScaleFactor)*0.5, 0.0); 1619 } 1620 if (rotation != 0) { 1621 painter->save(); 1622 QTransform t; 1623 t.rotate(-1*rotation); 1624 painter->rotate(rotation); 1625 1626 PaintNumber(painter, t.mapRect(bound), Qt::TextSingleLine | Qt::AlignCenter, label.value); 1627 painter->restore(); 1628 } else { 1629 PaintNumber(painter, bound, flags, label.value); 1630 } 1631 } 1632 painter->restore(); 1633 1634 } 1635 1636 1637 void PlotItem::paintLeftTickLabels(QPainter *painter) { 1638 int flags = Qt::TextSingleLine | Qt::AlignVCenter | Qt::AlignRight; 1639 1640 painter->save(); 1641 painter->setPen(_numberLabelDetails->fontColor()); 1642 1643 int rotation = _yAxis->axisLabelRotation(); 1644 1645 foreach(const CachedPlotLabel &label, _yPlotLabels) { 1646 if (label.baseLabel) { 1647 painter->save(); 1648 QTransform t; 1649 t.rotate(90.0); 1650 painter->rotate(-90.0); 1651 1652 PaintNumber(painter, t.mapRect(label.bound), flags, label.value); 1653 //painter->drawText(t.mapRect(label.bound), flags, label.value); 1654 painter->restore(); 1655 } else { 1656 if (rotation != 0) { 1657 painter->save(); 1658 QTransform t; 1659 t.rotate(-1*rotation); 1660 painter->rotate(rotation); 1661 1662 PaintNumber(painter, t.mapRect(label.bound), flags, label.value); 1663 //painter->drawText(t.mapRect(label.bound), flags, label.value); 1664 painter->restore(); 1665 } else { 1666 PaintNumber(painter, label.bound, flags, label.value); 1667 //painter->drawText(label.bound, flags, label.value); 1668 } 1669 } 1670 } 1671 painter->restore(); 1672 1673 #if DEBUG_LABEL_REGION 1674 QRectF yLabelRect; 1675 foreach(const CachedPlotLabel &label, _yPlotLabels) { 1676 if (yLabelRect.isValid()) { 1677 yLabelRect = yLabelRect.united(label.bound); 1678 } else { 1679 yLabelRect = label.bound; 1680 } 1681 } 1682 painter->save(); 1683 painter->setOpacity(0.3); 1684 qDebug() << "Left Tick Labels - yLabelRect:" << yLabelRect; 1685 painter->fillRect(yLabelRect, Qt::green); 1686 painter->restore(); 1687 #endif 1688 } 1689 1690 1691 void PlotItem::paintTickLabels(QPainter *painter) { 1692 if (_xAxis->isAxisVisible()) { 1693 paintBottomTickLabels(painter); 1694 } 1695 if (_yAxis->isAxisVisible()) { 1696 paintLeftTickLabels(painter); 1697 } 1698 } 1699 1700 1701 void PlotItem::paintPlotMarkers(QPainter *painter) { 1702 if (!_xPlotMarkerLines.isEmpty()) { 1703 painter->save(); 1704 painter->setPen(QPen(QBrush(_xAxis->axisPlotMarkers().lineColor()), 1705 Curve::lineDim(painter->window(),_xAxis->axisPlotMarkers().lineWidth()), 1706 _xAxis->axisPlotMarkers().lineStyle())); 1707 painter->drawLines(_xPlotMarkerLines); 1708 painter->restore(); 1709 } 1710 if (!_yPlotMarkerLines.isEmpty()) { 1711 painter->save(); 1712 painter->setPen(QPen(QBrush(_yAxis->axisPlotMarkers().lineColor()), 1713 Curve::lineDim(painter->window(),_yAxis->axisPlotMarkers().lineWidth()), 1714 _yAxis->axisPlotMarkers().lineStyle())); 1715 painter->drawLines(_yPlotMarkerLines); 1716 painter->restore(); 1717 } 1718 } 1719 1720 1721 void PlotItem::calculatePlotRects() { 1722 // Calculate the plotAxisRect first. 1723 qreal left = _leftLabelDetails->isVisible() ? leftLabelMargin() : 0.0; 1724 qreal bottom = _bottomLabelDetails->isVisible() ? bottomLabelMargin() : 0.0; 1725 qreal right = _rightLabelDetails->isVisible() ? rightMarginSize() : 0.0; 1726 qreal top = _topLabelDetails->isVisible() ? topMarginSize() : 0.0; 1727 1728 QPointF topLeft(rect().topLeft() + QPointF(left, top)); 1729 if (_manuallyHideRightAxisLabel && !_isInSharedAxisBox) { 1730 right += 1; 1731 } 1732 if (_manuallyHideBottomAxisLabel && !_isInSharedAxisBox) { 1733 bottom += 1; 1734 } 1735 QPointF bottomRight(rect().bottomRight() - QPointF(right, bottom)); 1736 1737 _calculatedPlotAxisRect = QRectF(topLeft, bottomRight); 1738 1739 // Use the PlotAxisRect as basis to calculate PlotRect. 1740 QRectF plot = _calculatedPlotAxisRect; 1741 qreal xOffset = _xAxis->isAxisVisible() ? axisMarginHeight() : 0.0; 1742 qreal yOffset = _yAxis->isAxisVisible() ? axisMarginWidth() : 0.0; 1743 qreal bottomPadding = _xAxis->isAxisVisible() ? _bottomPadding : 0.0; 1744 qreal leftPadding = _yAxis->isAxisVisible() ? _leftPadding : 0.0; 1745 qreal rightPadding = _rightLabelDetails->isVisible() ? _rightPadding : 0.0; 1746 qreal topPadding = _topLabelDetails->isVisible() ? _topPadding : 0.0; 1747 1748 plot.setLeft(plot.left() + yOffset + leftPadding); 1749 plot.setBottom(plot.bottom() - xOffset - bottomPadding); 1750 plot.setRight(plot.right() - rightPadding); 1751 plot.setTop(plot.top() + topPadding); 1752 if (!plot.isValid()) { 1753 if (plot.width() <= 0) { 1754 plot.setWidth(0.1); 1755 } 1756 if (plot.height() <= 0) { 1757 plot.setHeight(0.1); 1758 } 1759 } 1760 _calculatedPlotRect = plot; 1761 _plotRectsDirty = false; 1762 emit updatePlotRect(); 1763 } 1764 1765 1766 QRectF PlotItem::plotAxisRect() { 1767 if (_plotRectsDirty) { 1768 calculatePlotRects(); 1769 } 1770 return _calculatedPlotAxisRect; 1771 } 1772 1773 1774 QRectF PlotItem::plotRect() { 1775 if (_plotRectsDirty) { 1776 calculatePlotRects(); 1777 } 1778 return _calculatedPlotRect; 1779 } 1780 1781 1782 qreal PlotItem::leftMarginSize() const { 1783 qreal margin = _leftLabelDetails->isVisible() ? leftLabelMargin() : 0.0; 1784 margin += _yAxis->isAxisVisible() ? axisMarginWidth() : 0.0; 1785 1786 return margin; 1787 } 1788 1789 1790 qreal PlotItem::bottomMarginSize() const { 1791 qreal margin = _bottomLabelDetails->isVisible() ? bottomLabelMargin() : 0.0; 1792 margin += _xAxis->isAxisVisible() ? axisMarginHeight() : 0.0; 1793 1794 return margin; 1795 } 1796 1797 1798 qreal PlotItem::rightMarginSize() const { 1799 qreal margin = _rightLabelDetails->isVisible() ? rightLabelMargin() : 0.0; 1800 if (supportsTiedZoom() && margin < tiedZoomSize().width()) margin = tiedZoomSize().width(); 1801 return margin; 1802 } 1803 1804 1805 qreal PlotItem::topMarginSize() const { 1806 qreal margin = _topLabelDetails->isVisible() ? topLabelMargin() : 0.0; 1807 if (supportsTiedZoom() && margin < tiedZoomSize().height()) margin = tiedZoomSize().height(); 1808 return margin; 1809 } 1810 1811 1812 void PlotItem::setPadding(const qreal left, const qreal right, const qreal top, const qreal bottom) { 1813 if ((left == _leftPadding) && (right == _rightPadding) && (top == _topPadding) && (bottom == _bottomPadding)) { 1814 return; 1815 } 1816 _leftPadding = left; 1817 _rightPadding = right; 1818 _topPadding = top; 1819 _bottomPadding = bottom; 1820 setPlotRectsDirty(); 1821 emit triggerRedraw(); 1822 } 1823 1824 1825 void PlotItem::setLeftPadding(const qreal padding) { 1826 if (padding != _leftPadding) { 1827 _leftPadding = padding; 1828 setPlotRectsDirty(); 1829 } 1830 } 1831 1832 1833 void PlotItem::setBottomPadding(const qreal padding) { 1834 if (padding != _bottomPadding) { 1835 _bottomPadding = padding; 1836 setPlotRectsDirty(); 1837 } 1838 } 1839 1840 1841 void PlotItem::setRightPadding(const qreal padding) { 1842 if (padding != _rightPadding) { 1843 _rightPadding = padding; 1844 setPlotRectsDirty(); 1845 } 1846 } 1847 1848 1849 void PlotItem::setTopPadding(const qreal padding) { 1850 if (padding != _topPadding) { 1851 _topPadding = padding; 1852 setPlotRectsDirty(); 1853 } 1854 } 1855 1856 void PlotItem::setManuallyHideLeftAxisLabel(bool hide) { 1857 _manuallyHideLeftAxisLabel = hide; 1858 if (!_isInSharedAxisBox) { 1859 setLeftSuppressed(hide); 1860 } 1861 } 1862 1863 void PlotItem::setManuallyHideRightAxisLabel(bool hide) { 1864 _manuallyHideRightAxisLabel = hide; 1865 if (!_isInSharedAxisBox) { 1866 setRightSuppressed(hide); 1867 } 1868 } 1869 1870 void PlotItem::setManuallyHideTopAxisLabel(bool hide) { 1871 _manuallyHideTopAxisLabel = hide; 1872 if (!_isInSharedAxisBox) { 1873 setTopSuppressed(hide); 1874 } 1875 } 1876 1877 void PlotItem::setManuallyHideBottomAxisLabel(bool hide) { 1878 _manuallyHideBottomAxisLabel = hide; 1879 if (!_isInSharedAxisBox) { 1880 setBottomSuppressed(hide); 1881 } 1882 } 1883 1884 1885 QRectF PlotItem::projectionRect() const { 1886 return _projectionRect; 1887 } 1888 1889 1890 void PlotItem::setTiedZoom(bool tiedXZoom, bool tiedYZoom, bool checkAllTied) { 1891 if ((_isXTiedZoom == tiedXZoom) && (_isYTiedZoom == tiedYZoom)) 1892 return; 1893 1894 bool wasTiedZoom = isTiedZoom(); 1895 1896 _isXTiedZoom = tiedXZoom; 1897 _isYTiedZoom = tiedYZoom; 1898 1899 if (isTiedZoom() && !wasTiedZoom) { 1900 PlotItemManager::self()->addTiedZoomPlot(this, checkAllTied); 1901 } else if (!isTiedZoom() && wasTiedZoom) { 1902 PlotItemManager::self()->removeTiedZoomPlot(this); 1903 } 1904 1905 //FIXME ugh, this is expensive, but need to redraw the checkboxes... 1906 update(); 1907 } 1908 1909 1910 bool PlotItem::isInSharedAxisBox() const { 1911 return _isInSharedAxisBox; 1912 } 1913 1914 1915 void PlotItem::setInSharedAxisBox(bool inSharedBox) { 1916 _isInSharedAxisBox = inSharedBox; 1917 setLockParent(inSharedBox); 1918 } 1919 1920 1921 SharedAxisBoxItem* PlotItem::sharedAxisBox() const { 1922 return _sharedBox; 1923 } 1924 1925 1926 void PlotItem::setSharedAxisBox(SharedAxisBoxItem* parent) { 1927 if (parent) { 1928 if (isTiedZoom()) { 1929 setTiedZoom(false, false); 1930 } 1931 setInSharedAxisBox(true); 1932 setAllowedGripModes(0); 1933 setFlags(0); 1934 setParentViewItem(parent); 1935 //setBrush(Qt::transparent); 1936 1937 _sharedBox = parent; 1938 createSharedAxisBoxMenu(); 1939 } else { 1940 setSupportsTiedZoom(true); 1941 setInSharedAxisBox(false); 1942 setAllowedGripModes(Move | Resize | Rotate); 1943 setFlags(ItemIsMovable | ItemIsSelectable | ItemIsFocusable); 1944 setParentViewItem(0); 1945 //setBrush(Qt::white); 1946 1947 _sharedBox = 0; 1948 } 1949 } 1950 1951 1952 void PlotItem::setPlotBordersDirty(bool dirty) { 1953 if (isInSharedAxisBox() && dirty && _sharedBox) { 1954 _sharedBox->setDirty(); 1955 } else { 1956 view()->setPlotBordersDirty(dirty); 1957 } 1958 if (dirty) { 1959 setPlotRectsDirty(); 1960 } 1961 } 1962 1963 1964 void PlotItem::updateScale() { 1965 if (_xAxis->axisLog()) { 1966 _xMax = logXHi(projectionRect().right()); 1967 _xMin = logXLo(projectionRect().left()); 1968 } else { 1969 _xMax = projectionRect().right(); 1970 _xMin = projectionRect().left(); 1971 } 1972 1973 if (_yAxis->axisLog()) { 1974 _yMax = logYHi(projectionRect().bottom()); 1975 _yMin = logYLo(projectionRect().top()); 1976 } else { 1977 _yMax = projectionRect().bottom(); 1978 _yMin = projectionRect().top(); 1979 } 1980 } 1981 1982 1983 QRectF PlotItem::mapToProjection(const QRectF &rect) { 1984 QRectF projRect; 1985 1986 // Invert and convert points. 1987 QPointF topLeft; 1988 QPointF bottomRight; 1989 if (!(_xAxis->axisReversed() || _yAxis->axisReversed())) { 1990 topLeft = mapToProjection(rect.bottomLeft()); 1991 bottomRight = mapToProjection(rect.topRight()); 1992 } else if (_xAxis->axisReversed() && _yAxis->axisReversed()) { 1993 topLeft = mapToProjection(rect.topRight()); 1994 bottomRight = mapToProjection(rect.bottomLeft()); 1995 } else if (_yAxis->axisReversed()) { 1996 topLeft = mapToProjection(rect.topLeft()); 1997 bottomRight = mapToProjection(rect.bottomRight()); 1998 } else { 1999 topLeft = mapToProjection(rect.bottomRight()); 2000 bottomRight = mapToProjection(rect.topLeft()); 2001 } 2002 2003 projRect.setTopLeft(topLeft); 2004 2005 projRect.setWidth(bottomRight.x() - topLeft.x()); 2006 projRect.setHeight(bottomRight.y() - topLeft.y()); 2007 2008 return projRect; 2009 } 2010 2011 2012 QPointF PlotItem::mapToProjection(const QPointF &point) { 2013 QRectF pr = plotRect(); 2014 double xpos, ypos; 2015 2016 updateScale(); 2017 2018 if (_xAxis->axisReversed()) { 2019 xpos = (double)(pr.right() - point.x())/(double)pr.width(); 2020 } else { 2021 xpos = (double)(point.x() - pr.left())/(double)pr.width(); 2022 } 2023 xpos = xpos * (_xMax - _xMin) + _xMin; 2024 2025 if (_xAxis->axisLog()) { 2026 xpos = pow(10, xpos); 2027 } 2028 2029 if (_yAxis->axisReversed()) { 2030 ypos = (double)(point.y() - pr.top())/(double)pr.height(); 2031 } else { 2032 ypos = (double)(pr.bottom() - point.y())/(double)pr.height(); 2033 } 2034 ypos = ypos * (_yMax - _yMin) + _yMin; 2035 2036 if (_yAxis->axisLog()) { 2037 ypos = pow(10, ypos); 2038 } 2039 2040 return QPointF(xpos, ypos); 2041 } 2042 2043 2044 QPointF PlotItem::mapToPlot(const QPointF &point) { 2045 return QPointF(mapXToPlot(point.x()), mapYToPlot(point.y())); 2046 } 2047 2048 2049 qreal PlotItem::mapXToPlot(const qreal &x) { 2050 QRectF pr = plotRect(); 2051 double newX = x; 2052 2053 if (_xAxis->axisLog()) { 2054 newX = logXLo(x); 2055 } 2056 2057 newX -= _xMin; 2058 newX = newX / (_xMax - _xMin); 2059 2060 newX = newX * pr.width(); 2061 2062 if (_xAxis->axisLog() && x == -350) { 2063 newX = 0; 2064 } 2065 2066 if (_xAxis->axisReversed()) { 2067 newX = pr.right() - newX; 2068 } else { 2069 newX = newX + pr.left(); 2070 } 2071 return newX; 2072 } 2073 2074 2075 qreal PlotItem::mapYToPlot(const qreal &y) { 2076 QRectF pr = plotRect(); 2077 double newY = y; 2078 2079 if (_yAxis->axisLog()) { 2080 newY = logYLo(y); 2081 } 2082 2083 newY -= _yMin; 2084 newY = newY / (_yMax - _yMin); 2085 2086 newY = newY * pr.height(); 2087 2088 if (_yAxis->axisLog() && y == -350) { 2089 newY = 0; 2090 } 2091 2092 if (_yAxis->axisReversed()) { 2093 newY = newY + pr.top(); 2094 } else { 2095 newY = pr.bottom() - newY; 2096 } 2097 return newY; 2098 } 2099 2100 2101 QFont PlotItem::globalFont() const { 2102 return _globalFont; 2103 } 2104 2105 2106 void PlotItem::setGlobalFont(const QFont &font) { 2107 if (font != _globalFont) { 2108 _globalFont = font; 2109 setPlotBordersDirty(true); 2110 setLabelsDirty(); 2111 } 2112 } 2113 2114 2115 qreal PlotItem::globalFontScale() const { 2116 return _globalFontScale; 2117 } 2118 2119 2120 void PlotItem::setGlobalFontScale(const qreal scale) { 2121 if (scale != _globalFontScale) { 2122 _globalFontScale = scale; 2123 setPlotBordersDirty(true); 2124 setLabelsDirty(); 2125 } 2126 } 2127 2128 2129 QColor PlotItem::globalFontColor() const { 2130 return _globalFontColor; 2131 } 2132 2133 2134 void PlotItem::setGlobalFontColor(const QColor &color) { 2135 if (color != _globalFontColor) { 2136 _globalFontColor = color; 2137 setLabelsDirty(); 2138 } 2139 } 2140 2141 2142 QString PlotItem::leftLabel() const { 2143 if (!leftLabelDetails()->isAuto()) { 2144 return leftLabelDetails()->text(); 2145 } else { 2146 return autoLeftLabel(); 2147 } 2148 } 2149 2150 2151 QString PlotItem::autoLeftLabel() const { 2152 foreach (PlotRenderItem *renderer, renderItems()) { 2153 QString label = renderer->leftLabel(); 2154 if (!label.isEmpty()) { 2155 if (_yAxis->axisInterpret()) { // remove units 2156 QRegExp rx(" \\[*\\]"); 2157 rx.setPatternSyntax(QRegExp::Wildcard); 2158 return label.remove(rx); 2159 } else { 2160 return label; 2161 } 2162 } 2163 } 2164 return QString(); 2165 } 2166 2167 2168 QString PlotItem::bottomLabel() const { 2169 if (!bottomLabelDetails()->isAuto()) { 2170 return bottomLabelDetails()->text(); 2171 } else { 2172 return autoBottomLabel(); 2173 } 2174 } 2175 2176 2177 QString PlotItem::autoBottomLabel() const { 2178 foreach (PlotRenderItem *renderer, renderItems()) { 2179 QString label = renderer->bottomLabel(); 2180 if (!label.isEmpty()) { 2181 if (_xAxis->axisInterpret()) { // remove units if time interpretation 2182 QRegExp rx(" \\[*\\]"); 2183 rx.setPatternSyntax(QRegExp::Wildcard); 2184 return label.remove(rx); 2185 } else { 2186 return label; 2187 } 2188 } 2189 } 2190 return QString(); 2191 } 2192 2193 2194 QString PlotItem::rightLabel() const { 2195 if (!rightLabelDetails()->isAuto()) { 2196 return rightLabelDetails()->text(); 2197 } else { 2198 return autoRightLabel(); 2199 } 2200 } 2201 2202 2203 QString PlotItem::autoRightLabel() const { 2204 foreach (PlotRenderItem *renderer, renderItems()) { 2205 QString label = renderer->rightLabel(); 2206 if (!label.isEmpty()) 2207 return label; 2208 } 2209 return QString(); 2210 } 2211 2212 2213 QString PlotItem::topLabel() const { 2214 if (!topLabelDetails()->isAuto()) { 2215 return topLabelDetails()->text(); 2216 } else { 2217 return autoTopLabel(); 2218 } 2219 } 2220 2221 2222 QString PlotItem::autoTopLabel() const { 2223 if (showLegend()) { 2224 return QString(); 2225 } else { 2226 QString label; 2227 int count = renderItems().count(); 2228 for (int i=0; i<count; i++) { 2229 label += renderItems().at(i)->topLabel(); 2230 if (i<count - 1) { 2231 label += ' '; 2232 } 2233 } 2234 if (label == leftLabel()) { 2235 return QString(); 2236 } else { 2237 return label; 2238 } 2239 } 2240 } 2241 2242 2243 void PlotItem::setTopSuppressed(bool suppressed) { 2244 if (!_isInSharedAxisBox) { 2245 if (_manuallyHideTopAxisLabel) { 2246 suppressed = true; 2247 } 2248 } 2249 _topLabelDetails->setVisible(!suppressed); 2250 } 2251 2252 2253 void PlotItem::setRightSuppressed(bool suppressed) { 2254 if (!_isInSharedAxisBox) { 2255 if (_manuallyHideRightAxisLabel) { 2256 suppressed = true; 2257 } 2258 } 2259 _rightLabelDetails->setVisible(!suppressed); 2260 } 2261 2262 2263 void PlotItem::setLeftSuppressed(bool suppressed) { 2264 if (!_isInSharedAxisBox) { 2265 if (_manuallyHideLeftAxisLabel) { 2266 suppressed = true; 2267 } 2268 } 2269 _leftLabelDetails->setVisible(!suppressed); 2270 _yAxis->setAxisVisible(!suppressed); 2271 } 2272 2273 2274 void PlotItem::setBottomSuppressed(bool suppressed) { 2275 if (!_isInSharedAxisBox) { 2276 if (_manuallyHideBottomAxisLabel) { 2277 suppressed = true; 2278 } 2279 } 2280 _bottomLabelDetails->setVisible(!suppressed); 2281 _xAxis->setAxisVisible(!suppressed); 2282 } 2283 2284 2285 void PlotItem::setLabelsVisible(bool visible) { 2286 _leftLabelDetails->setVisible(visible); 2287 _rightLabelDetails->setVisible(visible); 2288 _topLabelDetails->setVisible(visible); 2289 _bottomLabelDetails->setVisible(visible); 2290 _xAxis->setAxisVisible(visible); 2291 _yAxis->setAxisVisible(visible); 2292 } 2293 2294 2295 qreal PlotItem::labelMarginWidth() const { 2296 return _calculatedLabelMarginWidth; 2297 } 2298 2299 2300 qreal PlotItem::leftLabelMargin() const { 2301 return _calculatedLeftLabelMargin; 2302 } 2303 2304 2305 qreal PlotItem::rightLabelMargin() const { 2306 return _calculatedRightLabelMargin; 2307 } 2308 2309 2310 qreal PlotItem::labelMarginHeight() const { 2311 return _calculatedLabelMarginHeight; 2312 } 2313 2314 2315 qreal PlotItem::topLabelMargin() const { 2316 return _calculatedTopLabelMargin; 2317 } 2318 2319 2320 2321 qreal PlotItem::bottomLabelMargin() const { 2322 return _calculatedBottomLabelMargin; 2323 } 2324 2325 2326 QRectF PlotItem::topLabelRect() const { 2327 if (topLabelMargin()>0) { 2328 return QRectF(0.0, 0.0, width() - leftLabelMargin() - rightLabelMargin(), topLabelMargin()); 2329 } else { 2330 return QRectF(0.0, 0.0, width() - leftLabelMargin() - rightLabelMargin(), _calculatedTopLabelHeight); 2331 } 2332 } 2333 2334 2335 QRectF PlotItem::bottomLabelRect() const { 2336 return QRectF(0.0, 0.0, width() - leftLabelMargin() - rightLabelMargin(), bottomLabelMargin()); 2337 } 2338 2339 2340 QRectF PlotItem::leftLabelRect() const { 2341 return QRectF(0.0, 0.0, leftLabelMargin(), height() - topLabelMargin() - bottomLabelMargin()); 2342 } 2343 2344 2345 QRectF PlotItem::rightLabelRect() const { 2346 return QRectF(0.0, 0.0, rightLabelMargin(), height() - topLabelMargin() - bottomLabelMargin()); 2347 } 2348 2349 2350 void PlotItem::generateLeftLabel(QPainter *p) { 2351 if (!_leftLabel.dirty) { 2352 return; 2353 } 2354 _leftLabel.valid = false; 2355 _leftLabel.dirty = false; 2356 Label::Parsed *parsed = Label::parse(leftLabel(), _leftLabelDetails->fontColor()); 2357 if (parsed) { 2358 2359 if (_leftLabel.rc) { 2360 delete _leftLabel.rc; 2361 } 2362 2363 Label::RenderContext *rc = new Label::RenderContext(leftLabelDetails()->calculatedFont(*p->device()), p); 2364 rc->y = rc->fontAscent(); 2365 Label::renderLabel(*rc, parsed->chunk, true, false); 2366 2367 QTransform t; 2368 t.translate(rect().left(),plotRect().center().y() + rc->x/2); 2369 t.rotate(-90.0); 2370 2371 connect(rc, SIGNAL(labelDirty()), this, SLOT(setLeftLabelDirty())); 2372 connect(rc, SIGNAL(labelDirty()), this, SLOT(redrawPlot())); 2373 2374 _leftLabel.rc = rc; 2375 _leftLabel.transform = t; 2376 _leftLabel.valid = true; 2377 2378 delete parsed; 2379 } 2380 } 2381 2382 2383 void PlotItem::paintLeftLabel(QPainter *painter) { 2384 if (!_leftLabelDetails->isVisible() || leftLabel().isEmpty()) 2385 return; 2386 2387 generateLeftLabel(painter); 2388 2389 if (_leftLabel.valid) { 2390 painter->save(); 2391 painter->setTransform(_leftLabel.transform, true); 2392 Label::paintLabel(*_leftLabel.rc, painter); 2393 painter->restore(); 2394 } 2395 } 2396 2397 2398 void PlotItem::calculateLeftLabelMargin(QPainter *painter) { 2399 if (!_leftLabelDetails->isVisible()) { 2400 _calculatedLeftLabelMargin = 0; 2401 } else { 2402 painter->save(); 2403 QTransform t; 2404 t.rotate(90.0); 2405 painter->rotate(-90.0); 2406 2407 painter->setFont(leftLabelDetails()->calculatedFont(*painter->device())); 2408 QRectF leftLabelBound = painter->boundingRect(t.mapRect(leftLabelRect()), 2409 Qt::AlignCenter, leftLabel()); 2410 painter->restore(); 2411 2412 _calculatedLeftLabelMargin = leftLabelBound.height(); 2413 _calculatedLeftLabelWidth = leftLabelBound.width(); 2414 2415 //No more than 1/4 the width of the plot 2416 if (width() < _calculatedLeftLabelMargin * 4) 2417 _calculatedLeftLabelMargin = width() / 4; 2418 } 2419 } 2420 2421 2422 void PlotItem::generateBottomLabel(QPainter *p) { 2423 if (!_bottomLabel.dirty) { 2424 return; 2425 } 2426 2427 _bottomLabel.valid = false; 2428 _bottomLabel.dirty = false; 2429 Label::Parsed *parsed = Label::parse(bottomLabel(),_bottomLabelDetails->fontColor()); 2430 if (parsed) { 2431 2432 if (_bottomLabel.rc) { 2433 delete _bottomLabel.rc; 2434 } 2435 2436 Label::RenderContext *rc = new Label::RenderContext(bottomLabelDetails()->calculatedFont(*p->device()), p); 2437 rc->y = rc->fontAscent(); 2438 Label::renderLabel(*rc, parsed->chunk, true, false); 2439 2440 QTransform t; 2441 t.translate(plotRect().center().x() - rc->x / 2, plotAxisRect().bottom()); 2442 2443 connect(rc, SIGNAL(labelDirty()), this, SLOT(setBottomLabelDirty())); 2444 connect(rc, SIGNAL(labelDirty()), this, SLOT(redrawPlot())); 2445 2446 _bottomLabel.rc = rc; 2447 _bottomLabel.transform = t; 2448 _bottomLabel.valid = true; 2449 2450 delete parsed; 2451 } 2452 } 2453 2454 2455 void PlotItem::paintBottomLabel(QPainter *painter) { 2456 if (!_bottomLabelDetails->isVisible() || bottomLabel().isEmpty()) 2457 return; 2458 2459 generateBottomLabel(painter); 2460 2461 if (_bottomLabel.valid) { 2462 painter->save(); 2463 painter->setTransform(_bottomLabel.transform, true); 2464 Label::paintLabel(*_bottomLabel.rc, painter); 2465 painter->restore(); 2466 } 2467 } 2468 2469 2470 void PlotItem::calculateBottomLabelMargin(QPainter *painter) { 2471 if (!_bottomLabelDetails->isVisible()) { 2472 _calculatedBottomLabelMargin = 0; 2473 } else { 2474 painter->save(); 2475 2476 painter->setFont(bottomLabelDetails()->calculatedFont(*painter->device())); 2477 2478 QRectF bottomLabelBound = painter->boundingRect(bottomLabelRect(), 2479 Qt::AlignCenter, bottomLabel()); 2480 painter->restore(); 2481 2482 _calculatedBottomLabelMargin = bottomLabelBound.height(); 2483 _calculatedBottomLabelWidth = bottomLabelBound.width(); 2484 2485 //No more than 1/4 the height of the plot 2486 if (height() < _calculatedBottomLabelMargin * 4) 2487 _calculatedLeftLabelMargin = height() / 4; 2488 } 2489 } 2490 2491 2492 void PlotItem::generateRightLabel(QPainter *p) { 2493 if (!_rightLabel.dirty) { 2494 return; 2495 } 2496 _rightLabel.valid = false; 2497 _rightLabel.dirty = false; 2498 Label::Parsed *parsed = Label::parse(rightLabel(), _rightLabelDetails->fontColor()); 2499 if (parsed && rightLabelRect().isValid()) { 2500 2501 if (_rightLabel.parsed) { 2502 delete _rightLabel.parsed; 2503 } 2504 2505 Label::RenderContext *rc = new Label::RenderContext(rightLabelDetails()->calculatedFont(*p->device()), p); 2506 rc->y = rc->fontAscent(); 2507 Label::renderLabel(*rc, parsed->chunk, true, false); 2508 2509 QTransform t; 2510 t.translate(rect().right(), plotRect().center().y() - rc->x/2); 2511 2512 t.rotate(90.0); 2513 2514 connect(rc, SIGNAL(labelDirty()), this, SLOT(setRightLabelDirty())); 2515 connect(rc, SIGNAL(labelDirty()), this, SLOT(redrawPlot())); 2516 2517 _rightLabel.rc = rc; 2518 _rightLabel.transform = t; 2519 _rightLabel.valid = true; 2520 2521 delete parsed; 2522 } 2523 } 2524 2525 2526 void PlotItem::paintRightLabel(QPainter *painter) { 2527 if (!_rightLabelDetails->isVisible() || rightLabel().isEmpty()) 2528 return; 2529 2530 generateRightLabel(painter); 2531 2532 if (_rightLabel.valid) { 2533 painter->save(); 2534 painter->setTransform(_rightLabel.transform, true); 2535 Label::paintLabel(*_rightLabel.rc, painter); 2536 painter->restore(); 2537 } 2538 2539 } 2540 2541 2542 void PlotItem::calculateRightLabelMargin(QPainter *painter) { 2543 if (!_rightLabelDetails->isVisible()) { 2544 _calculatedRightLabelMargin = 0; 2545 } else { 2546 painter->save(); 2547 QTransform t; 2548 t.rotate(-90.0); 2549 painter->rotate(90.0); 2550 2551 painter->setFont(rightLabelDetails()->calculatedFont(*painter->device())); 2552 2553 QRectF rightLabelBound = painter->boundingRect(t.mapRect(rightLabelRect()), 2554 Qt::AlignCenter, rightLabel()); 2555 painter->restore(); 2556 2557 _calculatedRightLabelMargin = qMax(_calculatedAxisMarginROverflow, rightLabelBound.height()); 2558 2559 //No more than 1/4 the width of the plot 2560 if (width() < _calculatedRightLabelMargin * 4) 2561 _calculatedRightLabelMargin = width() / 4; 2562 } 2563 } 2564 2565 2566 void PlotItem::generateTopLabel(QPainter *p) { 2567 if (!_topLabel.dirty) { 2568 return; 2569 } 2570 _topLabel.valid = false; 2571 _topLabel.dirty = false; 2572 Label::Parsed *parsed = Label::parse(topLabel(), _topLabelDetails->fontColor()); 2573 if (parsed && topLabelRect().isValid()) { 2574 2575 if (_topLabel.rc) { 2576 delete _topLabel.rc; 2577 } 2578 2579 Label::RenderContext *rc = new Label::RenderContext(topLabelDetails()->calculatedFont(*p->device()), p); 2580 rc->y = rc->fontAscent(); 2581 Label::renderLabel(*rc, parsed->chunk, true, false); 2582 2583 QTransform t; 2584 if (_topLabelDetails->isVisible()) { 2585 t.translate(plotRect().center().x() - rc->x / 2, rect().top()); 2586 } else { 2587 t.translate(plotRect().center().x() - rc->x / 2, rect().top() + topLabelRect().height()/2); 2588 } 2589 connect(rc, SIGNAL(labelDirty()), this, SLOT(setTopLabelDirty())); 2590 connect(rc, SIGNAL(labelDirty()), this, SLOT(redrawPlot())); 2591 2592 _topLabel.rc = rc; 2593 _topLabel.transform = t; 2594 _topLabel.valid = true; 2595 2596 delete parsed; 2597 } 2598 } 2599 2600 2601 void PlotItem::paintTopLabel(QPainter *painter) { 2602 if (topLabel().isEmpty()) 2603 return; 2604 2605 generateTopLabel(painter); 2606 if (_topLabel.valid) { 2607 painter->save(); 2608 painter->setTransform(_topLabel.transform, true); 2609 Label::paintLabel(*_topLabel.rc, painter); 2610 painter->restore(); 2611 2612 } 2613 } 2614 2615 2616 void PlotItem::calculateTopLabelMargin(QPainter *painter) { 2617 2618 painter->save(); 2619 2620 painter->setFont(topLabelDetails()->calculatedFont(*painter->device())); 2621 2622 QRectF topLabelBound = painter->boundingRect(topLabelRect(), 2623 Qt::AlignCenter, topLabel()); 2624 2625 painter->restore(); 2626 2627 _calculatedTopLabelHeight = topLabelBound.height(); 2628 2629 if (!_topLabelDetails->isVisible()) { 2630 _calculatedTopLabelMargin = 0; 2631 } else { 2632 _calculatedTopLabelMargin = qMax(_calculatedAxisMarginTOverflow, topLabelBound.height()); 2633 2634 //No more than 1/4 the height of the plot 2635 if (height() < _calculatedTopLabelMargin * 4) 2636 _calculatedTopLabelMargin = height() / 4; 2637 } 2638 } 2639 2640 2641 void PlotItem::calculateMargins() { 2642 qreal m = qMax(_calculatedLeftLabelMargin, _calculatedRightLabelMargin); 2643 2644 //No more than 1/4 the width of the plot 2645 if (width() < m * 4) 2646 m = width() / 4; 2647 2648 _calculatedLabelMarginWidth = m; 2649 2650 m = qMax(_calculatedTopLabelMargin, _calculatedBottomLabelMargin); 2651 2652 //No more than 1/4 the height of the plot 2653 if (height() < m * 4) 2654 m = height() / 4; 2655 2656 _calculatedLabelMarginHeight = m; 2657 } 2658 2659 2660 qreal PlotItem::axisMarginWidth() const { 2661 return _calculatedAxisMarginWidth; 2662 } 2663 2664 2665 qreal PlotItem::axisMarginHeight() const { 2666 return _calculatedAxisMarginHeight; 2667 } 2668 2669 /** This function calculates and sets three things: 2670 _calculatedAxisMarginVLead: spacing between bottom of plotRect and top of axis labels 2671 _calculatedAxisMarginROverflow: rightmost axis number extension beyond plotRect 2672 _calculatedAxisMarginHeight: the height of the axis numbers 2673 */ 2674 void PlotItem::calculateBottomTickLabelBound(QPainter *painter) { 2675 QRectF xLabelRect; 2676 2677 painter->save(); 2678 2679 painter->setFont(numberLabelDetails()->calculatedFont(*painter->device())); 2680 2681 2682 int flags = Qt::TextSingleLine | Qt::AlignCenter; 2683 2684 _calculatedAxisMarginVLead = painter->fontMetrics().boundingRect('0').height()/2; 2685 2686 if (_xAxis->isAxisVisible()) { 2687 // future potential optimization: only get bounds of the rightmost label 2688 // but remember: the axis may be reversed. 2689 QMapIterator<double, QString> xLabelIt(_xAxis->axisLabels()); 2690 while (xLabelIt.hasNext()) { 2691 xLabelIt.next(); 2692 2693 QRectF bound = painter->boundingRect(QRectF(), flags, xLabelIt.value()); 2694 QPointF p(mapXToPlot(xLabelIt.key()), plotRect().bottom() + bound.height() / 2.0 + _calculatedAxisMarginVLead); 2695 bound.moveCenter(p); 2696 2697 int rotation = _xAxis->axisLabelRotation(); 2698 QTransform t; 2699 t.rotate(rotation); 2700 2701 if (rotation != 0) { 2702 bound.setHeight(t.mapRect(bound).height()); 2703 } 2704 2705 if (xLabelRect.isValid()) { 2706 xLabelRect = xLabelRect.united(bound); 2707 } else { 2708 xLabelRect = bound; 2709 } 2710 } 2711 } 2712 2713 xLabelRect.setHeight(xLabelRect.height() + _calculatedAxisMarginVLead); 2714 2715 if (!_xAxis->baseLabel().isEmpty()) { 2716 qreal height = painter->boundingRect(QRectF(), flags, _xAxis->baseLabel()).height(); 2717 if (painter->boundingRect(QRectF(), flags, _xAxis->baseLabel()).width() + _calculatedBottomLabelWidth/2 + xLabelRect.height()/2 > plotRect().width()/2) { 2718 height += bottomLabelMargin(); 2719 } 2720 if (bottomLabelMargin() < height) { 2721 xLabelRect.setHeight(xLabelRect.height() + (height - bottomLabelMargin())); 2722 } 2723 } 2724 2725 _calculatedAxisMarginHeight = xLabelRect.height(); 2726 _calculatedAxisMarginROverflow = 2*ViewItem::sizeOfGrip().width(); 2727 2728 painter->restore(); 2729 } 2730 2731 /** This function calculates and sets three things: 2732 _calculatedAxisMarginHLead: spacing between left of plotRect and right of axis labels 2733 _calculatedAxisMarginVOverflow: topmost axis number extension beyond plotRect 2734 _calculatedAxisMarginWidth: the width of the widest axis number 2735 */ 2736 void PlotItem::calculateLeftTickLabelBound(QPainter *painter) { 2737 QRectF yLabelRect; 2738 int flags = Qt::TextSingleLine | Qt::AlignCenter; 2739 2740 painter->save(); 2741 2742 painter->setFont(numberLabelDetails()->calculatedFont(*painter->device())); 2743 2744 _calculatedAxisMarginHLead = painter->fontMetrics().boundingRect('[').height()/2; 2745 2746 if (_yAxis->isAxisVisible()) { 2747 2748 QMapIterator<double, QString> yLabelIt(_yAxis->axisLabels()); 2749 while (yLabelIt.hasNext()) { 2750 yLabelIt.next(); 2751 2752 // a hacky heuristic to guess the right width of the widest number for very small scientific notation numbers. 2753 // 'label' is only used to find its width. This is not exact but seems to work. 2754 QString label = yLabelIt.value(); 2755 if (label.contains("e-")) { 2756 label.append('+'); 2757 } 2758 2759 QRectF bound = painter->boundingRect(QRectF(), flags, label); 2760 QPointF p(plotRect().left() - bound.width() / 2.0 - _calculatedAxisMarginHLead, mapYToPlot(yLabelIt.key())); 2761 bound.moveCenter(p); 2762 2763 int rotation = _yAxis->axisLabelRotation(); 2764 QTransform t; 2765 t.rotate(rotation); 2766 2767 if (rotation != 0) { 2768 bound.setWidth(t.mapRect(bound).width()); 2769 bound.setHeight(t.mapRect(bound).height()); 2770 } 2771 2772 if (yLabelRect.isValid()) { 2773 yLabelRect = yLabelRect.united(bound); 2774 } else { 2775 yLabelRect = bound; 2776 } 2777 } 2778 } 2779 2780 yLabelRect.setWidth(yLabelRect.width() + _calculatedAxisMarginHLead); 2781 _calculatedLeftBaseOffset = 0.0; 2782 if (!_yAxis->baseLabel().isEmpty()) { 2783 qreal height = painter->boundingRect(QRectF(), flags, _yAxis->baseLabel()).height(); 2784 if (painter->boundingRect(QRectF(), flags, _yAxis->baseLabel()).width() + _calculatedLeftLabelWidth/2 + yLabelRect.width()/2 > plotRect().height()/2) { 2785 height += leftLabelMargin(); 2786 _calculatedLeftBaseOffset = leftLabelMargin(); 2787 } 2788 if (leftLabelMargin() < height) { 2789 yLabelRect.setWidth(yLabelRect.width() + (height - leftLabelMargin())); 2790 } 2791 } 2792 _calculatedAxisMarginWidth = yLabelRect.width(); 2793 if (yLabelRect.top() < plotRect().top()) { 2794 _calculatedAxisMarginTOverflow = qMax(ViewItem::sizeOfGrip().width(), -yLabelRect.top() + plotRect().top()); 2795 } else { 2796 _calculatedAxisMarginTOverflow = ViewItem::sizeOfGrip().width(); 2797 } 2798 painter->restore(); 2799 } 2800 2801 2802 bool PlotItem::showLegend() const { 2803 return _showLegend; 2804 } 2805 2806 2807 LegendItem* PlotItem::legend() { 2808 if (!_legend) { 2809 _legend = new LegendItem(this); 2810 _legend->setVisible(false); 2811 double margin = 0.025*(plotRect().width() + plotRect().height()); 2812 _legend->setPos(plotRect().x() + margin, plotRect().y() + margin); 2813 _legend->updateRelativeSize(); 2814 } 2815 return _legend; 2816 } 2817 2818 2819 void PlotItem::setShowLegend(const bool show, const bool resetFonts) { 2820 if (show != _showLegend) { 2821 legend()->setVisible(show); 2822 _showLegend = show; 2823 if (show && resetFonts) { 2824 legend()->setFontScale(qMax(globalFontScale()*qreal(0.6), ApplicationSettings::self()->minimumFontSize())); 2825 } 2826 } 2827 } 2828 2829 2830 bool PlotItem::tryShortcut(const QString &keySequence) { 2831 return ViewItem::tryShortcut(keySequence); 2832 } 2833 2834 2835 void PlotItem::setProjectionRect(const QRectF &rect, bool forceAxisUpdate) { 2836 if (!(rect.isEmpty() || !rect.isValid())) { 2837 _projectionRect = rect; 2838 setPlotBordersDirty(true); 2839 emit updateAxes(); 2840 update(); //slow, but need to update everything... 2841 } else if (forceAxisUpdate) { 2842 setPlotBordersDirty(true); 2843 emit updateAxes(); 2844 update(); //slow, but need to update everything... 2845 } 2846 // Need to update data relative rect for all children. 2847 foreach (PlotRenderItem *render_item, renderItems()) { 2848 QList<QGraphicsItem*> children = render_item->childItems(); 2849 foreach(QGraphicsItem* child, children) { 2850 ViewItem* item = dynamic_cast<ViewItem*>(child); 2851 if (item && !item->lockPosToData()) { 2852 item->updateDataRelativeRect(); 2853 } else { 2854 item->applyDataLockedDimensions(); 2855 } 2856 } 2857 } 2858 } 2859 2860 2861 QRectF PlotItem::computedProjectionRect() { 2862 QRectF rect; 2863 foreach (PlotRenderItem *renderer, renderItems()) { 2864 if (!renderer->computedProjectionRect().isEmpty()) { 2865 if (rect.isValid()) { 2866 rect = rect.united(renderer->computedProjectionRect()); 2867 } else { 2868 rect = renderer->computedProjectionRect(); 2869 } 2870 } 2871 } 2872 2873 if (!rect.isValid()) 2874 rect = QRectF(QPointF(-0.1, -0.1), QPointF(0.1, 0.1)); //default 2875 2876 return rect; 2877 } 2878 2879 2880 void PlotItem::computedRelationalMax(double &minimum, double &maximum) { 2881 //QRectF rect; 2882 foreach (PlotRenderItem *renderer, renderItems()) { 2883 foreach (RelationPtr relation, renderer->relationList()) { 2884 if (relation->ignoreAutoScale()) 2885 continue; 2886 2887 double min, max; 2888 relation->yRange(projectionRect().left(), 2889 projectionRect().right(), 2890 &min, &max); 2891 2892 //If the axis is in log mode, the lower extent will be the 2893 //minimum value larger than zero. 2894 if (yAxis()->axisLog()) 2895 minimum = minimum <= 0.0 ? min : qMin(min, minimum); 2896 else 2897 minimum = qMin(min, minimum); 2898 2899 maximum = qMax(max, maximum); 2900 } 2901 } 2902 } 2903 2904 2905 void PlotItem::computeBorder(Qt::Orientation orientation, double &minimum, double &maximum) const { 2906 //QRectF rect; 2907 foreach (PlotRenderItem *renderer, renderItems()) { 2908 double min = maximum; 2909 double max = minimum; 2910 renderer->computeBorder(orientation, &min, &max); 2911 minimum = qMin(min, minimum); 2912 maximum = qMax(max, maximum); 2913 } 2914 } 2915 2916 2917 void PlotItem::resetSelectionRect() { 2918 foreach (PlotRenderItem *renderer, renderItems()) { 2919 renderer->resetSelectionRect(); 2920 } 2921 } 2922 2923 2924 void PlotItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { 2925 if (event->button() == Qt::LeftButton) { 2926 if (checkBox().contains(event->pos())) { 2927 setTiedZoom(!isTiedZoom(), !isTiedZoom()); 2928 ViewItem::mousePressEvent(event); 2929 } else { 2930 ViewItem::mousePressEvent(event); 2931 } 2932 } 2933 } 2934 2935 2936 void PlotItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) { 2937 if (event->button() == Qt::LeftButton && view()->viewMode() == View::Data) { 2938 PlotClickEditRegion region = CONTENT; 2939 if (event->pos().x() - rect().left() < leftLabelMargin()) { 2940 region = LABEL; 2941 } else if (event->pos().y() - rect().top()< topLabelMargin()) { 2942 region = LABEL; 2943 } else if (rect().right()-event->pos().x() < rightLabelMargin()) { 2944 region = LABEL; 2945 } else if (rect().bottom()-event->pos().y() < bottomLabelMargin()) { 2946 region = LABEL; 2947 } else if (rect().bottom()-event->pos().y() < bottomMarginSize()) { 2948 region = XAXIS; 2949 } else if (event->pos().x() - rect().left() < leftMarginSize()) { 2950 region = YAXIS; 2951 } 2952 edit(region); 2953 } else { 2954 ViewItem::mouseDoubleClickEvent(event); 2955 } 2956 } 2957 2958 2959 QPainterPath PlotItem::checkBox() const { 2960 if (!isInSharedAxisBox() || (sharedAxisBox() && sharedAxisBox()->isXAxisShared() && sharedAxisBox()->isYAxisShared())) { 2961 return ViewItem::checkBox(); 2962 } else { 2963 QRectF grip; 2964 if (sharedAxisBox()->isXAxisShared()) { 2965 grip = QRectF(QPointF(_calculatedPlotRect.topRight().x() + sizeOfGrip().width() * .25, _calculatedPlotRect.topRight().y() - sizeOfGrip().height() * -.25), sizeOfGrip()); 2966 } else if (sharedAxisBox()->isYAxisShared()) { 2967 grip = QRectF(QPointF(_calculatedPlotRect.topRight().x() - sizeOfGrip().width() * 1.25, _calculatedPlotRect.topRight().y() - sizeOfGrip().height() * 1.25), sizeOfGrip()); 2968 } 2969 QPainterPath path; 2970 path.addEllipse(grip); 2971 return path; 2972 } 2973 } 2974 2975 2976 QPainterPath PlotItem::tiedZoomCheck() const { 2977 if (!isInSharedAxisBox() || (sharedAxisBox() && sharedAxisBox()->isXAxisShared() && sharedAxisBox()->isYAxisShared())) { 2978 return ViewItem::tiedZoomCheck(); 2979 } else { 2980 QRectF grip; 2981 if (sharedAxisBox()->isXAxisShared()) { 2982 grip = QRectF(QPointF(_calculatedPlotRect.topRight().x() + sizeOfGrip().width() * .25, _calculatedPlotRect.topRight().y() - sizeOfGrip().height() * -.25), sizeOfGrip()); 2983 } else if (sharedAxisBox()->isYAxisShared()) { 2984 grip = QRectF(QPointF(_calculatedPlotRect.topRight().x() - sizeOfGrip().width() * 1.25, _calculatedPlotRect.topRight().y() - sizeOfGrip().height() * 1.25), sizeOfGrip()); 2985 } else { 2986 qDebug() << "warning: no grip set in PlotItem::tiedZoomCheck (bug?)"; 2987 } 2988 QPainterPath path; 2989 if (isXTiedZoom() && isYTiedZoom()) { 2990 path.addEllipse(grip); 2991 } else if (isXTiedZoom()) { 2992 path.moveTo(grip.center()); 2993 path.arcTo(grip, 225, 180); 2994 } else if (isYTiedZoom()) { 2995 path.moveTo(grip.center()); 2996 path.arcTo(grip, 45, 180); 2997 } 2998 return path; 2999 } 3000 } 3001 3002 3003 bool PlotItem::supportsTiedZoom() const { 3004 if (isInSharedAxisBox()) { 3005 if (sharedAxisBox() && sharedAxisBox()->isXAxisShared() && sharedAxisBox()->isYAxisShared() && 3006 sharedAxisBox()->keyPlot() == this) { 3007 return true; 3008 } 3009 } 3010 return ViewItem::supportsTiedZoom(); 3011 } 3012 3013 3014 void PlotItem::setAllowUpdates(bool allowed) { 3015 _allowUpdates = allowed; 3016 UpdateManager::self()->doUpdates(true); 3017 } 3018 3019 3020 void PlotItem::plotMaximize() { 3021 if (!_plotMaximized && view()->viewMode() != View::Data) { 3022 return; 3023 } 3024 3025 if (_plotMaximized) { 3026 double x_rescale; 3027 double y_rescale; 3028 3029 x_rescale = view()->sceneRect().width()/_plotMaximizedSourceParentRect.width(); 3030 y_rescale = view()->sceneRect().height()/_plotMaximizedSourceParentRect.height(); 3031 _plotMaximizedSourceRect.setWidth(_plotMaximizedSourceRect.width()*x_rescale); 3032 _plotMaximizedSourceRect.setHeight(_plotMaximizedSourceRect.height()*y_rescale); 3033 _plotMaximizedSourcePosition.setX(_plotMaximizedSourcePosition.x()*x_rescale); 3034 _plotMaximizedSourcePosition.setY(_plotMaximizedSourcePosition.y()*y_rescale); 3035 xAxis()->setAxisVisible(_plotMaximizedBottomVisible); 3036 yAxis()->setAxisVisible(_plotMaximizedLeftVisible); 3037 _leftLabelDetails->setVisible(_plotMaximizedLeftVisible); 3038 _bottomLabelDetails->setVisible(_plotMaximizedBottomVisible); 3039 _rightLabelDetails->setVisible(_plotMaximizedRightVisible); 3040 _topLabelDetails->setVisible(_plotMaximizedTopVisible); 3041 _plotMaximized = false; 3042 PlotItemManager::self()->removeFocusPlot(this); 3043 setParentViewItem(_plotMaximizedSourceParent); 3044 setPos(_plotMaximizedSourcePosition); 3045 setViewRect(_plotMaximizedSourceRect); 3046 setZValue(_plotMaximizedSourceZValue); 3047 view()->setChildMaximized(false); 3048 view()->setFontRescale(1.0); 3049 } else { 3050 _plotMaximizedBottomVisible = _bottomLabelDetails->isVisible(); 3051 xAxis()->setAxisVisible(true); 3052 _bottomLabelDetails->setVisible(true); 3053 _plotMaximizedLeftVisible = _leftLabelDetails->isVisible(); 3054 yAxis()->setAxisVisible(true); 3055 _leftLabelDetails->setVisible(true); 3056 _plotMaximizedRightVisible = _rightLabelDetails->isVisible(); 3057 _rightLabelDetails->setVisible(true); 3058 _plotMaximizedTopVisible = _topLabelDetails->isVisible(); 3059 _topLabelDetails->setVisible(true); 3060 _plotMaximized = true; 3061 _plotMaximizedSourcePosition = pos(); 3062 _plotMaximizedSourceRect = viewRect(); 3063 _plotMaximizedSourceZValue = zValue(); 3064 _plotMaximizedSourceParent = parentViewItem(); 3065 _plotMaximizedSourceParentRect = view()->sceneRect(); 3066 3067 setParentViewItem(0); 3068 setPos(0, 0); 3069 setViewRect(view()->sceneRect()); 3070 setZValue(PLOT_MAXIMIZED_ZORDER); 3071 PlotItemManager::self()->setFocusPlot(this); 3072 3073 double rescale = double(view()->sceneRect().width() + 3074 view()->sceneRect().height())/ 3075 double(_plotMaximizedSourceRect.width() + _plotMaximizedSourceRect.height()); 3076 view()->setChildMaximized(true); 3077 view()->setFontRescale(rescale); 3078 } 3079 if (isInSharedAxisBox()) { 3080 view()->setPlotBordersDirty(true); 3081 } 3082 setPlotBordersDirty(); 3083 } 3084 3085 3086 void PlotItem::zoomFixedExpression(const QRectF &projection, bool force) { 3087 if (projection.isValid()) { 3088 if (isInSharedAxisBox()) { 3089 ZoomCommand *cmd = new ZoomFixedExpressionCommand(this, projection, force); 3090 _undoStack->push(cmd); 3091 // cmd->redo(); 3092 if (!force) { 3093 sharedAxisBox()->zoomFixedExpression(projection, this); 3094 } else { 3095 yAxis()->setAxisZoomMode(PlotAxis::FixedExpression); 3096 xAxis()->setAxisZoomMode(PlotAxis::FixedExpression); 3097 setProjectionRect(QRectF(projection.x(), projection.y(), projection.width(), projection.height())); 3098 } 3099 } else { 3100 ZoomCommand *cmd = new ZoomFixedExpressionCommand(this, projection, force); 3101 _undoStack->push(cmd); 3102 // cmd->redo(); 3103 } 3104 } 3105 } 3106 3107 3108 void PlotItem::zoomXRange(const QRectF &projection, bool force) { 3109 if (projection.isValid()) { 3110 if (isInSharedAxisBox()) { 3111 if (!force) { 3112 sharedAxisBox()->zoomXRange(projection, this); 3113 } else { 3114 xAxis()->setAxisZoomMode(PlotAxis::FixedExpression); 3115 setProjectionRect(QRectF(projection.x(), projectionRect().y(), projection.width(), projectionRect().height())); 3116 } 3117 } else { 3118 ZoomCommand *cmd = new ZoomXRangeCommand(this, projection, force); 3119 _undoStack->push(cmd); 3120 // cmd->redo(); 3121 } 3122 } 3123 } 3124 3125 3126 void PlotItem::zoomYRange(const QRectF &projection, bool force) { 3127 if (projection.isValid()) { 3128 if (isInSharedAxisBox()) { 3129 if (!force) { 3130 sharedAxisBox()->zoomYRange(projection, this); 3131 } else { 3132 yAxis()->setAxisZoomMode(PlotAxis::FixedExpression); 3133 setProjectionRect(QRectF(projectionRect().x(), projection.y(), projectionRect().width(), projection.height())); 3134 } 3135 } else { 3136 ZoomCommand *cmd = new ZoomYRangeCommand(this, projection, force); 3137 _undoStack->push(cmd); 3138 // cmd->redo(); 3139 } 3140 } 3141 } 3142 3143 3144 void PlotItem::zoomMaximum(bool force) { 3145 if (isInSharedAxisBox() && (!force)) { 3146 sharedAxisBox()->zoomMaximum(this); 3147 } else { 3148 ZoomCommand *cmd = new ZoomMaximumCommand(this, force); 3149 _undoStack->push(cmd); 3150 //cmd->redo(); 3151 } 3152 } 3153 3154 void PlotItem::adjustImageColorScale() { 3155 const double per[] = {0.0, 0.0001, 0.001, 0.005, 0.02, 0.1}; 3156 const int length = sizeof(per) / sizeof(double); 3157 3158 if (++_i_per >= length) { 3159 _i_per = 0; 3160 } 3161 foreach (PlotRenderItem *renderer, renderItems()) { 3162 foreach (RelationPtr relation, renderer->relationList()) { 3163 if (ImagePtr image = kst_cast<Image>(relation)) { 3164 image->writeLock(); 3165 image->setThresholdToSpikeInsensitive(per[_i_per]); 3166 image->registerChange(); 3167 image->unlock(); 3168 } 3169 } 3170 } 3171 UpdateManager::self()->doUpdates(true); 3172 } 3173 3174 void PlotItem::zoomMaxSpikeInsensitive(bool force) { 3175 if (isInSharedAxisBox() && !force) { 3176 sharedAxisBox()->zoomMaxSpikeInsensitive(this); 3177 } else { 3178 ZoomCommand *cmd = new ZoomMaxSpikeInsensitiveCommand(this, force); 3179 _undoStack->push(cmd); 3180 //cmd->redo(); 3181 } 3182 } 3183 3184 3185 void PlotItem::zoomPrevious() { 3186 if (!isInSharedAxisBox()) { 3187 if (_undoStack->canUndo()) { 3188 QAction *undoAction = _undoStack->createUndoAction(this); 3189 if (undoAction) { 3190 undoAction->activate(QAction::Trigger); 3191 } 3192 } 3193 } 3194 } 3195 3196 3197 void PlotItem::zoomTied() { 3198 setTiedZoom(!isTiedZoom(), !isTiedZoom()); 3199 } 3200 3201 3202 void PlotItem::zoomXTied() { 3203 setTiedZoom(!isXTiedZoom(), isYTiedZoom()); 3204 } 3205 3206 3207 void PlotItem::zoomYTied() { 3208 setTiedZoom(isXTiedZoom(), !isYTiedZoom()); 3209 } 3210 3211 3212 void PlotItem::zoomMeanCentered(bool force) { 3213 if (isInSharedAxisBox() && !force) { 3214 sharedAxisBox()->zoomMeanCentered(this); 3215 } else { 3216 ZoomCommand *cmd = new ZoomMeanCenteredCommand(this, force); 3217 _undoStack->push(cmd); 3218 // cmd->redo(); 3219 } 3220 } 3221 3222 3223 void PlotItem::zoomYMeanCentered(qreal dY, bool force) { 3224 if (isInSharedAxisBox() && !force) { 3225 sharedAxisBox()->zoomYMeanCentered(dY, this); 3226 } else { 3227 ZoomCommand *cmd = new ZoomYMeanCenteredCommand(this, dY, force); 3228 _undoStack->push(cmd); 3229 // cmd->redo(); 3230 } 3231 } 3232 3233 3234 void PlotItem::zoomXMeanCentered(qreal dX, bool force) { 3235 if (isInSharedAxisBox() && !force) { 3236 sharedAxisBox()->zoomXMeanCentered(this); 3237 } else { 3238 ZoomCommand *cmd = new ZoomXMeanCenteredCommand(this, dX, force); 3239 _undoStack->push(cmd); 3240 // cmd->redo(); 3241 } 3242 } 3243 3244 3245 void PlotItem::zoomXMaximum(bool force) { 3246 if (isInSharedAxisBox() && !force) { 3247 sharedAxisBox()->zoomXMaximum(this); 3248 } else { 3249 ZoomCommand *cmd = new ZoomXMaximumCommand(this, force); 3250 _undoStack->push(cmd); 3251 // cmd->redo(); 3252 } 3253 } 3254 3255 3256 void PlotItem::zoomXNoSpike(bool force) { 3257 if (isInSharedAxisBox() && !force) { 3258 sharedAxisBox()->zoomXNoSpike(this); 3259 } else { 3260 ZoomCommand *cmd = new ZoomXNoSpikeCommand(this, force); 3261 _undoStack->push(cmd); 3262 // cmd->redo(); 3263 } 3264 } 3265 3266 3267 void PlotItem::zoomXAutoBorder(bool force) { 3268 if (isInSharedAxisBox() && !force) { 3269 sharedAxisBox()->zoomXAutoBorder(this); 3270 } else { 3271 ZoomCommand *cmd = new ZoomXAutoBorderCommand(this, force); 3272 _undoStack->push(cmd); 3273 // cmd->redo(); 3274 } 3275 } 3276 3277 3278 void PlotItem::zoomXRight(bool force, bool scroll_far) { 3279 if (isInSharedAxisBox() && !force) { 3280 sharedAxisBox()->zoomXRight(this, scroll_far); 3281 } else { 3282 ZoomCommand *cmd; 3283 if (scroll_far) { 3284 cmd = new ZoomXFarRightCommand(this, force); 3285 } else { 3286 cmd = new ZoomXRightCommand(this, force); 3287 } 3288 _undoStack->push(cmd); 3289 //cmd->redo(); 3290 } 3291 } 3292 3293 3294 void PlotItem::zoomXLeft(bool force, bool scroll_far) { 3295 if (isInSharedAxisBox() && !force) { 3296 sharedAxisBox()->zoomXLeft(this, scroll_far); 3297 } else { 3298 ZoomCommand *cmd; 3299 if (scroll_far) { 3300 cmd = new ZoomXFarLeftCommand(this, force); 3301 } else { 3302 cmd = new ZoomXLeftCommand(this, force); 3303 } 3304 _undoStack->push(cmd); 3305 //cmd->redo(); 3306 } 3307 } 3308 3309 3310 void PlotItem::zoomXFarRight(bool force) { 3311 zoomXRight(force, true); 3312 } 3313 3314 void PlotItem::zoomXFarLeft(bool force) { 3315 zoomXLeft(force, true); 3316 } 3317 3318 void PlotItem::zoomXOut(bool force) { 3319 resetSelectionRect(); 3320 if (isInSharedAxisBox() && !force) { 3321 sharedAxisBox()->zoomXOut(this); 3322 } else { 3323 ZoomCommand *cmd = new ZoomXOutCommand(this, force); 3324 _undoStack->push(cmd); 3325 // cmd->redo(); 3326 } 3327 } 3328 3329 3330 void PlotItem::zoomXIn(bool force) { 3331 resetSelectionRect(); 3332 if (isInSharedAxisBox() && !force) { 3333 sharedAxisBox()->zoomXIn(this); 3334 } else { 3335 ZoomCommand *cmd = new ZoomXInCommand(this, force); 3336 _undoStack->push(cmd); 3337 // cmd->redo(); 3338 } 3339 } 3340 3341 3342 void PlotItem::zoomNormalizeXtoY(bool force) { 3343 if (xAxis()->axisLog() || yAxis()->axisLog()) 3344 return; //FIXME: if both are log, this could be supported 3345 3346 if (isInSharedAxisBox() && !force) { 3347 sharedAxisBox()->zoomNormalizeXtoY(this); 3348 } else { 3349 ZoomCommand *cmd = new ZoomNormalizeXToYCommand(this, force); 3350 _undoStack->push(cmd); 3351 // cmd->redo(); 3352 } 3353 } 3354 3355 3356 void PlotItem::zoomLogX(bool force, bool autoLog, bool enableLog) { 3357 if (isInSharedAxisBox() && !force) { 3358 sharedAxisBox()->zoomLogX(this); 3359 } else { 3360 bool log = enableLog; 3361 if (autoLog) { 3362 log = !xAxis()->axisLog(); 3363 } 3364 ZoomCommand *cmd = new ZoomXLogCommand(this, log, force); 3365 _undoStack->push(cmd); 3366 // cmd->redo(); 3367 } 3368 } 3369 3370 3371 void PlotItem::zoomYLocalMaximum(bool force) { 3372 if (isInSharedAxisBox() && !force) { 3373 sharedAxisBox()->zoomYLocalMaximum(this); 3374 } else { 3375 ZoomCommand *cmd = new ZoomYLocalMaximumCommand(this, force); 3376 _undoStack->push(cmd); 3377 // cmd->redo(); 3378 } 3379 } 3380 3381 3382 void PlotItem::zoomYMaximum(bool force) { 3383 if (isInSharedAxisBox() && !force) { 3384 sharedAxisBox()->zoomYMaximum(this); 3385 } else { 3386 ZoomCommand *cmd = new ZoomYMaximumCommand(this, force); 3387 _undoStack->push(cmd); 3388 // cmd->redo(); 3389 } 3390 } 3391 3392 3393 void PlotItem::zoomYNoSpike(bool force) { 3394 if (isInSharedAxisBox() && !force) { 3395 sharedAxisBox()->zoomYNoSpike(this); 3396 } else { 3397 ZoomCommand *cmd = new ZoomYNoSpikeCommand(this, force); 3398 _undoStack->push(cmd); 3399 // cmd->redo(); 3400 } 3401 } 3402 3403 3404 void PlotItem::zoomYAutoBorder(bool force) { 3405 if (isInSharedAxisBox() && !force) { 3406 sharedAxisBox()->zoomYAutoBorder(this); 3407 } else { 3408 ZoomCommand *cmd = new ZoomYAutoBorderCommand(this, force); 3409 _undoStack->push(cmd); 3410 // cmd->redo(); 3411 } 3412 } 3413 3414 3415 void PlotItem::zoomYUp(bool force) { 3416 if (isInSharedAxisBox() && !force) { 3417 sharedAxisBox()->zoomYUp(this); 3418 } else { 3419 ZoomCommand *cmd = new ZoomYUpCommand(this, force); 3420 _undoStack->push(cmd); 3421 // cmd->redo(); 3422 } 3423 } 3424 3425 3426 void PlotItem::zoomYDown(bool force) { 3427 if (isInSharedAxisBox() && !force) { 3428 sharedAxisBox()->zoomYDown(this); 3429 } else { 3430 ZoomCommand *cmd = new ZoomYDownCommand(this, force); 3431 _undoStack->push(cmd); 3432 //cmd->redo(); 3433 } 3434 } 3435 3436 3437 void PlotItem::zoomYOut(bool force) { 3438 resetSelectionRect(); 3439 if (isInSharedAxisBox() && !force) { 3440 sharedAxisBox()->zoomYOut(this); 3441 } else { 3442 ZoomCommand *cmd = new ZoomYOutCommand(this, force); 3443 _undoStack->push(cmd); 3444 // cmd->redo(); 3445 } 3446 } 3447 3448 3449 void PlotItem::zoomYIn(bool force) { 3450 resetSelectionRect(); 3451 if (isInSharedAxisBox() && !force) { 3452 sharedAxisBox()->zoomYIn(this); 3453 } else { 3454 ZoomCommand *cmd = new ZoomYInCommand(this, force); 3455 _undoStack->push(cmd); 3456 // cmd->redo(); 3457 } 3458 } 3459 3460 3461 void PlotItem::zoomNormalizeYtoX(bool force) { 3462 if (xAxis()->axisLog() || yAxis()->axisLog()) 3463 return; //apparently we don't want to do anything here according to kst2dplot... 3464 3465 if (isInSharedAxisBox() && !force) { 3466 sharedAxisBox()->zoomNormalizeYtoX(this); 3467 } else { 3468 ZoomCommand *cmd = new ZoomNormalizeYToXCommand(this, force); 3469 _undoStack->push(cmd); 3470 // cmd->redo(); 3471 } 3472 } 3473 3474 3475 void PlotItem::zoomLogY(bool force, bool autoLog, bool enableLog) { 3476 if (isInSharedAxisBox() && !force) { 3477 sharedAxisBox()->zoomLogY(this); 3478 } else { 3479 bool log = enableLog; 3480 if (autoLog) { 3481 log = !yAxis()->axisLog(); 3482 } 3483 ZoomCommand *cmd = new ZoomYLogCommand(this, log, force); 3484 _undoStack->push(cmd); 3485 // cmd->redo(); 3486 } 3487 } 3488 3489 void PlotItem::zoomOut(bool force) { 3490 zoomYOut(force); 3491 zoomXOut(force); 3492 } 3493 3494 void PlotItem::zoomIn(bool force) { 3495 zoomYIn(force); 3496 zoomXIn(force); 3497 } 3498 3499 void PlotItem::copyStatus() { 3500 kstApp->clipboard()->setText(kstApp->mainWindow()->statusMessage()); 3501 kstApp->mainWindow()->setStatusMessage(tr("Info copied to clipboard: ") + kstApp->mainWindow()->statusMessage()); 3502 } 3503 3504 void PlotItem::copyXCoord() { 3505 QString valueString = QString::number(renderItem()->statusMessagePoint.x(), 'g', 12); 3506 kstApp->clipboard()->setText(valueString); 3507 kstApp->mainWindow()->setStatusMessage(tr("X coordinate copied to clipboard: ") + valueString); 3508 } 3509 3510 void PlotItem::copyYCoord() { 3511 QString valueString = QString::number(renderItem()->statusMessagePoint.y(), 'g', 12); 3512 kstApp->clipboard()->setText(valueString); 3513 kstApp->mainWindow()->setStatusMessage(tr("Y coordinate copied to clipboard: ") + valueString); 3514 } 3515 3516 QString PlotItem::descriptionTip() const { 3517 QString contents; 3518 foreach (PlotRenderItem *renderer, renderItems()) { 3519 foreach (RelationPtr relation, renderer->relationList()) { 3520 contents += QString(" %1\n").arg(relation->Name()); 3521 } 3522 } 3523 3524 return tr("Plot: %1 \nContents:\n %2").arg(Name()).arg(contents); 3525 } 3526 3527 3528 QString PlotItem::_automaticDescriptiveName() const { 3529 QString name = tr("Empty Plot"); 3530 int n=0; 3531 foreach (PlotRenderItem *renderer, renderItems()) { 3532 foreach (RelationPtr relation, renderer->relationList()) { 3533 if (n==0) { 3534 name = relation->descriptiveName(); 3535 } 3536 n++; 3537 } 3538 } 3539 if (n>1) { 3540 name += ", ..."; 3541 } 3542 return name; 3543 } 3544 3545 3546 ZoomState PlotItem::currentZoomState() { 3547 ZoomState zoomState; 3548 zoomState.item = this; //the origin of this ZoomState 3549 zoomState.projectionRect = projectionRect(); 3550 zoomState.xAxisZoomMode = xAxis()->axisZoomMode(); 3551 zoomState.yAxisZoomMode = yAxis()->axisZoomMode(); 3552 zoomState.isXAxisLog = xAxis()->axisLog(); 3553 zoomState.isYAxisLog = yAxis()->axisLog(); 3554 return zoomState; 3555 } 3556 3557 3558 void PlotItem::setCurrentZoomState(ZoomState zoomState) { 3559 _xAxis->setAxisZoomMode(PlotAxis::ZoomMode(zoomState.xAxisZoomMode)); 3560 _yAxis->setAxisZoomMode(PlotAxis::ZoomMode(zoomState.yAxisZoomMode)); 3561 _xAxis->setAxisLog(zoomState.isXAxisLog); 3562 _yAxis->setAxisLog(zoomState.isYAxisLog); 3563 setProjectionRect(zoomState.projectionRect); 3564 } 3565 3566 3567 void PlotItem::updateChildGeometry(const QRectF &oldParentRect, const QRectF &newParentRect) { 3568 ViewItem::updateChildGeometry(oldParentRect, newParentRect); 3569 setPlotBordersDirty(true); 3570 setLabelsDirty(); 3571 setAxisLabelsDirty(); 3572 setPlotPixmapDirty(); 3573 } 3574 3575 void PlotItem::saveAsDialogDefaults() const { 3576 dialogDefaults().setValue(defaultsGroupName()+"/globalFontFamily", QVariant(globalFont()).toString()); 3577 dialogDefaults().setValue(defaultsGroupName()+"/globalFontScale",globalFontScale()); 3578 dialogDefaults().setValue(defaultsGroupName()+"/globalFontColor", QVariant(globalFontColor()).toString()); 3579 3580 leftLabelDetails()->saveAsDialogDefaults(QString(defaultsGroupName()+"/leftFont")); 3581 rightLabelDetails()->saveAsDialogDefaults(QString(defaultsGroupName()+"/rightFont")); 3582 topLabelDetails()->saveAsDialogDefaults(QString(defaultsGroupName()+"/topFont")); 3583 bottomLabelDetails()->saveAsDialogDefaults(QString(defaultsGroupName()+"/bottomFont")); 3584 numberLabelDetails()->saveAsDialogDefaults(QString(defaultsGroupName()+"/numberFont")); 3585 3586 _xAxis->saveAsDialogDefaults(defaultsGroupName()+"/xAxis"); 3587 _yAxis->saveAsDialogDefaults(defaultsGroupName()+"/yAxis"); 3588 } 3589 3590 void PlotItem::saveDialogDefaultsFont(QFont F, QColor C) { 3591 dialogDefaults().setValue(staticDefaultsGroupName()+"/globalFontFamily", QVariant(F).toString()); 3592 dialogDefaults().setValue(staticDefaultsGroupName()+"/globalFontScale",F.pointSize()); 3593 dialogDefaults().setValue(staticDefaultsGroupName()+"/globalFontColor", QVariant(C).toString()); 3594 3595 PlotLabel::saveDialogDefaults(staticDefaultsGroupName()+"/leftFont", F, C, true); 3596 PlotLabel::saveDialogDefaults(staticDefaultsGroupName()+"/rightFont", F, C, true); 3597 PlotLabel::saveDialogDefaults(staticDefaultsGroupName()+"/topFont", F, C, true); 3598 PlotLabel::saveDialogDefaults(staticDefaultsGroupName()+"/bottomFont", F, C, true); 3599 PlotLabel::saveDialogDefaults(staticDefaultsGroupName()+"/numberFont", F, C, true); 3600 } 3601 3602 void PlotItem::setFont(const QFont &f, const QColor &c) { 3603 leftLabelDetails()->setFontUseGlobal(true); 3604 rightLabelDetails()->setFontUseGlobal(true); 3605 topLabelDetails()->setFontUseGlobal(true); 3606 bottomLabelDetails()->setFontUseGlobal(true); 3607 numberLabelDetails()->setFontUseGlobal(true); 3608 setGlobalFontColor(c); 3609 setGlobalFont(f); 3610 setGlobalFontScale(f.pointSize()); 3611 leftLabelDetails()->setFontColor(c); 3612 rightLabelDetails()->setFontColor(c); 3613 topLabelDetails()->setFontColor(c); 3614 bottomLabelDetails()->setFontColor(c); 3615 numberLabelDetails()->setFontColor(c); 3616 } 3617 3618 3619 PlotLabel::PlotLabel(PlotItem *plotItem) : QObject(), 3620 _plotItem(plotItem), 3621 _visible(true), 3622 _fontScale(12), 3623 _fontUseGlobal(true), 3624 _isAuto(true) { 3625 3626 } 3627 3628 3629 void PlotLabel::setDetails(const QString &label, bool is_auto, 3630 const bool use_global, const QFont &font, 3631 const qreal scale, const QColor &color) { 3632 if ((label != _text) || (_isAuto != is_auto) || 3633 (use_global != _fontUseGlobal) || 3634 (font != _font) || 3635 (scale != _fontScale) || 3636 (color != _fontColor)) { 3637 _text = label; 3638 _isAuto = is_auto; 3639 _fontUseGlobal = use_global; 3640 _font = font; 3641 _fontScale = scale; 3642 _fontColor = color; 3643 emit labelChanged(); 3644 } 3645 } 3646 3647 3648 QFont PlotLabel::calculatedFont(const QPaintDevice &p) { 3649 QFont tempFont; 3650 if (fontUseGlobal()) { 3651 tempFont = _plotItem->globalFont(); 3652 tempFont.setPointSizeF(_plotItem->view()->scaledFontSize(_plotItem->globalFontScale(),p)); 3653 } else { 3654 tempFont = font(); 3655 tempFont.setPointSizeF(_plotItem->view()->scaledFontSize(fontScale(),p)); 3656 } 3657 return tempFont; 3658 } 3659 3660 3661 bool PlotLabel::isVisible() const { 3662 return _visible; 3663 } 3664 3665 3666 void PlotLabel::setVisible(bool visible) { 3667 if (_visible == visible) 3668 return; 3669 3670 _visible = visible; 3671 emit labelChanged(); 3672 } 3673 3674 3675 bool PlotLabel::fontUseGlobal() const { 3676 return _fontUseGlobal; 3677 } 3678 3679 3680 void PlotLabel::setFontUseGlobal(const bool use_global) { 3681 if (_fontUseGlobal == use_global) 3682 return; 3683 3684 _fontUseGlobal = use_global; 3685 emit labelChanged(); 3686 } 3687 3688 3689 QString PlotLabel::text() const { 3690 return _text; 3691 } 3692 3693 3694 void PlotLabel::setText(const QString &label) { 3695 if (label == _text) { 3696 return; 3697 } 3698 _text = label; 3699 emit labelChanged(); 3700 } 3701 3702 qreal PlotLabel::fontScale() const { 3703 return _fontScale; 3704 } 3705 3706 3707 void PlotLabel::setFontScale(const qreal scale) { 3708 if (scale != _fontScale) { 3709 _fontScale = scale; 3710 emit labelChanged(); 3711 } 3712 } 3713 3714 3715 QFont PlotLabel::font() const { 3716 return _font; 3717 } 3718 3719 3720 void PlotLabel::setFont(const QFont &font) { 3721 if (font != _font) { 3722 _font = font; 3723 emit labelChanged(); 3724 } 3725 } 3726 3727 3728 QColor PlotLabel::fontColor() const { 3729 return _fontColor; 3730 } 3731 3732 3733 void PlotLabel::setFontColor(const QColor &color) { 3734 if (color != _fontColor) { 3735 _fontColor = color; 3736 emit labelChanged(); 3737 } 3738 } 3739 3740 3741 void PlotLabel::saveInPlot(QXmlStreamWriter &xml, QString labelId) { 3742 xml.writeStartElement("plotlabel"); 3743 xml.writeAttribute("id", labelId); 3744 xml.writeAttribute("visible", QVariant(_visible).toString()); 3745 xml.writeAttribute("overridetext", _text); 3746 xml.writeAttribute("autolabel", QVariant(_isAuto).toString()); 3747 xml.writeAttribute("font", QVariant(_font).toString()); 3748 xml.writeAttribute("fontscale", QVariant(_fontScale).toString()); 3749 xml.writeAttribute("fontcolor", QVariant(_fontColor).toString()); 3750 xml.writeAttribute("fontuseglobal", QVariant(_fontUseGlobal).toString()); 3751 xml.writeEndElement(); 3752 } 3753 3754 3755 bool PlotLabel::configureFromXml(QXmlStreamReader &xml, ObjectStore *store) { 3756 Q_UNUSED(store); 3757 bool validTag = true; 3758 3759 QString primaryTag = xml.name().toString(); 3760 QXmlStreamAttributes attrs = xml.attributes(); 3761 QStringRef av = attrs.value("visible"); 3762 if (!av.isNull()) { 3763 setVisible(QVariant(av.toString()).toBool()); 3764 } 3765 av = attrs.value("overridetext"); 3766 if (!av.isNull()) { 3767 setText(av.toString()); 3768 } 3769 av = attrs.value("autolabel"); 3770 if (!av.isNull()) { 3771 setIsAuto(QVariant(av.toString()).toBool()); 3772 } 3773 av = attrs.value("fontuseglobal"); 3774 if (!av.isNull()) { 3775 setFontUseGlobal(QVariant(av.toString()).toBool()); 3776 } 3777 av = attrs.value("font"); 3778 if (!av.isNull()) { 3779 QFont font; 3780 font.fromString(av.toString()); 3781 setFont(font); 3782 } 3783 av = attrs.value("fontcolor"); 3784 if (!av.isNull()) { 3785 setFontColor(QColor(av.toString())); 3786 } 3787 av = attrs.value("fontscale"); 3788 if (!av.isNull()) { 3789 setFontScale(QVariant(av.toString()).toDouble()); 3790 } 3791 3792 QString expectedEnd; 3793 while (!(xml.isEndElement() && (xml.name().toString() == primaryTag))) { 3794 if (xml.isEndElement()) { 3795 if (xml.name().toString() != expectedEnd) { 3796 validTag = false; 3797 break; 3798 } 3799 } 3800 xml.readNext(); 3801 } 3802 3803 return validTag; 3804 } 3805 3806 void PlotLabel::saveAsDialogDefaults(const QString &group) const { 3807 QFont F = font(); 3808 F.setPointSize(fontScale()); 3809 PlotLabel::saveDialogDefaults(group, F, fontColor(), fontUseGlobal()); 3810 } 3811 3812 void PlotLabel::saveDialogDefaults(const QString &group, const QFont &F, const QColor &C, bool U) { 3813 dialogDefaults().setValue(group+QString("Global"), U); 3814 dialogDefaults().setValue(group+QString("Family"), QVariant(F).toString()); 3815 dialogDefaults().setValue(group+QString("Scale"), F.pointSize()); 3816 dialogDefaults().setValue(group+QString("Color"), QVariant(C).toString()); 3817 } 3818 3819 void CreatePlotCommand::createItem() { 3820 _item = new PlotItem(_view); 3821 _view->setCursor(Qt::CrossCursor); 3822 3823 CreateCommand::createItem(); 3824 } 3825 3826 3827 void CreatePlotForCurve::createItem() { 3828 _item = new PlotItem(_view); 3829 creationComplete(); //add to undo stack 3830 } 3831 3832 3833 PlotItemFactory::PlotItemFactory() 3834 : GraphicsFactory() { 3835 registerFactory("plot", this); 3836 } 3837 3838 3839 PlotItemFactory::~PlotItemFactory() { 3840 } 3841 3842 ViewItem* PlotItemFactory::generateGraphics(QXmlStreamReader& xml, ObjectStore *store, View *view, ViewItem *parent) { 3843 PlotItem *rc = 0; 3844 double x = 0, y = 0, w = 10, h = 10; 3845 bool xTiedZoom = false, yTiedZoom = false; 3846 while (!xml.atEnd()) { 3847 bool validTag = true; 3848 if (xml.isStartElement()) { 3849 if (!rc && xml.name().toString() == "plot") { 3850 Q_ASSERT(!rc); 3851 3852 QXmlStreamAttributes attrs = xml.attributes(); 3853 QStringRef av; 3854 3855 Object::processShortNameIndexAttributes(attrs); 3856 3857 rc = new PlotItem(view); 3858 if (parent) { 3859 rc->setParentViewItem(parent); 3860 } 3861 3862 av = attrs.value("tiedxzoom"); 3863 if (!av.isNull()) { 3864 xTiedZoom = QVariant(av.toString()).toBool(); 3865 } 3866 av = attrs.value("tiedyzoom"); 3867 if (!av.isNull()) { 3868 yTiedZoom = QVariant(av.toString()).toBool(); 3869 } 3870 av = attrs.value("leftlabelvisible"); 3871 if (!av.isNull()) { 3872 rc->leftLabelDetails()->setVisible(QVariant(av.toString()).toBool()); 3873 } 3874 av = attrs.value("bottomlabelvisible"); 3875 if (!av.isNull()) { 3876 rc->bottomLabelDetails()->setVisible(QVariant(av.toString()).toBool()); 3877 } 3878 av = attrs.value("rightlabelvisible"); 3879 if (!av.isNull()) { 3880 rc->rightLabelDetails()->setVisible(QVariant(av.toString()).toBool()); 3881 } 3882 av = attrs.value("toplabelvisible"); 3883 if (!av.isNull()) { 3884 rc->topLabelDetails()->setVisible(QVariant(av.toString()).toBool()); 3885 } 3886 av = attrs.value("globalfont"); 3887 if (!av.isNull()) { 3888 QFont font; 3889 font.fromString(av.toString()); 3890 rc->setGlobalFont(font); 3891 } 3892 double fontscale = 0.0; 3893 av = attrs.value("globalfontscale"); 3894 if (!av.isNull()) { 3895 fontscale = QVariant(av.toString()).toDouble(); 3896 } 3897 if (fontscale < 0.1) { 3898 fontscale = 14.0; 3899 } 3900 rc->setGlobalFontScale(fontscale); 3901 av = attrs.value("globalfontcolor"); 3902 if (!av.isNull()) { 3903 rc->setGlobalFontColor(QColor(av.toString())); 3904 } 3905 av = attrs.value("showlegend"); 3906 if (!av.isNull()) { 3907 rc->setShowLegend(QVariant(av.toString()).toBool()); 3908 } 3909 3910 av = attrs.value("hidebottomaxislabel"); 3911 if (!av.isNull()) { 3912 rc->setManuallyHideBottomAxisLabel(QVariant(av.toString()).toBool()); 3913 } 3914 3915 av = attrs.value("hidetopaxislabel"); 3916 if (!av.isNull()) { 3917 rc->setManuallyHideTopAxisLabel(QVariant(av.toString()).toBool()); 3918 } 3919 3920 av = attrs.value("hideleftaxislabel"); 3921 if (!av.isNull()) { 3922 rc->setManuallyHideLeftAxisLabel(QVariant(av.toString()).toBool()); 3923 } 3924 3925 av = attrs.value("hiderightaxislabel"); 3926 if (!av.isNull()) { 3927 rc->setManuallyHideRightAxisLabel(QVariant(av.toString()).toBool()); 3928 } 3929 3930 av = attrs.value("numberaxislabelscale"); 3931 if (!av.isNull()) { 3932 rc->setUseAxisScale(QVariant(av.toString()).toBool()); 3933 } 3934 3935 if (attrs.value("descriptiveNameIsManual").toString() == "true") { 3936 rc->setDescriptiveName(attrs.value("descriptiveName").toString()); 3937 } 3938 3939 // Add any new specialized PlotItem Properties here. 3940 } else if (xml.name().toString() == "projectionrect") { 3941 QXmlStreamAttributes attrs = xml.attributes(); 3942 QStringRef av; 3943 av = attrs.value("width"); 3944 if (!av.isNull()) { 3945 w = av.toString().toDouble(); 3946 } 3947 av = attrs.value("height"); 3948 if (!av.isNull()) { 3949 h = av.toString().toDouble(); 3950 } 3951 av = attrs.value("x"); 3952 if (!av.isNull()) { 3953 x = av.toString().toDouble(); 3954 } 3955 av = attrs.value("y"); 3956 if (!av.isNull()) { 3957 y = av.toString().toDouble(); 3958 } 3959 xml.readNext(); 3960 } else if (xml.name().toString() == "plotaxis") { 3961 Q_ASSERT(rc); 3962 QXmlStreamAttributes subattrs = xml.attributes(); 3963 QStringRef av = subattrs.value("id"); 3964 if (!av.isNull()) { 3965 if (av == "xaxis") { 3966 rc->xAxis()->configureFromXml(xml, store); 3967 } else if (av == "yaxis") { 3968 rc->yAxis()->configureFromXml(xml, store); 3969 } 3970 } 3971 xml.readNext(); 3972 } else if (xml.name().toString() == "plotlabel") { 3973 Q_ASSERT(rc); 3974 QXmlStreamAttributes subattrs = xml.attributes(); 3975 QStringRef av = subattrs.value("id"); 3976 if (!av.isNull()) { 3977 if (av == "leftlabel") { 3978 rc->leftLabelDetails()->configureFromXml(xml, store); 3979 } else if (av == "rightlabel") { 3980 rc->rightLabelDetails()->configureFromXml(xml, store); 3981 } else if (av == "toplabel") { 3982 rc->topLabelDetails()->configureFromXml(xml, store); 3983 } else if (av == "bottomlabel") { 3984 rc->bottomLabelDetails()->configureFromXml(xml, store); 3985 } else if (av == "numberlabel") { 3986 rc->numberLabelDetails()->configureFromXml(xml, store); } 3987 } 3988 xml.readNext(); 3989 } else if (xml.name().toString() == "cartesianrender") { 3990 Q_ASSERT(rc); 3991 PlotRenderItem * renderItem = rc->renderItem(PlotRenderItem::Cartesian); 3992 if (renderItem) { 3993 validTag = renderItem->configureFromXml(xml, store); 3994 } 3995 } else if (xml.name().toString() == "legend") { 3996 Q_ASSERT(rc); 3997 validTag = rc->legend()->configureFromXml(xml, store); 3998 } else { 3999 Q_ASSERT(rc); 4000 if (!rc->parse(xml, validTag) && validTag) { 4001 ViewItem *i = GraphicsFactory::parse(xml, store, view, rc); 4002 if (!i) { 4003 } 4004 } 4005 } 4006 } else if (xml.isEndElement()) { 4007 if (xml.name().toString() == "plot") { 4008 break; 4009 } else { 4010 validTag = false; 4011 } 4012 } 4013 if (!validTag) { 4014 Debug::self()->log(QObject::tr("Error creating plot object from Kst file."), Debug::Warning); 4015 delete rc; 4016 return 0; 4017 } 4018 xml.readNext(); 4019 } 4020 rc->setProjectionRect(QRectF(QPointF(x, y), QSizeF(w, h))); 4021 rc->setTiedZoom(xTiedZoom, yTiedZoom); 4022 return rc; 4023 } 4024 4025 4026 ZoomCommand::ZoomCommand(PlotItem *item, const QString &text, bool forced) 4027 : ViewItemCommand(item, text, false), _plotItem(item) { 4028 4029 if (!item->isTiedZoom() || forced) { 4030 _originalStates << item->currentZoomState(); 4031 } else { 4032 _viewItems = PlotItemManager::tiedZoomViewItems(item); 4033 4034 QList<PlotItem*> plots = PlotItemManager::tiedZoomPlots(item); 4035 foreach (PlotItem *plotItem, plots) { 4036 if (plotItem->isInSharedAxisBox()) { 4037 if (!_viewItems.contains(plotItem->sharedAxisBox())) { 4038 _viewItems << plotItem->sharedAxisBox(); 4039 } 4040 } else { // plots already in a shared box are going to get zoomed anyway, so don't re-add them. 4041 _originalStates << plotItem->currentZoomState(); 4042 } 4043 } 4044 } 4045 } 4046 4047 4048 ZoomCommand::~ZoomCommand() { 4049 } 4050 4051 4052 void ZoomCommand::undo() { 4053 foreach (const ZoomState &state, _originalStates) { 4054 state.item->setCurrentZoomState(state); 4055 } 4056 kstApp->mainWindow()->document()->setChanged(true); 4057 } 4058 4059 4060 void ZoomCommand::redo() { 4061 bool tiedX = _plotItem->isXTiedZoom(); 4062 bool tiedY = _plotItem->isYTiedZoom(); 4063 4064 foreach (const ZoomState &state, _originalStates) { 4065 if (state.item == _plotItem) { 4066 applyZoomTo(state.item, true, true); 4067 } else { 4068 applyZoomTo(state.item, state.item->isXTiedZoom() && tiedX, state.item->isYTiedZoom() && tiedY); 4069 } 4070 } 4071 foreach (ViewItem* item, _viewItems) { // _viewItems is the list of shared axis boxes tied in somehow. 4072 applyZoomTo(item, tiedX, tiedY); 4073 } 4074 4075 kstApp->mainWindow()->document()->setChanged(true); 4076 } 4077 4078 4079 /* 4080 * X axis zoom to FixedExpression, Y axis zoom to FixedExpression. 4081 */ 4082 void ZoomFixedExpressionCommand::applyZoomTo(PlotItem *item, bool applyX, bool applyY) { 4083 if (applyX && applyY) { 4084 item->xAxis()->setAxisZoomMode(PlotAxis::FixedExpression); 4085 item->yAxis()->setAxisZoomMode(PlotAxis::FixedExpression); 4086 item->setProjectionRect(_fixed); 4087 } else if (applyX) { 4088 item->xAxis()->setAxisZoomMode(PlotAxis::FixedExpression); 4089 item->setProjectionRect(QRectF(_fixed.x(), item->projectionRect().y(), _fixed.width(), item->projectionRect().height())); 4090 } else if (applyY) { 4091 item->yAxis()->setAxisZoomMode(PlotAxis::FixedExpression); 4092 item->setProjectionRect(QRectF(item->projectionRect().x(), _fixed.y(), item->projectionRect().width(), _fixed.height())); 4093 } 4094 } 4095 4096 4097 void ZoomFixedExpressionCommand::applyZoomTo(ViewItem *item, bool applyX, bool applyY) { 4098 SharedAxisBoxItem *shareBox = qobject_cast<SharedAxisBoxItem*>(item); 4099 if (shareBox) { 4100 if (applyX && applyY) { 4101 shareBox->zoomFixedExpression(_fixed, 0); 4102 } else if (applyX) { 4103 shareBox->zoomXRange(_fixed, 0); 4104 } else if (applyY) { 4105 shareBox->zoomYRange(_fixed, 0); 4106 } 4107 } 4108 } 4109 4110 4111 /* 4112 * X axis zoom to Range. 4113 */ 4114 void ZoomXRangeCommand::applyZoomTo(PlotItem *item, bool applyX, bool applyY) { 4115 Q_UNUSED(applyY); 4116 if (applyX) { 4117 item->xAxis()->setAxisZoomMode(PlotAxis::FixedExpression); 4118 item->setProjectionRect(QRectF(_fixed.x(), item->projectionRect().y(), _fixed.width(), item->projectionRect().height())); 4119 } 4120 } 4121 4122 4123 void ZoomXRangeCommand::applyZoomTo(ViewItem *item, bool applyX, bool applyY) { 4124 Q_UNUSED(applyY); 4125 SharedAxisBoxItem *shareBox = qobject_cast<SharedAxisBoxItem*>(item); 4126 if (shareBox) { 4127 if (applyX) { 4128 shareBox->zoomXRange(_fixed, 0); 4129 } 4130 } 4131 } 4132 4133 4134 /* 4135 * Y axis zoom to Range. 4136 */ 4137 void ZoomYRangeCommand::applyZoomTo(PlotItem *item, bool applyX, bool applyY) { 4138 Q_UNUSED(applyX); 4139 if (applyY) { 4140 item->yAxis()->setAxisZoomMode(PlotAxis::FixedExpression); 4141 item->setProjectionRect(QRectF(item->projectionRect().x(), _fixed.y(), item->projectionRect().width(), _fixed.height())); 4142 } 4143 } 4144 4145 4146 void ZoomYRangeCommand::applyZoomTo(ViewItem *item, bool applyX, bool applyY) { 4147 Q_UNUSED(applyX); 4148 SharedAxisBoxItem *shareBox = qobject_cast<SharedAxisBoxItem*>(item); 4149 if (shareBox) { 4150 if (applyY) { 4151 shareBox->zoomYRange(_fixed, 0); 4152 } 4153 } 4154 } 4155 4156 4157 /* 4158 * X axis zoom to Auto, Y axis zoom to AutoBorder. 4159 */ 4160 void ZoomMaximumCommand::applyZoomTo(PlotItem *item, bool applyX, bool applyY) { 4161 if (applyX && applyY) { 4162 item->xAxis()->setAxisZoomMode(PlotAxis::Auto); 4163 item->yAxis()->setAxisZoomMode(PlotAxis::AutoBorder); 4164 QRectF compute = item->computedProjectionRect(); 4165 item->setProjectionRect(compute); 4166 } else if (applyX) { 4167 item->xAxis()->setAxisZoomMode(PlotAxis::Auto); 4168 QRectF compute = item->computedProjectionRect(); 4169 item->setProjectionRect(QRectF(compute.x(), item->projectionRect().y(), compute.width(), item->projectionRect().height())); 4170 } else if (applyY) { 4171 item->yAxis()->setAxisZoomMode(PlotAxis::AutoBorder); 4172 QRectF compute = item->computedProjectionRect(); 4173 item->setProjectionRect(QRectF(item->projectionRect().x(), compute.y(), item->projectionRect().width(), compute.height())); 4174 } 4175 } 4176 4177 4178 void ZoomMaximumCommand::applyZoomTo(ViewItem *item, bool applyX, bool applyY) { 4179 SharedAxisBoxItem *shareBox = qobject_cast<SharedAxisBoxItem*>(item); 4180 if (shareBox) { 4181 if (applyX && applyY) { 4182 shareBox->zoomMaximum(0); 4183 } else if (applyX) { 4184 shareBox->zoomXMaximum(0); 4185 } else if (applyY) { 4186 shareBox->zoomYMaximum(0); 4187 } 4188 } 4189 } 4190 4191 /* 4192 * X axis zoom to Auto, Y axis zoom to SpikeInsensitive. 4193 */ 4194 void ZoomMaxSpikeInsensitiveCommand::applyZoomTo(PlotItem *item, bool applyX, bool applyY) { 4195 if (applyX && applyY) { 4196 item->xAxis()->setAxisZoomMode(PlotAxis::Auto); 4197 item->yAxis()->setAxisZoomMode(PlotAxis::SpikeInsensitive); 4198 QRectF compute = item->computedProjectionRect(); 4199 item->setProjectionRect(compute); 4200 } else if (applyX) { 4201 item->xAxis()->setAxisZoomMode(PlotAxis::Auto); 4202 QRectF compute = item->computedProjectionRect(); 4203 item->setProjectionRect(QRectF(compute.x(), item->projectionRect().y(), compute.width(), item->projectionRect().height())); 4204 } else if (applyY) { 4205 item->yAxis()->setAxisZoomMode(PlotAxis::SpikeInsensitive); 4206 QRectF compute = item->computedProjectionRect(); 4207 item->setProjectionRect(QRectF(item->projectionRect().x(), compute.y(), item->projectionRect().width(), compute.height())); 4208 } 4209 } 4210 4211 4212 void ZoomMaxSpikeInsensitiveCommand::applyZoomTo(ViewItem *item, bool applyX, bool applyY) { 4213 SharedAxisBoxItem *shareBox = qobject_cast<SharedAxisBoxItem*>(item); 4214 if (shareBox) { 4215 if (applyX && applyY) { 4216 shareBox->zoomMaxSpikeInsensitive(0); 4217 } else if (applyX) { 4218 shareBox->zoomXMaximum(0); 4219 } else if (applyY) { 4220 shareBox->zoomYNoSpike(0); 4221 } 4222 } 4223 } 4224 4225 4226 /* 4227 * X axis zoom to Auto, Y axis zoom to Mean Centered. 4228 */ 4229 void ZoomMeanCenteredCommand::applyZoomTo(PlotItem *item, bool applyX, bool applyY) { 4230 if (applyX && applyY) { 4231 item->xAxis()->setAxisZoomMode(PlotAxis::Auto); 4232 item->yAxis()->setAxisZoomMode(PlotAxis::MeanCentered); 4233 QRectF compute = item->computedProjectionRect(); 4234 item->setProjectionRect(compute); 4235 } else if (applyX) { 4236 item->xAxis()->setAxisZoomMode(PlotAxis::Auto); 4237 QRectF compute = item->computedProjectionRect(); 4238 item->setProjectionRect(QRectF(compute.x(), item->projectionRect().y(), compute.width(), item->projectionRect().height())); 4239 } else if (applyY) { 4240 item->yAxis()->setAxisZoomMode(PlotAxis::MeanCentered); 4241 QRectF compute = item->computedProjectionRect(); 4242 item->setProjectionRect(QRectF(item->projectionRect().x(), compute.y(), item->projectionRect().width(), compute.height())); 4243 } 4244 } 4245 4246 4247 void ZoomMeanCenteredCommand::applyZoomTo(ViewItem *item, bool applyX, bool applyY) { 4248 SharedAxisBoxItem *shareBox = qobject_cast<SharedAxisBoxItem*>(item); 4249 if (shareBox) { 4250 if (applyX && applyY) { 4251 shareBox->zoomMeanCentered(0); 4252 } else if (applyX) { 4253 shareBox->zoomXMaximum(0); 4254 } else if (applyY) { 4255 shareBox->zoomMeanCentered(0); 4256 } 4257 } 4258 } 4259 4260 /* 4261 * X axis zoom unchanged, Y axis zoom to Mean Centered. 4262 */ 4263 void ZoomYMeanCenteredCommand::applyZoomTo(PlotItem *item, bool applyX, bool applyY) { 4264 Q_UNUSED(applyX); 4265 4266 if (applyY) { 4267 item->yAxis()->setAxisZoomMode(PlotAxis::MeanCentered); 4268 QRectF compute = item->computedProjectionRect(); 4269 item->setProjectionRect(QRectF(item->projectionRect().x(), compute.y(), item->projectionRect().width(), _dY)); 4270 } 4271 } 4272 4273 4274 void ZoomYMeanCenteredCommand::applyZoomTo(ViewItem *item, bool applyX, bool applyY) { 4275 Q_UNUSED(applyX); 4276 SharedAxisBoxItem *shareBox = qobject_cast<SharedAxisBoxItem*>(item); 4277 if (shareBox) { 4278 if (applyY) { 4279 shareBox->zoomYMeanCentered(_dY, 0); 4280 } 4281 } 4282 } 4283 4284 /* 4285 * X axis zoom to Mean Centered, Y axis unchanged. 4286 */ 4287 void ZoomXMeanCenteredCommand::applyZoomTo(PlotItem *item, bool applyX, bool applyY) { 4288 Q_UNUSED(applyY); 4289 4290 if (applyX) { 4291 item->xAxis()->setAxisZoomMode(PlotAxis::MeanCentered); 4292 QRectF compute = item->computedProjectionRect(); 4293 item->setProjectionRect(QRectF(compute.x(), item->projectionRect().y(), _dX, item->projectionRect().height())); 4294 } 4295 } 4296 4297 4298 void ZoomXMeanCenteredCommand::applyZoomTo(ViewItem *item, bool applyX, bool applyY) { 4299 Q_UNUSED(applyY); 4300 SharedAxisBoxItem *shareBox = qobject_cast<SharedAxisBoxItem*>(item); 4301 if (shareBox) { 4302 if (applyX) { 4303 shareBox->zoomXMeanCentered(0); 4304 } 4305 } 4306 } 4307 4308 /* 4309 * X axis zoom to auto, Y zoom not changed. 4310 */ 4311 void ZoomXMaximumCommand::applyZoomTo(PlotItem *item, bool applyX, bool applyY) { 4312 Q_UNUSED(applyY); 4313 if (applyX) { 4314 item->xAxis()->setAxisZoomMode(PlotAxis::Auto); 4315 QRectF compute = item->computedProjectionRect(); 4316 item->setProjectionRect(QRectF(compute.x(), 4317 item->projectionRect().y(), 4318 compute.width(), 4319 item->projectionRect().height())); 4320 } 4321 } 4322 4323 4324 void ZoomXMaximumCommand::applyZoomTo(ViewItem *item, bool applyX, bool applyY) { 4325 Q_UNUSED(applyY); 4326 SharedAxisBoxItem *shareBox = qobject_cast<SharedAxisBoxItem*>(item); 4327 if (shareBox) { 4328 if (applyX) { 4329 shareBox->zoomXMaximum(0); 4330 } 4331 } 4332 } 4333 4334 4335 /* 4336 * X axis zoom to auto border, Y zoom not changed. 4337 */ 4338 void ZoomXAutoBorderCommand::applyZoomTo(PlotItem *item, bool applyX, bool applyY) { 4339 Q_UNUSED(applyY); 4340 if (applyX) { 4341 item->xAxis()->setAxisZoomMode(PlotAxis::AutoBorder); 4342 QRectF compute = item->computedProjectionRect(); 4343 item->setProjectionRect(QRectF(compute.x(), 4344 item->projectionRect().y(), 4345 compute.width(), 4346 item->projectionRect().height())); 4347 } 4348 } 4349 4350 4351 void ZoomXAutoBorderCommand::applyZoomTo(ViewItem *item, bool applyX, bool applyY) { 4352 Q_UNUSED(applyY); 4353 SharedAxisBoxItem *shareBox = qobject_cast<SharedAxisBoxItem*>(item); 4354 if (shareBox) { 4355 if (applyX) { 4356 shareBox->zoomXAutoBorder(0); 4357 } 4358 } 4359 } 4360 4361 4362 /* 4363 * X axis zoom to no spike, Y zoom not changed. 4364 */ 4365 void ZoomXNoSpikeCommand::applyZoomTo(PlotItem *item, bool applyX, bool applyY) { 4366 Q_UNUSED(applyY); 4367 if (applyX) { 4368 item->xAxis()->setAxisZoomMode(PlotAxis::SpikeInsensitive); 4369 QRectF compute = item->computedProjectionRect(); 4370 item->setProjectionRect(QRectF(compute.x(), 4371 item->projectionRect().y(), 4372 compute.width(), 4373 item->projectionRect().height())); 4374 } 4375 } 4376 4377 4378 void ZoomXNoSpikeCommand::applyZoomTo(ViewItem *item, bool applyX, bool applyY) { 4379 Q_UNUSED(applyY); 4380 SharedAxisBoxItem *shareBox = qobject_cast<SharedAxisBoxItem*>(item); 4381 if (shareBox) { 4382 if (applyX) { 4383 shareBox->zoomXNoSpike(0); 4384 } 4385 } 4386 } 4387 4388 4389 /* 4390 * X axis zoom changed to fixed and shifted to right: 4391 * new_xmin = xmin + (xmax - xmin)*0.10; 4392 * new_xmax = xmax + (xmax – xmin)*0.10; 4393 */ 4394 void ZoomXRightCommand::applyZoomTo(PlotItem *item, bool applyX, bool applyY) { 4395 Q_UNUSED(applyY); 4396 if (applyX) { 4397 item->xAxis()->setAxisZoomMode(PlotAxis::FixedExpression); 4398 4399 QRectF compute = item->projectionRect(); 4400 4401 qreal dx = (item->xMax() - item->xMin())*0.10; 4402 if (item->xAxis()->axisReversed()) { 4403 dx *=-1; 4404 } 4405 if (item->xAxis()->axisLog()) { 4406 compute.setLeft(pow(10, item->xMin() + dx)); 4407 compute.setRight(pow(10, item->xMax() + dx)); 4408 } else { 4409 compute.setLeft(compute.left() + dx); 4410 compute.setRight(compute.right() + dx); 4411 } 4412 4413 item->setProjectionRect(compute); 4414 } 4415 } 4416 4417 4418 void ZoomXRightCommand::applyZoomTo(ViewItem *item, bool applyX, bool applyY) { 4419 Q_UNUSED(applyY); 4420 SharedAxisBoxItem *shareBox = qobject_cast<SharedAxisBoxItem*>(item); 4421 if (shareBox) { 4422 if (applyX) { 4423 shareBox->zoomXRight(0); 4424 } 4425 } 4426 } 4427 4428 /* 4429 * X axis zoom changed to fixed and shifted to right: 4430 * new_xmin = xmin + (xmax - xmin); 4431 * new_xmax = xmax + (xmax – xmin); 4432 */ 4433 void ZoomXFarRightCommand::applyZoomTo(PlotItem *item, bool applyX, bool applyY) { 4434 Q_UNUSED(applyY); 4435 if (applyX) { 4436 item->xAxis()->setAxisZoomMode(PlotAxis::FixedExpression); 4437 4438 QRectF compute = item->projectionRect(); 4439 4440 qreal dx = (item->xMax() - item->xMin()); 4441 if (item->xAxis()->axisReversed()) { 4442 dx *=-1; 4443 } 4444 if (item->xAxis()->axisLog()) { 4445 compute.setLeft(pow(10, item->xMin() + dx)); 4446 compute.setRight(pow(10, item->xMax() + dx)); 4447 } else { 4448 compute.setLeft(compute.left() + dx); 4449 compute.setRight(compute.right() + dx); 4450 } 4451 4452 item->setProjectionRect(compute); 4453 } 4454 } 4455 4456 4457 void ZoomXFarRightCommand::applyZoomTo(ViewItem *item, bool applyX, bool applyY) { 4458 Q_UNUSED(applyY); 4459 SharedAxisBoxItem *shareBox = qobject_cast<SharedAxisBoxItem*>(item); 4460 if (shareBox) { 4461 if (applyX) { 4462 shareBox->zoomXRight(0, true); 4463 } 4464 } 4465 } 4466 4467 /* 4468 * X axis zoom changed to fixed and shifted to : 4469 * new_xmin = xmin - (xmax - xmin)*0.10; 4470 * new_xmax = xmax - (xmax – xmin)*0.10; 4471 */ 4472 void ZoomXLeftCommand::applyZoomTo(PlotItem *item, bool applyX, bool applyY) { 4473 Q_UNUSED(applyY); 4474 if (applyX) { 4475 item->xAxis()->setAxisZoomMode(PlotAxis::FixedExpression); 4476 4477 QRectF compute = item->projectionRect(); 4478 4479 qreal dx = (item->xMax() - item->xMin())*0.10; 4480 if (item->xAxis()->axisReversed()) { 4481 dx *=-1; 4482 } 4483 if (item->xAxis()->axisLog()) { 4484 compute.setLeft(pow(10, item->xMin() - dx)); 4485 compute.setRight(pow(10, item->xMax() - dx)); 4486 } else { 4487 compute.setLeft(compute.left() - dx); 4488 compute.setRight(compute.right() - dx); 4489 } 4490 4491 item->setProjectionRect(compute); 4492 } 4493 } 4494 4495 4496 void ZoomXLeftCommand::applyZoomTo(ViewItem *item, bool applyX, bool applyY) { 4497 Q_UNUSED(applyY); 4498 SharedAxisBoxItem *shareBox = qobject_cast<SharedAxisBoxItem*>(item); 4499 if (shareBox) { 4500 if (applyX) { 4501 shareBox->zoomXLeft(0); 4502 } 4503 } 4504 } 4505 4506 /* 4507 * X axis zoom changed to fixed and shifted to : 4508 * new_xmin = xmin - (xmax - xmin); 4509 * new_xmax = xmax - (xmax – xmin); 4510 */ 4511 void ZoomXFarLeftCommand::applyZoomTo(PlotItem *item, bool applyX, bool applyY) { 4512 Q_UNUSED(applyY); 4513 if (applyX) { 4514 item->xAxis()->setAxisZoomMode(PlotAxis::FixedExpression); 4515 4516 QRectF compute = item->projectionRect(); 4517 4518 qreal dx = (item->xMax() - item->xMin()); 4519 if (item->xAxis()->axisReversed()) { 4520 dx *=-1; 4521 } 4522 if (item->xAxis()->axisLog()) { 4523 compute.setLeft(pow(10, item->xMin() - dx)); 4524 compute.setRight(pow(10, item->xMax() - dx)); 4525 } else { 4526 compute.setLeft(compute.left() - dx); 4527 compute.setRight(compute.right() - dx); 4528 } 4529 4530 item->setProjectionRect(compute); 4531 } 4532 } 4533 4534 4535 void ZoomXFarLeftCommand::applyZoomTo(ViewItem *item, bool applyX, bool applyY) { 4536 Q_UNUSED(applyY); 4537 SharedAxisBoxItem *shareBox = qobject_cast<SharedAxisBoxItem*>(item); 4538 if (shareBox) { 4539 if (applyX) { 4540 shareBox->zoomXLeft(0, true); 4541 } 4542 } 4543 } 4544 4545 4546 /* 4547 * X axis zoom changed to fixed and increased: 4548 * new_xmin = xmin - (xmax - xmin)*0.25; 4549 * new_xmax = xmax + (xmax – xmin)*0.25; 4550 */ 4551 void ZoomXOutCommand::applyZoomTo(PlotItem *item, bool applyX, bool applyY) { 4552 Q_UNUSED(applyY); 4553 if (applyX) { 4554 item->xAxis()->setAxisZoomMode(PlotAxis::FixedExpression); 4555 4556 QRectF compute = item->projectionRect(); 4557 4558 qreal dx = (item->xMax() - item->xMin())*0.25; 4559 if (item->xAxis()->axisLog()) { 4560 compute.setLeft(pow(10, item->xMin() - dx)); 4561 compute.setRight(pow(10, item->xMax() + dx)); 4562 } else { 4563 compute.setLeft(compute.left() - dx); 4564 compute.setRight(compute.right() + dx); 4565 } 4566 4567 item->setProjectionRect(compute); 4568 // item->update(); 4569 } 4570 } 4571 4572 4573 void ZoomXOutCommand::applyZoomTo(ViewItem *item, bool applyX, bool applyY) { 4574 Q_UNUSED(applyY); 4575 SharedAxisBoxItem *shareBox = qobject_cast<SharedAxisBoxItem*>(item); 4576 if (shareBox) { 4577 if (applyX) { 4578 shareBox->zoomXOut(0); 4579 } 4580 } 4581 } 4582 4583 4584 /* 4585 * X axis zoom changed to fixed and decreased: 4586 * new_xmin = xmin + (xmax - xmin)*0.1666666; 4587 * new_xmax = xmax - (xmax – xmin)*0.1666666; 4588 */ 4589 void ZoomXInCommand::applyZoomTo(PlotItem *item, bool applyX, bool applyY) { 4590 Q_UNUSED(applyY); 4591 if (applyX) { 4592 item->xAxis()->setAxisZoomMode(PlotAxis::FixedExpression); 4593 4594 QRectF compute = item->projectionRect(); 4595 4596 qreal dx = (item->xMax() - item->xMin())*0.1666666; 4597 if (item->xAxis()->axisLog()) { 4598 compute.setLeft(pow(10, item->xMin() + dx)); 4599 compute.setRight(pow(10, item->xMax() - dx)); 4600 } else { 4601 compute.setLeft(compute.left() + dx); 4602 compute.setRight(compute.right() - dx); 4603 } 4604 4605 item->setProjectionRect(compute); 4606 } 4607 } 4608 4609 4610 void ZoomXInCommand::applyZoomTo(ViewItem *item, bool applyX, bool applyY) { 4611 Q_UNUSED(applyY); 4612 SharedAxisBoxItem *shareBox = qobject_cast<SharedAxisBoxItem*>(item); 4613 if (shareBox) { 4614 if (applyX) { 4615 shareBox->zoomXIn(0); 4616 } 4617 } 4618 } 4619 4620 4621 /* 4622 * Normalize X axis to Y axis: Given the current plot aspect ratio, change 4623 * the X axis range to have the same units per mm as the Y axis range. Particularly 4624 * useful for images. 4625 */ 4626 void ZoomNormalizeXToYCommand::applyZoomTo(PlotItem *item, bool applyX, bool applyY) { 4627 Q_UNUSED(applyY); 4628 if (applyX) { 4629 QRectF compute = item->projectionRect(); 4630 qreal mean = compute.center().x(); 4631 qreal range = item->plotRect().width() * compute.height() / item->plotRect().height(); 4632 4633 compute.setLeft(mean - (range / 2.0)); 4634 compute.setRight(mean + (range / 2.0)); 4635 4636 item->xAxis()->setAxisZoomMode(PlotAxis::FixedExpression); 4637 item->setProjectionRect(compute); 4638 } 4639 } 4640 4641 4642 void ZoomNormalizeXToYCommand::applyZoomTo(ViewItem *item, bool applyX, bool applyY) { 4643 Q_UNUSED(applyY); 4644 SharedAxisBoxItem *shareBox = qobject_cast<SharedAxisBoxItem*>(item); 4645 if (shareBox) { 4646 if (applyX) { 4647 shareBox->zoomNormalizeXtoY(0); 4648 } 4649 } 4650 } 4651 4652 4653 /* 4654 * When zoomed in in X, auto zoom Y, only 4655 * counting points within the current X range. (eg, curve goes from x=0 to 100, but 4656 * we are zoomed in to x = 30 to 40. Adjust Y zoom to include all points with x 4657 * values between 30 and 40. 4658 */ 4659 void ZoomYLocalMaximumCommand::applyZoomTo(PlotItem *item, bool applyX, bool applyY) { 4660 Q_UNUSED(applyX); 4661 if (applyY) { 4662 double minimum = item->yMax(); 4663 double maximum = item->yMin(); 4664 item->computedRelationalMax(minimum, maximum); 4665 4666 item->computeBorder(Qt::Vertical, minimum, maximum); 4667 4668 item->yAxis()->setAxisZoomMode(PlotAxis::FixedExpression); 4669 4670 QRectF compute = item->projectionRect(); 4671 compute.setTop(minimum); 4672 compute.setBottom(maximum); 4673 4674 item->setProjectionRect(compute); 4675 } 4676 } 4677 4678 4679 void ZoomYLocalMaximumCommand::applyZoomTo(ViewItem *item, bool applyX, bool applyY) { 4680 Q_UNUSED(applyX); 4681 SharedAxisBoxItem *shareBox = qobject_cast<SharedAxisBoxItem*>(item); 4682 if (shareBox) { 4683 if (applyY) { 4684 shareBox->zoomYLocalMaximum(0); 4685 } 4686 } 4687 } 4688 4689 4690 /* 4691 * Y axis zoom to auto, X zoom not changed. 4692 */ 4693 void ZoomYMaximumCommand::applyZoomTo(PlotItem *item, bool applyX, bool applyY) { 4694 Q_UNUSED(applyX); 4695 if (applyY) { 4696 item->yAxis()->setAxisZoomMode(PlotAxis::Auto); 4697 QRectF compute = item->computedProjectionRect(); 4698 item->setProjectionRect(QRectF(item->projectionRect().x(), 4699 compute.y(), 4700 item->projectionRect().width(), 4701 compute.height())); 4702 } 4703 } 4704 4705 4706 void ZoomYMaximumCommand::applyZoomTo(ViewItem *item, bool applyX, bool applyY) { 4707 Q_UNUSED(applyX); 4708 SharedAxisBoxItem *shareBox = qobject_cast<SharedAxisBoxItem*>(item); 4709 if (shareBox) { 4710 if (applyY) { 4711 shareBox->zoomYMaximum(0); 4712 } 4713 } 4714 } 4715 4716 4717 /* 4718 * Y axis zoom to auto border, X zoom not changed. 4719 */ 4720 void ZoomYAutoBorderCommand::applyZoomTo(PlotItem *item, bool applyX, bool applyY) { 4721 Q_UNUSED(applyX); 4722 if (applyY) { 4723 item->yAxis()->setAxisZoomMode(PlotAxis::AutoBorder); 4724 QRectF compute = item->computedProjectionRect(); 4725 item->setProjectionRect(QRectF(item->projectionRect().x(), 4726 compute.y(), 4727 item->projectionRect().width(), 4728 compute.height())); 4729 } 4730 } 4731 4732 4733 void ZoomYAutoBorderCommand::applyZoomTo(ViewItem *item, bool applyX, bool applyY) { 4734 Q_UNUSED(applyX); 4735 SharedAxisBoxItem *shareBox = qobject_cast<SharedAxisBoxItem*>(item); 4736 if (shareBox) { 4737 if (applyY) { 4738 shareBox->zoomYAutoBorder(0); 4739 } 4740 } 4741 } 4742 4743 4744 /* 4745 * Y axis zoom to no spike, X zoom not changed. 4746 */ 4747 void ZoomYNoSpikeCommand::applyZoomTo(PlotItem *item, bool applyX, bool applyY) { 4748 Q_UNUSED(applyX); 4749 if (applyY) { 4750 item->yAxis()->setAxisZoomMode(PlotAxis::SpikeInsensitive); 4751 QRectF compute = item->computedProjectionRect(); 4752 item->setProjectionRect(QRectF(item->projectionRect().x(), 4753 compute.y(), 4754 item->projectionRect().width(), 4755 compute.height())); 4756 } 4757 } 4758 4759 4760 void ZoomYNoSpikeCommand::applyZoomTo(ViewItem *item, bool applyX, bool applyY) { 4761 Q_UNUSED(applyX); 4762 SharedAxisBoxItem *shareBox = qobject_cast<SharedAxisBoxItem*>(item); 4763 if (shareBox) { 4764 if (applyY) { 4765 shareBox->zoomYNoSpike(0); 4766 } 4767 } 4768 } 4769 4770 4771 /* 4772 * Y axis zoom up. If the Y zoom mode is not 4773 * Mean Centered, change to Fixed (expression). 4774 * new_ymin = ymin + (ymax - ymin)*0.1; 4775 * new_ymax = ymax + (ymax - ymin)*0.1; 4776 */ 4777 void ZoomYUpCommand::applyZoomTo(PlotItem *item, bool applyX, bool applyY) { 4778 Q_UNUSED(applyX); 4779 if (applyY) { 4780 if (item->yAxis()->axisZoomMode() != PlotAxis::MeanCentered) 4781 item->yAxis()->setAxisZoomMode(PlotAxis::FixedExpression); 4782 4783 QRectF compute = item->projectionRect(); 4784 4785 qreal dy = (item->yMax() - item->yMin())*0.1; 4786 if (item->yAxis()->axisLog()) { 4787 compute.setTop(pow(10, item->yMin() + dy)); 4788 compute.setBottom(pow(10, item->yMax() + dy)); 4789 } else { 4790 compute.setTop(compute.top() + dy); 4791 compute.setBottom(compute.bottom() + dy); 4792 } 4793 4794 item->setProjectionRect(compute); 4795 } 4796 } 4797 4798 4799 void ZoomYUpCommand::applyZoomTo(ViewItem *item, bool applyX, bool applyY) { 4800 Q_UNUSED(applyX); 4801 SharedAxisBoxItem *shareBox = qobject_cast<SharedAxisBoxItem*>(item); 4802 if (shareBox) { 4803 if (applyY) { 4804 shareBox->zoomYUp(0); 4805 } 4806 } 4807 } 4808 4809 4810 /* 4811 * Y axis zoom down. If the Y zoom mode is not 4812 * Mean Centered, change to Fixed (expression). 4813 * new_ymin = ymin - (ymax - ymin)*0.10; 4814 * new_ymax = ymax - (ymax - ymin)*0.10; 4815 */ 4816 void ZoomYDownCommand::applyZoomTo(PlotItem *item, bool applyX, bool applyY) { 4817 Q_UNUSED(applyX); 4818 if (applyY) { 4819 if (item->yAxis()->axisZoomMode() != PlotAxis::MeanCentered) 4820 item->yAxis()->setAxisZoomMode(PlotAxis::FixedExpression); 4821 4822 QRectF compute = item->projectionRect(); 4823 4824 qreal dy = (item->yMax() - item->yMin())*0.1; 4825 if (item->yAxis()->axisLog()) { 4826 compute.setTop(pow(10, item->yMin() - dy)); 4827 compute.setBottom(pow(10, item->yMax() - dy)); 4828 } else { 4829 compute.setTop(compute.top() - dy); 4830 compute.setBottom(compute.bottom() - dy); 4831 } 4832 4833 item->setProjectionRect(compute); 4834 } 4835 } 4836 4837 4838 void ZoomYDownCommand::applyZoomTo(ViewItem *item, bool applyX, bool applyY) { 4839 Q_UNUSED(applyX); 4840 SharedAxisBoxItem *shareBox = qobject_cast<SharedAxisBoxItem*>(item); 4841 if (shareBox) { 4842 if (applyY) { 4843 shareBox->zoomYDown(0); 4844 } 4845 } 4846 } 4847 4848 4849 /* 4850 * Y axis zoom increased. If the Y zoom mode is not 4851 * Mean Centered, change to Fixed (expression). 4852 * new_ymin = ymin - (ymax - ymin)*0.25; 4853 * new_ymax = ymax + (ymax - ymin)*0.25; 4854 */ 4855 void ZoomYOutCommand::applyZoomTo(PlotItem *item, bool applyX, bool applyY) { 4856 Q_UNUSED(applyX); 4857 if (applyY) { 4858 if (item->yAxis()->axisZoomMode() != PlotAxis::MeanCentered) 4859 item->yAxis()->setAxisZoomMode(PlotAxis::FixedExpression); 4860 4861 QRectF compute = item->projectionRect(); 4862 4863 qreal dy = (item->yMax() - item->yMin())*0.25; 4864 if (item->yAxis()->axisLog()) { 4865 compute.setTop(pow(10, item->yMin() - dy)); 4866 compute.setBottom(pow(10, item->yMax() + dy)); 4867 } else { 4868 compute.setTop(compute.top() - dy); 4869 compute.setBottom(compute.bottom() + dy); 4870 } 4871 4872 item->setProjectionRect(compute); 4873 // item->update(); 4874 } 4875 } 4876 4877 4878 void ZoomYOutCommand::applyZoomTo(ViewItem *item, bool applyX, bool applyY) { 4879 Q_UNUSED(applyX); 4880 SharedAxisBoxItem *shareBox = qobject_cast<SharedAxisBoxItem*>(item); 4881 if (shareBox) { 4882 if (applyY) { 4883 shareBox->zoomYOut(0); 4884 } 4885 } 4886 } 4887 4888 4889 /* 4890 * Y axis zoom decreased. If the Y zoom mode is not 4891 * Mean Centered, change to Fixed (expression). 4892 * new_ymin = ymin + (ymax - ymin)*0.1666666; 4893 * new_ymax = ymax - (ymax – ymin)*0.1666666; 4894 */ 4895 void ZoomYInCommand::applyZoomTo(PlotItem *item, bool applyX, bool applyY) { 4896 Q_UNUSED(applyX); 4897 if (applyY) { 4898 if (item->yAxis()->axisZoomMode() != PlotAxis::MeanCentered) 4899 item->yAxis()->setAxisZoomMode(PlotAxis::FixedExpression); 4900 4901 QRectF compute = item->projectionRect(); 4902 4903 qreal dy = (item->yMax() - item->yMin())*0.1666666; 4904 if (item->yAxis()->axisLog()) { 4905 compute.setTop(pow(10, item->yMin() + dy)); 4906 compute.setBottom(pow(10, item->yMax() - dy)); 4907 } else { 4908 compute.setTop(compute.top() + dy); 4909 compute.setBottom(compute.bottom() - dy); 4910 } 4911 4912 item->setProjectionRect(compute); 4913 // item->update(); 4914 } 4915 } 4916 4917 4918 void ZoomYInCommand::applyZoomTo(ViewItem *item, bool applyX, bool applyY) { 4919 Q_UNUSED(applyX); 4920 SharedAxisBoxItem *shareBox = qobject_cast<SharedAxisBoxItem*>(item); 4921 if (shareBox) { 4922 if (applyY) { 4923 shareBox->zoomYIn(0); 4924 } 4925 } 4926 } 4927 4928 4929 /* 4930 * Normalize Y axis to X axis: Given the current plot aspect ratio, 4931 * change the Y axis range to have the same units per mm as the X axis range. 4932 * Particularly useful for images. 4933 */ 4934 void ZoomNormalizeYToXCommand::applyZoomTo(PlotItem *item, bool applyX, bool applyY) { 4935 Q_UNUSED(applyX); 4936 if (applyY) { 4937 QRectF compute = item->projectionRect(); 4938 qreal mean = compute.center().y(); 4939 qreal range = item->plotRect().height() * compute.width() / item->plotRect().width(); 4940 4941 compute.setTop(mean - (range / 2.0)); 4942 compute.setBottom(mean + (range / 2.0)); 4943 4944 item->yAxis()->setAxisZoomMode(PlotAxis::FixedExpression); 4945 item->setProjectionRect(compute); 4946 } 4947 } 4948 4949 4950 void ZoomNormalizeYToXCommand::applyZoomTo(ViewItem *item, bool applyX, bool applyY) { 4951 Q_UNUSED(applyX); 4952 SharedAxisBoxItem *shareBox = qobject_cast<SharedAxisBoxItem*>(item); 4953 if (shareBox) { 4954 if (applyY) { 4955 shareBox->zoomNormalizeYtoX(0); 4956 } 4957 } 4958 } 4959 4960 4961 /* 4962 * Switch the X Axis to a Log Scale. 4963 */ 4964 void ZoomXLogCommand::applyZoomTo(PlotItem *item, bool applyX, bool applyY) { 4965 Q_UNUSED(applyY); 4966 if (applyX) { 4967 item->xAxis()->setAxisLog(_enableLog); 4968 item->setProjectionRect(item->computedProjectionRect(), true); //need to recompute 4969 } 4970 } 4971 4972 4973 void ZoomXLogCommand::applyZoomTo(ViewItem *item, bool applyX, bool applyY) { 4974 Q_UNUSED(applyY); 4975 SharedAxisBoxItem *shareBox = qobject_cast<SharedAxisBoxItem*>(item); 4976 if (shareBox) { 4977 if (applyX) { 4978 shareBox->zoomLogX(0, false, _enableLog); 4979 } 4980 } 4981 } 4982 4983 4984 /* 4985 * Switch the Y Axis to a Log Scale. 4986 */ 4987 void ZoomYLogCommand::applyZoomTo(PlotItem *item, bool applyX, bool applyY) { 4988 Q_UNUSED(applyX); 4989 if (applyY) { 4990 item->yAxis()->setAxisLog(_enableLog); 4991 item->setProjectionRect(item->computedProjectionRect(), true); //need to recompute 4992 } 4993 } 4994 4995 4996 void ZoomYLogCommand::applyZoomTo(ViewItem *item, bool applyX, bool applyY) { 4997 Q_UNUSED(applyX); 4998 SharedAxisBoxItem *shareBox = qobject_cast<SharedAxisBoxItem*>(item); 4999 if (shareBox) { 5000 if (applyY) { 5001 shareBox->zoomLogY(0, false, _enableLog); 5002 } 5003 } 5004 } 5005 5006 } 5007 5008 // vim: ts=2 sw=2 et