GobChartsWidget  1.0
gobchartstoolswidget.cpp
1 /* Copyright (C) 2012 by William Hallatt.
2  *
3  * This file forms part of the "GobChartsWidget" library.
4  *
5  * This library is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have downloaded a copy of the GNU General Public License
16  * (GNUGPL.txt) and GNU Lesser General Public License (GNULGPL.txt)
17  * along with this library. If not, see <http://www.gnu.org/licenses/>.
18  *
19  * The official website for this project is www.goblincoding.com and,
20  * although not compulsory, it would be appreciated if all works of whatever
21  * nature referring to or using this library include a reference to this site.
22  */
23 
24 #include "gobchartstoolswidget.h"
25 #include "ui_gobchartstoolswidget.h"
26 
27 #include <QButtonGroup>
28 #include <QColorDialog>
29 #include <QDomDocument>
30 #include <QMessageBox>
31 
32 /*-------------------------------- FRIEND CLASS ----------------------------------*/
33 
34 class GobChartsToolsWidget::LabelDetails
35 {
36 public:
37  void setupLabel( const GobChartsToolsWidget * widget )
38  {
39  m_font = widget->ui->labelFontComboBox->currentFont();
40  /* m_fontColour assigned in labelColourPreferenceChanged. */
41  m_text = widget->ui->labelLineEdit->text();
42  /* m_align assigned in labelAlignmentPreferenceChanged. */
43  m_fontSize = widget->ui->labelFontSizeComboBox->currentText().toInt();
44  m_bold = widget->ui->labelBoldButton->isChecked();
45  m_italics = widget->ui->labelItalicsButton->isChecked();
46  m_underlined = widget->ui->labelUnderlineButton->isChecked();
47 
48  m_font.setBold( m_bold );
49  m_font.setItalic( m_italics );
50  m_font.setUnderline( m_underlined );
51  m_font.setPointSize( m_fontSize );
52  }
53 
54  Qt::Alignment m_align;
55  QFont m_font;
56  QColor m_fontColour;
57  QString m_text;
58  int m_fontSize;
59  bool m_bold;
60  bool m_italics;
61  bool m_underlined;
62  bool m_labelDetailsReceived;
63 
64  LabelDetails() :
65  m_align ( Qt::AlignCenter ),
66  m_font (),
67  m_fontColour(),
68  m_text ( "" ),
69  m_fontSize ( 11 ),
70  m_bold ( false ),
71  m_italics ( false ),
72  m_underlined( false ),
73  m_labelDetailsReceived( false ) {}
74 };
75 
76 /*--------------------------------- PIMPL STRUCT ---------------------------------*/
77 
78 struct GobChartsToolsWidget::GobChartsToolsWidgetPrivate
79 {
80  bool m_loadingChart;
81  GobChartsToolsWidget::LabelDetails m_labelDetails;
82 
83  /* Chart colour. */
84  QColor m_chartColour;
85  bool m_fixedColour;
86 
87  /* Data range. */
88  qreal m_lowerBound;
89  qreal m_upperBound;
90  bool m_showTotalRange;
91  bool m_rangePreferenceSet;
92 
93  /* Grid. */
94  Qt::PenStyle m_penStyle;
95  QColor m_gridColour;
96  bool m_gridColourSet;
97  bool m_verticalGrid;
98  bool m_horizontalGrid;
99 
100  /* Convenience map for easy button/type look-ups. */
101  QMap< GobChartsType, QToolButton* > m_typeButtonMap;
102 
103  /* These particular button groups need to have their "exclusive"
104  settings changed and must therefore be accessible (which is
105  why they're members). */
106  QButtonGroup m_labelButtonGroup;
107  QButtonGroup m_chartButtonGroup;
108 
109  GobChartsToolsWidgetPrivate() :
110  m_loadingChart ( false ),
111  m_labelDetails (),
112  m_chartColour (),
113  m_fixedColour ( false ),
114  m_lowerBound ( 0.0 ),
115  m_upperBound ( 0.0 ),
116  m_showTotalRange ( true ),
117  m_rangePreferenceSet( false ),
118  m_penStyle ( Qt::DotLine ),
119  m_gridColour (),
120  m_gridColourSet ( false ),
121  m_verticalGrid ( false ),
122  m_horizontalGrid ( false ),
123  m_typeButtonMap ()
124  {}
125 };
126 
127 
128 /*------------------------------- MEMBER FUNCTIONS -------------------------------*/
129 
131  QFrame ( parent ),
132  ui ( new Ui::GobChartsToolsWidget ),
133  m_private( new GobChartsToolsWidgetPrivate )
134 {
135  ui->setupUi( this );
136  ui->chartsRangeGroupBox->setEnabled( false );
137 
138  /* Disable until a chart is created. */
139  ui->labelTextGroupBox->setEnabled( false );
140  ui->labelStyleGroupBox->setEnabled( false );
141  ui->gridGroupBox->setEnabled( false );
142  ui->saveButton->setEnabled( false );
143  ui->chartClearButton->setEnabled( false );
144  ui->chartColourPickerButton->setEnabled( false );
145  ui->chartRangeToolButton->setEnabled( false );
146 
147  connect( ui->saveButton, SIGNAL( clicked() ), this, SIGNAL( saveChart() ) );
148  connect( ui->loadButton, SIGNAL( clicked() ), this, SIGNAL( loadChart() ) );
149 
150  connect( ui->chartClearButton, SIGNAL( clicked() ), this, SLOT ( clearAndReset() ) );
151  connect( ui->chartClearButton, SIGNAL( clicked() ), this, SIGNAL( clearChart() ) );
152  connect( ui->chartColourPickerButton, SIGNAL( clicked() ), this, SLOT( chartColourPreferenceChanged() ) );
153 
154  /* Data range related. */
155  connect( ui->chartRangeToolButton, SIGNAL( clicked() ), this, SLOT( chartRangePreferenceChanged() ) );
156  connect( ui->chartRangeLowerBoundarySpinBox, SIGNAL( valueChanged( double ) ), this, SLOT( chartRangePreferenceSelected() ) );
157  connect( ui->chartRangeUpperBoundarySpinBox, SIGNAL( valueChanged( double ) ), this, SLOT( chartRangePreferenceSelected() ) );
158 
159  /* Chart type related. */
160  m_private->m_chartButtonGroup.setExclusive( true );
161  m_private->m_chartButtonGroup.addButton( ui->chartBarToolButton );
162  m_private->m_chartButtonGroup.addButton( ui->chartPieToolButton );
163  m_private->m_chartButtonGroup.addButton( ui->chartLineToolButton );
164  connect( &m_private->m_chartButtonGroup, SIGNAL( buttonClicked( QAbstractButton* ) ), this, SLOT( chartTypeChanged( QAbstractButton* ) ) );
165 
166  m_private->m_typeButtonMap.insert( BAR, ui->chartBarToolButton );
167  m_private->m_typeButtonMap.insert( PIE, ui->chartPieToolButton );
168  m_private->m_typeButtonMap.insert( LINE, ui->chartLineToolButton );
169 
170  /* Grid related. */
171  QButtonGroup *gridLineButtonGroup = new QButtonGroup( this );
172  gridLineButtonGroup->setExclusive( true );
173  gridLineButtonGroup->addButton( ui->gridDashedLineToolButton );
174  gridLineButtonGroup->addButton( ui->gridDotLineToolButton );
175  gridLineButtonGroup->addButton( ui->gridSolidLineToolButton );
176  connect( gridLineButtonGroup, SIGNAL( buttonClicked( QAbstractButton* ) ), this, SLOT( gridLinePreferenceChanged( QAbstractButton* ) ) );
177 
178  connect( ui->gridHorizontalToolButton, SIGNAL( clicked() ), this, SLOT( gridLinesSelected() ) );
179  connect( ui->gridVerticalToolButton, SIGNAL( clicked() ), this, SLOT( gridLinesSelected() ) );
180  connect( ui->gridColourToolButton, SIGNAL( clicked() ), this, SLOT( gridColourSelected() ) );
181  connect( ui->gridHorizontalSpinBox, SIGNAL( valueChanged( int ) ), this, SLOT( gridLineNumbersChanged() ) );
182  connect( ui->gridVerticalSpinBox, SIGNAL( valueChanged( int ) ), this, SLOT( gridLineNumbersChanged() ) );
183 
184  /* Label related. */
185  m_private->m_labelButtonGroup.setExclusive( true );
186  m_private->m_labelButtonGroup.addButton( ui->labelHeaderToolButton );
187  m_private->m_labelButtonGroup.addButton( ui->labelXToolButton );
188  m_private->m_labelButtonGroup.addButton( ui->labelYToolButton );
189  connect( &m_private->m_labelButtonGroup, SIGNAL( buttonClicked( QAbstractButton* ) ), this, SLOT( generateLabelDetailRequest( QAbstractButton* ) ) );
190 
191  QButtonGroup *labelAlignmentButtonGroup = new QButtonGroup( this );
192  labelAlignmentButtonGroup->setExclusive( true );
193  labelAlignmentButtonGroup->addButton( ui->labelAlignCentreButton );
194  labelAlignmentButtonGroup->addButton( ui->labelAlignLeftButton );
195  labelAlignmentButtonGroup->addButton( ui->labelAlignRightButton );
196  connect( labelAlignmentButtonGroup, SIGNAL ( buttonClicked( QAbstractButton* ) ), this, SLOT( labelAlignmentPreferenceChanged( QAbstractButton* ) ) );
197 
198  connect( ui->labelFontComboBox, SIGNAL( currentIndexChanged( QString ) ), this, SLOT( updateLabelDetails() ) );
199  connect( ui->labelFontSizeComboBox, SIGNAL( currentIndexChanged( QString ) ), this, SLOT( updateLabelDetails() ) );
200  connect( ui->labelLineEdit, SIGNAL( textChanged( QString ) ), this, SLOT( updateLabelDetails() ) );
201  connect( ui->labelBoldButton, SIGNAL( clicked() ), this, SLOT( updateLabelDetails() ) );
202  connect( ui->labelItalicsButton, SIGNAL( clicked() ), this, SLOT( updateLabelDetails() ) );
203  connect( ui->labelUnderlineButton, SIGNAL( clicked() ), this, SLOT( updateLabelDetails() ) );
204  connect( ui->labelFontColourToolButton, SIGNAL( clicked() ), this, SLOT( labelColourPreferenceChanged() ) );
205 }
206 
207 /*--------------------------------------------------------------------------------*/
208 
210 {
211  delete ui;
212  delete m_private;
213 }
214 
215 /*--------------------------------------------------------------------------------*/
216 
217 void GobChartsToolsWidget::chartTypeChanged( QAbstractButton *button )
218 {
219  if( button == ui->chartBarToolButton )
220  {
221  ui->gridGroupBox->setEnabled( true );
222  ui->labelXToolButton->setEnabled( true );
223  ui->labelYToolButton->setEnabled( true );
224  emit createChart( BAR );
225  }
226  else if( button == ui->chartPieToolButton )
227  {
228  ui->gridGroupBox->setEnabled( false ); // makes no sense to have a grid with a pie chart
229  ui->labelXToolButton->setEnabled( false );
230  ui->labelYToolButton->setEnabled( false );
231  emit createChart( PIE );
232  }
233  else if( button == ui->chartLineToolButton )
234  {
235  ui->gridGroupBox->setEnabled( true );
236  ui->labelXToolButton->setEnabled( true );
237  ui->labelYToolButton->setEnabled( true );
238  emit createChart( LINE );
239  }
240 
241  ui->labelTextGroupBox->setEnabled( true );
242  ui->labelStyleGroupBox->setEnabled( true );
243  ui->saveButton->setEnabled( true );
244  ui->chartClearButton->setEnabled( true );
245  ui->chartColourPickerButton->setEnabled( true );
246  ui->chartRangeToolButton->setEnabled( true );
247 }
248 
249 /*--------------------------------------------------------------------------------*/
250 
251 void GobChartsToolsWidget::chartColourPreferenceChanged()
252 {
253  if( ui->chartColourPickerButton->isChecked() )
254  {
255  QColor colour = QColorDialog::getColor();
256 
257  if( colour.isValid() )
258  {
259  emit setFixedColour( colour );
260  m_private->m_chartColour = colour;
261  m_private->m_fixedColour = true;
262  }
263  else
264  {
265  emit setRandomColours();
266  ui->chartColourPickerButton->setChecked( false );
267  m_private->m_fixedColour = false;
268  }
269  }
270  else
271  {
272  emit setRandomColours();
273  m_private->m_fixedColour = false;
274  }
275 }
276 
277 /*--------------------------------------------------------------------------------*/
278 
279 void GobChartsToolsWidget::chartRangePreferenceChanged()
280 {
281  if( ui->chartRangeToolButton->isChecked() )
282  {
283  ui->chartsRangeGroupBox->setEnabled( true );
284 
285  /* If the user had previously specified a range, they might be toggling
286  the view to see what difference it makes, so we need to update the chart accordingly. */
287  if( m_private->m_rangePreferenceSet )
288  {
289  chartRangePreferenceSelected();
290  }
291  }
292  else
293  {
294  ui->chartsRangeGroupBox->setEnabled( false );
295  emit setShowTotalRange();
296  m_private->m_showTotalRange = true;
297  }
298 }
299 
300 /*--------------------------------------------------------------------------------*/
301 
302 void GobChartsToolsWidget::chartRangePreferenceSelected()
303 {
304  /* In the process of loading the chart from XML, this function was found to be
305  called too quickly in succession to be effective, so a flag was introduced to make
306  sure that this call isn't made until we're done reading in all the values. */
307  if( !m_private->m_loadingChart )
308  {
309  qreal lower( ui->chartRangeLowerBoundarySpinBox->value() );
310  qreal upper( ui->chartRangeUpperBoundarySpinBox->value() );
311 
312  m_private->m_showTotalRange = false;
313  m_private->m_rangePreferenceSet = true;
314  m_private->m_lowerBound = lower;
315  m_private->m_upperBound = upper;
316 
317  emit setAllowedDataRange( lower, upper );
318  }
319 }
320 
321 /*--------------------------------------------------------------------------------*/
322 
323 void GobChartsToolsWidget::gridLinePreferenceChanged( QAbstractButton *button )
324 {
325  if( button == ui->gridSolidLineToolButton )
326  {
327  m_private->m_penStyle = Qt::SolidLine;
328  emit setGridLineStyle( Qt::SolidLine );
329  }
330  else if( button == ui->gridDashedLineToolButton )
331  {
332  m_private->m_penStyle = Qt::DashLine;
333  emit setGridLineStyle( Qt::DashLine );
334  }
335  else if( button == ui->gridDotLineToolButton )
336  {
337  m_private->m_penStyle = Qt::DotLine;
338  emit setGridLineStyle( Qt::DotLine );
339  }
340 }
341 
342 /*--------------------------------------------------------------------------------*/
343 
344 void GobChartsToolsWidget::gridLineNumbersChanged()
345 {
346  emit setHorizontalGridLines( ui->gridHorizontalToolButton->isChecked(),
347  ui->gridHorizontalSpinBox->value() );
348 
349  emit setVerticalGridLines( ui->gridVerticalToolButton->isChecked(),
350  ui->gridVerticalSpinBox->value() );
351 }
352 
353 /*--------------------------------------------------------------------------------*/
354 
355 void GobChartsToolsWidget::gridLinesSelected()
356 {
357  m_private->m_verticalGrid = ui->gridVerticalToolButton->isChecked();
358  m_private->m_horizontalGrid = ui->gridHorizontalToolButton->isChecked();
359  emit setVerticalGridLines ( m_private->m_verticalGrid, ui->gridVerticalSpinBox->value() );
360  emit setHorizontalGridLines( m_private->m_horizontalGrid, ui->gridHorizontalSpinBox->value() );
361 }
362 
363 /*--------------------------------------------------------------------------------*/
364 
365 void GobChartsToolsWidget::gridColourSelected()
366 {
367  QColor colour = QColorDialog::getColor();
368 
369  if( colour.isValid() )
370  {
371  emit setGridColour( colour );
372  m_private->m_gridColour = colour;
373  m_private->m_gridColourSet = true;
374  }
375 }
376 
377 /*--------------------------------------------------------------------------------*/
378 
379 void GobChartsToolsWidget::updateLabelDetails()
380 {
381  /* We don't want to end up emitting changes if we just received label details via request. */
382  if( !m_private->m_labelDetails.m_labelDetailsReceived )
383  {
384  m_private->m_labelDetails.setupLabel( this );
385 
386  if( ui->labelHeaderToolButton->isChecked() )
387  {
388  emit setLabelDetails( HEADER,
389  m_private->m_labelDetails.m_text,
390  m_private->m_labelDetails.m_font,
391  m_private->m_labelDetails.m_fontColour,
392  m_private->m_labelDetails.m_align );
393  }
394  else if( ui->labelXToolButton->isChecked() )
395  {
396  emit setLabelDetails( XLABEL,
397  m_private->m_labelDetails.m_text,
398  m_private->m_labelDetails.m_font,
399  m_private->m_labelDetails.m_fontColour,
400  m_private->m_labelDetails.m_align );
401  }
402  else if( ui->labelYToolButton->isChecked() )
403  {
404  emit setLabelDetails( YLABEL,
405  m_private->m_labelDetails.m_text,
406  m_private->m_labelDetails.m_font,
407  m_private->m_labelDetails.m_fontColour,
408  m_private->m_labelDetails.m_align );
409  }
410  }
411 }
412 
413 /*--------------------------------------------------------------------------------*/
414 
415 void GobChartsToolsWidget::labelColourPreferenceChanged()
416 {
417  QColor colour = QColorDialog::getColor();
418 
419  if( colour.isValid() )
420  {
421  m_private->m_labelDetails.m_fontColour = colour;
422  updateLabelDetails();
423  }
424 }
425 
426 /*--------------------------------------------------------------------------------*/
427 
428 void GobChartsToolsWidget::labelAlignmentPreferenceChanged( QAbstractButton *button )
429 {
430  if( button == ui->labelAlignCentreButton )
431  {
432  m_private->m_labelDetails.m_align = Qt::AlignCenter;
433  }
434  else if( button == ui->labelAlignLeftButton )
435  {
436  m_private->m_labelDetails.m_align = Qt::AlignLeft;
437  }
438  else if( button == ui->labelAlignRightButton )
439  {
440  m_private->m_labelDetails.m_align = Qt::AlignRight;
441  }
442 
443  updateLabelDetails();
444 }
445 
446 /*--------------------------------------------------------------------------------*/
447 
448 void GobChartsToolsWidget::generateLabelDetailRequest( QAbstractButton *button )
449 {
450  if( button == ui->labelHeaderToolButton )
451  {
452  emit requestLabelDetails( HEADER );
453  }
454  else if( button == ui->labelYToolButton )
455  {
456  emit requestLabelDetails( YLABEL );
457  }
458  else if( button == ui->labelXToolButton )
459  {
460  emit requestLabelDetails( XLABEL );
461  }
462 
463  ui->labelLineEdit->setFocus();
464 }
465 
466 /*--------------------------------------------------------------------------------*/
467 
468 void GobChartsToolsWidget::receiveLabelDetails( GobChartsLabel label, QString text, QFont font, QColor colour, Qt::Alignment align )
469 {
470  /* Avoid recursively calling this function through signals emitted by the changes below. */
471  m_private->m_labelDetails.m_labelDetailsReceived = true;
472 
473  if( label == HEADER )
474  {
475  ui->labelHeaderToolButton->setChecked( true );
476  }
477  else if( label == YLABEL )
478  {
479  ui->labelYToolButton->setChecked( true );
480  }
481  else if( label == XLABEL )
482  {
483  ui->labelXToolButton->setChecked( true );
484  }
485 
486  ui->labelLineEdit->setText( text );
487  ui->labelFontComboBox->setCurrentFont( font );
488  ui->labelBoldButton->setChecked( font.bold() );
489  ui->labelItalicsButton->setChecked( font.italic() );
490  ui->labelUnderlineButton->setChecked( font.underline() );
491 
492  m_private->m_labelDetails.m_fontColour = colour;
493 
494  for( int i = 0; i < ui->labelFontSizeComboBox->count(); i++ )
495  {
496  if( ui->labelFontSizeComboBox->itemText( i ) == QString( "%1" ).arg( font.pointSize() ) )
497  {
498  ui->labelFontSizeComboBox->setCurrentIndex( i );
499  break;
500  }
501  }
502 
503  if( align == Qt::AlignCenter )
504  {
505  ui->labelAlignCentreButton->setChecked( true );
506  }
507  else if( align == Qt::AlignLeft )
508  {
509  ui->labelAlignLeftButton->setChecked( true );
510  }
511  else if( align == Qt::AlignRight )
512  {
513  ui->labelAlignRightButton->setChecked( true );
514  }
515 
516  m_private->m_labelDetails.m_labelDetailsReceived = false;
517 }
518 
519 /*--------------------------------------------------------------------------------*/
520 
522 {
523  QDomDocument doc;
524  QDomElement root = doc.createElement( "ToolsWidget" );
525  doc.appendChild( root );
526 
527  /* Chart. */
528  QDomElement chart = doc.createElement( "Chart" );
529 
530  if( m_private->m_fixedColour )
531  {
532  chart.setAttribute( "fixed", "true" );
533 
534  QDomElement colour = doc.createElement( "ChartColour" );
535  colour.setAttribute( "red", m_private->m_chartColour.red() );
536  colour.setAttribute( "green", m_private->m_chartColour.green() );
537  colour.setAttribute( "blue", m_private->m_chartColour.blue() );
538 
539  chart.appendChild( colour );
540  }
541  else
542  {
543  chart.setAttribute( "fixed", "false" );
544  }
545 
546  root.appendChild( chart );
547 
548  /* Range. */
549  QDomElement range = doc.createElement( "Range" );
550 
551  if( m_private->m_showTotalRange )
552  {
553  range.setAttribute( "total", "true" );
554  }
555  else
556  {
557  range.setAttribute( "total", "false" );
558  range.setAttribute( "lower", m_private->m_lowerBound );
559  range.setAttribute( "upper", m_private->m_upperBound );
560  }
561 
562  root.appendChild( range );
563 
564  /* Grid. */
565  QDomElement grid = doc.createElement( "Grid" );
566 
567  if( m_private->m_gridColourSet )
568  {
569  grid.setAttribute( "fixedColour", "true" );
570 
571  QDomElement colour = doc.createElement( "GridColour" );
572  colour.setAttribute( "red", m_private->m_gridColour.red() );
573  colour.setAttribute( "green", m_private->m_gridColour.green() );
574  colour.setAttribute( "blue", m_private->m_gridColour.blue() );
575 
576  grid.appendChild( colour );
577  }
578  else
579  {
580  grid.setAttribute( "fixedColour", "false" );
581  }
582 
583  if( m_private->m_verticalGrid )
584  {
585  grid.setAttribute( "vertical", "true" );
586  grid.setAttribute( "vertlines", QString( "%1" ).arg( ui->gridVerticalSpinBox->value() ) );
587  }
588  else
589  {
590  grid.setAttribute( "vertical", "false" );
591  }
592 
593  if( m_private->m_horizontalGrid )
594  {
595  grid.setAttribute( "horizontal", "true" );
596  grid.setAttribute( "horlines", QString( "%1" ).arg( ui->gridHorizontalSpinBox->value() ) );
597  }
598  else
599  {
600  grid.setAttribute( "horizontal", "true" );
601  }
602 
603  if( m_private->m_penStyle == Qt::SolidLine )
604  {
605  grid.setAttribute( "style", "solid" );
606  }
607  else if( m_private->m_penStyle == Qt::DotLine )
608  {
609  grid.setAttribute( "style", "dot" );
610  }
611  else
612  {
613  grid.setAttribute( "style", "dash" );
614  }
615 
616  root.appendChild( grid );
617 
618  /* Labels are not the responsibility of this widget as they don't form part of the widget's state. */
619 
620  return doc.toString( 2 );
621 }
622 
623 /*--------------------------------------------------------------------------------*/
624 
625 void GobChartsToolsWidget::setStateXML( GobChartsType type, const QDomNode &toolNode )
626 {
627  if( !toolNode.isNull() )
628  {
629  clearAndReset();
630 
631  /* If any of the QString to "int" or to "double" conversions fail we just inform the user,
632  no further action is taken. */
633  bool ok( true );
634 
635  /* Chart. */
636  if( toolNode.firstChildElement( "Chart" ).attribute( "fixed" ) == "true" )
637  {
638  m_private->m_fixedColour = true;
639  QDomNamedNodeMap colourMap = toolNode.namedItem( "Chart" ).namedItem( "ChartColour" ).attributes();
640 
641  QColor fixedColour;
642  fixedColour.setRed ( colourMap.namedItem( "red" ).nodeValue().toInt( &ok ) );
643  fixedColour.setGreen( colourMap.namedItem( "green" ).nodeValue().toInt( &ok ) );
644  fixedColour.setBlue ( colourMap.namedItem( "blue" ).nodeValue().toInt( &ok ) );
645 
646  m_private->m_chartColour = fixedColour;
647  ui->chartColourPickerButton->setChecked( true );
648  }
649  else
650  {
651  m_private->m_fixedColour = false;
652  ui->chartColourPickerButton->setChecked( false );
653  }
654 
655  /* Range. */
656  QDomNamedNodeMap rangeMap = toolNode.namedItem( "Range" ).attributes();
657 
658  if( rangeMap.namedItem( "total" ).nodeValue() == "true" )
659  {
660  m_private->m_showTotalRange = true;
661  ui->chartRangeToolButton->setChecked( false );
662  }
663  else
664  {
665  m_private->m_showTotalRange = false;
666  m_private->m_rangePreferenceSet = true;
667  m_private->m_lowerBound = rangeMap.namedItem( "lower" ).nodeValue().toDouble( &ok );
668  m_private->m_upperBound = rangeMap.namedItem( "upper" ).nodeValue().toDouble( &ok );
669 
670  /* Set the "loading chart" flag so that the chartRangePreferenceChanged() slot does
671  not interfere with the process. */
672  m_private->m_loadingChart = true;
673  ui->chartRangeLowerBoundarySpinBox->setValue( m_private->m_lowerBound );
674  ui->chartRangeUpperBoundarySpinBox->setValue( m_private->m_upperBound );
675  m_private->m_loadingChart = false;
676  chartRangePreferenceSelected();
677 
678  ui->chartRangeToolButton->setChecked( true );
679  }
680 
681  /* Grid. */
682  QDomNamedNodeMap gridMap = toolNode.namedItem( "Grid" ).attributes();
683 
684  if( gridMap.namedItem( "fixedColour" ).nodeValue() == "true" )
685  {
686  m_private->m_gridColourSet = true;
687 
688  QDomNamedNodeMap colourMap = toolNode.namedItem( "Grid" ).namedItem( "GridColour" ).attributes();
689 
690  QColor gridColour;
691  gridColour.setRed ( colourMap.namedItem( "red" ).nodeValue().toInt( &ok ) );
692  gridColour.setGreen( colourMap.namedItem( "green" ).nodeValue().toInt( &ok ) );
693  gridColour.setBlue ( colourMap.namedItem( "blue" ).nodeValue().toInt( &ok ) );
694 
695  m_private->m_gridColour = gridColour;
696  }
697  else
698  {
699  m_private->m_gridColourSet = false;
700  }
701 
702  if( gridMap.namedItem( "vertical" ).nodeValue() == "true" )
703  {
704  m_private->m_verticalGrid = true;
705  ui->gridGroupBox->setEnabled( true );
706  ui->gridVerticalToolButton->setChecked( true );
707  ui->gridVerticalSpinBox->setValue( gridMap.namedItem( "vertlines" ).toAttr().value().toInt() );
708  }
709  else
710  {
711  m_private->m_verticalGrid = false;
712  ui->gridVerticalToolButton->setChecked( false );
713  }
714 
715  if( gridMap.namedItem( "horizontal" ).nodeValue() == "true" )
716  {
717  m_private->m_horizontalGrid = true;
718  ui->gridGroupBox->setEnabled( true );
719  ui->gridHorizontalToolButton->setChecked( true );
720  ui->gridHorizontalSpinBox->setValue( gridMap.namedItem( "horlines" ).toAttr().value().toInt() );
721  }
722  else
723  {
724  m_private->m_horizontalGrid = false;
725  ui->gridHorizontalToolButton->setChecked( false );
726  }
727 
728  if( gridMap.namedItem( "style" ).nodeValue() == "solid" )
729  {
730  m_private->m_penStyle = Qt::SolidLine;
731  ui->gridSolidLineToolButton->setChecked( true );
732  }
733  else if( gridMap.namedItem( "style" ).nodeValue() == "dot" )
734  {
735  m_private->m_penStyle = Qt::DotLine;
736  ui->gridDotLineToolButton->setChecked( true );
737  }
738  else
739  {
740  m_private->m_penStyle = Qt::DashLine;
741  ui->gridDashedLineToolButton->setChecked( true );
742  }
743 
744  if( !ok )
745  {
746  QMessageBox::critical( this, "Error", "Failed to convert one or more data values to their appropriate type." );
747  }
748  else
749  {
750  /* Labels are not the responsibility of this widget as they don't form part of the widget's state,
751  so we don't want to attempt a label update when emitting the state signals. */
752  m_private->m_labelDetails.m_labelDetailsReceived = true;
754  m_private->m_labelDetails.m_labelDetailsReceived = false;
755  }
756 
757  ui->labelTextGroupBox->setEnabled( true );
758  ui->labelStyleGroupBox->setEnabled( true );
759  ui->saveButton->setEnabled( true );
760  ui->chartClearButton->setEnabled( true );
761  ui->chartColourPickerButton->setEnabled( true );
762  ui->chartRangeToolButton->setEnabled( true );
763 
764  const_cast< QToolButton* >( m_private->m_typeButtonMap.value( type ) )->setChecked( true );
765  }
766  else
767  {
768  QMessageBox::critical( this, "Error", "Failed to load chart." );
769  }
770 }
771 
772 /*--------------------------------------------------------------------------------*/
773 
775 {
776  /* Chart colour. */
777  if( m_private->m_fixedColour )
778  {
779  emit setFixedColour( m_private->m_chartColour );
780  }
781 
782  /* Data range. */
783  if( m_private->m_showTotalRange )
784  {
785  emit setShowTotalRange();
786  }
787  else
788  {
789  emit setAllowedDataRange( m_private->m_lowerBound, m_private->m_upperBound );
790  }
791 
792  /* Grid. */
793  if( ui->gridGroupBox->isEnabled() )
794  {
795  emit setHorizontalGridLines( m_private->m_horizontalGrid, ui->gridHorizontalSpinBox->value() );
796  emit setGridLineStyle ( m_private->m_penStyle );
797  emit setVerticalGridLines ( m_private->m_verticalGrid, ui->gridVerticalSpinBox->value() );
798 
799  if( m_private->m_gridColourSet )
800  {
801  emit setGridColour( m_private->m_gridColour );
802  }
803  }
804 
805  /* Label details are dealt with in GobChartsWidget::createChart. */
806 }
807 
808 /*--------------------------------------------------------------------------------*/
809 
810 void GobChartsToolsWidget::clearAndReset()
811 {
812  ui->labelTextGroupBox->setEnabled( false );
813  ui->labelStyleGroupBox->setEnabled( false );
814  ui->gridGroupBox->setEnabled( false );
815  ui->saveButton->setEnabled( false );
816  ui->chartClearButton->setEnabled( false );
817  ui->chartColourPickerButton->setEnabled( false );
818  ui->chartRangeToolButton->setEnabled( false );
819 
820  ui->gridHorizontalToolButton->setChecked( false );
821  ui->gridVerticalToolButton->setChecked( false );
822  ui->gridDotLineToolButton->setChecked( true );
823 
824  ui->labelBoldButton->setChecked( false );
825  ui->labelItalicsButton->setChecked( false );
826  ui->labelUnderlineButton->setChecked( false );
827  ui->labelAlignCentreButton->setChecked( false );
828  ui->labelAlignLeftButton->setChecked( false );
829  ui->labelAlignRightButton->setChecked( false );
830 
831  /* If we don't set the button group's exclusive flag to false
832  then we cannot ensure that all three chart buttons are set
833  as unchecked after the reset. */
834  m_private->m_chartButtonGroup.setExclusive( false );
835  ui->chartBarToolButton->setChecked( false );
836  ui->chartPieToolButton->setChecked( false );
837  ui->chartLineToolButton->setChecked( false );
838  m_private->m_chartButtonGroup.setExclusive( true );
839 
840  /* If we don't set the button group's exclusive flag to false
841  then we cannot ensure that all three label buttons are set
842  as unchecked after the reset. */
843  m_private->m_labelButtonGroup.setExclusive( false );
844  ui->labelHeaderToolButton->setChecked( false );
845  ui->labelYToolButton->setChecked( false );
846  ui->labelXToolButton->setChecked( false );
847  m_private->m_labelButtonGroup.setExclusive( true );
848 
849  ui->labelLineEdit->clear();
850 
851  ui->chartRangeLowerBoundarySpinBox->setValue( 0.0 );
852  ui->chartRangeUpperBoundarySpinBox->setValue( 0.0 );
853  ui->gridHorizontalSpinBox->setValue( 0 );
854  ui->gridVerticalSpinBox->setValue( 0 );
855 
856  m_private->m_labelDetails.m_labelDetailsReceived = false;
857  m_private->m_loadingChart = false;
858  m_private->m_fixedColour = false;
859  m_private->m_gridColourSet = false;
860  m_private->m_verticalGrid = false;
861  m_private->m_horizontalGrid = false;
862  m_private->m_rangePreferenceSet = false;
863  m_private->m_showTotalRange = true;
864 }
865 
866 /*--------------------------------------------------------------------------------*/