File indexing completed on 2025-07-13 04:09:36

0001 /***************************************************************************
0002  *                                                                         *
0003  *   copyright : (C) 2007 The University of Toronto                        *
0004  *                   netterfield@astro.utoronto.ca                         *
0005  *                                                                         *
0006  *   This program is free software; you can redistribute it and/or modify  *
0007  *   it under the terms of the GNU General Public License as published by  *
0008  *   the Free Software Foundation; either version 2 of the License, or     *
0009  *   (at your option) any later version.                                   *
0010  *                                                                         *
0011  ***************************************************************************/
0012 
0013 #include "mainwindow.h"
0014 #include "boxitem.h"
0015 #include "datamanager.h"
0016 #include "debugdialog.h"
0017 #include "debugnotifier.h"
0018 #include "document.h"
0019 #include "ellipseitem.h"
0020 #include "exportgraphicsdialog.h"
0021 #include "exportvectorsdialog.h"
0022 #include "logdialog.h"
0023 #include "application.h"
0024 #include "debug.h"
0025 #include "labelitem.h"
0026 #include "lineitem.h"
0027 #include "circleitem.h"
0028 #include "arrowitem.h"
0029 #include "memorywidget.h"
0030 #include "objectstore.h"
0031 #include "pictureitem.h"
0032 #include "plotitem.h"
0033 #include "plotitemmanager.h"
0034 #include "svgitem.h"
0035 #include "tabwidget.h"
0036 #include "sharedaxisboxitem.h"
0037 #include "ui_aboutdialog.h"
0038 #include "viewvectordialog.h"
0039 #include "viewmatrixdialog.h"
0040 #include "viewprimitivedialog.h"
0041 #include "view.h"
0042 #include "applicationsettings.h"
0043 #include "updatemanager.h"
0044 #include "datasourcepluginmanager.h"
0045 #include "pluginmenuitemaction.h"
0046 
0047 #include "applicationsettingsdialog.h"
0048 #include "themedialog.h"
0049 #include "differentiatecurvesdialog.h"
0050 #include "filtermultipledialog.h"
0051 #include "choosecolordialog.h"
0052 #include "changedatasampledialog.h"
0053 #include "changefiledialog.h"
0054 #include "bugreportwizard.h"
0055 #include "datawizard.h"
0056 #include "aboutdialog.h"
0057 #include "shortcutdialog.h"
0058 #include "datavector.h"
0059 #include "commandlineparser.h"
0060 #include "dialogdefaults.h"
0061 #include "colorsequence.h"
0062 #include "settings.h"
0063 
0064 #include "dialoglauncher.h"
0065 #include "scriptserver.h"
0066 
0067 #include "geticon.h"
0068 
0069 #ifndef KST_NO_SVG
0070 #include <QSvgGenerator>
0071 #endif
0072 
0073 #include <QUndoGroup>
0074 #ifndef KST_NO_PRINTER
0075 #include <QPrintDialog>
0076 #endif
0077 #include <QMenuBar>
0078 #include <QStatusBar>
0079 #include <QProgressBar>
0080 #include <QMessageBox>
0081 #include <QImageWriter>
0082 #include <QToolBar>
0083 #include <QDebug>
0084 #include <QDesktopServices>
0085 #include <QSignalMapper>
0086 #include <QClipboard>
0087 
0088 namespace Kst {
0089 
0090 MainWindow::MainWindow() :
0091     _settings(createSettings("application")),
0092     _dataManager(0),
0093     _exportGraphics(0),
0094     _exportVectors(0),
0095     _logDialog(0),
0096     _differentiateCurvesDialog(0),
0097     _filterMultipleDialog(0),
0098     _chooseColorDialog(0),
0099     _changeDataSampleDialog(0),
0100     _changeFileDialog(0),
0101     _bugReportWizard(0),
0102     _applicationSettingsDialog(0),
0103     _themeDialog(0),
0104     _aboutDialog(0),
0105     _shortcutDialog(0),
0106     _viewVectorDialog(0),
0107     _highlightPoint(false),
0108     _statusBarTimeout(0),
0109 #if defined(__QNX__)
0110     qnxToolbarsVisible(true),
0111 #endif
0112     _ae_width(1280),
0113     _ae_height(1024),
0114     _ae_display(2),
0115     _ae_export_all(false),
0116     _ae_autosave_period(0),
0117     _ae_Timer(0),
0118     _sessionFileName(QString())
0119 {
0120   _doc = new Document(this);
0121   _scriptServer = new ScriptServer(_doc->objectStore());
0122   _videoMapper = new QSignalMapper(this);
0123 
0124   _tabWidget = new TabWidget(this);
0125   _undoGroup = new QUndoGroup(this);
0126   _debugDialog = new DebugDialog(this);
0127 
0128   Debug::self()->setHandler(_debugDialog);
0129 
0130   setKstWindowTitle();
0131 
0132   createActions();
0133   createMenus();
0134   createToolBars();
0135   createStatusBar();
0136 
0137   _tabWidget->createView();
0138 
0139   setCentralWidget(_tabWidget);
0140   _tabWidget->setAcceptDrops(false); // Force drops to be passed to parent
0141   connect(_tabWidget, SIGNAL(currentChanged(int)), this, SLOT(currentViewChanged()));
0142   connect(_tabWidget, SIGNAL(currentViewModeChanged()), this, SLOT(currentViewModeChanged()));
0143   connect(PlotItemManager::self(), SIGNAL(tiedZoomRemoved()), this, SLOT(tiedZoomRemoved()));
0144   connect(PlotItemManager::self(), SIGNAL(allPlotsTiedZoom()), this, SLOT(allPlotsTiedZoom()));
0145 
0146   readSettings();
0147   connect(UpdateManager::self(), SIGNAL(objectsUpdated(qint64)), this, SLOT(updateViewItems(qint64)));
0148 
0149   QTimer::singleShot(0, this, SLOT(performHeavyStartupActions()));
0150 
0151   updateRecentKstFiles();
0152   setAcceptDrops(true);
0153 
0154 #if defined(__QNX__)
0155   // We want to be able to intercept bezel gestures, which show up in Qt as menu button keyPressEvents.
0156   qApp->installEventFilter(this);
0157   qnxToggleToolbarVisibility();
0158 #endif
0159 
0160 }
0161 
0162 
0163 MainWindow::~MainWindow() {
0164   delete _dataManager;
0165   _dataManager = 0;
0166   delete _doc;
0167   _doc = 0;
0168   delete _viewVectorDialog;
0169   _viewVectorDialog = 0;
0170   delete _scriptServer;
0171   _scriptServer = 0;
0172 }
0173 
0174 
0175 void MainWindow::performHeavyStartupActions() {
0176   // Set the timer for the UpdateManager.
0177   UpdateManager::self()->setMinimumUpdatePeriod(ApplicationSettings::self()->minimumUpdatePeriod());
0178   DataObject::init();
0179   DataSourcePluginManager::init();
0180 }
0181 
0182 void MainWindow::cleanup() {
0183   if (document() && document()->objectStore()) {
0184     document()->objectStore()->clear();
0185   }
0186 }
0187 
0188 
0189 void MainWindow::setLayoutMode(bool layoutMode) {
0190   foreach (View *v, tabWidget()->views() ) {
0191 
0192     Q_ASSERT(v);
0193 
0194     if (layoutMode) {
0195       v->setViewMode(View::Layout);
0196       _highlightPointAct->setEnabled(false);
0197       _tiedZoomAct->setEnabled(false);
0198     } else {
0199       v->setViewMode(View::Data);
0200       _highlightPointAct->setEnabled(true);
0201       _tiedZoomAct->setEnabled(true);
0202     }
0203   }
0204 }
0205 
0206 void MainWindow::setHighlightPoint(bool highlight) {
0207   _highlightPoint = highlight;
0208 }
0209 
0210 void MainWindow::changeZoomOnlyMode(QAction* act) {
0211   if (act == _layoutModeAct && act->isChecked()) {
0212     setLayoutMode(true);
0213   } else {
0214     setLayoutMode(false);
0215   }
0216   foreach (View *view, tabWidget()->views() ) {
0217     view->setZoomOnly((View::ZoomOnlyMode)act->data().toInt());
0218   }
0219 
0220 }
0221 
0222 void MainWindow::toggleTiedZoom() {
0223   if (isTiedTabs()) {
0224     PlotItemManager::self()->toggleAllTiedZoom(0);
0225     /*
0226     QList<View*> views = tabWidget()->views();
0227     foreach (View* view, views) {
0228       PlotItemManager::self()->toggleAllTiedZoom(view);
0229     }
0230     */
0231   } else {
0232     PlotItemManager::self()->toggleAllTiedZoom(tabWidget()->currentView());
0233   }
0234 }
0235 
0236 void MainWindow::tiedZoomRemoved() {
0237   _tiedZoomAct->setChecked(false);
0238 }
0239 
0240 
0241 void MainWindow::allPlotsTiedZoom() {
0242   _tiedZoomAct->setChecked(true);
0243 }
0244 
0245 
0246 bool MainWindow::promptSaveDone() {
0247   if (! _doc->isChanged()) {
0248     return true; // No need to ask if there is no unsaved change -> we're done
0249   }
0250   else { // Changes registered: ask the user
0251     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);
0252     if (rc == QMessageBox::Save) {
0253       save();
0254     } else if (rc == QMessageBox::Cancel) {
0255       return false;
0256     }
0257     return true;
0258   }
0259 }
0260 
0261 
0262 void MainWindow::closeEvent(QCloseEvent *e) {
0263   if (!promptSaveDone()) {
0264     e->ignore();
0265     return;
0266     }
0267     //cleanup();
0268     QMainWindow::closeEvent(e);
0269     kstApp->closeAllWindows();
0270   }
0271 
0272 
0273 Document *MainWindow::document() const {
0274   return _doc;
0275 }
0276 
0277 
0278 QUndoGroup *MainWindow::undoGroup() const {
0279   return _undoGroup;
0280 }
0281 
0282 
0283 TabWidget *MainWindow::tabWidget() const {
0284   return _tabWidget;
0285 }
0286 
0287 
0288 void MainWindow::save() {
0289   if (_doc->isOpen()) {
0290     _doc->save();
0291   } else {
0292     saveAs();
0293     }
0294 }
0295 
0296 
0297 void MainWindow::saveAs() {
0298   QString fn = QFileDialog::getSaveFileName(this, tr("Kst: Save File"), _doc->fileName(), tr("Kst Sessions (*.kst)"));
0299   if (fn.isEmpty()) {
0300     return;
0301   }
0302   QString restorePath = QDir::currentPath();
0303   QString kstfiledir = fn.left(fn.lastIndexOf('/')) + '/';
0304   QDir::setCurrent(kstfiledir);
0305   //QString currentP = QDir::currentPath();
0306   _doc->save(fn);
0307   QDir::setCurrent(restorePath);
0308   _sessionFileName = fn;
0309   setKstWindowTitle();
0310   updateRecentKstFiles(fn);
0311 }
0312 
0313 void MainWindow::newDoc(bool force) {
0314   bool clearApproved = false;
0315   if (force) {
0316     clearApproved = true;
0317   } else {
0318     clearApproved = promptSaveDone();
0319   }
0320 
0321   if (clearApproved) {
0322     cleanup();
0323     delete _dataManager;
0324     _dataManager = 0;
0325     delete _doc;
0326     resetNameIndexes();
0327     _doc = new Document(this);
0328     _scriptServer->setStore(_doc->objectStore());
0329     tabWidget()->clear();
0330     tabWidget()->createView();
0331     return;
0332   } else {
0333     return;
0334   }
0335 
0336 }
0337 
0338 void MainWindow::open() {
0339   if (!promptSaveDone()) {
0340     return;
0341   }
0342   const QString key = "lastOpenedKstFile";
0343   QString fn = _settings.value(key).toString();
0344   if (fn.isEmpty()) {
0345       fn = _doc->fileName();
0346   }
0347   fn = QFileDialog::getOpenFileName(this, tr("Kst: Open File"), fn, tr("Kst Sessions (*.kst)"));
0348   if (fn.isEmpty()) {
0349     return;
0350   }
0351   _settings.setValue(key, fn);
0352   openFile(fn);
0353 }
0354 
0355 
0356 
0357 QAction* MainWindow::createRecentFileAction(const QString& filename, int idx, const QString& name, const char* openslot)
0358 {
0359   QAction* action = new QAction(this);
0360   QString text = tr("&%1 %2", "Part of a list.  %1 is an index.  %2 is a file name").arg(idx).arg(name);
0361   action->setText(text);
0362   action->setData(filename);
0363   action->setStatusTip(filename);
0364   action->setVisible(true);
0365   connect(action, SIGNAL(triggered()), this, openslot);
0366   return action;
0367 }
0368 
0369 
0370 void MainWindow::updateRecentKstFiles(const QString& filename)
0371 {
0372   updateRecentFiles("recentKstFileList", _fileMenu, _bottomRecentKstActions, _recentKstFilesMenu, filename, SLOT(openRecentKstFile()));
0373 }
0374 
0375 void MainWindow::setKstWindowTitle()
0376 {
0377   QString title = "Kst";
0378   QString server_name = _scriptServer->serverName;
0379   QString user_name = "--"+kstApp->userName();
0380 
0381   if (server_name.endsWith(user_name)) {
0382     server_name.remove(server_name.lastIndexOf(user_name),10000);
0383   }
0384 
0385   if (!_sessionFileName.isEmpty()) {
0386     title += " - " + _sessionFileName;
0387   }
0388   if (scriptServerNameSet()) {
0389     title += " -- " + server_name;
0390   }
0391   setWindowTitle(title);
0392 }
0393 
0394 QString MainWindow::scriptServerName()
0395 {
0396   return _scriptServer->serverName;
0397 }
0398 
0399 bool MainWindow::scriptServerNameSet()
0400 {
0401   return _scriptServer->serverNameSet;
0402 }
0403 
0404 void MainWindow::setScriptServerName(QString server_name)
0405 {
0406   _scriptServer->setScriptServerName(server_name);
0407   setKstWindowTitle();
0408 }
0409 
0410 void MainWindow::copyTab()
0411 {
0412   View *view = _tabWidget->currentView();
0413   QClipboard *clipboard = QApplication::clipboard();
0414   QMimeData *mimedata = new QMimeData();
0415 
0416   QPainter painter;
0417   QPixmap pixmap(view->size());
0418 
0419   painter.begin(&pixmap);
0420 
0421   view->setPrinting(true);
0422   view->render(&painter);
0423   view->setPrinting(false);
0424 
0425   painter.end();
0426 
0427   //mimedata->setText("Some text from kst, just for you!");
0428   mimedata->setImageData(pixmap.toImage());
0429 
0430   clipboard->setMimeData(mimedata);
0431 }
0432 
0433 
0434 void MainWindow::updateRecentDataFiles(const QString& filename)
0435 {
0436   updateRecentFiles("recentDataFileList", _toolsMenu, _bottomRecentDataActions, _recentDataFilesMenu, filename, SLOT(openRecentDataFile()));
0437   if (!filename.isEmpty()) {
0438     dialogDefaults().setValue("vector/datasource", filename);
0439   }
0440 }
0441 
0442 
0443 QStringList MainWindow::recentDataFiles() {
0444   QStringList recentFiles = _settings.value("recentDataFileList").toStringList();
0445   if (recentFiles.removeDuplicates() > 0) {
0446     _settings.setValue("recentDataFileList", recentFiles);
0447   }
0448   return recentFiles;
0449 }
0450 
0451 void MainWindow::cleanupRecentDataFilesList() {
0452   QStringList recentFiles = _settings.value("recentDataFileList").toStringList();
0453   recentFiles.removeDuplicates();
0454   foreach(const QString& it, recentFiles) {
0455     if (!QFileInfo(it).exists()) {
0456       recentFiles.removeOne(it);
0457     }
0458   }
0459   _settings.setValue("recentDataFileList", recentFiles);
0460   updateRecentKstFiles();
0461   updateRecentDataFiles();
0462 }
0463 
0464 
0465 void MainWindow::updateRecentFiles(const QString& key ,QMenu* menu, QList<QAction*>& actions, QMenu* submenu, const QString& newfilename, const char* openslot)
0466 {
0467   // Always add absolute paths to the recent file lists, otherwise they are not very reusable
0468   QString absoluteFilePath = DataSource::cleanPath(newfilename);
0469   if (!newfilename.isEmpty() && !QDir::isAbsolutePath(newfilename)) { // If it's not empty and not absolute either, add the dir
0470     absoluteFilePath = DataSource::cleanPath(QDir::currentPath() + '/' + newfilename);
0471   }
0472   foreach(QAction* it, actions) {
0473     menu->removeAction(it);
0474     delete it;
0475   }
0476   actions.clear();
0477   QStringList recentFiles = _settings.value(key).toStringList();
0478   if (recentFiles.removeDuplicates() > 0) {
0479     _settings.setValue(key, recentFiles);
0480   }
0481   if (!absoluteFilePath.isEmpty()) {
0482     recentFiles.removeOne(absoluteFilePath);
0483     recentFiles.push_front(absoluteFilePath);
0484     recentFiles = recentFiles.mid(0, 30);
0485     _settings.setValue(key, recentFiles);
0486   }
0487 
0488   submenu->clear();
0489   QAction* check = new QAction(this);
0490   check->setText(tr("&Cleanup Non-Existent Files"));
0491   check->setData(key);
0492   check->setVisible(true);
0493   connect(check, SIGNAL(triggered()), this, SLOT(checkRecentFilesOnExistence()));
0494   submenu->addAction(check);
0495   submenu->addSeparator();
0496   int i = 0;
0497   foreach(const QString& it, recentFiles) {
0498     i++;
0499     if (i <= 5) {
0500       // don't make file menu too wide, show complete path in statusbar
0501       QAction* action = createRecentFileAction(it, i, QFileInfo(it).fileName(), openslot);
0502       actions << action;
0503       menu->addAction(action);
0504     }
0505     submenu->addAction(createRecentFileAction(it, i, it, openslot));
0506   }
0507 }
0508 
0509 
0510 void MainWindow::openRecentKstFile()
0511 {
0512   QAction *action = qobject_cast<QAction *>(sender());
0513   if (action) {
0514     openFile(action->data().toString());
0515   }
0516 }
0517 
0518 
0519 void MainWindow::checkRecentFilesOnExistence()
0520 {
0521   QAction *action = qobject_cast<QAction *>(sender());
0522   if (action) {
0523     QStringList recentFiles = _settings.value(action->data().toString()).toStringList();
0524     recentFiles.removeDuplicates();
0525     foreach(const QString& it, recentFiles) {
0526       if (!QFileInfo(it).exists()) {
0527         recentFiles.removeOne(it);
0528       }
0529     }
0530     _settings.setValue(action->data().toString(), recentFiles);
0531     updateRecentKstFiles();
0532     updateRecentDataFiles();
0533   }
0534 }
0535 
0536 void MainWindow::autoExportImage() {
0537   exportGraphicsFile(_ae_filename, _ae_format, _ae_width, _ae_height, _ae_display, _ae_export_all, _ae_autosave_period);
0538 }
0539 
0540 
0541 
0542 bool MainWindow::initFromCommandLine() {
0543   delete _doc;
0544   _doc = new Document(this);
0545   _scriptServer->setStore(_doc->objectStore());
0546 
0547   CommandLineParser P(_doc, this);
0548 
0549   bool ok = _doc->initFromCommandLine(&P);
0550   if (!P.pngFile().isEmpty()) {
0551     int w = 1280;
0552     int h = 1024;
0553 
0554     if (P.pngWidth()>1) {
0555       w = P.pngWidth();
0556     }
0557     if (P.pngHeight()>1) {
0558       h = P.pngHeight();
0559     }
0560     exportGraphicsFile(P.pngFile(), "png", w, h, 2, true, 0);
0561     ok = false;
0562   }
0563   if (!P.printFile().isEmpty()) {
0564 #ifndef KST_NO_PRINTER
0565     printFromCommandLine(P.printFile());
0566 #endif
0567     ok = false;
0568   }
0569   if (!P.kstFileName().isEmpty()) {
0570     _sessionFileName = P.kstFileName();
0571     setKstWindowTitle();
0572   }
0573   _doc->setChanged(false);
0574   return ok;
0575 }
0576 
0577 void MainWindow::openFile(const QString &file) {
0578   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
0579   cleanup();
0580   newDoc(true); // Does all the init stuff, but does not ask for override as it's supposed to be done elsewhere
0581   bool ok = _doc->open(file);
0582   updateProgress(100, "");
0583   QApplication::restoreOverrideCursor();
0584 
0585   if (!ok) {
0586     QString lastError = _doc->lastError();
0587     if (lastError.isEmpty())
0588       lastError = tr("For details see Help->Debug Dialog->Log.");
0589     QMessageBox::critical(this, tr("Kst"),tr("Error opening document:\n  '%1'\n%2\n").arg(file, lastError));
0590   }
0591 
0592   _sessionFileName = file;
0593   setKstWindowTitle();
0594   updateRecentKstFiles(file);
0595 }
0596 
0597 
0598 void MainWindow::exportGraphicsFile(const QString &filename, const QString &format, int width, int height, int display, bool export_all, int autosave_period) {
0599   int viewCount = 0;
0600   int n_views = _tabWidget->views().size();
0601   int i_startview, i_endview;
0602 
0603   _ae_filename = filename;
0604   _ae_format = format;
0605   _ae_width = width;
0606   _ae_height = height;
0607   _ae_display = display;
0608   _ae_export_all = export_all;
0609   _ae_autosave_period = autosave_period;
0610 
0611   dialogDefaults().setValue("export/filename", filename);
0612   dialogDefaults().setValue("export/format", format);
0613   dialogDefaults().setValue("export/xsize", width);
0614   dialogDefaults().setValue("export/ysize", height);
0615   dialogDefaults().setValue("export/sizeOption", display);
0616 
0617   if (export_all) {
0618     i_startview = 0;
0619     i_endview = n_views-1;
0620   } else {
0621     i_startview = i_endview = _tabWidget->currentIndex();
0622   }
0623 
0624   for (int i_view = i_startview; i_view<=i_endview; i_view++) {
0625     View *view = _tabWidget->views().at(i_view);
0626     QSize size;
0627     if (display == 0) { // Width set by user, maintain aspect ratio
0628       QSize sizeWindow(view->geometry().size());
0629       size.setWidth(width);
0630       size.setHeight((int)((qreal)width * (qreal)sizeWindow.height() / (qreal)sizeWindow.width()));
0631     } else if (display == 1) { // Height set by user, maintain aspect ratio
0632       QSize sizeWindow(view->geometry().size());
0633       size.setHeight(height);
0634       size.setWidth((int)((qreal)height * (qreal)sizeWindow.width() / (qreal)sizeWindow.height()));
0635     } else if (display == 2) { // Width and height set by user
0636       size.setWidth(width);
0637       size.setHeight(height);
0638     } else { //if (display == 3) { // Square (width x width)
0639       size.setWidth(width);
0640       size.setHeight(width);
0641     }
0642 
0643     QString file = filename;
0644     if (i_startview - i_endview != 0) {
0645       QFileInfo QFI(filename);
0646       file = QFI.dir().path() + '/' + QFI.completeBaseName() +
0647              '_' +
0648           _tabWidget->tabBar()->tabText(viewCount).replace(QString("&"),QString()) + '.' +
0649              QFI.suffix();
0650     }
0651     if (format == QString("svg")) {
0652 #ifndef KST_NO_SVG
0653       QPainter painter;
0654       QSvgGenerator generator;
0655 
0656       QSize currentSize(view->size());
0657       view->resize(size);
0658       view->processResize(size);
0659       view->setPrinting(true);
0660 
0661       generator.setFileName(file);
0662       generator.setResolution(300);
0663       generator.setSize(view->size());
0664       generator.setViewBox(view->rect());
0665 
0666       painter.begin(&generator);
0667       view->render(&painter);
0668       painter.end();
0669 
0670       view->setPrinting(false);
0671       view->resize(currentSize);
0672       view->processResize(currentSize);
0673 #endif
0674     } else if (format == QString("eps")) {
0675 #ifndef KST_NO_PRINTER
0676       QPrinter printer(QPrinter::ScreenResolution);
0677 #ifdef QT5
0678       printer.setOutputFormat(QPrinter::PdfFormat);
0679 #else
0680       printer.setOutputFormat(QPrinter::PostScriptFormat);
0681 #endif
0682       printer.setOutputFileName(file);
0683       printer.setOrientation(QPrinter::Portrait);
0684 
0685       printer.setPrintRange(QPrinter::PageRange);
0686       printer.setFromTo(i_view+1, i_view+1);
0687 
0688       printer.setPaperSize(size, QPrinter::DevicePixel);
0689       printToPrinter(&printer);
0690 
0691     } else if (format == QString("pdf")) {
0692       QPrinter printer(QPrinter::ScreenResolution);
0693       printer.setOutputFormat(QPrinter::PdfFormat);
0694       printer.setOutputFileName(file);
0695       //setPrinterDefaults(&printer);
0696       printer.setOrientation(QPrinter::Portrait);
0697 
0698       printer.setPrintRange(QPrinter::PageRange);
0699       printer.setFromTo(i_view+1, i_view+1);
0700 
0701       printer.setPaperSize(size, QPrinter::DevicePixel);
0702       printToPrinter(&printer);
0703 #endif
0704     } else {
0705       QPainter painter;
0706       QImage image(size, QImage::Format_ARGB32);
0707 
0708       painter.begin(&image);
0709 
0710       QSize currentSize(view->size());
0711       view->resize(size);
0712       view->processResize(size);
0713       view->setPrinting(true);
0714       view->render(&painter);
0715       view->setPrinting(false);
0716       view->resize(currentSize);
0717       view->processResize(currentSize);
0718 
0719       painter.end();
0720 
0721       QImageWriter imageWriter(file, format.toLatin1());
0722       imageWriter.write(image);
0723     }
0724     viewCount++;
0725   }
0726 
0727   if (_ae_autosave_period > 0) {
0728     if (_ae_Timer == 0) { // create timer (only once)
0729       _ae_Timer = new QTimer(this);
0730       _ae_Timer->setSingleShot(true);
0731       connect(_ae_Timer, SIGNAL(timeout()), this, SLOT(autoExportImage()));
0732     }
0733     _ae_Timer->start(_ae_autosave_period); // one shot timer...
0734   }
0735 }
0736 
0737 void MainWindow::exportLog(const QString &imagename, QString &msgfilename, const QString &format, int x_size, int y_size,
0738                            int size_option_index, const QString &message) {
0739   View *view = _tabWidget->currentView();
0740 
0741   QSize size;
0742   if (size_option_index == 0) {
0743     size.setWidth(x_size);
0744     size.setHeight(y_size);
0745   } else if (size_option_index == 1) {
0746     size.setWidth(x_size);
0747     size.setHeight(y_size);
0748   } else if (size_option_index == 2) {
0749     QSize sizeWindow(view->geometry().size());
0750 
0751     size.setWidth(x_size);
0752     size.setHeight((int)((qreal)x_size * (qreal)sizeWindow.height() / (qreal)sizeWindow.width()));
0753   } else {
0754     QSize sizeWindow(view->geometry().size());
0755 
0756     size.setHeight(y_size);
0757     size.setWidth((int)((qreal)y_size * (qreal)sizeWindow.width() / (qreal)sizeWindow.height()));
0758   }
0759 
0760   QImage image(size, QImage::Format_ARGB32);
0761 
0762   QPainter painter(&image);
0763   QSize currentSize(view->size());
0764   view->resize(size);
0765   view->processResize(size);
0766   view->setPrinting(true);
0767   view->render(&painter);
0768   view->setPrinting(false);
0769   view->resize(currentSize);
0770   view->processResize(currentSize);
0771 
0772   QImageWriter imageWriter(imagename, format.toLatin1());
0773   imageWriter.write(image);
0774 
0775   QFile file(msgfilename);
0776 
0777   if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
0778     QTextStream out(&file);
0779     out << message;
0780     file.close();
0781   }
0782 
0783 }
0784 
0785 #ifndef KST_NO_PRINTER
0786 void MainWindow::printToPrinter(QPrinter *printer) {
0787   QPainter painter(printer);
0788   QList<View*> pages;
0789 
0790   switch (printer->printRange()) {
0791    case QPrinter::PageRange:
0792     if (printer->fromPage()>0) {
0793       for (int i_page = printer->fromPage(); i_page<=printer->toPage(); i_page++) {
0794         pages.append(_tabWidget->views().at(i_page-1));
0795       }
0796     }
0797     break;
0798    case QPrinter::AllPages:
0799     foreach (View *view, _tabWidget->views()) {
0800       pages.append(view);
0801     }
0802     break;
0803    case QPrinter::Selection:
0804    default:
0805     pages.append(_tabWidget->currentView());
0806     break;
0807   }
0808 
0809   QSize printerPageSize = printer->pageRect().size();
0810   for (int i = 0; i < printer->numCopies(); ++i) {
0811     for (int i_page = 0; i_page<pages.count(); i_page++) {
0812       View *view = pages.at(i_page);
0813       QSize currentSize(view->size());
0814       view->resize(printerPageSize);
0815       view->processResize(printerPageSize);
0816       view->setPrinting(true);
0817       view->render(&painter);
0818       view->setPrinting(false);
0819       view->resize(currentSize);
0820       view->processResize(currentSize);
0821       if (i_page<pages.count()-1)
0822         printer->newPage();
0823 
0824     }
0825   }
0826 }
0827 
0828 void MainWindow::printFromCommandLine(const QString &printFileName) {
0829   QPrinter printer(QPrinter::ScreenResolution);
0830   printer.setResolution(300);
0831   printer.setOutputFileName(printFileName);
0832   setPrinterDefaults(&printer);
0833 
0834   printer.setPrintRange(QPrinter::AllPages);
0835   printToPrinter(&printer);
0836 }
0837 
0838 void MainWindow::setPrinterDefaults(QPrinter *printer) {
0839   if (dialogDefaults().value("print/landscape",true).toBool()) {
0840     printer->setOrientation(QPrinter::Landscape);
0841   } else {
0842     printer->setOrientation(QPrinter::Portrait);
0843   }
0844 
0845   printer->setPaperSize(QPrinter::PaperSize(dialogDefaults().value("print/paperSize", QPrinter::Letter).toInt()));
0846 
0847   QPointF topLeft =dialogDefaults().value("print/topLeftMargin", QPointF(15.0,15.0)).toPointF();
0848   QPointF bottomRight =dialogDefaults().value("print/bottomRightMargin", QPointF(15.0,15.0)).toPointF();
0849 
0850   printer->setPageMargins(topLeft.x(), topLeft.y(), bottomRight.x(), bottomRight.y(), QPrinter::Millimeter);
0851   // Apparent Qt bug: setting the page margins here doesn't set the correspoding values in the print
0852   // dialog->printer-options sub-dialog under linux.  If you don't open the printer-options sub-dialog,
0853   // the values here are honored.
0854 }
0855 
0856 void MainWindow::savePrinterDefaults(QPrinter *printer) {
0857   dialogDefaults().setValue("print/landscape", printer->orientation() == QPrinter::Landscape);
0858   dialogDefaults().setValue("print/paperSize", int(printer->paperSize()));
0859 
0860   qreal left, top, right, bottom;
0861   printer->getPageMargins(&left, &top, &right, &bottom, QPrinter::Millimeter);
0862   dialogDefaults().setValue("print/topLeftMargin", QPointF(left, top));
0863   dialogDefaults().setValue("print/bottomRightMargin", QPointF(right, bottom));
0864 
0865 }
0866 
0867 void MainWindow::print() {
0868   QPrinter printer(QPrinter::ScreenResolution);
0869   printer.setResolution(300);
0870 
0871   setPrinterDefaults(&printer);
0872 
0873 #ifndef Q_OS_WIN
0874   // QPrintDialog: Cannot be used on non-native printers
0875   printer.setOutputFileName(dialogDefaults().value("print/path", "./print.pdf").toString());
0876 #endif
0877   QPointer<QPrintDialog> pd = new QPrintDialog(&printer, this);
0878 #if QT_VERSION >= 0x040500
0879   pd->setOption(QPrintDialog::PrintToFile);
0880   pd->setOption(QPrintDialog::PrintPageRange, true);
0881   pd->setOption(QAbstractPrintDialog::PrintShowPageSize,true);
0882 #endif
0883 
0884   if (pd->exec() == QDialog::Accepted) {
0885     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
0886     printToPrinter(&printer);
0887     QApplication::restoreOverrideCursor();
0888     savePrinterDefaults(&printer);
0889   }
0890   dialogDefaults().setValue("print/path", printer.outputFileName());
0891   delete pd;
0892 }
0893 #endif
0894 
0895 void MainWindow::currentViewChanged() {
0896   if(!_tabWidget->currentView())
0897     return;
0898   _undoGroup->setActiveStack(_tabWidget->currentView()->undoStack());
0899   currentViewModeChanged();
0900 }
0901 
0902 
0903 void MainWindow::currentViewModeChanged() {
0904   if(!_tabWidget->currentView())
0905     return;
0906   _layoutModeAct->setChecked(_tabWidget->currentView()->viewMode() == View::Layout);
0907 }
0908 
0909 void MainWindow::aboutToQuit() {
0910   writeSettings();
0911 }
0912 
0913 
0914 void MainWindow::about() {
0915   if (!_aboutDialog) {
0916     _aboutDialog = new AboutDialog(this);
0917   }
0918   if (_aboutDialog->isVisible()) {
0919     _aboutDialog->raise();
0920     _aboutDialog->activateWindow();
0921   }
0922   _aboutDialog->show();
0923 }
0924 
0925 
0926 void MainWindow::showShortcutDialog() {
0927   if (!_shortcutDialog) {
0928     _shortcutDialog = new ShortcutDialog(this);
0929   } else if (_shortcutDialog->isVisible()) {
0930     _shortcutDialog->raise();
0931     _shortcutDialog->activateWindow();
0932   }
0933   _shortcutDialog->show();
0934 
0935   _shortcutDialog->resetWidth();
0936 
0937 }
0938 
0939 
0940 void MainWindow::clearDrawingMarker() {
0941   _createBoxAct->setChecked(false);
0942   _createSharedAxisBoxAct->setChecked(false);
0943   _createCircleAct->setChecked(false);
0944   _createEllipseAct->setChecked(false);
0945   _createLabelAct->setChecked(false);
0946   _createLineAct->setChecked(false);
0947   _createArrowAct->setChecked(false);
0948   _createPictureAct->setChecked(false);
0949   _createPlotAct->setChecked(false);
0950 #ifndef KST_NO_SVG
0951   _createSvgAct->setChecked(false);
0952 #endif
0953   _tabWidget->currentView()->setMouseMode(View::Default);
0954 }
0955 
0956 
0957 void MainWindow::createBox() {
0958   if (_createBoxAct->isChecked()) {
0959     clearDrawingMarker();
0960     _createBoxAct->setChecked(true);
0961     CreateBoxCommand *cmd = new CreateBoxCommand;
0962     cmd->createItem();
0963   } else {
0964     _tabWidget->currentView()->setMouseMode(View::Default);
0965   }
0966 }
0967 
0968 
0969 
0970 void MainWindow::createSharedAxisBox() {
0971   if (_createSharedAxisBoxAct->isChecked()) {
0972     clearDrawingMarker();
0973     _createSharedAxisBoxAct->setChecked(true);
0974     CreateSharedAxisBoxCommand *cmd = new CreateSharedAxisBoxCommand;
0975     cmd->createItem();
0976   } else {
0977     _tabWidget->currentView()->setMouseMode(View::Default);
0978   }
0979 }
0980 
0981 void MainWindow::createVector() {
0982   QString tmp;
0983   DialogLauncher::self()->showVectorDialog(tmp);
0984 }
0985 
0986 
0987 void MainWindow::createMatrix() {
0988   QString tmp;
0989   DialogLauncher::self()->showMatrixDialog(tmp);
0990 }
0991 
0992 
0993 void MainWindow::createScalar() {
0994   QString scalarName;
0995   DialogLauncher::self()->showScalarDialog(scalarName);
0996 }
0997 
0998 
0999 void MainWindow::createString() {
1000   QString stringName;
1001   DialogLauncher::self()->showStringDialog(stringName);
1002 }
1003 
1004 
1005 void MainWindow::createCircle() {
1006   if (_createCircleAct->isChecked()) {
1007     clearDrawingMarker();
1008     _createCircleAct->setChecked(true);
1009     CreateCircleCommand *cmd = new CreateCircleCommand;
1010     cmd->createItem();
1011   } else {
1012     _tabWidget->currentView()->setMouseMode(View::Default);
1013   }
1014 }
1015 
1016 
1017 void MainWindow::createEllipse() {
1018   if (_createEllipseAct->isChecked()) {
1019     clearDrawingMarker();
1020     _createEllipseAct->setChecked(true);
1021     CreateEllipseCommand *cmd = new CreateEllipseCommand;
1022     cmd->createItem();
1023   } else {
1024     _tabWidget->currentView()->setMouseMode(View::Default);
1025   }
1026 }
1027 
1028 
1029 void MainWindow::createLabel() {
1030   if (_createLabelAct->isChecked()) {
1031     clearDrawingMarker();
1032     _createLabelAct->setChecked(true);
1033     CreateLabelCommand *cmd = new CreateLabelCommand;
1034     cmd->createItem();
1035   } else {
1036     _tabWidget->currentView()->setMouseMode(View::Default);
1037   }
1038 }
1039 
1040 
1041 void MainWindow::createLine() {
1042   if (_createLineAct->isChecked()) {
1043     clearDrawingMarker();
1044     _createLineAct->setChecked(true);
1045     CreateLineCommand *cmd = new CreateLineCommand;
1046     cmd->createItem();
1047   } else {
1048     _tabWidget->currentView()->setMouseMode(View::Default);
1049   }
1050 }
1051 
1052 
1053 void MainWindow::createArrow() {
1054   if (_createArrowAct->isChecked()) {
1055     clearDrawingMarker();
1056     _createArrowAct->setChecked(true);
1057     CreateArrowCommand *cmd = new CreateArrowCommand;
1058     cmd->createItem();
1059   } else {
1060     _tabWidget->currentView()->setMouseMode(View::Default);
1061   }
1062 }
1063 
1064 
1065 void MainWindow::createPicture() {
1066   if (_createPictureAct->isChecked()) {
1067     clearDrawingMarker();
1068     _createPictureAct->setChecked(true);
1069     CreatePictureCommand *cmd = new CreatePictureCommand;
1070     cmd->createItem();
1071   } else {
1072     _tabWidget->currentView()->setMouseMode(View::Default);
1073   }
1074 }
1075 
1076 
1077 void MainWindow::createPlot() {
1078   if (_createPlotAct->isChecked()) {
1079     clearDrawingMarker();
1080     _createPlotAct->setChecked(true);
1081     CreatePlotCommand *cmd = new CreatePlotCommand;
1082     cmd->createItem();
1083   } else {
1084     _tabWidget->currentView()->setMouseMode(View::Default);
1085   }
1086 }
1087 
1088 void MainWindow::insertPlot() {
1089   CreatePlotForCurve *cmd = new CreatePlotForCurve();
1090   cmd->createItem();
1091 
1092   PlotItem *plotItem = static_cast<PlotItem*>(cmd->item());
1093   plotItem->view()->resetPlotFontSizes(plotItem);
1094   plotItem->view()->configurePlotFontDefaults(plotItem); // copy plots already in window
1095   plotItem->view()->appendToLayout(CurvePlacement::Auto, plotItem, 0);
1096 
1097 }
1098 
1099 #ifndef KST_NO_SVG
1100 void MainWindow::createSvg() {
1101   if (_createSvgAct->isChecked()) {
1102     clearDrawingMarker();
1103     _createSvgAct->setChecked(true);
1104     CreateSvgCommand *cmd = new CreateSvgCommand;
1105     cmd->createItem();
1106   } else {
1107     _tabWidget->currentView()->setMouseMode(View::Default);
1108   }
1109 }
1110 #endif
1111 
1112 void MainWindow::createCurve() {
1113   DialogLauncher::self()->showCurveDialog();
1114 }
1115 
1116 void MainWindow::createPSD() {
1117   DialogLauncher::self()->showPowerSpectrumDialog();
1118 }
1119 
1120 void MainWindow::createEquation() {
1121   DialogLauncher::self()->showEquationDialog();
1122 }
1123 
1124 void MainWindow::createHistogram() {
1125   DialogLauncher::self()->showHistogramDialog();
1126 }
1127 
1128 void MainWindow::createImage() {
1129   DialogLauncher::self()->showImageDialog();
1130 }
1131 
1132 void MainWindow::createSpectogram() {
1133   DialogLauncher::self()->showCSDDialog();
1134 }
1135 
1136 void MainWindow::createEventMonitor() {
1137   DialogLauncher::self()->showEventMonitorDialog();
1138 }
1139 
1140 void MainWindow::createActions() {
1141   // ***************************** File actions ******************************** //
1142   _openAct = new QAction(tr("&Open..."), this);
1143   _openAct->setStatusTip(tr("Open a new session"));
1144   _openAct->setShortcuts(QKeySequence::Open);
1145   _openAct->setIcon(KstGetIcon("document-open"));
1146   connect(_openAct, SIGNAL(triggered()), this, SLOT(open()));
1147 
1148   _saveAct = new QAction(tr("&Save"), this);
1149   _saveAct->setStatusTip(tr("Save the current session"));
1150   _saveAct->setShortcuts(QKeySequence::Save);
1151   _saveAct->setIcon(KstGetIcon("document-save"));
1152   connect(_saveAct, SIGNAL(triggered()), this, SLOT(save()));
1153 
1154   _saveAsAct = new QAction(tr("Save &as..."), this);
1155   _saveAsAct->setStatusTip(tr("Save the current session"));
1156   _saveAsAct->setIcon(KstGetIcon("document-save-as"));
1157   _saveAsAct->setShortcuts(QKeySequence::SaveAs);
1158   connect(_saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs()));
1159 
1160   _closeAct = new QAction(tr("Ne&w Session"), this);
1161   _closeAct->setStatusTip(tr("Close current session and start a new, empty one"));
1162   _closeAct->setIcon(KstGetIcon("document-close"));
1163   _closeAct->setShortcuts(QKeySequence::Close);
1164   connect(_closeAct, SIGNAL(triggered()), this, SLOT(newDoc()));
1165 
1166   _reloadAct = new QAction(tr("Reload All &Data Sources"), this);
1167   _reloadAct->setStatusTip(tr("Reload all data sources"));
1168   _reloadAct->setIcon(KstGetIcon("kst_reload"));
1169   connect(_reloadAct, SIGNAL(triggered()), this, SLOT(reload()));
1170 
1171   _printAct = new QAction(tr("&Print..."), this);
1172   _printAct->setStatusTip(tr("Print the current view"));
1173   _printAct->setIcon(KstGetIcon("document-print"));
1174   _printAct->setShortcuts(QKeySequence::Print);
1175   connect(_printAct, SIGNAL(triggered()), this, SLOT(print()));
1176 #ifdef KST_NO_PRINTER
1177   _printAct->setEnabled(false);
1178 #endif
1179 
1180   _exportGraphicsAct = new QAction(tr("&Export as Image(s)..."), this);
1181   _exportGraphicsAct->setStatusTip(tr("Export graphics to disk"));
1182   _exportGraphicsAct->setIcon(KstGetIcon("insert-image"));
1183   connect(_exportGraphicsAct, SIGNAL(triggered()), this, SLOT(showExportGraphicsDialog()));
1184 
1185   _exportVectorsAct = new QAction(tr("Save &Vectors to Disk..."), this);
1186   _exportVectorsAct->setStatusTip(tr("Export vectors to ascii file"));
1187   _exportVectorsAct->setIcon(KstGetIcon("save-vectors"));
1188   connect(_exportVectorsAct, SIGNAL(triggered()), this, SLOT(showExportVectorsDialog()));
1189 
1190   _logAct = new QAction(tr("&Log Entry..."), this);
1191   _logAct->setStatusTip(tr("Commit a log entry"));
1192   _logAct->setIcon(KstGetIcon("new-log-event"));
1193   connect(_logAct, SIGNAL(triggered()), this, SLOT(showLogDialog()));
1194 
1195   _newTabAct = new QAction(tr("&New Tab"), this);
1196   _newTabAct->setStatusTip(tr("Create a new tab"));
1197   _newTabAct->setIcon(KstGetIcon("tab-new"));
1198 
1199   connect(_newTabAct, SIGNAL(triggered()), tabWidget(), SLOT(createView()));
1200 
1201   _closeTabAct = new QAction(tr("&Close Tab"), this);
1202   _closeTabAct->setStatusTip(tr("Close the current tab"));
1203   _closeTabAct->setIcon(KstGetIcon("tab-close"));
1204   connect(_closeTabAct, SIGNAL(triggered()), tabWidget(), SLOT(closeCurrentView()));
1205 
1206   _exitAct = new QAction(tr("E&xit"), this);
1207   _exitAct->setShortcuts(QKeySequence::Quit);
1208   _exitAct->setStatusTip(tr("Exit the application"));
1209   _exitAct->setIcon(KstGetIcon("application-exit"));
1210   connect(_exitAct, SIGNAL(triggered()), this, SLOT(close()));
1211 
1212   // ************************** Edit Actions ******************************* //
1213   _undoAct = _undoGroup->createUndoAction(this);
1214   _undoAct->setShortcuts(QKeySequence::Undo);
1215   _undoAct->setIcon(KstGetIcon("edit-undo"));
1216 
1217   _redoAct = _undoGroup->createRedoAction(this);
1218   _redoAct->setShortcuts(QKeySequence::Redo);
1219   _redoAct->setIcon(KstGetIcon("edit-redo"));
1220 
1221   _copyTabAct = new QAction(tr("Copy Tab Image"), this);
1222   _copyTabAct->setStatusTip("Copy image of the current tab to the desktop clipboard");
1223   _copyTabAct->setIcon(KstGetIcon("edit-copy"));
1224   connect(_copyTabAct, SIGNAL(triggered()), this, SLOT(copyTab()));
1225 
1226   // ********************* View Actions ********************************** //
1227   _vectorEditorAct = new QAction(tr("&Vectors"), this);
1228   _vectorEditorAct->setStatusTip(tr("Show all vectors in a spreadsheet"));
1229   connect(_vectorEditorAct, SIGNAL(triggered()), this, SLOT(showVectorEditor()));
1230 
1231   _scalarEditorAct = new QAction(tr("&Scalars"), this);
1232   _scalarEditorAct->setStatusTip(tr("Show all scalars in a spreadsheet"));
1233   connect(_scalarEditorAct, SIGNAL(triggered()), this, SLOT(showScalarEditor()));
1234 
1235   _matrixEditorAct = new QAction(tr("&Matrices"), this);
1236   _matrixEditorAct->setStatusTip(tr("Show all matrices in a spreadsheet"));
1237   connect(_matrixEditorAct, SIGNAL(triggered()), this, SLOT(showMatrixEditor()));
1238 
1239   _stringEditorAct = new QAction(tr("S&trings"), this);
1240   _stringEditorAct->setStatusTip(tr("Show all strings in a spreadsheet"));
1241   connect(_stringEditorAct, SIGNAL(triggered()), this, SLOT(showStringEditor()));
1242 
1243   // ************************ Data Range 1 click Actions ************************** //
1244   _backAct = new QAction(tr("&Back One Screen"), this);
1245   _backAct->setStatusTip(tr("Back one screen (Page Up)"));
1246   _backAct->setToolTip(tr("Back one screen (Page Up)"));
1247   _backAct->setIcon(KstGetIcon("page-previous"));
1248   _backAct->setShortcut(Qt::Key_PageUp);
1249   connect(_backAct, SIGNAL(triggered()), this, SLOT(back()));
1250 
1251   _forwardAct = new QAction(tr("&Forward One Screen"), this);
1252   _forwardAct->setStatusTip(tr("Forward one screen (Page Down)"));
1253   _forwardAct->setToolTip(tr("Forward one screen (Page Down)"));
1254   _forwardAct->setIcon(KstGetIcon("page-next"));
1255   _forwardAct->setShortcut(Qt::Key_PageDown);
1256   connect(_forwardAct, SIGNAL(triggered()), this, SLOT(forward()));
1257 
1258   _backSmallAct = new QAction(tr("&Back 1/5th Screen"), this);
1259   _backSmallAct->setStatusTip(tr("Back 1/5th screen (Shift + Page Up)"));
1260   _backSmallAct->setToolTip(tr("Back 1/5th screen (Shift + Page Up)"));
1261   _backSmallAct->setIcon(KstGetIcon("page-previous"));
1262   _backSmallAct->setShortcut(Qt::SHIFT + Qt::Key_PageDown);
1263   connect(_backSmallAct, SIGNAL(triggered()), this, SLOT(backSmall()));
1264 
1265   _forwardSmallAct = new QAction(tr("&Forward 1/5th Screen"), this);
1266   _forwardSmallAct->setStatusTip(tr("Forward 1/5th screen (Page Down)"));
1267   _forwardSmallAct->setToolTip(tr("Forward 1/5th screen (Page Down)"));
1268   _forwardSmallAct->setIcon(KstGetIcon("page-next"));
1269   _forwardSmallAct->setShortcut(Qt::SHIFT + Qt::Key_PageUp);
1270   connect(_forwardSmallAct, SIGNAL(triggered()), this, SLOT(forwardSmall()));
1271 
1272   _readFromEndAct = new QAction(tr("&Count from End"), this);
1273   _readFromEndAct->setStatusTip(tr("Count from end mode (End)"));
1274   _readFromEndAct->setToolTip(tr("Count from end mode (End)"));
1275   _readFromEndAct->setIcon(KstGetIcon("count-from-end"));
1276   _readFromEndAct->setShortcut(Qt::Key_End);
1277   connect(_readFromEndAct, SIGNAL(triggered()), this, SLOT(readFromEnd()));
1278 
1279   _readToEndAct = new QAction(tr("&Read to End"), this);
1280   _readToEndAct->setStatusTip(tr("Read to end mode"));
1281   _readToEndAct->setToolTip(tr("Read to end mode (shift+end)"));
1282   _readToEndAct->setIcon(KstGetIcon("read-to-end"));
1283   _readToEndAct->setShortcut(Qt::ShiftModifier+Qt::Key_End);
1284   connect(_readToEndAct, SIGNAL(triggered()), this, SLOT(readToEnd()));
1285 
1286   _pauseAct = new QAction(tr("&Pause"), this);
1287   _pauseAct->setIcon(KstGetIcon("pause"));
1288   _pauseAct->setCheckable(true);
1289   _pauseAct->setShortcut(tr("p", "shortcut for pause"));
1290   _pauseAct->setStatusTip(tr("Toggle pause updates of data sources (%1)").arg(_pauseAct->shortcut().toString()));
1291   _pauseAct->setToolTip(tr("Toggle \"Pause Data Sources\" (%1)").arg(_pauseAct->shortcut().toString()));
1292   connect(_pauseAct, SIGNAL(toggled(bool)), this, SLOT(pause(bool)));
1293 
1294   _changeDataSampleDialogAct = new QAction(tr("Change Data &Sample Range..."), this);
1295   _changeDataSampleDialogAct->setShortcut(tr("J", "shortcut change data sample dialog"));
1296   _changeDataSampleDialogAct->setStatusTip(tr("Show Kst's Change Data Sample Range Dialog (%1)").arg(_changeDataSampleDialogAct->shortcut().toString()));
1297   _changeDataSampleDialogAct->setToolTip(tr("Change Data Sample Range (%1)").arg(_changeDataSampleDialogAct->shortcut().toString()));
1298   _changeDataSampleDialogAct->setIcon(KstGetIcon("kst_changenpts"));
1299   connect(_changeDataSampleDialogAct, SIGNAL(triggered()), this, SLOT(showChangeDataSampleDialog()));
1300 
1301   // ************************ Create Actions ************************** //
1302   _insertPlotAct = new QAction(tr("&Plot"), this);
1303   _insertPlotAct->setIcon(KstGetIcon("kst_newplot"));
1304   _insertPlotAct->setShortcut(QString("F11"));
1305   _insertPlotAct->setStatusTip(tr("Insert a plot in the current view (%1)").arg(_insertPlotAct->shortcut().toString()));
1306   _insertPlotAct->setToolTip(tr("New plot (%1)").arg(_insertPlotAct->shortcut().toString()));
1307   _insertPlotAct->setCheckable(false);
1308   connect(_insertPlotAct, SIGNAL(triggered()), this, SLOT(insertPlot()));
1309 
1310   _createPlotAct = new QAction(tr("&Plot"), this);
1311   _createPlotAct->setIcon(KstGetIcon("kst_newplot"));
1312   //_createPlotAct->setShortcut(QString("F11"));
1313   _createPlotAct->setStatusTip(tr("Create a plot for the current view"));
1314   _createPlotAct->setCheckable(true);
1315   connect(_createPlotAct, SIGNAL(triggered()), this, SLOT(createPlot()));
1316 
1317   _newScalarAct = new QAction(tr("&Scalar"), this);
1318   connect(_newScalarAct, SIGNAL(triggered()), this, SLOT(createScalar()));
1319 
1320   _newVectorAct = new QAction(tr("&Vector"), this);
1321   connect(_newVectorAct, SIGNAL(triggered()), this, SLOT(createVector()));
1322 
1323   _newMatrixAct = new QAction(tr("&Matrix"), this);
1324   connect(_newMatrixAct, SIGNAL(triggered()), this, SLOT(createMatrix()));
1325 
1326   _newStringAct = new QAction(tr("Strin&g"), this);
1327   connect(_newStringAct, SIGNAL(triggered()), this, SLOT(createString()));
1328 
1329   _newCurveAct = new QAction(tr("&Curve"), this);
1330   connect(_newCurveAct, SIGNAL(triggered()), this, SLOT(createCurve()));
1331 
1332   _newEquationAct = new QAction(tr("&Equation"), this);
1333   connect(_newEquationAct, SIGNAL(triggered()), this, SLOT(createEquation()));
1334 
1335   _newPSDAct = new QAction(tr("Po&wer Spectrum"), this);
1336   connect(_newPSDAct, SIGNAL(triggered()), this, SLOT(createPSD()));
1337 
1338   _newHistogramAct = new QAction(tr("&Histogram"), this);
1339   connect(_newHistogramAct, SIGNAL(triggered()), this, SLOT(createHistogram()));
1340 
1341   _newImageAct = new QAction(tr("&Image"), this);
1342   connect(_newImageAct, SIGNAL(triggered()), this, SLOT(createImage()));
1343 
1344   _newSpectrogramAct = new QAction(tr("Spectr&ogram"), this);
1345   connect(_newSpectrogramAct, SIGNAL(triggered()), this, SLOT(createSpectogram()));
1346 
1347   _newEventMonitorAct = new QAction(tr("Eve&nt Monitor"), this);
1348   connect(_newEventMonitorAct, SIGNAL(triggered()), this, SLOT(createEventMonitor()));
1349 
1350   // Advanced layout
1351   _createLabelAct = new QAction(tr("&Label"), this);
1352   _createLabelAct->setIcon(KstGetIcon("kst_gfx_label"));
1353   _createLabelAct->setShortcut(QString("F3"));
1354   _createLabelAct->setStatusTip(tr("Create a label for the current view (%1)").arg(_createLabelAct->shortcut().toString()));
1355   _createLabelAct->setToolTip(tr("Create label (%1)").arg(_createLabelAct->shortcut().toString()));
1356   _createLabelAct->setCheckable(true);
1357   connect(_createLabelAct, SIGNAL(triggered()), this, SLOT(createLabel()));
1358 
1359   _createBoxAct = new QAction(tr("&Box"), this);
1360   _createBoxAct->setIcon(KstGetIcon("kst_gfx_rectangle"));
1361   _createBoxAct->setShortcut(QString("F4"));
1362   _createBoxAct->setStatusTip(tr("Create a box for the current view (%1)").arg(_createBoxAct->shortcut().toString()));
1363   _createBoxAct->setToolTip(tr("Create box (%1)").arg(_createBoxAct->shortcut().toString()));
1364   _createBoxAct->setCheckable(true);
1365   connect(_createBoxAct, SIGNAL(triggered()), this, SLOT(createBox()));
1366 
1367   _createCircleAct = new QAction(tr("&Circle"), this);
1368   _createCircleAct->setIcon(KstGetIcon("kst_gfx_circle"));
1369   _createCircleAct->setShortcut(QString("F5"));
1370   _createCircleAct->setStatusTip(tr("Create a circle for the current view (%1)").arg(_createCircleAct->shortcut().toString()));
1371   _createCircleAct->setToolTip(tr("Create circle (%1)").arg(_createCircleAct->shortcut().toString()));
1372   _createCircleAct->setCheckable(true);
1373   connect(_createCircleAct, SIGNAL(triggered()), this, SLOT(createCircle()));
1374 
1375   _createEllipseAct = new QAction(tr("&Ellipse"), this);
1376   _createEllipseAct->setIcon(KstGetIcon("kst_gfx_ellipse"));
1377   _createEllipseAct->setShortcut(QString("F6"));
1378   _createEllipseAct->setStatusTip(tr("Create an ellipse for the current view (%1)").arg(_createEllipseAct->shortcut().toString()));
1379   _createEllipseAct->setToolTip(tr("Create ellipse (%1)").arg(_createEllipseAct->shortcut().toString()));
1380   _createEllipseAct->setCheckable(true);
1381   connect(_createEllipseAct, SIGNAL(triggered()), this, SLOT(createEllipse()));
1382 
1383   _createLineAct = new QAction(tr("&Line"), this);
1384   _createLineAct->setIcon(KstGetIcon("kst_gfx_line"));
1385   _createLineAct->setShortcut(QString("F7"));
1386   _createLineAct->setStatusTip(tr("Create a line for the current view (%1)").arg(_createLineAct->shortcut().toString()));
1387   _createLineAct->setToolTip(tr("Create line (%1)").arg(_createLineAct->shortcut().toString()));
1388   _createLineAct->setCheckable(true);
1389   connect(_createLineAct, SIGNAL(triggered()), this, SLOT(createLine()));
1390 
1391   _createArrowAct = new QAction(tr("&Arrow"), this);
1392   _createArrowAct->setIcon(KstGetIcon("kst_gfx_arrow"));
1393   _createArrowAct->setShortcut(QString("F8"));
1394   _createArrowAct->setStatusTip(tr("Create a arrow for the current view (%1)").arg(_createArrowAct->shortcut().toString()));
1395   _createArrowAct->setToolTip(tr("Create arrow (%1)").arg(_createArrowAct->shortcut().toString()));
1396   _createArrowAct->setCheckable(true);
1397   connect(_createArrowAct, SIGNAL(triggered()), this, SLOT(createArrow()));
1398 
1399   _createPictureAct = new QAction(tr("&Picture"), this);
1400   _createPictureAct->setIcon(KstGetIcon("insert-image"));
1401   _createPictureAct->setShortcut(QString("F9"));
1402   _createPictureAct->setStatusTip(tr("Create a picture for the current view (%1)").arg(_createPictureAct->shortcut().toString()));
1403   _createPictureAct->setToolTip(tr("Create picture (%1)").arg(_createPictureAct->shortcut().toString()));
1404   _createPictureAct->setCheckable(true);
1405   connect(_createPictureAct, SIGNAL(triggered()), this, SLOT(createPicture()));
1406 
1407 #ifndef KST_NO_SVG
1408   _createSvgAct = new QAction(tr("&Svg"), this);
1409   _createSvgAct->setIcon(KstGetIcon("draw-bezier-curves"));
1410   _createSvgAct->setShortcut(QString("F10"));
1411   _createSvgAct->setStatusTip(tr("Create a svg for the current view (%1)").arg(_createSvgAct->shortcut().toString()));
1412   _createSvgAct->setToolTip(tr("Create embedded svg image (%1)").arg(_createSvgAct->shortcut().toString()));
1413   _createSvgAct->setCheckable(true);
1414   connect(_createSvgAct, SIGNAL(triggered()), this, SLOT(createSvg()));
1415 #endif
1416 
1417   _createSharedAxisBoxAct = new QAction(tr("Shared Axis &Box"), this);
1418   _createSharedAxisBoxAct->setStatusTip(tr("Create a shared axis box for the current item"));
1419   _createSharedAxisBoxAct->setIcon(KstGetIcon("kst_gfx_sharedaxisbox"));
1420   _createSharedAxisBoxAct->setCheckable(true);
1421   connect(_createSharedAxisBoxAct, SIGNAL(triggered()), this, SLOT(createSharedAxisBox()));
1422 
1423   // ************************** Mode Actions ******************************* //
1424   // First, general options
1425   _tiedZoomAct = new QAction(tr("&Toggle Tied Zoom"), this);
1426   _tiedZoomAct->setIcon(KstGetIcon("tied-zoom"));
1427   _tiedZoomAct->setCheckable(false);
1428   _tiedZoomAct->setShortcut(Qt::Key_O);
1429   _tiedZoomAct->setStatusTip(tr("Toggle the current view's tied zoom (%1)").arg(_tiedZoomAct->shortcut().toString()));
1430   _tiedZoomAct->setToolTip(tr("Toggle tied zoom (%1)").arg(_tiedZoomAct->shortcut().toString()));
1431   connect(_tiedZoomAct, SIGNAL(triggered()), this, SLOT(toggleTiedZoom()));
1432 
1433   _tabTiedAct = new QAction(tr("Tie &Across All Tabs"), this);
1434   _tabTiedAct->setStatusTip(tr("Tied zoom applies between tabs"));
1435   //_tiedZoomAct->setIcon(KstGetIcon("tied-zoom"));
1436   _tabTiedAct->setCheckable(true);
1437   //connect(_tiedZoomAct, SIGNAL(triggered()), this, SLOT(toggleTiedZoom()));
1438 
1439 
1440   _highlightPointAct = new QAction(tr("&Highlight Data Points"), this);
1441   _highlightPointAct->setShortcut(QString("h"));
1442   _highlightPointAct->setStatusTip(tr("Highlight closest data point (%1)").arg(_highlightPointAct->shortcut().toString()));
1443   _highlightPointAct->setToolTip(tr("Highlight closest data point (%1)").arg(_highlightPointAct->shortcut().toString()));
1444   _highlightPointAct->setIcon(KstGetIcon("kst_datamode"));
1445   _highlightPointAct->setCheckable(true);
1446   connect(_highlightPointAct, SIGNAL(toggled(bool)), this, SLOT(setHighlightPoint(bool)));
1447 
1448 
1449   // Then, exclusive interaction modes
1450   QActionGroup* _interactionModeGroup = new QActionGroup(this);
1451 
1452   _standardZoomAct = _interactionModeGroup->addAction(tr("X-Y Zoom/Scroll"));
1453   _standardZoomAct->setStatusTip(tr("Zoom arbitrarily in X- or Y-direction"));
1454   _standardZoomAct->setShortcut(Qt::Key_K);
1455   _standardZoomAct->setToolTip(tr("X-Y Zoom mode (%1)").arg(_standardZoomAct->shortcut().toString()));
1456   _standardZoomAct->setCheckable(true);
1457   _standardZoomAct->setData(View::ZoomOnlyDisabled);
1458   _standardZoomAct->setIcon(KstGetIcon("xy-zoom"));
1459 
1460   _xOnlyZoomAct = _interactionModeGroup->addAction(tr("&X-only Zoom"));
1461   _xOnlyZoomAct->setStatusTip(tr("Zoom only in X direction"));
1462   _xOnlyZoomAct->setShortcut(Qt::CTRL + Qt::Key_K);
1463   _xOnlyZoomAct->setToolTip(tr("X Zoom mode (%1)").arg(_xOnlyZoomAct->shortcut().toString()));
1464   _xOnlyZoomAct->setCheckable(true);
1465   _xOnlyZoomAct->setData(View::ZoomOnlyX);
1466   _xOnlyZoomAct->setIcon(KstGetIcon("x-zoom"));
1467 
1468   _yOnlyZoomAct = _interactionModeGroup->addAction(tr("&Y-only Zoom"));
1469   _yOnlyZoomAct->setStatusTip(tr("Zoom only in Y direction"));
1470   _yOnlyZoomAct->setShortcut(Qt::SHIFT + Qt::Key_K);
1471   _yOnlyZoomAct->setToolTip(tr("Y Zoom mode (%1)").arg(_yOnlyZoomAct->shortcut().toString()));
1472   _yOnlyZoomAct->setData(View::ZoomOnlyY);
1473   _yOnlyZoomAct->setCheckable(true);
1474   _yOnlyZoomAct->setIcon(KstGetIcon("y-zoom"));
1475 
1476   _layoutModeAct = _interactionModeGroup->addAction(tr("&Layout Mode"));
1477   _layoutModeAct->setIcon(KstGetIcon("transform-move"));
1478   _layoutModeAct->setCheckable(true);
1479   _layoutModeAct->setShortcut(QString("F2"));
1480   _layoutModeAct->setStatusTip(tr("Toggle the current view's layout mode (%1)").arg(_layoutModeAct->shortcut().toString()));
1481   _layoutModeAct->setToolTip(tr("Layout mode (%1)").arg(_layoutModeAct->shortcut().toString()));
1482   connect(_layoutModeAct, SIGNAL(toggled(bool)), this, SLOT(setLayoutMode(bool)));
1483 
1484   _interactionModeGroup->setExclusive(true);
1485   connect(_interactionModeGroup, SIGNAL(triggered(QAction*)), this, SLOT(changeZoomOnlyMode(QAction*)));
1486 
1487   // *********************** Tools actions ************************************** //
1488   _dataManagerAct = new QAction(tr("Data Manager"), this);
1489   _dataManagerAct->setIcon(KstGetIcon("data-manager"));
1490   _dataManagerAct->setShortcut(QString("d"));
1491   _dataManagerAct->setStatusTip(tr("Show Kst's data manager window (%1)").arg(_dataManagerAct->shortcut().toString()));
1492   _dataManagerAct->setToolTip(tr("Show Data Manager (%1)").arg(_dataManagerAct->shortcut().toString()));
1493   connect(_dataManagerAct, SIGNAL(triggered()), this, SLOT(showDataManager()));
1494 
1495   _dataWizardAct = new QAction(tr("&Data Wizard"), this);
1496   _dataWizardAct->setIcon(KstGetIcon("tools-wizard"));
1497   _dataWizardAct->setShortcut(QString("w"));
1498   _dataWizardAct->setStatusTip(tr("Show Kst's Data Wizard (%1)").arg(_dataWizardAct->shortcut().toString()));
1499   _dataWizardAct->setToolTip(tr("Show Data Wizard (%1)").arg(_dataWizardAct->shortcut().toString()));
1500   connect(_dataWizardAct, SIGNAL(triggered()), this, SLOT(showDataWizard()));
1501 
1502   _changeFileDialogAct = new QAction(tr("Change Data &File"), this);
1503   _changeFileDialogAct->setIcon(KstGetIcon("change-data-file"));
1504   _changeFileDialogAct->setStatusTip(tr("Show Kst's Change Data File Dialog (%1)").arg(_changeFileDialogAct->shortcut().toString()));
1505   _changeFileDialogAct->setShortcut(QString("f"));
1506   _changeFileDialogAct->setToolTip(tr("Show Change Data File Dialog (%1)").arg(_changeFileDialogAct->shortcut().toString()));
1507   connect(_changeFileDialogAct, SIGNAL(triggered()), this, SLOT(showChangeFileDialog()));
1508 
1509   _chooseColorDialogAct = new QAction(tr("Assign Curve &Color per File"), this);
1510   _chooseColorDialogAct->setStatusTip(tr("Show Kst's Choose Color Dialog"));
1511   _chooseColorDialogAct->setIcon(KstGetIcon("code-class"));
1512   connect(_chooseColorDialogAct, SIGNAL(triggered()), this, SLOT(showChooseColorDialog()));
1513 
1514   _differentiateCurvesDialogAct = new QAction(tr("D&ifferentiate Curves"), this);
1515   _differentiateCurvesDialogAct->setStatusTip(tr("Show Kst's Differentiate Curves Dialog"));
1516   _differentiateCurvesDialogAct->setIcon(KstGetIcon("kst_differentiatecurves"));
1517   connect(_differentiateCurvesDialogAct, SIGNAL(triggered()), this, SLOT(showDifferentiateCurvesDialog()));
1518 
1519   _filterMultipleDialogAct = new QAction(tr("&Filter Vectors"), this);
1520   _filterMultipleDialogAct->setStatusTip(tr("Filter multiple vectors"));
1521   _filterMultipleDialogAct->setIcon(KstGetIcon("kst_filter_vectors"));
1522   connect(_filterMultipleDialogAct, SIGNAL(triggered()), this, SLOT(filterMultipleDialog()));
1523 
1524   // *********************** Settings actions ************************************** //
1525   _settingsDialogAct = new QAction(tr("&Configure Kst"), this);
1526   _settingsDialogAct->setStatusTip(tr("Show Kst's Configuration Dialog"));
1527   _settingsDialogAct->setIcon(KstGetIcon("configure"));
1528   connect(_settingsDialogAct, SIGNAL(triggered()), this, SLOT(showSettingsDialog()));
1529 
1530   _themeDialogAct = new QAction(tr("&Theme"), this);
1531   _themeDialogAct->setStatusTip(tr("Show Kst's Theme Dialog"));
1532   _themeDialogAct->setIcon(KstGetIcon("themes"));
1533   connect(_themeDialogAct, SIGNAL(triggered()), this, SLOT(showThemeDialog()));
1534 
1535   _clearUISettings =  new QAction(tr("Clear settings and defaults"), this);
1536   _clearUISettings->setStatusTip(tr("Clear sticky defaults and all settings in all dialogs."));
1537   //_clearUISettings->setIcon(KstGetIcon("configure"));  // FIXME: pick an icon (broom?)
1538   connect(_clearUISettings, SIGNAL(triggered()), this, SLOT(clearDefaults()));
1539 
1540   _clearDataSourceSettings =  new QAction(tr("Clear datasource settings"), this);
1541   _clearDataSourceSettings->setStatusTip(tr("Clear datasource settings"));
1542   //_clearDataSourceSettings->setIcon(KstGetIcon("configure"));   // FIXME: pick an icon (broom?)
1543   connect(_clearDataSourceSettings, SIGNAL(triggered()), this, SLOT(clearDataSourceSettings()));
1544 
1545   _toggleStatusBar =  new QAction(tr("Show status bar"), this);
1546   _toggleStatusBar->setCheckable(true);
1547   _toggleStatusBar->setChecked(_settings.value("showstatusbar", true).toBool());
1548   connect(_toggleStatusBar, SIGNAL(triggered()), this, SLOT(toggleStatusBar()));
1549 
1550   // *********************** Help actions ************************************** //
1551   _debugDialogAct = new QAction(tr("&Debug Dialog"), this);
1552   _debugDialogAct->setStatusTip(tr("Show the Kst debugging dialog"));
1553   _debugDialogAct->setIcon(KstGetIcon("text-x-log"));
1554   connect(_debugDialogAct, SIGNAL(triggered()), this, SLOT(showDebugDialog()));
1555 
1556   _bugReportWizardAct = new QAction(tr("&Bug Report Wizard"), this);
1557   _bugReportWizardAct->setStatusTip(tr("Show Kst's Bug Report Wizard"));
1558   _bugReportWizardAct->setIcon(KstGetIcon("kbugbuster"));
1559   connect(_bugReportWizardAct, SIGNAL(triggered()), this, SLOT(showBugReportWizard()));
1560 
1561   _aboutAct = new QAction(tr("&About"), this);
1562   _aboutAct->setStatusTip(tr("Show Kst's About box"));
1563   _aboutAct->setIcon(KstGetIcon("dialog-information"));
1564   connect(_aboutAct, SIGNAL(triggered()), this, SLOT(about()));
1565 
1566   _showShortcutAct = new QAction(tr("Keyboard Shortcuts"), this);
1567   _showShortcutAct->setStatusTip(tr("Show a list of keyboard shortcuts"));
1568   connect(_showShortcutAct, SIGNAL(triggered()), this, SLOT(showShortcutDialog()));
1569 
1570   _video1Act = new QAction(tr("#&1: Quick Start"), this);
1571   _video1Act->setStatusTip(tr("Kst presentation #1: The shortest tutorial to the fastest plotting tool"));
1572   connect(_video1Act, SIGNAL(triggered()), _videoMapper, SLOT(map()));
1573   _videoMapper->setMapping(_video1Act, 1);
1574   _video2Act = new QAction(tr("#&2: General UI Presentation"), this);
1575   _video2Act->setStatusTip(tr("Kst presentation #2: General presentation of the user interface and most important concepts"));
1576   connect(_video2Act, SIGNAL(triggered()), _videoMapper, SLOT(map()));
1577   _videoMapper->setMapping(_video2Act, 2);
1578   _video3Act = new QAction(tr("#&3: Live Data / Range Tools"), this);
1579   _video3Act->setStatusTip(tr("Kst presentation #3: Range tools and live plots with streaming data"));
1580   connect(_video3Act, SIGNAL(triggered()), _videoMapper, SLOT(map()));
1581   _videoMapper->setMapping(_video3Act, 3);
1582   _video4Act = new QAction(tr("#&4: FFT, Equations, Fits, Filters"), this);
1583   _video4Act->setStatusTip(tr("Kst presentation #4: FFTs, equations, filters, fits, plugins"));
1584   connect(_video4Act, SIGNAL(triggered()), _videoMapper, SLOT(map()));
1585   _videoMapper->setMapping(_video4Act, 4);
1586   _video5Act = new QAction(tr("#&5: Productivity Features"), this);
1587   _video5Act->setStatusTip(tr("Kst presentation #5: Unique productivity features like edit multiple mode and change data file tool"));
1588   connect(_video5Act, SIGNAL(triggered()), _videoMapper, SLOT(map()));
1589   _videoMapper->setMapping(_video5Act, 5);
1590   _video6Act = new QAction(tr("#&6: Advanced Layout / Export"), this);
1591   _video6Act->setStatusTip(tr("Kst presentation #6: Advanced layout and export options"));
1592   connect(_video6Act, SIGNAL(triggered()), _videoMapper, SLOT(map()));
1593   _videoMapper->setMapping(_video6Act, 6);
1594   _video7Act = new QAction(tr("#&7: Matrices / Images / Metadata"), this);
1595   _video7Act->setStatusTip(tr("Kst presentation #7: Matrices, images and metadata"));
1596   connect(_video7Act, SIGNAL(triggered()), _videoMapper, SLOT(map()));
1597   _videoMapper->setMapping(_video7Act, 7);
1598   connect(_videoMapper, SIGNAL(mapped(int)), this, SLOT(videoTutorial(int)));
1599 }
1600 
1601 
1602 void MainWindow::createMenus() {
1603   _fileMenu = menuBar()->addMenu(tr("&File"));
1604   // Session operations
1605   _fileMenu->addAction(_openAct);
1606   _fileMenu->addAction(_saveAct);
1607   _fileMenu->addAction(_saveAsAct);
1608   _fileMenu->addAction(_closeAct);
1609   _fileMenu->addSeparator();
1610   _recentKstFilesMenu = _fileMenu->addMenu(tr("&Recent Sessions"));
1611   _recentDataFilesMenu = _fileMenu->addMenu(tr("Recent Data &Files"));
1612   _fileMenu->addSeparator();
1613   // Reload, isolate it a bit from the other entries to avoid inadvertent triggering
1614   _fileMenu->addAction(_reloadAct);
1615   _fileMenu->addSeparator();
1616   // Print/export
1617   _fileMenu->addAction(_printAct);
1618   _fileMenu->addAction(_exportGraphicsAct);
1619   _fileMenu->addAction(_exportVectorsAct);
1620   _fileMenu->addAction(_logAct);
1621   _fileMenu->addSeparator();
1622   // Tabs
1623   _fileMenu->addAction(_newTabAct);
1624   _fileMenu->addAction(_closeTabAct);
1625   _fileMenu->addSeparator();
1626   // exit
1627   _fileMenu->addAction(_exitAct);
1628   // recent files
1629   _fileMenu->addSeparator();
1630   updateRecentKstFiles();
1631 
1632 
1633   _editMenu = menuBar()->addMenu(tr("&Edit"));
1634   _editMenu->addAction(_undoAct);
1635   _editMenu->addAction(_redoAct);
1636   _editMenu->addAction(_copyTabAct);
1637   // Cut/Copy/Paste will come here
1638 
1639   _viewMenu = menuBar()->addMenu(tr("&View"));
1640   _viewMenu->addAction(_vectorEditorAct);
1641   _viewMenu->addAction(_scalarEditorAct);
1642   _viewMenu->addAction(_matrixEditorAct);
1643   _viewMenu->addAction(_stringEditorAct);
1644 
1645   _rangeMenu = menuBar()->addMenu(tr("&Range"));
1646   _rangeMenu->addAction(_backAct);
1647   _rangeMenu->addAction(_backSmallAct);  
1648   _rangeMenu->addAction(_forwardAct);
1649   _rangeMenu->addAction(_forwardSmallAct);
1650   _rangeMenu->addSeparator();
1651   _rangeMenu->addAction(_readFromEndAct);
1652   _rangeMenu->addAction(_readToEndAct);
1653   _rangeMenu->addAction(_pauseAct);
1654   _rangeMenu->addSeparator();
1655   _rangeMenu->addAction(_changeDataSampleDialogAct);
1656 
1657   _createMenu = menuBar()->addMenu(tr("&Create"));
1658   // Containers
1659   _createMenu->addAction(_insertPlotAct);
1660   //_createMenu->addAction(_createPlotAct);
1661   _createMenu->addAction(_createSharedAxisBoxAct);
1662   _createMenu->addSeparator();
1663   // Primitives
1664   _createMenu->addAction(_newScalarAct);
1665   _createMenu->addAction(_newVectorAct);
1666   _createMenu->addAction(_newMatrixAct);
1667   _createMenu->addAction(_newStringAct);
1668   _createMenu->addSeparator();
1669   // Data objects
1670   _createMenu->addAction(_newEquationAct);
1671   _createMenu->addAction(_newHistogramAct);
1672   _createMenu->addAction(_newPSDAct);
1673   _createMenu->addAction(_newSpectrogramAct);
1674   _createMenu->addAction(_newEventMonitorAct);
1675   _createMenu->addSeparator();
1676 
1677   // Now, create the dynamic plugin menus
1678   QMenu* _pluginsMenu = _createMenu->addMenu(tr("Standard P&lugin"));
1679   QMenu* _fitPluginsMenu = _createMenu->addMenu(tr("Fit Pl&ugin"));
1680   QMenu* _filterPluginsMenu = _createMenu->addMenu(tr("Fil&ter Plugin"));
1681   PluginMenuItemAction* action;
1682   foreach (const QString &pluginName, DataObject::dataObjectPluginList()) {
1683     action = new PluginMenuItemAction(pluginName, this);
1684     connect(action, SIGNAL(triggered(QString&)), this, SLOT(showPluginDialog(QString&)));
1685     _pluginsMenu->addAction(action);
1686   }
1687   foreach (const QString &pluginName, DataObject::fitsPluginList()) {
1688     action = new PluginMenuItemAction(pluginName, this);
1689     connect(action, SIGNAL(triggered(QString&)), this, SLOT(showPluginDialog(QString&)));
1690     _fitPluginsMenu->addAction(action);
1691   }
1692   foreach (const QString &pluginName, DataObject::filterPluginList()) {
1693     action = new PluginMenuItemAction(pluginName, this);
1694     connect(action, SIGNAL(triggered(QString&)), this, SLOT(showPluginDialog(QString&)));
1695     _filterPluginsMenu->addAction(action);
1696   }
1697   _createMenu->addSeparator();
1698   // Relations
1699   _createMenu->addAction(_newCurveAct);
1700   _createMenu->addAction(_newImageAct);
1701   _createMenu->addSeparator();
1702   // Annotation objects
1703   QMenu* annotations = _createMenu->addMenu(tr("&Annotation"));
1704   annotations->addAction(_createLabelAct);
1705   annotations->addAction(_createBoxAct);
1706   annotations->addAction(_createCircleAct);
1707   annotations->addAction(_createEllipseAct);
1708   annotations->addAction(_createLineAct);
1709   annotations->addAction(_createArrowAct);
1710   annotations->addAction(_createPictureAct);
1711 #ifndef KST_NO_SVG
1712   annotations->addAction(_createSvgAct);
1713 #endif
1714 
1715   _modeMenu = menuBar()->addMenu(tr("&Mode"));
1716   // Interaction mode
1717   _modeMenu->addSeparator()->setText(tr("Interaction mode"));
1718   _modeMenu->addAction(_standardZoomAct);
1719   _modeMenu->addAction(_xOnlyZoomAct);
1720   _modeMenu->addAction(_yOnlyZoomAct);
1721   _modeMenu->addAction(_layoutModeAct);
1722   _standardZoomAct->setChecked(true);
1723   _modeMenu->addSeparator();
1724   // Tied zoom options
1725   _modeMenu->addAction(_tiedZoomAct);
1726   _modeMenu->addAction(_tabTiedAct);
1727   _modeMenu->addSeparator();
1728   // Data mode
1729   _modeMenu->addAction(_highlightPointAct);
1730 
1731   _toolsMenu = menuBar()->addMenu(tr("&Tools"));
1732   _toolsMenu->addAction(_dataManagerAct);
1733   _toolsMenu->addAction(_dataWizardAct);
1734   _toolsMenu->addAction(_changeFileDialogAct);
1735   _toolsMenu->addAction(_chooseColorDialogAct);
1736   _toolsMenu->addAction(_differentiateCurvesDialogAct);
1737   _toolsMenu->addAction(_filterMultipleDialogAct);
1738   _toolsMenu->addSeparator();
1739   updateRecentDataFiles();
1740 
1741   _settingsMenu = menuBar()->addMenu(tr("&Settings"));
1742   _settingsMenu->addAction(_settingsDialogAct);
1743   _settingsMenu->addAction(_themeDialogAct);
1744   _settingsMenu->addAction(_clearUISettings);
1745   _settingsMenu->addAction(_clearDataSourceSettings);
1746   _settingsMenu->addAction(_toggleStatusBar);
1747 
1748   menuBar()->addSeparator();
1749 
1750   _helpMenu = menuBar()->addMenu(tr("&Help"));
1751   QMenu* _videoTutorialsMenu = _helpMenu->addMenu(tr("&Video tutorials"));
1752   _videoTutorialsMenu->addAction(_video1Act);
1753   _videoTutorialsMenu->addAction(_video2Act);
1754   _videoTutorialsMenu->addAction(_video3Act);
1755   _videoTutorialsMenu->addAction(_video4Act);
1756   _videoTutorialsMenu->addAction(_video5Act);
1757   _videoTutorialsMenu->addAction(_video6Act);
1758   _videoTutorialsMenu->addAction(_video7Act);
1759   _helpMenu->addSeparator();
1760   _helpMenu->addAction(_debugDialogAct);
1761   _helpMenu->addAction(_bugReportWizardAct);
1762   _helpMenu->addSeparator();
1763   _helpMenu->addAction(_showShortcutAct);
1764   _helpMenu->addAction(_aboutAct);
1765 
1766 }
1767 
1768 
1769 void MainWindow::createToolBars() {
1770   setToolButtonStyle(Qt::ToolButtonIconOnly);
1771 
1772   _fileToolBar = addToolBar(tr("File"));
1773   _fileToolBar->setObjectName("File Toolbar");
1774   _fileToolBar->addAction(_openAct);
1775   _fileToolBar->addAction(_saveAct);
1776   _fileToolBar->addAction(_reloadAct);
1777   _fileToolBar->addAction(_printAct);
1778   _fileToolBar->addAction(_logAct);
1779 
1780   _editToolBar = addToolBar(tr("Edit"));
1781   _editToolBar->setObjectName("Edit Toolbar");
1782   _editToolBar->addAction(_undoAct);
1783   _editToolBar->addAction(_redoAct);
1784   _editToolBar->addAction(_copyTabAct);
1785 
1786   _toolsToolBar = addToolBar(tr("Tools"));
1787   _toolsToolBar->setObjectName("Tools Toolbar");
1788   _toolsToolBar->addAction(_dataManagerAct);
1789   _toolsToolBar->addAction(_dataWizardAct);
1790   _toolsToolBar->addAction(_changeDataSampleDialogAct);
1791   _toolsToolBar->addAction(_changeFileDialogAct);
1792 
1793   _rangeToolBar = addToolBar(tr("Data Range"));
1794   _rangeToolBar->setObjectName("Data Range Toolbar");
1795   _rangeToolBar->addAction(_backAct);
1796   _rangeToolBar->addAction(_forwardAct);
1797   _rangeToolBar->addAction(_readFromEndAct);
1798   _rangeToolBar->addAction(_readToEndAct);
1799   _rangeToolBar->addAction(_pauseAct);
1800 
1801   _modeToolBar = addToolBar(tr("Mode"));
1802   _modeToolBar->setObjectName("Mode Toolbar");
1803   _modeToolBar->addAction(_tiedZoomAct);
1804   _modeToolBar->addAction(_highlightPointAct);
1805   _modeToolBar->addSeparator();
1806   _modeToolBar->addAction(_standardZoomAct);
1807   _modeToolBar->addAction(_xOnlyZoomAct);
1808   _modeToolBar->addAction(_yOnlyZoomAct);
1809   _modeToolBar->addAction(_layoutModeAct);
1810 
1811   _plotLayoutToolBar = addToolBar(tr("Plot Layout"));
1812   _plotLayoutToolBar->setObjectName("Plot Layout Toolbar");
1813   _plotLayoutToolBar->addAction(_createSharedAxisBoxAct);
1814   _plotLayoutToolBar->addAction(_insertPlotAct);
1815   //_plotLayoutToolBar->addAction(_createPlotAct);
1816 
1817   _annotationToolBar = addToolBar(tr("Advanced Layout"));
1818   _annotationToolBar->setObjectName("Advanced Layout Toolbar");
1819   _annotationToolBar->addAction(_createLabelAct);
1820   _annotationToolBar->addAction(_createBoxAct);
1821   _annotationToolBar->addAction(_createCircleAct);
1822   _annotationToolBar->addAction(_createEllipseAct);
1823   _annotationToolBar->addAction(_createLineAct);
1824   _annotationToolBar->addAction(_createArrowAct);
1825   _annotationToolBar->addAction(_createPictureAct);
1826 #ifndef KST_NO_SVG
1827   _annotationToolBar->addAction(_createSvgAct);
1828 #endif
1829 }
1830 
1831 
1832 void MainWindow::createStatusBar() {
1833   _messageLabel = new QLabel(statusBar());
1834   setStatusMessage(tr("Ready"), 3000);
1835 
1836   _progressBar = new QProgressBar(statusBar());
1837   _progressBar->setFixedWidth(200);
1838   _progressBar->hide();
1839   statusBar()->addPermanentWidget(_progressBar);
1840   MemoryWidget *mw = new MemoryWidget(statusBar());
1841   statusBar()->addPermanentWidget(mw);
1842   DebugNotifier *dn = new DebugNotifier(statusBar());
1843   connect(dn, SIGNAL(showDebugLog()), this, SLOT(showDebugDialog()));
1844   connect(_debugDialog, SIGNAL(notifyOfError()), dn, SLOT(reanimate()));
1845   connect(_debugDialog, SIGNAL(notifyAllClear()), dn, SLOT(close()));
1846   statusBar()->addPermanentWidget(dn);
1847 
1848   bool statusBarVisible = _settings.value("showstatusbar", true).toBool();
1849   statusBar()->setVisible( statusBarVisible );
1850 
1851 }
1852 
1853 /** set the status bar message.  If you are doing this inside a view
1854  * object paint() call, then set delayed to true, and call ::updateStatusMessage()
1855  * later (after leaving paint). This is currently done for you in updateViewItems */
1856 void MainWindow::setStatusMessage(QString message, int timeout, bool delayed) {
1857   _statusBarMessage = message;
1858   _statusBarTimeout = timeout;
1859   if (!delayed) {
1860     statusBar()->showMessage(message, timeout);
1861   }
1862 }
1863 
1864 void MainWindow::videoTutorial(int i) {
1865   switch (i) {
1866   case 1:
1867     QDesktopServices::openUrl(QUrl("http://www.youtube.com/watch?v=d1uz5g_cWh4")); break;
1868   case 2:
1869     QDesktopServices::openUrl(QUrl("http://www.youtube.com/watch?v=6z2bGNrgwL0")); break;
1870   case 3:
1871     QDesktopServices::openUrl(QUrl("http://www.youtube.com/watch?v=dstOQpmfY1U")); break;
1872   case 4:
1873     QDesktopServices::openUrl(QUrl("http://www.youtube.com/watch?v=YJ54X0nKnmk")); break;
1874   case 5:
1875     QDesktopServices::openUrl(QUrl("http://www.youtube.com/watch?v=3YZVC-GiS_4")); break;
1876   case 6:
1877     QDesktopServices::openUrl(QUrl("http://www.youtube.com/watch?v=rI7nYHlz6rs")); break;
1878   case 7:
1879     QDesktopServices::openUrl(QUrl("http://www.youtube.com/watch?v=mgP24MryyKw")); break;
1880   default:
1881     break;
1882   }
1883 }
1884 
1885 QString MainWindow::statusMessage() {
1886   return statusBar()->currentMessage();
1887 }
1888 
1889 void MainWindow::updateStatusMessage() {
1890   statusBar()->showMessage(_statusBarMessage, _statusBarTimeout);
1891 }
1892 
1893 QProgressBar *MainWindow::progressBar() const {
1894   return _progressBar;
1895 }
1896 
1897 void MainWindow::updateProgress(int percent, const QString& message)
1898 {
1899   if (percent == -1) {
1900     _progressBar->setMaximum(0);
1901     _progressBar->setMinimum(0);
1902     _progressBar->show();
1903     return;
1904   }
1905 
1906   if (percent  > 0 && percent < 100) {
1907     _progressBar->setMaximum(100);
1908     _progressBar->setValue(percent);
1909     _progressBar->show();
1910   } else {
1911     _progressBar->hide();
1912   }
1913   setStatusMessage(message);
1914 }
1915 
1916 void MainWindow::readFromEnd() {
1917   int nf = 0;
1918   int skip;
1919   bool do_skip;
1920   bool do_filter;
1921 
1922   DataVectorList dataVectors = document()->objectStore()->getObjects<DataVector>();
1923 
1924   foreach (DataVectorPtr v, dataVectors) {
1925     v->readLock();
1926     nf = v->reqNumFrames();
1927     if (nf <=0 ) {
1928       nf = v->numFrames();
1929     }
1930     skip = v->skip();
1931     do_skip = v->doSkip();
1932     do_filter = v->doAve();
1933     v->unlock();
1934 
1935     v->writeLock();
1936     v->changeFrames(-1, nf, skip, do_skip, do_filter);
1937     v->registerChange();
1938     v->unlock();
1939   }
1940 
1941   VScalarList vScalars = document()->objectStore()->getObjects<VScalar>();
1942   foreach (VScalarPtr s, vScalars) {
1943     s->readLock();
1944     s->changeFrame(-1);
1945     s->registerChange();
1946     s->unlock();
1947   }
1948 
1949   DataStringList dataStrings = document()->objectStore()->getObjects<DataString>();
1950   foreach (DataStringPtr s, dataStrings) {
1951     if (s->isStream()) {
1952       s->readLock();
1953       s->setFrame(-1);
1954       s->registerChange();
1955       s->unlock();
1956     }
1957   }
1958 
1959   DataMatrixList dataMatrices = document()->objectStore()->getObjects<DataMatrix>();
1960   foreach (DataMatrixPtr m, dataMatrices) {
1961     m->readLock();
1962     m->setFrame(-1);
1963     m->registerChange();
1964     m->unlock();
1965   }
1966 
1967   UpdateManager::self()->doUpdates(true);
1968   dialogDefaults().setValue("vector/range", nf);
1969   dialogDefaults().setValue("vector/countFromEnd", true);
1970   dialogDefaults().setValue("vector/readToEnd", false);
1971 }
1972 
1973 void MainWindow::readToEnd() {
1974   int f0 = 0;
1975   int skip;
1976   bool do_skip;
1977   bool do_filter;
1978 
1979   DataVectorList dataVectors = document()->objectStore()->getObjects<DataVector>();
1980 
1981   foreach (DataVectorPtr v, dataVectors) {
1982     v->readLock();
1983     f0 = v->startFrame();
1984     skip = v->skip();
1985     do_skip = v->doSkip();
1986     do_filter = v->doAve();
1987     v->unlock();
1988 
1989     v->writeLock();
1990     v->changeFrames(f0, -1, skip, do_skip, do_filter);
1991     v->registerChange();
1992     v->unlock();
1993   }
1994 
1995   VScalarList vScalars = document()->objectStore()->getObjects<VScalar>();
1996   foreach (VScalarPtr s, vScalars) {
1997     s->readLock();
1998     s->changeFrame(-1);
1999     s->registerChange();
2000     s->unlock();
2001   }
2002 
2003   DataStringList dataStrings = document()->objectStore()->getObjects<DataString>();
2004   foreach (DataStringPtr s, dataStrings) {
2005     if (s->isStream()) {
2006       s->readLock();
2007       s->setFrame(-1);
2008       s->registerChange();
2009       s->unlock();
2010     }
2011   }
2012 
2013   DataMatrixList dataMatrices = document()->objectStore()->getObjects<DataMatrix>();
2014   foreach (DataMatrixPtr m, dataMatrices) {
2015     m->readLock();
2016     m->setFrame(-1);
2017     m->registerChange();
2018     m->unlock();
2019   }
2020 
2021   dialogDefaults().setValue("vector/start", f0);
2022   dialogDefaults().setValue("vector/countFromEnd", false);
2023   dialogDefaults().setValue("vector/readToEnd", true);
2024   UpdateManager::self()->doUpdates(true);
2025 }
2026 
2027 void MainWindow::pause(bool pause) {
2028   UpdateManager::self()->setPaused(pause);
2029 
2030   //if (!pause) {
2031      //foreach (DataSourcePtr s, document()->objectStore()->dataSourceList()) {
2032        //s->checkUpdate();
2033      //}
2034   //}
2035 }
2036 
2037 void MainWindow::forward(double scale) {
2038   int f0 = 0;
2039   int nf = 0;
2040   int lastF = -1;
2041   int skip;
2042   int filelength;
2043   bool count_from_end;
2044   bool read_to_end;
2045   bool do_skip;
2046   bool do_filter;
2047 
2048   DataVectorList dataVectors = document()->objectStore()->getObjects<DataVector>();
2049   DataMatrixList dataMatrices = document()->objectStore()->getObjects<DataMatrix>();
2050   VScalarList vScalars = document()->objectStore()->getObjects<VScalar>();
2051   DataStringList dataStrings = document()->objectStore()->getObjects<DataString>();
2052   QHash<int,int> lastframehash;
2053 
2054   foreach (DataVectorPtr v, dataVectors) {
2055     v->readLock();
2056     f0 = v->startFrame();
2057     nf = v->numFrames();
2058     count_from_end = v->countFromEOF();
2059     read_to_end = v->readToEOF();
2060     filelength = v->fileLength();
2061 
2062     skip = v->skip();
2063     do_skip = v->doSkip();
2064     do_filter = v->doAve();
2065     v->unlock();
2066 
2067     if ((!count_from_end) && (!read_to_end)) {
2068       f0 += ceil(scale*nf);
2069       if (f0+nf>=filelength) {
2070         f0 = filelength - nf;
2071       }
2072       lastF = f0 + nf - 1;
2073       ++lastframehash[lastF];
2074 
2075       v->writeLock();
2076       v->changeFrames(f0, nf, skip, do_skip, do_filter);
2077       v->registerChange();
2078       v->unlock();
2079     }
2080   }
2081 
2082   int most_popular_lastF = -1;
2083   int n_most_popular_lastF = -1;
2084   foreach (int key, lastframehash.keys()) {
2085     int n = lastframehash[key] ;
2086     if (n > n_most_popular_lastF) {
2087       n_most_popular_lastF = n;
2088       most_popular_lastF = key;
2089     }
2090   }
2091 
2092   foreach (VScalarPtr vs, vScalars) {
2093     int  new_frame;
2094     int filelength = vs->fileLength();
2095     if (most_popular_lastF>=0) {
2096       if (most_popular_lastF < filelength) {
2097         new_frame = most_popular_lastF;
2098       } else {
2099         new_frame = filelength-1;
2100       }
2101     } else {
2102       if (vs->F0() < 0) {
2103         new_frame = -1;
2104       } else if (vs->F0()+1 <= filelength) {
2105         new_frame = vs->F0()+1;
2106       } else {
2107         new_frame = filelength-1;
2108       }
2109     }
2110     vs->writeLock();
2111     vs->changeFrame(new_frame);
2112     vs->registerChange();
2113     vs->unlock();
2114   }
2115 
2116   foreach (DataStringPtr s, dataStrings) {
2117     if (s->isStream()) {
2118       int  new_frame;
2119       int filelength = s->fileLength();
2120       if (most_popular_lastF>=0) {
2121         if (most_popular_lastF < filelength) {
2122           new_frame = most_popular_lastF;
2123         } else {
2124           new_frame = filelength-1;
2125         }
2126       } else {
2127         if (s->frame() < 0) {
2128           new_frame = -1;
2129         } else if (s->frame()+1 < filelength) {
2130           new_frame = s->frame()+1;
2131         } else {
2132           new_frame = filelength-1;
2133         }
2134       }
2135       s->writeLock();
2136       s->setFrame(new_frame);
2137       s->registerChange();
2138       s->unlock();
2139     }
2140   }
2141 
2142 
2143   foreach (DataMatrixPtr m, dataMatrices) {
2144     if (m->isStream()) {
2145       int  new_frame;
2146       int filelength = m->fileLength();
2147       if (most_popular_lastF>=0) {
2148         if (most_popular_lastF < filelength) {
2149           new_frame = most_popular_lastF;
2150         } else {
2151           new_frame = filelength-1;
2152         }
2153       } else {
2154         if (m->frame() < 0) {
2155           new_frame = -1;
2156         } else if (m->frame()+1 < filelength) {
2157           new_frame = m->frame()+1;
2158         } else {
2159           new_frame = filelength-1;
2160         }
2161       }
2162       m->writeLock();
2163       m->setFrame(new_frame);
2164       m->registerChange();
2165       m->unlock();
2166     }
2167   }
2168 
2169   dialogDefaults().setValue("vector/range", nf);
2170   dialogDefaults().setValue("vector/start", f0);
2171   dialogDefaults().setValue("vector/countFromEnd", false);
2172   dialogDefaults().setValue("vector/readToEnd", false);
2173 
2174   UpdateManager::self()->doUpdates(true);
2175 }
2176 
2177 void MainWindow::back(double scale) {
2178   int f0 = 0;
2179   int nf = 0;
2180   int skip;
2181   int filelength;
2182   bool count_from_end;
2183   bool read_to_end;
2184   bool do_skip;
2185   bool do_filter;
2186   int lastF = -1;
2187 
2188   DataVectorList dataVectors = document()->objectStore()->getObjects<DataVector>();
2189   DataMatrixList dataMatrices = document()->objectStore()->getObjects<DataMatrix>();
2190   VScalarList vScalars = document()->objectStore()->getObjects<VScalar>();
2191   DataStringList dataStrings = document()->objectStore()->getObjects<DataString>();
2192 
2193   QHash<int,int> lastframehash;
2194 
2195   foreach (DataVectorPtr v, dataVectors) {
2196     v->readLock();
2197     f0 = v->startFrame();
2198     nf = v->numFrames();
2199     count_from_end = v->countFromEOF();
2200     read_to_end = v->readToEOF();
2201     filelength = v->fileLength();
2202 
2203     skip = v->skip();
2204     do_skip = v->doSkip();
2205     do_filter = v->doAve();
2206     v->unlock();
2207 
2208     if (f0 != 0) {
2209       if (count_from_end) {
2210         f0 = filelength - nf;
2211       }
2212       if (read_to_end) {
2213         nf = filelength - f0;
2214       }
2215 
2216       f0 -= ceil(scale*nf);
2217       if (f0<0) {
2218         f0 = 0;
2219       }
2220       lastF = f0 + nf - 1;
2221       ++lastframehash[lastF];
2222 
2223       v->writeLock();
2224       v->changeFrames(f0, nf, skip, do_skip, do_filter);
2225       v->registerChange();
2226       v->unlock();
2227     }
2228   }
2229 
2230   int most_popular_lastF = -1;
2231   int n_most_popular_lastF = -1;
2232   foreach (int key, lastframehash.keys()) {
2233     int n = lastframehash[key] ;
2234     if (n > n_most_popular_lastF) {
2235       n_most_popular_lastF = n;
2236       most_popular_lastF = key;
2237     }
2238   }
2239 
2240   foreach (VScalarPtr vs, vScalars) {
2241     int  new_frame;
2242     int filelength = vs->fileLength();
2243     if (most_popular_lastF>=0) {
2244       if (most_popular_lastF < filelength) {
2245         new_frame = most_popular_lastF;
2246       } else {
2247         new_frame = filelength-1;
2248       }
2249     } else {
2250       if (vs->F0() < 0) {
2251         new_frame = filelength-1;
2252       } else if (vs->F0()-1 >= 0) {
2253         new_frame = vs->F0()-1;
2254       } else {
2255         new_frame = 0;
2256       }
2257     }
2258     vs->writeLock();
2259     vs->changeFrame(new_frame);
2260     vs->registerChange();
2261     vs->unlock();
2262   }
2263 
2264   foreach (DataStringPtr s, dataStrings) {
2265     if (s->isStream()) {
2266       int  new_frame;
2267       int filelength = s->fileLength();
2268       if (most_popular_lastF>=0) {
2269         if (most_popular_lastF < filelength) {
2270           new_frame = most_popular_lastF;
2271         } else {
2272           new_frame = filelength-1;
2273         }
2274       } else {
2275         if (s->frame() < 0) {
2276           new_frame = filelength-1;
2277         } else if (s->frame()-1 >= 0) {
2278           new_frame = s->frame()-1;
2279         } else {
2280           new_frame = 0;
2281         }
2282       }
2283       s->writeLock();
2284       s->setFrame(new_frame);
2285       s->registerChange();
2286       s->unlock();
2287     }
2288   }
2289 
2290   foreach (DataMatrixPtr m, dataMatrices) {
2291     if (m->isStream()) {
2292       int  new_frame;
2293       int filelength = m->fileLength();
2294       if (most_popular_lastF>=0) {
2295         if (most_popular_lastF < filelength) {
2296           new_frame = most_popular_lastF;
2297         } else {
2298           new_frame = filelength-1;
2299         }
2300       } else {
2301         if (m->frame() < 0) {
2302           new_frame = filelength-1;
2303         } else if (m->frame()-1 >= 0) {
2304           new_frame = m->frame()-1;
2305         } else {
2306           new_frame = filelength-2;
2307         }
2308       }
2309       m->writeLock();
2310       m->setFrame(new_frame);
2311       m->registerChange();
2312       m->unlock();
2313     }
2314   }
2315 
2316   dialogDefaults().setValue("vector/range", nf);
2317   dialogDefaults().setValue("vector/start", f0);
2318   dialogDefaults().setValue("vector/countFromEnd", false);
2319   dialogDefaults().setValue("vector/readToEnd", false);
2320   UpdateManager::self()->doUpdates(true);
2321 }
2322 
2323 void MainWindow::reload() {
2324   document()->objectStore()->rebuildDataSourceList();
2325   UpdateManager::self()->doUpdates(true);
2326   //document()->setChanged(true);
2327 }
2328 
2329 void MainWindow::showDataManager() {
2330   if (!_dataManager) {
2331     _dataManager = new DataManager(this, _doc);
2332   }
2333   if (_dataManager->isVisible()) {
2334     _dataManager->raise();
2335     _dataManager->activateWindow();
2336   }
2337   _dataManager->show();
2338 }
2339 
2340 
2341 void Kst::MainWindow::updateViewItems(qint64 serial)
2342 {
2343 
2344   QList<PlotItem *> plots = ViewItem::getItems<PlotItem>();
2345 
2346   bool changed = false;
2347   foreach (PlotItem *plot, plots) {
2348     changed |= plot->handleChangedInputs(serial);
2349   }
2350 
2351   QList<LabelItem*> labels = ViewItem::getItems<LabelItem>();
2352   foreach (LabelItem * label, labels) {
2353     if (label->_labelRc) {
2354       label->inputsChanged(serial);
2355     }
2356   }
2357 
2358 
2359   if (changed) {
2360     _tabWidget->currentView()->update();
2361     if (_viewVectorDialog) {
2362       _viewVectorDialog->update();
2363     }
2364     kstApp->mainWindow()->updateStatusMessage();
2365   }
2366 
2367   QTimer::singleShot(20, UpdateManager::self(), SLOT(viewItemUpdateFinished())); // why 20ms ???
2368 }
2369 
2370 void MainWindow::showVectorEditor() {
2371     if (!_viewVectorDialog) {
2372       _viewVectorDialog = new ViewVectorDialog(this, _doc);
2373     }
2374     if (_viewVectorDialog->isVisible()) {
2375       _viewVectorDialog->raise();
2376       _viewVectorDialog->activateWindow();
2377     }
2378     _viewVectorDialog->show();
2379 }
2380 
2381 
2382 void MainWindow::showScalarEditor() {
2383   ViewPrimitiveDialog *viewScalarDialog = new ViewScalarDialog(this, _doc);
2384   viewScalarDialog->show();
2385 }
2386 
2387 
2388 void MainWindow::showStringEditor() {
2389   ViewPrimitiveDialog *viewStringDialog = new ViewStringDialog(this, _doc);
2390   viewStringDialog->show();
2391 }
2392 
2393 void MainWindow::showMatrixEditor() {
2394   ViewMatrixDialog *viewMatrixDialog = new ViewMatrixDialog(this, _doc);
2395   viewMatrixDialog->show();
2396 }
2397 
2398 
2399 void MainWindow::showDebugDialog() {
2400   if (!_debugDialog) {
2401     _debugDialog = new DebugDialog(this);
2402   }
2403   _debugDialog->setObjectStore(document()->objectStore());
2404   if (_debugDialog->isVisible()) {
2405     _debugDialog->raise();
2406     _debugDialog->activateWindow();
2407   }
2408   _debugDialog->show();
2409 }
2410 
2411 
2412 void MainWindow::showExportGraphicsDialog() {
2413   if (!_exportGraphics) {
2414     _exportGraphics = new ExportGraphicsDialog(this);
2415     connect(_exportGraphics, SIGNAL(exportGraphics(QString,QString,int,int,int,bool,int)),
2416             this, SLOT(exportGraphicsFile(QString,QString,int,int,int,bool,int)));
2417   }
2418   if (_exportGraphics->isVisible()) {
2419     _exportGraphics->raise();
2420     _exportGraphics->activateWindow();
2421   }
2422   _exportGraphics->show();
2423 }
2424 
2425 
2426 void MainWindow::showExportVectorsDialog() {
2427   if (!_exportVectors) {
2428     _exportVectors = new ExportVectorsDialog(this);
2429   }
2430   if (_exportVectors->isVisible()) {
2431     _exportVectors->raise();
2432     _exportVectors->activateWindow();
2433   }
2434   _exportVectors->show();
2435 }
2436 
2437 
2438 void MainWindow::showLogDialog() {
2439   if (!_logDialog) {
2440     _logDialog = new LogDialog(this);
2441     //connect(_logDialog, SIGNAL(exportLog(const QString &, time_t, const QString &, int, int, int, const QString &)),
2442     //        this, SLOT(exportLog(const QString &, time_t, const QString &, int, int, int, const QString &)));
2443   }
2444   if (_logDialog->isVisible()) {
2445     _logDialog->raise();
2446     _logDialog->activateWindow();
2447   }
2448   _logDialog->show();
2449 }
2450 
2451 
2452 void MainWindow::showSettingsDialog() {
2453   if (!_applicationSettingsDialog) {
2454     _applicationSettingsDialog = new ApplicationSettingsDialog(this);
2455   }
2456   if (_applicationSettingsDialog->isVisible()) {
2457     _applicationSettingsDialog->raise();
2458     _applicationSettingsDialog->activateWindow();
2459   }
2460   _applicationSettingsDialog->show();
2461 }
2462 
2463 
2464 void MainWindow::showThemeDialog() {
2465   if (!_themeDialog) {
2466     _themeDialog = new ThemeDialog(this);
2467   }
2468   if (_themeDialog->isVisible()) {
2469     _themeDialog->raise();
2470     _themeDialog->activateWindow();
2471   }
2472 
2473   _themeDialog->reset();
2474   _themeDialog->show();
2475 }
2476 
2477 
2478 void MainWindow::clearDefaults() {
2479 
2480   QMessageBox confirmationBox;
2481   confirmationBox.setText(tr("Clear all settings and defaults?"));
2482   confirmationBox.setInformativeText(tr("You are about to clear all settings defaults in all dialogs in kst.\nThis can not be undone."));
2483   confirmationBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
2484   confirmationBox.setDefaultButton(QMessageBox::Ok);
2485   int confirmed = confirmationBox.exec();
2486 
2487   switch (confirmed) {
2488   case QMessageBox::Ok:
2489     dialogDefaults().clear();
2490     ApplicationSettings::self()->clear();
2491     DataSourcePluginManager::settingsObject().clear();
2492     break;
2493   case QMessageBox::Cancel:
2494   default:
2495     // cancel: do nothing at all.
2496     break;
2497   }
2498 }
2499 
2500 void MainWindow::clearDataSourceSettings() {
2501 
2502   QMessageBox confirmationBox;
2503   confirmationBox.setText(tr("Clear datasource settings?"));
2504   confirmationBox.setInformativeText(tr("You are about to clear all\nconfiguration settings for\nall datasources/file types."));
2505   confirmationBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
2506   confirmationBox.setDefaultButton(QMessageBox::Ok);
2507   int confirmed = confirmationBox.exec();
2508 
2509   switch (confirmed) {
2510   case QMessageBox::Ok:
2511     DataSourcePluginManager::settingsObject().clear();
2512     break;
2513   case QMessageBox::Cancel:
2514   default:
2515     // cancel: do nothing at all.
2516     break;
2517   }
2518 
2519 }
2520 
2521 
2522 void MainWindow::showDifferentiateCurvesDialog() {
2523   if (!_differentiateCurvesDialog) {
2524     _differentiateCurvesDialog = new DifferentiateCurvesDialog(this);
2525   }
2526   if (_differentiateCurvesDialog->isVisible()) {
2527     _differentiateCurvesDialog->raise();
2528     _differentiateCurvesDialog->activateWindow();
2529   }
2530   _differentiateCurvesDialog->show();
2531 }
2532 
2533 
2534 void MainWindow::filterMultipleDialog() {
2535   if (!_filterMultipleDialog) {
2536     _filterMultipleDialog = new FilterMultipleDialog(this);
2537   }
2538   if (_filterMultipleDialog->isVisible()) {
2539     _filterMultipleDialog->raise();
2540     _filterMultipleDialog->activateWindow();
2541   }
2542   _filterMultipleDialog->show();
2543 }
2544 
2545 void MainWindow::toggleStatusBar() {
2546   bool statusBarVisible = _settings.value("showstatusbar", true).toBool();
2547 
2548   statusBarVisible = !statusBarVisible;
2549 
2550   statusBar()->setVisible(statusBarVisible);
2551   _toggleStatusBar->setChecked(statusBarVisible);
2552 
2553   _settings.setValue("showstatusbar",statusBarVisible);
2554 }
2555 
2556 
2557 void MainWindow::showChooseColorDialog() {
2558   if (!_chooseColorDialog) {
2559     _chooseColorDialog = new ChooseColorDialog(this);
2560   }
2561   if (_chooseColorDialog->isVisible()) {
2562     _chooseColorDialog->raise();
2563     _chooseColorDialog->activateWindow();
2564   }
2565   _chooseColorDialog->show();
2566 }
2567 
2568 
2569 void MainWindow::showChangeDataSampleDialog() {
2570   if (!_changeDataSampleDialog) {
2571     _changeDataSampleDialog = new ChangeDataSampleDialog(this);
2572   }
2573   if (_changeDataSampleDialog->isVisible()) {
2574     _changeDataSampleDialog->raise();
2575     _changeDataSampleDialog->activateWindow();
2576   }
2577   _changeDataSampleDialog->show();
2578 }
2579 
2580 
2581 void MainWindow::showDataWizard() {
2582   DataWizard *dataWizard = new DataWizard(this);
2583   connect(dataWizard, SIGNAL(dataSourceLoaded(QString)), this, SLOT(updateRecentDataFiles(QString)));
2584   dataWizard->show();
2585 }
2586 
2587 void MainWindow::showDataWizard(const QString &dataFile) {
2588   DataWizard *dataWizard = new DataWizard(this, dataFile);
2589   dataWizard->show();
2590 }
2591 
2592 
2593 void MainWindow::openRecentDataFile()
2594 {
2595   QAction *action = qobject_cast<QAction *>(sender());
2596   if (action) {
2597     DataWizard *dataWizard = new DataWizard(this, action->data().toString());
2598     connect(dataWizard, SIGNAL(dataSourceLoaded(QString)), this, SLOT(updateRecentDataFiles(QString)));
2599     dataWizard->show();
2600   }
2601 }
2602 
2603 
2604 void MainWindow::showBugReportWizard() {
2605   if (!_bugReportWizard) {
2606     _bugReportWizard = new BugReportWizard(this);
2607   }
2608   if (_bugReportWizard->isVisible()) {
2609     _bugReportWizard->raise();
2610     _bugReportWizard->activateWindow();
2611   }
2612   _bugReportWizard->show();
2613 }
2614 
2615 void MainWindow::showChangeFileDialog() {
2616   if (!_changeFileDialog) {
2617     _changeFileDialog = new ChangeFileDialog(this);
2618   }
2619   if (_changeFileDialog->isVisible()) {
2620     _changeFileDialog->raise();
2621     _changeFileDialog->activateWindow();
2622   }
2623   _changeFileDialog->show();
2624 }
2625 
2626 void MainWindow::showPluginDialog(QString &pluginName) {
2627   DialogLauncher::self()->showBasicPluginDialog(pluginName);
2628 }
2629 
2630 bool MainWindow::isTiedTabs() {
2631   return _tabTiedAct->isChecked();
2632 }
2633 
2634 void MainWindow::readSettings() {
2635 #if defined(__QNX__) || defined(__ANDROID__)
2636   // There is only one size we want on mobile platforms - full screen!
2637   setWindowState(Qt::WindowFullScreen);
2638 #else
2639   QByteArray geo = _settings.value("geometry").toByteArray();
2640   if (!geo.isEmpty()) {
2641       restoreGeometry(geo);
2642   } else {
2643       setGeometry(50, 50, 800, 600);
2644   }
2645 #endif // defined(__QNX__) || defined(__ANDROID__)
2646 
2647   restoreState(_settings.value("toolbarState").toByteArray());
2648   _tabTiedAct->setChecked(_settings.value("tieTabs").toBool());
2649 
2650   // read default curve color and set the color sequence.
2651   int color_offset = dialogDefaults().value("curves/default_color", 0).toInt();
2652   ColorSequence::self().setOffset(color_offset);
2653 }
2654 
2655 
2656 void MainWindow::writeSettings() {
2657   _settings.setValue("geometry", saveGeometry());
2658   _settings.setValue("toolbarState", saveState());
2659   _settings.setValue("tieTabs", _tabTiedAct->isChecked());
2660 }
2661 
2662 void MainWindow::setWidgetFlags(QWidget* widget)
2663 {
2664   if (widget) {
2665     // Make sure the dialog gets maximize and minimize buttons under Windows
2666     widget->QWidget::setWindowFlags((Qt::WindowFlags) Qt::Dialog |     Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint
2667 #if QT_VERSION >= 0x040500
2668         | Qt::WindowCloseButtonHint
2669 #endif
2670 );
2671   }
2672 }
2673 
2674 void MainWindow::dragEnterEvent(QDragEnterEvent *event)
2675 {
2676      if (event->mimeData()->hasUrls()) {
2677        event->acceptProposedAction();
2678      }
2679 }
2680 
2681 
2682 void MainWindow::dropEvent(QDropEvent *event)
2683 {
2684   QString path = event->mimeData()->urls().first().toLocalFile();
2685   if (path.endsWith(QString(".kst"))) {
2686      if (!promptSaveDone()) { // There are things to save => cancel
2687        event->ignore();
2688        return;
2689      }
2690      openFile(path);
2691    }
2692    else {
2693      showDataWizard(path); // This is not destructive: it only add data, no need to ask for confirmation
2694    }
2695    event->accept();
2696 }
2697 
2698 void MainWindow::cleanUpDataSourceList() {
2699   _doc->objectStore()->cleanUpDataSourceList();
2700 }
2701 
2702 #if defined(__QNX__)
2703 bool MainWindow::eventFilter(QObject *obj, QEvent *event) {
2704   if (!qApp->activeWindow()) {
2705     activateWindow();
2706   }
2707   if (event->type() == QEvent::KeyPress) {
2708     QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
2709     if (keyEvent->key()==Qt::Key_Menu) { // i.e., bezel swipe gesture...
2710       qnxToggleToolbarVisibility();
2711     }
2712     return false;
2713   } else if (event->type() == QEvent::MouseButtonPress && obj != menuBar()) {
2714     if (_qnxToolbarsVisible) qnxToggleToolbarVisibility();
2715     update();
2716     return false;
2717   } else if (event->type() == QEvent::WindowActivate) {
2718     update();
2719     return false;
2720   } else {
2721     return QObject::eventFilter(obj, event);
2722   }
2723 }
2724 
2725 void MainWindow::keyPressEvent(QKeyEvent *event) {
2726   if ((event->type() == QEvent::KeyPress && static_cast<QKeyEvent*>(event)->key() == Qt::Key_Menu)) {
2727     qnxToggleToolbarVisibility();
2728   }
2729 }
2730 
2731 void MainWindow::qnxToggleToolbarVisibility() {
2732   if (_qnxLastToolbarEvent.msecsTo(QDateTime::currentDateTime()) < 100) {
2733     return; // HACK
2734   }
2735   _qnxLastToolbarEvent = QDateTime::currentDateTime();
2736   menuBar()->setVisible(!_qnxToolbarsVisible);
2737   statusBar()->setVisible(!_qnxToolbarsVisible);
2738   _fileToolBar->setVisible(!_qnxToolbarsVisible);
2739   _editToolBar->setVisible(!_qnxToolbarsVisible);
2740   _toolsToolBar->setVisible(!_qnxToolbarsVisible);
2741   _rangeToolBar->setVisible(!_qnxToolbarsVisible);
2742   _modeToolBar->setVisible(!_qnxToolbarsVisible);
2743   _plotLayoutToolBar->setVisible(!_qnxToolbarsVisible);
2744   _annotationToolBar->setVisible(!_qnxToolbarsVisible);
2745   _qnxToolbarsVisible = !_qnxToolbarsVisible;
2746 }
2747 #endif
2748 
2749 }
2750 
2751 // vim: ts=2 sw=2 et