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