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 "mainwindow.h"
21 
22 #include <KChartChart>
23 #include <KChartDatasetProxyModel>
24 #include <KChartAbstractCoordinatePlane>
25 #include <KChartBarDiagram>
26 #include <KChartTextAttributes>
27 #include <KChartRelativePosition>
28 #include <KChartPosition>
29 
30 
31 #include <QDebug>
32 #include <QPainter>
33 
34 using namespace KChart;
35 
MainWindow(QWidget * parent)36 MainWindow::MainWindow( QWidget* parent ) :
37     QWidget( parent )
38 {
39     setupUi( this );
40 
41     QHBoxLayout* chartLayout = new QHBoxLayout( chartFrame );
42     m_chart = new Chart();
43     chartLayout->addWidget( m_chart );
44 
45     m_model.loadFromCSV( ":/data" );
46 
47     // Set up the diagram
48     m_bars = new BarDiagram();
49     m_bars->setModel( &m_model );
50 
51     QPen pen(  m_bars->pen() );
52     pen.setColor( Qt::darkGray );
53     pen.setWidth( 1 );
54     m_bars->setPen( pen );
55     m_chart->coordinatePlane()->replaceDiagram( m_bars );
56     m_chart->setGlobalLeadingTop( 20 );
57 
58     scopeCommonRB->setFocus( Qt::OtherFocusReason );
59     scopeCommonRB->setChecked( true );
60     paintValuesCB->setChecked( true );
61 }
62 
63 
on_scopeOneBarRB_toggled(bool checked)64 void MainWindow::on_scopeOneBarRB_toggled(  bool checked )
65 {
66     if ( checked ) {
67         scopeBarDatasetSB->setDisabled( false );
68         scopeBarItemSB->setDisabled(    false );
69         scopeDatasetSB->setDisabled(    true );
70         populateWidgets();
71     }
72 }
on_scopeBarDatasetSB_valueChanged(int i)73 void MainWindow::on_scopeBarDatasetSB_valueChanged( int i )
74 {
75     Q_UNUSED(i)
76     populateWidgets();
77 }
on_scopeBarItemSB_valueChanged(int i)78 void MainWindow::on_scopeBarItemSB_valueChanged(    int i )
79 {
80     Q_UNUSED(i)
81     populateWidgets();
82 }
on_scopeDatasetRB_toggled(bool checked)83 void MainWindow::on_scopeDatasetRB_toggled( bool checked )
84 {
85     if ( checked ) {
86         scopeBarDatasetSB->setDisabled( true );
87         scopeBarItemSB->setDisabled(    true );
88         scopeDatasetSB->setDisabled(    false );
89         populateWidgets();
90     }
91 }
on_scopeDatasetSB_valueChanged(int i)92 void MainWindow::on_scopeDatasetSB_valueChanged( int i )
93 {
94     Q_UNUSED(i)
95     populateWidgets();
96 }
on_scopeCommonRB_toggled(bool checked)97 void MainWindow::on_scopeCommonRB_toggled( bool checked )
98 {
99     if ( checked ) {
100         scopeBarDatasetSB->setDisabled( true );
101         scopeBarItemSB->setDisabled(    true );
102         scopeDatasetSB->setDisabled(    true );
103         populateWidgets();
104     }
105 }
106 
on_paintValuesCB_toggled(bool checked)107 void MainWindow::on_paintValuesCB_toggled( bool checked )
108 {
109     DataValueAttributes da( attributes() );
110     da.setVisible( checked );
111     setAttributes( da );
112 
113     m_chart->update();
114 }
115 
on_fontCombo_currentIndexChanged(const QString & text)116 void MainWindow::on_fontCombo_currentIndexChanged( const QString & text )
117 {
118     DataValueAttributes da( attributes() );
119     TextAttributes ta( da.textAttributes() );
120     QFont font( text );
121     ta.setFont( font );
122     da.setTextAttributes( ta );
123     setAttributes( da );
124 
125     m_chart->update();
126 }
127 
on_relativeSizeSB_valueChanged(int i)128 void MainWindow::on_relativeSizeSB_valueChanged( int i )
129 {
130     DataValueAttributes da( attributes() );
131     TextAttributes ta( da.textAttributes() );
132     Measure fs( ta.fontSize() );
133     fs.setValue( i );
134     ta.setFontSize( i );
135     da.setTextAttributes( ta );
136     setAttributes( da );
137 
138     m_chart->update();
139 }
140 
on_minimumSizeSB_valueChanged(int i)141 void MainWindow::on_minimumSizeSB_valueChanged(  int i )
142 {
143     DataValueAttributes da( attributes() );
144     TextAttributes ta( da.textAttributes() );
145     Measure fs( ta.fontSize() );
146     fs.setValue( i );
147     ta.setMinimalFontSize( i );
148     da.setTextAttributes( ta );
149     setAttributes( da );
150 
151     m_chart->update();
152 }
153 
on_rotationSB_valueChanged(int i)154 void MainWindow::on_rotationSB_valueChanged( int i )
155 {
156     DataValueAttributes da( attributes() );
157     TextAttributes ta( da.textAttributes() );
158     ta.setRotation( i );
159     da.setTextAttributes( ta );
160     setAttributes( da );
161 
162     m_chart->update();
163 }
164 
on_posPosCombo_currentIndexChanged(const QString & text)165 void MainWindow::on_posPosCombo_currentIndexChanged(   const QString & text )
166 {
167     DataValueAttributes da( attributes() );
168     RelativePosition relPos( da.positivePosition() );
169     relPos.setReferencePosition( Position::fromName( qPrintable( text ) ) );
170     da.setPositivePosition( relPos );
171     setAttributes( da );
172 
173     m_chart->update();
174 }
175 
on_posAlignCombo_currentIndexChanged(const QString & text)176 void MainWindow::on_posAlignCombo_currentIndexChanged( const QString & text )
177 {
178     DataValueAttributes da( attributes() );
179     RelativePosition relPos( da.positivePosition() );
180     relPos.setAlignment( alignmentFromScreeName( text ) );
181     da.setPositivePosition( relPos );
182     setAttributes( da );
183 
184     m_chart->update();
185 }
186 
on_posPadHoriSB_valueChanged(int i)187 void MainWindow::on_posPadHoriSB_valueChanged( int i )
188 {
189     DataValueAttributes da( attributes() );
190     RelativePosition relPos( da.positivePosition() );
191     Measure pad( relPos.horizontalPadding() );
192     pad.setValue( i );
193     relPos.setHorizontalPadding( pad );
194     da.setPositivePosition( relPos );
195     setAttributes( da );
196 
197     m_chart->update();
198 }
199 
on_posPadVertSB_valueChanged(int i)200 void MainWindow::on_posPadVertSB_valueChanged( int i )
201 {
202     DataValueAttributes da( attributes() );
203     RelativePosition relPos( da.positivePosition() );
204     Measure pad( relPos.verticalPadding() );
205     pad.setValue( i );
206     relPos.setVerticalPadding( pad );
207     da.setPositivePosition( relPos );
208     setAttributes( da );
209 
210     m_chart->update();
211 }
212 
on_negPosCombo_currentIndexChanged(const QString & text)213 void MainWindow::on_negPosCombo_currentIndexChanged(   const QString & text )
214 {
215     DataValueAttributes da( attributes() );
216     RelativePosition relPos( da.negativePosition() );
217     relPos.setReferencePosition( Position::fromName( qPrintable( text ) ) );
218     da.setNegativePosition( relPos );
219     setAttributes( da );
220 
221     m_chart->update();
222 }
223 
on_negAlignCombo_currentIndexChanged(const QString & text)224 void MainWindow::on_negAlignCombo_currentIndexChanged( const QString & text )
225 {
226     DataValueAttributes da( attributes() );
227     RelativePosition relPos( da.negativePosition() );
228     relPos.setAlignment( alignmentFromScreeName( text ) );
229     da.setNegativePosition( relPos );
230     setAttributes( da );
231 
232     m_chart->update();
233 }
234 
on_negPadHoriSB_valueChanged(int i)235 void MainWindow::on_negPadHoriSB_valueChanged( int i )
236 {
237     DataValueAttributes da( attributes() );
238     RelativePosition relPos( da.negativePosition() );
239     Measure pad( relPos.horizontalPadding() );
240     pad.setValue( i );
241     relPos.setHorizontalPadding( pad );
242     da.setNegativePosition( relPos );
243     setAttributes( da );
244 
245     m_chart->update();
246 }
247 
on_negPadVertSB_valueChanged(int i)248 void MainWindow::on_negPadVertSB_valueChanged( int i )
249 {
250     DataValueAttributes da( attributes() );
251     RelativePosition relPos( da.negativePosition() );
252     Measure pad( relPos.verticalPadding() );
253     pad.setValue( i );
254     relPos.setVerticalPadding( pad );
255     da.setNegativePosition( relPos );
256     setAttributes( da );
257 
258     m_chart->update();
259 }
260 
on_labelLE_textEdited(const QString & text)261 void MainWindow::on_labelLE_textEdited(  const QString & text )
262 {
263     DataValueAttributes da( attributes() );
264     da.setDataLabel( text.isEmpty() ? QString() : text );
265     setAttributes( da );
266 
267     m_chart->update();
268 }
269 
on_prefixLE_textEdited(const QString & text)270 void MainWindow::on_prefixLE_textEdited( const QString & text )
271 {
272     DataValueAttributes da( attributes() );
273     da.setPrefix( text.isEmpty() ? QString() : text );
274     setAttributes( da );
275 
276     m_chart->update();
277 }
278 
on_suffixLE_textEdited(const QString & text)279 void MainWindow::on_suffixLE_textEdited( const QString & text )
280 {
281     DataValueAttributes da( attributes() );
282     da.setSuffix( text.isEmpty() ? QString() : text );
283     setAttributes( da );
284 
285     m_chart->update();
286 }
287 
currentIndex() const288 const QModelIndex MainWindow::currentIndex() const
289 {
290     const int dataset = scopeBarDatasetSB->value();
291     const int item    = scopeBarItemSB->value();
292     return m_bars->model()->index( item, dataset, QModelIndex() );
293 }
294 
attributes() const295 const KChart::DataValueAttributes MainWindow::attributes() const
296 {
297     if ( scopeOneBarRB->isChecked() ) {
298         //qDebug() << "attributes() returns settings for one single bar";
299         return m_bars->dataValueAttributes( currentIndex() );
300     }
301     if ( scopeDatasetRB->isChecked() ) {
302         //qDebug() << "attributes() returns settings for a dataset";
303         return m_bars->dataValueAttributes( scopeDatasetSB->value() );
304     }
305     //qDebug() << "attributes() returns common settings";
306     return m_bars->dataValueAttributes();
307 }
308 
setAttributes(const KChart::DataValueAttributes & da)309 void MainWindow::setAttributes( const KChart::DataValueAttributes& da )
310 {
311     if ( scopeOneBarRB->isChecked() )
312         m_bars->setDataValueAttributes( currentIndex(), da );
313     else if ( scopeDatasetRB->isChecked() )
314         m_bars->setDataValueAttributes( scopeDatasetSB->value(), da );
315     else
316         m_bars->setDataValueAttributes( da );
317 }
318 
319 // just a convenience method:
320 // In the combo box we have the text "( Default Value )" instead of "Unknown Position"
321 // because by setting a position to unknown we get KD Chart to use the
322 // diagram-specific default positions.
positionToScreenName(const Position & pos) const323 const char* MainWindow::positionToScreenName( const Position& pos ) const
324 {
325     static const char* defaultPositionName = "( Default Value )";
326     if ( pos.isUnknown() )
327         return defaultPositionName;
328     return pos.name();
329 }
330 
alignmentFromScreeName(const QString & name) const331 const Qt::Alignment MainWindow::alignmentFromScreeName( const QString& name ) const
332 {
333     if ( name == "Center" )      return Qt::AlignCenter;
334     if ( name == "BottomLeft" )  return Qt::AlignLeft    | Qt::AlignBottom;
335     if ( name == "Bottom" )      return Qt::AlignHCenter | Qt::AlignBottom;
336     if ( name == "BottomRight" ) return Qt::AlignRight   | Qt::AlignBottom;
337     if ( name == "Right" )       return Qt::AlignRight   | Qt::AlignVCenter;
338     if ( name == "TopRight" )    return Qt::AlignRight   | Qt::AlignTop;
339     if ( name == "Top" )         return Qt::AlignHCenter | Qt::AlignTop;
340     if ( name == "TopLeft" )     return Qt::AlignLeft    | Qt::AlignTop;
341     if ( name == "Left" )        return Qt::AlignLeft    | Qt::AlignVCenter;
342     return Qt::AlignCenter;
343 }
344 
alignmentToScreenName(const Qt::Alignment & align) const345 const QString MainWindow::alignmentToScreenName( const Qt::Alignment& align ) const
346 {
347     if ( align == Qt::AlignCenter )                       return "Center";
348     if ( align == (Qt::AlignLeft    | Qt::AlignBottom) )  return "BottomLeft";
349     if ( align == (Qt::AlignHCenter | Qt::AlignBottom) )  return "Bottom";
350     if ( align == (Qt::AlignRight   | Qt::AlignBottom) )  return "BottomRight";
351     if ( align == (Qt::AlignRight   | Qt::AlignVCenter) ) return "Right";
352     if ( align == (Qt::AlignRight   | Qt::AlignTop) )     return "TopRight";
353     if ( align == (Qt::AlignHCenter | Qt::AlignTop) )     return "Top";
354     if ( align == (Qt::AlignLeft    | Qt::AlignTop) )     return "TopLeft";
355     if ( align == (Qt::AlignLeft    | Qt::AlignVCenter) ) return "Left";
356     return "Center";
357 }
358 
populateWidgets()359 void MainWindow::populateWidgets()
360 {
361     const DataValueAttributes da( attributes() );
362     const TextAttributes ta( da.textAttributes() );
363     const RelativePosition posPos( da.positivePosition() );
364     const RelativePosition negPos( da.negativePosition() );
365 
366     paintValuesCB->setChecked( da.isVisible() && ta.isVisible() );
367     fontCombo->setCurrentFont( ta.font() );
368     relativeSizeSB->setValue( static_cast<int>(ta.fontSize().value()) );
369     minimumSizeSB->setValue(  static_cast<int>(ta.minimalFontSize().value()) );
370     rotationSB->setValue( static_cast<int>(ta.rotation()) );
371 
372     posPosCombo->setCurrentIndex( posPosCombo->findText(
373             positionToScreenName( posPos.referencePosition() ) ) );
374     posAlignCombo->setCurrentIndex( posAlignCombo->findText(
375             alignmentToScreenName( posPos.alignment() ) ) );
376     posPadHoriSB->setValue( static_cast<int>(posPos.horizontalPadding().value()) );
377     posPadVertSB->setValue( static_cast<int>(posPos.verticalPadding().value()) );
378 
379     negPosCombo->setCurrentIndex( negPosCombo->findText( positionToScreenName(
380             negPos.referencePosition() ) ) );
381     negAlignCombo->setCurrentIndex( negAlignCombo->findText(
382             alignmentToScreenName( negPos.alignment() ) ) );
383     negPadHoriSB->setValue( static_cast<int>(negPos.horizontalPadding().value()) );
384     negPadVertSB->setValue( static_cast<int>(negPos.verticalPadding().value()) );
385 
386     labelLE->setText(  da.dataLabel() );
387     prefixLE->setText( da.prefix() );
388     suffixLE->setText( da.suffix() );
389 }
390