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 = 600;
52 const int MINIMUM_HEIGHT = 780;
53 
55  DlgSettingsAbstractBase (tr ("Export Format"),
56  "DlgSettingsExportFormat",
57  mainWindow),
58  m_modelExportBefore (nullptr),
59  m_modelExportAfter (nullptr),
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, 2);
200  connect (m_btnFunctionsPointsAllCurves, SIGNAL (released()), this, SLOT (slotFunctionsPointsAllCurves()));
201 
202  // Put extrapolation control up near interpolation controls and away from raw control which never uses extrapolation
203  m_chkExtrapolateOutsideEndpoints = new QCheckBox (tr ("Extrapolate outside endpoints"));
204  m_chkExtrapolateOutsideEndpoints->setWhatsThis (tr ("Enable or disable extrapolation outside of endpoints of each curve. If disabled, "
205  "only points between the endpoints of each curve are exported"));
206  layoutPointsSelections->addWidget (m_chkExtrapolateOutsideEndpoints, row++, 3, 1, 1, Qt::AlignRight);
207  connect (m_chkExtrapolateOutsideEndpoints, SIGNAL (stateChanged (int)), this, SLOT (slotFunctionsExtrapolateOutsideEndpoints(int)));
208 
209  m_btnFunctionsPointsFirstCurve = new QRadioButton (tr ("Interpolate Ys at Xs from first curve"));
210  m_btnFunctionsPointsFirstCurve->setWhatsThis (tr ("Exported file will have values at every unique X "
211  "value from the first curve. Y values will be linearly interpolated if necessary"));
212  layoutPointsSelections->addWidget (m_btnFunctionsPointsFirstCurve, row++, 0, 1, 4);
213  connect (m_btnFunctionsPointsFirstCurve, SIGNAL (released()), this, SLOT (slotFunctionsPointsFirstCurve()));
214 
215  m_btnFunctionsPointsEvenlySpaced = new QRadioButton (tr ("Interpolate Ys at evenly spaced X values that are automatically selected"));
216  m_btnFunctionsPointsEvenlySpaced->setWhatsThis (tr ("Exported file will have values at evenly spaced X values, separated by the interval selected below."));
217  layoutPointsSelections->addWidget (m_btnFunctionsPointsEvenlySpaced, row++, 0, 1, 4);
218  connect (m_btnFunctionsPointsEvenlySpaced, SIGNAL (released()), this, SLOT (slotFunctionsPointsEvenlySpaced()));
219 
220  QLabel *labelInterval = new QLabel (QString ("%1:").arg (tr ("Interval")));
221  layoutPointsSelections->addWidget (labelInterval, row, 1, 1, 1, Qt::AlignRight);
222 
223  m_editFunctionsPointsEvenlySpacing = new QLineEdit;
224  m_validatorFunctionsPointsEvenlySpacing = new QDoubleValidator; // Minimum value, to prevent overflow, is set later according to settings
225  m_editFunctionsPointsEvenlySpacing->setValidator (m_validatorFunctionsPointsEvenlySpacing);
226  m_editFunctionsPointsEvenlySpacing->setMinimumWidth (MIN_EDIT_WIDTH);
227  m_editFunctionsPointsEvenlySpacing->setMaximumWidth (MAX_EDIT_WIDTH);
228  m_editFunctionsPointsEvenlySpacing->setWhatsThis (tr ("Interval, in the units of X, between successive points in the X direction.\n\n"
229  "If the scale is linear, then this interval is added to successive X values. If the scale is "
230  "logarithmic, then this interval is multiplied to successive X values.\n\n"
231  "The X values will be automatically aligned along simple numbers. If the first and/or last "
232  "points are not along the aligned X values, then one or two additional points are added "
233  "as necessary."));
234  layoutPointsSelections->addWidget (m_editFunctionsPointsEvenlySpacing, row, 2, 1, 1, Qt::AlignLeft);
235  connect (m_editFunctionsPointsEvenlySpacing, SIGNAL (textChanged(const QString &)), this, SLOT (slotFunctionsPointsEvenlySpacedInterval(const QString &)));
236 
237  m_cmbFunctionsPointsEvenlySpacingUnits = new QComboBox;
238  m_cmbFunctionsPointsEvenlySpacingUnits->setWhatsThis (tr ("Units for spacing interval.\n\n"
239  "Pixel units are preferred when the spacing is to be independent of the X scale. The spacing will be "
240  "consistent across the graph, even if the X scale is logarithmic.\n\n"
241  "Graph units are preferred when the spacing is to depend on the X scale."));
242  m_cmbFunctionsPointsEvenlySpacingUnits->addItem(exportPointsIntervalUnitsToString (EXPORT_POINTS_INTERVAL_UNITS_GRAPH),
243  QVariant (EXPORT_POINTS_INTERVAL_UNITS_GRAPH));
244  m_cmbFunctionsPointsEvenlySpacingUnits->addItem(exportPointsIntervalUnitsToString (EXPORT_POINTS_INTERVAL_UNITS_SCREEN),
245  QVariant (EXPORT_POINTS_INTERVAL_UNITS_SCREEN));
246  connect (m_cmbFunctionsPointsEvenlySpacingUnits, SIGNAL (activated (const QString &)),
247  this, SLOT (slotFunctionsPointsEvenlySpacedIntervalUnits (const QString &))); // activated() ignores code changes
248  layoutPointsSelections->addWidget (m_cmbFunctionsPointsEvenlySpacingUnits, row++, 3, 1, 1, Qt::AlignLeft);
249 
250  m_btnFunctionsPointsGridLines = new QRadioButton (tr ("Interpolate Ys at evenly spaced X values on grid lines"));
251  m_btnFunctionsPointsGridLines->setWhatsThis (tr ("Exported file will have values at evenly spaced X values at the vertical grid lines."));
252  layoutPointsSelections->addWidget (m_btnFunctionsPointsGridLines, row++, 0, 1, 4);
253  connect (m_btnFunctionsPointsGridLines, SIGNAL (released()), this, SLOT (slotFunctionsPointsGridLines()));
254 
255  m_btnFunctionsPointsRaw = new QRadioButton (tr ("Raw Xs and Ys"));
256  m_btnFunctionsPointsRaw->setWhatsThis (tr ("Exported file will have only original X and Y values"));
257  layoutPointsSelections->addWidget (m_btnFunctionsPointsRaw, row++, 0, 1, 4);
258  connect (m_btnFunctionsPointsRaw, SIGNAL (released()), this, SLOT (slotFunctionsPointsRaw()));
259 }
260 
261 void DlgSettingsExportFormat::createHeader (QHBoxLayout *layoutMisc)
262 {
263  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::createHeader";
264 
265  const int COLUMN_RADIO_BUTTONS = 0, COLUMN_EMPTY = 1, COLUMN_LABEL = 2;
266 
267  QGroupBox *groupHeader = new QGroupBox (tr ("Header"));
268  layoutMisc->addWidget (groupHeader, 1);
269 
270  QGridLayout *layoutHeader = new QGridLayout;
271  layoutHeader->setColumnMinimumWidth(COLUMN_EMPTY,
272  MIN_HEADER_EMPTY_COLUMN_WIDTH);
273  groupHeader->setLayout (layoutHeader);
274  int row = 0;
275 
276  m_btnHeaderNone = new QRadioButton (exportHeaderToString (EXPORT_HEADER_NONE));
277  m_btnHeaderNone->setWhatsThis (tr ("Exported file will have no header line"));
278  layoutHeader->addWidget (m_btnHeaderNone, row++, COLUMN_RADIO_BUTTONS, 1, 1);
279  connect (m_btnHeaderNone, SIGNAL (released ()), this, SLOT (slotHeaderNone()));
280 
281  m_btnHeaderSimple = new QRadioButton (exportHeaderToString (EXPORT_HEADER_SIMPLE));
282  m_btnHeaderSimple->setWhatsThis (tr ("Exported file will have simple header line"));
283  layoutHeader->addWidget (m_btnHeaderSimple, row++, COLUMN_RADIO_BUTTONS, 1, 1);
284  connect (m_btnHeaderSimple, SIGNAL (released ()), this, SLOT (slotHeaderSimple()));
285 
286  m_btnHeaderGnuplot = new QRadioButton (exportHeaderToString (EXPORT_HEADER_GNUPLOT));
287  m_btnHeaderGnuplot->setWhatsThis (tr ("Exported file will have gnuplot header line"));
288  layoutHeader->addWidget (m_btnHeaderGnuplot, row++, COLUMN_RADIO_BUTTONS, 1, 1);
289  connect (m_btnHeaderGnuplot, SIGNAL (released()), this, SLOT (slotHeaderGnuplot()));
290 
291  createXLabel (layoutHeader,
292  COLUMN_LABEL);
293 }
294 
296 {
297  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::createOptionalSaveDefault";
298 
299  m_btnSaveDefault = new QPushButton (tr ("Save As Default"));
300  m_btnSaveDefault->setWhatsThis (tr ("Save the settings for use as future defaults."));
301  connect (m_btnSaveDefault, SIGNAL (released ()), this, SLOT (slotSaveDefault ()));
302  layout->addWidget (m_btnSaveDefault, 0, Qt::AlignLeft);
303 }
304 
305 void DlgSettingsExportFormat::createPreview(QGridLayout *layout, int &row)
306 {
307  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::createPreview";
308 
309  QLabel *label = new QLabel (tr ("Preview"));
310  layout->addWidget (label, row, 0, 1, 3);
311 
312  // Legend. Padding and margin in rich text do not work so &nbsp; is used for spacing
313  QLabel *labelLegend = new QLabel;
314  labelLegend->setTextFormat (Qt::RichText);
315  QString legendHtml = QString ("<span style=\"background-color: %1\">&nbsp;Functions&nbsp;</span>"
316  "&nbsp;&nbsp;&nbsp;"
317  "<span style=\"background-color: %2\">&nbsp;Relations&nbsp;</span>")
318  .arg (COLOR_FUNCTIONS)
319  .arg (COLOR_RELATIONS);
320  labelLegend->setText (legendHtml);
321  layout->addWidget (labelLegend, row++, 1, 1, 2, Qt::AlignRight);
322 
323  m_editPreview = new QTextEdit;
324  m_editPreview->setReadOnly (true);
325  m_editPreview->setWhatsThis (tr ("Preview window shows how current settings affect the exported file.\n\n"
326  "Functions (shown here in blue) are output first, followed by relations "
327  "(shown here in green) if any exist."));
328  m_editPreview->setMinimumHeight (MINIMUM_PREVIEW_HEIGHT);
329  m_editPreview->document()->setDefaultStyleSheet("div { padding-left: 20px; }");
330  QPalette p = m_editPreview->palette();
331  p.setColor (QPalette::Base, QColor (240, 240, 240)); // Replace attention-getting white border by gray
332  m_editPreview->setPalette (p);
333 
334  layout->addWidget (m_editPreview, row++, 0, 1, 3);
335 }
336 
337 void DlgSettingsExportFormat::createRelationsPointsSelection (QHBoxLayout *layoutRelations)
338 {
339  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::createRelationsPointsSelection";
340 
341  QGroupBox *groupPointsSelection = new QGroupBox (tr ("Relation Points Selection"));
342  layoutRelations->addWidget (groupPointsSelection);
343 
344  QGridLayout *layoutPointsSelections = new QGridLayout;
345  groupPointsSelection->setLayout (layoutPointsSelections);
346 
347  layoutPointsSelections->setColumnMinimumWidth(0, MIN_INDENT_COLUMN_WIDTH);
348  layoutPointsSelections->setColumnStretch (0, 0);
349  layoutPointsSelections->setColumnStretch (1, 0);
350  layoutPointsSelections->setColumnStretch (2, 0);
351  layoutPointsSelections->setColumnStretch (3, 1);
352 
353  int row = 0;
354 
355  m_btnRelationsPointsEvenlySpaced = new QRadioButton (tr ("Interpolate Xs and Ys at evenly spaced intervals."));
356  m_btnRelationsPointsEvenlySpaced->setWhatsThis (tr ("Exported file will have points evenly spaced along each relation, separated by the interval "
357  "selected below. If the last interval does not end at the last point, then a shorter last interval "
358  "is added that ends on the last point."));
359  layoutPointsSelections->addWidget (m_btnRelationsPointsEvenlySpaced, row++, 0, 1, 4);
360  connect (m_btnRelationsPointsEvenlySpaced, SIGNAL (released()), this, SLOT (slotRelationsPointsEvenlySpaced()));
361 
362  QLabel *labelInterval = new QLabel (QString ("%1:").arg (tr ("Interval")));
363  layoutPointsSelections->addWidget (labelInterval, row, 1, 1, 1, Qt::AlignRight);
364 
365  m_editRelationsPointsEvenlySpacing = new QLineEdit;
366  m_validatorRelationsPointsEvenlySpacing = new QDoubleValidator; // Minimum value, to prevent overflow, is set later according to settings
367  m_editRelationsPointsEvenlySpacing->setValidator (m_validatorRelationsPointsEvenlySpacing);
368  m_editRelationsPointsEvenlySpacing->setMinimumWidth (MIN_EDIT_WIDTH);
369  m_editRelationsPointsEvenlySpacing->setMaximumWidth (MAX_EDIT_WIDTH);
370  m_editRelationsPointsEvenlySpacing->setWhatsThis (tr ("Interval between successive points when "
371  "exporting at evenly spaced (X,Y) coordinates."));
372  layoutPointsSelections->addWidget (m_editRelationsPointsEvenlySpacing, row, 2, 1, 1, Qt::AlignLeft);
373  connect (m_editRelationsPointsEvenlySpacing, SIGNAL (textChanged(const QString &)), this, SLOT (slotRelationsPointsEvenlySpacedInterval(const QString &)));
374 
375  m_cmbRelationsPointsEvenlySpacingUnits = new QComboBox;
376  m_cmbRelationsPointsEvenlySpacingUnits->setWhatsThis (tr ("Units for spacing interval.\n\n"
377  "Pixel units are preferred when the spacing is to be independent of the X and Y scales. The spacing will be "
378  "consistent across the graph, even if a scale is logarithmic or the X and Y scales are different.\n\n"
379  "Graph units are usually preferred when the X and Y scales are identical."));
380  m_cmbRelationsPointsEvenlySpacingUnits->addItem(exportPointsIntervalUnitsToString (EXPORT_POINTS_INTERVAL_UNITS_GRAPH),
381  QVariant (EXPORT_POINTS_INTERVAL_UNITS_GRAPH));
382  m_cmbRelationsPointsEvenlySpacingUnits->addItem(exportPointsIntervalUnitsToString (EXPORT_POINTS_INTERVAL_UNITS_SCREEN),
383  QVariant (EXPORT_POINTS_INTERVAL_UNITS_SCREEN));
384  connect (m_cmbRelationsPointsEvenlySpacingUnits, SIGNAL (activated (const QString &)),
385  this, SLOT (slotRelationsPointsEvenlySpacedIntervalUnits (const QString &))); // activated() ignores code changes
386  layoutPointsSelections->addWidget (m_cmbRelationsPointsEvenlySpacingUnits, row++, 3, 1, 1, Qt::AlignLeft);
387 
388  m_btnRelationsPointsRaw = new QRadioButton (tr ("Raw Xs and Ys"));
389  m_btnRelationsPointsRaw->setWhatsThis (tr ("Exported file will have only original X and Y values"));
390  layoutPointsSelections->addWidget (m_btnRelationsPointsRaw, row++, 0, 1, 4);
391  connect (m_btnRelationsPointsRaw, SIGNAL (released()), this, SLOT (slotRelationsPointsRaw()));
392 }
393 
395 {
396  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::createSubPanel";
397 
398  QWidget *subPanel = new QWidget ();
399  QGridLayout *layout = new QGridLayout (subPanel);
400  subPanel->setLayout (layout);
401 
402  int row = 0;
403  createCurveSelection (layout, row);
404 
405  createTabWidget (layout,
406  row);
407 
408  QWidget *widgetMisc = new QWidget;
409  layout->addWidget (widgetMisc, row++, 0, 1, 3);
410  QHBoxLayout *layoutMisc = new QHBoxLayout;
411  widgetMisc->setLayout (layoutMisc);
412 
413  createDelimiters (layoutMisc); // One row of radio buttons
414  createHeader (layoutMisc); // Two rows with radio buttons and then header label
415  createFileLayout (layoutMisc); // One row of radio buttons
416 
417  createPreview (layout, row);
418 
419  return subPanel;
420 }
421 
422 void DlgSettingsExportFormat::createTabWidget (QGridLayout *layout,
423  int &row)
424 {
425  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::createTabWidget";
426 
427  m_tabWidget = new QTabWidget;
428  // This gets connected below, after the tabs have been added
429  layout->addWidget (m_tabWidget, row++, 0, 1, 3);
430 
431  QWidget *widgetFunctions = new QWidget;
432  int indexFunctions = m_tabWidget->addTab (widgetFunctions, tr ("Functions"));
433  QWidget *tabFunctions = m_tabWidget->widget (indexFunctions);
434  tabFunctions->setWhatsThis (tr ("Functions Tab\n\n"
435  "Controls for specifying the format of functions during export"));
436  QHBoxLayout *layoutFunctions = new QHBoxLayout;
437  widgetFunctions->setLayout (layoutFunctions);
438 
439  QWidget *widgetRelations = new QWidget;
440  int indexRelations = m_tabWidget->addTab (widgetRelations, tr ("Relations"));
441  QWidget *tabRelations = m_tabWidget->widget (indexRelations);
442  tabRelations->setWhatsThis (tr ("Relations Tab\n\n"
443  "Controls for specifying the format of relations during export"));
444  QHBoxLayout *layoutRelations = new QHBoxLayout;
445  widgetRelations->setLayout (layoutRelations);
446 
447  // Now that the tabs have been added we can connect this signal
448  connect (m_tabWidget, SIGNAL (currentChanged (int)), this, SLOT (slotTabChanged (int)));
449 
450  createFunctionsPointsSelection (layoutFunctions);
451  createRelationsPointsSelection (layoutRelations);
452 }
453 
454 void DlgSettingsExportFormat::createXLabel (QGridLayout *layoutHeader,
455  int colLabel)
456 {
457  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::createXLabel";
458 
459  int row = 1; // Skip first row
460 
461  QLabel *title = new QLabel (QString ("%1:").arg (tr ("X Label")));
462  layoutHeader->addWidget (title, row++, colLabel, 1, 1);
463 
464  m_editXLabel = new QLineEdit;
465  m_editXLabel->setWhatsThis (tr ("Label in the header for x values"));
466  layoutHeader->addWidget (m_editXLabel, row++, colLabel, 1, 1);
467  connect (m_editXLabel, SIGNAL (textChanged (const QString &)), this, SLOT (slotXLabel(const QString &)));
468 }
469 
470 QString DlgSettingsExportFormat::exportedTextToExportedHtml (const QString &text,
471  const QString &color) const
472 {
473  QRegExp re ("<br>$");
474 
475  QString textCopy (text);
476  QString replaced = textCopy
477  .replace ("\n", "<br>")
478  .replace (" ", "&nbsp;")
479  .replace (re, "")
480  .replace ("\t", "&nbsp;&nbsp;&nbsp;&nbsp;");
481 
482  QString html = QString ("<div style=\"display: inline; background-color: %1\">%2</div>")
483  .arg (color)
484  .arg (replaced);
485 
486  return html;
487 }
488 
489 bool DlgSettingsExportFormat::goodIntervalFunctions() const
490 {
491  // LOG4CPP_INFO_S is below
492 
493  QString textFunctions = m_editFunctionsPointsEvenlySpacing->text();
494  int posFunctions;
495 
496  bool isGood = (m_validatorFunctionsPointsEvenlySpacing->validate (textFunctions, posFunctions) == QValidator::Acceptable);
497 
498  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::goodIntervalFunctions"
499  << " text=" << textFunctions.toLatin1().data()
500  << " good=" << (isGood ? "true" : "false")
501  << " bottom=" << m_validatorFunctionsPointsEvenlySpacing->bottom()
502  << " top=" << m_validatorFunctionsPointsEvenlySpacing->top();
503 
504  return isGood;
505 }
506 
507 bool DlgSettingsExportFormat::goodIntervalRelations() const
508 {
509  // LOG4CPP_INFO_S is below
510 
511  QString textRelations = m_editRelationsPointsEvenlySpacing->text();
512  int posRelations;
513 
514  bool isGood = (m_validatorRelationsPointsEvenlySpacing->validate (textRelations, posRelations) == QValidator::Acceptable);
515 
516  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::goodIntervalRelations"
517  << " text=" << textRelations.toLatin1().data()
518  << " good=" << (isGood ? "true" : "false")
519  << " bottom=" << m_validatorRelationsPointsEvenlySpacing->bottom()
520  << " top=" << m_validatorRelationsPointsEvenlySpacing->top();
521 
522  return isGood;
523 }
524 
526 {
527  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::handleOk";
528 
530  cmdMediator ().document(),
531  *m_modelExportBefore,
532  *m_modelExportAfter);
533  cmdMediator ().push (cmd);
534 
535  hide ();
536 }
537 
538 void DlgSettingsExportFormat::initializeIntervalConstraints ()
539 {
540  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::initializeIntervalConstraints";
541 
542  const int MAX_POINTS_ACROSS_RANGE = 5000;
543 
544  // Get min and max of graph and screen coordinates
545  CallbackBoundingRects ftor (cmdMediator().document().documentAxesPointsRequired(),
546  mainWindow().transformation());
547 
548  Functor2wRet<const QString &, const Point &, CallbackSearchReturn> ftorWithCallback = functor_ret (ftor,
550  cmdMediator().iterateThroughCurvesPointsGraphs (ftorWithCallback);
551 
552  // If there are no points, then interval will be zero. That special case must be handled downstream to prevent infinite loops
553  bool isEmpty;
554  QPointF boundingRectGraphMin = ftor.boundingRectGraphMin (isEmpty);
555  QPointF boundingRectGraphMax = ftor.boundingRectGraphMax (isEmpty);
556  double maxSizeGraph = boundingRectGraphMax.x() - boundingRectGraphMin.x();
557  double maxSizeScreen = ftor.boundingRectScreen(isEmpty).width();
558  m_minIntervalGraph = maxSizeGraph / MAX_POINTS_ACROSS_RANGE; // Should be unaffected by y range
559  m_minIntervalScreen = maxSizeScreen / MAX_POINTS_ACROSS_RANGE; // Should be unaffected by y range
560 }
561 
563 {
564  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::load";
565 
566  setCmdMediator (cmdMediator);
567 
568  // Flush old data
569  delete m_modelExportBefore;
570  delete m_modelExportAfter;
571 
572  // Save new data
573  m_modelExportBefore = new DocumentModelExportFormat (cmdMediator.document());
574  m_modelExportAfter = new DocumentModelExportFormat (cmdMediator.document());
575 
576  // Populate controls. First load excluded curves
577  m_listExcluded->clear();
578  QStringList curveNamesExcluded = m_modelExportAfter->curveNamesNotExported();
579  QStringList::const_iterator itr;
580  for (itr = curveNamesExcluded.begin (); itr != curveNamesExcluded.end(); ++itr) {
581  QString curveNameNotExported = *itr;
582  m_listExcluded->addItem (curveNameNotExported);
583  }
584 
585  // Include curves that are not excluded
586  m_listIncluded->clear();
587  QStringList curveNamesAll = cmdMediator.document().curvesGraphsNames();
588  for (itr = curveNamesAll.begin (); itr != curveNamesAll.end(); itr++) {
589  QString curveName = *itr;
590  if (!curveNamesExcluded.contains (curveName)) {
591  m_listIncluded->addItem (curveName);
592  }
593  }
594 
595  ExportPointsSelectionFunctions pointsSelectionFunctions = m_modelExportAfter->pointsSelectionFunctions();
596  m_btnFunctionsPointsAllCurves->setChecked (pointsSelectionFunctions == EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_ALL_CURVES);
597  m_btnFunctionsPointsFirstCurve->setChecked (pointsSelectionFunctions == EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_FIRST_CURVE);
598  m_btnFunctionsPointsEvenlySpaced->setChecked (pointsSelectionFunctions == EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_PERIODIC);
599  m_btnFunctionsPointsGridLines->setChecked (pointsSelectionFunctions == EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_GRID_LINES);
600  m_btnFunctionsPointsRaw->setChecked (pointsSelectionFunctions == EXPORT_POINTS_SELECTION_FUNCTIONS_RAW);
601 
602  ExportLayoutFunctions layoutFunctions = m_modelExportAfter->layoutFunctions ();
603  m_btnCurvesLayoutAllCurves->setChecked (layoutFunctions == EXPORT_LAYOUT_ALL_PER_LINE);
604  m_btnCurvesLayoutOneCurve->setChecked (layoutFunctions == EXPORT_LAYOUT_ONE_PER_LINE);
605 
606  ExportPointsSelectionRelations pointsSelectionRelations = m_modelExportAfter->pointsSelectionRelations();
607  m_btnRelationsPointsEvenlySpaced->setChecked (pointsSelectionRelations == EXPORT_POINTS_SELECTION_RELATIONS_INTERPOLATE);
608  m_btnRelationsPointsRaw->setChecked (pointsSelectionRelations == EXPORT_POINTS_SELECTION_RELATIONS_RAW);
609 
610  ExportDelimiter delimiter = m_modelExportAfter->delimiter ();
611  m_btnDelimitersCommas->setChecked (delimiter == EXPORT_DELIMITER_COMMA);
612  m_btnDelimitersSpaces->setChecked (delimiter == EXPORT_DELIMITER_SPACE);
613  m_btnDelimitersTabs->setChecked (delimiter == EXPORT_DELIMITER_TAB);
614  m_btnDelimitersSemicolons->setChecked (delimiter == EXPORT_DELIMITER_SEMICOLON);
615 
616  m_chkExtrapolateOutsideEndpoints->setChecked (m_modelExportAfter->extrapolateOutsideEndpoints ());
617 
618  m_chkOverrideCsvTsv->setChecked (m_modelExportAfter->overrideCsvTsv());
619 
620  ExportHeader header = m_modelExportAfter->header ();
621  m_btnHeaderNone->setChecked (header == EXPORT_HEADER_NONE);
622  m_btnHeaderSimple->setChecked (header == EXPORT_HEADER_SIMPLE);
623  m_btnHeaderGnuplot->setChecked (header == EXPORT_HEADER_GNUPLOT);
624 
625  m_editXLabel->setText (m_modelExportAfter->xLabel());
626 
627  m_editFunctionsPointsEvenlySpacing->setText (QString::number (m_modelExportAfter->pointsIntervalFunctions()));
628  m_editRelationsPointsEvenlySpacing->setText (QString::number (m_modelExportAfter->pointsIntervalRelations()));
629 
630  ExportPointsIntervalUnits pointsIntervalUnitsFunctions = m_modelExportAfter->pointsIntervalUnitsFunctions();
631  ExportPointsIntervalUnits pointsIntervalUnitsRelations = m_modelExportAfter->pointsIntervalUnitsRelations();
632  int indexFunctions = m_cmbFunctionsPointsEvenlySpacingUnits->findData (QVariant (pointsIntervalUnitsFunctions));
633  int indexRelations = m_cmbRelationsPointsEvenlySpacingUnits->findData (QVariant (pointsIntervalUnitsRelations));
634  m_cmbFunctionsPointsEvenlySpacingUnits->setCurrentIndex (indexFunctions);
635  m_cmbRelationsPointsEvenlySpacingUnits->setCurrentIndex (indexRelations);
636 
637  initializeIntervalConstraints ();
638 
639  updateControlsUponLoad (); // Before updateControls so m_haveFunction and m_haveRelation are set
640  updateControls();
641  updateIntervalConstraints();
642  enableOk (false); // Disable Ok button since there not yet any changes
643  updatePreview();
644 }
645 
647 {
648  if (!smallDialogs) {
649  setMinimumHeight (MINIMUM_HEIGHT);
650  }
651 }
652 
653 void DlgSettingsExportFormat::slotDelimitersCommas()
654 {
655  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotDelimitersCommas";
656 
657  m_modelExportAfter->setDelimiter(EXPORT_DELIMITER_COMMA);
658  updateControls();
659  updatePreview();
660 }
661 
662 void DlgSettingsExportFormat::slotDelimitersSemicolons()
663 {
664  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotDelimitersSemicolons";
665 
666  m_modelExportAfter->setDelimiter(EXPORT_DELIMITER_SEMICOLON);
667  updateControls();
668  updatePreview();
669 }
670 
671 void DlgSettingsExportFormat::slotDelimitersSpaces()
672 {
673  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotDelimitersSpaces";
674 
675  m_modelExportAfter->setDelimiter(EXPORT_DELIMITER_SPACE);
676  updateControls();
677  updatePreview();
678 }
679 
680 void DlgSettingsExportFormat::slotDelimitersTabs()
681 {
682  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotDelimitersTabs";
683 
684  m_modelExportAfter->setDelimiter(EXPORT_DELIMITER_TAB);
685  updateControls();
686  updatePreview();
687 }
688 
689 void DlgSettingsExportFormat::slotExclude ()
690 {
691  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotExclude";
692 
693  // Perform forward pass to get excluded curves in the proper order
694  int i;
695  QStringList excluded;
696  for (i = 0; i < m_listIncluded->count(); i++) {
697  if (m_listIncluded->item(i)->isSelected()) {
698  excluded += m_listIncluded->item(i)->text();
699  }
700  }
701 
702  // Add the excluded curves to the excluded list
703  for (i = 0; i < excluded.count(); i++) {
704  QString curveName = excluded.at (i);
705  m_listExcluded->addItem (curveName);
706  }
707 
708  // Perform backwards pass to remove the excluded curves from the included list
709  for (i = m_listIncluded->count() - 1; i>= 0; i--) {
710  QString curveName = m_listIncluded->item(i)->text();
711  if (excluded.contains (curveName)) {
712  QListWidgetItem *item = m_listIncluded->item (i);
713  m_listIncluded->removeItemWidget (item);
714  delete item;
715  }
716  }
717 
718  m_modelExportAfter->setCurveNamesNotExported(excluded);
719  updateControls();
720  updatePreview();
721 }
722 
723 void DlgSettingsExportFormat::slotFunctionsExtrapolateOutsideEndpoints(int)
724 {
725  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotFunctionsExtrapolateOutsideEndpoints";
726 
727  m_modelExportAfter->setExtrapolateOutsideEndpoints (m_chkExtrapolateOutsideEndpoints->isChecked());
728  updateControls();
729  updatePreview();
730 }
731 
732 void DlgSettingsExportFormat::slotFunctionsLayoutAllCurves()
733 {
734  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotFunctionsLayoutAllCurves";
735 
736  m_modelExportAfter->setLayoutFunctions(EXPORT_LAYOUT_ALL_PER_LINE);
737  updateControls();
738  updatePreview();
739 }
740 
741 void DlgSettingsExportFormat::slotFunctionsLayoutOneCurve()
742 {
743  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotFunctionsLayoutOneCurve";
744 
745  m_modelExportAfter->setLayoutFunctions(EXPORT_LAYOUT_ONE_PER_LINE);
746  updateControls();
747  updatePreview();
748 }
749 
750 void DlgSettingsExportFormat::slotFunctionsPointsAllCurves()
751 {
752  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotFunctionsPointsAllCurves";
753 
754  m_modelExportAfter->setPointsSelectionFunctions(EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_ALL_CURVES);
755  updateControls();
756  updatePreview();
757 }
758 
759 void DlgSettingsExportFormat::slotFunctionsPointsEvenlySpaced()
760 {
761  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotFunctionsPointsEvenlySpaced";
762 
763  m_modelExportAfter->setPointsSelectionFunctions(EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_PERIODIC);
764  updateControls();
765  updatePreview();
766 }
767 
768 void DlgSettingsExportFormat::slotFunctionsPointsEvenlySpacedInterval(const QString &)
769 {
770  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotFunctionsPointsEvenlySpacedInterval";
771 
772  // Prevent infinite loop on empty and "-" values which get treated as zero interval
773  if (goodIntervalFunctions()) {
774  m_modelExportAfter->setPointsIntervalFunctions(m_editFunctionsPointsEvenlySpacing->text().toDouble());
775  updateControls();
776  updatePreview();
777  } else {
778  m_editPreview->setText(EMPTY_PREVIEW);
779  }
780 }
781 
782 void DlgSettingsExportFormat::slotFunctionsPointsEvenlySpacedIntervalUnits(const QString &)
783 {
784  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotFunctionsPointsEvenlySpacedIntervalUnits";
785 
786  int index = m_cmbFunctionsPointsEvenlySpacingUnits->currentIndex();
787  ExportPointsIntervalUnits units = static_cast<ExportPointsIntervalUnits> (m_cmbFunctionsPointsEvenlySpacingUnits->itemData (index).toInt());
788 
789  m_modelExportAfter->setPointsIntervalUnitsFunctions(units);
790  updateIntervalConstraints(); // Call this before updateControls so constraint checking is updated for ok button
791  updateControls();
792  updatePreview();
793 }
794 
795 void DlgSettingsExportFormat::slotFunctionsPointsFirstCurve()
796 {
797  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotFunctionsPointsFirstCurve";
798 
799  m_modelExportAfter->setPointsSelectionFunctions(EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_FIRST_CURVE);
800  updateControls();
801  updatePreview();
802 }
803 
804 void DlgSettingsExportFormat::slotFunctionsPointsGridLines()
805 {
806  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotFunctionsPointsGridLines";
807 
808  m_modelExportAfter->setPointsSelectionFunctions(EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_GRID_LINES);
809  updateControls();
810  updatePreview();
811 }
812 
813 void DlgSettingsExportFormat::slotFunctionsPointsRaw()
814 {
815  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotFunctionsPointsRaw";
816 
817  m_modelExportAfter->setPointsSelectionFunctions(EXPORT_POINTS_SELECTION_FUNCTIONS_RAW);
818  updateControls();
819  updatePreview();
820 }
821 
822 void DlgSettingsExportFormat::slotHeaderGnuplot()
823 {
824  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotHeaderGnuplot";
825 
826  m_modelExportAfter->setHeader(EXPORT_HEADER_GNUPLOT);
827  updateControls();
828  updatePreview();
829 }
830 
831 void DlgSettingsExportFormat::slotHeaderNone()
832 {
833  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotHeaderNone";
834 
835  m_modelExportAfter->setHeader(EXPORT_HEADER_NONE);
836  updateControls();
837  updatePreview();
838 }
839 
840 void DlgSettingsExportFormat::slotHeaderSimple()
841 {
842  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotHeaderSimple";
843 
844  m_modelExportAfter->setHeader(EXPORT_HEADER_SIMPLE);
845  updateControls();
846  updatePreview();
847 }
848 
849 void DlgSettingsExportFormat::slotInclude ()
850 {
851  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotInclude";
852 
853  // Perform forward pass to get included curves in the proper order
854  int i;
855  QStringList included;
856  for (i = 0; i < m_listExcluded->count(); i++) {
857  if (m_listExcluded->item(i)->isSelected()) {
858  included += m_listExcluded->item(i)->text();
859  }
860  }
861 
862  // Add the included curves to the included list
863  for (i = 0; i < included.count(); i++) {
864  QString curveName = included.at (i);
865  m_listIncluded->addItem (curveName);
866  }
867 
868  // Perform backwards pass to remove the included curves from the excluded list
869  QStringList excluded;
870  for (i = m_listExcluded->count() - 1; i>= 0; i--) {
871  QString curveName = m_listExcluded->item(i)->text();
872  QListWidgetItem *item = m_listExcluded->item (i);
873  if (included.contains (curveName)) {
874  m_listExcluded->removeItemWidget (item);
875  delete item;
876  } else {
877  excluded += item->text();
878  }
879  }
880 
881  m_modelExportAfter->setCurveNamesNotExported(excluded);
882  updateControls();
883  updatePreview();
884 }
885 
886 void DlgSettingsExportFormat::slotListExcluded()
887 {
888  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotListExcluded";
889 
890  updateControls();
891  // Do not call updatePreview since this method changes nothing
892 }
893 
894 void DlgSettingsExportFormat::slotListIncluded()
895 {
896  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotListIncluded";
897 
898  updateControls();
899  // Do not call updatePreview since this method changes nothing
900 }
901 
902 void DlgSettingsExportFormat::slotOverrideCsvTsv(int)
903 {
904  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotOverrideCsvTsv";
905 
906  m_modelExportAfter->setOverrideCsvTsv(m_chkOverrideCsvTsv->isChecked());
907  updateControls();
908  updatePreview();
909 }
910 
911 void DlgSettingsExportFormat::slotRelationsPointsEvenlySpaced()
912 {
913  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotRelationsPointsEvenlySpaced";
914 
915  m_modelExportAfter->setPointsSelectionRelations(EXPORT_POINTS_SELECTION_RELATIONS_INTERPOLATE);
916  updateControls();
917  updatePreview();
918 }
919 
920 void DlgSettingsExportFormat::slotRelationsPointsEvenlySpacedInterval(const QString &)
921 {
922  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotRelationsPointsEvenlySpacedInterval";
923 
924  m_modelExportAfter->setPointsIntervalRelations(m_editRelationsPointsEvenlySpacing->text().toDouble());
925  updateControls();
926  updatePreview();
927 }
928 
929 void DlgSettingsExportFormat::slotRelationsPointsEvenlySpacedIntervalUnits(const QString &)
930 {
931  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotRelationsPointsEvenlySpacedIntervalUnits";
932 
933  int index = m_cmbRelationsPointsEvenlySpacingUnits->currentIndex();
934  ExportPointsIntervalUnits units = static_cast<ExportPointsIntervalUnits> (m_cmbRelationsPointsEvenlySpacingUnits->itemData (index).toInt());
935 
936  m_modelExportAfter->setPointsIntervalUnitsRelations(units);
937  updateIntervalConstraints(); // Call this before updateControls so constraint checking is updated for ok button
938  updateControls();
939  updatePreview();
940 }
941 
942 void DlgSettingsExportFormat::slotRelationsPointsRaw()
943 {
944  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotRelationsPointsRaw";
945 
946  m_modelExportAfter->setPointsSelectionRelations(EXPORT_POINTS_SELECTION_RELATIONS_RAW);
947  updateControls();
948  updatePreview();
949 }
950 
951 void DlgSettingsExportFormat::slotSaveDefault()
952 {
953  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotSaveDefault";
954 
955  QSettings settings (SETTINGS_ENGAUGE, SETTINGS_DIGITIZER);
956  settings.beginGroup (SETTINGS_GROUP_EXPORT);
957 
958  settings.setValue (SETTINGS_EXPORT_DELIMITER,
959  QVariant (m_modelExportAfter->delimiter()));
960  settings.setValue (SETTINGS_EXPORT_EXTRAPOLATE_OUTSIDE_ENDPOINTS,
961  QVariant (m_modelExportAfter->extrapolateOutsideEndpoints()));
962  settings.setValue (SETTINGS_EXPORT_HEADER,
963  QVariant (m_modelExportAfter->header()));
964  settings.setValue (SETTINGS_EXPORT_LAYOUT_FUNCTIONS,
965  QVariant (m_modelExportAfter->layoutFunctions()));
966  settings.setValue (SETTINGS_EXPORT_POINTS_INTERVAL_FUNCTIONS,
967  QVariant (m_modelExportAfter->pointsIntervalFunctions()));
968  settings.setValue (SETTINGS_EXPORT_POINTS_INTERVAL_RELATIONS,
969  QVariant (m_modelExportAfter->pointsIntervalRelations()));
970  settings.setValue (SETTINGS_EXPORT_POINTS_INTERVAL_UNITS_FUNCTIONS,
971  QVariant (m_modelExportAfter->pointsIntervalUnitsFunctions()));
972  settings.setValue (SETTINGS_EXPORT_POINTS_INTERVAL_UNITS_RELATIONS,
973  QVariant (m_modelExportAfter->pointsIntervalUnitsRelations()));
974  settings.setValue (SETTINGS_EXPORT_POINTS_SELECTION_FUNCTIONS,
975  QVariant (m_modelExportAfter->pointsSelectionFunctions()));
976  settings.setValue (SETTINGS_EXPORT_POINTS_SELECTION_RELATIONS,
977  QVariant (m_modelExportAfter->pointsSelectionRelations()));
978  settings.setValue (SETTINGS_EXPORT_X_LABEL,
979  QVariant (m_modelExportAfter->xLabel()));
980 
981  settings.endGroup ();
982 }
983 
984 void DlgSettingsExportFormat::slotTabChanged (int)
985 {
986  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotTabChanged";
987 
988  updatePreview();
989 }
990 
991 void DlgSettingsExportFormat::slotXLabel(const QString &)
992 {
993  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotXLabel";
994 
995  m_modelExportAfter->setXLabel (m_editXLabel->text());
996  updateControls();
997  updatePreview();
998 }
999 
1000 void DlgSettingsExportFormat::updateControls ()
1001 {
1002  bool isGoodState = goodIntervalFunctions() &&
1003  goodIntervalRelations();
1004  enableOk (isGoodState);
1005 
1006  // Function extrapolation never applies when using raw points
1007  m_chkExtrapolateOutsideEndpoints->setEnabled (!m_btnFunctionsPointsRaw->isChecked ());
1008 
1009  int selectedForInclude = m_listExcluded->selectedItems().count();
1010  int selectedForExclude = m_listIncluded->selectedItems().count();
1011  int inInclude = m_listIncluded->count();
1012 
1013  m_btnInclude->setEnabled (selectedForInclude > 0); // Need at least one selection
1014  m_btnExclude->setEnabled ((selectedForExclude > 0) && (inInclude - selectedForExclude > 0)); // Need at least one selection, and one left after the move
1015 
1016  m_editFunctionsPointsEvenlySpacing->setEnabled (m_haveFunction && m_btnFunctionsPointsEvenlySpaced->isChecked ());
1017  m_editRelationsPointsEvenlySpacing->setEnabled (m_haveRelation && m_btnRelationsPointsEvenlySpaced->isChecked ());
1018 
1019  m_editXLabel->setEnabled (!m_btnHeaderNone->isChecked());
1020 }
1021 
1022 void DlgSettingsExportFormat::updateControlsUponLoad ()
1023 {
1024  CurveStyles curveStyles = cmdMediator().document().modelCurveStyles();
1025 
1026  m_haveFunction = false;
1027  m_haveRelation = false;
1028 
1029  QStringList curveNames = curveStyles.curveNames();
1030 
1031  QStringList::const_iterator itr;
1032  for (itr = curveNames.begin(); itr != curveNames.end (); itr++) {
1033  QString curveName = *itr;
1034  CurveStyle curveStyle = curveStyles.curveStyle (curveName);
1035  CurveConnectAs curveConnectAs = curveStyle.lineStyle().curveConnectAs();
1036  if (curveConnectAs == CONNECT_AS_FUNCTION_SMOOTH || curveConnectAs == CONNECT_AS_FUNCTION_STRAIGHT) {
1037  m_haveFunction = true;
1038  } else if (curveConnectAs == CONNECT_AS_RELATION_SMOOTH || curveConnectAs == CONNECT_AS_RELATION_STRAIGHT) {
1039  m_haveRelation = true;
1040  }
1041  }
1042 
1043  // Enable function-specific widgets if appropriate
1044  m_btnFunctionsPointsAllCurves->setEnabled (m_haveFunction);
1045  m_btnFunctionsPointsFirstCurve->setEnabled (m_haveFunction);
1046  m_btnFunctionsPointsEvenlySpaced->setEnabled (m_haveFunction);
1047  m_editFunctionsPointsEvenlySpacing->setEnabled (m_haveFunction);
1048  m_cmbFunctionsPointsEvenlySpacingUnits->setEnabled (m_haveFunction);
1049  m_btnFunctionsPointsRaw->setEnabled (m_haveFunction);
1050 
1051  // Enable relation-specific widgets if appropriate
1052  m_btnRelationsPointsEvenlySpaced->setEnabled (m_haveRelation);
1053  m_editRelationsPointsEvenlySpacing->setEnabled (m_haveRelation);
1054  m_cmbRelationsPointsEvenlySpacingUnits->setEnabled (m_haveRelation);
1055  m_btnRelationsPointsRaw->setEnabled (m_haveRelation);
1056 
1057  // Do not start with a tab that does not apply to the current set of functions/relations
1058  if (!m_haveRelation) {
1059  m_tabWidget->setCurrentIndex (TAB_WIDGET_INDEX_FUNCTIONS);
1060  } else if (!m_haveFunction) {
1061  m_tabWidget->setCurrentIndex (TAB_WIDGET_INDEX_RELATIONS);
1062  }
1063 }
1064 
1065 void DlgSettingsExportFormat::updateIntervalConstraints ()
1066 {
1067  double functionsMin = (m_modelExportAfter->pointsIntervalUnitsFunctions() == EXPORT_POINTS_INTERVAL_UNITS_GRAPH ?
1068  m_minIntervalGraph :
1069  m_minIntervalScreen);
1070  double relationsMin = (m_modelExportAfter->pointsIntervalUnitsRelations() == EXPORT_POINTS_INTERVAL_UNITS_GRAPH ?
1071  m_minIntervalGraph :
1072  m_minIntervalScreen);
1073 
1074  if (m_tabWidget->currentIndex() == TAB_WIDGET_INDEX_FUNCTIONS) {
1075 
1076  if (m_modelExportAfter->pointsIntervalFunctions() < functionsMin) {
1077 
1078  m_editFunctionsPointsEvenlySpacing->setText (QString::number (functionsMin));
1079 
1080  }
1081 
1082  m_validatorFunctionsPointsEvenlySpacing->setBottom (functionsMin);
1083 
1084  } else {
1085 
1086  if (m_modelExportAfter->pointsIntervalRelations() < relationsMin) {
1087 
1088  m_editRelationsPointsEvenlySpacing->setText (QString::number (relationsMin));
1089 
1090  }
1091 
1092  m_validatorRelationsPointsEvenlySpacing->setBottom (relationsMin);
1093  }
1094 }
1095 
1096 void DlgSettingsExportFormat::updatePreview()
1097 {
1098  // Save the scroll position for continuity before and after the preview update
1099  int scrollPosition = m_editPreview->verticalScrollBar()->value();
1100 
1101  QString exportedTextFunctions, exportedTextRelations, exportedHtml;
1102  QTextStream strFunctions (&exportedTextFunctions);
1103  QTextStream strRelations (&exportedTextRelations);
1104 
1105  if (mainWindow().transformation().transformIsDefined()) {
1106 
1107  unsigned int numWritesSoFar = 0;
1108 
1109  ExportFileFunctions exportStrategyFunctions;
1110  exportStrategyFunctions.exportToFile (*m_modelExportAfter,
1111  cmdMediator().document(),
1112  mainWindow().modelMainWindow(),
1113  mainWindow().transformation(),
1114  strFunctions,
1115  numWritesSoFar);
1116 
1117  ExportFileRelations exportStrategyRelations;
1118  exportStrategyRelations.exportToFile (*m_modelExportAfter,
1119  cmdMediator().document(),
1120  mainWindow().modelMainWindow(),
1121  mainWindow().transformation(),
1122  strRelations,
1123  numWritesSoFar);
1124 
1125  // Use html to set background color. A <div> fills the whole background, unlike a <span>.
1126  // Final carriage return is removed to prevent unwanted blank line. A requirement is that
1127  // if there are no functions then no empty <div> appears (too confusing), and likewise if
1128  // there are no relations
1129  QString exportedHtmlFunctions, exportedHtmlRelations;
1130  if (! exportedTextFunctions.isEmpty ()) {
1131 
1132  exportedHtmlFunctions = exportedTextToExportedHtml (exportedTextFunctions, COLOR_FUNCTIONS);
1133  }
1134  if (! exportedTextRelations.isEmpty ()) {
1135 
1136  exportedHtmlRelations = exportedTextToExportedHtml (exportedTextRelations, COLOR_RELATIONS);
1137  }
1138 
1139  exportedHtml = exportedHtmlFunctions + exportedHtmlRelations;
1140 
1141  } else {
1142 
1143  exportedHtml = tr ("Preview is unavailable until axis points are defined.");
1144  }
1145 
1146  m_editPreview->setHtml (exportedHtml);
1147 
1148  // Restore scroll position
1149  m_editPreview->verticalScrollBar()->setValue (scrollPosition);
1150 }
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.
void setExtrapolateOutsideEndpoints(bool extrapolateOutsideEndpoints)
Set methods for extrapolation.
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
bool extrapolateOutsideEndpoints() const
Get methods for extrapolation.
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:700
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:347
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.