File indexing completed on 2024-12-22 04:17:39
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 "plotaxis.h" 0014 0015 #include "math_kst.h" 0016 #include "dialogdefaults.h" 0017 0018 #include <QDate> 0019 #include <limits> 0020 0021 #define MAJOR_TICK_DEBUG 0 0022 0023 using namespace std; 0024 0025 static int FULL_PRECISION = 15; 0026 static qreal JD1900 = 2415020.5; 0027 static qreal JD1899_12_30 = 2415018.5; 0028 static qreal JD1970 = 2440587.5; 0029 static qreal JD_RJD = 2400000.0; 0030 static qreal JD_MJD = 2400000.5; 0031 0032 namespace Kst { 0033 0034 PlotAxis::PlotAxis(PlotItem *plotItem, Qt::Orientation orientation) : 0035 _plotItem(plotItem), 0036 _orientation(orientation), 0037 _dirty(true), 0038 _axisZoomMode(Auto), 0039 _isAxisVisible(true), 0040 _ns_zoom_level(0), 0041 _ticksUpdated(true), 0042 _axisLog(false), 0043 _axisReversed(false), 0044 _axisAutoBaseOffset(true), 0045 _axisBaseOffset(false), 0046 _axisBaseOffsetOverride(false), 0047 _axisForceOffsetMin(false), 0048 _axisInterpret(false), 0049 _axisDisplay(AXIS_DISPLAY_QTLOCALDATEHHMMSS_SS), 0050 _axisDisplayFormatString("hh:mm:ss.zzz"), 0051 _axisInterpretation(AXIS_INTERP_CTIME), 0052 _axisMajorTickMode(TicksNormal), 0053 _axisOverrideMajorTicks(TicksNormal), 0054 _axisMinorTickCount(4), 0055 _automaticMinorTicks(true), 0056 _automaticMinorTickCount(5), 0057 _axisSignificantDigits(9), 0058 _drawAxisMajorTicks(true), 0059 _drawAxisMinorTicks(true), 0060 _drawAxisMajorGridLines(true), 0061 _drawAxisMinorGridLines(false), 0062 _axisMajorGridLineColor(Qt::gray), 0063 _axisMinorGridLineColor(Qt::gray), 0064 _axisMajorGridLineStyle(Qt::DashLine), 0065 _axisMinorGridLineStyle(Qt::DashLine), 0066 _axisMajorGridLineWidth(1.0), 0067 _axisMinorGridLineWidth(1.0), 0068 _axisPlotMarkers(orientation == Qt::Horizontal), 0069 _labelRotation(0) 0070 { 0071 connect(_plotItem, SIGNAL(updateAxes()), this, SLOT(updateTicks())); 0072 } 0073 0074 0075 PlotAxis::~PlotAxis() { 0076 } 0077 0078 double PlotAxis::convertJDtoDisplayTime(double T) { 0079 switch (_axisDisplay) { 0080 case AXIS_DISPLAY_YEAR: 0081 T -= JD1900 + 0.5; 0082 T *= 1.0/365.25; // FIXME: make sure this is right 0083 T += 1900.0; 0084 break; 0085 case AXIS_DISPLAY_JD: 0086 break; 0087 case AXIS_DISPLAY_MJD: 0088 T -= JD_MJD; 0089 break; 0090 case AXIS_DISPLAY_RJD: 0091 T -= JD_RJD; 0092 break; 0093 default: 0094 break; 0095 } 0096 0097 return T; 0098 } 0099 0100 0101 double PlotAxis::convertJDtoCTime(double jdIn) { 0102 jdIn -= (JD1970); 0103 jdIn *= 24.0*3600.0; 0104 0105 if (jdIn > double(std::numeric_limits<time_t>::max())-1.0) { 0106 jdIn = std::numeric_limits<time_t>::max()-1; 0107 } 0108 if (jdIn<0) { 0109 jdIn = 0.0; 0110 } 0111 return (jdIn); 0112 } 0113 0114 0115 double PlotAxis::convertTimeValueToJD(double valueIn) { 0116 double value = valueIn; 0117 0118 switch (_axisInterpretation) { 0119 case AXIS_INTERP_YEAR: 0120 value -= 1900.0; 0121 value *= 365.25; // FIXME: seems wrong 0122 value += JD1900 + 0.5; 0123 break; 0124 case AXIS_INTERP_CTIME: 0125 value /= 24.0 * 60.0 * 60.0; 0126 value += JD1970; 0127 break; 0128 case AXIS_INTERP_JD: 0129 break; 0130 case AXIS_INTERP_MJD: 0131 value += JD_MJD; 0132 break; 0133 case AXIS_INTERP_RJD: 0134 value += JD_RJD; 0135 break; 0136 case AXIS_INTERP_EXCEL: 0137 value += JD1899_12_30; 0138 break; 0139 case AXIS_INTERP_AIT: 0140 value -= 86400.0 * (365.0 * 12.0 + 3.0); 0141 // current difference (seconds) between UTC and AIT 0142 // refer to the following for more information: 0143 // http://hpiers.obspm.fr/eop-pc/earthor/utc/TAI-UTC_tab.html 0144 value -= 32.0; 0145 value /= 24.0 * 60.0 * 60.0; 0146 value += JD1970; 0147 default: 0148 break; 0149 } 0150 0151 return value; 0152 } 0153 0154 0155 QString PlotAxis::convertJDToDateString(double jd, double range_jd) { 0156 QString label; 0157 QDate date; 0158 0159 int accuracy; 0160 range_jd *= 24.0 * 60.0 * 60.0; 0161 0162 0163 if (range_jd == 0.0) { 0164 accuracy = FULL_PRECISION; 0165 } else { 0166 accuracy = 1 - int(log10(range_jd)); 0167 if (accuracy < 0) { 0168 accuracy = 0; 0169 } 0170 } 0171 0172 // gmtOffset() is returned in seconds... as it must be since 0173 // some time zones are not an integer number of hours offset 0174 // from UTC... 0175 jd += (_timeZone.gmtOffset(convertJDtoCTime(jd)))/(3600.0*24.0); 0176 0177 // get the date from the Julian day number 0178 double jd_day = floor(jd); 0179 double jd_fraction = jd - jd_day; 0180 0181 // gregorian calendar correction 0182 if (jd >= 2299160.5) { 0183 double tmp = int( ( (jd_day - 1867216.0) - 0.25 ) / 36524.25 ); 0184 jd_day += 1.0 + tmp - floor(0.25*tmp); 0185 } 0186 0187 // correction for half day offset 0188 double dDayFraction = jd_fraction + 0.5; 0189 if (dDayFraction >= 1.0) { 0190 dDayFraction -= 1.0; 0191 jd_day += 1.0; 0192 } 0193 0194 // get time of day from day fraction 0195 int hour = int(dDayFraction*24.0); 0196 int minute = int((dDayFraction*24.0 - double(hour))*60.0); 0197 double second = ((dDayFraction*24.0 - double(hour))*60.0 - double(minute))*60.0; 0198 double fullseconds; 0199 double millisec = modf(second + 0.0005, &fullseconds) * 1000; 0200 0201 if (accuracy >= 0) { 0202 second *= pow(10.0, accuracy); 0203 second = floor(second+0.5); 0204 second /= pow(10.0,accuracy); 0205 if (second >= 60.0) { 0206 second -= 60.0; 0207 minute++; 0208 if (minute == 60) { 0209 minute = 0; 0210 hour++; 0211 if (hour == 24) { 0212 hour = 0; 0213 } 0214 } 0215 } 0216 } 0217 0218 double j2 = jd_day + 1524.0; 0219 double j3 = floor(6680.0 + ( (j2 - 2439870.0) - 122.1 )/365.25); 0220 double j4 = floor(j3 * 365.25); 0221 double j5 = floor((j2 - j4)/30.6001); 0222 0223 double day_d = floor(j2 - j4 - floor(j5*30.6001)); 0224 int day = int(qBound(-double(std::numeric_limits<int>::max()-1), day_d, double(std::numeric_limits<int>::max()))); 0225 0226 double month_d = floor(j5-1.0); 0227 int month = int(qBound(-double(std::numeric_limits<int>::max()-1), month_d, double(std::numeric_limits<int>::max()))); 0228 if (month > 12) { 0229 month -= 12; 0230 } 0231 0232 double year_d = floor(j3 - 4715.0); 0233 int year = int(qBound(-double(std::numeric_limits<int>::max()-1), year_d, double(std::numeric_limits<int>::max()))); 0234 if (month > 2) { 0235 --year; 0236 } 0237 if (year <= 0) { 0238 --year; 0239 } 0240 // check how many decimal places for the seconds we actually need to show 0241 if (accuracy > 0) { 0242 QString strSecond; 0243 0244 strSecond.sprintf("%02.*f", accuracy, second); 0245 for (int i=strSecond.length()-1; i>0; i--) { 0246 if (strSecond.at(i) == '0') { 0247 accuracy--; 0248 } else if (!strSecond.at(i).isDigit()) { 0249 break; 0250 } 0251 } 0252 } 0253 0254 if (accuracy < 0) { 0255 accuracy = 0; 0256 } 0257 0258 QString seconds; 0259 QString hourminute; 0260 hourminute.sprintf(" %02d:%02d:", hour, minute); 0261 seconds.sprintf("%02.*f", accuracy, second); 0262 switch (_axisDisplay) { 0263 case AXIS_DISPLAY_YYMMDDHHMMSS_SS: 0264 label.sprintf("%d/%02d/%02d", year, month, day); 0265 label += hourminute + seconds; 0266 break; 0267 case AXIS_DISPLAY_DDMMYYHHMMSS_SS: 0268 label.sprintf("%02d/%02d/%d", day, month, year); 0269 label += hourminute + seconds; 0270 break; 0271 case AXIS_DISPLAY_QTTEXTDATEHHMMSS_SS: 0272 date.setDate(year, month, day); 0273 label = date.toString(Qt::TextDate).toLatin1(); 0274 label += hourminute + seconds; 0275 break; 0276 case AXIS_DISPLAY_QTLOCALDATEHHMMSS_SS: 0277 date.setDate(year, month, day); 0278 label = date.toString(Qt::LocalDate).toLatin1(); 0279 label += hourminute + seconds; 0280 break; 0281 case AXIS_DISPLAY_QTDATETIME_FORMAT: 0282 label += QDateTime(QDate(year, month, day), QTime(hour, minute, second, millisec)) 0283 .toString(_axisDisplayFormatString); 0284 break; 0285 default: 0286 label = QString::number(convertJDtoDisplayTime(jd), 'G', FULL_PRECISION-2); 0287 break; 0288 } 0289 return label; 0290 } 0291 0292 0293 PlotAxis::ZoomMode PlotAxis::axisZoomMode() const { 0294 return _axisZoomMode; 0295 } 0296 0297 0298 void PlotAxis::setAxisZoomMode(ZoomMode mode) { 0299 if (_axisZoomMode != mode) { 0300 _axisZoomMode = mode; 0301 _ns_zoom_level = 0; 0302 _dirty = true; 0303 } else if (mode == PlotAxis::SpikeInsensitive) { 0304 _ns_zoom_level = (_ns_zoom_level+1)%5; 0305 } 0306 } 0307 0308 0309 bool PlotAxis::axisLog() const { 0310 return _axisLog; 0311 } 0312 0313 0314 void PlotAxis::setAxisLog(bool log) { 0315 if (_axisLog != log) { 0316 _axisLog = log; 0317 _dirty = true; 0318 } 0319 } 0320 0321 0322 int PlotAxis::axisSignificantDigits() const { 0323 return _axisSignificantDigits; 0324 } 0325 0326 0327 void PlotAxis::setAxisSignificantDigits(const int digits) { 0328 if (_axisSignificantDigits != digits) { 0329 _axisSignificantDigits = digits; 0330 _dirty = true; 0331 } 0332 } 0333 0334 0335 MajorTickMode PlotAxis::axisMajorTickMode() const { 0336 return _axisMajorTickMode; 0337 } 0338 0339 0340 void PlotAxis::setAxisMajorTickMode(MajorTickMode mode) { 0341 if (_axisMajorTickMode != mode) { 0342 _axisMajorTickMode = mode; 0343 _dirty = true; 0344 } 0345 } 0346 0347 0348 int PlotAxis::axisMinorTickCount() const { 0349 return _axisMinorTickCount; 0350 } 0351 0352 0353 void PlotAxis::setAxisMinorTickCount(const int count) { 0354 if (_axisMinorTickCount != count) { 0355 _axisMinorTickCount = count; 0356 _dirty = true; 0357 } 0358 } 0359 0360 0361 0362 bool PlotAxis::axisAutoMinorTicks() const { 0363 return _automaticMinorTicks; 0364 } 0365 0366 0367 void PlotAxis::setAxisAutoMinorTicks(const bool enabled) { 0368 if (_automaticMinorTicks != enabled) { 0369 _automaticMinorTicks = enabled; 0370 _dirty = true; 0371 } 0372 } 0373 0374 0375 bool PlotAxis::drawAxisMajorTicks() const { 0376 return _drawAxisMajorTicks; 0377 } 0378 0379 0380 void PlotAxis::setDrawAxisMajorTicks(bool draw) { 0381 if (_drawAxisMajorTicks != draw) { 0382 _drawAxisMajorTicks = draw; 0383 _dirty = true; 0384 } 0385 } 0386 0387 0388 bool PlotAxis::drawAxisMinorTicks() const { 0389 return _drawAxisMinorTicks; 0390 } 0391 0392 0393 void PlotAxis::setDrawAxisMinorTicks(bool draw) { 0394 if (_drawAxisMinorTicks != draw) { 0395 _drawAxisMinorTicks = draw; 0396 _dirty = true; 0397 } 0398 } 0399 0400 0401 bool PlotAxis::drawAxisMajorGridLines() const { 0402 return _drawAxisMajorGridLines; 0403 } 0404 0405 0406 void PlotAxis::setDrawAxisMajorGridLines(bool draw) { 0407 if (_drawAxisMajorGridLines != draw) { 0408 _drawAxisMajorGridLines = draw; 0409 _dirty = true; 0410 } 0411 } 0412 0413 0414 bool PlotAxis::drawAxisMinorGridLines() const { 0415 return _drawAxisMinorGridLines; 0416 } 0417 0418 0419 void PlotAxis::setDrawAxisMinorGridLines(bool draw) { 0420 if (_drawAxisMinorGridLines != draw) { 0421 _drawAxisMinorGridLines = draw; 0422 _dirty = true; 0423 } 0424 } 0425 0426 0427 QColor PlotAxis::axisMajorGridLineColor() const { 0428 return _axisMajorGridLineColor; 0429 } 0430 0431 0432 void PlotAxis::setAxisMajorGridLineColor(const QColor &color) { 0433 if (_axisMajorGridLineColor != color) { 0434 _axisMajorGridLineColor = color; 0435 _dirty = true; 0436 } 0437 } 0438 0439 0440 QColor PlotAxis::axisMinorGridLineColor() const { 0441 return _axisMinorGridLineColor; 0442 } 0443 0444 0445 void PlotAxis::setAxisMinorGridLineColor(const QColor &color) { 0446 if (_axisMinorGridLineColor != color) { 0447 _axisMinorGridLineColor = color; 0448 _dirty = true; 0449 } 0450 } 0451 0452 0453 Qt::PenStyle PlotAxis::axisMajorGridLineStyle() const { 0454 return _axisMajorGridLineStyle; 0455 } 0456 0457 0458 void PlotAxis::setAxisMajorGridLineStyle(const Qt::PenStyle style) { 0459 if (_axisMajorGridLineStyle != style) { 0460 _axisMajorGridLineStyle = style; 0461 _dirty = true; 0462 } 0463 } 0464 0465 0466 Qt::PenStyle PlotAxis::axisMinorGridLineStyle() const { 0467 return _axisMinorGridLineStyle; 0468 } 0469 0470 0471 void PlotAxis::setAxisMinorGridLineStyle(const Qt::PenStyle style) { 0472 if (_axisMinorGridLineStyle != style) { 0473 _axisMinorGridLineStyle = style; 0474 _dirty = true; 0475 } 0476 } 0477 0478 qreal PlotAxis::axisMajorGridLineWidth() const { 0479 return _axisMajorGridLineWidth; 0480 } 0481 0482 void PlotAxis::setAxisMajorGridLineWidth(qreal width) { 0483 if (_axisMajorGridLineWidth != width) { 0484 _axisMajorGridLineWidth = width; 0485 _dirty = true; 0486 } 0487 } 0488 0489 qreal PlotAxis::axisMinorGridLineWidth() const { 0490 return _axisMinorGridLineWidth; 0491 } 0492 0493 void PlotAxis::setAxisMinorGridLineWidth(qreal width) { 0494 if (_axisMinorGridLineWidth != width) { 0495 _axisMinorGridLineWidth = width; 0496 _dirty = true; 0497 } 0498 } 0499 0500 bool PlotAxis::isAxisVisible() const { 0501 return _isAxisVisible; 0502 } 0503 0504 0505 void PlotAxis::setAxisVisible(bool visible) { 0506 if (_isAxisVisible == visible) { 0507 return; 0508 } 0509 0510 _isAxisVisible = visible; 0511 _dirty = true; 0512 } 0513 0514 0515 bool PlotAxis::axisReversed() const { 0516 return _axisReversed; 0517 } 0518 0519 0520 void PlotAxis::setAxisReversed(const bool enabled) { 0521 if (_axisReversed != enabled) { 0522 _axisReversed = enabled; 0523 _dirty = true; 0524 } 0525 } 0526 0527 0528 bool PlotAxis::axisAutoBaseOffset() const { 0529 return _axisAutoBaseOffset; 0530 } 0531 0532 0533 void PlotAxis::setAxisAutoBaseOffset(const bool enabled) { 0534 if (_axisAutoBaseOffset != enabled) { 0535 _axisAutoBaseOffset = enabled; 0536 _dirty = true; 0537 } 0538 } 0539 0540 0541 bool PlotAxis::axisBaseOffset() const { 0542 return _axisBaseOffset; 0543 } 0544 0545 0546 void PlotAxis::setAxisBaseOffset(const bool enabled) { 0547 if (_axisBaseOffset != enabled) { 0548 _axisBaseOffset = enabled; 0549 _dirty = true; 0550 } 0551 } 0552 0553 0554 void PlotAxis::setAxisForceOffsetMin(bool enabled) { 0555 if (_axisForceOffsetMin != enabled) { 0556 _axisForceOffsetMin = enabled; 0557 _dirty = true; 0558 } 0559 } 0560 0561 0562 bool PlotAxis::axisInterpret() const { 0563 return _axisInterpret; 0564 } 0565 0566 0567 void PlotAxis::setAxisInterpret(const bool enabled) { 0568 if (_axisInterpret != enabled) { 0569 _axisInterpret = enabled; 0570 _dirty = true; 0571 } 0572 } 0573 0574 0575 QString PlotAxis::timezoneName() const { 0576 return _timeZone.tzName(); 0577 } 0578 0579 0580 void PlotAxis::setTimezoneName(QString timezone) { 0581 if (_timeZone.tzName() != timezone) { 0582 _timeZone.setTZ(timezone); 0583 _dirty = true; 0584 } 0585 } 0586 0587 0588 AxisDisplayType PlotAxis::axisDisplay() const { 0589 return _axisDisplay; 0590 } 0591 0592 QString PlotAxis::axisDisplayFormatString() const { 0593 return _axisDisplayFormatString; 0594 } 0595 0596 0597 void PlotAxis::setAxisDisplay(const AxisDisplayType display) { 0598 if (_axisDisplay != display) { 0599 _axisDisplay = display; 0600 _dirty = true; 0601 } 0602 } 0603 0604 void PlotAxis::setAxisDisplayFormatString(const QString& formatString) { 0605 if (_axisDisplayFormatString != formatString) { 0606 _axisDisplayFormatString = formatString; 0607 _dirty = true; 0608 } 0609 } 0610 0611 AxisInterpretationType PlotAxis::axisInterpretation() const { 0612 return _axisInterpretation; 0613 } 0614 0615 0616 void PlotAxis::setAxisInterpretation(const AxisInterpretationType display) { 0617 if (_axisInterpretation != display) { 0618 _axisInterpretation = display; 0619 _dirty = true; 0620 } 0621 } 0622 0623 0624 int PlotAxis::axisLabelRotation() const { 0625 return _labelRotation; 0626 } 0627 0628 0629 void PlotAxis::setAxisLabelRotation(const int rotation) { 0630 if (_labelRotation != rotation) { 0631 _labelRotation = rotation; 0632 _dirty = true; 0633 } 0634 } 0635 0636 // Function validates that the labels will not overlap. Only functions for X-axis. 0637 void PlotAxis::validateDrawingRegion(QPainter *painter) { 0638 // Always try to use the settings requested. 0639 if (_axisOverrideMajorTicks != _axisMajorTickMode) { 0640 _axisBaseOffsetOverride = false; 0641 updateTicks(); 0642 } 0643 0644 int flags = Qt::TextSingleLine | Qt::AlignCenter; 0645 int rotation = axisLabelRotation(); 0646 QTransform t; 0647 t.rotate(rotation); 0648 0649 QVector<QPolygonF> labels; 0650 QMapIterator<double, QString> iLabelCheck(_axisLabels); 0651 while (iLabelCheck.hasNext()) { 0652 iLabelCheck.next(); 0653 QRectF bound = painter->boundingRect(QRectF(), flags, iLabelCheck.value()); 0654 QPointF p; 0655 QPolygonF mappedPoly; 0656 0657 if (rotation == 0) { 0658 if (_orientation == Qt::Horizontal) { 0659 p = QPointF(plotItem()->mapXToPlot(iLabelCheck.key()), 0); 0660 } else { 0661 p = QPointF(0, plotItem()->mapYToPlot(iLabelCheck.key())); 0662 } 0663 0664 bound.moveCenter(p); 0665 mappedPoly = QPolygonF(bound); 0666 } else { 0667 if (_orientation == Qt::Horizontal) { 0668 p = QPointF(plotItem()->mapXToPlot(iLabelCheck.key()) - bound.height() * 0.5, 0); 0669 } else { 0670 p = QPointF(0, plotItem()->mapYToPlot(iLabelCheck.key()) - bound.height() * 0.5); 0671 } 0672 0673 mappedPoly = t.map(QPolygonF(bound)); 0674 mappedPoly.translate(p - bound.topLeft()); 0675 } 0676 0677 labels << mappedPoly; 0678 } 0679 0680 for (int i = 0; i < (labels.count() - 1); i++) { 0681 if (!labels[i].intersected(labels[i+1]).isEmpty()) { 0682 qreal labelSize; 0683 qreal plotSize; 0684 MajorTickMode old_override_major_ticks = _axisOverrideMajorTicks; 0685 0686 if (_orientation == Qt::Horizontal) { 0687 labelSize = qMax(labels[i].boundingRect().width(), labels[i+1].boundingRect().width()); 0688 plotSize = plotItem()->plotRect().width(); 0689 } else { 0690 labelSize = qMax(labels[i].boundingRect().height(), labels[i+1].boundingRect().height()); 0691 plotSize = plotItem()->plotRect().height(); 0692 } 0693 0694 _axisOverrideMajorTicks = convertToMajorTickMode((plotSize / labelSize) - 1, old_override_major_ticks); 0695 0696 if (_axisOverrideMajorTicks == TicksNone) { 0697 qreal scale = plotSize / (labelSize * (TicksNormal - 1)); 0698 if (scale < 1) { 0699 plotItem()->scaleAxisLabels(scale); 0700 } 0701 _axisOverrideMajorTicks = TicksCoarse; 0702 } 0703 0704 updateTicks(true); 0705 break; 0706 } 0707 } 0708 setTicksUpdated(); 0709 0710 } 0711 0712 0713 MajorTickMode PlotAxis::convertToMajorTickMode(int tickCount, MajorTickMode old_mode) { 0714 MajorTickMode mode = TicksNone; 0715 if ((tickCount >= TicksVeryFine) && (old_mode > TicksVeryFine)) { 0716 mode = TicksVeryFine; 0717 } else if ((tickCount >= TicksFine) && (old_mode > TicksFine)) { 0718 mode = TicksFine; 0719 } else if ((tickCount >= TicksNormal) && (old_mode > TicksNormal)) { 0720 mode = TicksNormal; 0721 } else if ((tickCount >= TicksCoarse) && (old_mode > TicksCoarse)) { 0722 mode = TicksCoarse; 0723 } 0724 return mode; 0725 } 0726 0727 0728 void PlotAxis::updateLogTicks(MajorTickMode tickMode) { 0729 QMap<double, QString> labels; 0730 QList<double> ticks; 0731 QList<double> minTicks; 0732 const int format_precision = 5; 0733 0734 double min = _orientation == Qt::Horizontal ? plotItem()->xMin() : plotItem()->yMin(); 0735 double max = _orientation == Qt::Horizontal ? plotItem()->xMax() : plotItem()->yMax(); 0736 0737 double tick; 0738 if (max - min <= (double)tickMode*1.5) { 0739 // show in logarithmic mode with major ticks nicely labelled and the 0740 // specified number of minor ticks between each major label 0741 tick = 1.0; 0742 } else { 0743 // show in logarithmic mode with major ticks nicely labelled and no minor ticks 0744 tick = floor((max - min) / (double)tickMode); 0745 } 0746 0747 int Low = ceil(min); 0748 int High = floor(max)+1; 0749 bool minorLabels = ((High - Low) <= 1); 0750 for (int i = Low - 1; i <= High; i+=tick) { 0751 double majorPoint = pow(10.0, i); 0752 if (majorPoint == 0) majorPoint = -350; 0753 if (i >= min && i <= max) { 0754 ticks << majorPoint; 0755 // 'x' is a sign to the plot item to write 10^i rather than 1.0x10^i 0756 labels.insert(majorPoint, QString("xe%1").arg(i)); 0757 } 0758 0759 if (tick == 1.0) { 0760 // draw minor lines 0761 bool first = true; 0762 double powMin = pow(10, min), powMax = pow(10, max); 0763 for (int j = 2; j < 10; j++) { 0764 double minorPoint = majorPoint * j; 0765 if (minorPoint >= powMin && minorPoint <= powMax) { 0766 minTicks << minorPoint; 0767 if (minorLabels && first) { 0768 labels.insert(minorPoint, QString::number(minorPoint, 'g', format_precision)); 0769 first = false; 0770 } 0771 } 0772 } 0773 } 0774 } 0775 if (minorLabels && !minTicks.isEmpty()) { 0776 double lastMinorTick = minTicks.last(); 0777 if (ticks.isEmpty() || ticks.last() < lastMinorTick) { 0778 if (labels.contains(lastMinorTick)) { 0779 labels.insert(lastMinorTick, QString::number(lastMinorTick, 'g', format_precision)); 0780 } 0781 } 0782 } 0783 0784 if (_axisMajorTicks == ticks && _axisMinorTicks == minTicks && !_dirty) { 0785 return; 0786 } 0787 0788 _dirty = false; 0789 0790 _axisMajorTicks = ticks; 0791 _axisMinorTicks = minTicks; 0792 _ticksUpdated = true; 0793 0794 _axisLabels = labels; 0795 _baseLabel.clear(); 0796 } 0797 0798 // returns true if axis is linear ticks 0799 // with no specially formatted time. 0800 bool PlotAxis::isLinearTickMode() { 0801 if (_axisLog) { 0802 return false; 0803 } 0804 0805 if (_axisInterpret) { 0806 switch (_axisDisplay) { 0807 case AXIS_DISPLAY_YYMMDDHHMMSS_SS: 0808 case AXIS_DISPLAY_DDMMYYHHMMSS_SS: 0809 case AXIS_DISPLAY_QTTEXTDATEHHMMSS_SS: 0810 case AXIS_DISPLAY_QTLOCALDATEHHMMSS_SS: 0811 case AXIS_DISPLAY_QTDATETIME_FORMAT: 0812 return false; 0813 default: 0814 return true; 0815 } 0816 } 0817 return true; 0818 } 0819 0820 void PlotAxis::updateInterpretTicks(MajorTickMode tickMode) { 0821 double min; 0822 double max; 0823 0824 if (_orientation == Qt::Horizontal) { 0825 min = plotItem()->projectionRect().left(); 0826 max = plotItem()->projectionRect().right(); 0827 } else { 0828 min = plotItem()->projectionRect().top(); 0829 max = plotItem()->projectionRect().bottom(); 0830 } 0831 0832 double range = max - min; 0833 double min_jd = convertTimeValueToJD(min); 0834 double max_jd = convertTimeValueToJD(max); 0835 double range_jd = fabs(max_jd - min_jd); 0836 double base_jd; 0837 double range_u; 0838 double tickspacing_u; 0839 double tickspacing; 0840 QString units; 0841 0842 double minimum_units = tickMode; 0843 0844 // find base_jd, range_u, units 0845 //double valid = true; 0846 if (range_jd > minimum_units*365.0*1.0e150) { 0847 _ticksUpdated = true; 0848 _axisLabels.clear(); 0849 _axisMinorTicks.clear(); 0850 _axisMajorTicks.clear(); 0851 _baseLabel.clear(); 0852 return; 0853 0854 } else if (range_jd > minimum_units*365.0) { 0855 // use years 0856 range_u = range_jd/365.25; 0857 units = tr(" [Years]"); 0858 computeMajorTickSpacing(&tickspacing_u, &_automaticMinorTickCount, tickMode, range_u); 0859 // round base to year; 0860 base_jd = floor((min_jd - (JD1900 + 0.5))/365.25) * 365.25 + (JD1900 + 0.5) + 1.0; 0861 } else if (range_jd > minimum_units) { 0862 // use days 0863 range_u = range_jd; 0864 units = tr(" [Days]"); 0865 computeMajorTickSpacing(&tickspacing_u, &_automaticMinorTickCount, tickMode, range_u); 0866 // round base to day 0867 base_jd = floor(min_jd)+1.0; 0868 } else if (range_jd > minimum_units/24.0) { 0869 // use hours 0870 range_u = range_jd*24.0; 0871 units = tr(" [Hours]"); 0872 computeMajorTickSpacing(&tickspacing_u, &_automaticMinorTickCount, tickMode, range_u, Hour); 0873 // round base to hour 0874 double d_jd = min_jd - floor(min_jd); 0875 base_jd = floor(min_jd) + (floor(d_jd*24.0/tickspacing_u)+1.0)/(24.0/tickspacing_u); 0876 } else if (range_jd > minimum_units/(24.0*60.0)) { 0877 // use minutes 0878 range_u = range_jd*24.0*60.0; 0879 units = tr(" [Minutes]"); 0880 computeMajorTickSpacing(&tickspacing_u, &_automaticMinorTickCount, tickMode, range_u, Minute); 0881 double d_jd = min_jd - floor(min_jd); 0882 base_jd = floor(min_jd) + (floor(d_jd*24.0*60.0/tickspacing_u)+1.0)/(24.0*60.0/tickspacing_u); 0883 } else { 0884 // use seconds 0885 range_u = range_jd*24.0*3600.0; 0886 units = tr(" [Seconds]"); 0887 double d_jd = min_jd - floor(min_jd); 0888 computeMajorTickSpacing(&tickspacing_u, &_automaticMinorTickCount, tickMode, range_u, Second); 0889 base_jd = floor(min_jd) + (floor(d_jd*24.0*3600.0/tickspacing_u)+1.0)/(24.0*3600.0/tickspacing_u); 0890 if (base_jd < min_jd) base_jd = min_jd; 0891 if (base_jd > max_jd) base_jd = min_jd; 0892 } 0893 0894 //TODO Why could range_u be 0? Then it hangs in while(1) 0895 if (range_u != 0) 0896 tickspacing = tickspacing_u * range/range_u; 0897 else 0898 tickspacing = range; 0899 0900 0901 0902 if (_axisForceOffsetMin) { 0903 base_jd = min_jd; 0904 } 0905 double base = (base_jd - min_jd) * range/range_jd + min; 0906 0907 int i0 = -floor((base-min)/tickspacing); 0908 0909 double tick; 0910 double first_tick; 0911 QMap<double, QString> labels; 0912 QList<double> ticks; 0913 QList<double> minTicks; 0914 0915 QString tick_label; 0916 first_tick = base+i0*tickspacing; 0917 for (int i_tick = i0; base + i_tick*tickspacing<=max; i_tick++) { 0918 tick = base+i_tick*tickspacing; 0919 ticks << tick; 0920 tick_label = '[' + QString::number(i_tick*tickspacing_u, 'g', FULL_PRECISION-2) + ']'; 0921 labels.insert(tick, tick_label); 0922 } 0923 0924 double minorTickSpacing = 0.0; 0925 int desiredTicks; 0926 if (_automaticMinorTicks) { 0927 desiredTicks = _automaticMinorTickCount; 0928 } else { 0929 desiredTicks = _axisMinorTickCount; 0930 } 0931 if (desiredTicks > 0) { 0932 minorTickSpacing = tickspacing / double(desiredTicks); 0933 } 0934 0935 if (minorTickSpacing != 0) { 0936 double firstMinorTick = (first_tick - tickspacing) + minorTickSpacing; 0937 0938 int i_minor = 0; 0939 double nextMinorTick = firstMinorTick; 0940 while (1) { 0941 nextMinorTick = firstMinorTick + (i_minor++ * minorTickSpacing); 0942 if (nextMinorTick > max || isnan(nextMinorTick)) 0943 break; 0944 if (!ticks.contains(nextMinorTick) && (nextMinorTick > min)) { 0945 minTicks << nextMinorTick; 0946 } 0947 } 0948 } 0949 0950 if (_axisMajorTicks == ticks && _axisMinorTicks == minTicks && !_dirty) { 0951 _ticksUpdated = false; 0952 return; 0953 } 0954 0955 _axisLabels = labels; 0956 _axisMinorTicks = minTicks; 0957 _axisMajorTicks = ticks; 0958 _baseLabel = convertJDToDateString(base_jd, range_jd) + units; 0959 _dirty = false; 0960 _ticksUpdated = true; 0961 0962 } 0963 0964 QString PlotAxis::statusBarString(double X) { 0965 if (_axisInterpret) { 0966 double X_jd = convertTimeValueToJD(X); 0967 double min; 0968 double max; 0969 0970 if (_orientation == Qt::Horizontal) { 0971 min = plotItem()->projectionRect().left(); 0972 max = plotItem()->projectionRect().right(); 0973 } else { 0974 min = plotItem()->projectionRect().top(); 0975 max = plotItem()->projectionRect().bottom(); 0976 } 0977 0978 double min_jd = convertTimeValueToJD(min); 0979 double max_jd = convertTimeValueToJD(max); 0980 double range_jd = fabs(max_jd - min_jd); 0981 0982 return convertJDToDateString(X_jd, range_jd/100.0); 0983 } else { 0984 return QString::number(X, 'G', FULL_PRECISION-2); 0985 } 0986 } 0987 0988 0989 void PlotAxis::updateLinearTicks(MajorTickMode tickMode) { 0990 QMap<double, QString> labels; 0991 QList<double> ticks; 0992 QList<double> minTicks; 0993 double min; 0994 double max; 0995 double R; 0996 double uR; // range in interpreted units 0997 double uMin; // min and max in interpreted units 0998 double uMax; 0999 double drdu = 1.0; // interpreted units per raw units; 1000 double rOffset = 0.0; // r = drdu*u + rOffset; 1001 double uMajorTickSpacing; // major Tick spacing in iterpreted units 1002 1003 if (_orientation == Qt::Horizontal) { 1004 min = plotItem()->projectionRect().left(); 1005 max = plotItem()->projectionRect().right(); 1006 R = plotItem()->projectionRect().width(); 1007 } else { 1008 min = plotItem()->projectionRect().top(); 1009 max = plotItem()->projectionRect().bottom(); 1010 R = plotItem()->projectionRect().height(); 1011 } 1012 1013 if (_axisInterpret) { 1014 uMin = convertJDtoDisplayTime(convertTimeValueToJD(min)); 1015 uMax = convertJDtoDisplayTime(convertTimeValueToJD(max)); 1016 uR = fabs(uMax - uMin); 1017 drdu = (max - min)/(uMax - uMin); 1018 rOffset = min - drdu * uMin; 1019 } else { 1020 uR = R; 1021 uMin = min; 1022 uMax = max; 1023 } 1024 1025 computeMajorTickSpacing(&uMajorTickSpacing, &_automaticMinorTickCount, tickMode, uR); 1026 1027 double uFirstTick; 1028 bool offset_is_min = (_axisInterpret || _axisBaseOffset || _axisBaseOffsetOverride ) && (_axisForceOffsetMin); 1029 if (offset_is_min) { 1030 uFirstTick = uMin; 1031 } else { 1032 uFirstTick = ceil(uMin / uMajorTickSpacing) * uMajorTickSpacing; 1033 } 1034 double firstTick = uFirstTick*drdu + rOffset; 1035 double majorTickSpacing = uMajorTickSpacing * drdu; 1036 1037 int i = 0; 1038 double lastTick = 12345678; 1039 while (1) { 1040 double uNextTick = uFirstTick + i++ * uMajorTickSpacing; 1041 if (fabs(uNextTick)<uMajorTickSpacing*0.5) { // fix roundoff... 1042 uNextTick = 0.0; 1043 } 1044 if (uNextTick > uMax) 1045 break; 1046 double nextTick = uNextTick * drdu + rOffset; 1047 if (lastTick == uNextTick) // prevent endless loop 1048 break; 1049 lastTick = nextTick; 1050 ticks << nextTick; 1051 // FULL_PRECISION - 2 because round off errors mean you never actually quite get 1052 // full precision... 1053 labels.insert(nextTick, QString::number(uNextTick, 'g', FULL_PRECISION-2)); 1054 } 1055 1056 double minorTickSpacing = 0; 1057 int desiredTicks; 1058 if (_automaticMinorTicks) { 1059 desiredTicks = _automaticMinorTickCount; 1060 } else { 1061 desiredTicks = _axisMinorTickCount; 1062 } 1063 if (desiredTicks > 0) { 1064 minorTickSpacing = majorTickSpacing / desiredTicks; 1065 } 1066 1067 if (minorTickSpacing != 0) { 1068 double firstMinorTick = (firstTick - majorTickSpacing) + minorTickSpacing; 1069 1070 i = 0; 1071 double nextMinorTick = firstMinorTick; 1072 while (1) { 1073 nextMinorTick = firstMinorTick + (i++ * minorTickSpacing); 1074 if (nextMinorTick > max) 1075 break; 1076 if (!ticks.contains(nextMinorTick) && nextMinorTick > min) { 1077 minTicks << nextMinorTick; 1078 } 1079 } 1080 } 1081 1082 if (_axisMajorTicks == ticks && _axisMinorTicks == minTicks && !_dirty) { 1083 return; 1084 } 1085 1086 _dirty = false; 1087 1088 _axisMajorTicks = ticks; 1089 _axisMinorTicks = minTicks; 1090 _ticksUpdated = true; 1091 1092 _axisLabels.clear(); 1093 _baseLabel.clear(); 1094 1095 int longest = 0, shortest = 1000; 1096 double base=10; 1097 QMapIterator<double, QString> iLabel(labels); 1098 while (iLabel.hasNext()) { 1099 iLabel.next(); 1100 if (iLabel.value().length() < shortest) { 1101 shortest = iLabel.value().length(); 1102 base = iLabel.key(); 1103 } 1104 if (iLabel.value().length() > longest) { 1105 longest = iLabel.value().length(); 1106 } 1107 } 1108 if (offset_is_min) { 1109 base = ticks[0]; 1110 } 1111 1112 // (shortest > 3) so that you don't use automatic base/offset mode when 1113 // it wouldn't actually take up less space. 1114 if (_axisBaseOffset || ((longest > _axisSignificantDigits)&&(shortest>3)) || _axisBaseOffsetOverride ) { 1115 _baseLabel = QString::number(base, 'g', FULL_PRECISION-2); 1116 QMapIterator<double, QString> i(labels); 1117 while (i.hasNext()) { 1118 i.next(); 1119 double offset; 1120 offset = i.key() - base; 1121 QString label, num; 1122 if (offset < 0) { 1123 label += "-["; 1124 offset = offset * -1; 1125 } else if (offset > 0) { 1126 label += "+["; 1127 } 1128 1129 if (offset==0.0) { 1130 num = "[0"; 1131 } else if ((fabs(offset)>9.9E3)||(fabs(offset)<0.99E-3)) { 1132 num = QString::number(offset, 'e', 1); 1133 } else { 1134 num = QString::number(offset, 'g', 5); 1135 } 1136 1137 label = label + num + ']'; 1138 _axisLabels.insert(i.key(), label); 1139 } 1140 } else { 1141 _axisLabels = labels; 1142 } 1143 } 1144 1145 void PlotAxis::updateTicks(bool useOverrideTicks) { 1146 MajorTickMode majorTickCount; 1147 if (useOverrideTicks) { 1148 majorTickCount = _axisOverrideMajorTicks; 1149 } else { 1150 _axisOverrideMajorTicks = _axisMajorTickMode; 1151 majorTickCount = _axisMajorTickMode; 1152 _axisBaseOffsetOverride = false; 1153 } 1154 1155 plotItem()->updateScale(); 1156 1157 if (_axisLog) { 1158 updateLogTicks(majorTickCount); 1159 return; 1160 } else if (isLinearTickMode()) { 1161 updateLinearTicks(majorTickCount); 1162 return; 1163 } else { 1164 updateInterpretTicks(majorTickCount); 1165 return; 1166 } 1167 } 1168 1169 1170 void PlotAxis::copyProperties(PlotAxis *source) { 1171 if (source) { 1172 setAxisVisible(source->isAxisVisible()); 1173 setAxisLog(source->axisLog()); 1174 setAxisReversed(source->axisReversed()); 1175 setAxisBaseOffset(source->axisBaseOffset()); 1176 setAxisForceOffsetMin(source->axisForceOffsetMin()); 1177 setAxisInterpret(source->axisInterpret()); 1178 setAxisInterpretation(source->axisInterpretation()); 1179 setAxisDisplay(source->axisDisplay()); 1180 setAxisDisplayFormatString(source->axisDisplayFormatString()); 1181 setAxisMajorTickMode(source->axisMajorTickMode()); 1182 setAxisMinorTickCount(source->axisMinorTickCount()); 1183 setAxisAutoMinorTicks(source->axisAutoMinorTicks()); 1184 setDrawAxisMajorTicks(source->drawAxisMajorTicks()); 1185 setDrawAxisMinorTicks(source->drawAxisMinorTicks()); 1186 setDrawAxisMajorGridLines(source->drawAxisMajorGridLines()); 1187 setDrawAxisMinorGridLines(source->drawAxisMinorGridLines()); 1188 setAxisMajorGridLineColor(source->axisMajorGridLineColor()); 1189 setAxisMinorGridLineColor(source->axisMinorGridLineColor()); 1190 setAxisMajorGridLineStyle(source->axisMajorGridLineStyle()); 1191 setAxisMinorGridLineStyle(source->axisMinorGridLineStyle()); 1192 setAxisMajorGridLineWidth(source->axisMinorGridLineWidth()); 1193 setAxisMinorGridLineWidth(source->axisMinorGridLineWidth()); 1194 setAxisSignificantDigits(source->axisSignificantDigits()); 1195 setAxisLabelRotation(source->axisLabelRotation()); 1196 setAxisZoomMode(source->axisZoomMode()); 1197 } 1198 } 1199 1200 void PlotAxis::saveAsDialogDefaults(const QString &group) const { 1201 dialogDefaults().setValue(group+"Visible", QVariant(isAxisVisible()).toString()); 1202 dialogDefaults().setValue(group+"Log", QVariant(axisLog()).toString()); 1203 dialogDefaults().setValue(group+"Reversed", QVariant(axisReversed()).toString()); 1204 dialogDefaults().setValue(group+"AutoBaseOffset", QVariant(axisAutoBaseOffset()).toString()); 1205 dialogDefaults().setValue(group+"BaseOffset", QVariant(axisBaseOffset()).toString()); 1206 dialogDefaults().setValue(group+"ForceOffsetMin", QVariant(axisForceOffsetMin()).toString()); 1207 dialogDefaults().setValue(group+"Interpret", QVariant(axisInterpret()).toString()); 1208 dialogDefaults().setValue(group+"Interpretation", QVariant(axisInterpretation()).toString()); 1209 dialogDefaults().setValue(group+"Display", QVariant(axisDisplay()).toString()); 1210 dialogDefaults().setValue(group+"DisplayFormatString", QVariant(axisDisplayFormatString()).toString()); 1211 dialogDefaults().setValue(group+"Timezone", QVariant(timezoneName())); 1212 dialogDefaults().setValue(group+"MajorTickMode", QVariant(axisMajorTickMode()).toString()); 1213 dialogDefaults().setValue(group+"MinorTickCount", QVariant(axisMinorTickCount()).toString()); 1214 dialogDefaults().setValue(group+"AutoMinorTickCount", QVariant(axisAutoMinorTicks()).toString()); 1215 dialogDefaults().setValue(group+"DrawMajorTicks", QVariant(drawAxisMajorTicks()).toString()); 1216 dialogDefaults().setValue(group+"DrawMajorTicks", QVariant(drawAxisMajorTicks()).toString()); 1217 dialogDefaults().setValue(group+"DrawMinorTicks", QVariant(drawAxisMinorTicks()).toString()); 1218 dialogDefaults().setValue(group+"DrawMajorGridLines", QVariant(drawAxisMajorGridLines()).toString()); 1219 dialogDefaults().setValue(group+"DrawMinorGridLines", QVariant(drawAxisMinorGridLines()).toString()); 1220 dialogDefaults().setValue(group+"DrawMajorGridLinecolor", QVariant(axisMajorGridLineColor()).toString()); 1221 dialogDefaults().setValue(group+"DrawMinorGridLinecolor", QVariant(axisMinorGridLineColor()).toString()); 1222 dialogDefaults().setValue(group+"DrawMajorGridLinestyle", QVariant((int)axisMajorGridLineStyle()).toString()); 1223 dialogDefaults().setValue(group+"DrawMinorGridLinestyle", QVariant((int)axisMinorGridLineStyle()).toString()); 1224 dialogDefaults().setValue(group+"DrawMajorGridLinewidth", QVariant(axisMajorGridLineWidth()).toString()); 1225 dialogDefaults().setValue(group+"DrawMinorGridLinewidth", QVariant(axisMinorGridLineWidth()).toString()); 1226 dialogDefaults().setValue(group+"SignificantDigits", QVariant(axisSignificantDigits()).toString()); 1227 dialogDefaults().setValue(group+"Rotation", QVariant(axisLabelRotation()).toString()); 1228 } 1229 1230 void PlotAxis::saveInPlot(QXmlStreamWriter &xml, QString axisId) { 1231 xml.writeStartElement("plotaxis"); 1232 xml.writeAttribute("id", axisId); 1233 xml.writeAttribute("visible", QVariant(isAxisVisible()).toString()); 1234 xml.writeAttribute("log", QVariant(axisLog()).toString()); 1235 xml.writeAttribute("reversed", QVariant(axisReversed()).toString()); 1236 xml.writeAttribute("autobaseoffset", QVariant(axisAutoBaseOffset()).toString()); 1237 xml.writeAttribute("baseoffset", QVariant(axisBaseOffset()).toString()); 1238 xml.writeAttribute("forceoffsetmin", QVariant(axisForceOffsetMin()).toString()); 1239 xml.writeAttribute("interpret", QVariant(axisInterpret()).toString()); 1240 xml.writeAttribute("interpretation", QVariant(axisInterpretation()).toString()); 1241 xml.writeAttribute("display", QVariant(axisDisplay()).toString()); 1242 xml.writeAttribute("displayformatstring", QVariant(axisDisplayFormatString()).toString()); 1243 xml.writeAttribute("majortickmode", QVariant(axisMajorTickMode()).toString()); 1244 xml.writeAttribute("minortickcount", QVariant(axisMinorTickCount()).toString()); 1245 xml.writeAttribute("autominortickcount", QVariant(axisAutoMinorTicks()).toString()); 1246 xml.writeAttribute("drawmajorticks", QVariant(drawAxisMajorTicks()).toString()); 1247 xml.writeAttribute("drawminorticks", QVariant(drawAxisMinorTicks()).toString()); 1248 xml.writeAttribute("drawmajorgridlines", QVariant(drawAxisMajorGridLines()).toString()); 1249 xml.writeAttribute("drawminorgridlines", QVariant(drawAxisMinorGridLines()).toString()); 1250 xml.writeAttribute("drawmajorgridlinecolor", QVariant(axisMajorGridLineColor()).toString()); 1251 xml.writeAttribute("drawminorgridlinecolor", QVariant(axisMinorGridLineColor()).toString()); 1252 xml.writeAttribute("drawmajorgridlinestyle", QVariant((int)axisMajorGridLineStyle()).toString()); 1253 xml.writeAttribute("drawminorgridlinestyle", QVariant((int)axisMinorGridLineStyle()).toString()); 1254 xml.writeAttribute("drawmajorgridlinewidth", QVariant(axisMajorGridLineWidth()).toString()); 1255 xml.writeAttribute("drawminorgridlinewidth", QVariant(axisMinorGridLineWidth()).toString()); 1256 xml.writeAttribute("significantdigits", QVariant(axisSignificantDigits()).toString()); 1257 xml.writeAttribute("rotation", QVariant(axisLabelRotation()).toString()); 1258 xml.writeAttribute("zoommode", QVariant(axisZoomMode()).toString()); 1259 xml.writeAttribute("timezonename", _timeZone.tzName()); 1260 xml.writeAttribute("timezoneoffset", QVariant(_timeZone.gmtOffset(0)).toString()); 1261 _axisPlotMarkers.saveInPlot(xml); 1262 xml.writeEndElement(); 1263 } 1264 1265 1266 bool PlotAxis::configureFromXml(QXmlStreamReader &xml, ObjectStore *store) { 1267 bool validTag = true; 1268 1269 QString primaryTag = xml.name().toString(); 1270 QXmlStreamAttributes attrs = xml.attributes(); 1271 QStringRef av = attrs.value("visible"); 1272 if (!av.isNull()) { 1273 setAxisVisible(QVariant(av.toString()).toBool()); 1274 } 1275 av = attrs.value("log"); 1276 if (!av.isNull()) { 1277 setAxisLog(QVariant(av.toString()).toBool()); 1278 } 1279 av = attrs.value("reversed"); 1280 if (!av.isNull()) { 1281 setAxisReversed(QVariant(av.toString()).toBool()); 1282 } 1283 av = attrs.value("autobaseoffset"); 1284 if (!av.isNull()) { 1285 setAxisAutoBaseOffset(QVariant(av.toString()).toBool()); 1286 } 1287 av = attrs.value("baseoffset"); 1288 if (!av.isNull()) { 1289 setAxisBaseOffset(QVariant(av.toString()).toBool()); 1290 } 1291 av = attrs.value("forceoffsetmin"); 1292 if (!av.isNull()) { 1293 setAxisForceOffsetMin(QVariant(av.toString()).toBool()); 1294 } 1295 av = attrs.value("interpret"); 1296 if (!av.isNull()) { 1297 setAxisInterpret(QVariant(av.toString()).toBool()); 1298 } 1299 av = attrs.value("interpretation"); 1300 if (!av.isNull()) { 1301 setAxisInterpretation((AxisInterpretationType)QVariant(av.toString()).toInt()); 1302 } 1303 av = attrs.value("display"); 1304 if (!av.isNull()) { 1305 setAxisDisplay((AxisDisplayType)QVariant(av.toString()).toInt()); 1306 } 1307 av = attrs.value("displayformatstring"); 1308 if (!av.isNull()) { 1309 setAxisDisplayFormatString(av.toString()); 1310 } 1311 av = attrs.value("majortickmode"); 1312 if (!av.isNull()) { 1313 setAxisMajorTickMode((MajorTickMode)QVariant(av.toString()).toInt()); 1314 } 1315 av = attrs.value("minortickcount"); 1316 if (!av.isNull()) { 1317 setAxisMinorTickCount(QVariant(av.toString()).toInt()); 1318 } 1319 av = attrs.value("autominortickcount"); 1320 if (!av.isNull()) { 1321 setAxisAutoMinorTicks(QVariant(av.toString()).toBool()); 1322 } 1323 av = attrs.value("drawmajorticks"); 1324 if (!av.isNull()) { 1325 setDrawAxisMajorTicks(QVariant(av.toString()).toBool()); 1326 } 1327 av = attrs.value("drawminorticks"); 1328 if (!av.isNull()) { 1329 setDrawAxisMinorTicks(QVariant(av.toString()).toBool()); 1330 } 1331 av = attrs.value("drawmajorgridlines"); 1332 if (!av.isNull()) { 1333 setDrawAxisMajorGridLines(QVariant(av.toString()).toBool()); 1334 } 1335 av = attrs.value("drawminorgridlines"); 1336 if (!av.isNull()) { 1337 setDrawAxisMinorGridLines(QVariant(av.toString()).toBool()); 1338 } 1339 av = attrs.value("drawmajorgridlinecolor"); 1340 if (!av.isNull()) { 1341 setAxisMajorGridLineColor(QColor(av.toString())); 1342 } 1343 av = attrs.value("drawminorgridlinecolor"); 1344 if (!av.isNull()) { 1345 setAxisMinorGridLineColor(QColor(av.toString())); 1346 } 1347 av = attrs.value("drawmajorgridlinestyle"); 1348 if (!av.isNull()) { 1349 setAxisMajorGridLineStyle((Qt::PenStyle)QVariant(av.toString()).toInt()); 1350 } 1351 av = attrs.value("drawminorgridlinestyle"); 1352 if (!av.isNull()) { 1353 setAxisMinorGridLineStyle((Qt::PenStyle)QVariant(av.toString()).toInt()); 1354 } 1355 av = attrs.value("drawmajorgridlinewidth"); 1356 if (!av.isNull()) { 1357 setAxisMajorGridLineWidth((qreal)QVariant(av.toString()).toDouble()); 1358 } 1359 av = attrs.value("drawminorgridlinewidth"); 1360 if (!av.isNull()) { 1361 setAxisMinorGridLineWidth((qreal)QVariant(av.toString()).toDouble()); 1362 } 1363 av = attrs.value("significantdigits"); 1364 if (!av.isNull()) { 1365 setAxisSignificantDigits(QVariant(av.toString()).toInt()); 1366 } 1367 av = attrs.value("rotation"); 1368 if (!av.isNull()) { 1369 setAxisLabelRotation(QVariant(av.toString()).toInt()); 1370 } 1371 av = attrs.value("zoommode"); 1372 if (!av.isNull()) { 1373 setAxisZoomMode((PlotAxis::ZoomMode)av.toString().toInt()); 1374 } 1375 av = attrs.value("timezonename"); 1376 if (!av.isNull()) { 1377 setTimezoneName(av.toString()); 1378 // fixme: handle unrecognised timezone name by using timezoneoffset 1379 } 1380 1381 QString expectedEnd; 1382 while (!(xml.isEndElement() && (xml.name().toString() == primaryTag))) { 1383 if (xml.isStartElement() && xml.name().toString() == "plotmarkers") { 1384 validTag = _axisPlotMarkers.configureFromXml(xml, store); 1385 } else if (xml.isEndElement()) { 1386 if (xml.name().toString() != expectedEnd) { 1387 validTag = false; 1388 break; 1389 } 1390 } 1391 xml.readNext(); 1392 } 1393 1394 return validTag; 1395 } 1396 1397 1398 } 1399 1400 // vim: ts=2 sw=2 et