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