Engauge Digitizer  2
DlgSettingsExportFormat.cpp
1 /******************************************************************************************************
2  * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
3  * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
4  * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
5  ******************************************************************************************************/
6 
7 #include "CallbackBoundingRects.h"
8 #include "CmdMediator.h"
9 #include "CmdSettingsExportFormat.h"
10 #include "DocumentModelExportFormat.h"
11 #include "DlgSettingsExportFormat.h"
12 #include "ExportFileFunctions.h"
13 #include "ExportFileRelations.h"
14 #include "Logger.h"
15 #include "MainWindow.h"
16 #include "MainWindowModel.h"
17 #include <QCheckBox>
18 #include <QComboBox>
19 #include <QDoubleValidator>
20 #include <QGridLayout>
21 #include <QGroupBox>
22 #include <QHBoxLayout>
23 #include <QLabel>
24 #include <QLineEdit>
25 #include <QListWidget>
26 #include <QPushButton>
27 #include <QRadioButton>
28 #include <QScrollBar>
29 #include <QSettings>
30 #include <QTabWidget>
31 #include <QTextEdit>
32 #include <QTextStream>
33 #include <QVBoxLayout>
34 #include "Settings.h"
35 #include "Transformation.h"
36 
37 // Colors that should match the help text for m_editPreview
38 const QString COLOR_FUNCTIONS = ("#DDDDFF");
39 const QString COLOR_RELATIONS = ("#DDFFDD");
40 
41 const int MIN_INDENT_COLUMN_WIDTH = 20;
42 const int MIN_HEADER_EMPTY_COLUMN_WIDTH = 10;
43 const int MIN_EDIT_WIDTH = 110;
44 const int MAX_EDIT_WIDTH = 180;
45 
46 const int TAB_WIDGET_INDEX_FUNCTIONS = 0;
47 const int TAB_WIDGET_INDEX_RELATIONS = 1;
48 
49 const QString EMPTY_PREVIEW;
50 
51 const int MINIMUM_DIALOG_WIDTH_EXPORT_FORMAT = 650;
52 const int MINIMUM_HEIGHT = 780;
53 
55  DlgSettingsAbstractBase (tr ("Export Format"),
56  "DlgSettingsExportFormat",
57  mainWindow),
58  m_modelExportBefore (0),
59  m_modelExportAfter (0),
60  m_haveFunction (false),
61  m_haveRelation (false)
62 {
63  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::DlgSettingsExportFormat";
64 
65  QWidget *subPanel = createSubPanel ();
66  finishPanel (subPanel,
67  MINIMUM_DIALOG_WIDTH_EXPORT_FORMAT);
68 }
69 
70 DlgSettingsExportFormat::~DlgSettingsExportFormat()
71 {
72  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::~DlgSettingsExportFormat";
73 }
74 
75 void DlgSettingsExportFormat::createCurveSelection (QGridLayout *layout, int &row)
76 {
77  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::createCurveSelection";
78 
79  QLabel *labelIncluded = new QLabel (tr ("Included"));
80  layout->addWidget (labelIncluded, row, 0);
81 
82  QLabel *labelExcluded = new QLabel (tr ("Not included"));
83  layout->addWidget (labelExcluded, row++, 2);
84 
85  m_listIncluded = new QListWidget;
86  m_listIncluded->setSortingEnabled (false); // Preserve order from Document
87  m_listIncluded->setWhatsThis (tr ("List of curves to be included in the exported file.\n\n"
88  "The order of the curves here does not affect the order in the exported file. That "
89  "order is determined by the Curves settings."));
90  m_listIncluded->setSelectionMode (QAbstractItemView::MultiSelection);
91  layout->addWidget (m_listIncluded, row, 0, 4, 1);
92  connect (m_listIncluded, SIGNAL (itemSelectionChanged ()), this, SLOT (slotListIncluded()));
93 
94  m_listExcluded = new QListWidget;
95  m_listExcluded->setSortingEnabled (false); // Preserve order from Document
96  m_listExcluded->setWhatsThis (tr ("List of curves to be excluded from the exported file"));
97  m_listExcluded->setSelectionMode (QAbstractItemView::MultiSelection);
98  layout->addWidget (m_listExcluded, row++, 2, 4, 1);
99  connect (m_listExcluded, SIGNAL (itemSelectionChanged ()), this, SLOT (slotListExcluded()));
100 
101  m_btnInclude = new QPushButton (tr ("<<Include"));
102  m_btnInclude->setEnabled (false);
103  m_btnInclude->setWhatsThis (tr ("Move the currently selected curve(s) from the excluded list"));
104  layout->addWidget (m_btnInclude, row++, 1);
105  connect (m_btnInclude, SIGNAL (released ()), this, SLOT (slotInclude()));
106 
107  m_btnExclude = new QPushButton (tr ("Exclude>>"));
108  m_btnExclude->setEnabled (false);
109  m_btnExclude->setWhatsThis (tr ("Move the currently selected curve(s) from the included list"));
110  layout->addWidget (m_btnExclude, row++, 1);
111  connect (m_btnExclude, SIGNAL (released ()), this, SLOT (slotExclude()));
112 
113  row++;
114 }
115 
116 void DlgSettingsExportFormat::createDelimiters (QHBoxLayout *layoutMisc)
117 {
118  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::createDelimiters";
119 
120  QGroupBox *groupDelimiters = new QGroupBox (tr ("Delimiters"));
121  layoutMisc->addWidget (groupDelimiters, 1);
122 
123  QVBoxLayout *layoutDelimiters = new QVBoxLayout;
124  groupDelimiters->setLayout (layoutDelimiters);
125 
126  m_btnDelimitersCommas = new QRadioButton (exportDelimiterToString (EXPORT_DELIMITER_COMMA));
127  m_btnDelimitersCommas->setWhatsThis (tr ("Exported file will have commas between adjacent values, unless overridden by tabs in TSV files."));
128  layoutDelimiters->addWidget (m_btnDelimitersCommas);
129  connect (m_btnDelimitersCommas, SIGNAL (released ()), this, SLOT (slotDelimitersCommas()));
130 
131  m_btnDelimitersSpaces = new QRadioButton (exportDelimiterToString (EXPORT_DELIMITER_SPACE));
132  m_btnDelimitersSpaces->setWhatsThis (tr ("Exported file will have spaces between adjacent values, unless overridden by commas in CSV files, "
133  "or tabs in TSV files."));
134  layoutDelimiters->addWidget (m_btnDelimitersSpaces);
135  connect (m_btnDelimitersSpaces, SIGNAL (released ()), this, SLOT (slotDelimitersSpaces()));
136 
137  m_btnDelimitersTabs = new QRadioButton (exportDelimiterToString (EXPORT_DELIMITER_TAB));
138  m_btnDelimitersTabs->setWhatsThis (tr ("Exported file will have tabs between adjacent values, unless overridden by commas in CSV files."));
139  layoutDelimiters->addWidget (m_btnDelimitersTabs);
140  connect (m_btnDelimitersTabs, SIGNAL (released ()), this, SLOT (slotDelimitersTabs()));
141 
142  m_btnDelimitersSemicolons = new QRadioButton (exportDelimiterToString (EXPORT_DELIMITER_SEMICOLON));
143  m_btnDelimitersSemicolons->setWhatsThis (tr ("Exported file will have semicolons between adjacent values, unless overridden by commas in CSV files."));
144  layoutDelimiters->addWidget (m_btnDelimitersSemicolons);
145  connect (m_btnDelimitersSemicolons, SIGNAL (released ()), this, SLOT (slotDelimitersSemicolons()));
146 
147  m_chkOverrideCsvTsv = new QCheckBox (tr ("Override in CSV/TSV files"));
148  m_chkOverrideCsvTsv->setWhatsThis (tr ("Comma-separated value (CSV) files and tab-separated value (TSV) files will use commas and tabs "
149  "respectively, unless this setting is selected. Selecting this setting will apply the delimiter setting "
150  "to every file."));
151  connect (m_chkOverrideCsvTsv, SIGNAL (stateChanged (int)), this, SLOT (slotOverrideCsvTsv(int)));
152  layoutDelimiters->addWidget (m_chkOverrideCsvTsv);
153 }
154 
155 void DlgSettingsExportFormat::createFileLayout (QHBoxLayout *layoutMisc)
156 {
157  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::createFileLayout";
158 
159  QGroupBox *groupLayout = new QGroupBox (tr ("Layout"));
160  layoutMisc->addWidget (groupLayout, 1);
161 
162  QVBoxLayout *layoutLayout = new QVBoxLayout;
163  groupLayout->setLayout (layoutLayout);
164 
165  m_btnCurvesLayoutAllCurves = new QRadioButton (tr ("All curves on each line"));
166  m_btnCurvesLayoutAllCurves->setWhatsThis (tr ("Exported file will have, on each line, "
167  "an X value, the Y value for the first curve, the Y value for the second curve,..."));
168  layoutLayout->addWidget (m_btnCurvesLayoutAllCurves);
169  connect (m_btnCurvesLayoutAllCurves, SIGNAL (released()), this, SLOT (slotFunctionsLayoutAllCurves ()));
170 
171  m_btnCurvesLayoutOneCurve = new QRadioButton (tr ("One curve on each line"));
172  m_btnCurvesLayoutOneCurve->setWhatsThis (tr ("Exported file will have all the points for "
173  "the first curve, with one X-Y pair on each line, then the points for the second curve,..."));
174  layoutLayout->addWidget (m_btnCurvesLayoutOneCurve);
175  connect (m_btnCurvesLayoutOneCurve, SIGNAL (released()), this, SLOT (slotFunctionsLayoutOneCurve ()));
176 }
177 
178 void DlgSettingsExportFormat::createFunctionsPointsSelection (QHBoxLayout *layoutFunctions)
179 {
180  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::createFunctionsPointsSelection";
181 
182  QGroupBox *groupPointsSelection = new QGroupBox (tr ("Function Points Selection"));
183  layoutFunctions->addWidget (groupPointsSelection, 1);
184 
185  QGridLayout *layoutPointsSelections = new QGridLayout;
186  groupPointsSelection->setLayout (layoutPointsSelections);
187 
188  layoutPointsSelections->setColumnMinimumWidth(0, MIN_INDENT_COLUMN_WIDTH);
189  layoutPointsSelections->setColumnStretch (0, 0);
190  layoutPointsSelections->setColumnStretch (1, 0);
191  layoutPointsSelections->setColumnStretch (2, 0);
192  layoutPointsSelections->setColumnStretch (3, 1);
193 
194  int row = 0;
195 
196  m_btnFunctionsPointsAllCurves = new QRadioButton (tr ("Interpolate Ys at Xs from all curves"));
197  m_btnFunctionsPointsAllCurves->setWhatsThis (tr ("Exported file will have values at every unique X "
198  "value from every curve. Y values will be linearly interpolated if necessary"));
199  layoutPointsSelections->addWidget (m_btnFunctionsPointsAllCurves, row++, 0, 1, 4);
200  connect (m_btnFunctionsPointsAllCurves, SIGNAL (released()), this, SLOT (slotFunctionsPointsAllCurves()));
201 
202  m_btnFunctionsPointsFirstCurve = new QRadioButton (tr ("Interpolate Ys at Xs from first curve"));
203  m_btnFunctionsPointsFirstCurve->setWhatsThis (tr ("Exported file will have values at every unique X "
204  "value from the first curve. Y values will be linearly interpolated if necessary"));
205  layoutPointsSelections->addWidget (m_btnFunctionsPointsFirstCurve, row++, 0, 1, 4);
206  connect (m_btnFunctionsPointsFirstCurve, SIGNAL (released()), this, SLOT (slotFunctionsPointsFirstCurve()));
207 
208  m_btnFunctionsPointsEvenlySpaced = new QRadioButton (tr ("Interpolate Ys at evenly spaced X values."));
209  m_btnFunctionsPointsEvenlySpaced->setWhatsThis (tr ("Exported file will have values at evenly spaced X values, separated by the interval selected below."));
210  layoutPointsSelections->addWidget (m_btnFunctionsPointsEvenlySpaced, row++, 0, 1, 4);
211  connect (m_btnFunctionsPointsEvenlySpaced, SIGNAL (released()), this, SLOT (slotFunctionsPointsEvenlySpaced()));
212 
213  QLabel *labelInterval = new QLabel (tr ("Interval:"));
214  layoutPointsSelections->addWidget (labelInterval, row, 1, 1, 1, Qt::AlignRight);
215 
216  m_editFunctionsPointsEvenlySpacing = new QLineEdit;
217  m_validatorFunctionsPointsEvenlySpacing = new QDoubleValidator; // Minimum value, to prevent overflow, is set later according to settings
218  m_editFunctionsPointsEvenlySpacing->setValidator (m_validatorFunctionsPointsEvenlySpacing);
219  m_editFunctionsPointsEvenlySpacing->setMinimumWidth (MIN_EDIT_WIDTH);
220  m_editFunctionsPointsEvenlySpacing->setMaximumWidth (MAX_EDIT_WIDTH);
221  m_editFunctionsPointsEvenlySpacing->setWhatsThis (tr ("Interval, in the units of X, between successive points in the X direction.\n\n"
222  "If the scale is linear, then this interval is added to successive X values. If the scale is "
223  "logarithmic, then this interval is multiplied to successive X values.\n\n"
224  "The X values will be automatically aligned along simple numbers. If the first and/or last "
225  "points are not along the aligned X values, then one or two additional points are added "
226  "as necessary."));
227  layoutPointsSelections->addWidget (m_editFunctionsPointsEvenlySpacing, row, 2, 1, 1, Qt::AlignLeft);
228  connect (m_editFunctionsPointsEvenlySpacing, SIGNAL (textChanged(const QString &)), this, SLOT (slotFunctionsPointsEvenlySpacedInterval(const QString &)));
229 
230  m_cmbFunctionsPointsEvenlySpacingUnits = new QComboBox;
231  m_cmbFunctionsPointsEvenlySpacingUnits->setWhatsThis (tr ("Units for spacing interval.\n\n"
232  "Pixel units are preferred when the spacing is to be independent of the X scale. The spacing will be "
233  "consistent across the graph, even if the X scale is logarithmic.\n\n"
234  "Graph units are preferred when the spacing is to depend on the X scale."));
235  m_cmbFunctionsPointsEvenlySpacingUnits->addItem(exportPointsIntervalUnitsToString (EXPORT_POINTS_INTERVAL_UNITS_GRAPH),
236  QVariant (EXPORT_POINTS_INTERVAL_UNITS_GRAPH));
237  m_cmbFunctionsPointsEvenlySpacingUnits->addItem(exportPointsIntervalUnitsToString (EXPORT_POINTS_INTERVAL_UNITS_SCREEN),
238  QVariant (EXPORT_POINTS_INTERVAL_UNITS_SCREEN));
239  connect (m_cmbFunctionsPointsEvenlySpacingUnits, SIGNAL (activated (const QString &)),
240  this, SLOT (slotFunctionsPointsEvenlySpacedIntervalUnits (const QString &))); // activated() ignores code changes
241  layoutPointsSelections->addWidget (m_cmbFunctionsPointsEvenlySpacingUnits, row++, 3, 1, 1, Qt::AlignLeft);
242 
243  m_btnFunctionsPointsRaw = new QRadioButton (tr ("Raw Xs and Ys"));
244  m_btnFunctionsPointsRaw->setWhatsThis (tr ("Exported file will have only original X and Y values"));
245  layoutPointsSelections->addWidget (m_btnFunctionsPointsRaw, row++, 0, 1, 4);
246  connect (m_btnFunctionsPointsRaw, SIGNAL (released()), this, SLOT (slotFunctionsPointsRaw()));
247 }
248 
249 void DlgSettingsExportFormat::createHeader (QHBoxLayout *layoutMisc)
250 {
251  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::createHeader";
252 
253  const int COLUMN_RADIO_BUTTONS = 0, COLUMN_EMPTY = 1, COLUMN_LABEL = 2;
254 
255  QGroupBox *groupHeader = new QGroupBox (tr ("Header"));
256  layoutMisc->addWidget (groupHeader, 1);
257 
258  QGridLayout *layoutHeader = new QGridLayout;
259  layoutHeader->setColumnMinimumWidth(COLUMN_EMPTY,
260  MIN_HEADER_EMPTY_COLUMN_WIDTH);
261  groupHeader->setLayout (layoutHeader);
262  int row = 0;
263 
264  m_btnHeaderNone = new QRadioButton (exportHeaderToString (EXPORT_HEADER_NONE));
265  m_btnHeaderNone->setWhatsThis (tr ("Exported file will have no header line"));
266  layoutHeader->addWidget (m_btnHeaderNone, row++, COLUMN_RADIO_BUTTONS, 1, 1);
267  connect (m_btnHeaderNone, SIGNAL (released ()), this, SLOT (slotHeaderNone()));
268 
269  m_btnHeaderSimple = new QRadioButton (exportHeaderToString (EXPORT_HEADER_SIMPLE));
270  m_btnHeaderSimple->setWhatsThis (tr ("Exported file will have simple header line"));
271  layoutHeader->addWidget (m_btnHeaderSimple, row++, COLUMN_RADIO_BUTTONS, 1, 1);
272  connect (m_btnHeaderSimple, SIGNAL (released ()), this, SLOT (slotHeaderSimple()));
273 
274  m_btnHeaderGnuplot = new QRadioButton (exportHeaderToString (EXPORT_HEADER_GNUPLOT));
275  m_btnHeaderGnuplot->setWhatsThis (tr ("Exported file will have gnuplot header line"));
276  layoutHeader->addWidget (m_btnHeaderGnuplot, row++, COLUMN_RADIO_BUTTONS, 1, 1);
277  connect (m_btnHeaderGnuplot, SIGNAL (released()), this, SLOT (slotHeaderGnuplot()));
278 
279  createXLabel (layoutHeader,
280  COLUMN_LABEL);
281 }
282 
284 {
285  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::createOptionalSaveDefault";
286 
287  m_btnSaveDefault = new QPushButton (tr ("Save As Default"));
288  m_btnSaveDefault->setWhatsThis (tr ("Save the settings for use as future defaults."));
289  connect (m_btnSaveDefault, SIGNAL (released ()), this, SLOT (slotSaveDefault ()));
290  layout->addWidget (m_btnSaveDefault, 0, Qt::AlignLeft);
291 }
292 
293 void DlgSettingsExportFormat::createPreview(QGridLayout *layout, int &row)
294 {
295  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::createPreview";
296 
297  QLabel *label = new QLabel (tr ("Preview"));
298  layout->addWidget (label, row, 0, 1, 3);
299 
300  // Legend. Padding and margin in rich text do not work so &nbsp; is used for spacing
301  QLabel *labelLegend = new QLabel;
302  labelLegend->setTextFormat (Qt::RichText);
303  QString legendHtml = QString ("<span style=\"background-color: %1\">&nbsp;Functions&nbsp;</span>"
304  "&nbsp;&nbsp;&nbsp;"
305  "<span style=\"background-color: %2\">&nbsp;Relations&nbsp;</span>")
306  .arg (COLOR_FUNCTIONS)
307  .arg (COLOR_RELATIONS);
308  labelLegend->setText (legendHtml);
309  layout->addWidget (labelLegend, row++, 1, 1, 2, Qt::AlignRight);
310 
311  m_editPreview = new QTextEdit;
312  m_editPreview->setReadOnly (true);
313  m_editPreview->setWhatsThis (tr ("Preview window shows how current settings affect the exported file.\n\n"
314  "Functions (shown here in blue) are output first, followed by relations "
315  "(shown here in green) if any exist."));
316  m_editPreview->setMinimumHeight (MINIMUM_PREVIEW_HEIGHT);
317  m_editPreview->document()->setDefaultStyleSheet("div { padding-left: 20px; }");
318  QPalette p = m_editPreview->palette();
319  p.setColor (QPalette::Base, QColor (240, 240, 240)); // Replace attention-getting white border by gray
320  m_editPreview->setPalette (p);
321 
322  layout->addWidget (m_editPreview, row++, 0, 1, 3);
323 }
324 
325 void DlgSettingsExportFormat::createRelationsPointsSelection (QHBoxLayout *layoutRelations)
326 {
327  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::createRelationsPointsSelection";
328 
329  QGroupBox *groupPointsSelection = new QGroupBox (tr ("Relation Points Selection"));
330  layoutRelations->addWidget (groupPointsSelection);
331 
332  QGridLayout *layoutPointsSelections = new QGridLayout;
333  groupPointsSelection->setLayout (layoutPointsSelections);
334 
335  layoutPointsSelections->setColumnMinimumWidth(0, MIN_INDENT_COLUMN_WIDTH);
336  layoutPointsSelections->setColumnStretch (0, 0);
337  layoutPointsSelections->setColumnStretch (1, 0);
338  layoutPointsSelections->setColumnStretch (2, 0);
339  layoutPointsSelections->setColumnStretch (3, 1);
340 
341  int row = 0;
342 
343  m_btnRelationsPointsEvenlySpaced = new QRadioButton (tr ("Interpolate Xs and Ys at evenly spaced intervals."));
344  m_btnRelationsPointsEvenlySpaced->setWhatsThis (tr ("Exported file will have points evenly spaced along each relation, separated by the interval "
345  "selected below. If the last interval does not end at the last point, then a shorter last interval "
346  "is added that ends on the last point."));
347  layoutPointsSelections->addWidget (m_btnRelationsPointsEvenlySpaced, row++, 0, 1, 4);
348  connect (m_btnRelationsPointsEvenlySpaced, SIGNAL (released()), this, SLOT (slotRelationsPointsEvenlySpaced()));
349 
350  QLabel *labelInterval = new QLabel (tr ("Interval:"));
351  layoutPointsSelections->addWidget (labelInterval, row, 1, 1, 1, Qt::AlignRight);
352 
353  m_editRelationsPointsEvenlySpacing = new QLineEdit;
354  m_validatorRelationsPointsEvenlySpacing = new QDoubleValidator; // Minimum value, to prevent overflow, is set later according to settings
355  m_editRelationsPointsEvenlySpacing->setValidator (m_validatorRelationsPointsEvenlySpacing);
356  m_editRelationsPointsEvenlySpacing->setMinimumWidth (MIN_EDIT_WIDTH);
357  m_editRelationsPointsEvenlySpacing->setMaximumWidth (MAX_EDIT_WIDTH);
358  m_editRelationsPointsEvenlySpacing->setWhatsThis (tr ("Interval between successive points when "
359  "exporting at evenly spaced (X,Y) coordinates."));
360  layoutPointsSelections->addWidget (m_editRelationsPointsEvenlySpacing, row, 2, 1, 1, Qt::AlignLeft);
361  connect (m_editRelationsPointsEvenlySpacing, SIGNAL (textChanged(const QString &)), this, SLOT (slotRelationsPointsEvenlySpacedInterval(const QString &)));
362 
363  m_cmbRelationsPointsEvenlySpacingUnits = new QComboBox;
364  m_cmbRelationsPointsEvenlySpacingUnits->setWhatsThis (tr ("Units for spacing interval.\n\n"
365  "Pixel units are preferred when the spacing is to be independent of the X and Y scales. The spacing will be "
366  "consistent across the graph, even if a scale is logarithmic or the X and Y scales are different.\n\n"
367  "Graph units are usually preferred when the X and Y scales are identical."));
368  m_cmbRelationsPointsEvenlySpacingUnits->addItem(exportPointsIntervalUnitsToString (EXPORT_POINTS_INTERVAL_UNITS_GRAPH),
369  QVariant (EXPORT_POINTS_INTERVAL_UNITS_GRAPH));
370  m_cmbRelationsPointsEvenlySpacingUnits->addItem(exportPointsIntervalUnitsToString (EXPORT_POINTS_INTERVAL_UNITS_SCREEN),
371  QVariant (EXPORT_POINTS_INTERVAL_UNITS_SCREEN));
372  connect (m_cmbRelationsPointsEvenlySpacingUnits, SIGNAL (activated (const QString &)),
373  this, SLOT (slotRelationsPointsEvenlySpacedIntervalUnits (const QString &))); // activated() ignores code changes
374  layoutPointsSelections->addWidget (m_cmbRelationsPointsEvenlySpacingUnits, row++, 3, 1, 1, Qt::AlignLeft);
375 
376  m_btnRelationsPointsRaw = new QRadioButton (tr ("Raw Xs and Ys"));
377  m_btnRelationsPointsRaw->setWhatsThis (tr ("Exported file will have only original X and Y values"));
378  layoutPointsSelections->addWidget (m_btnRelationsPointsRaw, row++, 0, 1, 4);
379  connect (m_btnRelationsPointsRaw, SIGNAL (released()), this, SLOT (slotRelationsPointsRaw()));
380 }
381 
383 {
384  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::createSubPanel";
385 
386  QWidget *subPanel = new QWidget ();
387  QGridLayout *layout = new QGridLayout (subPanel);
388  subPanel->setLayout (layout);
389 
390  int row = 0;
391  createCurveSelection (layout, row);
392 
393  createTabWidget (layout,
394  row);
395 
396  QWidget *widgetMisc = new QWidget;
397  layout->addWidget (widgetMisc, row++, 0, 1, 3);
398  QHBoxLayout *layoutMisc = new QHBoxLayout;
399  widgetMisc->setLayout (layoutMisc);
400 
401  createDelimiters (layoutMisc); // One row of radio buttons
402  createHeader (layoutMisc); // Two rows with radio buttons and then header label
403  createFileLayout (layoutMisc); // One row of radio buttons
404 
405  createPreview (layout, row);
406 
407  return subPanel;
408 }
409 
410 void DlgSettingsExportFormat::createTabWidget (QGridLayout *layout,
411  int &row)
412 {
413  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::createTabWidget";
414 
415  m_tabWidget = new QTabWidget;
416  // This gets connected below, after the tabs have been added
417  layout->addWidget (m_tabWidget, row++, 0, 1, 3);
418 
419  QWidget *widgetFunctions = new QWidget;
420  int indexFunctions = m_tabWidget->addTab (widgetFunctions, tr ("Functions"));
421  QWidget *tabFunctions = m_tabWidget->widget (indexFunctions);
422  tabFunctions->setWhatsThis (tr ("Functions Tab\n\n"
423  "Controls for specifying the format of functions during export"));
424  QHBoxLayout *layoutFunctions = new QHBoxLayout;
425  widgetFunctions->setLayout (layoutFunctions);
426 
427  QWidget *widgetRelations = new QWidget;
428  int indexRelations = m_tabWidget->addTab (widgetRelations, tr ("Relations"));
429  QWidget *tabRelations = m_tabWidget->widget (indexRelations);
430  tabRelations->setWhatsThis (tr ("Relations Tab\n\n"
431  "Controls for specifying the format of relations during export"));
432  QHBoxLayout *layoutRelations = new QHBoxLayout;
433  widgetRelations->setLayout (layoutRelations);
434 
435  // Now that the tabs have been added we can connect this signal
436  connect (m_tabWidget, SIGNAL (currentChanged (int)), this, SLOT (slotTabChanged (int)));
437 
438  createFunctionsPointsSelection (layoutFunctions);
439  createRelationsPointsSelection (layoutRelations);
440 }
441 
442 void DlgSettingsExportFormat::createXLabel (QGridLayout *layoutHeader,
443  int colLabel)
444 {
445  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::createXLabel";
446 
447  int row = 1; // Skip first row
448 
449  QLabel *title;
450  if (true) {
451  title = new QLabel (tr ("X Label:"));
452  } else {
453  title = new QLabel (tr ("Theta Label:"));
454  }
455  layoutHeader->addWidget (title, row++, colLabel, 1, 1);
456 
457  m_editXLabel = new QLineEdit;
458  if (true) {
459  m_editXLabel->setWhatsThis (tr ("Label in the header for x values"));
460  } else {
461  m_editXLabel->setWhatsThis (tr ("Label in the header for theta values"));
462  }
463  layoutHeader->addWidget (m_editXLabel, row++, colLabel, 1, 1);
464  connect (m_editXLabel, SIGNAL (textChanged (const QString &)), this, SLOT (slotXLabel(const QString &)));
465 }
466 
467 QString DlgSettingsExportFormat::exportedTextToExportedHtml (const QString &text,
468  const QString &color) const
469 {
470  QRegExp re ("<br>$");
471 
472  QString textCopy (text);
473  QString replaced = textCopy
474  .replace ("\n", "<br>")
475  .replace (" ", "&nbsp;")
476  .replace (re, "")
477  .replace ("\t", "&nbsp;&nbsp;&nbsp;&nbsp;");
478 
479  QString html = QString ("<div style=\"display: inline; background-color: %1\">%2</div>")
480  .arg (color)
481  .arg (replaced);
482 
483  return html;
484 }
485 
486 bool DlgSettingsExportFormat::goodIntervalFunctions() const
487 {
488  // LOG4CPP_INFO_S is below
489 
490  QString textFunctions = m_editFunctionsPointsEvenlySpacing->text();
491  int posFunctions;
492 
493  bool isGood = (m_validatorFunctionsPointsEvenlySpacing->validate (textFunctions, posFunctions) == QValidator::Acceptable);
494 
495  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::goodIntervalFunctions"
496  << " text=" << textFunctions.toLatin1().data()
497  << " good=" << (isGood ? "true" : "false")
498  << " bottom=" << m_validatorFunctionsPointsEvenlySpacing->bottom()
499  << " top=" << m_validatorFunctionsPointsEvenlySpacing->top();
500 
501  return isGood;
502 }
503 
504 bool DlgSettingsExportFormat::goodIntervalRelations() const
505 {
506  // LOG4CPP_INFO_S is below
507 
508  QString textRelations = m_editRelationsPointsEvenlySpacing->text();
509  int posRelations;
510 
511  bool isGood = (m_validatorRelationsPointsEvenlySpacing->validate (textRelations, posRelations) == QValidator::Acceptable);
512 
513  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::goodIntervalRelations"
514  << " text=" << textRelations.toLatin1().data()
515  << " good=" << (isGood ? "true" : "false")
516  << " bottom=" << m_validatorRelationsPointsEvenlySpacing->bottom()
517  << " top=" << m_validatorRelationsPointsEvenlySpacing->top();
518 
519  return isGood;
520 }
521 
523 {
524  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::handleOk";
525 
527  cmdMediator ().document(),
528  *m_modelExportBefore,
529  *m_modelExportAfter);
530  cmdMediator ().push (cmd);
531 
532  hide ();
533 }
534 
535 void DlgSettingsExportFormat::initializeIntervalConstraints ()
536 {
537  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::initializeIntervalConstraints";
538 
539  const int MAX_POINTS_ACROSS_RANGE = 5000;
540 
541  // Get min and max of graph and screen coordinates
542  CallbackBoundingRects ftor (mainWindow().transformation());
543 
544  Functor2wRet<const QString &, const Point &, CallbackSearchReturn> ftorWithCallback = functor_ret (ftor,
546  cmdMediator().iterateThroughCurvesPointsGraphs (ftorWithCallback);
547 
548  // If there are no points, then interval will be zero. That special case must be handled downstream to prevent infinite loops
549  bool isEmpty;
550  double maxSizeGraph = qMax (ftor.boundingRectGraph(isEmpty).width(),
551  ftor.boundingRectGraph(isEmpty).height());
552  double maxSizeScreen = qMax (ftor.boundingRectScreen(isEmpty).width(),
553  ftor.boundingRectScreen(isEmpty).height());
554  m_minIntervalGraph = maxSizeGraph / MAX_POINTS_ACROSS_RANGE;
555  m_minIntervalScreen = maxSizeScreen / MAX_POINTS_ACROSS_RANGE;
556 }
557 
559 {
560  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::load";
561 
562  setCmdMediator (cmdMediator);
563 
564  // Flush old data
565  if (m_modelExportBefore != 0) {
566  delete m_modelExportBefore;
567  }
568  if (m_modelExportAfter != 0) {
569  delete m_modelExportAfter;
570  }
571 
572  // Save new data
573  m_modelExportBefore = new DocumentModelExportFormat (cmdMediator.document());
574  m_modelExportAfter = new DocumentModelExportFormat (cmdMediator.document());
575 
576  // Populate controls. First load excluded curves
577  m_listExcluded->clear();
578  QStringList curveNamesExcluded = m_modelExportAfter->curveNamesNotExported();
579  QStringList::const_iterator itr;
580  for (itr = curveNamesExcluded.begin (); itr != curveNamesExcluded.end(); ++itr) {
581  QString curveNameNotExported = *itr;
582  m_listExcluded->addItem (curveNameNotExported);
583  }
584 
585  // Include curves that are not excluded
586  m_listIncluded->clear();
587  QStringList curveNamesAll = cmdMediator.document().curvesGraphsNames();
588  for (itr = curveNamesAll.begin (); itr != curveNamesAll.end(); itr++) {
589  QString curveName = *itr;
590  if (!curveNamesExcluded.contains (curveName)) {
591  m_listIncluded->addItem (curveName);
592  }
593  }
594 
595  ExportPointsSelectionFunctions pointsSelectionFunctions = m_modelExportAfter->pointsSelectionFunctions();
596  m_btnFunctionsPointsAllCurves->setChecked (pointsSelectionFunctions == EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_ALL_CURVES);
597  m_btnFunctionsPointsFirstCurve->setChecked (pointsSelectionFunctions == EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_FIRST_CURVE);
598  m_btnFunctionsPointsEvenlySpaced->setChecked (pointsSelectionFunctions == EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_PERIODIC);
599  m_btnFunctionsPointsRaw->setChecked (pointsSelectionFunctions == EXPORT_POINTS_SELECTION_FUNCTIONS_RAW);
600 
601  ExportLayoutFunctions layoutFunctions = m_modelExportAfter->layoutFunctions ();
602  m_btnCurvesLayoutAllCurves->setChecked (layoutFunctions == EXPORT_LAYOUT_ALL_PER_LINE);
603  m_btnCurvesLayoutOneCurve->setChecked (layoutFunctions == EXPORT_LAYOUT_ONE_PER_LINE);
604 
605  ExportPointsSelectionRelations pointsSelectionRelations = m_modelExportAfter->pointsSelectionRelations();
606  m_btnRelationsPointsEvenlySpaced->setChecked (pointsSelectionRelations == EXPORT_POINTS_SELECTION_RELATIONS_INTERPOLATE);
607  m_btnRelationsPointsRaw->setChecked (pointsSelectionRelations == EXPORT_POINTS_SELECTION_RELATIONS_RAW);
608 
609  ExportDelimiter delimiter = m_modelExportAfter->delimiter ();
610  m_btnDelimitersCommas->setChecked (delimiter == EXPORT_DELIMITER_COMMA);
611  m_btnDelimitersSpaces->setChecked (delimiter == EXPORT_DELIMITER_SPACE);
612  m_btnDelimitersTabs->setChecked (delimiter == EXPORT_DELIMITER_TAB);
613  m_btnDelimitersSemicolons->setChecked (delimiter == EXPORT_DELIMITER_SEMICOLON);
614 
615  m_chkOverrideCsvTsv->setChecked (m_modelExportAfter->overrideCsvTsv());
616 
617  ExportHeader header = m_modelExportAfter->header ();
618  m_btnHeaderNone->setChecked (header == EXPORT_HEADER_NONE);
619  m_btnHeaderSimple->setChecked (header == EXPORT_HEADER_SIMPLE);
620  m_btnHeaderGnuplot->setChecked (header == EXPORT_HEADER_GNUPLOT);
621 
622  m_editXLabel->setText (m_modelExportAfter->xLabel());
623 
624  m_editFunctionsPointsEvenlySpacing->setText (QString::number (m_modelExportAfter->pointsIntervalFunctions()));
625  m_editRelationsPointsEvenlySpacing->setText (QString::number (m_modelExportAfter->pointsIntervalRelations()));
626 
627  ExportPointsIntervalUnits pointsIntervalUnitsFunctions = m_modelExportAfter->pointsIntervalUnitsFunctions();
628  ExportPointsIntervalUnits pointsIntervalUnitsRelations = m_modelExportAfter->pointsIntervalUnitsRelations();
629  int indexFunctions = m_cmbFunctionsPointsEvenlySpacingUnits->findData (QVariant (pointsIntervalUnitsFunctions));
630  int indexRelations = m_cmbRelationsPointsEvenlySpacingUnits->findData (QVariant (pointsIntervalUnitsRelations));
631  m_cmbFunctionsPointsEvenlySpacingUnits->setCurrentIndex (indexFunctions);
632  m_cmbRelationsPointsEvenlySpacingUnits->setCurrentIndex (indexRelations);
633 
634  initializeIntervalConstraints ();
635 
636  updateControlsUponLoad (); // Before updateControls so m_haveFunction and m_haveRelation are set
637  updateControls();
638  updateIntervalConstraints();
639  enableOk (false); // Disable Ok button since there not yet any changes
640  updatePreview();
641 }
642 
644 {
645  if (!smallDialogs) {
646  setMinimumHeight (MINIMUM_HEIGHT);
647  }
648 }
649 
650 void DlgSettingsExportFormat::slotDelimitersCommas()
651 {
652  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotDelimitersCommas";
653 
654  m_modelExportAfter->setDelimiter(EXPORT_DELIMITER_COMMA);
655  updateControls();
656  updatePreview();
657 }
658 
659 void DlgSettingsExportFormat::slotDelimitersSemicolons()
660 {
661  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotDelimitersSemicolons";
662 
663  m_modelExportAfter->setDelimiter(EXPORT_DELIMITER_SEMICOLON);
664  updateControls();
665  updatePreview();
666 }
667 
668 void DlgSettingsExportFormat::slotDelimitersSpaces()
669 {
670  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotDelimitersSpaces";
671 
672  m_modelExportAfter->setDelimiter(EXPORT_DELIMITER_SPACE);
673  updateControls();
674  updatePreview();
675 }
676 
677 void DlgSettingsExportFormat::slotDelimitersTabs()
678 {
679  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotDelimitersTabs";
680 
681  m_modelExportAfter->setDelimiter(EXPORT_DELIMITER_TAB);
682  updateControls();
683  updatePreview();
684 }
685 
686 void DlgSettingsExportFormat::slotExclude ()
687 {
688  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotExclude";
689 
690  // Perform forward pass to get excluded curves in the proper order
691  int i;
692  QStringList excluded;
693  for (i = 0; i < m_listIncluded->count(); i++) {
694  if (m_listIncluded->item(i)->isSelected()) {
695  excluded += m_listIncluded->item(i)->text();
696  }
697  }
698 
699  // Add the excluded curves to the excluded list
700  for (i = 0; i < excluded.count(); i++) {
701  QString curveName = excluded.at (i);
702  m_listExcluded->addItem (curveName);
703  }
704 
705  // Perform backwards pass to remove the excluded curves from the included list
706  for (i = m_listIncluded->count() - 1; i>= 0; i--) {
707  QString curveName = m_listIncluded->item(i)->text();
708  if (excluded.contains (curveName)) {
709  QListWidgetItem *item = m_listIncluded->item (i);
710  m_listIncluded->removeItemWidget (item);
711  delete item;
712  }
713  }
714 
715  m_modelExportAfter->setCurveNamesNotExported(excluded);
716  updateControls();
717  updatePreview();
718 }
719 
720 void DlgSettingsExportFormat::slotFunctionsLayoutAllCurves()
721 {
722  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotFunctionsLayoutAllCurves";
723 
724  m_modelExportAfter->setLayoutFunctions(EXPORT_LAYOUT_ALL_PER_LINE);
725  updateControls();
726  updatePreview();
727 }
728 
729 void DlgSettingsExportFormat::slotFunctionsLayoutOneCurve()
730 {
731  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotFunctionsLayoutOneCurve";
732 
733  m_modelExportAfter->setLayoutFunctions(EXPORT_LAYOUT_ONE_PER_LINE);
734  updateControls();
735  updatePreview();
736 }
737 
738 void DlgSettingsExportFormat::slotFunctionsPointsAllCurves()
739 {
740  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotFunctionsPointsAllCurves";
741 
742  m_modelExportAfter->setPointsSelectionFunctions(EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_ALL_CURVES);
743  updateControls();
744  updatePreview();
745 }
746 
747 void DlgSettingsExportFormat::slotFunctionsPointsEvenlySpaced()
748 {
749  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotFunctionsPointsEvenlySpaced";
750 
751  m_modelExportAfter->setPointsSelectionFunctions(EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_PERIODIC);
752  updateControls();
753  updatePreview();
754 }
755 
756 void DlgSettingsExportFormat::slotFunctionsPointsEvenlySpacedInterval(const QString &)
757 {
758  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotFunctionsPointsEvenlySpacedInterval";
759 
760  // Prevent infinite loop on empty and "-" values which get treated as zero interval
761  if (goodIntervalFunctions()) {
762  m_modelExportAfter->setPointsIntervalFunctions(m_editFunctionsPointsEvenlySpacing->text().toDouble());
763  updateControls();
764  updatePreview();
765  } else {
766  m_editPreview->setText(EMPTY_PREVIEW);
767  }
768 }
769 
770 void DlgSettingsExportFormat::slotFunctionsPointsEvenlySpacedIntervalUnits(const QString &)
771 {
772  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotFunctionsPointsEvenlySpacedIntervalUnits";
773 
774  int index = m_cmbFunctionsPointsEvenlySpacingUnits->currentIndex();
775  ExportPointsIntervalUnits units = (ExportPointsIntervalUnits) m_cmbFunctionsPointsEvenlySpacingUnits->itemData (index).toInt();
776 
777  m_modelExportAfter->setPointsIntervalUnitsFunctions(units);
778  updateIntervalConstraints(); // Call this before updateControls so constraint checking is updated for ok button
779  updateControls();
780  updatePreview();
781 }
782 
783 void DlgSettingsExportFormat::slotFunctionsPointsFirstCurve()
784 {
785  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotFunctionsPointsFirstCurve";
786 
787  m_modelExportAfter->setPointsSelectionFunctions(EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_FIRST_CURVE);
788  updateControls();
789  updatePreview();
790 }
791 
792 void DlgSettingsExportFormat::slotFunctionsPointsRaw()
793 {
794  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotFunctionsPointsRaw";
795 
796  m_modelExportAfter->setPointsSelectionFunctions(EXPORT_POINTS_SELECTION_FUNCTIONS_RAW);
797  updateControls();
798  updatePreview();
799 }
800 
801 void DlgSettingsExportFormat::slotHeaderGnuplot()
802 {
803  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotHeaderGnuplot";
804 
805  m_modelExportAfter->setHeader(EXPORT_HEADER_GNUPLOT);
806  updateControls();
807  updatePreview();
808 }
809 
810 void DlgSettingsExportFormat::slotHeaderNone()
811 {
812  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotHeaderNone";
813 
814  m_modelExportAfter->setHeader(EXPORT_HEADER_NONE);
815  updateControls();
816  updatePreview();
817 }
818 
819 void DlgSettingsExportFormat::slotHeaderSimple()
820 {
821  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotHeaderSimple";
822 
823  m_modelExportAfter->setHeader(EXPORT_HEADER_SIMPLE);
824  updateControls();
825  updatePreview();
826 }
827 
828 void DlgSettingsExportFormat::slotInclude ()
829 {
830  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotInclude";
831 
832  // Perform forward pass to get included curves in the proper order
833  int i;
834  QStringList included;
835  for (i = 0; i < m_listExcluded->count(); i++) {
836  if (m_listExcluded->item(i)->isSelected()) {
837  included += m_listExcluded->item(i)->text();
838  }
839  }
840 
841  // Add the included curves to the included list
842  for (i = 0; i < included.count(); i++) {
843  QString curveName = included.at (i);
844  m_listIncluded->addItem (curveName);
845  }
846 
847  // Perform backwards pass to remove the included curves from the excluded list
848  QStringList excluded;
849  for (i = m_listExcluded->count() - 1; i>= 0; i--) {
850  QString curveName = m_listExcluded->item(i)->text();
851  QListWidgetItem *item = m_listExcluded->item (i);
852  if (included.contains (curveName)) {
853  m_listExcluded->removeItemWidget (item);
854  delete item;
855  } else {
856  excluded += item->text();
857  }
858  }
859 
860  m_modelExportAfter->setCurveNamesNotExported(excluded);
861  updateControls();
862  updatePreview();
863 }
864 
865 void DlgSettingsExportFormat::slotListExcluded()
866 {
867  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotListExcluded";
868 
869  updateControls();
870  // Do not call updatePreview since this method changes nothing
871 }
872 
873 void DlgSettingsExportFormat::slotListIncluded()
874 {
875  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotListIncluded";
876 
877  updateControls();
878  // Do not call updatePreview since this method changes nothing
879 }
880 
881 void DlgSettingsExportFormat::slotOverrideCsvTsv(int)
882 {
883  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotOverrideCsvTsv";
884 
885  m_modelExportAfter->setOverrideCsvTsv(m_chkOverrideCsvTsv->isChecked());
886  updateControls();
887  updatePreview();
888 }
889 
890 void DlgSettingsExportFormat::slotRelationsPointsEvenlySpaced()
891 {
892  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotRelationsPointsEvenlySpaced";
893 
894  m_modelExportAfter->setPointsSelectionRelations(EXPORT_POINTS_SELECTION_RELATIONS_INTERPOLATE);
895  updateControls();
896  updatePreview();
897 }
898 
899 void DlgSettingsExportFormat::slotRelationsPointsEvenlySpacedInterval(const QString &)
900 {
901  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotRelationsPointsEvenlySpacedInterval";
902 
903  m_modelExportAfter->setPointsIntervalRelations(m_editRelationsPointsEvenlySpacing->text().toDouble());
904  updateControls();
905  updatePreview();
906 }
907 
908 void DlgSettingsExportFormat::slotRelationsPointsEvenlySpacedIntervalUnits(const QString &)
909 {
910  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotRelationsPointsEvenlySpacedIntervalUnits";
911 
912  int index = m_cmbRelationsPointsEvenlySpacingUnits->currentIndex();
913  ExportPointsIntervalUnits units = (ExportPointsIntervalUnits) m_cmbRelationsPointsEvenlySpacingUnits->itemData (index).toInt();
914 
915  m_modelExportAfter->setPointsIntervalUnitsRelations(units);
916  updateIntervalConstraints(); // Call this before updateControls so constraint checking is updated for ok button
917  updateControls();
918  updatePreview();
919 }
920 
921 void DlgSettingsExportFormat::slotRelationsPointsRaw()
922 {
923  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotRelationsPointsRaw";
924 
925  m_modelExportAfter->setPointsSelectionRelations(EXPORT_POINTS_SELECTION_RELATIONS_RAW);
926  updateControls();
927  updatePreview();
928 }
929 
930 void DlgSettingsExportFormat::slotSaveDefault()
931 {
932  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotSaveDefault";
933 
934  QSettings settings (SETTINGS_ENGAUGE, SETTINGS_DIGITIZER);
935  settings.beginGroup (SETTINGS_GROUP_EXPORT);
936 
937  settings.setValue (SETTINGS_EXPORT_DELIMITER,
938  QVariant (m_modelExportAfter->delimiter()));
939  settings.setValue (SETTINGS_EXPORT_HEADER,
940  QVariant (m_modelExportAfter->header()));
941  settings.setValue (SETTINGS_EXPORT_LAYOUT_FUNCTIONS,
942  QVariant (m_modelExportAfter->layoutFunctions()));
943  settings.setValue (SETTINGS_EXPORT_POINTS_INTERVAL_FUNCTIONS,
944  QVariant (m_modelExportAfter->pointsIntervalFunctions()));
945  settings.setValue (SETTINGS_EXPORT_POINTS_INTERVAL_RELATIONS,
946  QVariant (m_modelExportAfter->pointsIntervalRelations()));
947  settings.setValue (SETTINGS_EXPORT_POINTS_INTERVAL_UNITS_FUNCTIONS,
948  QVariant (m_modelExportAfter->pointsIntervalUnitsFunctions()));
949  settings.setValue (SETTINGS_EXPORT_POINTS_INTERVAL_UNITS_RELATIONS,
950  QVariant (m_modelExportAfter->pointsIntervalUnitsRelations()));
951  settings.setValue (SETTINGS_EXPORT_POINTS_SELECTION_FUNCTIONS,
952  QVariant (m_modelExportAfter->pointsSelectionFunctions()));
953  settings.setValue (SETTINGS_EXPORT_POINTS_SELECTION_RELATIONS,
954  QVariant (m_modelExportAfter->pointsSelectionRelations()));
955  settings.setValue (SETTINGS_EXPORT_X_LABEL,
956  QVariant (m_modelExportAfter->xLabel()));
957 
958  settings.endGroup ();
959 }
960 
961 void DlgSettingsExportFormat::slotTabChanged (int)
962 {
963  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotTabChanged";
964 
965  updatePreview();
966 }
967 
968 void DlgSettingsExportFormat::slotXLabel(const QString &)
969 {
970  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotXLabel";
971 
972  m_modelExportAfter->setXLabel (m_editXLabel->text());
973  updateControls();
974  updatePreview();
975 }
976 
977 void DlgSettingsExportFormat::updateControls ()
978 {
979  bool isGoodState = goodIntervalFunctions() &&
980  goodIntervalRelations();
981  enableOk (isGoodState);
982 
983  int selectedForInclude = m_listExcluded->selectedItems().count();
984  int selectedForExclude = m_listIncluded->selectedItems().count();
985  int inInclude = m_listIncluded->count();
986 
987  m_btnInclude->setEnabled (selectedForInclude > 0); // Need at least one selection
988  m_btnExclude->setEnabled ((selectedForExclude > 0) && (inInclude - selectedForExclude > 0)); // Need at least one selection, and one left after the move
989 
990  m_editFunctionsPointsEvenlySpacing->setEnabled (m_haveFunction && m_btnFunctionsPointsEvenlySpaced->isChecked ());
991  m_editRelationsPointsEvenlySpacing->setEnabled (m_haveRelation && m_btnRelationsPointsEvenlySpaced->isChecked ());
992 
993  m_editXLabel->setEnabled (!m_btnHeaderNone->isChecked());
994 }
995 
996 void DlgSettingsExportFormat::updateControlsUponLoad ()
997 {
998  CurveStyles curveStyles = cmdMediator().document().modelCurveStyles();
999 
1000  m_haveFunction = false;
1001  m_haveRelation = false;
1002 
1003  QStringList curveNames = curveStyles.curveNames();
1004 
1005  QStringList::const_iterator itr;
1006  for (itr = curveNames.begin(); itr != curveNames.end (); itr++) {
1007  QString curveName = *itr;
1008  CurveStyle curveStyle = curveStyles.curveStyle (curveName);
1009  CurveConnectAs curveConnectAs = curveStyle.lineStyle().curveConnectAs();
1010  if (curveConnectAs == CONNECT_AS_FUNCTION_SMOOTH || curveConnectAs == CONNECT_AS_FUNCTION_STRAIGHT) {
1011  m_haveFunction = true;
1012  } else if (curveConnectAs == CONNECT_AS_RELATION_SMOOTH || curveConnectAs == CONNECT_AS_RELATION_STRAIGHT) {
1013  m_haveRelation = true;
1014  }
1015  }
1016 
1017  // Enable function-specific widgets if appropriate
1018  m_btnFunctionsPointsAllCurves->setEnabled (m_haveFunction);
1019  m_btnFunctionsPointsFirstCurve->setEnabled (m_haveFunction);
1020  m_btnFunctionsPointsEvenlySpaced->setEnabled (m_haveFunction);
1021  m_editFunctionsPointsEvenlySpacing->setEnabled (m_haveFunction);
1022  m_cmbFunctionsPointsEvenlySpacingUnits->setEnabled (m_haveFunction);
1023  m_btnFunctionsPointsRaw->setEnabled (m_haveFunction);
1024 
1025  // Enable relation-specific widgets if appropriate
1026  m_btnRelationsPointsEvenlySpaced->setEnabled (m_haveRelation);
1027  m_editRelationsPointsEvenlySpacing->setEnabled (m_haveRelation);
1028  m_cmbRelationsPointsEvenlySpacingUnits->setEnabled (m_haveRelation);
1029  m_btnRelationsPointsRaw->setEnabled (m_haveRelation);
1030 
1031  // Do not start with a tab that does not apply to the current set of functions/relations
1032  if (!m_haveRelation) {
1033  m_tabWidget->setCurrentIndex (TAB_WIDGET_INDEX_FUNCTIONS);
1034  } else if (!m_haveFunction) {
1035  m_tabWidget->setCurrentIndex (TAB_WIDGET_INDEX_RELATIONS);
1036  }
1037 }
1038 
1039 void DlgSettingsExportFormat::updateIntervalConstraints ()
1040 {
1041  double functionsMin = (m_modelExportAfter->pointsIntervalUnitsFunctions() == EXPORT_POINTS_INTERVAL_UNITS_GRAPH ?
1042  m_minIntervalGraph :
1043  m_minIntervalScreen);
1044  double relationsMin = (m_modelExportAfter->pointsIntervalUnitsRelations() == EXPORT_POINTS_INTERVAL_UNITS_GRAPH ?
1045  m_minIntervalGraph :
1046  m_minIntervalScreen);
1047 
1048  if (m_tabWidget->currentIndex() == TAB_WIDGET_INDEX_FUNCTIONS) {
1049 
1050  if (m_modelExportAfter->pointsIntervalFunctions() < functionsMin) {
1051 
1052  m_editFunctionsPointsEvenlySpacing->setText (QString::number (functionsMin));
1053 
1054  }
1055 
1056  m_validatorFunctionsPointsEvenlySpacing->setBottom (functionsMin);
1057 
1058  } else {
1059 
1060  if (m_modelExportAfter->pointsIntervalRelations() < relationsMin) {
1061 
1062  m_editRelationsPointsEvenlySpacing->setText (QString::number (relationsMin));
1063 
1064  }
1065 
1066  m_validatorRelationsPointsEvenlySpacing->setBottom (relationsMin);
1067  }
1068 }
1069 
1070 void DlgSettingsExportFormat::updatePreview()
1071 {
1072  // Save the scroll position for continuity before and after the preview update
1073  int scrollPosition = m_editPreview->verticalScrollBar()->value();
1074 
1075  QString exportedTextFunctions, exportedTextRelations, exportedHtml;
1076  QTextStream strFunctions (&exportedTextFunctions);
1077  QTextStream strRelations (&exportedTextRelations);
1078 
1079  if (mainWindow().transformation().transformIsDefined()) {
1080 
1081  unsigned int numWritesSoFar = 0;
1082 
1083  ExportFileFunctions exportStrategyFunctions;
1084  exportStrategyFunctions.exportToFile (*m_modelExportAfter,
1085  cmdMediator().document(),
1086  mainWindow().modelMainWindow(),
1087  mainWindow().transformation(),
1088  strFunctions,
1089  numWritesSoFar);
1090 
1091  ExportFileRelations exportStrategyRelations;
1092  exportStrategyRelations.exportToFile (*m_modelExportAfter,
1093  cmdMediator().document(),
1094  mainWindow().modelMainWindow(),
1095  mainWindow().transformation(),
1096  strRelations,
1097  numWritesSoFar);
1098 
1099  // Use html to set background color. A <div> fills the whole background, unlike a <span>.
1100  // Final carriage return is removed to prevent unwanted blank line. A requirement is that
1101  // if there are no functions then no empty <div> appears (too confusing), and likewise if
1102  // there are no relations
1103  QString exportedHtmlFunctions, exportedHtmlRelations;
1104  if (! exportedTextFunctions.isEmpty ()) {
1105 
1106  exportedHtmlFunctions = exportedTextToExportedHtml (exportedTextFunctions, COLOR_FUNCTIONS);
1107  }
1108  if (! exportedTextRelations.isEmpty ()) {
1109 
1110  exportedHtmlRelations = exportedTextToExportedHtml (exportedTextRelations, COLOR_RELATIONS);
1111  }
1112 
1113  exportedHtml = exportedHtmlFunctions + exportedHtmlRelations;
1114 
1115  } else {
1116 
1117  exportedHtml = tr ("Preview is unavailable until axis points are defined.");
1118  }
1119 
1120  m_editPreview->setHtml (exportedHtml);
1121 
1122  // Restore scroll position
1123  m_editPreview->verticalScrollBar()->setValue (scrollPosition);
1124 }
void setPointsSelectionFunctions(ExportPointsSelectionFunctions exportPointsSelectionFunctions)
Set method for point selection for functions.
virtual void setSmallDialogs(bool smallDialogs)
If false then dialogs have a minimum size so all controls are visible.
bool overrideCsvTsv() const
Get method for csv/tsv format override.
CurveStyle curveStyle(const QString &curveName) const
CurveStyle in specified curve.
Definition: CurveStyles.cpp:79
QStringList curveNamesNotExported() const
Get method for curve names not exported.
CurveConnectAs curveConnectAs() const
Get method for connect type.
Definition: LineStyle.cpp:63
CallbackSearchReturn callback(const QString &curveName, const Point &point)
Callback method.
virtual void handleOk()
Process slotOk.
Model for DlgSettingsExportFormat and CmdSettingsExportFormat.
QStringList curveNames() const
List of all curve names.
Definition: CurveStyles.cpp:67
Model for DlgSettingsCurveProperties and CmdSettingsCurveProperties.
Definition: CurveStyles.h:22
virtual QWidget * createSubPanel()
Create dialog-specific panel to which base class will add Ok and Cancel buttons.
void setPointsSelectionRelations(ExportPointsSelectionRelations exportPointsSelectionRelations)
Set method for point selection for relations.
void setCurveNamesNotExported(const QStringList &curveNamesNotExported)
Set method for curve names not exported.
void setCmdMediator(CmdMediator &cmdMediator)
Store CmdMediator for easy access by the leaf class.
QRectF boundingRectScreen(bool &isEmpty) const
Screen coordinate bounding rectangle.
ExportPointsSelectionRelations pointsSelectionRelations() const
Get method for point selection for relations.
Document & document()
Provide the Document to commands, primarily for undo/redo processing.
Definition: CmdMediator.cpp:72
double pointsIntervalFunctions() const
Get method for points interval for functions.
void finishPanel(QWidget *subPanel, int minimumWidth=MINIMUM_DIALOG_WIDTH, int minimumHeightOrZero=0)
Add Ok and Cancel buttons to subpanel to get the whole dialog.
void setDelimiter(ExportDelimiter exportDelimiter)
Set method for delimiter.
void setPointsIntervalFunctions(double pointsIntervalFunctions)
Set method for points interval for functions.
void setLayoutFunctions(ExportLayoutFunctions exportLayoutFunctions)
Set method for functions layout.
virtual void createOptionalSaveDefault(QHBoxLayout *layout)
Let subclass define an optional Save As Default button.
Strategy class for exporting to a file. This strategy is external to the Document class so that class...
void setPointsIntervalUnitsFunctions(ExportPointsIntervalUnits pointsIntervalUnitsFunctions)
Set method for points interval units for functions.
LineStyle lineStyle() const
Get method for LineStyle.
Definition: CurveStyle.cpp:26
ExportPointsIntervalUnits pointsIntervalUnitsRelations() const
Get method for points interval units for relations.
ExportDelimiter delimiter() const
Get method for delimiter.
void setPointsIntervalRelations(double pointsIntervalRelations)
Set method for relations interval for relations.
void exportToFile(const DocumentModelExportFormat &modelExportOverride, const Document &document, const MainWindowModel &modelMainWindow, const Transformation &transformation, QTextStream &str, unsigned int &numWritesSoFar) const
Export Document points according to the settings.
Container for LineStyle and PointStyle for one Curve.
Definition: CurveStyle.h:18
ExportPointsIntervalUnits pointsIntervalUnitsFunctions() const
Get method for points interval units for functions.
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
ExportHeader header() const
Get method for header.
double pointsIntervalRelations() const
Get method for relations interval for relations.
static int MINIMUM_PREVIEW_HEIGHT
Dialog layout constant that guarantees preview has sufficent room.
ExportLayoutFunctions layoutFunctions() const
Get method for functions layout.
void enableOk(bool enable)
Let leaf subclass control the Ok button.
QString xLabel() const
Get method for x label.
QRectF boundingRectGraph(bool &isEmpty) const
Graph coordinate bounding rectangle.
Command queue stack.
Definition: CmdMediator.h:23
Strategy class for exporting to a file. This strategy is external to the Document class so that class...
void setPointsIntervalUnitsRelations(ExportPointsIntervalUnits pointsIntervalUnitsRelations)
Set method for points interval units for relations.
Abstract base class for all Settings dialogs.
void setHeader(ExportHeader exportHeader)
Set method for header.
void iterateThroughCurvesPointsGraphs(const Functor2wRet< const QString &, const Point &, CallbackSearchReturn > &ftorWithCallback)
See Curve::iterateThroughCurvePoints, for all the graphs curves.
Definition: CmdMediator.cpp:97
void setOverrideCsvTsv(bool overrideCsvTsv)
Set method for csv/tsv format override.
CurveStyles modelCurveStyles() const
Get method for CurveStyles.
Definition: Document.cpp:696
ExportPointsSelectionFunctions pointsSelectionFunctions() const
Get method for point selection for functions.
Callback for computing the bounding rectangles of the screen and graph coordinates of the points in t...
MainWindow & mainWindow()
Get method for MainWindow.
QStringList curvesGraphsNames() const
See CurvesGraphs::curvesGraphsNames.
Definition: Document.cpp:346
Main window consisting of menu, graphics scene, status bar and optional toolbars as a Single Document...
Definition: MainWindow.h:89
CmdMediator & cmdMediator()
Provide access to Document information wrapped inside CmdMediator.
Command for DlgSettingsExportFormat.
void setXLabel(const QString &xLabel)
Set method for x label.
void exportToFile(const DocumentModelExportFormat &modelExportOverride, const Document &document, const MainWindowModel &modelMainWindow, const Transformation &transformation, QTextStream &str, unsigned int &numWritesSoFar) const
Export Document points according to the settings.
DlgSettingsExportFormat(MainWindow &mainWindow)
Single constructor.