File indexing completed on 2024-05-12 15:54:10
0001 /* 0002 * Copyright (C) 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved. 0003 * 0004 * This file is part of the KD Chart library. 0005 * 0006 * This program is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU General Public License as 0008 * published by the Free Software Foundation; either version 2 of 0009 * the License, or (at your option) any later version. 0010 * 0011 * This program is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0014 * GNU General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU General Public License 0017 * along with this program. If not, see <https://www.gnu.org/licenses/>. 0018 */ 0019 0020 #include "KChartAbstractAxis.h" 0021 #include "KChartAbstractAxis_p.h" 0022 #include "KChartAbstractDiagram.h" 0023 #include "KChartAbstractCartesianDiagram.h" 0024 #include "KChartEnums.h" 0025 #include "KChartMeasure.h" 0026 #include "KChartMath_p.h" 0027 0028 using namespace KChart; 0029 0030 #define d d_func() 0031 0032 AbstractAxis::Private::Private( AbstractDiagram* diagram, AbstractAxis* axis ) 0033 : observer( nullptr ) 0034 , mDiagram( diagram ) 0035 , mAxis( axis ) 0036 { 0037 // Note: We do NOT call setDiagram( diagram, axis ); 0038 // but it is called in AbstractAxis::delayedInit() instead! 0039 } 0040 0041 AbstractAxis::Private::~Private() 0042 { 0043 delete observer; 0044 observer = nullptr; 0045 } 0046 0047 bool AbstractAxis::Private::setDiagram( AbstractDiagram* diagram_, bool delayedInit ) 0048 { 0049 AbstractDiagram* diagram = delayedInit ? mDiagram : diagram_; 0050 if ( delayedInit ) { 0051 mDiagram = nullptr; 0052 } 0053 0054 // do not set a diagram again that was already set 0055 if ( diagram && 0056 ((diagram == mDiagram) || secondaryDiagrams.contains( diagram )) ) 0057 return false; 0058 0059 bool bNewDiagramStored = false; 0060 if ( ! mDiagram ) { 0061 mDiagram = diagram; 0062 delete observer; 0063 if ( mDiagram ) { 0064 observer = new DiagramObserver( mDiagram, mAxis ); 0065 const bool con = connect( observer, SIGNAL(diagramDataChanged(AbstractDiagram*)), 0066 mAxis, SIGNAL(coordinateSystemChanged()) ); 0067 Q_UNUSED( con ) 0068 Q_ASSERT( con ); 0069 bNewDiagramStored = true; 0070 } else { 0071 observer = nullptr; 0072 } 0073 } else { 0074 if ( diagram ) 0075 secondaryDiagrams.enqueue( diagram ); 0076 } 0077 return bNewDiagramStored; 0078 } 0079 0080 void AbstractAxis::Private::unsetDiagram( AbstractDiagram* diagram ) 0081 { 0082 if ( diagram == mDiagram ) { 0083 mDiagram = nullptr; 0084 delete observer; 0085 observer = nullptr; 0086 } else { 0087 secondaryDiagrams.removeAll( diagram ); 0088 } 0089 if ( !secondaryDiagrams.isEmpty() ) { 0090 AbstractDiagram *nextDiagram = secondaryDiagrams.dequeue(); 0091 setDiagram( nextDiagram ); 0092 } 0093 } 0094 0095 bool AbstractAxis::Private::hasDiagram( AbstractDiagram* diagram ) const 0096 { 0097 return diagram == mDiagram || secondaryDiagrams.contains( diagram ); 0098 } 0099 0100 void AbstractAxis::Private::updateLayouts() 0101 { 0102 if ( CartesianAxis* cartesianAxis = qobject_cast< CartesianAxis* >( mAxis ) ) { 0103 cartesianAxis->layoutPlanes(); 0104 } else { 0105 mAxis->update(); 0106 } 0107 } 0108 0109 AbstractAxis::AbstractAxis ( AbstractDiagram* diagram ) 0110 : AbstractArea( new Private( diagram, this ) ) 0111 { 0112 init(); 0113 QTimer::singleShot(0, this, SLOT(delayedInit())); 0114 } 0115 0116 AbstractAxis::~AbstractAxis() 0117 { 0118 d->mDiagram = nullptr; 0119 d->secondaryDiagrams.clear(); 0120 } 0121 0122 0123 void AbstractAxis::init() 0124 { 0125 Measure m( 14, KChartEnums::MeasureCalculationModeAuto, KChartEnums::MeasureOrientationAuto ); 0126 d->textAttributes.setFontSize( m ); 0127 m.setValue( 6 ); 0128 m.setCalculationMode( KChartEnums::MeasureCalculationModeAbsolute ); 0129 d->textAttributes.setMinimalFontSize( m ); 0130 if ( d->diagram() ) 0131 createObserver( d->diagram() ); 0132 } 0133 0134 void AbstractAxis::delayedInit() 0135 { 0136 // We call setDiagram() here, because the c'tor of Private 0137 // only has stored the pointers, but it did not call setDiagram(). 0138 if ( d ) 0139 d->setDiagram( nullptr, true /* delayedInit */ ); 0140 } 0141 0142 bool AbstractAxis::compare( const AbstractAxis* other ) const 0143 { 0144 if ( other == this ) { 0145 return true; 0146 } 0147 if ( !other ) { 0148 return false; 0149 } 0150 0151 return ( static_cast<const AbstractAreaBase*>(this)->compare( other ) ) && 0152 (textAttributes() == other->textAttributes()) && 0153 (labels() == other->labels()) && 0154 (shortLabels() == other->shortLabels()); 0155 } 0156 0157 0158 const QString AbstractAxis::customizedLabel( const QString& label ) const 0159 { 0160 return label; 0161 } 0162 0163 0164 void AbstractAxis::createObserver( AbstractDiagram* diagram ) 0165 { 0166 d->setDiagram( diagram ); 0167 } 0168 0169 void AbstractAxis::deleteObserver( AbstractDiagram* diagram ) 0170 { 0171 d->unsetDiagram( diagram ); 0172 } 0173 0174 void AbstractAxis::connectSignals() 0175 { 0176 if ( d->observer ) { 0177 const bool con = connect( d->observer, SIGNAL(diagramDataChanged(AbstractDiagram*)), 0178 this, SIGNAL(coordinateSystemChanged()) ); 0179 Q_UNUSED( con ); 0180 Q_ASSERT( con ); 0181 } 0182 } 0183 0184 void AbstractAxis::setTextAttributes( const TextAttributes &a ) 0185 { 0186 if ( d->textAttributes == a ) 0187 return; 0188 0189 d->textAttributes = a; 0190 d->updateLayouts(); 0191 } 0192 0193 TextAttributes AbstractAxis::textAttributes() const 0194 { 0195 return d->textAttributes; 0196 } 0197 0198 0199 void AbstractAxis::setRulerAttributes( const RulerAttributes &a ) 0200 { 0201 d->rulerAttributes = a; 0202 d->updateLayouts(); 0203 } 0204 0205 RulerAttributes AbstractAxis::rulerAttributes() const 0206 { 0207 return d->rulerAttributes; 0208 } 0209 0210 void AbstractAxis::setLabels( const QStringList& list ) 0211 { 0212 if ( d->hardLabels == list ) 0213 return; 0214 0215 d->hardLabels = list; 0216 d->updateLayouts(); 0217 } 0218 0219 QStringList AbstractAxis::labels() const 0220 { 0221 return d->hardLabels; 0222 } 0223 0224 void AbstractAxis::setShortLabels( const QStringList& list ) 0225 { 0226 if ( d->hardShortLabels == list ) 0227 return; 0228 0229 d->hardShortLabels = list; 0230 d->updateLayouts(); 0231 } 0232 0233 QStringList AbstractAxis::shortLabels() const 0234 { 0235 return d->hardShortLabels; 0236 } 0237 0238 const AbstractCoordinatePlane* AbstractAxis::coordinatePlane() const 0239 { 0240 if ( d->diagram() ) 0241 return d->diagram()->coordinatePlane(); 0242 return nullptr; 0243 } 0244 0245 const AbstractDiagram * KChart::AbstractAxis::diagram() const 0246 { 0247 return d->diagram(); 0248 } 0249 0250 bool KChart::AbstractAxis::observedBy( AbstractDiagram * diagram ) const 0251 { 0252 return d->hasDiagram( diagram ); 0253 } 0254 0255 void KChart::AbstractAxis::update() 0256 { 0257 if ( d->diagram() ) 0258 d->diagram()->update(); 0259 }