1 /***************************************************************************
2  *                                                                         *
3  *   copyright : (C) 2007 The University of Toronto                        *
4  *                   netterfield@astro.utoronto.ca                         *
5  *                                                                         *
6  *   This program is free software; you can redistribute it and/or modify  *
7  *   it under the terms of the GNU General Public License as published by  *
8  *   the Free Software Foundation; either version 2 of the License, or     *
9  *   (at your option) any later version.                                   *
10  *                                                                         *
11  ***************************************************************************/
12 
13 #include "mainwindow.h"
14 #include "boxitem.h"
15 #include "datamanager.h"
16 #include "debugdialog.h"
17 #include "debugnotifier.h"
18 #include "document.h"
19 #include "ellipseitem.h"
20 #include "exportgraphicsdialog.h"
21 #include "exportvectorsdialog.h"
22 #include "logdialog.h"
23 #include "application.h"
24 #include "debug.h"
25 #include "labelitem.h"
26 #include "lineitem.h"
27 #include "circleitem.h"
28 #include "arrowitem.h"
29 #include "memorywidget.h"
30 #include "objectstore.h"
31 #include "pictureitem.h"
32 #include "plotitem.h"
33 #include "plotitemmanager.h"
34 #include "svgitem.h"
35 #include "tabwidget.h"
36 #include "sharedaxisboxitem.h"
37 #include "ui_aboutdialog.h"
38 #include "viewvectordialog.h"
39 #include "viewmatrixdialog.h"
40 #include "viewprimitivedialog.h"
41 #include "view.h"
42 #include "applicationsettings.h"
43 #include "updatemanager.h"
44 #include "datasourcepluginmanager.h"
45 #include "pluginmenuitemaction.h"
46 
47 #include "applicationsettingsdialog.h"
48 #include "themedialog.h"
49 #include "differentiatecurvesdialog.h"
50 #include "filtermultipledialog.h"
51 #include "choosecolordialog.h"
52 #include "changedatasampledialog.h"
53 #include "changefiledialog.h"
54 #include "bugreportwizard.h"
55 #include "datawizard.h"
56 #include "aboutdialog.h"
57 #include "shortcutdialog.h"
58 #include "datavector.h"
59 #include "commandlineparser.h"
60 #include "dialogdefaults.h"
61 #include "settings.h"
62 
63 #include "dialoglauncher.h"
64 #include "scriptserver.h"
65 
66 #include "geticon.h"
67 
68 #ifndef KST_NO_SVG
69 #include <QSvgGenerator>
70 #endif
71 
72 #include <QUndoGroup>
73 #ifndef KST_NO_PRINTER
74 #include <QPrintDialog>
75 #endif
76 #include <QMenuBar>
77 #include <QStatusBar>
78 #include <QProgressBar>
79 #include <QMessageBox>
80 #include <QImageWriter>
81 #include <QToolBar>
82 #include <QDebug>
83 #include <QDesktopServices>
84 #include <QSignalMapper>
85 #include <QClipboard>
86 
87 namespace Kst {
88 
MainWindow()89 MainWindow::MainWindow() :
90     _settings(createSettings("application")),
91     _dataManager(0),
92     _exportGraphics(0),
93     _exportVectors(0),
94     _logDialog(0),
95     _differentiateCurvesDialog(0),
96     _filterMultipleDialog(0),
97     _chooseColorDialog(0),
98     _changeDataSampleDialog(0),
99     _changeFileDialog(0),
100     _bugReportWizard(0),
101     _applicationSettingsDialog(0),
102     _themeDialog(0),
103     _aboutDialog(0),
104     _shortcutDialog(0),
105     _viewVectorDialog(0),
106     _highlightPoint(false),
107     _statusBarTimeout(0),
108 #if defined(__QNX__)
109     qnxToolbarsVisible(true),
110 #endif
111     _ae_width(1280),
112     _ae_height(1024),
113     _ae_display(2),
114     _ae_export_all(false),
115     _ae_autosave_period(0),
116     _ae_Timer(0),
117     _sessionFileName(QString())
118 {
119   _doc = new Document(this);
120   _scriptServer = new ScriptServer(_doc->objectStore());
121   _videoMapper = new QSignalMapper(this);
122 
123   _tabWidget = new TabWidget(this);
124   _undoGroup = new QUndoGroup(this);
125   _debugDialog = new DebugDialog(this);
126 
127   Debug::self()->setHandler(_debugDialog);
128 
129   setKstWindowTitle();
130 
131   createActions();
132   createMenus();
133   createToolBars();
134   createStatusBar();
135 
136   _tabWidget->createView();
137 
138   setCentralWidget(_tabWidget);
139   _tabWidget->setAcceptDrops(false); // Force drops to be passed to parent
140   connect(_tabWidget, SIGNAL(currentChanged(int)), this, SLOT(currentViewChanged()));
141   connect(_tabWidget, SIGNAL(currentViewModeChanged()), this, SLOT(currentViewModeChanged()));
142   connect(PlotItemManager::self(), SIGNAL(tiedZoomRemoved()), this, SLOT(tiedZoomRemoved()));
143   connect(PlotItemManager::self(), SIGNAL(allPlotsTiedZoom()), this, SLOT(allPlotsTiedZoom()));
144 
145   readSettings();
146   connect(UpdateManager::self(), SIGNAL(objectsUpdated(qint64)), this, SLOT(updateViewItems(qint64)));
147 
148   QTimer::singleShot(0, this, SLOT(performHeavyStartupActions()));
149 
150   updateRecentKstFiles();
151   setAcceptDrops(true);
152 
153 #if defined(__QNX__)
154   // We want to be able to intercept bezel gestures, which show up in Qt as menu button keyPressEvents.
155   qApp->installEventFilter(this);
156   qnxToggleToolbarVisibility();
157 #endif
158 
159 }
160 
161 
~MainWindow()162 MainWindow::~MainWindow() {
163   delete _dataManager;
164   _dataManager = 0;
165   delete _doc;
166   _doc = 0;
167   delete _viewVectorDialog;
168   _viewVectorDialog = 0;
169   delete _scriptServer;
170   _scriptServer = 0;
171 }
172 
173 
performHeavyStartupActions()174 void MainWindow::performHeavyStartupActions() {
175   // Set the timer for the UpdateManager.
176   UpdateManager::self()->setMinimumUpdatePeriod(ApplicationSettings::self()->minimumUpdatePeriod());
177   DataObject::init();
178   DataSourcePluginManager::init();
179 }
180 
cleanup()181 void MainWindow::cleanup() {
182   if (document() && document()->objectStore()) {
183     document()->objectStore()->clear();
184   }
185 }
186 
187 
setLayoutMode(bool layoutMode)188 void MainWindow::setLayoutMode(bool layoutMode) {
189   foreach (View *v, tabWidget()->views() ) {
190 
191     Q_ASSERT(v);
192 
193     if (layoutMode) {
194       v->setViewMode(View::Layout);
195       _highlightPointAct->setEnabled(false);
196       _tiedZoomAct->setEnabled(false);
197     } else {
198       v->setViewMode(View::Data);
199       _highlightPointAct->setEnabled(true);
200       _tiedZoomAct->setEnabled(true);
201     }
202   }
203 }
204 
setHighlightPoint(bool highlight)205 void MainWindow::setHighlightPoint(bool highlight) {
206   _highlightPoint = highlight;
207 }
208 
changeZoomOnlyMode(QAction * act)209 void MainWindow::changeZoomOnlyMode(QAction* act) {
210   if (act == _layoutModeAct && act->isChecked()) {
211     setLayoutMode(true);
212   } else {
213     setLayoutMode(false);
214   }
215   foreach (View *view, tabWidget()->views() ) {
216     view->setZoomOnly((View::ZoomOnlyMode)act->data().toInt());
217   }
218 
219 }
220 
toggleTiedZoom()221 void MainWindow::toggleTiedZoom() {
222   if (isTiedTabs()) {
223     PlotItemManager::self()->toggleAllTiedZoom(0);
224     /*
225     QList<View*> views = tabWidget()->views();
226     foreach (View* view, views) {
227       PlotItemManager::self()->toggleAllTiedZoom(view);
228     }
229     */
230   } else {
231     PlotItemManager::self()->toggleAllTiedZoom(tabWidget()->currentView());
232   }
233 }
234 
tiedZoomRemoved()235 void MainWindow::tiedZoomRemoved() {
236   _tiedZoomAct->setChecked(false);
237 }
238 
239 
allPlotsTiedZoom()240 void MainWindow::allPlotsTiedZoom() {
241   _tiedZoomAct->setChecked(true);
242 }
243 
244 
promptSaveDone()245 bool MainWindow::promptSaveDone() {
246   if (! _doc->isChanged()) {
247     return true; // No need to ask if there is no unsaved change -> we're done
248   }
249   else { // Changes registered: ask the user
250     int rc = QMessageBox::warning(this, tr("Kst: Save Prompt"), tr("Your document has been modified.\nSave changes?"), QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Save);
251     if (rc == QMessageBox::Save) {
252       save();
253     } else if (rc == QMessageBox::Cancel) {
254       return false;
255     }
256     return true;
257   }
258 }
259 
260 
closeEvent(QCloseEvent * e)261 void MainWindow::closeEvent(QCloseEvent *e) {
262   if (!promptSaveDone()) {
263     e->ignore();
264     return;
265     }
266     //cleanup();
267     QMainWindow::closeEvent(e);
268     kstApp->closeAllWindows();
269   }
270 
271 
document() const272 Document *MainWindow::document() const {
273   return _doc;
274 }
275 
276 
undoGroup() const277 QUndoGroup *MainWindow::undoGroup() const {
278   return _undoGroup;
279 }
280 
281 
tabWidget() const282 TabWidget *MainWindow::tabWidget() const {
283   return _tabWidget;
284 }
285 
286 
save()287 void MainWindow::save() {
288   if (_doc->isOpen()) {
289     _doc->save();
290   } else {
291     saveAs();
292     }
293 }
294 
295 
saveAs()296 void MainWindow::saveAs() {
297   QString fn = QFileDialog::getSaveFileName(this, tr("Kst: Save File"), _doc->fileName(), tr("Kst Sessions (*.kst)"));
298   if (fn.isEmpty()) {
299     return;
300   }
301   QString restorePath = QDir::currentPath();
302   QString kstfiledir = fn.left(fn.lastIndexOf('/')) + '/';
303   QDir::setCurrent(kstfiledir);
304   //QString currentP = QDir::currentPath();
305   _doc->save(fn);
306   QDir::setCurrent(restorePath);
307   _sessionFileName = fn;
308   setKstWindowTitle();
309   updateRecentKstFiles(fn);
310 }
311 
newDoc(bool force)312 void MainWindow::newDoc(bool force) {
313   bool clearApproved = false;
314   if (force) {
315     clearApproved = true;
316   } else {
317     clearApproved = promptSaveDone();
318   }
319 
320   if (clearApproved) {
321     cleanup();
322     delete _dataManager;
323     _dataManager = 0;
324     delete _doc;
325     resetNameIndexes();
326     _doc = new Document(this);
327     _scriptServer->setStore(_doc->objectStore());
328     tabWidget()->clear();
329     tabWidget()->createView();
330     return;
331   } else {
332     return;
333   }
334 
335 }
336 
open()337 void MainWindow::open() {
338   if (!promptSaveDone()) {
339     return;
340   }
341   const QString key = "lastOpenedKstFile";
342   QString fn = _settings.value(key).toString();
343   if (fn.isEmpty()) {
344       fn = _doc->fileName();
345   }
346   fn = QFileDialog::getOpenFileName(this, tr("Kst: Open File"), fn, tr("Kst Sessions (*.kst)"));
347   if (fn.isEmpty()) {
348     return;
349   }
350   _settings.setValue(key, fn);
351   openFile(fn);
352 }
353 
354 
355 
createRecentFileAction(const QString & filename,int idx,const QString & name,const char * openslot)356 QAction* MainWindow::createRecentFileAction(const QString& filename, int idx, const QString& name, const char* openslot)
357 {
358   QAction* action = new QAction(this);
359   QString text = tr("&%1 %2", "Part of a list.  %1 is an index.  %2 is a file name").arg(idx).arg(name);
360   action->setText(text);
361   action->setData(filename);
362   action->setStatusTip(filename);
363   action->setVisible(true);
364   connect(action, SIGNAL(triggered()), this, openslot);
365   return action;
366 }
367 
368 
updateRecentKstFiles(const QString & filename)369 void MainWindow::updateRecentKstFiles(const QString& filename)
370 {
371   updateRecentFiles("recentKstFileList", _fileMenu, _bottomRecentKstActions, _recentKstFilesMenu, filename, SLOT(openRecentKstFile()));
372 }
373 
setKstWindowTitle()374 void MainWindow::setKstWindowTitle()
375 {
376   QString title = "Kst";
377   QString server_name = _scriptServer->serverName;
378   QString user_name = "--"+kstApp->userName();
379 
380   if (server_name.endsWith(user_name)) {
381     server_name.remove(server_name.lastIndexOf(user_name),10000);
382   }
383 
384   if (!_sessionFileName.isEmpty()) {
385     title += " - " + _sessionFileName;
386   }
387   if (scriptServerNameSet()) {
388     title += " -- " + server_name;
389   }
390   setWindowTitle(title);
391 }
392 
scriptServerName()393 QString MainWindow::scriptServerName()
394 {
395   return _scriptServer->serverName;
396 }
397 
scriptServerNameSet()398 bool MainWindow::scriptServerNameSet()
399 {
400   return _scriptServer->serverNameSet;
401 }
402 
setScriptServerName(QString server_name)403 void MainWindow::setScriptServerName(QString server_name)
404 {
405   _scriptServer->setScriptServerName(server_name);
406   setKstWindowTitle();
407 }
408 
copyTab()409 void MainWindow::copyTab()
410 {
411   View *view = _tabWidget->currentView();
412   QClipboard *clipboard = QApplication::clipboard();
413   QMimeData *mimedata = new QMimeData();
414 
415   QPainter painter;
416   QPixmap pixmap(view->size());
417 
418   painter.begin(&pixmap);
419 
420   view->setPrinting(true);
421   view->render(&painter);
422   view->setPrinting(false);
423 
424   painter.end();
425 
426   //mimedata->setText("Some text from kst, just for you!");
427   mimedata->setImageData(pixmap.toImage());
428 
429   clipboard->setMimeData(mimedata);
430 }
431 
432 
updateRecentDataFiles(const QString & filename)433 void MainWindow::updateRecentDataFiles(const QString& filename)
434 {
435   updateRecentFiles("recentDataFileList", _toolsMenu, _bottomRecentDataActions, _recentDataFilesMenu, filename, SLOT(openRecentDataFile()));
436   if (!filename.isEmpty()) {
437     dialogDefaults().setValue("vector/datasource", filename);
438   }
439 }
440 
441 
recentDataFiles()442 QStringList MainWindow::recentDataFiles() {
443   QStringList recentFiles = _settings.value("recentDataFileList").toStringList();
444   if (recentFiles.removeDuplicates() > 0) {
445     _settings.setValue("recentDataFileList", recentFiles);
446   }
447   return recentFiles;
448 }
449 
cleanupRecentDataFilesList()450 void MainWindow::cleanupRecentDataFilesList() {
451   QStringList recentFiles = _settings.value("recentDataFileList").toStringList();
452   recentFiles.removeDuplicates();
453   foreach(const QString& it, recentFiles) {
454     if (!QFileInfo(it).exists()) {
455       recentFiles.removeOne(it);
456     }
457   }
458   _settings.setValue("recentDataFileList", recentFiles);
459   updateRecentKstFiles();
460   updateRecentDataFiles();
461 }
462 
463 
updateRecentFiles(const QString & key,QMenu * menu,QList<QAction * > & actions,QMenu * submenu,const QString & newfilename,const char * openslot)464 void MainWindow::updateRecentFiles(const QString& key ,QMenu* menu, QList<QAction*>& actions, QMenu* submenu, const QString& newfilename, const char* openslot)
465 {
466   // Always add absolute paths to the recent file lists, otherwise they are not very reusable
467   QString absoluteFilePath = DataSource::cleanPath(newfilename);
468   if (!newfilename.isEmpty() && !QDir::isAbsolutePath(newfilename)) { // If it's not empty and not absolute either, add the dir
469     absoluteFilePath = DataSource::cleanPath(QDir::currentPath() + '/' + newfilename);
470   }
471   foreach(QAction* it, actions) {
472     menu->removeAction(it);
473     delete it;
474   }
475   actions.clear();
476   QStringList recentFiles = _settings.value(key).toStringList();
477   if (recentFiles.removeDuplicates() > 0) {
478     _settings.setValue(key, recentFiles);
479   }
480   if (!absoluteFilePath.isEmpty()) {
481     recentFiles.removeOne(absoluteFilePath);
482     recentFiles.push_front(absoluteFilePath);
483     recentFiles = recentFiles.mid(0, 30);
484     _settings.setValue(key, recentFiles);
485   }
486 
487   submenu->clear();
488   QAction* check = new QAction(this);
489   check->setText(tr("&Cleanup Non-Existent Files"));
490   check->setData(key);
491   check->setVisible(true);
492   connect(check, SIGNAL(triggered()), this, SLOT(checkRecentFilesOnExistence()));
493   submenu->addAction(check);
494   submenu->addSeparator();
495   int i = 0;
496   foreach(const QString& it, recentFiles) {
497     i++;
498     if (i <= 5) {
499       // don't make file menu too wide, show complete path in statusbar
500       QAction* action = createRecentFileAction(it, i, QFileInfo(it).fileName(), openslot);
501       actions << action;
502       menu->addAction(action);
503     }
504     submenu->addAction(createRecentFileAction(it, i, it, openslot));
505   }
506 }
507 
508 
openRecentKstFile()509 void MainWindow::openRecentKstFile()
510 {
511   QAction *action = qobject_cast<QAction *>(sender());
512   if (action) {
513     openFile(action->data().toString());
514   }
515 }
516 
517 
checkRecentFilesOnExistence()518 void MainWindow::checkRecentFilesOnExistence()
519 {
520   QAction *action = qobject_cast<QAction *>(sender());
521   if (action) {
522     QStringList recentFiles = _settings.value(action->data().toString()).toStringList();
523     recentFiles.removeDuplicates();
524     foreach(const QString& it, recentFiles) {
525       if (!QFileInfo(it).exists()) {
526         recentFiles.removeOne(it);
527       }
528     }
529     _settings.setValue(action->data().toString(), recentFiles);
530     updateRecentKstFiles();
531     updateRecentDataFiles();
532   }
533 }
534 
autoExportImage()535 void MainWindow::autoExportImage() {
536   exportGraphicsFile(_ae_filename, _ae_format, _ae_width, _ae_height, _ae_display, _ae_export_all, _ae_autosave_period);
537 }
538 
539 
540 
initFromCommandLine()541 bool MainWindow::initFromCommandLine() {
542   delete _doc;
543   _doc = new Document(this);
544   _scriptServer->setStore(_doc->objectStore());
545 
546   CommandLineParser P(_doc, this);
547 
548   bool ok = _doc->initFromCommandLine(&P);
549   if (!P.pngFile().isEmpty()) {
550     int w = 1280;
551     int h = 1024;
552 
553     if (P.pngWidth()>1) {
554       w = P.pngWidth();
555     }
556     if (P.pngHeight()>1) {
557       h = P.pngHeight();
558     }
559     exportGraphicsFile(P.pngFile(), "png", w, h, 2, true, 0);
560     ok = false;
561   }
562   if (!P.printFile().isEmpty()) {
563 #ifndef KST_NO_PRINTER
564     printFromCommandLine(P.printFile());
565 #endif
566     ok = false;
567   }
568   if (!P.kstFileName().isEmpty()) {
569     _sessionFileName = P.kstFileName();
570     setKstWindowTitle();
571   }
572   _doc->setChanged(false);
573   return ok;
574 }
575 
openFile(const QString & file)576 void MainWindow::openFile(const QString &file) {
577   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
578   cleanup();
579   newDoc(true); // Does all the init stuff, but does not ask for override as it's supposed to be done elsewhere
580   bool ok = _doc->open(file);
581   updateProgress(100, "");
582   QApplication::restoreOverrideCursor();
583 
584   if (!ok) {
585     QString lastError = _doc->lastError();
586     if (lastError.isEmpty())
587       lastError = tr("For details see Help->Debug Dialog->Log.");
588     QMessageBox::critical(this, tr("Kst"),tr("Error opening document:\n  '%1'\n%2\n").arg(file, lastError));
589   }
590 
591   _sessionFileName = file;
592   setKstWindowTitle();
593   updateRecentKstFiles(file);
594 }
595 
596 
exportGraphicsFile(const QString & filename,const QString & format,int width,int height,int display,bool export_all,int autosave_period)597 void MainWindow::exportGraphicsFile(const QString &filename, const QString &format, int width, int height, int display, bool export_all, int autosave_period) {
598   int viewCount = 0;
599   int n_views = _tabWidget->views().size();
600   int i_startview, i_endview;
601 
602   _ae_filename = filename;
603   _ae_format = format;
604   _ae_width = width;
605   _ae_height = height;
606   _ae_display = display;
607   _ae_export_all = export_all;
608   _ae_autosave_period = autosave_period;
609 
610   dialogDefaults().setValue("export/filename", filename);
611   dialogDefaults().setValue("export/format", format);
612   dialogDefaults().setValue("export/xsize", width);
613   dialogDefaults().setValue("export/ysize", height);
614   dialogDefaults().setValue("export/sizeOption", display);
615 
616   if (export_all) {
617     i_startview = 0;
618     i_endview = n_views-1;
619   } else {
620     i_startview = i_endview = _tabWidget->currentIndex();
621   }
622 
623   for (int i_view = i_startview; i_view<=i_endview; i_view++) {
624     View *view = _tabWidget->views().at(i_view);
625     QSize size;
626     if (display == 0) { // Width set by user, maintain aspect ratio
627       QSize sizeWindow(view->geometry().size());
628       size.setWidth(width);
629       size.setHeight((int)((qreal)width * (qreal)sizeWindow.height() / (qreal)sizeWindow.width()));
630     } else if (display == 1) { // Height set by user, maintain aspect ratio
631       QSize sizeWindow(view->geometry().size());
632       size.setHeight(height);
633       size.setWidth((int)((qreal)height * (qreal)sizeWindow.width() / (qreal)sizeWindow.height()));
634     } else if (display == 2) { // Width and height set by user
635       size.setWidth(width);
636       size.setHeight(height);
637     } else { //if (display == 3) { // Square (width x width)
638       size.setWidth(width);
639       size.setHeight(width);
640     }
641 
642     QString file = filename;
643     if (i_startview - i_endview != 0) {
644       QFileInfo QFI(filename);
645       file = QFI.dir().path() + '/' + QFI.completeBaseName() +
646              '_' +
647           _tabWidget->tabBar()->tabText(viewCount).replace(QString("&"),QString()) + '.' +
648              QFI.suffix();
649     }
650     if (format == QString("svg")) {
651 #ifndef KST_NO_SVG
652       QPainter painter;
653       QSvgGenerator generator;
654 
655       QSize currentSize(view->size());
656       view->resize(size);
657       view->processResize(size);
658       view->setPrinting(true);
659 
660       generator.setFileName(file);
661       generator.setResolution(300);
662       generator.setSize(view->size());
663       generator.setViewBox(view->rect());
664 
665       painter.begin(&generator);
666       view->render(&painter);
667       painter.end();
668 
669       view->setPrinting(false);
670       view->resize(currentSize);
671       view->processResize(currentSize);
672 #endif
673     } else if (format == QString("eps")) {
674 #ifndef KST_NO_PRINTER
675       QPrinter printer(QPrinter::ScreenResolution);
676 #ifdef QT5
677       printer.setOutputFormat(QPrinter::PdfFormat);
678 #else
679       printer.setOutputFormat(QPrinter::PostScriptFormat);
680 #endif
681       printer.setOutputFileName(file);
682       printer.setOrientation(QPrinter::Portrait);
683 
684       printer.setPrintRange(QPrinter::PageRange);
685       printer.setFromTo(i_view+1, i_view+1);
686 
687       printer.setPaperSize(size, QPrinter::DevicePixel);
688       printToPrinter(&printer);
689 
690     } else if (format == QString("pdf")) {
691       QPrinter printer(QPrinter::ScreenResolution);
692       printer.setOutputFormat(QPrinter::PdfFormat);
693       printer.setOutputFileName(file);
694       //setPrinterDefaults(&printer);
695       printer.setOrientation(QPrinter::Portrait);
696 
697       printer.setPrintRange(QPrinter::PageRange);
698       printer.setFromTo(i_view+1, i_view+1);
699 
700       printer.setPaperSize(size, QPrinter::DevicePixel);
701       printToPrinter(&printer);
702 #endif
703     } else {
704       QPainter painter;
705       QImage image(size, QImage::Format_ARGB32);
706 
707       painter.begin(&image);
708 
709       QSize currentSize(view->size());
710       view->resize(size);
711       view->processResize(size);
712       view->setPrinting(true);
713       view->render(&painter);
714       view->setPrinting(false);
715       view->resize(currentSize);
716       view->processResize(currentSize);
717 
718       painter.end();
719 
720       QImageWriter imageWriter(file, format.toLatin1());
721       imageWriter.write(image);
722     }
723     viewCount++;
724   }
725 
726   if (_ae_autosave_period > 0) {
727     if (_ae_Timer == 0) { // create timer (only once)
728       _ae_Timer = new QTimer(this);
729       _ae_Timer->setSingleShot(true);
730       connect(_ae_Timer, SIGNAL(timeout()), this, SLOT(autoExportImage()));
731     }
732     _ae_Timer->start(_ae_autosave_period); // one shot timer...
733   }
734 }
735 
exportLog(const QString & imagename,QString & msgfilename,const QString & format,int x_size,int y_size,int size_option_index,const QString & message)736 void MainWindow::exportLog(const QString &imagename, QString &msgfilename, const QString &format, int x_size, int y_size,
737                            int size_option_index, const QString &message) {
738   View *view = _tabWidget->currentView();
739 
740   QSize size;
741   if (size_option_index == 0) {
742     size.setWidth(x_size);
743     size.setHeight(y_size);
744   } else if (size_option_index == 1) {
745     size.setWidth(x_size);
746     size.setHeight(y_size);
747   } else if (size_option_index == 2) {
748     QSize sizeWindow(view->geometry().size());
749 
750     size.setWidth(x_size);
751     size.setHeight((int)((qreal)x_size * (qreal)sizeWindow.height() / (qreal)sizeWindow.width()));
752   } else {
753     QSize sizeWindow(view->geometry().size());
754 
755     size.setHeight(y_size);
756     size.setWidth((int)((qreal)y_size * (qreal)sizeWindow.width() / (qreal)sizeWindow.height()));
757   }
758 
759   QImage image(size, QImage::Format_ARGB32);
760 
761   QPainter painter(&image);
762   QSize currentSize(view->size());
763   view->resize(size);
764   view->processResize(size);
765   view->setPrinting(true);
766   view->render(&painter);
767   view->setPrinting(false);
768   view->resize(currentSize);
769   view->processResize(currentSize);
770 
771   QImageWriter imageWriter(imagename, format.toLatin1());
772   imageWriter.write(image);
773 
774   QFile file(msgfilename);
775 
776   if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
777     QTextStream out(&file);
778     out << message;
779     file.close();
780   }
781 
782 }
783 
784 #ifndef KST_NO_PRINTER
printToPrinter(QPrinter * printer)785 void MainWindow::printToPrinter(QPrinter *printer) {
786   QPainter painter(printer);
787   QList<View*> pages;
788 
789   switch (printer->printRange()) {
790    case QPrinter::PageRange:
791     if (printer->fromPage()>0) {
792       for (int i_page = printer->fromPage(); i_page<=printer->toPage(); i_page++) {
793         pages.append(_tabWidget->views().at(i_page-1));
794       }
795     }
796     break;
797    case QPrinter::AllPages:
798     foreach (View *view, _tabWidget->views()) {
799       pages.append(view);
800     }
801     break;
802    case QPrinter::Selection:
803    default:
804     pages.append(_tabWidget->currentView());
805     break;
806   }
807 
808   QSize printerPageSize = printer->pageRect().size();
809   for (int i = 0; i < printer->numCopies(); ++i) {
810     for (int i_page = 0; i_page<pages.count(); i_page++) {
811       View *view = pages.at(i_page);
812       QSize currentSize(view->size());
813       view->resize(printerPageSize);
814       view->processResize(printerPageSize);
815       view->setPrinting(true);
816       view->render(&painter);
817       view->setPrinting(false);
818       view->resize(currentSize);
819       view->processResize(currentSize);
820       if (i_page<pages.count()-1)
821         printer->newPage();
822 
823     }
824   }
825 }
826 
printFromCommandLine(const QString & printFileName)827 void MainWindow::printFromCommandLine(const QString &printFileName) {
828   QPrinter printer(QPrinter::ScreenResolution);
829   printer.setResolution(300);
830   printer.setOutputFileName(printFileName);
831   setPrinterDefaults(&printer);
832 
833   printer.setPrintRange(QPrinter::AllPages);
834   printToPrinter(&printer);
835 }
836 
setPrinterDefaults(QPrinter * printer)837 void MainWindow::setPrinterDefaults(QPrinter *printer) {
838   if (dialogDefaults().value("print/landscape",true).toBool()) {
839     printer->setOrientation(QPrinter::Landscape);
840   } else {
841     printer->setOrientation(QPrinter::Portrait);
842   }
843 
844   printer->setPaperSize(QPrinter::PaperSize(dialogDefaults().value("print/paperSize", QPrinter::Letter).toInt()));
845 
846   QPointF topLeft =dialogDefaults().value("print/topLeftMargin", QPointF(15.0,15.0)).toPointF();
847   QPointF bottomRight =dialogDefaults().value("print/bottomRightMargin", QPointF(15.0,15.0)).toPointF();
848 
849   printer->setPageMargins(topLeft.x(), topLeft.y(), bottomRight.x(), bottomRight.y(), QPrinter::Millimeter);
850   // Apparent Qt bug: setting the page margins here doesn't set the correspoding values in the print
851   // dialog->printer-options sub-dialog under linux.  If you don't open the printer-options sub-dialog,
852   // the values here are honored.
853 }
854 
savePrinterDefaults(QPrinter * printer)855 void MainWindow::savePrinterDefaults(QPrinter *printer) {
856   dialogDefaults().setValue("print/landscape", printer->orientation() == QPrinter::Landscape);
857   dialogDefaults().setValue("print/paperSize", int(printer->paperSize()));
858 
859   qreal left, top, right, bottom;
860   printer->getPageMargins(&left, &top, &right, &bottom, QPrinter::Millimeter);
861   dialogDefaults().setValue("print/topLeftMargin", QPointF(left, top));
862   dialogDefaults().setValue("print/bottomRightMargin", QPointF(right, bottom));
863 
864 }
865 
print()866 void MainWindow::print() {
867   QPrinter printer(QPrinter::ScreenResolution);
868   printer.setResolution(300);
869 
870   setPrinterDefaults(&printer);
871 
872 #ifndef Q_OS_WIN
873   // QPrintDialog: Cannot be used on non-native printers
874   printer.setOutputFileName(dialogDefaults().value("print/path", "./print.pdf").toString());
875 #endif
876   QPointer<QPrintDialog> pd = new QPrintDialog(&printer, this);
877 #if QT_VERSION >= 0x040500
878   pd->setOption(QPrintDialog::PrintToFile);
879   pd->setOption(QPrintDialog::PrintPageRange, true);
880   pd->setOption(QAbstractPrintDialog::PrintShowPageSize,true);
881 #endif
882 
883   if (pd->exec() == QDialog::Accepted) {
884     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
885     printToPrinter(&printer);
886     QApplication::restoreOverrideCursor();
887     savePrinterDefaults(&printer);
888   }
889   dialogDefaults().setValue("print/path", printer.outputFileName());
890   delete pd;
891 }
892 #endif
893 
currentViewChanged()894 void MainWindow::currentViewChanged() {
895   if(!_tabWidget->currentView())
896     return;
897   _undoGroup->setActiveStack(_tabWidget->currentView()->undoStack());
898   currentViewModeChanged();
899 }
900 
901 
currentViewModeChanged()902 void MainWindow::currentViewModeChanged() {
903   if(!_tabWidget->currentView())
904     return;
905   _layoutModeAct->setChecked(_tabWidget->currentView()->viewMode() == View::Layout);
906 }
907 
aboutToQuit()908 void MainWindow::aboutToQuit() {
909   writeSettings();
910 }
911 
912 
about()913 void MainWindow::about() {
914   if (!_aboutDialog) {
915     _aboutDialog = new AboutDialog(this);
916   }
917   if (_aboutDialog->isVisible()) {
918     _aboutDialog->raise();
919     _aboutDialog->activateWindow();
920   }
921   _aboutDialog->show();
922 }
923 
924 
showShortcutDialog()925 void MainWindow::showShortcutDialog() {
926   if (!_shortcutDialog) {
927     _shortcutDialog = new ShortcutDialog(this);
928   } else if (_shortcutDialog->isVisible()) {
929     _shortcutDialog->raise();
930     _shortcutDialog->activateWindow();
931   }
932   _shortcutDialog->show();
933 
934   _shortcutDialog->resetWidth();
935 
936 }
937 
938 
clearDrawingMarker()939 void MainWindow::clearDrawingMarker() {
940   _createBoxAct->setChecked(false);
941   _createSharedAxisBoxAct->setChecked(false);
942   _createCircleAct->setChecked(false);
943   _createEllipseAct->setChecked(false);
944   _createLabelAct->setChecked(false);
945   _createLineAct->setChecked(false);
946   _createArrowAct->setChecked(false);
947   _createPictureAct->setChecked(false);
948   _createPlotAct->setChecked(false);
949 #ifndef KST_NO_SVG
950   _createSvgAct->setChecked(false);
951 #endif
952   _tabWidget->currentView()->setMouseMode(View::Default);
953 }
954 
955 
createBox()956 void MainWindow::createBox() {
957   if (_createBoxAct->isChecked()) {
958     clearDrawingMarker();
959     _createBoxAct->setChecked(true);
960     CreateBoxCommand *cmd = new CreateBoxCommand;
961     cmd->createItem();
962   } else {
963     _tabWidget->currentView()->setMouseMode(View::Default);
964   }
965 }
966 
967 
968 
createSharedAxisBox()969 void MainWindow::createSharedAxisBox() {
970   if (_createSharedAxisBoxAct->isChecked()) {
971     clearDrawingMarker();
972     _createSharedAxisBoxAct->setChecked(true);
973     CreateSharedAxisBoxCommand *cmd = new CreateSharedAxisBoxCommand;
974     cmd->createItem();
975   } else {
976     _tabWidget->currentView()->setMouseMode(View::Default);
977   }
978 }
979 
createVector()980 void MainWindow::createVector() {
981   QString tmp;
982   DialogLauncher::self()->showVectorDialog(tmp);
983 }
984 
985 
createMatrix()986 void MainWindow::createMatrix() {
987   QString tmp;
988   DialogLauncher::self()->showMatrixDialog(tmp);
989 }
990 
991 
createScalar()992 void MainWindow::createScalar() {
993   QString scalarName;
994   DialogLauncher::self()->showScalarDialog(scalarName);
995 }
996 
997 
createString()998 void MainWindow::createString() {
999   QString stringName;
1000   DialogLauncher::self()->showStringDialog(stringName);
1001 }
1002 
1003 
createCircle()1004 void MainWindow::createCircle() {
1005   if (_createCircleAct->isChecked()) {
1006     clearDrawingMarker();
1007     _createCircleAct->setChecked(true);
1008     CreateCircleCommand *cmd = new CreateCircleCommand;
1009     cmd->createItem();
1010   } else {
1011     _tabWidget->currentView()->setMouseMode(View::Default);
1012   }
1013 }
1014 
1015 
createEllipse()1016 void MainWindow::createEllipse() {
1017   if (_createEllipseAct->isChecked()) {
1018     clearDrawingMarker();
1019     _createEllipseAct->setChecked(true);
1020     CreateEllipseCommand *cmd = new CreateEllipseCommand;
1021     cmd->createItem();
1022   } else {
1023     _tabWidget->currentView()->setMouseMode(View::Default);
1024   }
1025 }
1026 
1027 
createLabel()1028 void MainWindow::createLabel() {
1029   if (_createLabelAct->isChecked()) {
1030     clearDrawingMarker();
1031     _createLabelAct->setChecked(true);
1032     CreateLabelCommand *cmd = new CreateLabelCommand;
1033     cmd->createItem();
1034   } else {
1035     _tabWidget->currentView()->setMouseMode(View::Default);
1036   }
1037 }
1038 
1039 
createLine()1040 void MainWindow::createLine() {
1041   if (_createLineAct->isChecked()) {
1042     clearDrawingMarker();
1043     _createLineAct->setChecked(true);
1044     CreateLineCommand *cmd = new CreateLineCommand;
1045     cmd->createItem();
1046   } else {
1047     _tabWidget->currentView()->setMouseMode(View::Default);
1048   }
1049 }
1050 
1051 
createArrow()1052 void MainWindow::createArrow() {
1053   if (_createArrowAct->isChecked()) {
1054     clearDrawingMarker();
1055     _createArrowAct->setChecked(true);
1056     CreateArrowCommand *cmd = new CreateArrowCommand;
1057     cmd->createItem();
1058   } else {
1059     _tabWidget->currentView()->setMouseMode(View::Default);
1060   }
1061 }
1062 
1063 
createPicture()1064 void MainWindow::createPicture() {
1065   if (_createPictureAct->isChecked()) {
1066     clearDrawingMarker();
1067     _createPictureAct->setChecked(true);
1068     CreatePictureCommand *cmd = new CreatePictureCommand;
1069     cmd->createItem();
1070   } else {
1071     _tabWidget->currentView()->setMouseMode(View::Default);
1072   }
1073 }
1074 
1075 
createPlot()1076 void MainWindow::createPlot() {
1077   if (_createPlotAct->isChecked()) {
1078     clearDrawingMarker();
1079     _createPlotAct->setChecked(true);
1080     CreatePlotCommand *cmd = new CreatePlotCommand;
1081     cmd->createItem();
1082   } else {
1083     _tabWidget->currentView()->setMouseMode(View::Default);
1084   }
1085 }
1086 
insertPlot()1087 void MainWindow::insertPlot() {
1088   CreatePlotForCurve *cmd = new CreatePlotForCurve();
1089   cmd->createItem();
1090 
1091   PlotItem *plotItem = static_cast<PlotItem*>(cmd->item());
1092   plotItem->view()->resetPlotFontSizes(plotItem);
1093   plotItem->view()->configurePlotFontDefaults(plotItem); // copy plots already in window
1094   plotItem->view()->appendToLayout(CurvePlacement::Auto, plotItem, 0);
1095 
1096 }
1097 
1098 #ifndef KST_NO_SVG
createSvg()1099 void MainWindow::createSvg() {
1100   if (_createSvgAct->isChecked()) {
1101     clearDrawingMarker();
1102     _createSvgAct->setChecked(true);
1103     CreateSvgCommand *cmd = new CreateSvgCommand;
1104     cmd->createItem();
1105   } else {
1106     _tabWidget->currentView()->setMouseMode(View::Default);
1107   }
1108 }
1109 #endif
1110 
createCurve()1111 void MainWindow::createCurve() {
1112   DialogLauncher::self()->showCurveDialog();
1113 }
1114 
createPSD()1115 void MainWindow::createPSD() {
1116   DialogLauncher::self()->showPowerSpectrumDialog();
1117 }
1118 
createEquation()1119 void MainWindow::createEquation() {
1120   DialogLauncher::self()->showEquationDialog();
1121 }
1122 
createHistogram()1123 void MainWindow::createHistogram() {
1124   DialogLauncher::self()->showHistogramDialog();
1125 }
1126 
createImage()1127 void MainWindow::createImage() {
1128   DialogLauncher::self()->showImageDialog();
1129 }
1130 
createSpectogram()1131 void MainWindow::createSpectogram() {
1132   DialogLauncher::self()->showCSDDialog();
1133 }
1134 
createEventMonitor()1135 void MainWindow::createEventMonitor() {
1136   DialogLauncher::self()->showEventMonitorDialog();
1137 }
1138 
createActions()1139 void MainWindow::createActions() {
1140   // ***************************** File actions ******************************** //
1141   _openAct = new QAction(tr("&Open..."), this);
1142   _openAct->setStatusTip(tr("Open a new session"));
1143   _openAct->setShortcuts(QKeySequence::Open);
1144   _openAct->setIcon(KstGetIcon("document-open"));
1145   connect(_openAct, SIGNAL(triggered()), this, SLOT(open()));
1146 
1147   _saveAct = new QAction(tr("&Save"), this);
1148   _saveAct->setStatusTip(tr("Save the current session"));
1149   _saveAct->setShortcuts(QKeySequence::Save);
1150   _saveAct->setIcon(KstGetIcon("document-save"));
1151   connect(_saveAct, SIGNAL(triggered()), this, SLOT(save()));
1152 
1153   _saveAsAct = new QAction(tr("Save &as..."), this);
1154   _saveAsAct->setStatusTip(tr("Save the current session"));
1155   _saveAsAct->setIcon(KstGetIcon("document-save-as"));
1156   _saveAsAct->setShortcuts(QKeySequence::SaveAs);
1157   connect(_saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs()));
1158 
1159   _closeAct = new QAction(tr("Ne&w Session"), this);
1160   _closeAct->setStatusTip(tr("Close current session and start a new, empty one"));
1161   _closeAct->setIcon(KstGetIcon("document-close"));
1162   _closeAct->setShortcuts(QKeySequence::Close);
1163   connect(_closeAct, SIGNAL(triggered()), this, SLOT(newDoc()));
1164 
1165   _reloadAct = new QAction(tr("Reload All &Data Sources"), this);
1166   _reloadAct->setStatusTip(tr("Reload all data sources"));
1167   _reloadAct->setIcon(KstGetIcon("kst_reload"));
1168   connect(_reloadAct, SIGNAL(triggered()), this, SLOT(reload()));
1169 
1170   _printAct = new QAction(tr("&Print..."), this);
1171   _printAct->setStatusTip(tr("Print the current view"));
1172   _printAct->setIcon(KstGetIcon("document-print"));
1173   _printAct->setShortcuts(QKeySequence::Print);
1174   connect(_printAct, SIGNAL(triggered()), this, SLOT(print()));
1175 #ifdef KST_NO_PRINTER
1176   _printAct->setEnabled(false);
1177 #endif
1178 
1179   _exportGraphicsAct = new QAction(tr("&Export as Image(s)..."), this);
1180   _exportGraphicsAct->setStatusTip(tr("Export graphics to disk"));
1181   _exportGraphicsAct->setIcon(KstGetIcon("insert-image"));
1182   connect(_exportGraphicsAct, SIGNAL(triggered()), this, SLOT(showExportGraphicsDialog()));
1183 
1184   _exportVectorsAct = new QAction(tr("Save &Vectors to Disk..."), this);
1185   _exportVectorsAct->setStatusTip(tr("Export vectors to ascii file"));
1186   _exportVectorsAct->setIcon(KstGetIcon("save-vectors"));
1187   connect(_exportVectorsAct, SIGNAL(triggered()), this, SLOT(showExportVectorsDialog()));
1188 
1189   _logAct = new QAction(tr("&Log Entry..."), this);
1190   _logAct->setStatusTip(tr("Commit a log entry"));
1191   _logAct->setIcon(KstGetIcon("new-log-event"));
1192   connect(_logAct, SIGNAL(triggered()), this, SLOT(showLogDialog()));
1193 
1194   _newTabAct = new QAction(tr("&New Tab"), this);
1195   _newTabAct->setStatusTip(tr("Create a new tab"));
1196   _newTabAct->setIcon(KstGetIcon("tab-new"));
1197 
1198   connect(_newTabAct, SIGNAL(triggered()), tabWidget(), SLOT(createView()));
1199 
1200   _closeTabAct = new QAction(tr("&Close Tab"), this);
1201   _closeTabAct->setStatusTip(tr("Close the current tab"));
1202   _closeTabAct->setIcon(KstGetIcon("tab-close"));
1203   connect(_closeTabAct, SIGNAL(triggered()), tabWidget(), SLOT(closeCurrentView()));
1204 
1205   _exitAct = new QAction(tr("E&xit"), this);
1206   _exitAct->setShortcuts(QKeySequence::Quit);
1207   _exitAct->setStatusTip(tr("Exit the application"));
1208   _exitAct->setIcon(KstGetIcon("application-exit"));
1209   connect(_exitAct, SIGNAL(triggered()), this, SLOT(close()));
1210 
1211   // ************************** Edit Actions ******************************* //
1212   _undoAct = _undoGroup->createUndoAction(this);
1213   _undoAct->setShortcuts(QKeySequence::Undo);
1214   _undoAct->setIcon(KstGetIcon("edit-undo"));
1215 
1216   _redoAct = _undoGroup->createRedoAction(this);
1217   _redoAct->setShortcuts(QKeySequence::Redo);
1218   _redoAct->setIcon(KstGetIcon("edit-redo"));
1219 
1220   _copyTabAct = new QAction(tr("Copy Tab Image"), this);
1221   _copyTabAct->setStatusTip("Copy image of the current tab to the desktop clipboard");
1222   _copyTabAct->setIcon(KstGetIcon("edit-copy"));
1223   connect(_copyTabAct, SIGNAL(triggered()), this, SLOT(copyTab()));
1224 
1225   // ********************* View Actions ********************************** //
1226   _vectorEditorAct = new QAction(tr("&Vectors"), this);
1227   _vectorEditorAct->setStatusTip(tr("Show all vectors in a spreadsheet"));
1228   connect(_vectorEditorAct, SIGNAL(triggered()), this, SLOT(showVectorEditor()));
1229 
1230   _scalarEditorAct = new QAction(tr("&Scalars"), this);
1231   _scalarEditorAct->setStatusTip(tr("Show all scalars in a spreadsheet"));
1232   connect(_scalarEditorAct, SIGNAL(triggered()), this, SLOT(showScalarEditor()));
1233 
1234   _matrixEditorAct = new QAction(tr("&Matrices"), this);
1235   _matrixEditorAct->setStatusTip(tr("Show all matrices in a spreadsheet"));
1236   connect(_matrixEditorAct, SIGNAL(triggered()), this, SLOT(showMatrixEditor()));
1237 
1238   _stringEditorAct = new QAction(tr("S&trings"), this);
1239   _stringEditorAct->setStatusTip(tr("Show all strings in a spreadsheet"));
1240   connect(_stringEditorAct, SIGNAL(triggered()), this, SLOT(showStringEditor()));
1241 
1242   // ************************ Data Range 1 click Actions ************************** //
1243   _backAct = new QAction(tr("&Back One Screen"), this);
1244   _backAct->setStatusTip(tr("Back one screen (Page Up)"));
1245   _backAct->setToolTip(tr("Back one screen (Page Up)"));
1246   _backAct->setIcon(KstGetIcon("page-previous"));
1247   _backAct->setShortcut(Qt::Key_PageUp);
1248   connect(_backAct, SIGNAL(triggered()), this, SLOT(back()));
1249 
1250   _forwardAct = new QAction(tr("&Forward One Screen"), this);
1251   _forwardAct->setStatusTip(tr("Forward one screen (Page Down)"));
1252   _forwardAct->setToolTip(tr("Forward one screen (Page Down)"));
1253   _forwardAct->setIcon(KstGetIcon("page-next"));
1254   _forwardAct->setShortcut(Qt::Key_PageDown);
1255   connect(_forwardAct, SIGNAL(triggered()), this, SLOT(forward()));
1256 
1257   _backSmallAct = new QAction(tr("&Back 1/5th Screen"), this);
1258   _backSmallAct->setStatusTip(tr("Back 1/5th screen (Shift + Page Up)"));
1259   _backSmallAct->setToolTip(tr("Back 1/5th screen (Shift + Page Up)"));
1260   _backSmallAct->setIcon(KstGetIcon("page-previous"));
1261   _backSmallAct->setShortcut(Qt::SHIFT + Qt::Key_PageDown);
1262   connect(_backSmallAct, SIGNAL(triggered()), this, SLOT(backSmall()));
1263 
1264   _forwardSmallAct = new QAction(tr("&Forward 1/5th Screen"), this);
1265   _forwardSmallAct->setStatusTip(tr("Forward 1/5th screen (Page Down)"));
1266   _forwardSmallAct->setToolTip(tr("Forward 1/5th screen (Page Down)"));
1267   _forwardSmallAct->setIcon(KstGetIcon("page-next"));
1268   _forwardSmallAct->setShortcut(Qt::SHIFT + Qt::Key_PageUp);
1269   connect(_forwardSmallAct, SIGNAL(triggered()), this, SLOT(forwardSmall()));
1270 
1271   _readFromEndAct = new QAction(tr("&Count from End"), this);
1272   _readFromEndAct->setStatusTip(tr("Count from end mode (End)"));
1273   _readFromEndAct->setToolTip(tr("Count from end mode (End)"));
1274   _readFromEndAct->setIcon(KstGetIcon("count-from-end"));
1275   _readFromEndAct->setShortcut(Qt::Key_End);
1276   connect(_readFromEndAct, SIGNAL(triggered()), this, SLOT(readFromEnd()));
1277 
1278   _readToEndAct = new QAction(tr("&Read to End"), this);
1279   _readToEndAct->setStatusTip(tr("Read to end mode"));
1280   _readToEndAct->setToolTip(tr("Read to end mode (shift+end)"));
1281   _readToEndAct->setIcon(KstGetIcon("read-to-end"));
1282   _readToEndAct->setShortcut(Qt::ShiftModifier+Qt::Key_End);
1283   connect(_readToEndAct, SIGNAL(triggered()), this, SLOT(readToEnd()));
1284 
1285   _pauseAct = new QAction(tr("&Pause"), this);
1286   _pauseAct->setIcon(KstGetIcon("pause"));
1287   _pauseAct->setCheckable(true);
1288   _pauseAct->setShortcut(tr("p", "shortcut for pause"));
1289   _pauseAct->setStatusTip(tr("Toggle pause updates of data sources (%1)").arg(_pauseAct->shortcut().toString()));
1290   _pauseAct->setToolTip(tr("Toggle \"Pause Data Sources\" (%1)").arg(_pauseAct->shortcut().toString()));
1291   connect(_pauseAct, SIGNAL(toggled(bool)), this, SLOT(pause(bool)));
1292 
1293   _changeDataSampleDialogAct = new QAction(tr("Change Data &Sample Range..."), this);
1294   _changeDataSampleDialogAct->setShortcut(tr("J", "shortcut change data sample dialog"));
1295   _changeDataSampleDialogAct->setStatusTip(tr("Show Kst's Change Data Sample Range Dialog (%1)").arg(_changeDataSampleDialogAct->shortcut().toString()));
1296   _changeDataSampleDialogAct->setToolTip(tr("Change Data Sample Range (%1)").arg(_changeDataSampleDialogAct->shortcut().toString()));
1297   _changeDataSampleDialogAct->setIcon(KstGetIcon("kst_changenpts"));
1298   connect(_changeDataSampleDialogAct, SIGNAL(triggered()), this, SLOT(showChangeDataSampleDialog()));
1299 
1300   // ************************ Create Actions ************************** //
1301   _insertPlotAct = new QAction(tr("&Plot"), this);
1302   _insertPlotAct->setIcon(KstGetIcon("kst_newplot"));
1303   _insertPlotAct->setShortcut(QString("F11"));
1304   _insertPlotAct->setStatusTip(tr("Insert a plot in the current view (%1)").arg(_insertPlotAct->shortcut().toString()));
1305   _insertPlotAct->setToolTip(tr("New plot (%1)").arg(_insertPlotAct->shortcut().toString()));
1306   _insertPlotAct->setCheckable(false);
1307   connect(_insertPlotAct, SIGNAL(triggered()), this, SLOT(insertPlot()));
1308 
1309   _createPlotAct = new QAction(tr("&Plot"), this);
1310   _createPlotAct->setIcon(KstGetIcon("kst_newplot"));
1311   //_createPlotAct->setShortcut(QString("F11"));
1312   _createPlotAct->setStatusTip(tr("Create a plot for the current view"));
1313   _createPlotAct->setCheckable(true);
1314   connect(_createPlotAct, SIGNAL(triggered()), this, SLOT(createPlot()));
1315 
1316   _newScalarAct = new QAction(tr("&Scalar"), this);
1317   connect(_newScalarAct, SIGNAL(triggered()), this, SLOT(createScalar()));
1318 
1319   _newVectorAct = new QAction(tr("&Vector"), this);
1320   connect(_newVectorAct, SIGNAL(triggered()), this, SLOT(createVector()));
1321 
1322   _newMatrixAct = new QAction(tr("&Matrix"), this);
1323   connect(_newMatrixAct, SIGNAL(triggered()), this, SLOT(createMatrix()));
1324 
1325   _newStringAct = new QAction(tr("Strin&g"), this);
1326   connect(_newStringAct, SIGNAL(triggered()), this, SLOT(createString()));
1327 
1328   _newCurveAct = new QAction(tr("&Curve"), this);
1329   connect(_newCurveAct, SIGNAL(triggered()), this, SLOT(createCurve()));
1330 
1331   _newEquationAct = new QAction(tr("&Equation"), this);
1332   connect(_newEquationAct, SIGNAL(triggered()), this, SLOT(createEquation()));
1333 
1334   _newPSDAct = new QAction(tr("Po&wer Spectrum"), this);
1335   connect(_newPSDAct, SIGNAL(triggered()), this, SLOT(createPSD()));
1336 
1337   _newHistogramAct = new QAction(tr("&Histogram"), this);
1338   connect(_newHistogramAct, SIGNAL(triggered()), this, SLOT(createHistogram()));
1339 
1340   _newImageAct = new QAction(tr("&Image"), this);
1341   connect(_newImageAct, SIGNAL(triggered()), this, SLOT(createImage()));
1342 
1343   _newSpectrogramAct = new QAction(tr("Spectr&ogram"), this);
1344   connect(_newSpectrogramAct, SIGNAL(triggered()), this, SLOT(createSpectogram()));
1345 
1346   _newEventMonitorAct = new QAction(tr("Eve&nt Monitor"), this);
1347   connect(_newEventMonitorAct, SIGNAL(triggered()), this, SLOT(createEventMonitor()));
1348 
1349   // Advanced layout
1350   _createLabelAct = new QAction(tr("&Label"), this);
1351   _createLabelAct->setIcon(KstGetIcon("kst_gfx_label"));
1352   _createLabelAct->setShortcut(QString("F3"));
1353   _createLabelAct->setStatusTip(tr("Create a label for the current view (%1)").arg(_createLabelAct->shortcut().toString()));
1354   _createLabelAct->setToolTip(tr("Create label (%1)").arg(_createLabelAct->shortcut().toString()));
1355   _createLabelAct->setCheckable(true);
1356   connect(_createLabelAct, SIGNAL(triggered()), this, SLOT(createLabel()));
1357 
1358   _createBoxAct = new QAction(tr("&Box"), this);
1359   _createBoxAct->setIcon(KstGetIcon("kst_gfx_rectangle"));
1360   _createBoxAct->setShortcut(QString("F4"));
1361   _createBoxAct->setStatusTip(tr("Create a box for the current view (%1)").arg(_createBoxAct->shortcut().toString()));
1362   _createBoxAct->setToolTip(tr("Create box (%1)").arg(_createBoxAct->shortcut().toString()));
1363   _createBoxAct->setCheckable(true);
1364   connect(_createBoxAct, SIGNAL(triggered()), this, SLOT(createBox()));
1365 
1366   _createCircleAct = new QAction(tr("&Circle"), this);
1367   _createCircleAct->setIcon(KstGetIcon("kst_gfx_circle"));
1368   _createCircleAct->setShortcut(QString("F5"));
1369   _createCircleAct->setStatusTip(tr("Create a circle for the current view (%1)").arg(_createCircleAct->shortcut().toString()));
1370   _createCircleAct->setToolTip(tr("Create circle (%1)").arg(_createCircleAct->shortcut().toString()));
1371   _createCircleAct->setCheckable(true);
1372   connect(_createCircleAct, SIGNAL(triggered()), this, SLOT(createCircle()));
1373 
1374   _createEllipseAct = new QAction(tr("&Ellipse"), this);
1375   _createEllipseAct->setIcon(KstGetIcon("kst_gfx_ellipse"));
1376   _createEllipseAct->setShortcut(QString("F6"));
1377   _createEllipseAct->setStatusTip(tr("Create an ellipse for the current view (%1)").arg(_createEllipseAct->shortcut().toString()));
1378   _createEllipseAct->setToolTip(tr("Create ellipse (%1)").arg(_createEllipseAct->shortcut().toString()));
1379   _createEllipseAct->setCheckable(true);
1380   connect(_createEllipseAct, SIGNAL(triggered()), this, SLOT(createEllipse()));
1381 
1382   _createLineAct = new QAction(tr("&Line"), this);
1383   _createLineAct->setIcon(KstGetIcon("kst_gfx_line"));
1384   _createLineAct->setShortcut(QString("F7"));
1385   _createLineAct->setStatusTip(tr("Create a line for the current view (%1)").arg(_createLineAct->shortcut().toString()));
1386   _createLineAct->setToolTip(tr("Create line (%1)").arg(_createLineAct->shortcut().toString()));
1387   _createLineAct->setCheckable(true);
1388   connect(_createLineAct, SIGNAL(triggered()), this, SLOT(createLine()));
1389 
1390   _createArrowAct = new QAction(tr("&Arrow"), this);
1391   _createArrowAct->setIcon(KstGetIcon("kst_gfx_arrow"));
1392   _createArrowAct->setShortcut(QString("F8"));
1393   _createArrowAct->setStatusTip(tr("Create a arrow for the current view (%1)").arg(_createArrowAct->shortcut().toString()));
1394   _createArrowAct->setToolTip(tr("Create arrow (%1)").arg(_createArrowAct->shortcut().toString()));
1395   _createArrowAct->setCheckable(true);
1396   connect(_createArrowAct, SIGNAL(triggered()), this, SLOT(createArrow()));
1397 
1398   _createPictureAct = new QAction(tr("&Picture"), this);
1399   _createPictureAct->setIcon(KstGetIcon("insert-image"));
1400   _createPictureAct->setShortcut(QString("F9"));
1401   _createPictureAct->setStatusTip(tr("Create a picture for the current view (%1)").arg(_createPictureAct->shortcut().toString()));
1402   _createPictureAct->setToolTip(tr("Create picture (%1)").arg(_createPictureAct->shortcut().toString()));
1403   _createPictureAct->setCheckable(true);
1404   connect(_createPictureAct, SIGNAL(triggered()), this, SLOT(createPicture()));
1405 
1406 #ifndef KST_NO_SVG
1407   _createSvgAct = new QAction(tr("&Svg"), this);
1408   _createSvgAct->setIcon(KstGetIcon("draw-bezier-curves"));
1409   _createSvgAct->setShortcut(QString("F10"));
1410   _createSvgAct->setStatusTip(tr("Create a svg for the current view (%1)").arg(_createSvgAct->shortcut().toString()));
1411   _createSvgAct->setToolTip(tr("Create embedded svg image (%1)").arg(_createSvgAct->shortcut().toString()));
1412   _createSvgAct->setCheckable(true);
1413   connect(_createSvgAct, SIGNAL(triggered()), this, SLOT(createSvg()));
1414 #endif
1415 
1416   _createSharedAxisBoxAct = new QAction(tr("Shared Axis &Box"), this);
1417   _createSharedAxisBoxAct->setStatusTip(tr("Create a shared axis box for the current item"));
1418   _createSharedAxisBoxAct->setIcon(KstGetIcon("kst_gfx_sharedaxisbox"));
1419   _createSharedAxisBoxAct->setCheckable(true);
1420   connect(_createSharedAxisBoxAct, SIGNAL(triggered()), this, SLOT(createSharedAxisBox()));
1421 
1422   // ************************** Mode Actions ******************************* //
1423   // First, general options
1424   _tiedZoomAct = new QAction(tr("&Toggle Tied Zoom"), this);
1425   _tiedZoomAct->setIcon(KstGetIcon("tied-zoom"));
1426   _tiedZoomAct->setCheckable(false);
1427   _tiedZoomAct->setShortcut(Qt::Key_O);
1428   _tiedZoomAct->setStatusTip(tr("Toggle the current view's tied zoom (%1)").arg(_tiedZoomAct->shortcut().toString()));
1429   _tiedZoomAct->setToolTip(tr("Toggle tied zoom (%1)").arg(_tiedZoomAct->shortcut().toString()));
1430   connect(_tiedZoomAct, SIGNAL(triggered()), this, SLOT(toggleTiedZoom()));
1431 
1432   _tabTiedAct = new QAction(tr("Tie &Across All Tabs"), this);
1433   _tabTiedAct->setStatusTip(tr("Tied zoom applies between tabs"));
1434   //_tiedZoomAct->setIcon(KstGetIcon("tied-zoom"));
1435   _tabTiedAct->setCheckable(true);
1436   //connect(_tiedZoomAct, SIGNAL(triggered()), this, SLOT(toggleTiedZoom()));
1437 
1438 
1439   _highlightPointAct = new QAction(tr("&Highlight Data Points"), this);
1440   _highlightPointAct->setShortcut(QString("h"));
1441   _highlightPointAct->setStatusTip(tr("Highlight closest data point (%1)").arg(_highlightPointAct->shortcut().toString()));
1442   _highlightPointAct->setToolTip(tr("Highlight closest data point (%1)").arg(_highlightPointAct->shortcut().toString()));
1443   _highlightPointAct->setIcon(KstGetIcon("kst_datamode"));
1444   _highlightPointAct->setCheckable(true);
1445   connect(_highlightPointAct, SIGNAL(toggled(bool)), this, SLOT(setHighlightPoint(bool)));
1446 
1447 
1448   // Then, exclusive interaction modes
1449   QActionGroup* _interactionModeGroup = new QActionGroup(this);
1450 
1451   _standardZoomAct = _interactionModeGroup->addAction(tr("X-Y Zoom/Scroll"));
1452   _standardZoomAct->setStatusTip(tr("Zoom arbitrarily in X- or Y-direction"));
1453   _standardZoomAct->setShortcut(Qt::Key_K);
1454   _standardZoomAct->setToolTip(tr("X-Y Zoom mode (%1)").arg(_standardZoomAct->shortcut().toString()));
1455   _standardZoomAct->setCheckable(true);
1456   _standardZoomAct->setData(View::ZoomOnlyDisabled);
1457   _standardZoomAct->setIcon(KstGetIcon("xy-zoom"));
1458 
1459   _xOnlyZoomAct = _interactionModeGroup->addAction(tr("&X-only Zoom"));
1460   _xOnlyZoomAct->setStatusTip(tr("Zoom only in X direction"));
1461   _xOnlyZoomAct->setShortcut(Qt::CTRL + Qt::Key_K);
1462   _xOnlyZoomAct->setToolTip(tr("X Zoom mode (%1)").arg(_xOnlyZoomAct->shortcut().toString()));
1463   _xOnlyZoomAct->setCheckable(true);
1464   _xOnlyZoomAct->setData(View::ZoomOnlyX);
1465   _xOnlyZoomAct->setIcon(KstGetIcon("x-zoom"));
1466 
1467   _yOnlyZoomAct = _interactionModeGroup->addAction(tr("&Y-only Zoom"));
1468   _yOnlyZoomAct->setStatusTip(tr("Zoom only in Y direction"));
1469   _yOnlyZoomAct->setShortcut(Qt::SHIFT + Qt::Key_K);
1470   _yOnlyZoomAct->setToolTip(tr("Y Zoom mode (%1)").arg(_yOnlyZoomAct->shortcut().toString()));
1471   _yOnlyZoomAct->setData(View::ZoomOnlyY);
1472   _yOnlyZoomAct->setCheckable(true);
1473   _yOnlyZoomAct->setIcon(KstGetIcon("y-zoom"));
1474 
1475   _layoutModeAct = _interactionModeGroup->addAction(tr("&Layout Mode"));
1476   _layoutModeAct->setIcon(KstGetIcon("transform-move"));
1477   _layoutModeAct->setCheckable(true);
1478   _layoutModeAct->setShortcut(QString("F2"));
1479   _layoutModeAct->setStatusTip(tr("Toggle the current view's layout mode (%1)").arg(_layoutModeAct->shortcut().toString()));
1480   _layoutModeAct->setToolTip(tr("Layout mode (%1)").arg(_layoutModeAct->shortcut().toString()));
1481   connect(_layoutModeAct, SIGNAL(toggled(bool)), this, SLOT(setLayoutMode(bool)));
1482 
1483   _interactionModeGroup->setExclusive(true);
1484   connect(_interactionModeGroup, SIGNAL(triggered(QAction*)), this, SLOT(changeZoomOnlyMode(QAction*)));
1485 
1486   // *********************** Tools actions ************************************** //
1487   _dataManagerAct = new QAction(tr("Data Manager"), this);
1488   _dataManagerAct->setIcon(KstGetIcon("data-manager"));
1489   _dataManagerAct->setShortcut(QString("d"));
1490   _dataManagerAct->setStatusTip(tr("Show Kst's data manager window (%1)").arg(_dataManagerAct->shortcut().toString()));
1491   _dataManagerAct->setToolTip(tr("Show Data Manager (%1)").arg(_dataManagerAct->shortcut().toString()));
1492   connect(_dataManagerAct, SIGNAL(triggered()), this, SLOT(showDataManager()));
1493 
1494   _dataWizardAct = new QAction(tr("&Data Wizard"), this);
1495   _dataWizardAct->setIcon(KstGetIcon("tools-wizard"));
1496   _dataWizardAct->setShortcut(QString("w"));
1497   _dataWizardAct->setStatusTip(tr("Show Kst's Data Wizard (%1)").arg(_dataWizardAct->shortcut().toString()));
1498   _dataWizardAct->setToolTip(tr("Show Data Wizard (%1)").arg(_dataWizardAct->shortcut().toString()));
1499   connect(_dataWizardAct, SIGNAL(triggered()), this, SLOT(showDataWizard()));
1500 
1501   _changeFileDialogAct = new QAction(tr("Change Data &File"), this);
1502   _changeFileDialogAct->setIcon(KstGetIcon("change-data-file"));
1503   _changeFileDialogAct->setStatusTip(tr("Show Kst's Change Data File Dialog (%1)").arg(_changeFileDialogAct->shortcut().toString()));
1504   _changeFileDialogAct->setShortcut(QString("f"));
1505   _changeFileDialogAct->setToolTip(tr("Show Change Data File Dialog (%1)").arg(_changeFileDialogAct->shortcut().toString()));
1506   connect(_changeFileDialogAct, SIGNAL(triggered()), this, SLOT(showChangeFileDialog()));
1507 
1508   _chooseColorDialogAct = new QAction(tr("Assign Curve &Color per File"), this);
1509   _chooseColorDialogAct->setStatusTip(tr("Show Kst's Choose Color Dialog"));
1510   _chooseColorDialogAct->setIcon(KstGetIcon("code-class"));
1511   connect(_chooseColorDialogAct, SIGNAL(triggered()), this, SLOT(showChooseColorDialog()));
1512 
1513   _differentiateCurvesDialogAct = new QAction(tr("D&ifferentiate Curves"), this);
1514   _differentiateCurvesDialogAct->setStatusTip(tr("Show Kst's Differentiate Curves Dialog"));
1515   _differentiateCurvesDialogAct->setIcon(KstGetIcon("kst_differentiatecurves"));
1516   connect(_differentiateCurvesDialogAct, SIGNAL(triggered()), this, SLOT(showDifferentiateCurvesDialog()));
1517 
1518   _filterMultipleDialogAct = new QAction(tr("&Filter Vectors"), this);
1519   _filterMultipleDialogAct->setStatusTip(tr("Filter multiple vectors"));
1520   _filterMultipleDialogAct->setIcon(KstGetIcon("kst_filter_vectors"));
1521   connect(_filterMultipleDialogAct, SIGNAL(triggered()), this, SLOT(filterMultipleDialog()));
1522 
1523   // *********************** Settings actions ************************************** //
1524   _settingsDialogAct = new QAction(tr("&Configure Kst"), this);
1525   _settingsDialogAct->setStatusTip(tr("Show Kst's Configuration Dialog"));
1526   _settingsDialogAct->setIcon(KstGetIcon("configure"));
1527   connect(_settingsDialogAct, SIGNAL(triggered()), this, SLOT(showSettingsDialog()));
1528 
1529   _themeDialogAct = new QAction(tr("&Theme"), this);
1530   _themeDialogAct->setStatusTip(tr("Show Kst's Theme Dialog"));
1531   _themeDialogAct->setIcon(KstGetIcon("themes"));
1532   connect(_themeDialogAct, SIGNAL(triggered()), this, SLOT(showThemeDialog()));
1533 
1534   _clearUISettings =  new QAction(tr("Clear settings and defaults"), this);
1535   _clearUISettings->setStatusTip(tr("Clear sticky defaults and all settings in all dialogs."));
1536   //_clearUISettings->setIcon(KstGetIcon("configure"));  // FIXME: pick an icon (broom?)
1537   connect(_clearUISettings, SIGNAL(triggered()), this, SLOT(clearDefaults()));
1538 
1539   _clearDataSourceSettings =  new QAction(tr("Clear datasource settings"), this);
1540   _clearDataSourceSettings->setStatusTip(tr("Clear datasource settings"));
1541   //_clearDataSourceSettings->setIcon(KstGetIcon("configure"));   // FIXME: pick an icon (broom?)
1542   connect(_clearDataSourceSettings, SIGNAL(triggered()), this, SLOT(clearDataSourceSettings()));
1543 
1544   // *********************** Help actions ************************************** //
1545   _debugDialogAct = new QAction(tr("&Debug Dialog"), this);
1546   _debugDialogAct->setStatusTip(tr("Show the Kst debugging dialog"));
1547   _debugDialogAct->setIcon(KstGetIcon("text-x-log"));
1548   connect(_debugDialogAct, SIGNAL(triggered()), this, SLOT(showDebugDialog()));
1549 
1550   _bugReportWizardAct = new QAction(tr("&Bug Report Wizard"), this);
1551   _bugReportWizardAct->setStatusTip(tr("Show Kst's Bug Report Wizard"));
1552   _bugReportWizardAct->setIcon(KstGetIcon("kbugbuster"));
1553   connect(_bugReportWizardAct, SIGNAL(triggered()), this, SLOT(showBugReportWizard()));
1554 
1555   _aboutAct = new QAction(tr("&About"), this);
1556   _aboutAct->setStatusTip(tr("Show Kst's About box"));
1557   _aboutAct->setIcon(KstGetIcon("dialog-information"));
1558   connect(_aboutAct, SIGNAL(triggered()), this, SLOT(about()));
1559 
1560   _showShortcutAct = new QAction(tr("Keyboard Shortcuts"), this);
1561   _showShortcutAct->setStatusTip(tr("Show a list of keyboard shortcuts"));
1562   connect(_showShortcutAct, SIGNAL(triggered()), this, SLOT(showShortcutDialog()));
1563 
1564   _video1Act = new QAction(tr("#&1: Quick Start"), this);
1565   _video1Act->setStatusTip(tr("Kst presentation #1: The shortest tutorial to the fastest plotting tool"));
1566   connect(_video1Act, SIGNAL(triggered()), _videoMapper, SLOT(map()));
1567   _videoMapper->setMapping(_video1Act, 1);
1568   _video2Act = new QAction(tr("#&2: General UI Presentation"), this);
1569   _video2Act->setStatusTip(tr("Kst presentation #2: General presentation of the user interface and most important concepts"));
1570   connect(_video2Act, SIGNAL(triggered()), _videoMapper, SLOT(map()));
1571   _videoMapper->setMapping(_video2Act, 2);
1572   _video3Act = new QAction(tr("#&3: Live Data / Range Tools"), this);
1573   _video3Act->setStatusTip(tr("Kst presentation #3: Range tools and live plots with streaming data"));
1574   connect(_video3Act, SIGNAL(triggered()), _videoMapper, SLOT(map()));
1575   _videoMapper->setMapping(_video3Act, 3);
1576   _video4Act = new QAction(tr("#&4: FFT, Equations, Fits, Filters"), this);
1577   _video4Act->setStatusTip(tr("Kst presentation #4: FFTs, equations, filters, fits, plugins"));
1578   connect(_video4Act, SIGNAL(triggered()), _videoMapper, SLOT(map()));
1579   _videoMapper->setMapping(_video4Act, 4);
1580   _video5Act = new QAction(tr("#&5: Productivity Features"), this);
1581   _video5Act->setStatusTip(tr("Kst presentation #5: Unique productivity features like edit multiple mode and change data file tool"));
1582   connect(_video5Act, SIGNAL(triggered()), _videoMapper, SLOT(map()));
1583   _videoMapper->setMapping(_video5Act, 5);
1584   _video6Act = new QAction(tr("#&6: Advanced Layout / Export"), this);
1585   _video6Act->setStatusTip(tr("Kst presentation #6: Advanced layout and export options"));
1586   connect(_video6Act, SIGNAL(triggered()), _videoMapper, SLOT(map()));
1587   _videoMapper->setMapping(_video6Act, 6);
1588   _video7Act = new QAction(tr("#&7: Matrices / Images / Metadata"), this);
1589   _video7Act->setStatusTip(tr("Kst presentation #7: Matrices, images and metadata"));
1590   connect(_video7Act, SIGNAL(triggered()), _videoMapper, SLOT(map()));
1591   _videoMapper->setMapping(_video7Act, 7);
1592   connect(_videoMapper, SIGNAL(mapped(int)), this, SLOT(videoTutorial(int)));
1593 }
1594 
1595 
createMenus()1596 void MainWindow::createMenus() {
1597   _fileMenu = menuBar()->addMenu(tr("&File"));
1598   // Session operations
1599   _fileMenu->addAction(_openAct);
1600   _fileMenu->addAction(_saveAct);
1601   _fileMenu->addAction(_saveAsAct);
1602   _fileMenu->addAction(_closeAct);
1603   _fileMenu->addSeparator();
1604   _recentKstFilesMenu = _fileMenu->addMenu(tr("&Recent Sessions"));
1605   _recentDataFilesMenu = _fileMenu->addMenu(tr("Recent Data &Files"));
1606   _fileMenu->addSeparator();
1607   // Reload, isolate it a bit from the other entries to avoid inadvertent triggering
1608   _fileMenu->addAction(_reloadAct);
1609   _fileMenu->addSeparator();
1610   // Print/export
1611   _fileMenu->addAction(_printAct);
1612   _fileMenu->addAction(_exportGraphicsAct);
1613   _fileMenu->addAction(_exportVectorsAct);
1614   _fileMenu->addAction(_logAct);
1615   _fileMenu->addSeparator();
1616   // Tabs
1617   _fileMenu->addAction(_newTabAct);
1618   _fileMenu->addAction(_closeTabAct);
1619   _fileMenu->addSeparator();
1620   // exit
1621   _fileMenu->addAction(_exitAct);
1622   // recent files
1623   _fileMenu->addSeparator();
1624   updateRecentKstFiles();
1625 
1626 
1627   _editMenu = menuBar()->addMenu(tr("&Edit"));
1628   _editMenu->addAction(_undoAct);
1629   _editMenu->addAction(_redoAct);
1630   _editMenu->addAction(_copyTabAct);
1631   // Cut/Copy/Paste will come here
1632 
1633   _viewMenu = menuBar()->addMenu(tr("&View"));
1634   _viewMenu->addAction(_vectorEditorAct);
1635   _viewMenu->addAction(_scalarEditorAct);
1636   _viewMenu->addAction(_matrixEditorAct);
1637   _viewMenu->addAction(_stringEditorAct);
1638 
1639   _rangeMenu = menuBar()->addMenu(tr("&Range"));
1640   _rangeMenu->addAction(_backAct);
1641   _rangeMenu->addAction(_backSmallAct);
1642   _rangeMenu->addAction(_forwardAct);
1643   _rangeMenu->addAction(_forwardSmallAct);
1644   _rangeMenu->addSeparator();
1645   _rangeMenu->addAction(_readFromEndAct);
1646   _rangeMenu->addAction(_readToEndAct);
1647   _rangeMenu->addAction(_pauseAct);
1648   _rangeMenu->addSeparator();
1649   _rangeMenu->addAction(_changeDataSampleDialogAct);
1650 
1651   _createMenu = menuBar()->addMenu(tr("&Create"));
1652   // Containers
1653   _createMenu->addAction(_insertPlotAct);
1654   //_createMenu->addAction(_createPlotAct);
1655   _createMenu->addAction(_createSharedAxisBoxAct);
1656   _createMenu->addSeparator();
1657   // Primitives
1658   _createMenu->addAction(_newScalarAct);
1659   _createMenu->addAction(_newVectorAct);
1660   _createMenu->addAction(_newMatrixAct);
1661   _createMenu->addAction(_newStringAct);
1662   _createMenu->addSeparator();
1663   // Data objects
1664   _createMenu->addAction(_newEquationAct);
1665   _createMenu->addAction(_newHistogramAct);
1666   _createMenu->addAction(_newPSDAct);
1667   _createMenu->addAction(_newSpectrogramAct);
1668   _createMenu->addAction(_newEventMonitorAct);
1669   _createMenu->addSeparator();
1670 
1671   // Now, create the dynamic plugin menus
1672   QMenu* _pluginsMenu = _createMenu->addMenu(tr("Standard P&lugin"));
1673   QMenu* _fitPluginsMenu = _createMenu->addMenu(tr("Fit Pl&ugin"));
1674   QMenu* _filterPluginsMenu = _createMenu->addMenu(tr("Fil&ter Plugin"));
1675   PluginMenuItemAction* action;
1676   foreach (const QString &pluginName, DataObject::dataObjectPluginList()) {
1677     action = new PluginMenuItemAction(pluginName, this);
1678     connect(action, SIGNAL(triggered(QString&)), this, SLOT(showPluginDialog(QString&)));
1679     _pluginsMenu->addAction(action);
1680   }
1681   foreach (const QString &pluginName, DataObject::fitsPluginList()) {
1682     action = new PluginMenuItemAction(pluginName, this);
1683     connect(action, SIGNAL(triggered(QString&)), this, SLOT(showPluginDialog(QString&)));
1684     _fitPluginsMenu->addAction(action);
1685   }
1686   foreach (const QString &pluginName, DataObject::filterPluginList()) {
1687     action = new PluginMenuItemAction(pluginName, this);
1688     connect(action, SIGNAL(triggered(QString&)), this, SLOT(showPluginDialog(QString&)));
1689     _filterPluginsMenu->addAction(action);
1690   }
1691   _createMenu->addSeparator();
1692   // Relations
1693   _createMenu->addAction(_newCurveAct);
1694   _createMenu->addAction(_newImageAct);
1695   _createMenu->addSeparator();
1696   // Annotation objects
1697   QMenu* annotations = _createMenu->addMenu(tr("&Annotation"));
1698   annotations->addAction(_createLabelAct);
1699   annotations->addAction(_createBoxAct);
1700   annotations->addAction(_createCircleAct);
1701   annotations->addAction(_createEllipseAct);
1702   annotations->addAction(_createLineAct);
1703   annotations->addAction(_createArrowAct);
1704   annotations->addAction(_createPictureAct);
1705 #ifndef KST_NO_SVG
1706   annotations->addAction(_createSvgAct);
1707 #endif
1708 
1709   _modeMenu = menuBar()->addMenu(tr("&Mode"));
1710   // Interaction mode
1711   _modeMenu->addSeparator()->setText(tr("Interaction mode"));
1712   _modeMenu->addAction(_standardZoomAct);
1713   _modeMenu->addAction(_xOnlyZoomAct);
1714   _modeMenu->addAction(_yOnlyZoomAct);
1715   _modeMenu->addAction(_layoutModeAct);
1716   _standardZoomAct->setChecked(true);
1717   _modeMenu->addSeparator();
1718   // Tied zoom options
1719   _modeMenu->addAction(_tiedZoomAct);
1720   _modeMenu->addAction(_tabTiedAct);
1721   _modeMenu->addSeparator();
1722   // Data mode
1723   _modeMenu->addAction(_highlightPointAct);
1724 
1725   _toolsMenu = menuBar()->addMenu(tr("&Tools"));
1726   _toolsMenu->addAction(_dataManagerAct);
1727   _toolsMenu->addAction(_dataWizardAct);
1728   _toolsMenu->addAction(_changeFileDialogAct);
1729   _toolsMenu->addAction(_chooseColorDialogAct);
1730   _toolsMenu->addAction(_differentiateCurvesDialogAct);
1731   _toolsMenu->addAction(_filterMultipleDialogAct);
1732   _toolsMenu->addSeparator();
1733   updateRecentDataFiles();
1734 
1735   _settingsMenu = menuBar()->addMenu(tr("&Settings"));
1736   _settingsMenu->addAction(_settingsDialogAct);
1737   _settingsMenu->addAction(_themeDialogAct);
1738   _settingsMenu->addAction(_clearUISettings);
1739   _settingsMenu->addAction(_clearDataSourceSettings);
1740 
1741   menuBar()->addSeparator();
1742 
1743   _helpMenu = menuBar()->addMenu(tr("&Help"));
1744   QMenu* _videoTutorialsMenu = _helpMenu->addMenu(tr("&Video tutorials"));
1745   _videoTutorialsMenu->addAction(_video1Act);
1746   _videoTutorialsMenu->addAction(_video2Act);
1747   _videoTutorialsMenu->addAction(_video3Act);
1748   _videoTutorialsMenu->addAction(_video4Act);
1749   _videoTutorialsMenu->addAction(_video5Act);
1750   _videoTutorialsMenu->addAction(_video6Act);
1751   _videoTutorialsMenu->addAction(_video7Act);
1752   _helpMenu->addSeparator();
1753   _helpMenu->addAction(_debugDialogAct);
1754   _helpMenu->addAction(_bugReportWizardAct);
1755   _helpMenu->addSeparator();
1756   _helpMenu->addAction(_showShortcutAct);
1757   _helpMenu->addAction(_aboutAct);
1758 
1759 }
1760 
1761 
createToolBars()1762 void MainWindow::createToolBars() {
1763   setToolButtonStyle(Qt::ToolButtonIconOnly);
1764 
1765   _fileToolBar = addToolBar(tr("File"));
1766   _fileToolBar->setObjectName("File Toolbar");
1767   _fileToolBar->addAction(_openAct);
1768   _fileToolBar->addAction(_saveAct);
1769   _fileToolBar->addAction(_reloadAct);
1770   _fileToolBar->addAction(_printAct);
1771   _fileToolBar->addAction(_logAct);
1772 
1773   _editToolBar = addToolBar(tr("Edit"));
1774   _editToolBar->setObjectName("Edit Toolbar");
1775   _editToolBar->addAction(_undoAct);
1776   _editToolBar->addAction(_redoAct);
1777   _editToolBar->addAction(_copyTabAct);
1778 
1779   _toolsToolBar = addToolBar(tr("Tools"));
1780   _toolsToolBar->setObjectName("Tools Toolbar");
1781   _toolsToolBar->addAction(_dataManagerAct);
1782   _toolsToolBar->addAction(_dataWizardAct);
1783   _toolsToolBar->addAction(_changeDataSampleDialogAct);
1784   _toolsToolBar->addAction(_changeFileDialogAct);
1785 
1786   _rangeToolBar = addToolBar(tr("Data Range"));
1787   _rangeToolBar->setObjectName("Data Range Toolbar");
1788   _rangeToolBar->addAction(_backAct);
1789   _rangeToolBar->addAction(_forwardAct);
1790   _rangeToolBar->addAction(_readFromEndAct);
1791   _rangeToolBar->addAction(_readToEndAct);
1792   _rangeToolBar->addAction(_pauseAct);
1793 
1794   _modeToolBar = addToolBar(tr("Mode"));
1795   _modeToolBar->setObjectName("Mode Toolbar");
1796   _modeToolBar->addAction(_tiedZoomAct);
1797   _modeToolBar->addAction(_highlightPointAct);
1798   _modeToolBar->addSeparator();
1799   _modeToolBar->addAction(_standardZoomAct);
1800   _modeToolBar->addAction(_xOnlyZoomAct);
1801   _modeToolBar->addAction(_yOnlyZoomAct);
1802   _modeToolBar->addAction(_layoutModeAct);
1803 
1804   _plotLayoutToolBar = addToolBar(tr("Plot Layout"));
1805   _plotLayoutToolBar->setObjectName("Plot Layout Toolbar");
1806   _plotLayoutToolBar->addAction(_createSharedAxisBoxAct);
1807   _plotLayoutToolBar->addAction(_insertPlotAct);
1808   //_plotLayoutToolBar->addAction(_createPlotAct);
1809 
1810   _annotationToolBar = addToolBar(tr("Advanced Layout"));
1811   _annotationToolBar->setObjectName("Advanced Layout Toolbar");
1812   _annotationToolBar->addAction(_createLabelAct);
1813   _annotationToolBar->addAction(_createBoxAct);
1814   _annotationToolBar->addAction(_createCircleAct);
1815   _annotationToolBar->addAction(_createEllipseAct);
1816   _annotationToolBar->addAction(_createLineAct);
1817   _annotationToolBar->addAction(_createArrowAct);
1818   _annotationToolBar->addAction(_createPictureAct);
1819 #ifndef KST_NO_SVG
1820   _annotationToolBar->addAction(_createSvgAct);
1821 #endif
1822 }
1823 
1824 
createStatusBar()1825 void MainWindow::createStatusBar() {
1826   _messageLabel = new QLabel(statusBar());
1827   setStatusMessage(tr("Ready"), 3000);
1828 
1829   _progressBar = new QProgressBar(statusBar());
1830   _progressBar->setFixedWidth(200);
1831   _progressBar->hide();
1832   statusBar()->addPermanentWidget(_progressBar);
1833   MemoryWidget *mw = new MemoryWidget(statusBar());
1834   statusBar()->addPermanentWidget(mw);
1835   DebugNotifier *dn = new DebugNotifier(statusBar());
1836   connect(dn, SIGNAL(showDebugLog()), this, SLOT(showDebugDialog()));
1837   connect(_debugDialog, SIGNAL(notifyOfError()), dn, SLOT(reanimate()));
1838   connect(_debugDialog, SIGNAL(notifyAllClear()), dn, SLOT(close()));
1839   statusBar()->addPermanentWidget(dn);
1840 }
1841 
1842 /** set the status bar message.  If you are doing this inside a view
1843  * object paint() call, then set delayed to true, and call ::updateStatusMessage()
1844  * later (after leaving paint). This is currently done for you in updateViewItems */
setStatusMessage(QString message,int timeout,bool delayed)1845 void MainWindow::setStatusMessage(QString message, int timeout, bool delayed) {
1846   _statusBarMessage = message;
1847   _statusBarTimeout = timeout;
1848   if (!delayed) {
1849     statusBar()->showMessage(message, timeout);
1850   }
1851 }
1852 
videoTutorial(int i)1853 void MainWindow::videoTutorial(int i) {
1854   switch (i) {
1855   case 1:
1856     QDesktopServices::openUrl(QUrl("http://www.youtube.com/watch?v=d1uz5g_cWh4")); break;
1857   case 2:
1858     QDesktopServices::openUrl(QUrl("http://www.youtube.com/watch?v=6z2bGNrgwL0")); break;
1859   case 3:
1860     QDesktopServices::openUrl(QUrl("http://www.youtube.com/watch?v=dstOQpmfY1U")); break;
1861   case 4:
1862     QDesktopServices::openUrl(QUrl("http://www.youtube.com/watch?v=YJ54X0nKnmk")); break;
1863   case 5:
1864     QDesktopServices::openUrl(QUrl("http://www.youtube.com/watch?v=3YZVC-GiS_4")); break;
1865   case 6:
1866     QDesktopServices::openUrl(QUrl("http://www.youtube.com/watch?v=rI7nYHlz6rs")); break;
1867   case 7:
1868     QDesktopServices::openUrl(QUrl("http://www.youtube.com/watch?v=mgP24MryyKw")); break;
1869   default:
1870     break;
1871   }
1872 }
1873 
statusMessage()1874 QString MainWindow::statusMessage() {
1875   return statusBar()->currentMessage();
1876 }
1877 
updateStatusMessage()1878 void MainWindow::updateStatusMessage() {
1879   statusBar()->showMessage(_statusBarMessage, _statusBarTimeout);
1880 }
1881 
progressBar() const1882 QProgressBar *MainWindow::progressBar() const {
1883   return _progressBar;
1884 }
1885 
updateProgress(int percent,const QString & message)1886 void MainWindow::updateProgress(int percent, const QString& message)
1887 {
1888   if (percent == -1) {
1889     _progressBar->setMaximum(0);
1890     _progressBar->setMinimum(0);
1891     _progressBar->show();
1892     return;
1893   }
1894 
1895   if (percent  > 0 && percent < 100) {
1896     _progressBar->setMaximum(100);
1897     _progressBar->setValue(percent);
1898     _progressBar->show();
1899   } else {
1900     _progressBar->hide();
1901   }
1902   setStatusMessage(message);
1903 }
1904 
readFromEnd()1905 void MainWindow::readFromEnd() {
1906   int nf = 0;
1907   int skip;
1908   bool do_skip;
1909   bool do_filter;
1910 
1911   DataVectorList dataVectors = document()->objectStore()->getObjects<DataVector>();
1912 
1913   foreach (DataVectorPtr v, dataVectors) {
1914     v->readLock();
1915     nf = v->reqNumFrames();
1916     if (nf <=0 ) {
1917       nf = v->numFrames();
1918     }
1919     skip = v->skip();
1920     do_skip = v->doSkip();
1921     do_filter = v->doAve();
1922     v->unlock();
1923 
1924     v->writeLock();
1925     v->changeFrames(-1, nf, skip, do_skip, do_filter);
1926     v->registerChange();
1927     v->unlock();
1928   }
1929 
1930   VScalarList vScalars = document()->objectStore()->getObjects<VScalar>();
1931   foreach (VScalarPtr s, vScalars) {
1932     s->readLock();
1933     s->changeFrame(-1);
1934     s->registerChange();
1935     s->unlock();
1936   }
1937 
1938   DataStringList dataStrings = document()->objectStore()->getObjects<DataString>();
1939   foreach (DataStringPtr s, dataStrings) {
1940     if (s->isStream()) {
1941       s->readLock();
1942       s->setFrame(-1);
1943       s->registerChange();
1944       s->unlock();
1945     }
1946   }
1947 
1948   DataMatrixList dataMatrices = document()->objectStore()->getObjects<DataMatrix>();
1949   foreach (DataMatrixPtr m, dataMatrices) {
1950     m->readLock();
1951     m->setFrame(-1);
1952     m->registerChange();
1953     m->unlock();
1954   }
1955 
1956   UpdateManager::self()->doUpdates(true);
1957   dialogDefaults().setValue("vector/range", nf);
1958   dialogDefaults().setValue("vector/countFromEnd", true);
1959   dialogDefaults().setValue("vector/readToEnd", false);
1960 }
1961 
readToEnd()1962 void MainWindow::readToEnd() {
1963   int f0 = 0;
1964   int skip;
1965   bool do_skip;
1966   bool do_filter;
1967 
1968   DataVectorList dataVectors = document()->objectStore()->getObjects<DataVector>();
1969 
1970   foreach (DataVectorPtr v, dataVectors) {
1971     v->readLock();
1972     f0 = v->startFrame();
1973     skip = v->skip();
1974     do_skip = v->doSkip();
1975     do_filter = v->doAve();
1976     v->unlock();
1977 
1978     v->writeLock();
1979     v->changeFrames(f0, -1, skip, do_skip, do_filter);
1980     v->registerChange();
1981     v->unlock();
1982   }
1983 
1984   VScalarList vScalars = document()->objectStore()->getObjects<VScalar>();
1985   foreach (VScalarPtr s, vScalars) {
1986     s->readLock();
1987     s->changeFrame(-1);
1988     s->registerChange();
1989     s->unlock();
1990   }
1991 
1992   DataStringList dataStrings = document()->objectStore()->getObjects<DataString>();
1993   foreach (DataStringPtr s, dataStrings) {
1994     if (s->isStream()) {
1995       s->readLock();
1996       s->setFrame(-1);
1997       s->registerChange();
1998       s->unlock();
1999     }
2000   }
2001 
2002   DataMatrixList dataMatrices = document()->objectStore()->getObjects<DataMatrix>();
2003   foreach (DataMatrixPtr m, dataMatrices) {
2004     m->readLock();
2005     m->setFrame(-1);
2006     m->registerChange();
2007     m->unlock();
2008   }
2009 
2010   dialogDefaults().setValue("vector/start", f0);
2011   dialogDefaults().setValue("vector/countFromEnd", false);
2012   dialogDefaults().setValue("vector/readToEnd", true);
2013   UpdateManager::self()->doUpdates(true);
2014 }
2015 
pause(bool pause)2016 void MainWindow::pause(bool pause) {
2017   UpdateManager::self()->setPaused(pause);
2018 
2019   //if (!pause) {
2020      //foreach (DataSourcePtr s, document()->objectStore()->dataSourceList()) {
2021        //s->checkUpdate();
2022      //}
2023   //}
2024 }
2025 
forward(double scale)2026 void MainWindow::forward(double scale) {
2027   int f0 = 0;
2028   int nf = 0;
2029   int lastF = -1;
2030   int skip;
2031   int filelength;
2032   bool count_from_end;
2033   bool read_to_end;
2034   bool do_skip;
2035   bool do_filter;
2036 
2037   DataVectorList dataVectors = document()->objectStore()->getObjects<DataVector>();
2038   DataMatrixList dataMatrices = document()->objectStore()->getObjects<DataMatrix>();
2039   VScalarList vScalars = document()->objectStore()->getObjects<VScalar>();
2040   DataStringList dataStrings = document()->objectStore()->getObjects<DataString>();
2041   QHash<int,int> lastframehash;
2042 
2043   foreach (DataVectorPtr v, dataVectors) {
2044     v->readLock();
2045     f0 = v->startFrame();
2046     nf = v->numFrames();
2047     count_from_end = v->countFromEOF();
2048     read_to_end = v->readToEOF();
2049     filelength = v->fileLength();
2050 
2051     skip = v->skip();
2052     do_skip = v->doSkip();
2053     do_filter = v->doAve();
2054     v->unlock();
2055 
2056     if ((!count_from_end) && (!read_to_end)) {
2057       f0 += ceil(scale*nf);
2058       if (f0+nf>=filelength) {
2059         f0 = filelength - nf;
2060       }
2061       lastF = f0 + nf - 1;
2062       ++lastframehash[lastF];
2063 
2064       v->writeLock();
2065       v->changeFrames(f0, nf, skip, do_skip, do_filter);
2066       v->registerChange();
2067       v->unlock();
2068     }
2069   }
2070 
2071   int most_popular_lastF = -1;
2072   int n_most_popular_lastF = -1;
2073   foreach (int key, lastframehash.keys()) {
2074     int n = lastframehash[key] ;
2075     if (n > n_most_popular_lastF) {
2076       n_most_popular_lastF = n;
2077       most_popular_lastF = key;
2078     }
2079   }
2080 
2081   foreach (VScalarPtr vs, vScalars) {
2082     int  new_frame;
2083     int filelength = vs->fileLength();
2084     if (most_popular_lastF>=0) {
2085       if (most_popular_lastF < filelength) {
2086         new_frame = most_popular_lastF;
2087       } else {
2088         new_frame = filelength-1;
2089       }
2090     } else {
2091       if (vs->F0() < 0) {
2092         new_frame = -1;
2093       } else if (vs->F0()+1 <= filelength) {
2094         new_frame = vs->F0()+1;
2095       } else {
2096         new_frame = filelength-1;
2097       }
2098     }
2099     vs->writeLock();
2100     vs->changeFrame(new_frame);
2101     vs->registerChange();
2102     vs->unlock();
2103   }
2104 
2105   foreach (DataStringPtr s, dataStrings) {
2106     if (s->isStream()) {
2107       int  new_frame;
2108       int filelength = s->fileLength();
2109       if (most_popular_lastF>=0) {
2110         if (most_popular_lastF < filelength) {
2111           new_frame = most_popular_lastF;
2112         } else {
2113           new_frame = filelength-1;
2114         }
2115       } else {
2116         if (s->frame() < 0) {
2117           new_frame = -1;
2118         } else if (s->frame()+1 < filelength) {
2119           new_frame = s->frame()+1;
2120         } else {
2121           new_frame = filelength-1;
2122         }
2123       }
2124       s->writeLock();
2125       s->setFrame(new_frame);
2126       s->registerChange();
2127       s->unlock();
2128     }
2129   }
2130 
2131 
2132   foreach (DataMatrixPtr m, dataMatrices) {
2133     if (m->isStream()) {
2134       int  new_frame;
2135       int filelength = m->fileLength();
2136       if (most_popular_lastF>=0) {
2137         if (most_popular_lastF < filelength) {
2138           new_frame = most_popular_lastF;
2139         } else {
2140           new_frame = filelength-1;
2141         }
2142       } else {
2143         if (m->frame() < 0) {
2144           new_frame = -1;
2145         } else if (m->frame()+1 < filelength) {
2146           new_frame = m->frame()+1;
2147         } else {
2148           new_frame = filelength-1;
2149         }
2150       }
2151       m->writeLock();
2152       m->setFrame(new_frame);
2153       m->registerChange();
2154       m->unlock();
2155     }
2156   }
2157 
2158   dialogDefaults().setValue("vector/range", nf);
2159   dialogDefaults().setValue("vector/start", f0);
2160   dialogDefaults().setValue("vector/countFromEnd", false);
2161   dialogDefaults().setValue("vector/readToEnd", false);
2162 
2163   UpdateManager::self()->doUpdates(true);
2164 }
2165 
back(double scale)2166 void MainWindow::back(double scale) {
2167   int f0 = 0;
2168   int nf = 0;
2169   int skip;
2170   int filelength;
2171   bool count_from_end;
2172   bool read_to_end;
2173   bool do_skip;
2174   bool do_filter;
2175   int lastF = -1;
2176 
2177   DataVectorList dataVectors = document()->objectStore()->getObjects<DataVector>();
2178   DataMatrixList dataMatrices = document()->objectStore()->getObjects<DataMatrix>();
2179   VScalarList vScalars = document()->objectStore()->getObjects<VScalar>();
2180   DataStringList dataStrings = document()->objectStore()->getObjects<DataString>();
2181 
2182   QHash<int,int> lastframehash;
2183 
2184   foreach (DataVectorPtr v, dataVectors) {
2185     v->readLock();
2186     f0 = v->startFrame();
2187     nf = v->numFrames();
2188     count_from_end = v->countFromEOF();
2189     read_to_end = v->readToEOF();
2190     filelength = v->fileLength();
2191 
2192     skip = v->skip();
2193     do_skip = v->doSkip();
2194     do_filter = v->doAve();
2195     v->unlock();
2196 
2197     if (f0 != 0) {
2198       if (count_from_end) {
2199         f0 = filelength - nf;
2200       }
2201       if (read_to_end) {
2202         nf = filelength - f0;
2203       }
2204 
2205       f0 -= ceil(scale*nf);
2206       if (f0<0) {
2207         f0 = 0;
2208       }
2209       lastF = f0 + nf - 1;
2210       ++lastframehash[lastF];
2211 
2212       v->writeLock();
2213       v->changeFrames(f0, nf, skip, do_skip, do_filter);
2214       v->registerChange();
2215       v->unlock();
2216     }
2217   }
2218 
2219   int most_popular_lastF = -1;
2220   int n_most_popular_lastF = -1;
2221   foreach (int key, lastframehash.keys()) {
2222     int n = lastframehash[key] ;
2223     if (n > n_most_popular_lastF) {
2224       n_most_popular_lastF = n;
2225       most_popular_lastF = key;
2226     }
2227   }
2228 
2229   foreach (VScalarPtr vs, vScalars) {
2230     int  new_frame;
2231     int filelength = vs->fileLength();
2232     if (most_popular_lastF>=0) {
2233       if (most_popular_lastF < filelength) {
2234         new_frame = most_popular_lastF;
2235       } else {
2236         new_frame = filelength-1;
2237       }
2238     } else {
2239       if (vs->F0() < 0) {
2240         new_frame = filelength-1;
2241       } else if (vs->F0()-1 >= 0) {
2242         new_frame = vs->F0()-1;
2243       } else {
2244         new_frame = 0;
2245       }
2246     }
2247     vs->writeLock();
2248     vs->changeFrame(new_frame);
2249     vs->registerChange();
2250     vs->unlock();
2251   }
2252 
2253   foreach (DataStringPtr s, dataStrings) {
2254     if (s->isStream()) {
2255       int  new_frame;
2256       int filelength = s->fileLength();
2257       if (most_popular_lastF>=0) {
2258         if (most_popular_lastF < filelength) {
2259           new_frame = most_popular_lastF;
2260         } else {
2261           new_frame = filelength-1;
2262         }
2263       } else {
2264         if (s->frame() < 0) {
2265           new_frame = filelength-1;
2266         } else if (s->frame()-1 >= 0) {
2267           new_frame = s->frame()-1;
2268         } else {
2269           new_frame = 0;
2270         }
2271       }
2272       s->writeLock();
2273       s->setFrame(new_frame);
2274       s->registerChange();
2275       s->unlock();
2276     }
2277   }
2278 
2279   foreach (DataMatrixPtr m, dataMatrices) {
2280     if (m->isStream()) {
2281       int  new_frame;
2282       int filelength = m->fileLength();
2283       if (most_popular_lastF>=0) {
2284         if (most_popular_lastF < filelength) {
2285           new_frame = most_popular_lastF;
2286         } else {
2287           new_frame = filelength-1;
2288         }
2289       } else {
2290         if (m->frame() < 0) {
2291           new_frame = filelength-1;
2292         } else if (m->frame()-1 >= 0) {
2293           new_frame = m->frame()-1;
2294         } else {
2295           new_frame = filelength-2;
2296         }
2297       }
2298       m->writeLock();
2299       m->setFrame(new_frame);
2300       m->registerChange();
2301       m->unlock();
2302     }
2303   }
2304 
2305   dialogDefaults().setValue("vector/range", nf);
2306   dialogDefaults().setValue("vector/start", f0);
2307   dialogDefaults().setValue("vector/countFromEnd", false);
2308   dialogDefaults().setValue("vector/readToEnd", false);
2309   UpdateManager::self()->doUpdates(true);
2310 }
2311 
reload()2312 void MainWindow::reload() {
2313   document()->objectStore()->rebuildDataSourceList();
2314   UpdateManager::self()->doUpdates(true);
2315   //document()->setChanged(true);
2316 }
2317 
showDataManager()2318 void MainWindow::showDataManager() {
2319   if (!_dataManager) {
2320     _dataManager = new DataManager(this, _doc);
2321   }
2322   if (_dataManager->isVisible()) {
2323     _dataManager->raise();
2324     _dataManager->activateWindow();
2325   }
2326   _dataManager->show();
2327 }
2328 
2329 
updateViewItems(qint64 serial)2330 void Kst::MainWindow::updateViewItems(qint64 serial)
2331 {
2332 
2333   QList<PlotItem *> plots = ViewItem::getItems<PlotItem>();
2334 
2335   bool changed = false;
2336   foreach (PlotItem *plot, plots) {
2337     changed |= plot->handleChangedInputs(serial);
2338   }
2339 
2340   QList<LabelItem*> labels = ViewItem::getItems<LabelItem>();
2341   foreach (LabelItem * label, labels) {
2342     if (label->_labelRc) {
2343       label->inputsChanged(serial);
2344     }
2345   }
2346 
2347 
2348   if (changed) {
2349     _tabWidget->currentView()->update();
2350     if (_viewVectorDialog) {
2351       _viewVectorDialog->update();
2352     }
2353     kstApp->mainWindow()->updateStatusMessage();
2354   }
2355 
2356   QTimer::singleShot(20, UpdateManager::self(), SLOT(viewItemUpdateFinished())); // why 20ms ???
2357 }
2358 
showVectorEditor()2359 void MainWindow::showVectorEditor() {
2360     if (!_viewVectorDialog) {
2361       _viewVectorDialog = new ViewVectorDialog(this, _doc);
2362     }
2363     if (_viewVectorDialog->isVisible()) {
2364       _viewVectorDialog->raise();
2365       _viewVectorDialog->activateWindow();
2366     }
2367     _viewVectorDialog->show();
2368 }
2369 
2370 
showScalarEditor()2371 void MainWindow::showScalarEditor() {
2372   ViewPrimitiveDialog *viewScalarDialog = new ViewScalarDialog(this, _doc);
2373   viewScalarDialog->show();
2374 }
2375 
2376 
showStringEditor()2377 void MainWindow::showStringEditor() {
2378   ViewPrimitiveDialog *viewStringDialog = new ViewStringDialog(this, _doc);
2379   viewStringDialog->show();
2380 }
2381 
showMatrixEditor()2382 void MainWindow::showMatrixEditor() {
2383   ViewMatrixDialog *viewMatrixDialog = new ViewMatrixDialog(this, _doc);
2384   viewMatrixDialog->show();
2385 }
2386 
2387 
showDebugDialog()2388 void MainWindow::showDebugDialog() {
2389   if (!_debugDialog) {
2390     _debugDialog = new DebugDialog(this);
2391   }
2392   _debugDialog->setObjectStore(document()->objectStore());
2393   if (_debugDialog->isVisible()) {
2394     _debugDialog->raise();
2395     _debugDialog->activateWindow();
2396   }
2397   _debugDialog->show();
2398 }
2399 
2400 
showExportGraphicsDialog()2401 void MainWindow::showExportGraphicsDialog() {
2402   if (!_exportGraphics) {
2403     _exportGraphics = new ExportGraphicsDialog(this);
2404     connect(_exportGraphics, SIGNAL(exportGraphics(QString,QString,int,int,int,bool,int)),
2405             this, SLOT(exportGraphicsFile(QString,QString,int,int,int,bool,int)));
2406   }
2407   if (_exportGraphics->isVisible()) {
2408     _exportGraphics->raise();
2409     _exportGraphics->activateWindow();
2410   }
2411   _exportGraphics->show();
2412 }
2413 
2414 
showExportVectorsDialog()2415 void MainWindow::showExportVectorsDialog() {
2416   if (!_exportVectors) {
2417     _exportVectors = new ExportVectorsDialog(this);
2418   }
2419   if (_exportVectors->isVisible()) {
2420     _exportVectors->raise();
2421     _exportVectors->activateWindow();
2422   }
2423   _exportVectors->show();
2424 }
2425 
2426 
showLogDialog()2427 void MainWindow::showLogDialog() {
2428   if (!_logDialog) {
2429     _logDialog = new LogDialog(this);
2430     //connect(_logDialog, SIGNAL(exportLog(const QString &, time_t, const QString &, int, int, int, const QString &)),
2431     //        this, SLOT(exportLog(const QString &, time_t, const QString &, int, int, int, const QString &)));
2432   }
2433   if (_logDialog->isVisible()) {
2434     _logDialog->raise();
2435     _logDialog->activateWindow();
2436   }
2437   _logDialog->show();
2438 }
2439 
2440 
showSettingsDialog()2441 void MainWindow::showSettingsDialog() {
2442   if (!_applicationSettingsDialog) {
2443     _applicationSettingsDialog = new ApplicationSettingsDialog(this);
2444   }
2445   if (_applicationSettingsDialog->isVisible()) {
2446     _applicationSettingsDialog->raise();
2447     _applicationSettingsDialog->activateWindow();
2448   }
2449   _applicationSettingsDialog->show();
2450 }
2451 
2452 
showThemeDialog()2453 void MainWindow::showThemeDialog() {
2454   if (!_themeDialog) {
2455     _themeDialog = new ThemeDialog(this);
2456   }
2457   if (_themeDialog->isVisible()) {
2458     _themeDialog->raise();
2459     _themeDialog->activateWindow();
2460   }
2461 
2462   _themeDialog->reset();
2463   _themeDialog->show();
2464 }
2465 
2466 
clearDefaults()2467 void MainWindow::clearDefaults() {
2468 
2469   QMessageBox confirmationBox;
2470   confirmationBox.setText(tr("Clear all settings and defaults?"));
2471   confirmationBox.setInformativeText(tr("You are about to clear all settings defaults in all dialogs in kst.\nThis can not be undone."));
2472   confirmationBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
2473   confirmationBox.setDefaultButton(QMessageBox::Ok);
2474   int confirmed = confirmationBox.exec();
2475 
2476   switch (confirmed) {
2477   case QMessageBox::Ok:
2478     dialogDefaults().clear();
2479     ApplicationSettings::self()->clear();
2480     DataSourcePluginManager::settingsObject().clear();
2481     break;
2482   case QMessageBox::Cancel:
2483   default:
2484     // cancel: do nothing at all.
2485     break;
2486   }
2487 }
2488 
clearDataSourceSettings()2489 void MainWindow::clearDataSourceSettings() {
2490 
2491   QMessageBox confirmationBox;
2492   confirmationBox.setText(tr("Clear datasource settings?"));
2493   confirmationBox.setInformativeText(tr("You are about to clear all\nconfiguration settings for\nall datasources/file types."));
2494   confirmationBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
2495   confirmationBox.setDefaultButton(QMessageBox::Ok);
2496   int confirmed = confirmationBox.exec();
2497 
2498   switch (confirmed) {
2499   case QMessageBox::Ok:
2500     DataSourcePluginManager::settingsObject().clear();
2501     break;
2502   case QMessageBox::Cancel:
2503   default:
2504     // cancel: do nothing at all.
2505     break;
2506   }
2507 
2508 }
2509 
2510 
showDifferentiateCurvesDialog()2511 void MainWindow::showDifferentiateCurvesDialog() {
2512   if (!_differentiateCurvesDialog) {
2513     _differentiateCurvesDialog = new DifferentiateCurvesDialog(this);
2514   }
2515   if (_differentiateCurvesDialog->isVisible()) {
2516     _differentiateCurvesDialog->raise();
2517     _differentiateCurvesDialog->activateWindow();
2518   }
2519   _differentiateCurvesDialog->show();
2520 }
2521 
2522 
filterMultipleDialog()2523 void MainWindow::filterMultipleDialog() {
2524   if (!_filterMultipleDialog) {
2525     _filterMultipleDialog = new FilterMultipleDialog(this);
2526   }
2527   if (_filterMultipleDialog->isVisible()) {
2528     _filterMultipleDialog->raise();
2529     _filterMultipleDialog->activateWindow();
2530   }
2531   _filterMultipleDialog->show();
2532 }
2533 
2534 
2535 
showChooseColorDialog()2536 void MainWindow::showChooseColorDialog() {
2537   if (!_chooseColorDialog) {
2538     _chooseColorDialog = new ChooseColorDialog(this);
2539   }
2540   if (_chooseColorDialog->isVisible()) {
2541     _chooseColorDialog->raise();
2542     _chooseColorDialog->activateWindow();
2543   }
2544   _chooseColorDialog->show();
2545 }
2546 
2547 
showChangeDataSampleDialog()2548 void MainWindow::showChangeDataSampleDialog() {
2549   if (!_changeDataSampleDialog) {
2550     _changeDataSampleDialog = new ChangeDataSampleDialog(this);
2551   }
2552   if (_changeDataSampleDialog->isVisible()) {
2553     _changeDataSampleDialog->raise();
2554     _changeDataSampleDialog->activateWindow();
2555   }
2556   _changeDataSampleDialog->show();
2557 }
2558 
2559 
showDataWizard()2560 void MainWindow::showDataWizard() {
2561   DataWizard *dataWizard = new DataWizard(this);
2562   connect(dataWizard, SIGNAL(dataSourceLoaded(QString)), this, SLOT(updateRecentDataFiles(QString)));
2563   dataWizard->show();
2564 }
2565 
showDataWizard(const QString & dataFile)2566 void MainWindow::showDataWizard(const QString &dataFile) {
2567   DataWizard *dataWizard = new DataWizard(this, dataFile);
2568   dataWizard->show();
2569 }
2570 
2571 
openRecentDataFile()2572 void MainWindow::openRecentDataFile()
2573 {
2574   QAction *action = qobject_cast<QAction *>(sender());
2575   if (action) {
2576     DataWizard *dataWizard = new DataWizard(this, action->data().toString());
2577     connect(dataWizard, SIGNAL(dataSourceLoaded(QString)), this, SLOT(updateRecentDataFiles(QString)));
2578     dataWizard->show();
2579   }
2580 }
2581 
2582 
showBugReportWizard()2583 void MainWindow::showBugReportWizard() {
2584   if (!_bugReportWizard) {
2585     _bugReportWizard = new BugReportWizard(this);
2586   }
2587   if (_bugReportWizard->isVisible()) {
2588     _bugReportWizard->raise();
2589     _bugReportWizard->activateWindow();
2590   }
2591   _bugReportWizard->show();
2592 }
2593 
showChangeFileDialog()2594 void MainWindow::showChangeFileDialog() {
2595   if (!_changeFileDialog) {
2596     _changeFileDialog = new ChangeFileDialog(this);
2597   }
2598   if (_changeFileDialog->isVisible()) {
2599     _changeFileDialog->raise();
2600     _changeFileDialog->activateWindow();
2601   }
2602   _changeFileDialog->show();
2603 }
2604 
showPluginDialog(QString & pluginName)2605 void MainWindow::showPluginDialog(QString &pluginName) {
2606   DialogLauncher::self()->showBasicPluginDialog(pluginName);
2607 }
2608 
isTiedTabs()2609 bool MainWindow::isTiedTabs() {
2610   return _tabTiedAct->isChecked();
2611 }
2612 
readSettings()2613 void MainWindow::readSettings() {
2614 #if defined(__QNX__) || defined(__ANDROID__)
2615   // There is only one size we want on mobile platforms - full screen!
2616   setWindowState(Qt::WindowFullScreen);
2617 #else
2618   QByteArray geo = _settings.value("geometry").toByteArray();
2619   if (!geo.isEmpty()) {
2620       restoreGeometry(geo);
2621   } else {
2622       setGeometry(50, 50, 800, 600);
2623   }
2624 #endif // defined(__QNX__) || defined(__ANDROID__)
2625 
2626   restoreState(_settings.value("toolbarState").toByteArray());
2627   _tabTiedAct->setChecked(_settings.value("tieTabs").toBool());
2628 }
2629 
2630 
writeSettings()2631 void MainWindow::writeSettings() {
2632   _settings.setValue("geometry", saveGeometry());
2633   _settings.setValue("toolbarState", saveState());
2634   _settings.setValue("tieTabs", _tabTiedAct->isChecked());
2635 }
2636 
setWidgetFlags(QWidget * widget)2637 void MainWindow::setWidgetFlags(QWidget* widget)
2638 {
2639   if (widget) {
2640     // Make sure the dialog gets maximize and minimize buttons under Windows
2641     widget->QWidget::setWindowFlags((Qt::WindowFlags) Qt::Dialog |     Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint
2642 #if QT_VERSION >= 0x040500
2643         | Qt::WindowCloseButtonHint
2644 #endif
2645 );
2646   }
2647 }
2648 
dragEnterEvent(QDragEnterEvent * event)2649 void MainWindow::dragEnterEvent(QDragEnterEvent *event)
2650 {
2651      if (event->mimeData()->hasUrls()) {
2652        event->acceptProposedAction();
2653      }
2654 }
2655 
2656 
dropEvent(QDropEvent * event)2657 void MainWindow::dropEvent(QDropEvent *event)
2658 {
2659   QString path = event->mimeData()->urls().first().toLocalFile();
2660   if (path.endsWith(QString(".kst"))) {
2661      if (!promptSaveDone()) { // There are things to save => cancel
2662        event->ignore();
2663        return;
2664      }
2665      openFile(path);
2666    }
2667    else {
2668      showDataWizard(path); // This is not destructive: it only add data, no need to ask for confirmation
2669    }
2670    event->accept();
2671 }
2672 
cleanUpDataSourceList()2673 void MainWindow::cleanUpDataSourceList() {
2674   _doc->objectStore()->cleanUpDataSourceList();
2675 }
2676 
2677 #if defined(__QNX__)
eventFilter(QObject * obj,QEvent * event)2678 bool MainWindow::eventFilter(QObject *obj, QEvent *event) {
2679   if (!qApp->activeWindow()) {
2680     activateWindow();
2681   }
2682   if (event->type() == QEvent::KeyPress) {
2683     QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
2684     if (keyEvent->key()==Qt::Key_Menu) { // i.e., bezel swipe gesture...
2685       qnxToggleToolbarVisibility();
2686     }
2687     return false;
2688   } else if (event->type() == QEvent::MouseButtonPress && obj != menuBar()) {
2689     if (_qnxToolbarsVisible) qnxToggleToolbarVisibility();
2690     update();
2691     return false;
2692   } else if (event->type() == QEvent::WindowActivate) {
2693     update();
2694     return false;
2695   } else {
2696     return QObject::eventFilter(obj, event);
2697   }
2698 }
2699 
keyPressEvent(QKeyEvent * event)2700 void MainWindow::keyPressEvent(QKeyEvent *event) {
2701   if ((event->type() == QEvent::KeyPress && static_cast<QKeyEvent*>(event)->key() == Qt::Key_Menu)) {
2702     qnxToggleToolbarVisibility();
2703   }
2704 }
2705 
qnxToggleToolbarVisibility()2706 void MainWindow::qnxToggleToolbarVisibility() {
2707   if (_qnxLastToolbarEvent.msecsTo(QDateTime::currentDateTime()) < 100) {
2708     return; // HACK
2709   }
2710   _qnxLastToolbarEvent = QDateTime::currentDateTime();
2711   menuBar()->setVisible(!_qnxToolbarsVisible);
2712   statusBar()->setVisible(!_qnxToolbarsVisible);
2713   _fileToolBar->setVisible(!_qnxToolbarsVisible);
2714   _editToolBar->setVisible(!_qnxToolbarsVisible);
2715   _toolsToolBar->setVisible(!_qnxToolbarsVisible);
2716   _rangeToolBar->setVisible(!_qnxToolbarsVisible);
2717   _modeToolBar->setVisible(!_qnxToolbarsVisible);
2718   _plotLayoutToolBar->setVisible(!_qnxToolbarsVisible);
2719   _annotationToolBar->setVisible(!_qnxToolbarsVisible);
2720   _qnxToolbarsVisible = !_qnxToolbarsVisible;
2721 }
2722 #endif
2723 
2724 }
2725 
2726 // vim: ts=2 sw=2 et
2727