1 /***************************************************************************
2 File : ApplicationWindow.cpp
3 Project : SciDAVis
4 Description : SciDAVis's main window
5 --------------------------------------------------------------------
6 Copyright : (C) 2006-2009 Knut Franke (knut.franke*gmx.de)
7 Copyright : (C) 2006-2009 Tilman Benkert (thzs*gmx.net)
8 Copyright : (C) 2004-2007 by Ion Vasilief (ion_vasilief*yahoo.fr)
9 (replace * with @ in the email address)
10
11 ***************************************************************************/
12
13 /***************************************************************************
14 * *
15 * This program is free software; you can redistribute it and/or modify *
16 * it under the terms of the GNU General Public License as published by *
17 * the Free Software Foundation; either version 2 of the License, or *
18 * (at your option) any later version. *
19 * *
20 * This program is distributed in the hope that it will be useful, *
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
23 * GNU General Public License for more details. *
24 * *
25 * You should have received a copy of the GNU General Public License *
26 * along with this program; if not, write to the Free Software *
27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
28 * Boston, MA 02110-1301 USA *
29 * *
30 ***************************************************************************/
31
32 #define HOMEPAGE_URI "http://scidavis.sourceforge.net"
33 #define MANUAL_URI "http://sourceforge.net/projects/scidavis/files/SciDAVis%20Documentation/0.1/"
34 #define FORUM_URI "http://sourceforge.net/forum/?group_id=199120"
35 #define BUGREPORT_URI "http://sourceforge.net/tracker/?group_id=199120&atid=968214"
36 #define DOWNLOAD_URI "http://sourceforge.net/projects/scidavis/files/SciDAVis/"
37
38 #include "globals.h"
39 #include "ApplicationWindow.h"
40 #include "CurvesDialog.h"
41 #include "PlotDialog.h"
42 #include "AxesDialog.h"
43 #include "LineDialog.h"
44 #include "TextDialog.h"
45 #include "ExportDialog.h"
46 #include "ErrDialog.h"
47 #include "Legend.h"
48 #include "ArrowMarker.h"
49 #include "ImageMarker.h"
50 #include "Graph.h"
51 #include "Plot.h"
52 #include "Grid.h"
53 #include "PlotWizard.h"
54 #include "PolynomFitDialog.h"
55 #include "ExpDecayDialog.h"
56 #include "FunctionDialog.h"
57 #include "FitDialog.h"
58 #include "SurfaceDialog.h"
59 #include "Graph3D.h"
60 #include "Plot3DDialog.h"
61 #include "ImageDialog.h"
62 #include "MultiLayer.h"
63 #include "LayerDialog.h"
64 #include "DataSetDialog.h"
65 #include "IntDialog.h"
66 #include "ConfigDialog.h"
67 #ifdef ORIGIN_IMPORT
68 #include "importOPJ.h"
69 #endif
70 #include "AssociationsDialog.h"
71 #include "RenameWindowDialog.h"
72 #include "QwtErrorPlotCurve.h"
73 #include "InterpolationDialog.h"
74 #include "ImportASCIIDialog.h"
75 #include "ImageExportDialog.h"
76 #include "SmoothCurveDialog.h"
77 #include "FilterDialog.h"
78 #include "FFTDialog.h"
79 #include "Note.h"
80 #include "Folder.h"
81 #include "FindDialog.h"
82 #include "ScaleDraw.h"
83 #include "ScriptingLangDialog.h"
84 #include "TableStatistics.h"
85 #include "Fit.h"
86 #include "MultiPeakFit.h"
87 #include "PolynomialFit.h"
88 #include "SigmoidalFit.h"
89 #include "FunctionCurve.h"
90 #include "QwtPieCurve.h"
91 #include "Spectrogram.h"
92 #include "Differentiation.h"
93 #include "SmoothFilter.h"
94 #include "FFTFilter.h"
95 #include "Convolution.h"
96 #include "Correlation.h"
97 #include "CurveRangeDialog.h"
98 #include "ColorButton.h"
99 #include "QwtHistogram.h"
100 #include "OpenProjectDialog.h"
101 #include "IconLoader.h"
102 #include "core/Project.h"
103 #include "core/column/Column.h"
104 #include "lib/XmlStreamReader.h"
105 #include "table/future_Table.h"
106
107 // TODO: move tool-specific code to an extension manager
108 #include "ScreenPickerTool.h"
109 #include "DataPickerTool.h"
110 #include "TranslateCurveTool.h"
111 #include "MultiPeakFitTool.h"
112 #include "LineProfileTool.h"
113
114 #include <stdio.h>
115 #include <stdlib.h>
116
117 #include <QFileDialog>
118 #include <QInputDialog>
119 #include <QProgressDialog>
120 #include <QPrintDialog>
121 #include <QPixmapCache>
122 #include <QMenuBar>
123 #include <QClipboard>
124 #include <QMdiArea>
125 #include <QMdiSubWindow>
126 #include <QTranslator>
127 #include <QSplitter>
128 #include <QApplication>
129 #include <QMessageBox>
130 #include <QPrinter>
131 #include <QActionGroup>
132 #include <QAction>
133 #include <QToolBar>
134 #include <QKeySequence>
135 #include <QImageReader>
136 #include <QImageWriter>
137 #include <QDateTime>
138 #include <QShortcut>
139 #include <QDockWidget>
140 #include <QTextStream>
141 #include <QVarLengthArray>
142 #include <QList>
143 #include <QUrl>
144 #include <QDesktopServices>
145 #include <QStatusBar>
146 #include <QToolButton>
147 #include <QSignalMapper>
148 #include <QUndoStack>
149 #include <QtDebug>
150 #include <QDialogButtonBox>
151 #include <QUndoView>
152 #include <QUndoStack>
153 #include <QTemporaryFile>
154 #include <QDebug>
155 #include <QTextCodec>
156 #include <QScrollBar>
157 #include <QMimeData>
158 #include <QElapsedTimer>
159
160 #include <zlib.h>
161
162 #include <iostream>
163 #include <memory>
164 using namespace std;
165
166 #ifdef Q_OS_WIN
167 #include <io.h> // for _commit()
168 #else
169 #include <unistd.h> // for fsync()
170 #endif
171
172 using namespace Qwt3D;
173
174 extern "C" {
175 void file_compress(const char *file, const char *mode);
176 }
177
ApplicationWindow()178 ApplicationWindow::ApplicationWindow()
179 : scripted(ScriptingLangManager::newEnv(this)),
180 // logWindow(new QDockWidget(this)),
181 // explorerWindow(new QDockWidget(this)),
182 // results(new QTextEdit(logWindow)),
183 //#ifdef SCRIPTING_CONSOLE
184 // consoleWindow(new QDockWidget(this)),
185 // console(new QTextEdit(consoleWindow)),
186 //#endif
187 // d_workspace(new QMdiArea(this)),
188 // lv(new FolderListView()),
189 // folders(new FolderListView()),
190
191 // hiddenWindows(new QList<MyWidget*>()),
192 // outWindows(new QList<MyWidget*>()),
193 lastModified(0),
194 current_folder(new Folder(tr("UNTITLED"))),
195 show_windows_policy(ActiveFolder),
196 appStyle(qApp->style()->objectName()),
197 appFont(QFont()),
198 projectname("untitled"),
199 logInfo(QString()),
200 savingTimerId(0),
201 copiedLayer(false),
202 renamedTables(QStringList()),
203 copiedMarkerType(Graph::None),
204 #ifdef SEARCH_FOR_UPDATES
205 autoSearchUpdatesRequest(false),
206 #endif
207 lastCopiedLayer(0),
208 explorerSplitter(new QSplitter(Qt::Horizontal, &explorerWindow)),
209 actionNextWindow(new QAction(QIcon(QPixmap(":/next.xpm")), tr("&Next", "next window"), this)),
210 actionPrevWindow(
211 new QAction(QIcon(QPixmap(":/prev.xpm")), tr("&Previous", "previous window"), this))
212
213 {
214 setAttribute(Qt::WA_DeleteOnClose);
215 QCoreApplication::setAttribute(Qt::AA_DontShowIconsInMenus, false);
216
217 setWindowTitle(tr("SciDAVis - untitled"));
218
219 // Icons
220 IconLoader::init();
221 IconLoader::lumen_ = IconLoader::isLight(palette().color(QPalette::Window));
222
223 initFonts();
224 QPixmapCache::setCacheLimit(20 * QPixmapCache::cacheLimit());
225
226 d_project = new Project();
227 connect(d_project, SIGNAL(aspectAdded(const AbstractAspect *, int)), this,
228 SLOT(handleAspectAdded(const AbstractAspect *, int)));
229 connect(d_project, SIGNAL(aspectAboutToBeRemoved(const AbstractAspect *, int)), this,
230 SLOT(handleAspectAboutToBeRemoved(const AbstractAspect *, int)));
231
232 explorerWindow.setWindowTitle(tr("Project Explorer"));
233 explorerWindow.setObjectName(
234 "explorerWindow"); // this is needed for QMainWindow::restoreState()
235 explorerWindow.setMinimumHeight(150);
236 addDockWidget(Qt::BottomDockWidgetArea, &explorerWindow);
237
238 folders.setObjectName("folders");
239 folders.setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
240 folders.setContextMenuPolicy(Qt::CustomContextMenu);
241
242 folders.setHeaderLabels(QStringList() << tr("Folder") << QString());
243 folders.setRootIsDecorated(true);
244 folders.setColumnWidth(1, 0); // helps autoScroll
245 folders.hideColumn(1); // helps autoScroll
246 #if QT_VERSION >= 0x050000
247 folders.header()->setSectionsClickable(false);
248 folders.header()->setSectionResizeMode(QHeaderView::ResizeToContents);
249 #else
250 folders.header()->setClickable(false);
251 folders.header()->setResizeMode(QHeaderView::ResizeToContents);
252 #endif
253 folders.header()->hide();
254 folders.setSelectionMode(QTreeWidget::SingleSelection);
255
256 connect(&folders, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), this,
257 SLOT(folderItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
258 connect(&folders, SIGNAL(itemRenamed(QTreeWidgetItem *, int, const QString &)), this,
259 SLOT(renameFolder(QTreeWidgetItem *, int, const QString &)));
260 connect(&folders, SIGNAL(customContextMenuRequested(const QPoint &)), this,
261 SLOT(showFolderPopupMenu(const QPoint &)));
262 connect(&folders, SIGNAL(dragItems(QList<QTreeWidgetItem *>)), this,
263 SLOT(dragFolderItems(QList<QTreeWidgetItem *>)));
264 connect(&folders, SIGNAL(dropItems(QTreeWidgetItem *)), this,
265 SLOT(dropFolderItems(QTreeWidgetItem *)));
266 connect(&folders, SIGNAL(renameItem(QTreeWidgetItem *, int)), this,
267 SLOT(startRenameFolder(QTreeWidgetItem *, int)));
268 connect(&folders, SIGNAL(addFolderItem()), this, SLOT(addFolder()));
269 connect(&folders, SIGNAL(deleteSelection()), this, SLOT(deleteSelectedItems()));
270
271 FolderListItem *fli = new FolderListItem(&folders, current_folder);
272 current_folder->setFolderListItem(fli);
273 folders.setCurrentItem(fli);
274 fli->setExpanded(true);
275
276 lv.setObjectName("lv");
277 lv.setRootIsDecorated(false);
278 lv.setContextMenuPolicy(Qt::CustomContextMenu);
279 lv.setHeaderLabels(QStringList()
280 << tr("Name") << tr("Type") << tr("View") << tr("Created") << tr("Label"));
281 lv.header()->setStretchLastSection(true);
282 lv.setMinimumHeight(80);
283 lv.setSelectionMode(QTreeWidget::ExtendedSelection);
284
285 explorerSplitter->addWidget(&folders);
286 explorerSplitter->addWidget(&lv);
287 explorerWindow.setWidget(explorerSplitter);
288 explorerSplitter->setSizes(QList<int>() << 50 << 50);
289 explorerWindow.hide();
290
291 logWindow.setObjectName("logWindow"); // this is needed for QMainWindow::restoreState()
292 logWindow.setWindowTitle(tr("Results Log"));
293 addDockWidget(Qt::TopDockWidgetArea, &logWindow);
294
295 results->setReadOnly(true);
296
297 logWindow.setWidget(results);
298 logWindow.hide();
299
300 #ifdef SCRIPTING_CONSOLE
301 consoleWindow.setObjectName("consoleWindow"); // this is needed for QMainWindow::restoreState()
302 consoleWindow.setWindowTitle(tr("Scripting Console"));
303 addDockWidget(Qt::TopDockWidgetArea, &consoleWindow);
304 console.setReadOnly(true);
305 consoleWindow.setWidget(&console);
306 consoleWindow.hide();
307 #endif
308
309 // Needs to be done after initialization of dock windows,
310 // because we now use QDockWidget::toggleViewAction()
311 createActions();
312 initToolBars();
313 initPlot3DToolBar();
314 initMainMenu();
315
316 d_workspace.setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
317 d_workspace.setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
318 d_workspace.setActivationOrder(QMdiArea::ActivationHistoryOrder);
319 setCentralWidget(&d_workspace);
320 setAcceptDrops(true);
321
322 readSettings();
323 createLanguagesList();
324 insertTranslatedStrings();
325
326 actionNextWindow->setShortcut(tr("F5", "next window shortcut"));
327 connect(actionNextWindow, SIGNAL(triggered()), &d_workspace, SLOT(activateNextSubWindow()));
328
329 actionPrevWindow->setShortcut(tr("F6", "previous window shortcut"));
330 connect(actionPrevWindow, SIGNAL(triggered()), &d_workspace, SLOT(activatePreviousSubWindow()));
331
332 connect(this, SIGNAL(modified()), this, SLOT(modifiedProject()));
333 connect(&d_workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)), this,
334 SLOT(windowActivated(QMdiSubWindow *)));
335 connect(&lv, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this,
336 SLOT(folderItemDoubleClicked(QTreeWidgetItem *, int)));
337 connect(&lv, SIGNAL(customContextMenuRequested(const QPoint &)), this,
338 SLOT(showWindowPopupMenu(const QPoint &)));
339 connect(&lv, SIGNAL(dragItems(QList<QTreeWidgetItem *>)), this,
340 SLOT(dragFolderItems(QList<QTreeWidgetItem *>)));
341 connect(&lv, SIGNAL(dropItems(QTreeWidgetItem *)), this,
342 SLOT(dropFolderItems(QTreeWidgetItem *)));
343 connect(&lv, SIGNAL(renameItem(QTreeWidgetItem *, int)), this,
344 SLOT(startRenameFolder(QTreeWidgetItem *, int)));
345 connect(&lv, SIGNAL(addFolderItem()), this, SLOT(addFolder()));
346 connect(&lv, SIGNAL(deleteSelection()), this, SLOT(deleteSelectedItems()));
347 connect(&lv, SIGNAL(itemRenamed(QTreeWidgetItem *, int, const QString &)), this,
348 SLOT(renameWindow(QTreeWidgetItem *, int, const QString &)));
349 connect(scriptEnv, SIGNAL(error(const QString &, const QString &, int)), this,
350 SLOT(scriptError(const QString &, const QString &, int)));
351 connect(scriptEnv, SIGNAL(print(const QString &)), this, SLOT(scriptPrint(const QString &)));
352
353 #ifdef SEARCH_FOR_UPDATES
354 connect(&http, SIGNAL(finished(QNetworkReply *)), this,
355 SLOT(receivedVersionFile(QNetworkReply *)));
356 #endif
357
358 // this has to be done after connecting scriptEnv
359 scriptEnv->initialize();
360
361 lv.setDragEnabled(true);
362 lv.setAcceptDrops(true);
363 lv.setDefaultDropAction(Qt::MoveAction);
364 folders.setDragEnabled(true);
365 folders.setAcceptDrops(true);
366 folders.setDefaultDropAction(Qt::MoveAction);
367
368 connect(d_project->undoStack(), SIGNAL(canUndoChanged(bool)), actionUndo,
369 SLOT(setEnabled(bool)));
370 connect(d_project->undoStack(), SIGNAL(canRedoChanged(bool)), actionRedo,
371 SLOT(setEnabled(bool)));
372 }
373
initFonts()374 void ApplicationWindow::initFonts()
375 {
376 QString family = appFont.family();
377 int pointSize = appFont.pointSize();
378 tableTextFont = appFont;
379 tableHeaderFont = appFont;
380 plotAxesFont = QFont(family, pointSize, QFont::Bold, false);
381 plotNumbersFont = QFont(family, pointSize);
382 plotLegendFont = appFont;
383 plotTitleFont = QFont(family, pointSize + 2, QFont::Bold, false);
384
385 plot3DAxesFont = QFont(family, pointSize, QFont::Bold, false);
386 plot3DNumbersFont = QFont(family, pointSize);
387 plot3DTitleFont = QFont(family, pointSize + 2, QFont::Bold, false);
388 }
389
applyUserSettings()390 void ApplicationWindow::applyUserSettings()
391 {
392 updateAppFonts();
393 setScriptingLang(defaultScriptingLang);
394
395 d_workspace.setBackground(workspaceColor);
396
397 QPalette cg;
398 cg.setColor(QPalette::Base, QColor(panelsColor));
399 qApp->setPalette(cg);
400
401 cg.setColor(QPalette::Text, QColor(panelsTextColor));
402 cg.setColor(QPalette::WindowText, QColor(panelsTextColor));
403 cg.setColor(QPalette::HighlightedText, QColor(panelsTextColor));
404 lv.setPalette(cg);
405 results->setPalette(cg);
406
407 cg.setColor(QPalette::Text, QColor(Qt::green));
408 cg.setColor(QPalette::HighlightedText, QColor(Qt::darkGreen));
409 cg.setColor(QPalette::Base, QColor(Qt::black));
410 }
411
initToolBars()412 void ApplicationWindow::initToolBars()
413 {
414 setWindowIcon(QIcon(":/appicon"));
415 QPixmap openIcon, saveIcon;
416
417 file_tools = new QToolBar(tr("File"), this);
418 file_tools->setObjectName("file_tools"); // this is needed for QMainWindow::restoreState()
419 file_tools->setIconSize(QSize(22, 22));
420 addToolBar(Qt::TopToolBarArea, file_tools);
421
422 file_tools->addAction(actionNewProject);
423
424 QMenu *menu_new_aspect = new QMenu(this);
425 menu_new_aspect->addAction(actionNewTable);
426 menu_new_aspect->addAction(actionNewMatrix);
427 menu_new_aspect->addAction(actionNewNote);
428 menu_new_aspect->addAction(actionNewGraph);
429 menu_new_aspect->addAction(actionNewFunctionPlot);
430 menu_new_aspect->addAction(actionNewSurfacePlot);
431 QToolButton *btn_new_aspect = new QToolButton(this);
432 btn_new_aspect->setMenu(menu_new_aspect);
433 btn_new_aspect->setPopupMode(QToolButton::InstantPopup);
434 btn_new_aspect->setIcon(QPixmap(":/new_aspect.xpm"));
435 btn_new_aspect->setToolTip(tr("New Aspect"));
436 file_tools->addWidget(btn_new_aspect);
437
438 file_tools->addAction(actionOpen);
439 file_tools->addAction(actionOpenTemplate);
440 file_tools->addAction(actionLoad);
441 file_tools->addAction(actionSaveProject);
442 file_tools->addAction(actionSaveTemplate);
443
444 file_tools->addSeparator();
445
446 file_tools->addAction(actionPrint);
447 file_tools->addAction(actionExportPDF);
448
449 file_tools->addSeparator();
450
451 file_tools->addAction(actionShowExplorer);
452 file_tools->addAction(actionShowLog);
453 file_tools->addAction(locktoolbar);
454
455 edit_tools = new QToolBar(tr("Edit"), this);
456 edit_tools->setObjectName("edit_tools"); // this is needed for QMainWindow::restoreState()
457 edit_tools->setIconSize(QSize(22, 22));
458 addToolBar(edit_tools);
459
460 edit_tools->addAction(actionUndo);
461 edit_tools->addAction(actionRedo);
462 edit_tools->addAction(actionCutSelection);
463 edit_tools->addAction(actionCopySelection);
464 edit_tools->addAction(actionPasteSelection);
465 edit_tools->addAction(actionClearSelection);
466
467 graph_tools = new QToolBar(tr("Graph"), this);
468 graph_tools->setObjectName("graph_tools"); // this is needed for QMainWindow::restoreState()
469 graph_tools->setIconSize(QSize(22, 22));
470 addToolBar(graph_tools);
471
472 dataTools = new QActionGroup(this);
473 dataTools->setExclusive(true);
474
475 btnPointer = new QAction(tr("Disable &Tools"), this);
476 btnPointer->setActionGroup(dataTools);
477 btnPointer->setCheckable(true);
478 btnPointer->setIcon(QIcon(QPixmap(":/pointer.xpm")));
479 btnPointer->setChecked(true);
480 graph_tools->addAction(btnPointer);
481
482 graph_tools->addSeparator();
483
484 QMenu *menu_layers = new QMenu(this);
485 QToolButton *btn_layers = new QToolButton(this);
486 btn_layers->setMenu(menu_layers);
487 btn_layers->setPopupMode(QToolButton::InstantPopup);
488 btn_layers->setIcon(QPixmap(":/arrangeLayers.xpm"));
489 btn_layers->setToolTip(tr("Manage layers"));
490 graph_tools->addWidget(btn_layers);
491
492 menu_layers->addAction(actionAutomaticLayout);
493 menu_layers->addAction(actionAddLayer);
494 menu_layers->addAction(actionDeleteLayer);
495 menu_layers->addAction(actionShowLayerDialog);
496
497 QMenu *menu_curves = new QMenu(this);
498 QToolButton *btn_curves = new QToolButton(this);
499 btn_curves->setMenu(menu_curves);
500 btn_curves->setPopupMode(QToolButton::InstantPopup);
501 btn_curves->setIcon(QPixmap(":/curves.xpm"));
502 btn_curves->setToolTip(tr("Add curves / error bars"));
503 graph_tools->addWidget(btn_curves);
504
505 menu_curves->addAction(actionShowCurvesDialog);
506 menu_curves->addAction(actionAddErrorBars);
507 menu_curves->addAction(actionAddFunctionCurve);
508
509 QMenu *menu_plot_enrichments = new QMenu(this);
510 QToolButton *btn_plot_enrichments = new QToolButton(this);
511 btn_plot_enrichments->setMenu(menu_plot_enrichments);
512 btn_plot_enrichments->setPopupMode(QToolButton::InstantPopup);
513 btn_plot_enrichments->setIcon(QPixmap(":/text.xpm"));
514 btn_plot_enrichments->setToolTip(tr("Enrichments"));
515 graph_tools->addWidget(btn_plot_enrichments);
516
517 actionAddText = new QAction(tr("Add &Text"), this);
518 actionAddText->setShortcut(tr("ALT+T"));
519 actionAddText->setIcon(QIcon(QPixmap(":/text.xpm")));
520 actionAddText->setCheckable(true);
521 connect(actionAddText, SIGNAL(triggered()), this, SLOT(addText()));
522 menu_plot_enrichments->addAction(actionAddText);
523
524 btnArrow = new QAction(tr("Draw &Arrow"), this);
525 btnArrow->setShortcut(tr("CTRL+ALT+A"));
526 btnArrow->setActionGroup(dataTools);
527 btnArrow->setCheckable(true);
528 btnArrow->setIcon(QIcon(QPixmap(":/arrow.xpm")));
529 menu_plot_enrichments->addAction(btnArrow);
530
531 btnLine = new QAction(tr("Draw &Line"), this);
532 btnLine->setShortcut(tr("CTRL+ALT+L"));
533 btnLine->setActionGroup(dataTools);
534 btnLine->setCheckable(true);
535 btnLine->setIcon(QIcon(QPixmap(":/lPlot.xpm")));
536 menu_plot_enrichments->addAction(btnLine);
537
538 menu_plot_enrichments->addAction(actionTimeStamp);
539 menu_plot_enrichments->addAction(actionAddImage);
540 menu_plot_enrichments->addAction(actionNewLegend);
541
542 graph_tools->addSeparator();
543
544 btnZoomIn = new QAction(tr("&Zoom In"), this);
545 btnZoomIn->setShortcut(tr("Ctrl++"));
546 btnZoomIn->setActionGroup(dataTools);
547 btnZoomIn->setCheckable(true);
548 btnZoomIn->setIcon(QIcon(QPixmap(":/zoom.xpm")));
549 graph_tools->addAction(btnZoomIn);
550
551 btnZoomOut = new QAction(tr("&Zoom Out"), this);
552 btnZoomOut->setShortcut(tr("Ctrl+-"));
553 btnZoomOut->setActionGroup(dataTools);
554 btnZoomOut->setCheckable(true);
555 btnZoomOut->setIcon(QIcon(QPixmap(":/zoomOut.xpm")));
556 graph_tools->addAction(btnZoomOut);
557
558 graph_tools->addAction(actionUnzoom);
559
560 graph_tools->addSeparator();
561
562 btnPicker = new QAction(tr("S&creen Reader"), this);
563 btnPicker->setActionGroup(dataTools);
564 btnPicker->setCheckable(true);
565 btnPicker->setIcon(QIcon(QPixmap(":/cursor_16.xpm")));
566 graph_tools->addAction(btnPicker);
567
568 btnCursor = new QAction(tr("&Data Reader"), this);
569 btnCursor->setShortcut(tr("CTRL+D"));
570 btnCursor->setActionGroup(dataTools);
571 btnCursor->setCheckable(true);
572 btnCursor->setIcon(QIcon(QPixmap(":/select.xpm")));
573 graph_tools->addAction(btnCursor);
574
575 btnSelect = new QAction(tr("&Select Data Range"), this);
576 btnSelect->setShortcut(tr("ALT+S"));
577 btnSelect->setActionGroup(dataTools);
578 btnSelect->setCheckable(true);
579 btnSelect->setIcon(QIcon(QPixmap(":/cursors.xpm")));
580 graph_tools->addAction(btnSelect);
581
582 btnMovePoints = new QAction(tr("&Move Data Points..."), this);
583 btnMovePoints->setShortcut(tr("Ctrl+ALT+M"));
584 btnMovePoints->setActionGroup(dataTools);
585 btnMovePoints->setCheckable(true);
586 btnMovePoints->setIcon(QIcon(QPixmap(":/hand.xpm")));
587
588 btnRemovePoints = new QAction(tr("Remove &Bad Data Points..."), this);
589 btnRemovePoints->setShortcut(tr("Alt+B"));
590 btnRemovePoints->setActionGroup(dataTools);
591 btnRemovePoints->setCheckable(true);
592 btnRemovePoints->setIcon(QIcon(QPixmap(":/gomme.xpm")));
593
594 connect(dataTools, SIGNAL(triggered(QAction *)), this, SLOT(pickDataTool(QAction *)));
595
596 plot_tools = new QToolBar(tr("Plot"), this);
597 plot_tools->setObjectName("plot_tools"); // this is needed for QMainWindow::restoreState()
598 plot_tools->setIconSize(QSize(22, 22));
599 addToolBar(Qt::TopToolBarArea, plot_tools);
600
601 QMenu *menu_plot_linespoints = new QMenu(this);
602 QToolButton *btn_plot_linespoints = new QToolButton(this);
603 btn_plot_linespoints->setMenu(menu_plot_linespoints);
604 btn_plot_linespoints->setPopupMode(QToolButton::InstantPopup);
605 btn_plot_linespoints->setIcon(QPixmap(":/lpPlot.xpm"));
606 btn_plot_linespoints->setToolTip(tr("Lines and/or symbols"));
607 plot_tools->addWidget(btn_plot_linespoints);
608 menu_plot_linespoints->addAction(actionPlotL);
609 menu_plot_linespoints->addAction(actionPlotP);
610 menu_plot_linespoints->addAction(actionPlotLP);
611 menu_plot_linespoints->addAction(actionPlotSpline);
612 menu_plot_linespoints->addAction(actionPlotVerticalDropLines);
613 menu_plot_linespoints->addAction(actionPlotHorSteps);
614 menu_plot_linespoints->addAction(actionPlotVertSteps);
615
616 QMenu *menu_plot_bars = new QMenu(this);
617 QToolButton *btn_plot_bars = new QToolButton(this);
618 btn_plot_bars->setMenu(menu_plot_bars);
619 btn_plot_bars->setPopupMode(QToolButton::InstantPopup);
620 btn_plot_bars->setIcon(QPixmap(":/vertBars.xpm"));
621 plot_tools->addWidget(btn_plot_bars);
622 menu_plot_bars->addAction(actionPlotVerticalBars);
623 menu_plot_bars->addAction(actionPlotHorizontalBars);
624
625 plot_tools->addAction(actionPlotArea);
626 plot_tools->addAction(actionPlotPie);
627 plot_tools->addAction(actionPlotHistogram);
628 plot_tools->addAction(actionBoxPlot);
629
630 QMenu *menu_plot_vect = new QMenu(this);
631 QToolButton *btn_plot_vect = new QToolButton(this);
632 btn_plot_vect->setMenu(menu_plot_vect);
633 btn_plot_vect->setPopupMode(QToolButton::InstantPopup);
634 btn_plot_vect->setIcon(QPixmap(":/vectXYXY.xpm"));
635 plot_tools->addWidget(btn_plot_vect);
636 menu_plot_vect->addAction(actionPlotVectXYXY);
637 menu_plot_vect->addAction(actionPlotVectXYAM);
638
639 plot_tools->addSeparator();
640
641 plot_tools->addAction(actionPlot3DRibbon);
642 plot_tools->addAction(actionPlot3DBars);
643 plot_tools->addAction(actionPlot3DScatter);
644 plot_tools->addAction(actionPlot3DTrajectory);
645
646 table_tools = new QToolBar(tr("Table"), this);
647 table_tools->setObjectName("table_tools"); // this is needed for QMainWindow::restoreState()
648 table_tools->setIconSize(QSize(22, 22));
649 addToolBar(Qt::TopToolBarArea, table_tools);
650
651 graph_tools->setEnabled(false);
652 table_tools->setEnabled(false);
653 plot_tools->setEnabled(false);
654
655 d_status_info = new QLabel(this);
656 d_status_info->setFrameStyle(QFrame::Sunken | QFrame::StyledPanel);
657 d_status_info->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
658 d_status_info->setContextMenuPolicy(Qt::CustomContextMenu);
659 connect(d_status_info, SIGNAL(customContextMenuRequested(const QPoint &)), this,
660 SLOT(showStatusBarContextMenu(const QPoint &)));
661
662 statusBar()->addWidget(d_status_info, 1);
663
664 matrix_plot_tools = new QToolBar(tr("Matrix Plot"), this);
665 matrix_plot_tools->setObjectName("matrix_plot_tools");
666 addToolBar(Qt::BottomToolBarArea, matrix_plot_tools);
667
668 matrix_plot_tools->addAction(actionPlot3DWireFrame);
669 matrix_plot_tools->addAction(actionPlot3DHiddenLine);
670
671 matrix_plot_tools->addAction(actionPlot3DPolygons);
672 matrix_plot_tools->addAction(actionPlot3DWireSurface);
673
674 matrix_plot_tools->addSeparator();
675
676 matrix_plot_tools->addAction(actionPlot3DBars);
677 matrix_plot_tools->addAction(actionPlot3DScatter);
678
679 matrix_plot_tools->addSeparator();
680 matrix_plot_tools->addAction(actionColorMap);
681 matrix_plot_tools->addAction(actionContourMap);
682 matrix_plot_tools->addAction(actionGrayMap);
683
684 matrix_plot_tools->setEnabled(false);
685 }
686
lockToolbar(const bool status)687 void ApplicationWindow::lockToolbar(const bool status)
688 {
689 if (status) {
690 file_tools->setMovable(false);
691 edit_tools->setMovable(false);
692 graph_tools->setMovable(false);
693 graph_3D_tools->setMovable(false);
694 plot_tools->setMovable(false);
695 table_tools->setMovable(false);
696 matrix_plot_tools->setMovable(false);
697 locktoolbar->setIcon(QIcon(QPixmap(":/lock.xpm")));
698 } else {
699 file_tools->setMovable(true);
700 edit_tools->setMovable(true);
701 graph_tools->setMovable(true);
702 graph_3D_tools->setMovable(true);
703 plot_tools->setMovable(true);
704 table_tools->setMovable(true);
705 matrix_plot_tools->setMovable(true);
706 locktoolbar->setIcon(QIcon(QPixmap(":/unlock.xpm")));
707 }
708 }
709
insertTranslatedStrings()710 void ApplicationWindow::insertTranslatedStrings()
711 {
712 if (projectname == "untitled")
713 setWindowTitle(tr("SciDAVis - untitled"));
714
715 lv.headerItem()->setText(0, tr("Name"));
716 lv.headerItem()->setText(1, tr("Type"));
717 lv.headerItem()->setText(2, tr("View"));
718 lv.headerItem()->setText(3, tr("Created"));
719 lv.headerItem()->setText(4, tr("Label"));
720
721 explorerWindow.setWindowTitle(tr("Project Explorer"));
722 logWindow.setWindowTitle(tr("Results Log"));
723 #ifdef SCRIPTING_CONSOLE
724 consoleWindow.setWindowTitle(tr("Scripting Console"));
725 #endif
726 table_tools->setWindowTitle(tr("Table"));
727 plot_tools->setWindowTitle(tr("Plot"));
728 graph_tools->setWindowTitle(tr("Graph"));
729 file_tools->setWindowTitle(tr("File"));
730 edit_tools->setWindowTitle(tr("Edit"));
731 matrix_plot_tools->setWindowTitle(tr("Matrix Plot"));
732 graph_3D_tools->setWindowTitle(tr("3D Surface"));
733
734 file->setTitle(tr("&File"));
735 edit->setTitle(tr("&Edit"));
736 view->setTitle(tr("&View"));
737 scriptingMenu->setTitle(tr("Scripting"));
738 graph->setTitle(tr("&Graph"));
739 plot3DMenu->setTitle(tr("3D &Plot"));
740 matrixMenu->setTitle(tr("&Matrix"));
741 tableMenu->setTitle(tr("&Table"));
742 plot2D->setTitle(tr("&Plot"));
743 dataMenu->setTitle(tr("&Analysis"));
744 plotDataMenu->setTitle(tr("&Tools"));
745 calcul->setTitle(tr("&Analysis"));
746 d_quick_fit_menu->setTitle(tr("&Quick Fit"));
747 format->setTitle(tr("For&mat"));
748 windowsMenu->setTitle(tr("&Windows"));
749 help->setTitle(tr("&Help"));
750
751 type->setTitle(tr("&New"));
752 recent->setTitle(tr("&Recent Projects"));
753 exportPlot->setTitle(tr("&Export Graph"));
754
755 specialPlot->setTitle(tr("Special Line/Symb&ol"));
756 stat->setTitle(tr("Statistical &Graphs"));
757 panels->setTitle(tr("Pa&nel"));
758 plot3D->setTitle(tr("3&D Plot"));
759
760 translateMenu->setTitle(tr("&Translate"));
761 smooth->setTitle(tr("&Smooth"));
762 filter->setTitle(tr("&FFT Filter"));
763 decay->setTitle(tr("Fit E&xponential Decay"));
764 multiPeakMenu->setTitle(tr("Fit &Multi-Peak"));
765
766 translateActionsStrings();
767 for (auto w : windowsList())
768 customMenu(w);
769 }
770
initMainMenu()771 void ApplicationWindow::initMainMenu()
772 {
773 file = new QMenu(this);
774 file->setTitle(tr("&File"));
775 file->setFont(appFont);
776
777 type = file->addMenu(tr("&New"));
778 type->setFont(appFont);
779 type->addAction(actionNewProject);
780 type->addAction(actionNewTable);
781 type->addAction(actionNewMatrix);
782 type->addAction(actionNewNote);
783 type->addAction(actionNewGraph);
784 type->addAction(actionNewFunctionPlot);
785 type->addAction(actionNewSurfacePlot);
786
787 file->addAction(actionOpen);
788
789 recent = file->addMenu(tr("&Recent Projects"));
790 recent->setFont(appFont);
791
792 file->addSeparator();
793
794 file->addAction(actionLoadImage);
795 file->addAction(actionImportImage);
796
797 file->addSeparator();
798
799 file->addAction(actionSaveProject);
800 file->addAction(actionSaveProjectAs);
801
802 file->addSeparator();
803 file->addAction(actionOpenTemplate);
804 file->addAction(actionSaveTemplate);
805 file->addSeparator();
806
807 exportPlot = file->addMenu(tr("&Export Graph"));
808 exportPlot->addAction(actionExportGraph);
809 exportPlot->addAction(actionExportAllGraphs);
810
811 file->addAction(actionPrint);
812 file->addAction(actionPrintAllPlots);
813
814 file->addSeparator();
815
816 file->addAction(actionShowExportASCIIDialog);
817 file->addAction(actionLoad);
818
819 file->addSeparator();
820
821 file->addAction(actionCloseAllWindows);
822
823 edit = new QMenu(this);
824 edit->setFont(appFont);
825 edit->setTitle(tr("&Edit"));
826 edit->addAction(actionUndo);
827 edit->addAction(actionRedo);
828
829 edit->addSeparator();
830
831 edit->addAction(actionCutSelection);
832 edit->addAction(actionCopySelection);
833 edit->addAction(actionPasteSelection);
834 edit->addAction(actionClearSelection);
835
836 edit->addSeparator();
837
838 edit->addAction(actionDeleteFitTables);
839 edit->addAction(actionClearLogInfo);
840
841 edit->addSeparator();
842
843 edit->addAction(actionShowConfigureDialog);
844
845 view = new QMenu(this);
846 view->setFont(appFont);
847 view->setTitle(tr("&View"));
848 toolbarsMenu = createToolbarsMenu();
849 if (!toolbarsMenu)
850 toolbarsMenu = new QMenu(this);
851 toolbarsMenu->setTitle(tr("Toolbars"));
852
853 view->addMenu(toolbarsMenu);
854 view->addAction(locktoolbar);
855 view->addSeparator();
856 view->addAction(actionShowPlotWizard);
857 view->addAction(actionShowExplorer);
858 view->addAction(actionShowLog);
859 view->addAction(actionShowHistory);
860 #ifdef SCRIPTING_CONSOLE
861 view->addAction(actionShowConsole);
862 #endif
863
864 graph = new QMenu(this);
865 graph->setFont(appFont);
866 graph->setTitle(tr("&Graph"));
867 graph->addAction(actionShowCurvesDialog);
868 graph->addAction(actionAddErrorBars);
869 graph->addAction(actionAddFunctionCurve);
870
871 graph->addSeparator();
872
873 graph->addAction(actionAddText);
874 graph->addAction(btnArrow);
875 graph->addAction(btnLine);
876 graph->addAction(actionTimeStamp);
877 graph->addAction(actionAddImage);
878 graph->addAction(actionNewLegend);
879
880 graph->addSeparator(); // layers section
881 graph->addAction(actionAutomaticLayout);
882 graph->addAction(actionAddLayer);
883 graph->addAction(actionDeleteLayer);
884 graph->addAction(actionShowLayerDialog);
885
886 plot3DMenu = new QMenu(this);
887 plot3DMenu->setFont(appFont);
888 plot3DMenu->setTitle(tr("3D &Plot"));
889
890 plot3DMenu->addAction(actionPlot3DWireFrame);
891 plot3DMenu->addAction(actionPlot3DHiddenLine);
892
893 plot3DMenu->addAction(actionPlot3DPolygons);
894 plot3DMenu->addAction(actionPlot3DWireSurface);
895
896 plot3DMenu->addSeparator();
897
898 plot3DMenu->addAction(actionPlot3DBars);
899 plot3DMenu->addAction(actionPlot3DScatter);
900
901 plot3DMenu->addSeparator();
902 plot3DMenu->addAction(actionColorMap);
903 plot3DMenu->addAction(actionContourMap);
904 plot3DMenu->addAction(actionGrayMap);
905
906 matrixMenu = new QMenu(this);
907 matrixMenu->setFont(appFont);
908 matrixMenu->setTitle(tr("&Matrix"));
909
910 tableMenu = new QMenu(this);
911 tableMenu->setFont(appFont);
912 tableMenu->setTitle(tr("&Table"));
913
914 initPlotMenu();
915 initTableAnalysisMenu();
916 initPlotDataMenu();
917
918 calcul = new QMenu(this);
919 calcul->setFont(appFont);
920 calcul->setTitle(tr("&Analysis"));
921
922 translateMenu = calcul->addMenu(tr("&Translate"));
923 translateMenu->setFont(appFont);
924 translateMenu->addAction(actionTranslateVert);
925 translateMenu->addAction(actionTranslateHor);
926 calcul->addSeparator();
927
928 calcul->addAction(actionDifferentiate);
929 calcul->addAction(actionShowIntDialog);
930
931 calcul->addSeparator();
932
933 smooth = calcul->addMenu(tr("&Smooth"));
934 smooth->setFont(appFont);
935 smooth->addAction(actionSmoothSavGol);
936 smooth->addAction(actionSmoothAverage);
937 smooth->addAction(actionSmoothFFT);
938
939 filter = calcul->addMenu(tr("&FFT Filter"));
940 filter->setFont(appFont);
941 filter->addAction(actionLowPassFilter);
942 filter->addAction(actionHighPassFilter);
943 filter->addAction(actionBandPassFilter);
944 filter->addAction(actionBandBlockFilter);
945
946 calcul->addSeparator();
947 calcul->addAction(actionInterpolate);
948 calcul->addAction(actionFFT);
949 calcul->addSeparator();
950
951 d_quick_fit_menu = new QMenu(this);
952 d_quick_fit_menu->setTitle(tr("&Quick Fit"));
953
954 d_quick_fit_menu->addAction(actionFitLinear);
955 d_quick_fit_menu->addAction(actionShowFitPolynomDialog);
956
957 d_quick_fit_menu->addSeparator();
958
959 decay = d_quick_fit_menu->addMenu(tr("Fit E&xponential Decay"));
960 decay->setFont(appFont);
961 decay->addAction(actionShowExpDecayDialog);
962 decay->addAction(actionShowTwoExpDecayDialog);
963 decay->addAction(actionShowExpDecay3Dialog);
964
965 d_quick_fit_menu->addAction(actionFitExpGrowth);
966 d_quick_fit_menu->addAction(actionFitSigmoidal);
967 d_quick_fit_menu->addAction(actionFitGauss);
968 d_quick_fit_menu->addAction(actionFitLorentz);
969
970 multiPeakMenu = d_quick_fit_menu->addMenu(tr("Fit &Multi-peak"));
971 multiPeakMenu->setFont(appFont);
972 multiPeakMenu->addAction(actionMultiPeakGauss);
973 multiPeakMenu->addAction(actionMultiPeakLorentz);
974
975 d_quick_fit_menu->addSeparator();
976
977 calcul->addMenu(d_quick_fit_menu);
978 calcul->addAction(actionShowFitDialog);
979
980 format = new QMenu(this);
981 format->setFont(appFont);
982 format->setTitle(tr("For&mat"));
983
984 scriptingMenu = new QMenu(this);
985 scriptingMenu->setFont(appFont);
986 scriptingMenu->setTitle(tr("Scripting"));
987
988 windowsMenu = new QMenu(this);
989 windowsMenu->setFont(appFont);
990 windowsMenu->setTitle(tr("&Windows"));
991 connect(windowsMenu, SIGNAL(aboutToShow()), this, SLOT(windowsMenuAboutToShow()));
992
993 help = new QMenu(this);
994 help->setFont(appFont);
995 help->setTitle(tr("&Help"));
996
997 help->addAction(actionShowHelp);
998 #ifdef DYNAMIC_MANUAL_PATH
999 help->addAction(actionChooseHelpFolder);
1000 #endif
1001 help->addSeparator();
1002 help->addAction(actionHomePage);
1003 #ifdef SEARCH_FOR_UPDATES
1004 help->addAction(actionCheckUpdates);
1005 #endif
1006 #ifdef DOWNLOAD_LINKS
1007 help->addAction(actionDownloadManual);
1008 #endif
1009 help->addSeparator();
1010 help->addAction(actionHelpForums);
1011 help->addAction(actionHelpBugReports);
1012 help->addSeparator();
1013 help->addAction(actionAbout);
1014
1015 disableActions();
1016 }
1017
initPlotDataMenu()1018 void ApplicationWindow::initPlotDataMenu()
1019 {
1020 plotDataMenu = new QMenu(this);
1021 plotDataMenu->setFont(appFont);
1022 plotDataMenu->setTitle(tr("&Tools"));
1023
1024 plotDataMenu->addAction(btnPointer);
1025 plotDataMenu->addAction(btnZoomIn);
1026 plotDataMenu->addAction(btnZoomOut);
1027 plotDataMenu->addAction(actionUnzoom);
1028 plotDataMenu->addSeparator();
1029
1030 plotDataMenu->addAction(btnPicker);
1031 plotDataMenu->addAction(btnCursor);
1032 plotDataMenu->addAction(btnSelect);
1033
1034 plotDataMenu->addSeparator();
1035
1036 plotDataMenu->addAction(btnMovePoints);
1037 plotDataMenu->addAction(btnRemovePoints);
1038 }
1039
initPlotMenu()1040 void ApplicationWindow::initPlotMenu()
1041 {
1042 plot2D = new QMenu(this);
1043 plot2D->setFont(appFont);
1044 plot2D->setTitle(tr("&Plot"));
1045
1046 plot2D->addAction(actionPlotL);
1047 plot2D->addAction(actionPlotP);
1048 plot2D->addAction(actionPlotLP);
1049
1050 specialPlot = plot2D->addMenu(tr("Special Line/Symb&ol"));
1051 specialPlot->setFont(appFont);
1052 specialPlot->addAction(actionPlotVerticalDropLines);
1053 specialPlot->addAction(actionPlotSpline);
1054 specialPlot->addAction(actionPlotVertSteps);
1055 specialPlot->addAction(actionPlotHorSteps);
1056
1057 plot2D->addSeparator();
1058
1059 plot2D->addAction(actionPlotVerticalBars);
1060 plot2D->addAction(actionPlotHorizontalBars);
1061 plot2D->addAction(actionPlotArea);
1062 plot2D->addAction(actionPlotPie);
1063 plot2D->addAction(actionPlotVectXYXY);
1064 plot2D->addAction(actionPlotVectXYAM);
1065
1066 plot2D->addSeparator();
1067
1068 stat = plot2D->addMenu(tr("Statistical &Graphs"));
1069 stat->setFont(appFont);
1070 stat->addAction(actionBoxPlot);
1071 stat->addAction(actionPlotHistogram);
1072 stat->addAction(actionPlotStackedHistograms);
1073
1074 panels = plot2D->addMenu(tr("Pa&nel"));
1075 panels->setFont(appFont);
1076 panels->addAction(actionPlot2VerticalLayers);
1077 panels->addAction(actionPlot2HorizontalLayers);
1078 panels->addAction(actionPlot4Layers);
1079 panels->addAction(actionPlotStackedLayers);
1080
1081 plot2D->addSeparator();
1082
1083 plot3D = plot2D->addMenu(tr("3&D Plot"));
1084 plot3D->setFont(appFont);
1085 plot3D->addAction(actionPlot3DRibbon);
1086 plot3D->addAction(actionPlot3DBars);
1087 plot3D->addAction(actionPlot3DScatter);
1088 plot3D->addAction(actionPlot3DTrajectory);
1089 }
1090
initTableAnalysisMenu()1091 void ApplicationWindow::initTableAnalysisMenu()
1092 {
1093 dataMenu = new QMenu(this);
1094 dataMenu->setFont(appFont);
1095 dataMenu->setTitle(tr("&Analysis"));
1096
1097 dataMenu->addAction(actionShowColStatistics);
1098 dataMenu->addAction(actionShowRowStatistics);
1099
1100 dataMenu->addSeparator();
1101 dataMenu->addAction(actionFFT);
1102 dataMenu->addSeparator();
1103 dataMenu->addAction(actionCorrelate);
1104 dataMenu->addAction(actionAutoCorrelate);
1105 dataMenu->addSeparator();
1106 dataMenu->addAction(actionConvolute);
1107 dataMenu->addAction(actionDeconvolute);
1108
1109 dataMenu->addSeparator();
1110 dataMenu->addAction(actionShowFitDialog);
1111 }
1112
customMenu(MyWidget * w)1113 void ApplicationWindow::customMenu(MyWidget *w)
1114 {
1115 menuBar()->clear();
1116 menuBar()->addMenu(file);
1117 menuBar()->addMenu(edit);
1118 menuBar()->addMenu(view);
1119 menuBar()->addMenu(scriptingMenu);
1120
1121 scriptingMenu->clear();
1122 #ifdef SCRIPTING_DIALOG
1123 scriptingMenu->addAction(actionScriptingLang);
1124 #endif
1125 scriptingMenu->addAction(actionRestartScripting);
1126
1127 // these use the same keyboard shortcut (Ctrl+Return) and should not be enabled at the same time
1128 actionNoteEvaluate->setEnabled(false);
1129
1130 if (w) {
1131 actionPrintAllPlots->setEnabled(projectHas2DPlots());
1132 actionPrint->setEnabled(true);
1133 actionCutSelection->setEnabled(true);
1134 actionCopySelection->setEnabled(true);
1135 actionPasteSelection->setEnabled(true);
1136 actionClearSelection->setEnabled(true);
1137 actionSaveTemplate->setEnabled(true);
1138
1139 if (w->inherits("MultiLayer")) {
1140 menuBar()->addMenu(graph);
1141 menuBar()->addMenu(plotDataMenu);
1142 menuBar()->addMenu(calcul);
1143 menuBar()->addMenu(format);
1144
1145 exportPlot->setEnabled(true);
1146 actionShowExportASCIIDialog->setEnabled(false);
1147 // file->setItemEnabled (closeID,true);
1148
1149 format->clear();
1150 format->addAction(actionShowPlotDialog);
1151 format->addSeparator();
1152 format->addAction(actionShowScaleDialog);
1153 format->addAction(actionShowAxisDialog);
1154 actionShowAxisDialog->setEnabled(true);
1155 format->addSeparator();
1156 format->addAction(actionShowGridDialog);
1157 format->addAction(actionShowTitleDialog);
1158 } else if (w->inherits("Graph3D")) {
1159 disableActions();
1160
1161 menuBar()->addMenu(format);
1162
1163 actionPrint->setEnabled(true);
1164 actionSaveTemplate->setEnabled(true);
1165 exportPlot->setEnabled(true);
1166 // file->setItemEnabled (closeID,true);
1167
1168 format->clear();
1169 format->addAction(actionShowPlotDialog);
1170 format->addAction(actionShowScaleDialog);
1171 format->addAction(actionShowAxisDialog);
1172 format->addAction(actionShowTitleDialog);
1173 if (((Graph3D *)w)->coordStyle() == Qwt3D::NOCOORD)
1174 actionShowAxisDialog->setEnabled(false);
1175 } else if (w->inherits("Table")) {
1176 menuBar()->addMenu(plot2D);
1177 menuBar()->addMenu(dataMenu);
1178
1179 actionShowExportASCIIDialog->setEnabled(true);
1180 exportPlot->setEnabled(false);
1181 // file->setItemEnabled (closeID,true);
1182
1183 tableMenu->clear();
1184 static_cast<Table *>(w)->d_future_table->fillProjectMenu(tableMenu);
1185 tableMenu->addSeparator();
1186 tableMenu->addAction(actionShowExportASCIIDialog);
1187 tableMenu->addSeparator();
1188 tableMenu->addAction(actionConvertTable);
1189 menuBar()->addMenu(tableMenu);
1190 } else if (w->inherits("Matrix")) {
1191 menuBar()->addMenu(plot3DMenu);
1192
1193 matrixMenu->clear();
1194 static_cast<Matrix *>(w)->d_future_matrix->fillProjectMenu(matrixMenu);
1195 matrixMenu->addSeparator();
1196 matrixMenu->addAction(actionInvertMatrix);
1197 matrixMenu->addAction(actionMatrixDeterminant);
1198 matrixMenu->addSeparator();
1199 matrixMenu->addAction(actionConvertMatrix);
1200 menuBar()->addMenu(matrixMenu);
1201 } else if (w->inherits("Note")) {
1202 actionSaveTemplate->setEnabled(false);
1203 actionNoteEvaluate->setEnabled(true);
1204 scriptingMenu->addSeparator();
1205 scriptingMenu->addAction(actionNoteExecute);
1206 scriptingMenu->addAction(actionNoteExecuteAll);
1207 scriptingMenu->addAction(actionNoteEvaluate);
1208
1209 actionNoteExecute->disconnect(SIGNAL(triggered()));
1210 actionNoteExecuteAll->disconnect(SIGNAL(triggered()));
1211 actionNoteEvaluate->disconnect(SIGNAL(triggered()));
1212 connect(actionNoteExecute, SIGNAL(triggered()), w, SLOT(execute()));
1213 connect(actionNoteExecuteAll, SIGNAL(triggered()), w, SLOT(executeAll()));
1214 connect(actionNoteEvaluate, SIGNAL(triggered()), w, SLOT(evaluate()));
1215 } else
1216 disableActions();
1217
1218 menuBar()->addMenu(windowsMenu);
1219 } else
1220 disableActions();
1221
1222 menuBar()->addMenu(help);
1223 }
1224
disableActions()1225 void ApplicationWindow::disableActions()
1226 {
1227 actionSaveTemplate->setEnabled(false);
1228 actionPrintAllPlots->setEnabled(false);
1229 actionPrint->setEnabled(false);
1230 actionShowExportASCIIDialog->setEnabled(false);
1231 exportPlot->setEnabled(false);
1232 // file->setItemEnabled (closeID,false);
1233
1234 actionUndo->setEnabled(false);
1235 actionRedo->setEnabled(false);
1236
1237 actionCutSelection->setEnabled(false);
1238 actionCopySelection->setEnabled(false);
1239 actionPasteSelection->setEnabled(false);
1240 actionClearSelection->setEnabled(false);
1241 }
1242
customToolBars(MyWidget * w)1243 void ApplicationWindow::customToolBars(MyWidget *w)
1244 {
1245 if (w) {
1246 if (!projectHas3DPlots())
1247 graph_3D_tools->setEnabled(false);
1248 if (!projectHas2DPlots())
1249 graph_tools->setEnabled(false);
1250 if (!projectHasMatrices())
1251 matrix_plot_tools->setEnabled(false);
1252 if (tableWindows().count() <= 0) {
1253 table_tools->setEnabled(false);
1254 plot_tools->setEnabled(false);
1255 }
1256
1257 if (w->inherits("MultiLayer")) {
1258 graph_tools->setEnabled(true);
1259 graph_3D_tools->setEnabled(false);
1260 table_tools->setEnabled(false);
1261 matrix_plot_tools->setEnabled(false);
1262
1263 Graph *g = static_cast<MultiLayer *>(w)->activeGraph();
1264 if (g) {
1265 dataTools->blockSignals(true);
1266 if (g->rangeSelectorsEnabled())
1267 btnSelect->setChecked(true);
1268 else if (g->zoomOn())
1269 btnZoomIn->setChecked(true);
1270 else if (g->drawArrow())
1271 btnArrow->setChecked(true);
1272 else if (g->drawLineActive())
1273 btnLine->setChecked(true);
1274 else if (g->activeTool() == 0)
1275 btnPointer->setChecked(true);
1276 else
1277 switch (g->activeTool()->rtti()) {
1278 case PlotToolInterface::DataPicker:
1279 switch (static_cast<DataPickerTool *>(g->activeTool())->mode()) {
1280 case DataPickerTool::Display:
1281 btnCursor->setChecked(true);
1282 break;
1283 case DataPickerTool::Move:
1284 btnMovePoints->setChecked(true);
1285 break;
1286 case DataPickerTool::Remove:
1287 btnRemovePoints->setChecked(true);
1288 break;
1289 }
1290 break;
1291 case PlotToolInterface::ScreenPicker:
1292 btnPicker->setChecked(true);
1293 break;
1294 default:
1295 btnPointer->setChecked(true);
1296 break;
1297 }
1298 dataTools->blockSignals(false);
1299 }
1300 if (g && g->curves() > 0) {
1301 plot_tools->setEnabled(true);
1302 QwtPlotCurve *c = g->curve(g->curves() - 1);
1303 // plot tools managed by d_plot_mapper
1304 for (int i = 0; i <= (int)Graph::VerticalSteps; i++) {
1305 QAction *a = static_cast<QAction *>(d_plot_mapper->mapping(i));
1306 if (a)
1307 a->setEnabled(Graph::canConvertTo(c, (Graph::CurveType)i));
1308 }
1309 // others
1310 actionPlotPie->setEnabled(Graph::canConvertTo(c, Graph::Pie));
1311 actionPlotVectXYAM->setEnabled(Graph::canConvertTo(c, Graph::VectXYAM));
1312 actionPlotVectXYXY->setEnabled(Graph::canConvertTo(c, Graph::VectXYXY));
1313 actionBoxPlot->setEnabled(Graph::canConvertTo(c, Graph::Box));
1314 // 3D plots
1315 actionPlot3DRibbon->setEnabled(false);
1316 actionPlot3DScatter->setEnabled(false);
1317 actionPlot3DTrajectory->setEnabled(false);
1318 actionPlot3DBars->setEnabled(false);
1319 } else
1320 plot_tools->setEnabled(false);
1321 } else if (w->inherits("Table")) {
1322 table_tools->clear();
1323 static_cast<Table *>(w)->d_future_table->fillProjectToolBar(table_tools);
1324 table_tools->setEnabled(true);
1325
1326 graph_tools->setEnabled(false);
1327 graph_3D_tools->setEnabled(false);
1328 matrix_plot_tools->setEnabled(false);
1329
1330 plot_tools->setEnabled(true);
1331 // plot tools managed by d_plot_mapper
1332 for (int i = 0; i <= (int)Graph::VerticalSteps; i++) {
1333 QAction *a = static_cast<QAction *>(d_plot_mapper->mapping(i));
1334 if (a)
1335 a->setEnabled(true);
1336 }
1337 // others
1338 actionPlotPie->setEnabled(true);
1339 actionPlotVectXYAM->setEnabled(true);
1340 actionPlotVectXYXY->setEnabled(true);
1341 actionBoxPlot->setEnabled(true);
1342 // 3D plots
1343 actionPlot3DRibbon->setEnabled(true);
1344 actionPlot3DScatter->setEnabled(true);
1345 actionPlot3DTrajectory->setEnabled(true);
1346 actionPlot3DBars->setEnabled(true);
1347 } else if (w->inherits("Matrix")) {
1348 graph_tools->setEnabled(false);
1349 graph_3D_tools->setEnabled(false);
1350 table_tools->setEnabled(false);
1351 plot_tools->setEnabled(false);
1352 matrix_plot_tools->setEnabled(true);
1353 } else if (w->inherits("Graph3D")) {
1354 graph_tools->setEnabled(false);
1355 table_tools->setEnabled(false);
1356 plot_tools->setEnabled(false);
1357 matrix_plot_tools->setEnabled(false);
1358
1359 Graph3D *plot = (Graph3D *)w;
1360 if (plot->plotStyle() == Qwt3D::NOPLOT)
1361 graph_3D_tools->setEnabled(false);
1362 else
1363 graph_3D_tools->setEnabled(true);
1364
1365 custom3DActions(w);
1366 } else if (w->inherits("Note")) {
1367 graph_tools->setEnabled(false);
1368 graph_3D_tools->setEnabled(false);
1369 table_tools->setEnabled(false);
1370 plot_tools->setEnabled(false);
1371 matrix_plot_tools->setEnabled(false);
1372 }
1373
1374 } else {
1375 graph_tools->setEnabled(false);
1376 table_tools->setEnabled(false);
1377 plot_tools->setEnabled(false);
1378 graph_3D_tools->setEnabled(false);
1379 matrix_plot_tools->setEnabled(false);
1380 }
1381 }
1382
plot3DRibbon()1383 void ApplicationWindow::plot3DRibbon()
1384 {
1385 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("Table"))
1386 return;
1387
1388 Table *table = static_cast<Table *>(d_workspace.activeSubWindow());
1389 if (table->selectedColumns().count() == 1) {
1390 if (!validFor3DPlot(table))
1391 return;
1392 dataPlot3D(table, table->colName(table->firstSelectedColumn()));
1393 } else
1394 QMessageBox::warning(this, tr("Plot error"),
1395 tr("You must select exactly one column for plotting!"));
1396 }
1397
plot3DWireframe()1398 void ApplicationWindow::plot3DWireframe()
1399 {
1400 plot3DMatrix(Qwt3D::WIREFRAME);
1401 }
1402
plot3DHiddenLine()1403 void ApplicationWindow::plot3DHiddenLine()
1404 {
1405 plot3DMatrix(Qwt3D::HIDDENLINE);
1406 }
1407
plot3DPolygons()1408 void ApplicationWindow::plot3DPolygons()
1409 {
1410 plot3DMatrix(Qwt3D::FILLED);
1411 }
1412
plot3DWireSurface()1413 void ApplicationWindow::plot3DWireSurface()
1414 {
1415 plot3DMatrix(Qwt3D::FILLEDMESH);
1416 }
1417
plot3DBars()1418 void ApplicationWindow::plot3DBars()
1419 {
1420 MyWidget *w = (MyWidget *)d_workspace.activeSubWindow();
1421 if (!w)
1422 return;
1423
1424 if (w->inherits("Table")) {
1425 Table *table = static_cast<Table *>(w);
1426
1427 if (table->selectedColumns().count() == 1) {
1428 if (!validFor3DPlot(table))
1429 return;
1430 dataPlotXYZ(table, table->colName(table->firstSelectedColumn()), Graph3D::Bars);
1431 } else
1432 QMessageBox::warning(this, tr("Plot error"),
1433 tr("You must select exactly one column for plotting!"));
1434 } else if (w->inherits("Matrix"))
1435 plot3DMatrix(Qwt3D::USER);
1436 }
1437
plot3DScatter()1438 void ApplicationWindow::plot3DScatter()
1439 {
1440 MyWidget *w = (MyWidget *)d_workspace.activeSubWindow();
1441 if (!w)
1442 return;
1443
1444 if (w->inherits("Table")) {
1445 Table *table = static_cast<Table *>(w);
1446
1447 if (table->selectedColumns().count() == 1) {
1448 if (!validFor3DPlot(table))
1449 return;
1450 dataPlotXYZ(table, table->colName(table->firstSelectedColumn()), Graph3D::Scatter);
1451 } else
1452 QMessageBox::warning(this, tr("Plot error"),
1453 tr("You must select exactly one column for plotting!"));
1454 } else if (w->inherits("Matrix"))
1455 plot3DMatrix(Qwt3D::POINTS);
1456 }
1457
plot3DTrajectory()1458 void ApplicationWindow::plot3DTrajectory()
1459 {
1460 MyWidget *w = (MyWidget *)d_workspace.activeSubWindow();
1461 if (!w)
1462 return;
1463
1464 if (w->inherits("Table")) {
1465 Table *table = static_cast<Table *>(w);
1466
1467 if (table->selectedColumns().count() == 1) {
1468 if (!validFor3DPlot(table))
1469 return;
1470 dataPlotXYZ(table, table->colName(table->firstSelectedColumn()), Graph3D::Trajectory);
1471 } else
1472 QMessageBox::warning(this, tr("Plot error"),
1473 tr("You must select exactly one column for plotting!"));
1474 }
1475 }
1476
plotPie()1477 void ApplicationWindow::plotPie()
1478 {
1479 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("Table"))
1480 return;
1481
1482 Table *table = static_cast<Table *>(d_workspace.activeSubWindow());
1483
1484 if (table->selectedColumns().count() != 1) {
1485 QMessageBox::warning(this, tr("Plot error"),
1486 tr("You must select exactly one column for plotting!"));
1487 return;
1488 }
1489 if (table->noXColumn()) {
1490 QMessageBox::critical(0, tr("Error"),
1491 tr("Please set a default X column for this table, first!"));
1492 return;
1493 }
1494
1495 QStringList s = table->selectedColumns();
1496 if (s.count() > 0) {
1497 multilayerPlot(table, s, Graph::Pie, table->firstSelectedRow(), table->lastSelectedRow());
1498 } else
1499 QMessageBox::warning(this, tr("Error"), tr("Please select a column to plot!"));
1500 }
1501
plotVectXYXY()1502 void ApplicationWindow::plotVectXYXY()
1503 {
1504 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("Table"))
1505 return;
1506
1507 Table *table = static_cast<Table *>(d_workspace.activeSubWindow());
1508
1509 if (!validFor2DPlot(table, Graph::VectXYXY))
1510 return;
1511
1512 QStringList s = table->selectedColumns();
1513 if (s.count() == 4) {
1514 multilayerPlot(table, s, Graph::VectXYXY, table->firstSelectedRow(),
1515 table->lastSelectedRow());
1516 } else
1517 QMessageBox::warning(this, tr("Error"),
1518 tr("Please select four columns for this operation!"));
1519 }
1520
plotVectXYAM()1521 void ApplicationWindow::plotVectXYAM()
1522 {
1523 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("Table"))
1524 return;
1525
1526 Table *table = static_cast<Table *>(d_workspace.activeSubWindow());
1527
1528 if (!validFor2DPlot(table, Graph::VectXYAM))
1529 return;
1530
1531 QStringList s = table->selectedColumns();
1532 if (s.count() == 4) {
1533 multilayerPlot(table, s, Graph::VectXYAM, table->firstSelectedRow(),
1534 table->lastSelectedRow());
1535 } else
1536 QMessageBox::warning(this, tr("Error"),
1537 tr("Please select four columns for this operation!"));
1538 }
1539
renameListViewItem(const QString & oldName,const QString & newName)1540 void ApplicationWindow::renameListViewItem(const QString &oldName, const QString &newName)
1541 {
1542 QTreeWidgetItem *it = lv.findItems(oldName, Qt::MatchExactly | Qt::MatchCaseSensitive).value(0);
1543 if (it)
1544 it->setText(0, newName);
1545 }
1546
setListViewLabel(const QString & caption,const QString & label)1547 void ApplicationWindow::setListViewLabel(const QString &caption, const QString &label)
1548 {
1549 QTreeWidgetItem *it = lv.findItems(caption, Qt::MatchExactly | Qt::MatchCaseSensitive).value(0);
1550 if (it)
1551 it->setText(4, label);
1552 }
1553
setListViewDate(const QString & caption,const QString & date)1554 void ApplicationWindow::setListViewDate(const QString &caption, const QString &date)
1555 {
1556 QTreeWidgetItem *it = lv.findItems(caption, Qt::MatchExactly | Qt::MatchCaseSensitive).value(0);
1557 if (it)
1558 it->setText(3, date);
1559 }
1560
setListView(const QString & caption,const QString & view)1561 void ApplicationWindow::setListView(const QString &caption, const QString &view)
1562 {
1563 QTreeWidgetItem *it = lv.findItems(caption, Qt::MatchExactly | Qt::MatchCaseSensitive).value(0);
1564 if (it)
1565 it->setText(2, view);
1566 }
1567
updateTableNames(const QString & oldName,const QString & newName)1568 void ApplicationWindow::updateTableNames(const QString &oldName, const QString &newName)
1569 {
1570 QList<MyWidget *> windows = windowsList();
1571 foreach (MyWidget *w, windows) {
1572 if (w->inherits("MultiLayer")) {
1573 QWidgetList gr_lst = ((MultiLayer *)w)->graphPtrs();
1574 foreach (QWidget *widget, gr_lst)
1575 ((Graph *)widget)->updateCurveNames(oldName, newName);
1576 } else if (w->inherits("Graph3D")) {
1577 QString name = ((Graph3D *)w)->formula();
1578 if (name.contains(oldName, Qt::CaseSensitive)) {
1579 name.replace(oldName, newName);
1580 ((Graph3D *)w)->setPlotAssociation(name);
1581 }
1582 }
1583 }
1584 }
1585
updateColNames(const QString & oldName,const QString & newName)1586 void ApplicationWindow::updateColNames(const QString &oldName, const QString &newName)
1587 {
1588 QList<MyWidget *> windows = windowsList();
1589 foreach (MyWidget *w, windows) {
1590 if (w->inherits("MultiLayer")) {
1591 QWidgetList gr_lst = ((MultiLayer *)w)->graphPtrs();
1592 foreach (QWidget *widget, gr_lst)
1593 ((Graph *)widget)->updateCurveNames(oldName, newName, false);
1594 } else if (w->inherits("Graph3D")) {
1595 QString name = ((Graph3D *)w)->formula();
1596 if (name.contains(oldName)) {
1597 name.replace(oldName, newName);
1598 ((Graph3D *)w)->setPlotAssociation(name);
1599 }
1600 }
1601 }
1602 }
1603
changeMatrixName(const QString & oldName,const QString & newName)1604 void ApplicationWindow::changeMatrixName(const QString &oldName, const QString &newName)
1605 {
1606 QList<MyWidget *> lst = windowsList();
1607 foreach (MyWidget *w, lst) {
1608 if (w->inherits("Graph3D")) {
1609 QString s = ((Graph3D *)w)->formula();
1610 if (s.contains(oldName)) {
1611 s.replace(oldName, newName);
1612 ((Graph3D *)w)->setPlotAssociation(s);
1613 }
1614 } else if (w->inherits("MultiLayer")) {
1615 QWidgetList graphsList = ((MultiLayer *)w)->graphPtrs();
1616 foreach (QWidget *gr_widget, graphsList) {
1617 Graph *g = (Graph *)gr_widget;
1618 for (int i = 0; i < g->curves(); i++) {
1619 QwtPlotItem *sp = (QwtPlotItem *)g->plotItem(i);
1620 if (sp && sp->rtti() == QwtPlotItem::Rtti_PlotSpectrogram
1621 && sp->title().text() == oldName)
1622 sp->setTitle(newName);
1623 }
1624 }
1625 }
1626 }
1627 }
1628
remove3DMatrixPlots(Matrix * m)1629 void ApplicationWindow::remove3DMatrixPlots(Matrix *m)
1630 {
1631 if (!m)
1632 return;
1633
1634 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1635
1636 QList<MyWidget *> windows = windowsList();
1637 foreach (MyWidget *w, windows) {
1638 if (w->inherits("Graph3D") && ((Graph3D *)w)->matrix() == m)
1639 ((Graph3D *)w)->clearData();
1640 else if (w->inherits("MultiLayer")) {
1641 QWidgetList graphsList = ((MultiLayer *)w)->graphPtrs();
1642 for (int j = 0; j < (int)graphsList.count(); j++) {
1643 Graph *g = (Graph *)graphsList.at(j);
1644 for (int i = 0; i < g->curves(); i++) {
1645 Spectrogram *sp = (Spectrogram *)g->plotItem(i);
1646 if (sp && sp->rtti() == QwtPlotItem::Rtti_PlotSpectrogram && sp->matrix() == m)
1647 g->removeCurve(i);
1648 }
1649 }
1650 }
1651 }
1652 QApplication::restoreOverrideCursor();
1653 }
1654
updateMatrixPlots(MyWidget * window)1655 void ApplicationWindow::updateMatrixPlots(MyWidget *window)
1656 {
1657 Matrix *m = (Matrix *)window;
1658 if (!m)
1659 return;
1660
1661 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1662
1663 QList<MyWidget *> windows = windowsList();
1664 foreach (MyWidget *w, windows) {
1665 if (w->inherits("Graph3D") && ((Graph3D *)w)->matrix() == m)
1666 ((Graph3D *)w)->updateMatrixData(m);
1667 else if (w->inherits("MultiLayer")) {
1668 QWidgetList graphsList = ((MultiLayer *)w)->graphPtrs();
1669 for (int j = 0; j < (int)graphsList.count(); j++) {
1670 Graph *g = (Graph *)graphsList.at(j);
1671 for (int i = 0; i < g->curves(); i++) {
1672 Spectrogram *sp = (Spectrogram *)g->plotItem(i);
1673 if (sp && sp->rtti() == QwtPlotItem::Rtti_PlotSpectrogram && sp->matrix() == m)
1674 sp->updateData(m);
1675 }
1676 }
1677 }
1678 }
1679
1680 QApplication::restoreOverrideCursor();
1681 }
1682
add3DData()1683 void ApplicationWindow::add3DData()
1684 {
1685 if (tableWindows().count() <= 0) {
1686 QMessageBox::warning(this, tr("Warning"),
1687 tr("<h4>There are no tables available in this project.</h4>"
1688 "<p><h4>Please create a table and try again!</h4>"));
1689 return;
1690 }
1691
1692 // TODO: string list -> Column * list
1693 QStringList zColumns = columnsList(SciDAVis::Z);
1694 if ((int)zColumns.count() <= 0) {
1695 QMessageBox::critical(this, tr("Warning"),
1696 tr("There are no available columns with plot designation set to Z!"));
1697 return;
1698 }
1699
1700 DataSetDialog *ad = new DataSetDialog(tr("Column") + " : ", this);
1701 ad->setAttribute(Qt::WA_DeleteOnClose);
1702 connect(ad, SIGNAL(options(const QString &)), this, SLOT(insertNew3DData(const QString &)));
1703 ad->setWindowTitle(tr("Choose data set"));
1704 ad->setCurveNames(zColumns);
1705 ad->exec();
1706 }
1707
change3DData()1708 void ApplicationWindow::change3DData()
1709 {
1710 DataSetDialog *ad = new DataSetDialog(tr("Column") + " : ", this);
1711 ad->setAttribute(Qt::WA_DeleteOnClose);
1712 connect(ad, SIGNAL(options(const QString &)), this, SLOT(change3DData(const QString &)));
1713
1714 ad->setWindowTitle(tr("Choose data set"));
1715 // TODO: string list -> Column * list
1716 ad->setCurveNames(columnsList(SciDAVis::Z));
1717 ad->exec();
1718 }
1719
change3DMatrix()1720 void ApplicationWindow::change3DMatrix()
1721 {
1722 DataSetDialog *ad = new DataSetDialog(tr("Matrix") + " : ", this);
1723 ad->setAttribute(Qt::WA_DeleteOnClose);
1724 connect(ad, SIGNAL(options(const QString &)), this, SLOT(change3DMatrix(const QString &)));
1725
1726 ad->setWindowTitle(tr("Choose matrix to plot"));
1727 ad->setCurveNames(matrixNames());
1728
1729 Graph3D *g = (Graph3D *)d_workspace.activeSubWindow();
1730 if (g && g->matrix())
1731 ad->setCurentDataSet(g->matrix()->name());
1732 ad->exec();
1733 }
1734
change3DMatrix(const QString & matrix_name)1735 void ApplicationWindow::change3DMatrix(const QString &matrix_name)
1736 {
1737 if (d_workspace.activeSubWindow() && d_workspace.activeSubWindow()->inherits("Graph3D")) {
1738 Graph3D *g = (Graph3D *)d_workspace.activeSubWindow();
1739 Matrix *m = matrix(matrix_name);
1740 if (m && g)
1741 g->changeMatrix(m);
1742
1743 emit modified();
1744 }
1745 }
1746
add3DMatrixPlot()1747 void ApplicationWindow::add3DMatrixPlot()
1748 {
1749 QStringList matrices = matrixNames();
1750 if ((int)matrices.count() <= 0) {
1751 QMessageBox::warning(this, tr("Warning"),
1752 tr("<h4>There are no matrices available in this project.</h4>"
1753 "<p><h4>Please create a matrix and try again!</h4>"));
1754 return;
1755 }
1756
1757 DataSetDialog *ad = new DataSetDialog(tr("Matrix") + " :", this);
1758 ad->setAttribute(Qt::WA_DeleteOnClose);
1759 connect(ad, SIGNAL(options(const QString &)), this, SLOT(insert3DMatrixPlot(const QString &)));
1760
1761 ad->setWindowTitle(tr("Choose matrix to plot"));
1762 ad->setCurveNames(matrices);
1763 ad->exec();
1764 }
1765
insert3DMatrixPlot(const QString & matrix_name)1766 void ApplicationWindow::insert3DMatrixPlot(const QString &matrix_name)
1767 {
1768 if (d_workspace.activeSubWindow() && d_workspace.activeSubWindow()->inherits("Graph3D")) {
1769 ((Graph3D *)d_workspace.activeSubWindow())->addMatrixData(matrix(matrix_name));
1770 emit modified();
1771 }
1772 }
1773
insertNew3DData(const QString & colName)1774 void ApplicationWindow::insertNew3DData(const QString &colName)
1775 {
1776 if (d_workspace.activeSubWindow() && d_workspace.activeSubWindow()->inherits("Graph3D")) {
1777 ((Graph3D *)d_workspace.activeSubWindow())->insertNewData(table(colName), colName);
1778 emit modified();
1779 }
1780 }
1781
change3DData(const QString & colName)1782 void ApplicationWindow::change3DData(const QString &colName)
1783 {
1784 if (d_workspace.activeSubWindow() && d_workspace.activeSubWindow()->inherits("Graph3D")) {
1785 ((Graph3D *)d_workspace.activeSubWindow())->changeDataColumn(table(colName), colName);
1786 emit modified();
1787 }
1788 }
1789
editSurfacePlot()1790 void ApplicationWindow::editSurfacePlot()
1791 {
1792 if (d_workspace.activeSubWindow() && d_workspace.activeSubWindow()->inherits("Graph3D")) {
1793 Graph3D *g = (Graph3D *)d_workspace.activeSubWindow();
1794
1795 SurfaceDialog *sd = new SurfaceDialog(this);
1796 sd->setAttribute(Qt::WA_DeleteOnClose);
1797 connect(sd,
1798 SIGNAL(options(const QString &, double, double, double, double, double, double)), g,
1799 SLOT(insertFunction(const QString &, double, double, double, double, double,
1800 double)));
1801 connect(sd, SIGNAL(clearFunctionsList()), this, SLOT(clearSurfaceFunctionsList()));
1802
1803 sd->insertFunctionsList(surfaceFunc);
1804 if (g->hasData()) {
1805 sd->setFunction(g->formula());
1806 sd->setLimits(g->xStart(), g->xStop(), g->yStart(), g->yStop(), g->zStart(),
1807 g->zStop());
1808 }
1809 sd->exec();
1810 }
1811 }
1812
newSurfacePlot()1813 void ApplicationWindow::newSurfacePlot()
1814 {
1815 SurfaceDialog *sd = new SurfaceDialog(this);
1816 sd->setAttribute(Qt::WA_DeleteOnClose);
1817 connect(sd, SIGNAL(options(const QString &, double, double, double, double, double, double)),
1818 this, SLOT(newPlot3D(const QString &, double, double, double, double, double, double)));
1819 connect(sd, SIGNAL(clearFunctionsList()), this, SLOT(clearSurfaceFunctionsList()));
1820
1821 sd->insertFunctionsList(surfaceFunc);
1822 sd->exec();
1823 }
1824
newPlot3D(const QString & formula,double xl,double xr,double yl,double yr,double zl,double zr)1825 Graph3D *ApplicationWindow::newPlot3D(const QString &formula, double xl, double xr, double yl,
1826 double yr, double zl, double zr)
1827 {
1828 QString label = generateUniqueName(tr("Graph"));
1829
1830 Graph3D *plot = new Graph3D("", &d_workspace, 0);
1831 plot->setAttribute(Qt::WA_DeleteOnClose);
1832 plot->addFunction(formula, xl, xr, yl, yr, zl, zr);
1833 plot->resize(500, 400);
1834 plot->setWindowTitle(label);
1835 plot->setName(label);
1836 customPlot3D(plot);
1837 plot->update();
1838
1839 initPlot3D(plot);
1840
1841 emit modified();
1842 return plot;
1843 }
1844
updateSurfaceFuncList(const QString & s)1845 void ApplicationWindow::updateSurfaceFuncList(const QString &s)
1846 {
1847 surfaceFunc.removeAll(s);
1848 surfaceFunc.push_front(s);
1849 while ((int)surfaceFunc.size() > 10)
1850 surfaceFunc.pop_back();
1851 }
1852
newPlot3D(const QString & caption,const QString & formula,double xl,double xr,double yl,double yr,double zl,double zr)1853 Graph3D *ApplicationWindow::newPlot3D(const QString &caption, const QString &formula, double xl,
1854 double xr, double yl, double yr, double zl, double zr)
1855 {
1856 Graph3D *plot = new Graph3D("", &d_workspace, 0);
1857 plot->setAttribute(Qt::WA_DeleteOnClose);
1858 plot->addFunction(formula, xl, xr, yl, yr, zl, zr);
1859 plot->update();
1860
1861 QString label = caption;
1862 while (alreadyUsedName(label))
1863 label = generateUniqueName(tr("Graph"));
1864
1865 plot->setWindowTitle(label);
1866 plot->setName(label);
1867 initPlot3D(plot);
1868 return plot;
1869 }
1870
dataPlot3D(Table * table,const QString & colName)1871 Graph3D *ApplicationWindow::dataPlot3D(Table *table, const QString &colName)
1872 {
1873 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1874
1875 QString label = generateUniqueName(tr("Graph"));
1876 Graph3D *plot = new Graph3D("", &d_workspace, 0);
1877 plot->setAttribute(Qt::WA_DeleteOnClose);
1878 plot->addData(table, colName);
1879 plot->resize(500, 400);
1880 plot->setWindowTitle(label);
1881 plot->setName(label);
1882
1883 customPlot3D(plot);
1884 plot->update();
1885 initPlot3D(plot);
1886
1887 emit modified();
1888 QApplication::restoreOverrideCursor();
1889 return plot;
1890 }
1891
dataPlot3D(const QString & caption,const QString & formula,double xl,double xr,double yl,double yr,double zl,double zr)1892 Graph3D *ApplicationWindow::dataPlot3D(const QString &caption, const QString &formula, double xl,
1893 double xr, double yl, double yr, double zl, double zr)
1894 {
1895 int pos = formula.indexOf("_", 0);
1896 QString wCaption = formula.left(pos);
1897
1898 Table *w = table(wCaption);
1899 if (!w)
1900 return 0;
1901
1902 int posX = formula.indexOf("(", pos);
1903 QString xCol = formula.mid(pos + 1, posX - pos - 1);
1904
1905 pos = formula.indexOf(",", posX);
1906 posX = formula.indexOf("(", pos);
1907 QString yCol = formula.mid(pos + 1, posX - pos - 1);
1908
1909 Graph3D *plot = new Graph3D("", &d_workspace, 0);
1910 plot->setAttribute(Qt::WA_DeleteOnClose);
1911 plot->addData(w, xCol, yCol, xl, xr, yl, yr, zl, zr);
1912 plot->update();
1913
1914 QString label = caption;
1915 while (alreadyUsedName(label))
1916 label = generateUniqueName(tr("Graph"));
1917
1918 plot->setWindowTitle(label);
1919 plot->setName(label);
1920 initPlot3D(plot);
1921
1922 return plot;
1923 }
1924
newPlot3D()1925 Graph3D *ApplicationWindow::newPlot3D()
1926 {
1927 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1928
1929 QString label = generateUniqueName(tr("Graph"));
1930
1931 Graph3D *plot = new Graph3D("", &d_workspace, 0);
1932 plot->setAttribute(Qt::WA_DeleteOnClose);
1933 plot->resize(500, 400);
1934 plot->setWindowTitle(label);
1935 plot->setName(label);
1936
1937 customPlot3D(plot);
1938 initPlot3D(plot);
1939
1940 emit modified();
1941 QApplication::restoreOverrideCursor();
1942 return plot;
1943 }
1944
dataPlotXYZ(Table * table,const QString & zColName,int type)1945 Graph3D *ApplicationWindow::dataPlotXYZ(Table *table, const QString &zColName, int type)
1946 {
1947 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1948
1949 QString label = generateUniqueName(tr("Graph"));
1950 int zCol = table->colIndex(zColName);
1951 int yCol = table->colY(zCol);
1952 int xCol = table->colX(zCol);
1953
1954 Graph3D *plot = new Graph3D("", &d_workspace, 0);
1955 plot->setAttribute(Qt::WA_DeleteOnClose);
1956 plot->addData(table, xCol, yCol, zCol, type);
1957 plot->resize(500, 400);
1958 plot->setWindowTitle(label);
1959 plot->setName(label);
1960
1961 customPlot3D(plot);
1962 plot->update();
1963 initPlot3D(plot);
1964
1965 emit modified();
1966 QApplication::restoreOverrideCursor();
1967 return plot;
1968 }
1969
dataPlotXYZ(const QString & caption,const QString & formula,double xl,double xr,double yl,double yr,double zl,double zr)1970 Graph3D *ApplicationWindow::dataPlotXYZ(const QString &caption, const QString &formula, double xl,
1971 double xr, double yl, double yr, double zl, double zr)
1972 {
1973 int pos = formula.indexOf("_", 0);
1974 QString wCaption = formula.left(pos);
1975
1976 Table *w = table(wCaption);
1977 if (!w)
1978 return 0;
1979
1980 int posX = formula.indexOf("(X)", pos);
1981 QString xColName = formula.mid(pos + 1, posX - pos - 1);
1982
1983 pos = formula.indexOf(",", posX);
1984
1985 posX = formula.indexOf("(Y)", pos);
1986 QString yColName = formula.mid(pos + 1, posX - pos - 1);
1987
1988 pos = formula.indexOf(",", posX);
1989 posX = formula.indexOf("(Z)", pos);
1990 QString zColName = formula.mid(pos + 1, posX - pos - 1);
1991
1992 int xCol = w->colIndex(xColName);
1993 int yCol = w->colIndex(yColName);
1994 int zCol = w->colIndex(zColName);
1995
1996 Graph3D *plot = new Graph3D("", &d_workspace, 0);
1997 plot->setAttribute(Qt::WA_DeleteOnClose);
1998 plot->addData(w, xCol, yCol, zCol, xl, xr, yl, yr, zl, zr);
1999 plot->update();
2000
2001 QString label = caption;
2002 if (alreadyUsedName(label))
2003 label = generateUniqueName(tr("Graph"));
2004
2005 plot->setWindowTitle(label);
2006 plot->setName(label);
2007 initPlot3D(plot);
2008 return plot;
2009 }
2010
customPlot3D(Graph3D * plot)2011 void ApplicationWindow::customPlot3D(Graph3D *plot)
2012 {
2013 plot->setDataColors(QColor(COLORVALUE(plot3DColors[4])), QColor(COLORVALUE(plot3DColors[0])));
2014 plot->updateColors(QColor(COLORVALUE(plot3DColors[2])), QColor(COLORVALUE(plot3DColors[6])),
2015 QColor(COLORVALUE(plot3DColors[5])), QColor(COLORVALUE(plot3DColors[1])),
2016 QColor(COLORVALUE(plot3DColors[7])), QColor(COLORVALUE(plot3DColors[3])));
2017
2018 plot->setResolution(plot3DResolution);
2019 plot->showColorLegend(showPlot3DLegend);
2020 plot->setSmoothMesh(smooth3DMesh);
2021 plot->setOrtho(orthogonal3DPlots);
2022 if (showPlot3DProjection)
2023 plot->setFloorData();
2024
2025 plot->setNumbersFont(plot3DNumbersFont);
2026 plot->setXAxisLabelFont(plot3DAxesFont);
2027 plot->setYAxisLabelFont(plot3DAxesFont);
2028 plot->setZAxisLabelFont(plot3DAxesFont);
2029 plot->setTitleFont(plot3DTitleFont);
2030 }
2031
initPlot3D(Graph3D * plot)2032 void ApplicationWindow::initPlot3D(Graph3D *plot)
2033 {
2034 d_workspace.addSubWindow(plot);
2035 current_folder->addWindow(plot);
2036 plot->setFolder(current_folder);
2037 connectSurfacePlot(plot);
2038
2039 plot->setWindowIcon(QPixmap(":/trajectory.xpm"));
2040 plot->show();
2041 plot->setFocus();
2042
2043 addListViewItem(plot);
2044
2045 if (!graph_3D_tools->isEnabled())
2046 graph_3D_tools->setEnabled(true);
2047
2048 customMenu(plot);
2049 customToolBars(plot);
2050 }
2051
importImage()2052 Matrix *ApplicationWindow::importImage()
2053 {
2054 QList<QByteArray> list = QImageReader::supportedImageFormats();
2055 QString filter = tr("Images") + " (", aux1, aux2;
2056 for (int i = 0; i < (int)list.count(); i++) {
2057 aux1 = " *." + list[i] + " ";
2058 aux2 += " *." + list[i] + ";;";
2059 filter += aux1;
2060 }
2061 filter += ");;" + aux2;
2062
2063 QString fn =
2064 QFileDialog::getOpenFileName(this, tr("Import image from file"), imagesDirPath, filter);
2065 if (!fn.isEmpty()) {
2066 QFileInfo fi(fn);
2067 imagesDirPath = fi.absolutePath();
2068 return importImage(fn);
2069 } else
2070 return 0;
2071 }
2072
loadImage()2073 void ApplicationWindow::loadImage()
2074 {
2075 QList<QByteArray> list = QImageReader::supportedImageFormats();
2076 QString filter = tr("Images") + " (", aux1, aux2;
2077 for (int i = 0; i < (int)list.count(); i++) {
2078 aux1 = " *." + list[i] + " ";
2079 aux2 += " *." + list[i] + ";;";
2080 filter += aux1;
2081 }
2082 filter += ");;" + aux2;
2083
2084 QString fn =
2085 QFileDialog::getOpenFileName(this, tr("Load image from file"), imagesDirPath, filter);
2086 if (!fn.isEmpty()) {
2087 loadImage(fn);
2088 QFileInfo fi(fn);
2089 imagesDirPath = fi.absolutePath();
2090 }
2091 }
2092
loadImage(const QString & fn)2093 void ApplicationWindow::loadImage(const QString &fn)
2094 {
2095 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
2096
2097 MultiLayer *plot = multilayerPlot(generateUniqueName(tr("Graph")));
2098 plot->setWindowLabel(fn);
2099 plot->setCaptionPolicy(MyWidget::Both);
2100 setListViewLabel(plot->name(), fn);
2101
2102 plot->showNormal();
2103 Graph *g = plot->addLayer(0, 0, plot->width(), plot->height());
2104
2105 g->setTitle("");
2106 QVector<bool> axesOn(4);
2107 for (int j = 0; j < 4; j++)
2108 axesOn[j] = false;
2109 g->enableAxes(axesOn);
2110 g->removeLegend();
2111 g->setIgnoreResizeEvents(false);
2112 g->addImage(fn);
2113 QApplication::restoreOverrideCursor();
2114 }
2115
polishGraph(Graph * g,int style)2116 void ApplicationWindow::polishGraph(Graph *g, int style)
2117 {
2118 if (style == Graph::VerticalBars || style == Graph::HorizontalBars
2119 || style == Graph::Histogram) {
2120 QList<int> ticksList;
2121 int ticksStyle = ScaleDraw::Out;
2122 ticksList << ticksStyle << ticksStyle << ticksStyle << ticksStyle;
2123 g->setMajorTicksType(ticksList);
2124 g->setMinorTicksType(ticksList);
2125 }
2126 if (style == Graph::HorizontalBars) {
2127 g->setAxisTitle(0, tr("Y Axis Title"));
2128 g->setAxisTitle(1, tr("X Axis Title"));
2129 }
2130 }
2131
multilayerPlot(const QString & caption)2132 MultiLayer *ApplicationWindow::multilayerPlot(const QString &caption)
2133 {
2134 MultiLayer *ml = new MultiLayer("", &d_workspace, 0);
2135 ml->setAttribute(Qt::WA_DeleteOnClose);
2136 QString label = caption;
2137 initMultilayerPlot(ml, label.replace(QRegExp("_"), "-"));
2138 return ml;
2139 }
2140
newGraph(const QString & caption)2141 MultiLayer *ApplicationWindow::newGraph(const QString &caption)
2142 {
2143 MultiLayer *ml = multilayerPlot(generateUniqueName(caption));
2144 if (ml) {
2145 Graph *g = ml->addLayer();
2146 setPreferences(g);
2147 g->newLegend();
2148 g->setAutoscaleFonts(false);
2149 g->setIgnoreResizeEvents(false);
2150 ml->arrangeLayers(false, false);
2151 g->setAutoscaleFonts(autoScaleFonts); // restore user defined fonts behaviour
2152 g->setIgnoreResizeEvents(!autoResizeLayers);
2153 customMenu(ml);
2154 }
2155 return ml;
2156 }
2157
multilayerPlot(Table * w,const QStringList & colList,int style,int startRow,int endRow)2158 MultiLayer *ApplicationWindow::multilayerPlot(Table *w, const QStringList &colList, int style,
2159 int startRow, int endRow)
2160 { // used when plotting selected columns
2161 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
2162
2163 MultiLayer *g = new MultiLayer("", &d_workspace, 0);
2164 g->setAttribute(Qt::WA_DeleteOnClose);
2165
2166 initMultilayerPlot(g, generateUniqueName(tr("Graph")));
2167
2168 Graph *ag = g->addLayer();
2169 if (!ag)
2170 return 0;
2171
2172 setPreferences(ag);
2173 ag->insertCurvesList(w, colList, style, defaultCurveLineWidth, defaultSymbolSize, startRow,
2174 endRow);
2175
2176 polishGraph(ag, style);
2177 ag->newLegend();
2178 g->arrangeLayers(false, false);
2179 customMenu(g);
2180
2181 emit modified();
2182 QApplication::restoreOverrideCursor();
2183 return g;
2184 }
2185
multilayerPlot(int c,int r,int style)2186 MultiLayer *ApplicationWindow::multilayerPlot(int c, int r, int style)
2187 { // used when plotting from the panel menu
2188 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("Table"))
2189 return 0;
2190
2191 Table *w = (Table *)d_workspace.activeSubWindow();
2192 if (!validFor2DPlot(w, style))
2193 return 0;
2194
2195 QStringList list;
2196 switch (style) {
2197 case Graph::Histogram:
2198 case Graph::Pie:
2199 case Graph::Box:
2200 list = w->selectedColumns();
2201 break;
2202 default:
2203 list = w->selectedYColumns();
2204 break;
2205 }
2206
2207 int curves = (int)list.count();
2208 if (r < 0)
2209 r = curves;
2210
2211 MultiLayer *g = new MultiLayer("", &d_workspace, 0);
2212 g->setAttribute(Qt::WA_DeleteOnClose);
2213
2214 initMultilayerPlot(g, generateUniqueName(tr("Graph")));
2215
2216 int layers = c * r;
2217 if (curves < layers) {
2218 for (int i = 0; i < curves; i++) {
2219 Graph *ag = g->addLayer();
2220 if (ag) {
2221 setPreferences(ag);
2222 ag->insertCurvesList(w, QStringList(list[i]), style, defaultCurveLineWidth,
2223 defaultSymbolSize);
2224 ag->newLegend();
2225 ag->setAutoscaleFonts(false); // in order to avoid to small fonts
2226 ag->setIgnoreResizeEvents(false);
2227 polishGraph(ag, style);
2228 }
2229 }
2230 } else {
2231 for (int i = 0; i < layers; i++) {
2232 Graph *ag = g->addLayer();
2233 if (ag) {
2234 QStringList lst;
2235 lst << list[i];
2236 setPreferences(ag);
2237 ag->insertCurvesList(w, lst, style, defaultCurveLineWidth, defaultSymbolSize);
2238 ag->newLegend();
2239 ag->setAutoscaleFonts(false); // in order to avoid to small fonts
2240 ag->setIgnoreResizeEvents(false);
2241 polishGraph(ag, style);
2242 }
2243 }
2244 }
2245 g->setRows(r);
2246 g->setCols(c);
2247 g->arrangeLayers(false, false);
2248 QWidgetList lst = g->graphPtrs();
2249 foreach (QWidget *widget, lst) {
2250 Graph *ag = (Graph *)widget;
2251 ag->setAutoscaleFonts(autoScaleFonts); // restore user defined fonts behaviour
2252 ag->setIgnoreResizeEvents(!autoResizeLayers);
2253 }
2254 customMenu(g);
2255 emit modified();
2256 return g;
2257 }
2258
multilayerPlot(const QStringList & colList)2259 MultiLayer *ApplicationWindow::multilayerPlot(const QStringList &colList)
2260 { // used when plotting from wizard
2261 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
2262 MultiLayer *g = new MultiLayer("", &d_workspace, 0);
2263 g->setAttribute(Qt::WA_DeleteOnClose);
2264
2265 initMultilayerPlot(g, generateUniqueName(tr("Graph")));
2266
2267 Graph *ag = g->addLayer();
2268 setPreferences(ag);
2269 polishGraph(ag, defaultCurveStyle);
2270 int curves = (int)colList.count();
2271 int errorBars = 0;
2272 for (int i = 0; i < curves; i++) {
2273 if (colList[i].contains("(yErr)") || colList[i].contains("(xErr)"))
2274 errorBars++;
2275 }
2276
2277 for (int i = 0; i < curves; i++) {
2278 QString s = colList[i];
2279 int pos = s.indexOf(":", 0);
2280 QString caption = s.left(pos) + "_";
2281 Table *w = (Table *)table(caption);
2282
2283 int posX = s.indexOf("(X)", pos);
2284 QString xColName = caption + s.mid(pos + 2, posX - pos - 2);
2285 int xCol = w->colIndex(xColName);
2286
2287 posX = s.indexOf(",", posX);
2288 int posY = s.indexOf("(Y)", posX);
2289 QString yColName = caption + s.mid(posX + 2, posY - posX - 2);
2290
2291 if (s.contains("(yErr)") || s.contains("(xErr)")) {
2292 posY = s.indexOf(",", posY);
2293 int posErr, errType;
2294 if (s.contains("(yErr)")) {
2295 errType = QwtErrorPlotCurve::Vertical;
2296 posErr = s.indexOf("(yErr)", posY);
2297 } else {
2298 errType = QwtErrorPlotCurve::Horizontal;
2299 posErr = s.indexOf("(xErr)", posY);
2300 }
2301
2302 QString errColName = caption + s.mid(posY + 2, posErr - posY - 2);
2303 ag->addErrorBars(xColName, yColName, w, errColName, errType);
2304 } else
2305 ag->insertCurve(w, xCol, yColName, defaultCurveStyle);
2306
2307 CurveLayout cl = ag->initCurveLayout(defaultCurveStyle, curves - errorBars);
2308 cl.lWidth = defaultCurveLineWidth;
2309 cl.sSize = defaultSymbolSize;
2310 ag->updateCurveLayout(i, &cl);
2311 }
2312 ag->newLegend();
2313 ag->updatePlot();
2314 g->arrangeLayers(true, false);
2315 customMenu(g);
2316 emit modified();
2317 QApplication::restoreOverrideCursor();
2318 return g;
2319 }
2320
initBareMultilayerPlot(MultiLayer * g,const QString & name)2321 void ApplicationWindow::initBareMultilayerPlot(MultiLayer *g, const QString &name)
2322 { // FIXME: workaround, init without unnecessary g->show()
2323 QString label = name;
2324 while (alreadyUsedName(label))
2325 label = generateUniqueName(tr("Graph"));
2326
2327 connectMultilayerPlot(g);
2328
2329 g->setWindowTitle(label);
2330 g->setName(label);
2331 g->setWindowIcon(QPixmap(":/graph.xpm"));
2332 g->setScaleLayersOnPrint(d_scale_plots_on_print);
2333 g->printCropmarks(d_print_cropmarks);
2334
2335 d_workspace.addSubWindow(g);
2336 current_folder->addWindow(g);
2337 g->setFolder(current_folder);
2338 addListViewItem(g);
2339 }
2340
initMultilayerPlot(MultiLayer * g,const QString & name)2341 void ApplicationWindow::initMultilayerPlot(MultiLayer *g, const QString &name)
2342 {
2343 initBareMultilayerPlot(g, name);
2344 g->show(); // FIXME: bad idea do it here
2345 g->setFocus();
2346 }
2347
customizeTables(const QColor & bgColor,const QColor & textColor,const QColor & headerColor,const QFont & textFont,const QFont & headerFont,bool showComments)2348 void ApplicationWindow::customizeTables(const QColor &bgColor, const QColor &textColor,
2349 const QColor &headerColor, const QFont &textFont,
2350 const QFont &headerFont, bool showComments)
2351 {
2352 tableBkgdColor = bgColor;
2353 tableTextColor = textColor;
2354 tableHeaderColor = headerColor;
2355 tableTextFont = textFont;
2356 tableHeaderFont = headerFont;
2357 d_show_table_comments = showComments;
2358
2359 QList<MyWidget *> windows = windowsList();
2360 foreach (MyWidget *w, windows) {
2361 if (w->inherits("Table"))
2362 customTable((Table *)w);
2363 }
2364 }
2365
customTable(Table * w)2366 void ApplicationWindow::customTable(Table *w)
2367 {
2368 QPalette cg;
2369 cg.setColor(QPalette::Base, QColor(tableBkgdColor));
2370 cg.setColor(QPalette::Text, QColor(tableTextColor));
2371 w->setPalette(cg);
2372
2373 w->setHeaderColor(tableHeaderColor);
2374 w->setTextFont(tableTextFont);
2375 w->setHeaderFont(tableHeaderFont);
2376 w->showComments(d_show_table_comments);
2377 }
2378
setPreferences(Graph * g)2379 void ApplicationWindow::setPreferences(Graph *g)
2380 {
2381 if (!g->isPiePlot()) {
2382 if (allAxesOn) {
2383 QVector<bool> axesOn(QwtPlot::axisCnt);
2384 axesOn.fill(true);
2385 g->enableAxes(axesOn);
2386 g->updateSecondaryAxis(QwtPlot::xTop);
2387 g->updateSecondaryAxis(QwtPlot::yRight);
2388 }
2389
2390 QList<int> ticksList;
2391 ticksList << majTicksStyle << majTicksStyle << majTicksStyle << majTicksStyle;
2392 g->setMajorTicksType(ticksList);
2393 ticksList.clear();
2394 ticksList << minTicksStyle << minTicksStyle << minTicksStyle << minTicksStyle;
2395 g->setMinorTicksType(ticksList);
2396
2397 g->setTicksLength(minTicksLength, majTicksLength);
2398 g->setAxesLinewidth(axesLineWidth);
2399 g->drawAxesBackbones(drawBackbones);
2400 }
2401
2402 g->initFonts(plotAxesFont, plotNumbersFont);
2403 g->setTextMarkerDefaults(legendFrameStyle, plotLegendFont, legendTextColor, legendBackground);
2404 g->setArrowDefaults(defaultArrowLineWidth, defaultArrowColor, defaultArrowLineStyle,
2405 defaultArrowHeadLength, defaultArrowHeadAngle, defaultArrowHeadFill);
2406 g->initTitle(titleOn, plotTitleFont);
2407 g->drawCanvasFrame(canvasFrameOn, canvasFrameWidth);
2408 g->plotWidget()->setMargin(defaultPlotMargin);
2409 g->enableAutoscaling(autoscale2DPlots);
2410 g->setAutoscaleFonts(autoScaleFonts);
2411 g->setIgnoreResizeEvents(!autoResizeLayers);
2412 g->setAntialiasing(antialiasing2DPlots);
2413 }
2414
newWrksheetPlot(const QString & name,const QString & label,QList<Column * > columns)2415 void ApplicationWindow::newWrksheetPlot(const QString &name, const QString &label,
2416 QList<Column *> columns)
2417 {
2418 Table *w = newTable(name, label, columns);
2419 MultiLayer *plot = multilayerPlot(w, QStringList(QString(w->name()) + "_intensity"), 0);
2420 Graph *g = (Graph *)plot->activeGraph();
2421 if (g) {
2422 g->setTitle("");
2423 g->setXAxisTitle(tr("pixels"));
2424 g->setYAxisTitle(tr("pixel intensity (a.u.)"));
2425 }
2426 }
2427
2428 /*
2429 *used when importing an ASCII file
2430 */
newTable(const QString & fname,const QString & sep,int lines,bool renameCols,bool stripSpaces,bool simplifySpaces,bool convertToNumeric,QLocale numericLocale)2431 Table *ApplicationWindow::newTable(const QString &fname, const QString &sep, int lines,
2432 bool renameCols, bool stripSpaces, bool simplifySpaces,
2433 bool convertToNumeric, QLocale numericLocale)
2434 {
2435 Table *w = new Table(scriptEnv, fname, sep, lines, renameCols, stripSpaces, simplifySpaces,
2436 convertToNumeric, numericLocale, fname, &d_workspace);
2437 if (w) {
2438 w->setName(generateUniqueName(tr("Table")));
2439 d_project->addChild(w->d_future_table);
2440 }
2441 return w;
2442 }
2443
2444 /*
2445 *creates a new empty table
2446 */
newTable()2447 Table *ApplicationWindow::newTable()
2448 {
2449 Table *w = new Table(scriptEnv, 30, 2, "", &d_workspace, 0);
2450 w->setName(generateUniqueName(tr("Table")));
2451 d_project->addChild(w->d_future_table);
2452 return w;
2453 }
2454
2455 /*
2456 *used when opening a project file
2457 */
newTable(const QString & caption,int r,int c)2458 Table *ApplicationWindow::newTable(const QString &caption, int r, int c)
2459 {
2460 Table *w = new Table(scriptEnv, r, c, "", &d_workspace, 0);
2461 w->setName(caption);
2462 d_project->addChild(w->d_future_table);
2463 if (w->name() != caption) // the table was renamed
2464 {
2465 renamedTables << caption << w->name();
2466
2467 QMessageBox::warning(this, tr("Renamed Window"),
2468 tr("The table '%1' already exists. It has been renamed '%2'.")
2469 .arg(caption)
2470 .arg(w->name()));
2471 }
2472 return w;
2473 }
2474
newTable(int r,int c,const QString & name,const QString & legend)2475 Table *ApplicationWindow::newTable(int r, int c, const QString &name, const QString &legend)
2476 {
2477 Table *w = new Table(scriptEnv, r, c, legend, &d_workspace, 0);
2478 w->setName(name);
2479 d_project->addChild(w->d_future_table);
2480 return w;
2481 }
2482
newTable(const QString & name,const QString & legend,QList<Column * > columns)2483 Table *ApplicationWindow::newTable(const QString &name, const QString &legend,
2484 QList<Column *> columns)
2485 {
2486 Table *w = new Table(scriptEnv, 0, 0, legend, &d_workspace, 0);
2487 w->d_future_table->appendColumns(columns);
2488 w->setName(name);
2489 d_project->addChild(w->d_future_table);
2490 return w;
2491 }
2492
newHiddenTable(const QString & name,const QString & label,QList<Column * > columns)2493 Table *ApplicationWindow::newHiddenTable(const QString &name, const QString &label,
2494 QList<Column *> columns)
2495 {
2496 auto w = newTable(name, label, columns);
2497 hideWindow(w);
2498 return w;
2499 }
2500
initTable(Table * w)2501 void ApplicationWindow::initTable(Table *w)
2502 {
2503 d_workspace.addSubWindow(w);
2504 w->setWindowIcon(QPixmap(":/worksheet.xpm"));
2505 current_folder->addWindow(w);
2506 w->setFolder(current_folder);
2507 addListViewItem(w);
2508 w->showNormal();
2509
2510 connectTable(w);
2511 customTable(w);
2512
2513 w->d_future_table->setPlotMenu(plot2D);
2514
2515 emit modified();
2516 }
2517
2518 /*
2519 * !creates a new table with type statistics on target columns/rows of table base
2520 */
newTableStatistics(Table * base,int type,QList<int> target,const QString & caption)2521 TableStatistics *ApplicationWindow::newTableStatistics(Table *base, int type, QList<int> target,
2522 const QString &caption)
2523 {
2524 TableStatistics *s =
2525 new TableStatistics(scriptEnv, &d_workspace, base, (TableStatistics::Type)type, target);
2526 if (!caption.isEmpty())
2527 s->setName(caption);
2528
2529 d_project->addChild(s->d_future_table);
2530 connect(base, SIGNAL(modifiedData(Table *, const QString &)), s,
2531 SLOT(update(Table *, const QString &)));
2532 connect(base, SIGNAL(changedColHeader(const QString &, const QString &)), s,
2533 SLOT(renameCol(const QString &, const QString &)));
2534 connect(base, SIGNAL(removedCol(const QString &)), s, SLOT(removeCol(const QString &)));
2535 connect(base->d_future_table, SIGNAL(aspectAboutToBeRemoved(const AbstractAspect *)), this,
2536 SLOT(removeDependentTableStatistics(const AbstractAspect *)));
2537 return s;
2538 }
2539
removeDependentTableStatistics(const AbstractAspect * aspect)2540 void ApplicationWindow::removeDependentTableStatistics(const AbstractAspect *aspect)
2541 {
2542 ::future::Table *future_table =
2543 qobject_cast<::future::Table *>(const_cast<AbstractAspect *>(aspect));
2544 if (!future_table)
2545 return;
2546 QList<MyWidget *> windows = windowsList();
2547 foreach (MyWidget *win, windows) {
2548 TableStatistics *table_stat = qobject_cast<TableStatistics *>(win);
2549 if (!table_stat)
2550 continue;
2551 Table *table = qobject_cast<Table *>(future_table->view());
2552 if (!table)
2553 continue;
2554 if (table_stat->base() == table)
2555 d_project->removeChild(table_stat->d_future_table);
2556 }
2557 }
2558
2559 /*
2560 *creates a new empty note window
2561 */
newNote(const QString & caption)2562 Note *ApplicationWindow::newNote(const QString &caption)
2563 {
2564 Note *m = new Note(scriptEnv, "", &d_workspace);
2565 if (caption.isEmpty())
2566 initNote(m, generateUniqueName(tr("Notes")));
2567 else
2568 initNote(m, caption);
2569 m->showNormal();
2570 return m;
2571 }
2572
initNote(Note * m,const QString & caption)2573 void ApplicationWindow::initNote(Note *m, const QString &caption)
2574 {
2575 QString name = caption;
2576 while (name.isEmpty() || alreadyUsedName(name))
2577 name = generateUniqueName(tr("Notes"));
2578
2579 d_workspace.addSubWindow(m);
2580 m->setWindowTitle(name);
2581 m->setName(name);
2582 m->setWindowIcon(QPixmap(":/note.xpm"));
2583 m->askOnCloseEvent(confirmCloseNotes);
2584 m->setFolder(current_folder);
2585
2586 current_folder->addWindow(m);
2587 addListViewItem(m);
2588
2589 connect(m, SIGNAL(modifiedWindow(MyWidget *)), this, SLOT(modifiedProject(MyWidget *)));
2590 connect(m, SIGNAL(closedWindow(MyWidget *)), this, SLOT(closeWindow(MyWidget *)));
2591 connect(m, SIGNAL(hiddenWindow(MyWidget *)), this, SLOT(hideWindow(MyWidget *)));
2592 connect(m, SIGNAL(statusChanged(MyWidget *)), this, SLOT(updateWindowStatus(MyWidget *)));
2593 connect(m, SIGNAL(showTitleBarMenu()), this, SLOT(showWindowTitleBarMenu()));
2594
2595 emit modified();
2596 }
2597
newMatrix(int rows,int columns)2598 Matrix *ApplicationWindow::newMatrix(int rows, int columns)
2599 {
2600 Matrix *m = new Matrix(scriptEnv, rows, columns, "", 0, 0);
2601 QString caption = generateUniqueName(tr("Matrix"));
2602 while (alreadyUsedName(caption)) {
2603 caption = generateUniqueName(tr("Matrix"));
2604 }
2605 m->setName(caption);
2606 d_project->addChild(m->d_future_matrix);
2607 return m;
2608 }
2609
newMatrix(const QString & caption,int r,int c)2610 Matrix *ApplicationWindow::newMatrix(const QString &caption, int r, int c)
2611 {
2612 Matrix *w = new Matrix(scriptEnv, r, c, "", 0, 0);
2613 QString name = caption;
2614 while (alreadyUsedName(name)) {
2615 name = generateUniqueName(caption);
2616 }
2617 w->setName(name);
2618 d_project->addChild(w->d_future_matrix);
2619 if (w->name() != caption) // the matrix was renamed
2620 renamedTables << caption << w->name();
2621
2622 return w;
2623 }
2624
matrixDeterminant()2625 void ApplicationWindow::matrixDeterminant()
2626 {
2627 Matrix *m = (Matrix *)d_workspace.activeSubWindow();
2628 if (!m)
2629 return;
2630
2631 QDateTime dt = QDateTime::currentDateTime();
2632 QString info = QLocale().toString(dt);
2633 info += "\n" + tr("Determinant of ") + QString(m->name()) + ":\t";
2634 info += "det = " + QString::number(m->determinant()) + "\n";
2635 info += "-------------------------------------------------------------\n";
2636
2637 logInfo += info;
2638
2639 showResults(true);
2640 }
2641
invertMatrix()2642 void ApplicationWindow::invertMatrix()
2643 {
2644 Matrix *m = (Matrix *)d_workspace.activeSubWindow();
2645 if (!m)
2646 return;
2647
2648 m->invert();
2649 }
2650
convertMatrixToTable()2651 Table *ApplicationWindow::convertMatrixToTable()
2652 {
2653 Matrix *m = (Matrix *)d_workspace.activeSubWindow();
2654 if (!m)
2655 return 0;
2656
2657 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
2658
2659 int rows = m->numRows();
2660 int cols = m->numCols();
2661
2662 Table *w = new Table(scriptEnv, rows, cols, "", &d_workspace, 0);
2663 for (int i = 0; i < rows; i++) {
2664 for (int j = 0; j < cols; j++)
2665 w->setCell(i, j, m->cell(i, j));
2666 }
2667
2668 w->setName(generateUniqueName(tr("Table")));
2669 d_project->addChild(w->d_future_table);
2670 w->setWindowLabel(m->windowLabel());
2671 w->setCaptionPolicy(m->captionPolicy());
2672 w->resize(m->size());
2673 w->showNormal();
2674
2675 QApplication::restoreOverrideCursor();
2676
2677 return w;
2678 }
2679
initMatrix(Matrix * m)2680 void ApplicationWindow::initMatrix(Matrix *m)
2681 {
2682 d_workspace.addSubWindow(m);
2683 m->setWindowIcon(QPixmap(":/matrix.xpm"));
2684 m->askOnCloseEvent(confirmCloseMatrix);
2685 m->setNumericFormat(d_default_numeric_format, d_decimal_digits);
2686 m->setFolder(current_folder);
2687
2688 current_folder->addWindow(m);
2689 m->setFolder(current_folder);
2690 addListViewItem(m);
2691 m->showNormal();
2692
2693 connect(m, SIGNAL(showTitleBarMenu()), this, SLOT(showWindowTitleBarMenu()));
2694 connect(m, SIGNAL(modifiedWindow(MyWidget *)), this, SLOT(modifiedProject(MyWidget *)));
2695 connect(m, SIGNAL(modifiedWindow(MyWidget *)), this, SLOT(updateMatrixPlots(MyWidget *)));
2696 connect(m, SIGNAL(hiddenWindow(MyWidget *)), this, SLOT(hideWindow(MyWidget *)));
2697 connect(m, SIGNAL(statusChanged(MyWidget *)), this, SLOT(updateWindowStatus(MyWidget *)));
2698 connect(m, SIGNAL(showContextMenu()), this, SLOT(showWindowContextMenu()));
2699 emit modified();
2700 }
2701
convertTableToMatrix()2702 Matrix *ApplicationWindow::convertTableToMatrix()
2703 {
2704 Table *m = (Table *)d_workspace.activeSubWindow();
2705 if (!m)
2706 return 0;
2707
2708 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
2709
2710 int rows = m->numRows();
2711 int cols = m->numCols();
2712
2713 Matrix *w = new Matrix(scriptEnv, rows, cols, "", 0, 0);
2714 for (int i = 0; i < rows; i++) {
2715 for (int j = 0; j < cols; j++)
2716 w->setText(i, j, m->text(i, j));
2717 }
2718
2719 QString caption = generateUniqueName(m->name());
2720 w->setName(caption);
2721 d_project->addChild(w->d_future_matrix);
2722
2723 w->setCaptionPolicy(m->captionPolicy());
2724 w->resize(m->size());
2725 w->showNormal();
2726
2727 QApplication::restoreOverrideCursor();
2728 return w;
2729 }
2730
window(const QString & name)2731 MyWidget *ApplicationWindow::window(const QString &name)
2732 {
2733 MyWidget *widget = 0;
2734 QList<MyWidget *> windows = windowsList();
2735 for (int i = 0; i < windows.count(); i++) {
2736 widget = windows.at(i);
2737 if (widget && widget->name() == name)
2738 return widget;
2739 }
2740 return widget;
2741 }
2742
table(const QString & name)2743 Table *ApplicationWindow::table(const QString &name)
2744 {
2745 int pos = name.indexOf("_", 0);
2746 QString caption = name.left(pos);
2747
2748 QList<MyWidget *> lst = windowsList();
2749 foreach (MyWidget *w, lst) {
2750 if (w->inherits("Table") && static_cast<Table *>(w)->name() == caption) {
2751 return (Table *)w;
2752 }
2753 }
2754 return 0;
2755 }
2756
matrix(const QString & name)2757 Matrix *ApplicationWindow::matrix(const QString &name)
2758 {
2759 QString caption = name;
2760 if (!renamedTables.isEmpty() && renamedTables.contains(caption)) {
2761 int index = renamedTables.indexOf(caption);
2762 caption = renamedTables[index + 1];
2763 }
2764
2765 QList<MyWidget *> lst = windowsList();
2766 foreach (MyWidget *w, lst) {
2767 if (w->inherits("Matrix") && static_cast<Matrix *>(w)->name() == caption) {
2768 return (Matrix *)w;
2769 }
2770 }
2771 return 0;
2772 }
2773
windowActivated(QMdiSubWindow * w)2774 void ApplicationWindow::windowActivated(QMdiSubWindow *w)
2775 {
2776 if (!w || !w->inherits("MyWidget"))
2777 return;
2778
2779 customToolBars((MyWidget *)w);
2780 customMenu((MyWidget *)w);
2781
2782 Folder *f = ((MyWidget *)w)->folder();
2783 if (f)
2784 f->setActiveWindow((MyWidget *)w);
2785 }
2786
addErrorBars()2787 void ApplicationWindow::addErrorBars()
2788 {
2789 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
2790 return;
2791
2792 MultiLayer *plot = (MultiLayer *)d_workspace.activeSubWindow();
2793 if (plot->isEmpty()) {
2794 QMessageBox::warning(this, tr("Warning"),
2795 tr("<h4>There are no plot layers available in this window.</h4>"
2796 "<p><h4>Please add a layer and try again!</h4>"));
2797 return;
2798 }
2799
2800 Graph *g = (Graph *)plot->activeGraph();
2801 if (!g)
2802 return;
2803
2804 if (!g->curves()) {
2805 QMessageBox::warning(this, tr("Warning"),
2806 tr("There are no curves available on this plot!"));
2807 return;
2808 }
2809
2810 if (g->isPiePlot()) {
2811 QMessageBox::warning(this, tr("Warning"),
2812 tr("This functionality is not available for pie plots!"));
2813 return;
2814 }
2815
2816 ErrDialog *ed = new ErrDialog(this);
2817 ed->setAttribute(Qt::WA_DeleteOnClose);
2818 connect(ed, SIGNAL(options(const QString &, int, const QString &, int)), this,
2819 SLOT(defineErrorBars(const QString &, int, const QString &, int)));
2820 connect(ed, SIGNAL(options(const QString &, const QString &, int)), this,
2821 SLOT(defineErrorBars(const QString &, const QString &, int)));
2822
2823 ed->setCurveNames(g->analysableCurvesList());
2824 ed->setSrcTables(tableList());
2825 ed->exec();
2826 }
2827
defineErrorBars(const QString & name,int type,const QString & percent,int direction)2828 void ApplicationWindow::defineErrorBars(const QString &name, int type, const QString &percent,
2829 int direction)
2830 {
2831 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
2832 return;
2833
2834 Graph *g = ((MultiLayer *)d_workspace.activeSubWindow())->activeGraph();
2835 if (!g)
2836 return;
2837
2838 Table *w = table(name);
2839 if (!w) { // user defined function
2840 QMessageBox::critical(
2841 this, tr("Error bars error"),
2842 tr("This feature is not available for user defined function curves!"));
2843 return;
2844 }
2845
2846 DataCurve *master_curve = (DataCurve *)g->curve(name);
2847 QString xColName = master_curve->xColumnName();
2848 if (xColName.isEmpty())
2849 return;
2850
2851 Column *errors = new Column("1", SciDAVis::ColumnMode::Numeric);
2852 Column *data;
2853 if (direction == QwtErrorPlotCurve::Horizontal) {
2854 errors->setPlotDesignation(SciDAVis::xErr);
2855 data = w->d_future_table->column(xColName);
2856 } else {
2857 errors->setPlotDesignation(SciDAVis::yErr);
2858 data = w->d_future_table->column(name);
2859 }
2860 if (!data)
2861 return;
2862
2863 int rows = data->rowCount();
2864 if (type == 0) {
2865 double fraction = percent.toDouble() / 100.0;
2866 for (int i = 0; i < rows; i++)
2867 errors->setValueAt(i, data->valueAt(i) * fraction);
2868 } else if (type == 1) {
2869 double average = 0.0;
2870 double dev = 0.0;
2871 for (int i = 0; i < rows; i++)
2872 average += data->valueAt(i);
2873 average /= rows;
2874 for (int i = 0; i < rows; i++)
2875 dev += pow(data->valueAt(i) - average, 2);
2876 dev = sqrt(dev / rows);
2877 for (int i = 0; i < rows; i++)
2878 errors->setValueAt(i, dev);
2879 }
2880 w->d_future_table->addChild(errors);
2881 g->addErrorBars(xColName, name, w, errors->name(), direction);
2882 }
2883
defineErrorBars(const QString & curveName,const QString & errColumnName,int direction)2884 void ApplicationWindow::defineErrorBars(const QString &curveName, const QString &errColumnName,
2885 int direction)
2886 {
2887 Table *w = table(curveName);
2888 if (!w) { // user defined function --> no worksheet available
2889 QMessageBox::critical(
2890 this, tr("Error"),
2891 tr("This feature is not available for user defined function curves!"));
2892 return;
2893 }
2894
2895 Table *errTable = table(errColumnName);
2896 if (w->numRows() != errTable->numRows()) {
2897 QMessageBox::critical(this, tr("Error"),
2898 tr("The selected columns have different numbers of rows!"));
2899
2900 addErrorBars();
2901 return;
2902 }
2903
2904 int errCol = errTable->colIndex(errColumnName);
2905 if (errTable->d_future_table->column(errCol)->dataType() != SciDAVis::TypeDouble) {
2906 QMessageBox::critical(this, tr("Error"),
2907 tr("You can only define error bars for numeric columns."));
2908 addErrorBars();
2909 return;
2910 }
2911
2912 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
2913 return;
2914
2915 Graph *g = ((MultiLayer *)d_workspace.activeSubWindow())->activeGraph();
2916 if (!g)
2917 return;
2918
2919 g->addErrorBars(curveName, errTable, errColumnName, direction);
2920 emit modified();
2921 }
2922
removeCurves(const QString & name)2923 void ApplicationWindow::removeCurves(const QString &name)
2924 {
2925 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
2926
2927 QList<MyWidget *> windows = windowsList();
2928 foreach (MyWidget *w, windows) {
2929 if (w->inherits("MultiLayer")) {
2930 QWidgetList lst = ((MultiLayer *)w)->graphPtrs();
2931 foreach (QWidget *widget, lst)
2932 ((Graph *)widget)->removeCurves(name);
2933 } else if (w->inherits("Graph3D")) {
2934 if ((((Graph3D *)w)->formula()).contains(name))
2935 ((Graph3D *)w)->clearData();
2936 }
2937 }
2938 QApplication::restoreOverrideCursor();
2939 }
2940
updateCurves(Table * t,const QString & name)2941 void ApplicationWindow::updateCurves(Table *t, const QString &name)
2942 {
2943 QList<MyWidget *> windows = windowsList();
2944 foreach (MyWidget *w, windows) {
2945 if (w->inherits("MultiLayer")) {
2946 QWidgetList graphsList = ((MultiLayer *)w)->graphPtrs();
2947 for (int k = 0; k < (int)graphsList.count(); k++) {
2948 Graph *g = (Graph *)graphsList.at(k);
2949 if (g)
2950 g->updateCurvesData(t, name);
2951 }
2952 } else if (w->inherits("Graph3D")) {
2953 Graph3D *g = (Graph3D *)w;
2954 if ((g->formula()).contains(name))
2955 g->updateData(t);
2956 }
2957 }
2958 }
2959
showPreferencesDialog()2960 void ApplicationWindow::showPreferencesDialog()
2961 {
2962 ConfigDialog *cd = new ConfigDialog(this);
2963 cd->setAttribute(Qt::WA_DeleteOnClose);
2964 cd->setColumnSeparator(columnSeparator);
2965 cd->exec();
2966 }
2967
setSaveSettings(bool autoSaving,int min)2968 void ApplicationWindow::setSaveSettings(bool autoSaving, int min)
2969 {
2970 if (autoSave == autoSaving && autoSaveTime == min)
2971 return;
2972
2973 autoSave = autoSaving;
2974 autoSaveTime = min;
2975
2976 killTimer(savingTimerId);
2977
2978 if (autoSave)
2979 savingTimerId = startTimer(autoSaveTime * 60000);
2980 else
2981 savingTimerId = 0;
2982 }
2983
changeAppStyle(const QString & s)2984 void ApplicationWindow::changeAppStyle(const QString &s)
2985 {
2986 // style keys are case insensitive
2987 if (appStyle.toLower() == s.toLower())
2988 return;
2989
2990 qApp->setStyle(s);
2991 appStyle = qApp->style()->objectName();
2992
2993 QPalette pal = qApp->palette();
2994 pal.setColor(QPalette::Active, QPalette::Base, QColor(panelsColor));
2995 qApp->setPalette(pal);
2996 }
2997
changeAppFont(const QFont & f)2998 void ApplicationWindow::changeAppFont(const QFont &f)
2999 {
3000 if (appFont == f)
3001 return;
3002
3003 appFont = f;
3004 updateAppFonts();
3005 }
3006
updateAppFonts()3007 void ApplicationWindow::updateAppFonts()
3008 {
3009 qApp->setFont(appFont);
3010 this->setFont(appFont);
3011 scriptingMenu->setFont(appFont);
3012 windowsMenu->setFont(appFont);
3013 view->setFont(appFont);
3014 graph->setFont(appFont);
3015 file->setFont(appFont);
3016 format->setFont(appFont);
3017 calcul->setFont(appFont);
3018 edit->setFont(appFont);
3019 dataMenu->setFont(appFont);
3020 recent->setFont(appFont);
3021 help->setFont(appFont);
3022 type->setFont(appFont);
3023 plot2D->setFont(appFont);
3024 plot3D->setFont(appFont);
3025 plot3DMenu->setFont(appFont);
3026 matrixMenu->setFont(appFont);
3027 specialPlot->setFont(appFont);
3028 panels->setFont(appFont);
3029 stat->setFont(appFont);
3030 smooth->setFont(appFont);
3031 filter->setFont(appFont);
3032 decay->setFont(appFont);
3033 plotDataMenu->setFont(appFont);
3034 tableMenu->setFont(appFont);
3035 exportPlot->setFont(appFont);
3036 translateMenu->setFont(appFont);
3037 multiPeakMenu->setFont(appFont);
3038 }
3039
updateConfirmOptions(bool askTables,bool askMatrices,bool askPlots2D,bool askPlots3D,bool askNotes)3040 void ApplicationWindow::updateConfirmOptions(bool askTables, bool askMatrices, bool askPlots2D,
3041 bool askPlots3D, bool askNotes)
3042 {
3043 QList<MyWidget *> windows = windowsList();
3044 if (confirmCloseTable != askTables) {
3045 confirmCloseTable = askTables;
3046 for (int i = 0; i < int(windows.count()); i++) {
3047 if (windows.at(i)->inherits("Table"))
3048 ((MyWidget *)windows.at(i))->askOnCloseEvent(confirmCloseTable);
3049 }
3050 }
3051
3052 if (confirmCloseMatrix != askMatrices) {
3053 confirmCloseMatrix = askMatrices;
3054 for (int i = 0; i < int(windows.count()); i++) {
3055 if (windows.at(i)->inherits("Matrix"))
3056 ((MyWidget *)windows.at(i))->askOnCloseEvent(confirmCloseMatrix);
3057 }
3058 }
3059
3060 if (confirmClosePlot2D != askPlots2D) {
3061 confirmClosePlot2D = askPlots2D;
3062 for (int i = 0; i < int(windows.count()); i++) {
3063 if (windows.at(i)->inherits("MultiLayer"))
3064 ((MyWidget *)windows.at(i))->askOnCloseEvent(confirmClosePlot2D);
3065 }
3066 }
3067
3068 if (confirmClosePlot3D != askPlots3D) {
3069 confirmClosePlot3D = askPlots3D;
3070 for (int i = 0; i < int(windows.count()); i++) {
3071 if (windows.at(i)->inherits("Graph3D"))
3072 ((MyWidget *)windows.at(i))->askOnCloseEvent(confirmClosePlot3D);
3073 }
3074 }
3075
3076 if (confirmCloseNotes != askNotes) {
3077 confirmCloseNotes = askNotes;
3078 for (int i = 0; i < int(windows.count()); i++) {
3079 if (windows.at(i)->inherits("Note"))
3080 ((MyWidget *)windows.at(i))->askOnCloseEvent(confirmCloseNotes);
3081 }
3082 }
3083 }
3084
setGraphDefaultSettings(bool autoscale,bool scaleFonts,bool resizeLayers,bool antialiasing)3085 void ApplicationWindow::setGraphDefaultSettings(bool autoscale, bool scaleFonts, bool resizeLayers,
3086 bool antialiasing)
3087 {
3088 if (autoscale2DPlots == autoscale && autoScaleFonts == scaleFonts
3089 && autoResizeLayers != resizeLayers && antialiasing2DPlots == antialiasing)
3090 return;
3091
3092 autoscale2DPlots = autoscale;
3093 autoScaleFonts = scaleFonts;
3094 autoResizeLayers = !resizeLayers;
3095 antialiasing2DPlots = antialiasing;
3096
3097 QList<MyWidget *> windows = windowsList();
3098 foreach (MyWidget *w, windows) {
3099 if (w->inherits("MultiLayer")) {
3100 QWidgetList lst = ((MultiLayer *)w)->graphPtrs();
3101 Graph *g;
3102 foreach (QWidget *widget, lst) {
3103 g = (Graph *)widget;
3104 g->enableAutoscaling(autoscale2DPlots);
3105 g->updateScale();
3106 g->setIgnoreResizeEvents(!autoResizeLayers);
3107 g->setAutoscaleFonts(autoScaleFonts);
3108 g->setAntialiasing(antialiasing2DPlots);
3109 }
3110 }
3111 }
3112 }
3113
setLegendDefaultSettings(int frame,const QFont & font,const QColor & textCol,const QColor & backgroundCol)3114 void ApplicationWindow::setLegendDefaultSettings(int frame, const QFont &font,
3115 const QColor &textCol, const QColor &backgroundCol)
3116 {
3117 if (legendFrameStyle == frame && legendTextColor == textCol && legendBackground == backgroundCol
3118 && plotLegendFont == font)
3119 return;
3120
3121 legendFrameStyle = frame;
3122 legendTextColor = textCol;
3123 legendBackground = backgroundCol;
3124 plotLegendFont = font;
3125
3126 QList<MyWidget *> windows = windowsList();
3127 foreach (MyWidget *w, windows) {
3128 if (w->inherits("MultiLayer")) {
3129 QWidgetList graphsList = ((MultiLayer *)w)->graphPtrs();
3130 foreach (QWidget *widget, graphsList)
3131 ((Graph *)widget)->setTextMarkerDefaults(frame, font, textCol, backgroundCol);
3132 }
3133 }
3134 saveSettings();
3135 }
3136
setArrowDefaultSettings(const QPen & pen,int headLength,int headAngle,bool fillHead)3137 void ApplicationWindow::setArrowDefaultSettings(const QPen &pen, int headLength, int headAngle,
3138 bool fillHead)
3139 {
3140 if (defaultArrowLineWidth == pen.width() && defaultArrowColor == pen.color()
3141 && defaultArrowLineStyle == pen.style() && defaultArrowHeadLength == headLength
3142 && defaultArrowHeadAngle == headAngle && defaultArrowHeadFill == fillHead)
3143 return;
3144
3145 defaultArrowLineWidth = pen.width();
3146 defaultArrowColor = pen.color();
3147 defaultArrowLineStyle = pen.style();
3148 defaultArrowHeadLength = headLength;
3149 defaultArrowHeadAngle = headAngle;
3150 defaultArrowHeadFill = fillHead;
3151
3152 QList<MyWidget *> windows = windowsList();
3153 foreach (MyWidget *w, windows) {
3154 if (w->inherits("MultiLayer")) {
3155 QWidgetList graphsList = ((MultiLayer *)w)->graphPtrs();
3156 foreach (QWidget *widget, graphsList)
3157 ((Graph *)widget)
3158 ->setArrowDefaults(defaultArrowLineWidth, defaultArrowColor,
3159
3160 defaultArrowLineStyle, defaultArrowHeadLength,
3161 defaultArrowHeadAngle, defaultArrowHeadFill);
3162 }
3163 }
3164 saveSettings();
3165 }
3166
plotFile(const QString & fn)3167 ApplicationWindow *ApplicationWindow::plotFile(const QString &fn)
3168 {
3169 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
3170 ApplicationWindow *app = new ApplicationWindow();
3171 app->applyUserSettings();
3172 app->showMaximized();
3173
3174 Table *t = app->newTable(fn, app->columnSeparator, 0, true, app->strip_spaces,
3175 app->simplify_spaces, app->d_convert_to_numeric,
3176 app->d_ASCII_import_locale);
3177 t->setCaptionPolicy(MyWidget::Both);
3178 app->multilayerPlot(t, t->YColumns(), Graph::LineSymbols);
3179 QApplication::restoreOverrideCursor();
3180 return 0;
3181 }
3182
importASCII()3183 void ApplicationWindow::importASCII()
3184 {
3185 ImportASCIIDialog *import_dialog = new ImportASCIIDialog(
3186 d_workspace.currentSubWindow() && d_workspace.currentSubWindow()->inherits("Table"),
3187 this, d_extended_import_ASCII_dialog);
3188 import_dialog->setDirectory(asciiDirPath);
3189 import_dialog->selectNameFilter(d_ASCII_file_filter);
3190 if (import_dialog->exec() != QDialog::Accepted)
3191 return;
3192
3193 asciiDirPath = import_dialog->directory().path();
3194 if (import_dialog->rememberOptions()) {
3195 columnSeparator = import_dialog->columnSeparator();
3196 ignoredLines = import_dialog->ignoredLines();
3197 renameColumns = import_dialog->renameColumns();
3198 strip_spaces = import_dialog->stripSpaces();
3199 simplify_spaces = import_dialog->simplifySpaces();
3200 d_ASCII_import_locale = import_dialog->decimalSeparators();
3201 d_convert_to_numeric = import_dialog->convertToNumeric();
3202 saveSettings();
3203 }
3204
3205 QLocale save_locale = QLocale();
3206 QLocale::setDefault(import_dialog->decimalSeparators());
3207 importASCII(import_dialog->selectedFiles(), import_dialog->importMode(),
3208 import_dialog->columnSeparator(), import_dialog->ignoredLines(),
3209 import_dialog->renameColumns(), import_dialog->stripSpaces(),
3210 import_dialog->simplifySpaces(), import_dialog->convertToNumeric(),
3211 import_dialog->decimalSeparators());
3212 QLocale::setDefault(save_locale);
3213 }
3214
importASCII(const QStringList & files,int import_mode,const QString & local_column_separator,int local_ignored_lines,bool local_rename_columns,bool local_strip_spaces,bool local_simplify_spaces,bool local_convert_to_numeric,QLocale local_numeric_locale)3215 void ApplicationWindow::importASCII(const QStringList &files, int import_mode,
3216 const QString &local_column_separator, int local_ignored_lines,
3217 bool local_rename_columns, bool local_strip_spaces,
3218 bool local_simplify_spaces, bool local_convert_to_numeric,
3219 QLocale local_numeric_locale)
3220 {
3221 if (files.isEmpty())
3222 return;
3223
3224 // this is very much a special case, and thus is handled completely in its own block
3225 if (import_mode == ImportASCIIDialog::NewTables) {
3226 int dx = 0, dy = 0;
3227 QStringList sorted_files = files;
3228 sorted_files.sort();
3229 for (int i = 0; i < sorted_files.size(); i++) {
3230 Table *w = newTable(sorted_files[i], local_column_separator, local_ignored_lines,
3231 local_rename_columns, local_strip_spaces, local_simplify_spaces,
3232 local_convert_to_numeric, local_numeric_locale);
3233 if (!w)
3234 continue;
3235 w->setCaptionPolicy(MyWidget::Both);
3236 setListViewLabel(w->name(), sorted_files[i]);
3237 if (i == 0) {
3238 dx = w->verticalHeaderWidth();
3239 dy = w->frameGeometry().height() - w->height();
3240 w->move(QPoint(0, 0));
3241 } else
3242 w->move(QPoint(i * dx, i * dy));
3243 }
3244 modifiedProject();
3245 return;
3246 }
3247
3248 Table *table = qobject_cast<Table *>(d_workspace.currentSubWindow());
3249 if (!table)
3250 return;
3251
3252 foreach (QString file, files) {
3253 Table *temp = new Table(scriptEnv, file, local_column_separator, local_ignored_lines,
3254 local_rename_columns, local_strip_spaces, local_simplify_spaces,
3255 local_convert_to_numeric, local_numeric_locale, "temp");
3256 if (!temp)
3257 continue;
3258
3259 // need to check data types of columns for append/overwrite
3260 if (import_mode == ImportASCIIDialog::NewRows
3261 || import_mode == ImportASCIIDialog::Overwrite) {
3262 if (local_convert_to_numeric) {
3263 for (int col = 0; col < qMin(temp->columnCount(), table->columnCount()); col++)
3264 if (table->column(col)->columnMode() != SciDAVis::ColumnMode::Numeric) {
3265 QMessageBox::critical(this, tr("ASCII Import Failed"),
3266 tr("Numeric data cannot be imported into non-numeric "
3267 "column \"%1\".")
3268 .arg(table->column(col)->name()));
3269 delete temp;
3270 return;
3271 }
3272 } else {
3273 for (int col = 0; col < qMin(temp->columnCount(), table->columnCount()); col++)
3274 if (table->column(col)->columnMode() != SciDAVis::ColumnMode::Text) {
3275 QMessageBox::critical(this, tr("ASCII Import Failed"),
3276 tr("Non-numeric data cannot be imported into "
3277 "non-text column \"%1\".")
3278 .arg(table->column(col)->name()));
3279 delete temp;
3280 return;
3281 }
3282 }
3283 }
3284
3285 // copy or move data from temp to table
3286 switch (import_mode) {
3287 case ImportASCIIDialog::NewColumns:
3288 while (temp->d_future_table->childCount() > 0)
3289 temp->d_future_table->reparentChild(table->d_future_table,
3290 temp->d_future_table->child(0));
3291 break;
3292 case ImportASCIIDialog::NewRows: {
3293 int missing_columns = temp->columnCount() - table->columnCount();
3294 for (int col = 0; col < missing_columns; col++) {
3295 Column *new_col =
3296 new Column(tr("new_by_import") + QString::number(col + 1),
3297 local_convert_to_numeric ? SciDAVis::ColumnMode::Numeric : SciDAVis::ColumnMode::Text);
3298 new_col->setPlotDesignation(SciDAVis::Y);
3299 table->d_future_table->addChild(new_col);
3300 }
3301 Q_ASSERT(table->columnCount() >= temp->columnCount());
3302 int start_row = table->rowCount();
3303 table->d_future_table->setRowCount(table->rowCount() + temp->rowCount());
3304 for (int col = 0; col < temp->columnCount(); col++) {
3305 Column *src_col = temp->column(col);
3306 Column *dst_col = table->column(col);
3307 Q_ASSERT(src_col->dataType() == dst_col->dataType());
3308 dst_col->copy(src_col, 0, start_row, src_col->rowCount());
3309 if (local_rename_columns)
3310 dst_col->setName(src_col->name());
3311 }
3312 break;
3313 }
3314 case ImportASCIIDialog::Overwrite: {
3315 if (table->rowCount() < temp->rowCount())
3316 table->d_future_table->setRowCount(temp->rowCount());
3317 for (int col = 0; col < table->columnCount() && col < temp->columnCount(); col++) {
3318 Column *src_col = temp->column(col);
3319 Column *dst_col = table->column(col);
3320 Q_ASSERT(src_col->dataType() == dst_col->dataType());
3321 dst_col->copy(src_col, 0, 0, temp->rowCount());
3322 if (local_rename_columns)
3323 dst_col->setName(src_col->name());
3324 }
3325 if (temp->columnCount() > table->columnCount()) {
3326 temp->d_future_table->removeColumns(0, table->columnCount());
3327 while (temp->d_future_table->childCount() > 0)
3328 temp->d_future_table->reparentChild(table->d_future_table,
3329 temp->d_future_table->child(0));
3330 }
3331 break;
3332 }
3333 }
3334 delete temp;
3335 }
3336
3337 table->setWindowLabel(files.join("; "));
3338 table->notifyChanges();
3339 modifiedProject(table);
3340 modifiedProject();
3341 }
3342
open()3343 void ApplicationWindow::open()
3344 {
3345 OpenProjectDialog *open_dialog = new OpenProjectDialog(this, d_extended_open_dialog);
3346 open_dialog->setDirectory(workingDir);
3347 auto &settings = getSettings();
3348 open_dialog->setCodec(settings.value("/General/Dialogs/LastUsedOriginLocale", "").toString());
3349 if (open_dialog->exec() != QDialog::Accepted || open_dialog->selectedFiles().isEmpty())
3350 return;
3351 workingDir = open_dialog->directory().path();
3352 settings.setValue("/General/Dialogs/LastUsedOriginLocale", open_dialog->codec());
3353
3354 switch (open_dialog->openMode()) {
3355 case OpenProjectDialog::NewProject: {
3356 QString fn = open_dialog->selectedFiles()[0];
3357 QFileInfo fi(fn);
3358
3359 if (projectname != "untitled") {
3360 QFileInfo fi(projectname);
3361 QString pn = fi.absolutePath();
3362 if (fn == pn) {
3363 QMessageBox::warning(this, tr("File opening error"),
3364 tr("The file: <b>%1</b> is the current file!").arg(fn));
3365 return;
3366 }
3367 }
3368
3369 if (fn.endsWith(".sciprj", Qt::CaseInsensitive)
3370 || fn.endsWith(".sciprj~", Qt::CaseInsensitive)
3371 || fn.endsWith(".qti", Qt::CaseInsensitive) || fn.endsWith(".qti~", Qt::CaseInsensitive)
3372 || fn.endsWith(".sciprj.gz", Qt::CaseInsensitive)
3373 || fn.endsWith(".qti.gz", Qt::CaseInsensitive)
3374 || fn.endsWith(".opj", Qt::CaseInsensitive) || fn.endsWith(".ogm", Qt::CaseInsensitive)
3375 || fn.endsWith(".ogw", Qt::CaseInsensitive) || fn.endsWith(".ogg", Qt::CaseInsensitive)
3376 || fn.endsWith(".org", Qt::CaseInsensitive)) {
3377 if (!fi.exists()) {
3378 QMessageBox::critical(this, tr("File opening error"),
3379 tr("The file: <b>%1</b> doesn't exist!").arg(fn));
3380 return;
3381 }
3382
3383 saveSettings(); // the recent projects must be saved
3384
3385 ApplicationWindow *a = open(fn);
3386 if (a) {
3387 a->workingDir = workingDir;
3388 if (fn.endsWith(".sciprj", Qt::CaseInsensitive)
3389 || fn.endsWith(".sciprj~", Qt::CaseInsensitive)
3390 || fn.endsWith(".sciprj.gz", Qt::CaseInsensitive)
3391 || fn.endsWith(".qti.gz", Qt::CaseInsensitive)
3392 || fn.endsWith(".qti", Qt::CaseInsensitive)
3393 || fn.endsWith(".qti~", Qt::CaseInsensitive)
3394 || fn.endsWith(".opj", Qt::CaseInsensitive)
3395 || fn.endsWith(".ogg", Qt::CaseInsensitive)
3396 || fn.endsWith(".org", Qt::CaseInsensitive))
3397 this->close();
3398 }
3399 } else {
3400 QMessageBox::critical(this, tr("File opening error"),
3401 tr("The file <b>%1</b> is not a valid project file.").arg(fn));
3402 return;
3403 }
3404 break;
3405 }
3406 case OpenProjectDialog::NewFolder:
3407 appendProject(open_dialog->selectedFiles()[0]);
3408 break;
3409 }
3410 }
3411
open(const QString & fn,const QStringList & scriptArgs)3412 ApplicationWindow *ApplicationWindow::open(const QString &fn, const QStringList &scriptArgs)
3413 {
3414 if (fn.endsWith(".opj", Qt::CaseInsensitive) || fn.endsWith(".ogm", Qt::CaseInsensitive)
3415 || fn.endsWith(".ogw", Qt::CaseInsensitive) || fn.endsWith(".ogg", Qt::CaseInsensitive)
3416 || fn.endsWith(".org", Qt::CaseInsensitive))
3417 #ifdef ORIGIN_IMPORT
3418 return importOPJ(fn);
3419 #else
3420 {
3421 QMessageBox::critical(
3422 this, tr("File opening error"),
3423 tr("SciDAVis currently does not support Origin import. If you are interested in "
3424 "reviving and maintaining an Origin import filter, contact the developers.")
3425 .arg(fn));
3426 return 0;
3427 }
3428 #endif
3429 else if (fn.endsWith(".py", Qt::CaseInsensitive))
3430 return loadScript(fn, scriptArgs);
3431 else if (fn.endsWith(".sciprj", Qt::CaseInsensitive)
3432 || fn.endsWith(".sciprj.gz", Qt::CaseInsensitive)
3433 || fn.endsWith(".qti", Qt::CaseInsensitive)
3434 || fn.endsWith(".qti.gz", Qt::CaseInsensitive)
3435 || fn.endsWith(".sciprj~", Qt::CaseInsensitive)
3436 || fn.endsWith(".sciprj.gz~", Qt::CaseInsensitive)
3437 || fn.endsWith(".qti~", Qt::CaseInsensitive)
3438 || fn.endsWith(".qti.gz~", Qt::CaseInsensitive))
3439 return openProject(fn);
3440 else
3441 return plotFile(fn);
3442 }
3443
openRecentProject()3444 void ApplicationWindow::openRecentProject()
3445 {
3446 QAction *trigger = qobject_cast<QAction *>(sender());
3447 if (!trigger)
3448 return;
3449 QString fn = trigger->text();
3450 int pos = fn.indexOf(" ", 0);
3451 fn = fn.right(fn.length() - pos - 1);
3452
3453 QFile f(fn);
3454 if (!f.exists()) {
3455 QMessageBox::critical(this, tr("File Open Error"),
3456 tr("The file: <b> %1 </b> <p>does not exist anymore!"
3457 "<p>It will be removed from the list.")
3458 .arg(fn));
3459
3460 recentProjects.removeAll(fn);
3461 updateRecentProjectsList();
3462 return;
3463 }
3464
3465 if (projectname != "untitled") {
3466 QFileInfo fi(projectname);
3467 QString pn = fi.absolutePath();
3468 if (fn == pn) {
3469 QMessageBox::warning(this, tr("File opening error"),
3470 tr("The file: <p><b> %1 </b><p> is the current file!").arg(fn));
3471 return;
3472 }
3473 }
3474
3475 if (!fn.isEmpty()) {
3476 saveSettings(); // the recent projects must be saved
3477 ApplicationWindow *a = open(fn);
3478 if (a
3479 && (fn.endsWith(".sciprj", Qt::CaseInsensitive)
3480 || fn.endsWith(".sciprj~", Qt::CaseInsensitive)
3481 || fn.endsWith(".sciprj.gz", Qt::CaseInsensitive)
3482 || fn.endsWith(".qti.gz", Qt::CaseInsensitive)
3483 || fn.endsWith(".qti", Qt::CaseInsensitive)
3484 || fn.endsWith(".qti~", Qt::CaseInsensitive)
3485 || fn.endsWith(".opj", Qt::CaseInsensitive)
3486 || fn.endsWith(".ogg", Qt::CaseInsensitive)
3487 || fn.endsWith(".org", Qt::CaseInsensitive)))
3488 this->close();
3489 }
3490 }
3491
openCompressedFile(const QString & fn)3492 QFile *ApplicationWindow::openCompressedFile(const QString &fn)
3493 {
3494 QTemporaryFile *file;
3495 char buf[16384];
3496 int len, err;
3497
3498 gzFile in = gzopen(QFile::encodeName(fn).constData(), "rb");
3499 if (!in) {
3500 QMessageBox::critical(this, tr("File opening error"), tr("zlib can't open %1.").arg(fn));
3501 return 0;
3502 }
3503 file = new QTemporaryFile();
3504 if (!file || !file->open()) {
3505 gzclose(in);
3506 QMessageBox::critical(
3507 this, tr("File opening error"),
3508 tr("Can't create temporary file for writing uncompressed copy of %1.").arg(fn));
3509 return 0;
3510 }
3511
3512 forever {
3513 len = gzread(in, buf, sizeof(buf));
3514 if (len == 0)
3515 break;
3516 if (len < 0) {
3517 QMessageBox::critical(this, tr("File opening error"), gzerror(in, &err));
3518 gzclose(in);
3519 file->close();
3520 delete file;
3521 return 0;
3522 }
3523 if (file->write(buf, len) != len) {
3524 QMessageBox::critical(
3525 this, tr("File opening error"),
3526 tr("Error writing to temporary file: %1").arg(file->errorString()));
3527 gzclose(in);
3528 file->close();
3529 delete file;
3530 return 0;
3531 }
3532 }
3533
3534 gzclose(in);
3535 file->reset();
3536 return file;
3537 }
3538
loadProject(const QString & fn)3539 bool ApplicationWindow::loadProject(const QString &fn)
3540 {
3541 unique_ptr<QFile> file;
3542
3543 if (fn.endsWith(".gz", Qt::CaseInsensitive) || fn.endsWith(".gz~", Qt::CaseInsensitive)) {
3544 file.reset(openCompressedFile(fn));
3545 if (!file)
3546 return false;
3547 } else {
3548 file.reset(new QFile(fn));
3549 if (!file->open(QIODevice::ReadOnly)) {
3550 QMessageBox::critical(this, tr("File opening error"), file->errorString());
3551 return false;
3552 }
3553 }
3554
3555 QTextStream t(file.get());
3556 t.setCodec(QTextCodec::codecForName("UTF-8"));
3557 QString s;
3558 QStringList list;
3559
3560 s = t.readLine();
3561 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
3562 list = s.split(QRegExp("\\s"), Qt::SkipEmptyParts);
3563 #else
3564 list = s.split(QRegExp("\\s"), QString::SkipEmptyParts);
3565 #endif
3566 if (list.count() < 2 || (list[0] != "SciDAVis" && list[0] != "QtiPlot")) {
3567 if (QFile::exists(fn + "~")) {
3568 int choice = QMessageBox::question(
3569 this, tr("File opening error"),
3570 tr("The file <b>%1</b> is corrupted, but there exists a backup copy.<br>Do you "
3571 "want to open the backup instead?")
3572 .arg(fn),
3573 QMessageBox::Yes | QMessageBox::Default, QMessageBox::No | QMessageBox::Escape);
3574 if (choice == QMessageBox::Yes) {
3575 QMessageBox::information(
3576 this, tr("Opening backup copy"),
3577 tr("The original (corrupt) file is being left untouched, in case you want "
3578 "to "
3579 "try rescuing data manually. If you want to continue working with the "
3580 "automatically restored backup copy, you have to explicitly overwrite "
3581 "the "
3582 "original file."));
3583 return loadProject(fn + "~");
3584 }
3585 }
3586 QMessageBox::critical(this, tr("File opening error"),
3587 tr("The file <b>%1</b> is not a valid project file.").arg(fn));
3588 return false;
3589 }
3590
3591 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
3592 QStringList vl = list[1].split(".", Qt::SkipEmptyParts);
3593 #else
3594 QStringList vl = list[1].split(".", QString::SkipEmptyParts);
3595 #endif
3596 if (fn.endsWith(".qti", Qt::CaseInsensitive) || fn.endsWith(".qti.gz", Qt::CaseInsensitive)
3597 || fn.endsWith(".qti~", Qt::CaseInsensitive)
3598 || fn.endsWith(".qti.gz~", Qt::CaseInsensitive)) {
3599 d_file_version = 100 * (vl[0]).toInt() + 10 * (vl[1]).toInt() + (vl[2]).toInt();
3600 if (d_file_version > 90) {
3601 QMessageBox::critical(this, tr("File opening error"),
3602 tr("SciDAVis does not support QtiPlot project files from "
3603 "versions later than 0.9.0.")
3604 .arg(fn));
3605 return false;
3606 }
3607 } else
3608 d_file_version = ((vl[0]).toInt() << 16) + ((vl[1]).toInt() << 8) + (vl[2]).toInt();
3609
3610 projectname = fn;
3611 setWindowTitle(tr("SciDAVis") + " - " + fn);
3612
3613 QFileInfo fi(fn);
3614 QString baseName = fi.fileName();
3615
3616 if (d_file_version < 73)
3617 t.readLine();
3618
3619 s = t.readLine();
3620 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
3621 list = s.split("\t", Qt::SkipEmptyParts);
3622 #else
3623 list = s.split("\t", QString::SkipEmptyParts);
3624 #endif
3625 if (list[0] == "<scripting-lang>") {
3626 if (!setScriptingLang(list[1], true))
3627 QMessageBox::warning(
3628 this, tr("File opening error"),
3629 tr("The file \"%1\" was created using \"%2\" as scripting language.\n\n"
3630 "Initializing support for this language FAILED; I'm using \"%3\" instead.\n"
3631 "Various parts of this file may not be displayed as expected.")
3632 .arg(fn)
3633 .arg(list[1])
3634 .arg(scriptEnv->objectName()));
3635
3636 s = t.readLine();
3637 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
3638 list = s.split("\t", Qt::SkipEmptyParts);
3639 #else
3640 list = s.split("\t", QString::SkipEmptyParts);
3641 #endif
3642 }
3643 int aux = 0, widgets = list[1].toInt();
3644
3645 QString titleBase = tr("Window") + ": ";
3646 QString title = titleBase + "1/" + QString::number(widgets) + " ";
3647
3648 QProgressDialog progress; /*(this);*/
3649 progress.setWindowModality(Qt::WindowModal);
3650 progress.setRange(0, widgets);
3651 progress.setMinimumWidth(width() / 2);
3652 progress.setWindowTitle(tr("Opening file") + ": " + baseName);
3653 progress.setLabelText(title);
3654 progress.activateWindow();
3655
3656 Folder *cf = projectFolder();
3657 folders.blockSignals(true);
3658 blockSignals(true);
3659 // rename project folder item
3660 FolderListItem *item = (FolderListItem *)folders.topLevelItem(0);
3661 item->setText(0, fi.baseName());
3662 item->folder()->setName(fi.baseName());
3663
3664 // process tables and matrix information
3665 while (!t.atEnd() && !progress.wasCanceled()) {
3666 s = t.readLine(4096); // workaround for safely reading very big lines
3667 list.clear();
3668 if (s.left(8) == "<folder>") {
3669 list = s.split("\t");
3670 Folder &f = current_folder->addChild<Folder>(list[1]);
3671 f.setBirthDate(list[2]);
3672 f.setModificationDate(list[3]);
3673 if (list.count() > 4)
3674 if (list[4] == "current")
3675 cf = &f;
3676
3677 FolderListItem *fli = new FolderListItem(current_folder->folderListItem(), &f);
3678 fli->setText(0, list[1]);
3679 f.setFolderListItem(fli);
3680
3681 current_folder = &f;
3682 } else if (s == "<table>") {
3683 title = titleBase + QString::number(++aux) + "/" + QString::number(widgets);
3684 progress.setLabelText(title);
3685
3686 openTable(this, t);
3687 progress.setValue(aux);
3688 } else if (s.left(17) == "<TableStatistics>") {
3689 QStringList lst;
3690 while (s != "</TableStatistics>") {
3691 s = t.readLine();
3692 lst << s;
3693 }
3694 lst.pop_back();
3695 openTableStatistics(lst);
3696 } else if (s == "<matrix>") {
3697 title = titleBase + QString::number(++aux) + "/" + QString::number(widgets);
3698 progress.setLabelText(title);
3699 QStringList lst;
3700 while (s != "</matrix>") {
3701 s = t.readLine();
3702 lst << s;
3703 }
3704 lst.pop_back();
3705 openMatrix(this, lst);
3706 progress.setValue(aux);
3707 } else if (s == "<note>") {
3708 title = titleBase + QString::number(++aux) + "/" + QString::number(widgets);
3709 progress.setLabelText(title);
3710 for (int i = 0; i < 3; i++) {
3711 s = t.readLine();
3712 list << s;
3713 }
3714 Note *m = openNote(this, list);
3715 QStringList cont;
3716 while (s != "</note>") {
3717 s = t.readLine();
3718 cont << s;
3719 }
3720 cont.pop_back();
3721 m->restore(cont);
3722 progress.setValue(aux);
3723 } else if (s == "</folder>") {
3724 Folder *parent = (Folder *)current_folder->parent();
3725 if (!parent)
3726 current_folder = projectFolder();
3727 else
3728 current_folder = parent;
3729 }
3730 }
3731
3732 if (progress.wasCanceled()) {
3733 saved = true;
3734 close();
3735 return false;
3736 }
3737
3738 // process the rest
3739 t.seek(0);
3740
3741 MultiLayer *plot = 0;
3742 while (!t.atEnd() && !progress.wasCanceled()) {
3743 s = t.readLine(4096); // workaround for safely reading very big lines
3744 if (s.left(8) == "<folder>") {
3745 list = s.split("\t");
3746 current_folder = current_folder->findSubfolder(list[1]);
3747 } else if (s == "<multiLayer>") { // process multilayers information
3748 title = titleBase + QString::number(++aux) + "/" + QString::number(widgets);
3749 progress.setLabelText(title);
3750
3751 s = t.readLine();
3752 QStringList graph = s.split("\t");
3753 QString caption = graph[0];
3754 plot = multilayerPlot(caption);
3755 plot->setCols(graph[1].toInt());
3756 plot->setRows(graph[2].toInt());
3757
3758 setListViewDate(caption, graph[3]);
3759 plot->setBirthDate(graph[3]);
3760
3761 restoreWindowGeometry(this, plot, t.readLine());
3762 plot->blockSignals(true);
3763
3764 if (d_file_version > 71) {
3765 QStringList lst = t.readLine().split("\t");
3766 plot->setWindowLabel(lst[1]);
3767 setListViewLabel(plot->name(), lst[1]);
3768 if (lst.length() > 2) {
3769 plot->setCaptionPolicy((MyWidget::CaptionPolicy)lst[2].toInt());
3770 } else {
3771 QMessageBox::warning(this, tr("File opening error"),
3772 tr("Invalid WindowLabel line:\n'%1'\nin file %2.")
3773 .arg(lst.join(" "))
3774 .arg(fn));
3775 plot->setCaptionPolicy(MyWidget::CaptionPolicy::Name);
3776 // Partial fix for sf #403
3777 t.readLine();
3778 }
3779 }
3780 if (d_file_version > 83) {
3781 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
3782 QStringList lst = t.readLine().split("\t", Qt::SkipEmptyParts);
3783 plot->setMargins(lst[1].toInt(), lst[2].toInt(), lst[3].toInt(), lst[4].toInt());
3784 lst = t.readLine().split("\t", Qt::SkipEmptyParts);
3785 plot->setSpacing(lst[1].toInt(), lst[2].toInt());
3786 lst = t.readLine().split("\t", Qt::SkipEmptyParts);
3787 plot->setLayerCanvasSize(lst[1].toInt(), lst[2].toInt());
3788 lst = t.readLine().split("\t", Qt::SkipEmptyParts);
3789 plot->setAlignement(lst[1].toInt(), lst[2].toInt());
3790 #else
3791 QStringList lst = t.readLine().split("\t", QString::SkipEmptyParts);
3792 plot->setMargins(lst[1].toInt(), lst[2].toInt(), lst[3].toInt(), lst[4].toInt());
3793 lst = t.readLine().split("\t", QString::SkipEmptyParts);
3794 plot->setSpacing(lst[1].toInt(), lst[2].toInt());
3795 lst = t.readLine().split("\t", QString::SkipEmptyParts);
3796 plot->setLayerCanvasSize(lst[1].toInt(), lst[2].toInt());
3797 lst = t.readLine().split("\t", QString::SkipEmptyParts);
3798 plot->setAlignement(lst[1].toInt(), lst[2].toInt());
3799 #endif
3800 }
3801
3802 while (s != "</multiLayer>") { // open layers
3803 s = t.readLine();
3804 if (s.left(7) == "<graph>") {
3805 list.clear();
3806 while (s != "</graph>") {
3807 s = t.readLine();
3808 list << s;
3809 }
3810 openGraph(this, plot, list);
3811 }
3812 }
3813 plot->blockSignals(false);
3814 activateSubWindow(plot);
3815 progress.setValue(aux);
3816 } else if (s == "<SurfacePlot>") { // process 3D plots information
3817 list.clear();
3818 title = titleBase + QString::number(++aux) + "/" + QString::number(widgets);
3819 progress.setLabelText(title);
3820 while (s != "</SurfacePlot>") {
3821 s = t.readLine();
3822 list << s;
3823 }
3824 openSurfacePlot(this, list);
3825 progress.setValue(aux);
3826 } else if (s == "</folder>") {
3827 Folder *parent = (Folder *)current_folder->parent();
3828 if (!parent)
3829 current_folder = projectFolder();
3830 else
3831 current_folder = parent;
3832 } else if (s.left(5) == "<log>") { // process analysis information
3833 s = t.readLine();
3834 while (s != "</log>") {
3835 logInfo += s + "\n";
3836 s = t.readLine();
3837 }
3838 results->setText(logInfo);
3839 }
3840 }
3841
3842 if (progress.wasCanceled()) {
3843 saved = true;
3844 close();
3845 return false;
3846 }
3847
3848 logInfo = logInfo.remove("</log>\n", Qt::CaseInsensitive);
3849
3850 folders.setCurrentItem(cf->folderListItem());
3851 folders.blockSignals(false);
3852 // change folder to user defined current folder
3853 changeFolder(cf, true);
3854
3855 blockSignals(false);
3856 renamedTables.clear();
3857
3858 show();
3859 executeNotes();
3860 savedProject();
3861
3862 recentProjects.removeAll(fn);
3863 recentProjects.push_front(fn);
3864 updateRecentProjectsList();
3865
3866 return true;
3867 }
3868
openProject(const QString & fn)3869 ApplicationWindow *ApplicationWindow::openProject(const QString &fn)
3870 {
3871 unique_ptr<ApplicationWindow> app(new ApplicationWindow);
3872 app->applyUserSettings();
3873 return app->loadProject(fn) ? app.release() : nullptr;
3874 }
3875
executeNotes()3876 void ApplicationWindow::executeNotes()
3877 {
3878 QList<MyWidget *> lst = projectFolder()->windowsList();
3879 foreach (MyWidget *widget, lst)
3880 if (widget->inherits("Note") && ((Note *)widget)->autoexec())
3881 ((Note *)widget)->executeAll();
3882 }
3883
scriptError(const QString & message,const QString & scriptName,int lineNumber)3884 void ApplicationWindow::scriptError(const QString &message, const QString &scriptName,
3885 int lineNumber)
3886 {
3887 Q_UNUSED(scriptName)
3888 Q_UNUSED(lineNumber)
3889 QMessageBox::critical(this, tr("SciDAVis") + " - " + tr("Script Error"), message);
3890 }
3891
scriptPrint(const QString & text)3892 void ApplicationWindow::scriptPrint(const QString &text)
3893 {
3894 #ifdef SCRIPTING_CONSOLE
3895 if (!text.isEmpty())
3896 console.insertPlainText(text);
3897 #else
3898 printf(text.toUtf8().constData());
3899 #endif
3900 }
3901
setScriptingLang(const QString & lang,bool force,bool batch)3902 bool ApplicationWindow::setScriptingLang(const QString &lang, bool force, bool batch)
3903 {
3904 if (!force && lang == scriptEnv->objectName())
3905 return true;
3906 if (lang.isEmpty())
3907 return false;
3908
3909 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
3910
3911 ScriptingEnv *newEnv = ScriptingLangManager::newEnv(lang.toStdString(), this, batch);
3912 if (!newEnv) {
3913 QApplication::restoreOverrideCursor();
3914 return false;
3915 }
3916
3917 connect(newEnv, SIGNAL(error(const QString &, const QString &, int)), this,
3918 SLOT(scriptError(const QString &, const QString &, int)));
3919 connect(newEnv, SIGNAL(print(const QString &)), this, SLOT(scriptPrint(const QString &)));
3920 if (!newEnv->initialize()) {
3921 QApplication::restoreOverrideCursor();
3922 return false;
3923 }
3924
3925 // notify everyone who might be interested
3926 ScriptingChangeEvent sce(newEnv);
3927 QApplication::sendEvent(this, &sce);
3928
3929 foreach (QObject *i, findChildren<QWidget *>())
3930 QApplication::postEvent(i, new ScriptingChangeEvent(newEnv));
3931
3932 QApplication::restoreOverrideCursor();
3933
3934 return true;
3935 }
3936
showScriptingLangDialog()3937 void ApplicationWindow::showScriptingLangDialog()
3938 {
3939 ScriptingLangDialog *d = new ScriptingLangDialog(scriptEnv, this);
3940 d->showNormal();
3941 d->activateWindow();
3942 }
3943
restartScriptingEnv()3944 void ApplicationWindow::restartScriptingEnv()
3945 {
3946 if (setScriptingLang(scriptEnv->objectName(), true))
3947 executeNotes();
3948 else
3949 QMessageBox::critical(
3950 this, tr("Scripting Error"),
3951 tr("Scripting language \"%1\" failed to initialize.").arg(scriptEnv->objectName()));
3952 }
3953
3954 // TODO: rewrite the template system
openTemplate()3955 void ApplicationWindow::openTemplate()
3956 {
3957 QString filter = "SciDAVis/QtiPlot 2D Graph Template (*.qpt);;";
3958 filter += "SciDAVis/QtiPlot 3D Surface Template (*.qst);;";
3959 filter += "SciDAVis/QtiPlot Table Template (*.qtt);;";
3960 filter += "SciDAVis/QtiPlot Matrix Template (*.qmt)";
3961
3962 QString fn = QFileDialog::getOpenFileName(this, tr("Open Template File"), templatesDir, filter);
3963 if (!fn.isEmpty()) {
3964 QFileInfo fi(fn);
3965 templatesDir = fi.absolutePath();
3966 if (fn.contains(".qmt", Qt::CaseSensitive) || fn.contains(".qpt", Qt::CaseSensitive)
3967 || fn.contains(".qtt", Qt::CaseSensitive) || fn.contains(".qst", Qt::CaseSensitive)) {
3968 if (!fi.exists()) {
3969 QMessageBox::critical(this, tr("File opening error"),
3970 tr("The file: <b>%1</b> doesn't exist!").arg(fn));
3971 return;
3972 }
3973 QFile f(fn);
3974 QTextStream t(&f);
3975 t.setCodec(QTextCodec::codecForName("UTF-8"));
3976 f.open(QIODevice::ReadOnly);
3977 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
3978 QStringList l = t.readLine().split(QRegExp("\\s"), Qt::SkipEmptyParts);
3979 #else
3980 QStringList l = t.readLine().split(QRegExp("\\s"), QString::SkipEmptyParts);
3981 #endif
3982 QString fileType = l[0];
3983 if ((fileType != "SciDAVis") && (fileType != "QtiPlot")) {
3984 QMessageBox::critical(
3985 this, tr("File opening error"),
3986 tr("The file: <b> %1 </b> was not created using SciDAVis!").arg(fn));
3987 return;
3988 }
3989 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
3990 QStringList vl = l[1].split(".", Qt::SkipEmptyParts);
3991 #else
3992 QStringList vl = l[1].split(".", QString::SkipEmptyParts);
3993 #endif
3994 if (fileType == "QtiPlot") {
3995 d_file_version = 100 * (vl[0]).toInt() + 10 * (vl[1]).toInt() + (vl[2]).toInt();
3996 if (d_file_version > 90) {
3997 QMessageBox::critical(this, tr("File opening error"),
3998 tr("SciDAVis does not support QtiPlot template files "
3999 "from versions later than 0.9.0.")
4000 .arg(fn));
4001 return;
4002 }
4003 } else
4004 d_file_version = ((vl[0]).toInt() << 16) + ((vl[1]).toInt() << 8) + (vl[2]).toInt();
4005
4006 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
4007
4008 MyWidget *w = 0;
4009 QString templateType;
4010 t >> templateType;
4011
4012 if (templateType == "<SurfacePlot>") {
4013 t.skipWhiteSpace();
4014 QStringList lst;
4015 while (!t.atEnd())
4016 lst << t.readLine();
4017 w = openSurfacePlot(this, lst);
4018 if (w)
4019 ((Graph3D *)w)->clearData();
4020 } else {
4021 int rows, cols;
4022 t >> rows;
4023 t >> cols;
4024 t.skipWhiteSpace();
4025 QString geometry = t.readLine();
4026
4027 if (templateType == "<multiLayer>") { // FIXME: workarounds for template
4028 w = new MultiLayer("", &d_workspace, 0);
4029 w->setAttribute(Qt::WA_DeleteOnClose);
4030 QString label = generateUniqueName(tr("Graph"));
4031 initBareMultilayerPlot((MultiLayer *)w, label.replace(QRegExp("_"), "-"));
4032 if (w) {
4033 ((MultiLayer *)w)->setCols(cols);
4034 ((MultiLayer *)w)->setRows(rows);
4035 restoreWindowGeometry(this, w, geometry);
4036 if (d_file_version > 83) {
4037 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
4038 QStringList lst = t.readLine().split("\t", Qt::SkipEmptyParts);
4039 ((MultiLayer *)w)
4040 ->setMargins(lst[1].toInt(), lst[2].toInt(), lst[3].toInt(),
4041 lst[4].toInt());
4042 lst = t.readLine().split("\t", Qt::SkipEmptyParts);
4043 ((MultiLayer *)w)->setSpacing(lst[1].toInt(), lst[2].toInt());
4044 lst = t.readLine().split("\t", Qt::SkipEmptyParts);
4045 ((MultiLayer *)w)->setLayerCanvasSize(lst[1].toInt(), lst[2].toInt());
4046 lst = t.readLine().split("\t", Qt::SkipEmptyParts);
4047 ((MultiLayer *)w)->setAlignement(lst[1].toInt(), lst[2].toInt());
4048 #else
4049 QStringList lst = t.readLine().split("\t", QString::SkipEmptyParts);
4050 ((MultiLayer *)w)
4051 ->setMargins(lst[1].toInt(), lst[2].toInt(), lst[3].toInt(),
4052 lst[4].toInt());
4053 lst = t.readLine().split("\t", QString::SkipEmptyParts);
4054 ((MultiLayer *)w)->setSpacing(lst[1].toInt(), lst[2].toInt());
4055 lst = t.readLine().split("\t", QString::SkipEmptyParts);
4056 ((MultiLayer *)w)->setLayerCanvasSize(lst[1].toInt(), lst[2].toInt());
4057 lst = t.readLine().split("\t", QString::SkipEmptyParts);
4058 ((MultiLayer *)w)->setAlignement(lst[1].toInt(), lst[2].toInt());
4059 #endif
4060 }
4061 while (!t.atEnd()) { // open layers
4062 QString s = t.readLine();
4063 if (s.left(7) == "<graph>") {
4064 QStringList lst;
4065 while (s != "</graph>") {
4066 s = t.readLine();
4067 lst << s;
4068 }
4069 openGraph(this, (MultiLayer *)w, lst);
4070 }
4071 }
4072 }
4073 } else {
4074 if (templateType == "<table>")
4075 w = newTable(tr("Table1"), rows, cols);
4076 else if (templateType == "<matrix>")
4077 w = newMatrix(rows, cols);
4078 if (w) {
4079 QStringList lst;
4080 while (!t.atEnd())
4081 lst << t.readLine();
4082 w->restore(lst);
4083 restoreWindowGeometry(this, w, geometry);
4084 }
4085 }
4086 }
4087
4088 f.close();
4089 if (w) {
4090 switch (w->status()) {
4091 case MyWidget::Maximized:
4092 w->setMaximized();
4093 break;
4094 case MyWidget::Minimized:
4095 w->setMinimized();
4096 break;
4097 case MyWidget::Hidden:
4098 w->setHidden();
4099 break;
4100 case MyWidget::Normal:
4101 w->setNormal();
4102 break;
4103 }
4104 customMenu((MyWidget *)w);
4105 customToolBars((MyWidget *)w);
4106 }
4107 QApplication::restoreOverrideCursor();
4108 } else {
4109 QMessageBox::critical(
4110 this, tr("File opening error"),
4111 tr("The file: <b>%1</b> is not a SciDAVis template file!").arg(fn));
4112 return;
4113 }
4114 }
4115 }
4116
readSettings()4117 void ApplicationWindow::readSettings()
4118 {
4119 auto &settings = getSettings();
4120 /* ---------------- group General --------------- */
4121 settings.beginGroup("/General");
4122 #ifdef SEARCH_FOR_UPDATES
4123 autoSearchUpdates = settings.value("/AutoSearchUpdates", false).toBool();
4124 #endif
4125 appLanguage =
4126 settings.value("/Language", QLocale::system().name().section('_', 0, 0)).toString();
4127 show_windows_policy =
4128 (ShowWindowsPolicy)settings.value("/ShowWindowsPolicy", ApplicationWindow::ActiveFolder)
4129 .toInt();
4130
4131 recentProjects = settings.value("/RecentProjects").toStringList();
4132 // Follows an ugly hack added by Ion in order to fix Qt4 porting issues
4133 //(only needed on Windows due to a Qt bug?)
4134 #ifdef Q_OS_WIN
4135 if (!recentProjects.isEmpty() && recentProjects[0].contains("^e"))
4136 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
4137 recentProjects = recentProjects[0].split("^e", Qt::SkipEmptyParts);
4138 #else
4139 recentProjects = recentProjects[0].split("^e", QString::SkipEmptyParts);
4140 #endif
4141 else if (recentProjects.count() == 1) {
4142 QString s = recentProjects[0];
4143 if (s.remove(QRegExp("\\s")).isEmpty())
4144 recentProjects = QStringList();
4145 }
4146 #endif
4147
4148 updateRecentProjectsList();
4149
4150 changeAppStyle(settings.value("/Style", appStyle).toString());
4151 undoLimit = settings.value("/UndoLimit", 10).toInt();
4152 d_project->undoStack()->setUndoLimit(undoLimit);
4153 autoSave = settings.value("/AutoSave", true).toBool();
4154 autoSaveTime = settings.value("/AutoSaveTime", 15).toInt();
4155 defaultScriptingLang = settings.value("/ScriptingLang", "muParser").toString();
4156
4157 QLocale temp_locale = QLocale(settings.value("/Locale", QLocale::system().name()).toString());
4158 bool usegl = settings.value("/LocaleUseGroupSeparator", true).toBool();
4159 if (usegl)
4160 temp_locale.setNumberOptions(temp_locale.numberOptions() & ~QLocale::OmitGroupSeparator);
4161 else
4162 temp_locale.setNumberOptions(temp_locale.numberOptions() | QLocale::OmitGroupSeparator);
4163 QLocale::setDefault(temp_locale);
4164
4165 d_decimal_digits = settings.value("/DecimalDigits", 6).toInt();
4166 d_default_numeric_format = settings.value("/DefaultNumericFormat", 'g').toChar().toLatin1();
4167
4168 // restore geometry of main window
4169 restoreGeometry(settings.value("/ProjectWindow/Geometry").toByteArray());
4170
4171 // restore dock windows and tool bars
4172 restoreState(settings.value("/DockWindows").toByteArray());
4173 explorerSplitter->restoreState(settings.value("/ExplorerSplitter").toByteArray());
4174
4175 QStringList applicationFont = settings.value("/Font").toStringList();
4176 if (applicationFont.size() == 4)
4177 appFont = QFont(applicationFont[0], applicationFont[1].toInt(), applicationFont[2].toInt(),
4178 applicationFont[3].toInt());
4179
4180 settings.beginGroup("/Dialogs");
4181 d_extended_open_dialog = settings.value("/ExtendedOpenDialog", true).toBool();
4182 d_extended_export_dialog = settings.value("/ExtendedExportDialog", true).toBool();
4183 d_extended_import_ASCII_dialog = settings.value("/ExtendedImportAsciiDialog", true).toBool();
4184 d_extended_plot_dialog =
4185 settings.value("/ExtendedPlotDialog", true).toBool(); // used by PlotDialog
4186
4187 settings.beginGroup("/AddRemoveCurves");
4188 d_add_curves_dialog_size =
4189 QSize(settings.value("/Width", 700).toInt(), settings.value("/Height", 400).toInt());
4190 d_show_current_folder = settings.value("/ShowCurrentFolder", false).toBool();
4191 settings.endGroup(); // AddRemoveCurves Dialog
4192 settings.endGroup(); // Dialogs
4193
4194 settings.beginGroup("/Colors");
4195 workspaceColor = QColor(COLORVALUE(settings.value("/Workspace", "darkGray").toString()));
4196 // see http://doc.trolltech.com/4.2/qvariant.html for instructions on qcolor <-> qvariant
4197 // conversion
4198 panelsColor = QColor(COLORVALUE(settings.value("/Panels", "#ffffffff").toString()));
4199 panelsTextColor = QColor(COLORVALUE(settings.value("/PanelsText", "#ff000000").toString()));
4200 settings.endGroup(); // Colors
4201
4202 settings.beginGroup("/Paths");
4203 workingDir = settings.value("/WorkingDir", QDir::homePath()).toString();
4204 helpFilePath = settings.value("/HelpFile", "").toString();
4205 #ifdef PLUGIN_PATH
4206 QString defaultFitPluginsPath = PLUGIN_PATH;
4207 #else // defined PLUGIN_PATH
4208 #ifdef Q_OS_WIN
4209 QString defaultFitPluginsPath = "fitPlugins";
4210 #else
4211 QString defaultFitPluginsPath = "/usr/lib/scidavis/plugins";
4212 #endif
4213 #endif // defined PLUGIN_PATH
4214 #ifdef DYNAMIC_PLUGIN_PATH
4215 fitPluginsPath = settings.value("/FitPlugins", defaultFitPluginsPath).toString();
4216 #else // defined PLUGIN_PATH
4217 fitPluginsPath = defaultFitPluginsPath;
4218 #endif
4219
4220 #ifdef Q_OS_WIN
4221 templatesDir = settings.value("/TemplatesDir", qApp->applicationDirPath()).toString();
4222 asciiDirPath = settings.value("/ASCII", qApp->applicationDirPath()).toString();
4223 imagesDirPath = settings.value("/Images", qApp->applicationDirPath()).toString();
4224 #else
4225 templatesDir = settings.value("/TemplatesDir", QDir::homePath()).toString();
4226 asciiDirPath = settings.value("/ASCII", QDir::homePath()).toString();
4227 imagesDirPath = settings.value("/Images", QDir::homePath()).toString();
4228 #endif
4229 locktoolbar->setChecked(settings.value("LockToolbars", false).toBool());
4230 settings.endGroup(); // Paths
4231 settings.endGroup();
4232 /* ------------- end group General ------------------- */
4233
4234 settings.beginGroup("/UserFunctions");
4235 fitFunctions = settings.value("/FitFunctions").toStringList();
4236 surfaceFunc = settings.value("/SurfaceFunctions").toStringList();
4237 xFunctions = settings.value("/xFunctions").toStringList();
4238 yFunctions = settings.value("/yFunctions").toStringList();
4239 rFunctions = settings.value("/rFunctions").toStringList();
4240 thetaFunctions = settings.value("/thetaFunctions").toStringList();
4241 settings.endGroup(); // UserFunctions
4242
4243 settings.beginGroup("/Confirmations");
4244 confirmCloseFolder = settings.value("/Folder", true).toBool();
4245 confirmCloseTable = settings.value("/Table", true).toBool();
4246 confirmCloseMatrix = settings.value("/Matrix", true).toBool();
4247 confirmClosePlot2D = settings.value("/Plot2D", true).toBool();
4248 confirmClosePlot3D = settings.value("/Plot3D", true).toBool();
4249 confirmCloseNotes = settings.value("/Note", true).toBool();
4250 settings.endGroup(); // Confirmations
4251
4252 /* ---------------- group Tables --------------- */
4253 settings.beginGroup("/Tables");
4254 d_show_table_comments = settings.value("/DisplayComments", false).toBool();
4255 QStringList tableFonts = settings.value("/Fonts").toStringList();
4256 if (tableFonts.size() == 8) {
4257 tableTextFont = QFont(tableFonts[0], tableFonts[1].toInt(), tableFonts[2].toInt(),
4258 tableFonts[3].toInt());
4259 tableHeaderFont = QFont(tableFonts[4], tableFonts[5].toInt(), tableFonts[6].toInt(),
4260 tableFonts[7].toInt());
4261 }
4262
4263 settings.beginGroup("/Colors");
4264 tableBkgdColor = QColor(COLORVALUE(settings.value("/Background", "#ffffffff").toString()));
4265 tableTextColor = QColor(COLORVALUE(settings.value("/Text", "#ff000000").toString()));
4266 tableHeaderColor = QColor(COLORVALUE(settings.value("/Header", "#ff000000").toString()));
4267 settings.endGroup(); // Colors
4268 settings.endGroup();
4269 /* --------------- end group Tables ------------------------ */
4270
4271 /* --------------- group 2D Plots ----------------------------- */
4272 settings.beginGroup("/2DPlots");
4273 settings.beginGroup("/General");
4274 titleOn = settings.value("/Title", true).toBool();
4275 allAxesOn = settings.value("/AllAxes", false).toBool();
4276 canvasFrameOn = settings.value("/CanvasFrame", false).toBool();
4277 canvasFrameWidth = settings.value("/CanvasFrameWidth", 0).toInt();
4278 defaultPlotMargin = settings.value("/Margin", 0).toInt();
4279 drawBackbones = settings.value("/AxesBackbones", true).toBool();
4280 axesLineWidth = settings.value("/AxesLineWidth", 1).toInt();
4281 autoscale2DPlots = settings.value("/Autoscale", true).toBool();
4282 autoScaleFonts = settings.value("/AutoScaleFonts", true).toBool();
4283 autoResizeLayers = settings.value("/AutoResizeLayers", true).toBool();
4284 antialiasing2DPlots = settings.value("/Antialiasing", true).toBool();
4285 d_scale_plots_on_print = settings.value("/ScaleLayersOnPrint", false).toBool();
4286 d_print_cropmarks = settings.value("/PrintCropmarks", false).toBool();
4287
4288 QStringList graphFonts = settings.value("/Fonts").toStringList();
4289 if (graphFonts.size() == 16) {
4290 plotAxesFont = QFont(graphFonts[0], graphFonts[1].toInt(), graphFonts[2].toInt(),
4291 graphFonts[3].toInt());
4292 plotNumbersFont = QFont(graphFonts[4], graphFonts[5].toInt(), graphFonts[6].toInt(),
4293 graphFonts[7].toInt());
4294 plotLegendFont = QFont(graphFonts[8], graphFonts[9].toInt(), graphFonts[10].toInt(),
4295 graphFonts[11].toInt());
4296 plotTitleFont = QFont(graphFonts[12], graphFonts[13].toInt(), graphFonts[14].toInt(),
4297 graphFonts[15].toInt());
4298 }
4299 settings.endGroup(); // General
4300
4301 settings.beginGroup("/Curves");
4302 defaultCurveStyle = settings.value("/Style", Graph::LineSymbols).toInt();
4303 defaultCurveLineWidth = settings.value("/LineWidth", 1).toInt();
4304 defaultSymbolSize = settings.value("/SymbolSize", 7).toInt();
4305 settings.endGroup(); // Curves
4306
4307 settings.beginGroup("/Ticks");
4308 majTicksStyle = settings.value("/MajTicksStyle", ScaleDraw::Out).toInt();
4309 minTicksStyle = settings.value("/MinTicksStyle", ScaleDraw::Out).toInt();
4310 minTicksLength = settings.value("/MinTicksLength", 5).toInt();
4311 majTicksLength = settings.value("/MajTicksLength", 9).toInt();
4312 settings.endGroup(); // Ticks
4313
4314 settings.beginGroup("/Legend");
4315 legendFrameStyle = settings.value("/FrameStyle", Legend::Line).toInt();
4316 legendTextColor = QColor(COLORVALUE(
4317 settings.value("/TextColor", "#ff000000").toString())); // default color Qt::black
4318 legendBackground = QColor(COLORVALUE(
4319 settings.value("/BackgroundColor", "#ffffffff").toString())); // default color Qt::white
4320 legendBackground.setAlpha(
4321 settings.value("/Transparency", 0).toInt()); // transparent by default;
4322 settings.endGroup(); // Legend
4323
4324 settings.beginGroup("/Arrows");
4325 defaultArrowLineWidth = settings.value("/Width", 1).toInt();
4326 defaultArrowColor = QColor(COLORVALUE(
4327 settings.value("/Color", "#ff000000").toString())); // default color Qt::black
4328 defaultArrowHeadLength = settings.value("/HeadLength", 4).toInt();
4329 defaultArrowHeadAngle = settings.value("/HeadAngle", 45).toInt();
4330 defaultArrowHeadFill = settings.value("/HeadFill", true).toBool();
4331 defaultArrowLineStyle =
4332 Graph::getPenStyle(settings.value("/LineStyle", "SolidLine").toString());
4333 settings.endGroup(); // Arrows
4334 settings.endGroup();
4335 /* ----------------- end group 2D Plots --------------------------- */
4336
4337 /* ----------------- group 3D Plots --------------------------- */
4338 settings.beginGroup("/3DPlots");
4339 showPlot3DLegend = settings.value("/Legend", true).toBool();
4340 showPlot3DProjection = settings.value("/Projection", false).toBool();
4341 smooth3DMesh = settings.value("/Antialiasing", true).toBool();
4342 plot3DResolution = settings.value("/Resolution", 1).toInt();
4343 orthogonal3DPlots = settings.value("/Orthogonal", false).toBool();
4344 autoscale3DPlots = settings.value("/Autoscale", true).toBool();
4345
4346 QStringList plot3DFonts = settings.value("/Fonts").toStringList();
4347 if (plot3DFonts.size() == 12) {
4348 plot3DTitleFont = QFont(plot3DFonts[0], plot3DFonts[1].toInt(), plot3DFonts[2].toInt(),
4349 plot3DFonts[3].toInt());
4350 plot3DNumbersFont = QFont(plot3DFonts[4], plot3DFonts[5].toInt(), plot3DFonts[6].toInt(),
4351 plot3DFonts[7].toInt());
4352 plot3DAxesFont = QFont(plot3DFonts[8], plot3DFonts[9].toInt(), plot3DFonts[10].toInt(),
4353 plot3DFonts[11].toInt());
4354 }
4355
4356 settings.beginGroup("/Colors");
4357 plot3DColors << settings.value("/MaxData", "blue").toString();
4358 plot3DColors << settings.value("/Labels", "#000000").toString();
4359 plot3DColors << settings.value("/Mesh", "#000000").toString();
4360 plot3DColors << settings.value("/Grid", "#000000").toString();
4361 plot3DColors << settings.value("/MinData", "red").toString();
4362 plot3DColors << settings.value("/Numbers", "#000000").toString();
4363 plot3DColors << settings.value("/Axes", "#000000").toString();
4364 plot3DColors << settings.value("/Background", "#ffffff").toString();
4365 settings.endGroup(); // Colors
4366 settings.endGroup();
4367 /* ----------------- end group 3D Plots --------------------------- */
4368
4369 settings.beginGroup("/Fitting");
4370 fit_output_precision = settings.value("/OutputPrecision", 15).toInt();
4371 pasteFitResultsToPlot = settings.value("/PasteResultsToPlot", false).toBool();
4372 writeFitResultsToLog = settings.value("/WriteResultsToLog", true).toBool();
4373 generateUniformFitPoints = settings.value("/GenerateFunction", true).toBool();
4374 fitPoints = settings.value("/Points", 100).toInt();
4375 generatePeakCurves = settings.value("/GeneratePeakCurves", true).toBool();
4376 peakCurvesColor = QColor(
4377 COLORVALUE(settings.value("/PeaksColor", "#ff00ff00").toString())); // green color
4378 fit_scale_errors = settings.value("/ScaleErrors", false).toBool();
4379 d_2_linear_fit_points = settings.value("/TwoPointsLinearFit", true).toBool();
4380 settings.endGroup(); // Fitting
4381
4382 settings.beginGroup("/ImportASCII");
4383 columnSeparator = settings.value("/ColumnSeparator", "\\t").toString();
4384 columnSeparator.replace("\\t", "\t").replace("\\s", " ");
4385 ignoredLines = settings.value("/IgnoreLines", 0).toInt();
4386 renameColumns = settings.value("/RenameColumns", true).toBool();
4387 strip_spaces = settings.value("/StripSpaces", false).toBool();
4388 simplify_spaces = settings.value("/SimplifySpaces", false).toBool();
4389 d_ASCII_file_filter = settings.value("/AsciiFileTypeFilter", "*").toString();
4390 d_ASCII_import_locale = settings.value("/AsciiImportLocale", "C").toString();
4391 d_convert_to_numeric = settings.value("/ConvertToNumeric", true).toBool();
4392 settings.endGroup(); // Import ASCII
4393
4394 settings.beginGroup("/ExportImage");
4395 d_image_export_filter = settings.value("/ImageFileTypeFilter", ".png").toString();
4396 d_export_transparency = settings.value("/ExportTransparency", false).toBool();
4397 d_export_quality = settings.value("/ImageQuality", 100).toInt();
4398 d_export_resolution = settings.value("/Resolution", 72).toInt();
4399 d_export_color = settings.value("/ExportColor", true).toBool();
4400 d_export_vector_size = settings.value("/ExportPageSize", QPrinter::Custom).toInt();
4401 d_keep_plot_aspect = settings.value("/KeepAspect", true).toBool();
4402 d_export_orientation = settings.value("/Orientation", QPrinter::Landscape).toInt();
4403 settings.endGroup(); // ExportImage
4404 }
4405
saveSettings()4406 void ApplicationWindow::saveSettings()
4407 {
4408 auto &settings = getSettings();
4409 /* ---------------- group General --------------- */
4410 settings.beginGroup("/General");
4411 #ifdef SEARCH_FOR_UPDATES
4412 settings.setValue("/AutoSearchUpdates", autoSearchUpdates);
4413 #endif
4414 settings.setValue("/Language", appLanguage);
4415 settings.setValue("/ShowWindowsPolicy", show_windows_policy);
4416 settings.setValue("/RecentProjects", recentProjects);
4417 settings.setValue("/Style", appStyle);
4418 settings.setValue("/AutoSave", autoSave);
4419 settings.setValue("/AutoSaveTime", autoSaveTime);
4420 settings.setValue("/UndoLimit", undoLimit);
4421 settings.setValue("/ScriptingLang", defaultScriptingLang);
4422 settings.setValue("/Locale", QLocale().name());
4423 settings.setValue("/LocaleUseGroupSeparator",
4424 bool(!(QLocale().numberOptions() & QLocale::OmitGroupSeparator)));
4425 settings.setValue("/DecimalDigits", d_decimal_digits);
4426 settings.setValue("/DefaultNumericFormat", QChar(d_default_numeric_format));
4427
4428 settings.setValue("/ProjectWindow/Geometry", saveGeometry());
4429 settings.setValue("/DockWindows", saveState());
4430 settings.setValue("/ExplorerSplitter", explorerSplitter->saveState());
4431
4432 QStringList applicationFont;
4433 applicationFont << appFont.family();
4434 applicationFont << QString::number(appFont.pointSize());
4435 applicationFont << QString::number(appFont.weight());
4436 applicationFont << QString::number(appFont.italic());
4437 settings.setValue("/Font", applicationFont);
4438
4439 settings.beginGroup("/Dialogs");
4440 settings.setValue("/ExtendedOpenDialog", d_extended_open_dialog);
4441 settings.setValue("/ExtendedExportDialog", d_extended_export_dialog);
4442 settings.setValue("/ExtendedImportAsciiDialog", d_extended_import_ASCII_dialog);
4443 settings.setValue("/ExtendedPlotDialog", d_extended_plot_dialog);
4444 settings.beginGroup("/AddRemoveCurves");
4445 settings.setValue("/Width", d_add_curves_dialog_size.width());
4446 settings.setValue("/Height", d_add_curves_dialog_size.height());
4447 settings.setValue("/ShowCurrentFolder", d_show_current_folder);
4448 settings.endGroup(); // AddRemoveCurves Dialog
4449 settings.endGroup(); // Dialogs
4450
4451 settings.beginGroup("/Colors");
4452 settings.setValue("/Workspace", COLORNAME(workspaceColor));
4453 settings.setValue("/Panels", COLORNAME(panelsColor));
4454 settings.setValue("/PanelsText", COLORNAME(panelsTextColor));
4455 settings.endGroup(); // Colors
4456
4457 settings.beginGroup("/Paths");
4458 settings.setValue("/WorkingDir", workingDir);
4459 settings.setValue("/TemplatesDir", templatesDir);
4460 settings.setValue("/HelpFile", helpFilePath);
4461 settings.setValue("/FitPlugins", fitPluginsPath);
4462 settings.setValue("/ASCII", asciiDirPath);
4463 settings.setValue("/Images", imagesDirPath);
4464
4465 settings.setValue("LockToolbars", locktoolbar->isChecked());
4466
4467 settings.endGroup(); // Paths
4468 settings.endGroup();
4469 /* ---------------- end group General --------------- */
4470
4471 settings.beginGroup("/UserFunctions");
4472 settings.setValue("/FitFunctions", fitFunctions);
4473 settings.setValue("/SurfaceFunctions", surfaceFunc);
4474 settings.setValue("/xFunctions", xFunctions);
4475 settings.setValue("/yFunctions", yFunctions);
4476 settings.setValue("/rFunctions", rFunctions);
4477 settings.setValue("/thetaFunctions", thetaFunctions);
4478 settings.endGroup(); // UserFunctions
4479
4480 settings.beginGroup("/Confirmations");
4481 settings.setValue("/Folder", confirmCloseFolder);
4482 settings.setValue("/Table", confirmCloseTable);
4483 settings.setValue("/Matrix", confirmCloseMatrix);
4484 settings.setValue("/Plot2D", confirmClosePlot2D);
4485 settings.setValue("/Plot3D", confirmClosePlot3D);
4486 settings.setValue("/Note", confirmCloseNotes);
4487 settings.endGroup(); // Confirmations
4488
4489 /* ----------------- group Tables -------------- */
4490 settings.beginGroup("/Tables");
4491 settings.setValue("/DisplayComments", d_show_table_comments);
4492 QStringList tableFonts;
4493 tableFonts << tableTextFont.family();
4494 tableFonts << QString::number(tableTextFont.pointSize());
4495 tableFonts << QString::number(tableTextFont.weight());
4496 tableFonts << QString::number(tableTextFont.italic());
4497 tableFonts << tableHeaderFont.family();
4498 tableFonts << QString::number(tableHeaderFont.pointSize());
4499 tableFonts << QString::number(tableHeaderFont.weight());
4500 tableFonts << QString::number(tableHeaderFont.italic());
4501 settings.setValue("/Fonts", tableFonts);
4502
4503 settings.beginGroup("/Colors");
4504 settings.setValue("/Background", COLORNAME(tableBkgdColor));
4505 settings.setValue("/Text", COLORNAME(tableTextColor));
4506 settings.setValue("/Header", COLORNAME(tableHeaderColor));
4507 settings.endGroup(); // Colors
4508 settings.endGroup();
4509 /* ----------------- end group Tables ---------- */
4510
4511 /* ----------------- group 2D Plots ------------ */
4512 settings.beginGroup("/2DPlots");
4513 settings.beginGroup("/General");
4514 settings.setValue("/Title", titleOn);
4515 settings.setValue("/AllAxes", allAxesOn);
4516 settings.setValue("/CanvasFrame", canvasFrameOn);
4517 settings.setValue("/CanvasFrameWidth", canvasFrameWidth);
4518 settings.setValue("/Margin", defaultPlotMargin);
4519 settings.setValue("/AxesBackbones", drawBackbones);
4520 settings.setValue("/AxesLineWidth", axesLineWidth);
4521 settings.setValue("/Autoscale", autoscale2DPlots);
4522 settings.setValue("/AutoScaleFonts", autoScaleFonts);
4523 settings.setValue("/AutoResizeLayers", autoResizeLayers);
4524 settings.setValue("/Antialiasing", antialiasing2DPlots);
4525 settings.setValue("/ScaleLayersOnPrint", d_scale_plots_on_print);
4526 settings.setValue("/PrintCropmarks", d_print_cropmarks);
4527
4528 QStringList graphFonts;
4529 graphFonts << plotAxesFont.family();
4530 graphFonts << QString::number(plotAxesFont.pointSize());
4531 graphFonts << QString::number(plotAxesFont.weight());
4532 graphFonts << QString::number(plotAxesFont.italic());
4533 graphFonts << plotNumbersFont.family();
4534 graphFonts << QString::number(plotNumbersFont.pointSize());
4535 graphFonts << QString::number(plotNumbersFont.weight());
4536 graphFonts << QString::number(plotNumbersFont.italic());
4537 graphFonts << plotLegendFont.family();
4538 graphFonts << QString::number(plotLegendFont.pointSize());
4539 graphFonts << QString::number(plotLegendFont.weight());
4540 graphFonts << QString::number(plotLegendFont.italic());
4541 graphFonts << plotTitleFont.family();
4542 graphFonts << QString::number(plotTitleFont.pointSize());
4543 graphFonts << QString::number(plotTitleFont.weight());
4544 graphFonts << QString::number(plotTitleFont.italic());
4545 settings.setValue("/Fonts", graphFonts);
4546 settings.endGroup(); // General
4547
4548 settings.beginGroup("/Curves");
4549 settings.setValue("/Style", defaultCurveStyle);
4550 settings.setValue("/LineWidth", defaultCurveLineWidth);
4551 settings.setValue("/SymbolSize", defaultSymbolSize);
4552 settings.endGroup(); // Curves
4553
4554 settings.beginGroup("/Ticks");
4555 settings.setValue("/MajTicksStyle", majTicksStyle);
4556 settings.setValue("/MinTicksStyle", minTicksStyle);
4557 settings.setValue("/MinTicksLength", minTicksLength);
4558 settings.setValue("/MajTicksLength", majTicksLength);
4559 settings.endGroup(); // Ticks
4560
4561 settings.beginGroup("/Legend");
4562 settings.setValue("/FrameStyle", legendFrameStyle);
4563 settings.setValue("/TextColor", COLORNAME(legendTextColor));
4564 settings.setValue("/BackgroundColor", COLORNAME(legendBackground));
4565 settings.setValue("/Transparency", legendBackground.alpha());
4566 settings.endGroup(); // Legend
4567
4568 settings.beginGroup("/Arrows");
4569 settings.setValue("/Width", defaultArrowLineWidth);
4570 settings.setValue("/Color", COLORNAME(defaultArrowColor));
4571 settings.setValue("/HeadLength", defaultArrowHeadLength);
4572 settings.setValue("/HeadAngle", defaultArrowHeadAngle);
4573 settings.setValue("/HeadFill", defaultArrowHeadFill);
4574 settings.setValue("/LineStyle", Graph::penStyleName(defaultArrowLineStyle));
4575 settings.endGroup(); // Arrows
4576 settings.endGroup();
4577 /* ----------------- end group 2D Plots -------- */
4578
4579 /* ----------------- group 3D Plots ------------ */
4580 settings.beginGroup("/3DPlots");
4581 settings.setValue("/Legend", showPlot3DLegend);
4582 settings.setValue("/Projection", showPlot3DProjection);
4583 settings.setValue("/Antialiasing", smooth3DMesh);
4584 settings.setValue("/Resolution", plot3DResolution);
4585 settings.setValue("/Orthogonal", orthogonal3DPlots);
4586 settings.setValue("/Autoscale", autoscale3DPlots);
4587
4588 QStringList plot3DFonts;
4589 plot3DFonts << plot3DTitleFont.family();
4590 plot3DFonts << QString::number(plot3DTitleFont.pointSize());
4591 plot3DFonts << QString::number(plot3DTitleFont.weight());
4592 plot3DFonts << QString::number(plot3DTitleFont.italic());
4593 plot3DFonts << plot3DNumbersFont.family();
4594 plot3DFonts << QString::number(plot3DNumbersFont.pointSize());
4595 plot3DFonts << QString::number(plot3DNumbersFont.weight());
4596 plot3DFonts << QString::number(plot3DNumbersFont.italic());
4597 plot3DFonts << plot3DAxesFont.family();
4598 plot3DFonts << QString::number(plot3DAxesFont.pointSize());
4599 plot3DFonts << QString::number(plot3DAxesFont.weight());
4600 plot3DFonts << QString::number(plot3DAxesFont.italic());
4601 settings.setValue("/Fonts", plot3DFonts);
4602
4603 settings.beginGroup("/Colors");
4604 settings.setValue("/MaxData", plot3DColors[0]);
4605 settings.setValue("/Labels", plot3DColors[1]);
4606 settings.setValue("/Mesh", plot3DColors[2]);
4607 settings.setValue("/Grid", plot3DColors[3]);
4608 settings.setValue("/MinData", plot3DColors[4]);
4609 settings.setValue("/Numbers", plot3DColors[5]);
4610 settings.setValue("/Axes", plot3DColors[6]);
4611 settings.setValue("/Background", plot3DColors[7]);
4612 settings.endGroup(); // Colors
4613 settings.endGroup();
4614 /* ----------------- end group 2D Plots -------- */
4615
4616 settings.beginGroup("/Fitting");
4617 settings.setValue("/OutputPrecision", fit_output_precision);
4618 settings.setValue("/PasteResultsToPlot", pasteFitResultsToPlot);
4619 settings.setValue("/WriteResultsToLog", writeFitResultsToLog);
4620 settings.setValue("/GenerateFunction", generateUniformFitPoints);
4621 settings.setValue("/Points", fitPoints);
4622 settings.setValue("/GeneratePeakCurves", generatePeakCurves);
4623 settings.setValue("/PeaksColor", COLORNAME(peakCurvesColor));
4624 settings.setValue("/ScaleErrors", fit_scale_errors);
4625 settings.setValue("/TwoPointsLinearFit", d_2_linear_fit_points);
4626 settings.endGroup(); // Fitting
4627
4628 settings.beginGroup("/ImportASCII");
4629 QString sep = columnSeparator;
4630 settings.setValue("/ColumnSeparator", sep.replace("\t", "\\t").replace(" ", "\\s"));
4631 settings.setValue("/IgnoreLines", ignoredLines);
4632 settings.setValue("/RenameColumns", renameColumns);
4633 settings.setValue("/StripSpaces", strip_spaces);
4634 settings.setValue("/SimplifySpaces", simplify_spaces);
4635 settings.setValue("/AsciiFileTypeFilter", d_ASCII_file_filter);
4636 settings.setValue("/AsciiImportLocale", d_ASCII_import_locale.name());
4637 settings.setValue("/ConvertToNumeric", d_convert_to_numeric);
4638 settings.endGroup(); // ImportASCII
4639
4640 settings.beginGroup("/ExportImage");
4641 settings.setValue("/ImageFileTypeFilter", d_image_export_filter);
4642 settings.setValue("/ExportTransparency", d_export_transparency);
4643 settings.setValue("/ImageQuality", d_export_quality);
4644 settings.setValue("/Resolution", d_export_resolution);
4645 settings.setValue("/ExportColor", d_export_color);
4646 settings.setValue("/ExportPageSize", d_export_vector_size);
4647 settings.setValue("/KeepAspect", d_keep_plot_aspect);
4648 settings.setValue("/Orientation", d_export_orientation);
4649 settings.endGroup(); // ExportImage
4650 }
4651
exportGraph()4652 void ApplicationWindow::exportGraph()
4653 {
4654 QWidget *w = d_workspace.activeSubWindow();
4655 if (!w)
4656 return;
4657
4658 MultiLayer *plot2D = 0;
4659 Graph3D *plot3D = 0;
4660 if (w->inherits("MultiLayer")) {
4661 plot2D = (MultiLayer *)w;
4662 if (plot2D->isEmpty()) {
4663 QMessageBox::critical(
4664 this, tr("Export Error"),
4665 tr("<h4>There are no plot layers available in this window!</h4>"));
4666 return;
4667 }
4668 } else if (w->inherits("Graph3D"))
4669 plot3D = (Graph3D *)w;
4670 else
4671 return;
4672
4673 ImageExportDialog *ied = new ImageExportDialog(this, plot2D != NULL, d_extended_export_dialog);
4674 ied->setDirectory(workingDir);
4675 ied->selectFilter(d_image_export_filter);
4676 if (ied->exec() != QDialog::Accepted)
4677 return;
4678 workingDir = ied->directory().path();
4679 if (ied->selectedFiles().isEmpty())
4680 return;
4681
4682 QString selected_filter = ied->selectedNameFilter();
4683 QString file_name = ied->selectedFiles()[0];
4684 QFileInfo file_info(file_name);
4685 if (!file_info.fileName().contains("."))
4686 file_name.append(selected_filter.remove("*"));
4687
4688 QFile file(file_name);
4689 if (!file.open(QIODevice::WriteOnly)) {
4690 QMessageBox::critical(this, tr("Export Error"),
4691 tr("Could not write to file: <br><h4> %1 </h4><p>Please verify that "
4692 "you have the right to write to this location!")
4693 .arg(file_name));
4694 return;
4695 }
4696
4697 if (selected_filter.contains(".eps") || selected_filter.contains(".pdf")
4698 || selected_filter.contains(".ps")) {
4699 if (plot3D)
4700 plot3D->exportVector(file_name, selected_filter.remove(QRegularExpression("\\.")));
4701 else if (plot2D)
4702 plot2D->exportVector(file_name, ied->resolution(), ied->color(), ied->keepAspect(),
4703 ied->pageSize(), ied->pageOrientation());
4704 } else if (selected_filter.contains(".svg")) {
4705 if (plot2D)
4706 plot2D->exportSVG(file_name);
4707 else
4708 plot3D->exportVector(file_name, "svg");
4709 } else {
4710 QList<QByteArray> list = QImageWriter::supportedImageFormats();
4711 for (int i = 0; i < (int)list.count(); i++) {
4712 if (selected_filter.contains("." + (list[i]).toLower())) {
4713 if (plot2D)
4714 plot2D->exportImage(file_name, ied->quality());
4715 else if (plot3D)
4716 plot3D->exportImage(file_name, ied->quality());
4717 }
4718 }
4719 }
4720 }
4721
exportLayer()4722 void ApplicationWindow::exportLayer()
4723 {
4724 QWidget *w = d_workspace.activeSubWindow();
4725 if (!w || !w->inherits("MultiLayer"))
4726 return;
4727
4728 Graph *g = ((MultiLayer *)w)->activeGraph();
4729 if (!g)
4730 return;
4731
4732 ImageExportDialog *ied = new ImageExportDialog(this, g != NULL, d_extended_export_dialog);
4733 ied->setDirectory(workingDir);
4734 ied->selectFilter(d_image_export_filter);
4735 if (ied->exec() != QDialog::Accepted)
4736 return;
4737 workingDir = ied->directory().path();
4738 if (ied->selectedFiles().isEmpty())
4739 return;
4740
4741 QString selected_filter = ied->selectedNameFilter();
4742 QString file_name = ied->selectedFiles()[0];
4743 QFileInfo file_info(file_name);
4744 if (!file_info.fileName().contains("."))
4745 file_name.append(selected_filter.remove("*"));
4746
4747 QFile file(file_name);
4748 if (!file.open(QIODevice::WriteOnly)) {
4749 QMessageBox::critical(this, tr("Export Error"),
4750 tr("Could not write to file: <br><h4> %1 </h4><p>Please verify that "
4751 "you have the right to write to this location!")
4752 .arg(file_name));
4753 return;
4754 }
4755
4756 if (selected_filter.contains(".eps") || selected_filter.contains(".pdf")
4757 || selected_filter.contains(".ps"))
4758 g->exportVector(file_name, ied->resolution(), ied->color(), ied->keepAspect(),
4759 ied->pageSize(), ied->pageOrientation());
4760 else if (selected_filter.contains(".svg"))
4761 g->exportSVG(file_name);
4762 else {
4763 QList<QByteArray> list = QImageWriter::supportedImageFormats();
4764 for (int i = 0; i < (int)list.count(); i++)
4765 if (selected_filter.contains("." + (list[i]).toLower()))
4766 g->exportImage(file_name, ied->quality());
4767 }
4768 }
4769
exportAllGraphs()4770 void ApplicationWindow::exportAllGraphs()
4771 {
4772 ImageExportDialog *ied = new ImageExportDialog(this, true, d_extended_export_dialog);
4773 ied->setWindowTitle(tr("Choose a directory to export the graphs to"));
4774 QStringList tmp = ied->nameFilters();
4775 ied->setFileMode(QFileDialog::Directory);
4776 ied->setNameFilters(tmp);
4777 ied->setLabelText(QFileDialog::FileType, tr("Output format:"));
4778 ied->setLabelText(QFileDialog::FileName, tr("Directory:"));
4779
4780 ied->setDirectory(workingDir);
4781 ied->selectFilter(d_image_export_filter);
4782
4783 if (ied->exec() != QDialog::Accepted)
4784 return;
4785 workingDir = ied->directory().path();
4786 if (ied->selectedFiles().isEmpty())
4787 return;
4788
4789 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
4790
4791 QString output_dir = ied->selectedFiles()[0];
4792 QString file_suffix = ied->selectedNameFilter();
4793 file_suffix = file_suffix.toLower();
4794 file_suffix.remove("*");
4795
4796 QList<MyWidget *> windows = windowsList();
4797 bool confirm_overwrite = true;
4798 MultiLayer *plot2D;
4799 Graph3D *plot3D;
4800
4801 foreach (MyWidget *w, windows) {
4802 if (w->inherits("MultiLayer")) {
4803 plot3D = 0;
4804 plot2D = (MultiLayer *)w;
4805 if (plot2D->isEmpty()) {
4806 QApplication::restoreOverrideCursor();
4807 QMessageBox::warning(
4808 this, tr("Warning"),
4809 tr("There are no plot layers available in window <b>%1</b>.<br>"
4810 "Graph window not exported!")
4811 .arg(plot2D->name()));
4812 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
4813 continue;
4814 }
4815 } else if (w->inherits("Graph3D")) {
4816 plot2D = 0;
4817 plot3D = (Graph3D *)w;
4818 } else
4819 continue;
4820
4821 QString file_name = output_dir + "/" + w->objectName() + file_suffix;
4822 QFile f(file_name);
4823 if (f.exists() && confirm_overwrite) {
4824 QApplication::restoreOverrideCursor();
4825 switch (QMessageBox::question(this, tr("Overwrite file?"),
4826 tr("A file called: <p><b>%1</b><p>already exists. "
4827 "Do you want to overwrite it?")
4828 .arg(file_name),
4829 tr("&Yes"), tr("&All"), tr("&Cancel"), 0, 1)) {
4830 case 1:
4831 confirm_overwrite = false;
4832 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
4833 break;
4834 case 0:
4835 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
4836 break;
4837 case 2:
4838 return;
4839 }
4840 }
4841 if (!f.open(QIODevice::WriteOnly)) {
4842 QApplication::restoreOverrideCursor();
4843 QMessageBox::critical(
4844 this, tr("Export Error"),
4845 tr("Could not write to file: <br><h4>%1</h4><p>"
4846 "Please verify that you have the right to write to this location!")
4847 .arg(file_name));
4848 return;
4849 }
4850 if (file_suffix.contains(".eps") || file_suffix.contains(".pdf")
4851 || file_suffix.contains(".ps")) {
4852 if (plot3D)
4853 plot3D->exportVector(file_name, file_suffix.remove("."));
4854 else if (plot2D)
4855 plot2D->exportVector(file_name, ied->resolution(), ied->color());
4856 } else if (file_suffix.contains(".svg")) {
4857 if (plot2D)
4858 plot2D->exportSVG(file_name);
4859 } else {
4860 QList<QByteArray> list = QImageWriter::supportedImageFormats();
4861 for (int i = 0; i < (int)list.count(); i++) {
4862 if (file_suffix.contains("." + (list[i]).toLower())) {
4863 if (plot2D)
4864 plot2D->exportImage(file_name, ied->quality());
4865 else if (plot3D)
4866 plot3D->exportImage(file_name, ied->quality());
4867 }
4868 }
4869 }
4870 }
4871
4872 QApplication::restoreOverrideCursor();
4873 }
4874
windowGeometryInfo(MyWidget * w)4875 QString ApplicationWindow::windowGeometryInfo(MyWidget *w)
4876 {
4877 QString s = "geometry\t";
4878 if (w->status() == MyWidget::Maximized) {
4879 if (w == w->folder()->activeWindow())
4880 return s + "maximized\tactive\n";
4881 else
4882 return s + "maximized\n";
4883 }
4884
4885 if (!w->parent())
4886 s += "0\t0\t500\t400\t";
4887 else {
4888 QPoint p = w->pos(); // store position
4889 s += QString::number(p.x()) + "\t";
4890 s += QString::number(p.y()) + "\t";
4891 s += QString::number(w->frameGeometry().width()) + "\t";
4892 s += QString::number(w->frameGeometry().height()) + "\t";
4893 }
4894
4895 if (w->status() == MyWidget::Minimized)
4896 s += "minimized\t";
4897
4898 bool hide = hidden(w);
4899 if (w == w->folder()->activeWindow() && !hide)
4900 s += "active\n";
4901 else if (hide)
4902 s += "hidden\n";
4903 else
4904 s += "\n";
4905 return s;
4906 }
4907
restoreWindowGeometry(ApplicationWindow * app,MyWidget * w,const QString s)4908 void ApplicationWindow::restoreWindowGeometry(ApplicationWindow *app, MyWidget *w, const QString s)
4909 {
4910 w->blockSignals(true);
4911 QString caption = w->name();
4912 if (s.contains("minimized")) {
4913 QStringList lst = s.split("\t");
4914 if (lst.count() > 4)
4915 w->setGeometry(lst[1].toInt(), lst[2].toInt(), lst[3].toInt(), lst[4].toInt());
4916 w->setStatus(MyWidget::Minimized);
4917 app->setListView(caption, tr("Minimized"));
4918 } else if (s.contains("maximized")) {
4919 w->setStatus(MyWidget::Maximized);
4920 app->setListView(caption, tr("Maximized"));
4921 } else {
4922 QStringList lst = s.split("\t");
4923 w->setGeometry(lst[1].toInt(), lst[2].toInt(), lst[3].toInt(), lst[4].toInt());
4924 w->setStatus(MyWidget::Normal);
4925
4926 if (lst.count() > 5) {
4927 if (lst[5] == "hidden")
4928 app->hideWindow(w);
4929 }
4930 }
4931
4932 if (s.contains("active")) {
4933 Folder *f = w->folder();
4934 if (f)
4935 f->setActiveWindow(w);
4936 }
4937
4938 w->blockSignals(false);
4939 }
4940
projectFolder()4941 Folder *ApplicationWindow::projectFolder()
4942 {
4943 return ((FolderListItem *)folders.topLevelItem(0))->folder();
4944 }
4945
saveProject()4946 bool ApplicationWindow::saveProject()
4947 {
4948 if (projectname == "untitled" || projectname.endsWith(".opj", Qt::CaseInsensitive)
4949 || projectname.endsWith(".ogm", Qt::CaseInsensitive)
4950 || projectname.endsWith(".ogw", Qt::CaseInsensitive)
4951 || projectname.endsWith(".ogg", Qt::CaseInsensitive)
4952 || projectname.endsWith(".org", Qt::CaseInsensitive)) {
4953 saveProjectAs();
4954 return false;
4955 }
4956
4957 bool compress = false;
4958 QString fn = projectname;
4959 if (fn.endsWith(".gz")) {
4960 fn = fn.left(fn.length() - 3);
4961 compress = true;
4962 }
4963
4964 saveFolder(projectFolder(), fn);
4965
4966 if (compress)
4967 file_compress(QFile::encodeName(fn).constData(), "wb9");
4968
4969 setWindowTitle("SciDAVis - " + projectname);
4970 savedProject();
4971 actionUndo->setEnabled(false);
4972 actionRedo->setEnabled(false);
4973
4974 if (autoSave) {
4975 if (savingTimerId)
4976 killTimer(savingTimerId);
4977 savingTimerId = startTimer(autoSaveTime * 60000);
4978 } else
4979 savingTimerId = 0;
4980
4981 QApplication::restoreOverrideCursor();
4982 return true;
4983 }
4984
saveProjectAs()4985 void ApplicationWindow::saveProjectAs()
4986 {
4987 QString filter = tr("SciDAVis project") + " (*.sciprj);;";
4988 filter += tr("Compressed SciDAVis project") + " (*.sciprj.gz)";
4989
4990 QString selectedFilter;
4991 QString fn = QFileDialog::getSaveFileName(this, tr("Save Project As"), workingDir, filter,
4992 &selectedFilter);
4993 if (!fn.isEmpty()) {
4994 QFileInfo fi(fn);
4995 workingDir = fi.absolutePath();
4996 QString baseName = fi.fileName();
4997 if (!baseName.endsWith(".sciprj") && !baseName.endsWith(".sciprj.gz")) {
4998 fn.append(".sciprj");
4999 if (selectedFilter.contains(".gz"))
5000 fn.append(".gz");
5001 }
5002 projectname = fn;
5003
5004 if (saveProject()) {
5005 recentProjects.removeAll(fn);
5006 recentProjects.push_front(fn);
5007 updateRecentProjectsList();
5008
5009 QFileInfo fi(fn);
5010 QString baseName = fi.baseName();
5011 FolderListItem *item = (FolderListItem *)folders.topLevelItem(0);
5012 item->setText(0, baseName);
5013 item->folder()->setName(baseName);
5014 }
5015 }
5016 }
5017
saveNoteAs()5018 void ApplicationWindow::saveNoteAs()
5019 {
5020 Note *w = (Note *)d_workspace.activeSubWindow();
5021 if (!w || !w->inherits("Note"))
5022 return;
5023 w->exportASCII();
5024 }
5025
saveAsTemplate()5026 void ApplicationWindow::saveAsTemplate()
5027 {
5028 MyWidget *w = (MyWidget *)d_workspace.activeSubWindow();
5029 if (!w)
5030 return;
5031
5032 QString filter;
5033 if (w->inherits("Matrix"))
5034 filter = tr("SciDAVis/QtiPlot Matrix Template") + " (*.qmt)";
5035 else if (w->inherits("MultiLayer"))
5036 filter = tr("SciDAVis/QtiPlot 2D Graph Template") + " (*.qpt)";
5037 else if (w->inherits("Table"))
5038 filter = tr("SciDAVis/QtiPlot Table Template") + " (*.qtt)";
5039 else if (w->inherits("Graph3D"))
5040 filter = tr("SciDAVis/QtiPlot 3D Surface Template") + " (*.qst)";
5041
5042 QString selectedFilter;
5043 QString fn =
5044 QFileDialog::getSaveFileName(this, tr("Save Window As Template"),
5045 templatesDir + "/" + w->name(), filter, &selectedFilter);
5046 if (!fn.isEmpty()) {
5047 QFileInfo fi(fn);
5048 workingDir = fi.absolutePath();
5049 QString baseName = fi.fileName();
5050 if (!baseName.contains(".")) {
5051 selectedFilter = selectedFilter.right(5).left(4);
5052 fn.append(selectedFilter);
5053 }
5054
5055 QFile f(fn);
5056 if (!f.open(QIODevice::WriteOnly)) {
5057 QMessageBox::critical(this, tr("Export Error"),
5058 tr("Could not write to file: <br><h4> %1 </h4><p>Please verify "
5059 "that you have the right to write to this location!")
5060 .arg(fn));
5061 return;
5062 }
5063 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
5064 QString text = SciDAVis::schemaVersion() + " template file\n";
5065 text += w->saveAsTemplate(windowGeometryInfo(w));
5066 QTextStream t(&f);
5067 t.setCodec(QTextCodec::codecForName("UTF-8"));
5068 t << text;
5069 f.close();
5070 QApplication::restoreOverrideCursor();
5071 }
5072 }
5073
renameActiveWindow()5074 void ApplicationWindow::renameActiveWindow()
5075 {
5076 MyWidget *m = (MyWidget *)d_workspace.activeSubWindow();
5077 if (!m)
5078 return;
5079
5080 RenameWindowDialog *rwd = new RenameWindowDialog(this);
5081 rwd->setAttribute(Qt::WA_DeleteOnClose);
5082 rwd->setWidget(m);
5083 rwd->exec();
5084 }
5085
renameWindow(QTreeWidgetItem * item,int,const QString & text)5086 void ApplicationWindow::renameWindow(QTreeWidgetItem *item, int, const QString &text)
5087 {
5088 if (auto wli = dynamic_cast<WindowListItem *>(item))
5089 if (auto w = wli->window())
5090 if (text != w->name())
5091 renameWindow(w, text);
5092 }
5093
renameWindow(MyWidget * w,const QString & text)5094 bool ApplicationWindow::renameWindow(MyWidget *w, const QString &text)
5095 {
5096 if (!w)
5097 return false;
5098
5099 QString name = w->name();
5100
5101 QString newName = text;
5102 newName.replace("-", "_");
5103 if (newName.isEmpty()) {
5104 QMessageBox::critical(this, tr("Error"), tr("Please enter a valid name!"));
5105 return false;
5106 } else if (newName.contains(QRegExp("\\W"))) {
5107 QMessageBox::critical(
5108 this, tr("Error"),
5109 tr("The name you chose is not valid: only letters and digits are allowed!") + "<p>"
5110 + tr("Please choose another name!"));
5111 return false;
5112 }
5113
5114 newName.replace("_", "-");
5115
5116 while (alreadyUsedName(newName)) {
5117 QMessageBox::critical(this, tr("Error"),
5118 tr("Name <b>%1</b> already exists!").arg(newName) + "<p>"
5119 + tr("Please choose another name!") + "<p>"
5120 + tr("Warning: for internal consistency reasons the "
5121 "underscore character is replaced with a minus sign."));
5122 return false;
5123 }
5124
5125 if (w->inherits("Table")) {
5126 QStringList labels = ((Table *)w)->colNames();
5127 if (labels.contains(newName)) {
5128 QMessageBox::critical(
5129 this, tr("Error"),
5130 tr("The table name must be different from the names of its columns!") + "<p>"
5131 + tr("Please choose another name!"));
5132 return false;
5133 }
5134
5135 updateTableNames(name, newName);
5136 } else if (w->inherits("Matrix"))
5137 changeMatrixName(name, newName);
5138
5139 w->setName(newName);
5140 w->setCaptionPolicy(w->captionPolicy());
5141 renameListViewItem(name, newName);
5142 return true;
5143 }
5144
5145 // TODO: string list -> Column * list
columnsList(SciDAVis::PlotDesignation plotType)5146 QStringList ApplicationWindow::columnsList(SciDAVis::PlotDesignation plotType)
5147 {
5148 QList<MyWidget *> windows = windowsList();
5149 QStringList list;
5150 foreach (MyWidget *w, windows) {
5151 if (!w->inherits("Table"))
5152 continue;
5153
5154 Table *t = (Table *)w;
5155 for (int i = 0; i < t->numCols(); i++) {
5156 if (t->colPlotDesignation(i) == plotType)
5157 list << QString(t->name()) + "_" + t->colLabel(i);
5158 }
5159 }
5160
5161 return list;
5162 }
5163
5164 // TODO: string list -> Column * list
columnsList()5165 QStringList ApplicationWindow::columnsList()
5166 {
5167 QList<MyWidget *> windows = windowsList();
5168 QStringList list;
5169 foreach (MyWidget *w, windows) {
5170 if (!w->inherits("Table"))
5171 continue;
5172
5173 Table *t = (Table *)w;
5174 for (int i = 0; i < t->numCols(); i++) {
5175 list << QString(t->name()) + "_" + t->colLabel(i);
5176 }
5177 }
5178
5179 return list;
5180 }
5181
showCurvesDialog()5182 void ApplicationWindow::showCurvesDialog()
5183 {
5184 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
5185 return;
5186
5187 if (((MultiLayer *)d_workspace.activeSubWindow())->isEmpty()) {
5188 QMessageBox::warning(this, tr("Error"),
5189 tr("<h4>There are no plot layers available in this window.</h4>"
5190 "<p><h4>Please add a layer and try again!</h4>"));
5191 return;
5192 }
5193
5194 Graph *g = ((MultiLayer *)d_workspace.activeSubWindow())->activeGraph();
5195 if (!g)
5196 return;
5197
5198 if (g->isPiePlot()) {
5199 QMessageBox::warning(this, tr("Error"),
5200 tr("This functionality is not available for pie plots!"));
5201 } else {
5202 CurvesDialog *crvDialog = new CurvesDialog(this);
5203 crvDialog->setAttribute(Qt::WA_DeleteOnClose);
5204 crvDialog->setGraph(g);
5205 crvDialog->resize(d_add_curves_dialog_size);
5206 crvDialog->show();
5207 }
5208 }
5209
tableList()5210 QList<MyWidget *> *ApplicationWindow::tableList()
5211 {
5212 QList<MyWidget *> *lst = new QList<MyWidget *>();
5213 foreach (MyWidget *w, windowsList()) {
5214 if (w->inherits("Table"))
5215 lst->append(w);
5216 }
5217 return lst;
5218 }
5219
showPlotAssociations(int curve)5220 void ApplicationWindow::showPlotAssociations(int curve)
5221 {
5222 QWidget *w = d_workspace.activeSubWindow();
5223 if (!w || !w->inherits("MultiLayer"))
5224 return;
5225
5226 Graph *g = ((MultiLayer *)w)->activeGraph();
5227 if (!g)
5228 return;
5229
5230 AssociationsDialog *ad = new AssociationsDialog(this, Qt::WindowStaysOnTopHint);
5231 ad->setAttribute(Qt::WA_DeleteOnClose);
5232 ad->setGraph(g);
5233 ad->initTablesList(tableList(), curve);
5234 ad->exec();
5235 }
5236
showTitleDialog()5237 void ApplicationWindow::showTitleDialog()
5238 {
5239 QWidget *w = d_workspace.activeSubWindow();
5240 if (!w)
5241 return;
5242
5243 if (w->inherits("MultiLayer")) {
5244 Graph *g = ((MultiLayer *)w)->activeGraph();
5245 if (g) {
5246 TextDialog *td = new TextDialog(TextDialog::AxisTitle, this, Qt::Widget);
5247 td->setAttribute(Qt::WA_DeleteOnClose);
5248 connect(td, SIGNAL(changeFont(const QFont &)), g, SLOT(setTitleFont(const QFont &)));
5249 connect(td, SIGNAL(changeText(const QString &)), g, SLOT(setTitle(const QString &)));
5250 connect(td, SIGNAL(changeColor(const QColor &)), g,
5251 SLOT(setTitleColor(const QColor &)));
5252 connect(td, SIGNAL(changeAlignment(int)), g, SLOT(setTitleAlignment(int)));
5253
5254 QwtText t = g->plotWidget()->title();
5255 td->setText(t.text());
5256 td->setFont(t.font());
5257 td->setTextColor(t.color());
5258 td->setAlignment(t.renderFlags());
5259 td->exec();
5260 }
5261 } else if (w->inherits("Graph3D")) {
5262 Plot3DDialog *pd = (Plot3DDialog *)showPlot3dDialog();
5263 if (pd)
5264 pd->showTitleTab();
5265 delete pd;
5266 }
5267 }
5268
showXAxisTitleDialog()5269 void ApplicationWindow::showXAxisTitleDialog()
5270 {
5271 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
5272 return;
5273
5274 Graph *g = ((MultiLayer *)d_workspace.activeSubWindow())->activeGraph();
5275 if (g) {
5276 TextDialog *td = new TextDialog(TextDialog::AxisTitle, this, Qt::Widget);
5277 td->setAttribute(Qt::WA_DeleteOnClose);
5278 connect(td, SIGNAL(changeFont(const QFont &)), g, SLOT(setXAxisTitleFont(const QFont &)));
5279 connect(td, SIGNAL(changeText(const QString &)), g, SLOT(setXAxisTitle(const QString &)));
5280 connect(td, SIGNAL(changeColor(const QColor &)), g,
5281 SLOT(setXAxisTitleColor(const QColor &)));
5282 connect(td, SIGNAL(changeAlignment(int)), g, SLOT(setXAxisTitleAlignment(int)));
5283
5284 QStringList t = g->scalesTitles();
5285 td->setText(t[0]);
5286 td->setFont(g->axisTitleFont(2));
5287 td->setTextColor(g->axisTitleColor(2));
5288 td->setAlignment(g->axisTitleAlignment(2));
5289 td->setWindowTitle(tr("X Axis Title"));
5290 td->exec();
5291 }
5292 }
5293
showYAxisTitleDialog()5294 void ApplicationWindow::showYAxisTitleDialog()
5295 {
5296 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
5297 return;
5298
5299 Graph *g = ((MultiLayer *)d_workspace.activeSubWindow())->activeGraph();
5300 if (g) {
5301 TextDialog *td = new TextDialog(TextDialog::AxisTitle, this, Qt::Widget);
5302 td->setAttribute(Qt::WA_DeleteOnClose);
5303 connect(td, SIGNAL(changeFont(const QFont &)), g, SLOT(setYAxisTitleFont(const QFont &)));
5304 connect(td, SIGNAL(changeText(const QString &)), g, SLOT(setYAxisTitle(const QString &)));
5305 connect(td, SIGNAL(changeColor(const QColor &)), g,
5306 SLOT(setYAxisTitleColor(const QColor &)));
5307 connect(td, SIGNAL(changeAlignment(int)), g, SLOT(setYAxisTitleAlignment(int)));
5308
5309 QStringList t = g->scalesTitles();
5310 td->setText(t[1]);
5311 td->setFont(g->axisTitleFont(0));
5312 td->setTextColor(g->axisTitleColor(0));
5313 td->setAlignment(g->axisTitleAlignment(0));
5314 td->setWindowTitle(tr("Y Axis Title"));
5315 td->exec();
5316 }
5317 }
5318
showRightAxisTitleDialog()5319 void ApplicationWindow::showRightAxisTitleDialog()
5320 {
5321 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
5322 return;
5323
5324 Graph *g = ((MultiLayer *)d_workspace.activeSubWindow())->activeGraph();
5325 if (g) {
5326 TextDialog *td = new TextDialog(TextDialog::AxisTitle, this, Qt::Widget);
5327 td->setAttribute(Qt::WA_DeleteOnClose);
5328 connect(td, SIGNAL(changeFont(const QFont &)), g,
5329 SLOT(setRightAxisTitleFont(const QFont &)));
5330 connect(td, SIGNAL(changeText(const QString &)), g,
5331 SLOT(setRightAxisTitle(const QString &)));
5332 connect(td, SIGNAL(changeColor(const QColor &)), g,
5333 SLOT(setRightAxisTitleColor(const QColor &)));
5334 connect(td, SIGNAL(changeAlignment(int)), g, SLOT(setRightAxisTitleAlignment(int)));
5335
5336 QStringList t = g->scalesTitles();
5337 td->setText(t[3]);
5338 td->setFont(g->axisTitleFont(1));
5339 td->setTextColor(g->axisTitleColor(1));
5340 td->setAlignment(g->axisTitleAlignment(1));
5341 td->setWindowTitle(tr("Right Axis Title"));
5342 td->exec();
5343 }
5344 }
5345
showTopAxisTitleDialog()5346 void ApplicationWindow::showTopAxisTitleDialog()
5347 {
5348 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
5349 return;
5350
5351 Graph *g = ((MultiLayer *)d_workspace.activeSubWindow())->activeGraph();
5352 if (g) {
5353 TextDialog *td = new TextDialog(TextDialog::AxisTitle, this, Qt::Widget);
5354 td->setAttribute(Qt::WA_DeleteOnClose);
5355 connect(td, SIGNAL(changeFont(const QFont &)), g, SLOT(setTopAxisTitleFont(const QFont &)));
5356 connect(td, SIGNAL(changeText(const QString &)), g, SLOT(setTopAxisTitle(const QString &)));
5357 connect(td, SIGNAL(changeColor(const QColor &)), g,
5358 SLOT(setTopAxisTitleColor(const QColor &)));
5359 connect(td, SIGNAL(changeAlignment(int)), g, SLOT(setTopAxisTitleAlignment(int)));
5360
5361 QStringList t = g->scalesTitles();
5362 td->setText(t[2]);
5363 td->setFont(g->axisTitleFont(3));
5364 td->setTextColor(g->axisTitleColor(3));
5365 td->setAlignment(g->axisTitleAlignment(3));
5366 td->setWindowTitle(tr("Top Axis Title"));
5367 td->exec();
5368 }
5369 }
5370
showExportASCIIDialog()5371 void ApplicationWindow::showExportASCIIDialog()
5372 {
5373 Table *table = qobject_cast<Table *>(d_workspace.activeSubWindow());
5374 if (table) {
5375 ExportDialog *ed = new ExportDialog(this, Qt::WindowContextHelpButtonHint);
5376 ed->setAttribute(Qt::WA_DeleteOnClose);
5377 connect(ed, SIGNAL(exportTable(const QString &, const QString &, bool, bool)), this,
5378 SLOT(exportASCII(const QString &, const QString &, bool, bool)));
5379 connect(ed, SIGNAL(exportAllTables(const QString &, bool, bool)), this,
5380 SLOT(exportAllTables(const QString &, bool, bool)));
5381
5382 ed->setTableNames(tableWindows());
5383 ed->setActiveTableName(table->name());
5384 ed->setColumnSeparator(columnSeparator);
5385 ed->exec();
5386 }
5387 }
5388
exportAllTables(const QString & sep,bool colNames,bool expSelection)5389 void ApplicationWindow::exportAllTables(const QString &sep, bool colNames, bool expSelection)
5390 {
5391 QString dir = QFileDialog::getExistingDirectory(
5392 this, tr("Choose a directory to export the tables to"), workingDir,
5393 QFileDialog::ShowDirsOnly);
5394 if (!dir.isEmpty()) {
5395 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
5396 workingDir = dir;
5397
5398 bool confirmOverwrite = true;
5399 bool success = true;
5400 foreach (MyWidget *w, windowsList()) {
5401 if (w->inherits("Table")) {
5402 Table *t = (Table *)w;
5403 QString fileName = dir + "/" + t->name() + ".txt";
5404 QFile f(fileName);
5405 if (f.exists(fileName) && confirmOverwrite) {
5406 QApplication::restoreOverrideCursor();
5407 switch (QMessageBox::question(
5408 this, tr("Overwrite file?"),
5409 tr("A file called: <p><b>%1</b><p>already exists. "
5410 "Do you want to overwrite it?")
5411 .arg(fileName),
5412 tr("&Yes"), tr("&All"), tr("&Cancel"), 0, 1)) {
5413 case 0:
5414 success = t->exportASCII(fileName, sep, colNames, expSelection);
5415 break;
5416
5417 case 1:
5418 confirmOverwrite = false;
5419 success = t->exportASCII(fileName, sep, colNames, expSelection);
5420 break;
5421
5422 case 2:
5423 return;
5424 break;
5425 }
5426 } else
5427 success = t->exportASCII(fileName, sep, colNames, expSelection);
5428
5429 if (!success)
5430 break;
5431 }
5432 }
5433 QApplication::restoreOverrideCursor();
5434 }
5435 }
5436
exportASCII(const QString & tableName,const QString & sep,bool colNames,bool expSelection)5437 void ApplicationWindow::exportASCII(const QString &tableName, const QString &sep, bool colNames,
5438 bool expSelection)
5439 {
5440 Table *t = table(tableName);
5441 if (!t)
5442 return;
5443
5444 QString selectedFilter;
5445 QString fname =
5446 QFileDialog::getSaveFileName(this, tr("Choose a filename to save under"), asciiDirPath,
5447 "*.txt;;*.csv;;*.dat;;*.DAT", &selectedFilter);
5448 if (!fname.isEmpty()) {
5449 QFileInfo fi(fname);
5450 QString baseName = fi.fileName();
5451 if (baseName.contains(".") == 0)
5452 fname.append(selectedFilter.remove("*"));
5453
5454 asciiDirPath = fi.absolutePath();
5455
5456 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
5457 t->exportASCII(fname, sep, colNames, expSelection);
5458 QApplication::restoreOverrideCursor();
5459 }
5460 }
5461
correlate()5462 void ApplicationWindow::correlate()
5463 {
5464 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("Table"))
5465 return;
5466
5467 Table *t = (Table *)d_workspace.activeSubWindow();
5468 QStringList s = t->selectedColumns();
5469 if ((int)s.count() != 2) {
5470 QMessageBox::warning(this, tr("Error"),
5471 tr("Please select two columns for this operation!"));
5472 return;
5473 }
5474
5475 Correlation *cor = new Correlation(this, t, s[0], s[1]);
5476 cor->run();
5477 delete cor;
5478 }
5479
autoCorrelate()5480 void ApplicationWindow::autoCorrelate()
5481 {
5482 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("Table"))
5483 return;
5484
5485 Table *t = (Table *)d_workspace.activeSubWindow();
5486 QStringList s = t->selectedColumns();
5487 if ((int)s.count() != 1) {
5488 QMessageBox::warning(this, tr("Error"),
5489 tr("Please select exactly one columns for this operation!"));
5490 return;
5491 }
5492
5493 Correlation *cor = new Correlation(this, t, s[0], s[0]);
5494 cor->run();
5495 delete cor;
5496 }
5497
convolute()5498 void ApplicationWindow::convolute()
5499 {
5500 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("Table"))
5501 return;
5502
5503 Table *t = (Table *)d_workspace.activeSubWindow();
5504 QStringList s = t->selectedColumns();
5505 if ((int)s.count() != 2) {
5506 QMessageBox::warning(this, tr("Error"),
5507 tr("Please select two columns for this operation:\n the first "
5508 "represents the signal and the second the response function!"));
5509 return;
5510 }
5511
5512 Convolution *cv = new Convolution(this, t, s[0], s[1]);
5513 cv->run();
5514 delete cv;
5515 }
5516
deconvolute()5517 void ApplicationWindow::deconvolute()
5518 {
5519 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("Table"))
5520 return;
5521
5522 Table *t = (Table *)d_workspace.activeSubWindow();
5523 QStringList s = t->selectedColumns();
5524 if ((int)s.count() != 2) {
5525 QMessageBox::warning(this, tr("Error"),
5526 tr("Please select two columns for this operation:\n the first "
5527 "represents the signal and the second the response function!"));
5528 return;
5529 }
5530
5531 Deconvolution *dcv = new Deconvolution(this, t, s[0], s[1]);
5532 dcv->run();
5533 delete dcv;
5534 }
5535
showColStatistics()5536 void ApplicationWindow::showColStatistics()
5537 {
5538 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("Table"))
5539 return;
5540 Table *t = (Table *)d_workspace.activeSubWindow();
5541
5542 if (int(t->selectedColumns().count()) > 0) {
5543 QList<int> targets;
5544 for (int i = 0; i < t->numCols(); i++)
5545 if (t->isColumnSelected(i, false))
5546 targets << i;
5547 newTableStatistics(t, TableStatistics::StatColumn, targets)->showNormal();
5548 } else
5549 QMessageBox::warning(this, tr("Column selection error"),
5550 tr("Please select a column first!"));
5551 }
5552
showRowStatistics()5553 void ApplicationWindow::showRowStatistics()
5554 {
5555 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("Table"))
5556 return;
5557 Table *t = (Table *)d_workspace.activeSubWindow();
5558
5559 if (t->numSelectedRows() > 0) {
5560 QList<int> targets;
5561 for (int i = 0; i < t->numRows(); i++)
5562 if (t->isRowSelected(i, false))
5563 targets << i;
5564 newTableStatistics(t, TableStatistics::StatRow, targets)->showNormal();
5565 } else
5566 QMessageBox::warning(this, tr("Row selection error"), tr("Please select a row first!"));
5567 }
5568
plot2VerticalLayers()5569 void ApplicationWindow::plot2VerticalLayers()
5570 {
5571 multilayerPlot(1, 2, defaultCurveStyle);
5572 }
5573
plot2HorizontalLayers()5574 void ApplicationWindow::plot2HorizontalLayers()
5575 {
5576 multilayerPlot(2, 1, defaultCurveStyle);
5577 }
5578
plot4Layers()5579 void ApplicationWindow::plot4Layers()
5580 {
5581 multilayerPlot(2, 2, defaultCurveStyle);
5582 }
5583
plotStackedLayers()5584 void ApplicationWindow::plotStackedLayers()
5585 {
5586 multilayerPlot(1, -1, defaultCurveStyle);
5587 }
5588
plotStackedHistograms()5589 void ApplicationWindow::plotStackedHistograms()
5590 {
5591 multilayerPlot(1, -1, Graph::Histogram);
5592 }
5593
showGeneralPlotDialog()5594 void ApplicationWindow::showGeneralPlotDialog()
5595 {
5596 MyWidget *plot = (MyWidget *)d_workspace.activeSubWindow();
5597 if (!plot)
5598 return;
5599
5600 if (plot->inherits("MultiLayer") && ((MultiLayer *)plot)->layers())
5601 showPlotDialog();
5602 else if (plot->inherits("Graph3D")) {
5603 if (auto gd = dynamic_cast<Plot3DDialog *>(showScaleDialog()))
5604 gd->showGeneralTab();
5605 }
5606 }
5607
showAxisDialog()5608 void ApplicationWindow::showAxisDialog()
5609 {
5610 QWidget *plot = (QWidget *)d_workspace.activeSubWindow();
5611 if (!plot)
5612 return;
5613
5614 if (plot->inherits("MultiLayer") && ((MultiLayer *)plot)->layers()) {
5615 if (auto gd = dynamic_cast<AxesDialog *>(showScaleDialog()))
5616 gd->showAxesPage();
5617 } else if (plot->inherits("Graph3D"))
5618 if (auto gd = dynamic_cast<Plot3DDialog *>(showScaleDialog()))
5619 gd->showAxisTab();
5620 }
5621
showGridDialog()5622 void ApplicationWindow::showGridDialog()
5623 {
5624 if (auto gd = dynamic_cast<AxesDialog *>(showScaleDialog()))
5625 gd->showGridPage();
5626 }
5627
showScaleDialog()5628 QDialog *ApplicationWindow::showScaleDialog()
5629 {
5630 QWidget *w = d_workspace.activeSubWindow();
5631 if (!w)
5632 return 0;
5633
5634 if (w->inherits("MultiLayer")) {
5635 if (((MultiLayer *)w)->isEmpty())
5636 return 0;
5637
5638 Graph *g = ((MultiLayer *)w)->activeGraph();
5639 auto &ad = addChild<AxesDialog>();
5640 ad.setGraph(g);
5641 ad.exec();
5642 return &ad;
5643 } else if (w->inherits("Graph3D"))
5644 return showPlot3dDialog();
5645
5646 return 0;
5647 }
5648
showScalePageFromAxisDialog(int axisPos)5649 AxesDialog *ApplicationWindow::showScalePageFromAxisDialog(int axisPos)
5650 {
5651 AxesDialog *gd = (AxesDialog *)showScaleDialog();
5652 if (gd)
5653 gd->setCurrentScale(axisPos);
5654
5655 return gd;
5656 }
5657
showAxisPageFromAxisDialog(int axisPos)5658 AxesDialog *ApplicationWindow::showAxisPageFromAxisDialog(int axisPos)
5659 {
5660 AxesDialog *gd = (AxesDialog *)showScaleDialog();
5661 if (gd) {
5662 gd->showAxesPage();
5663 gd->setCurrentScale(axisPos);
5664 }
5665 return gd;
5666 }
5667
showPlot3dDialog()5668 QDialog *ApplicationWindow::showPlot3dDialog()
5669 {
5670 if (d_workspace.activeSubWindow() && d_workspace.activeSubWindow()->inherits("Graph3D")) {
5671 Graph3D *g = (Graph3D *)d_workspace.activeSubWindow();
5672 if (!g->hasData()) {
5673 QApplication::restoreOverrideCursor();
5674 QMessageBox::warning(this, tr("Warning"),
5675 tr("Not available for empty 3D surface plots!"));
5676 return 0;
5677 }
5678
5679 Plot3DDialog *pd = new Plot3DDialog(this);
5680 pd->setPlot(g);
5681
5682 connect(pd,
5683 SIGNAL(updateColors(const QColor &, const QColor &, const QColor &, const QColor &,
5684 const QColor &, const QColor &)),
5685 g,
5686 SLOT(updateColors(const QColor &, const QColor &, const QColor &, const QColor &,
5687 const QColor &, const QColor &)));
5688 connect(pd, SIGNAL(setDataColorMap(const QString &)), g,
5689 SLOT(setDataColorMap(const QString &)));
5690 connect(pd, SIGNAL(updateDataColors(const QColor &, const QColor &)), g,
5691 SLOT(setDataColors(const QColor &, const QColor &)));
5692 connect(pd, SIGNAL(updateTitle(const QString &, const QColor &, const QFont &)), g,
5693 SLOT(updateTitle(const QString &, const QColor &, const QFont &)));
5694 connect(pd, SIGNAL(updateResolution(int)), g, SLOT(setResolution(int)));
5695 connect(pd, SIGNAL(showColorLegend(bool)), g, SLOT(showColorLegend(bool)));
5696 connect(pd, SIGNAL(setOrtho(bool)), g, SLOT(setOrtho(bool)));
5697 connect(pd, SIGNAL(updateLabel(int, const QString &, const QFont &)), g,
5698 SLOT(updateLabel(int, const QString &, const QFont &)));
5699 connect(pd, SIGNAL(updateScale(int, const QStringList &)), g,
5700 SLOT(updateScale(int, const QStringList &)));
5701 connect(pd, SIGNAL(adjustLabels(int)), g, SLOT(adjustLabels(int)));
5702 connect(pd, SIGNAL(updateTickLength(int, double, double)), g,
5703 SLOT(updateTickLength(int, double, double)));
5704 connect(pd, SIGNAL(setNumbersFont(const QFont &)), g, SLOT(setNumbersFont(const QFont &)));
5705 connect(pd, SIGNAL(updateMeshLineWidth(int)), g, SLOT(setMeshLineWidth(int)));
5706 connect(pd, SIGNAL(updateBars(double)), g, SLOT(updateBars(double)));
5707 connect(pd, SIGNAL(updatePoints(double, bool)), g, SLOT(updatePoints(double, bool)));
5708 connect(pd, SIGNAL(showWorksheet()), g, SLOT(showWorksheet()));
5709 connect(pd, SIGNAL(updateZoom(double)), g, SLOT(updateZoom(double)));
5710 connect(pd, SIGNAL(updateScaling(double, double, double)), g,
5711 SLOT(updateScaling(double, double, double)));
5712 connect(pd, SIGNAL(updateCones(double, int)), g, SLOT(updateCones(double, int)));
5713 connect(pd, SIGNAL(updateCross(double, double, bool, bool)), g,
5714 SLOT(updateCross(double, double, bool, bool)));
5715
5716 pd->setMeshLineWidth(g->meshLineWidth());
5717 pd->setDataColors(g->minDataColor(), g->maxDataColor());
5718 pd->setColors(g->titleColor(), g->meshColor(), g->axesColor(), g->numColor(),
5719 g->labelColor(), g->bgColor(), g->gridColor());
5720
5721 pd->setTitle(g->plotTitle());
5722 pd->setTitleFont(g->titleFont());
5723
5724 pd->setZoom(g->zoom());
5725 pd->setScaling(g->xScale(), g->yScale(), g->zScale());
5726 pd->setResolution(g->resolution());
5727 pd->showLegend(g->isLegendOn());
5728 pd->setOrthogonal(g->isOrthogonal());
5729 pd->setAxesLabels(g->axesLabels());
5730 pd->setAxesTickLengths(g->axisTickLengths());
5731 pd->setAxesFonts(g->xAxisLabelFont(), g->yAxisLabelFont(), g->zAxisLabelFont());
5732 pd->setScales(g->scaleLimits());
5733 pd->setLabelsDistance(g->labelsDistance());
5734 pd->setNumbersFonts(g->numbersFont());
5735
5736 if (g->coordStyle() == Qwt3D::NOCOORD)
5737 pd->disableAxesOptions();
5738
5739 Qwt3D::PLOTSTYLE style = g->plotStyle();
5740 Graph3D::PointStyle pt = g->pointType();
5741
5742 if (style == Qwt3D::USER) {
5743 switch (pt) {
5744 case Graph3D::None:
5745 break;
5746
5747 case Graph3D::Dots:
5748 pd->disableMeshOptions();
5749 pd->initPointsOptionsStack();
5750 pd->showPointsTab(g->pointsSize(), g->smoothPoints());
5751 break;
5752
5753 case Graph3D::VerticalBars:
5754 pd->showBarsTab(g->barsRadius());
5755 break;
5756
5757 case Graph3D::HairCross:
5758 pd->disableMeshOptions();
5759 pd->initPointsOptionsStack();
5760 pd->showCrossHairTab(g->crossHairRadius(), g->crossHairLinewidth(),
5761 g->smoothCrossHair(), g->boxedCrossHair());
5762 break;
5763
5764 case Graph3D::Cones:
5765 pd->disableMeshOptions();
5766 pd->initPointsOptionsStack();
5767 pd->showConesTab(g->coneRadius(), g->coneQuality());
5768 break;
5769 }
5770 } else if (style == Qwt3D::FILLED)
5771 pd->disableMeshOptions();
5772 else if (style == Qwt3D::HIDDENLINE || style == Qwt3D::WIREFRAME)
5773 pd->disableLegend();
5774
5775 if (g->grids() == 0)
5776 pd->disableGridOptions();
5777
5778 if (g->userFunction())
5779 pd->customWorksheetBtn(QString());
5780 else if (g->getTable())
5781 pd->customWorksheetBtn(tr("&Worksheet"));
5782 else if (g->matrix())
5783 pd->customWorksheetBtn(tr("&Matrix"));
5784
5785 pd->exec();
5786 return pd;
5787 } else
5788 return 0;
5789 }
5790
showPlotDialog(int curveKey)5791 void ApplicationWindow::showPlotDialog(int curveKey)
5792 {
5793 QWidget *w = d_workspace.activeSubWindow();
5794 if (!w)
5795 return;
5796
5797 if (w->inherits("MultiLayer")) {
5798 PlotDialog *pd = new PlotDialog(d_extended_plot_dialog, this);
5799 pd->setAttribute(Qt::WA_DeleteOnClose);
5800 pd->setMultiLayer((MultiLayer *)w);
5801 pd->insertColumnsList(columnsList());
5802 if (curveKey >= 0) {
5803 Graph *g = ((MultiLayer *)w)->activeGraph();
5804 if (g)
5805 pd->selectCurve(g->curveIndex(curveKey));
5806 }
5807 pd->initFonts(plotTitleFont, plotAxesFont, plotNumbersFont, plotLegendFont);
5808 pd->showAll(d_extended_plot_dialog);
5809 pd->show();
5810 }
5811 }
5812
showCurvePlotDialog()5813 void ApplicationWindow::showCurvePlotDialog()
5814 {
5815 showPlotDialog(actionShowCurvePlotDialog->data().toInt());
5816 }
5817
showCurveContextMenuImpl(int curveKey)5818 QMenu *ApplicationWindow::showCurveContextMenuImpl(int curveKey)
5819 {
5820 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
5821 return nullptr;
5822
5823 Graph *g = ((MultiLayer *)d_workspace.activeSubWindow())->activeGraph();
5824 DataCurve *c = (DataCurve *)g->curve(g->curveIndex(curveKey));
5825 if (!c || !c->isVisible())
5826 return nullptr;
5827
5828 auto curveMenu = new QMenu(this);
5829 curveMenu->addAction(c->title().text(), this, SLOT(showCurvePlotDialog()));
5830 curveMenu->addSeparator();
5831
5832 curveMenu->addAction(actionHideCurve);
5833 actionHideCurve->setData(curveKey);
5834
5835 if (g->visibleCurves() > 1 && c->type() == Graph::Function) {
5836 curveMenu->addAction(actionHideOtherCurves);
5837 actionHideOtherCurves->setData(curveKey);
5838 } else if (c->type() != Graph::Function) {
5839 if ((g->visibleCurves() - c->errorBarsList().count()) > 1) {
5840 curveMenu->addAction(actionHideOtherCurves);
5841 actionHideOtherCurves->setData(curveKey);
5842 }
5843 }
5844
5845 if (g->visibleCurves() != g->curves())
5846 curveMenu->addAction(actionShowAllCurves);
5847 curveMenu->addSeparator();
5848
5849 if (c->type() == Graph::Function) {
5850 curveMenu->addAction(actionEditFunction);
5851 actionEditFunction->setData(curveKey);
5852 } else if (c->type() != Graph::ErrorBars) {
5853 curveMenu->addAction(actionEditCurveRange);
5854 actionEditCurveRange->setData(curveKey);
5855
5856 curveMenu->addAction(actionCurveFullRange);
5857 if (c->isFullRange())
5858 actionCurveFullRange->setDisabled(true);
5859 else
5860 actionCurveFullRange->setEnabled(true);
5861 actionCurveFullRange->setData(curveKey);
5862
5863 curveMenu->addSeparator();
5864 }
5865
5866 curveMenu->addAction(actionShowCurveWorksheet);
5867 actionShowCurveWorksheet->setData(curveKey);
5868
5869 curveMenu->addAction(actionShowCurvePlotDialog);
5870 actionShowCurvePlotDialog->setData(curveKey);
5871
5872 curveMenu->addSeparator();
5873
5874 curveMenu->addAction(actionRemoveCurve);
5875 actionRemoveCurve->setData(curveKey);
5876 return curveMenu;
5877 }
5878
showAllCurves()5879 void ApplicationWindow::showAllCurves()
5880 {
5881 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
5882 return;
5883
5884 Graph *g = ((MultiLayer *)d_workspace.activeSubWindow())->activeGraph();
5885 if (!g)
5886 return;
5887
5888 for (int i = 0; i < g->curves(); i++)
5889 g->showCurve(i);
5890 g->replot();
5891 }
5892
hideOtherCurves()5893 void ApplicationWindow::hideOtherCurves()
5894 {
5895 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
5896 return;
5897
5898 Graph *g = ((MultiLayer *)d_workspace.activeSubWindow())->activeGraph();
5899 if (!g)
5900 return;
5901
5902 int curveKey = actionHideOtherCurves->data().toInt();
5903 for (int i = 0; i < g->curves(); i++)
5904 g->showCurve(i, false);
5905
5906 g->showCurve(g->curveIndex(curveKey));
5907 g->replot();
5908 }
5909
hideCurve()5910 void ApplicationWindow::hideCurve()
5911 {
5912 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
5913 return;
5914
5915 Graph *g = ((MultiLayer *)d_workspace.activeSubWindow())->activeGraph();
5916 if (!g)
5917 return;
5918
5919 int curveKey = actionHideCurve->data().toInt();
5920 g->showCurve(g->curveIndex(curveKey), false);
5921 }
5922
removeCurve()5923 void ApplicationWindow::removeCurve()
5924 {
5925 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
5926 return;
5927
5928 Graph *g = ((MultiLayer *)d_workspace.activeSubWindow())->activeGraph();
5929 if (!g)
5930 return;
5931
5932 int curveKey = actionRemoveCurve->data().toInt();
5933 g->removeCurve(g->curveIndex(curveKey));
5934 g->updatePlot();
5935 }
5936
showCurveWorksheet(Graph * g,int curveIndex)5937 void ApplicationWindow::showCurveWorksheet(Graph *g, int curveIndex)
5938 {
5939 if (!g)
5940 return;
5941
5942 QwtPlotItem *it = g->plotItem(curveIndex);
5943 if (!it)
5944 return;
5945
5946 if (auto sp = dynamic_cast<Spectrogram *>(it)) {
5947 if (sp->matrix())
5948 sp->matrix()->showMaximized();
5949 } else if (((PlotCurve *)it)->type() == Graph::Function)
5950 g->createTable((PlotCurve *)it);
5951 else
5952 showTable(it->title().text());
5953 }
5954
showCurveWorksheet()5955 void ApplicationWindow::showCurveWorksheet()
5956 {
5957 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
5958 return;
5959
5960 Graph *g = ((MultiLayer *)d_workspace.activeSubWindow())->activeGraph();
5961 if (!g)
5962 return;
5963
5964 int curveKey = actionShowCurveWorksheet->data().toInt();
5965 showCurveWorksheet(g, g->curveIndex(curveKey));
5966 }
5967
zoomIn()5968 void ApplicationWindow::zoomIn()
5969 {
5970 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
5971 return;
5972
5973 MultiLayer *plot = (MultiLayer *)d_workspace.activeSubWindow();
5974 if (plot->isEmpty()) {
5975 QMessageBox::warning(this, tr("Warning"),
5976 tr("<h4>There are no plot layers available in this window.</h4>"
5977 "<p><h4>Please add a layer and try again!</h4>"));
5978 btnPointer->setChecked(true);
5979 return;
5980 }
5981
5982 if ((Graph *)plot->activeGraph()->isPiePlot()) {
5983 if (btnZoomIn->isChecked())
5984 QMessageBox::warning(this, tr("Warning"),
5985 tr("This functionality is not available for pie plots!"));
5986 btnPointer->setChecked(true);
5987 return;
5988 }
5989
5990 QWidgetList graphsList = plot->graphPtrs();
5991 foreach (QWidget *widget, graphsList) {
5992 Graph *g = (Graph *)widget;
5993 if (!g->isPiePlot())
5994 g->zoom(true);
5995 }
5996 }
5997
zoomOut()5998 void ApplicationWindow::zoomOut()
5999 {
6000 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
6001 return;
6002
6003 MultiLayer *plot = (MultiLayer *)d_workspace.activeSubWindow();
6004 if (plot->isEmpty() || (Graph *)plot->activeGraph()->isPiePlot())
6005 return;
6006
6007 ((Graph *)plot->activeGraph())->zoomOut();
6008 btnPointer->setChecked(true);
6009 }
6010
setAutoScale()6011 void ApplicationWindow::setAutoScale()
6012 {
6013 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
6014 return;
6015
6016 MultiLayer *plot = (MultiLayer *)d_workspace.activeSubWindow();
6017 if (plot->isEmpty()) {
6018 QMessageBox::warning(this, tr("Warning"),
6019 tr("<h4>There are no plot layers available in this window.</h4>"));
6020 return;
6021 }
6022
6023 Graph *g = (Graph *)plot->activeGraph();
6024 if (g) {
6025 g->setAutoScale();
6026 emit modified();
6027 }
6028 }
6029
removePoints()6030 void ApplicationWindow::removePoints()
6031 {
6032 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
6033 return;
6034
6035 MultiLayer *plot = (MultiLayer *)d_workspace.activeSubWindow();
6036 if (plot->isEmpty()) {
6037 QMessageBox::warning(this, tr("Warning"),
6038 tr("<h4>There are no plot layers available in this window.</h4>"
6039 "<p><h4>Please add a layer and try again!</h4>"));
6040 btnPointer->setChecked(true);
6041 return;
6042 }
6043
6044 Graph *g = (Graph *)plot->activeGraph();
6045 if (!g || !g->validCurvesDataSize()) {
6046 btnPointer->setChecked(true);
6047 return;
6048 }
6049
6050 if (g->isPiePlot()) {
6051 QMessageBox::warning(this, tr("Warning"),
6052 tr("This functionality is not available for pie plots!"));
6053 btnPointer->setChecked(true);
6054 return;
6055 } else {
6056 switch (QMessageBox::warning(this, tr("SciDAVis"),
6057 tr("This will modify the data in the worksheets!\nAre you "
6058 "sure you want to continue?"),
6059 tr("Continue"), tr("Cancel"), 0, 1)) {
6060 case 0:
6061 g->setActiveTool(new DataPickerTool(g, this, DataPickerTool::Remove, d_status_info,
6062 SLOT(setText(const QString &))));
6063 break;
6064
6065 case 1:
6066 btnPointer->setChecked(true);
6067 break;
6068 }
6069 }
6070 }
6071
movePoints()6072 void ApplicationWindow::movePoints()
6073 {
6074 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
6075 return;
6076
6077 MultiLayer *plot = (MultiLayer *)d_workspace.activeSubWindow();
6078 if (plot->isEmpty()) {
6079 QMessageBox::warning(this, tr("Warning"),
6080 tr("<h4>There are no plot layers available in this window.</h4>"
6081 "<p><h4>Please add a layer and try again!</h4>"));
6082 btnPointer->setChecked(true);
6083 return;
6084 }
6085
6086 Graph *g = (Graph *)plot->activeGraph();
6087 if (!g || !g->validCurvesDataSize()) {
6088 btnPointer->setChecked(true);
6089 return;
6090 }
6091
6092 if (g->isPiePlot()) {
6093 QMessageBox::warning(this, tr("Warning"),
6094 tr("This functionality is not available for pie plots!"));
6095
6096 btnPointer->setChecked(true);
6097 return;
6098 } else {
6099 switch (QMessageBox::warning(this, tr("SciDAVis"),
6100 tr("This will modify the data in the worksheets!\nAre you "
6101 "sure you want to continue?"),
6102 tr("Continue"), tr("Cancel"), 0, 1)) {
6103 case 0:
6104 if (g) {
6105 g->setActiveTool(new DataPickerTool(g, this, DataPickerTool::Move, d_status_info,
6106 SLOT(setText(const QString &))));
6107 }
6108 break;
6109
6110 case 1:
6111 btnPointer->setChecked(true);
6112 break;
6113 }
6114 }
6115 }
6116
exportPDF()6117 void ApplicationWindow::exportPDF()
6118 {
6119 QWidget *w = d_workspace.activeSubWindow();
6120 if (!w)
6121 return;
6122
6123 if (w->inherits("MultiLayer") && ((MultiLayer *)w)->isEmpty()) {
6124 QMessageBox::warning(this, tr("Warning"),
6125 tr("<h4>There are no plot layers available in this window.</h4>"));
6126 return;
6127 }
6128
6129 QString fname = QFileDialog::getSaveFileName(this, tr("Choose a filename to save under"),
6130 workingDir, "*.pdf");
6131 if (!fname.isEmpty()) {
6132 QFileInfo fi(fname);
6133 QString baseName = fi.fileName();
6134 if (!baseName.contains("."))
6135 fname.append(".pdf");
6136
6137 workingDir = fi.absolutePath();
6138
6139 QFile f(fname);
6140 if (!f.open(QIODevice::WriteOnly)) {
6141 QMessageBox::critical(this, tr("Export Error"),
6142 tr("Could not write to file: <h4>%1</h4><p>Please verify that "
6143 "you have the right to write to this location or that the "
6144 "file is not being used by another application!")
6145 .arg(fname));
6146 return;
6147 }
6148
6149 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
6150
6151 ((MyWidget *)w)->exportPDF(fname);
6152
6153 QApplication::restoreOverrideCursor();
6154 }
6155 }
6156
print(MyWidget * w)6157 void ApplicationWindow::print(MyWidget *w)
6158 {
6159 if (w->inherits("MultiLayer") && ((MultiLayer *)w)->isEmpty()) {
6160 QMessageBox::warning(this, tr("Warning"),
6161 tr("<h4>There are no plot layers available in this window.</h4>"));
6162 return;
6163 }
6164
6165 w->print();
6166 }
6167
6168 // print active window
print()6169 void ApplicationWindow::print()
6170 {
6171 MyWidget *w = (MyWidget *)(d_workspace.activeSubWindow());
6172 if (!w)
6173 return;
6174
6175 print(w);
6176 }
6177
6178 // print window from project explorer
printWindow()6179 void ApplicationWindow::printWindow()
6180 {
6181 WindowListItem *it = (WindowListItem *)lv.currentItem();
6182 MyWidget *w = it->window();
6183 if (!w)
6184 return;
6185
6186 print(w);
6187 }
6188
printAllPlots()6189 void ApplicationWindow::printAllPlots()
6190 {
6191 QPrinter printer;
6192 printer.setPageOrientation(QPageLayout::Landscape);
6193 printer.setColorMode(QPrinter::Color);
6194 printer.setFullPage(true);
6195
6196 QList<MyWidget *> windows = windowsList();
6197
6198 int plots = 0;
6199 for (auto w : windows) {
6200 if (w->inherits("MultiLayer"))
6201 plots++;
6202 }
6203
6204 QPrintDialog dialog(&printer, this);
6205 dialog.setMinMax(0, plots);
6206 if (dialog.exec()) {
6207 QPainter paint(&printer);
6208
6209 printer.setFromTo(0, plots);
6210
6211 for (auto w : windows) {
6212 if (w->inherits("MultiLayer") && printer.newPage())
6213 ((MultiLayer *)w)->printAllLayers(&paint);
6214 }
6215 paint.end();
6216 }
6217 }
6218
showExpGrowthDialog()6219 void ApplicationWindow::showExpGrowthDialog()
6220 {
6221 showExpDecayDialog(-1);
6222 }
6223
showExpDecayDialog()6224 void ApplicationWindow::showExpDecayDialog()
6225 {
6226 showExpDecayDialog(1);
6227 }
6228
showExpDecayDialog(int type)6229 void ApplicationWindow::showExpDecayDialog(int type)
6230 {
6231 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
6232 return;
6233
6234 Graph *g = ((MultiLayer *)d_workspace.activeSubWindow())->activeGraph();
6235 if (!g || !g->validCurvesDataSize())
6236 return;
6237
6238 ExpDecayDialog *edd = new ExpDecayDialog(type, this);
6239 edd->setAttribute(Qt::WA_DeleteOnClose);
6240 connect(g, SIGNAL(destroyed()), edd, SLOT(close()));
6241
6242 edd->setGraph(g);
6243 edd->show();
6244 }
6245
showTwoExpDecayDialog()6246 void ApplicationWindow::showTwoExpDecayDialog()
6247 {
6248 showExpDecayDialog(2);
6249 }
6250
showExpDecay3Dialog()6251 void ApplicationWindow::showExpDecay3Dialog()
6252 {
6253 showExpDecayDialog(3);
6254 }
6255
showFitDialog()6256 void ApplicationWindow::showFitDialog()
6257 {
6258 QWidget *w = d_workspace.activeSubWindow();
6259 if (!w)
6260 return;
6261
6262 MultiLayer *plot = 0;
6263 if (w->inherits("MultiLayer"))
6264 plot = (MultiLayer *)w;
6265 else if (w->inherits("Table"))
6266 plot = multilayerPlot((Table *)w, ((Table *)w)->drawableColumnSelection(),
6267 Graph::LineSymbols);
6268
6269 if (!plot)
6270 return;
6271
6272 Graph *g = (Graph *)plot->activeGraph();
6273 if (!g || !g->validCurvesDataSize())
6274 return;
6275
6276 FitDialog *fd = new FitDialog(this);
6277 fd->setAttribute(Qt::WA_DeleteOnClose);
6278 connect(fd, SIGNAL(clearFunctionsList()), this, SLOT(clearFitFunctionsList()));
6279 connect(fd, SIGNAL(saveFunctionsList(const QStringList &)), this,
6280 SLOT(saveFitFunctionsList(const QStringList &)));
6281 connect(plot, SIGNAL(destroyed()), fd, SLOT(close()));
6282
6283 fd->addUserFunctions(fitFunctions);
6284 fd->setGraph(g);
6285 fd->setSrcTables(tableList());
6286 fd->exec();
6287 }
6288
showFilterDialog(int filter)6289 void ApplicationWindow::showFilterDialog(int filter)
6290 {
6291 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
6292 return;
6293
6294 Graph *g = ((MultiLayer *)d_workspace.activeSubWindow())->activeGraph();
6295 if (g && g->validCurvesDataSize()) {
6296 FilterDialog *fd = new FilterDialog(filter, this);
6297 fd->setAttribute(Qt::WA_DeleteOnClose);
6298 fd->setGraph(g);
6299 fd->exec();
6300 }
6301 }
6302
lowPassFilterDialog()6303 void ApplicationWindow::lowPassFilterDialog()
6304 {
6305 showFilterDialog(FFTFilter::LowPass);
6306 }
6307
highPassFilterDialog()6308 void ApplicationWindow::highPassFilterDialog()
6309 {
6310 showFilterDialog(FFTFilter::HighPass);
6311 }
6312
bandPassFilterDialog()6313 void ApplicationWindow::bandPassFilterDialog()
6314 {
6315 showFilterDialog(FFTFilter::BandPass);
6316 }
6317
bandBlockFilterDialog()6318 void ApplicationWindow::bandBlockFilterDialog()
6319 {
6320 showFilterDialog(FFTFilter::BandBlock);
6321 }
6322
showFFTDialog()6323 void ApplicationWindow::showFFTDialog()
6324 {
6325 QWidget *w = d_workspace.activeSubWindow();
6326 if (!w)
6327 return;
6328
6329 FFTDialog *sd = 0;
6330 if (w->inherits("MultiLayer")) {
6331 Graph *g = ((MultiLayer *)w)->activeGraph();
6332 if (g && g->validCurvesDataSize()) {
6333 sd = new FFTDialog(FFTDialog::onGraph, this);
6334 sd->setAttribute(Qt::WA_DeleteOnClose);
6335 sd->setGraph(g);
6336 }
6337 } else if (w->inherits("Table")) {
6338 sd = new FFTDialog(FFTDialog::onTable, this);
6339 sd->setAttribute(Qt::WA_DeleteOnClose);
6340 sd->setTable((Table *)w);
6341 }
6342
6343 if (sd)
6344 sd->exec();
6345 }
6346
showSmoothDialog(int m)6347 void ApplicationWindow::showSmoothDialog(int m)
6348 {
6349 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
6350 return;
6351
6352 Graph *g = ((MultiLayer *)d_workspace.activeSubWindow())->activeGraph();
6353 if (!g || !g->validCurvesDataSize())
6354 return;
6355
6356 SmoothCurveDialog *sd = new SmoothCurveDialog(m, this);
6357 sd->setAttribute(Qt::WA_DeleteOnClose);
6358 sd->setGraph(g);
6359 sd->exec();
6360 }
6361
showSmoothSavGolDialog()6362 void ApplicationWindow::showSmoothSavGolDialog()
6363 {
6364 showSmoothDialog(SmoothFilter::SavitzkyGolay);
6365 }
6366
showSmoothFFTDialog()6367 void ApplicationWindow::showSmoothFFTDialog()
6368 {
6369 showSmoothDialog(SmoothFilter::FFT);
6370 }
6371
showSmoothAverageDialog()6372 void ApplicationWindow::showSmoothAverageDialog()
6373 {
6374 showSmoothDialog(SmoothFilter::Average);
6375 }
6376
showInterpolationDialog()6377 void ApplicationWindow::showInterpolationDialog()
6378 {
6379 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
6380 return;
6381
6382 Graph *g = ((MultiLayer *)d_workspace.activeSubWindow())->activeGraph();
6383 if (!g || !g->validCurvesDataSize())
6384 return;
6385
6386 InterpolationDialog *id = new InterpolationDialog(this);
6387 id->setAttribute(Qt::WA_DeleteOnClose);
6388 connect(g, SIGNAL(destroyed()), id, SLOT(close()));
6389 id->setGraph(g);
6390 id->show();
6391 }
6392
showFitPolynomDialog()6393 void ApplicationWindow::showFitPolynomDialog()
6394 {
6395 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
6396 return;
6397
6398 Graph *g = ((MultiLayer *)d_workspace.activeSubWindow())->activeGraph();
6399 if (!g || !g->validCurvesDataSize())
6400 return;
6401
6402 PolynomFitDialog *pfd = new PolynomFitDialog(this);
6403 pfd->setAttribute(Qt::WA_DeleteOnClose);
6404 connect(g, SIGNAL(destroyed()), pfd, SLOT(close()));
6405 pfd->setGraph(g);
6406 pfd->show();
6407 }
6408
fitLinear()6409 void ApplicationWindow::fitLinear()
6410 {
6411 analysis("fitLinear");
6412 }
6413
updateLog(const QString & result)6414 void ApplicationWindow::updateLog(const QString &result)
6415 {
6416 if (!result.isEmpty()) {
6417 logInfo += result;
6418 showResults(true);
6419 emit modified();
6420 }
6421 }
6422
showIntegrationDialog()6423 void ApplicationWindow::showIntegrationDialog()
6424 {
6425 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
6426 return;
6427
6428 Graph *g = ((MultiLayer *)d_workspace.activeSubWindow())->activeGraph();
6429 if (!g || !g->validCurvesDataSize())
6430 return;
6431
6432 IntDialog *id = new IntDialog(this);
6433 id->setAttribute(Qt::WA_DeleteOnClose);
6434 connect(g, SIGNAL(destroyed()), id, SLOT(close()));
6435 id->setGraph(g);
6436 id->show();
6437 }
6438
fitSigmoidal()6439 void ApplicationWindow::fitSigmoidal()
6440 {
6441 analysis("fitSigmoidal");
6442 }
6443
fitGauss()6444 void ApplicationWindow::fitGauss()
6445 {
6446 analysis("fitGauss");
6447 }
6448
fitLorentz()6449 void ApplicationWindow::fitLorentz()
6450
6451 {
6452 analysis("fitLorentz");
6453 }
6454
differentiate()6455 void ApplicationWindow::differentiate()
6456 {
6457 analysis("differentiate");
6458 }
6459
showResults(bool ok)6460 void ApplicationWindow::showResults(bool ok)
6461 {
6462 if (ok) {
6463 if (!logInfo.isEmpty())
6464 results->setText(logInfo);
6465 else
6466 results->setText(tr("Sorry, there are no results to display!"));
6467
6468 logWindow.show();
6469 QTextCursor cur = results->textCursor();
6470 cur.movePosition(QTextCursor::End);
6471 results->setTextCursor(cur);
6472 } else
6473 logWindow.hide();
6474 }
6475
showResults(const QString & s,bool ok)6476 void ApplicationWindow::showResults(const QString &s, bool ok)
6477 {
6478 logInfo += s;
6479 if (!logInfo.isEmpty())
6480 results->setText(logInfo);
6481 showResults(ok);
6482 }
6483
showScreenReader()6484 void ApplicationWindow::showScreenReader()
6485 {
6486 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
6487 return;
6488
6489 MultiLayer *plot = (MultiLayer *)d_workspace.activeSubWindow();
6490 if (plot->isEmpty()) {
6491 QMessageBox::warning(this, tr("Warning"),
6492 tr("<h4>There are no plot layers available in this window.</h4>"
6493 "<p><h4>Please add a layer and try again!</h4>"));
6494 btnPointer->setChecked(true);
6495 return;
6496 }
6497
6498 QWidgetList graphsList = plot->graphPtrs();
6499 foreach (QWidget *w, graphsList)
6500 ((Graph *)w)
6501 ->setActiveTool(new ScreenPickerTool((Graph *)w, d_status_info,
6502 SLOT(setText(const QString &))));
6503 }
6504
showRangeSelectors()6505 void ApplicationWindow::showRangeSelectors()
6506 {
6507 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
6508 return;
6509
6510 MultiLayer *plot = (MultiLayer *)d_workspace.activeSubWindow();
6511 if (plot->isEmpty()) {
6512 QMessageBox::warning(this, tr("Warning"),
6513 tr("There are no plot layers available in this window!"));
6514 btnPointer->setChecked(true);
6515 return;
6516 }
6517
6518 Graph *g = (Graph *)plot->activeGraph();
6519 if (!g)
6520 return;
6521
6522 if (!g->curves()) {
6523 QMessageBox::warning(this, tr("Warning"),
6524 tr("There are no curves available on this plot!"));
6525 btnPointer->setChecked(true);
6526 return;
6527 } else if (g->isPiePlot()) {
6528 QMessageBox::warning(this, tr("Warning"),
6529 tr("This functionality is not available for pie plots!"));
6530 btnPointer->setChecked(true);
6531 return;
6532 }
6533
6534 g->enableRangeSelectors(d_status_info, SLOT(setText(const QString &)));
6535 }
6536
showCursor()6537 void ApplicationWindow::showCursor()
6538 {
6539 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
6540 return;
6541
6542 MultiLayer *plot = (MultiLayer *)d_workspace.activeSubWindow();
6543 if (plot->isEmpty()) {
6544 QMessageBox::warning(this, tr("Warning"),
6545 tr("<h4>There are no plot layers available in this window.</h4>"
6546 "<p><h4>Please add a layer and try again!</h4>"));
6547 btnPointer->setChecked(true);
6548 return;
6549 }
6550
6551 if ((Graph *)plot->activeGraph()->isPiePlot()) {
6552 QMessageBox::warning(this, tr("Warning"),
6553 tr("This functionality is not available for pie plots!"));
6554
6555 btnPointer->setChecked(true);
6556 return;
6557 }
6558
6559 QWidgetList graphsList = plot->graphPtrs();
6560 foreach (QWidget *w, graphsList)
6561 if (!((Graph *)w)->isPiePlot() && ((Graph *)w)->validCurvesDataSize())
6562 ((Graph *)w)
6563 ->setActiveTool(new DataPickerTool((Graph *)w, this, DataPickerTool::Display,
6564 d_status_info,
6565 SLOT(setText(const QString &))));
6566 }
6567
newLegend()6568 void ApplicationWindow::newLegend()
6569 {
6570 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
6571 return;
6572
6573 MultiLayer *plot = (MultiLayer *)d_workspace.activeSubWindow();
6574 if (plot->isEmpty()) {
6575 QMessageBox::warning(this, tr("Warning"),
6576 tr("<h4>There are no plot layers available in this window.</h4>"
6577 "<p><h4>Please add a layer and try again!</h4>"));
6578 return;
6579 }
6580
6581 Graph *g = (Graph *)plot->activeGraph();
6582 if (g)
6583 g->newLegend();
6584 }
6585
addTimeStamp()6586 void ApplicationWindow::addTimeStamp()
6587 {
6588 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
6589 return;
6590
6591 MultiLayer *plot = (MultiLayer *)d_workspace.activeSubWindow();
6592 if (plot->isEmpty()) {
6593 QMessageBox::warning(this, tr("Warning"),
6594 tr("<h4>There are no plot layers available in this window.</h4>"
6595 "<p><h4>Please add a layer and try again!</h4>"));
6596 return;
6597 }
6598
6599 Graph *g = (Graph *)plot->activeGraph();
6600 if (g)
6601 g->addTimeStamp();
6602 }
6603
disableAddText()6604 void ApplicationWindow::disableAddText()
6605 {
6606 actionAddText->setChecked(false);
6607 showTextDialog();
6608 }
6609
addText()6610 void ApplicationWindow::addText()
6611 {
6612 if (!btnPointer->isChecked())
6613 btnPointer->setChecked(true);
6614
6615 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
6616 return;
6617
6618 MultiLayer *plot = (MultiLayer *)d_workspace.activeSubWindow();
6619
6620 switch (QMessageBox::information(
6621 this, tr("Add new layer?"),
6622 tr("Do you want to add the text on a new layer or on the active layer?"),
6623 tr("On &New Layer"), tr("On &Active Layer"), tr("&Cancel"), 0, 2)) {
6624 case 0:
6625 plot->addTextLayer(legendFrameStyle, plotLegendFont, legendTextColor, legendBackground);
6626 break;
6627
6628 case 1: {
6629 if (plot->isEmpty()) {
6630 QMessageBox::warning(this, tr("Warning"),
6631 tr("<h4>There are no plot layers available in this window.</h4>"
6632 "<p><h4>Please add a layer and try again!</h4>"));
6633
6634 actionAddText->setChecked(false);
6635 return;
6636 }
6637
6638 Graph *g = (Graph *)plot->activeGraph();
6639 if (g)
6640 g->drawText(true);
6641 } break;
6642
6643 case 2:
6644 actionAddText->setChecked(false);
6645 return;
6646 break;
6647 }
6648 }
6649
addImage()6650 void ApplicationWindow::addImage()
6651 {
6652 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
6653 return;
6654
6655 MultiLayer *plot = (MultiLayer *)d_workspace.activeSubWindow();
6656 if (plot->isEmpty()) {
6657 QMessageBox::warning(this, tr("Warning"),
6658 tr("<h4>There are no plot layers available in this window.</h4>"
6659 "<p><h4>Please add a layer and try again!</h4>"));
6660 return;
6661 }
6662
6663 Graph *g = (Graph *)plot->activeGraph();
6664 if (!g)
6665 return;
6666
6667 QList<QByteArray> list = QImageReader::supportedImageFormats();
6668 QString filter = tr("Images") + " (", aux1, aux2;
6669 for (int i = 0; i < (int)list.count(); i++) {
6670 aux1 = " *." + list[i] + " ";
6671 aux2 += " *." + list[i] + ";;";
6672 filter += aux1;
6673 }
6674 filter += ");;" + aux2;
6675
6676 QString fn =
6677 QFileDialog::getOpenFileName(this, tr("Insert image from file"), imagesDirPath, filter);
6678 if (!fn.isEmpty()) {
6679 QFileInfo fi(fn);
6680 imagesDirPath = fi.absolutePath();
6681
6682 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
6683 g->addImage(fn);
6684 QApplication::restoreOverrideCursor();
6685 }
6686 }
6687
drawLine()6688 void ApplicationWindow::drawLine()
6689 {
6690 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
6691 return;
6692
6693 MultiLayer *plot = (MultiLayer *)d_workspace.activeSubWindow();
6694 if (plot->isEmpty()) {
6695 QMessageBox::warning(this, tr("Warning"),
6696 tr("<h4>There are no plot layers available in this window.</h4>"
6697 "<p><h4>Please add a layer and try again!</h4>"));
6698
6699 btnPointer->setChecked(true);
6700 return;
6701 }
6702
6703 Graph *g = (Graph *)plot->activeGraph();
6704 if (g) {
6705 g->drawLine(true);
6706 emit modified();
6707 }
6708 }
6709
drawArrow()6710 void ApplicationWindow::drawArrow()
6711 {
6712 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
6713 return;
6714
6715 MultiLayer *plot = (MultiLayer *)d_workspace.activeSubWindow();
6716 if (plot->isEmpty()) {
6717 QMessageBox::warning(this, tr("Warning"),
6718 tr("<h4>There are no plot layers available in this window.</h4>"
6719 "<p><h4>Please add a layer and try again!</h4>"));
6720
6721 btnPointer->setChecked(true);
6722 return;
6723 }
6724
6725 Graph *g = (Graph *)plot->activeGraph();
6726 if (g) {
6727 g->drawLine(true, 1);
6728 emit modified();
6729 }
6730 }
6731
showImageDialog()6732 void ApplicationWindow::showImageDialog()
6733 {
6734 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
6735 return;
6736
6737 Graph *g = ((MultiLayer *)d_workspace.activeSubWindow())->activeGraph();
6738 if (g) {
6739 ImageMarker *im = (ImageMarker *)g->selectedMarkerPtr();
6740 if (!im)
6741 return;
6742
6743 ImageDialog *id = new ImageDialog(this);
6744 id->setAttribute(Qt::WA_DeleteOnClose);
6745 connect(id, SIGNAL(setGeometry(int, int, int, int)), g,
6746 SLOT(updateImageMarker(int, int, int, int)));
6747 id->setWindowIcon(QPixmap(":/appicon"));
6748 id->setOrigin(im->origin());
6749 id->setSize(im->size());
6750 id->exec();
6751 }
6752 }
6753
showLayerDialog()6754 void ApplicationWindow::showLayerDialog()
6755 {
6756 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
6757 return;
6758
6759 MultiLayer *plot = (MultiLayer *)d_workspace.activeSubWindow();
6760 if (plot->isEmpty()) {
6761 QMessageBox::warning(this, tr("Warning"),
6762 tr("There are no plot layers available in this window."));
6763 return;
6764 }
6765
6766 LayerDialog *id = new LayerDialog(this);
6767 id->setAttribute(Qt::WA_DeleteOnClose);
6768 id->setMultiLayer(plot);
6769 id->exec();
6770 }
6771
showPlotGeometryDialog()6772 void ApplicationWindow::showPlotGeometryDialog()
6773 {
6774 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
6775 return;
6776
6777 MultiLayer *plot = (MultiLayer *)d_workspace.activeSubWindow();
6778 Graph *g = plot->activeGraph();
6779 if (g) {
6780 ImageDialog *id = new ImageDialog(this);
6781 id->setAttribute(Qt::WA_DeleteOnClose);
6782 connect(id, SIGNAL(setGeometry(int, int, int, int)), plot,
6783 SLOT(setGraphGeometry(int, int, int, int)));
6784 id->setWindowIcon(QPixmap(":/appicon"));
6785 id->setWindowTitle(tr("Layer Geometry"));
6786 id->setOrigin(g->pos());
6787 id->setSize(g->plotWidget()->size());
6788 id->exec();
6789 }
6790 }
6791
showTextDialog()6792 void ApplicationWindow::showTextDialog()
6793 {
6794 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
6795 return;
6796
6797 Graph *g = ((MultiLayer *)d_workspace.activeSubWindow())->activeGraph();
6798 if (g) {
6799 Legend *m = (Legend *)g->selectedMarkerPtr();
6800 if (!m)
6801 return;
6802
6803 TextDialog *td = new TextDialog(TextDialog::TextMarker, this, Qt::Widget);
6804 td->setAttribute(Qt::WA_DeleteOnClose);
6805 connect(td,
6806 SIGNAL(values(const QString &, int, int, const QFont &, const QColor &,
6807 const QColor &)),
6808 g,
6809 SLOT(updateTextMarker(const QString &, int, int, const QFont &, const QColor &,
6810 const QColor &)));
6811
6812 td->setWindowIcon(QPixmap(":/appicon"));
6813 td->setText(m->text());
6814 td->setFont(m->font());
6815 td->setTextColor(m->textColor());
6816 td->setBackgroundColor(m->backgroundColor());
6817 td->setBackgroundType(m->frameStyle());
6818 td->setAngle(m->angle());
6819 td->exec();
6820 }
6821 }
6822
showLineDialog()6823 void ApplicationWindow::showLineDialog()
6824 {
6825 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
6826 return;
6827
6828 Graph *g = ((MultiLayer *)d_workspace.activeSubWindow())->activeGraph();
6829 if (g) {
6830 ArrowMarker *lm = (ArrowMarker *)g->selectedMarkerPtr();
6831 if (!lm)
6832 return;
6833
6834 LineDialog *ld = new LineDialog(lm, this);
6835 ld->setAttribute(Qt::WA_DeleteOnClose);
6836 ld->exec();
6837 }
6838 }
6839
addColToTable()6840 void ApplicationWindow::addColToTable()
6841 {
6842 Table *m = (Table *)d_workspace.activeSubWindow();
6843 if (m)
6844 m->addCol();
6845 }
6846
clearSelection()6847 void ApplicationWindow::clearSelection()
6848 {
6849 if (lv.hasFocus()) {
6850 deleteSelectedItems();
6851 return;
6852 }
6853
6854 QWidget *m = (QWidget *)d_workspace.activeSubWindow();
6855 if (!m)
6856 return;
6857
6858 if (m->inherits("Table"))
6859 ((Table *)m)->clearSelection();
6860 else if (m->inherits("Matrix"))
6861 ((Matrix *)m)->clearSelection();
6862 else if (m->inherits("MultiLayer")) {
6863 Graph *g = ((MultiLayer *)m)->activeGraph();
6864 if (!g)
6865 return;
6866
6867 if (g->titleSelected())
6868 g->removeTitle();
6869 else if (g->markerSelected())
6870 g->removeMarker();
6871 } else if (m->inherits("Note"))
6872 ((Note *)m)->textWidget()->clear();
6873 emit modified();
6874 }
6875
copySelection()6876 void ApplicationWindow::copySelection()
6877 {
6878 if (results->hasFocus()) {
6879 results->copy();
6880 return;
6881 }
6882
6883 QWidget *m = (QWidget *)d_workspace.activeSubWindow();
6884 if (!m)
6885 return;
6886
6887 if (m->inherits("Table"))
6888 ((Table *)m)->copySelection();
6889 else if (m->inherits("Matrix"))
6890 ((Matrix *)m)->copySelection();
6891 else if (m->inherits("MultiLayer")) {
6892 MultiLayer *plot = (MultiLayer *)m;
6893 if (!plot || plot->layers() == 0)
6894 return;
6895
6896 Graph *g = (Graph *)plot->activeGraph();
6897 if (!g)
6898 return;
6899 if (g->markerSelected())
6900 copyMarker();
6901 else
6902 copyActiveLayer();
6903 } else if (m->inherits("Note"))
6904 ((Note *)m)->textWidget()->copy();
6905 }
6906
cutSelection()6907 void ApplicationWindow::cutSelection()
6908 {
6909 QWidget *m = (QWidget *)d_workspace.activeSubWindow();
6910 if (!m)
6911 return;
6912
6913 if (m->inherits("Table"))
6914 ((Table *)m)->cutSelection();
6915 else if (m->inherits("Matrix"))
6916 ((Matrix *)m)->cutSelection();
6917 else if (m->inherits("MultiLayer")) {
6918 MultiLayer *plot = (MultiLayer *)m;
6919 if (!plot || plot->layers() == 0)
6920 return;
6921
6922 Graph *g = (Graph *)plot->activeGraph();
6923 if (!g)
6924 return;
6925 if (g->markerSelected()) {
6926 copyMarker();
6927 g->removeMarker();
6928 } else {
6929 copyActiveLayer();
6930 plot->removeLayer();
6931 }
6932 } else if (m->inherits("Note"))
6933 ((Note *)m)->textWidget()->cut();
6934
6935 emit modified();
6936 }
6937
copyMarker()6938 void ApplicationWindow::copyMarker()
6939 {
6940 QWidget *m = (QWidget *)d_workspace.activeSubWindow();
6941 MultiLayer *plot = (MultiLayer *)m;
6942 Graph *g = (Graph *)plot->activeGraph();
6943 if (g && g->markerSelected()) {
6944 g->copyMarker();
6945 copiedMarkerType = g->copiedMarkerType();
6946 QRect rect = g->copiedMarkerRect();
6947 auxMrkStart = rect.topLeft();
6948 auxMrkEnd = rect.bottomRight();
6949
6950 if (copiedMarkerType == Graph::Text) {
6951 Legend *m = (Legend *)g->selectedMarkerPtr();
6952 auxMrkText = m->text();
6953 auxMrkColor = m->textColor();
6954 auxMrkFont = m->font();
6955 auxMrkBkg = m->frameStyle();
6956 auxMrkBkgColor = m->backgroundColor();
6957 } else if (copiedMarkerType == Graph::Arrow) {
6958 ArrowMarker *m = (ArrowMarker *)g->selectedMarkerPtr();
6959 auxMrkWidth = m->width();
6960 auxMrkColor = m->color();
6961 auxMrkStyle = m->style();
6962 startArrowOn = m->hasStartArrow();
6963 endArrowOn = m->hasEndArrow();
6964 arrowHeadLength = m->headLength();
6965 arrowHeadAngle = m->headAngle();
6966 fillArrowHead = m->filledArrowHead();
6967 } else if (copiedMarkerType == Graph::Image) {
6968 ImageMarker *im = (ImageMarker *)g->selectedMarkerPtr();
6969 if (im)
6970 auxMrkFileName = im->fileName();
6971 }
6972 }
6973 copiedLayer = false;
6974 }
6975
pasteSelection()6976 void ApplicationWindow::pasteSelection()
6977 {
6978 QWidget *m = (QWidget *)d_workspace.activeSubWindow();
6979 if (!m)
6980 return;
6981
6982 if (m->inherits("Table"))
6983 ((Table *)m)->pasteSelection();
6984 else if (m->inherits("Matrix"))
6985 ((Matrix *)m)->pasteSelection();
6986 else if (m->inherits("Note"))
6987 ((Note *)m)->textWidget()->paste();
6988 else if (m->inherits("MultiLayer")) {
6989 MultiLayer *plot = (MultiLayer *)m;
6990 if (!plot)
6991 return;
6992 if (copiedLayer) {
6993 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
6994
6995 Graph *g = plot->addLayer();
6996 setPreferences(g);
6997 g->copy(this, lastCopiedLayer);
6998 QPoint pos = plot->mapFromGlobal(QCursor::pos());
6999 plot->setGraphGeometry(pos.x(), pos.y() - 20, lastCopiedLayer->width(),
7000 lastCopiedLayer->height());
7001
7002 QApplication::restoreOverrideCursor();
7003 } else {
7004 if (plot->layers() == 0)
7005 return;
7006
7007 Graph *g = (Graph *)plot->activeGraph();
7008 if (!g)
7009 return;
7010
7011 g->setCopiedMarkerType(copiedMarkerType);
7012 g->setCopiedMarkerEnds(auxMrkStart, auxMrkEnd);
7013
7014 if (copiedMarkerType == Graph::Text)
7015 g->setCopiedTextOptions(auxMrkBkg, auxMrkText, auxMrkFont, auxMrkColor,
7016 auxMrkBkgColor);
7017 if (copiedMarkerType == Graph::Arrow)
7018 g->setCopiedArrowOptions(auxMrkWidth, auxMrkStyle, auxMrkColor, startArrowOn,
7019 endArrowOn, arrowHeadLength, arrowHeadAngle,
7020 fillArrowHead);
7021 if (copiedMarkerType == Graph::Image)
7022 g->setCopiedImageName(auxMrkFileName);
7023 g->pasteMarker();
7024 }
7025 }
7026 emit modified();
7027 }
7028
clone()7029 MyWidget *ApplicationWindow::clone()
7030 {
7031 MyWidget *w = (MyWidget *)d_workspace.activeSubWindow();
7032 if (!w) {
7033 QMessageBox::critical(this, tr("Duplicate window error"),
7034 tr("There are no windows available in this project!"));
7035 return 0;
7036 }
7037
7038 return clone(w);
7039 }
7040
clone(MyWidget * w)7041 MyWidget *ApplicationWindow::clone(MyWidget *w)
7042 {
7043 if (!w)
7044 return 0;
7045
7046 MyWidget *nw = 0;
7047 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
7048
7049 if (w->inherits("MultiLayer")) {
7050 nw = multilayerPlot(generateUniqueName(tr("Graph")));
7051 ((MultiLayer *)nw)->copy(this, (MultiLayer *)w);
7052 } else if (w->inherits("Table")) {
7053 Table *t = (Table *)w;
7054 QString caption = generateUniqueName(tr("Table"));
7055 nw = newTable(caption, t->numRows(), t->numCols());
7056 ((Table *)nw)->copy(t);
7057 } else if (w->inherits("Graph3D")) {
7058 Graph3D *g = (Graph3D *)w;
7059 if (!g->hasData()) {
7060 QApplication::restoreOverrideCursor();
7061 QMessageBox::warning(this, tr("Duplicate error"),
7062 tr("Empty 3D surface plots cannot be duplicated!"));
7063 return 0;
7064 }
7065
7066 QString caption = generateUniqueName(tr("Graph"));
7067 QString s = g->formula();
7068 if (g->userFunction())
7069 nw = newPlot3D(caption, s, g->xStart(), g->xStop(), g->yStart(), g->yStop(),
7070 g->zStart(), g->zStop());
7071 else if (s.endsWith("(Z)"))
7072 nw = dataPlotXYZ(caption, s, g->xStart(), g->xStop(), g->yStart(), g->yStop(),
7073 g->zStart(), g->zStop());
7074 else if (s.endsWith("(Y)")) // Ribbon plot
7075 nw = dataPlot3D(caption, s, g->xStart(), g->xStop(), g->yStart(), g->yStop(),
7076 g->zStart(), g->zStop());
7077 else
7078 nw = openMatrixPlot3D(caption, s, g->xStart(), g->xStop(), g->yStart(), g->yStop(),
7079 g->zStart(), g->zStop());
7080
7081 if (!nw)
7082 return 0;
7083
7084 ((Graph3D *)nw)->copy(g);
7085 customToolBars((MyWidget *)nw);
7086 } else if (w->inherits("Matrix")) {
7087 nw = newMatrix(((Matrix *)w)->numRows(), ((Matrix *)w)->numCols());
7088 ((Matrix *)nw)->copy((Matrix *)w);
7089 } else if (w->inherits("Note")) {
7090 nw = newNote();
7091 if (nw)
7092 ((Note *)nw)->setText(((Note *)w)->text());
7093 }
7094
7095 if (nw) {
7096 if (w->inherits("MultiLayer")) {
7097 if (w->status() == MyWidget::Maximized)
7098 nw->showMaximized();
7099 } else if (w->inherits("Graph3D")) {
7100 ((Graph3D *)nw)->setIgnoreFonts(true);
7101 if (w->status() == MyWidget::Maximized) {
7102 w->showNormal();
7103 w->resize(500, 400);
7104 nw->resize(w->size());
7105 nw->showMaximized();
7106 } else
7107 nw->resize(w->size());
7108 ((Graph3D *)nw)->setIgnoreFonts(false);
7109 } else {
7110 nw->resize(w->size());
7111 nw->showNormal();
7112 }
7113
7114 nw->setWindowLabel(w->windowLabel());
7115 nw->setCaptionPolicy(w->captionPolicy());
7116 setListViewLabel(nw->name(), w->windowLabel());
7117 }
7118 QApplication::restoreOverrideCursor();
7119 return nw;
7120 }
7121
undo()7122 void ApplicationWindow::undo()
7123 {
7124 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
7125 d_project->undoStack()->undo();
7126 QApplication::restoreOverrideCursor();
7127 }
7128
redo()7129 void ApplicationWindow::redo()
7130 {
7131 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
7132 d_project->undoStack()->redo();
7133 QApplication::restoreOverrideCursor();
7134 }
7135
hidden(MyWidget * window)7136 bool ApplicationWindow::hidden(MyWidget *window)
7137 {
7138 if (hiddenWindows.contains(window) || outWindows.contains(window))
7139 return true;
7140
7141 return false;
7142 }
7143
updateWindowStatus(MyWidget * w)7144 void ApplicationWindow::updateWindowStatus(MyWidget *w)
7145 {
7146 setListView(w->name(), w->aspect());
7147 if (w->status() == MyWidget::Maximized) {
7148 QList<MyWidget *> windows = current_folder->windowsList();
7149 foreach (MyWidget *oldMaxWindow, windows) {
7150 if (oldMaxWindow != w && oldMaxWindow->status() == MyWidget::Maximized)
7151 oldMaxWindow->setStatus(MyWidget::Normal);
7152 }
7153 }
7154 }
7155
hideActiveWindow()7156 void ApplicationWindow::hideActiveWindow()
7157 {
7158 MyWidget *w = (MyWidget *)d_workspace.activeSubWindow();
7159 if (!w)
7160 return;
7161
7162 hideWindow(w);
7163 }
7164
hideWindow(MyWidget * w)7165 void ApplicationWindow::hideWindow(MyWidget *w)
7166 {
7167 hiddenWindows.append(w);
7168 w->setHidden();
7169 emit modified();
7170 }
7171
resizeActiveWindow()7172 void ApplicationWindow::resizeActiveWindow()
7173 {
7174 MyWidget *w = qobject_cast<MyWidget *>(d_workspace.activeSubWindow());
7175 if (!w)
7176 return;
7177
7178 ImageDialog *id = new ImageDialog(this);
7179 id->setAttribute(Qt::WA_DeleteOnClose);
7180 connect(id, SIGNAL(setGeometry(int, int, int, int)), this,
7181 SLOT(setWindowGeometry(int, int, int, int)));
7182
7183 id->setWindowTitle(tr("Window Geometry"));
7184 id->setOrigin(w->pos());
7185 id->setSize(w->size());
7186 id->exec();
7187 }
7188
resizeWindow()7189 void ApplicationWindow::resizeWindow()
7190 {
7191 MyWidget *w = qobject_cast<MyWidget *>(d_workspace.activeSubWindow());
7192 if (!w)
7193 return;
7194
7195 d_workspace.setActiveSubWindow(w);
7196
7197 ImageDialog *id = new ImageDialog(this);
7198 id->setAttribute(Qt::WA_DeleteOnClose);
7199 connect(id, SIGNAL(setGeometry(int, int, int, int)), this,
7200 SLOT(setWindowGeometry(int, int, int, int)));
7201
7202 id->setWindowTitle(tr("Window Geometry"));
7203 id->setOrigin(w->pos());
7204 id->setSize(w->size());
7205 id->exec();
7206 }
7207
setWindowGeometry(int x,int y,int w,int h)7208 void ApplicationWindow::setWindowGeometry(int x, int y, int w, int h)
7209 {
7210 d_workspace.activeSubWindow()->setGeometry(x, y, w, h);
7211 }
7212
activateSubWindow()7213 void ApplicationWindow::activateSubWindow()
7214 {
7215 setWindowState(Qt::WindowActive);
7216 raise();
7217 show();
7218 WindowListItem *it = (WindowListItem *)lv.currentItem();
7219 activateSubWindow(it->window());
7220 }
7221
activateSubWindow(MyWidget * w)7222 void ApplicationWindow::activateSubWindow(MyWidget *w)
7223 {
7224 if (!w)
7225 return;
7226
7227 w->setNormal();
7228 d_workspace.setActiveSubWindow(w);
7229
7230 updateWindowLists(w);
7231 emit modified();
7232 }
7233
maximizeWindow()7234 void ApplicationWindow::maximizeWindow()
7235 {
7236 MyWidget *w = qobject_cast<MyWidget *>(d_workspace.activeSubWindow());
7237 if (!w)
7238 return;
7239
7240 updateWindowLists(w);
7241 w->setMaximized();
7242 emit modified();
7243 }
7244
minimizeWindow()7245 void ApplicationWindow::minimizeWindow()
7246 {
7247 MyWidget *w = qobject_cast<MyWidget *>(d_workspace.activeSubWindow());
7248 if (!w)
7249 return;
7250
7251 updateWindowLists(w);
7252 w->setMinimized();
7253 emit modified();
7254 }
7255
updateWindowLists(MyWidget * w)7256 void ApplicationWindow::updateWindowLists(MyWidget *w)
7257 {
7258 if (!w)
7259 return;
7260
7261 if (hiddenWindows.contains(w))
7262 hiddenWindows.takeAt(hiddenWindows.indexOf(w));
7263 else if (outWindows.contains(w)) {
7264 outWindows.takeAt(outWindows.indexOf(w));
7265 d_workspace.addSubWindow(w);
7266 w->setAttribute(Qt::WA_DeleteOnClose);
7267 }
7268 }
7269
closeActiveWindow()7270 void ApplicationWindow::closeActiveWindow()
7271 {
7272 QWidget *w = (QWidget *)d_workspace.activeSubWindow();
7273 if (w)
7274 w->close();
7275 }
7276
removeWindowFromLists(MyWidget * w)7277 void ApplicationWindow::removeWindowFromLists(MyWidget *w)
7278 {
7279 if (!w)
7280 return;
7281
7282 QString caption = w->name();
7283 if (w->inherits("Table")) {
7284 Table *m = (Table *)w;
7285 for (int i = 0; i < m->numCols(); i++) {
7286 QString name = m->colName(i);
7287 removeCurves(name);
7288 }
7289 if (w == lastModified) {
7290 actionUndo->setEnabled(false);
7291 actionRedo->setEnabled(false);
7292 }
7293 } else if (w->inherits("MultiLayer")) {
7294 MultiLayer *ml = (MultiLayer *)w;
7295 Graph *g = ml->activeGraph();
7296 if (g)
7297 btnPointer->setChecked(true);
7298 } else if (w->inherits("Matrix"))
7299 remove3DMatrixPlots((Matrix *)w);
7300
7301 if (hiddenWindows.contains(w))
7302 hiddenWindows.takeAt(hiddenWindows.indexOf(w));
7303 else if (outWindows.contains(w))
7304 outWindows.takeAt(outWindows.indexOf(w));
7305 }
7306
closeWindow(MyWidget * window)7307 void ApplicationWindow::closeWindow(MyWidget *window)
7308 {
7309 if (!window)
7310 return;
7311
7312 removeWindowFromLists(window);
7313 window->folder()->removeWindow(window);
7314
7315 // update list view in project explorer
7316 QTreeWidgetItem *it =
7317 lv.findItems(window->name(), Qt::MatchExactly | Qt::MatchCaseSensitive).at(0);
7318 if (it)
7319 lv.takeTopLevelItem(lv.indexOfTopLevelItem(it));
7320
7321 if (window->inherits("Matrix"))
7322 window->setParent(0);
7323 else if (window->inherits("Table"))
7324 window->setParent(0);
7325 else
7326 window->deleteLater();
7327 emit modified();
7328 }
7329
about()7330 void ApplicationWindow::about()
7331 {
7332 SciDAVis::about();
7333 }
7334
windowsMenuAboutToShow()7335 void ApplicationWindow::windowsMenuAboutToShow()
7336 {
7337 QList<QMdiSubWindow *> windows = d_workspace.subWindowList();
7338 int n = int(windows.count());
7339 if (!n)
7340 return;
7341
7342 windowsMenu->clear();
7343 windowsMenu->addAction(tr("&Cascade"), this, SLOT(cascade()));
7344 windowsMenu->addAction(tr("&Tile"), &d_workspace, SLOT(tileSubWindows()));
7345 windowsMenu->addSeparator();
7346 windowsMenu->addAction(actionNextWindow);
7347 windowsMenu->addAction(actionPrevWindow);
7348 windowsMenu->addSeparator();
7349 windowsMenu->addAction(actionRename);
7350 windowsMenu->addAction(actionCopyWindow);
7351 windowsMenu->addSeparator();
7352 windowsMenu->addAction(actionResizeActiveWindow);
7353 windowsMenu->addAction(tr("&Hide Window"), this, SLOT(hideActiveWindow()));
7354 windowsMenu->addAction(QPixmap(":/close.xpm"), tr("Close &Window"), this,
7355 SLOT(closeActiveWindow()), Qt::CTRL + Qt::Key_W);
7356
7357 if (n > 0 && n < 10) {
7358 windowsMenu->addSeparator();
7359 for (int i = 0; i < n; ++i) {
7360 MyWidget *widget = qobject_cast<MyWidget *>(windows.at(i));
7361 if (!widget)
7362 continue;
7363 QAction *actId =
7364 windowsMenu->addAction(widget->name(), this, SLOT(windowsMenuActivated(bool)));
7365 actId->setData(i);
7366 actId->setCheckable(true);
7367 actId->setChecked(d_workspace.activeSubWindow() == windows.at(i));
7368 }
7369 } else if (n >= 10) {
7370 windowsMenu->addSeparator();
7371 for (int i = 0; i < 9; ++i) {
7372 MyWidget *widget = qobject_cast<MyWidget *>(windows.at(i));
7373 if (!widget)
7374 continue;
7375 QAction *actId =
7376 windowsMenu->addAction(widget->name(), this, SLOT(windowsMenuActivated(bool)));
7377 actId->setData(i);
7378 actId->setCheckable(true);
7379 actId->setChecked(d_workspace.activeSubWindow() == windows.at(i));
7380 }
7381 windowsMenu->addSeparator();
7382 windowsMenu->addAction(tr("More windows..."), this, SLOT(showMoreWindows()));
7383 }
7384 }
7385
showMarkerPopupMenuImpl()7386 QMenu *ApplicationWindow::showMarkerPopupMenuImpl()
7387 {
7388 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
7389 return nullptr;
7390
7391 Graph *g = ((MultiLayer *)d_workspace.activeSubWindow())->activeGraph();
7392 auto markerMenu = new QMenu(this);
7393
7394 if (g->imageMarkerSelected()) {
7395 markerMenu->addAction(QPixmap(":/pixelProfile.xpm"), tr("&View Pixel Line profile"), this,
7396 SLOT(pixelLineProfile()));
7397 markerMenu->addAction(tr("&Intensity Matrix"), this, SLOT(intensityTable()));
7398 markerMenu->addSeparator();
7399 }
7400
7401 markerMenu->addAction(IconLoader::load("edit-cut"), tr("&Cut"), this, SLOT(cutSelection()));
7402 markerMenu->addAction(IconLoader::load("edit-copy"), tr("&Copy"), this, SLOT(copySelection()));
7403 markerMenu->addAction(QPixmap(":/erase.xpm"), tr("&Delete"), this, SLOT(clearSelection()));
7404 markerMenu->addSeparator();
7405 if (g->arrowMarkerSelected())
7406 markerMenu->addAction(tr("&Properties..."), this, SLOT(showLineDialog()));
7407 else if (g->imageMarkerSelected())
7408 markerMenu->addAction(tr("&Properties..."), this, SLOT(showImageDialog()));
7409 else
7410 markerMenu->addAction(tr("&Properties..."), this, SLOT(showTextDialog()));
7411
7412 return markerMenu;
7413 }
7414
showMoreWindows()7415 void ApplicationWindow::showMoreWindows()
7416 {
7417 if (explorerWindow.isVisible())
7418 QMessageBox::information(this, "SciDAVis",
7419 tr("Please use the project explorer to select a window!"));
7420 else
7421 explorerWindow.show();
7422 }
7423
windowsMenuActivated(bool checked)7424 void ApplicationWindow::windowsMenuActivated(bool checked)
7425 {
7426 Q_UNUSED(checked)
7427
7428 QAction *act = qobject_cast<QAction *>(sender());
7429 if (!act)
7430 return;
7431 int id = act->data().toInt();
7432
7433 QList<QMdiSubWindow *> windows = d_workspace.subWindowList();
7434 MyWidget *w = qobject_cast<MyWidget *>(windows.at(id));
7435 if (w) {
7436 w->showNormal();
7437 w->setFocus();
7438 if (hidden(w)) {
7439 hiddenWindows.takeAt(hiddenWindows.indexOf(w));
7440 setListView(w->name(), tr("Normal"));
7441 }
7442 }
7443 }
7444
newProject()7445 void ApplicationWindow::newProject()
7446 {
7447 saveSettings(); // the recent projects must be saved
7448
7449 ApplicationWindow *ed = new ApplicationWindow();
7450 ed->applyUserSettings();
7451 ed->newTable();
7452
7453 if (this->isMaximized())
7454 ed->showMaximized();
7455 else
7456 ed->show();
7457
7458 ed->savedProject();
7459
7460 this->close();
7461 }
7462
savedProject()7463 void ApplicationWindow::savedProject()
7464 {
7465 actionSaveProject->setEnabled(false);
7466 saved = true;
7467 d_project->undoStack()->clear();
7468 }
7469
modifiedProject()7470 void ApplicationWindow::modifiedProject()
7471 {
7472 actionSaveProject->setEnabled(true);
7473 saved = false;
7474 }
7475
modifiedProject(MyWidget * w)7476 void ApplicationWindow::modifiedProject(MyWidget *w)
7477 {
7478 modifiedProject();
7479
7480 actionUndo->setEnabled(true);
7481 lastModified = w;
7482 }
7483
timerEvent(QTimerEvent * e)7484 void ApplicationWindow::timerEvent(QTimerEvent *e)
7485 {
7486 if (e->timerId() == savingTimerId)
7487 saveProject();
7488 else
7489 QWidget::timerEvent(e);
7490 }
7491
dropEvent(QDropEvent * e)7492 void ApplicationWindow::dropEvent(QDropEvent *e)
7493 {
7494 if (e->mimeData()->hasUrls()) {
7495 QStringList asciiFiles;
7496 QList<QUrl> urls = e->mimeData()->urls();
7497
7498 foreach (QUrl url, urls) {
7499 QString fileName = url.toLocalFile();
7500 QFileInfo fileInfo(fileName);
7501 QString ext = fileInfo.completeSuffix().toLower();
7502
7503 if (ext == "sciprj" || ext == "sciprj~" || ext == "sciprj.gz" || ext == "sciprj.gz~"
7504 || ext == "opj" || ext == "qti" || ext == "qti.gz" || ext == "ogm" || ext == "ogw"
7505 || ext == "ogg" || ext == "org") {
7506 open(fileName);
7507 } else if (ext == "csv" || ext == "dat" || ext == "txt" || ext == "tsv") {
7508 asciiFiles << fileName;
7509 } else if (ext == "bmp" || ext == "bw" || ext == "eps" || ext == "epsf" || ext == "epsi"
7510 || ext == "exr" || ext == "kra" || ext == "ora" || ext == "pcx"
7511 || ext == "psd" || ext == "ras" || ext == "rgb" || ext == "rgba"
7512 || ext == "sgi" || ext == "tga" || ext == "xcf" || ext == "dds"
7513 || ext == "gif" || ext == "ico" || ext == "jp2" || ext == "jpeg"
7514 || ext == "jpg" || ext == "mng" || ext == "pbm" || ext == "pgm"
7515 || ext == "pic" || ext == "png" || ext == "ppm" || ext == "svg"
7516 || ext == "svgz" || ext == "tif" || ext == "tiff" || ext == "webp"
7517 || ext == "xbm" || ext == "xpm" || ext == "xv") {
7518 loadImage(fileName);
7519 }
7520 }
7521 if (!asciiFiles.isEmpty()) {
7522 importASCII(asciiFiles, ImportASCIIDialog::NewTables, columnSeparator, ignoredLines,
7523 renameColumns, strip_spaces, simplify_spaces, d_convert_to_numeric,
7524 d_ASCII_import_locale);
7525 }
7526 }
7527 }
7528
dragEnterEvent(QDragEnterEvent * e)7529 void ApplicationWindow::dragEnterEvent(QDragEnterEvent *e)
7530 {
7531 if (e->source()) {
7532 e->ignore();
7533 return;
7534 }
7535 (e->mimeData()->hasUrls()) ? e->acceptProposedAction() : e->ignore();
7536 }
7537
closeEvent(QCloseEvent * ce)7538 void ApplicationWindow::closeEvent(QCloseEvent *ce)
7539 {
7540 if (!saved) {
7541 QString s = tr("Save changes to project: <p><b> %1 </b> ?").arg(projectname);
7542 switch (QMessageBox::information(this, tr("SciDAVis"), s, tr("Yes"), tr("No"), tr("Cancel"),
7543 0, 2)) {
7544 case 0:
7545 if (!saveProject()) {
7546 ce->ignore();
7547 break;
7548 }
7549 saveSettings(); // the recent projects must be saved
7550 ce->accept();
7551 break;
7552
7553 case 1:
7554 default:
7555 saveSettings(); // the recent projects must be saved
7556 ce->accept();
7557 break;
7558
7559 case 2:
7560 ce->ignore();
7561 break;
7562 }
7563 } else {
7564 saveSettings(); // the recent projects must be saved
7565 ce->accept();
7566 }
7567 }
7568
customEvent(QEvent * e)7569 void ApplicationWindow::customEvent(QEvent *e)
7570 {
7571 if (e->type() == SCRIPTING_CHANGE_EVENT) {
7572 scriptingChangeEvent((ScriptingChangeEvent *)e);
7573 // If the event is triggered by setScriptingLang(), the connections are already made
7574 // (for messages emitted during initialization). However, it's good programming practice not
7575 // to assume a particular call path for an event; which means that we don't know for sure
7576 // at this point whether scriptEnv is connected or not.
7577 scriptEnv->disconnect(this);
7578 connect(scriptEnv, SIGNAL(error(const QString &, const QString &, int)), this,
7579 SLOT(scriptError(const QString &, const QString &, int)));
7580 connect(scriptEnv, SIGNAL(print(const QString &)), this,
7581 SLOT(scriptPrint(const QString &)));
7582 }
7583 }
7584
deleteSelectedItems()7585 void ApplicationWindow::deleteSelectedItems()
7586 {
7587 if (folders.hasFocus()
7588 && folders.currentItem()
7589 != folders.topLevelItem(
7590 0)) { // we never allow the user to delete the project folder item
7591 deleteFolder();
7592 return;
7593 }
7594
7595 QList<QTreeWidgetItem *> lst;
7596 for (QTreeWidgetItemIterator it(&lv); *it; it++) {
7597 if ((*it)->isSelected())
7598 lst.append((*it));
7599 }
7600
7601 folders.blockSignals(true);
7602 for (auto item : lst) {
7603 if (item->type() == FolderListItem::FolderType) {
7604 Folder *f = ((FolderListItem *)item)->folder();
7605 if (deleteFolder(f))
7606 delete item;
7607 } else
7608 ((WindowListItem *)item)->window()->close();
7609 }
7610 folders.blockSignals(false);
7611 }
7612
showListViewSelectionMenuImpl()7613 QMenu *ApplicationWindow::showListViewSelectionMenuImpl()
7614 {
7615 QMenu *cm = new QMenu(this);
7616 cm->addAction(tr("&Delete Selection"), this, SLOT(deleteSelectedItems()), Qt::Key_F8);
7617 return cm;
7618 }
7619
showListViewPopupMenuImpl()7620 QMenu *ApplicationWindow::showListViewPopupMenuImpl()
7621 {
7622 QMenu *cm = new QMenu(this);
7623 QMenu *window = cm->addMenu(tr("New &Window"));
7624
7625 window->addAction(actionNewTable);
7626 window->addAction(actionNewMatrix);
7627 window->addAction(actionNewNote);
7628 window->addAction(actionNewGraph);
7629 window->addAction(actionNewFunctionPlot);
7630 window->addAction(actionNewSurfacePlot);
7631 cm->addAction(QPixmap(":/newfolder.xpm"), tr("New F&older"), this, SLOT(addFolder()),
7632 Qt::Key_F7);
7633 cm->addSeparator();
7634 cm->addAction(tr("Auto &Column Width"), &lv, SLOT(adjustColumns()));
7635 return cm;
7636 }
7637
showWindowPopupMenu(const QPoint & p)7638 void ApplicationWindow::showWindowPopupMenu(const QPoint &p)
7639 {
7640 if (auto m = showWindowPopupMenuImpl(lv.itemAt(p)))
7641 m->exec(lv.mapToGlobal(p) + QPoint(0, lv.header()->height()));
7642 }
7643
showWindowPopupMenuImpl(QTreeWidgetItem * it)7644 QMenu *ApplicationWindow::showWindowPopupMenuImpl(QTreeWidgetItem *it)
7645 {
7646 if (folders.isRenaming())
7647 return nullptr;
7648
7649 if (!it)
7650 return showListViewPopupMenuImpl();
7651
7652 int selected = 0;
7653 QTreeWidgetItemIterator itv(&lv);
7654 while (*itv) {
7655 if ((*itv)->isSelected())
7656 selected++;
7657
7658 if (selected > 1)
7659 return showListViewSelectionMenuImpl();
7660 itv++;
7661 }
7662
7663 if (auto fl = dynamic_cast<FolderListItem *>(it)) {
7664 current_folder = fl->folder();
7665 return showFolderPopupMenuImpl(fl, false);
7666 }
7667
7668 if (auto wli = dynamic_cast<WindowListItem *>(it))
7669 if (auto w = wli->window())
7670 return showWindowMenuImpl(w);
7671 return nullptr;
7672 }
7673
showTable(const QString & curve)7674 void ApplicationWindow::showTable(const QString &curve)
7675 {
7676 Table *w = table(curve);
7677 if (!w)
7678 return;
7679
7680 updateWindowLists(w);
7681 int colIndex = w->colIndex(curve);
7682 w->deselectAll();
7683 w->setCellsSelected(0, colIndex, w->d_future_table->rowCount() - 1, colIndex);
7684 w->showMaximized();
7685 QTreeWidgetItem *it = lv.findItems(w->name(), Qt::MatchExactly | Qt::MatchCaseSensitive).at(0);
7686 if (it)
7687 it->setText(2, tr("Maximized"));
7688 emit modified();
7689 }
7690
depending3DPlots(Matrix * m)7691 QStringList ApplicationWindow::depending3DPlots(Matrix *m)
7692 {
7693 QList<MyWidget *> windows = windowsList();
7694 QStringList plots;
7695 for (int i = 0; i < (int)windows.count(); i++) {
7696 MyWidget *w = windows.at(i);
7697 if (w && w->inherits("Graph3D") && ((Graph3D *)w)->matrix() == m)
7698 plots << w->name();
7699 }
7700 return plots;
7701 }
7702
7703 // TODO: Implement this in an elegant way
dependingPlots(const QString & name)7704 QStringList ApplicationWindow::dependingPlots(const QString &name)
7705 {
7706 QList<MyWidget *> windows = windowsList();
7707 QStringList onPlot, plots;
7708
7709 for (int i = 0; i < windows.count(); i++) {
7710 MyWidget *w = windows.at(i);
7711 if (!w)
7712 continue;
7713 if (w->inherits("MultiLayer")) {
7714 QWidgetList lst = ((MultiLayer *)w)->graphPtrs();
7715 foreach (QWidget *widget, lst) {
7716 Graph *g = (Graph *)widget;
7717 onPlot = g->curvesList();
7718 onPlot = onPlot.filter(QRegExp("^" + name + "_.*"));
7719 if (onPlot.count() > 0 && !plots.contains(w->name()))
7720 plots << w->name();
7721 }
7722 } else if (w->inherits("Graph3D")) {
7723 if ((((Graph3D *)w)->formula()).contains(name, Qt::CaseSensitive)
7724 && !plots.contains(w->name()))
7725 plots << w->name();
7726 }
7727 }
7728 return plots;
7729 }
7730
multilayerDependencies(MyWidget * w)7731 QStringList ApplicationWindow::multilayerDependencies(MyWidget *w)
7732 {
7733 QStringList tables;
7734 MultiLayer *g = (MultiLayer *)w;
7735 QWidgetList graphsList = g->graphPtrs();
7736 for (int i = 0; i < graphsList.count(); i++) {
7737 Graph *ag = (Graph *)graphsList.at(i);
7738 QStringList onPlot = ag->curvesList();
7739 for (int j = 0; j < onPlot.count(); j++) {
7740 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
7741 QStringList tl = onPlot[j].split("_", Qt::SkipEmptyParts);
7742 #else
7743 QStringList tl = onPlot[j].split("_", QString::SkipEmptyParts);
7744 #endif
7745 if (!tables.contains(tl[0]))
7746 tables << tl[0];
7747 }
7748 }
7749 return tables;
7750 }
7751
showGraphContextMenu()7752 void ApplicationWindow::showGraphContextMenu()
7753 {
7754 QWidget *w = (QWidget *)d_workspace.activeSubWindow();
7755 if (!w)
7756 return;
7757
7758 if (w->inherits("MultiLayer")) {
7759 MultiLayer *plot = (MultiLayer *)w;
7760 QMenu cm(this);
7761 QMenu *calcul = cm.addMenu(tr("Anal&yze"));
7762
7763 Graph *ag = (Graph *)plot->activeGraph();
7764 if (ag->isPiePlot())
7765 cm.addAction(tr("Re&move Pie Curve"), ag, SLOT(removePie()));
7766 else {
7767 if (ag->visibleCurves() != ag->curves()) {
7768 cm.addAction(actionShowAllCurves);
7769 cm.addSeparator();
7770 }
7771 cm.addAction(actionShowCurvesDialog);
7772 cm.addAction(actionAddFunctionCurve);
7773
7774 QMenu *translate = calcul->addMenu(tr("&Translate"));
7775 translate->addAction(actionTranslateVert);
7776 translate->addAction(actionTranslateHor);
7777 calcul->addSeparator();
7778
7779 calcul->addAction(actionDifferentiate);
7780 calcul->addAction(actionShowIntDialog);
7781 calcul->addSeparator();
7782
7783 QMenu *smooth = calcul->addMenu(tr("&Smooth"));
7784 smooth->addAction(actionSmoothSavGol);
7785 smooth->addAction(actionSmoothFFT);
7786 smooth->addAction(actionSmoothAverage);
7787
7788 QMenu *filter = calcul->addMenu(tr("&FFT Filter"));
7789 filter->addAction(actionLowPassFilter);
7790 filter->addAction(actionHighPassFilter);
7791 filter->addAction(actionBandPassFilter);
7792 filter->addAction(actionBandBlockFilter);
7793
7794 calcul->addSeparator();
7795 calcul->addAction(actionInterpolate);
7796 calcul->addAction(actionFFT);
7797 calcul->addSeparator();
7798 calcul->addAction(actionFitLinear);
7799 calcul->addAction(actionShowFitPolynomDialog);
7800 calcul->addSeparator();
7801
7802 QMenu *decay = calcul->addMenu(tr("Fit E&xponential Decay"));
7803 decay->addAction(actionShowExpDecayDialog);
7804 decay->addAction(actionShowTwoExpDecayDialog);
7805 decay->addAction(actionShowExpDecay3Dialog);
7806
7807 calcul->addAction(actionFitExpGrowth);
7808 calcul->addAction(actionFitSigmoidal);
7809 calcul->addAction(actionFitGauss);
7810 calcul->addAction(actionFitLorentz);
7811
7812 QMenu *multiPeakMenu = calcul->addMenu(tr("Fit &Multi-Peak"));
7813 multiPeakMenu->addAction(actionMultiPeakGauss);
7814 multiPeakMenu->addAction(actionMultiPeakLorentz);
7815
7816 calcul->addSeparator();
7817 calcul->addAction(actionShowFitDialog);
7818 }
7819
7820 if (copiedLayer) {
7821 cm.addSeparator();
7822 cm.addAction(IconLoader::load("edit-paste"), tr("&Paste Layer"), this,
7823 SLOT(pasteSelection()));
7824 } else if (copiedMarkerType >= 0) {
7825 cm.addSeparator();
7826 if (copiedMarkerType == Graph::Text)
7827 cm.addAction(IconLoader::load("edit-paste"), tr("&Paste Text"), plot,
7828 SIGNAL(pasteMarker()));
7829 else if (copiedMarkerType == Graph::Arrow)
7830 cm.addAction(IconLoader::load("edit-paste"), tr("&Paste Line/Arrow"), plot,
7831 SIGNAL(pasteMarker()));
7832 else if (copiedMarkerType == Graph::Image)
7833 cm.addAction(IconLoader::load("edit-paste"), tr("&Paste Image"), plot,
7834 SIGNAL(pasteMarker()));
7835 }
7836 cm.addSeparator();
7837 QMenu *copy = cm.addMenu(tr("&Copy"));
7838 copy->setIcon(IconLoader::load("edit-copy"));
7839 copy->addAction(tr("&Layer"), this, SLOT(copyActiveLayer()));
7840 copy->addAction(tr("&Window"), plot, SLOT(copyAllLayers()));
7841
7842 QMenu *exports = cm.addMenu(tr("E&xport"));
7843 exports->addAction(tr("&Layer"), this, SLOT(exportLayer()));
7844 exports->addAction(tr("&Window"), this, SLOT(exportGraph()));
7845
7846 QMenu *prints = cm.addMenu(tr("&Print"));
7847 prints->setIcon(QPixmap(":/fileprint.xpm"));
7848 prints->addAction(tr("&Layer"), plot, SLOT(printActiveLayer()));
7849 prints->addAction(tr("&Window"), plot, SLOT(print()));
7850
7851 cm.addSeparator();
7852 cm.addAction(QPixmap(":/resize.xpm"), tr("&Geometry..."), plot,
7853 SIGNAL(showGeometryDialog()));
7854 cm.addAction(tr("P&roperties..."), this, SLOT(showGeneralPlotDialog()));
7855 cm.addSeparator();
7856 cm.addAction(QPixmap(":/close.xpm"), tr("&Delete Layer"), plot, SLOT(confirmRemoveLayer()));
7857 cm.exec(QCursor::pos());
7858 }
7859 }
7860
showLayerButtonContextMenu()7861 void ApplicationWindow::showLayerButtonContextMenu()
7862 {
7863 QWidget *w = (QWidget *)d_workspace.activeSubWindow();
7864 if (!w)
7865 return;
7866
7867 if (w->inherits("MultiLayer")) {
7868 MultiLayer *plot = (MultiLayer *)w;
7869 QMenu cm(this);
7870
7871 Graph *ag = (Graph *)plot->activeGraph();
7872
7873 cm.addAction(actionAddLayer);
7874 cm.addAction(actionDeleteLayer);
7875 cm.addSeparator();
7876
7877 if (ag->isPiePlot())
7878 cm.addAction(tr("Re&move Pie Curve"), ag, SLOT(removePie()));
7879 else {
7880 if (ag->visibleCurves() != ag->curves()) {
7881 cm.addAction(actionShowAllCurves);
7882 cm.addSeparator();
7883 }
7884 cm.addAction(actionShowCurvesDialog);
7885 cm.addAction(actionAddFunctionCurve);
7886
7887 QMenu *calcul = cm.addMenu(tr("Anal&yze"));
7888
7889 QMenu *translate = calcul->addMenu(tr("&Translate"));
7890 translate->addAction(actionTranslateVert);
7891 translate->addAction(actionTranslateHor);
7892 calcul->addSeparator();
7893
7894 calcul->addAction(actionDifferentiate);
7895 calcul->addAction(actionShowIntDialog);
7896 calcul->addSeparator();
7897
7898 QMenu *smooth = calcul->addMenu(tr("&Smooth"));
7899 smooth->addAction(actionSmoothSavGol);
7900 smooth->addAction(actionSmoothFFT);
7901 smooth->addAction(actionSmoothAverage);
7902
7903 QMenu *filter = calcul->addMenu(tr("&FFT Filter"));
7904 filter->addAction(actionLowPassFilter);
7905 filter->addAction(actionHighPassFilter);
7906 filter->addAction(actionBandPassFilter);
7907 filter->addAction(actionBandBlockFilter);
7908
7909 calcul->addSeparator();
7910 calcul->addAction(actionInterpolate);
7911 calcul->addAction(actionFFT);
7912 calcul->addSeparator();
7913 calcul->addAction(actionFitLinear);
7914 calcul->addAction(actionShowFitPolynomDialog);
7915 calcul->addSeparator();
7916
7917 QMenu *decay = calcul->addMenu(tr("Fit E&xponential Decay"));
7918 decay->addAction(actionShowExpDecayDialog);
7919 decay->addAction(actionShowTwoExpDecayDialog);
7920 decay->addAction(actionShowExpDecay3Dialog);
7921
7922 calcul->addAction(actionFitExpGrowth);
7923 calcul->addAction(actionFitSigmoidal);
7924 calcul->addAction(actionFitGauss);
7925 calcul->addAction(actionFitLorentz);
7926
7927 QMenu *multiPeakMenu = calcul->addMenu(tr("Fit &Multi-Peak"));
7928 multiPeakMenu->addAction(actionMultiPeakGauss);
7929 multiPeakMenu->addAction(actionMultiPeakLorentz);
7930
7931 calcul->addSeparator();
7932 calcul->addAction(actionShowFitDialog);
7933 }
7934
7935 if (copiedLayer) {
7936 cm.addSeparator();
7937 cm.addAction(IconLoader::load("edit-paste"), tr("&Paste Layer"), this,
7938 SLOT(pasteSelection()));
7939 } else if (copiedMarkerType >= 0) {
7940 cm.addSeparator();
7941 if (copiedMarkerType == Graph::Text)
7942 cm.addAction(IconLoader::load("edit-paste"), tr("&Paste Text"), plot,
7943 SIGNAL(pasteMarker()));
7944 else if (copiedMarkerType == Graph::Arrow)
7945 cm.addAction(IconLoader::load("edit-paste"), tr("&Paste Line/Arrow"), plot,
7946 SIGNAL(pasteMarker()));
7947 else if (copiedMarkerType == Graph::Image)
7948 cm.addAction(IconLoader::load("edit-paste"), tr("&Paste Image"), plot,
7949 SIGNAL(pasteMarker()));
7950 }
7951 cm.addSeparator();
7952
7953 QMenu *copy = cm.addMenu(tr("&Copy"));
7954 copy->setIcon(IconLoader::load("edit-copy"));
7955 copy->addAction(tr("&Layer"), this, SLOT(copyActiveLayer()));
7956 copy->addAction(tr("&Window"), plot, SLOT(copyAllLayers()));
7957
7958 QMenu *exports = cm.addMenu(tr("E&xport"));
7959 exports->addAction(tr("&Layer"), this, SLOT(exportLayer()));
7960 exports->addAction(tr("&Window"), this, SLOT(exportGraph()));
7961
7962 QMenu *prints = cm.addMenu(tr("&Print"));
7963 prints->setIcon(QPixmap(":/fileprint.xpm"));
7964 prints->addAction(tr("&Layer"), plot, SLOT(printActiveLayer()));
7965 prints->addAction(tr("&Window"), plot, SLOT(print()));
7966
7967 cm.addSeparator();
7968 cm.addAction(QPixmap(":/resize.xpm"), tr("&Geometry..."), plot,
7969 SIGNAL(showGeometryDialog()));
7970 cm.addAction(tr("P&roperties..."), this, SLOT(showGeneralPlotDialog()));
7971 cm.addSeparator();
7972 cm.addAction(QPixmap(":/close.xpm"), tr("&Delete Layer"), plot, SLOT(confirmRemoveLayer()));
7973 cm.exec(QCursor::pos());
7974 }
7975 }
7976
showWindowContextMenu()7977 void ApplicationWindow::showWindowContextMenu()
7978 {
7979 QWidget *w = (QWidget *)d_workspace.activeSubWindow();
7980 if (!w)
7981 return;
7982
7983 QMenu cm(this);
7984 if (w->inherits("MultiLayer")) {
7985 MultiLayer *g = (MultiLayer *)w;
7986 if (copiedLayer) {
7987 cm.addAction(IconLoader::load("edit-paste"), tr("&Paste Layer"), this,
7988 SLOT(pasteSelection()));
7989 cm.addSeparator();
7990 }
7991
7992 cm.addAction(actionAddLayer);
7993 if (g->layers() != 0) {
7994 cm.addAction(actionDeleteLayer);
7995 cm.addSeparator();
7996 cm.addAction(actionShowPlotGeometryDialog);
7997 cm.addAction(actionShowLayerDialog);
7998 cm.addSeparator();
7999 } else
8000 cm.addSeparator();
8001 cm.addAction(actionRename);
8002 cm.addAction(actionCopyWindow);
8003 cm.addSeparator();
8004 cm.addAction(IconLoader::load("edit-copy"), tr("&Copy Page"), g, SLOT(copyAllLayers()));
8005 cm.addAction(tr("E&xport Page"), this, SLOT(exportGraph()));
8006 cm.addAction(actionPrint);
8007 cm.addSeparator();
8008 cm.addAction(actionCloseWindow);
8009 } else if (w->inherits("Graph3D")) {
8010 Graph3D *g = (Graph3D *)w;
8011 if (!g->hasData()) {
8012 QMenu *plot3D = cm.addMenu(tr("3D &Plot"));
8013 plot3D->addAction(actionAdd3DData);
8014 plot3D->addAction(tr("&Matrix..."), this, SLOT(add3DMatrixPlot()));
8015 plot3D->addAction(actionEditSurfacePlot);
8016 } else {
8017 if (g->getTable())
8018 cm.addAction(tr("Choose &Data Set..."), this, SLOT(change3DData()));
8019 else if (g->matrix())
8020 cm.addAction(tr("Choose &Matrix..."), this, SLOT(change3DMatrix()));
8021 else if (g->userFunction())
8022 cm.addAction(actionEditSurfacePlot);
8023 cm.addAction(QPixmap(":/erase.xpm"), tr("C&lear"), g, SLOT(clearData()));
8024 }
8025
8026 cm.addSeparator();
8027 cm.addAction(actionRename);
8028 cm.addAction(actionCopyWindow);
8029 cm.addSeparator();
8030 cm.addAction(tr("&Copy Graph"), g, SLOT(copyImage()));
8031 cm.addAction(tr("&Export"), this, SLOT(exportGraph()));
8032 cm.addAction(actionPrint);
8033 cm.addSeparator();
8034 cm.addAction(actionCloseWindow);
8035 } else if (w->inherits("Matrix")) {
8036 Matrix *t = (Matrix *)w;
8037 cm.addAction(IconLoader::load("edit-cut"), tr("Cu&t"), t, SLOT(cutSelection()));
8038 cm.addAction(IconLoader::load("edit-copy"), tr("&Copy"), t, SLOT(copySelection()));
8039 cm.addAction(IconLoader::load("edit-paste"), tr("&Paste"), t, SLOT(pasteSelection()));
8040 cm.addSeparator();
8041 cm.addAction(tr("&Insert Row"), t, SLOT(insertRow()));
8042 cm.addAction(tr("&Insert Column"), t, SLOT(insertColumn()));
8043 if (t->rowsSelected()) {
8044 cm.addAction(QPixmap(":/close.xpm"), tr("&Delete Rows"), t, SLOT(deleteSelectedRows()));
8045 } else if (t->columnsSelected()) {
8046 cm.addAction(QPixmap(":/close.xpm"), tr("&Delete Columns"), t,
8047 SLOT(deleteSelectedColumns()));
8048 }
8049 cm.addAction(QPixmap(":/erase.xpm"), tr("Clea&r"), t, SLOT(clearSelection()));
8050 }
8051 cm.exec(QCursor::pos());
8052 }
8053
showWindowTitleBarMenu()8054 void ApplicationWindow::showWindowTitleBarMenu()
8055 {
8056 if (!qobject_cast<MyWidget *>(d_workspace.activeSubWindow()))
8057 return;
8058
8059 showWindowMenu(qobject_cast<MyWidget *>(d_workspace.activeSubWindow()));
8060 }
8061
chooseHelpFolder()8062 void ApplicationWindow::chooseHelpFolder()
8063 {
8064 // TODO: move all paths & location handling to anothor class
8065 #ifdef DOC_PATH
8066 const QString locateDefaultHelp = DOC_PATH +
8067 QDir::toNativeSeparators("/manual/index.html");
8068 #else // defined DOC_PATH
8069 #if defined(Q_OS_WIN)
8070 const QString locateDefaultHelp =
8071 qApp->applicationDirPath() + QDir::toNativeSeparators("/manual/index.html");
8072 #else
8073 const QString locateDefaultHelp =
8074 QDir::toNativeSeparators("/usr/share/doc/scidavis/manual/index.html");
8075 #endif
8076 #endif // defined DOC_PATH
8077
8078 if (QFile(locateDefaultHelp).exists()) {
8079 helpFilePath = locateDefaultHelp;
8080 } else {
8081 const QString dir = QFileDialog::getExistingDirectory(
8082 this, tr("Choose the location of the SciDAVis help folder!"),
8083 qApp->applicationDirPath());
8084
8085 if (!dir.isEmpty()) {
8086 const QFile helpFile(dir + QDir::toNativeSeparators("/index.html"));
8087 // TODO: Probably some kind of validity check to make sure that the
8088 // index.html file belongs to sciDavis
8089 if (!helpFile.exists()) {
8090 QMessageBox::information(
8091 this, tr("index.html File Not Found!"),
8092 tr("There is no file called <b>index.html</b> in this folder."
8093 "<br>Please choose another folder!"));
8094 } else {
8095 helpFilePath = dir + QDir::toNativeSeparators("/index.html");
8096 }
8097 }
8098 }
8099 }
8100
showHelp()8101 void ApplicationWindow::showHelp()
8102 {
8103 QFile helpFile(helpFilePath);
8104 if (!helpFile.exists()) {
8105 QMessageBox::information(
8106 this, tr("Help Files Not Found!"),
8107 tr("Please indicate the location of the help file!") + "<br>"
8108 + tr("The manual can be downloaded from the following internet address:")
8109 + "<p><a href = \"" MANUAL_URI "\">" MANUAL_URI "</a></p>");
8110 chooseHelpFolder();
8111 #ifdef Q_OS_MAC
8112 QSettings settings(QSettings::IniFormat, QSettings::UserScope, "SciDAVis", "SciDAVis");
8113 #else
8114 QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "SciDAVis", "SciDAVis");
8115 #endif
8116 settings.beginGroup("/Paths");
8117 settings.setValue("/HelpFile", helpFilePath);
8118 settings.endGroup();
8119 }
8120
8121 if (!QDesktopServices::openUrl(QUrl(helpFilePath))) {
8122 QMessageBox::information(this, tr("unable to open index.html!"),
8123 tr("<b>index.html</b> file cannot be opened"));
8124 }
8125 }
8126
showPlotWizard()8127 void ApplicationWindow::showPlotWizard()
8128 {
8129 if (tableWindows().count() > 0) {
8130 PlotWizard *pw = new PlotWizard(this, Qt::Widget);
8131 pw->setAttribute(Qt::WA_DeleteOnClose);
8132 connect(pw, SIGNAL(plot(const QStringList &)), this,
8133 SLOT(multilayerPlot(const QStringList &)));
8134
8135 pw->insertTablesList(tableWindows());
8136 // TODO: string list -> Column * list
8137 pw->setColumnsList(columnsList());
8138 pw->changeColumnsList(tableWindows()[0]);
8139 pw->exec();
8140 } else
8141 QMessageBox::warning(this, tr("Warning"),
8142 tr("<h4>There are no tables available in this project.</h4>"
8143 "<p><h4>Please create a table and try again!</h4>"));
8144 }
8145
setCurveFullRange()8146 void ApplicationWindow::setCurveFullRange()
8147 {
8148 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
8149 return;
8150
8151 Graph *g = ((MultiLayer *)d_workspace.activeSubWindow())->activeGraph();
8152 if (!g)
8153 return;
8154
8155 int curveKey = actionCurveFullRange->data().toInt();
8156 g->setCurveFullRange(g->curveIndex(curveKey));
8157 }
8158
showCurveRangeDialog()8159 void ApplicationWindow::showCurveRangeDialog()
8160 {
8161 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
8162 return;
8163
8164 Graph *g = ((MultiLayer *)d_workspace.activeSubWindow())->activeGraph();
8165 if (!g)
8166 return;
8167
8168 int curveKey = actionEditCurveRange->data().toInt();
8169 showCurveRangeDialog(g, g->curveIndex(curveKey));
8170 }
8171
showCurveRangeDialog(Graph * g,int curve)8172 CurveRangeDialog *ApplicationWindow::showCurveRangeDialog(Graph *g, int curve)
8173 {
8174 if (!g)
8175 return 0;
8176
8177 CurveRangeDialog *crd = new CurveRangeDialog(this);
8178 crd->setAttribute(Qt::WA_DeleteOnClose);
8179 crd->setCurveToModify(g, curve);
8180 crd->show();
8181 return crd;
8182 }
8183
showFunctionDialog()8184 void ApplicationWindow::showFunctionDialog()
8185 {
8186 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
8187 return;
8188
8189 Graph *g = ((MultiLayer *)d_workspace.activeSubWindow())->activeGraph();
8190 if (!g)
8191 return;
8192
8193 int curveKey = actionEditFunction->data().toInt();
8194 showFunctionDialog(g, g->curveIndex(curveKey));
8195 }
8196
showFunctionDialog(Graph * g,int curve)8197 void ApplicationWindow::showFunctionDialog(Graph *g, int curve)
8198 {
8199 if (!g)
8200 return;
8201
8202 FunctionDialog *fd = functionDialog();
8203 fd->setWindowTitle(tr("Edit function"));
8204 fd->setCurveToModify(g, curve);
8205 }
8206
functionDialog()8207 FunctionDialog *ApplicationWindow::functionDialog()
8208 {
8209 FunctionDialog *fd = new FunctionDialog(this);
8210 fd->setAttribute(Qt::WA_DeleteOnClose);
8211 connect(fd, SIGNAL(clearParamFunctionsList()), this, SLOT(clearParamFunctionsList()));
8212 connect(fd, SIGNAL(clearPolarFunctionsList()), this, SLOT(clearPolarFunctionsList()));
8213
8214 fd->insertParamFunctionsList(xFunctions, yFunctions);
8215 fd->insertPolarFunctionsList(rFunctions, thetaFunctions);
8216 fd->show();
8217 fd->activateWindow();
8218 return fd;
8219 }
8220
addFunctionCurve()8221 void ApplicationWindow::addFunctionCurve()
8222 {
8223 QWidget *w = d_workspace.activeSubWindow();
8224 if (!w || !w->inherits("MultiLayer"))
8225 return;
8226
8227 if (((MultiLayer *)w)->isEmpty()) {
8228 QMessageBox::warning(this, tr("Warning"),
8229 tr("<h4>There are no plot layers available in this window.</h4>"
8230 "<p><h4>Please add a layer and try again!</h4>"));
8231 return;
8232 }
8233
8234 Graph *g = ((MultiLayer *)w)->activeGraph();
8235 if (g) {
8236 FunctionDialog *fd = functionDialog();
8237 if (fd)
8238 fd->setGraph(g);
8239 }
8240 }
8241
updateFunctionLists(int type,QStringList & formulas)8242 void ApplicationWindow::updateFunctionLists(int type, QStringList &formulas)
8243 {
8244 int maxListSize = 10;
8245 if (type == 2) {
8246 rFunctions.removeAll(formulas[0]);
8247 rFunctions.push_front(formulas[0]);
8248
8249 thetaFunctions.removeAll(formulas[1]);
8250 thetaFunctions.push_front(formulas[1]);
8251
8252 while ((int)rFunctions.size() > maxListSize)
8253 rFunctions.pop_back();
8254 while ((int)thetaFunctions.size() > maxListSize)
8255 thetaFunctions.pop_back();
8256 } else if (type == 1) {
8257 xFunctions.removeAll(formulas[0]);
8258 xFunctions.push_front(formulas[0]);
8259
8260 yFunctions.removeAll(formulas[1]);
8261 yFunctions.push_front(formulas[1]);
8262
8263 while ((int)xFunctions.size() > maxListSize)
8264 xFunctions.pop_back();
8265 while ((int)yFunctions.size() > maxListSize)
8266 yFunctions.pop_back();
8267 }
8268 }
8269
newFunctionPlot(int type,QStringList & formulas,const QString & var,QList<double> & ranges,int points)8270 bool ApplicationWindow::newFunctionPlot(int type, QStringList &formulas, const QString &var,
8271 QList<double> &ranges, int points)
8272 {
8273 MultiLayer *ml = newGraph();
8274 if (!ml)
8275 return false;
8276
8277 if (!ml->activeGraph()->addFunctionCurve(this, type, formulas, var, ranges, points))
8278 return false;
8279
8280 updateFunctionLists(type, formulas);
8281 return true;
8282 }
8283
clearLogInfo()8284 void ApplicationWindow::clearLogInfo()
8285 {
8286 if (!logInfo.isEmpty()) {
8287 logInfo = "";
8288 results->setText(logInfo);
8289 emit modified();
8290 }
8291 }
8292
clearParamFunctionsList()8293 void ApplicationWindow::clearParamFunctionsList()
8294 {
8295 xFunctions.clear();
8296 yFunctions.clear();
8297 }
8298
clearPolarFunctionsList()8299 void ApplicationWindow::clearPolarFunctionsList()
8300 {
8301 rFunctions.clear();
8302 thetaFunctions.clear();
8303 }
8304
clearFitFunctionsList()8305 void ApplicationWindow::clearFitFunctionsList()
8306 {
8307 fitFunctions.clear();
8308 }
8309
saveFitFunctionsList(const QStringList & l)8310 void ApplicationWindow::saveFitFunctionsList(const QStringList &l)
8311 {
8312 fitFunctions = l;
8313 }
8314
clearSurfaceFunctionsList()8315 void ApplicationWindow::clearSurfaceFunctionsList()
8316 {
8317 surfaceFunc.clear();
8318 }
8319
setFramed3DPlot()8320 void ApplicationWindow::setFramed3DPlot()
8321 {
8322 if (d_workspace.activeSubWindow() && d_workspace.activeSubWindow()->inherits("Graph3D")) {
8323 ((Graph3D *)d_workspace.activeSubWindow())->setFramed();
8324 actionShowAxisDialog->setEnabled(true);
8325 }
8326 }
8327
setBoxed3DPlot()8328 void ApplicationWindow::setBoxed3DPlot()
8329 {
8330 if (d_workspace.activeSubWindow() && d_workspace.activeSubWindow()->inherits("Graph3D")) {
8331 ((Graph3D *)d_workspace.activeSubWindow())->setBoxed();
8332 actionShowAxisDialog->setEnabled(true);
8333 }
8334 }
8335
removeAxes3DPlot()8336 void ApplicationWindow::removeAxes3DPlot()
8337 {
8338 if (d_workspace.activeSubWindow() && d_workspace.activeSubWindow()->inherits("Graph3D")) {
8339 ((Graph3D *)d_workspace.activeSubWindow())->setNoAxes();
8340 actionShowAxisDialog->setEnabled(false);
8341 }
8342 }
8343
removeGrid3DPlot()8344 void ApplicationWindow::removeGrid3DPlot()
8345 {
8346 if (d_workspace.activeSubWindow() && d_workspace.activeSubWindow()->inherits("Graph3D"))
8347 ((Graph3D *)d_workspace.activeSubWindow())->setNoGrid();
8348 }
8349
setHiddenLineGrid3DPlot()8350 void ApplicationWindow::setHiddenLineGrid3DPlot()
8351 {
8352 if (d_workspace.activeSubWindow() && d_workspace.activeSubWindow()->inherits("Graph3D"))
8353 ((Graph3D *)d_workspace.activeSubWindow())->setHiddenLineGrid();
8354 }
8355
setPoints3DPlot()8356 void ApplicationWindow::setPoints3DPlot()
8357 {
8358 if (d_workspace.activeSubWindow() && d_workspace.activeSubWindow()->inherits("Graph3D"))
8359 ((Graph3D *)d_workspace.activeSubWindow())->setPointsMesh();
8360 }
8361
setCones3DPlot()8362 void ApplicationWindow::setCones3DPlot()
8363 {
8364 if (d_workspace.activeSubWindow() && d_workspace.activeSubWindow()->inherits("Graph3D"))
8365 ((Graph3D *)d_workspace.activeSubWindow())->setConesMesh();
8366 }
8367
setCrosses3DPlot()8368 void ApplicationWindow::setCrosses3DPlot()
8369 {
8370 if (d_workspace.activeSubWindow() && d_workspace.activeSubWindow()->inherits("Graph3D"))
8371 ((Graph3D *)d_workspace.activeSubWindow())->setCrossMesh();
8372 }
8373
setBars3DPlot()8374 void ApplicationWindow::setBars3DPlot()
8375 {
8376 if (d_workspace.activeSubWindow() && d_workspace.activeSubWindow()->inherits("Graph3D"))
8377 ((Graph3D *)d_workspace.activeSubWindow())->setBarsPlot();
8378 }
8379
setLineGrid3DPlot()8380 void ApplicationWindow::setLineGrid3DPlot()
8381 {
8382 if (d_workspace.activeSubWindow() && d_workspace.activeSubWindow()->inherits("Graph3D"))
8383 ((Graph3D *)d_workspace.activeSubWindow())->setLineGrid();
8384 }
8385
setFilledMesh3DPlot()8386 void ApplicationWindow::setFilledMesh3DPlot()
8387 {
8388 if (d_workspace.activeSubWindow() && d_workspace.activeSubWindow()->inherits("Graph3D"))
8389 ((Graph3D *)d_workspace.activeSubWindow())->setFilledMesh();
8390 }
8391
setFloorData3DPlot()8392 void ApplicationWindow::setFloorData3DPlot()
8393 {
8394 if (d_workspace.activeSubWindow() && d_workspace.activeSubWindow()->inherits("Graph3D"))
8395 ((Graph3D *)d_workspace.activeSubWindow())->setFloorData();
8396 }
8397
setFloorIso3DPlot()8398 void ApplicationWindow::setFloorIso3DPlot()
8399 {
8400 if (d_workspace.activeSubWindow() && d_workspace.activeSubWindow()->inherits("Graph3D"))
8401 ((Graph3D *)d_workspace.activeSubWindow())->setFloorIsolines();
8402 }
8403
setEmptyFloor3DPlot()8404 void ApplicationWindow::setEmptyFloor3DPlot()
8405 {
8406 if (d_workspace.activeSubWindow() && d_workspace.activeSubWindow()->inherits("Graph3D"))
8407 ((Graph3D *)d_workspace.activeSubWindow())->setEmptyFloor();
8408 }
8409
setFrontGrid3DPlot(bool on)8410 void ApplicationWindow::setFrontGrid3DPlot(bool on)
8411 {
8412 if (d_workspace.activeSubWindow() && d_workspace.activeSubWindow()->inherits("Graph3D"))
8413 ((Graph3D *)d_workspace.activeSubWindow())->setFrontGrid(on);
8414 }
8415
setBackGrid3DPlot(bool on)8416 void ApplicationWindow::setBackGrid3DPlot(bool on)
8417 {
8418 if (d_workspace.activeSubWindow() && d_workspace.activeSubWindow()->inherits("Graph3D"))
8419 ((Graph3D *)d_workspace.activeSubWindow())->setBackGrid(on);
8420 }
8421
setFloorGrid3DPlot(bool on)8422 void ApplicationWindow::setFloorGrid3DPlot(bool on)
8423 {
8424 if (d_workspace.activeSubWindow() && d_workspace.activeSubWindow()->inherits("Graph3D"))
8425 ((Graph3D *)d_workspace.activeSubWindow())->setFloorGrid(on);
8426 }
8427
setCeilGrid3DPlot(bool on)8428 void ApplicationWindow::setCeilGrid3DPlot(bool on)
8429 {
8430 if (d_workspace.activeSubWindow() && d_workspace.activeSubWindow()->inherits("Graph3D"))
8431 ((Graph3D *)d_workspace.activeSubWindow())->setCeilGrid(on);
8432 }
8433
setRightGrid3DPlot(bool on)8434 void ApplicationWindow::setRightGrid3DPlot(bool on)
8435 {
8436 if (d_workspace.activeSubWindow() && d_workspace.activeSubWindow()->inherits("Graph3D"))
8437 ((Graph3D *)d_workspace.activeSubWindow())->setRightGrid(on);
8438 }
8439
setLeftGrid3DPlot(bool on)8440 void ApplicationWindow::setLeftGrid3DPlot(bool on)
8441 {
8442 if (d_workspace.activeSubWindow() && d_workspace.activeSubWindow()->inherits("Graph3D"))
8443 ((Graph3D *)d_workspace.activeSubWindow())->setLeftGrid(on);
8444 }
8445
pickPlotStyle(QAction * action)8446 void ApplicationWindow::pickPlotStyle(QAction *action)
8447 {
8448 if (!action)
8449 return;
8450
8451 if (action == polygon) {
8452 removeGrid3DPlot();
8453 } else if (action == filledmesh) {
8454 setFilledMesh3DPlot();
8455 } else if (action == wireframe) {
8456 setLineGrid3DPlot();
8457 } else if (action == hiddenline) {
8458 setHiddenLineGrid3DPlot();
8459 } else if (action == pointstyle) {
8460 setPoints3DPlot();
8461 } else if (action == conestyle) {
8462 setCones3DPlot();
8463 } else if (action == crossHairStyle) {
8464 setCrosses3DPlot();
8465 } else if (action == barstyle) {
8466 setBars3DPlot();
8467 }
8468 emit modified();
8469 }
8470
pickCoordSystem(QAction * action)8471 void ApplicationWindow::pickCoordSystem(QAction *action)
8472 {
8473 if (!action)
8474 return;
8475
8476 if (action == Box || action == Frame) {
8477 if (action == Box)
8478 setBoxed3DPlot();
8479 if (action == Frame)
8480 setFramed3DPlot();
8481 grids->setEnabled(true);
8482 } else if (action == None) {
8483 removeAxes3DPlot();
8484 grids->setEnabled(false);
8485 }
8486
8487 emit modified();
8488 }
8489
pickFloorStyle(QAction * action)8490 void ApplicationWindow::pickFloorStyle(QAction *action)
8491 {
8492 if (!action)
8493 return;
8494
8495 if (action == floordata) {
8496 setFloorData3DPlot();
8497 } else if (action == flooriso) {
8498 setFloorIso3DPlot();
8499 } else {
8500 setEmptyFloor3DPlot();
8501 }
8502
8503 emit modified();
8504 }
8505
custom3DActions(MyWidget * w)8506 void ApplicationWindow::custom3DActions(MyWidget *w)
8507 {
8508 if (w && w->inherits("Graph3D")) {
8509 Graph3D *plot = (Graph3D *)w;
8510 actionAnimate->setChecked(plot->isAnimated());
8511 actionPerspective->setChecked(!plot->isOrthogonal());
8512 switch (plot->plotStyle()) {
8513 case FILLEDMESH:
8514 wireframe->setChecked(false);
8515 hiddenline->setChecked(false);
8516 polygon->setChecked(false);
8517 filledmesh->setChecked(true);
8518 pointstyle->setChecked(false);
8519 barstyle->setChecked(false);
8520 conestyle->setChecked(false);
8521 crossHairStyle->setChecked(false);
8522 break;
8523
8524 case FILLED:
8525 wireframe->setChecked(false);
8526 hiddenline->setChecked(false);
8527 polygon->setChecked(true);
8528 filledmesh->setChecked(false);
8529 pointstyle->setChecked(false);
8530 barstyle->setChecked(false);
8531 conestyle->setChecked(false);
8532 crossHairStyle->setChecked(false);
8533 break;
8534
8535 case Qwt3D::USER:
8536 wireframe->setChecked(false);
8537 hiddenline->setChecked(false);
8538 polygon->setChecked(false);
8539 filledmesh->setChecked(false);
8540
8541 if (plot->pointType() == Graph3D::VerticalBars) {
8542 pointstyle->setChecked(false);
8543 conestyle->setChecked(false);
8544 crossHairStyle->setChecked(false);
8545 barstyle->setChecked(true);
8546 } else if (plot->pointType() == Graph3D::Dots) {
8547 pointstyle->setChecked(true);
8548 barstyle->setChecked(false);
8549 conestyle->setChecked(false);
8550 crossHairStyle->setChecked(false);
8551 } else if (plot->pointType() == Graph3D::HairCross) {
8552 pointstyle->setChecked(false);
8553 barstyle->setChecked(false);
8554 conestyle->setChecked(false);
8555 crossHairStyle->setChecked(true);
8556 } else if (plot->pointType() == Graph3D::Cones) {
8557 pointstyle->setChecked(false);
8558 barstyle->setChecked(false);
8559 conestyle->setChecked(true);
8560 crossHairStyle->setChecked(false);
8561 }
8562 break;
8563
8564 case WIREFRAME:
8565 wireframe->setChecked(true);
8566 hiddenline->setChecked(false);
8567 polygon->setChecked(false);
8568 filledmesh->setChecked(false);
8569 pointstyle->setChecked(false);
8570 barstyle->setChecked(false);
8571 conestyle->setChecked(false);
8572 crossHairStyle->setChecked(false);
8573 break;
8574
8575 case HIDDENLINE:
8576 wireframe->setChecked(false);
8577 hiddenline->setChecked(true);
8578 polygon->setChecked(false);
8579 filledmesh->setChecked(false);
8580 pointstyle->setChecked(false);
8581 barstyle->setChecked(false);
8582 conestyle->setChecked(false);
8583 crossHairStyle->setChecked(false);
8584 break;
8585
8586 default:
8587 break;
8588 }
8589
8590 switch (plot->coordStyle()) {
8591 case Qwt3D::NOCOORD:
8592 None->setChecked(true);
8593 Box->setChecked(false);
8594 Frame->setChecked(false);
8595 break;
8596
8597 case Qwt3D::BOX:
8598 None->setChecked(false);
8599 Box->setChecked(true);
8600 Frame->setChecked(false);
8601 break;
8602
8603 case Qwt3D::FRAME:
8604 None->setChecked(false);
8605 Box->setChecked(false);
8606 Frame->setChecked(true);
8607 break;
8608 }
8609
8610 switch (plot->floorStyle()) {
8611 case NOFLOOR:
8612 floornone->setChecked(true);
8613 flooriso->setChecked(false);
8614 floordata->setChecked(false);
8615 break;
8616
8617 case FLOORISO:
8618 floornone->setChecked(false);
8619 flooriso->setChecked(true);
8620 floordata->setChecked(false);
8621 break;
8622
8623 case FLOORDATA:
8624 floornone->setChecked(false);
8625 flooriso->setChecked(false);
8626 floordata->setChecked(true);
8627 break;
8628 }
8629 custom3DGrids(plot->grids());
8630 }
8631 }
8632
custom3DGrids(int grids)8633 void ApplicationWindow::custom3DGrids(int grids)
8634 {
8635 if (Qwt3D::BACK & grids)
8636 back->setChecked(true);
8637 else
8638 back->setChecked(false);
8639
8640 if (Qwt3D::FRONT & grids)
8641 front->setChecked(true);
8642 else
8643 front->setChecked(false);
8644
8645 if (Qwt3D::CEIL & grids)
8646 ceil->setChecked(true);
8647 else
8648 ceil->setChecked(false);
8649
8650 if (Qwt3D::FLOOR & grids)
8651 floor->setChecked(true);
8652 else
8653 floor->setChecked(false);
8654
8655 if (Qwt3D::RIGHT & grids)
8656 right->setChecked(true);
8657 else
8658 right->setChecked(false);
8659
8660 if (Qwt3D::LEFT & grids)
8661 left->setChecked(true);
8662 else
8663 left->setChecked(false);
8664 }
8665
initPlot3DToolBar()8666 void ApplicationWindow::initPlot3DToolBar()
8667 {
8668 graph_3D_tools = new QToolBar(tr("3D Surface"), this);
8669 graph_3D_tools->setObjectName(
8670 "graph_3D_tools"); // this is needed for QMainWindow::restoreState()
8671 graph_3D_tools->setIconSize(QSize(20, 20));
8672 addToolBarBreak(Qt::TopToolBarArea);
8673 addToolBar(Qt::TopToolBarArea, graph_3D_tools);
8674
8675 coord = new QActionGroup(this);
8676 Box = new QAction(coord);
8677 Box->setIcon(QIcon(QPixmap(":/box.xpm")));
8678 Box->setCheckable(true);
8679
8680 Frame = new QAction(coord);
8681 Frame->setIcon(QIcon(QPixmap(":/free_axes.xpm")));
8682 Frame->setCheckable(true);
8683
8684 None = new QAction(coord);
8685 None->setIcon(QIcon(QPixmap(":/no_axes.xpm")));
8686 None->setCheckable(true);
8687
8688 graph_3D_tools->addAction(Frame);
8689 graph_3D_tools->addAction(Box);
8690 graph_3D_tools->addAction(None);
8691 Box->setChecked(true);
8692
8693 graph_3D_tools->addSeparator();
8694
8695 // grid actions
8696 grids = new QActionGroup(this);
8697 grids->setEnabled(true);
8698 grids->setExclusive(false);
8699 front = new QAction(grids);
8700 front->setCheckable(true);
8701 front->setIcon(QIcon(QPixmap(":/frontGrid.xpm")));
8702 back = new QAction(grids);
8703 back->setCheckable(true);
8704 back->setIcon(QIcon(QPixmap(":/backGrid.xpm")));
8705 right = new QAction(grids);
8706 right->setCheckable(true);
8707 right->setIcon(QIcon(QPixmap(":/leftGrid.xpm")));
8708 left = new QAction(grids);
8709 left->setCheckable(true);
8710 left->setIcon(QIcon(QPixmap(":/rightGrid.xpm")));
8711 ceil = new QAction(grids);
8712 ceil->setCheckable(true);
8713 ceil->setIcon(QIcon(QPixmap(":/ceilGrid.xpm")));
8714 floor = new QAction(grids);
8715 floor->setCheckable(true);
8716 floor->setIcon(QIcon(QPixmap(":/floorGrid.xpm")));
8717
8718 graph_3D_tools->addAction(front);
8719 graph_3D_tools->addAction(back);
8720 graph_3D_tools->addAction(right);
8721 graph_3D_tools->addAction(left);
8722 graph_3D_tools->addAction(ceil);
8723 graph_3D_tools->addAction(floor);
8724
8725 graph_3D_tools->addSeparator();
8726
8727 actionPerspective = new QAction(this);
8728 actionPerspective->setCheckable(true);
8729 actionPerspective->setIcon(QPixmap(":/perspective.xpm"));
8730 graph_3D_tools->addAction(actionPerspective);
8731 actionPerspective->setChecked(!orthogonal3DPlots);
8732 connect(actionPerspective, SIGNAL(toggled(bool)), this, SLOT(togglePerspective(bool)));
8733
8734 actionResetRotation = new QAction(this);
8735 actionResetRotation->setCheckable(false);
8736 actionResetRotation->setIcon(QPixmap(":/reset_rotation.xpm"));
8737 graph_3D_tools->addAction(actionResetRotation);
8738 connect(actionResetRotation, SIGNAL(triggered()), this, SLOT(resetRotation()));
8739
8740 actionFitFrame = new QAction(this);
8741 actionFitFrame->setCheckable(false);
8742 actionFitFrame->setIcon(QPixmap(":/fit_frame.xpm"));
8743 graph_3D_tools->addAction(actionFitFrame);
8744 connect(actionFitFrame, SIGNAL(triggered()), this, SLOT(fitFrameToLayer()));
8745
8746 graph_3D_tools->addSeparator();
8747
8748 // plot style actions
8749 plotstyle = new QActionGroup(this);
8750 wireframe = new QAction(plotstyle);
8751 wireframe->setCheckable(true);
8752 wireframe->setEnabled(true);
8753 wireframe->setIcon(QIcon(QPixmap(":/lineMesh.xpm")));
8754 hiddenline = new QAction(plotstyle);
8755 hiddenline->setCheckable(true);
8756 hiddenline->setEnabled(true);
8757 hiddenline->setIcon(QIcon(QPixmap(":/grid_only.xpm")));
8758 polygon = new QAction(plotstyle);
8759 polygon->setCheckable(true);
8760 polygon->setEnabled(true);
8761 polygon->setIcon(QIcon(QPixmap(":/no_grid.xpm")));
8762 filledmesh = new QAction(plotstyle);
8763 filledmesh->setCheckable(true);
8764 filledmesh->setIcon(QIcon(QPixmap(":/grid_poly.xpm")));
8765 pointstyle = new QAction(plotstyle);
8766 pointstyle->setCheckable(true);
8767 pointstyle->setIcon(QIcon(QPixmap(":/pointsMesh.xpm")));
8768
8769 conestyle = new QAction(plotstyle);
8770 conestyle->setCheckable(true);
8771 conestyle->setIcon(QIcon(QPixmap(":/cones.xpm")));
8772
8773 crossHairStyle = new QAction(plotstyle);
8774 crossHairStyle->setCheckable(true);
8775 crossHairStyle->setIcon(QIcon(QPixmap(":/crosses.xpm")));
8776
8777 barstyle = new QAction(plotstyle);
8778 barstyle->setCheckable(true);
8779 barstyle->setIcon(QIcon(QPixmap(":/plot_bars.xpm")));
8780
8781 graph_3D_tools->addAction(barstyle);
8782 graph_3D_tools->addAction(pointstyle);
8783
8784 graph_3D_tools->addAction(conestyle);
8785 graph_3D_tools->addAction(crossHairStyle);
8786 graph_3D_tools->addSeparator();
8787
8788 graph_3D_tools->addAction(wireframe);
8789 graph_3D_tools->addAction(hiddenline);
8790 graph_3D_tools->addAction(polygon);
8791 graph_3D_tools->addAction(filledmesh);
8792 filledmesh->setChecked(true);
8793
8794 graph_3D_tools->addSeparator();
8795
8796 // floor actions
8797 floorstyle = new QActionGroup(this);
8798 floordata = new QAction(floorstyle);
8799 floordata->setCheckable(true);
8800 floordata->setIcon(QIcon(QPixmap(":/floor.xpm")));
8801 flooriso = new QAction(floorstyle);
8802 flooriso->setCheckable(true);
8803 flooriso->setIcon(QIcon(QPixmap(":/isolines.xpm")));
8804 floornone = new QAction(floorstyle);
8805 floornone->setCheckable(true);
8806 floornone->setIcon(QIcon(QPixmap(":/no_floor.xpm")));
8807
8808 graph_3D_tools->addAction(floordata);
8809 graph_3D_tools->addAction(flooriso);
8810 graph_3D_tools->addAction(floornone);
8811 floornone->setChecked(true);
8812
8813 graph_3D_tools->addSeparator();
8814
8815 actionAnimate = new QAction(this);
8816 actionAnimate->setCheckable(true);
8817 actionAnimate->setIcon(QPixmap(":/movie.xpm"));
8818 graph_3D_tools->addAction(actionAnimate);
8819
8820 connect(actionAnimate, SIGNAL(toggled(bool)), this, SLOT(toggle3DAnimation(bool)));
8821 connect(coord, SIGNAL(triggered(QAction *)), this, SLOT(pickCoordSystem(QAction *)));
8822 connect(floorstyle, SIGNAL(triggered(QAction *)), this, SLOT(pickFloorStyle(QAction *)));
8823 connect(plotstyle, SIGNAL(triggered(QAction *)), this, SLOT(pickPlotStyle(QAction *)));
8824
8825 connect(left, SIGNAL(triggered(bool)), this, SLOT(setLeftGrid3DPlot(bool)));
8826 connect(right, SIGNAL(triggered(bool)), this, SLOT(setRightGrid3DPlot(bool)));
8827 connect(ceil, SIGNAL(triggered(bool)), this, SLOT(setCeilGrid3DPlot(bool)));
8828 connect(floor, SIGNAL(triggered(bool)), this, SLOT(setFloorGrid3DPlot(bool)));
8829 connect(back, SIGNAL(triggered(bool)), this, SLOT(setBackGrid3DPlot(bool)));
8830 connect(front, SIGNAL(triggered(bool)), this, SLOT(setFrontGrid3DPlot(bool)));
8831 }
8832
pixelLineProfile()8833 void ApplicationWindow::pixelLineProfile()
8834 {
8835 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
8836 return;
8837
8838 Graph *g = ((MultiLayer *)d_workspace.activeSubWindow())->activeGraph();
8839 if (!g)
8840 return;
8841
8842 bool ok;
8843 int res = QInputDialog::getInt(this, tr("Set the number of pixels to average"),
8844 tr("Number of averaged pixels"), 1, 1, 2000, 2, &ok);
8845 if (!ok)
8846 return;
8847
8848 LineProfileTool *lpt = new LineProfileTool(g, res);
8849 connect(lpt, SIGNAL(createTablePlot(const QString &, const QString &, QList<Column *>)), this,
8850 SLOT(newWrksheetPlot(const QString &, const QString &, QList<Column *>)));
8851 g->setActiveTool(lpt);
8852 }
8853
intensityTable()8854 void ApplicationWindow::intensityTable()
8855 {
8856 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
8857 return;
8858
8859 Graph *g = ((MultiLayer *)d_workspace.activeSubWindow())->activeGraph();
8860 if (g)
8861 g->showIntensityTable();
8862 }
8863
importImage(const QString & fileName)8864 Matrix *ApplicationWindow::importImage(const QString &fileName)
8865 {
8866 QImage image(fileName);
8867 if (image.isNull())
8868 return NULL;
8869
8870 Matrix *m = Matrix::fromImage(image, scriptEnv);
8871 if (!m) {
8872 QMessageBox::information(0, tr("Error importing image"),
8873 tr("Import of image '%1' failed").arg(fileName));
8874 return NULL;
8875 }
8876 QString caption = generateUniqueName(tr("Matrix"));
8877 m->setName(caption);
8878 d_project->addChild(m->d_future_matrix);
8879 return m;
8880 }
8881
autoArrangeLayers()8882 void ApplicationWindow::autoArrangeLayers()
8883 {
8884 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
8885 return;
8886
8887 MultiLayer *plot = (MultiLayer *)d_workspace.activeSubWindow();
8888 plot->setMargins(5, 5, 5, 5);
8889 plot->setSpacing(5, 5);
8890 plot->arrangeLayers(true, false);
8891 }
8892
addLayer()8893 void ApplicationWindow::addLayer()
8894 {
8895 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
8896 return;
8897
8898 MultiLayer *plot = (MultiLayer *)d_workspace.activeSubWindow();
8899 switch (QMessageBox::information(
8900 this, tr("Guess best origin for the new layer?"),
8901 tr("Do you want SciDAVis to guess the best position for the new layer?\n Warning: this "
8902 "will rearrange existing layers!"),
8903 tr("&Guess"), tr("&Top-left corner"), tr("&Cancel"), 0, 2)) {
8904 case 0: {
8905 setPreferences(plot->addLayer());
8906 plot->arrangeLayers(true, false);
8907 } break;
8908
8909 case 1:
8910 setPreferences(plot->addLayer(0, 0, plot->size().width(), plot->size().height()));
8911 break;
8912
8913 case 2:
8914 return;
8915 break;
8916 }
8917 }
8918
deleteLayer()8919 void ApplicationWindow::deleteLayer()
8920 {
8921 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
8922 return;
8923
8924 ((MultiLayer *)d_workspace.activeSubWindow())->confirmRemoveLayer();
8925 }
8926
openNote(ApplicationWindow * app,const QStringList & flist)8927 Note *ApplicationWindow::openNote(ApplicationWindow *app, const QStringList &flist)
8928 {
8929 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
8930 QStringList lst = flist[0].split("\t", Qt::SkipEmptyParts);
8931 #else
8932 QStringList lst = flist[0].split("\t", QString::SkipEmptyParts);
8933 #endif
8934 QString caption = lst[0];
8935 Note *w = app->newNote(caption);
8936 if (lst.count() == 2) {
8937 app->setListViewDate(caption, lst[1]);
8938 w->setBirthDate(lst[1]);
8939 }
8940 restoreWindowGeometry(app, w, flist[1]);
8941
8942 lst = flist[2].split("\t");
8943 w->setWindowLabel(lst[1]);
8944 w->setCaptionPolicy((MyWidget::CaptionPolicy)lst[2].toInt());
8945 app->setListViewLabel(w->name(), lst[1]);
8946 return w;
8947 }
8948
8949 // TODO: most of this code belongs into matrix
openMatrix(ApplicationWindow * app,const QStringList & flist)8950 Matrix *ApplicationWindow::openMatrix(ApplicationWindow *app, const QStringList &flist)
8951 {
8952 if (app->d_file_version < 0x000200) {
8953 QStringList::const_iterator line = flist.begin();
8954
8955 QStringList list = (*line).split("\t");
8956 QString caption = list[0];
8957 int rows = list[1].toInt();
8958 int cols = list[2].toInt();
8959
8960 Matrix *w = app->newMatrix(caption, rows, cols);
8961 app->setListViewDate(caption, list[3]);
8962 w->setBirthDate(list[3]);
8963
8964 for (line++; line != flist.end(); line++) {
8965 QStringList fields = (*line).split("\t");
8966 if (fields[0] == "geometry") {
8967 restoreWindowGeometry(app, w, *line);
8968 } else if (fields[0] == "ColWidth") {
8969 w->setColumnsWidth(fields[1].toInt());
8970 } else if (fields[0] == "Formula") {
8971 w->setFormula(fields[1]);
8972 } else if (fields[0] == "<formula>") {
8973 QString formula;
8974 for (line++; line != flist.end() && *line != "</formula>"; line++)
8975 formula += *line + "\n";
8976 formula.truncate(formula.length() - 1);
8977 w->setFormula(formula);
8978 } else if (fields[0] == "TextFormat") {
8979 if (fields[1] == "f")
8980 w->setTextFormat('f', fields[2].toInt());
8981 else
8982 w->setTextFormat('e', fields[2].toInt());
8983 } else if (fields[0] == "WindowLabel") { // d_file_version > 71
8984 w->setWindowLabel(fields[1]);
8985 w->setCaptionPolicy((MyWidget::CaptionPolicy)fields[2].toInt());
8986 app->setListViewLabel(w->name(), fields[1]);
8987 } else if (fields[0] == "Coordinates") { // d_file_version > 81
8988 w->setCoordinates(fields[1].toDouble(), fields[2].toDouble(), fields[3].toDouble(),
8989 fields[4].toDouble());
8990 } else // <data> or values
8991 break;
8992 }
8993 if (*line == "<data>")
8994 line++;
8995
8996 QElapsedTimer t;
8997 t.start();
8998 // read and set table values
8999 for (; line != flist.end() && *line != "</data>"; line++) {
9000 QStringList fields = (*line).split("\t");
9001 int row = fields[0].toInt();
9002 for (int col = 0; col < cols; col++) {
9003 QString cell = fields[col + 1];
9004 if (cell.isEmpty())
9005 continue;
9006
9007 if (d_file_version < 90)
9008 w->setCell(row, col, QLocale::c().toDouble(cell));
9009 else if (d_file_version >= 0x000100)
9010 w->setCell(row, col, QLocale().toDouble(cell));
9011 else
9012 w->setText(row, col, cell);
9013 }
9014 if (t.elapsed() > 1000) {
9015 QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
9016 t.start();
9017 }
9018 }
9019
9020 return w;
9021 } else {
9022 Matrix *w = app->newMatrix("matrix", 1, 1);
9023 int length = flist.at(0).toInt();
9024 int index = 1;
9025 QString xml(flist.at(index++));
9026 while (xml.length() < length && index < flist.size())
9027 xml += '\n' + flist.at(index++);
9028 XmlStreamReader reader(xml);
9029 reader.readNext();
9030 reader.readNext(); // read the start document
9031 if (w->d_future_matrix->load(&reader) == false) {
9032 QString msg_text = reader.errorString();
9033 QMessageBox::critical(this, tr("Error reading matrix from project file"), msg_text);
9034 }
9035 if (reader.hasWarnings()) {
9036 QString msg_text =
9037 tr("The following problems occured when loading the project file:\n");
9038 QStringList warnings = reader.warningStrings();
9039 foreach (QString str, warnings)
9040 msg_text += str + "\n";
9041 QMessageBox::warning(this, tr("Project loading partly failed"), msg_text);
9042 }
9043 restoreWindowGeometry(app, w, flist.at(index));
9044
9045 activateSubWindow(w);
9046 return w;
9047 }
9048 }
9049
9050 // TODO: most of this code belongs into Table
openTable(ApplicationWindow * app,QTextStream & stream)9051 Table *ApplicationWindow::openTable(ApplicationWindow *app, QTextStream &stream)
9052 {
9053 if (app->d_file_version < 0x000200) {
9054 QStringList flist;
9055 QString s;
9056 while (s != "</table>") {
9057 s = stream.readLine();
9058 flist << s;
9059 }
9060 flist.pop_back();
9061 QStringList::const_iterator line = flist.begin();
9062
9063 QStringList list = (*line).split("\t");
9064 QString caption = list[0];
9065 int rows = list[1].toInt();
9066 int cols = list[2].toInt();
9067
9068 Table *w = app->newTable(caption, rows, cols);
9069 app->setListViewDate(caption, list[3]);
9070 w->setBirthDate(list[3]);
9071
9072 for (line++; line != flist.end(); line++) {
9073 QStringList fields = (*line).split("\t");
9074 if (fields[0] == "geometry" || fields[0] == "tgeometry") {
9075 restoreWindowGeometry(app, w, *line);
9076 } else if (fields[0] == "header") {
9077 fields.pop_front();
9078 if (d_file_version >= 78)
9079 w->importV0x0001XXHeader(fields);
9080 else {
9081 w->setColPlotDesignation(list[4].toInt(), SciDAVis::X);
9082 w->setColPlotDesignation(list[6].toInt(), SciDAVis::Y);
9083 w->setHeader(fields);
9084 }
9085 } else if (fields[0] == "ColWidth") {
9086 fields.pop_front();
9087 w->setColWidths(fields);
9088 } else if (fields[0] == "com") { // legacy code
9089 w->setCommands(*line);
9090 } else if (fields[0] == "<com>") {
9091 for (line++; line != flist.end() && *line != "</com>"; line++) {
9092 int col = (*line).mid(9, (*line).length() - 11).toInt();
9093 QString formula;
9094 for (line++; line != flist.end() && *line != "</col>"; line++)
9095 formula += *line + "\n";
9096 formula.truncate(formula.length() - 1);
9097 w->setCommand(col, formula);
9098 }
9099 } else if (fields[0] == "ColType") { // d_file_version > 65
9100 fields.pop_front();
9101 w->setColumnTypes(fields);
9102 } else if (fields[0] == "Comments") { // d_file_version > 71
9103 fields.pop_front();
9104 w->setColComments(fields);
9105 } else if (fields[0] == "WindowLabel") { // d_file_version > 71
9106 w->setWindowLabel(fields[1]);
9107 w->setCaptionPolicy((MyWidget::CaptionPolicy)fields[2].toInt());
9108 app->setListViewLabel(w->name(), fields[1]);
9109 } else // <data> or values
9110 break;
9111 }
9112
9113 QElapsedTimer t;
9114 t.start();
9115 QApplication::setOverrideCursor(Qt::WaitCursor);
9116 for (line++; line != flist.end() && *line != "</data>";
9117 line++) { // read and set table values
9118 QStringList fields = (*line).split("\t");
9119 int row = fields[0].toInt();
9120 for (int col = 0; col < cols; col++) {
9121 if (fields.count() >= col + 2) {
9122 QString cell = fields[col + 1];
9123 if (cell.isEmpty())
9124 continue;
9125
9126 if (d_file_version < 90 && w->columnType(col) == SciDAVis::ColumnMode::Numeric)
9127 w->setCell(row, col, QLocale::c().toDouble(cell.replace(",", ".")));
9128 else if (d_file_version >= 0x000100 && w->columnType(col) == SciDAVis::ColumnMode::Numeric)
9129 w->setCell(row, col, QLocale().toDouble(cell));
9130 else
9131 w->setText(row, col, cell);
9132 }
9133 }
9134 if (t.elapsed() > 1000) {
9135 QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
9136 t.start();
9137 }
9138 }
9139 QApplication::restoreOverrideCursor();
9140
9141 return w;
9142 } else {
9143 QString s = stream.readLine();
9144 int length = s.toInt();
9145
9146 // On Windows, loading large tables to a QString has been observed to crash
9147 // (apparently due to excessive memory usage).
9148 // => use temporary file if possible
9149 QTemporaryFile tmp_file;
9150 QString tmp_string;
9151 if (tmp_file.open()) {
9152 QTextStream tmp(&tmp_file);
9153 tmp.setCodec(QTextCodec::codecForName("UTF-8"));
9154 int read = 0;
9155 while (length - read >= 1024) {
9156 tmp << stream.read(1024);
9157 read += 1024;
9158 }
9159 tmp << stream.read(length - read);
9160 tmp.flush();
9161 tmp_file.seek(0);
9162 stream.readLine(); // skip to next newline
9163 } else
9164 while (tmp_string.length() < length)
9165 tmp_string += '\n' + stream.readLine();
9166
9167 XmlStreamReader reader(tmp_string);
9168 if (tmp_file.isOpen())
9169 reader.setDevice(&tmp_file);
9170
9171 Table *w = app->newTable("table", 1, 1);
9172 reader.readNext();
9173 reader.readNext(); // read the start document
9174 if (w->d_future_table->load(&reader) == false) {
9175 QString msg_text = reader.errorString();
9176 QMessageBox::critical(this, tr("Error reading table from project file"), msg_text);
9177 }
9178 if (reader.hasWarnings()) {
9179 QString msg_text =
9180 tr("The following problems occured when loading the project file:\n");
9181 QStringList warnings = reader.warningStrings();
9182 foreach (QString str, warnings)
9183 msg_text += str + "\n";
9184 QMessageBox::warning(this, tr("Project loading partly failed"), msg_text);
9185 }
9186 w->setBirthDate(QLocale().toString(w->d_future_table->creationTime()));
9187
9188 s = stream.readLine();
9189 restoreWindowGeometry(app, w, s);
9190
9191 s = stream.readLine(); // </table>
9192
9193 activateSubWindow(w);
9194 return w;
9195 }
9196 }
9197
openTableStatistics(const QStringList & flist)9198 TableStatistics *ApplicationWindow::openTableStatistics(const QStringList &flist)
9199 {
9200 QStringList::const_iterator line = flist.begin();
9201
9202 QStringList list = (*line++).split("\t");
9203 QString caption = list[0];
9204
9205 QList<int> targets;
9206 for (int i = 1; i <= (*line).count('\t'); i++)
9207 targets << (*line).section('\t', i, i).toInt();
9208
9209 TableStatistics *w = newTableStatistics(table(list[1]),
9210 list[2] == "row" ? TableStatistics::StatRow
9211 : TableStatistics::StatColumn,
9212 targets, caption);
9213
9214 setListViewDate(caption, list[3]);
9215 w->setBirthDate(list[3]);
9216
9217 for (line++; line != flist.end(); line++) {
9218 QStringList fields = (*line).split("\t");
9219 if (fields[0] == "geometry") {
9220 restoreWindowGeometry(this, w, *line);
9221 } else if (fields[0] == "header") {
9222 fields.pop_front();
9223 if (d_file_version >= 78)
9224 w->importV0x0001XXHeader(fields);
9225 else {
9226 w->setColPlotDesignation(list[4].toInt(), SciDAVis::X);
9227 w->setColPlotDesignation(list[6].toInt(), SciDAVis::Y);
9228 w->setHeader(fields);
9229 }
9230 } else if (fields[0] == "ColWidth") {
9231 fields.pop_front();
9232 w->setColWidths(fields);
9233 } else if (fields[0] == "com") { // legacy code
9234 w->setCommands(*line);
9235 } else if (fields[0] == "<com>") {
9236 for (line++; line != flist.end() && *line != "</com>"; line++) {
9237 int col = (*line).mid(9, (*line).length() - 11).toInt();
9238 QString formula;
9239 for (line++; line != flist.end() && *line != "</col>"; line++)
9240 formula += *line + "\n";
9241 formula.truncate(formula.length() - 1);
9242 w->setCommand(col, formula);
9243 }
9244 } else if (fields[0] == "ColType") { // d_file_version > 65
9245 fields.pop_front();
9246 w->setColumnTypes(fields);
9247 } else if (fields[0] == "Comments") { // d_file_version > 71
9248 fields.pop_front();
9249 w->setColComments(fields);
9250 } else if (fields[0] == "WindowLabel") { // d_file_version > 71
9251 w->setWindowLabel(fields[1]);
9252 w->setCaptionPolicy((MyWidget::CaptionPolicy)fields[2].toInt());
9253 setListViewLabel(w->name(), fields[1]);
9254 }
9255 }
9256 return w;
9257 }
9258
openGraph(ApplicationWindow * app,MultiLayer * plot,const QStringList & list)9259 Graph *ApplicationWindow::openGraph(ApplicationWindow *app, MultiLayer *plot,
9260 const QStringList &list)
9261 {
9262 Graph *ag = 0;
9263 int curveID = 0;
9264 for (int j = 0; j < (int)list.count() - 1; j++) {
9265 QString s = list[j];
9266 if (s.contains("ggeometry")) {
9267 QStringList fList = s.split("\t");
9268 ag = (Graph *)plot->addLayer(fList[1].toInt(), fList[2].toInt(), fList[3].toInt(),
9269 fList[4].toInt());
9270 ag->blockSignals(true);
9271 ag->enableAutoscaling(autoscale2DPlots);
9272 } else if (s.left(10) == "Background") {
9273 QStringList fList = s.split("\t");
9274 QColor c = QColor(COLORVALUE(fList[1]));
9275 if (fList.count() == 3)
9276 c.setAlpha(fList[2].toInt());
9277 ag->setBackgroundColor(c);
9278 } else if (s.startsWith("Margin")) {
9279 QStringList fList = s.split("\t");
9280 ag->plotWidget()->setMargin(fList[1].toInt());
9281 } else if (s.startsWith("Border")) {
9282 QStringList fList = s.split("\t");
9283 ag->setFrame(fList[1].toInt(), QColor(COLORVALUE(fList[2])));
9284 } else if (s.contains("EnabledAxes")) {
9285 QStringList fList = s.split("\t");
9286 ag->enableAxes(fList);
9287 } else if (s.contains("AxesBaseline")) {
9288 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
9289 QStringList fList = s.split("\t", Qt::SkipEmptyParts);
9290 #else
9291 QStringList fList = s.split("\t", QString::SkipEmptyParts);
9292 #endif
9293 ag->setAxesBaseline(fList);
9294 } else if (s.contains("EnabledTicks")) { // version < 0.8.6
9295 QStringList fList = s.split("\t");
9296 fList.pop_front();
9297 fList.replaceInStrings("-1", "3");
9298 ag->setMajorTicksType(fList);
9299 ag->setMinorTicksType(fList);
9300 } else if (s.contains("MajorTicks")) { // version >= 0.8.6
9301 QStringList fList = s.split("\t");
9302 fList.pop_front();
9303 ag->setMajorTicksType(fList);
9304 } else if (s.contains("MinorTicks")) { // version >= 0.8.6
9305 QStringList fList = s.split("\t");
9306 fList.pop_front();
9307 ag->setMinorTicksType(fList);
9308 } else if (s.contains("TicksLength")) {
9309 QStringList fList = s.split("\t");
9310 ag->setTicksLength(fList[1].toInt(), fList[2].toInt());
9311 } else if (s.contains("EnabledTickLabels")) {
9312 QStringList fList = s.split("\t");
9313 fList.pop_front();
9314 ag->setEnabledTickLabels(fList);
9315 } else if (s.contains("AxesColors")) {
9316 QStringList fList = s.split("\t");
9317 fList.pop_front();
9318 ag->setAxesColors(fList);
9319 } else if (s.contains("AxesNumberColors")) {
9320 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
9321 QStringList fList = s.split("\t", Qt::KeepEmptyParts);
9322 #else
9323 QStringList fList = s.split("\t", QString::KeepEmptyParts);
9324 #endif
9325 fList.pop_front();
9326 ag->setAxesNumColors(fList);
9327 } else if (s.left(5) == "grid\t") {
9328 ag->plotWidget()->grid()->load(s.split("\t"));
9329 } else if (s.startsWith("<Antialiasing>") && s.endsWith("</Antialiasing>")) {
9330 bool antialiasing = s.remove("<Antialiasing>").remove("</Antialiasing>").toInt();
9331 ag->setAntialiasing(antialiasing, false);
9332 } else if (s.contains("PieCurve")) {
9333 QStringList curve = s.split("\t");
9334 if (!app->renamedTables.isEmpty()) {
9335 QString caption = (curve[1]).left((curve[1]).indexOf("_", 0));
9336 if (app->renamedTables.contains(caption)) { // modify the name of the curve
9337 // according to the new table name
9338 int index = app->renamedTables.indexOf(caption);
9339 QString newCaption = app->renamedTables[++index];
9340 curve.replaceInStrings(caption + "_", newCaption + "_");
9341 }
9342 }
9343 QPen pen = QPen(QColor(COLORVALUE(curve[3])), curve[2].toInt(),
9344 Graph::getPenStyle(curve[4]));
9345
9346 Table *table = app->table(curve[1]);
9347 if (table) {
9348 int startRow = 0;
9349 int endRow = table->numRows() - 1;
9350 int first_color = curve[7].toInt();
9351 bool visible = true;
9352 if (d_file_version >= 90) {
9353 startRow = curve[8].toInt();
9354 endRow = curve[9].toInt();
9355 visible = ((curve.last() == "1") ? true : false);
9356 }
9357
9358 if (d_file_version <= 89)
9359 first_color = convertOldToNewColorIndex(first_color);
9360
9361 ag->plotPie(table, curve[1], pen, curve[5].toInt(), curve[6].toInt(), first_color,
9362 startRow, endRow, visible);
9363 }
9364 } else if (s.left(6) == "curve\t") {
9365 bool curve_loaded = false; // Graph::insertCurve may fail
9366 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
9367 QStringList curve = s.split("\t", Qt::KeepEmptyParts);
9368 #else
9369 QStringList curve = s.split("\t", QString::KeepEmptyParts);
9370 #endif
9371 int s_offset = 0;
9372 if (curve.count() > 14) {
9373 if (!app->renamedTables.isEmpty()) {
9374 QString caption = (curve[2]).left((curve[2]).indexOf("_", 0));
9375
9376 if (app->renamedTables.contains(caption)) { // modify the name of the curve
9377 // according to the new table name
9378 int index = app->renamedTables.indexOf(caption);
9379 QString newCaption = app->renamedTables[++index];
9380 curve.replaceInStrings(caption + "_", newCaption + "_");
9381 }
9382 }
9383
9384 CurveLayout cl;
9385 cl.connectType = curve[4].toInt();
9386 cl.lCol = COLORUINT(curve[5]);
9387 if (d_file_version <= 89)
9388 cl.lCol = convertOldToNewColorIndex(cl.lCol);
9389 cl.lStyle = curve[6].toInt();
9390 cl.lWidth = curve[7].toInt();
9391 cl.sSize = curve[8].toInt();
9392 if (d_file_version <= 78)
9393 cl.sType = Graph::obsoleteSymbolStyle(curve[9].toInt());
9394 else
9395 cl.sType = curve[9].toInt();
9396
9397 cl.symCol = COLORUINT(curve[10]);
9398 if (d_file_version <= 89)
9399 cl.symCol = convertOldToNewColorIndex(cl.symCol);
9400 if (curve[11] == "-1")
9401 cl.symbolFill = false;
9402 else {
9403 cl.symbolFill = true;
9404 cl.fillCol = COLORUINT(curve[11]);
9405 }
9406 if (d_file_version <= 89)
9407 cl.fillCol = convertOldToNewColorIndex(cl.fillCol);
9408 cl.filledArea = curve[12].toInt();
9409 cl.aCol = COLORUINT(curve[13]);
9410 if (d_file_version <= 89)
9411 cl.aCol = convertOldToNewColorIndex(cl.aCol);
9412 cl.aStyle = curve[14].toInt();
9413 if (curve.count() < 16)
9414 cl.penWidth = cl.lWidth;
9415 else if ((d_file_version >= 79) && (curve[3].toInt() == Graph::Box)) {
9416 cl.penWidth = curve[15].toInt();
9417 s_offset++;
9418 } else if ((d_file_version >= 78) && (curve[3].toInt() <= Graph::LineSymbols)) {
9419 cl.penWidth = curve[15].toInt();
9420 s_offset++;
9421 } else
9422 cl.penWidth = cl.lWidth;
9423 if (d_file_version >= 0x011800) // 1.24.0
9424 {
9425 // custom dash pattern
9426 cl.lCapStyle = curve[15 + s_offset].toInt();
9427 cl.lJoinStyle = curve[16 + s_offset].toInt();
9428 cl.lCustomDash = curve[17 + s_offset];
9429 s_offset += 3;
9430 }
9431
9432 Table *w = app->table(curve[2]);
9433 if (w) {
9434 int plotType = curve[3].toInt();
9435 if (curve.count() > (21 + s_offset)
9436 && (plotType == Graph::VectXYXY || plotType == Graph::VectXYAM)) {
9437 QStringList colsList;
9438 colsList << curve[2];
9439 colsList << curve[20 + s_offset];
9440 colsList << curve[21 + s_offset];
9441 if (d_file_version < 72)
9442 colsList.prepend(w->colName(curve[1].toInt()));
9443 else
9444 colsList.prepend(curve[1]);
9445
9446 int startRow = 0;
9447 int endRow = -1;
9448 if (d_file_version >= 90) {
9449 startRow = curve[curve.count() - 3].toInt();
9450 endRow = curve[curve.count() - 2].toInt();
9451 }
9452
9453 ag->plotVectorCurve(w, colsList, plotType, startRow, endRow);
9454 curve_loaded = true;
9455
9456 if (d_file_version <= 77) {
9457 int temp_index = convertOldToNewColorIndex(curve[15].toInt());
9458 ag->updateVectorsLayout(curveID, ColorButton::color(temp_index),
9459 curve[16].toInt(), curve[17].toInt(),
9460 curve[18].toInt(), curve[19].toInt(), 0,
9461 curve[20], curve[21]);
9462 } else {
9463 if (plotType == Graph::VectXYXY)
9464 ag->updateVectorsLayout(
9465 curveID, curve[15 + s_offset], curve[16 + s_offset].toInt(),
9466 curve[17 + s_offset].toInt(), curve[18 + s_offset].toInt(),
9467 curve[19 + s_offset].toInt(), 0);
9468 else if (curve.count() > 22 + s_offset)
9469 ag->updateVectorsLayout(
9470 curveID, curve[15 + s_offset], curve[16 + s_offset].toInt(),
9471 curve[17 + s_offset].toInt(), curve[18 + s_offset].toInt(),
9472 curve[19 + s_offset].toInt(), curve[22 + s_offset].toInt());
9473 }
9474 } else if (plotType == Graph::Box) {
9475 ag->openBoxDiagram(w, curve, d_file_version);
9476 curve_loaded = true;
9477 } else if (plotType == Graph::Histogram && curve.count() > 19) {
9478 if (d_file_version < 90)
9479 curve_loaded = ag->plotHistogram(w, QStringList() << curve[2]);
9480 else
9481 curve_loaded = ag->plotHistogram(w, QStringList() << curve[2],
9482 curve[curve.count() - 3].toInt(),
9483 curve[curve.count() - 2].toInt());
9484 if (curve_loaded) {
9485 QwtHistogram *h = (QwtHistogram *)ag->curve(curveID);
9486 if (d_file_version <= 76)
9487 h->setBinning(curve[16].toInt(), curve[17].toDouble(),
9488 curve[18].toDouble(), curve[19].toDouble());
9489 else if (curve.count() > 20 + s_offset)
9490 h->setBinning(curve[17 + s_offset].toInt(),
9491 curve[18 + s_offset].toDouble(),
9492 curve[19 + s_offset].toDouble(),
9493 curve[20 + s_offset].toDouble());
9494 h->loadData();
9495 }
9496 } else {
9497 if (d_file_version < 72)
9498 curve_loaded = ag->insertCurve(w, curve[1].toInt(), curve[2], plotType);
9499 else if (d_file_version < 90)
9500 curve_loaded = ag->insertCurve(w, curve[1], curve[2], plotType);
9501 else {
9502 int startRow = curve[curve.count() - 3].toInt();
9503 int endRow = curve[curve.count() - 2].toInt();
9504 curve_loaded = ag->insertCurve(w, curve[1], curve[2], plotType,
9505 startRow, endRow);
9506 }
9507 }
9508
9509 if (curve_loaded
9510 && (plotType == Graph::VerticalBars || plotType == Graph::HorizontalBars
9511 || plotType == Graph::Histogram)) {
9512 if (d_file_version <= 76 && curve.count() > 15)
9513 ag->setBarsGap(curveID, curve[15].toInt(), 0);
9514 else if (curve.count() > (16 + s_offset))
9515 ag->setBarsGap(curveID, curve[15 + s_offset].toInt(),
9516 curve[16 + s_offset].toInt());
9517 }
9518 if (curve_loaded)
9519 ag->updateCurveLayout(curveID, &cl);
9520 if (d_file_version >= 88) {
9521 QwtPlotCurve *c = ag->curve(curveID);
9522 if (c && c->rtti() == QwtPlotItem::Rtti_PlotCurve) {
9523 if (d_file_version < 90)
9524 c->setAxis(curve[curve.count() - 2].toInt(),
9525 curve[curve.count() - 1].toInt());
9526 else {
9527 c->setAxis(curve[curve.count() - 5].toInt(),
9528 curve[curve.count() - 4].toInt());
9529 c->setVisible(curve.last().toInt());
9530 }
9531 }
9532 }
9533 }
9534 if (curve_loaded)
9535 curveID++;
9536 }
9537 } else if (s.contains("FunctionCurve")) {
9538 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
9539 QStringList curve = s.split("\t", Qt::KeepEmptyParts);
9540 #else
9541 QStringList curve = s.split("\t", QString::KeepEmptyParts);
9542 #endif
9543 CurveLayout cl;
9544 cl.connectType = curve[6].toInt();
9545 cl.lCol = COLORUINT(curve[7]);
9546 cl.lStyle = curve[8].toInt();
9547 cl.lWidth = curve[9].toInt();
9548 cl.sSize = curve[10].toInt();
9549 cl.sType = curve[11].toInt();
9550 cl.symCol = COLORUINT(curve[12]);
9551 if (curve[13] == "-1")
9552 cl.symbolFill = false;
9553 else {
9554 cl.symbolFill = true;
9555 cl.fillCol = COLORUINT(curve[13]);
9556 }
9557 cl.filledArea = curve[14].toInt();
9558 cl.aCol = COLORUINT(curve[15]);
9559 cl.aStyle = curve[16].toInt();
9560 int current_index = 17;
9561 if (curve.count() < 16)
9562 cl.penWidth = cl.lWidth;
9563 else if ((d_file_version >= 79) && (curve[5].toInt() == Graph::Box)) {
9564 cl.penWidth = curve[17].toInt();
9565 current_index++;
9566 } else if ((d_file_version >= 78) && (curve[5].toInt() <= Graph::LineSymbols)) {
9567 cl.penWidth = curve[17].toInt();
9568 current_index++;
9569 } else
9570 cl.penWidth = cl.lWidth;
9571
9572 if (d_file_version >= 0x011800) // 1.24.0
9573 {
9574 // skeep capStyle, joinStyle and custom dash pattern values
9575 current_index += 3;
9576 }
9577
9578 QStringList func_spec;
9579 func_spec << curve[1];
9580
9581 j++;
9582 while (list[j] == "<formula>") { // d_file_version >= 0x000105
9583 QString formula;
9584 for (j++; list[j] != "</formula>"; j++)
9585 formula += list[j] + "\n";
9586 func_spec << formula;
9587 j++;
9588 }
9589 j--;
9590
9591 if (ag->insertFunctionCurve(app, func_spec, curve[2].toInt(), d_file_version)) {
9592 ag->setCurveType(curveID, (Graph::CurveType)curve[5].toInt(), false);
9593 ag->updateCurveLayout(curveID, &cl);
9594 if (d_file_version >= 88) {
9595 QwtPlotCurve *c = ag->curve(curveID);
9596 if (c) {
9597 if (current_index + 1 < curve.size())
9598 c->setAxis(curve[current_index].toInt(),
9599 curve[current_index + 1].toInt());
9600 if (d_file_version >= 90 && current_index + 2 < curve.size())
9601 c->setVisible(curve.last().toInt());
9602 else
9603 c->setVisible(true);
9604 }
9605 }
9606 if (ag->curve(curveID))
9607 curveID++;
9608 }
9609 } else if (s.contains("ErrorBars")) {
9610 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
9611 QStringList curve = s.split("\t", Qt::SkipEmptyParts);
9612 #else
9613 QStringList curve = s.split("\t", QString::SkipEmptyParts);
9614 #endif
9615 Table *w = app->table(curve[3]);
9616 Table *errTable = app->table(curve[4]);
9617 if (w && errTable) {
9618 ag->addErrorBars(curve[2], curve[3], errTable, curve[4], curve[1].toInt(),
9619 curve[5].toInt(), curve[6].toInt(), QColor(COLORVALUE(curve[7])),
9620 curve[8].toInt(), curve[10].toInt(), curve[9].toInt());
9621 }
9622 curveID++;
9623 } else if (s == "<spectrogram>") {
9624 curveID++;
9625 QStringList lst;
9626 while (s != "</spectrogram>") {
9627 s = list[++j];
9628 lst << s;
9629 }
9630 lst.pop_back();
9631 ag->restoreSpectrogram(app, lst);
9632 } else if (s.left(6) == "scale\t") {
9633 QStringList scl = s.split("\t");
9634 scl.pop_front();
9635 if (d_file_version < 88) {
9636 double step = scl[2].toDouble();
9637 if (scl[5] == "0")
9638 step = 0.0;
9639 ag->setScale(QwtPlot::xBottom, scl[0].toDouble(), scl[1].toDouble(), step,
9640 scl[3].toInt(), scl[4].toInt(), scl[6].toInt(), bool(scl[7].toInt()));
9641 ag->setScale(QwtPlot::xTop, scl[0].toDouble(), scl[1].toDouble(), step,
9642 scl[3].toInt(), scl[4].toInt(), scl[6].toInt(), bool(scl[7].toInt()));
9643
9644 step = scl[10].toDouble();
9645 if (scl[13] == "0")
9646 step = 0.0;
9647 ag->setScale(QwtPlot::yLeft, scl[8].toDouble(), scl[9].toDouble(), step,
9648 scl[11].toInt(), scl[12].toInt(), scl[14].toInt(),
9649 bool(scl[15].toInt()));
9650 ag->setScale(QwtPlot::yRight, scl[8].toDouble(), scl[9].toDouble(), step,
9651 scl[11].toInt(), scl[12].toInt(), scl[14].toInt(),
9652 bool(scl[15].toInt()));
9653 } else
9654 ag->setScale(scl[0].toInt(), scl[1].toDouble(), scl[2].toDouble(),
9655 scl[3].toDouble(), scl[4].toInt(), scl[5].toInt(), scl[6].toInt(),
9656 bool(scl[7].toInt()));
9657 } else if (s.contains("PlotTitle")) {
9658 QStringList fList = s.split("\t");
9659 ag->setTitle(fList[1]);
9660 ag->setTitleColor(QColor(COLORVALUE(fList[2])));
9661 ag->setTitleAlignment(fList[3].toInt());
9662 } else if (s.contains("TitleFont")) {
9663 QStringList fList = s.split("\t");
9664 QFont fnt = QFont(fList[1], fList[2].toInt(), fList[3].toInt(), fList[4].toInt());
9665 fnt.setUnderline(fList[5].toInt());
9666 fnt.setStrikeOut(fList[6].toInt());
9667 ag->setTitleFont(fnt);
9668 } else if (s.contains("AxesTitles")) {
9669 QStringList legend = s.split("\t");
9670 legend.pop_front();
9671 for (int i = 0; i < 4; i++) {
9672 if (legend.count() > i)
9673 ag->setAxisTitle(Graph::mapToQwtAxis(i), legend[i]);
9674 }
9675 } else if (s.contains("AxesTitleColors")) {
9676 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
9677 QStringList colors = s.split("\t", Qt::SkipEmptyParts);
9678 #else
9679 QStringList colors = s.split("\t", QString::SkipEmptyParts);
9680 #endif
9681 ag->setAxesTitleColor(colors);
9682 } else if (s.contains("AxesTitleAlignment")) {
9683 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
9684 QStringList align = s.split("\t", Qt::SkipEmptyParts);
9685 #else
9686 QStringList align = s.split("\t", QString::SkipEmptyParts);
9687 #endif
9688 ag->setAxesTitlesAlignment(align);
9689 } else if (s.contains("ScaleFont")) {
9690 QStringList fList = s.split("\t");
9691 QFont fnt = QFont(fList[1], fList[2].toInt(), fList[3].toInt(), fList[4].toInt());
9692 fnt.setUnderline(fList[5].toInt());
9693 fnt.setStrikeOut(fList[6].toInt());
9694
9695 int axis = (fList[0].right(1)).toInt();
9696 ag->setAxisTitleFont(axis, fnt);
9697 } else if (s.contains("AxisFont")) {
9698 QStringList fList = s.split("\t");
9699 QFont fnt = QFont(fList[1], fList[2].toInt(), fList[3].toInt(), fList[4].toInt());
9700 fnt.setUnderline(fList[5].toInt());
9701 fnt.setStrikeOut(fList[6].toInt());
9702
9703 int axis = (fList[0].right(1)).toInt();
9704 ag->setAxisFont(axis, fnt);
9705 } else if (s.contains("AxesFormulas")) {
9706 QStringList fList = s.split("\t");
9707 fList.removeAll(fList.first());
9708 ag->setAxesFormulas(fList);
9709 } else if (s.startsWith("<AxisFormula ")) {
9710 int pos = s.mid(18, s.length() - 20).toInt();
9711 QString formula;
9712 for (j++; j < (int)list.count() && list[j] != "</AxisFormula>"; j++)
9713 formula += list[j] + "\n";
9714 formula.truncate(formula.length() - 1);
9715 ag->setAxisFormula(pos, formula);
9716 } else if (s.contains("LabelsFormat")) {
9717 QStringList fList = s.split("\t");
9718 fList.pop_front();
9719 ag->setLabelsNumericFormat(fList);
9720 } else if (s.contains("LabelsRotation")) {
9721 QStringList fList = s.split("\t");
9722 ag->setAxisLabelRotation(QwtPlot::xBottom, fList[1].toInt());
9723 ag->setAxisLabelRotation(QwtPlot::xTop, fList[2].toInt());
9724 } else if (s.contains("DrawAxesBackbone")) {
9725 QStringList fList = s.split("\t");
9726 ag->loadAxesOptions(fList[1]);
9727 } else if (s.contains("AxesLineWidth")) {
9728 QStringList fList = s.split("\t");
9729 ag->loadAxesLinewidth(fList[1].toInt());
9730 } else if (s.contains("CanvasFrame")) {
9731 QStringList list = s.split("\t");
9732 ag->drawCanvasFrame(list);
9733 } else if (s.contains("CanvasBackground")) {
9734 QStringList list = s.split("\t");
9735 QColor c = QColor(COLORVALUE(list[1]));
9736 if (list.count() == 3)
9737 c.setAlpha(list[2].toInt());
9738 ag->setCanvasBackground(c);
9739 } else if (s.contains("Legend")) { // version <= 0.8.9
9740 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
9741 QStringList fList = s.split("\t", Qt::KeepEmptyParts);
9742 #else
9743 QStringList fList = s.split("\t", QString::KeepEmptyParts);
9744 #endif
9745 ag->insertLegend(fList, d_file_version);
9746 } else if (s.startsWith("<legend>") && s.endsWith("</legend>")) {
9747 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
9748 QStringList fList = s.remove("</legend>").split("\t", Qt::KeepEmptyParts);
9749 #else
9750 QStringList fList = s.remove("</legend>").split("\t", QString::KeepEmptyParts);
9751 #endif
9752 ag->insertLegend(fList, d_file_version);
9753 } else if (s.contains("textMarker")) { // version <= 0.8.9
9754 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
9755 QStringList fList = s.split("\t", Qt::KeepEmptyParts);
9756 #else
9757 QStringList fList = s.split("\t", QString::KeepEmptyParts);
9758 #endif
9759 ag->insertTextMarker(fList, d_file_version);
9760 } else if (s.startsWith("<text>") && s.endsWith("</text>")) {
9761 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
9762 QStringList fList = s.remove("</text>").split("\t", Qt::KeepEmptyParts);
9763 #else
9764 QStringList fList = s.remove("</text>").split("\t", QString::KeepEmptyParts);
9765 #endif
9766 ag->insertTextMarker(fList, d_file_version);
9767 } else if (s.contains("lineMarker")) { // version <= 0.8.9
9768 QStringList fList = s.split("\t");
9769 ag->addArrow(fList, d_file_version);
9770 } else if (s.startsWith("<line>") && s.endsWith("</line>")) {
9771 QStringList fList = s.remove("</line>").split("\t");
9772 ag->addArrow(fList, d_file_version);
9773 } else if (s.contains("ImageMarker")
9774 || (s.startsWith("<image>") && s.endsWith("</image>"))) {
9775 QStringList fList = s.remove("</image>").split("\t");
9776 ag->insertImageMarker(fList, d_file_version);
9777 } else if (s.contains("AxisType")) {
9778 QStringList fList = s.split("\t");
9779 if (fList.size() >= 5)
9780 for (int i = 0; i < 4; i++) {
9781 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
9782 QStringList lst = fList[i + 1].split(";", Qt::SkipEmptyParts);
9783 #else
9784 QStringList lst = fList[i + 1].split(";", QString::SkipEmptyParts);
9785 #endif
9786 if (lst.size() < 2)
9787 continue;
9788 Graph::AxisType format = static_cast<Graph::AxisType>(lst[0].toInt());
9789 switch (format) {
9790 case Graph::AxisType::Day:
9791 ag->setLabelsDayFormat(i, lst[1].toInt());
9792 break;
9793 case Graph::AxisType::Month:
9794 ag->setLabelsMonthFormat(i, lst[1].toInt());
9795 break;
9796 case Graph::AxisType::Time:
9797 case Graph::AxisType::Date:
9798 case Graph::AxisType::DateTime:
9799 ag->setLabelsDateTimeFormat(i, format, lst[1] + ";" + lst[2]);
9800 break;
9801 case Graph::AxisType::Txt:
9802 ag->setLabelsTextFormat(i, app->table(lst[1]), lst[1]);
9803 break;
9804 case Graph::AxisType::ColHeader:
9805 ag->setLabelsColHeaderFormat(i, app->table(lst[1]));
9806 break;
9807 }
9808 }
9809 } else if (d_file_version < 69 && s.contains("AxesTickLabelsCol")) {
9810 QStringList fList = s.split("\t");
9811 if (fList.size() >= 5) {
9812 const QList<Graph::AxisType> &axesTypes = ag->axesType();
9813 for (int i = 0; i < 4; i++) {
9814 switch (axesTypes[i]) {
9815 case Graph::AxisType::Txt:
9816 ag->setLabelsTextFormat(i, app->table(fList[i + 1]), fList[i + 1]);
9817 break;
9818 case Graph::AxisType::ColHeader:
9819 ag->setLabelsColHeaderFormat(i, app->table(fList[i + 1]));
9820 break;
9821 }
9822 }
9823 }
9824 }
9825 }
9826 ag->replot();
9827 if (ag->isPiePlot()) {
9828 QwtPieCurve *c = (QwtPieCurve *)ag->curve(0);
9829 if (c)
9830 c->updateBoundingRect();
9831 }
9832
9833 ag->blockSignals(false);
9834 ag->setIgnoreResizeEvents(!app->autoResizeLayers);
9835 ag->setAutoscaleFonts(app->autoScaleFonts);
9836 ag->setTextMarkerDefaults(app->legendFrameStyle, app->plotLegendFont, app->legendTextColor,
9837 app->legendBackground);
9838 ag->setArrowDefaults(app->defaultArrowLineWidth, app->defaultArrowColor,
9839 app->defaultArrowLineStyle, app->defaultArrowHeadLength,
9840 app->defaultArrowHeadAngle, app->defaultArrowHeadFill);
9841 return ag;
9842 }
9843
openSurfacePlot(ApplicationWindow * app,const QStringList & lst)9844 Graph3D *ApplicationWindow::openSurfacePlot(ApplicationWindow *app, const QStringList &lst)
9845 {
9846 QStringList fList = lst[0].split("\t");
9847 QString caption = fList[0];
9848 QString date = fList[1];
9849 if (date.isEmpty())
9850 date = QLocale().toString(QDateTime::currentDateTime());
9851
9852 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
9853 fList = lst[2].split("\t", Qt::SkipEmptyParts);
9854 #else
9855 fList = lst[2].split("\t", QString::SkipEmptyParts);
9856 #endif
9857 Graph3D *plot = 0;
9858
9859 if (fList[1].endsWith("(Y)", Qt::CaseSensitive)) // Ribbon plot
9860 plot = app->dataPlot3D(caption, fList[1], fList[2].toDouble(), fList[3].toDouble(),
9861 fList[4].toDouble(), fList[5].toDouble(), fList[6].toDouble(),
9862 fList[7].toDouble());
9863 else if (fList[1].contains("(Z)", Qt::CaseSensitive))
9864 plot = app->dataPlotXYZ(caption, fList[1], fList[2].toDouble(), fList[3].toDouble(),
9865 fList[4].toDouble(), fList[5].toDouble(), fList[6].toDouble(),
9866 fList[7].toDouble());
9867 else if (fList[1].startsWith("matrix<", Qt::CaseSensitive)
9868 && fList[1].endsWith(">", Qt::CaseInsensitive))
9869 plot = app->openMatrixPlot3D(caption, fList[1], fList[2].toDouble(), fList[3].toDouble(),
9870 fList[4].toDouble(), fList[5].toDouble(), fList[6].toDouble(),
9871 fList[7].toDouble());
9872 else
9873 plot = app->newPlot3D(caption, fList[1], fList[2].toDouble(), fList[3].toDouble(),
9874 fList[4].toDouble(), fList[5].toDouble(), fList[6].toDouble(),
9875 fList[7].toDouble());
9876
9877 if (!plot)
9878 return 0;
9879
9880 app->setListViewDate(caption, date);
9881 plot->setBirthDate(date);
9882 plot->setIgnoreFonts(true);
9883 restoreWindowGeometry(app, plot, lst[1]);
9884
9885 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
9886 fList = lst[3].split("\t", Qt::SkipEmptyParts);
9887 plot->setStyle(fList);
9888
9889 fList = lst[4].split("\t", Qt::SkipEmptyParts);
9890 plot->setGrid(fList[1].toInt());
9891
9892 fList = lst[5].split("\t");
9893 plot->setTitle(fList);
9894
9895 fList = lst[6].split("\t", Qt::SkipEmptyParts);
9896 plot->setColors(fList);
9897
9898 fList = lst[7].split("\t", Qt::SkipEmptyParts);
9899 fList.pop_front();
9900 plot->setAxesLabels(fList);
9901
9902 fList = lst[8].split("\t", Qt::SkipEmptyParts);
9903 plot->setTicks(fList);
9904
9905 fList = lst[9].split("\t", Qt::SkipEmptyParts);
9906 plot->setTickLengths(fList);
9907
9908 fList = lst[10].split("\t", Qt::SkipEmptyParts);
9909 plot->setOptions(fList);
9910
9911 fList = lst[11].split("\t", Qt::SkipEmptyParts);
9912 plot->setNumbersFont(fList);
9913
9914 fList = lst[12].split("\t", Qt::SkipEmptyParts);
9915 plot->setXAxisLabelFont(fList);
9916
9917 fList = lst[13].split("\t", Qt::SkipEmptyParts);
9918 plot->setYAxisLabelFont(fList);
9919
9920 fList = lst[14].split("\t", Qt::SkipEmptyParts);
9921 plot->setZAxisLabelFont(fList);
9922
9923 fList = lst[15].split("\t", Qt::SkipEmptyParts);
9924 plot->setRotation(fList[1].toDouble(), fList[2].toDouble(), fList[3].toDouble());
9925
9926 fList = lst[16].split("\t", Qt::SkipEmptyParts);
9927 plot->setZoom(fList[1].toDouble());
9928
9929 fList = lst[17].split("\t", Qt::SkipEmptyParts);
9930 plot->setScale(fList[1].toDouble(), fList[2].toDouble(), fList[3].toDouble());
9931
9932 fList = lst[18].split("\t", Qt::SkipEmptyParts);
9933 plot->setShift(fList[1].toDouble(), fList[2].toDouble(), fList[3].toDouble());
9934
9935 fList = lst[19].split("\t", Qt::SkipEmptyParts);
9936 plot->setMeshLineWidth(fList[1].toInt());
9937 #else
9938 fList = lst[3].split("\t", QString::SkipEmptyParts);
9939 plot->setStyle(fList);
9940
9941 fList = lst[4].split("\t", QString::SkipEmptyParts);
9942 plot->setGrid(fList[1].toInt());
9943
9944 fList = lst[5].split("\t");
9945 plot->setTitle(fList);
9946
9947 fList = lst[6].split("\t", QString::SkipEmptyParts);
9948 plot->setColors(fList);
9949
9950 fList = lst[7].split("\t", QString::SkipEmptyParts);
9951 fList.pop_front();
9952 plot->setAxesLabels(fList);
9953
9954 fList = lst[8].split("\t", QString::SkipEmptyParts);
9955 plot->setTicks(fList);
9956
9957 fList = lst[9].split("\t", QString::SkipEmptyParts);
9958 plot->setTickLengths(fList);
9959
9960 fList = lst[10].split("\t", QString::SkipEmptyParts);
9961 plot->setOptions(fList);
9962
9963 fList = lst[11].split("\t", QString::SkipEmptyParts);
9964 plot->setNumbersFont(fList);
9965
9966 fList = lst[12].split("\t", QString::SkipEmptyParts);
9967 plot->setXAxisLabelFont(fList);
9968
9969 fList = lst[13].split("\t", QString::SkipEmptyParts);
9970 plot->setYAxisLabelFont(fList);
9971
9972 fList = lst[14].split("\t", QString::SkipEmptyParts);
9973 plot->setZAxisLabelFont(fList);
9974
9975 fList = lst[15].split("\t", QString::SkipEmptyParts);
9976 plot->setRotation(fList[1].toDouble(), fList[2].toDouble(), fList[3].toDouble());
9977
9978 fList = lst[16].split("\t", QString::SkipEmptyParts);
9979 plot->setZoom(fList[1].toDouble());
9980
9981 fList = lst[17].split("\t", QString::SkipEmptyParts);
9982 plot->setScale(fList[1].toDouble(), fList[2].toDouble(), fList[3].toDouble());
9983
9984 fList = lst[18].split("\t", QString::SkipEmptyParts);
9985 plot->setShift(fList[1].toDouble(), fList[2].toDouble(), fList[3].toDouble());
9986
9987 fList = lst[19].split("\t", QString::SkipEmptyParts);
9988 plot->setMeshLineWidth(fList[1].toInt());
9989 #endif
9990
9991 if (d_file_version > 71) {
9992 fList = lst[20].split(
9993 "\t"); // using QString::SkipEmptyParts here causes a crash for empty window labels
9994 plot->setWindowLabel(fList[1]);
9995 plot->setCaptionPolicy((MyWidget::CaptionPolicy)fList[2].toInt());
9996 app->setListViewLabel(plot->name(), fList[1]);
9997 }
9998
9999 if (d_file_version >= 88) {
10000 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
10001 fList = lst[21].split("\t", Qt::SkipEmptyParts);
10002 #else
10003 fList = lst[21].split("\t", QString::SkipEmptyParts);
10004 #endif
10005 plot->setOrtho(fList[1].toInt());
10006 }
10007
10008 plot->update();
10009 plot->setIgnoreFonts(true);
10010 return plot;
10011 }
10012
copyActiveLayer()10013 void ApplicationWindow::copyActiveLayer()
10014 {
10015 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
10016 return;
10017
10018 copiedLayer = true;
10019
10020 Graph *g = ((MultiLayer *)d_workspace.activeSubWindow())->activeGraph();
10021 delete lastCopiedLayer;
10022 lastCopiedLayer = new Graph(0, 0, Qt::Widget);
10023 lastCopiedLayer->setAttribute(Qt::WA_DeleteOnClose);
10024 lastCopiedLayer->setGeometry(0, 0, g->width(), g->height());
10025 lastCopiedLayer->copy(this, g);
10026 g->copyImage();
10027 }
10028
showDataSetDialog(const QString & whichFit)10029 void ApplicationWindow::showDataSetDialog(const QString &whichFit)
10030 {
10031 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
10032 return;
10033
10034 Graph *g = ((MultiLayer *)d_workspace.activeSubWindow())->activeGraph();
10035 if (!g)
10036 return;
10037
10038 DataSetDialog *ad = new DataSetDialog(tr("Curve") + ": ", this);
10039 ad->setAttribute(Qt::WA_DeleteOnClose);
10040 ad->setGraph(g);
10041 ad->setOperationType(whichFit);
10042 ad->exec();
10043 }
10044
analyzeCurve(Graph * g,const QString & whichFit,const QString & curveTitle)10045 void ApplicationWindow::analyzeCurve(Graph *g, const QString &whichFit, const QString &curveTitle)
10046 {
10047 if (whichFit == "fitLinear" || whichFit == "fitSigmoidal" || whichFit == "fitGauss"
10048 || whichFit == "fitLorentz") {
10049 Fit *fitter = 0;
10050 if (whichFit == "fitLinear")
10051 fitter = new LinearFit(this, g);
10052 else if (whichFit == "fitSigmoidal")
10053 fitter = new SigmoidalFit(this, g);
10054 else if (whichFit == "fitGauss")
10055 fitter = new GaussFit(this, g);
10056 else if (whichFit == "fitLorentz")
10057 fitter = new LorentzFit(this, g);
10058
10059 if (fitter->setDataFromCurve(curveTitle)) {
10060 if (whichFit != "fitLinear")
10061 fitter->guessInitialValues();
10062
10063 fitter->scaleErrors(fit_scale_errors);
10064 fitter->setOutputPrecision(fit_output_precision);
10065
10066 if (whichFit == "fitLinear" && d_2_linear_fit_points)
10067 fitter->generateFunction(generateUniformFitPoints, 2);
10068 else
10069 fitter->generateFunction(generateUniformFitPoints, fitPoints);
10070 fitter->fit();
10071 if (pasteFitResultsToPlot)
10072 fitter->showLegend();
10073 delete fitter;
10074 }
10075 } else if (whichFit == "differentiate") {
10076 Differentiation *diff = new Differentiation(this, g, curveTitle);
10077 diff->run();
10078 delete diff;
10079 }
10080 }
10081
analysis(const QString & whichFit)10082 void ApplicationWindow::analysis(const QString &whichFit)
10083 {
10084 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("MultiLayer"))
10085 return;
10086
10087 Graph *g = ((MultiLayer *)d_workspace.activeSubWindow())->activeGraph();
10088 if (!g || !g->validCurvesDataSize())
10089 return;
10090
10091 QString curve_title = g->selectedCurveTitle();
10092 if (!curve_title.isNull()) {
10093 analyzeCurve(g, whichFit, curve_title);
10094 return;
10095 }
10096
10097 QStringList lst = g->analysableCurvesList();
10098 if (lst.count() == 1) {
10099 const QwtPlotCurve *c = g->curve(lst[0]);
10100 if (c)
10101 analyzeCurve(g, whichFit, lst[0]);
10102 } else
10103 showDataSetDialog(whichFit);
10104 }
10105
pickPointerCursor()10106 void ApplicationWindow::pickPointerCursor()
10107 {
10108 btnPointer->setChecked(true);
10109 }
10110
pickDataTool(QAction * action)10111 void ApplicationWindow::pickDataTool(QAction *action)
10112 {
10113 if (!action)
10114 return;
10115
10116 MultiLayer *m = qobject_cast<MultiLayer *>(d_workspace.activeSubWindow());
10117 if (!m)
10118 return;
10119
10120 Graph *g = m->activeGraph();
10121 if (!g)
10122 return;
10123
10124 g->disableTools();
10125
10126 if (action == btnCursor)
10127 showCursor();
10128 else if (action == btnSelect)
10129 showRangeSelectors();
10130 else if (action == btnPicker)
10131 showScreenReader();
10132 else if (action == btnMovePoints)
10133 movePoints();
10134 else if (action == btnRemovePoints)
10135 removePoints();
10136 else if (action == btnZoomIn)
10137 zoomIn();
10138 else if (action == btnZoomOut)
10139 zoomOut();
10140 else if (action == btnArrow)
10141 drawArrow();
10142 else if (action == btnLine)
10143 drawLine();
10144 }
10145
connectSurfacePlot(Graph3D * plot)10146 void ApplicationWindow::connectSurfacePlot(Graph3D *plot)
10147 {
10148 connect(plot, SIGNAL(showTitleBarMenu()), this, SLOT(showWindowTitleBarMenu()));
10149 connect(plot, SIGNAL(showContextMenu()), this, SLOT(showWindowContextMenu()));
10150 connect(plot, SIGNAL(showOptionsDialog()), this, SLOT(showPlot3dDialog()));
10151 connect(plot, SIGNAL(closedWindow(MyWidget *)), this, SLOT(closeWindow(MyWidget *)));
10152 connect(plot, SIGNAL(hiddenWindow(MyWidget *)), this, SLOT(hideWindow(MyWidget *)));
10153 connect(plot, SIGNAL(statusChanged(MyWidget *)), this, SLOT(updateWindowStatus(MyWidget *)));
10154 connect(plot, SIGNAL(modified()), this, SIGNAL(modified()));
10155 connect(plot, SIGNAL(custom3DActions(MyWidget *)), this, SLOT(custom3DActions(MyWidget *)));
10156
10157 plot->askOnCloseEvent(confirmClosePlot3D);
10158 }
10159
connectMultilayerPlot(MultiLayer * g)10160 void ApplicationWindow::connectMultilayerPlot(MultiLayer *g)
10161 {
10162 connect(g, SIGNAL(showTitleBarMenu()), this, SLOT(showWindowTitleBarMenu()));
10163 connect(g, SIGNAL(showTextDialog()), this, SLOT(showTextDialog()));
10164 connect(g, SIGNAL(showPlotDialog(int)), this, SLOT(showPlotDialog(int)));
10165 connect(g, SIGNAL(showScaleDialog(int)), this, SLOT(showScalePageFromAxisDialog(int)));
10166 connect(g, SIGNAL(showAxisDialog(int)), this, SLOT(showAxisPageFromAxisDialog(int)));
10167 connect(g, SIGNAL(showCurveContextMenu(int)), this, SLOT(showCurveContextMenu(int)));
10168 connect(g, SIGNAL(showWindowContextMenu()), this, SLOT(showWindowContextMenu()));
10169 connect(g, SIGNAL(showCurvesDialog()), this, SLOT(showCurvesDialog()));
10170 connect(g, SIGNAL(drawLineEnded(bool)), btnPointer, SLOT(setChecked(bool)));
10171 connect(g, SIGNAL(drawTextOff()), this, SLOT(disableAddText()));
10172 connect(g, SIGNAL(showXAxisTitleDialog()), this, SLOT(showXAxisTitleDialog()));
10173 connect(g, SIGNAL(showYAxisTitleDialog()), this, SLOT(showYAxisTitleDialog()));
10174 connect(g, SIGNAL(showRightAxisTitleDialog()), this, SLOT(showRightAxisTitleDialog()));
10175 connect(g, SIGNAL(showTopAxisTitleDialog()), this, SLOT(showTopAxisTitleDialog()));
10176 connect(g, SIGNAL(showMarkerPopupMenu()), this, SLOT(showMarkerPopupMenu()));
10177 connect(g, SIGNAL(closedWindow(MyWidget *)), this, SLOT(closeWindow(MyWidget *)));
10178 connect(g, SIGNAL(hiddenWindow(MyWidget *)), this, SLOT(hideWindow(MyWidget *)));
10179 connect(g, SIGNAL(statusChanged(MyWidget *)), this, SLOT(updateWindowStatus(MyWidget *)));
10180 connect(g, SIGNAL(cursorInfo(const QString &)), d_status_info, SLOT(setText(const QString &)));
10181 connect(g, SIGNAL(showImageDialog()), this, SLOT(showImageDialog()));
10182 connect(g, SIGNAL(createTable(const QString &, const QString &, QList<Column *>)), this,
10183 SLOT(newTable(const QString &, const QString &, QList<Column *>)));
10184 connect(g, SIGNAL(viewTitleDialog()), this, SLOT(showTitleDialog()));
10185 connect(g, SIGNAL(modifiedWindow(MyWidget *)), this, SLOT(modifiedProject(MyWidget *)));
10186 connect(g, SIGNAL(modifiedPlot()), this, SLOT(modifiedProject()));
10187 connect(g, SIGNAL(showLineDialog()), this, SLOT(showLineDialog()));
10188 connect(g, SIGNAL(showGeometryDialog()), this, SLOT(showPlotGeometryDialog()));
10189 connect(g, SIGNAL(pasteMarker()), this, SLOT(pasteSelection()));
10190 connect(g, SIGNAL(showGraphContextMenu()), this, SLOT(showGraphContextMenu()));
10191 connect(g, SIGNAL(showLayerButtonContextMenu()), this, SLOT(showLayerButtonContextMenu()));
10192 connect(g, SIGNAL(createIntensityTable(const QString &)), this,
10193 SLOT(importImage(const QString &)));
10194 connect(g, SIGNAL(setPointerCursor()), this, SLOT(pickPointerCursor()));
10195
10196 g->askOnCloseEvent(confirmClosePlot2D);
10197 }
10198
connectTable(Table * w)10199 void ApplicationWindow::connectTable(Table *w)
10200 {
10201 connect(w, SIGNAL(showTitleBarMenu()), this, SLOT(showWindowTitleBarMenu()));
10202 connect(w, SIGNAL(statusChanged(MyWidget *)), this, SLOT(updateWindowStatus(MyWidget *)));
10203 connect(w, SIGNAL(hiddenWindow(MyWidget *)), this, SLOT(hideWindow(MyWidget *)));
10204 connect(w, SIGNAL(closedWindow(MyWidget *)), this, SLOT(closeWindow(MyWidget *)));
10205 connect(w, SIGNAL(aboutToRemoveCol(const QString &)), this,
10206 SLOT(removeCurves(const QString &)));
10207 connect(w, SIGNAL(modifiedData(Table *, const QString &)), this,
10208 SLOT(updateCurves(Table *, const QString &)));
10209 connect(w, SIGNAL(modifiedWindow(MyWidget *)), this, SLOT(modifiedProject(MyWidget *)));
10210 connect(w, SIGNAL(changedColHeader(const QString &, const QString &)), this,
10211 SLOT(updateColNames(const QString &, const QString &)));
10212
10213 #ifdef LEGACY_CODE_0_2_x
10214 connect(w->d_future_table, SIGNAL(requestRowStatistics()), this, SLOT(showRowStatistics()));
10215 connect(w->d_future_table, SIGNAL(requestColumnStatistics()), this, SLOT(showColStatistics()));
10216 #endif
10217 w->askOnCloseEvent(confirmCloseTable);
10218 }
10219
setAppColors(const QColor & wc,const QColor & pc,const QColor & tpc)10220 void ApplicationWindow::setAppColors(const QColor &wc, const QColor &pc, const QColor &tpc)
10221 {
10222 if (workspaceColor != wc) {
10223 workspaceColor = wc;
10224 d_workspace.setBackground(wc);
10225 }
10226
10227 if (panelsColor == pc && panelsTextColor == tpc)
10228 return;
10229
10230 panelsColor = pc;
10231 panelsTextColor = tpc;
10232
10233 QPalette cg;
10234 cg.setColor(QPalette::Base, QColor(panelsColor));
10235 qApp->setPalette(cg);
10236
10237 cg.setColor(QPalette::Text, QColor(panelsTextColor));
10238 cg.setColor(QPalette::WindowText, QColor(panelsTextColor));
10239 cg.setColor(QPalette::HighlightedText, QColor(panelsTextColor));
10240 lv.setPalette(cg);
10241 results->setPalette(cg);
10242 }
10243
setPlot3DOptions()10244 void ApplicationWindow::setPlot3DOptions()
10245 {
10246 QList<MyWidget *> windows = windowsList();
10247 for (int i = 0; i < int(windows.count()); i++) {
10248 if (windows.at(i)->inherits("Graph3D")) {
10249 Graph3D *g = (Graph3D *)windows.at(i);
10250 g->setSmoothMesh(smooth3DMesh);
10251 g->setOrtho(orthogonal3DPlots);
10252 g->setAutoscale(autoscale3DPlots);
10253 }
10254 }
10255 }
10256
createActions()10257 void ApplicationWindow::createActions()
10258 {
10259 actionNewProject = new QAction(QIcon(QPixmap(":/new.xpm")), tr("New &Project"), this);
10260 actionNewProject->setShortcut(tr("Ctrl+N"));
10261 connect(actionNewProject, SIGNAL(triggered()), this, SLOT(newProject()));
10262
10263 actionNewGraph = new QAction(QIcon(QPixmap(":/new_graph.xpm")), tr("New &Graph"), this);
10264 actionNewGraph->setShortcut(tr("Ctrl+G"));
10265 connect(actionNewGraph, SIGNAL(triggered()), this, SLOT(newGraph()));
10266
10267 actionNewNote = new QAction(QIcon(QPixmap(":/new_note.xpm")), tr("New &Note / Script"), this);
10268 actionNewNote->setShortcut(tr("Ctrl+ALT+N"));
10269 connect(actionNewNote, SIGNAL(triggered()), this, SLOT(newNote()));
10270
10271 actionNewTable = new QAction(QIcon(QPixmap(":/table.xpm")), tr("New &Table"), this);
10272 actionNewTable->setShortcut(tr("Ctrl+T"));
10273 connect(actionNewTable, SIGNAL(triggered()), this, SLOT(newTable()));
10274
10275 actionNewMatrix = new QAction(QIcon(QPixmap(":/new_matrix.xpm")), tr("New &Matrix"), this);
10276 actionNewMatrix->setShortcut(tr("Ctrl+M"));
10277 connect(actionNewMatrix, SIGNAL(triggered()), this, SLOT(newMatrix()));
10278
10279 actionNewFunctionPlot =
10280 new QAction(QIcon(QPixmap(":/newF.xpm")), tr("New &Function Plot"), this);
10281 actionNewFunctionPlot->setShortcut(tr("Ctrl+F"));
10282 connect(actionNewFunctionPlot, SIGNAL(triggered()), this, SLOT(functionDialog()));
10283
10284 actionNewSurfacePlot =
10285 new QAction(QIcon(QPixmap(":/newFxy.xpm")), tr("New 3D &Surface Plot"), this);
10286 actionNewSurfacePlot->setShortcut(tr("Ctrl+ALT+Z"));
10287 connect(actionNewSurfacePlot, SIGNAL(triggered()), this, SLOT(newSurfacePlot()));
10288
10289 // FIXME: "..." should be added before translating, but this would break translations
10290 actionOpen = new QAction(QIcon(QPixmap(":/fileopen.xpm")), tr("&Open") + "...", this);
10291 actionOpen->setShortcut(tr("Ctrl+O"));
10292 connect(actionOpen, SIGNAL(triggered()), this, SLOT(open()));
10293
10294 actionLoadImage = new QAction(tr("Open Image &File"), this);
10295 actionLoadImage->setShortcut(tr("Ctrl+I"));
10296 connect(actionLoadImage, SIGNAL(triggered()), this, SLOT(loadImage()));
10297
10298 actionImportImage = new QAction(tr("Import I&mage..."), this);
10299 connect(actionImportImage, SIGNAL(triggered()), this, SLOT(importImage()));
10300
10301 actionSaveProject = new QAction(QIcon(QPixmap(":/filesave.xpm")), tr("&Save Project"), this);
10302 actionSaveProject->setShortcut(tr("Ctrl+S"));
10303 connect(actionSaveProject, SIGNAL(triggered()), this, SLOT(saveProject()));
10304 savedProject();
10305
10306 actionSaveProjectAs = new QAction(tr("Save Project &As..."), this);
10307 connect(actionSaveProjectAs, SIGNAL(triggered()), this, SLOT(saveProjectAs()));
10308
10309 actionOpenTemplate =
10310 new QAction(QIcon(QPixmap(":/open_template.xpm")), tr("Open Temp&late..."), this);
10311 connect(actionOpenTemplate, SIGNAL(triggered()), this, SLOT(openTemplate()));
10312
10313 actionSaveTemplate =
10314 new QAction(QIcon(QPixmap(":/save_template.xpm")), tr("Save As &Template..."), this);
10315 connect(actionSaveTemplate, SIGNAL(triggered()), this, SLOT(saveAsTemplate()));
10316
10317 actionSaveNote = new QAction(tr("Save Note As..."), this);
10318 connect(actionSaveNote, SIGNAL(triggered()), this, SLOT(saveNoteAs()));
10319
10320 actionLoad = new QAction(QIcon(QPixmap(":/import.xpm")), tr("&Import ASCII..."), this);
10321 connect(actionLoad, SIGNAL(triggered()), this, SLOT(importASCII()));
10322
10323 actionUndo = new QAction(IconLoader::load("edit-undo"), tr("&Undo"), this);
10324 actionUndo->setShortcut(tr("Ctrl+Z"));
10325 connect(actionUndo, SIGNAL(triggered()), this, SLOT(undo()));
10326 actionUndo->setEnabled(false);
10327
10328 actionRedo = new QAction(IconLoader::load("edit-redo"), tr("&Redo"), this);
10329 actionRedo->setShortcut(tr("Ctrl+R"));
10330 connect(actionRedo, SIGNAL(triggered()), this, SLOT(redo()));
10331 actionRedo->setEnabled(false);
10332
10333 actionCopyWindow = new QAction(QIcon(QPixmap(":/duplicate.xpm")), tr("&Duplicate"), this);
10334 connect(actionCopyWindow, SIGNAL(triggered()), this, SLOT(clone()));
10335
10336 actionCutSelection = new QAction(IconLoader::load("edit-cut"), tr("Cu&t Selection"), this);
10337 actionCutSelection->setShortcut(tr("Ctrl+X"));
10338 connect(actionCutSelection, SIGNAL(triggered()), this, SLOT(cutSelection()));
10339
10340 actionCopySelection = new QAction(IconLoader::load("edit-copy"), tr("&Copy Selection"), this);
10341 actionCopySelection->setShortcut(tr("Ctrl+C"));
10342 connect(actionCopySelection, SIGNAL(triggered()), this, SLOT(copySelection()));
10343
10344 actionPasteSelection =
10345 new QAction(IconLoader::load("edit-paste"), tr("&Paste Selection"), this);
10346 actionPasteSelection->setShortcut(tr("Ctrl+V"));
10347 connect(actionPasteSelection, SIGNAL(triggered()), this, SLOT(pasteSelection()));
10348
10349 actionClearSelection =
10350 new QAction(QIcon(QPixmap(":/erase.xpm")), tr("&Delete Selection"), this);
10351 actionClearSelection->setShortcut(tr("Del", "delete key"));
10352 connect(actionClearSelection, SIGNAL(triggered()), this, SLOT(clearSelection()));
10353
10354 locktoolbar = new QAction(QIcon(QPixmap(":/unlock.xpm")), tr("&Lock Toolbars"), this);
10355 locktoolbar->setCheckable(true);
10356 connect(locktoolbar, SIGNAL(toggled(bool)), this, SLOT(lockToolbar(bool)));
10357
10358 actionShowExplorer = explorerWindow.toggleViewAction();
10359 actionShowExplorer->setIcon(QPixmap(":/folder.xpm"));
10360 actionShowExplorer->setShortcut(tr("Ctrl+E"));
10361
10362 actionShowLog = logWindow.toggleViewAction();
10363 actionShowLog->setIcon(QPixmap(":/log.xpm"));
10364
10365 actionShowHistory = new QAction(tr("Undo/Redo &History"), this);
10366 connect(actionShowHistory, SIGNAL(triggered(bool)), this, SLOT(showHistory()));
10367
10368 #ifdef SCRIPTING_CONSOLE
10369 actionShowConsole = consoleWindow.toggleViewAction();
10370 #endif
10371
10372 actionAddLayer = new QAction(QIcon(QPixmap(":/newLayer.xpm")), tr("Add La&yer"), this);
10373 actionAddLayer->setShortcut(tr("ALT+L"));
10374 connect(actionAddLayer, SIGNAL(triggered()), this, SLOT(addLayer()));
10375
10376 // FIXME: "..." should be added before translating, but this would break translations
10377 actionShowLayerDialog =
10378 new QAction(QIcon(QPixmap(":/arrangeLayers.xpm")), tr("Arran&ge Layers") + "...", this);
10379 actionShowLayerDialog->setShortcut(tr("ALT+A"));
10380 connect(actionShowLayerDialog, SIGNAL(triggered()), this, SLOT(showLayerDialog()));
10381
10382 actionAutomaticLayout =
10383 new QAction(QIcon(QPixmap(":/auto_layout.xpm")), tr("Automatic Layout"), this);
10384 connect(actionAutomaticLayout, SIGNAL(triggered()), this, SLOT(autoArrangeLayers()));
10385
10386 // FIXME: "..." should be added before translating, but this would break translations
10387 actionExportGraph = new QAction(tr("&Current") + "...", this);
10388 actionExportGraph->setShortcut(tr("Alt+G"));
10389 connect(actionExportGraph, SIGNAL(triggered()), this, SLOT(exportGraph()));
10390
10391 // FIXME: "..." should be added before translating, but this would break translations
10392 actionExportAllGraphs = new QAction(tr("&All") + "...", this);
10393 actionExportAllGraphs->setShortcut(tr("Alt+X"));
10394 connect(actionExportAllGraphs, SIGNAL(triggered()), this, SLOT(exportAllGraphs()));
10395
10396 // FIXME: "..." should be added before translating, but this would break translations
10397 actionExportPDF = new QAction(QIcon(QPixmap(":/pdf.xpm")), tr("&Export PDF") + "...", this);
10398 actionExportPDF->setShortcut(tr("Ctrl+Alt+P"));
10399 connect(actionExportPDF, SIGNAL(triggered()), this, SLOT(exportPDF()));
10400
10401 // FIXME: "..." should be added before translating, but this would break translations
10402 actionPrint = new QAction(QIcon(QPixmap(":/fileprint.xpm")), tr("&Print") + "...", this);
10403 actionPrint->setShortcut(tr("Ctrl+P"));
10404 connect(actionPrint, SIGNAL(triggered()), this, SLOT(print()));
10405
10406 actionPrintAllPlots = new QAction(tr("Print All Plo&ts"), this);
10407 connect(actionPrintAllPlots, SIGNAL(triggered()), this, SLOT(printAllPlots()));
10408
10409 // FIXME: "..." should be added before translating, but this would break translations
10410 actionShowExportASCIIDialog = new QAction(tr("E&xport ASCII") + "...", this);
10411 connect(actionShowExportASCIIDialog, SIGNAL(triggered()), this, SLOT(showExportASCIIDialog()));
10412
10413 actionCloseAllWindows = new QAction(QIcon(QPixmap(":/quit.xpm")), tr("&Quit"), this);
10414 actionCloseAllWindows->setShortcut(tr("Ctrl+Q"));
10415 connect(actionCloseAllWindows, SIGNAL(triggered()), qApp, SLOT(closeAllWindows()));
10416
10417 actionClearLogInfo = new QAction(tr("Clear &Log Information"), this);
10418 connect(actionClearLogInfo, SIGNAL(triggered()), this, SLOT(clearLogInfo()));
10419
10420 actionDeleteFitTables =
10421 new QAction(QIcon(QPixmap(":/close.xpm")), tr("Delete &Fit Tables"), this);
10422 connect(actionDeleteFitTables, SIGNAL(triggered()), this, SLOT(deleteFitTables()));
10423
10424 // FIXME: "..." should be added before translating, but this would break translations
10425 actionShowPlotWizard =
10426 new QAction(QIcon(QPixmap(":/wizard.xpm")), tr("Plot &Wizard") + "...", this);
10427 actionShowPlotWizard->setShortcut(tr("Ctrl+Alt+W"));
10428 connect(actionShowPlotWizard, SIGNAL(triggered()), this, SLOT(showPlotWizard()));
10429
10430 actionShowConfigureDialog = new QAction(tr("&Preferences..."), this);
10431 connect(actionShowConfigureDialog, SIGNAL(triggered()), this, SLOT(showPreferencesDialog()));
10432
10433 actionShowCurvesDialog =
10434 new QAction(QIcon(QPixmap(":/curves.xpm")), tr("Add/Remove &Curve..."), this);
10435 actionShowCurvesDialog->setShortcut(tr("ALT+C"));
10436 connect(actionShowCurvesDialog, SIGNAL(triggered()), this, SLOT(showCurvesDialog()));
10437
10438 actionAddErrorBars =
10439 new QAction(QIcon(QPixmap(":/yerror.xpm")), tr("Add &Error Bars..."), this);
10440 actionAddErrorBars->setShortcut(tr("Ctrl+B"));
10441 connect(actionAddErrorBars, SIGNAL(triggered()), this, SLOT(addErrorBars()));
10442
10443 actionAddFunctionCurve = new QAction(QIcon(QPixmap(":/fx.xpm")), tr("Add &Function..."), this);
10444 actionAddFunctionCurve->setShortcut(tr("Ctrl+Alt+F"));
10445 connect(actionAddFunctionCurve, SIGNAL(triggered()), this, SLOT(addFunctionCurve()));
10446
10447 actionUnzoom = new QAction(QIcon(QPixmap(":/unzoom.xpm")), tr("&Rescale to Show All"), this);
10448 actionUnzoom->setShortcut(tr("Ctrl+Shift+R"));
10449 connect(actionUnzoom, SIGNAL(triggered()), this, SLOT(setAutoScale()));
10450
10451 actionNewLegend = new QAction(QIcon(QPixmap(":/legend.xpm")), tr("New &Legend"), this);
10452 actionNewLegend->setShortcut(tr("Ctrl+L"));
10453 connect(actionNewLegend, SIGNAL(triggered()), this, SLOT(newLegend()));
10454
10455 actionTimeStamp = new QAction(QIcon(QPixmap(":/clock.xpm")), tr("Add Time Stamp"), this);
10456 actionTimeStamp->setShortcut(tr("Ctrl+ALT+T"));
10457 connect(actionTimeStamp, SIGNAL(triggered()), this, SLOT(addTimeStamp()));
10458
10459 actionAddImage = new QAction(QIcon(QPixmap(":/monalisa.xpm")), tr("Add &Image"), this);
10460 actionAddImage->setShortcut(tr("ALT+I"));
10461 connect(actionAddImage, SIGNAL(triggered()), this, SLOT(addImage()));
10462
10463 d_plot_mapper = new QSignalMapper;
10464 connect(d_plot_mapper, SIGNAL(mapped(int)), this, SLOT(selectPlotType(int)));
10465
10466 actionPlotL = new QAction(QIcon(QPixmap(":/lPlot.xpm")), tr("&Line"), this);
10467 connect(actionPlotL, SIGNAL(triggered()), d_plot_mapper, SLOT(map()));
10468 d_plot_mapper->setMapping(actionPlotL, Graph::Line);
10469
10470 actionPlotP = new QAction(QIcon(QPixmap(":/pPlot.xpm")), tr("&Scatter"), this);
10471 connect(actionPlotP, SIGNAL(triggered()), d_plot_mapper, SLOT(map()));
10472 d_plot_mapper->setMapping(actionPlotP, Graph::Scatter);
10473
10474 actionPlotLP = new QAction(QIcon(QPixmap(":/lpPlot.xpm")), tr("Line + S&ymbol"), this);
10475 connect(actionPlotLP, SIGNAL(triggered()), d_plot_mapper, SLOT(map()));
10476 d_plot_mapper->setMapping(actionPlotLP, Graph::LineSymbols);
10477
10478 actionPlotVerticalDropLines =
10479 new QAction(QIcon(QPixmap(":/dropLines.xpm")), tr("Vertical &Drop Lines"), this);
10480 connect(actionPlotVerticalDropLines, SIGNAL(triggered()), d_plot_mapper, SLOT(map()));
10481 d_plot_mapper->setMapping(actionPlotVerticalDropLines, Graph::VerticalDropLines);
10482
10483 actionPlotSpline = new QAction(QIcon(QPixmap(":/spline.xpm")), tr("&Spline"), this);
10484 connect(actionPlotSpline, SIGNAL(triggered()), d_plot_mapper, SLOT(map()));
10485 d_plot_mapper->setMapping(actionPlotSpline, Graph::Spline);
10486
10487 actionPlotHorSteps = new QAction(QPixmap(":/hor_steps.xpm"), tr("&Horizontal Steps"), this);
10488 connect(actionPlotHorSteps, SIGNAL(triggered()), d_plot_mapper, SLOT(map()));
10489 d_plot_mapper->setMapping(actionPlotHorSteps, Graph::HorizontalSteps);
10490
10491 actionPlotVertSteps =
10492 new QAction(QIcon(QPixmap(":/vert_steps.xpm")), tr("&Vertical Steps"), this);
10493 connect(actionPlotVertSteps, SIGNAL(triggered()), d_plot_mapper, SLOT(map()));
10494 d_plot_mapper->setMapping(actionPlotVertSteps, Graph::VerticalSteps);
10495
10496 actionPlotVerticalBars =
10497 new QAction(QIcon(QPixmap(":/vertBars.xpm")), tr("&Vertical Bars"), this);
10498 connect(actionPlotVerticalBars, SIGNAL(triggered()), d_plot_mapper, SLOT(map()));
10499 d_plot_mapper->setMapping(actionPlotVerticalBars, Graph::VerticalBars);
10500
10501 actionPlotHorizontalBars =
10502 new QAction(QIcon(QPixmap(":/hBars.xpm")), tr("&Horizontal Bars"), this);
10503 connect(actionPlotHorizontalBars, SIGNAL(triggered()), d_plot_mapper, SLOT(map()));
10504 d_plot_mapper->setMapping(actionPlotHorizontalBars, Graph::HorizontalBars);
10505
10506 actionPlotArea = new QAction(QIcon(QPixmap(":/area.xpm")), tr("&Area"), this);
10507 connect(actionPlotArea, SIGNAL(triggered()), d_plot_mapper, SLOT(map()));
10508 d_plot_mapper->setMapping(actionPlotArea, Graph::Area);
10509
10510 actionPlotPie = new QAction(QIcon(QPixmap(":/pie.xpm")), tr("&Pie"), this);
10511 connect(actionPlotPie, SIGNAL(triggered()), this, SLOT(plotPie()));
10512
10513 actionPlotVectXYAM = new QAction(QIcon(QPixmap(":/vectXYAM.xpm")), tr("Vectors XY&AM"), this);
10514 connect(actionPlotVectXYAM, SIGNAL(triggered()), this, SLOT(plotVectXYAM()));
10515
10516 actionPlotVectXYXY = new QAction(QIcon(QPixmap(":/vectXYXY.xpm")), tr("Vectors &XYXY"), this);
10517 connect(actionPlotVectXYXY, SIGNAL(triggered()), this, SLOT(plotVectXYXY()));
10518
10519 actionPlotHistogram = new QAction(QIcon(QPixmap(":/histogram.xpm")), tr("&Histogram"), this);
10520 connect(actionPlotHistogram, SIGNAL(triggered()), d_plot_mapper, SLOT(map()));
10521 d_plot_mapper->setMapping(actionPlotHistogram, Graph::Histogram);
10522
10523 actionPlotStackedHistograms =
10524 new QAction(QIcon(QPixmap(":/stacked_hist.xpm")), tr("&Stacked Histogram"), this);
10525 connect(actionPlotStackedHistograms, SIGNAL(triggered()), this, SLOT(plotStackedHistograms()));
10526
10527 actionPlot2VerticalLayers =
10528 new QAction(QIcon(QPixmap(":/panel_v2.xpm")), tr("&Vertical 2 Layers"), this);
10529 connect(actionPlot2VerticalLayers, SIGNAL(triggered()), this, SLOT(plot2VerticalLayers()));
10530
10531 actionPlot2HorizontalLayers =
10532 new QAction(QIcon(QPixmap(":/panel_h2.xpm")), tr("&Horizontal 2 Layers"), this);
10533 connect(actionPlot2HorizontalLayers, SIGNAL(triggered()), this, SLOT(plot2HorizontalLayers()));
10534
10535 actionPlot4Layers = new QAction(QIcon(QPixmap(":/panel_4.xpm")), tr("&4 Layers"), this);
10536 connect(actionPlot4Layers, SIGNAL(triggered()), this, SLOT(plot4Layers()));
10537
10538 actionPlotStackedLayers =
10539 new QAction(QIcon(QPixmap(":/stacked.xpm")), tr("&Stacked Layers"), this);
10540 connect(actionPlotStackedLayers, SIGNAL(triggered()), this, SLOT(plotStackedLayers()));
10541
10542 actionPlot3DRibbon = new QAction(QIcon(QPixmap(":/ribbon.xpm")), tr("&Ribbon"), this);
10543 connect(actionPlot3DRibbon, SIGNAL(triggered()), this, SLOT(plot3DRibbon()));
10544
10545 actionPlot3DBars = new QAction(QIcon(QPixmap(":/bars.xpm")), tr("&Bars"), this);
10546 connect(actionPlot3DBars, SIGNAL(triggered()), this, SLOT(plot3DBars()));
10547
10548 actionPlot3DScatter = new QAction(QIcon(QPixmap(":/scatter.xpm")), tr("&Scatter"), this);
10549 connect(actionPlot3DScatter, SIGNAL(triggered()), this, SLOT(plot3DScatter()));
10550
10551 actionPlot3DTrajectory =
10552 new QAction(QIcon(QPixmap(":/trajectory.xpm")), tr("&Trajectory"), this);
10553 connect(actionPlot3DTrajectory, SIGNAL(triggered()), this, SLOT(plot3DTrajectory()));
10554
10555 actionShowColStatistics =
10556 new QAction(QIcon(QPixmap(":/col_stat.xpm")), tr("Statistics on &Columns"), this);
10557 connect(actionShowColStatistics, SIGNAL(triggered()), this, SLOT(showColStatistics()));
10558
10559 actionShowRowStatistics =
10560 new QAction(QIcon(QPixmap(":/stat_rows.xpm")), tr("Statistics on &Rows"), this);
10561 connect(actionShowRowStatistics, SIGNAL(triggered()), this, SLOT(showRowStatistics()));
10562
10563 actionShowIntDialog = new QAction(tr("&Integrate ..."), this);
10564 connect(actionShowIntDialog, SIGNAL(triggered()), this, SLOT(showIntegrationDialog()));
10565
10566 actionInterpolate = new QAction(tr("Inte&rpolate ..."), this);
10567 connect(actionInterpolate, SIGNAL(triggered()), this, SLOT(showInterpolationDialog()));
10568
10569 actionLowPassFilter = new QAction(tr("&Low Pass..."), this);
10570 connect(actionLowPassFilter, SIGNAL(triggered()), this, SLOT(lowPassFilterDialog()));
10571
10572 actionHighPassFilter = new QAction(tr("&High Pass..."), this);
10573 connect(actionHighPassFilter, SIGNAL(triggered()), this, SLOT(highPassFilterDialog()));
10574
10575 actionBandPassFilter = new QAction(tr("&Band Pass..."), this);
10576 connect(actionBandPassFilter, SIGNAL(triggered()), this, SLOT(bandPassFilterDialog()));
10577
10578 actionBandBlockFilter = new QAction(tr("&Band Block..."), this);
10579 connect(actionBandBlockFilter, SIGNAL(triggered()), this, SLOT(bandBlockFilterDialog()));
10580
10581 actionFFT = new QAction(tr("&FFT..."), this);
10582 connect(actionFFT, SIGNAL(triggered()), this, SLOT(showFFTDialog()));
10583
10584 actionSmoothSavGol = new QAction(tr("&Savitzky-Golay..."), this);
10585 connect(actionSmoothSavGol, SIGNAL(triggered()), this, SLOT(showSmoothSavGolDialog()));
10586
10587 actionSmoothFFT = new QAction(tr("&FFT Filter..."), this);
10588 connect(actionSmoothFFT, SIGNAL(triggered()), this, SLOT(showSmoothFFTDialog()));
10589
10590 actionSmoothAverage = new QAction(tr("Moving Window &Average..."), this);
10591 connect(actionSmoothAverage, SIGNAL(triggered()), this, SLOT(showSmoothAverageDialog()));
10592
10593 actionDifferentiate = new QAction(tr("&Differentiate"), this);
10594 connect(actionDifferentiate, SIGNAL(triggered()), this, SLOT(differentiate()));
10595
10596 actionFitLinear = new QAction(tr("Fit &Linear"), this);
10597 connect(actionFitLinear, SIGNAL(triggered()), this, SLOT(fitLinear()));
10598
10599 actionShowFitPolynomDialog = new QAction(tr("Fit &Polynomial ..."), this);
10600 connect(actionShowFitPolynomDialog, SIGNAL(triggered()), this, SLOT(showFitPolynomDialog()));
10601
10602 actionShowExpDecayDialog = new QAction(tr("&First Order ..."), this);
10603 connect(actionShowExpDecayDialog, SIGNAL(triggered()), this, SLOT(showExpDecayDialog()));
10604
10605 actionShowTwoExpDecayDialog = new QAction(tr("&Second Order ..."), this);
10606 connect(actionShowTwoExpDecayDialog, SIGNAL(triggered()), this, SLOT(showTwoExpDecayDialog()));
10607
10608 actionShowExpDecay3Dialog = new QAction(tr("&Third Order ..."), this);
10609 connect(actionShowExpDecay3Dialog, SIGNAL(triggered()), this, SLOT(showExpDecay3Dialog()));
10610
10611 actionFitExpGrowth = new QAction(tr("Fit Exponential Gro&wth ..."), this);
10612 connect(actionFitExpGrowth, SIGNAL(triggered()), this, SLOT(showExpGrowthDialog()));
10613
10614 actionFitSigmoidal = new QAction(tr("Fit &Boltzmann (Sigmoidal)"), this);
10615 connect(actionFitSigmoidal, SIGNAL(triggered()), this, SLOT(fitSigmoidal()));
10616
10617 actionFitGauss = new QAction(tr("Fit &Gaussian"), this);
10618 connect(actionFitGauss, SIGNAL(triggered()), this, SLOT(fitGauss()));
10619
10620 actionFitLorentz = new QAction(tr("Fit Lorent&zian"), this);
10621 connect(actionFitLorentz, SIGNAL(triggered()), this, SLOT(fitLorentz()));
10622
10623 actionShowFitDialog = new QAction(tr("Fit &Wizard..."), this);
10624 actionShowFitDialog->setShortcut(tr("Ctrl+Y"));
10625 connect(actionShowFitDialog, SIGNAL(triggered()), this, SLOT(showFitDialog()));
10626
10627 actionShowPlotDialog = new QAction(tr("&Plot ..."), this);
10628 connect(actionShowPlotDialog, SIGNAL(triggered()), this, SLOT(showGeneralPlotDialog()));
10629
10630 actionShowScaleDialog = new QAction(tr("&Scales..."), this);
10631 connect(actionShowScaleDialog, SIGNAL(triggered()), this, SLOT(showScaleDialog()));
10632
10633 actionShowAxisDialog = new QAction(tr("&Axes..."), this);
10634 connect(actionShowAxisDialog, SIGNAL(triggered()), this, SLOT(showAxisDialog()));
10635
10636 actionShowGridDialog = new QAction(tr("&Grid ..."), this);
10637 connect(actionShowGridDialog, SIGNAL(triggered()), this, SLOT(showGridDialog()));
10638
10639 actionShowTitleDialog = new QAction(tr("&Title ..."), this);
10640 connect(actionShowTitleDialog, SIGNAL(triggered()), this, SLOT(showTitleDialog()));
10641
10642 actionAbout = new QAction(tr("&About SciDAVis"), this);
10643 actionAbout->setShortcut(tr("F1"));
10644 connect(actionAbout, SIGNAL(triggered()), this, SLOT(about()));
10645
10646 actionShowHelp = new QAction(tr("&Help"), this);
10647 actionShowHelp->setShortcut(tr("Ctrl+H"));
10648 connect(actionShowHelp, SIGNAL(triggered()), this, SLOT(showHelp()));
10649
10650 #ifdef DYNAMIC_MANUAL_PATH
10651 actionChooseHelpFolder = new QAction(tr("&Choose Help Folder..."), this);
10652 connect(actionChooseHelpFolder, SIGNAL(triggered()), this, SLOT(chooseHelpFolder()));
10653 #endif
10654
10655 actionRename = new QAction(tr("&Rename Window"), this);
10656 connect(actionRename, SIGNAL(triggered()), this, SLOT(renameActiveWindow()));
10657
10658 actionCloseWindow = new QAction(QIcon(QPixmap(":/close.xpm")), tr("Close &Window"), this);
10659 actionCloseWindow->setShortcut(tr("Ctrl+W"));
10660 connect(actionCloseWindow, SIGNAL(triggered()), this, SLOT(closeActiveWindow()));
10661
10662 actionDeleteLayer = new QAction(QIcon(QPixmap(":/erase.xpm")), tr("&Remove Layer"), this);
10663 actionDeleteLayer->setShortcut(tr("Alt+R"));
10664 connect(actionDeleteLayer, SIGNAL(triggered()), this, SLOT(deleteLayer()));
10665
10666 actionResizeActiveWindow =
10667 new QAction(QIcon(QPixmap(":/resize.xpm")), tr("Window &Geometry..."), this);
10668 connect(actionResizeActiveWindow, SIGNAL(triggered()), this, SLOT(resizeActiveWindow()));
10669
10670 actionHideActiveWindow = new QAction(tr("&Hide Window"), this);
10671 connect(actionHideActiveWindow, SIGNAL(triggered()), this, SLOT(hideActiveWindow()));
10672
10673 actionShowMoreWindows = new QAction(tr("More windows..."), this);
10674 connect(actionShowMoreWindows, SIGNAL(triggered()), this, SLOT(showMoreWindows()));
10675
10676 actionPixelLineProfile =
10677 new QAction(QIcon(QPixmap(":/pixelProfile.xpm")), tr("&View Pixel Line Profile"), this);
10678 connect(actionPixelLineProfile, SIGNAL(triggered()), this, SLOT(pixelLineProfile()));
10679
10680 actionIntensityTable = new QAction(tr("&Intensity Table"), this);
10681 connect(actionIntensityTable, SIGNAL(triggered()), this, SLOT(intensityTable()));
10682
10683 actionShowLineDialog = new QAction(tr("&Properties"), this);
10684 connect(actionShowLineDialog, SIGNAL(triggered()), this, SLOT(showLineDialog()));
10685
10686 actionShowImageDialog = new QAction(tr("&Properties"), this);
10687 connect(actionShowImageDialog, SIGNAL(triggered()), this, SLOT(showImageDialog()));
10688
10689 actionShowTextDialog = new QAction(tr("&Properties"), this);
10690 connect(actionShowTextDialog, SIGNAL(triggered()), this, SLOT(showTextDialog()));
10691
10692 actionActivateWindow = new QAction(tr("&Activate Window"), this);
10693 connect(actionActivateWindow, SIGNAL(triggered()), this, SLOT(activateSubWindow()));
10694
10695 actionMinimizeWindow = new QAction(tr("Mi&nimize Window"), this);
10696 connect(actionMinimizeWindow, SIGNAL(triggered()), this, SLOT(minimizeWindow()));
10697
10698 actionMaximizeWindow = new QAction(tr("Ma&ximize Window"), this);
10699 connect(actionMaximizeWindow, SIGNAL(triggered()), this, SLOT(maximizeWindow()));
10700
10701 actionResizeWindow = new QAction(QIcon(QPixmap(":/resize.xpm")), tr("Re&size Window..."), this);
10702 connect(actionResizeWindow, SIGNAL(triggered()), this, SLOT(resizeWindow()));
10703
10704 actionPrintWindow = new QAction(QIcon(QPixmap(":/fileprint.xpm")), tr("&Print Window"), this);
10705 connect(actionPrintWindow, SIGNAL(triggered()), this, SLOT(printWindow()));
10706
10707 actionShowPlotGeometryDialog =
10708 new QAction(QIcon(QPixmap(":/resize.xpm")), tr("&Layer Geometry"), this);
10709 connect(actionShowPlotGeometryDialog, SIGNAL(triggered()), this,
10710 SLOT(showPlotGeometryDialog()));
10711
10712 actionEditSurfacePlot = new QAction(tr("&Surface..."), this);
10713 connect(actionEditSurfacePlot, SIGNAL(triggered()), this, SLOT(editSurfacePlot()));
10714
10715 actionAdd3DData = new QAction(tr("&Data Set..."), this);
10716 connect(actionAdd3DData, SIGNAL(triggered()), this, SLOT(add3DData()));
10717
10718 actionInvertMatrix = new QAction(tr("&Invert"), this);
10719 connect(actionInvertMatrix, SIGNAL(triggered()), this, SLOT(invertMatrix()));
10720
10721 actionMatrixDeterminant = new QAction(tr("&Determinant"), this);
10722 connect(actionMatrixDeterminant, SIGNAL(triggered()), this, SLOT(matrixDeterminant()));
10723
10724 actionConvertMatrix = new QAction(tr("&Convert to Table"), this);
10725 connect(actionConvertMatrix, SIGNAL(triggered()), this, SLOT(convertMatrixToTable()));
10726
10727 actionConvertTable = new QAction(tr("Convert to &Matrix"), this);
10728 connect(actionConvertTable, SIGNAL(triggered()), this, SLOT(convertTableToMatrix()));
10729
10730 actionPlot3DWireFrame =
10731 new QAction(QIcon(QPixmap(":/lineMesh.xpm")), tr("3D &Wire Frame"), this);
10732 connect(actionPlot3DWireFrame, SIGNAL(triggered()), this, SLOT(plot3DWireframe()));
10733
10734 actionPlot3DHiddenLine =
10735 new QAction(QIcon(QPixmap(":/grid_only.xpm")), tr("3D &Hidden Line"), this);
10736 connect(actionPlot3DHiddenLine, SIGNAL(triggered()), this, SLOT(plot3DHiddenLine()));
10737
10738 actionPlot3DPolygons = new QAction(QIcon(QPixmap(":/no_grid.xpm")), tr("3D &Polygons"), this);
10739 connect(actionPlot3DPolygons, SIGNAL(triggered()), this, SLOT(plot3DPolygons()));
10740
10741 actionPlot3DWireSurface =
10742 new QAction(QIcon(QPixmap(":/grid_poly.xpm")), tr("3D Wire &Surface"), this);
10743 connect(actionPlot3DWireSurface, SIGNAL(triggered()), this, SLOT(plot3DWireSurface()));
10744
10745 actionColorMap =
10746 new QAction(QIcon(QPixmap(":/color_map.xpm")), tr("Contour - &Color Fill"), this);
10747 connect(actionColorMap, SIGNAL(triggered()), this, SLOT(plotColorMap()));
10748
10749 actionContourMap = new QAction(QIcon(QPixmap(":/contour_map.xpm")), tr("Contour &Lines"), this);
10750 connect(actionContourMap, SIGNAL(triggered()), this, SLOT(plotContour()));
10751
10752 actionGrayMap = new QAction(QIcon(QPixmap(":/gray_map.xpm")), tr("&Gray Scale Map"), this);
10753 connect(actionGrayMap, SIGNAL(triggered()), this, SLOT(plotGrayScale()));
10754
10755 actionCorrelate = new QAction(tr("Co&rrelate"), this);
10756 connect(actionCorrelate, SIGNAL(triggered()), this, SLOT(correlate()));
10757
10758 actionAutoCorrelate = new QAction(tr("&Autocorrelate"), this);
10759 connect(actionAutoCorrelate, SIGNAL(triggered()), this, SLOT(autoCorrelate()));
10760
10761 actionConvolute = new QAction(tr("&Convolute"), this);
10762 connect(actionConvolute, SIGNAL(triggered()), this, SLOT(convolute()));
10763
10764 actionDeconvolute = new QAction(tr("&Deconvolute"), this);
10765 connect(actionDeconvolute, SIGNAL(triggered()), this, SLOT(deconvolute()));
10766
10767 actionTranslateHor = new QAction(tr("&Horizontal"), this);
10768 connect(actionTranslateHor, SIGNAL(triggered()), this, SLOT(translateCurveHor()));
10769
10770 actionTranslateVert = new QAction(tr("&Vertical"), this);
10771 connect(actionTranslateVert, SIGNAL(triggered()), this, SLOT(translateCurveVert()));
10772
10773 actionBoxPlot = new QAction(QIcon(QPixmap(":/boxPlot.xpm")), tr("&Box Plot"), this);
10774 connect(actionBoxPlot, SIGNAL(triggered()), d_plot_mapper, SLOT(map()));
10775 d_plot_mapper->setMapping(actionBoxPlot, Graph::Box);
10776
10777 actionMultiPeakGauss = new QAction(tr("&Gaussian..."), this);
10778 connect(actionMultiPeakGauss, SIGNAL(triggered()), this, SLOT(fitMultiPeakGauss()));
10779
10780 actionMultiPeakLorentz = new QAction(tr("&Lorentzian..."), this);
10781 connect(actionMultiPeakLorentz, SIGNAL(triggered()), this, SLOT(fitMultiPeakLorentz()));
10782
10783 #ifdef SEARCH_FOR_UPDATES
10784 actionCheckUpdates = new QAction(tr("Search for &Updates"), this);
10785 connect(actionCheckUpdates, SIGNAL(triggered()), this, SLOT(searchForUpdates()));
10786 #endif // defined SEARCH_FOR_UPDATES
10787
10788 actionHomePage = new QAction(tr("&SciDAVis Homepage"), this);
10789 connect(actionHomePage, SIGNAL(triggered()), this, SLOT(showHomePage()));
10790
10791 actionHelpForums = new QAction(tr("SciDAVis &Forums"), this);
10792 connect(actionHelpForums, SIGNAL(triggered()), this, SLOT(showForums()));
10793
10794 actionHelpBugReports = new QAction(tr("Report a &Bug"), this);
10795 connect(actionHelpBugReports, SIGNAL(triggered()), this, SLOT(showBugTracker()));
10796
10797 #ifdef DOWNLOAD_LINKS
10798 actionDownloadManual = new QAction(tr("Download &Manual"), this);
10799 connect(actionDownloadManual, SIGNAL(triggered()), this, SLOT(downloadManual()));
10800 #endif
10801
10802 #ifdef SCRIPTING_DIALOG
10803 actionScriptingLang = new QAction(tr("Scripting &Language"), this);
10804 connect(actionScriptingLang, SIGNAL(triggered()), this, SLOT(showScriptingLangDialog()));
10805 #endif
10806
10807 actionRestartScripting = new QAction(tr("&Restart Scripting"), this);
10808 connect(actionRestartScripting, SIGNAL(triggered()), this, SLOT(restartScriptingEnv()));
10809
10810 actionNoteExecute = new QAction(tr("E&xecute"), this);
10811 actionNoteExecute->setShortcut(tr("Ctrl+J"));
10812
10813 actionNoteExecuteAll = new QAction(tr("Execute &All"), this);
10814 actionNoteExecuteAll->setShortcut(tr("Ctrl+Shift+J"));
10815
10816 actionNoteEvaluate = new QAction(tr("&Evaluate Expression"), this);
10817 actionNoteEvaluate->setShortcut(tr("Ctrl+Return"));
10818
10819 actionShowCurvePlotDialog = new QAction(tr("&Plot details..."), this);
10820 connect(actionShowCurvePlotDialog, SIGNAL(triggered()), this, SLOT(showCurvePlotDialog()));
10821
10822 actionShowCurveWorksheet = new QAction(tr("&Worksheet"), this);
10823 connect(actionShowCurveWorksheet, SIGNAL(triggered()), this, SLOT(showCurveWorksheet()));
10824
10825 actionCurveFullRange = new QAction(tr("&Reset to Full Range"), this);
10826 connect(actionCurveFullRange, SIGNAL(triggered()), this, SLOT(setCurveFullRange()));
10827
10828 actionEditCurveRange = new QAction(tr("Edit &Range..."), this);
10829 connect(actionEditCurveRange, SIGNAL(triggered()), this, SLOT(showCurveRangeDialog()));
10830
10831 actionRemoveCurve = new QAction(QPixmap(":/close.xpm"), tr("&Delete"), this);
10832 connect(actionRemoveCurve, SIGNAL(triggered()), this, SLOT(removeCurve()));
10833
10834 actionHideCurve = new QAction(tr("&Hide"), this);
10835 connect(actionHideCurve, SIGNAL(triggered()), this, SLOT(hideCurve()));
10836
10837 actionHideOtherCurves = new QAction(tr("Hide &Other Curves"), this);
10838 connect(actionHideOtherCurves, SIGNAL(triggered()), this, SLOT(hideOtherCurves()));
10839
10840 actionShowAllCurves = new QAction(tr("&Show All Curves"), this);
10841 connect(actionShowAllCurves, SIGNAL(triggered()), this, SLOT(showAllCurves()));
10842
10843 actionEditFunction = new QAction(tr("&Edit Function..."), this);
10844 connect(actionEditFunction, SIGNAL(triggered()), this, SLOT(showFunctionDialog()));
10845
10846 actionCopyStatusBarText = new QAction(tr("&Copy status bar text"), this);
10847 connect(actionCopyStatusBarText, SIGNAL(triggered()), this, SLOT(copyStatusBarText()));
10848 }
10849
translateActionsStrings()10850 void ApplicationWindow::translateActionsStrings()
10851 {
10852 actionShowCurvePlotDialog->setText(tr("&Plot details..."));
10853 actionShowCurveWorksheet->setText(tr("&Worksheet"));
10854 actionRemoveCurve->setText(tr("&Delete"));
10855 actionEditFunction->setText(tr("&Edit Function..."));
10856 actionCopyStatusBarText->setText(tr("&Copy status bar text"));
10857
10858 actionCurveFullRange->setText(tr("&Reset to Full Range"));
10859 actionEditCurveRange->setText(tr("Edit &Range..."));
10860 actionHideCurve->setText(tr("&Hide"));
10861 actionHideOtherCurves->setText(tr("Hide &Other Curves"));
10862 actionShowAllCurves->setText(tr("&Show All Curves"));
10863
10864 actionNewProject->setText(tr("New &Project"));
10865 actionNewProject->setToolTip(tr("Open a new project"));
10866 actionNewProject->setShortcut(tr("Ctrl+N"));
10867
10868 actionNewGraph->setText(tr("New &Graph"));
10869 actionNewGraph->setToolTip(tr("Create an empty 2D plot"));
10870 actionNewGraph->setShortcut(tr("Ctrl+G"));
10871
10872 actionNewNote->setText(tr("New &Note / Script"));
10873 actionNewNote->setShortcut(tr("Ctrl+ALT+N"));
10874 actionNewNote->setToolTip(tr("Create an empty note / script window"));
10875
10876 actionNewTable->setText(tr("New &Table"));
10877 actionNewTable->setShortcut(tr("Ctrl+T"));
10878 actionNewTable->setToolTip(tr("New table"));
10879
10880 actionNewMatrix->setText(tr("New &Matrix"));
10881 actionNewMatrix->setShortcut(tr("Ctrl+M"));
10882 actionNewMatrix->setToolTip(tr("New matrix"));
10883
10884 actionNewFunctionPlot->setText(tr("New &Function Plot"));
10885 actionNewFunctionPlot->setToolTip(tr("Create a new 2D function plot"));
10886 actionNewFunctionPlot->setShortcut(tr("Ctrl+F"));
10887
10888 actionNewSurfacePlot->setText(tr("New 3D &Surface Plot"));
10889 actionNewSurfacePlot->setToolTip(tr("Create a new 3D surface plot"));
10890 actionNewSurfacePlot->setShortcut(tr("Ctrl+ALT+Z"));
10891
10892 // FIXME: "..." should be added before translating, but this would break translations
10893 actionOpen->setText(tr("&Open") + "...");
10894 actionOpen->setShortcut(tr("Ctrl+O"));
10895 actionOpen->setToolTip(tr("Open project"));
10896
10897 // FIXME: "..." should be added before translating, but this would break translations
10898 actionLoadImage->setText(tr("Open Image &File") + "...");
10899 actionLoadImage->setShortcut(tr("Ctrl+I"));
10900
10901 actionImportImage->setText(tr("Import I&mage..."));
10902
10903 actionSaveProject->setText(tr("&Save Project"));
10904 actionSaveProject->setToolTip(tr("Save project"));
10905 actionSaveProject->setShortcut(tr("Ctrl+S"));
10906
10907 actionSaveProjectAs->setText(tr("Save Project &As..."));
10908
10909 actionOpenTemplate->setText(tr("Open Te&mplate..."));
10910 actionOpenTemplate->setToolTip(tr("Open template"));
10911
10912 actionSaveTemplate->setText(tr("Save As &Template..."));
10913 actionSaveTemplate->setToolTip(tr("Save window as template"));
10914
10915 actionLoad->setText(tr("&Import ASCII..."));
10916 actionLoad->setToolTip(tr("Import data file(s)"));
10917 actionLoad->setShortcut(tr("Ctrl+K"));
10918
10919 actionUndo->setText(tr("&Undo"));
10920 actionUndo->setToolTip(tr("Undo changes"));
10921 actionUndo->setShortcut(tr("Ctrl+Z"));
10922
10923 actionRedo->setText(tr("&Redo"));
10924 actionRedo->setToolTip(tr("Redo changes"));
10925 actionRedo->setShortcut(tr("Ctrl+R"));
10926
10927 actionCopyWindow->setText(tr("&Duplicate"));
10928 actionCopyWindow->setToolTip(tr("Duplicate window"));
10929
10930 actionCutSelection->setText(tr("Cu&t Selection"));
10931 actionCutSelection->setToolTip(tr("Cut selection"));
10932 actionCutSelection->setShortcut(tr("Ctrl+X"));
10933
10934 actionCopySelection->setText(tr("&Copy Selection"));
10935 actionCopySelection->setToolTip(tr("Copy selection"));
10936 actionCopySelection->setShortcut(tr("Ctrl+C"));
10937
10938 actionPasteSelection->setText(tr("&Paste Selection"));
10939 actionPasteSelection->setToolTip(tr("Paste selection"));
10940 actionPasteSelection->setShortcut(tr("Ctrl+V"));
10941
10942 actionClearSelection->setText(tr("&Delete Selection"));
10943 actionClearSelection->setToolTip(tr("Delete selection"));
10944 actionClearSelection->setShortcut(tr("Del", "delete key"));
10945
10946 actionShowExplorer->setText(tr("Project &Explorer"));
10947 actionShowExplorer->setShortcut(tr("Ctrl+E"));
10948 actionShowExplorer->setToolTip(tr("Show project explorer"));
10949
10950 actionShowLog->setText(tr("Results &Log"));
10951 actionShowLog->setToolTip(tr("Show analysis results"));
10952
10953 #ifdef SCRIPTING_CONSOLE
10954 actionShowConsole->setText(tr("&Console"));
10955 actionShowConsole->setToolTip(tr("Show Scripting console"));
10956 #endif
10957
10958 actionAddLayer->setText(tr("Add La&yer"));
10959 actionAddLayer->setToolTip(tr("Add Layer"));
10960 actionAddLayer->setShortcut(tr("ALT+L"));
10961
10962 // FIXME: "..." should be added before translating, but this would break translations
10963 actionShowLayerDialog->setText(tr("Arran&ge Layers") + "...");
10964 actionShowLayerDialog->setToolTip(tr("Arrange Layers"));
10965 actionShowLayerDialog->setShortcut(tr("ALT+A"));
10966
10967 actionAutomaticLayout->setText(tr("Automatic Layout"));
10968 actionAutomaticLayout->setToolTip(tr("Automatic Layout"));
10969
10970 // FIXME: "..." should be added before translating, but this would break translations
10971 actionExportGraph->setText(tr("&Current") + "...");
10972 actionExportGraph->setShortcut(tr("Alt+G"));
10973 actionExportGraph->setToolTip(tr("Export current graph"));
10974
10975 // FIXME: "..." should be added before translating, but this would break translations
10976 actionExportAllGraphs->setText(tr("&All") + "...");
10977 actionExportAllGraphs->setShortcut(tr("Alt+X"));
10978 actionExportAllGraphs->setToolTip(tr("Export all graphs"));
10979
10980 // FIXME: "..." should be added before translating, but this would break translations
10981 actionExportPDF->setText(tr("&Export PDF") + "...");
10982 actionExportPDF->setShortcut(tr("Ctrl+Alt+P"));
10983 actionExportPDF->setToolTip(tr("Export to PDF"));
10984
10985 // FIXME: "..." should be added before translating, but this would break translations
10986 actionPrint->setText(tr("&Print") + "...");
10987 actionPrint->setShortcut(tr("Ctrl+P"));
10988 actionPrint->setToolTip(tr("Print window"));
10989
10990 // FIXME: "..." should be added before translating, but this would break translations
10991 actionPrintAllPlots->setText(tr("Print All Plo&ts") + "...");
10992 // FIXME: "..." should be added before translating, but this would break translations
10993 actionShowExportASCIIDialog->setText(tr("E&xport ASCII") + "...");
10994
10995 actionCloseAllWindows->setText(tr("&Quit"));
10996 actionCloseAllWindows->setShortcut(tr("Ctrl+Q"));
10997
10998 actionClearLogInfo->setText(tr("Clear &Log Information"));
10999 actionDeleteFitTables->setText(tr("Delete &Fit Tables"));
11000
11001 actionShowPlotWizard->setText(tr("Plot &Wizard"));
11002 actionShowPlotWizard->setShortcut(tr("Ctrl+Alt+W"));
11003 toolbarsMenu->setTitle(tr("Toolbars"));
11004
11005 actionShowConfigureDialog->setText(tr("&Preferences..."));
11006
11007 actionShowCurvesDialog->setText(tr("Add/Remove &Curve..."));
11008 actionShowCurvesDialog->setShortcut(tr("ALT+C"));
11009 actionShowCurvesDialog->setToolTip(tr("Add curve to graph"));
11010
11011 actionAddErrorBars->setText(tr("Add &Error Bars..."));
11012 actionAddErrorBars->setToolTip(tr("Add Error Bars..."));
11013 actionAddErrorBars->setShortcut(tr("Ctrl+B"));
11014
11015 actionAddFunctionCurve->setText(tr("Add &Function..."));
11016 actionAddFunctionCurve->setToolTip(tr("Add Function..."));
11017 actionAddFunctionCurve->setShortcut(tr("Ctrl+Alt+F"));
11018
11019 actionUnzoom->setText(tr("&Rescale to Show All"));
11020 actionUnzoom->setShortcut(tr("Ctrl+Shift+R"));
11021 actionUnzoom->setToolTip(tr("Best fit"));
11022
11023 actionNewLegend->setText(tr("New &Legend"));
11024 actionNewLegend->setShortcut(tr("Ctrl+L"));
11025 actionNewLegend->setToolTip(tr("Add new legend"));
11026
11027 actionTimeStamp->setText(tr("Add Time Stamp"));
11028 actionTimeStamp->setShortcut(tr("Ctrl+ALT+T"));
11029 actionTimeStamp->setToolTip(tr("Date & time "));
11030
11031 actionAddImage->setText(tr("Add &Image"));
11032 actionAddImage->setToolTip(tr("Add Image"));
11033 actionAddImage->setShortcut(tr("ALT+I"));
11034
11035 actionPlotL->setText(tr("&Line"));
11036 actionPlotL->setToolTip(tr("Plot as line"));
11037
11038 actionPlotP->setText(tr("&Scatter"));
11039 actionPlotP->setToolTip(tr("Plot as symbols"));
11040
11041 actionPlotLP->setText(tr("Line + S&ymbol"));
11042 actionPlotLP->setToolTip(tr("Plot as line + symbols"));
11043
11044 actionPlotVerticalDropLines->setText(tr("Vertical &Drop Lines"));
11045
11046 actionPlotSpline->setText(tr("&Spline"));
11047 actionPlotVertSteps->setText(tr("&Vertical Steps"));
11048 actionPlotHorSteps->setText(tr("&Horizontal Steps"));
11049
11050 actionPlotVerticalBars->setText(tr("&Vertical Bars"));
11051 actionPlotVerticalBars->setToolTip(tr("Plot with vertical bars"));
11052
11053 actionPlotHorizontalBars->setText(tr("&Horizontal Bars"));
11054 actionPlotHorizontalBars->setToolTip(tr("Plot with horizontal bars"));
11055
11056 actionPlotArea->setText(tr("&Area"));
11057 actionPlotArea->setToolTip(tr("Plot area"));
11058
11059 actionPlotPie->setText(tr("&Pie"));
11060 actionPlotPie->setToolTip(tr("Plot pie"));
11061
11062 actionPlotVectXYXY->setText(tr("Vectors &XYXY"));
11063 actionPlotVectXYXY->setToolTip(tr("Vectors XYXY"));
11064
11065 actionPlotVectXYAM->setText(tr("Vectors XY&AM"));
11066 actionPlotVectXYAM->setToolTip(tr("Vectors XYAM"));
11067
11068 actionPlotHistogram->setText(tr("&Histogram"));
11069 actionPlotStackedHistograms->setText(tr("&Stacked Histogram"));
11070 actionPlot2VerticalLayers->setText(tr("&Vertical 2 Layers"));
11071 actionPlot2HorizontalLayers->setText(tr("&Horizontal 2 Layers"));
11072 actionPlot4Layers->setText(tr("&4 Layers"));
11073 actionPlotStackedLayers->setText(tr("&Stacked Layers"));
11074
11075 actionPlot3DRibbon->setText(tr("&Ribbon"));
11076 actionPlot3DRibbon->setToolTip(tr("Plot 3D ribbon"));
11077
11078 actionPlot3DBars->setText(tr("&Bars"));
11079 actionPlot3DBars->setToolTip(tr("Plot 3D bars"));
11080
11081 actionPlot3DScatter->setText(tr("&Scatter"));
11082 actionPlot3DScatter->setToolTip(tr("Plot 3D scatter"));
11083
11084 actionPlot3DTrajectory->setText(tr("&Trajectory"));
11085 actionPlot3DTrajectory->setToolTip(tr("Plot 3D trajectory"));
11086
11087 actionColorMap->setText(tr("Contour + &Color Fill"));
11088 actionColorMap->setToolTip(tr("Contour Lines + Color Fill"));
11089
11090 actionContourMap->setText(tr("Contour &Lines"));
11091 actionContourMap->setToolTip(tr("Contour Lines"));
11092
11093 actionGrayMap->setText(tr("&Gray Scale Map"));
11094 actionGrayMap->setToolTip(tr("Gray Scale Map"));
11095
11096 actionShowColStatistics->setText(tr("Statistics on &Columns"));
11097 actionShowColStatistics->setToolTip(tr("Selected columns statistics"));
11098
11099 actionShowRowStatistics->setText(tr("Statistics on &Rows"));
11100 actionShowRowStatistics->setToolTip(tr("Selected rows statistics"));
11101 actionShowIntDialog->setText(tr("&Integrate ..."));
11102 actionInterpolate->setText(tr("Inte&rpolate ..."));
11103 actionLowPassFilter->setText(tr("&Low Pass..."));
11104 actionHighPassFilter->setText(tr("&High Pass..."));
11105 actionBandPassFilter->setText(tr("&Band Pass..."));
11106 actionBandBlockFilter->setText(tr("&Band Block..."));
11107 actionFFT->setText(tr("&FFT..."));
11108 actionSmoothSavGol->setText(tr("&Savitzky-Golay..."));
11109 actionSmoothFFT->setText(tr("&FFT Filter..."));
11110 actionSmoothAverage->setText(tr("Moving Window &Average..."));
11111 actionDifferentiate->setText(tr("&Differentiate"));
11112 actionFitLinear->setText(tr("Fit &Linear"));
11113 actionShowFitPolynomDialog->setText(tr("Fit &Polynomial ..."));
11114 actionShowExpDecayDialog->setText(tr("&First Order ..."));
11115 actionShowTwoExpDecayDialog->setText(tr("&Second Order ..."));
11116 actionShowExpDecay3Dialog->setText(tr("&Third Order ..."));
11117 actionFitExpGrowth->setText(tr("Fit Exponential Gro&wth ..."));
11118 actionFitSigmoidal->setText(tr("Fit &Boltzmann (Sigmoidal)"));
11119 actionFitGauss->setText(tr("Fit &Gaussian"));
11120 actionFitLorentz->setText(tr("Fit Lorent&zian"));
11121
11122 actionShowFitDialog->setText(tr("Fit &Wizard..."));
11123 actionShowFitDialog->setShortcut(tr("Ctrl+Y"));
11124
11125 actionShowPlotDialog->setText(tr("&Plot ..."));
11126 actionShowScaleDialog->setText(tr("&Scales..."));
11127 actionShowAxisDialog->setText(tr("&Axes..."));
11128 actionShowGridDialog->setText(tr("&Grid ..."));
11129 actionShowTitleDialog->setText(tr("&Title ..."));
11130
11131 actionAbout->setText(tr("&About SciDAVis"));
11132 actionAbout->setShortcut(tr("F1"));
11133
11134 actionShowHelp->setText(tr("&Help"));
11135 actionShowHelp->setShortcut(tr("Ctrl+H"));
11136
11137 #ifdef DYNAMIC_MANUAL_PATH
11138 actionChooseHelpFolder->setText(tr("&Choose Help Folder..."));
11139 #endif
11140
11141 actionRename->setText(tr("&Rename Window"));
11142
11143 actionCloseWindow->setText(tr("Close &Window"));
11144 actionCloseWindow->setShortcut(tr("Ctrl+W"));
11145
11146 actionDeleteLayer->setText(tr("&Remove Layer"));
11147 actionDeleteLayer->setShortcut(tr("Alt+R"));
11148
11149 actionResizeActiveWindow->setText(tr("Window &Geometry..."));
11150 actionHideActiveWindow->setText(tr("&Hide Window"));
11151 actionShowMoreWindows->setText(tr("More Windows..."));
11152 actionPixelLineProfile->setText(tr("&View Pixel Line Profile"));
11153 actionIntensityTable->setText(tr("&Intensity Table"));
11154 actionShowLineDialog->setText(tr("&Properties"));
11155 actionShowImageDialog->setText(tr("&Properties"));
11156 actionShowTextDialog->setText(tr("&Properties"));
11157 actionActivateWindow->setText(tr("&Activate Window"));
11158 actionMinimizeWindow->setText(tr("Mi&nimize Window"));
11159 actionMaximizeWindow->setText(tr("Ma&ximize Window"));
11160 actionResizeWindow->setText(tr("Re&size Window..."));
11161 actionPrintWindow->setText(tr("&Print Window"));
11162 actionShowPlotGeometryDialog->setText(tr("&Layer Geometry"));
11163 actionEditSurfacePlot->setText(tr("&Surface..."));
11164 actionAdd3DData->setText(tr("&Data Set..."));
11165 actionInvertMatrix->setText(tr("&Invert"));
11166 actionMatrixDeterminant->setText(tr("&Determinant"));
11167 actionConvertMatrix->setText(tr("&Convert to Table"));
11168 actionConvertTable->setText(tr("Convert to &Matrix"));
11169 actionPlot3DWireFrame->setText(tr("3D &Wire Frame"));
11170 actionPlot3DHiddenLine->setText(tr("3D &Hidden Line"));
11171 actionPlot3DPolygons->setText(tr("3D &Polygons"));
11172 actionPlot3DWireSurface->setText(tr("3D Wire &Surface"));
11173 actionCorrelate->setText(tr("Co&rrelate"));
11174 actionAutoCorrelate->setText(tr("&Autocorrelate"));
11175 actionConvolute->setText(tr("&Convolute"));
11176 actionDeconvolute->setText(tr("&Deconvolute"));
11177 actionTranslateHor->setText(tr("&Horizontal"));
11178 actionTranslateVert->setText(tr("&Vertical"));
11179
11180 actionBoxPlot->setText(tr("&Box Plot"));
11181 actionBoxPlot->setToolTip(tr("Box and whiskers plot"));
11182
11183 actionMultiPeakGauss->setText(tr("&Gaussian..."));
11184 actionMultiPeakLorentz->setText(tr("&Lorentzian..."));
11185 actionHomePage->setText(tr("&SciDAVis Homepage"));
11186 #ifdef SEARCH_FOR_UPDATES
11187 actionCheckUpdates->setText(tr("Search for &Updates"));
11188 #endif
11189 actionHelpForums->setText(tr("Visit SciDAVis &Forums"));
11190 actionHelpBugReports->setText(tr("Report a &Bug"));
11191 #ifdef DOWNLOAD_LINKS
11192 actionDownloadManual->setText(tr("Download &Manual"));
11193 #endif
11194
11195 #ifdef SCRIPTING_DIALOG
11196 actionScriptingLang->setText(tr("Scripting &Language"));
11197 #endif
11198 actionRestartScripting->setText(tr("&Restart Scripting"));
11199
11200 actionNoteExecute->setText(tr("E&xecute"));
11201 actionNoteExecute->setShortcut(tr("Ctrl+J"));
11202
11203 actionNoteExecuteAll->setText(tr("Execute &All"));
11204 actionNoteExecuteAll->setShortcut(tr("Ctrl+Shift+J"));
11205
11206 actionNoteEvaluate->setText(tr("&Evaluate Expression"));
11207 actionNoteEvaluate->setShortcut(tr("Ctrl+Return"));
11208
11209 btnPointer->setText(tr("Disable &tools"));
11210 btnPointer->setToolTip(tr("Pointer"));
11211
11212 btnZoomIn->setText(tr("&Zoom In"));
11213 btnZoomIn->setShortcut(tr("Ctrl++"));
11214 btnZoomIn->setToolTip(tr("Zoom In"));
11215
11216 btnZoomOut->setText(tr("Zoom &Out"));
11217 btnZoomOut->setShortcut(tr("Ctrl+-"));
11218 btnZoomOut->setToolTip(tr("Zoom Out"));
11219
11220 btnCursor->setText(tr("&Data Reader"));
11221 btnCursor->setShortcut(tr("CTRL+D"));
11222 btnCursor->setToolTip(tr("Data reader"));
11223
11224 btnSelect->setText(tr("&Select Data Range"));
11225 btnSelect->setShortcut(tr("ALT+S"));
11226 btnSelect->setToolTip(tr("Select data range"));
11227
11228 btnPicker->setText(tr("S&creen Reader"));
11229 btnPicker->setToolTip(tr("Screen reader"));
11230
11231 btnMovePoints->setText(tr("&Move Data Points..."));
11232 btnMovePoints->setShortcut(tr("Ctrl+ALT+M"));
11233 btnMovePoints->setToolTip(tr("Move data points"));
11234
11235 btnRemovePoints->setText(tr("Remove &Bad Data Points..."));
11236 btnRemovePoints->setShortcut(tr("Alt+B"));
11237 btnRemovePoints->setToolTip(tr("Remove data points"));
11238
11239 actionAddText->setText(tr("Add &Text"));
11240 actionAddText->setToolTip(tr("Add Text"));
11241 actionAddText->setShortcut(tr("ALT+T"));
11242
11243 actionNextWindow->setText(tr("&Next", "next window"));
11244 actionPrevWindow->setText(tr("&Previous", "previous window"));
11245
11246 btnArrow->setText(tr("Draw &Arrow"));
11247 btnArrow->setShortcut(tr("CTRL+ALT+A"));
11248 btnArrow->setToolTip(tr("Draw arrow"));
11249
11250 btnLine->setText(tr("Draw &Line"));
11251 btnLine->setShortcut(tr("CTRL+ALT+L"));
11252 btnLine->setToolTip(tr("Draw line"));
11253
11254 // FIXME: is setText necessary for action groups?
11255 // coord->setText( tr( "Coordinates" ) );
11256 // coord->setIconText( tr( "&Coord" ) );
11257 // coord->setStatusTip( tr( "Coordinates" ) );
11258 Box->setText(tr("Box"));
11259 Box->setIconText(tr("Box"));
11260 Box->setToolTip(tr("Box"));
11261 Box->setStatusTip(tr("Box"));
11262 Frame->setText(tr("Frame"));
11263 Frame->setIconText(tr("&Frame"));
11264 Frame->setToolTip(tr("Frame"));
11265 Frame->setStatusTip(tr("Frame"));
11266 None->setText(tr("No Axes"));
11267 None->setIconText(tr("No Axes"));
11268 None->setToolTip(tr("No axes"));
11269 None->setStatusTip(tr("No axes"));
11270
11271 front->setToolTip(tr("Front grid"));
11272 back->setToolTip(tr("Back grid"));
11273 right->setToolTip(tr("Right grid"));
11274 left->setToolTip(tr("Left grid"));
11275 ceil->setToolTip(tr("Ceiling grid"));
11276 floor->setToolTip(tr("Floor grid"));
11277
11278 wireframe->setText(tr("Wireframe"));
11279 wireframe->setIconText(tr("Wireframe"));
11280 wireframe->setToolTip(tr("Wireframe"));
11281 wireframe->setStatusTip(tr("Wireframe"));
11282 hiddenline->setText(tr("Hidden Line"));
11283 hiddenline->setIconText(tr("Hidden Line"));
11284 hiddenline->setToolTip(tr("Hidden line"));
11285 hiddenline->setStatusTip(tr("Hidden line"));
11286 polygon->setText(tr("Polygon Only"));
11287 polygon->setIconText(tr("Polygon Only"));
11288 polygon->setToolTip(tr("Polygon only"));
11289 polygon->setStatusTip(tr("Polygon only"));
11290 filledmesh->setText(tr("Mesh & Filled Polygons"));
11291 filledmesh->setIconText(tr("Mesh & Filled Polygons"));
11292 filledmesh->setToolTip(tr("Mesh & filled Polygons"));
11293 filledmesh->setStatusTip(tr("Mesh & filled Polygons"));
11294 pointstyle->setText(tr("Dots"));
11295 pointstyle->setIconText(tr("Dots"));
11296 pointstyle->setToolTip(tr("Dots"));
11297 pointstyle->setStatusTip(tr("Dots"));
11298 barstyle->setText(tr("Bars"));
11299 barstyle->setIconText(tr("Bars"));
11300 barstyle->setToolTip(tr("Bars"));
11301 barstyle->setStatusTip(tr("Bars"));
11302 conestyle->setText(tr("Cones"));
11303 conestyle->setIconText(tr("Cones"));
11304 conestyle->setToolTip(tr("Cones"));
11305 conestyle->setStatusTip(tr("Cones"));
11306 crossHairStyle->setText(tr("Crosshairs"));
11307 crossHairStyle->setIconText(tr("Crosshairs"));
11308 crossHairStyle->setToolTip(tr("Crosshairs"));
11309 crossHairStyle->setStatusTip(tr("Crosshairs"));
11310
11311 // floorstyle->setText( tr( "Floor Style" ) );
11312 // floorstyle->setIconText( tr( "Floor Style" ) );
11313 // floorstyle->setStatusTip( tr( "Floor Style" ) );
11314 floordata->setText(tr("Floor Data Projection"));
11315 floordata->setIconText(tr("Floor Data Projection"));
11316 floordata->setToolTip(tr("Floor data projection"));
11317 floordata->setStatusTip(tr("Floor data projection"));
11318 flooriso->setText(tr("Floor Isolines"));
11319 flooriso->setIconText(tr("Floor Isolines"));
11320 flooriso->setToolTip(tr("Floor isolines"));
11321 flooriso->setStatusTip(tr("Floor isolines"));
11322 floornone->setText(tr("Empty Floor"));
11323 floornone->setIconText(tr("Empty Floor"));
11324 floornone->setToolTip(tr("Empty floor"));
11325 floornone->setStatusTip(tr("Empty floor"));
11326
11327 actionAnimate->setText(tr("Animation"));
11328 actionAnimate->setIconText(tr("Animation"));
11329 actionAnimate->setToolTip(tr("Animation"));
11330 actionAnimate->setStatusTip(tr("Animation"));
11331
11332 actionPerspective->setText(tr("Enable perspective"));
11333 actionPerspective->setIconText(tr("Enable perspective"));
11334 actionPerspective->setToolTip(tr("Enable perspective"));
11335 actionPerspective->setStatusTip(tr("Enable perspective"));
11336
11337 actionResetRotation->setText(tr("Reset rotation"));
11338 actionResetRotation->setIconText(tr("Reset rotation"));
11339 actionResetRotation->setToolTip(tr("Reset rotation"));
11340 actionResetRotation->setStatusTip(tr("Reset rotation"));
11341
11342 actionFitFrame->setText(tr("Fit frame to window"));
11343 actionFitFrame->setIconText(tr("Fit frame to window"));
11344 actionFitFrame->setToolTip(tr("Fit frame to window"));
11345 actionFitFrame->setStatusTip(tr("Fit frame to window"));
11346 }
11347
openMatrixPlot3D(const QString & caption,const QString & matrix_name,double xl,double xr,double yl,double yr,double zl,double zr)11348 Graph3D *ApplicationWindow::openMatrixPlot3D(const QString &caption, const QString &matrix_name,
11349 double xl, double xr, double yl, double yr, double zl,
11350 double zr)
11351 {
11352 QString name = matrix_name;
11353 name.remove("matrix<", Qt::CaseSensitive);
11354 name.remove(">");
11355 Matrix *m = matrix(name);
11356 if (!m)
11357 return 0;
11358
11359 Graph3D *plot = new Graph3D("", &d_workspace, 0, Qt::Widget);
11360 plot->setAttribute(Qt::WA_DeleteOnClose);
11361 plot->setWindowTitle(caption);
11362 plot->setName(caption);
11363 plot->addMatrixData(m, xl, xr, yl, yr, zl, zr);
11364 plot->update();
11365
11366 initPlot3D(plot);
11367 return plot;
11368 }
11369
plot3DMatrix(int style)11370 void ApplicationWindow::plot3DMatrix(int style)
11371 {
11372 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("Matrix"))
11373 return;
11374
11375 QApplication::setOverrideCursor(Qt::WaitCursor);
11376 QString label = generateUniqueName(tr("Graph"));
11377
11378 Graph3D *plot = new Graph3D("", &d_workspace, 0);
11379 plot->setAttribute(Qt::WA_DeleteOnClose);
11380 plot->addMatrixData((Matrix *)d_workspace.activeSubWindow());
11381 plot->customPlotStyle(style);
11382 customPlot3D(plot);
11383 plot->update();
11384
11385 plot->resize(500, 400);
11386 plot->setWindowTitle(label);
11387 plot->setName(label);
11388 initPlot3D(plot);
11389
11390 emit modified();
11391 QApplication::restoreOverrideCursor();
11392 }
11393
plotGrayScale()11394 void ApplicationWindow::plotGrayScale()
11395 {
11396 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("Matrix"))
11397 return;
11398
11399 plotSpectrogram((Matrix *)d_workspace.activeSubWindow(), Graph::GrayMap);
11400 }
11401
plotGrayScale(Matrix * m)11402 MultiLayer *ApplicationWindow::plotGrayScale(Matrix *m)
11403 {
11404 if (!m)
11405 return 0;
11406
11407 return plotSpectrogram(m, Graph::GrayMap);
11408 }
11409
plotContour()11410 void ApplicationWindow::plotContour()
11411 {
11412 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("Matrix"))
11413 return;
11414
11415 plotSpectrogram((Matrix *)d_workspace.activeSubWindow(), Graph::ContourMap);
11416 }
11417
plotContour(Matrix * m)11418 MultiLayer *ApplicationWindow::plotContour(Matrix *m)
11419 {
11420 if (!m)
11421 return 0;
11422
11423 return plotSpectrogram(m, Graph::ContourMap);
11424 }
11425
plotColorMap()11426 void ApplicationWindow::plotColorMap()
11427 {
11428 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("Matrix"))
11429 return;
11430
11431 plotSpectrogram((Matrix *)d_workspace.activeSubWindow(), Graph::ColorMap);
11432 }
11433
plotColorMap(Matrix * m)11434 MultiLayer *ApplicationWindow::plotColorMap(Matrix *m)
11435 {
11436 if (!m)
11437 return 0;
11438
11439 return plotSpectrogram(m, Graph::ColorMap);
11440 }
11441
plotSpectrogram(Matrix * m,Graph::CurveType type)11442 MultiLayer *ApplicationWindow::plotSpectrogram(Matrix *m, Graph::CurveType type)
11443 {
11444 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
11445
11446 MultiLayer *g = multilayerPlot(generateUniqueName(tr("Graph")));
11447 Graph *plot = g->addLayer();
11448 setPreferences(plot);
11449
11450 plot->plotSpectrogram(m, type);
11451 g->showNormal();
11452
11453 emit modified();
11454 QApplication::restoreOverrideCursor();
11455 return g;
11456 }
11457
importOPJ(const QString & filename)11458 ApplicationWindow *ApplicationWindow::importOPJ(const QString &filename [[maybe_unused]])
11459 {
11460 #ifdef ORIGIN_IMPORT
11461 auto codec = getSettings().value("/General/Dialogs/LastUsedOriginLocale", "").toString();
11462 if (filename.endsWith(".opj", Qt::CaseInsensitive)
11463 || filename.endsWith(".ogg", Qt::CaseInsensitive)
11464 || filename.endsWith(".org", Qt::CaseInsensitive)) {
11465 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
11466
11467 ApplicationWindow *app = new ApplicationWindow();
11468 app->applyUserSettings();
11469 app->setWindowTitle("SciDAVis - " + filename);
11470 app->showMaximized();
11471 app->projectname = filename;
11472 app->recentProjects.removeAll(filename);
11473 app->recentProjects.push_front(filename);
11474 app->updateRecentProjectsList();
11475
11476 ImportOPJ(app, filename, codec);
11477
11478 QApplication::restoreOverrideCursor();
11479 return app;
11480 } else if (filename.endsWith(".ogm", Qt::CaseInsensitive)
11481 || filename.endsWith(".ogw", Qt::CaseInsensitive)) {
11482 ImportOPJ(this, filename, codec);
11483 recentProjects.removeAll(filename);
11484 recentProjects.push_front(filename);
11485 updateRecentProjectsList();
11486 return this;
11487 } else
11488 return 0;
11489 #else
11490 return NULL;
11491 #endif
11492 }
11493
deleteFitTables()11494 void ApplicationWindow::deleteFitTables()
11495 {
11496 QList<MyWidget *> *mLst = new QList<MyWidget *>();
11497 QList<MyWidget *> windows = windowsList();
11498 for (int i = 0; i < int(windows.count()); i++) {
11499 if (windows.at(i)->inherits("MultiLayer"))
11500 mLst->append(windows.at(i));
11501 }
11502
11503 foreach (MyWidget *ml, *mLst) {
11504 if (ml->inherits("MultiLayer")) {
11505 QWidgetList lst = ((MultiLayer *)ml)->graphPtrs();
11506 foreach (QWidget *widget, lst) {
11507 QList<QwtPlotCurve *> curves = ((Graph *)widget)->fitCurvesList();
11508 foreach (QwtPlotCurve *c, curves) {
11509 if (((PlotCurve *)c)->type() != Graph::Function) {
11510 Table *t = ((DataCurve *)c)->table();
11511 if (!t)
11512 continue;
11513
11514 t->askOnCloseEvent(false);
11515 t->close();
11516 }
11517 }
11518 }
11519 }
11520 }
11521 delete mLst;
11522 }
11523
windowsList()11524 QList<MyWidget *> ApplicationWindow::windowsList()
11525 {
11526 QList<MyWidget *> lst = QList<MyWidget *>();
11527
11528 Folder *project_folder = projectFolder();
11529 FolderListItem *item = project_folder->folderListItem();
11530 int initial_depth = item->depth();
11531 QTreeWidgetItemIterator it(item);
11532 while (item && item->depth() >= initial_depth) {
11533 QList<MyWidget *> folderWindows = item->folder()->windowsList();
11534 foreach (MyWidget *w, folderWindows)
11535 lst.append(w);
11536 it++;
11537 item = (FolderListItem *)(*it);
11538 }
11539
11540 for (MyWidget *w : hiddenWindows)
11541 lst.append(w);
11542 for (MyWidget *w : outWindows)
11543 lst.append(w);
11544
11545 return lst;
11546 }
11547
updateRecentProjectsList()11548 void ApplicationWindow::updateRecentProjectsList()
11549 {
11550 if (recentProjects.isEmpty())
11551 return;
11552
11553 while ((int)recentProjects.size() > MaxRecentProjects)
11554 recentProjects.pop_back();
11555
11556 foreach (QAction *action, recent->actions())
11557 action->deleteLater();
11558
11559 for (int i = 0; i < (int)recentProjects.size(); i++)
11560 connect(recent->addAction("&" + QString::number(i + 1) + " " + recentProjects[i]),
11561 SIGNAL(triggered()), this, SLOT(openRecentProject()));
11562 }
11563
translateCurveHor()11564 void ApplicationWindow::translateCurveHor()
11565 {
11566 QWidget *w = d_workspace.activeSubWindow();
11567 if (!w || !w->inherits("MultiLayer"))
11568 return;
11569
11570 MultiLayer *plot = (MultiLayer *)w;
11571 if (plot->isEmpty()) {
11572 QMessageBox::warning(this, tr("Warning"),
11573 tr("<h4>There are no plot layers available in this window.</h4>"
11574 "<p><h4>Please add a layer and try again!</h4>"));
11575 btnPointer->setChecked(true);
11576 return;
11577 }
11578
11579 Graph *g = (Graph *)plot->activeGraph();
11580 if (!g)
11581 return;
11582
11583 if (g->isPiePlot()) {
11584 QMessageBox::warning(this, tr("Warning"),
11585 tr("This functionality is not available for pie plots!"));
11586
11587 btnPointer->setChecked(true);
11588 return;
11589 } else if (g->validCurvesDataSize()) {
11590 btnPointer->setChecked(true);
11591 g->setActiveTool(new TranslateCurveTool(g, this, TranslateCurveTool::Horizontal,
11592 d_status_info, SLOT(setText(const QString &))));
11593 }
11594 }
11595
translateCurveVert()11596 void ApplicationWindow::translateCurveVert()
11597 {
11598 QWidget *w = d_workspace.activeSubWindow();
11599 if (!w || !w->inherits("MultiLayer"))
11600 return;
11601
11602 MultiLayer *plot = (MultiLayer *)w;
11603 if (plot->isEmpty()) {
11604 QMessageBox::warning(this, tr("Warning"),
11605 tr("<h4>There are no plot layers available in this window.</h4>"
11606 "<p><h4>Please add a layer and try again!</h4>"));
11607 btnPointer->setChecked(true);
11608 return;
11609 }
11610
11611 Graph *g = (Graph *)plot->activeGraph();
11612 if (!g)
11613 return;
11614
11615 if (g->isPiePlot()) {
11616 QMessageBox::warning(this, tr("Warning"),
11617 tr("This functionality is not available for pie plots!"));
11618
11619 btnPointer->setChecked(true);
11620 return;
11621 } else if (g->validCurvesDataSize()) {
11622 btnPointer->setChecked(true);
11623 g->setActiveTool(new TranslateCurveTool(g, this, TranslateCurveTool::Vertical,
11624 d_status_info, SLOT(setText(const QString &))));
11625 }
11626 }
11627
fitMultiPeakGauss()11628 void ApplicationWindow::fitMultiPeakGauss()
11629 {
11630 fitMultiPeak((int)MultiPeakFit::Gauss);
11631 }
11632
fitMultiPeakLorentz()11633 void ApplicationWindow::fitMultiPeakLorentz()
11634 {
11635 fitMultiPeak((int)MultiPeakFit::Lorentz);
11636 }
11637
fitMultiPeak(int profile)11638 void ApplicationWindow::fitMultiPeak(int profile)
11639 {
11640 QWidget *w = d_workspace.activeSubWindow();
11641 if (!w || !w->inherits("MultiLayer"))
11642 return;
11643
11644 MultiLayer *plot = (MultiLayer *)w;
11645 if (plot->isEmpty()) {
11646 QMessageBox::warning(this, tr("Warning"),
11647 tr("<h4>There are no plot layers available in this window.</h4>"
11648 "<p><h4>Please add a layer and try again!</h4>"));
11649 btnPointer->setChecked(true);
11650 return;
11651 }
11652
11653 Graph *g = (Graph *)plot->activeGraph();
11654 if (!g || !g->validCurvesDataSize())
11655 return;
11656
11657 if (g->isPiePlot()) {
11658 QMessageBox::warning(this, tr("Warning"),
11659 tr("This functionality is not available for pie plots!"));
11660 return;
11661 } else {
11662 bool ok;
11663 int peaks = QInputDialog::getInt(this, tr("Enter the number of peaks"), tr("Peaks"), 2, 2,
11664 1000000, 1, &ok);
11665 if (ok && peaks) {
11666 g->setActiveTool(new MultiPeakFitTool(g, this, (MultiPeakFit::PeakProfile)profile,
11667 peaks, d_status_info,
11668 SLOT(setText(const QString &))));
11669 }
11670 }
11671 }
11672
11673 #ifdef DOWNLOAD_LINKS
downloadManual()11674 void ApplicationWindow::downloadManual()
11675 {
11676 QDesktopServices::openUrl(QUrl(MANUAL_URI));
11677 }
11678 #endif // defined DOWNLOAD_LINKS
11679
showHomePage()11680 void ApplicationWindow::showHomePage()
11681 {
11682 QDesktopServices::openUrl(QUrl(HOMEPAGE_URI));
11683 }
11684
showForums()11685 void ApplicationWindow::showForums()
11686 {
11687 QDesktopServices::openUrl(QUrl(FORUM_URI));
11688 }
11689
showBugTracker()11690 void ApplicationWindow::showBugTracker()
11691 {
11692 QDesktopServices::openUrl(QUrl(BUGREPORT_URI));
11693 }
11694
parseCommandLineArguments(const QStringList & args)11695 void ApplicationWindow::parseCommandLineArguments(const QStringList &args)
11696 {
11697 int num_args = args.count();
11698 if (num_args == 0)
11699 return;
11700
11701 QString str;
11702 bool exec = false;
11703 int scriptArg = 0;
11704 // foreach(str, args){
11705 for (int i = 0; i < num_args; ++i) {
11706 str = args[i];
11707 if ((str == "-a" || str == "--about") || (str == "-m" || str == "--manual")) {
11708 QMessageBox::critical(this, tr("Error"),
11709 tr("<b> %1 </b>: This command line option must be used without "
11710 "other arguments!")
11711 .arg(str));
11712 } else if (str == "-v" || str == "--version") {
11713 QString s = SciDAVis::versionString() + SciDAVis::extraVersion() + "\n";
11714 s += QObject::tr("Released") + ": " + SciDAVis::releaseDateString() + "\n";
11715 s += SciDAVis::copyrightString() + "\n";
11716
11717 #ifdef Q_OS_WIN
11718 hide();
11719 QMessageBox::information(this, tr("SciDAVis") + " - " + tr("Version"), s);
11720 #else
11721 std::cout << s.toStdString();
11722 #endif
11723 ::exit(0);
11724 } else if (str == "-h" || str == "--help") {
11725 QString s = "\n" + tr("Usage") + ": ";
11726 s += "scidavis [" + tr("options") + "] [" + tr("file") + "_" + tr("name") + "]\n\n";
11727 s += tr("Valid options are") + ":\n";
11728 s += "-a " + tr("or") + " --about: " + tr("show about dialog and exit") + "\n";
11729 s += "-h " + tr("or") + " --help: " + tr("show command line options") + "\n";
11730 s += "-l=XX " + tr("or") + " --lang=XX: " + tr("start SciDAVis in language")
11731 + " XX ('en', 'fr', 'de', ...)\n";
11732 s += "-m " + tr("or")
11733 + " --manual: " + tr("show SciDAVis manual in a standalone window") + "\n";
11734 s += "-v " + tr("or") + " --version: " + tr("print SciDAVis version and release date")
11735 + "\n";
11736 s += "-x " + tr("or") + " --execute: " + tr("execute the script file given as argument")
11737 + "\n\n";
11738 #ifdef ORIGIN_IMPORT
11739 s += "'" + tr("file") + "_" + tr("name") + "' "
11740 + tr("can be any .sciprj, .sciprj.gz, .qti, qti.gz, .opj, .ogm, .ogw, .ogg, "
11741 ".org, .py or ASCII file")
11742 + "\n";
11743 #else
11744 s += "'" + tr("file") + "_" + tr("name") + "' "
11745 + tr("can be any .sciprj, .sciprj.gz, .qti, qti.gz, .py or ASCII file") + "\n";
11746 #endif
11747 #ifdef Q_OS_WIN
11748 hide();
11749 QMessageBox::information(this, tr("SciDAVis - Help"), s);
11750 #else
11751 std::cout << s.toStdString();
11752 #endif
11753 ::exit(0);
11754 } else if (str.startsWith("--lang=") || str.startsWith("-l=")) {
11755 QString locale = str.mid(str.indexOf('=') + 1);
11756 if (locales.contains(locale))
11757 switchToLanguage(locale);
11758
11759 if (!locales.contains(locale))
11760 QMessageBox::critical(
11761 this, tr("Error"),
11762 tr("<b> %1 </b>: Wrong locale option or no translation available!")
11763 .arg(locale));
11764 } else if (str.startsWith("--execute") || str.startsWith("-x"))
11765 exec = true;
11766 else if (str.startsWith("-") || str.startsWith("--")) {
11767 QMessageBox::critical(this, tr("Error"),
11768 tr("<b> %1 </b> unknown command line option!").arg(str) + "\n"
11769 + tr("Type %1 to see the list of the valid options.")
11770 .arg("'scidavis -h'"));
11771 }
11772 if (str.startsWith("-"))
11773 scriptArg = i; // save last flag
11774 }
11775
11776 if (scriptArg < num_args - 1)
11777 scriptArg++;
11778 QString file_name = args[scriptArg]; // last argument
11779
11780 QStringList scriptArgs;
11781 for (auto i = scriptArg + 1; i < num_args; ++i)
11782 scriptArgs << args[i];
11783
11784 if (file_name.startsWith("-"))
11785 return; // no file name given
11786
11787 if (!file_name.isEmpty()) {
11788 QFileInfo fi(file_name);
11789 if (fi.isDir()) {
11790 QMessageBox::critical(
11791 this, tr("File opening error"),
11792 tr("<b>%1</b> is a directory, please specify a file name!").arg(file_name));
11793 return;
11794 } else if (!fi.isReadable()) {
11795 QMessageBox::critical(this, tr("File opening error"),
11796 tr("You don't have the permission to open this file: <b>%1</b>")
11797 .arg(file_name));
11798 return;
11799 } else if (!fi.exists()) {
11800 QMessageBox::critical(this, tr("File opening error"),
11801 tr("The file: <b>%1</b> doesn't exist!").arg(file_name));
11802 return;
11803 }
11804
11805 workingDir = fi.absolutePath();
11806 saveSettings(); // the recent projects must be saved
11807
11808 ApplicationWindow *a;
11809 if (exec)
11810 a = loadScript(file_name, scriptArgs, exec);
11811 else
11812 a = open(file_name, scriptArgs);
11813
11814 if (a) {
11815 a->workingDir = workingDir;
11816 close();
11817 }
11818 }
11819 }
11820
createLanguagesList()11821 void ApplicationWindow::createLanguagesList()
11822 {
11823 appTranslator = new QTranslator(this);
11824 qtTranslator = new QTranslator(this);
11825 qApp->installTranslator(appTranslator);
11826 qApp->installTranslator(qtTranslator);
11827
11828 qmPath = TS_PATH;
11829
11830 QString lng; // lang, as en_GB
11831 QString slng; // short lang, as en
11832 lng = QLocale().name();
11833 {
11834 if (lng == "C")
11835 lng = "en";
11836 int i = lng.indexOf(QString("."));
11837 if (i >= 0)
11838 lng = lng.left(i);
11839 i = lng.indexOf(QString("_"));
11840 if (i >= 0)
11841 slng = lng.left(i);
11842 else
11843 slng = lng;
11844 }
11845 if (slng.size() > 2)
11846 slng = slng.left(2);
11847
11848 QDir dir(qmPath);
11849 QStringList fileNames = dir.entryList(QStringList("scidavis_*.qm"));
11850 if (fileNames.size() == 0) {
11851 // fall back to looking in the executable's directory
11852 qmPath = QFileInfo(QCoreApplication::applicationFilePath()).path() + "/translations";
11853 dir.setPath(qmPath);
11854 fileNames = dir.entryList(QStringList("scidavis_*.qm"));
11855 }
11856 for (int i = 0; i < (int)fileNames.size(); i++) {
11857 QString locale = fileNames[i];
11858 locale = locale.mid(locale.indexOf('_') + 1);
11859 locale.truncate(locale.indexOf('.'));
11860 locales.push_back(locale);
11861 }
11862 locales.push_back("en");
11863 locales.sort();
11864
11865 if (appLanguage != "en") {
11866 if (!appTranslator->load("scidavis_" + appLanguage, qmPath))
11867 if (!appTranslator->load("scidavis_" + appLanguage))
11868 if (!appTranslator->load("scidavis_" + lng, qmPath))
11869 if (!appTranslator->load("scidavis_" + lng))
11870 if (!appTranslator->load("scidavis_" + slng, qmPath))
11871 appTranslator->load("scidavis_" + slng);
11872 if (!qtTranslator->load("qt_" + appLanguage, qmPath + "/qt"))
11873 if (!qtTranslator->load("qt_" + appLanguage))
11874 if (!qtTranslator->load("qt_" + lng, qmPath + "/qt"))
11875 if (!qtTranslator->load("qt_" + lng))
11876 if (!qtTranslator->load("qt_" + slng, qmPath + "/qt"))
11877 qtTranslator->load("qt_" + slng);
11878 }
11879 }
11880
switchToLanguage(int param)11881 void ApplicationWindow::switchToLanguage(int param)
11882 {
11883 if (param < (int)locales.size())
11884 switchToLanguage(locales[param]);
11885 }
11886
switchToLanguage(const QString & locale)11887 void ApplicationWindow::switchToLanguage(const QString &locale)
11888 {
11889 if (!locales.contains(locale) || appLanguage == locale)
11890 return;
11891
11892 appLanguage = locale;
11893 if (locale == "en") {
11894 qApp->removeTranslator(appTranslator);
11895 qApp->removeTranslator(qtTranslator);
11896 delete appTranslator;
11897 delete qtTranslator;
11898 appTranslator = new QTranslator(this);
11899 qtTranslator = new QTranslator(this);
11900 qApp->installTranslator(appTranslator);
11901 qApp->installTranslator(qtTranslator);
11902 } else {
11903 if (!appTranslator->load("scidavis_" + appLanguage, qmPath))
11904 appTranslator->load("scidavis_" + appLanguage);
11905 if (!qtTranslator->load("qt_" + appLanguage, qmPath + "/qt"))
11906 qtTranslator->load("qt_" + appLanguage);
11907 }
11908 insertTranslatedStrings();
11909 }
11910
matrixNames()11911 QStringList ApplicationWindow::matrixNames()
11912 {
11913 QStringList names;
11914 QList<MyWidget *> windows = windowsList();
11915 foreach (MyWidget *w, windows) {
11916 if (w->inherits("Matrix"))
11917 names << static_cast<Matrix *>(w)->name();
11918 }
11919 return names;
11920 }
11921
alreadyUsedName(const QString & label)11922 bool ApplicationWindow::alreadyUsedName(const QString &label)
11923 {
11924 QList<MyWidget *> windows = windowsList();
11925 bool used = false;
11926 foreach (MyWidget *widget, windows) {
11927 if (widget && widget->name() == label) {
11928 used = true;
11929 break;
11930 }
11931 }
11932 return used;
11933 }
11934
projectHasMatrices()11935 bool ApplicationWindow::projectHasMatrices()
11936 {
11937 QList<MyWidget *> windows = windowsList();
11938 bool has = false;
11939 foreach (MyWidget *w, windows) {
11940 if (w->inherits("Matrix")) {
11941 has = true;
11942 break;
11943 }
11944 }
11945 return has;
11946 }
11947
projectHas2DPlots()11948 bool ApplicationWindow::projectHas2DPlots()
11949 {
11950 QList<MyWidget *> windows = windowsList();
11951 bool hasPlots = false;
11952 foreach (MyWidget *w, windows) {
11953 if (w->inherits("MultiLayer")) {
11954 hasPlots = true;
11955 break;
11956 }
11957 }
11958 return hasPlots;
11959 }
11960
projectHas3DPlots()11961 bool ApplicationWindow::projectHas3DPlots()
11962 {
11963 QList<MyWidget *> windows = windowsList();
11964 bool has3DPlots = false;
11965 foreach (MyWidget *w, windows) {
11966 if (w->inherits("Graph3D")) {
11967 has3DPlots = true;
11968 break;
11969 }
11970 }
11971 return has3DPlots;
11972 }
11973
appendProject()11974 void ApplicationWindow::appendProject()
11975 {
11976 OpenProjectDialog *open_dialog = new OpenProjectDialog(this, false);
11977 open_dialog->setDirectory(workingDir);
11978 open_dialog->setExtensionWidget(0);
11979 if (open_dialog->exec() != QDialog::Accepted || open_dialog->selectedFiles().isEmpty())
11980 return;
11981 workingDir = open_dialog->directory().path();
11982 appendProject(open_dialog->selectedFiles()[0]);
11983 }
11984
appendProject(const QString & fn)11985 void ApplicationWindow::appendProject(const QString &fn)
11986 {
11987 if (fn.isEmpty())
11988 return;
11989
11990 QFile *file;
11991
11992 QFileInfo fi(fn);
11993 workingDir = fi.absolutePath();
11994
11995 if (fn.contains(".sciprj") || fn.contains(".qti") || fn.contains(".opj", Qt::CaseInsensitive)
11996 || fn.contains(".ogm", Qt::CaseInsensitive) || fn.contains(".ogw", Qt::CaseInsensitive)
11997 || fn.contains(".ogg", Qt::CaseInsensitive) || fn.contains(".org", Qt::CaseInsensitive)) {
11998 QFileInfo f(fn);
11999 if (!f.exists()) {
12000 QMessageBox::critical(this, tr("File opening error"),
12001 tr("The file: <b>%1</b> doesn't exist!").arg(fn));
12002 return;
12003 }
12004 } else {
12005 QMessageBox::critical(
12006 this, tr("File opening error"),
12007 tr("The file: <b>%1</b> is not a SciDAVis or Origin project file!").arg(fn));
12008 return;
12009 }
12010
12011 if (fn.endsWith(".gz", Qt::CaseInsensitive) || fn.endsWith(".gz~", Qt::CaseInsensitive)) {
12012 file = openCompressedFile(fn);
12013 if (!file)
12014 return;
12015 } else {
12016 file = new QFile(fn);
12017 file->open(QIODevice::ReadOnly);
12018 }
12019
12020 recentProjects.removeAll(fn);
12021 recentProjects.push_front(fn);
12022 updateRecentProjectsList();
12023
12024 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
12025
12026 Folder *cf = current_folder;
12027 FolderListItem *item = (FolderListItem *)current_folder->folderListItem();
12028 folders.blockSignals(true);
12029 blockSignals(true);
12030
12031 QString baseName = fi.baseName();
12032 QStringList lst = current_folder->subfolders();
12033 int n = lst.count(baseName);
12034 if (n) { // avoid identical subfolder names
12035 while (lst.count(baseName + QString::number(n)))
12036 n++;
12037 baseName += QString::number(n);
12038 }
12039
12040 current_folder = ¤t_folder->addChild<Folder>(baseName);
12041 FolderListItem *fli = new FolderListItem(item, current_folder);
12042 current_folder->setFolderListItem(fli);
12043
12044 if (fn.contains(".opj", Qt::CaseInsensitive) || fn.contains(".ogm", Qt::CaseInsensitive)
12045 || fn.contains(".ogw", Qt::CaseInsensitive) || fn.contains(".ogg", Qt::CaseInsensitive)
12046 || fn.contains(".org", Qt::CaseInsensitive))
12047 #ifdef ORIGIN_IMPORT
12048 {
12049 auto codec = getSettings().value("/General/Dialogs/LastUsedOriginLocale", "").toString();
12050 ImportOPJ(this, fn, codec);
12051 }
12052 #else
12053 {
12054 QMessageBox::critical(
12055 this, tr("File opening error"),
12056 tr("SciDAVis currently does not support Origin import. If you are interested in "
12057 "reviving and maintaining an Origin import filter, contact the developers.")
12058 .arg(fn));
12059 return;
12060 }
12061 #endif
12062 else {
12063 QTextStream t(file);
12064 t.setCodec(QTextCodec::codecForName("UTF-8"));
12065
12066 QString s = t.readLine();
12067 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
12068 lst = s.split(QRegExp("\\s"), Qt::SkipEmptyParts);
12069 QString version = lst[1];
12070 lst = version.split(".", Qt::SkipEmptyParts);
12071 #else
12072 lst = s.split(QRegExp("\\s"), QString::SkipEmptyParts);
12073 QString version = lst[1];
12074 lst = version.split(".", QString::SkipEmptyParts);
12075 #endif
12076 if (fn.endsWith(".qti", Qt::CaseInsensitive) || fn.endsWith(".qti.gz", Qt::CaseInsensitive))
12077 d_file_version = 100 * (lst[0]).toInt() + 10 * (lst[1]).toInt() + (lst[2]).toInt();
12078 else
12079 d_file_version = ((lst[0]).toInt() << 16) + ((lst[1]).toInt() << 8) + (lst[2]).toInt();
12080
12081 t.readLine();
12082 if (d_file_version < 73)
12083 t.readLine();
12084
12085 // process tables and matrix information
12086 while (!t.atEnd()) {
12087 s = t.readLine(4096); // workaround for safely reading very big lines
12088 lst.clear();
12089 if (s.left(8) == "<folder>") {
12090 lst = s.split("\t");
12091 Folder &f = current_folder->addChild<Folder>(lst[1]);
12092 f.setBirthDate(lst[2]);
12093 f.setModificationDate(lst[3]);
12094 if (lst.count() > 4)
12095 if (lst[4] == "current")
12096 cf = &f;
12097
12098 FolderListItem *fli = new FolderListItem(current_folder->folderListItem(), &f);
12099 fli->setText(0, lst[1]);
12100 f.setFolderListItem(fli);
12101
12102 current_folder = &f;
12103 } else if (s == "<table>") {
12104 openTable(this, t);
12105 } else if (s == "<matrix>") {
12106 while (s != "</matrix>") {
12107 s = t.readLine();
12108 lst << s;
12109 }
12110 lst.pop_back();
12111 openMatrix(this, lst);
12112 } else if (s == "<note>") {
12113 for (int i = 0; i < 3; i++) {
12114 s = t.readLine();
12115 lst << s;
12116 }
12117 Note *m = openNote(this, lst);
12118 QStringList cont;
12119 while (s != "</note>") {
12120 s = t.readLine();
12121 cont << s;
12122 }
12123 cont.pop_back();
12124 m->restore(cont);
12125 } else if (s == "</folder>") {
12126 Folder *parent = (Folder *)current_folder->parent();
12127 if (!parent)
12128 current_folder = projectFolder();
12129 else
12130 current_folder = parent;
12131 }
12132 }
12133
12134 // process the rest
12135 t.seek(0);
12136
12137 MultiLayer *plot = 0;
12138 while (!t.atEnd()) {
12139 s = t.readLine(4096); // workaround for safely reading very big lines
12140 if (s.left(8) == "<folder>") {
12141 lst = s.split("\t");
12142 current_folder = current_folder->findSubfolder(lst[1]);
12143 } else if (s == "<multiLayer>") { // process multilayers information
12144 s = t.readLine();
12145 QStringList graph = s.split("\t");
12146 QString caption = graph[0];
12147 plot = multilayerPlot(caption);
12148 plot->setCols(graph[1].toInt());
12149 plot->setRows(graph[2].toInt());
12150 setListViewDate(caption, graph[3]);
12151 plot->setBirthDate(graph[3]);
12152 plot->blockSignals(true);
12153
12154 restoreWindowGeometry(this, plot, t.readLine());
12155
12156 if (d_file_version > 71) {
12157 QStringList lst = t.readLine().split("\t");
12158 plot->setWindowLabel(lst[1]);
12159 setListViewLabel(plot->name(), lst[1]);
12160 plot->setCaptionPolicy((MyWidget::CaptionPolicy)lst[2].toInt());
12161 }
12162
12163 if (d_file_version > 83) {
12164 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
12165 QStringList lst = t.readLine().split("\t", Qt::SkipEmptyParts);
12166 plot->setMargins(lst[1].toInt(), lst[2].toInt(), lst[3].toInt(),
12167 lst[4].toInt());
12168 lst = t.readLine().split("\t", Qt::SkipEmptyParts);
12169 plot->setSpacing(lst[1].toInt(), lst[2].toInt());
12170 lst = t.readLine().split("\t", Qt::SkipEmptyParts);
12171 plot->setLayerCanvasSize(lst[1].toInt(), lst[2].toInt());
12172 lst = t.readLine().split("\t", Qt::SkipEmptyParts);
12173 plot->setAlignement(lst[1].toInt(), lst[2].toInt());
12174 #else
12175 QStringList lst = t.readLine().split("\t", QString::SkipEmptyParts);
12176 plot->setMargins(lst[1].toInt(), lst[2].toInt(), lst[3].toInt(),
12177 lst[4].toInt());
12178 lst = t.readLine().split("\t", QString::SkipEmptyParts);
12179 plot->setSpacing(lst[1].toInt(), lst[2].toInt());
12180 lst = t.readLine().split("\t", QString::SkipEmptyParts);
12181 plot->setLayerCanvasSize(lst[1].toInt(), lst[2].toInt());
12182 lst = t.readLine().split("\t", QString::SkipEmptyParts);
12183 plot->setAlignement(lst[1].toInt(), lst[2].toInt());
12184 #endif
12185 }
12186
12187 while (s != "</multiLayer>") { // open layers
12188 s = t.readLine();
12189 if (s.left(7) == "<graph>") {
12190 lst.clear();
12191 while (s != "</graph>") {
12192 s = t.readLine();
12193 lst << s;
12194 }
12195 openGraph(this, plot, lst);
12196 }
12197 }
12198 plot->blockSignals(false);
12199 } else if (s == "<SurfacePlot>") { // process 3D plots information
12200 lst.clear();
12201 while (s != "</SurfacePlot>") {
12202 s = t.readLine();
12203 lst << s;
12204 }
12205 openSurfacePlot(this, lst);
12206 } else if (s == "</folder>") {
12207 Folder *parent = (Folder *)current_folder->parent();
12208 if (!parent)
12209 current_folder = projectFolder();
12210 else
12211 current_folder = parent;
12212 }
12213 }
12214 file->close();
12215 delete file;
12216 }
12217
12218 folders.blockSignals(false);
12219 // change folder to user defined current folder
12220 changeFolder(cf);
12221 blockSignals(false);
12222 renamedTables = QStringList();
12223 QApplication::restoreOverrideCursor();
12224 }
12225
rawSaveFolder(Folder * folder,QIODevice * device)12226 void ApplicationWindow::rawSaveFolder(Folder *folder, QIODevice *device)
12227 {
12228 QTextStream stream(device);
12229 stream.setCodec(QTextCodec::codecForName("UTF-8"));
12230 foreach (MyWidget *w, folder->windowsList()) {
12231 Table *t = qobject_cast<Table *>(w);
12232 if (t)
12233 t->saveToDevice(device, windowGeometryInfo(w));
12234 else
12235 stream << w->saveToString(windowGeometryInfo(w));
12236 }
12237 foreach (Folder *subfolder, folder->folders()) {
12238 stream << "<folder>\t" + QString(subfolder->name()) + "\t" + subfolder->birthDate() + "\t"
12239 + subfolder->modificationDate();
12240 if (subfolder == current_folder)
12241 stream << "\tcurrent\n";
12242 else
12243 stream << "\n"; // FIXME: Having no 5th string here is not a good idea
12244 stream.flush();
12245 rawSaveFolder(subfolder, device);
12246 stream << "</folder>\n";
12247 }
12248 }
12249
saveFolder(Folder * folder,const QString & fn)12250 void ApplicationWindow::saveFolder(Folder *folder, const QString &fn)
12251 {
12252 // file saving procedure follows
12253 // https://bugs.launchpad.net/ubuntu/+source/linux/+bug/317781/comments/54
12254 QFile f(fn + ".new");
12255 while (!f.open(QIODevice::WriteOnly)) {
12256 if (f.isOpen())
12257 f.close();
12258 // The following message is slightly misleading, since it may be that fn.new can't be opened
12259 // _at_all_. However, changing this would break translations, in a bugfix release.
12260 // TODO: rephrase message for next minor release
12261 switch (QMessageBox::critical(
12262 this, tr("File save error"),
12263 tr("The file: <br><b>%1</b> is opened in read-only mode").arg(fn + ".new"),
12264 QMessageBox::Retry | QMessageBox::Default,
12265 QMessageBox::Abort | QMessageBox::Escape)) {
12266 case QMessageBox::Abort:
12267 return;
12268 }
12269 }
12270
12271 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
12272
12273 QTextStream t(&f);
12274 t.setCodec(QTextCodec::codecForName("UTF-8"));
12275 t << SciDAVis::schemaVersion() + " project file\n";
12276 t << "<scripting-lang>\t" + QString(scriptEnv->objectName()) + "\n";
12277 t << "<windows>\t" + QString::number(folder->windowCount(true)) + "\n";
12278 t.flush();
12279 rawSaveFolder(folder, &f);
12280 t << "<log>\n" + logInfo + "</log>";
12281
12282 // second part of secure file saving (see comment at the start of this method)
12283 #ifdef Q_OS_WIN
12284 // this one was taken from
12285 // http://support.microsoft.com/kb/148505/en-us
12286 // http://msdn.microsoft.com/en-us/library/17618685(VS.80).aspx
12287 if (!f.flush() || _commit(f.handle()) != 0) {
12288 #else
12289 if (!f.flush() || fsync(f.handle()) != 0) {
12290 #endif
12291 QApplication::restoreOverrideCursor();
12292 QMessageBox::critical(
12293 this, tr("Error writing data to disk"),
12294 tr("<html>%1<br><br>Your data may or may not have ended up in <em>%2</em> (%3). \
12295 If there already was a version of this project on disk, it has not been touched.</html>")
12296 .arg(QString::fromLocal8Bit(strerror(errno)))
12297 .arg(fn + ".new")
12298 .arg(f.handle()));
12299 f.close();
12300 return;
12301 }
12302 f.close();
12303 #ifdef Q_OS_WIN
12304 // unfortunately, Windows doesn't support atomic renames; so Windows users will have to live
12305 // with the risk of losing the file in case of a crash between remove and rename
12306 if ((QFile::exists(fn)
12307 && ((QFile::exists(fn + "~") && !QFile::remove(fn + "~")) || !QFile::rename(fn, fn + "~")))
12308 || !QFile::rename(fn + ".new", fn)) {
12309 #else
12310 // we want to atomically replace existing files, so we can't use QFile::rename()
12311 if ((QFile::exists(fn) && rename(QFile::encodeName(fn), QFile::encodeName(fn + "~")) != 0)
12312 || rename(QFile::encodeName(fn + ".new"), QFile::encodeName(fn)) != 0) {
12313 #endif
12314 QApplication::restoreOverrideCursor();
12315 QMessageBox::critical(
12316 this, tr("Error renaming backup files"),
12317 tr("<html>%1<br><br>Data was written to <em>%2</em>, but saving the original file as <em>%3</em>\
12318 and moving the new file to <em>%4</em> failed. In case you wonder why the original file hasn't\
12319 been simply replaced, see here:\
12320 <a href=\"http://bugs.launchpad.net/ubuntu/+source/linux/+bug/317781/comments/54\">\
12321 http://bugs.launchpad.net/ubuntu/+source/linux/+bug/317781/comments/54</a>.</html>")
12322 .arg(QString::fromLocal8Bit(strerror(errno)))
12323 .arg(fn + ".new")
12324 .arg(fn + "~")
12325 .arg(fn));
12326 return;
12327 }
12328
12329 QApplication::restoreOverrideCursor();
12330 }
12331
12332 void ApplicationWindow::saveAsProject()
12333 {
12334 saveFolderAsProject(current_folder);
12335 }
12336
12337 void ApplicationWindow::saveFolderAsProject(Folder *f)
12338 {
12339 QString filter = tr("SciDAVis project") + " (*.sciprj);;";
12340 filter += tr("Compressed SciDAVis project") + " (*.sciprj.gz)";
12341
12342 QString selectedFilter;
12343 QString fn = QFileDialog::getSaveFileName(this, tr("Save project as"), workingDir, filter,
12344 &selectedFilter);
12345 if (!fn.isEmpty()) {
12346 QFileInfo fi(fn);
12347 workingDir = fi.absolutePath();
12348 QString baseName = fi.fileName();
12349 if (!baseName.endsWith(".sciprj") && !baseName.endsWith(".sciprj.gz")) {
12350 fn.append(".sciprj");
12351 }
12352 bool compress = false;
12353 if (fn.endsWith(".gz")) {
12354 fn = fn.left(fn.length() - 3);
12355 compress = true;
12356 }
12357
12358 saveFolder(f, fn);
12359 if (selectedFilter.contains(".gz") || compress)
12360 file_compress(QFile::encodeName(fn).constData(), "wb9");
12361 }
12362 }
12363
12364 void ApplicationWindow::showFolderPopupMenu(const QPoint &p, bool fromFolders)
12365 {
12366 QMenu *cm = nullptr;
12367 if (fromFolders) {
12368 cm = showFolderPopupMenuImpl(folders.itemAt(p), fromFolders);
12369 if (cm)
12370 cm->exec(folders.mapToGlobal(p));
12371 } else {
12372 cm = showFolderPopupMenuImpl(lv.itemAt(p), fromFolders);
12373 if (cm)
12374 cm->exec(lv.mapToGlobal(p));
12375 }
12376 }
12377
12378 QMenu *ApplicationWindow::showFolderPopupMenuImpl(QTreeWidgetItem *it, bool fromFolders)
12379 {
12380 if (!it || folders.isRenaming())
12381 return nullptr;
12382
12383 QMenu *cm = new QMenu(this);
12384 cm->addAction(tr("&Find..."), this, SLOT(showFindDialogue()));
12385 cm->addSeparator();
12386 cm->addAction(tr("App&end Project..."), this, SLOT(appendProject()));
12387 if (((FolderListItem *)it)->folder()->parent())
12388 cm->addAction(tr("Save &As Project..."), this, SLOT(saveAsProject()));
12389 else
12390 cm->addAction(tr("Save Project &As..."), this, SLOT(saveProjectAs()));
12391 cm->addSeparator();
12392
12393 if (fromFolders && show_windows_policy != HideAll) {
12394 cm->addAction(tr("&Show All Windows"), this, SLOT(showAllFolderWindows()));
12395 cm->addAction(tr("&Hide All Windows"), this, SLOT(hideAllFolderWindows()));
12396 cm->addSeparator();
12397 }
12398
12399 if (((FolderListItem *)it)->folder()->parent()) {
12400 cm->addAction(QPixmap(":/close.xpm"), tr("&Delete Folder"), this, SLOT(deleteFolder()),
12401 Qt::Key_F8);
12402 cm->addAction(tr("&Rename"), this, SLOT(startRenameFolder()), Qt::Key_F2);
12403 cm->addSeparator();
12404 }
12405
12406 if (fromFolders) {
12407 QMenu *window = cm->addMenu(tr("New &Window"));
12408 window->addAction(actionNewTable);
12409 window->addAction(actionNewMatrix);
12410 window->addAction(actionNewNote);
12411 window->addAction(actionNewGraph);
12412 window->addAction(actionNewFunctionPlot);
12413 window->addAction(actionNewSurfacePlot);
12414 }
12415
12416 cm->addAction(QPixmap(":/newfolder.xpm"), tr("New F&older"), this, SLOT(addFolder()),
12417 Qt::Key_F7);
12418 cm->addSeparator();
12419
12420 QMenu *viewWindowsMenu = cm->addMenu(tr("&View Windows"));
12421 QStringList lst;
12422 lst << tr("&None") << tr("&Windows in Active Folder")
12423 << tr("Windows in &Active Folder && Subfolders");
12424 for (int i = 0; i < 3; ++i) {
12425 QAction *actId = viewWindowsMenu->addAction(lst[i], this, SLOT(setShowWindowsPolicy(bool)));
12426 actId->setData(i);
12427 actId->setCheckable(true);
12428 actId->setChecked(show_windows_policy == i);
12429 }
12430 cm->addSeparator();
12431 cm->addAction(tr("&Properties..."), this, SLOT(folderProperties()));
12432 return cm;
12433 }
12434
12435 void ApplicationWindow::setShowWindowsPolicy(bool checked)
12436 {
12437 Q_UNUSED(checked)
12438
12439 QAction *act = qobject_cast<QAction *>(sender());
12440 if (!act)
12441 return;
12442 int p = act->data().toInt();
12443
12444 if (show_windows_policy == (ShowWindowsPolicy)p)
12445 return;
12446
12447 show_windows_policy = (ShowWindowsPolicy)p;
12448 if (show_windows_policy == HideAll) {
12449 QList<MyWidget *> lst = windowsList();
12450 foreach (MyWidget *widget, lst) {
12451 if (!widget)
12452 continue;
12453 hiddenWindows.append(widget);
12454 widget->hide();
12455 setListView(widget->name(), tr("Hidden"));
12456 }
12457 } else
12458 showAllFolderWindows();
12459 }
12460
12461 void ApplicationWindow::showFindDialogue()
12462 {
12463 FindDialog *fd = new FindDialog(this);
12464 fd->setAttribute(Qt::WA_DeleteOnClose);
12465 fd->exec();
12466 }
12467
12468 void ApplicationWindow::startRenameFolder()
12469 {
12470 FolderListItem *fi = current_folder->folderListItem();
12471 if (!fi)
12472 return;
12473
12474 disconnect(&folders, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), this,
12475 SLOT(folderItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
12476 fi->setFlags(fi->flags() | Qt::ItemIsEditable);
12477 fi->treeWidget()->editItem(fi, 0);
12478 }
12479
12480 void ApplicationWindow::startRenameFolder(QTreeWidgetItem *item, int column)
12481 {
12482 if (!item || item == folders.topLevelItem(0))
12483 return;
12484
12485 if (item->treeWidget() == &lv && item->type() == FolderListItem::FolderType) {
12486 disconnect(
12487 &folders,
12488 SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *, QTreeWidgetItem *)),
12489 this, SLOT(folderItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
12490 current_folder = ((FolderListItem *)item)->folder();
12491 FolderListItem *it = current_folder->folderListItem();
12492 it->treeWidget()->setCurrentItem(it, 0);
12493 it->setFlags(it->flags() | Qt::ItemIsEditable);
12494 it->treeWidget()->editItem(it, column);
12495 } else {
12496 item->setFlags(item->flags() | Qt::ItemIsEditable);
12497 item->treeWidget()->editItem(item, 0);
12498 item->setFlags(item->flags() & ~Qt::ItemIsEditable);
12499 }
12500 }
12501
12502 void ApplicationWindow::renameFolder(QTreeWidgetItem *it, int col, const QString &text)
12503 {
12504 Q_UNUSED(col)
12505
12506 if (!it)
12507 return;
12508
12509 if (it->text(0) == text)
12510 return;
12511
12512 Folder *parent = (Folder *)current_folder->parent();
12513 if (!parent) // the parent folder is the project folder (it always exists)
12514 parent = projectFolder();
12515
12516 if (text.isEmpty()) {
12517 QMessageBox::critical(this, tr("Error"), tr("Please enter a valid name!"));
12518 it->setFlags(it->flags() | Qt::ItemIsEditable);
12519 return;
12520 }
12521
12522 QStringList lst = parent->subfolders();
12523 lst.removeAll(current_folder->name());
12524 while (lst.contains(text)) {
12525 QMessageBox::critical(this, tr("Error"),
12526 tr("Name already exists!") + "\n"
12527 + tr("Please choose another name!"));
12528
12529 it->setFlags(it->flags() | Qt::ItemIsEditable);
12530 it->setText(0, current_folder->name());
12531 it->treeWidget()->editItem(it, 0);
12532 return;
12533 }
12534
12535 current_folder->setName(text);
12536 it->setText(0, text);
12537 it->setFlags(it->flags() & ~Qt::ItemIsEditable);
12538 connect(&folders, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), this,
12539 SLOT(folderItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
12540 folders.scrollToItem(parent->folderListItem(), QAbstractItemView::EnsureVisible);
12541 folders.setCurrentItem(parent->folderListItem()); // update the list views
12542 }
12543
12544 void ApplicationWindow::showAllFolderWindows()
12545 {
12546 QList<MyWidget *> lst = current_folder->windowsList();
12547 foreach (MyWidget *w, lst) { // force show all windows in current folder
12548 if (w) {
12549 updateWindowLists(w);
12550 switch (w->status()) {
12551 case MyWidget::Hidden:
12552 w->showNormal();
12553 break;
12554
12555 case MyWidget::Normal:
12556 w->showNormal();
12557 break;
12558
12559 case MyWidget::Minimized:
12560 w->showMinimized();
12561 break;
12562
12563 case MyWidget::Maximized:
12564 w->showMaximized();
12565 break;
12566 }
12567 }
12568 }
12569
12570 if ((current_folder->children()).isEmpty())
12571 return;
12572
12573 FolderListItem *fi = current_folder->folderListItem();
12574 FolderListItem *item = (FolderListItem *)fi->child(0);
12575 int initial_depth = item->depth();
12576 QTreeWidgetItemIterator it(item);
12577 while (item && item->depth() >= initial_depth) { // show/hide windows in all subfolders
12578 lst = ((Folder *)item->folder())->windowsList();
12579 foreach (MyWidget *w, lst) {
12580 if (w && show_windows_policy == SubFolders) {
12581 updateWindowLists(w);
12582 switch (w->status()) {
12583 case MyWidget::Hidden:
12584 w->showNormal();
12585 break;
12586
12587 case MyWidget::Normal:
12588 w->showNormal();
12589 break;
12590
12591 case MyWidget::Minimized:
12592 w->showMinimized();
12593 break;
12594
12595 case MyWidget::Maximized:
12596 w->showMaximized();
12597 break;
12598 }
12599 } else
12600 w->hide();
12601 }
12602
12603 it++;
12604 item = (FolderListItem *)(*it);
12605 }
12606 }
12607
12608 void ApplicationWindow::hideAllFolderWindows()
12609 {
12610 QList<MyWidget *> lst = current_folder->windowsList();
12611 foreach (MyWidget *w, lst)
12612 hideWindow(w);
12613
12614 if ((current_folder->children()).isEmpty())
12615 return;
12616
12617 if (show_windows_policy == SubFolders) {
12618 FolderListItem *fi = current_folder->folderListItem();
12619 FolderListItem *item = (FolderListItem *)fi->child(0);
12620 int initial_depth = item->depth();
12621 QTreeWidgetItemIterator it(item);
12622 while (item && item->depth() >= initial_depth) {
12623 lst = item->folder()->windowsList();
12624 foreach (MyWidget *w, lst)
12625 hideWindow(w);
12626
12627 it++;
12628 item = (FolderListItem *)(*it);
12629 }
12630 }
12631 }
12632
12633 void ApplicationWindow::projectProperties()
12634 {
12635 QString s = QString(current_folder->name()) + "\n\n";
12636 s += "\n\n\n";
12637 s += tr("Type") + ": " + tr("Project") + "\n\n";
12638 if (projectname != "untitled") {
12639 s += tr("Path") + ": " + projectname + "\n\n";
12640
12641 QFileInfo fi(projectname);
12642 s += tr("Size") + ": " + QString::number(fi.size()) + " " + tr("bytes") + "\n\n";
12643 }
12644
12645 s += tr("Contents") + ": " + QString::number(windowsList().count()) + " " + tr("windows");
12646
12647 s += ", " + QString::number(current_folder->subfolders().count()) + " " + tr("folders")
12648 + "\n\n";
12649 s += "\n\n\n";
12650
12651 if (projectname != "untitled") {
12652 QFileInfo fi(projectname);
12653 #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
12654 s += tr("Created") + ": " + QLocale().toString(fi.created()) + "\n\n";
12655 #else
12656 s += tr("Created") + ": " + QLocale().toString(fi.birthTime()) + "\n\n";
12657 #endif
12658 s += tr("Modified") + ": " + QLocale().toString(fi.lastModified()) + "\n\n";
12659 } else
12660 s += tr("Created") + ": " + current_folder->birthDate() + "\n\n";
12661
12662 QMessageBox *mbox = new QMessageBox(tr("Properties"), s, QMessageBox::NoIcon, QMessageBox::Ok,
12663 QMessageBox::NoButton, QMessageBox::NoButton, this);
12664
12665 mbox->setIconPixmap(QPixmap(":/appicon"));
12666 mbox->show();
12667 }
12668
12669 void ApplicationWindow::folderProperties()
12670 {
12671 if (!current_folder->parent()) {
12672 projectProperties();
12673 return;
12674 }
12675
12676 QString s = current_folder->name() + "\n\n";
12677 s += "\n\n\n";
12678 s += tr("Type") + ": " + tr("Folder") + "\n\n";
12679 s += tr("Path") + ": " + current_folder->path() + "\n\n";
12680 s += tr("Contents") + ": " + QString::number(current_folder->windowsList().count()) + " "
12681 + tr("windows");
12682 s += ", " + QString::number(current_folder->subfolders().count()) + " " + tr("folders")
12683 + "\n\n";
12684 // s += "\n\n\n";
12685 s += tr("Created") + ": " + current_folder->birthDate() + "\n\n";
12686 // s += tr("Modified") + ": " + current_folder->modificationDate() + "\n\n";
12687
12688 QMessageBox *mbox = new QMessageBox(tr("Properties"), s, QMessageBox::NoIcon, QMessageBox::Ok,
12689 QMessageBox::NoButton, QMessageBox::NoButton, this);
12690
12691 mbox->setIconPixmap(QPixmap(":/folder_open.xpm"));
12692 mbox->show();
12693 }
12694
12695 void ApplicationWindow::addFolder()
12696 {
12697 QStringList lst = current_folder->subfolders();
12698 QString name = tr("New Folder");
12699 lst = lst.filter(name);
12700 if (!lst.isEmpty())
12701 name += " (" + QString::number(lst.size() + 1) + ")";
12702
12703 Folder &f = current_folder->addChild<Folder>(name);
12704 addFolderListViewItem(&f);
12705
12706 FolderListItem *fi = new FolderListItem(current_folder->folderListItem(), &f);
12707 f.setFolderListItem(fi);
12708 fi->setFlags(fi->flags() | Qt::ItemIsEditable);
12709 fi->treeWidget()->setCurrentItem(fi, 0);
12710 fi->treeWidget()->editItem(fi, 0);
12711 fi->treeWidget()->resizeColumnToContents(0);
12712 }
12713
12714 bool ApplicationWindow::deleteFolder(Folder *f)
12715 {
12716 if (confirmCloseFolder
12717 && QMessageBox::information(
12718 this, tr("Delete folder?"),
12719 tr("Delete folder '%1' and all the windows it contains?").arg(f->name()), tr("Yes"),
12720 tr("No"), 0, 0)) {
12721 return false;
12722 } else {
12723 FolderListItem *fi = f->folderListItem();
12724 foreach (MyWidget *w, f->windowsList())
12725 closeWindow(w);
12726
12727 if (!(f->children()).isEmpty()) {
12728 FolderListItem *item = (FolderListItem *)fi->child(0);
12729 int initial_depth = item->depth();
12730 QTreeWidgetItemIterator it(item);
12731 while (item && item->depth() >= initial_depth) {
12732 Folder *subFolder = (Folder *)item->folder();
12733 if (subFolder) {
12734 foreach (MyWidget *w, subFolder->windowsList()) {
12735 removeWindowFromLists(w);
12736 subFolder->removeWindow(w);
12737 delete w;
12738 }
12739
12740 FolderListItem *old_item = item;
12741 it++;
12742 item = (FolderListItem *)(*it);
12743 delete subFolder;
12744 delete old_item;
12745 }
12746 }
12747 }
12748
12749 delete f;
12750 delete fi;
12751 return true;
12752 }
12753 }
12754
12755 void ApplicationWindow::deleteFolder()
12756 {
12757 Folder *parent = (Folder *)current_folder->parent();
12758 if (!parent)
12759 parent = projectFolder();
12760
12761 folders.blockSignals(true);
12762
12763 if (deleteFolder(current_folder)) {
12764 current_folder = parent;
12765 folders.setCurrentItem(parent->folderListItem());
12766 changeFolder(parent, true);
12767 }
12768
12769 folders.blockSignals(false);
12770 folders.setFocus();
12771 }
12772
12773 void ApplicationWindow::folderItemDoubleClicked(QTreeWidgetItem *it, int column)
12774 {
12775 Q_UNUSED(column)
12776 if (!it)
12777 return;
12778
12779 if (it->type() == FolderListItem::FolderType) {
12780 FolderListItem *item = ((FolderListItem *)it)->folder()->folderListItem();
12781 folders.setCurrentItem(item);
12782 } else if (it->type() == WindowListItem::WindowType) {
12783 MyWidget *w = ((WindowListItem *)it)->window();
12784 if (!w)
12785 return;
12786 if (d_workspace.activeSubWindow() != w)
12787 activateSubWindow(w);
12788 else {
12789 if (!w->isMaximized())
12790 w->setMaximized();
12791 else
12792 w->setNormal();
12793 }
12794 }
12795 }
12796
12797 void ApplicationWindow::folderItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
12798 {
12799 Q_UNUSED(previous)
12800
12801 if (!current)
12802 return;
12803
12804 if (current == previous)
12805 return;
12806
12807 current->setExpanded(true);
12808 changeFolder(((FolderListItem *)current)->folder());
12809 folders.scrollToItem(folders.currentItem(), QAbstractItemView::EnsureVisible);
12810 folders.setFocus();
12811 }
12812
12813 void ApplicationWindow::hideFolderWindows(Folder *f)
12814 {
12815 QList<MyWidget *> lst = f->windowsList();
12816 foreach (MyWidget *w, lst)
12817 w->hide();
12818
12819 if ((f->children()).isEmpty())
12820 return;
12821
12822 FolderListItem *fi = f->folderListItem();
12823 FolderListItem *item = (FolderListItem *)fi->child(0);
12824 if (!item)
12825 return;
12826 int initial_depth = item->depth();
12827 QTreeWidgetItemIterator it(item);
12828 while (item && item->depth() >= initial_depth) {
12829 lst = item->folder()->windowsList();
12830 foreach (MyWidget *w, lst)
12831 w->hide();
12832 it++;
12833 item = (FolderListItem *)(*it);
12834 }
12835 }
12836
12837 bool ApplicationWindow::changeFolder(Folder *newFolder, bool force)
12838 {
12839 if (current_folder == newFolder && !force)
12840 return false;
12841
12842 deactivateFolders();
12843 newFolder->folderListItem()->setActive(true);
12844
12845 Folder *oldFolder = current_folder;
12846 MyWidget::Status old_active_window_state = MyWidget::Normal;
12847 MyWidget *old_active_window = oldFolder->activeWindow();
12848 if (old_active_window)
12849 old_active_window_state = old_active_window->status();
12850
12851 MyWidget::Status active_window_state = MyWidget::Normal;
12852 MyWidget *active_window = newFolder->activeWindow();
12853 if (active_window)
12854 active_window_state = active_window->status();
12855
12856 d_workspace.blockSignals(true);
12857 hideFolderWindows(oldFolder);
12858 current_folder = newFolder;
12859
12860 lv.clear();
12861
12862 QObjectList folderLst = newFolder->children();
12863 if (!folderLst.isEmpty()) {
12864 foreach (QObject *f, folderLst)
12865 addFolderListViewItem(static_cast<Folder *>(f));
12866 }
12867
12868 QList<MyWidget *> lst = newFolder->windowsList();
12869 foreach (MyWidget *w, lst) {
12870 w->blockSignals(true);
12871 if (!hiddenWindows.contains(w) && !outWindows.contains(w)
12872 && show_windows_policy != HideAll) {
12873 // show only windows in the current folder which are not hidden by the user
12874 if (w->status() == MyWidget::Normal)
12875 w->showNormal();
12876 else if (w->status() == MyWidget::Minimized)
12877 w->showMinimized();
12878 } else
12879 w->setStatus(MyWidget::Hidden);
12880
12881 addListViewItem(w);
12882 }
12883
12884 if (!(newFolder->children()).isEmpty()) {
12885 FolderListItem *fi = newFolder->folderListItem();
12886 FolderListItem *item = (FolderListItem *)fi->child(0);
12887 if (!item)
12888 return false;
12889 int initial_depth = item->depth();
12890 QTreeWidgetItemIterator it(item);
12891 while (item && item->depth() >= initial_depth) { // show/hide windows in subfolders
12892 lst = ((Folder *)item->folder())->windowsList();
12893 foreach (MyWidget *w, lst) {
12894 if (!hiddenWindows.contains(w) && !outWindows.contains(w)) {
12895 if (show_windows_policy == SubFolders) {
12896 if (w->status() == MyWidget::Normal || w->status() == MyWidget::Maximized)
12897 w->showNormal();
12898 else if (w->status() == MyWidget::Minimized)
12899 w->showMinimized();
12900 } else if (w->isVisible())
12901 w->hide();
12902 }
12903 }
12904 it++;
12905 item = (FolderListItem *)(*it);
12906 }
12907 }
12908
12909 d_workspace.blockSignals(false);
12910
12911 if (active_window) {
12912 d_workspace.setActiveSubWindow(active_window);
12913 if (active_window_state == MyWidget::Minimized)
12914 active_window->showMinimized(); // d_workspace.setActiveWindow() makes minimized windows
12915 // to be shown normally
12916 else if (active_window_state == MyWidget::Maximized) {
12917 if (active_window->inherits("Graph3D"))
12918 ((Graph3D *)active_window)->setIgnoreFonts(true);
12919 active_window->showMaximized();
12920 if (active_window->inherits("Graph3D"))
12921 ((Graph3D *)active_window)->setIgnoreFonts(false);
12922 }
12923 current_folder->setActiveWindow(active_window);
12924 customMenu(active_window);
12925 customToolBars(active_window);
12926 }
12927
12928 if (old_active_window) {
12929 old_active_window->setStatus(old_active_window_state);
12930 oldFolder->setActiveWindow(old_active_window);
12931 }
12932
12933 foreach (MyWidget *w, newFolder->windowsList())
12934 w->blockSignals(false);
12935
12936 return true;
12937 }
12938
12939 void ApplicationWindow::deactivateFolders()
12940 {
12941 QTreeWidgetItemIterator it(&folders);
12942 while (*it) {
12943 ((FolderListItem *)(*it))->setActive(false);
12944 it++;
12945 }
12946 }
12947
12948 void ApplicationWindow::addListViewItem(MyWidget *w)
12949 {
12950 if (!w)
12951 return;
12952
12953 WindowListItem *it = new WindowListItem(&lv, w);
12954 if (w->inherits("Matrix")) {
12955 it->setIcon(0, QIcon(QPixmap(":/matrix.xpm")));
12956 it->setText(1, tr("Matrix"));
12957 } else if (w->inherits("Table")) {
12958 it->setIcon(0, QIcon(QPixmap(":/worksheet.xpm")));
12959 it->setText(1, tr("Table"));
12960 } else if (w->inherits("Note")) {
12961 it->setIcon(0, QIcon(QPixmap(":/note.xpm")));
12962 it->setText(1, tr("Note"));
12963 } else if (w->inherits("MultiLayer")) {
12964 it->setIcon(0, QIcon(QPixmap(":/graph.xpm")));
12965 it->setText(1, tr("Graph"));
12966 } else if (w->inherits("Graph3D")) {
12967 it->setIcon(0, QIcon(QPixmap(":/trajectory.xpm")));
12968 it->setText(1, tr("3D Graph"));
12969 }
12970
12971 it->setText(0, w->name());
12972 it->setText(2, w->aspect());
12973 it->setText(3, w->birthDate());
12974 it->setText(4, w->windowLabel());
12975 }
12976
12977 void ApplicationWindow::windowProperties()
12978 {
12979 WindowListItem *it = (WindowListItem *)lv.currentItem();
12980 MyWidget *w = it->window();
12981 if (!w)
12982 return;
12983
12984 QMessageBox *mbox =
12985 new QMessageBox(tr("Properties"), QString(), QMessageBox::NoIcon, QMessageBox::Ok,
12986 QMessageBox::NoButton, QMessageBox::NoButton, this);
12987
12988 QString s = QString(w->name()) + "\n\n";
12989 s += "\n\n\n";
12990
12991 s += tr("Label") + ": " + ((MyWidget *)w)->windowLabel() + "\n\n";
12992
12993 if (w->inherits("Matrix")) {
12994 mbox->setIconPixmap(QPixmap(":/matrix.xpm"));
12995 s += tr("Type") + ": " + tr("Matrix") + "\n\n";
12996 } else if (w->inherits("Table")) {
12997 mbox->setIconPixmap(QPixmap(":/worksheet.xpm"));
12998 s += tr("Type") + ": " + tr("Table") + "\n\n";
12999 } else if (w->inherits("Note")) {
13000 mbox->setIconPixmap(QPixmap(":/note.xpm"));
13001 s += tr("Type") + ": " + tr("Note") + "\n\n";
13002 } else if (w->inherits("MultiLayer")) {
13003 mbox->setIconPixmap(QPixmap(":/graph.xpm"));
13004 s += tr("Type") + ": " + tr("Graph") + "\n\n";
13005 } else if (w->inherits("Graph3D")) {
13006 mbox->setIconPixmap(QPixmap(":/trajectory.xpm"));
13007 s += tr("Type") + ": " + tr("3D Graph") + "\n\n";
13008 }
13009 s += tr("Path") + ": " + current_folder->path() + "\n\n";
13010 s += tr("Created") + ": " + w->birthDate() + "\n\n";
13011 s += tr("Status") + ": " + it->text(2) + "\n\n";
13012 mbox->setText(s);
13013 mbox->show();
13014 }
13015
13016 void ApplicationWindow::addFolderListViewItem(Folder *f)
13017 {
13018 if (!f)
13019 return;
13020
13021 FolderListItem *it = new FolderListItem(&lv, f);
13022 it->setActive(false);
13023 it->setText(0, f->name());
13024 it->setText(1, tr("Folder"));
13025 it->setText(3, f->birthDate());
13026 }
13027
13028 void ApplicationWindow::find(const QString &s, bool windowNames, bool labels, bool folderNames,
13029 bool caseSensitive, bool partialMatch, bool subfolders)
13030 {
13031 if (windowNames || labels) {
13032 MyWidget *w =
13033 current_folder->findWindow(s, windowNames, labels, caseSensitive, partialMatch);
13034 if (w) {
13035 activateSubWindow(w);
13036 return;
13037 }
13038
13039 if (subfolders) {
13040 FolderListItem *item = (FolderListItem *)folders.currentItem()->child(0);
13041 QTreeWidgetItemIterator it(item);
13042 while (item) {
13043 Folder *f = item->folder();
13044 MyWidget *w = f->findWindow(s, windowNames, labels, caseSensitive, partialMatch);
13045 if (w) {
13046 folders.setCurrentItem(f->folderListItem());
13047 activateSubWindow(w);
13048 return;
13049 }
13050 it++;
13051 item = (FolderListItem *)(*it);
13052 }
13053 }
13054 }
13055
13056 if (folderNames) {
13057 Folder *f = current_folder->findSubfolder(s, caseSensitive, partialMatch);
13058 if (f) {
13059 folders.setCurrentItem(f->folderListItem());
13060 return;
13061 }
13062
13063 if (subfolders) {
13064 FolderListItem *item = (FolderListItem *)folders.currentItem()->child(0);
13065 QTreeWidgetItemIterator it(item);
13066 while (item) {
13067 Folder *f = item->folder()->findSubfolder(s, caseSensitive, partialMatch);
13068 if (f) {
13069 folders.setCurrentItem(f->folderListItem());
13070 return;
13071 }
13072
13073 it++;
13074 item = (FolderListItem *)(*it);
13075 }
13076 }
13077 }
13078
13079 QMessageBox::warning(this, tr("No match found"),
13080 tr("Sorry, no match found for string: '%1'").arg(s));
13081 }
13082
13083 void ApplicationWindow::dropFolderItems(QTreeWidgetItem *dest)
13084 {
13085 if (!dest || draggedItems.isEmpty())
13086 return;
13087
13088 Folder *dest_f = ((FolderListItem *)dest)->folder();
13089
13090 QTreeWidgetItem *it;
13091 QStringList subfolders = dest_f->subfolders();
13092
13093 foreach (it, draggedItems) {
13094 if (it->type() == FolderListItem::FolderType) {
13095 Folder *f = ((FolderListItem *)it)->folder();
13096 FolderListItem *src = f->folderListItem();
13097 if (dest_f == f) {
13098 QMessageBox::critical(this, "Error", tr("Cannot move an object to itself!"));
13099 return;
13100 }
13101
13102 if (((FolderListItem *)dest)->isChildOf(src)) {
13103 QMessageBox::critical(this, "Error",
13104 tr("Cannot move a parent folder into a child folder!"));
13105 draggedItems.clear();
13106 folders.setCurrentItem(current_folder->folderListItem());
13107 return;
13108 }
13109
13110 Folder *parent = (Folder *)f->parent();
13111 if (!parent)
13112 parent = projectFolder();
13113 if (dest_f == parent)
13114 return;
13115
13116 if (subfolders.contains(f->name())) {
13117 QMessageBox::critical(this, tr("SciDAVis") + " - " + tr("Skipped moving folder"),
13118 tr("The destination folder already contains a folder called "
13119 "'%1'! Folder skipped!")
13120 .arg(f->name()));
13121 } else
13122 moveFolder(src, (FolderListItem *)dest);
13123 } else {
13124 if (dest_f == current_folder)
13125 return;
13126
13127 MyWidget *w = ((WindowListItem *)it)->window();
13128 if (w) {
13129 current_folder->removeWindow(w);
13130 w->hide();
13131 dest_f->addWindow(w);
13132 delete it;
13133 }
13134 }
13135 }
13136
13137 draggedItems.clear();
13138 current_folder = dest_f;
13139 folders.setCurrentItem(dest_f->folderListItem());
13140 changeFolder(dest_f, true);
13141 folders.setFocus();
13142 modifiedProject();
13143 }
13144
13145 void ApplicationWindow::moveFolder(FolderListItem *src, FolderListItem *dest)
13146 {
13147 folders.blockSignals(true);
13148
13149 Folder *dest_f = dest->folder();
13150 Folder *src_f = src->folder();
13151
13152 dest_f = &dest_f->addChild<Folder>(src_f->name());
13153 dest_f->setBirthDate(src_f->birthDate());
13154 dest_f->setModificationDate(src_f->modificationDate());
13155
13156 FolderListItem *copy_item = new FolderListItem(dest, dest_f);
13157 copy_item->setText(0, src_f->name());
13158 dest_f->setFolderListItem(copy_item);
13159
13160 QList<MyWidget *> lst = src_f->windowsList();
13161 foreach (MyWidget *w, lst) {
13162 src_f->removeWindow(w);
13163 w->hide();
13164 dest_f->addWindow(w);
13165 }
13166
13167 if (!(src_f->children()).isEmpty()) {
13168 FolderListItem *item = (FolderListItem *)src->child(0);
13169 int initial_depth = item->depth();
13170 QTreeWidgetItemIterator it(item);
13171 while (item && item->depth() >= initial_depth) {
13172 src_f = (Folder *)item->folder();
13173
13174 dest_f = &dest_f->addChild<Folder>(src_f->name());
13175 dest_f->setBirthDate(src_f->birthDate());
13176 dest_f->setModificationDate(src_f->modificationDate());
13177
13178 copy_item = new FolderListItem(copy_item, dest_f);
13179 copy_item->setText(0, src_f->name());
13180 dest_f->setFolderListItem(copy_item);
13181
13182 lst = QList<MyWidget *>(src_f->windowsList());
13183 foreach (MyWidget *w, lst) {
13184 src_f->removeWindow(w);
13185 w->hide();
13186 dest_f->addWindow(w);
13187 }
13188
13189 it++;
13190 item = (FolderListItem *)(*it);
13191 }
13192 }
13193
13194 src_f = src->folder();
13195 delete src_f;
13196 delete src;
13197 folders.blockSignals(false);
13198 }
13199
13200 #ifdef SEARCH_FOR_UPDATES
13201
13202 void ApplicationWindow::searchForUpdates()
13203 {
13204 int choice = QMessageBox::question(
13205 this, versionString(),
13206 tr("SciDAVis will now try to determine whether a new version of SciDAVis is available. "
13207 "Please modify your firewall settings in order to allow SciDAVis to connect to the "
13208 "internet.")
13209 + "\n" + tr("Do you wish to continue?"),
13210 QMessageBox::Yes | QMessageBox::Default, QMessageBox::No | QMessageBox::Escape);
13211
13212 if (choice == QMessageBox::Yes) {
13213 // http.get(QNetworkRequest(QUrl("http://scidavis.sourceforge.net/current_version.txt")));
13214 http.get(QNetworkRequest(QUrl("https://raw.githubusercontent.com/highperformancecoder/"
13215 "scidavis/master/libscidavis/src/version.cpp")));
13216 }
13217 }
13218
13219 void ApplicationWindow::receivedVersionFile(QNetworkReply *netreply)
13220 {
13221 if (netreply->error() != QNetworkReply::NoError) {
13222 QMessageBox::warning(
13223 this, tr("HTTP get version file"),
13224 tr("Error while fetching version file with HTTP: %1.").arg(netreply->error()));
13225 return;
13226 }
13227
13228 version_buffer = netreply->readAll();
13229
13230 if (version_buffer.size() > 0) {
13231 QString available_versionString = QString();
13232 int available_version = 0;
13233 bool intok = false;
13234 QTextStream t(version_buffer);
13235 t.setCodec(QTextCodec::codecForName("UTF-8"));
13236 QStringList version_lines = t.readAll().split('\n');
13237
13238 if (version_lines.count() == 1) {
13239 QStringList list = version_lines.at(0).split(".");
13240 if (list.count() > 2)
13241 available_version = (list.at(0).toInt() << 16) + (list.at(1).toInt() << 8)
13242 + list.at(2).toInt(&intok);
13243 available_versionString = version_lines.at(0);
13244 } else if (version_lines.count() > 2) {
13245 available_version = version_lines.at(1).split('=').at(1).split(';').at(0).toInt(&intok);
13246 available_versionString = version_lines.at(2).split('=').at(1).split('"').at(1);
13247 }
13248
13249 if (intok) {
13250 if (available_version > SciDAVis::version()) {
13251 if (QMessageBox::question(this, tr("Updates Available"),
13252 tr("There is a newer version of SciDAVis (%1) available "
13253 "for download. Would you like to download it now?")
13254 .arg(available_versionString),
13255 QMessageBox::Yes | QMessageBox::Default,
13256 QMessageBox::No | QMessageBox::Escape)
13257 == QMessageBox::Yes)
13258 QDesktopServices::openUrl(QUrl(DOWNLOAD_URI));
13259 } else {
13260 QMessageBox::information(
13261 this, versionString(),
13262 tr("No updates available. You are already running the latest version."));
13263 }
13264 } else
13265 QMessageBox::information(this, tr("Invalid version file"),
13266 tr("The version file (contents: \"%1\") could not be decoded "
13267 "into a valid version number.")
13268 .arg(version_lines.join("\n")));
13269 autoSearchUpdatesRequest = false;
13270 }
13271 }
13272
13273 #endif // defined SEARCH_FOR_UPDATES
13274
13275 /*!
13276 Turns 3D animation on or off
13277 */
13278 void ApplicationWindow::toggle3DAnimation(bool on)
13279 {
13280 if (d_workspace.activeSubWindow() && d_workspace.activeSubWindow()->inherits("Graph3D"))
13281 ((Graph3D *)d_workspace.activeSubWindow())->animate(on);
13282 }
13283
13284 QString ApplicationWindow::generateUniqueName(const QString &name, bool increment)
13285 {
13286 int index = 0;
13287 QList<MyWidget *> windows = windowsList();
13288 QStringList lst;
13289
13290 for (int i = 0; i < windows.count(); i++) {
13291 MyWidget *widget = windows.at(i);
13292 if (!widget)
13293 continue;
13294 lst << widget->name();
13295 if (widget->name().startsWith(name))
13296 index++;
13297 }
13298
13299 QString newName = name;
13300 if (increment) // force return of a different name
13301 newName += QString::number(++index);
13302 else {
13303 if (index > 0)
13304 newName += QString::number(index);
13305 }
13306
13307 while (lst.contains(newName))
13308 newName = name + QString::number(++index);
13309 return newName;
13310 }
13311
13312 void ApplicationWindow::clearTable()
13313 {
13314 Table *t = (Table *)d_workspace.activeSubWindow();
13315 if (!t || !t->inherits("Table"))
13316 return;
13317
13318 if (QMessageBox::question(this, tr("Warning"),
13319 tr("This will clear the contents of all the data associated with the "
13320 "table. Are you sure?"),
13321 tr("&Yes"), tr("&No"), QString(), 0, 1))
13322 return;
13323 else
13324 t->clear();
13325 }
13326
13327 /*!
13328 Turns perspective mode on or off
13329 */
13330 void ApplicationWindow::togglePerspective(bool on)
13331 {
13332 if (d_workspace.activeSubWindow() && d_workspace.activeSubWindow()->inherits("Graph3D")) {
13333 ((Graph3D *)d_workspace.activeSubWindow())->setOrtho(!on);
13334 }
13335 }
13336
13337 /*!
13338 Resets rotation of 3D plots to default values
13339 */
13340 void ApplicationWindow::resetRotation()
13341 {
13342 if (d_workspace.activeSubWindow() && d_workspace.activeSubWindow()->inherits("Graph3D")) {
13343 ((Graph3D *)d_workspace.activeSubWindow())->setRotation(30, 0, 15);
13344 }
13345 }
13346
13347 /*!
13348 Finds best layout for the 3D plot
13349 */
13350 void ApplicationWindow::fitFrameToLayer()
13351 {
13352 if (!d_workspace.activeSubWindow() || !d_workspace.activeSubWindow()->inherits("Graph3D"))
13353 return;
13354
13355 ((Graph3D *)d_workspace.activeSubWindow())->findBestLayout();
13356 }
13357
13358 ApplicationWindow::~ApplicationWindow()
13359 {
13360 if (lastCopiedLayer)
13361 delete lastCopiedLayer;
13362
13363 QApplication::clipboard()->clear(QClipboard::Clipboard);
13364 }
13365
13366 QString ApplicationWindow::versionString()
13367 {
13368 return SciDAVis::versionString();
13369 }
13370
13371 unsigned int ApplicationWindow::convertOldToNewColorIndex(unsigned int cindex)
13372 {
13373 if ((cindex == 13) || (cindex == 14)) // white and light gray
13374 return cindex + 4;
13375
13376 if (cindex == 15) // dark gray
13377 return cindex + 8;
13378
13379 return cindex;
13380 }
13381
13382 void ApplicationWindow::cascade()
13383 {
13384 QList<QMdiSubWindow *> windows = d_workspace.subWindowList(QMdiArea::StackingOrder);
13385
13386 const int xoffset = 13;
13387 const int yoffset = 20;
13388
13389 int x = 0;
13390 int y = 0;
13391
13392 foreach (QWidget *w, windows) {
13393 w->activateWindow();
13394 w->showNormal();
13395 ((MyWidget *)w)->setStatus(MyWidget::Normal);
13396 updateWindowStatus((MyWidget *)w);
13397
13398 w->setGeometry(x, y, w->width(), w->height());
13399 w->raise();
13400 x += xoffset;
13401 y += yoffset;
13402 }
13403 modifiedProject();
13404 }
13405
13406 ApplicationWindow *ApplicationWindow::loadScript(const QString &fn, const QStringList &args,
13407 bool execute)
13408 {
13409 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
13410 ApplicationWindow *app = new ApplicationWindow();
13411 app->applyUserSettings();
13412 bool isPython = fn.endsWith(".py", Qt::CaseInsensitive);
13413 app->m_batch = true;
13414 if (isPython)
13415 app->setScriptingLangForBatch("Python");
13416 else
13417 app->setScriptingLangForBatch("muParser");
13418 app->showMaximized();
13419 Note *script_note = app->newNote(fn);
13420 if (isPython) {
13421 // copy any arguments into the sys.argv array
13422 script_note->insert("import sys\n");
13423 QString prologue = "sys.argv=['" + fn + "'";
13424 for (auto &a : args)
13425 prologue += ",'" + a + "'";
13426 prologue += "]\n";
13427 script_note->insert(prologue);
13428 }
13429 script_note->importASCII(fn);
13430 QApplication::restoreOverrideCursor();
13431 if (execute) {
13432 // we need to disable the redirect of stdio, as this is batch processing
13433 Script *script = nullptr;
13434 if (auto scriptEdit = script_note->findChild<ScriptEdit *>())
13435 if ((script = scriptEdit->findChild<Script *>()))
13436 script->batchMode = true;
13437 if (!script_note->executeAll())
13438 exit(1);
13439 if (script)
13440 script->batchMode = false;
13441 }
13442 app->m_batch = false;
13443 return app;
13444 }
13445
13446 QMenu *ApplicationWindow::createToolbarsMenu()
13447 {
13448 QMenu *menu = 0;
13449 QList<QToolBar *> toolbars = this->findChildren<QToolBar *>();
13450 if (toolbars.size()) {
13451 menu = new QMenu(this);
13452 foreach (QToolBar *toolbar, toolbars) {
13453 if (toolbar->parentWidget() == this)
13454 menu->addAction(toolbar->toggleViewAction());
13455 }
13456 }
13457 return menu;
13458 }
13459
13460 void ApplicationWindow::setStatusBarText(const QString &text)
13461 {
13462 d_status_info->setText(text);
13463 QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
13464 }
13465
13466 void ApplicationWindow::copyStatusBarText()
13467 {
13468 QApplication::clipboard()->setText(d_status_info->text());
13469 }
13470
13471 void ApplicationWindow::showStatusBarContextMenu(const QPoint &pos)
13472 {
13473 QMenu cm(this);
13474 cm.addAction(actionCopyStatusBarText);
13475 cm.exec(d_status_info->mapToGlobal(pos));
13476 }
13477
13478 QMenu *ApplicationWindow::showWindowMenuImpl(MyWidget *widget)
13479 {
13480 d_workspace.setActiveSubWindow(widget); // FIXME not user-friendly, but can't be simply removed
13481
13482 QMenu *cm = new QMenu(this);
13483 QMenu *depend_menu = new QMenu(this);
13484
13485 if (widget->inherits("Table"))
13486 cm->addAction(actionShowExportASCIIDialog);
13487 else if (widget->inherits("Note"))
13488 cm->addAction(actionSaveNote);
13489 else
13490 cm->addAction(actionSaveTemplate);
13491 cm->addAction(actionPrint);
13492 cm->addAction(actionCopyWindow);
13493 cm->addSeparator();
13494 cm->addAction(actionRename);
13495 cm->addAction(actionCloseWindow);
13496 if (!hidden(widget))
13497 cm->addAction(actionHideActiveWindow);
13498 cm->addAction(actionActivateWindow);
13499 cm->addAction(actionMinimizeWindow);
13500 cm->addAction(actionMaximizeWindow);
13501 cm->addAction(actionResizeWindow);
13502 cm->addSeparator();
13503 cm->addAction(tr("&Properties..."), this, SLOT(windowProperties()));
13504
13505 int n;
13506 if (widget->inherits("Table")) {
13507 QStringList graphs = dependingPlots(widget->name());
13508 n = graphs.count();
13509 if (n > 0) {
13510 cm->addSeparator();
13511 for (int i = 0; i < n; i++)
13512 depend_menu->addAction(graphs[i], this, SLOT(setActiveWindowFromAction()));
13513
13514 depend_menu->setTitle(tr("D&epending Graphs"));
13515 cm->addMenu(depend_menu);
13516 }
13517 } else if (widget->inherits("Matrix")) {
13518 QStringList graphs = depending3DPlots((Matrix *)widget);
13519 n = graphs.count();
13520 if (n > 0) {
13521 cm->addSeparator();
13522 for (int i = 0; i < n; i++)
13523 depend_menu->addAction(graphs[i], this, SLOT(setActiveWindowFromAction()));
13524
13525 depend_menu->setTitle(tr("D&epending 3D Graphs"));
13526 cm->addMenu(depend_menu);
13527 }
13528 } else if (widget->inherits("MultiLayer")) {
13529 QStringList tbls = multilayerDependencies(widget);
13530 n = tbls.count();
13531 if (n > 0) {
13532 cm->addSeparator();
13533 for (int i = 0; i < n; i++)
13534 depend_menu->addAction(tbls[i], this, SLOT(setActiveWindowFromAction()));
13535
13536 depend_menu->setTitle(tr("D&epends on"));
13537 cm->addMenu(depend_menu);
13538 }
13539 } else if (widget->inherits("Graph3D")) {
13540 Graph3D *sp = (Graph3D *)widget;
13541 Matrix *m = sp->matrix();
13542 QString formula = sp->formula();
13543 if (!formula.isEmpty()) {
13544 cm->addSeparator();
13545 if (formula.contains("_")) {
13546 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
13547 QStringList tl = formula.split("_", Qt::SkipEmptyParts);
13548 #else
13549 QStringList tl = formula.split("_", QString::SkipEmptyParts);
13550 #endif
13551
13552 depend_menu->addAction(tl[0], this, SLOT(setActiveWindowFromAction()));
13553
13554 depend_menu->setTitle(tr("D&epends on"));
13555 cm->addMenu(depend_menu);
13556 } else if (m) {
13557 depend_menu->addAction(m->name(), this, SLOT(setActiveWindowFromAction()));
13558 depend_menu->setTitle(tr("D&epends on"));
13559 cm->addMenu(depend_menu);
13560 }
13561 }
13562 }
13563
13564 return cm;
13565 }
13566
13567 void ApplicationWindow::setActiveWindowFromAction()
13568 {
13569 QAction *action = qobject_cast<QAction *>(sender());
13570 if (action)
13571 activateSubWindow(qobject_cast<MyWidget *>(window(action->text())));
13572 }
13573
13574 bool ApplicationWindow::validFor3DPlot(Table *table)
13575 {
13576 if (table->numCols() < 2) {
13577 QMessageBox::critical(0, tr("Error"),
13578 tr("You need at least two columns for this operation!"));
13579 return false;
13580 }
13581 if (table->firstSelectedColumn() < 0
13582 || table->colPlotDesignation(table->firstSelectedColumn()) != SciDAVis::Z) {
13583 QMessageBox::critical(0, tr("Error"), tr("Please select a Z column for this operation!"));
13584 return false;
13585 }
13586 if (table->noXColumn()) {
13587 QMessageBox::critical(0, tr("Error"), tr("You need to define a X column first!"));
13588 return false;
13589 }
13590 if (table->noYColumn()) {
13591 QMessageBox::critical(0, tr("Error"), tr("You need to define a Y column first!"));
13592 return false;
13593 }
13594 return true;
13595 }
13596
13597 bool ApplicationWindow::validFor2DPlot(Table *table, int type)
13598 {
13599 switch (type) {
13600 case Graph::Histogram:
13601 case Graph::Pie:
13602 case Graph::Box:
13603 if (table->selectedColumnCount() < 1) {
13604 QMessageBox::warning(this, tr("Error"), tr("Please select a column to plot!"));
13605 return false;
13606 }
13607 break;
13608 default:
13609 if (table->selectedColumnCount(SciDAVis::Y) < 1) {
13610 QMessageBox::warning(this, tr("Error"), tr("Please select a Y column to plot!"));
13611 return false;
13612 } else if (table->numCols() < 2) {
13613 QMessageBox::critical(this, tr("Error"),
13614 tr("You need at least two columns for this operation!"));
13615 return false;
13616 } else if (table->noXColumn()) {
13617 QMessageBox::critical(this, tr("Error"),
13618 tr("Please set a default X column for this table, first!"));
13619 return false;
13620 }
13621 break;
13622 }
13623
13624 return true;
13625 }
13626
13627 void ApplicationWindow::selectPlotType(int type)
13628 {
13629 if (!d_workspace.activeSubWindow())
13630 return;
13631
13632 Table *table = qobject_cast<Table *>(d_workspace.activeSubWindow());
13633 if (table && validFor2DPlot(table, type)) {
13634 switch (type) {
13635 case Graph::Histogram:
13636 case Graph::Pie:
13637 case Graph::Box:
13638 multilayerPlot(table, table->selectedColumns(), (Graph::CurveType)type,
13639 table->firstSelectedRow(), table->lastSelectedRow());
13640 break;
13641 default:
13642 multilayerPlot(table, table->drawableColumnSelection(), (Graph::CurveType)type,
13643 table->firstSelectedRow(), table->lastSelectedRow());
13644 break;
13645 }
13646 return;
13647 }
13648
13649 MultiLayer *ml = qobject_cast<MultiLayer *>(d_workspace.activeSubWindow());
13650 if (ml) {
13651 Graph *g = ml->activeGraph();
13652 if (g->curves() > 0)
13653 g->setCurveType(g->curves() - 1, (Graph::CurveType)type);
13654 }
13655 }
13656
13657 void ApplicationWindow::handleAspectAdded(const AbstractAspect *parent, int index)
13658 {
13659 AbstractAspect *aspect = parent->child(index);
13660 ::future::Matrix *matrix = qobject_cast<::future::Matrix *>(aspect);
13661 if (matrix) {
13662 initMatrix(static_cast<Matrix *>(matrix->view()));
13663 return;
13664 }
13665 ::future::Table *table = qobject_cast<::future::Table *>(aspect);
13666 if (table) {
13667 initTable(static_cast<Table *>(table->view()));
13668 return;
13669 }
13670 }
13671
13672 void ApplicationWindow::handleAspectAboutToBeRemoved(const AbstractAspect *parent, int index)
13673 {
13674 AbstractAspect *aspect = parent->child(index);
13675 ::future::Matrix *matrix = qobject_cast<::future::Matrix *>(aspect);
13676 if (matrix) {
13677 closeWindow(static_cast<Matrix *>(matrix->view()));
13678 return;
13679 }
13680 ::future::Table *table = qobject_cast<::future::Table *>(aspect);
13681 if (table) {
13682 closeWindow(static_cast<Table *>(table->view()));
13683 return;
13684 }
13685 }
13686
13687 void ApplicationWindow::showHistory()
13688 {
13689 if (!d_project->undoStack())
13690 return;
13691 QDialog dialog;
13692 QVBoxLayout layout(&dialog);
13693
13694 QDialogButtonBox button_box;
13695 button_box.setOrientation(Qt::Horizontal);
13696 button_box.setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::NoButton
13697 | QDialogButtonBox::Ok);
13698 QObject::connect(&button_box, SIGNAL(accepted()), &dialog, SLOT(accept()));
13699 QObject::connect(&button_box, SIGNAL(rejected()), &dialog, SLOT(reject()));
13700
13701 int index = d_project->undoStack()->index();
13702 QUndoView undo_view(d_project->undoStack());
13703
13704 layout.addWidget(&undo_view);
13705 layout.addWidget(&button_box);
13706
13707 dialog.setWindowTitle(tr("Undo/Redo History"));
13708 if (dialog.exec() == QDialog::Accepted)
13709 return;
13710
13711 d_project->undoStack()->setIndex(index);
13712 }
13713
13714 QStringList ApplicationWindow::tableWindows()
13715 {
13716 QList<AbstractAspect *> tables = d_project->descendantsThatInherit("future::Table");
13717 QStringList result;
13718 foreach (AbstractAspect *aspect, tables)
13719 result.append(aspect->name());
13720 return result;
13721 }
13722
13723 QSettings &ApplicationWindow::getSettings()
13724 {
13725 #ifdef Q_OS_MAC // Mac
13726 static QSettings d_settings(QSettings::IniFormat, QSettings::UserScope, "SciDAVis", "SciDAVis");
13727 #else
13728 static QSettings d_settings(QSettings::NativeFormat, QSettings::UserScope, "SciDAVis",
13729 "SciDAVis");
13730 #endif
13731 return d_settings;
13732 }
13733
13734 // initialize singleton
13735 static auto &SciDavisSettingsSingleton = ApplicationWindow::getSettings();
13736