Engauge Digitizer  2
 All Classes Functions Variables Typedefs Enumerations Friends Pages
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 (QString ("<<%1").arg (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 (QString ("%1>>").arg (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 (QString ("%1:").arg (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 (QString ("%1:").arg (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 (QString ("%1:").arg (tr ("X Label")));
452  } else {
453  title = new QLabel (QString ("%1:").arg (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 (cmdMediator().document().documentAxesPointsRequired(),
543  mainWindow().transformation());
544 
545  Functor2wRet<const QString &, const Point &, CallbackSearchReturn> ftorWithCallback = functor_ret (ftor,
547  cmdMediator().iterateThroughCurvesPointsGraphs (ftorWithCallback);
548 
549  // If there are no points, then interval will be zero. That special case must be handled downstream to prevent infinite loops
550  bool isEmpty;
551  QPointF boundingRectGraphMin = ftor.boundingRectGraphMin (isEmpty);
552  QPointF boundingRectGraphMax = ftor.boundingRectGraphMax (isEmpty);
553  double maxSizeGraph = qMax (qAbs (boundingRectGraphMax.x() - boundingRectGraphMin.x()),
554  qAbs (boundingRectGraphMax.y() - boundingRectGraphMin.y()));
555  double maxSizeScreen = qMax (ftor.boundingRectScreen(isEmpty).width(),
556  ftor.boundingRectScreen(isEmpty).height());
557  m_minIntervalGraph = maxSizeGraph / MAX_POINTS_ACROSS_RANGE;
558  m_minIntervalScreen = maxSizeScreen / MAX_POINTS_ACROSS_RANGE;
559 }
560 
562 {
563  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::load";
564 
565  setCmdMediator (cmdMediator);
566 
567  // Flush old data
568  delete m_modelExportBefore;
569  delete m_modelExportAfter;
570 
571  // Save new data
572  m_modelExportBefore = new DocumentModelExportFormat (cmdMediator.document());
573  m_modelExportAfter = new DocumentModelExportFormat (cmdMediator.document());
574 
575  // Populate controls. First load excluded curves
576  m_listExcluded->clear();
577  QStringList curveNamesExcluded = m_modelExportAfter->curveNamesNotExported();
578  QStringList::const_iterator itr;
579  for (itr = curveNamesExcluded.begin (); itr != curveNamesExcluded.end(); ++itr) {
580  QString curveNameNotExported = *itr;
581  m_listExcluded->addItem (curveNameNotExported);
582  }
583 
584  // Include curves that are not excluded
585  m_listIncluded->clear();
586  QStringList curveNamesAll = cmdMediator.document().curvesGraphsNames();
587  for (itr = curveNamesAll.begin (); itr != curveNamesAll.end(); itr++) {
588  QString curveName = *itr;
589  if (!curveNamesExcluded.contains (curveName)) {
590  m_listIncluded->addItem (curveName);
591  }
592  }
593 
594  ExportPointsSelectionFunctions pointsSelectionFunctions = m_modelExportAfter->pointsSelectionFunctions();
595  m_btnFunctionsPointsAllCurves->setChecked (pointsSelectionFunctions == EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_ALL_CURVES);
596  m_btnFunctionsPointsFirstCurve->setChecked (pointsSelectionFunctions == EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_FIRST_CURVE);
597  m_btnFunctionsPointsEvenlySpaced->setChecked (pointsSelectionFunctions == EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_PERIODIC);
598  m_btnFunctionsPointsRaw->setChecked (pointsSelectionFunctions == EXPORT_POINTS_SELECTION_FUNCTIONS_RAW);
599 
600  ExportLayoutFunctions layoutFunctions = m_modelExportAfter->layoutFunctions ();
601  m_btnCurvesLayoutAllCurves->setChecked (layoutFunctions == EXPORT_LAYOUT_ALL_PER_LINE);
602  m_btnCurvesLayoutOneCurve->setChecked (layoutFunctions == EXPORT_LAYOUT_ONE_PER_LINE);
603 
604  ExportPointsSelectionRelations pointsSelectionRelations = m_modelExportAfter->pointsSelectionRelations();
605  m_btnRelationsPointsEvenlySpaced->setChecked (pointsSelectionRelations == EXPORT_POINTS_SELECTION_RELATIONS_INTERPOLATE);
606  m_btnRelationsPointsRaw->setChecked (pointsSelectionRelations == EXPORT_POINTS_SELECTION_RELATIONS_RAW);
607 
608  ExportDelimiter delimiter = m_modelExportAfter->delimiter ();
609  m_btnDelimitersCommas->setChecked (delimiter == EXPORT_DELIMITER_COMMA);
610  m_btnDelimitersSpaces->setChecked (delimiter == EXPORT_DELIMITER_SPACE);
611  m_btnDelimitersTabs->setChecked (delimiter == EXPORT_DELIMITER_TAB);
612  m_btnDelimitersSemicolons->setChecked (delimiter == EXPORT_DELIMITER_SEMICOLON);
613 
614  m_chkOverrideCsvTsv->setChecked (m_modelExportAfter->overrideCsvTsv());
615 
616  ExportHeader header = m_modelExportAfter->header ();
617  m_btnHeaderNone->setChecked (header == EXPORT_HEADER_NONE);
618  m_btnHeaderSimple->setChecked (header == EXPORT_HEADER_SIMPLE);
619  m_btnHeaderGnuplot->setChecked (header == EXPORT_HEADER_GNUPLOT);
620 
621  m_editXLabel->setText (m_modelExportAfter->xLabel());
622 
623  m_editFunctionsPointsEvenlySpacing->setText (QString::number (m_modelExportAfter->pointsIntervalFunctions()));
624  m_editRelationsPointsEvenlySpacing->setText (QString::number (m_modelExportAfter->pointsIntervalRelations()));
625 
626  ExportPointsIntervalUnits pointsIntervalUnitsFunctions = m_modelExportAfter->pointsIntervalUnitsFunctions();
627  ExportPointsIntervalUnits pointsIntervalUnitsRelations = m_modelExportAfter->pointsIntervalUnitsRelations();
628  int indexFunctions = m_cmbFunctionsPointsEvenlySpacingUnits->findData (QVariant (pointsIntervalUnitsFunctions));
629  int indexRelations = m_cmbRelationsPointsEvenlySpacingUnits->findData (QVariant (pointsIntervalUnitsRelations));
630  m_cmbFunctionsPointsEvenlySpacingUnits->setCurrentIndex (indexFunctions);
631  m_cmbRelationsPointsEvenlySpacingUnits->setCurrentIndex (indexRelations);
632 
633  initializeIntervalConstraints ();
634 
635  updateControlsUponLoad (); // Before updateControls so m_haveFunction and m_haveRelation are set
636  updateControls();
637  updateIntervalConstraints();
638  enableOk (false); // Disable Ok button since there not yet any changes
639  updatePreview();
640 }
641 
643 {
644  if (!smallDialogs) {
645  setMinimumHeight (MINIMUM_HEIGHT);
646  }
647 }
648 
649 void DlgSettingsExportFormat::slotDelimitersCommas()
650 {
651  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotDelimitersCommas";
652 
653  m_modelExportAfter->setDelimiter(EXPORT_DELIMITER_COMMA);
654  updateControls();
655  updatePreview();
656 }
657 
658 void DlgSettingsExportFormat::slotDelimitersSemicolons()
659 {
660  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotDelimitersSemicolons";
661 
662  m_modelExportAfter->setDelimiter(EXPORT_DELIMITER_SEMICOLON);
663  updateControls();
664  updatePreview();
665 }
666 
667 void DlgSettingsExportFormat::slotDelimitersSpaces()
668 {
669  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotDelimitersSpaces";
670 
671  m_modelExportAfter->setDelimiter(EXPORT_DELIMITER_SPACE);
672  updateControls();
673  updatePreview();
674 }
675 
676 void DlgSettingsExportFormat::slotDelimitersTabs()
677 {
678  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotDelimitersTabs";
679 
680  m_modelExportAfter->setDelimiter(EXPORT_DELIMITER_TAB);
681  updateControls();
682  updatePreview();
683 }
684 
685 void DlgSettingsExportFormat::slotExclude ()
686 {
687  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotExclude";
688 
689  // Perform forward pass to get excluded curves in the proper order
690  int i;
691  QStringList excluded;
692  for (i = 0; i < m_listIncluded->count(); i++) {
693  if (m_listIncluded->item(i)->isSelected()) {
694  excluded += m_listIncluded->item(i)->text();
695  }
696  }
697 
698  // Add the excluded curves to the excluded list
699  for (i = 0; i < excluded.count(); i++) {
700  QString curveName = excluded.at (i);
701  m_listExcluded->addItem (curveName);
702  }
703 
704  // Perform backwards pass to remove the excluded curves from the included list
705  for (i = m_listIncluded->count() - 1; i>= 0; i--) {
706  QString curveName = m_listIncluded->item(i)->text();
707  if (excluded.contains (curveName)) {
708  QListWidgetItem *item = m_listIncluded->item (i);
709  m_listIncluded->removeItemWidget (item);
710  delete item;
711  }
712  }
713 
714  m_modelExportAfter->setCurveNamesNotExported(excluded);
715  updateControls();
716  updatePreview();
717 }
718 
719 void DlgSettingsExportFormat::slotFunctionsLayoutAllCurves()
720 {
721  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotFunctionsLayoutAllCurves";
722 
723  m_modelExportAfter->setLayoutFunctions(EXPORT_LAYOUT_ALL_PER_LINE);
724  updateControls();
725  updatePreview();
726 }
727 
728 void DlgSettingsExportFormat::slotFunctionsLayoutOneCurve()
729 {
730  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotFunctionsLayoutOneCurve";
731 
732  m_modelExportAfter->setLayoutFunctions(EXPORT_LAYOUT_ONE_PER_LINE);
733  updateControls();
734  updatePreview();
735 }
736 
737 void DlgSettingsExportFormat::slotFunctionsPointsAllCurves()
738 {
739  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotFunctionsPointsAllCurves";
740 
741  m_modelExportAfter->setPointsSelectionFunctions(EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_ALL_CURVES);
742  updateControls();
743  updatePreview();
744 }
745 
746 void DlgSettingsExportFormat::slotFunctionsPointsEvenlySpaced()
747 {
748  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotFunctionsPointsEvenlySpaced";
749 
750  m_modelExportAfter->setPointsSelectionFunctions(EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_PERIODIC);
751  updateControls();
752  updatePreview();
753 }
754 
755 void DlgSettingsExportFormat::slotFunctionsPointsEvenlySpacedInterval(const QString &)
756 {
757  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotFunctionsPointsEvenlySpacedInterval";
758 
759  // Prevent infinite loop on empty and "-" values which get treated as zero interval
760  if (goodIntervalFunctions()) {
761  m_modelExportAfter->setPointsIntervalFunctions(m_editFunctionsPointsEvenlySpacing->text().toDouble());
762  updateControls();
763  updatePreview();
764  } else {
765  m_editPreview->setText(EMPTY_PREVIEW);
766  }
767 }
768 
769 void DlgSettingsExportFormat::slotFunctionsPointsEvenlySpacedIntervalUnits(const QString &)
770 {
771  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotFunctionsPointsEvenlySpacedIntervalUnits";
772 
773  int index = m_cmbFunctionsPointsEvenlySpacingUnits->currentIndex();
774  ExportPointsIntervalUnits units = (ExportPointsIntervalUnits) m_cmbFunctionsPointsEvenlySpacingUnits->itemData (index).toInt();
775 
776  m_modelExportAfter->setPointsIntervalUnitsFunctions(units);
777  updateIntervalConstraints(); // Call this before updateControls so constraint checking is updated for ok button
778  updateControls();
779  updatePreview();
780 }
781 
782 void DlgSettingsExportFormat::slotFunctionsPointsFirstCurve()
783 {
784  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotFunctionsPointsFirstCurve";
785 
786  m_modelExportAfter->setPointsSelectionFunctions(EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_FIRST_CURVE);
787  updateControls();
788  updatePreview();
789 }
790 
791 void DlgSettingsExportFormat::slotFunctionsPointsRaw()
792 {
793  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotFunctionsPointsRaw";
794 
795  m_modelExportAfter->setPointsSelectionFunctions(EXPORT_POINTS_SELECTION_FUNCTIONS_RAW);
796  updateControls();
797  updatePreview();
798 }
799 
800 void DlgSettingsExportFormat::slotHeaderGnuplot()
801 {
802  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotHeaderGnuplot";
803 
804  m_modelExportAfter->setHeader(EXPORT_HEADER_GNUPLOT);
805  updateControls();
806  updatePreview();
807 }
808 
809 void DlgSettingsExportFormat::slotHeaderNone()
810 {
811  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotHeaderNone";
812 
813  m_modelExportAfter->setHeader(EXPORT_HEADER_NONE);
814  updateControls();
815  updatePreview();
816 }
817 
818 void DlgSettingsExportFormat::slotHeaderSimple()
819 {
820  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotHeaderSimple";
821 
822  m_modelExportAfter->setHeader(EXPORT_HEADER_SIMPLE);
823  updateControls();
824  updatePreview();
825 }
826 
827 void DlgSettingsExportFormat::slotInclude ()
828 {
829  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotInclude";
830 
831  // Perform forward pass to get included curves in the proper order
832  int i;
833  QStringList included;
834  for (i = 0; i < m_listExcluded->count(); i++) {
835  if (m_listExcluded->item(i)->isSelected()) {
836  included += m_listExcluded->item(i)->text();
837  }
838  }
839 
840  // Add the included curves to the included list
841  for (i = 0; i < included.count(); i++) {
842  QString curveName = included.at (i);
843  m_listIncluded->addItem (curveName);
844  }
845 
846  // Perform backwards pass to remove the included curves from the excluded list
847  QStringList excluded;
848  for (i = m_listExcluded->count() - 1; i>= 0; i--) {
849  QString curveName = m_listExcluded->item(i)->text();
850  QListWidgetItem *item = m_listExcluded->item (i);
851  if (included.contains (curveName)) {
852  m_listExcluded->removeItemWidget (item);
853  delete item;
854  } else {
855  excluded += item->text();
856  }
857  }
858 
859  m_modelExportAfter->setCurveNamesNotExported(excluded);
860  updateControls();
861  updatePreview();
862 }
863 
864 void DlgSettingsExportFormat::slotListExcluded()
865 {
866  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotListExcluded";
867 
868  updateControls();
869  // Do not call updatePreview since this method changes nothing
870 }
871 
872 void DlgSettingsExportFormat::slotListIncluded()
873 {
874  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotListIncluded";
875 
876  updateControls();
877  // Do not call updatePreview since this method changes nothing
878 }
879 
880 void DlgSettingsExportFormat::slotOverrideCsvTsv(int)
881 {
882  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotOverrideCsvTsv";
883 
884  m_modelExportAfter->setOverrideCsvTsv(m_chkOverrideCsvTsv->isChecked());
885  updateControls();
886  updatePreview();
887 }
888 
889 void DlgSettingsExportFormat::slotRelationsPointsEvenlySpaced()
890 {
891  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotRelationsPointsEvenlySpaced";
892 
893  m_modelExportAfter->setPointsSelectionRelations(EXPORT_POINTS_SELECTION_RELATIONS_INTERPOLATE);
894  updateControls();
895  updatePreview();
896 }
897 
898 void DlgSettingsExportFormat::slotRelationsPointsEvenlySpacedInterval(const QString &)
899 {
900  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotRelationsPointsEvenlySpacedInterval";
901 
902  m_modelExportAfter->setPointsIntervalRelations(m_editRelationsPointsEvenlySpacing->text().toDouble());
903  updateControls();
904  updatePreview();
905 }
906 
907 void DlgSettingsExportFormat::slotRelationsPointsEvenlySpacedIntervalUnits(const QString &)
908 {
909  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotRelationsPointsEvenlySpacedIntervalUnits";
910 
911  int index = m_cmbRelationsPointsEvenlySpacingUnits->currentIndex();
912  ExportPointsIntervalUnits units = (ExportPointsIntervalUnits) m_cmbRelationsPointsEvenlySpacingUnits->itemData (index).toInt();
913 
914  m_modelExportAfter->setPointsIntervalUnitsRelations(units);
915  updateIntervalConstraints(); // Call this before updateControls so constraint checking is updated for ok button
916  updateControls();
917  updatePreview();
918 }
919 
920 void DlgSettingsExportFormat::slotRelationsPointsRaw()
921 {
922  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotRelationsPointsRaw";
923 
924  m_modelExportAfter->setPointsSelectionRelations(EXPORT_POINTS_SELECTION_RELATIONS_RAW);
925  updateControls();
926  updatePreview();
927 }
928 
929 void DlgSettingsExportFormat::slotSaveDefault()
930 {
931  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotSaveDefault";
932 
933  QSettings settings (SETTINGS_ENGAUGE, SETTINGS_DIGITIZER);
934  settings.beginGroup (SETTINGS_GROUP_EXPORT);
935 
936  settings.setValue (SETTINGS_EXPORT_DELIMITER,
937  QVariant (m_modelExportAfter->delimiter()));
938  settings.setValue (SETTINGS_EXPORT_HEADER,
939  QVariant (m_modelExportAfter->header()));
940  settings.setValue (SETTINGS_EXPORT_LAYOUT_FUNCTIONS,
941  QVariant (m_modelExportAfter->layoutFunctions()));
942  settings.setValue (SETTINGS_EXPORT_POINTS_INTERVAL_FUNCTIONS,
943  QVariant (m_modelExportAfter->pointsIntervalFunctions()));
944  settings.setValue (SETTINGS_EXPORT_POINTS_INTERVAL_RELATIONS,
945  QVariant (m_modelExportAfter->pointsIntervalRelations()));
946  settings.setValue (SETTINGS_EXPORT_POINTS_INTERVAL_UNITS_FUNCTIONS,
947  QVariant (m_modelExportAfter->pointsIntervalUnitsFunctions()));
948  settings.setValue (SETTINGS_EXPORT_POINTS_INTERVAL_UNITS_RELATIONS,
949  QVariant (m_modelExportAfter->pointsIntervalUnitsRelations()));
950  settings.setValue (SETTINGS_EXPORT_POINTS_SELECTION_FUNCTIONS,
951  QVariant (m_modelExportAfter->pointsSelectionFunctions()));
952  settings.setValue (SETTINGS_EXPORT_POINTS_SELECTION_RELATIONS,
953  QVariant (m_modelExportAfter->pointsSelectionRelations()));
954  settings.setValue (SETTINGS_EXPORT_X_LABEL,
955  QVariant (m_modelExportAfter->xLabel()));
956 
957  settings.endGroup ();
958 }
959 
960 void DlgSettingsExportFormat::slotTabChanged (int)
961 {
962  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotTabChanged";
963 
964  updatePreview();
965 }
966 
967 void DlgSettingsExportFormat::slotXLabel(const QString &)
968 {
969  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotXLabel";
970 
971  m_modelExportAfter->setXLabel (m_editXLabel->text());
972  updateControls();
973  updatePreview();
974 }
975 
976 void DlgSettingsExportFormat::updateControls ()
977 {
978  bool isGoodState = goodIntervalFunctions() &&
979  goodIntervalRelations();
980  enableOk (isGoodState);
981 
982  int selectedForInclude = m_listExcluded->selectedItems().count();
983  int selectedForExclude = m_listIncluded->selectedItems().count();
984  int inInclude = m_listIncluded->count();
985 
986  m_btnInclude->setEnabled (selectedForInclude > 0); // Need at least one selection
987  m_btnExclude->setEnabled ((selectedForExclude > 0) && (inInclude - selectedForExclude > 0)); // Need at least one selection, and one left after the move
988 
989  m_editFunctionsPointsEvenlySpacing->setEnabled (m_haveFunction && m_btnFunctionsPointsEvenlySpaced->isChecked ());
990  m_editRelationsPointsEvenlySpacing->setEnabled (m_haveRelation && m_btnRelationsPointsEvenlySpaced->isChecked ());
991 
992  m_editXLabel->setEnabled (!m_btnHeaderNone->isChecked());
993 }
994 
995 void DlgSettingsExportFormat::updateControlsUponLoad ()
996 {
997  CurveStyles curveStyles = cmdMediator().document().modelCurveStyles();
998 
999  m_haveFunction = false;
1000  m_haveRelation = false;
1001 
1002  QStringList curveNames = curveStyles.curveNames();
1003 
1004  QStringList::const_iterator itr;
1005  for (itr = curveNames.begin(); itr != curveNames.end (); itr++) {
1006  QString curveName = *itr;
1007  CurveStyle curveStyle = curveStyles.curveStyle (curveName);
1008  CurveConnectAs curveConnectAs = curveStyle.lineStyle().curveConnectAs();
1009  if (curveConnectAs == CONNECT_AS_FUNCTION_SMOOTH || curveConnectAs == CONNECT_AS_FUNCTION_STRAIGHT) {
1010  m_haveFunction = true;
1011  } else if (curveConnectAs == CONNECT_AS_RELATION_SMOOTH || curveConnectAs == CONNECT_AS_RELATION_STRAIGHT) {
1012  m_haveRelation = true;
1013  }
1014  }
1015 
1016  // Enable function-specific widgets if appropriate
1017  m_btnFunctionsPointsAllCurves->setEnabled (m_haveFunction);
1018  m_btnFunctionsPointsFirstCurve->setEnabled (m_haveFunction);
1019  m_btnFunctionsPointsEvenlySpaced->setEnabled (m_haveFunction);
1020  m_editFunctionsPointsEvenlySpacing->setEnabled (m_haveFunction);
1021  m_cmbFunctionsPointsEvenlySpacingUnits->setEnabled (m_haveFunction);
1022  m_btnFunctionsPointsRaw->setEnabled (m_haveFunction);
1023 
1024  // Enable relation-specific widgets if appropriate
1025  m_btnRelationsPointsEvenlySpaced->setEnabled (m_haveRelation);
1026  m_editRelationsPointsEvenlySpacing->setEnabled (m_haveRelation);
1027  m_cmbRelationsPointsEvenlySpacingUnits->setEnabled (m_haveRelation);
1028  m_btnRelationsPointsRaw->setEnabled (m_haveRelation);
1029 
1030  // Do not start with a tab that does not apply to the current set of functions/relations
1031  if (!m_haveRelation) {
1032  m_tabWidget->setCurrentIndex (TAB_WIDGET_INDEX_FUNCTIONS);
1033  } else if (!m_haveFunction) {
1034  m_tabWidget->setCurrentIndex (TAB_WIDGET_INDEX_RELATIONS);
1035  }
1036 }
1037 
1038 void DlgSettingsExportFormat::updateIntervalConstraints ()
1039 {
1040  double functionsMin = (m_modelExportAfter->pointsIntervalUnitsFunctions() == EXPORT_POINTS_INTERVAL_UNITS_GRAPH ?
1041  m_minIntervalGraph :
1042  m_minIntervalScreen);
1043  double relationsMin = (m_modelExportAfter->pointsIntervalUnitsRelations() == EXPORT_POINTS_INTERVAL_UNITS_GRAPH ?
1044  m_minIntervalGraph :
1045  m_minIntervalScreen);
1046 
1047  if (m_tabWidget->currentIndex() == TAB_WIDGET_INDEX_FUNCTIONS) {
1048 
1049  if (m_modelExportAfter->pointsIntervalFunctions() < functionsMin) {
1050 
1051  m_editFunctionsPointsEvenlySpacing->setText (QString::number (functionsMin));
1052 
1053  }
1054 
1055  m_validatorFunctionsPointsEvenlySpacing->setBottom (functionsMin);
1056 
1057  } else {
1058 
1059  if (m_modelExportAfter->pointsIntervalRelations() < relationsMin) {
1060 
1061  m_editRelationsPointsEvenlySpacing->setText (QString::number (relationsMin));
1062 
1063  }
1064 
1065  m_validatorRelationsPointsEvenlySpacing->setBottom (relationsMin);
1066  }
1067 }
1068 
1069 void DlgSettingsExportFormat::updatePreview()
1070 {
1071  // Save the scroll position for continuity before and after the preview update
1072  int scrollPosition = m_editPreview->verticalScrollBar()->value();
1073 
1074  QString exportedTextFunctions, exportedTextRelations, exportedHtml;
1075  QTextStream strFunctions (&exportedTextFunctions);
1076  QTextStream strRelations (&exportedTextRelations);
1077 
1078  if (mainWindow().transformation().transformIsDefined()) {
1079 
1080  unsigned int numWritesSoFar = 0;
1081 
1082  ExportFileFunctions exportStrategyFunctions;
1083  exportStrategyFunctions.exportToFile (*m_modelExportAfter,
1084  cmdMediator().document(),
1085  mainWindow().modelMainWindow(),
1086  mainWindow().transformation(),
1087  strFunctions,
1088  numWritesSoFar);
1089 
1090  ExportFileRelations exportStrategyRelations;
1091  exportStrategyRelations.exportToFile (*m_modelExportAfter,
1092  cmdMediator().document(),
1093  mainWindow().modelMainWindow(),
1094  mainWindow().transformation(),
1095  strRelations,
1096  numWritesSoFar);
1097 
1098  // Use html to set background color. A <div> fills the whole background, unlike a <span>.
1099  // Final carriage return is removed to prevent unwanted blank line. A requirement is that
1100  // if there are no functions then no empty <div> appears (too confusing), and likewise if
1101  // there are no relations
1102  QString exportedHtmlFunctions, exportedHtmlRelations;
1103  if (! exportedTextFunctions.isEmpty ()) {
1104 
1105  exportedHtmlFunctions = exportedTextToExportedHtml (exportedTextFunctions, COLOR_FUNCTIONS);
1106  }
1107  if (! exportedTextRelations.isEmpty ()) {
1108 
1109  exportedHtmlRelations = exportedTextToExportedHtml (exportedTextRelations, COLOR_RELATIONS);
1110  }
1111 
1112  exportedHtml = exportedHtmlFunctions + exportedHtmlRelations;
1113 
1114  } else {
1115 
1116  exportedHtml = tr ("Preview is unavailable until axis points are defined.");
1117  }
1118 
1119  m_editPreview->setHtml (exportedHtml);
1120 
1121  // Restore scroll position
1122  m_editPreview->verticalScrollBar()->setValue (scrollPosition);
1123 }
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.
QStringList curveNames() const
List of all curve names.
Definition: CurveStyles.cpp:67
CallbackSearchReturn callback(const QString &curveName, const Point &point)
Callback method.
ExportPointsSelectionFunctions pointsSelectionFunctions() const
Get method for point selection for functions.
ExportLayoutFunctions layoutFunctions() const
Get method for functions layout.
ExportPointsIntervalUnits pointsIntervalUnitsRelations() const
Get method for points interval units for relations.
virtual void handleOk()
Process slotOk.
ExportPointsIntervalUnits pointsIntervalUnitsFunctions() const
Get method for points interval units for functions.
Model for DlgSettingsExportFormat and CmdSettingsExportFormat.
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.
LineStyle lineStyle() const
Get method for LineStyle.
Definition: CurveStyle.cpp:26
Document & document()
Provide the Document to commands, primarily for undo/redo processing.
Definition: CmdMediator.cpp:72
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.
double pointsIntervalFunctions() const
Get method for points interval for functions.
ExportHeader header() const
Get method for header.
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...
QString xLabel() const
Get method for x label.
void setPointsIntervalUnitsFunctions(ExportPointsIntervalUnits pointsIntervalUnitsFunctions)
Set method for points interval units for functions.
CurveStyles modelCurveStyles() const
Get method for CurveStyles.
Definition: Document.cpp:698
ExportDelimiter delimiter() const
Get method for delimiter.
QStringList curveNamesNotExported() const
Get method for curve names not exported.
void setPointsIntervalRelations(double pointsIntervalRelations)
Set method for relations interval for relations.
double pointsIntervalRelations() const
Get method for relations interval for relations.
Container for LineStyle and PointStyle for one Curve.
Definition: CurveStyle.h:18
QStringList curvesGraphsNames() const
See CurvesGraphs::curvesGraphsNames.
Definition: Document.cpp:345
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
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.
static int MINIMUM_PREVIEW_HEIGHT
Dialog layout constant that guarantees preview has sufficent room.
void enableOk(bool enable)
Let leaf subclass control the Ok button.
CurveStyle curveStyle(const QString &curveName) const
CurveStyle in specified curve.
Definition: CurveStyles.cpp:79
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.
CurveConnectAs curveConnectAs() const
Get method for connect type.
Definition: LineStyle.cpp:63
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.
Callback for computing the bounding rectangles of the screen and graph coordinates of the points in t...
MainWindow & mainWindow()
Get method for MainWindow.
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.
Main window consisting of menu, graphics scene, status bar and optional toolbars as a Single Document...
Definition: MainWindow.h:91
CmdMediator & cmdMediator()
Provide access to Document information wrapped inside CmdMediator.
ExportPointsSelectionRelations pointsSelectionRelations() const
Get method for point selection for relations.
bool overrideCsvTsv() const
Get method for csv/tsv format override.
Command for DlgSettingsExportFormat.
void setXLabel(const QString &xLabel)
Set method for x label.
DlgSettingsExportFormat(MainWindow &mainWindow)
Single constructor.