1 /*
2 * Copyright (C) 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved.
3 *
4 * This file is part of the KD Chart library.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of
9 * the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20 #include "KChartAbstractAxis.h"
21 #include "KChartAbstractAxis_p.h"
22 #include "KChartAbstractDiagram.h"
23 #include "KChartAbstractCartesianDiagram.h"
24 #include "KChartEnums.h"
25 #include "KChartMeasure.h"
26 #include "KChartMath_p.h"
27
28 using namespace KChart;
29
30 #define d d_func()
31
Private(AbstractDiagram * diagram,AbstractAxis * axis)32 AbstractAxis::Private::Private( AbstractDiagram* diagram, AbstractAxis* axis )
33 : observer( nullptr )
34 , mDiagram( diagram )
35 , mAxis( axis )
36 {
37 // Note: We do NOT call setDiagram( diagram, axis );
38 // but it is called in AbstractAxis::delayedInit() instead!
39 }
40
~Private()41 AbstractAxis::Private::~Private()
42 {
43 delete observer;
44 observer = nullptr;
45 }
46
setDiagram(AbstractDiagram * diagram_,bool delayedInit)47 bool AbstractAxis::Private::setDiagram( AbstractDiagram* diagram_, bool delayedInit )
48 {
49 AbstractDiagram* diagram = delayedInit ? mDiagram : diagram_;
50 if ( delayedInit ) {
51 mDiagram = nullptr;
52 }
53
54 // do not set a diagram again that was already set
55 if ( diagram &&
56 ((diagram == mDiagram) || secondaryDiagrams.contains( diagram )) )
57 return false;
58
59 bool bNewDiagramStored = false;
60 if ( ! mDiagram ) {
61 mDiagram = diagram;
62 delete observer;
63 if ( mDiagram ) {
64 observer = new DiagramObserver( mDiagram, mAxis );
65 const bool con = connect( observer, SIGNAL(diagramDataChanged(AbstractDiagram*)),
66 mAxis, SIGNAL(coordinateSystemChanged()) );
67 Q_UNUSED( con )
68 Q_ASSERT( con );
69 bNewDiagramStored = true;
70 } else {
71 observer = nullptr;
72 }
73 } else {
74 if ( diagram )
75 secondaryDiagrams.enqueue( diagram );
76 }
77 return bNewDiagramStored;
78 }
79
unsetDiagram(AbstractDiagram * diagram)80 void AbstractAxis::Private::unsetDiagram( AbstractDiagram* diagram )
81 {
82 if ( diagram == mDiagram ) {
83 mDiagram = nullptr;
84 delete observer;
85 observer = nullptr;
86 } else {
87 secondaryDiagrams.removeAll( diagram );
88 }
89 if ( !secondaryDiagrams.isEmpty() ) {
90 AbstractDiagram *nextDiagram = secondaryDiagrams.dequeue();
91 setDiagram( nextDiagram );
92 }
93 }
94
hasDiagram(AbstractDiagram * diagram) const95 bool AbstractAxis::Private::hasDiagram( AbstractDiagram* diagram ) const
96 {
97 return diagram == mDiagram || secondaryDiagrams.contains( diagram );
98 }
99
updateLayouts()100 void AbstractAxis::Private::updateLayouts()
101 {
102 if ( CartesianAxis* cartesianAxis = qobject_cast< CartesianAxis* >( mAxis ) ) {
103 cartesianAxis->layoutPlanes();
104 } else {
105 mAxis->update();
106 }
107 }
108
AbstractAxis(AbstractDiagram * diagram)109 AbstractAxis::AbstractAxis ( AbstractDiagram* diagram )
110 : AbstractArea( new Private( diagram, this ) )
111 {
112 init();
113 QTimer::singleShot(0, this, SLOT(delayedInit()));
114 }
115
~AbstractAxis()116 AbstractAxis::~AbstractAxis()
117 {
118 d->mDiagram = nullptr;
119 d->secondaryDiagrams.clear();
120 }
121
122
init()123 void AbstractAxis::init()
124 {
125 Measure m( 14, KChartEnums::MeasureCalculationModeAuto, KChartEnums::MeasureOrientationAuto );
126 d->textAttributes.setFontSize( m );
127 m.setValue( 6 );
128 m.setCalculationMode( KChartEnums::MeasureCalculationModeAbsolute );
129 d->textAttributes.setMinimalFontSize( m );
130 if ( d->diagram() )
131 createObserver( d->diagram() );
132 }
133
delayedInit()134 void AbstractAxis::delayedInit()
135 {
136 // We call setDiagram() here, because the c'tor of Private
137 // only has stored the pointers, but it did not call setDiagram().
138 if ( d )
139 d->setDiagram( nullptr, true /* delayedInit */ );
140 }
141
compare(const AbstractAxis * other) const142 bool AbstractAxis::compare( const AbstractAxis* other ) const
143 {
144 if ( other == this ) {
145 return true;
146 }
147 if ( !other ) {
148 return false;
149 }
150
151 return ( static_cast<const AbstractAreaBase*>(this)->compare( other ) ) &&
152 (textAttributes() == other->textAttributes()) &&
153 (labels() == other->labels()) &&
154 (shortLabels() == other->shortLabels());
155 }
156
157
customizedLabel(const QString & label) const158 const QString AbstractAxis::customizedLabel( const QString& label ) const
159 {
160 return label;
161 }
162
163
createObserver(AbstractDiagram * diagram)164 void AbstractAxis::createObserver( AbstractDiagram* diagram )
165 {
166 d->setDiagram( diagram );
167 }
168
deleteObserver(AbstractDiagram * diagram)169 void AbstractAxis::deleteObserver( AbstractDiagram* diagram )
170 {
171 d->unsetDiagram( diagram );
172 }
173
connectSignals()174 void AbstractAxis::connectSignals()
175 {
176 if ( d->observer ) {
177 const bool con = connect( d->observer, SIGNAL(diagramDataChanged(AbstractDiagram*)),
178 this, SIGNAL(coordinateSystemChanged()) );
179 Q_UNUSED( con );
180 Q_ASSERT( con );
181 }
182 }
183
setTextAttributes(const TextAttributes & a)184 void AbstractAxis::setTextAttributes( const TextAttributes &a )
185 {
186 if ( d->textAttributes == a )
187 return;
188
189 d->textAttributes = a;
190 d->updateLayouts();
191 }
192
textAttributes() const193 TextAttributes AbstractAxis::textAttributes() const
194 {
195 return d->textAttributes;
196 }
197
198
setRulerAttributes(const RulerAttributes & a)199 void AbstractAxis::setRulerAttributes( const RulerAttributes &a )
200 {
201 d->rulerAttributes = a;
202 d->updateLayouts();
203 }
204
rulerAttributes() const205 RulerAttributes AbstractAxis::rulerAttributes() const
206 {
207 return d->rulerAttributes;
208 }
209
setLabels(const QStringList & list)210 void AbstractAxis::setLabels( const QStringList& list )
211 {
212 if ( d->hardLabels == list )
213 return;
214
215 d->hardLabels = list;
216 d->updateLayouts();
217 }
218
labels() const219 QStringList AbstractAxis::labels() const
220 {
221 return d->hardLabels;
222 }
223
setShortLabels(const QStringList & list)224 void AbstractAxis::setShortLabels( const QStringList& list )
225 {
226 if ( d->hardShortLabels == list )
227 return;
228
229 d->hardShortLabels = list;
230 d->updateLayouts();
231 }
232
shortLabels() const233 QStringList AbstractAxis::shortLabels() const
234 {
235 return d->hardShortLabels;
236 }
237
coordinatePlane() const238 const AbstractCoordinatePlane* AbstractAxis::coordinatePlane() const
239 {
240 if ( d->diagram() )
241 return d->diagram()->coordinatePlane();
242 return nullptr;
243 }
244
diagram() const245 const AbstractDiagram * KChart::AbstractAxis::diagram() const
246 {
247 return d->diagram();
248 }
249
observedBy(AbstractDiagram * diagram) const250 bool KChart::AbstractAxis::observedBy( AbstractDiagram * diagram ) const
251 {
252 return d->hasDiagram( diagram );
253 }
254
update()255 void KChart::AbstractAxis::update()
256 {
257 if ( d->diagram() )
258 d->diagram()->update();
259 }
260