Skip to content
Snippets Groups Projects
ApplicationWindow.cpp 560 KiB
Newer Older
/***************************************************************************
        File                 : ApplicationWindow.cpp
        Project              : QtiPlot
--------------------------------------------------------------------
        Copyright            : (C) 2006 by Ion Vasilief,
                               Tilman Hoener zu Siederdissen,
                           Knut Franke
        Email (use @ for *)  : ion_vasilief*yahoo.fr, thzs*gmx.net,
                               knut.franke*gmx.de
        Description          : QtiPlot's main window

 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *  This program is free software; you can redistribute it and/or modify   *
 *  it under the terms of the GNU General Public License as published by   *
 *  the Free Software Foundation; either version 2 of the License, or      *
 *  (at your option) any later version.                                    *
 *                                                                         *
 *  This program is distributed in the hope that it will be useful,        *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
 *  GNU General Public License for more details.                           *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the Free Software           *
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
 *   Boston, MA  02110-1301  USA                                           *
 *                                                                         *
 ***************************************************************************/
#include "globals.h"
#include "ApplicationWindow.h"
#include "pixmaps.h"
#include "CurvesDialog.h"
#include "PlotDialog.h"
#include "AxesDialog.h"
#include "LineDialog.h"
#include "TextDialog.h"
#include "ExportDialog.h"
#include "TableDialog.h"
#include "SetColValuesDialog.h"
#include "ErrDialog.h"
#include "LegendWidget.h"
#include "ArrowMarker.h"
#include "ImageMarker.h"
#include "Graph.h"
#include "Plot.h"
#include "Grid.h"
#include "PlotWizard.h"
#include "PolynomFitDialog.h"
#include "ExpDecayDialog.h"
#include "FunctionDialog.h"
#include "FitDialog.h"
#include "SurfaceDialog.h"
#include "Graph3D.h"
#include "Plot3DDialog.h"
#include "ImageDialog.h"
#include "MultiLayer.h"
#include "LayerDialog.h"
#include "DataSetDialog.h"
#include "IntDialog.h"
#include "ConfigDialog.h"
#include "MatrixDialog.h"
#include "MatrixSizeDialog.h"
#include "MatrixValuesDialog.h"
#include "MatrixModel.h"
#include "MatrixCommand.h"
#include "importOPJ.h"
#include "AssociationsDialog.h"
#include "RenameWindowDialog.h"
#include "QwtErrorPlotCurve.h"
#include "InterpolationDialog.h"
#include "ImportASCIIDialog.h"
#include "ImageExportDialog.h"
#include "SmoothCurveDialog.h"
#include "FilterDialog.h"
#include "FFTDialog.h"
#include "Note.h"
#include "Folder.h"
#include "FindDialog.h"
#include "ScaleDraw.h"
#include "MantidQtAPI/ScaleEngine.h"
#include "ScriptingLangDialog.h"
#include "ScriptingWindow.h"
#include "ScriptFileInterpreter.h"
#include "TableStatistics.h"
#include "Fit.h"
#include "MultiPeakFit.h"
#include "PolynomialFit.h"
#include "SigmoidalFit.h"
#include "LogisticFit.h"
#include "NonLinearFit.h"
#include "FunctionCurve.h"
#include "QwtPieCurve.h"
#include "Spectrogram.h"
#include "Integration.h"
#include "Differentiation.h"
#include "SmoothFilter.h"
#include "FFTFilter.h"
#include "Convolution.h"
#include "Correlation.h"
#include "CurveRangeDialog.h"
#include "ColorBox.h"
#include "QwtHistogram.h"
#include "OpenProjectDialog.h"
#include "ColorMapDialog.h"
#include "TextEditor.h"
#include "SymbolDialog.h"
#include "CustomActionDialog.h"
#include "MdiSubWindow.h"
#include "FloatingWindow.h"
#include "DataPickerTool.h"
#include "TiledWindow.h"
#include "TSVSerialiser.h"

// TODO: move tool-specific code to an extension manager
#include "ScreenPickerTool.h"
#include "TranslateCurveTool.h"
#include "MultiPeakFitTool.h"
#include "LineProfileTool.h"
#include "RangeSelectorTool.h"
#include "PlotToolInterface.h"
#include "Mantid/IProjectSerialisable.h"
#include "Mantid/MantidMatrix.h"
#include "Mantid/MantidTable.h"
#include "Mantid/MantidMatrixCurve.h"
#include "ContourLinesEditor.h"
#include "Mantid/InstrumentWidget/InstrumentWindow.h"
#include "Mantid/RemoveErrorsDialog.h"

#include <stdio.h>
#include <stdlib.h>

#include <qwt_scale_engine.h>
#include <QFileDialog>
#include <QInputDialog>
#include <QProgressDialog>
#include <QPrintDialog>
#include <QPixmapCache>
#include <QMenuBar>
#include <QClipboard>
#include <QTranslator>
#include <QSplitter>
#include <QSettings>
#include <QApplication>
#include <QMessageBox>
#include <QPrinter>
#include <QPrinterInfo>
#include <QActionGroup>
#include <QAction>
#include <QToolBar>
#include <QKeySequence>
#include <QImageReader>
#include <QImageWriter>
#include <QDateTime>
#include <QShortcut>
#include <QDockWidget>
#include <QTextStream>
#include <QVarLengthArray>
#include <QList>
#include <QUrl>
#include <QFontComboBox>
#include <QSpinBox>
#include <QMdiArea>
#include <QMdiSubWindow>
#include <QSignalMapper>
#include <QDesktopWidget>
#include <QtAlgorithms>
#include <zlib.h>

#include <gsl/gsl_sort.h>

#include <boost/regex.hpp>
#include <boost/scoped_ptr.hpp>
#include "Mantid/PeakPickerTool.h"
#include "Mantid/ManageCustomMenus.h"
#include "Mantid/ManageInterfaceCategories.h"
#include "Mantid/FirstTimeSetup.h"

#include "MantidQtAPI/FileDialogHandler.h"
#include "MantidQtAPI/InterfaceManager.h"
#include "MantidQtAPI/UserSubWindow.h"
#include "MantidQtAPI/AlgorithmInputHistory.h"
#include "MantidQtAPI/ManageUserDirectories.h"
#include "MantidQtAPI/Message.h"
#include "MantidQtMantidWidgets/CatalogHelper.h"
#include "MantidQtMantidWidgets/CatalogSearch.h"
#include "MantidQtMantidWidgets/FitPropertyBrowser.h"
#include "MantidQtMantidWidgets/MessageDisplay.h"
#include "MantidQtMantidWidgets/MuonFitPropertyBrowser.h"

#include "MantidKernel/ConfigService.h"
#include "MantidKernel/FacilityInfo.h"
#include "MantidKernel/InstrumentInfo.h"
#include "MantidKernel/LibraryManager.h"
#include "MantidKernel/Logger.h"
#include "MantidKernel/MantidVersion.h"

#include "MantidAPI/AlgorithmFactory.h"
#include "MantidAPI/AnalysisDataService.h"
#include "MantidAPI/CatalogManager.h"
#include "MantidAPI/ITableWorkspace.h"
#include "MantidAPI/WorkspaceFactory.h"
#include "MantidQtAPI/ScriptRepositoryView.h"

using namespace Qwt3D;
using namespace MantidQt::API;
using Mantid::Kernel::ConfigService;
using Mantid::API::FrameworkManager;
using Mantid::Kernel::ConfigService;
using Mantid::Kernel::LibraryManager;
using Mantid::Kernel::Logger;

namespace {
/// static logger
Logger g_log("ApplicationWindow");
extern "C" {
void file_compress(const char *file, const char *mode);
void file_uncompress(const char *file);
}

ApplicationWindow::ApplicationWindow(bool factorySettings)
    : QMainWindow(), Scripted(ScriptingLangManager::newEnv(this)),
      blockWindowActivation(false), m_enableQtiPlotFitting(false),
      m_exitCode(0),
#ifdef Q_OS_MAC // Mac
      settings(QSettings::IniFormat, QSettings::UserScope, "Mantid",
               "MantidPlot")
#else
      settings("Mantid", "MantidPlot")
  QStringList empty;
  init(factorySettings, empty);
}

ApplicationWindow::ApplicationWindow(bool factorySettings,
                                     const QStringList &args)
    : QMainWindow(), Scripted(ScriptingLangManager::newEnv(this)),
      blockWindowActivation(false), m_enableQtiPlotFitting(false),
      m_exitCode(0),
#ifdef Q_OS_MAC // Mac
      settings(QSettings::IniFormat, QSettings::UserScope, "Mantid",
               "MantidPlot")
      settings("Mantid", "MantidPlot")
#endif
{
  init(factorySettings, args);
/**
 * This function is responsible for copying the old configuration
 * information from the ISIS\MantidPlot area to the new Mantid\MantidPlot
 * area. The old area is deleted once the trnasfer is complete. On subsequent
 * runs, if the old configuration area is missing or empty, the copying
 * is ignored.
 */
void ApplicationWindow::handleConfigDir() {
#ifdef Q_OS_WIN
  // We use the registry for settings on Windows
  QSettings oldSettings("ISIS", "MantidPlot");
  QStringList keys = oldSettings.allKeys();
  // If the keys are empty, we removed the MantidPlot entries
  if (!keys.empty()) {
    foreach (QString key, keys) {
      settings.setValue(key, oldSettings.value(key));
    }
    // This unfortunately cannot remove the top-level entry
    oldSettings.remove("");
  }
#else
  QFileInfo curConfig(settings.fileName());
  QString oldPath = settings.fileName();
  oldPath.replace("Mantid", "ISIS");
  QFileInfo oldConfig(oldPath);

  // If the old config directory exists, copy it's contents and
  // then delete it
  QDir oldConfigDir = oldConfig.dir();
  if (oldConfigDir.exists()) {
    QStringList entries = oldConfigDir.entryList();
    foreach (QString entry, entries) {
      if (!entry.startsWith(".")) {
        QFileInfo oldFile(oldConfig.dir(), entry);
        QFileInfo newFile(curConfig.dir(), entry);
        // Qt will not overwrite files, so remove new one first
        QFile::remove(newFile.filePath());
        QFile::copy(oldFile.filePath(), newFile.filePath());
        QFile::remove(oldFile.filePath());
      }
    }
    oldConfigDir.rmdir(oldConfig.path());
  }
/**
 * Calls QCoreApplication::exit(m_exitCode)
 */
void ApplicationWindow::exitWithPresetCode() {
  QCoreApplication::exit(m_exitCode);
void ApplicationWindow::init(bool factorySettings, const QStringList &args) {
  QCoreApplication::setOrganizationName("Mantid");
  QCoreApplication::setApplicationName("MantidPlot");
  setAttribute(Qt::WA_DeleteOnClose);

  m_sharedMenuBar = new QMenuBar(NULL);
  m_sharedMenuBar->setNativeMenuBar(true);
#endif
  setWindowTitle(tr("MantidPlot - untitled")); // Mantid
  setObjectName("main application");
  initGlobalConstants();
  QPixmapCache::setCacheLimit(20 * QPixmapCache::cacheLimit());
  // Logging as early as possible
  logWindow = new QDockWidget(this);
  logWindow->hide();
  logWindow->setObjectName(
      "logWindow"); // this is needed for QMainWindow::restoreState()
  logWindow->setWindowTitle(tr("Results Log"));
  addDockWidget(Qt::TopDockWidgetArea, logWindow);
  using MantidQt::MantidWidgets::MessageDisplay;
  using MantidQt::API::Message;
  qRegisterMetaType<Message>("Message"); // Required to use it in signals-slots
  resultsLog =
      new MessageDisplay(MessageDisplay::EnableLogLevelControl, logWindow);
  logWindow->setWidget(resultsLog);
  connect(resultsLog, SIGNAL(errorReceived(const QString &)), logWindow,
          SLOT(show()));
  // Process all pending events before loading Mantid
  // Helps particularly on Windows with cleaning up the
  // splash screen after the 3D visualization dialog has closed
  qApp->processEvents();
  auto &config = ConfigService::Instance(); // Starts logging
  resultsLog->attachLoggingChannel();       // Must be done after logging starts
  // Load Mantid core libraries by starting the framework
  FrameworkManager::Instance();
  // Load Paraview plugin libraries if possible
  if (config.pvPluginsAvailable()) {
    if (g_log.getLevel() == Logger::Priority::PRIO_DEBUG) {
      g_log.debug("Loading libraries from \"" + config.getPVPluginsPath() +
                  "\"");
    LibraryManager::Instance().OpenAllLibraries(config.getPVPluginsPath(),
                                                false);
  // Create UI object
  mantidUI = new MantidUI(this);

  // Everything else...
  tablesDepend = new QMenu(this);
  explorerWindow = new QDockWidget(this);
  explorerWindow->setWindowTitle(tr("Project Explorer"));
  explorerWindow->setObjectName(
      "explorerWindow"); // this is needed for QMainWindow::restoreState()
  explorerWindow->setMinimumHeight(150);
  addDockWidget(Qt::BottomDockWidgetArea, explorerWindow);
  actionSaveFile = NULL;
  actionSaveProject = NULL;
  actionSaveProjectAs = NULL;
  folders = new FolderListView(this);
  folders->header()->setClickEnabled(false);
  folders->addColumn(tr("Folder"));
  folders->setRootIsDecorated(true);
  folders->setResizeMode(Q3ListView::LastColumn);
  folders->header()->hide();
  folders->setSelectionMode(Q3ListView::Single);

  connect(folders, SIGNAL(currentChanged(Q3ListViewItem *)), this,
          SLOT(folderItemChanged(Q3ListViewItem *)));
  connect(folders, SIGNAL(itemRenamed(Q3ListViewItem *, int, const QString &)),
          this, SLOT(renameFolder(Q3ListViewItem *, int, const QString &)));
  connect(folders,
          SIGNAL(contextMenuRequested(Q3ListViewItem *, const QPoint &, int)),
          this,
          SLOT(showFolderPopupMenu(Q3ListViewItem *, const QPoint &, int)));
  connect(folders, SIGNAL(dragItems(QList<Q3ListViewItem *>)), this,
          SLOT(dragFolderItems(QList<Q3ListViewItem *>)));
  connect(folders, SIGNAL(dropItems(Q3ListViewItem *)), this,
          SLOT(dropFolderItems(Q3ListViewItem *)));
  connect(folders, SIGNAL(renameItem(Q3ListViewItem *)), this,
          SLOT(startRenameFolder(Q3ListViewItem *)));
  connect(folders, SIGNAL(addFolderItem()), this, SLOT(addFolder()));
  connect(folders, SIGNAL(deleteSelection()), this,
          SLOT(deleteSelectedItems()));
  d_current_folder = new Folder(0, tr("untitled"));
  FolderListItem *fli = new FolderListItem(folders, d_current_folder);
  d_current_folder->setFolderListItem(fli);

  lv = new FolderListView();
  lv->addColumn(tr("Name"), -1);
  lv->addColumn(tr("Type"), -1);
  lv->addColumn(tr("View"), -1);
  lv->addColumn(tr("Size"), -1);
  lv->addColumn(tr("Created"), -1);
  lv->addColumn(tr("Label"), -1);
  lv->setResizeMode(Q3ListView::LastColumn);
  lv->setMinimumHeight(80);
  lv->setSelectionMode(Q3ListView::Extended);
  lv->setDefaultRenameAction(Q3ListView::Accept);

  explorerSplitter = new QSplitter(Qt::Horizontal, explorerWindow);
  explorerSplitter->addWidget(folders);
  explorerSplitter->addWidget(lv);
  explorerWindow->setWidget(explorerSplitter);

  QList<int> splitterSizes;
  explorerSplitter->setSizes(splitterSizes << 45 << 45);
  explorerWindow->hide();

  // Needs to be done after initialization of dock windows,
  // because we now use QDockWidget::toggleViewAction()
  createActions();
  initToolBars();
  initMainMenu();
  makeToolbarsMenu();

  d_workspace = new QMdiArea();
  d_workspace->setOption(QMdiArea::DontMaximizeSubWindowOnActivation);
  d_workspace->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
  d_workspace->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
  setCentralWidget(d_workspace);

  setAcceptDrops(true);

  hiddenWindows = new QList<QWidget *>();

  scriptingWindow = NULL;
  d_text_editor = NULL;

  const QString scriptsDir = QString::fromStdString(
      Mantid::Kernel::ConfigService::Instance().getString(
          "mantidqt.python_interfaces_directory"));

  // Parse the list of registered PyQt interfaces and their respective
  // categories.
  QString pyQtInterfacesProperty = QString::fromStdString(
      Mantid::Kernel::ConfigService::Instance().getString(
          "mantidqt.python_interfaces"));
  foreach (const QString pyQtInterfaceInfo,
           QStringList::split(" ", pyQtInterfacesProperty)) {
    QString pyQtInterfaceFile;
    QSet<QString> pyQtInterfaceCategories;
    const QStringList tokens = QStringList::split("/", pyQtInterfaceInfo);

    if (tokens.size() == 0) // Empty token - ignore.
    } else if (tokens.size() == 1) // Assume missing category.
      pyQtInterfaceCategories += "Uncatagorised";
      pyQtInterfaceFile = tokens[0];
    } else if (tokens.size() ==
               2) // Assume correct interface name and categories.
      pyQtInterfaceCategories += QStringList::split(";", tokens[0]).toSet();
      pyQtInterfaceFile = tokens[1];
    } else // Too many forward slashes, or no space between two interfaces.
           // Warn user and move on.
      g_log.warning() << "The mantidqt.python_interfaces property contains an "
                         "unparsable value: "
                      << pyQtInterfaceInfo.toStdString();
      continue;
    }

    const QString scriptPath = scriptsDir + '/' + pyQtInterfaceFile;

    if (QFileInfo(scriptPath).exists()) {
      const QString pyQtInterfaceName =
          QFileInfo(scriptPath).baseName().replace("_", " ");
      m_interfaceNameDataPairs.append(qMakePair(pyQtInterfaceName, scriptPath));

      // Keep track of the interface's categories as we go.
      m_interfaceCategories[pyQtInterfaceName] = pyQtInterfaceCategories;
      m_allCategories += pyQtInterfaceCategories;
    } else {
      g_log.warning() << "Could not find interface script: "
                      << scriptPath.ascii() << "\n";
  MantidQt::API::InterfaceManager interfaceManager;
  // Add all interfaces inherited from UserSubWindow.
  foreach (const QString userSubWindowName,
           interfaceManager.getUserSubWindowKeys()) {
    m_interfaceNameDataPairs.append(
        qMakePair(userSubWindowName, userSubWindowName));
    const QSet<QString> categories =
        UserSubWindowFactory::Instance().getInterfaceCategories(
            userSubWindowName);

    m_interfaceCategories[userSubWindowName] = categories;
    m_allCategories += categories;

  renamedTables = QStringList();
  if (!factorySettings)
    readSettings();
  createLanguagesList();
  insertTranslatedStrings();
  disableToolbars();
  displayToolbars();
  actionNextWindow = new QAction(QIcon(getQPixmap("next_xpm")),
                                 tr("&Next", "next window"), this);
  actionNextWindow->setShortcut(tr("F5", "next window shortcut"));
  connect(actionNextWindow, SIGNAL(activated()), d_workspace,
          SLOT(activateNextSubWindow()));

  actionPrevWindow = new QAction(QIcon(getQPixmap("prev_xpm")),
                                 tr("&Previous", "previous window"), this);
  actionPrevWindow->setShortcut(tr("F6", "previous window shortcut"));
  connect(actionPrevWindow, SIGNAL(activated()), d_workspace,
          SLOT(activatePreviousSubWindow()));

  connect(tablesDepend, SIGNAL(activated(int)), this, SLOT(showTable(int)));

  connect(this, SIGNAL(modified()), this, SLOT(modifiedProject()));
  connect(d_workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)), this,
          SLOT(windowActivated(QMdiSubWindow *)));
  connect(lv, SIGNAL(doubleClicked(Q3ListViewItem *)), this,
          SLOT(activateWindow(Q3ListViewItem *)));
  connect(lv, SIGNAL(doubleClicked(Q3ListViewItem *)), this,
          SLOT(folderItemDoubleClicked(Q3ListViewItem *)));
  connect(
      lv, SIGNAL(contextMenuRequested(Q3ListViewItem *, const QPoint &, int)),
      this, SLOT(showWindowPopupMenu(Q3ListViewItem *, const QPoint &, int)));
  connect(lv, SIGNAL(dragItems(QList<Q3ListViewItem *>)), this,
          SLOT(dragFolderItems(QList<Q3ListViewItem *>)));
  connect(lv, SIGNAL(dropItems(Q3ListViewItem *)), this,
          SLOT(dropFolderItems(Q3ListViewItem *)));
  connect(lv, SIGNAL(renameItem(Q3ListViewItem *)), this,
          SLOT(startRenameFolder(Q3ListViewItem *)));
  connect(lv, SIGNAL(addFolderItem()), this, SLOT(addFolder()));
  connect(lv, SIGNAL(deleteSelection()), this, SLOT(deleteSelectedItems()));
  connect(lv, SIGNAL(itemRenamed(Q3ListViewItem *, int, const QString &)), this,
          SLOT(renameWindow(Q3ListViewItem *, int, const QString &)));
  connect(recentProjectsMenu, SIGNAL(activated(int)), this,
          SLOT(openRecentProject(int)));
  connect(recentFilesMenu, SIGNAL(activated(int)), this,
          SLOT(openRecentFile(int)));
  updateAppFonts();
  setAppColors(workspaceColor, panelsColor, panelsTextColor, true);

  // Scripting
  m_script_envs = QHash<QString, ScriptingEnv *>();
  setScriptingLanguage(defaultScriptingLang);
  m_iface_script = NULL;
  m_interpreterDock->setObjectName(
      "interpreterDock"); // this is needed for QMainWindow::restoreState()
  m_interpreterDock->setWindowTitle("Script Interpreter");
  runPythonScript("from ipython_widget import *\nw = "
                  "_qti.app._getInterpreterDock()\nw.setWidget("
                  "MantidIPythonWidget())",
                  false, true, true);
  if (!restoreDockWidget(m_interpreterDock)) {
    // Restoring the widget fails if the settings aren't found or read.
    // Therefore, add it manually.
    addDockWidget(Qt::BottomDockWidgetArea, m_interpreterDock);
  loadCustomActions();

  // Nullify catalogSearch
  catalogSearch = NULL;
  // Print a warning message if the scripting language is set to muParser
  if (defaultScriptingLang == "muParser") {
    logWindow->show();
    g_log.warning("The scripting language is set to muParser. This is probably "
                  "not what you want! Change the default in "
                  "View->Preferences.");
  // Need to show first time setup dialog?
  // It is raised in the about2start method as on OS X if the event loop is not
  // running then raise()
  // does not push the dialog to the top of the stack
  d_showFirstTimeSetup = shouldWeShowFirstTimeSetup(args);
  using namespace Mantid::API;
  // Do this as late as possible to avoid unnecessary updates
  AlgorithmFactory::Instance().enableNotifications();
  AlgorithmFactory::Instance().notificationCenter.postNotification(
      new AlgorithmFactoryUpdateNotification);
/** Determines if the first time dialog should be shown
* @param commandArguments : all command line arguments.
* @returns true if the dialog should be shown
*/
bool ApplicationWindow::shouldWeShowFirstTimeSetup(
    const QStringList &commandArguments) {
  // Early check of execute and quit command arguments used by system tests.
  QString str;
  foreach (str, commandArguments) {
    if ((this->shouldExecuteAndQuit(str)) || (this->isSilentStartup(str))) {
      return false;
    }
  }
  // first check the facility and instrument
  using Mantid::Kernel::ConfigService;
  auto &config = ConfigService::Instance();
  std::string facility = config.getString("default.facility");
  std::string instrument = config.getString("default.instrument");
  if (facility.empty() || instrument.empty()) {
    return true;
  } else {
    // check we can get the facility and instrument
    try {
      const Mantid::Kernel::FacilityInfo &facilityInfo =
          config.getFacility(facility);
      const Mantid::Kernel::InstrumentInfo &instrumentInfo =
          config.getInstrument(instrument);
      g_log.information() << "Default facility '" << facilityInfo.name()
                          << "', instrument '" << instrumentInfo.name() << "'"
                          << std::endl;
    } catch (Mantid::Kernel::Exception::NotFoundError &) {
      // failed to find the facility or instrument
      g_log.error() << "Could not find your default facility '" << facility
                    << "' or instrument '" << instrument
                    << "' in facilities.xml, showing please select again."
                    << std::endl;
      return true;
  QSettings settings;
  settings.beginGroup("Mantid/FirstUse");
  const bool doNotShowUntilNextRelease =
      settings.value("DoNotShowUntilNextRelease", 0).toInt();
  const QString lastVersion = settings.value("LastVersion", "").toString();
  settings.endGroup();

  if (!doNotShowUntilNextRelease) {
  // Now check if the version has changed since last time
  const QString version =
      QString::fromStdString(Mantid::Kernel::MantidVersion::releaseNotes());
  if (version != lastVersion) {
    return true;
  }

  return false;
void ApplicationWindow::initWindow() {
  switch (d_init_window_type) {
  case TableWindow:
    newTable();
    break;
  case MatrixWindow:
    newMatrix();
    break;
  case MultiLayerWindow:
    newGraph();
    break;
  case NoteWindow:
    newNote();
    break;
  default:
    break;
  }
}

void ApplicationWindow::initGlobalConstants() {
  d_auto_update_table_values = true;
  d_active_window = NULL;
  d_matrix_undo_stack_size = 10;

  d_opening_file = false;
  d_in_place_editing = true;

  d_matrix_tool_bar = true;
  d_standard_tool_bar = true;
  d_column_tool_bar = true;
  d_edit_tool_bar = true;
  d_plot_tool_bar = true;
  d_display_tool_bar = false;
  d_format_tool_bar = true;

  appStyle = qApp->style()->objectName();
  d_app_rect = QRect();
  projectname = "untitled";
  lastCopiedLayer = NULL;
  d_text_copy = NULL;
  d_arrow_copy = NULL;
  d_image_copy = NULL;

  savingTimerId = 0;

  autoSearchUpdatesRequest = false;

  show_windows_policy = ActiveFolder;
  d_init_window_type = NoWindow;

  QString aux = qApp->applicationDirPath();
  workingDir = aux;

  d_translations_folder = aux + "/translations";
  helpFilePath = aux + "/manual/index.html";
  d_python_config_folder = aux;

  fitPluginsPath = aux + "fitPlugins";
  fitModelsPath = QString::null;
  templatesDir = aux;
  asciiDirPath = aux;
  imagesDirPath = aux;
  scriptsDirPath = aux;
  customActionsDirPath = QString::null;

  appFont = QFont();
  QString family = appFont.family();
  int pointSize = appFont.pointSize();
  tableTextFont = appFont;
  tableHeaderFont = appFont;
  plotAxesFont = QFont(family, pointSize, QFont::Bold, false);
  plotNumbersFont = QFont(family, pointSize);
  plotLegendFont = appFont;
  plotTitleFont = QFont(family, pointSize + 2, QFont::Bold, false);
  plot3DAxesFont = QFont(family, pointSize, QFont::Bold, false);
  plot3DNumbersFont = QFont(family, pointSize);
  plot3DTitleFont = QFont(family, pointSize + 2, QFont::Bold, false);

  autoSearchUpdates = false;
  appLanguage = QLocale::system().name().section('_', 0, 0);
  show_windows_policy = ApplicationWindow::ActiveFolder;

  workspaceColor = QColor("darkGray");
  panelsColor = QColor("#ffffff");
  panelsTextColor = QColor("#000000");
  tableBkgdColor = QColor("#ffffff");
  tableTextColor = QColor("#000000");
  tableHeaderColor = QColor("#000000");

  plot3DColors = QStringList();
  plot3DColors << "blue";
  plot3DColors << "#000000";
  plot3DColors << "#000000";
  plot3DColors << "#000000";
  plot3DColors << "red";
  plot3DColors << "#000000";
  plot3DColors << "#000000";
  plot3DColors << "#ffffff";

  d_graph_tick_labels_dist = 4;
  d_graph_axes_labels_dist = 2;

  autoSave = false;
  autoSaveTime = 15;
  d_backup_files = true;
  defaultScriptingLang = "Python"; // Mantid M. Gigg
  // Scripting window geometry
  d_script_win_pos = QPoint(250, 200);
  d_script_win_size = QSize(600, 660);
  d_thousands_sep = true;
  d_locale = QLocale::system().name();
  if (!d_thousands_sep)
    d_locale.setNumberOptions(QLocale::OmitGroupSeparator);

  d_decimal_digits = 13;
  d_graphing_digits = 13;

  d_extended_open_dialog = true;
  d_extended_export_dialog = true;
  d_extended_import_ASCII_dialog = true;
  d_extended_plot_dialog = true;

  d_add_curves_dialog_size = QSize(700, 400);
  d_show_current_folder = false;

  confirmCloseFolder = false;
  confirmCloseTable = false;
  confirmCloseMatrix = false;
  confirmClosePlot2D = false;
  confirmClosePlot3D = false;
  confirmCloseNotes = false;
  d_inform_delete_workspace = true;
  d_inform_rename_table = false;
  confirmCloseInstrWindow = false;

  d_show_table_comments = false;

  titleOn = true;
  // 'Factory' default is to show top & right axes but without labels
  d_show_axes = QVector<bool>(QwtPlot::axisCnt, true);
  d_show_axes_labels = QVector<bool>(QwtPlot::axisCnt, true);
  d_show_axes_labels[1] = false;
  d_show_axes_labels[3] = false;
  canvasFrameWidth = 0;
  defaultPlotMargin = 0;
  drawBackbones = true;

  // these settings are overridden, but the default axes scales are linear
  d_axes_scales = QVector<QString>(QwtPlot::axisCnt, "linear");

  axesLineWidth = 1;
  autoscale2DPlots = true;
  autoScaleFonts = true;
  autoResizeLayers = true;
  antialiasing2DPlots = true;
  fixedAspectRatio2DPlots = false; // Mantid
  d_scale_plots_on_print = false;
  d_print_cropmarks = false;
  d_synchronize_graph_scales = true;

  defaultCurveStyle = static_cast<int>(Graph::Line);
  defaultCurveLineWidth = 1;
  defaultSymbolSize = 7;

  majTicksStyle = static_cast<int>(ScaleDraw::In);
  minTicksStyle = static_cast<int>(ScaleDraw::In);
  minTicksLength = 5;
  majTicksLength = 9;

  legendFrameStyle = static_cast<int>(LegendWidget::Line);
  legendTextColor = Qt::black;
  legendBackground = Qt::white;
  legendBackground.setAlpha(255); // opaque by default;

  defaultArrowLineWidth = 1;
  defaultArrowColor = Qt::black;
  defaultArrowHeadLength = 4;
  defaultArrowHeadAngle = 45;
  defaultArrowHeadFill = true;
  defaultArrowLineStyle = Graph::getPenStyle("SolidLine");

  showPlot3DLegend = true;
  showPlot3DProjection = false;
  smooth3DMesh = false;
  plot3DResolution = 1;
  orthogonal3DPlots = false;
  autoscale3DPlots = true;

  fit_output_precision = 13;
  pasteFitResultsToPlot = false;
  writeFitResultsToLog = true;
  generateUniformFitPoints = true;
  fitPoints = 100;
  generatePeakCurves = true;
  peakCurvesColor = 2;
  fit_scale_errors = true;
  d_2_linear_fit_points = true;

  columnSeparator = "\t";
  ignoredLines = 0;
  renameColumns = true;
  strip_spaces = false;
  simplify_spaces = false;
  d_ASCII_file_filter = "*";
  d_ASCII_import_locale = QLocale::system().name();
  d_import_dec_separators = true;
  d_ASCII_import_mode = static_cast<int>(ImportASCIIDialog::NewTables);
  d_ASCII_comment_string = "#";
  d_ASCII_import_comments = false;
  d_ASCII_import_read_only = false;
  d_ASCII_import_preview = true;
  d_preview_lines = 100;
#ifdef Q_OS_MAC
  d_eol = CR;
#endif

  d_export_col_names = false;
  d_export_col_comment = false;
  d_export_table_selection = false;

  d_image_export_filter = ".png";
  d_export_transparency = false;
  d_export_quality = 100;

  // MG: On Linux, if cups defines a printer queue that cannot be contact, the
  // QPrinter constructor hangs and doesn't timeout.

  //	QPrinterInfo::availablePrinters();

  //	d_export_resolution = QPrinter().resolution();
  d_export_color = true;
  d_export_vector_size = static_cast<int>(QPrinter::Custom);
  d_keep_plot_aspect = true;
}

QMenuBar *ApplicationWindow::myMenuBar() {
#ifdef SHARED_MENUBAR
  return m_sharedMenuBar == NULL ? menuBar() : m_sharedMenuBar;
#else
  return menuBar();
#endif
}

void ApplicationWindow::initToolBars() {
  initPlot3DToolBar();

  //	setWindowIcon(QIcon(getQPixmap("logo_xpm")));
  setWindowIcon(QIcon(":/MantidPlot_Icon_32offset.png"));
  QPixmap openIcon, saveIcon;

  standardTools = new QToolBar(tr("Standard Tools"), this);
  standardTools->setObjectName(
      "standardTools"); // this is needed for QMainWindow::restoreState()
  standardTools->setIconSize(QSize(18, 20));
  addToolBar(Qt::TopToolBarArea, standardTools);
  standardTools->addAction(actionLoadFile);
  standardTools->addSeparator();
  standardTools->addAction(actionNewProject);
  standardTools->addAction(actionOpenProj);
  standardTools->addAction(actionSaveProject);
  standardTools->addSeparator();
  standardTools->addAction(actionShowLog);
#ifdef SCRIPTING_PYTHON
  standardTools->addAction(actionShowScriptWindow);
  standardTools->addSeparator();
  standardTools->addAction(actionManageDirs);
  standardTools->addSeparator();
  standardTools->addAction(actionCopySelection);
  standardTools->addAction(actionPasteSelection);

  plotTools = new QToolBar(tr("Plot"), this);
  plotTools->setObjectName(
      "plotTools"); // this is needed for QMainWindow::restoreState()
  plotTools->setIconSize(QSize(16, 20));
  addToolBar(plotTools);
  dataTools = new QActionGroup(this);
  dataTools->setExclusive(true);

  btnPointer = new QAction(tr("Disable &Tools"), this);
  btnPointer->setActionGroup(dataTools);
  btnPointer->setCheckable(true);
  btnPointer->setIcon(QIcon(getQPixmap("pointer_xpm")));
  btnPointer->setChecked(true);
  plotTools->addAction(btnPointer);

  actionPanPlot->setActionGroup(dataTools);
  actionPanPlot->setCheckable(true);
  plotTools->addAction(actionPanPlot);

  btnZoomIn = new QAction(tr("&Zoom In"), this);
  btnZoomIn->setShortcut(tr("Ctrl++"));
  btnZoomIn->setActionGroup(dataTools);
  btnZoomIn->setCheckable(true);
  btnZoomIn->setIcon(QIcon(getQPixmap("zoom_xpm")));
  plotTools->addAction(btnZoomIn);

  btnZoomOut = new QAction(tr("&Zoom Out"), this);
  btnZoomOut->setShortcut(tr("Ctrl+-"));
  btnZoomOut->setActionGroup(dataTools);
  btnZoomOut->setCheckable(true);
  btnZoomOut->setIcon(QIcon(getQPixmap("zoomOut_xpm")));
  plotTools->addAction(btnZoomOut);