#include "mainwindow.h"

#include <iostream>
using namespace std;

#include <typeinfo>

#if defined(VYM_DBUS)
#include "adaptorvym.h"
#endif

#include <QColorDialog>
#include <QDockWidget>
#include <QFileDialog>
#include <QFontDialog>
#include <QInputDialog>
#include <QMenuBar>
#include <QScriptEngine>
#include <QSslSocket>
#include <QStatusBar>
#include <QTextStream>

#include "aboutdialog.h"
#include "attributeitem.h"
#include "branchitem.h"
#include "branchpropeditor.h"
#include "command.h"
#include "confluence-agent.h"
#include "confluence-user.h"
#include "confluence-userdialog.h"
#include "confluence-settings-dialog.h"
#include "darktheme-settings-dialog.h"
#include "debuginfo.h"
#include "default-map-settings-dialog.h"
#include "download-agent.h"
#include "file.h"
#include "findresultmodel.h"
#include "findresultwidget.h"
#include "flagrow.h"
#include "headingeditor.h"
#include "historywindow.h"
#include "imports.h"
#include "jira-agent.h"
#include "jira-settings-dialog.h"
#include "lineeditdialog.h"
#include "macros.h"
#include "mapeditor.h"
#include "misc.h"
#include "noteeditor.h"
#include "options.h"
#include "scripteditor.h"
#include "scripting.h"
#include "scriptoutput.h"
#include "settings.h"
#include "shortcuts.h"
#include "showtextdialog.h"
#include "task.h"
#include "taskeditor.h"
#include "taskmodel.h"
#include "treeeditor.h"
#include "vymprocess.h"
#include "warningdialog.h"
#include "xlinkitem.h"
#include "zip-settings-dialog.h"

QPrinter *printer = NULL;

//#include <modeltest.h>

#if defined(VYM_DBUS)
#include <QDBusConnection>
#endif

extern NoteEditor *noteEditor;
extern HeadingEditor *headingEditor;
extern BranchPropertyEditor *branchPropertyEditor;
extern ScriptEditor *scriptEditor;
extern ScriptOutput *scriptOutput;
extern Main *mainWindow;
extern FindResultWidget *findResultWidget;
extern TaskEditor *taskEditor;
extern TaskModel *taskModel;
extern Macros macros;
extern QDir tmpVymDir;
extern QDir cacheDir;
extern QString clipboardDir;
extern QString clipboardFile;
extern int statusbarTime;
extern FlagRowMaster *standardFlagsMaster;
extern FlagRowMaster *userFlagsMaster;
extern FlagRowMaster *systemFlagsMaster;
extern QString vymName;
extern QString vymVersion;
extern QString vymPlatform;
extern QString vymCodeQuality;
extern QString vymCodeName;
extern QString vymBuildDate;
extern QString localeName;
extern bool debug;
extern bool testmode;
extern QTextStream vout;
extern Switchboard switchboard;

extern bool restoreMode;
extern QStringList ignoredLockedFiles;
extern QStringList lastSessionFiles;

extern QList<Command *> modelCommands;
extern QList<Command *> vymCommands;

extern bool usingDarkTheme;

QMenu *branchAddContextMenu;
QMenu *branchContextMenu;
QMenu *branchLinksContextMenu;
QMenu *branchRemoveContextMenu;
QMenu *branchXLinksContextMenuEdit;
QMenu *branchXLinksContextMenuFollow;
QMenu *canvasContextMenu;
QMenu *floatimageContextMenu;
QMenu *targetsContextMenu;
QMenu *taskContextMenu;
QMenu *fileLastMapsMenu;
QMenu *fileImportMenu;
QMenu *fileExportMenu;

extern Settings settings;
extern Options options;
extern ImageIO imageIO;

extern QDir vymBaseDir;
extern QDir vymTranslationsDir;
extern QDir lastImageDir;
extern QDir lastMapDir;
#if defined(Q_OS_WIN32)
extern QDir vymInstallDir;
#endif
extern QString zipToolPath;

extern QColor vymBlue;

Main::Main(QWidget *parent) : QMainWindow(parent)
{
    mainWindow = this;

    setWindowTitle("VYM - View Your Mind");

    shortcutScope = tr("Main window", "Shortcut scope");

// Load window settings
#if defined(Q_OS_WIN32)
    if (settings.value("/mainwindow/geometry/maximized", false).toBool()) {
        setWindowState(Qt::WindowMaximized);
    }
    else
#endif
    {
        resize(settings.value("/mainwindow/geometry/size", QSize(1024, 900))
                   .toSize());
        move(settings.value("/mainwindow/geometry/pos", QPoint(50, 50))
                 .toPoint());
    }

    // Sometimes we may need to remember old selections
    prevSelection = "";

    // Create unique temporary directory
    bool ok;
    QString tmpVymDirPath = makeTmpDir(ok, "vym");
    if (!ok) {
        qWarning("Mainwindow: Could not create temporary directory, failed to "
                 "start vym");
        exit(1);
    }
    if (debug)
        qDebug() << "tmpVymDirPath = " << tmpVymDirPath;
    tmpVymDir.setPath(tmpVymDirPath);

    // Create direcctory for clipboard
    clipboardDir = tmpVymDirPath + "/clipboard";
    clipboardFile = "clipboard";
    QDir d(clipboardDir);
    d.mkdir(clipboardDir);
    makeSubDirs(clipboardDir);

    // Create directory for cached files, e.g. svg images
    if (!tmpVymDir.mkdir("cache")) {
        qWarning(
            "Mainwindow: Could not create cache directory, failed to start vym");
        exit(1);
    }
    cacheDir = QDir(tmpVymDirPath + "/cache");

    // Remember PID of our friendly webbrowser
    browserPID = new qint64;
    *browserPID = 0;

    // Define commands in API (used globally)
    setupAPI();

    // Initialize some settings, which are platform dependant
    QString p, s;

    // application to open URLs
    p = "/system/readerURL";
#if defined(Q_OS_WIN)
    // Assume that system has been set up so that
    // Explorer automagically opens up the URL
    // in the user's preferred browser.
    s = settings.value(p, "explorer").toString();
#elif defined(Q_OS_MACX)
    s = settings.value(p, "/usr/bin/open").toString();
#else
    s = settings.value(p, "xdg-open").toString();
#endif
    settings.setValue(p, s);

    // application to open PDFs
    p = "/system/readerPDF";
#if defined(Q_OS_WIN)
    s = settings.value(p, "explorer").toString();
#elif defined(Q_OS_MACX)
    s = settings.value(p, "/usr/bin/open").toString();
#else
    s = settings.value(p, "xdg-open").toString();
#endif
    settings.setValue(p, s);

    // width of xLinksMenu
    xLinkMenuWidth = 60;

    // Create Layout
    QWidget *centralWidget = new QWidget(this);
    QVBoxLayout *layout = new QVBoxLayout(centralWidget);
    setCentralWidget(centralWidget);

    // Create tab widget which holds the maps
    tabWidget = new QTabWidget(centralWidget);
    connect(tabWidget, SIGNAL(currentChanged(int)), this,
            SLOT(editorChanged()));

    // Allow closing of tabs (introduced in Qt 4.5)
    tabWidget->setTabsClosable(true);
    connect(tabWidget, SIGNAL(tabCloseRequested(int)), this,
            SLOT(fileCloseMap(int)));

    tabWidget->setMovable(true);

    layout->addWidget(tabWidget);

    switchboard.addGroup("MainWindow", tr("Main window", "Shortcut group"));
    switchboard.addGroup("MapEditor", tr("Map Editors", "Shortcut group"));
    switchboard.addGroup("TextEditor", tr("Text Editors", "Shortcut group"));

    // Setup actions
    setupFileActions();
    setupEditActions();
    setupSelectActions();
    setupFormatActions();
    setupViewActions();
    setupModeActions();
    setupNetworkActions();
    setupSettingsActions();
    setupConnectActions();
    setupContextMenus();
    setupMacros();
    setupToolbars();
    setupFlagActions();

    // Dock widgets ///////////////////////////////////////////////
    QDockWidget *dw;
    dw = new QDockWidget();
    dw->setWidget(noteEditor);
    dw->setObjectName("NoteEditor");
    dw->setWindowTitle(noteEditor->getEditorTitle());
    dw->hide();
    noteEditorDW = dw;
    addDockWidget(Qt::LeftDockWidgetArea, dw);

    dw = new QDockWidget();
    dw->setWidget(headingEditor);
    dw->setObjectName("HeadingEditor");
    dw->setWindowTitle(headingEditor->getEditorTitle());
    dw->hide();
    headingEditorDW = dw;
    addDockWidget(Qt::BottomDockWidgetArea, dw);

    findResultWidget = new FindResultWidget();
    dw = new QDockWidget(tr("Search results list", "FindResultWidget"));
    dw->setWidget(findResultWidget);
    dw->setObjectName("FindResultWidget");
    dw->hide();
    addDockWidget(Qt::RightDockWidgetArea, dw);
    connect(findResultWidget, SIGNAL(noteSelected(QString, int)), this,
            SLOT(selectInNoteEditor(QString, int)));
    connect(findResultWidget, SIGNAL(findPressed(QString, bool)), this,
            SLOT(editFindNext(QString, bool)));

    scriptEditor = new ScriptEditor(this);
    dw = new QDockWidget(tr("Script Editor", "ScriptEditor"));
    dw->setWidget(scriptEditor);
    dw->setObjectName("ScriptEditor");
    dw->hide();
    addDockWidget(Qt::LeftDockWidgetArea, dw);

    scriptOutput = new ScriptOutput(this);
    dw = new QDockWidget(tr("Script output window"));
    dw->setWidget(scriptOutput);
    dw->setObjectName("ScriptOutput");
    dw->hide();
    addDockWidget(Qt::BottomDockWidgetArea, dw);

    dw = new QDockWidget(tr("Property Editor", "PropertyEditor"));
    dw->setWidget(branchPropertyEditor);
    dw->setObjectName("PropertyEditor");
    dw->hide();
    addDockWidget(Qt::LeftDockWidgetArea, dw);
    branchPropertyEditorDW = dw;

    historyWindow = new HistoryWindow();
    dw = new QDockWidget(tr("History window", "HistoryWidget"));
    dw->setWidget(historyWindow);
    dw->setObjectName("HistoryWidget");
    dw->hide();
    addDockWidget(Qt::RightDockWidgetArea, dw);
    connect(dw, SIGNAL(visibilityChanged(bool)), this, SLOT(updateActions()));

    // Connect NoteEditor, so that we can update flags if text changes
    connect(noteEditor, SIGNAL(textHasChanged(const VymText &)), this,
            SLOT(updateNoteText(const VymText &)));
    connect(noteEditor, SIGNAL(windowClosed()), this, SLOT(updateActions()));

    // Connect heading editor
    connect(headingEditor, SIGNAL(textHasChanged(const VymText &)), this,
            SLOT(updateHeading(const VymText &)));

    connect(scriptEditor, SIGNAL(runScript(QString)), this,
            SLOT(runScript(QString)));

    // Switch back  to MapEditor using Esc  or end presentation mode
    QAction *a = new QAction(this);
    a->setShortcut(Qt::Key_Escape);
    a->setShortcutContext(Qt::ApplicationShortcut);
    a->setCheckable(false);
    a->setEnabled(true);
    addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(escapePressed()));

    // Create TaskEditor after setting up above actions, allow cloning
    taskEditor = new TaskEditor();
    dw = new QDockWidget(tr("Task list", "TaskEditor"));
    dw->setWidget(taskEditor);
    dw->setObjectName("TaskEditor");
    dw->hide();
    addDockWidget(Qt::TopDockWidgetArea, dw);
    connect(dw, SIGNAL(visibilityChanged(bool)), this, SLOT(updateActions()));
    // FIXME -0 connect (taskEditor, SIGNAL (focusReleased() ), this, SLOT
    // (setFocusMapEditor()));

    if (options.isOn("shortcutsLaTeX"))
        switchboard.printLaTeX();

    if (settings.value("/mainwindow/showTestMenu", false).toBool())
        setupTestActions();
    setupHelpActions();

    // Status bar and progress bar there
    statusBar();
    progressMax = 0;
    progressCounter = 0;
    progressCounterTotal = 0;

    progressDialog.setAutoReset(false);
    progressDialog.setAutoClose(false);
    progressDialog.setMinimumWidth(600);
    // progressDialog.setWindowModality (Qt::WindowModal);   // That forces
    // mainwindo to update and slows down
    progressDialog.setCancelButton(NULL);

    restoreState(settings.value("/mainwindow/state", 0).toByteArray());

    updateGeometry();

    // After startup, schedule looking for updates AFTER
    // release notes have been downloaded
    // (avoid race condition with simultanously receiving cookies)
    checkUpdatesAfterReleaseNotes = true;

#if defined(VYM_DBUS)
    // Announce myself on DBUS
    new AdaptorVym(this); // Created and not deleted as documented in Qt
    if (!QDBusConnection::sessionBus().registerObject("/vym", this))
        qWarning("MainWindow: Couldn't register DBUS object!");
#endif
}

Main::~Main()
{
    // qDebug()<<"Destr Mainwindow"<<flush;

    // Save Settings

    if (!testmode) {
#if defined(Q_OS_WIN32)
        settings.setValue("/mainwindow/geometry/maximized", isMaximized());
#endif
        settings.setValue("/mainwindow/geometry/size", size());
        settings.setValue("/mainwindow/geometry/pos", pos());
        settings.setValue("/mainwindow/state", saveState(0));

        settings.setValue("/mainwindow/view/AntiAlias",
                          actionViewToggleAntiAlias->isChecked());
        settings.setValue("/mainwindow/view/SmoothPixmapTransform",
                          actionViewToggleSmoothPixmapTransform->isChecked());
        settings.setValue("/system/autosave/use",
                          actionSettingsToggleAutosave->isChecked());
        settings.setValue("/system/autosave/ms",
                          settings.value("/system/autosave/ms", 60000));
        settings.setValue("/mainwindow/autoLayout/use",
                          actionSettingsToggleAutoLayout->isChecked());
        settings.setValue("/mapeditor/editmode/autoSelectNewBranch",
                          actionSettingsAutoSelectNewBranch->isChecked());
        settings.setValue("/system/writeBackupFile",
                          actionSettingsWriteBackupFile->isChecked());

        if (printer) {
            settings.setValue("/system/printerName", printer->printerName());
            settings.setValue("/system/printerFormat", printer->outputFormat());
            settings.setValue("/system/printerFileName",
                              printer->outputFileName());
        }
        settings.setValue("/mapeditor/editmode/autoSelectText",
                          actionSettingsAutoSelectText->isChecked());
        settings.setValue("/mapeditor/editmode/useFlagGroups",
                          actionSettingsUseFlagGroups->isChecked());
        settings.setValue("/export/useHideExport",
                          actionSettingsUseHideExport->isChecked());
        settings.setValue("/system/version", vymVersion);
        settings.setValue("/system/builddate", vymBuildDate);
    }

    // call the destructors
    delete noteEditorDW;
    delete historyWindow;
    delete branchPropertyEditorDW;

    delete standardFlagsMaster;
    delete userFlagsMaster;
    delete systemFlagsMaster;

    // Remove temporary directory
    removeDir(tmpVymDir);
}

void Main::loadCmdLine()
{
    QStringList flist = options.getFileList();
    QStringList::Iterator it = flist.begin();

    initProgressCounter(flist.count());
    while (it != flist.end()) {
        FileType type = getMapType(*it);
        fileLoad(*it, NewMap, type);
        *it++;
    }
    removeProgressCounter();
}

void Main::statusMessage(const QString &s)
{
    // Surpress messages while progressdialog during
    // load is active
    statusBar()->showMessage(s, statusbarTime);
}

void Main::setProgressMaximum(int max)
{
    if (progressCounter == 0) {
        // Init range only on first time, when progressCounter still 0
        // Normalize range to 1000
        progressDialog.setRange(0, 1000);
        progressDialog.setValue(1);
    }
    progressCounter++; // Another map is loaded

    progressMax = max * 1000;
    QApplication::processEvents();
}

void Main::addProgressValue(float v)

{
    int progress_value =
        (v + progressCounter - 1) * 1000 / progressCounterTotal;
    /*
        qDebug() << "addVal v="<<v
         <<"  cur="<<progressDialog.value()
         <<"  pCounter="<<progressCounter
         <<"  pCounterTotal="<<progressCounterTotal
             <<"  newv="<< progress_value
         ;
         */

    // Make sure the progress dialog shows, even if value == 0
    if (progress_value < 1)
        progress_value = 1;
    progressDialog.setValue(progress_value);
    if (progress_value == 1)
        QApplication::processEvents();
}

void Main::initProgressCounter(uint n) { progressCounterTotal = n; }

void Main::removeProgressCounter()
{
    // Hide dialog again
    progressCounter = 0;
    progressCounterTotal = 0;
    progressDialog.reset();
    progressDialog.hide();
}

void Main::closeEvent(QCloseEvent *event)
{
    if (fileExitVYM())
        event->ignore();
    else
        event->accept();
}

QPrinter *Main::setupPrinter()
{
    // Global Printer
    printer = new QPrinter(QPrinter::HighResolution);
    return printer;
}

// Define commands for models
void Main::setupAPI()
{
    Command *c = new Command("addBranch", Command::Branch);
    c->addPar(Command::Int, true, "Index of new branch");
    modelCommands.append(c);

    c = new Command("addBranchBefore", Command::Branch);
    modelCommands.append(c);

    c = new Command("addMapCenter", Command::Any);
    c->addPar(Command::Double, false, "Position x");
    c->addPar(Command::Double, false, "Position y");
    modelCommands.append(c);

    c = new Command("addMapInsert", Command::Any);
    c->addPar(Command::String, false, "Filename of map to load");
    c->addPar(Command::Int, true, "Index where map is inserted");
    c->addPar(Command::Int, true, "Content filter");
    modelCommands.append(c);

    c = new Command("addMapReplace", Command::Branch);
    c->addPar(Command::String, false, "Filename of map to load");
    modelCommands.append(c);

    c = new Command("addSlide", Command::Branch);
    modelCommands.append(c);

    c = new Command("addXLink", Command::BranchLike);
    c->addPar(Command::String, false, "Begin of XLink");
    c->addPar(Command::String, false, "End of XLink");
    c->addPar(Command::Int, true, "Width of XLink");
    c->addPar(Command::Color, true, "Color of XLink");
    c->addPar(Command::String, true, "Penstyle of XLink");
    modelCommands.append(c);

    c = new Command("branchCount", Command::Any, Command::Int);
    modelCommands.append(c);

    c = new Command("centerCount", Command::BranchLike, Command::Int);
    modelCommands.append(c);

    c = new Command("centerOnID", Command::Any);
    c->addPar(Command::String, false, "UUID of object to center on");
    modelCommands.append(c);

    c = new Command("clearFlags", Command::BranchLike);
    modelCommands.append(c);

    c = new Command("colorBranch", Command::Branch);
    c->addPar(Command::Color, true, "New color");
    modelCommands.append(c);

    c = new Command("colorSubtree", Command::Branch);
    c->addPar(Command::Color, true, "New color");
    modelCommands.append(c);

    c = new Command("copy", Command::BranchOrImage);
    modelCommands.append(c);

    c = new Command("cut", Command::BranchOrImage);
    modelCommands.append(c);

    c = new Command("cycleTask", Command::BranchOrImage);
    c->addPar(Command::Bool, true, "True, if cycling in reverse order");
    modelCommands.append(c);

    c = new Command("depth", Command::BranchOrImage, Command::Int);
    modelCommands.append(c);

    c = new Command("exportMap", Command::Any, Command::Bool);
    c->addPar(Command::String, false,
              "Format (AO, ASCII, CONFLUENCE, CSV, HTML, Image, Impress, Last, "
              "LaTeX, Markdown, OrgMode, PDF, SVG, XML)");
    modelCommands.append(c);

    c = new Command("getDestPath", Command::Any, Command::String);
    modelCommands.append(c);

    c = new Command("getFileDir", Command::Any, Command::String);
    modelCommands.append(c);

    c = new Command("getFileName", Command::Any, Command::String);
    modelCommands.append(c);

    c = new Command("getFrameType", Command::Branch, Command::String);
    modelCommands.append(c);

    c = new Command("getHeadingPlainText", Command::TreeItem, Command::String);
    modelCommands.append(c);

    c = new Command("getHeadingXML", Command::TreeItem, Command::String);
    modelCommands.append(c);

    c = new Command("getMapAuthor", Command::Any, Command::String);
    modelCommands.append(c);

    c = new Command("getMapComment", Command::Any, Command::String);
    modelCommands.append(c);

    c = new Command("getMapTitle", Command::Any, Command::String);
    modelCommands.append(c);

    c = new Command("getNotePlainText", Command::TreeItem, Command::String);
    modelCommands.append(c);

    c = new Command("getNoteXML", Command::TreeItem, Command::String);
    modelCommands.append(c);

    c = new Command("getSelectionString", Command::TreeItem, Command::String);
    modelCommands.append(c);

    c = new Command("getTaskPriorityDelta", Command::Branch, Command::Int);
    modelCommands.append(c);

    c = new Command("getTaskSleep", Command::Branch, Command::String);
    modelCommands.append(c);

    c = new Command("getTaskSleepDays", Command::Branch, Command::Int);
    modelCommands.append(c);

    c = new Command("getURL", Command::TreeItem, Command::String);
    modelCommands.append(c);

    c = new Command("getVymLink", Command::Branch, Command::String);
    modelCommands.append(c);

    c = new Command("getXLinkColor", Command::XLink, Command::String);
    modelCommands.append(c);

    c = new Command("getXLinkWidth", Command::XLink, Command::Int);
    modelCommands.append(c);

    c = new Command("getXLinkPenStyle", Command::XLink, Command::String);
    modelCommands.append(c);

    c = new Command("getXLinkStyleBegin", Command::XLink, Command::String);
    modelCommands.append(c);

    c = new Command("getXLinkStyleEnd", Command::XLink, Command::String);
    modelCommands.append(c);

    c = new Command("hasActiveFlag", Command::TreeItem, Command::Bool);
    c->addPar(Command::String, false, "Name of flag");
    modelCommands.append(c);

    c = new Command("hasNote", Command::Branch, Command::Bool);
    modelCommands.append(c);

    c = new Command("hasRichTextNote", Command::Branch, Command::Bool);
    modelCommands.append(c);

    c = new Command("hasTask", Command::Branch, Command::Bool);
    modelCommands.append(c);

    c = new Command("importDir", Command::Branch);
    c->addPar(Command::String, false, "Directory name to import");
    modelCommands.append(c);

    c = new Command("initIterator", Command::Branch, Command::Bool);
    c->addPar(Command::String, false, "Name of iterator");
    c->addPar(Command::Bool, true, "Flag to go deep levels first");
    modelCommands.append(c);

    c = new Command("isScrolled", Command::Branch, Command::Bool);
    modelCommands.append(c);

    c = new Command("loadImage", Command::Branch);
    c->addPar(Command::String, false, "Filename of image");
    modelCommands.append(c);

    c = new Command("loadNote", Command::Branch);
    c->addPar(Command::String, false, "Filename of note");
    modelCommands.append(c);

    c = new Command("moveDown", Command::Branch);
    modelCommands.append(c);

    c = new Command("moveUp", Command::Branch);
    modelCommands.append(c);

    c = new Command("moveSlideDown", Command::Any);
    modelCommands.append(c);

    c = new Command("moveSlideUp", Command::Any);
    modelCommands.append(c);

    c = new Command("move", Command::BranchOrImage);
    c->addPar(Command::Double, false, "Position x");
    c->addPar(Command::Double, false, "Position y");
    modelCommands.append(c);

    c = new Command("moveRel", Command::BranchOrImage);
    c->addPar(Command::Double, false, "Position x");
    c->addPar(Command::Double, false, "Position y");
    modelCommands.append(c);

    c = new Command("nextIterator", Command::Branch, Command::Bool);
    c->addPar(Command::String, false, "Name of iterator");
    modelCommands.append(c);

    c = new Command("nop", Command::Any);
    modelCommands.append(c);

    c = new Command("note2URLs", Command::Branch);
    modelCommands.append(c);

    // internally required for undo/redo of changing VymText:
    c = new Command("parseVymText", Command::Branch, Command::Bool);
    c->addPar(Command::String, false,
              "parse XML of VymText, e.g for Heading or VymNote");
    modelCommands.append(c);

    c = new Command("paste", Command::Branch);
    modelCommands.append(c);

    c = new Command("redo", Command::Any);
    modelCommands.append(c);

    c = new Command("relinkTo",
                    Command::TreeItem,
                    Command::Bool); // FIXME different number of parameters for Image or Branch
    c->addPar(Command::String, false, "Selection string of parent");
    c->addPar(Command::Int, false, "Index position");
    c->addPar(Command::Double, true, "Position x");
    c->addPar(Command::Double, true, "Position y");
    modelCommands.append(c);

    c = new Command("remove", Command::TreeItem);
    modelCommands.append(c);

    c = new Command("removeChildren", Command::Branch);
    modelCommands.append(c);

    c = new Command("removeKeepChildren", Command::Branch);
    modelCommands.append(c);

    c = new Command("removeSlide", Command::Any);
    c->addPar(Command::Int, false, "Index of slide to remove");
    modelCommands.append(c);

    c = new Command("repeatLastCommand", Command::Any);
    modelCommands.append(c);

    c = new Command("saveImage", Command::Image);
    c->addPar(Command::String, false, "Filename of image to save");
    c->addPar(Command::String, false, "Format of image to save");
    modelCommands.append(c);

    c = new Command("saveNote", Command::Branch);
    c->addPar(Command::String, false, "Filename of note to save");
    modelCommands.append(c);

    c = new Command("scroll", Command::Branch);
    modelCommands.append(c);

    c = new Command("select", Command::Any, Command::Bool);
    c->addPar(Command::String, false, "Selection string");
    modelCommands.append(c);

    c = new Command("selectFirstBranch", Command::Branch, Command::Bool);
    modelCommands.append(c);

    c = new Command("selectFirstChildBranch", Command::Branch, Command::Bool);
    modelCommands.append(c);

    c = new Command("selectID", Command::Any, Command::Bool);
    c->addPar(Command::String, false, "Unique ID");
    modelCommands.append(c);

    c = new Command("selectLastBranch", Command::Branch, Command::Bool);
    modelCommands.append(c);

    c = new Command("selectLastChildBranch", Command::Branch, Command::Bool);
    modelCommands.append(c);

    c = new Command("selectLastImage", Command::Branch, Command::Bool);
    modelCommands.append(c);

    c = new Command("selectLatestAdded", Command::Any, Command::Bool);
    modelCommands.append(c);

    c = new Command("selectParent", Command::Branch, Command::Bool);
    modelCommands.append(c);

    c = new Command("selectToggle", Command::BranchOrImage, Command::Bool);
    modelCommands.append(c);

    c = new Command("setFlagByName", Command::TreeItem);
    c->addPar(Command::String, false, "Name of flag");
    modelCommands.append(c);

    c = new Command("setTaskPriorityDelta", Command::Branch);
    c->addPar(Command::String, false, "Manually add value to priority of task");
    modelCommands.append(c);

    c = new Command("setTaskSleep", Command::Branch);
    c->addPar(Command::String, false, "Days to sleep");
    modelCommands.append(c);

    c = new Command("setFrameIncludeChildren", Command::BranchOrImage);
    c->addPar(Command::Bool, false,
              "Include or don't include children in frame");
    modelCommands.append(c);

    c = new Command("setFrameType", Command::BranchOrImage);
    c->addPar(Command::String, false, "Type of frame");
    modelCommands.append(c);

    c = new Command("setFramePenColor", Command::BranchOrImage);
    c->addPar(Command::Color, false, "Color of frame border line");
    modelCommands.append(c);

    c = new Command("setFrameBrushColor", Command::BranchOrImage);
    c->addPar(Command::Color, false, "Color of frame background");
    modelCommands.append(c);

    c = new Command("setFramePadding", Command::BranchOrImage);
    c->addPar(Command::Int, false, "Padding around frame");
    modelCommands.append(c);

    c = new Command("setFrameBorderWidth", Command::BranchOrImage);
    c->addPar(Command::Int, false, "Width of frame borderline");
    modelCommands.append(c);

    c = new Command("setHeadingConfluencePageName", Command::Branch);
    modelCommands.append(c);

    c = new Command("setHeadingPlainText", Command::TreeItem);
    c->addPar(Command::String, false, "New heading");
    modelCommands.append(c);

    c = new Command("setHideExport", Command::BranchOrImage);
    c->addPar(Command::Bool, false, "Set if item should be visible in export");
    modelCommands.append(c);

    c = new Command("setIncludeImagesHorizontally", Command::Branch);
    c->addPar(Command::Bool, false,
              "Set if images should be included horizontally in parent branch");
    modelCommands.append(c);

    c = new Command("setIncludeImagesVertically", Command::Branch);
    c->addPar(Command::Bool, false,
              "Set if images should be included vertically in parent branch");
    modelCommands.append(c);

    c = new Command("setHideLinksUnselected", Command::BranchOrImage);
    c->addPar(Command::Bool, false,
              "Set if links of items should be visible for unselected items");
    modelCommands.append(c);

    c = new Command("setMapAnimCurve", Command::Any);
    c->addPar(Command::Int, false,
              "EasingCurve used in animation in MapEditor");
    modelCommands.append(c);

    c = new Command("setMapAuthor", Command::Any);
    c->addPar(Command::String, false, "");
    modelCommands.append(c);

    c = new Command("setMapAnimDuration", Command::Any);
    c->addPar(Command::Int, false,
              "Duration of animation in MapEditor in milliseconds");
    modelCommands.append(c);

    c = new Command("setMapBackgroundColor", Command::Any);
    c->addPar(Command::Color, false, "Color of map background");
    modelCommands.append(c);

    c = new Command("setMapComment", Command::Any);
    c->addPar(Command::String, false, "");
    modelCommands.append(c);

    c = new Command("setMapTitle", Command::Any);
    c->addPar(Command::String, false, "");
    modelCommands.append(c);

    c = new Command("setMapDefLinkColor", Command::Any);
    c->addPar(Command::Color, false, "Default color of links");
    modelCommands.append(c);

    c = new Command("setMapLinkStyle", Command::Any);
    c->addPar(Command::String, false, "Link style in map");
    modelCommands.append(c);

    c = new Command("setMapRotation", Command::Any);
    c->addPar(Command::Double, false, "Rotation of map");
    modelCommands.append(c);

    c = new Command("setMapTitle", Command::Any);
    c->addPar(Command::String, false, "");
    modelCommands.append(c);

    c = new Command("setMapZoom", Command::Any);
    c->addPar(Command::Double, false, "Zoomfactor of map");
    modelCommands.append(c);

    c = new Command("setNotePlainText", Command::Branch);
    c->addPar(Command::String, false, "Note of branch");
    modelCommands.append(c);

    c = new Command("setScaleFactor", Command::Image);
    c->addPar(Command::Double, false, "Scale image by factor f");
    modelCommands.append(c);

    c = new Command("setSelectionColor", Command::Any);
    c->addPar(Command::Color, false, "Color of selection box");
    modelCommands.append(c);

    c = new Command("setSelectionPenColor", Command::Any);
    c->addPar(Command::Color, false, "Color of selection box border");
    modelCommands.append(c);

    c = new Command("setSelectionPenWidth", Command::Any);
    c->addPar(Command::Int, false, "Selection box border width ");
    modelCommands.append(c);

    c = new Command("setSelectionBrushColor", Command::Any);
    c->addPar(Command::Color, false, "Color of selection box background");
    modelCommands.append(c);

    c = new Command("setTaskPriority", Command::Branch);
    c->addPar(Command::Int, false, "Priority of task");
    modelCommands.append(c);

    c = new Command("setTaskSleep", Command::Branch, Command::Bool);
    c->addPar(Command::String, false, "Sleep time of task");
    modelCommands.append(c);

    c = new Command("setURL", Command::TreeItem);
    c->addPar(Command::String, false, "URL of TreeItem");
    modelCommands.append(c);

    c = new Command("setVymLink", Command::Branch);
    c->addPar(Command::String, false, "Vymlink of branch");
    modelCommands.append(c);

    c = new Command("setXLinkColor", Command::XLink);
    c->addPar(Command::String, false, "Color of xlink");
    modelCommands.append(c);

    c = new Command("setXLinkStyle", Command::XLink);
    c->addPar(Command::String, false, "Style of xlink");
    modelCommands.append(c);

    c = new Command("setXLinkStyleBegin", Command::XLink);
    c->addPar(Command::String, false, "Style of xlink begin");
    modelCommands.append(c);

    c = new Command("setXLinkStyleEnd", Command::XLink);
    c->addPar(Command::String, false, "Style of xlink end");
    modelCommands.append(c);

    c = new Command("setXLinkWidth", Command::XLink);
    c->addPar(Command::Int, false, "Width of xlink");
    modelCommands.append(c);

    c = new Command("sleep", Command::Any);
    c->addPar(Command::Int, false, "Sleep (seconds)");
    modelCommands.append(c);

    c = new Command("sortChildren", Command::Branch);
    c->addPar(Command::Bool, true,
              "Sort children of branch in revers order if set");
    modelCommands.append(c);

    c = new Command("toggleFlagByUid", Command::Branch);
    c->addPar(Command::String, false, "Uid of flag to toggle");
    modelCommands.append(c);

    c = new Command("toggleFlagByName", Command::Branch);
    c->addPar(Command::String, false, "Name of flag to toggle");
    modelCommands.append(c);

    c = new Command("toggleFrameIncludeChildren", Command::Branch);
    modelCommands.append(c);

    c = new Command("toggleScroll", Command::Branch);
    modelCommands.append(c);

    c = new Command("toggleTarget", Command::Branch);
    modelCommands.append(c);

    c = new Command("toggleTask", Command::Branch);
    modelCommands.append(c);

    c = new Command("undo", Command::Any);
    modelCommands.append(c);

    c = new Command("unscroll", Command::Branch, Command::Bool);
    modelCommands.append(c);

    c = new Command("unscrollChildren", Command::Branch);
    modelCommands.append(c);

    c = new Command("unselectAll", Command::Any);
    modelCommands.append(c);

    c = new Command("unsetFlagByName", Command::Branch);
    c->addPar(Command::String, false, "Name of flag to unset");
    modelCommands.append(c);

    //
    // Below are the commands for vym itself:
    //

    c = new Command("clearConsole", Command::Any);
    vymCommands.append(c);

    c = new Command("closeMapWithID", Command::Any);
    c->addPar(Command::Int, false, "ID of map (unsigned int)");
    vymCommands.append(c);

    c = new Command("currentMap", Command::Any);
    vymCommands.append(c);

    c = new Command("currentMapIndex", Command::Any);
    vymCommands.append(c);

    c = new Command("editHeading", Command::Branch);
    vymCommands.append(c);

    c = new Command("loadMap", Command::Any);
    c->addPar(Command::String, false, "Path to map");
    vymCommands.append(c);

    c = new Command("mapCount", Command::Any);
    vymCommands.append(c);

    c = new Command("gotoMap", Command::Any);
    c->addPar(Command::Int, false, "Index of map");
    vymCommands.append(c);

    c = new Command("selectQuickColor", Command::Any);
    c->addPar(Command::Int, false, "Index of quick color [0..6]");
    vymCommands.append(c);

    c = new Command("currentColor", Command::Any);
    vymCommands.append(c);

    c = new Command("toggleTreeEditor", Command::Any);
    vymCommands.append(c);

    c = new Command("version", Command::Any);
    vymCommands.append(c);
}

void Main::cloneActionMapEditor(QAction *a, QKeySequence ks)
{
    a->setShortcut(ks);
    a->setShortcutContext(Qt::WidgetShortcut);
    mapEditorActions.append(a);
}

// File Actions
void Main::setupFileActions()
{
    QString tag = tr("&Map", "Menu for file actions");
    QMenu *fileMenu = menuBar()->addMenu(tag);

    QAction *a;
    a = new QAction(QPixmap(":/filenew.png"), tr("&New map", "File menu"),
                    this);
    switchboard.addSwitch("fileMapNew", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(fileNew()));
    cloneActionMapEditor(a, Qt::CTRL + Qt::Key_N);
    fileMenu->addAction(a);
    actionFileNew = a;

    a = new QAction(QPixmap(":/filenewcopy.png"),
                    tr("&Copy to new map", "File menu"), this);
    switchboard.addSwitch("fileMapNewCopy", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(fileNewCopy()));
    cloneActionMapEditor(a, Qt::CTRL + Qt::SHIFT + Qt::Key_C);
    fileMenu->addAction(a);
    actionFileNewCopy = a;

    a = new QAction(QPixmap(":/fileopen.png"), tr("&Open...", "File menu"),
                    this);
    switchboard.addSwitch("fileMapOpen", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(fileLoad()));
    cloneActionMapEditor(a, Qt::CTRL + Qt::Key_L);
    fileMenu->addAction(a);
    actionFileOpen = a;

    a = new QAction(tr("&Restore last session", "Edit menu"), this);
    a->setShortcut(Qt::CTRL + Qt::Key_R);
    switchboard.addSwitch("fileMapRestore", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(fileRestoreSession()));
    fileMenu->addAction(a);
    actionListFiles.append(a);
    actionCopy = a;

    fileLastMapsMenu = fileMenu->addMenu(tr("Open Recent", "File menu"));
    fileMenu->addSeparator();

    a = new QAction(QPixmap(":/filesave.svg"), tr("&Save...", "File menu"),
                    this);
    switchboard.addSwitch("fileMapSave", shortcutScope, a, tag);
    cloneActionMapEditor(a, Qt::CTRL + Qt::Key_S);
    fileMenu->addAction(a);
    restrictedMapActions.append(a);
    connect(a, SIGNAL(triggered()), this, SLOT(fileSave()));
    actionFileSave = a;

    a = new QAction(QPixmap(":/filesaveas.png"), tr("Save &As...", "File menu"),
                    this);
    fileMenu->addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(fileSaveAs()));

    a = new QAction(tr("Save as default map", "File menu"), this);
    fileMenu->addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(fileSaveAsDefault()));

    fileMenu->addSeparator();

    fileImportMenu = fileMenu->addMenu(tr("Import", "File menu"));

    a = new QAction( tr("Firefox Bookmarks", "Import filters") + 
                        tr("(experimental)"),
                    this);
    connect(a, SIGNAL(triggered()), this,
            SLOT(fileImportFirefoxBookmarks()));
    fileImportMenu->addAction(a);

    a = new QAction("Freemind...", this);
    connect(a, SIGNAL(triggered()), this, SLOT(fileImportFreemind()));
    fileImportMenu->addAction(a);

    a = new QAction("Mind Manager...", this);
    connect(a, SIGNAL(triggered()), this, SLOT(fileImportMM()));
    fileImportMenu->addAction(a);

    a = new QAction(tr("Import Dir...", "Import Filters") + " " +
                        tr("(still experimental)"),
                    this);
    connect(a, SIGNAL(triggered()), this, SLOT(fileImportDir()));
    fileImportMenu->addAction(a);

    fileExportMenu = fileMenu->addMenu(tr("Export", "File menu"));

    a = new QAction(QPixmap(":/file-document-export.png"),
                    tr("Repeat last export (%1)").arg("-"), this);
    switchboard.addSwitch("fileExportLast", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(fileExportLast()));
    cloneActionMapEditor(a, Qt::CTRL + Qt::Key_E);
    fileExportMenu->addAction(a);
    actionFileExportLast = a;
    actionListFiles.append(a);

    a = new QAction(tr("Webpage (HTML)...", "File export menu"), this);
    connect(a, SIGNAL(triggered()), this, SLOT(fileExportHTML()));
    fileExportMenu->addAction(a);
    actionListFiles.append(a);

    a = new QAction(tr("Confluence (HTML)...", "File export menu") + " " + " " +
                        tr("(still experimental)"),
                    this);
    connect(a, SIGNAL(triggered()), this, SLOT(fileExportConfluence()));
    fileExportMenu->addAction(a);
    actionListFiles.append(a);
    actionFileExportConfluence = a;

    a = new QAction( tr("Firefox Bookmarks", "File export menu") + 
                        tr("(still experimental)"),
                    this);
    connect(a, SIGNAL(triggered()), this,
            SLOT(fileExportFirefoxBookmarks()));
    fileExportMenu->addAction(a);
    actionListFiles.append(a);

    a = new QAction(tr("Text (ASCII)...", "File export menu"), this);
    connect(a, SIGNAL(triggered()), this, SLOT(fileExportASCII()));
    fileExportMenu->addAction(a);
    actionListFiles.append(a);

    a = new QAction(tr("Text (Markdown)...", "File export menu") + " " +
                        tr("(still experimental)"),
                    this);
    connect(a, SIGNAL(triggered()), this, SLOT(fileExportMarkdown()));
    fileExportMenu->addAction(a);
    actionListFiles.append(a);

    a = new QAction(tr("Text with tasks", "File export menu") + " " +
                        tr("(still experimental)"),
                    this);
    connect(a, SIGNAL(triggered()), this, SLOT(fileExportASCIITasks()));
    fileExportMenu->addAction(a);
    actionListFiles.append(a);

    a = new QAction(tr("Text (A&O report)...", "Export format"), this);
    connect(a, SIGNAL(triggered()), this, SLOT(fileExportAO()));
    fileExportMenu->addAction(a);
    actionListFiles.append(a);

    a = new QAction(tr("Image%1", "File export menu").arg("..."), this);
    connect(a, SIGNAL(triggered()), this, SLOT(fileExportImage()));
    fileExportMenu->addAction(a);
    actionListFiles.append(a);

    a = new QAction(tr("PDF%1", "File export menu").arg("..."), this);
    connect(a, SIGNAL(triggered()), this, SLOT(fileExportPDF()));
    fileExportMenu->addAction(a);
    actionListFiles.append(a);

    a = new QAction(tr("SVG%1", "File export menu").arg("..."), this);
    connect(a, SIGNAL(triggered()), this, SLOT(fileExportSVG()));
    fileExportMenu->addAction(a);
    actionListFiles.append(a);

    a = new QAction("LibreOffice...", this);
    connect(a, SIGNAL(triggered()), this, SLOT(fileExportImpress()));
    fileExportMenu->addAction(a);
    actionListFiles.append(a);

    a = new QAction("XML...", this);
    connect(a, SIGNAL(triggered()), this, SLOT(fileExportXML()));
    fileExportMenu->addAction(a);
    actionListFiles.append(a);

    a = new QAction(tr("CSV...") + " " + tr("(still experimental)"), this);
    connect(a, SIGNAL(triggered()), this, SLOT(fileExportCSV()));
    fileExportMenu->addAction(a);
    actionListFiles.append(a);

    a = new QAction("Taskjuggler... " + tr("(still experimental)"), this);
    connect(a, SIGNAL(triggered()), this, SLOT(fileExportTaskjuggler()));
    fileExportMenu->addAction(a);
    actionListFiles.append(a);

    a = new QAction("OrgMode... " + tr("(still experimental)"), this);
    connect(a, SIGNAL(triggered()), this, SLOT(fileExportOrgMode()));
    fileExportMenu->addAction(a);
    actionListFiles.append(a);

    a = new QAction("LaTeX... " + tr("(still experimental)"), this);
    connect(a, SIGNAL(triggered()), this, SLOT(fileExportLaTeX()));
    fileExportMenu->addAction(a);
    actionListFiles.append(a);

    fileMenu->addSeparator();

    a = new QAction(tr("Properties"), this);
    switchboard.addSwitch("editMapProperties", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editMapProperties()));
    fileMenu->addAction(a);
    actionListFiles.append(a);
    actionMapProperties = a;

    fileMenu->addSeparator();

    a = new QAction(QPixmap(":/fileprint.png"), tr("&Print") + QString("..."),
                    this);
    a->setShortcut(Qt::CTRL + Qt::Key_P);
    switchboard.addSwitch("fileMapPrint", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(filePrint()));
    fileMenu->addAction(a);
    unrestrictedMapActions.append(a);
    actionFilePrint = a;

    a = new QAction(QPixmap(":/fileclose.png"), tr("&Close Map", "File menu"),
                    this);
    a->setShortcut(Qt::CTRL + Qt::Key_W);
    switchboard.addSwitch("fileMapClose", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(fileCloseMap()));
    fileMenu->addAction(a);

    a = new QAction(QPixmap(":/exit.png"), tr("E&xit", "File menu"), this);
    a->setShortcut(Qt::CTRL + Qt::Key_Q);
    switchboard.addSwitch("fileExit", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(fileExitVYM()));
    fileMenu->addAction(a);

    a = new QAction("Toggle winter mode", this);
    a->setShortcut(Qt::CTRL + Qt::Key_Asterisk);
    a->setShortcutContext(Qt::WidgetShortcut);

    if (settings.value("/mainwindow/showTestMenu", false).toBool()) {
        addAction(a);
        mapEditorActions.append(a);
        switchboard.addSwitch("mapWinterMode", shortcutScope, a, tag);
    }
    connect(a, SIGNAL(triggered()), this, SLOT(toggleWinter()));
    actionToggleWinter = a;
}

// Edit Actions
void Main::setupEditActions()
{
    QString tag = tr("E&dit", "Edit menu");
    QMenu *editMenu = menuBar()->addMenu(tag);

    QAction *a;
    a = new QAction(QPixmap(":/undo.png"), tr("&Undo", "Edit menu"), this);
    a->setShortcut(Qt::CTRL + Qt::Key_Z);
    a->setShortcutContext(Qt::WidgetShortcut);
    a->setEnabled(false);
    editMenu->addAction(a);
    mapEditorActions.append(a);
    restrictedMapActions.append(a);
    switchboard.addSwitch("mapUndo", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editUndo()));
    actionUndo = a;

    a = new QAction(QPixmap(":/redo.png"), tr("&Redo", "Edit menu"), this);
    a->setShortcut(Qt::CTRL + Qt::Key_Y);
    a->setShortcutContext(Qt::WidgetShortcut);
    editMenu->addAction(a);
    restrictedMapActions.append(a);
    mapEditorActions.append(a);
    switchboard.addSwitch("mapRedo", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editRedo()));
    actionRedo = a;

    editMenu->addSeparator();
    a = new QAction(QPixmap(":/editcopy.png"), tr("&Copy", "Edit menu"), this);
    a->setShortcut(Qt::CTRL + Qt::Key_C);
    a->setShortcutContext(Qt::WidgetShortcut);
    a->setEnabled(false);
    editMenu->addAction(a);
    unrestrictedMapActions.append(a);
    mapEditorActions.append(a);
    switchboard.addSwitch("mapCopy", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editCopy()));
    actionCopy = a;

    a = new QAction(QPixmap(":/editcut.png"), tr("Cu&t", "Edit menu"), this);
    a->setShortcut(Qt::CTRL + Qt::Key_X);
    a->setEnabled(false);
    a->setShortcutContext(Qt::WidgetShortcut);
    editMenu->addAction(a);
    restrictedMapActions.append(a);
    mapEditorActions.append(a);
    restrictedMapActions.append(a);
    switchboard.addSwitch("mapCut", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editCut()));
    addAction(a);
    actionCut = a;

    a = new QAction(QPixmap(":/editpaste.png"), tr("&Paste", "Edit menu"),
                    this);
    connect(a, SIGNAL(triggered()), this, SLOT(editPaste()));
    a->setShortcut(Qt::CTRL + Qt::Key_V);
    a->setShortcutContext(Qt::WidgetShortcut);
    a->setEnabled(false);
    editMenu->addAction(a);
    restrictedMapActions.append(a);
    mapEditorActions.append(a);
    switchboard.addSwitch("mapPaste", shortcutScope, a, tag);
    actionPaste = a;

    // Shortcut to delete selection
    a = new QAction(tr("Delete Selection", "Edit menu"), this);
    a->setShortcut(Qt::Key_Delete);
    a->setShortcutContext(Qt::WindowShortcut);
    switchboard.addSwitch("mapDelete", shortcutScope, a, tag);
    addAction(a);
    editMenu->addAction(a);
    actionListItems.append(a);
    actionDelete = a;

    connect(a, SIGNAL(triggered()), this, SLOT(editDeleteSelection()));
    a = new QAction(tr("Delete Selection", "Edit menu"), this);
    a->setShortcut(Qt::Key_D);
    a->setShortcutContext(Qt::WindowShortcut);
    switchboard.addSwitch("mapDelete", shortcutScope, a, tag);
    addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(editDeleteSelection()));
    editMenu->addAction(a);
    actionListItems.append(a);
    actionDeleteAlt = a;

    // Shortcut to add attribute
    a = new QAction(tr("Add attribute") + " (test)", this);
    if (settings.value("/mainwindow/showTestMenu", false).toBool()) {
        a->setShortcutContext(Qt::WindowShortcut);
        switchboard.addSwitch("mapAddAttribute", shortcutScope, a, tag);
        connect(a, SIGNAL(triggered()), this, SLOT(editAddAttribute()));
        editMenu->addAction(a);
    }
    actionAddAttribute = a;

    // Shortcut to add mapcenter
    a = new QAction(QPixmap(":/newmapcenter.png"),
                    tr("Add mapcenter", "Canvas context menu"), this);
    a->setShortcut(Qt::Key_C);
    a->setShortcutContext(Qt::WindowShortcut);
    switchboard.addSwitch("mapAddCenter", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editAddMapCenter()));
    editMenu->addAction(a);
    actionListFiles.append(a);
    actionAddMapCenter = a;

    // Shortcut to add branch
    a = new QAction(QPixmap(":/newbranch.png"),
                    tr("Add branch as child", "Edit menu"), this);
    switchboard.addSwitch("mapEditNewBranch", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editNewBranch()));
    cloneActionMapEditor(a, Qt::Key_A);
    taskEditorActions.append(a);
    actionListBranches.append(a);
    actionAddBranch = a;

    // Add branch by inserting it at selection
    a = new QAction(tr("Add branch (insert)", "Edit menu"), this);
    switchboard.addSwitch("mapEditAddBranchBefore", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editNewBranchBefore()));
    editMenu->addAction(a);
    actionListBranches.append(a);
    actionAddBranchBefore = a;

    // Add branch above
    a = new QAction(tr("Add branch above", "Edit menu"), this);
    a->setShortcut(Qt::SHIFT + Qt::Key_Insert);
    a->setShortcutContext(Qt::WindowShortcut);
    switchboard.addSwitch("mapEditAddBranchAbove", shortcutScope, a, tag);
    addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(editNewBranchAbove()));
    a->setEnabled(false);
    actionListBranches.append(a);
    actionAddBranchAbove = a;

    a = new QAction(tr("Add branch above", "Edit menu"), this);
    a->setShortcut(Qt::SHIFT + Qt::Key_A);
    a->setShortcutContext(Qt::WindowShortcut);
    switchboard.addSwitch("mapEditAddBranchAboveAlt", shortcutScope, a, tag);
    addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(editNewBranchAbove()));
    actionListBranches.append(a);
    editMenu->addAction(a);

    // Add branch below
    a = new QAction(tr("Add branch below", "Edit menu"), this);
    a->setShortcut(Qt::CTRL + Qt::Key_Insert);
    a->setShortcutContext(Qt::WindowShortcut);
    switchboard.addSwitch("mapEditAddBranchBelow", shortcutScope, a, tag);
    addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(editNewBranchBelow()));
    a->setEnabled(false);
    actionListBranches.append(a);

    a = new QAction(tr("Add branch below", "Edit menu"), this);
    a->setShortcut(Qt::CTRL + Qt::Key_A);
    a->setShortcutContext(Qt::WindowShortcut);
    switchboard.addSwitch("mapEditAddBranchBelowAlt", shortcutScope, a, tag);
    addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(editNewBranchBelow()));
    actionListBranches.append(a);
    actionAddBranchBelow = a;

    a = new QAction(QPixmap(":/up.png"), tr("Move branch up", "Edit menu"),
                    this);
    a->setShortcut(Qt::Key_PageUp);
    a->setShortcutContext(Qt::WidgetShortcut);
    mapEditorActions.append(a);
    taskEditorActions.append(a);
    restrictedMapActions.append(a);
    actionListBranches.append(a);
    editMenu->addAction(a);
    switchboard.addSwitch("mapEditMoveBranchUp", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editMoveUp()));
    actionMoveUp = a;

    a = new QAction(QPixmap(":/down.png"), tr("Move branch down", "Edit menu"),
                    this);
    a->setShortcut(Qt::Key_PageDown);
    a->setShortcutContext(Qt::WidgetShortcut);
    mapEditorActions.append(a);
    taskEditorActions.append(a);
    restrictedMapActions.append(a);
    actionListBranches.append(a);
    editMenu->addAction(a);
    switchboard.addSwitch("mapEditMoveBranchDown", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editMoveDown()));
    actionMoveDown = a;

    a = new QAction(QPixmap(":up-diagonal-right.png"), tr("Move branch diagonally up", "Edit menu"),
                    this);
    a->setShortcut(Qt::CTRL + Qt::Key_PageUp);
    a->setShortcutContext(Qt::WidgetShortcut);
    mapEditorActions.append(a);
    taskEditorActions.append(a);
    restrictedMapActions.append(a);
    actionListBranches.append(a);
    editMenu->addAction(a);
    switchboard.addSwitch("mapEditMoveBranchUpDiagonally", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editMoveUpDiagonally()));
    actionMoveUpDiagonally = a;

    a = new QAction(QPixmap(":down-diagonal-left.png"), tr("Move branch diagonally down", "Edit menu"),
                    this);
    a->setShortcut(Qt::CTRL + Qt::Key_PageDown);
    a->setShortcutContext(Qt::WidgetShortcut);
    mapEditorActions.append(a);
    taskEditorActions.append(a);
    restrictedMapActions.append(a);
    actionListBranches.append(a);
    editMenu->addAction(a);
    switchboard.addSwitch("mapEditMoveBranchDownDiagonally", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editMoveDownDiagonally()));
    actionMoveDownDiagonally = a;

    a = new QAction(QPixmap(), tr("&Detach", "Context menu"), this);
    a->setStatusTip(tr("Detach branch and use as mapcenter", "Context menu"));
    a->setShortcut(Qt::Key_D + Qt::SHIFT);
    switchboard.addSwitch("mapDetachBranch", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editDetach()));
    editMenu->addAction(a);
    actionListBranches.append(a);
    actionDetach = a;

    a = new QAction(QPixmap(":/editsort.png"), tr("Sort children", "Edit menu"),
                    this);
    a->setEnabled(true);
    a->setShortcut(Qt::Key_O);
    switchboard.addSwitch("mapSortBranches", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editSortChildren()));
    editMenu->addAction(a);
    actionListBranches.append(a);
    actionSortChildren = a;

    a = new QAction(QPixmap(":/editsortback.png"),
                    tr("Sort children backwards", "Edit menu"), this);
    a->setEnabled(true);
    a->setShortcut(Qt::SHIFT + Qt::Key_O);
    switchboard.addSwitch("mapSortBranchesReverse", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editSortBackChildren()));
    editMenu->addAction(a);
    actionListBranches.append(a);
    actionSortBackChildren = a;

    a = new QAction(QPixmap(":/flag-scrolled-right.png"),
                    tr("Scroll branch", "Edit menu"), this);
    a->setShortcut(Qt::Key_S);
    switchboard.addSwitch("mapToggleScroll", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editToggleScroll()));
    editMenu->addAction(a);
    actionListBranches.append(a);
    a->setEnabled(false);
    a->setCheckable(true);
    addAction(a);
    actionListBranches.append(a);
    actionToggleScroll = a;

    a = new QAction(tr("Unscroll children", "Edit menu"), this);
    editMenu->addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(editUnscrollChildren()));
    actionListBranches.append(a);

    a = new QAction(tr("Grow selection", "Edit menu"), this);
    a->setShortcut(Qt::CTRL + Qt::Key_Plus);
    switchboard.addSwitch("mapGrowSelection", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editGrowSelectionSize()));
    editMenu->addAction(a);
    actionListBranches.append(a);
    actionListItems.append(a);
    actionGrowSelectionSize = a;

    a = new QAction(tr("Shrink selection", "Edit menu"), this);
    a->setShortcut(Qt::CTRL + Qt::Key_Minus);
    switchboard.addSwitch("mapShrinkSelection", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editShrinkSelectionSize()));
    editMenu->addAction(a);
    actionListBranches.append(a);
    actionListItems.append(a);
    actionShrinkSelectionSize = a;

    a = new QAction(tr("Reset selection size", "Edit menu"), this);
    a->setShortcut(Qt::CTRL + Qt::Key_0);
    switchboard.addSwitch("mapResetSelectionSize", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editResetSelectionSize()));
    editMenu->addAction(a);
    actionListBranches.append(a);
    actionListItems.append(a);
    actionResetSelectionSize = a;

    editMenu->addSeparator();

    a = new QAction(QPixmap(), "TE: " + tr("Collapse one level", "Edit menu"),
                    this);
    a->setShortcut(Qt::Key_Less + Qt::CTRL);
    switchboard.addSwitch("mapCollapseOneLevel", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editCollapseOneLevel()));
    editMenu->addAction(a);
    a->setEnabled(false);
    a->setCheckable(false);
    actionListBranches.append(a);
    addAction(a);
    actionCollapseOneLevel = a;

    a = new QAction(QPixmap(),
                    "TE: " + tr("Collapse unselected levels", "Edit menu"),
                    this);
    a->setShortcut(Qt::Key_Less);
    switchboard.addSwitch("mapCollapseUnselectedLevels", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editCollapseUnselected()));
    editMenu->addAction(a);
    a->setEnabled(false);
    a->setCheckable(false);
    actionListBranches.append(a);
    addAction(a);
    actionCollapseUnselected = a;

    a = new QAction(QPixmap(), tr("Expand all branches", "Edit menu"), this);
    connect(a, SIGNAL(triggered()), this, SLOT(editExpandAll()));
    actionExpandAll = a;
    actionExpandAll->setEnabled(false);
    actionExpandAll->setCheckable(false);
    actionListBranches.append(actionExpandAll);
    addAction(a);

    a = new QAction(QPixmap(), tr("Expand one level", "Edit menu"), this);
    a->setShortcut(Qt::Key_Greater);
    switchboard.addSwitch("mapExpandOneLevel", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editExpandOneLevel()));
    a->setEnabled(false);
    a->setCheckable(false);
    addAction(a);
    actionListBranches.append(a);
    actionExpandOneLevel = a;

    tag = tr("References Context menu", "Shortcuts");
    a = new QAction(QPixmap(":/flag-url.svg"), tr("Open URL", "Edit menu"),
                    this);
    a->setShortcut(Qt::SHIFT + Qt::Key_U);
    switchboard.addSwitch("mapOpenUrl", shortcutScope, a, tag);
    addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(editOpenURL()));
    actionListBranches.append(a);
    actionOpenURL = a;

    a = new QAction(tr("Open URL in new tab", "Edit menu"), this);
    // a->setShortcut (Qt::CTRL+Qt::Key_U );
    switchboard.addSwitch("mapOpenUrlTab", shortcutScope, a, tag);
    addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(editOpenURLTab()));
    actionListBranches.append(a);
    actionOpenURLTab = a;

    a = new QAction(tr("Open all URLs in subtree (including scrolled branches)",
                       "Edit menu"),
                    this);
    a->setShortcut(Qt::CTRL + Qt::Key_U);
    switchboard.addSwitch("mapOpenUrlsSubTree", shortcutScope, a, tag);
    addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(editOpenMultipleVisURLTabs()));
    actionListBranches.append(a);
    actionOpenMultipleVisURLTabs = a;

    a = new QAction(tr("Open all URLs in subtree", "Edit menu"), this);
    switchboard.addSwitch("mapOpenMultipleUrlTabs", shortcutScope, a, tag);
    addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(editOpenMultipleURLTabs()));
    actionListBranches.append(a);
    actionOpenMultipleURLTabs = a;

    a = new QAction(QPixmap(), tr("Extract URLs from note", "Edit menu"), this);
    a->setShortcut(Qt::SHIFT + Qt::Key_N);
    a->setShortcutContext(Qt::WindowShortcut);
    switchboard.addSwitch("mapUrlsFromNote", shortcutScope, a, tag);
    addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(editNote2URLs()));
    actionListBranches.append(a);
    actionGetURLsFromNote = a;

    a = new QAction(QPixmap(":/flag-urlnew.svg"),
                    tr("Edit URL...", "Edit menu"), this);
    a->setShortcut(Qt::Key_U);
    a->setShortcutContext(Qt::WindowShortcut);
    switchboard.addSwitch("mapEditURL", shortcutScope, a, tag);
    addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(editURL()));
    actionListBranches.append(a);
    actionURLNew = a;

    a = new QAction(QPixmap(), tr("Edit local URL...", "Edit menu"), this);
    // a->setShortcut (Qt::SHIFT +  Qt::Key_U );
    a->setShortcutContext(Qt::WindowShortcut);
    switchboard.addSwitch("mapEditLocalURL", shortcutScope, a, tag);
    addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(editLocalURL()));
    actionListBranches.append(a);
    actionLocalURL = a;

    a = new QAction(tr("Use heading for URL", "Edit menu"), this);
    //a->setShortcut(Qt::ALT + Qt::Key_U);
    a->setShortcutContext(Qt::ApplicationShortcut);
    a->setEnabled(false);
    switchboard.addSwitch("mapHeading2URL", shortcutScope, a, tag);
    addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(editHeading2URL()));
    actionListBranches.append(a);
    actionHeading2URL = a;

    tag = "JIRA";
    a = new QAction(tr("Get data from JIRA for subtree", "Edit menu"),
                    this);
    a->setShortcut(Qt::Key_J + Qt::SHIFT);
    a->setShortcutContext(Qt::WindowShortcut);
    switchboard.addSwitch("mapUpdateSubTreeFromJira", shortcutScope, a, tag);
    addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(getJiraDataSubtree()));
    actionGetJiraDataSubtree = a;

    a = new QAction(tr("Get page name from Confluence", "Edit menu"),
                    this);
    //    a->setShortcut ( Qt::Key_J + Qt::CTRL);
    //    a->setShortcutContext (Qt::WindowShortcut);
    //    switchboard.addSwitch ("mapUpdateSubTreeFromJira", shortcutScope, a,
    //    tag);
    addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(setHeadingConfluencePageName()));
    actionListBranches.append(a);
    actionGetConfluencePageName = a;

    tag = tr("vymlinks - linking maps", "Shortcuts");
    a = new QAction(QPixmap(":/flag-vymlink.png"),
                    tr("Open linked map", "Edit menu"), this);
    a->setShortcut(Qt::SHIFT + Qt::Key_V);
    a->setEnabled(false);
    switchboard.addSwitch("mapOpenVymLink", shortcutScope, a, tag);
    addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(editOpenVymLink()));
    actionListBranches.append(a);
    actionOpenVymLink = a;

    a = new QAction(QPixmap(":/flag-vymlink.png"),
                    tr("Open linked map in background tab", "Edit menu"), this);
    a->setEnabled(false);
    switchboard.addSwitch("mapOpenVymLink", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editOpenVymLinkBackground()));
    actionListBranches.append(a);
    actionOpenVymLinkBackground = a;

    a = new QAction(QPixmap(), tr("Open all vym links in subtree", "Edit menu"),
                    this);
    a->setEnabled(false);
    switchboard.addSwitch("mapOpenMultipleVymLinks", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editOpenMultipleVymLinks()));
    actionListBranches.append(a);
    actionOpenMultipleVymLinks = a;

    a = new QAction(QPixmap(":/flag-vymlinknew.png"),
                    tr("Edit vym link...", "Edit menu"), this);
    a->setShortcut(Qt::Key_V);
    a->setShortcutContext(Qt::WindowShortcut);
    a->setEnabled(false);
    switchboard.addSwitch("mapEditVymLink", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editVymLink()));
    actionListBranches.append(a);
    actionEditVymLink = a;

    a = new QAction(tr("Delete vym link", "Edit menu"), this);
    a->setEnabled(false);
    switchboard.addSwitch("mapDeleteVymLink", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editDeleteVymLink()));
    actionListBranches.append(a);
    actionDeleteVymLink = a;

    tag = tr("Exports", "Shortcuts");
    a = new QAction(QPixmap(":/flag-hideexport.png"),
                    tr("Hide in exports", "Edit menu"), this);
    a->setShortcut(Qt::Key_H);
    a->setShortcutContext(Qt::WindowShortcut);
    a->setCheckable(true);
    a->setEnabled(false);
    addAction(a);
    switchboard.addSwitch("mapToggleHideExport", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editToggleHideExport()));
    actionListItems.append(a);
    actionToggleHideExport = a;

    tag = tr("Tasks", "Shortcuts");
    a = new QAction(QPixmap(":/taskeditor.png"), tr("Toggle task", "Edit menu"),
                    this);
    a->setShortcut(Qt::Key_W + Qt::SHIFT);
    a->setShortcutContext(Qt::WindowShortcut);
    a->setCheckable(true);
    a->setEnabled(false);
    addAction(a);
    switchboard.addSwitch("mapToggleTask", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editToggleTask()));
    actionListBranches.append(a);
    actionToggleTask = a;

    a = new QAction(QPixmap(), tr("Cycle task status", "Edit menu"), this);
    a->setShortcut(Qt::Key_W);
    a->setShortcutContext(Qt::WindowShortcut);
    a->setCheckable(false);
    a->setEnabled(false);
    addAction(a);
    switchboard.addSwitch("mapCycleTaskStatus", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editCycleTaskStatus()));
    actionListBranches.append(a);
    actionCycleTaskStatus = a;

    a = new QAction(QPixmap(), tr("Reset delta priority for visible tasks", "Reset delta"), this);
    a->setShortcutContext(Qt::WindowShortcut);
    a->setCheckable(false);
    a->setEnabled(false);
    addAction(a);
    switchboard.addSwitch("mapResetTaskDeltaPrio", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editTaskResetDeltaPrio()));
    actionListBranches.append(a);
    actionTaskResetDeltaPrio = a;

    a = new QAction(QPixmap(), tr("Reset sleep", "Task sleep"), this);
    a->setShortcutContext(Qt::WindowShortcut);
    a->setCheckable(false);
    a->setEnabled(false);
    a->setData(0);
    addAction(a);
    switchboard.addSwitch("mapResetSleep", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
    actionListBranches.append(a);
    actionTaskSleep0 = a;

    a = new QAction(QPixmap(),
                    tr("Sleep %1 days", "Task sleep").arg("n") + "...", this);
    a->setShortcutContext(Qt::WindowShortcut);
    a->setShortcut(Qt::Key_Q + Qt::SHIFT);
    a->setCheckable(false);
    a->setEnabled(false);
    a->setData(-1);
    addAction(a);
    switchboard.addSwitch("mapTaskSleepN", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
    actionListBranches.append(a);
    actionTaskSleepN = a;

    a = new QAction(QPixmap(), tr("Sleep %1 day", "Task sleep").arg(1), this);
    a->setShortcutContext(Qt::WindowShortcut);
    a->setCheckable(false);
    a->setEnabled(false);
    a->setData(1);
    addAction(a);
    switchboard.addSwitch("mapTaskSleep1", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
    actionListBranches.append(a);
    actionTaskSleep1 = a;

    a = new QAction(QPixmap(), tr("Sleep %1 days", "Task sleep").arg(2), this);
    a->setShortcutContext(Qt::WindowShortcut);
    a->setCheckable(false);
    a->setEnabled(false);
    a->setData(2);
    addAction(a);
    switchboard.addSwitch("mapTaskSleep2", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
    actionListBranches.append(a);
    actionTaskSleep2 = a;

    a = new QAction(QPixmap(), tr("Sleep %1 days", "Task sleep").arg(3), this);
    a->setShortcutContext(Qt::WindowShortcut);
    a->setCheckable(false);
    a->setEnabled(false);
    a->setData(3);
    addAction(a);
    switchboard.addSwitch("mapTaskSleep3", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
    actionListBranches.append(a);
    actionTaskSleep3 = a;

    a = new QAction(QPixmap(), tr("Sleep %1 days", "Task sleep").arg(4), this);
    a->setShortcutContext(Qt::WindowShortcut);
    a->setCheckable(false);
    a->setEnabled(false);
    a->setData(4);
    addAction(a);
    switchboard.addSwitch("mapTaskSleep4", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
    actionListBranches.append(a);
    actionTaskSleep4 = a;

    a = new QAction(QPixmap(), tr("Sleep %1 days", "Task sleep").arg(5), this);
    a->setShortcutContext(Qt::WindowShortcut);
    a->setCheckable(false);
    a->setEnabled(false);
    a->setData(5);
    addAction(a);
    switchboard.addSwitch("mapTaskSleep5", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
    actionListBranches.append(a);
    actionTaskSleep5 = a;

    a = new QAction(QPixmap(), tr("Sleep %1 days", "Task sleep").arg(7), this);
    a->setShortcutContext(Qt::WindowShortcut);
    a->setCheckable(false);
    a->setEnabled(false);
    a->setData(7);
    addAction(a);
    switchboard.addSwitch("mapTaskSleep7", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
    actionListBranches.append(a);
    actionTaskSleep7 = a;

    a = new QAction(QPixmap(), tr("Sleep %1 weeks", "Task sleep").arg(2), this);
    a->setShortcutContext(Qt::WindowShortcut);
    a->setCheckable(false);
    a->setEnabled(false);
    a->setData(14);
    addAction(a);
    switchboard.addSwitch("mapTaskSleep14", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
    actionListBranches.append(a);
    actionTaskSleep14 = a;

    a = new QAction(QPixmap(), tr("Sleep %1 weeks", "Task sleep").arg(4), this);
    a->setShortcutContext(Qt::WindowShortcut);
    a->setCheckable(false);
    a->setEnabled(false);
    a->setData(28);
    addAction(a);
    switchboard.addSwitch("mapTaskSleep28", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
    actionListBranches.append(a);
    actionTaskSleep28 = a;

    // Import at selection (adding to selection)
    a = new QAction(tr("Add map (insert)", "Edit menu"), this);
    connect(a, SIGNAL(triggered()), this, SLOT(editImportAdd()));
    a->setEnabled(false);
    actionListBranches.append(a);
    actionImportAdd = a;

    // Import at selection (replacing selection)
    a = new QAction(tr("Add map (replace)", "Edit menu"), this);
    connect(a, SIGNAL(triggered()), this, SLOT(editImportReplace()));
    a->setEnabled(false);
    actionListBranches.append(a);
    actionImportReplace = a;

    // Save selection
    a = new QAction(tr("Save selection", "Edit menu"), this);
    connect(a, SIGNAL(triggered()), this, SLOT(editSaveBranch()));
    a->setEnabled(false);
    actionListBranches.append(a);
    actionSaveBranch = a;

    tag = tr("Removing parts of a map", "Shortcuts");

    // Only remove branch, not its children
    a = new QAction(
        tr("Remove only branch and keep its children ", "Edit menu"), this);
    a->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_X);
    connect(a, SIGNAL(triggered()), this, SLOT(editDeleteKeepChildren()));
    a->setEnabled(false);
    addAction(a);
    switchboard.addSwitch("mapDeleteKeepChildren", shortcutScope, a, tag);
    actionListBranches.append(a);
    actionDeleteKeepChildren = a;

    // Only remove children of a branch
    a = new QAction(tr("Remove children", "Edit menu"), this);
    a->setShortcut(Qt::SHIFT + Qt::Key_X);
    addAction(a);
    switchboard.addSwitch("mapDeleteChildren", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editDeleteChildren()));
    a->setEnabled(false);
    addAction(a);
    actionListBranches.append(a);
    actionDeleteChildren = a;

    tag = tr("Various", "Shortcuts");
    a = new QAction(tr("Add timestamp", "Edit menu"), this);
    a->setEnabled(false);
    actionListBranches.append(a);
    a->setShortcut(Qt::Key_T);
    a->setShortcutContext(Qt::WindowShortcut);
    addAction(a);
    switchboard.addSwitch("mapAddTimestamp", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editAddTimestamp()));
    actionListBranches.append(a);
    actionAddTimestamp = a;

    a = new QAction(tr("Map properties...", "Edit menu"), this);
    a->setEnabled(true);
    connect(a, SIGNAL(triggered()), this, SLOT(editMapProperties()));
    actionListFiles.append(a);
    actionMapInfo = a;

    a = new QAction(tr("Add image...", "Edit menu"), this);
    a->setShortcutContext(Qt::WindowShortcut);
    a->setShortcut(Qt::Key_I + Qt::SHIFT);
    addAction(a);
    switchboard.addSwitch("mapLoadImage", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editLoadImage()));
    actionLoadImage = a;

    a = new QAction(
        tr("Property window", "Dialog to edit properties of selection") +
            QString("..."),
        this);
    a->setShortcut(Qt::Key_P);
    a->setShortcutContext(Qt::WindowShortcut);
    a->setCheckable(true);
    addAction(a);
    switchboard.addSwitch("mapTogglePropertEditor", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(windowToggleProperty()));
    actionViewTogglePropertyEditor = a;
}

// Select Actions
void Main::setupSelectActions()
{
    QString tag = tr("Selections", "Shortcuts");
    QMenu *selectMenu = menuBar()->addMenu(tr("Select", "Select menu"));
    QAction *a;
    a = new QAction(QPixmap(":/flag-target.svg"),
                    tr("Toggle target...", "Edit menu"), this);
    a->setShortcut(Qt::SHIFT + Qt::Key_T);
    a->setCheckable(true);
    selectMenu->addAction(a);
    switchboard.addSwitch("mapToggleTarget", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editToggleTarget()));
    actionListBranches.append(a);
    actionToggleTarget = a;

    a = new QAction(QPixmap(":/flag-target.svg"),
                    tr("Goto target...", "Edit menu"), this);
    a->setShortcut(Qt::Key_G);
    selectMenu->addAction(a);
    switchboard.addSwitch("mapGotoTarget", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editGoToTarget()));
    actionListBranches.append(a);
    actionGoToTarget = a;

    a = new QAction(QPixmap(":/flag-target.svg"),
                    tr("Move to target...", "Edit menu"), this);
    a->setShortcut(Qt::Key_M);
    selectMenu->addAction(a);
    switchboard.addSwitch("mapMoveToTarget", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editMoveToTarget()));
    actionListBranches.append(a);
    actionMoveToTarget = a;

    a = new QAction(QPixmap(":/flag-vymlink.png"),
                    tr("Goto linked map...", "Edit menu"), this);
    a->setShortcut(Qt::Key_G + Qt::SHIFT);
    selectMenu->addAction(a);
    switchboard.addSwitch("gotoLinkedMap", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editGoToLinkedMap()));
    actionListBranches.append(a);
    actionGoToTargetLinkedMap = a;

    a = new QAction(QPixmap(":/selectprevious.png"),
                    tr("Select previous", "Edit menu"), this);
    a->setShortcut(Qt::CTRL + Qt::Key_O);
    a->setShortcutContext(Qt::WidgetShortcut);
    selectMenu->addAction(a);
    actionListFiles.append(a);
    mapEditorActions.append(a);
    switchboard.addSwitch("mapSelectPrevious", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editSelectPrevious()));
    actionSelectPrevious = a;

    a = new QAction(QPixmap(":/selectnext.png"), tr("Select next", "Edit menu"),
                    this);
    a->setShortcut(Qt::CTRL + Qt::Key_I);
    a->setShortcutContext(Qt::WidgetShortcut);
    selectMenu->addAction(a);
    actionListFiles.append(a);
    mapEditorActions.append(a);
    switchboard.addSwitch("mapSelectNext", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editSelectNext()));
    actionSelectNext = a;

    a = new QAction(tr("Unselect all", "Edit menu"), this);
    // a->setShortcut (Qt::CTRL + Qt::Key_I );
    selectMenu->addAction(a);
    switchboard.addSwitch("mapSelectNothing", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editSelectNothing()));
    actionListFiles.append(a);
    actionSelectNothing = a;

    tag = tr("Search functions", "Shortcuts");
    a = new QAction(QPixmap(":/find.png"), tr("Find...", "Edit menu"), this);
    a->setShortcut(Qt::CTRL + Qt::Key_F);
    selectMenu->addAction(a);
    switchboard.addSwitch("mapFind", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editOpenFindResultWidget()));
    actionListFiles.append(a);
    actionFind = a;

    a = new QAction(QPixmap(":/find.png"), tr("Find...", "Edit menu"), this);
    a->setShortcut(Qt::Key_Slash);
    selectMenu->addAction(a);
    switchboard.addSwitch("mapFindAlt", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(editOpenFindResultWidget()));
    actionListFiles.append(a);

    a = new QAction(tr("Find duplicate URLs", "Edit menu") + " (test)", this);
    a->setShortcut(Qt::SHIFT + Qt::Key_F);
    switchboard.addSwitch("mapFindDuplicates", shortcutScope, a, tag);
    if (settings.value("/mainwindow/showTestMenu", false).toBool())
        selectMenu->addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(editFindDuplicateURLs()));
}

// Format Actions
void Main::setupFormatActions()
{
    QMenu *formatMenu = menuBar()->addMenu(tr("F&ormat", "Format menu"));

    QString tag = tr("Formatting", "Shortcuts");

    QAction* a;

    a = new QAction(QPixmap(":/formatcolorpicker.png"),
                    tr("Pic&k color", "Edit menu"), this);
    // a->setShortcut (Qt::CTRL + Qt::Key_K );
    formatMenu->addAction(a);
    switchboard.addSwitch("mapFormatColorPicker", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(formatPickColor()));
    a->setEnabled(false);
    actionListBranches.append(a);
    actionFormatPickColor = a;

    a = new QAction(QPixmap(":/formatcolorbranch.png"),
                    tr("Color &branch", "Edit menu"), this);
    // a->setShortcut (Qt::CTRL + Qt::Key_B + Qt::SHIFT);
    formatMenu->addAction(a);
    switchboard.addSwitch("mapFormatColorBranch", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(formatColorBranch()));
    a->setEnabled(false);
    actionListBranches.append(a);
    actionFormatColorBranch = a;

    a = new QAction(QPixmap(":/formatcolorsubtree.png"),
                    tr("Color sub&tree", "Edit menu"), this);
    // a->setShortcut (Qt::CTRL + Qt::Key_B);	// Color subtree
    formatMenu->addAction(a);
    switchboard.addSwitch("mapFormatColorSubtree", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(formatColorSubtree()));
    a->setEnabled(false);
    actionListBranches.append(a);
    actionFormatColorSubtree = a;

    formatMenu->addSeparator();

    a = new QAction(tr("Select default font", "Branch attribute") + "...",
                    this);
    a->setCheckable(false);
    connect(a, SIGNAL(triggered()), this, SLOT(formatSelectFont()));
    formatMenu->addAction(a);
    actionFormatFont = a;

    formatMenu->addSeparator();

    actionGroupFormatLinkStyles = new QActionGroup(this);
    actionGroupFormatLinkStyles->setExclusive(true);
    a = new QAction(tr("Linkstyle Line"), actionGroupFormatLinkStyles);
    a->setCheckable(true);
    restrictedMapActions.append(a);
    formatMenu->addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(formatLinkStyleLine()));
    actionFormatLinkStyleLine = a;

    a = new QAction(tr("Linkstyle Curve"), actionGroupFormatLinkStyles);
    a->setCheckable(true);
    restrictedMapActions.append(a);
    formatMenu->addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(formatLinkStyleParabel()));
    actionFormatLinkStyleParabel = a;

    a = new QAction(tr("Linkstyle Thick Line"), actionGroupFormatLinkStyles);
    a->setCheckable(true);
    restrictedMapActions.append(a);
    formatMenu->addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(formatLinkStylePolyLine()));
    actionFormatLinkStylePolyLine = a;

    a = new QAction(tr("Linkstyle Thick Curve"), actionGroupFormatLinkStyles);
    a->setCheckable(true);
    a->setChecked(true);
    restrictedMapActions.append(a);
    formatMenu->addAction(a);
    formatMenu->addSeparator();
    connect(a, SIGNAL(triggered()), this, SLOT(formatLinkStylePolyParabel()));
    actionFormatLinkStylePolyParabel = a;

    a = new QAction(
        tr("Hide link if object is not selected", "Branch attribute"), this);
    a->setCheckable(true);
    connect(a, SIGNAL(triggered()), this, SLOT(formatHideLinkUnselected()));
    actionListBranches.append(a);
    actionFormatHideLinkUnselected = a;

    a = new QAction(tr("&Use color of heading for link", "Branch attribute"),
                    this);
    a->setCheckable(true);
    connect(a, SIGNAL(triggered()), this, SLOT(formatToggleLinkColorHint()));
    formatMenu->addAction(a);
    actionFormatLinkColorHint = a;

    QPixmap pix(16, 16);
    pix.fill(Qt::white);
    a = new QAction(pix, tr("Set &Link Color") + "...", this);
    formatMenu->addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(formatSelectLinkColor()));
    actionFormatLinkColor = a;

    a = new QAction(pix, tr("Set &Selection Color") + "...", this);
    formatMenu->addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(formatSelectSelectionColor()));
    actionFormatSelectionColor = a;

    a = new QAction(pix, tr("Set &Background Color") + "...", this);
    formatMenu->addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(formatSelectBackColor()));
    actionFormatBackColor = a;

    a = new QAction(pix, tr("Set &Background image") + "...", this);
    formatMenu->addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(formatSelectBackImage()));
    actionFormatBackImage = a;
}

// View Actions
void Main::setupViewActions()
{
    QMenu *viewMenu = menuBar()->addMenu(tr("&View"));
    toolbarsMenu =
        viewMenu->addMenu(tr("Toolbars", "Toolbars overview in view menu"));
    QString tag = tr("Views", "Shortcuts");

    viewMenu->addSeparator();

    QAction *a;

    a = new QAction(QPixmap(":view-video-projector.png"), 
            tr("Toggle Presentation mode", "View action") + " " +
            tr("(still experimental)"),
            this);
    // a->setShortcut(Qt::Key_Plus);
    viewMenu->addAction(a);
    switchboard.addSwitch ("presentationMode", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(togglePresentationMode()));
    actionTogglePresentationMode = a;

    a = new QAction(QPixmap(":/viewmag+.png"), tr("Zoom in", "View action"),
                    this);
    a->setShortcut(Qt::Key_Plus);
    viewMenu->addAction(a);
    switchboard.addSwitch("mapZoomIn", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(viewZoomIn()));
    actionZoomIn = a;

    a = new QAction(QPixmap(":/viewmag-.png"), tr("Zoom out", "View action"),
                    this);
    a->setShortcut(Qt::Key_Minus);
    viewMenu->addAction(a);
    switchboard.addSwitch("mapZoomOut", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(viewZoomOut()));
    actionZoomOut = a;

    a = new QAction(QPixmap(":/transform-rotate-ccw.svg"),
                    tr("Rotate counterclockwise", "View action"), this);
    a->setShortcut(Qt::SHIFT + Qt::Key_R);
    viewMenu->addAction(a);
    switchboard.addSwitch("mapRotateCounterClockwise", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(viewRotateCounterClockwise()));
    actionRotateCounterClockwise = a;

    a = new QAction(QPixmap(":/transform-rotate-cw.svg"),
                    tr("Rotate rclockwise", "View action"), this);
    a->setShortcut(Qt::Key_R);
    viewMenu->addAction(a);
    switchboard.addSwitch("mapRotateClockwise", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(viewRotateClockwise()));
    actionRotateClockwise = a;

    a = new QAction(QPixmap(":/viewmag-reset.png"),
                    tr("reset Zoom", "View action"), this);
    a->setShortcut(Qt::Key_Comma);
    switchboard.addSwitch("mapZoomReset", shortcutScope, a, tag);
    viewMenu->addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(viewZoomReset()));
    actionZoomReset = a;

    a = new QAction(QPixmap(":/viewshowsel.png"),
                    tr("Center on selection", "View action"), this);
    a->setShortcut(Qt::Key_Period);
    viewMenu->addAction(a);
    switchboard.addSwitch("mapCenterOn", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(viewCenter()));
    actionCenterOn = a;

    a = new QAction(QPixmap(),
                    tr("Fit view to selection", "View action"), this);
    a->setShortcut(Qt::Key_Period + Qt::SHIFT);
    viewMenu->addAction(a);
    switchboard.addSwitch("mapCenterAndFitView", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(viewCenterScaled()));
    actionFitToSelection = a;

    viewMenu->addSeparator();

    // a=noteEditorDW->toggleViewAction();
    a = new QAction(QPixmap(":/flag-note.svg"),
                    tr("Note editor", "View action"), this);
    a->setShortcut(Qt::Key_N);
    a->setShortcutContext(Qt::WidgetShortcut);
    a->setCheckable(true);
    viewMenu->addAction(a);
    mapEditorActions.append(a);
    switchboard.addSwitch("mapToggleNoteEditor", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(windowToggleNoteEditor()));
    actionViewToggleNoteEditor = a;

    // a=headingEditorDW->toggleViewAction();
    a = new QAction(QPixmap(":/headingeditor.png"),
                    tr("Heading editor", "View action"), this);
    a->setCheckable(true);
    a->setIcon(QPixmap(":/headingeditor.png"));
    a->setShortcut(Qt::Key_E);
    a->setShortcutContext(Qt::WidgetShortcut);
    mapEditorActions.append(a);
    viewMenu->addAction(a);
    switchboard.addSwitch("mapToggleHeadingEditor", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(windowToggleHeadingEditor()));
    actionViewToggleHeadingEditor = a;

    // Original icon is "category" from KDE
    a = new QAction(QPixmap(":/treeeditor.png"),
                    tr("Tree editor", "View action"), this);
    a->setShortcut(Qt::CTRL + Qt::Key_T);
    a->setCheckable(true);
    viewMenu->addAction(a);
    switchboard.addSwitch("mapToggleTreeEditor", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(windowToggleTreeEditor()));
    actionViewToggleTreeEditor = a;

    a = new QAction(QPixmap(":/taskeditor.png"),
                    tr("Task editor", "View action"), this);
    a->setCheckable(true);
    a->setShortcut(Qt::Key_Q);
    a->setShortcutContext(Qt::WidgetShortcut);
    mapEditorActions.append(a);
    viewMenu->addAction(a);
    switchboard.addSwitch("mapToggleTaskEditor", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(windowToggleTaskEditor()));
    actionViewToggleTaskEditor = a;

    a = new QAction(QPixmap(":/slideeditor.png"),
                    tr("Slide editor", "View action"), this);
    a->setCheckable(true);
    viewMenu->addAction(a);
    switchboard.addSwitch("mapToggleSlideEditor", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(windowToggleSlideEditor()));
    actionViewToggleSlideEditor = a;

    a = new QAction(QPixmap(":/scripteditor.png"),
                    tr("Script editor", "View action"), this);
    a->setShortcut(Qt::SHIFT + Qt::Key_S);
    a->setCheckable(true);
    viewMenu->addAction(a);
    switchboard.addSwitch("mapToggleScriptEditor", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(windowToggleScriptEditor()));
    actionViewToggleScriptEditor = a;

    a = new QAction(QPixmap(), tr("Script output window", "View action"), this);
    a->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_S);
    a->setCheckable(true);
    viewMenu->addAction(a);
    switchboard.addSwitch("mapToggleScriptOutput", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(windowToggleScriptOutput()));
    actionViewToggleScriptOutput = a;

    a = new QAction(QPixmap(":/history.png"),
                    tr("History Window", "View action"), this);
    a->setShortcut(Qt::CTRL + Qt::Key_H);
    a->setShortcutContext(Qt::WidgetShortcut);
    a->setCheckable(true);
    viewMenu->addAction(a);
    mapEditorActions.append(a);
    switchboard.addSwitch("mapToggleHistoryWindow", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(windowToggleHistory()));
    actionViewToggleHistoryWindow = a;

    viewMenu->addAction(actionViewTogglePropertyEditor);

    viewMenu->addSeparator();

    a = new QAction(tr("Antialiasing", "View action"), this);
    a->setCheckable(true);
    a->setChecked(settings.value("/mainwindow/view/AntiAlias", true).toBool());
    viewMenu->addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(windowToggleAntiAlias()));
    actionViewToggleAntiAlias = a;

    a = new QAction(tr("Smooth pixmap transformations", "View action"), this);
    a->setStatusTip(a->text());
    a->setCheckable(true);
    a->setChecked(
        settings.value("/mainwindow/view/SmoothPixmapTransformation", true)
            .toBool());
    viewMenu->addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(windowToggleSmoothPixmap()));
    actionViewToggleSmoothPixmapTransform = a;

    a = new QAction(tr("Next Map", "View action"), this);
    a->setStatusTip(a->text());
    a->setShortcut(Qt::SHIFT + Qt::Key_Right);
    viewMenu->addAction(a);
    switchboard.addSwitch("mapPrevious", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(windowNextEditor()));

    a = new QAction(tr("Previous Map", "View action"), this);
    a->setStatusTip(a->text());
    a->setShortcut(Qt::SHIFT + Qt::Key_Left);
    viewMenu->addAction(a);
    switchboard.addSwitch("mapNext", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(windowPreviousEditor()));

    a = new QAction(tr("Next slide", "View action"), this);
    a->setStatusTip(a->text());
    a->setShortcut(Qt::Key_Space);
    viewMenu->addAction(a);
    switchboard.addSwitch("mapNextSlide", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(nextSlide()));

    a = new QAction(tr("Previous slide", "View action"), this);
    a->setStatusTip(a->text());
    a->setShortcut(Qt::Key_Backspace);
    viewMenu->addAction(a);
    switchboard.addSwitch("mapPreviousSlide", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(previousSlide()));
}

// Connect Actions
void Main::setupConnectActions()
{
    QMenu *connectMenu = menuBar()->addMenu(tr("&Connect"));
    QString tag = tr("Connect", "Shortcuts");

    QAction *a;

    a = new QAction( tr("Get Confluence user data", "Connect action"), this);
    a->setShortcut(Qt::SHIFT + Qt::Key_C);
    connectMenu->addAction(a);
    switchboard.addSwitch ("confluenceUser", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(getConfluenceUser()));
    actionConnectGetConfluenceUser = a;

    connectMenu->addAction(actionGetConfluencePageName);
    connectMenu->addAction(actionGetJiraDataSubtree);

    connectMenu->addSeparator();

    connectMenu->addAction(actionSettingsJIRA);
    connectMenu->addAction(actionSettingsConfluence);
}

// Mode Actions
void Main::setupModeActions()
{
    // QPopupMenu *menu = new QPopupMenu( this );
    // menuBar()->insertItem( tr( "&Mode (using modifiers)" ), menu );

    QString tag = tr("Modifier modes", "Shortcuts");
    QAction *a;
    actionGroupModModes = new QActionGroup(this);
    actionGroupModModes->setExclusive(true);

    a = new QAction(
        QIcon(":/mode-select.svg"),
        tr("Use modifier to select and reorder objects", "Mode modifier"),
        actionGroupModModes);
    a->setShortcut(Qt::Key_J);
    addAction(a);
    switchboard.addSwitch("mapModModePoint", shortcutScope, a, tag);
    a->setCheckable(true);
    a->setChecked(true);
    actionListFiles.append(a);
    actionModModePoint = a;

    a = new QAction(
        QPixmap(":/mode-color.png"),
        tr("Format painter: pick color from another branch and apply",
           "Mode modifier"),
        actionGroupModModes);
    a->setShortcut(Qt::Key_K);
    addAction(a);
    switchboard.addSwitch("mapModModeColor", shortcutScope, a, tag);
    a->setCheckable(true);
    actionListFiles.append(a);
    actionModModeColor = a;

    a = new QAction(QPixmap(":/mode-xlink.png"),
                    tr("Use modifier to draw xLinks", "Mode modifier"),
                    actionGroupModModes);
    a->setShortcut(Qt::Key_L);
    addAction(a);
    switchboard.addSwitch("mapModModeXLink", shortcutScope, a, tag);
    a->setCheckable(true);
    actionListFiles.append(a);
    actionModModeXLink = a;

    a = new QAction(
        QPixmap(":/mode-move-object.svg"),
        tr("Use modifier to move branches without linking", "Mode modifier"),
        actionGroupModModes);
    a->setShortcut(Qt::Key_Odiaeresis);
    addAction(a);
    switchboard.addSwitch("mapModModeMoveObject", shortcutScope, a, tag);
    a->setCheckable(true);
    actionListFiles.append(a);
    actionModModeMoveObject = a;

    a = new QAction(
        QPixmap(":/mode-move-view.png"),
        tr("Use modifier to move view without selecting", "Mode modifier"),
        actionGroupModModes);
    a->setShortcut(Qt::Key_Adiaeresis);
    addAction(a);
    switchboard.addSwitch("mapModModeMoveView", shortcutScope, a, tag);
    a->setCheckable(true);
    actionListFiles.append(a);
    actionModModeMoveView = a;
}

void Main::addUserFlag()
{
    VymModel *m = currentModel();

    if (m) {
        QFileDialog fd;
        QStringList filters;
        filters << tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif "
                                  "*.pnm *.svg *.svgz)";
        filters << tr("All", "Filedialog") + " (*.*)";
        fd.setFileMode(QFileDialog::ExistingFiles);
        fd.setNameFilters(filters);
        fd.setWindowTitle(vymName + " - " + "Load user flag");
        fd.setAcceptMode(QFileDialog::AcceptOpen);

        QString fn;
        if (fd.exec() == QDialog::Accepted) {
            lastMapDir = fd.directory();
            QStringList flist = fd.selectedFiles();
            QStringList::Iterator it = flist.begin();
            initProgressCounter(flist.count());
            while (it != flist.end()) {
                fn = *it;
                setupFlag(*it, Flag::UserFlag, *it, "");
                ++it;
            }
        }
    }
}

void Main::setupFlagActions()
{
    Flag *flag;

    // Create System Flags

    // Tasks
    // Origin: ./share/icons/oxygen/48x48/status/task-reject.png
    flag = setupFlag(":/flag-task-new.svg", Flag::SystemFlag, "system-task-new",
                     tr("Note", "SystemFlag"));
    flag->setGroup("system-tasks");

    flag = setupFlag(":/flag-task-new-morning.svg", Flag::SystemFlag,
                     "system-task-new-morning", tr("Note", "SystemFlag"));
    flag->setGroup("system-tasks");

    flag = setupFlag(":/flag-task-new-sleeping.svg", Flag::SystemFlag,
                     "system-task-new-sleeping", tr("Note", "SystemFlag"));
    flag->setGroup("system-tasks");

    // Origin: ./share/icons/oxygen/48x48/status/task-reject.png
    flag = setupFlag(":/flag-task-wip.svg", Flag::SystemFlag, "system-task-wip",
                     tr("Note", "SystemFlag"));
    flag->setGroup("system-tasks");

    flag = setupFlag(":/flag-task-wip-morning.svg", Flag::SystemFlag,
                     "system-task-wip-morning", tr("Note", "SystemFlag"));
    flag->setGroup("system-tasks");

    flag = setupFlag(":/flag-task-wip-sleeping.svg", Flag::SystemFlag,
                     "system-task-wip-sleeping", tr("Note", "SystemFlag"));
    flag->setGroup("system-tasks");

    // Origin: ./share/icons/oxygen/48x48/status/task-complete.png
    flag = setupFlag(":/flag-task-finished.svg", Flag::SystemFlag,
                     "system-task-finished", tr("Note", "SystemFlag"));
    flag->setGroup("system-tasks");

    setupFlag(":/flag-note.svg", Flag::SystemFlag, "system-note",
              tr("Note", "SystemFlag"));

    setupFlag(":/flag-url.svg", Flag::SystemFlag, "system-url",
              tr("URL", "SystemFlag"));

    setupFlag(":/flag-target.svg", Flag::SystemFlag, "system-target",
              tr("Map target", "SystemFlag"));

    setupFlag(":/flag-vymlink.png", Flag::SystemFlag, "system-vymLink",
              tr("Link to another vym map", "SystemFlag"));

    setupFlag(":/flag-scrolled-right.png", Flag::SystemFlag,
              "system-scrolledright", tr("subtree is scrolled", "SystemFlag"));

    setupFlag(":/flag-tmpUnscrolled-right.png", Flag::SystemFlag,
              "system-tmpUnscrolledRight",
              tr("subtree is temporary scrolled", "SystemFlag"));

    setupFlag(":/flag-hideexport", Flag::SystemFlag, "system-hideInExport",
              tr("Hide object in exported maps", "SystemFlag"));

    addToolBarBreak();

    // Add entry now, to avoid chicken and egg problem and position toolbar
    // after all others:
    setupFlag(":/flag-stopsign.svg", Flag::StandardFlag, "stopsign",
                  tr("This won't work!", "Standardflag"), QUuid(), Qt::Key_1);

    flag = setupFlag(":/flag-hook-green.svg",
                  // flag = setupFlag ( "flags/standard/dialog-ok-apply.svg",
                  Flag::StandardFlag, "hook-green",
                  tr("Status - ok,done", "Standardflag"), QUuid(), Qt::Key_2);
    flag->setGroup("standard-status");

    flag = setupFlag(":/flag-wip.svg", Flag::StandardFlag, "wip",
                     tr("Status - work in progress", "Standardflag"), QUuid(),
                     Qt::Key_3);
    flag->setGroup("standard-status");

    flag = setupFlag(":/flag-cross-red.svg", Flag::StandardFlag, "cross-red",
                     tr("Status - missing, not started", "Standardflag"),
                     QUuid(), Qt::Key_4);
    flag->setGroup("standard-status");

    flag = setupFlag(":/flag-exclamation-mark.svg", Flag::StandardFlag,
                     "exclamationmark", tr("Take care!", "Standardflag"),
                     QUuid(), Qt::Key_Exclam);
    flag->setGroup("standard-mark");

    flag = setupFlag(":/flag-question-mark.svg", Flag::StandardFlag,
                     "questionmark", tr("Really?", "Standardflag"), QUuid(),
                     Qt::Key_Question);
    flag->setGroup("standard-mark");

    setupFlag(":/flag-info.svg", Flag::StandardFlag, "info",
                     tr("Info", "Standardflag"), QUuid(), Qt::Key_I);

    setupFlag(":/flag-lamp.svg", Flag::StandardFlag, "lamp",
                     tr("Idea!", "Standardflag"), QUuid(), Qt::Key_Asterisk);

    setupFlag(":/flag-heart.svg", Flag::StandardFlag, "heart",
                     tr("I just love...", "Standardflag"));

    flag = setupFlag(":/flag-face-smile.svg", Flag::StandardFlag, "smiley-good",
                     tr("Good", "Standardflag"), QUuid(), Qt::Key_ParenRight);
    flag->setGroup("standard-faces");

    flag = setupFlag(":/flag-face-sad.svg", Flag::StandardFlag, "smiley-sad",
                     tr("Bad", "Standardflag"), QUuid(), Qt::Key_ParenLeft);
    flag->setGroup("standard-faces");

    flag = setupFlag(":/flag-face-plain.svg", Flag::StandardFlag,
                     "smiley-plain", tr("Hm...", "Standardflag"), QUuid());
    flag->setGroup("standard-faces");

    flag = setupFlag(":/flag-face-surprise.svg", Flag::StandardFlag,
                     "smiley-omb", tr("Oh no!", "Standardflag"), QUuid());
    flag->setGroup("standard-faces");

    setupFlag(":/flag-flash.svg", Flag::StandardFlag, "flash",
                     tr("Dangerous", "Standardflag"));

    flag = setupFlag(":/flag-arrow-up.svg", Flag::StandardFlag, "arrow-up",
                     tr("Important", "Standardflag"), QUuid(),
                     Qt::SHIFT + Qt::Key_PageUp);
    flag->setGroup("standard-arrow");

    flag = setupFlag(":/flag-arrow-down.svg", Flag::StandardFlag, "arrow-down",
                     tr("Unimportant", "Standardflag"), QUuid(),
                     Qt::SHIFT + Qt::Key_PageDown);
    flag->setGroup("standard-arrow");

    flag = setupFlag(":/flag-arrow-2up.svg", Flag::StandardFlag, "2arrow-up",
                     tr("Very important!", "Standardflag"), QUuid(),
                     Qt::SHIFT + Qt::CTRL + Qt::Key_PageUp);
    flag->setGroup("standard-arrow");

    flag = setupFlag(":/flag-arrow-2down.svg", Flag::StandardFlag,
                     "2arrow-down", tr("Very unimportant!", "Standardflag"),
                     QUuid(), Qt::SHIFT + Qt::CTRL + Qt::Key_PageDown);
    flag->setGroup("standard-arrow");

    setupFlag(":/flag-thumb-up.png", Flag::StandardFlag, "thumb-up",
                     tr("I like this", "Standardflag"));

    setupFlag(":/flag-thumb-down.png", Flag::StandardFlag, "thumb-down",
                     tr("I do not like this", "Standardflag"));

    // Original khelpcenter.png
    setupFlag(":/flag-lifebelt.svg", Flag::StandardFlag, "lifebelt",
                     tr("This will help", "Standardflag"));

    setupFlag(":/flag-phone.svg", Flag::StandardFlag, "phone",
                     tr("Call...", "Standardflag"));

    setupFlag(":/flag-clock.svg", Flag::StandardFlag, "clock",
                     tr("Time critical", "Standardflag"));

    setupFlag(":/flag-present.png", Flag::StandardFlag, "present",
                     tr("Surprise!", "Standardflag"));

    setupFlag(":/flag-rose.png", Flag::StandardFlag, "rose",
                     tr("Rose", "Standardflag"));

    // Freemind flags
    setupFlag(":/freemind/warning.png", Flag::FreemindFlag,
                     "freemind-warning", tr("Important", "Freemind flag"));

    for (int i = 1; i < 8; i++) {
        setupFlag(QString(":/freemind/priority-%1.png").arg(i),
                         Flag::FreemindFlag,
                         QString("freemind-priority-%1").arg(i),
                         tr("Important", "Freemind flag"));
        flag->setGroup("freemind-priority");
    }

    setupFlag(":/freemind/back.png", Flag::FreemindFlag, "freemind-back",
                     tr("Back", "Freemind flag"));

    setupFlag(":/freemind/forward.png", Flag::FreemindFlag,
                     "freemind-forward", tr("Forward", "Freemind flag"));

    setupFlag(":/freemind/attach.png", Flag::FreemindFlag,
                     "freemind-attach", tr("Look here", "Freemind flag"));

    setupFlag(":/freemind/clanbomber.png", Flag::FreemindFlag,
                     "freemind-clanbomber", tr("Dangerous", "Freemind flag"));

    setupFlag(":/freemind/desktopnew.png", Flag::FreemindFlag,
                  "freemind-desktopnew", tr("Don't forget", "Freemind flag"));

    setupFlag(":/freemind/flag.png", Flag::FreemindFlag, "freemind-flag",
                     tr("Flag", "Freemind flag"));

    setupFlag(":/freemind/gohome.png", Flag::FreemindFlag,
                     "freemind-gohome", tr("Home", "Freemind flag"));

    setupFlag(":/freemind/kaddressbook.png", Flag::FreemindFlag,
                     "freemind-kaddressbook", tr("Telephone", "Freemind flag"));

    setupFlag(":/freemind/knotify.png", Flag::FreemindFlag,
                     "freemind-knotify", tr("Music", "Freemind flag"));

    setupFlag(":/freemind/korn.png", Flag::FreemindFlag, "freemind-korn",
                     tr("Mailbox", "Freemind flag"));

    setupFlag(":/freemind/mail.png", Flag::FreemindFlag, "freemind-mail",
                     tr("Mail", "Freemind flag"));

    setupFlag(":/freemind/password.png", Flag::FreemindFlag,
                     "freemind-password", tr("Password", "Freemind flag"));

    setupFlag(":/freemind/pencil.png", Flag::FreemindFlag,
                     "freemind-pencil", tr("To be improved", "Freemind flag"));

    setupFlag(":/freemind/stop.png", Flag::FreemindFlag, "freemind-stop",
                     tr("Stop", "Freemind flag"));

    setupFlag(":/freemind/wizard.png", Flag::FreemindFlag,
                     "freemind-wizard", tr("Magic", "Freemind flag"));

    setupFlag(":/freemind/xmag.png", Flag::FreemindFlag, "freemind-xmag",
                     tr("To be discussed", "Freemind flag"));

    setupFlag(":/freemind/bell.png", Flag::FreemindFlag, "freemind-bell",
                     tr("Reminder", "Freemind flag"));

    setupFlag(":/freemind/bookmark.png", Flag::FreemindFlag,
                     "freemind-bookmark", tr("Excellent", "Freemind flag"));

    setupFlag(":/freemind/penguin.png", Flag::FreemindFlag,
                     "freemind-penguin", tr("Linux", "Freemind flag"));

    setupFlag(":/freemind/licq.png", Flag::FreemindFlag, "freemind-licq",
                     tr("Sweet", "Freemind flag"));
}

Flag *Main::setupFlag(const QString &path, Flag::FlagType type,
                      const QString &name, const QString &tooltip,
                      const QUuid &uid, const QKeySequence &keyseq)
{
    Flag *flag = nullptr;

    // Create flag in toolbar
    switch (type) {
    case Flag::FreemindFlag:
        // Maybe introduce dedicated toolbar later,
        // so for now switch to standard flag
        flag = standardFlagsMaster->createFlag(path);
        break;

    case Flag::StandardFlag:
        flag = standardFlagsMaster->createFlag(path);
        break;

    case Flag::UserFlag:
        flag = userFlagsMaster->createFlag(path);

        // User flags read from file already have a Uuid - use it
        if (!uid.isNull())
            flag->setUuid(uid);
        break;

    case Flag::SystemFlag:
        flag = systemFlagsMaster->createFlag(path);
        break;

    default:
        qWarning() << "Unknown flag type in MainWindow::setupFlag";
        break;
    }

    if (!flag)
        return flag;

    flag->setName(name);
    flag->setToolTip(tooltip);
    flag->setType(type);

    if (type == Flag::SystemFlag)
        return flag;

    // StandardFlag or user flag

    QAction *a;

    // Set icon for action
    ImageObj *image = flag->getImageObj();
    a = new QAction(image->getIcon(), flag->getUuid().toString(), this);

    flag->setAction(a);
    a->setCheckable(true);
    a->setObjectName(flag->getUuid().toString());
    if (tooltip.isEmpty())
        a->setToolTip(flag->getName()); // Stripped name
    else
        a->setToolTip(tooltip);

    if (keyseq != 0) {
        a->setShortcut(keyseq);
        a->setShortcutContext(Qt::WidgetShortcut);

        // Allow mapEditors to actually trigger this action
        mapEditorActions.append(a);
        taskEditorActions.append(a);
    }

    switch (type) {
    case Flag::FreemindFlag:
        // Hide freemind flags per default
        // Maybe introduce dedicate toolbar later,
        // so for now switch to standard flag
        flag->setVisible(false);
        type = Flag::StandardFlag;
        standardFlagsMaster->addActionToToolbar(a);

        connect(a, SIGNAL(triggered()), this, SLOT(flagChanged()));
        break;
    case Flag::StandardFlag:
        // Hide some old flags, if not used
        if (name == "present" || name == "rose" || name == "phone" ||
            name == "clock")
            flag->setVisible(false);
        standardFlagsMaster->addActionToToolbar(a);
        connect(a, SIGNAL(triggered()), this, SLOT(flagChanged()));
        break;
    case Flag::UserFlag:
        userFlagsMaster->addActionToToolbar(a);
        connect(a, SIGNAL(triggered()), this, SLOT(flagChanged()));
        break;
    default:
        qWarning() << "Unknown flag type in MainWindow::setupFlag";
    }

    a->setVisible(flag->isVisible());

    return flag;
}

// Network Actions
void Main::setupNetworkActions()
{
    if (!settings.value("/mainwindow/showTestMenu", false).toBool())
        return;

    QAction *a;

    a = new QAction("Start TCPserver for MapEditor", this);
    connect(a, SIGNAL(triggered()), this, SLOT(networkStartServer()));

    a = new QAction("Connect MapEditor to server", this);
    connect(a, SIGNAL(triggered()), this, SLOT(networkConnect()));
}

// Settings Actions
void Main::setupSettingsActions()
{
    QMenu *settingsMenu = menuBar()->addMenu(tr("Settings"));

    QAction *a;

    a = new QAction(
        tr("Check for release notes and updates", "Settings action"), this);
    a->setCheckable(true);
    a->setChecked(settings.value("/downloads/enabled", true).toBool());
    connect(a, SIGNAL(triggered()), this, SLOT(settingsToggleDownloads()));
    settingsMenu->addAction(a);
    actionSettingsToggleDownloads = a;

    a = new QAction(tr("Set author for new maps", "Settings action") + "...",
                    this);
    connect(a, SIGNAL(triggered()), this, SLOT(settingsDefaultMapAuthor()));
    settingsMenu->addAction(a);

    settingsMenu->addSeparator();

    a = new QAction(tr("Set application to open pdf files", "Settings action") +
                        "...",
                    this);
    connect(a, SIGNAL(triggered()), this, SLOT(settingsPDF()));
    settingsMenu->addAction(a);

    a = new QAction(
        tr("Set application to open external links", "Settings action") + "...",
        this);
    connect(a, SIGNAL(triggered()), this, SLOT(settingsURL()));
    settingsMenu->addAction(a);

    a = new QAction(
        tr("Set application to zip/unzip files", "Settings action") + "...",
        this);
    connect(a, SIGNAL(triggered()), this, SLOT(settingsZipTool()));
    // FIXME-2 Disabled for now  settingsMenu->addAction(a);

    a = new QAction(tr("Confluence Credentials", "Settings action") + "...",
                    this);
    connect(a, SIGNAL(triggered()), this, SLOT(settingsConfluence()));
    settingsMenu->addAction(a);
    actionSettingsConfluence = a;

    a = new QAction(tr("JIRA Credentials", "Settings action") + "...",
                    this);
    connect(a, SIGNAL(triggered()), this, SLOT(settingsJIRA()));
    settingsMenu->addAction(a);
    actionSettingsJIRA = a;

    a = new QAction(tr("Set path for new maps", "Settings action") + "...",
                    this);
    connect(a, SIGNAL(triggered()), this, SLOT(settingsDefaultMapPath()));
    settingsMenu->addAction(a);

    a = new QAction(tr("Set path for macros", "Settings action") + "...", this);
    connect(a, SIGNAL(triggered()), this, SLOT(settingsMacroPath()));
    settingsMenu->addAction(a);

    a = new QAction(tr("Set number of undo levels", "Settings action") + "...",
                    this);
    connect(a, SIGNAL(triggered()), this, SLOT(settingsUndoLevels()));
    settingsMenu->addAction(a);

    settingsMenu->addSeparator();

    a = new QAction(tr("Autosave", "Settings action"), this);
    a->setCheckable(true);
    a->setChecked(settings.value("/system/autosave/use", true).toBool());
    settingsMenu->addAction(a);
    actionSettingsToggleAutosave = a;

    a = new QAction(tr("Autosave time", "Settings action") + "...", this);
    connect(a, SIGNAL(triggered()), this, SLOT(settingsAutosaveTime()));
    settingsMenu->addAction(a);
    actionSettingsAutosaveTime = a;

    // Disable certain actions during testing
    if (testmode) {
        actionSettingsToggleAutosave->setChecked(false);
        actionSettingsToggleAutosave->setEnabled(false);
        actionSettingsAutosaveTime->setEnabled(false);
    }

    a = new QAction(tr("Write backup file on save", "Settings action"), this);
    a->setCheckable(true);
    a->setChecked(settings.value("/system/writeBackupFile", false).toBool());
    connect(a, SIGNAL(triggered()), this,
            SLOT(settingsToggleWriteBackupFile()));
    settingsMenu->addAction(a);
    actionSettingsWriteBackupFile = a;

    settingsMenu->addSeparator();

    a = new QAction(tr("Select branch after adding it", "Settings action"),
                    this);
    a->setCheckable(true);
    a->setChecked(
        settings.value("/mapeditor/editmode/autoSelectNewBranch", false)
            .toBool());
    settingsMenu->addAction(a);
    actionSettingsAutoSelectNewBranch = a;

    a = new QAction(tr("Select existing heading", "Settings action"), this);
    a->setCheckable(true);
    a->setChecked(
        settings.value("/mapeditor/editmode/autoSelectText", true).toBool());
    settingsMenu->addAction(a);
    actionSettingsAutoSelectText = a;

    a = new QAction(tr("Exclusive flags", "Settings action"), this);
    a->setCheckable(true);
    a->setChecked(
        settings.value("/mapeditor/editmode/useFlagGroups", true).toBool());
    settingsMenu->addAction(a);
    actionSettingsUseFlagGroups = a;

    a = new QAction(tr("Use hide flags", "Settings action"), this);
    a->setCheckable(true);
    a->setChecked(settings.value("/export/useHideExport", true).toBool());
    settingsMenu->addAction(a);
    actionSettingsUseHideExport = a;

    settingsMenu->addSeparator();

    a = new QAction(
        tr("Dark theme", "Settings action") + "...",
        this);
    connect(a, SIGNAL(triggered()), this,
            SLOT(settingsDarkTheme()));
    settingsMenu->addAction(a);
    actionSettingsDarkTheme= a;

    a = new QAction(
        tr("Number of visible parents in task editor", "Settings action") + "...",
        this);
    connect(a, SIGNAL(triggered()), this,
            SLOT(settingsShowParentsLevelTasks()));
    settingsMenu->addAction(a);
    actionSettingsShowParentsLevelTasks = a;

    a = new QAction(tr("Number of visible parents in find results window",
                       "Settings action") + "...",
                    this);
    connect(a, SIGNAL(triggered()), this,
            SLOT(settingsShowParentsLevelFindResults()));
    settingsMenu->addAction(a);
    actionSettingsShowParentsLevelFindResults = a;

    a = new QAction(tr("Animation", "Settings action"), this);
    a->setCheckable(true);
    a->setChecked(settings.value("/animation/use", true).toBool());
    connect(a, SIGNAL(triggered()), this, SLOT(settingsToggleAnimation()));
    settingsMenu->addAction(a);
    actionSettingsUseAnimation = a;

    a = new QAction(tr("Automatic layout", "Settings action"), this);
    a->setCheckable(true);
    a->setChecked(settings.value("/mainwindow/autoLayout/use", true).toBool());
    connect(a, SIGNAL(triggered()), this, SLOT(settingsToggleAutoLayout()));
    settingsMenu->addAction(a);
    actionSettingsToggleAutoLayout = a;
}

// Test Actions
void Main::setupTestActions()
{
    QMenu *testMenu = menuBar()->addMenu(tr("Test"));

    QString tag = "Testing";
    QAction *a;
    a = new QAction("Test function 1", this);
    a->setShortcut(Qt::ALT + Qt::Key_T);
    testMenu->addAction(a);
    switchboard.addSwitch("mapTest1", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(testFunction1()));

    a = new QAction("Test function 2", this);
    // a->setShortcut (Qt::ALT + Qt::Key_T);
    testMenu->addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(testFunction2()));

    a = new QAction("Toggle hide export mode", this);
    a->setCheckable(true);
    a->setChecked(false);
    testMenu->addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(toggleHideExport()));
    actionToggleHideMode = a;

    testMenu->addAction(actionToggleWinter);
}

// Help Actions
void Main::setupHelpActions()
{
    QMenu *helpMenu = menuBar()->addMenu(tr("&Help", "Help menubar entry"));

    QAction *a;
    a = new QAction(tr("Open VYM Documentation (pdf) ", "Help action"), this);
    helpMenu->addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(helpDoc()));

    a = new QAction(tr("Open VYM example maps ", "Help action"), this);
    helpMenu->addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(helpDemo()));
    helpMenu->addSeparator();

    a = new QAction(tr("Download and show release notes", "Help action"), this);
    helpMenu->addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(checkReleaseNotes()));

    a = new QAction(tr("Check, if updates are available", "Help action"), this);
    helpMenu->addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(checkUpdates()));
    helpMenu->addSeparator();

    a = new QAction(tr("Show keyboard shortcuts", "Help action"), this);
    helpMenu->addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(helpShortcuts()));

    a = new QAction(tr("Show keyboard macros", "Help action"), this);
    helpMenu->addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(helpMacros()));

    a = new QAction(tr("Show scripting commands", "Help action"), this);
    helpMenu->addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(helpScriptingCommands()));

    a = new QAction(tr("Debug info", "Option to show debugging info"), this);
    helpMenu->addAction(a);
    connect(a, SIGNAL(triggered()), this, SLOT(helpDebugInfo()));

    a = new QAction(tr("About QT", "Help action"), this);
    connect(a, SIGNAL(triggered()), this, SLOT(helpAboutQT()));
    helpMenu->addAction(a);

    a = new QAction(tr("About VYM", "Help action"), this);
    connect(a, SIGNAL(triggered()), this, SLOT(helpAbout()));
    helpMenu->addAction(a);
}

// Context Menus
void Main::setupContextMenus()
{
    // Context menu for goto/move targets  (populated on demand)
    targetsContextMenu = new QMenu(this);

    // Context Menu for branch or mapcenter
    branchContextMenu = new QMenu(this);
    branchContextMenu->addAction(actionViewTogglePropertyEditor);
    branchContextMenu->addSeparator();

    // Submenu "Add"
    branchAddContextMenu = branchContextMenu->addMenu(tr("Add"));
    branchAddContextMenu->addAction(actionPaste);
    branchAddContextMenu->addAction(actionAddMapCenter);
    branchAddContextMenu->addAction(actionAddBranch);
    branchAddContextMenu->addAction(actionAddBranchBefore);
    branchAddContextMenu->addAction(actionAddBranchAbove);
    branchAddContextMenu->addAction(actionAddBranchBelow);
    branchAddContextMenu->addSeparator();
    branchAddContextMenu->addAction(actionImportAdd);
    branchAddContextMenu->addAction(actionImportReplace);

    // Submenu "Remove"
    branchRemoveContextMenu =
        branchContextMenu->addMenu(tr("Remove", "Context menu name"));
    branchRemoveContextMenu->addAction(actionCut);
    branchRemoveContextMenu->addAction(actionDelete);
    branchRemoveContextMenu->addAction(actionDeleteKeepChildren);
    branchRemoveContextMenu->addAction(actionDeleteChildren);

    branchContextMenu->addAction(actionSaveBranch);
    branchContextMenu->addAction(actionFileNewCopy);
    branchContextMenu->addAction(actionDetach);

    branchContextMenu->addSeparator();
    branchContextMenu->addAction(actionLoadImage);
    if (settings.value("/mainwindow/showTestMenu", false).toBool())
        branchContextMenu->addAction(actionAddAttribute);

    branchContextMenu->addSeparator();

    // Context menu for tasks
    taskContextMenu = branchContextMenu->addMenu(tr("Tasks", "Context menu"));
    taskContextMenu->addAction(actionToggleTask);
    taskContextMenu->addAction(actionCycleTaskStatus);
    taskContextMenu->addAction(actionTaskResetDeltaPrio);
    taskContextMenu->addSeparator();
    taskContextMenu->addAction(actionTaskSleep0);
    taskContextMenu->addAction(actionTaskSleepN);
    taskContextMenu->addAction(actionTaskSleep1);
    taskContextMenu->addAction(actionTaskSleep2);
    taskContextMenu->addAction(actionTaskSleep3);
    taskContextMenu->addAction(actionTaskSleep4);
    taskContextMenu->addAction(actionTaskSleep5);
    taskContextMenu->addAction(actionTaskSleep7);
    taskContextMenu->addAction(actionTaskSleep14);
    taskContextMenu->addAction(actionTaskSleep28);

    // Submenu for Links (URLs, vymLinks)
    branchLinksContextMenu = new QMenu(this);

    branchLinksContextMenu = branchContextMenu->addMenu(
        tr("References (URLs, vymLinks, ...)", "Context menu name"));
    branchLinksContextMenu->addAction(actionOpenURL);
    branchLinksContextMenu->addAction(actionOpenURLTab);
    branchLinksContextMenu->addAction(actionOpenMultipleVisURLTabs);
    branchLinksContextMenu->addAction(actionOpenMultipleURLTabs);
    branchLinksContextMenu->addAction(actionURLNew);
    branchLinksContextMenu->addAction(actionLocalURL);
    branchLinksContextMenu->addAction(actionGetURLsFromNote);
    branchLinksContextMenu->addAction(actionHeading2URL);
    branchLinksContextMenu->addAction(actionGetJiraDataSubtree);
    branchLinksContextMenu->addAction(actionGetConfluencePageName);
    branchLinksContextMenu->addSeparator();
    branchLinksContextMenu->addAction(actionOpenVymLink);
    branchLinksContextMenu->addAction(actionOpenVymLinkBackground);
    branchLinksContextMenu->addAction(actionOpenMultipleVymLinks);
    branchLinksContextMenu->addAction(actionEditVymLink);
    branchLinksContextMenu->addAction(actionDeleteVymLink);

    // Context Menu for XLinks in a branch menu
    // This will be populated "on demand" in updateActions
    QString tag = tr("XLinks", "Menu for file actions");
    branchContextMenu->addSeparator();
    branchXLinksContextMenuEdit =
        branchContextMenu->addMenu(tr("Edit XLink", "Context menu name"));
    connect(branchXLinksContextMenuEdit, SIGNAL(triggered(QAction *)), this,
            SLOT(editEditXLink(QAction *)));
    QAction *a;
    a = new QAction(tr("Follow XLink", "Context menu"), this);
    a->setShortcut(Qt::Key_F);
    addAction(a);
    switchboard.addSwitch("mapFollowXLink", shortcutScope, a, tag);
    connect(a, SIGNAL(triggered()), this, SLOT(popupFollowXLink()));

    branchXLinksContextMenuFollow =
        branchContextMenu->addMenu(tr("Follow XLink", "Context menu name"));
    connect(branchXLinksContextMenuFollow, SIGNAL(triggered(QAction *)), this,
            SLOT(editFollowXLink(QAction *)));

    // Context menu for floatimage
    floatimageContextMenu = new QMenu(this);
    a = new QAction(tr("Save image", "Context action"), this);
    connect(a, SIGNAL(triggered()), this, SLOT(editSaveImage()));
    floatimageContextMenu->addAction(a);

    floatimageContextMenu->addSeparator();
    floatimageContextMenu->addAction(actionCopy);
    floatimageContextMenu->addAction(actionCut);

    floatimageContextMenu->addSeparator();
    floatimageContextMenu->addAction(actionGrowSelectionSize);
    floatimageContextMenu->addAction(actionShrinkSelectionSize);
    floatimageContextMenu->addAction(actionFormatHideLinkUnselected);

    // Context menu for canvas
    canvasContextMenu = new QMenu(this);

    canvasContextMenu->addAction(actionAddMapCenter);

    canvasContextMenu->addSeparator();

    canvasContextMenu->addAction(actionMapProperties);
    canvasContextMenu->addAction(actionFormatFont);

    canvasContextMenu->addSeparator();

    canvasContextMenu->addActions(actionGroupFormatLinkStyles->actions());

    canvasContextMenu->addSeparator();

    canvasContextMenu->addAction(actionFormatLinkColorHint);

    canvasContextMenu->addSeparator();

    canvasContextMenu->addAction(actionFormatLinkColor);
    canvasContextMenu->addAction(actionFormatSelectionColor);
    canvasContextMenu->addAction(actionFormatBackColor);
    // if (settings.value( "/mainwindow/showTestMenu",false).toBool() )
    //    canvasContextMenu->addAction( actionFormatBackImage );  //FIXME-3
    //    makes vym too slow: postponed for later version

    // Menu for last opened files
    // Create actions
    for (int i = 0; i < MaxRecentFiles; ++i) {
        recentFileActions[i] = new QAction(this);
        recentFileActions[i]->setVisible(false);
        fileLastMapsMenu->addAction(recentFileActions[i]);
        connect(recentFileActions[i], SIGNAL(triggered()), this,
                SLOT(fileLoadRecent()));
    }
    setupRecentMapsMenu();
}

void Main::setupRecentMapsMenu()
{
    QStringList files =
        settings.value("/mainwindow/recentFileList").toStringList();

    int numRecentFiles = qMin(files.size(), (int)MaxRecentFiles);

    for (int i = 0; i < numRecentFiles; ++i) {
        QString text = QString("&%1 %2").arg(i + 1).arg(files[i]);
        recentFileActions[i]->setText(text);
        recentFileActions[i]->setData(files[i]);
        recentFileActions[i]->setVisible(true);
    }
    for (int j = numRecentFiles; j < MaxRecentFiles; ++j)
        recentFileActions[j]->setVisible(false);
}

void Main::setupMacros()
{
    for (int i = 0; i <= 47; i++) {
        macroActions[i] = new QAction(this);
        macroActions[i]->setData(i);
        addAction(macroActions[i]);
        connect(macroActions[i], SIGNAL(triggered()), this, SLOT(callMacro()));
    }
    macroActions[0]->setShortcut(Qt::Key_F1);
    macroActions[1]->setShortcut(Qt::Key_F2);
    macroActions[2]->setShortcut(Qt::Key_F3);
    macroActions[3]->setShortcut(Qt::Key_F4);
    macroActions[4]->setShortcut(Qt::Key_F5);
    macroActions[5]->setShortcut(Qt::Key_F6);
    macroActions[6]->setShortcut(Qt::Key_F7);
    macroActions[7]->setShortcut(Qt::Key_F8);
    macroActions[8]->setShortcut(Qt::Key_F9);
    macroActions[9]->setShortcut(Qt::Key_F10);
    macroActions[10]->setShortcut(Qt::Key_F11);
    macroActions[11]->setShortcut(Qt::Key_F12);

    // Shift Modifier
    macroActions[12]->setShortcut(Qt::Key_F1 + Qt::SHIFT);
    macroActions[13]->setShortcut(Qt::Key_F2 + Qt::SHIFT);
    macroActions[14]->setShortcut(Qt::Key_F3 + Qt::SHIFT);
    macroActions[15]->setShortcut(Qt::Key_F4 + Qt::SHIFT);
    macroActions[16]->setShortcut(Qt::Key_F5 + Qt::SHIFT);
    macroActions[17]->setShortcut(Qt::Key_F6 + Qt::SHIFT);
    macroActions[18]->setShortcut(Qt::Key_F7 + Qt::SHIFT);
    macroActions[19]->setShortcut(Qt::Key_F8 + Qt::SHIFT);
    macroActions[20]->setShortcut(Qt::Key_F9 + Qt::SHIFT);
    macroActions[21]->setShortcut(Qt::Key_F10 + Qt::SHIFT);
    macroActions[22]->setShortcut(Qt::Key_F11 + Qt::SHIFT);
    macroActions[23]->setShortcut(Qt::Key_F12 + Qt::SHIFT);

    // Ctrl Modifier
    macroActions[24]->setShortcut(Qt::Key_F1 + Qt::CTRL);
    macroActions[25]->setShortcut(Qt::Key_F2 + Qt::CTRL);
    macroActions[26]->setShortcut(Qt::Key_F3 + Qt::CTRL);
    macroActions[27]->setShortcut(Qt::Key_F4 + Qt::CTRL);
    macroActions[28]->setShortcut(Qt::Key_F5 + Qt::CTRL);
    macroActions[29]->setShortcut(Qt::Key_F6 + Qt::CTRL);
    macroActions[30]->setShortcut(Qt::Key_F7 + Qt::CTRL);
    macroActions[31]->setShortcut(Qt::Key_F8 + Qt::CTRL);
    macroActions[32]->setShortcut(Qt::Key_F9 + Qt::CTRL);
    macroActions[33]->setShortcut(Qt::Key_F10 + Qt::CTRL);
    macroActions[34]->setShortcut(Qt::Key_F11 + Qt::CTRL);
    macroActions[35]->setShortcut(Qt::Key_F12 + Qt::CTRL);

    // Shift + Ctrl Modifier
    macroActions[36]->setShortcut(Qt::Key_F1 + Qt::CTRL + Qt::SHIFT);
    macroActions[37]->setShortcut(Qt::Key_F2 + Qt::CTRL + Qt::SHIFT);
    macroActions[38]->setShortcut(Qt::Key_F3 + Qt::CTRL + Qt::SHIFT);
    macroActions[39]->setShortcut(Qt::Key_F4 + Qt::CTRL + Qt::SHIFT);
    macroActions[40]->setShortcut(Qt::Key_F5 + Qt::CTRL + Qt::SHIFT);
    macroActions[41]->setShortcut(Qt::Key_F6 + Qt::CTRL + Qt::SHIFT);
    macroActions[42]->setShortcut(Qt::Key_F7 + Qt::CTRL + Qt::SHIFT);
    macroActions[43]->setShortcut(Qt::Key_F8 + Qt::CTRL + Qt::SHIFT);
    macroActions[44]->setShortcut(Qt::Key_F9 + Qt::CTRL + Qt::SHIFT);
    macroActions[45]->setShortcut(Qt::Key_F10 + Qt::CTRL + Qt::SHIFT);
    macroActions[46]->setShortcut(Qt::Key_F11 + Qt::CTRL + Qt::SHIFT);
    macroActions[47]->setShortcut(Qt::Key_F12 + Qt::CTRL + Qt::SHIFT);
}

void Main::setupToolbars()
{
    // File actions
    fileToolbar =
        addToolBar(tr("File actions toolbar", "Toolbar for file actions"));
    fileToolbar->setObjectName("fileTB");
    fileToolbar->addAction(actionFileNew);
    fileToolbar->addAction(actionFileOpen);
    fileToolbar->addAction(actionFileSave);
    fileToolbar->addAction(actionFileExportLast);
    fileToolbar->addAction(actionFilePrint);

    // Undo/Redo and clipboard
    clipboardToolbar = addToolBar(tr("Undo and clipboard toolbar",
                                     "Toolbar for redo/undo and clipboard"));
    clipboardToolbar->setObjectName("clipboard toolbar");
    clipboardToolbar->addAction(actionUndo);
    clipboardToolbar->addAction(actionRedo);
    clipboardToolbar->addAction(actionCopy);
    clipboardToolbar->addAction(actionCut);
    clipboardToolbar->addAction(actionPaste);

    // Basic edits
    editActionsToolbar = addToolBar(tr("Edit actions toolbar", "Toolbar name"));
    editActionsToolbar->setObjectName("basic edit actions TB");
    editActionsToolbar->addAction(actionAddMapCenter);
    editActionsToolbar->addAction(actionAddBranch);
    editActionsToolbar->addAction(actionMoveUp);
    editActionsToolbar->addAction(actionMoveDown);
    editActionsToolbar->addAction(actionMoveDownDiagonally);
    editActionsToolbar->addAction(actionMoveUpDiagonally);
    editActionsToolbar->addAction(actionSortChildren);
    editActionsToolbar->addAction(actionSortBackChildren);
    editActionsToolbar->addAction(actionToggleScroll);
    editActionsToolbar->addAction(actionToggleHideExport);
    editActionsToolbar->addAction(actionToggleTask);
    // editActionsToolbar->addAction (actionExpandAll);
    // editActionsToolbar->addAction (actionExpandOneLevel);
    // editActionsToolbar->addAction (actionCollapseOneLevel);
    // editActionsToolbar->addAction (actionCollapseUnselected);

    // Selections
    selectionToolbar = addToolBar(tr("Selection toolbar", "Toolbar name"));
    selectionToolbar->setObjectName("toolbar for selecting items");
    selectionToolbar->addAction(actionToggleTarget);
    selectionToolbar->addAction(actionSelectPrevious);
    selectionToolbar->addAction(actionSelectNext);
    selectionToolbar->addAction(actionFind);

    // URLs and vymLinks
    referencesToolbar = addToolBar(
        tr("URLs and vymLinks toolbar", "Toolbar for URLs and vymlinks"));
    referencesToolbar->setObjectName("URLs and vymlinks toolbar");
    referencesToolbar->addAction(actionURLNew);
    referencesToolbar->addAction(actionEditVymLink);

    // Format and colors
    colorsToolbar = new QToolBar(tr("Colors toolbar", "Colors toolbar name"));
    colorsToolbar->setObjectName("colorsTB");

    actionGroupQuickColors = new QActionGroup(this);
    actionGroupQuickColors->setExclusive(true);

    // Define quickColors
    QColor c;
    c.setNamedColor ("#ff0000"); quickColors << c;  // Red
    c.setNamedColor ("#d95100"); quickColors << c;  // Orange
    c.setNamedColor ("#009900"); quickColors << c;  // Green
    c.setNamedColor ("#aa00ff"); quickColors << c;  // Purple
    c.setNamedColor ("#0000ff"); quickColors << c;  // Blue
    c.setNamedColor ("#00aaff"); quickColors << c;  // LightBlue
    usingDarkTheme ? vymBlue = c : vymBlue = quickColors.count() - 2;
    c.setNamedColor ("#000000"); quickColors << c;  // Black
    c.setNamedColor ("#444444"); quickColors << c;  // Dark gray
    c.setNamedColor ("#aaaaaa"); quickColors << c;  // Light gray
    c.setNamedColor ("#ffffff"); quickColors << c;  // White
    //c.setNamedColor ("#00aa7f"); quickColors << c;  // Light green
    //c.setNamedColor ("#c466ff"); quickColors << c;  // Light purple

    QPixmap pix(16, 16);
    QAction *a;
    int n = 0;
    foreach (c, quickColors) {
        pix.fill(c);
        a = new QAction(pix, tr("Select color (Press Shift for more options)") + QString("..."), actionGroupQuickColors);
        a->setCheckable(true);
        a->setData(n);
        //formatMenu->addAction(a);
        // switchboard.addSwitch("mapFormatColor", shortcutScope, a, tag);
        connect(a, SIGNAL(triggered()), this, SLOT(quickColorPressed()));
        colorsToolbar->addAction(a);
        n++;
    }
    actionGroupQuickColors->actions().first()->setChecked(true);

    colorsToolbar->addAction(actionFormatPickColor);
    colorsToolbar->addAction(actionFormatColorBranch);
    colorsToolbar->addAction(actionFormatColorSubtree);
    // Only place toolbar on very first startup
    if (settings.value("/mainwindow/recentFileList").toStringList().isEmpty())
        addToolBar (Qt::RightToolBarArea, colorsToolbar);
    else
        addToolBar (colorsToolbar);

    // Zoom
    zoomToolbar = addToolBar(tr("View toolbar", "View Toolbar name"));
    zoomToolbar->setObjectName("viewTB");
    zoomToolbar->addAction(actionTogglePresentationMode);
    zoomToolbar->addAction(actionZoomIn);
    zoomToolbar->addAction(actionZoomOut);
    zoomToolbar->addAction(actionZoomReset);
    zoomToolbar->addAction(actionCenterOn);
    zoomToolbar->addAction(actionRotateCounterClockwise);
    zoomToolbar->addAction(actionRotateClockwise);

    // Editors
    editorsToolbar = addToolBar(tr("Editors toolbar", "Editor Toolbar name"));
    editorsToolbar->setObjectName("editorsTB");
    editorsToolbar->addAction(actionViewToggleNoteEditor);
    editorsToolbar->addAction(actionViewToggleHeadingEditor);
    editorsToolbar->addAction(actionViewToggleTreeEditor);
    editorsToolbar->addAction(actionViewToggleTaskEditor);
    editorsToolbar->addAction(actionViewToggleSlideEditor);
    editorsToolbar->addAction(actionViewToggleScriptEditor);
    editorsToolbar->addAction(actionViewToggleHistoryWindow);

    // Modifier modes
    modModesToolbar =
        addToolBar(tr("Modifier modes toolbar", "Modifier Toolbar name"));
    modModesToolbar->setObjectName("modesTB");
    modModesToolbar->addAction(actionModModePoint);
    modModesToolbar->addAction(actionModModeColor);
    modModesToolbar->addAction(actionModModeXLink);
    modModesToolbar->addAction(actionModModeMoveObject);
    modModesToolbar->addAction(actionModModeMoveView);

    // Create flag toolbars (initialized later in setupFlagActions() )
    addToolBarBreak();
    standardFlagsToolbar =
        addToolBar(tr("Standard Flags toolbar", "Standard Flag Toolbar"));
    standardFlagsToolbar->setObjectName("standardFlagTB");
    standardFlagsMaster->setToolBar(standardFlagsToolbar);

    userFlagsToolbar =
        addToolBar(tr("User Flags toolbar", "user Flags Toolbar"));
    userFlagsToolbar->setObjectName("userFlagsTB");
    userFlagsMaster->setToolBar(userFlagsToolbar);
    userFlagsMaster->createConfigureAction();

    // Add all toolbars to View menu
    toolbarsMenu->addAction(fileToolbar->toggleViewAction());
    toolbarsMenu->addAction(clipboardToolbar->toggleViewAction());
    toolbarsMenu->addAction(editActionsToolbar->toggleViewAction());
    toolbarsMenu->addAction(selectionToolbar->toggleViewAction());
    toolbarsMenu->addAction(colorsToolbar->toggleViewAction());
    toolbarsMenu->addAction(zoomToolbar->toggleViewAction());
    toolbarsMenu->addAction(modModesToolbar->toggleViewAction());
    toolbarsMenu->addAction(referencesToolbar->toggleViewAction());
    toolbarsMenu->addAction(editorsToolbar->toggleViewAction());
    toolbarsMenu->addAction(userFlagsToolbar->toggleViewAction());
    toolbarsMenu->addAction(standardFlagsToolbar->toggleViewAction());

    // Initialize toolbarStates for presentation mode
    toolbarStates[fileToolbar] = true;
    toolbarStates[clipboardToolbar] = true;
    toolbarStates[editActionsToolbar] = true;
    toolbarStates[selectionToolbar] = false;
    toolbarStates[colorsToolbar] = true;
    toolbarStates[zoomToolbar] = true;
    toolbarStates[modModesToolbar] = false;
    toolbarStates[referencesToolbar] = true;
    toolbarStates[editorsToolbar] = false;
    toolbarStates[standardFlagsToolbar] = true;
    toolbarStates[userFlagsToolbar] = true;

    // Initialize toolbar visibilities and switch off presentation mode
    presentationMode = true;
    togglePresentationMode();
}

VymView *Main::currentView() const
{
    if (tabWidget->currentWidget())
        return (VymView *)tabWidget->currentWidget();
    else
        return nullptr;
}

VymView *Main::view(const int i) { return (VymView *)tabWidget->widget(i); }

MapEditor *Main::currentMapEditor() const
{
    if (tabWidget->currentWidget())
        return currentView()->getMapEditor();
    return nullptr;
}

uint Main::currentMapID() const
{
    VymModel *m = currentModel();
    if (m)
        return m->getModelID();
    else
        return 0;
}

int Main::currentMapIndex() const { return tabWidget->currentIndex(); }

VymModel *Main::currentModel() const
{
    VymView *vv = currentView();
    if (vv)
        return vv->getModel();
    else
        return NULL;
}

VymModel *Main::getModel(uint id) // Used in BugAgent
{
    if (id <= 0)
        return NULL;

    for (int i = 0; i < tabWidget->count(); i++) {
        if (view(i)->getModel()->getModelID() == id)
            return view(i)->getModel();
    }
    return NULL;
}

void Main::gotoModel(VymModel *m)
{
    for (int i = 0; i < tabWidget->count(); i++)
        if (view(i)->getModel() == m) {
            tabWidget->setCurrentIndex(i);
            return;
        }
}

void Main::gotoModelWithID(uint id)
{
    VymModel *vm;
    for (int i = 0; i < tabWidget->count(); i++) {
        vm = view(i)->getModel();
        if (vm && vm->getModelID() == id) {
            tabWidget->setCurrentIndex(i);
            return;
        }
    }
}

bool Main::closeModelWithID(uint id)
{
    VymModel *vm;
    for (int i = 0; i < tabWidget->count(); i++) {
        vm = view(i)->getModel();
        if (vm && vm->getModelID() == id) {
            tabWidget->removeTab(i);

            // Destroy stuff, order is important
            delete (vm->getMapEditor());
            delete (view(i));
            delete (vm);

            updateActions();
            return true;
        }
    }
    return false;
}

int Main::modelCount() { return tabWidget->count(); }

void Main::updateTabName(VymModel *vm)
{
    if (!vm) {
        qWarning() << "Main::updateTabName   vm == NULL";
        return;
    }

    for (int i = 0; i < tabWidget->count(); i++)
        if (view(i)->getModel() == vm) {
            if (vm->isReadOnly())
                tabWidget->setTabText(i, vm->getFileName() + " " +
                                             tr("(readonly)"));
            else
                tabWidget->setTabText(i, vm->getFileName());
            return;
        }
}

void Main::editorChanged()
{
    VymModel *vm = currentModel();
    if (vm) {
        BranchItem *bi = vm->getSelectedBranch();
        updateNoteEditor(bi);
        updateHeadingEditor(bi);
        updateQueries(vm);
        taskEditor->setMapName(vm->getMapName());
        updateDockWidgetTitles(vm);
    }

    // Update actions to in menus and toolbars according to editor
    updateActions();
}

void Main::fileNew()
{
    VymModel *vm;

    // Don't show counter while loading default map
    removeProgressCounter();

    if (File::Success != fileLoad(newMapPath(), DefaultMap, VymMap)) {
        QMessageBox::critical(0, tr("Critical Error"),
                              tr("Couldn't load default map:\n\n%1\n\nvym will "
                                 "create an empty map now.",
                                 "Mainwindow: Failed to load default map")
                                  .arg(newMapPath()));

        vm = currentModel();

        // Create MapCenter for empty map  
        vm->addMapCenter(false);
        vm->makeDefault();

        // For the very first map we do not have flagrows yet...
        vm->select("mc:");

        // Set name to "unnamed"
        updateTabName(vm);
    }
    else {
        vm = currentModel();
    }
    
    // Switch to new tab    
    tabWidget->setCurrentIndex(tabWidget->count() - 1);
}

void Main::fileNewCopy()
{
    QString fn = "unnamed";
    VymModel *srcModel = currentModel();
    if (srcModel) {
        srcModel->copy();
        fileNew();
        VymModel *dstModel = view(tabWidget->count() - 1)->getModel();
        if (dstModel && dstModel->select("mc:0"))
            dstModel->paste();
        else
            qWarning() << "Main::fileNewCopy couldn't select mapcenter";
    }
}

File::ErrorCode Main::fileLoad(QString fn, const LoadMode &lmode,
                               const FileType &ftype)
{
    File::ErrorCode err = File::Success;

    // fn is usually the archive, mapfile the file after uncompressing
    QString mapfile;

    // Make fn absolute (needed for unzip)
    fn = QDir(fn).absolutePath();

    VymModel *vm;

    if (lmode == NewMap) {
        // Check, if map is already loaded
        int i = 0;
        while (i <= tabWidget->count() - 1) {
            if (view(i)->getModel()->getFilePath() == fn) {
                // Already there, ask for confirmation
                QMessageBox mb(
                    vymName,
                    tr("The map %1\nis already opened."
                       "Opening the same map in multiple editors may lead \n"
                       "to confusion when finishing working with vym."
                       "Do you want to")
                        .arg(fn),
                    QMessageBox::Warning,
                    QMessageBox::Yes | QMessageBox::Default,
                    QMessageBox::Cancel | QMessageBox::Escape,
                    QMessageBox::NoButton);
                mb.setButtonText(QMessageBox::Yes, tr("Open anyway"));
                mb.setButtonText(QMessageBox::Cancel, tr("Cancel"));
                switch (mb.exec()) {
                case QMessageBox::Yes:
                    // end loop and load anyway
                    i = tabWidget->count();
                    break;
                case QMessageBox::Cancel:
                    // do nothing
                    return File::Aborted;
                    break;
                }
            }
            i++;
        }
    }

    bool createModel;

    // Try to load map
    if (!fn.isEmpty()) {
        // Find out, if we need to create a new map model

        vm = currentModel();

        if (lmode == NewMap) {
            if (vm && vm->isDefault()) {
                // There is a map model already and it still the default map,
                // use it.
                createModel = false;
            }
            else
                createModel = true;
        }
        else if (lmode == DefaultMap) {
            createModel = true;
        }
        else if (lmode == ImportAdd || lmode == ImportReplace) {
            if (!vm) {
                QMessageBox::warning(0, "Warning",
                                     "Trying to import into non existing map");
                return File::Aborted;
            }
            else
                createModel = false;
        }
        else
            createModel = true;

        if (createModel) {
            vm = new VymModel;
            VymView *vv = new VymView(vm);

            tabWidget->addTab(vv, fn);
            vv->initFocus();
        }

        // Check, if file exists (important for creating new files
        // from command line
        if (!QFile(fn).exists()) {
            if (lmode == DefaultMap) {
                return File::Aborted;
            }

            if (lmode == NewMap) {
                QMessageBox mb(vymName,
                               tr("This map does not exist:\n  %1\nDo you want "
                                  "to create a new one?")
                                   .arg(fn),
                               QMessageBox::Question, QMessageBox::Yes,
                               QMessageBox::Cancel | QMessageBox::Default,
                               QMessageBox::NoButton);

                mb.setButtonText(QMessageBox::Yes, tr("Create"));
                mb.setButtonText(QMessageBox::No, tr("Cancel"));

                vm = currentMapEditor()->getModel();
                switch (mb.exec()) {
                case QMessageBox::Yes:
                    // Create new map
                    vm->setFilePath(fn);
                    updateTabName(vm);
                    statusBar()->showMessage("Created " + fn, statusbarTime);
                    return File::Success;

                case QMessageBox::Cancel:
                    // don't create new map
                    statusBar()->showMessage("Loading " + fn + " failed!",
                                             statusbarTime);
                    int cur = tabWidget->currentIndex();
                    tabWidget->setCurrentIndex(tabWidget->count() - 1);
                    fileCloseMap();
                    tabWidget->setCurrentIndex(cur);
                    return File::Aborted;
                }

                // ImportAdd or ImportReplace
                qWarning() << QString("Warning:  Could not import %1 into %2")
                                  .arg(fn)
                                  .arg(vm->getFilePath());
                return File::Aborted;
            }
        }

        if (err != File::Aborted) {
            // Save existing filename in case  we import
            QString fn_org = vm->getFilePath();

            if (lmode != DefaultMap) {

                vm->setFilePath(fn);
                vm->saveStateBeforeLoad(lmode, fn);

                progressDialog.setLabelText(
                    tr("Loading: %1", "Progress dialog while loading maps")
                        .arg(fn));
            }

            // Finally load map into mapEditor
            err = vm->loadMap(fn, lmode, ftype);

            // Restore old (maybe empty) filepath, if this is an import
            if (lmode == ImportAdd || lmode == ImportReplace)
                vm->setFilePath(fn_org);
        }

        // Finally check for errors and go home
        if (err == File::Aborted) {
            if (lmode == NewMap)
                fileCloseMap();
            statusBar()->showMessage("Could not load " + fn, statusbarTime);
        }
        else {
            if (lmode == NewMap) {
                vm->setFilePath(fn);
                updateTabName(vm);
                actionFilePrint->setEnabled(true);
                addRecentMap(fn);
            }
            else if (lmode == DefaultMap) {
                vm->makeDefault();
                updateTabName(vm);
            }
            editorChanged();
            vm->emitShowSelection();
            statusBar()->showMessage(tr("Loaded %1").arg(fn), statusbarTime);
        }
    }

    fileSaveSession();

    return err;
}

void Main::fileLoad(const LoadMode &lmode)
{
    QString caption;
    switch (lmode) {
    case NewMap:
        caption = vymName + " - " + tr("Load vym map");
        break;
    case DefaultMap:
        // Not used directly
        return;
    case ImportAdd:
        caption = vymName + " - " + tr("Import: Add vym map to selection");
        break;
    case ImportReplace:
        caption =
            vymName + " - " + tr("Import: Replace selection with vym map");
        break;
    }

    QString filter;
    filter += "VYM map " + tr("or", "File Dialog") + " Freemind map" +
              " (*.xml *.vym *.vyp *.mm);;";
    filter += "VYM map (*.vym *.vyp);;";
    filter += "VYM Backups (*.vym~);;";
    filter += "Freemind map (*.mm);;";
    filter += "XML (*.xml);;";
    filter += "All (* *.*)";
    QStringList fns =
        QFileDialog::getOpenFileNames(this, caption, lastMapDir.path(), filter);

    if (!fns.isEmpty()) {
        initProgressCounter(fns.count());
        lastMapDir.setPath(fns.first().left(fns.first().lastIndexOf("/")));
        foreach (QString fn, fns)
            fileLoad(fn, lmode, getMapType(fn));
    }
    removeProgressCounter();
}

void Main::fileLoad()
{
    fileLoad(NewMap);
    tabWidget->setCurrentIndex(tabWidget->count() - 1);
}

void Main::fileSaveSession()
{
    QStringList flist;
    for (int i = 0; i < tabWidget->count(); i++)
        flist.append(view(i)->getModel()->getFilePath());

    settings.setValue("/mainwindow/sessionFileList", flist);

    // Also called by event loop regulary, but apparently not often enough
    settings.sync();
}

void Main::fileRestoreSession()
{
    restoreMode = true;

    QStringList::Iterator it = lastSessionFiles.begin();

    initProgressCounter(lastSessionFiles.count());
    while (it != lastSessionFiles.end()) {
        FileType type = getMapType(*it);
        fileLoad(*it, NewMap, type);
        *it++;
    }
    removeProgressCounter();

    // By now all files should have been loaded
    // Reset the restore flag and display message if needed
    if (ignoredLockedFiles.count() > 0) {
        QString msg(
            QObject::tr("Existing lockfiles have been ignored for the maps "
                        "listed below. Please check, if the maps might be "
                        "openend in another instance of vym:\n\n"));
        WarningDialog warn;
        warn.setMinimumWidth(800);
        warn.setMinimumHeight(350);
        warn.showCancelButton(false);
        warn.setCaption("Existing lockfiles ignored");
        warn.setText(msg + ignoredLockedFiles.join("\n"));
        warn.exec();
    }

    restoreMode = false;
    ignoredLockedFiles.clear();
}

void Main::fileLoadRecent()
{
    QAction *action = qobject_cast<QAction *>(sender());
    if (action) {
        initProgressCounter();
        QString fn = action->data().toString();
        FileType type = getMapType(fn);
        fileLoad(fn, NewMap, type);
        removeProgressCounter();
        tabWidget->setCurrentIndex(tabWidget->count() - 1);
    }
}

void Main::addRecentMap(const QString &fileName)
{

    QStringList files =
        settings.value("/mainwindow/recentFileList").toStringList();
    files.removeAll(fileName);
    files.prepend(fileName);
    while (files.size() > MaxRecentFiles)
        files.removeLast();

    settings.setValue("/mainwindow/recentFileList", files);

    setupRecentMapsMenu();
}

void Main::fileSave(VymModel *m, const SaveMode &savemode)
{
    if (!m)
        return;

    if (m->isReadOnly())
        return;

    if (m->getFilePath().isEmpty()) {
        // We have  no filepath yet,
        // call fileSaveAs() now, this will call fileSave()
        // again.  First switch to editor
        fileSaveAs(savemode);
        return; // avoid saving twice...
    }

    // Notification, that we start to save
    statusBar()->showMessage(tr("Saving  %1...").arg(m->getFilePath()),
                         statusbarTime);
    qApp->processEvents();

    if (m->save(savemode) == File::Success) {
        statusBar()->showMessage(tr("Saved  %1").arg(m->getFilePath()),
                                 statusbarTime);
    }
    else
        statusBar()->showMessage(tr("Couldn't save ").arg(m->getFilePath()),
                                 statusbarTime);
}

void Main::fileSave() { fileSave(currentModel(), CompleteMap); }

void Main::fileSave(VymModel *m) { fileSave(m, CompleteMap); }

void Main::fileSaveAs(const SaveMode &savemode)
{
    VymModel *m = currentModel();
    if (!m) return;

    if (currentMapEditor()) {   // FIXME-2 this check is not needed
        QString filter;
        if (savemode == CompleteMap)
            filter = "VYM map (*.vym)";
        else
            filter = "VYM part of map (*vyp)";
        filter += ";;All (* *.*)";

        // Get destination path
        QString fn = QFileDialog::getSaveFileName(
            this, tr("Save map as"), lastMapDir.path(), filter, NULL,
            QFileDialog::DontConfirmOverwrite);
        if (!fn.isEmpty()) {
            // Check for existing file
            if (QFile(fn).exists()) {
                // Check if the existing file is writable
                if (!QFileInfo(fn).isWritable()) {
                    QMessageBox::critical(0, tr("Critical Error"),
                                          tr("Couldn't save %1,\nbecause file "
                                             "exists and cannot be changed.")
                                              .arg(fn));
                    return;
                }

                QMessageBox mb(
                    vymName,
                    tr("The file %1\nexists already. Do you want to").arg(fn),
                    QMessageBox::Warning,
                    QMessageBox::Yes | QMessageBox::Default,
                    QMessageBox::Cancel | QMessageBox::Escape,
                    QMessageBox::NoButton);
                mb.setButtonText(QMessageBox::Yes, tr("Overwrite"));
                mb.setButtonText(QMessageBox::Cancel, tr("Cancel"));
                switch (mb.exec()) {
                case QMessageBox::Yes:
                    // save
                    break;
                case QMessageBox::Cancel:
                    // do nothing
                    return;
                    break;
                }
                lastMapDir.setPath(fn.left(fn.lastIndexOf("/")));
            }
            else {
                // New file, add extension to filename, if missing
                // This is always .vym or .vyp, depending on savemode
                if (savemode == CompleteMap) {
                    if (!fn.contains(".vym") && !fn.contains(".xml"))
                        fn += ".vym";
                }
                else {
                    if (!fn.contains(".vyp") && !fn.contains(".xml"))
                        fn += ".vyp";
                }
            }

            // Save original filepath, might want to restore after saving
            QString fn_org = m->getFilePath();

            // Check for existing lockfile
            QFile lockFile(fn + ".lock");
            if (lockFile.exists()) {
                QMessageBox::critical(0, tr("Critical Error"),
                                      tr("Couldn't save %1,\nbecause of "
                                         "existing lockfile:\n\n%2")
                                          .arg(fn)
                                          .arg(lockFile.fileName()));
                return;
            }

            if (!m->renameMap(fn)) {
                QMessageBox::critical(0, tr("Critical Error"),
                                      tr("Saving the map failed:\nCouldn't rename map to %1").arg(fn));
                return; // FIXME-3 Check: If saved part of map and this error occurs?
            }

            fileSave(m, savemode);

            // Set name of tab
            if (savemode == CompleteMap)
                updateTabName(m);
            else { // Renaming map to original name, because we only saved the
                   // selected part of it
                m->setFilePath(fn_org);
                if (!m->renameMap(fn_org)) {
                    QMessageBox::critical(0, "Critical Error",
                                          "Couldn't rename map back to " + fn_org);
                }
            }
            return;
        }
    }
}

void Main::fileSaveAs() { fileSaveAs(CompleteMap); }

void Main::fileSaveAsDefault()
{
    if (currentMapEditor()) {
        QString fn = QFileDialog::getSaveFileName(
            this, tr("Save map as new default map"), newMapPath(),
            "VYM map (*.vym)", NULL, QFileDialog::DontConfirmOverwrite);

        if (!fn.isEmpty()) {
            // Check for existing file
            if (QFile(fn).exists()) {
                // Check if the existing file is writable
                if (!QFileInfo(fn).isWritable()) {
                    QMessageBox::critical(
                        0, tr("Warning"),
                        tr("You have no permissions to write to ") + fn);
                    return;
                }

                // Confirm overwrite of existing file
                QMessageBox mb(
                    vymName,
                    tr("The file %1\nexists already. Do you want to").arg(fn),
                    QMessageBox::Warning,
                    QMessageBox::Yes | QMessageBox::Default,
                    QMessageBox::Cancel | QMessageBox::Escape,
                    QMessageBox::NoButton);
                mb.setButtonText(QMessageBox::Yes,
                                 tr("Overwrite as new default map"));
                mb.setButtonText(QMessageBox::Cancel, tr("Cancel"));
                switch (mb.exec()) {
                case QMessageBox::Yes:
                    // save
                    break;
                case QMessageBox::Cancel:
                    // do nothing
                    return;
                    break;
                }
            }

            // Save now as new default
            VymModel *m = currentModel();
            QString fn_org = m->getFilePath(); // Restore fn later, if savemode
                                               // != CompleteMap
            // Check for existing lockfile
            QFile lockFile(fn + ".lock");
            if (lockFile.exists()) {
                QMessageBox::critical(
                    0, tr("Critical Error"),
                    tr("Couldn't save %1,\nbecause of existing lockfile:\n\n%2")
                        .arg(fn)
                        .arg(lockFile.fileName()));
                return;
            }

            if (!m->renameMap(fn)) {
                QMessageBox::critical(0, tr("Critical Error"),
                                      tr("Couldn't save as default, failed to rename to\n%1").arg(fn));
                return;
            }

            fileSave(m, CompleteMap);

            // Set name of tab
            updateTabName(m);

            // Set new default path
            settings.setValue("/system/defaultMap/auto", false);
            settings.setValue("/system/defaultMap/path", fn);
        }
    }
}

void Main::fileImportFirefoxBookmarks()
{
    VymModel *m = currentModel();
    if (!m) {
        fileNew();
        m = currentModel();
        if (!m) return;
    } else {
        if (!m->isDefault())
            // Import into new map
            fileNew();
    }

    if (m) {
        // Try to select first mapcenter of default map
        if (!m->select("mc:0")) return;

        m->setHeadingPlainText("Firefox");

        // Try to add one branch and select it
        /*
        if (!m->addNewBranch()) return;

        m->selectLatestAdded();
        m->setHeadingPlainText("Bookmarks");
        */

        // Open file dialog
        QFileDialog fd;
        fd.setDirectory(vymBaseDir.homePath());
        fd.setFileMode(QFileDialog::ExistingFiles);
        QStringList filters;
        filters << tr("Firefox Bookmarks") + " (*.json)";
        fd.setNameFilters(filters);
        fd.setAcceptMode(QFileDialog::AcceptOpen);
        fd.setWindowTitle(tr("Import Firefox Bookmarks into new map"));
        fd.setLabelText( QFileDialog::Accept, tr("Import"));

        if (fd.exec() == QDialog::Accepted) {
            qApp->processEvents(); // close QFileDialog
            ImportFirefoxBookmarks im(m);
            QStringList flist = fd.selectedFiles();
            QStringList::Iterator it = flist.begin();
            while (it != flist.end()) {
                im.setFile(*it);
                im.transform(); 
                ++it;
            }
        }
    }
}

void Main::fileImportFreemind()
{
    QStringList filters;
    filters << "Freemind map (*.mm)"
            << "All files (*)";
    QFileDialog fd;
    fd.setDirectory(lastMapDir);
    fd.setFileMode(QFileDialog::ExistingFiles);
    fd.setNameFilters(filters);
    fd.setWindowTitle(vymName + " - " + tr("Open Freemind map"));
    fd.setAcceptMode(QFileDialog::AcceptOpen);

    QString fn;
    if (fd.exec() == QDialog::Accepted) {
        lastMapDir = fd.directory();
        QStringList flist = fd.selectedFiles();
        QStringList::Iterator it = flist.begin();
        while (it != flist.end()) {
            fn = *it;
            if (fileLoad(fn, NewMap, FreemindMap)) {
                currentMapEditor()->getModel()->setFilePath("");
            }
            ++it;
        }
    }
}

void Main::fileImportMM()
{
    ImportMM im;

    QFileDialog fd;
    fd.setDirectory(lastMapDir);
    fd.setFileMode(QFileDialog::ExistingFiles);
    QStringList filters;
    filters << "Mind Manager (*.mmap)";
    fd.setNameFilters(filters);
    fd.setAcceptMode(QFileDialog::AcceptOpen);
    fd.setWindowTitle(tr("Import") + " " + "Mind Manager");
    fd.setLabelText( QFileDialog::Accept, tr("Import"));

    if (fd.exec() == QDialog::Accepted) {
        lastMapDir = fd.directory();
        QStringList flist = fd.selectedFiles();
        QStringList::Iterator it = flist.begin();
        while (it != flist.end()) {
            im.setFile(*it);
            if (im.transform() &&
                File::Success ==
                    fileLoad(im.getTransformedFile(), NewMap, VymMap) &&
                currentMapEditor())
                currentMapEditor()->getModel()->setFilePath("");
            ++it;
        }
    }
}

void Main::fileImportDir()
{
    VymModel *m = currentModel();
    if (m)
        m->importDir();
}

void Main::fileExportAO()
{
    VymModel *m = currentModel();
    if (m)
        m->exportAO();
}

void Main::fileExportASCII()
{
    VymModel *m = currentModel();
    if (m)
        m->exportASCII();
}

void Main::fileExportASCIITasks()
{
    VymModel *m = currentModel();
    if (m)
        m->exportASCII("", true);
}

void Main::fileExportConfluence()
{
    VymModel *m = currentModel();
    if (m)
        m->exportConfluence();
}

#include "export-csv.h"
void Main::fileExportCSV() // FIXME-3 not scriptable yet
{
    VymModel *m = currentModel();
    if (m) {
        ExportCSV ex;
        ex.setModel(m);
        ex.addFilter("CSV (*.csv)");
        ex.setDirPath(lastImageDir.absolutePath());
        ex.setWindowTitle(vymName + " -" + tr("Export as CSV") + " " +
                          tr("(still experimental)"));
        if (ex.execDialog()) {
            m->setExportMode(true);
            ex.doExport();
            m->setExportMode(false);
        }
    }
}

void Main::fileExportFirefoxBookmarks()
{
    VymModel *m = currentModel();
    if (m)
        m->exportFirefoxBookmarks();
}

void Main::fileExportHTML()
{
    VymModel *m = currentModel();
    if (m)
        m->exportHTML();
}

void Main::fileExportImage()
{
    VymModel *m = currentModel();
    if (m)
        m->exportImage();
}

#include "export-impress.h"
#include "exportoofiledialog.h"
void Main::fileExportImpress()
{
    ExportOOFileDialog fd;
    // TODO add preview in dialog
    fd.setWindowTitle(vymName + " - " + tr("Export to") + " LibreOffice");
    fd.setDirectory(QDir().current());
    fd.setAcceptMode(QFileDialog::AcceptSave);
    fd.setFileMode(QFileDialog::AnyFile);
    if (fd.foundConfig()) {
        if (fd.exec() == QDialog::Accepted) {
            if (!fd.selectedFiles().isEmpty()) {
                QString fn = fd.selectedFiles().first();
                if (!fn.contains(".odp"))
                    fn += ".odp";

                // lastImageDir=fn.left(fn.findRev ("/"));
                VymModel *m = currentModel();
                if (m)
                    m->exportImpress(fn, fd.selectedConfig());
            }
        }
    }
    else {
        QMessageBox::warning(
            0, tr("Warning"),
            tr("Couldn't find configuration for export to LibreOffice\n"));
    }
}

#include "export-latex.h"
void Main::fileExportLaTeX()
{
    VymModel *m = currentModel();
    if (m)
        m->exportLaTeX();
}

void Main::fileExportMarkdown()
{
    VymModel *m = currentModel();
    if (m)
        m->exportMarkdown();
}

void Main::fileExportOrgMode()
{
    VymModel *m = currentModel();
    if (m)
        m->exportOrgMode();
}

void Main::fileExportPDF()
{
    VymModel *m = currentModel();
    if (m)
        m->exportPDF();
}

void Main::fileExportSVG()
{
    VymModel *m = currentModel();
    if (m)
        m->exportSVG();
}

#include "export-taskjuggler.h"
void Main::fileExportTaskjuggler() // FIXME-3 not scriptable yet
{
    ExportTaskjuggler ex;
    VymModel *m = currentModel();
    if (m) {
        ex.setModel(m);
        ex.setWindowTitle(vymName + " - " + tr("Export to") + " Taskjuggler" +
                          tr("(still experimental)"));
        ex.setDirPath(lastImageDir.absolutePath());
        ex.addFilter("Taskjuggler (*.tjp)");

        if (ex.execDialog()) {
            m->setExportMode(true);
            ex.doExport();
            m->setExportMode(false);
        }
    }
}

void Main::fileExportXML()
{
    VymModel *m = currentModel();
    if (m)
        m->exportXML();
}

void Main::fileExportLast()
{
    VymModel *m = currentModel();
    if (m)
        m->exportLast();
}

bool Main::fileCloseMap(int i)
{
    VymModel *m;
    VymView *vv;
    if (i < 0)
        i = tabWidget->currentIndex();

    vv = view(i);
    m = vv->getModel();

    if (m) {
        if (m->hasChanged()) {
            QMessageBox mb(
                vymName,
                tr("The map %1 has been modified but not saved yet. Do you "
                   "want to")
                    .arg(m->getFileName()),
                QMessageBox::Warning, QMessageBox::Yes | QMessageBox::Default,
                QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape);
            mb.setButtonText(QMessageBox::Yes,
                             tr("Save modified map before closing it"));
            mb.setButtonText(QMessageBox::No, tr("Discard changes"));
            mb.setModal(true);
            mb.show();
            switch (mb.exec()) {
            case QMessageBox::Yes:
                // save and close
                fileSave(m, CompleteMap);
                break;
            case QMessageBox::No:
                // close  without saving
                break;
            case QMessageBox::Cancel:
                // do nothing
                return true;
            }
        }

        tabWidget->removeTab(i);

        // Destroy stuff, order is important
        delete (m->getMapEditor());
        delete (vv);
        delete (m);

        updateActions();
        return false;
    }
    return true; // Better don't exit vym if there is no currentModel()...
}

void Main::filePrint()
{
    if (currentMapEditor())
        currentMapEditor()->print();
}

bool Main::fileExitVYM()
{
    fileSaveSession();

    // Check if one or more editors have changed
    while (tabWidget->count() > 0) {
        tabWidget->setCurrentIndex(0);
        if (fileCloseMap())
            return true;
        qApp->processEvents(); // Update widgets to show progress
    }
    qApp->quit();
    return false;
}

void Main::editUndo()
{
    VymModel *m = currentModel();
    if (m)
        m->undo();
}

void Main::editRedo()
{
    VymModel *m = currentModel();
    if (m)
        m->redo();
}

void Main::gotoHistoryStep(int i)
{
    VymModel *m = currentModel();
    if (m)
        m->gotoHistoryStep(i);
}

void Main::editCopy()
{
    VymModel *m = currentModel();
    if (m)
        m->copy();
}

void Main::editPaste()
{
    VymModel *m = currentModel();
    if (m)
        m->paste();
}

void Main::editCut()
{
    VymModel *m = currentModel();
    if (m)
        m->cut();
}

bool Main::openURL(const QString &url)
{
    if (url.isEmpty())
        return false;

    QString browser = settings.value("/system/readerURL").toString();
    QStringList args;
    args << url;
    if (!QProcess::startDetached(browser, args, QDir::currentPath(),
                                 browserPID)) {
        // try to set path to browser
        QMessageBox::warning(
            0, tr("Warning"),
            tr("Couldn't find a viewer to open %1.\n").arg(url) +
                tr("Please use Settings->") +
                tr("Set application to open an URL"));
        settingsURL();
        return false;
    }
    return true;
}

void Main::openTabs(QStringList urls)
{
    if (urls.isEmpty())
        return;

    // Other browser, e.g. xdg-open
    // Just open all urls and leave it to the system to cope with it
    foreach (QString u, urls)
        openURL(u);
}

void Main::editOpenURL()
{
    // Open new browser
    VymModel *m = currentModel();
    if (m) {
        QString url = m->getURL();
        if (url == "")
            return;
        openURL(url);
    }
}
void Main::editOpenURLTab()
{
    VymModel *m = currentModel();
    if (m) {
        QStringList urls;
        urls.append(m->getURL());
        openTabs(urls);
    }
}

void Main::editOpenMultipleVisURLTabs(bool ignoreScrolled)
{
    VymModel *m = currentModel();
    if (m) {
        QStringList urls;
        urls = m->getURLs(ignoreScrolled);
        openTabs(urls);
    }
}

void Main::editOpenMultipleURLTabs() { editOpenMultipleVisURLTabs(false); }

void Main::editNote2URLs()
{
    VymModel *m = currentModel();
    if (m)
        m->note2URLs();
}

void Main::editURL()
{
    VymModel *m = currentModel();
    if (m) {
        QInputDialog *dia = new QInputDialog(this);
        dia->setLabelText(tr("Enter URL:"));
        dia->setWindowTitle(vymName);
        dia->setInputMode(QInputDialog::TextInput);
        TreeItem *selti = m->getSelectedItem();
        if (selti)
            dia->setTextValue(selti->getURL());
        dia->resize(width() * 0.6, 80);
        centerDialog(dia);

        if (dia->exec())
            m->setURL(dia->textValue());
        delete dia;
    }
}

void Main::editLocalURL()
{
    VymModel *m = currentModel();
    if (m) {
        TreeItem *selti = m->getSelectedItem();
        if (selti) {
            QString filter;
            filter += "All files (*);;";
            filter += tr("HTML", "Filedialog") + " (*.html,*.htm);;";
            filter += tr("Text", "Filedialog") + " (*.txt);;";
            filter += tr("Spreadsheet", "Filedialog") + " (*.odp,*.sxc);;";
            filter += tr("Textdocument", "Filedialog") + " (*.odw,*.sxw);;";
            filter += tr("Images", "Filedialog") +
                      " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)";

            QString fn = QFileDialog::getOpenFileName(
                this, vymName + " - " + tr("Set URL to a local file"),
                lastMapDir.path(), filter);

            if (!fn.isEmpty()) {
                lastMapDir.setPath(fn.left(fn.lastIndexOf("/")));
                if (!fn.startsWith("file://"))
                    fn = "file://" + fn;
                m->setURL(fn);
            }
        }
    }
}

void Main::editHeading2URL()
{
    VymModel *m = currentModel();
    if (m)
        m->editHeading2URL();
}

void Main::getJiraDataSubtree()
{
    VymModel *m = currentModel();
    if (m)
        m->getJiraData(true);
}

void Main::setHeadingConfluencePageName()
{
    VymModel *m = currentModel();
    if (m)
        m->setHeadingConfluencePageName();
}

void Main::getConfluenceUser()
{
    VymModel *m = currentModel();
    if (m) {
        BranchItem *selbi = m->getSelectedBranch();
        if (selbi) {
            ConfluenceUserDialog *dia = new ConfluenceUserDialog;
            centerDialog(dia);
            if (dia->exec() > 0) {
                BranchItem *bi = m->addNewBranch();
                if (!bi) return;
                if (!m->select(bi)) return;
                selbi = m->getSelectedBranch();

                ConfluenceUser user = dia->getSelectedUser();

                AttributeItem *ai;

                ai = new AttributeItem();
                ai->setKey("ConfluenceUser.displayName");
                ai->setValue(user.getDisplayName());
                m->setAttribute(selbi, ai);

                ai = new AttributeItem();
                ai->setKey("ConfluenceUser.userKey");
                ai->setValue(user.getUserKey());
                m->setAttribute(selbi, ai);

                ai = new AttributeItem();
                ai->setKey("ConfluenceUser.userName");
                ai->setValue(user.getUserName());
                m->setAttribute(selbi, ai);

                ai = new AttributeItem();
                ai->setKey("ConfluenceUser.url");
                ai->setValue(user.getURL());
                m->setAttribute(selbi, ai);

                m->setURL(user.getURL(), false);
                m->setHeading(user.getDisplayName());

                m->selectParent();
            }
            dia->clearFocus();
            delete dia;
            m->getMapEditor()->activateWindow();
            m->getMapEditor()->setFocus();
        }
    }
}

void Main::editHeading()
{
    MapEditor *me = currentMapEditor();
    if (me)
        me->editHeading();
}

void Main::editHeadingFinished(VymModel *m)
{
    if (m) {
        if (!actionSettingsAutoSelectNewBranch->isChecked() &&
            !prevSelection.isEmpty())
            m->select(prevSelection);
        prevSelection = "";
    }
}

void Main::openVymLinks(const QStringList &vl, bool background)
{
    QStringList vlmin;
    int index = -1;
    for (int j = 0; j < vl.size(); ++j) {
        // compare path with already loaded maps
        QString absPath = QFileInfo(vl.at(j)).absoluteFilePath();
        index = -1;
        for (int i = 0; i <= tabWidget->count() - 1; i++) {
            if (absPath == view(i)->getModel()->getFilePath()) {
                index = i;
                break;
            }
        }
        if (index < 0)
            vlmin.append(absPath);
    }

    progressCounterTotal = vlmin.size();
    for (int j = 0; j < vlmin.size(); j++) {
        // Load map
        if (!QFile(vlmin.at(j)).exists())
            QMessageBox::critical(0, tr("Critical Error"),
                                  tr("Couldn't open map %1").arg(vlmin.at(j)));
        else {
            fileLoad(vlmin.at(j), NewMap, VymMap);
            if (!background)
                tabWidget->setCurrentIndex(tabWidget->count() - 1);
        }
    }
    // Go to tab containing the map
    if (index >= 0)
        tabWidget->setCurrentIndex(index);
    removeProgressCounter();
}

void Main::editOpenVymLink(bool background)
{
    VymModel *m = currentModel();
    if (m) {
        QStringList vl;
        vl.append(m->getVymLink());
        openVymLinks(vl, background);
    }
}

void Main::editOpenVymLinkBackground() { editOpenVymLink(true); }

void Main::editOpenMultipleVymLinks()
{
    QString currentVymLink;
    VymModel *m = currentModel();
    if (m) {
        QStringList vl = m->getVymLinks();
        openVymLinks(vl, true);
    }
}

void Main::editVymLink()
{
    VymModel *m = currentModel();
    if (m) {
        BranchItem *bi = m->getSelectedBranch();
        if (bi) {
            QStringList filters;
            filters << "VYM map (*.vym)";
            QFileDialog fd;
            fd.setWindowTitle(vymName + " - " + tr("Link to another vym map"));
            fd.setNameFilters(filters);
            fd.setLabelText( QFileDialog::Accept, tr("Set as link to vym map"));
            fd.setDirectory(lastMapDir);
            fd.setAcceptMode(QFileDialog::AcceptOpen);
            if (!bi->getVymLink().isEmpty())
                fd.selectFile(bi->getVymLink());
            fd.show();

            QString fn;
            if (fd.exec() == QDialog::Accepted &&
                !fd.selectedFiles().isEmpty()) {
                QString fn = fd.selectedFiles().first();
                lastMapDir = QDir(fd.directory().path());
                m->setVymLink(fn);
            }
        }
    }
}

void Main::editDeleteVymLink()
{
    VymModel *m = currentModel();
    if (m)
        m->deleteVymLink();
}

void Main::editToggleHideExport()
{
    VymModel *m = currentModel();
    if (m)
        m->toggleHideExport();
}

void Main::editToggleTask()
{
    VymModel *m = currentModel();
    if (m)
        m->toggleTask();
}

void Main::editCycleTaskStatus()
{
    VymModel *m = currentModel();
    if (m)
        m->cycleTaskStatus();
}

void Main::editTaskResetDeltaPrio() // FIXME-2 With multiple selections enabled, old selection should be restored
{
    QList <Task*> tasks;
    QList <VymModel*> models;
    for (int i = 0; i < taskModel->count(); i++)
    {
        Task *task = taskModel->getTask(i);
        if (taskEditor->taskVisible(task) && task->getPriorityDelta() != 0) {
            tasks << task;
            VymModel *m = task->getBranch()->getModel();
            if (!models.contains(m))
                models << m;
        }
    }

    foreach (VymModel *model, models) {
        // Unselect everything
        model->unselectAll();

        // Select all branches, where tasks whill be updated
        foreach (Task *task, tasks) {
            BranchItem *bi = task->getBranch();
            if (bi->getModel() == model) {
                model->selectToggle(bi);
            }
        }

        // Bulk update all branches in this model
        model->setTaskPriorityDelta(0);
    }
}

void Main::editTaskSleepN()
{
    VymModel *m = currentModel();
    if (m) {
        qint64 n = ((QAction *)sender())->data().toInt();
        Task *task = m->getSelectedTask();
        if (task) {
            bool ok = true;
            QString s;
            if (n < 0) {
                QString currentSleep;
                QDateTime d = task->getSleep();
                n = task->getSecsSleep();
                if (n <= 0)
                    currentSleep = "0";
                else if (n < 60)
                    currentSleep = QString("%1s").arg(n);
                else if (n < 24 * 3600) {
                    currentSleep = d.time().toString("hh:mm");
                }
                else if (d.time().hour() == 0 && d.time().minute() == 0) {
                    currentSleep = d.date().toString("dd.MM.yyyy");
                }
                else
                    currentSleep = d.toString(Qt::ISODate);

                LineEditDialog *dia = new LineEditDialog(this);
                dia->setLabel(tr("Enter sleep time (number of days, hours with "
                                 "'h' or date YYYY-MM-DD or DD.MM[.YYYY]",
                                 "task sleep time dialog"));
                dia->setText(currentSleep);
                centerDialog(dia);
                if (dia->exec() == QDialog::Accepted) {
                    ok = true;
                    s = dia->getText();
                }
                else
                    ok = false;

                delete dia;
            }
            else
                s = QString("%1").arg(n);

            if (ok && !m->setTaskSleep(s))
                QMessageBox::warning(
                    0, tr("Warning"),
                    tr("Couldn't set sleep time to %1.\n").arg(s));
        }
    }
}

void Main::editAddTimestamp()
{
    VymModel *m = currentModel();
    if (m)
        m->addTimestamp();
}

void Main::editMapProperties()
{
    VymModel *m = currentModel();
    if (!m)
        return;

    ExtraInfoDialog dia;
    dia.setMapName(m->getFileName());
    dia.setFileLocation(m->getFilePath());
    dia.setMapTitle(m->getTitle());
    dia.setAuthor(m->getAuthor());
    dia.setComment(m->getComment());
    dia.setReadOnly(m->isReadOnly());

    // Calc some stats
    QString stats;
    stats += tr("%1 items on map\n", "Info about map")
                 .arg(m->getScene()->items().size(), 6);

    uint b = 0;
    uint f = 0;
    uint n = 0;
    uint xl = 0;
    BranchItem *cur = NULL;
    BranchItem *prev = NULL;
    m->nextBranch(cur, prev);
    while (cur) {
        if (!cur->getNote().isEmpty())
            n++;
        f += cur->imageCount();
        b++;
        xl += cur->xlinkCount();
        m->nextBranch(cur, prev);
    }

    stats += QString("%1 %2\n")
                 .arg(m->branchCount(), 6)
                 .arg(tr("branches", "Info about map"));
    stats += QString("%1 %2\n")
                 .arg(taskModel->count(), 6)
                 .arg(tr("tasks total", "Info about map"));
    stats += QString("%1 %2\n")
                 .arg(taskModel->count(m), 6)
                 .arg(tr("tasks in map", "Info about map"));
    stats += QString("%1 %2\n").arg(n, 6).arg(tr("notes", "Info about map"));
    stats += QString("%1 %2\n").arg(f, 6).arg(tr("images", "Info about map"));
    stats += QString("%1 %2\n")
                 .arg(m->slideCount(), 6)
                 .arg(tr("slides", "Info about map"));
    stats +=
        QString("%1 %2\n").arg(xl / 2, 6).arg(tr("xLinks", "Info about map"));
    dia.setStats(stats);

    // Finally show dialog
    if (dia.exec() == QDialog::Accepted) {
        m->setAuthor(dia.getAuthor());
        m->setComment(dia.getComment());
        m->setTitle(dia.getMapTitle());
    }
}

void Main::editMoveUp()
{
    MapEditor *me = currentMapEditor();
    VymModel *m = currentModel();
    if (me && m && me->getState() != MapEditor::EditingHeading)
        m->moveUp();
}

void Main::editMoveDown()
{
    MapEditor *me = currentMapEditor();
    VymModel *m = currentModel();
    if (me && m && me->getState() != MapEditor::EditingHeading)
        m->moveDown();
}

void Main::editMoveDownDiagonally()
{
    MapEditor *me = currentMapEditor();
    VymModel *m = currentModel();
    if (me && m && me->getState() != MapEditor::EditingHeading)
        m->moveDownDiagonally();
}

void Main::editMoveUpDiagonally()
{
    MapEditor *me = currentMapEditor();
    VymModel *m = currentModel();
    if (me && m && me->getState() != MapEditor::EditingHeading)
        m->moveUpDiagonally();
}

void Main::editDetach()
{
    VymModel *m = currentModel();
    if (m)
        m->detach();
}

void Main::editSortChildren()
{
    VymModel *m = currentModel();
    if (m)
        m->sortChildren(false);
}

void Main::editSortBackChildren()
{
    VymModel *m = currentModel();
    if (m)
        m->sortChildren(true);
}

void Main::editToggleScroll()
{
    VymModel *m = currentModel();
    if (m)
        m->toggleScroll();
}

void Main::editExpandAll()
{
    VymModel *m = currentModel();
    if (m)
        m->emitExpandAll();
}

void Main::editExpandOneLevel()
{
    VymModel *m = currentModel();
    if (m)
        m->emitExpandOneLevel();
}

void Main::editCollapseOneLevel()
{
    VymModel *m = currentModel();
    if (m)
        m->emitCollapseOneLevel();
}

void Main::editCollapseUnselected()
{
    VymModel *m = currentModel();
    if (m)
        m->emitCollapseUnselected();
}

void Main::editUnscrollChildren()
{
    VymModel *m = currentModel();
    if (m)
        m->unscrollChildren();
}

void Main::editGrowSelectionSize()
{
    VymModel *m = currentModel();
    if (m)
        m->growSelectionSize();
}

void Main::editShrinkSelectionSize()
{
    VymModel *m = currentModel();
    if (m)
        m->shrinkSelectionSize();
}

void Main::editResetSelectionSize()
{
    VymModel *m = currentModel();
    if (m)
        m->resetSelectionSize();
}

void Main::editAddAttribute()
{
    VymModel *m = currentModel();
    if (m) {

        m->setAttribute();
    }
}

void Main::editAddMapCenter()
{
    VymModel *m = currentModel();
    if (m) {
        m->select(m->addMapCenter());
        MapEditor *me = currentMapEditor();
        if (me) {
            m->setHeadingPlainText("");
            me->editHeading();
        }
    }
}

void Main::editNewBranch()
{
    VymModel *m = currentModel();
    if (m) {
        BranchItem *bi = m->addNewBranch();
        if (!bi)
            return;

        if (!actionSettingsAutoSelectNewBranch->isChecked())
            prevSelection = m->getSelectString();

        m->select(bi);
        currentMapEditor()->editHeading();
    }
}

void Main::editNewBranchBefore()
{
    VymModel *m = currentModel();
    if (m) {
        if (!actionSettingsAutoSelectNewBranch->isChecked())
            prevSelection = m->getSelectString();

        BranchItem *bi = m->addNewBranchBefore();

        if (bi)
            m->select(bi);
        else
            return;

        currentMapEditor()->editHeading();
    }
}

void Main::editNewBranchAbove()
{
    VymModel *m = currentModel();
    if (m) {
        if (!actionSettingsAutoSelectNewBranch->isChecked())
            prevSelection = m->getSelectString();

        BranchItem *selbi = m->getSelectedBranch();
        if (selbi) {
            BranchItem *bi = m->addNewBranch(selbi, -3);

            if (bi)
                m->select(bi);
            else
                return;

            currentMapEditor()->editHeading();
        }
    }
}

void Main::editNewBranchBelow()
{
    VymModel *m = currentModel();
    if (m) {
        BranchItem *selbi = m->getSelectedBranch();
        if (selbi) {
            BranchItem *bi = m->addNewBranch(selbi, -1);

            if (bi)
                m->select(bi);
            else
                return;

            if (!actionSettingsAutoSelectNewBranch->isChecked())
                prevSelection = m->getSelectString(bi);

            currentMapEditor()->editHeading();
        }
    }
}

void Main::editImportAdd() { fileLoad(ImportAdd); }

void Main::editImportReplace() { fileLoad(ImportReplace); }

void Main::editSaveBranch() { fileSaveAs(PartOfMap); }

void Main::editDeleteKeepChildren()
{
    VymModel *m = currentModel();
    if (m)
        m->deleteKeepChildren();
}

void Main::editDeleteChildren()
{
    VymModel *m = currentModel();
    if (m)
        m->deleteChildren();
}

void Main::editDeleteSelection()
{
    VymModel *m = currentModel();
    if (m)
        m->deleteSelection();
}

void Main::editLoadImage()
{
    VymModel *m = currentModel();
    if (m)
        m->loadImage();
}

void Main::editSaveImage()
{
    VymModel *m = currentModel();
    if (m)
        m->saveImage();
}

void Main::editEditXLink(QAction *a)
{
    VymModel *m = currentModel();
    if (m) {
        BranchItem *selbi = m->getSelectedBranch();
        if (selbi) {
            Link *l = selbi
                          ->getXLinkItemNum(
                              branchXLinksContextMenuEdit->actions().indexOf(a))
                          ->getLink();
            if (l && m->select(l->getBeginLinkItem()))
                m->editXLink();
        }
    }
}

void Main::popupFollowXLink()
{
    branchXLinksContextMenuFollow->exec(QCursor::pos());
}

void Main::editFollowXLink(QAction *a)
{
    VymModel *m = currentModel();

    if (m)
        m->followXLink(branchXLinksContextMenuFollow->actions().indexOf(a));
}

bool Main::initLinkedMapsMenu(VymModel *model, QMenu *menu)
{
    if (model) {
        ItemList targets = model->getLinkedMaps();

        menu->clear();

        QStringList targetNames;
        QList<uint> targetIDs;

        // Build QStringList with all names of targets
        QMap<uint, QStringList>::const_iterator i;
        i = targets.constBegin();
        while (i != targets.constEnd()) {
            targetNames.append(i.value().first());
            targetIDs.append(i.key());
            ++i;
        }

        // Sort list of names
        targetNames.sort(Qt::CaseInsensitive);

        // Build menu based on sorted names
        while (!targetNames.isEmpty()) {
            // Find target by value
            i = targets.constBegin();
            while (i != targets.constEnd()) {
                if (i.value().first() == targetNames.first())
                    break;
                ++i;
            }

            menu->addAction(targetNames.first())->setData(i.value().last());
            targetNames.removeFirst();
            targets.remove(i.key());
        }
        return true;
    }
    return false;
}

void Main::editGoToLinkedMap()
{
    VymModel *model = currentModel();
    if (initLinkedMapsMenu(model, targetsContextMenu)) {
        QAction *a = targetsContextMenu->exec(QCursor::pos());
        if (a) {
            QStringList sl;
            sl << a->data().toString();
            openVymLinks(sl);
        }
    }
}

void Main::editToggleTarget()
{
    VymModel *m = currentModel();
    if (m)
        m->toggleTarget();
}

bool Main::initTargetsMenu(VymModel *model, QMenu *menu)
{
    if (model) {
        ItemList targets = model->getTargets();

        menu->clear();

        QStringList targetNames;
        QList<uint> targetIDs;

        // Build QStringList with all names of targets
        QMap<uint, QStringList>::const_iterator i;
        i = targets.constBegin();
        while (i != targets.constEnd()) {
            targetNames.append(i.value().first());
            targetIDs.append(i.key());
            ++i;
        }

        // Sort list of names
        targetNames.sort(Qt::CaseInsensitive);

        // Build menu based on sorted names
        while (!targetNames.isEmpty()) {
            // Find target by value
            i = targets.constBegin();
            while (i != targets.constEnd()) {
                if (i.value().first() == targetNames.first())
                    break;
                ++i;
            }

            menu->addAction(targetNames.first())->setData(i.key());
            targetNames.removeFirst();
            targets.remove(i.key());
        }
        return true;
    }
    return false;
}

void Main::editGoToTarget()
{
    VymModel *model = currentModel();
    if (initTargetsMenu(model, targetsContextMenu)) {
        QAction *a = targetsContextMenu->exec(QCursor::pos());
        if (a)
            model->select(model->findID(a->data().toUInt()));
    }
}

void Main::editMoveToTarget()
{
    VymModel *model = currentModel();
    if (initTargetsMenu(model, targetsContextMenu)) {
        QAction *a = targetsContextMenu->exec(QCursor::pos());
        if (a) {
            TreeItem *dsti = model->findID(a->data().toUInt());
            /*
            BranchItem *selbi = model->getSelectedBranch();
            if (!selbi)
                return;
            */

            QList<TreeItem *> itemList = model->getSelectedItems();
            if (itemList.count() < 1) return;

            if (dsti && dsti->isBranchLikeType() ) {
                BranchItem *selbi;
                BranchItem *pi;
                foreach (TreeItem *ti, itemList) {
                    if (ti->isBranchLikeType() )
                    {
                        selbi = (BranchItem*)ti;
                        pi = selbi->parentBranch();
                        
                        // If branch below exists, select that one
                        // Makes it easier to quickly resort using the MoveTo function
                        BranchItem *below = pi->getBranchNum(selbi->num() + 1);
                        LinkableMapObj *lmo = selbi->getLMO();
                        QPointF orgPos;
                        if (lmo)
                            orgPos = lmo->getAbsPos();

                        if (model->relinkBranch(selbi, (BranchItem *)dsti, -1, true,
                                                orgPos)) {
                            if (below)
                                model->select(below);
                            else if (pi)
                                model->select(pi);
                        }
                    }
                }
            }
        }
    }
}

void Main::editSelectPrevious()
{
    VymModel *m = currentModel();
    if (m)
        m->selectPrevious();
}

void Main::editSelectNext()
{
    VymModel *m = currentModel();
    if (m)
        m->selectNext();
}

void Main::editSelectNothing()
{
    VymModel *m = currentModel();
    if (m)
        m->unselectAll();
}

void Main::editOpenFindResultWidget()
{
    if (!findResultWidget->parentWidget()->isVisible()) {
        //	findResultWidget->parentWidget()->show();
        findResultWidget->popup();
    }
    else
        findResultWidget->parentWidget()->hide();
}

#include "findwidget.h" // FIXME-4 Integrated FRW and FW
void Main::editFindNext(QString s, bool searchNotesFlag)
{
    Qt::CaseSensitivity cs = Qt::CaseInsensitive;
    VymModel *m = currentModel();
    if (m) {
        if (m->findAll(findResultWidget->getResultModel(), s, cs,
                       searchNotesFlag))
            findResultWidget->setStatus(FindWidget::Success);
        else
            findResultWidget->setStatus(FindWidget::Failed);
    }
}

void Main::editFindDuplicateURLs() // FIXME-4 feature: use FindResultWidget for
                                   // display
{
    VymModel *m = currentModel();
    if (m)
        m->findDuplicateURLs();
}

void Main::updateQueries(
    VymModel *) // FIXME-4 disabled for now to avoid selection in FRW
{
    return;
    /*
        qDebug() << "MW::updateQueries m="<<m<<"   cM="<<currentModel();
        if (m && currentModel()==m)
        {
        QString s=findResultWidget->getFindText();
        if (!s.isEmpty() ) editFindNext (s);
        }
    */
}

void Main::selectQuickColor(int n)
{
    if (n < 0 || n > quickColors.count() - 1) return;

    actionGroupQuickColors->actions().at(n)->setChecked(true);
    setCurrentColor(quickColors.at(n));
}

void Main::setQuickColor(QColor col)
{
    int i = getCurrentColorIndex();
    if (i < 0) return;

    QPixmap pix(16, 16);
    pix.fill(col);
    actionGroupQuickColors->checkedAction()->setIcon(pix);
    quickColors.replace(i, col);
}

void Main::quickColorPressed()
{
    int i = getCurrentColorIndex();

    if (i < 0) return;

    if (QApplication::keyboardModifiers() == Qt::ShiftModifier) {
        QColor col = getCurrentColor();
        col = QColorDialog::getColor((col), this);
        if (!col.isValid()) return;

        setQuickColor(col);
    } else
        selectQuickColor(i);
}

void Main::formatPickColor()
{
    VymModel *m = currentModel();
    if (m)
        setQuickColor( m->getCurrentHeadingColor());
}

QColor Main::getCurrentColor() 
{ 
    int i = getCurrentColorIndex();

    if (i < 0) return QColor();

    return quickColors.at(i);
}

int Main::getCurrentColorIndex()
{
    QAction* a = actionGroupQuickColors->checkedAction();

    if (a == nullptr) return -1;

    return actionGroupQuickColors->actions().indexOf(a);
}

void Main::setCurrentColor(QColor c)
{
    int i = getCurrentColorIndex();

    if (i < 0) return;

    QPixmap pix(16, 16);
    pix.fill(c);

    actionGroupQuickColors->actions().at(i)->setIcon(pix);
}

void Main::formatColorBranch()
{
    VymModel *m = currentModel();
    if (m)
        m->colorBranch(getCurrentColor());
}

void Main::formatColorSubtree()
{
    VymModel *m = currentModel();
    if (m)
        m->colorSubtree(getCurrentColor());
}

void Main::formatLinkStyleLine()
{
    VymModel *m = currentModel();
    if (m) {
        m->setMapLinkStyle("StyleLine");
        actionFormatLinkStyleLine->setChecked(true);
    }
}

void Main::formatLinkStyleParabel()
{
    VymModel *m = currentModel();
    if (m) {
        m->setMapLinkStyle("StyleParabel");
        actionFormatLinkStyleParabel->setChecked(true);
    }
}

void Main::formatLinkStylePolyLine()
{
    VymModel *m = currentModel();
    if (m) {
        m->setMapLinkStyle("StylePolyLine");
        actionFormatLinkStylePolyLine->setChecked(true);
    }
}

void Main::formatLinkStylePolyParabel()
{
    VymModel *m = currentModel();
    if (m) {
        m->setMapLinkStyle("StylePolyParabel");
        actionFormatLinkStylePolyParabel->setChecked(true);
    }
}

void Main::formatSelectBackColor()
{
    VymModel *m = currentModel();
    if (m)
        m->selectMapBackgroundColor();
}

void Main::formatSelectBackImage()
{
    VymModel *m = currentModel();
    if (m)
        m->selectMapBackgroundImage();
}

void Main::formatSelectLinkColor()
{
    VymModel *m = currentModel();
    if (m) {
        QColor col = QColorDialog::getColor(m->getMapDefLinkColor(), this);
        m->setMapDefLinkColor(col);
    }
}

void Main::formatSelectSelectionColor() // FIXME-2 no Pen/Brush support yet
{
    VymModel *m = currentModel();
    if (m) {
        QColor col = QColorDialog::getColor(
                m->getSelectionBrushColor(),
                this,
                tr("Color of selection box","Mainwindow"),
                QColorDialog::ShowAlphaChannel);
        m->setSelectionPenColor(col);
        m->setSelectionBrushColor(col);
    }
}

void Main::formatSelectFont()
{
    VymModel *m = currentModel();
    if (m) {
        bool ok;
        QFont font = QFontDialog::getFont(&ok, m->getMapDefaultFont(), this);
        if (ok)
            m->setMapDefaultFont(font);
    }
}

void Main::formatToggleLinkColorHint()
{
    VymModel *m = currentModel();
    if (m)
        m->toggleMapLinkColorHint();
}

void Main::formatHideLinkUnselected() // FIXME-4 get rid of this with
                                      // imagepropertydialog
{
    VymModel *m = currentModel();
    if (m)
        m->setHideLinkUnselected(actionFormatHideLinkUnselected->isChecked());
}

void Main::viewZoomReset()
{
    MapEditor *me = currentMapEditor();
    if (me)
        me->setViewCenterTarget();
}

void Main::viewZoomIn()
{
    MapEditor *me = currentMapEditor();
    if (me)
        me->setZoomFactorTarget(me->getZoomFactorTarget() * 1.15);
}

void Main::viewZoomOut()
{
    MapEditor *me = currentMapEditor();
    if (me)
        me->setZoomFactorTarget(me->getZoomFactorTarget() * 0.85);
}

void Main::viewRotateCounterClockwise() // FIXME-3 move to ME
{
    MapEditor *me = currentMapEditor();
    if (me)
        me->setAngleTarget(me->getAngleTarget() - 10);
}

void Main::viewRotateClockwise() // FIXME-3 move to ME
{
    MapEditor *me = currentMapEditor();
    if (me)
        me->setAngleTarget(me->getAngleTarget() + 10);
}

void Main::viewCenter()
{
    VymModel *m = currentModel();
    if (m)
        m->emitShowSelection(false);
}

void Main::viewCenterScaled()
{
    VymModel *m = currentModel();
    if (m)
        m->emitShowSelection(true);
}

void Main::networkStartServer()
{
    VymModel *m = currentModel();
    if (m)
        m->newServer();
}

void Main::networkConnect()
{
    VymModel *m = currentModel();
    if (m)
        m->connectToServer();
}

void Main::downloadFinished() // only used for drop events in mapeditor and
                              // VM::downloadImage
{
    QString s;
    DownloadAgent *agent = static_cast<DownloadAgent *>(sender());
    agent->isSuccess() ? s = "Success" : s = "Error  ";

    /*
    qDebug()<<"Main::downloadFinished ";
    qDebug()<<"  result" <<  s;
    qDebug()<<"     msg" << agent->getResultMessage();
    */

    QString script = agent->getFinishedScript();
    VymModel *model = getModel(agent->getFinishedScriptModelID());
    if (!script.isEmpty() && model) {
        script.replace("$TMPFILE", agent->getDestination());
        model->execute(script);
    }
    agent->deleteLater();
}

bool Main::settingsPDF()
{
    // Default browser is set in constructor
    bool ok;
    QString text = QInputDialog::getText(
        this, "VYM", tr("Set application to open PDF files") + ":",
        QLineEdit::Normal, settings.value("/system/readerPDF").toString(), &ok);
    if (ok)
        settings.setValue("/system/readerPDF", text);
    return ok;
}

bool Main::settingsURL()
{
    // Default browser is set in constructor
    bool ok;
    QString text = QInputDialog::getText(
        this, "VYM", tr("Set application to open an URL") + ":",
        QLineEdit::Normal, settings.value("/system/readerURL").toString(), &ok);
    if (ok)
        settings.setValue("/system/readerURL", text);
    return ok;
}

void Main::settingsZipTool()    // FIXME-2 Disabled for now, to be removed completely in 2.9.1
{
    // Default zip tool is tar on Windows 10, zip/unzip elsewhere
    ZipSettingsDialog dia;
    dia.exec();
}

void Main::settingsMacroPath()
{
    QString macroPath = macros.getPath();

    QStringList filters;
    filters << "VYM script files (*.vys)";
    QFileDialog fd;
    fd.setDirectory(dirname(macroPath));
    fd.selectFile(basename(macroPath));
    fd.setFileMode(QFileDialog::ExistingFile);
    fd.setNameFilters(filters);
    fd.setWindowTitle(vymName + " - " + tr("Load vym script"));
    fd.setAcceptMode(QFileDialog::AcceptOpen);

    QString fn;
    if (fd.exec() == QDialog::Accepted) {
        if (macros.setPath( fd.selectedFiles().first()))
            settings.setValue("/macros/path", macros.getPath());
    }
}

void Main::settingsUndoLevels()
{
    bool ok;
    int i = QInputDialog::getInt(
        this, "QInputDialog::getInt()", tr("Number of undo/redo levels:"),
        settings.value("/history/stepsTotal", 1000).toInt(), 0, 100000, 1, &ok);
    if (ok) {
        settings.setValue("/history/stepsTotal", i);
        QMessageBox::information(this, tr("VYM -Information:"),
                                 tr("Settings have been changed. The next map "
                                    "opened will have \"%1\" undo/redo levels")
                                     .arg(i));
    }
}

void Main::settingsDefaultMapPath()
{
    DefaultMapSettingsDialog dia;
    dia.exec();
}

QString Main::defaultMapPath()
{
    // Define default automatical path (also as fallback)
    QString ext_dark;
    if (usingDarkTheme)
        ext_dark = "-dark";

    return vymBaseDir.path() + QString("/demos/default%1.vym").arg(ext_dark);
}

QString Main::newMapPath()
{
    if (settings.value("/system/defaultMap/auto", true).toBool())
        return defaultMapPath();
    else
        return settings
           .value("/system/defaultMap/path", defaultMapPath())
           .toString();
}

bool Main::useAutosave() { return actionSettingsToggleAutosave->isChecked(); }

void Main::setAutosave(bool b) { actionSettingsToggleAutosave->setChecked(b); }

void Main::settingsAutosaveTime()
{
    bool ok;
    int i = QInputDialog::getInt(
        this, vymName, tr("Number of seconds before autosave:"),
        settings.value("/system/autosave/ms").toInt() / 1000, 10, 60000, 1,
        &ok);
    if (ok)
        settings.setValue("/system/autosave/ms", i * 1000);
}

void Main::settingsDefaultMapAuthor()
{
    bool ok;
    QString s = QInputDialog::getText(
        this, vymName, tr("Set author for new maps (used in lockfile)") + ":",
        QLineEdit::Normal,
        settings
            .value("/user/name", tr("unknown user",
                                    "default name for map author in settings"))
            .toString(),
        &ok);
    if (ok)
        settings.setValue("/user/name", s);
}

void Main::settingsDarkTheme()
{
    DarkThemeSettingsDialog dia;
    QString settingDarkTheme = settings.value("/system/darkTheme", "system").toString();
    if (settingDarkTheme == "always")
        dia.ui.alwaysUseDarkThemeButton->setChecked(true);
    else 
        if (settingDarkTheme == "never")
            dia.ui.neverUseDarkThemeButton->setChecked(true);
        else
            dia.ui.systemUseDarkThemeButton->setChecked(true);
    dia.exec();

    QString newSetting;
    if (dia.ui.alwaysUseDarkThemeButton->isChecked())
            newSetting = "always";
    else
        if (dia.ui.neverUseDarkThemeButton->isChecked())
            newSetting = "never";
        else
            newSetting = "system";

    if (settingDarkTheme != newSetting) {
        settings.setValue("/system/darkTheme", newSetting);
        QMessageBox::information(
            0, tr("Information"),
            tr("Restart vym to apply the changed dark theme setting"));
    }
}

void Main::settingsShowParentsLevelFindResults()
{
    bool ok;
    int i = QInputDialog::getInt(
        this, vymName, tr("Number of parents shown in find results:"),
        findResultWidget->getResultModel()->getShowParentsLevel(), 0, 10, 0,
        &ok);
    if (ok)
        findResultWidget->getResultModel()->setShowParentsLevel(i);
}

void Main::settingsShowParentsLevelTasks()
{
    bool ok;
    int i = QInputDialog::getInt(
        this, vymName, tr("Number of parents shown for a task:"),
        taskModel->getShowParentsLevel(), 0, 10, 0, &ok);
    if (ok)
        taskModel->setShowParentsLevel(i);
}

void Main::settingsToggleAutoLayout()
{
    settings.setValue("/mainwindow/autoLayout/use",
                      actionSettingsToggleAutoLayout->isChecked());
}

void Main::settingsToggleWriteBackupFile()
{
    settings.setValue("/system/writeBackupFile",
                      actionSettingsWriteBackupFile->isChecked());
}

void Main::settingsToggleAnimation()
{
    settings.setValue("/animation/use",
                      actionSettingsUseAnimation->isChecked());
}

void Main::settingsToggleDownloads() { downloadsEnabled(true); }

bool Main::settingsConfluence()
{
    if (!QSslSocket::supportsSsl())
    {
        QMessageBox::warning(
            0, tr("Warning"),
            tr("No SSL support available for this build of vym"));
        helpDebugInfo();
        return false;
    }

    ConfluenceSettingsDialog dia;
    dia.exec();

    if (dia.result() > 0)
        return true;
    else
        return false;
}

bool Main::settingsJIRA()
{
    if (!QSslSocket::supportsSsl())
    {
        QMessageBox::warning(
            0, tr("Warning"),
            tr("No SSL support available for this build of vym"));
        helpDebugInfo();
        return false;
    }

    JiraSettingsDialog dia;
    dia.exec();

    if (dia.result() > 0)
        return true;
    else
        return false;
}

void Main::windowToggleNoteEditor()
{
    if (noteEditor->parentWidget()->isVisible())
        noteEditor->parentWidget()->hide();
    else {
        noteEditor->parentWidget()->show();
        noteEditor->setFocus();
    }
}

void Main::windowToggleTreeEditor()
{
    if (tabWidget->currentWidget())
        currentView()->toggleTreeEditor();
}

void Main::windowToggleTaskEditor()
{
    if (taskEditor->parentWidget()->isVisible()) {
        taskEditor->parentWidget()->hide();
        actionViewToggleTaskEditor->setChecked(false);
    }
    else {
        taskEditor->parentWidget()->show();
        actionViewToggleTaskEditor->setChecked(true);
    }
}

void Main::windowToggleSlideEditor()
{
    if (tabWidget->currentWidget())
        currentView()->toggleSlideEditor();
}

void Main::windowToggleScriptEditor()
{
    if (scriptEditor->parentWidget()->isVisible()) {
        scriptEditor->parentWidget()->hide();
        actionViewToggleScriptEditor->setChecked(false);
    }
    else {
        scriptEditor->parentWidget()->show();
        actionViewToggleScriptEditor->setChecked(true);
    }
}

void Main::windowToggleScriptOutput()
{
    if (scriptOutput->parentWidget()->isVisible()) {
        scriptOutput->parentWidget()->hide();
        actionViewToggleScriptOutput->setChecked(false);
    }
    else {
        scriptOutput->parentWidget()->show();
        actionViewToggleScriptOutput->setChecked(true);
    }
}

void Main::windowToggleHistory()
{
    if (historyWindow->parentWidget()->isVisible())
        historyWindow->parentWidget()->hide();
    else
        historyWindow->parentWidget()->show();
}

void Main::windowToggleProperty()
{
    if (branchPropertyEditor->parentWidget()->isVisible())
        branchPropertyEditor->parentWidget()->hide();
    else
        branchPropertyEditor->parentWidget()->show();
    branchPropertyEditor->setModel(currentModel());
}

void Main::windowShowHeadingEditor() { headingEditorDW->show(); }

void Main::windowToggleHeadingEditor()
{
    if (headingEditor->parentWidget()->isVisible())
        headingEditor->parentWidget()->hide();
    else {
        headingEditor->parentWidget()->show();
        headingEditor->setFocus();
    }
}

void Main::windowToggleAntiAlias()
{
    bool b = actionViewToggleAntiAlias->isChecked();
    MapEditor *me;
    for (int i = 0; i < tabWidget->count(); i++) {
        me = view(i)->getMapEditor();
        if (me)
            me->setAntiAlias(b);
    }
}

bool Main::isAliased() { return actionViewToggleAntiAlias->isChecked(); }

bool Main::hasSmoothPixmapTransform()
{
    return actionViewToggleSmoothPixmapTransform->isChecked();
}

void Main::windowToggleSmoothPixmap()
{
    bool b = actionViewToggleSmoothPixmapTransform->isChecked();
    MapEditor *me;
    for (int i = 0; i < tabWidget->count(); i++) {

        me = view(i)->getMapEditor();
        if (me)
            me->setSmoothPixmap(b);
    }
}

void Main::clearScriptOutput() { scriptOutput->clear(); }

void Main::updateHistory(SimpleSettings &undoSet)
{
    historyWindow->update(undoSet);
}

void Main::updateHeading(const VymText &vt)
{
    VymModel *m = currentModel();
    if (m)
        m->setHeading(vt);
}

void Main::updateNoteText(const VymText &vt)
{
    // this slot is connected to noteEditor::textHasChanged()
    VymModel *m = currentModel();
    if (m)
        m->updateNoteText(vt);
}

void Main::updateNoteEditor(TreeItem *ti)
{
    if (ti) {
        if (!ti->hasEmptyNote())
            noteEditor->setNote(ti->getNote());
        else
            noteEditor->clear(); // Also sets empty state
        return;
    }
    noteEditor->setInactive();
}

void Main::updateHeadingEditor(BranchItem *bi)  // FIXME-3 move to HeadingEditor
{
    if (!bi) {
        VymModel *m = currentModel();
        if (!m) return;

        bi = m->getSelectedBranch();
    }

    // Give up, if not a single branch is selected
    if (!bi) return;

    // Color settings, also to prepare switching to RichText later
    headingEditor->setColorMapBackground(bi->getBackgroundColor(bi));
    headingEditor->setColorRichTextDefaultForeground(bi->getHeadingColor());

    headingEditor->setVymText(bi->getHeading());
    headingEditor->setEditorTitle();

}

void Main::selectInNoteEditor(QString s, int i)
{
    // TreeItem is already selected at this time, therefor
    // the note is already in the editor
    noteEditor->findText(s, QTextDocument::FindFlags(), i);
}

void Main::setFocusMapEditor()
{
    VymView *vv = currentView();
    if (vv)
        vv->setFocusMapEditor();
}

void Main::changeSelection(VymModel *model, const QItemSelection &,
                           const QItemSelection &)
{
    // Setting the model in BPE implicitely
    // also sets treeItem and updates content in BPE
    branchPropertyEditor->setModel(model);

    if (model && model == currentModel()) {
        int selectedCount = model->getSelectionModel()->selectedIndexes().count();

        if (selectedCount == 0 || selectedCount > 1) {
            noteEditor->setInactive();
            headingEditor->setInactive();
            taskEditor->clearSelection();

        } else {
            BranchItem *bi = model->getSelectedBranch();
            if (!bi) return;

            // Update note editor
            updateNoteEditor(bi);

            // Show URL and link in statusbar
            QString status;
            QString s = bi->getURL();
            if (!s.isEmpty())
                status += "URL: " + s + "  ";
            s = bi->getVymLink();
            if (!s.isEmpty())
                status += "Link: " + s;
            if (!status.isEmpty())
                statusMessage(status);

            // Update text in HeadingEditor
            updateHeadingEditor(bi);

            // Select in TaskEditor, if necessary
            Task *t = bi->getTask();

            if (t)
                taskEditor->select(t);
            else
                taskEditor->clearSelection();
        }
    }

    updateActions();
}

void Main::updateDockWidgetTitles(VymModel *model)
{
    QString s;
    if (model && !model->isRepositionBlocked()) {
        BranchItem *bi = model->getSelectedBranch();
        if (bi) {
            s = bi->getHeadingPlain();
            noteEditor->setVymText(bi->getNote());
        }

        noteEditor->setEditorTitle(s);
        branchPropertyEditor->setModel(model);
    }
}

void Main::updateActions()
{
    // updateActions is also called when satellites are closed
    actionViewToggleNoteEditor->setChecked(
        noteEditor->parentWidget()->isVisible());
    actionViewToggleTaskEditor->setChecked(
        taskEditor->parentWidget()->isVisible());
    actionViewToggleHistoryWindow->setChecked(
        historyWindow->parentWidget()->isVisible());
    actionViewTogglePropertyEditor->setChecked(
        branchPropertyEditor->parentWidget()->isVisible());
    actionViewToggleScriptEditor->setChecked(
        scriptEditor->parentWidget()->isVisible());

    if (JiraAgent::available())
        actionGetJiraDataSubtree->setEnabled(true);
    else
        actionGetJiraDataSubtree->setEnabled(false);

    if (ConfluenceAgent::available())
    {
        actionGetConfluencePageName->setEnabled(true);
        actionConnectGetConfluenceUser->setEnabled(true);
        actionFileExportConfluence->setEnabled(true);
    } else
    {
        actionGetConfluencePageName->setEnabled(false);
        actionConnectGetConfluenceUser->setEnabled(false);
        actionFileExportConfluence->setEnabled(false);
    }

    VymView *vv = currentView();
    if (vv) {
        actionViewToggleTreeEditor->setChecked(vv->treeEditorIsVisible());
        actionViewToggleSlideEditor->setChecked(vv->slideEditorIsVisible());
    }
    else {
        actionViewToggleTreeEditor->setChecked(false);
        actionViewToggleSlideEditor->setChecked(false);
    }

    VymModel *m = currentModel();
    if (m) {
        QList<TreeItem *> seltis = m->getSelectedItems();
        QList<BranchItem *> selbis = m->getSelectedBranches();
        TreeItem *selti;
        selti = (seltis.count() == 1) ? seltis.first() : nullptr;

        BranchItem *selbi;
        selbi = (selbis.count() == 1) ? selbis.first() : nullptr;

        // readonly mode
        if (m->isReadOnly()) {
            // Disable toolbars
            standardFlagsMaster->setEnabled(false);
            userFlagsMaster->setEnabled(false);
            clipboardToolbar->setEnabled(false);
            editActionsToolbar->setEnabled(false);
            selectionToolbar->setEnabled(false);
            editorsToolbar->setEnabled(false);
            colorsToolbar->setEnabled(false);
            zoomToolbar->setEnabled(false);
            modModesToolbar->setEnabled(false);
            referencesToolbar->setEnabled(false);
            standardFlagsToolbar->setEnabled(false);
            userFlagsToolbar->setEnabled(false);

            // Disable map related actions in readonly mode // FIXME-2 not all actions disabled 
            foreach (QAction *a, restrictedMapActions)
                a->setEnabled(false);

        }
        else { // not readonly     

            // Enable toolbars
            standardFlagsMaster->setEnabled(true);
            userFlagsMaster->setEnabled(true);
            clipboardToolbar->setEnabled(true);
            editActionsToolbar->setEnabled(true);
            selectionToolbar->setEnabled(true);
            editorsToolbar->setEnabled(true);
            colorsToolbar->setEnabled(true);
            zoomToolbar->setEnabled(true);
            modModesToolbar->setEnabled(true);
            referencesToolbar->setEnabled(true);
            standardFlagsToolbar->setEnabled(true);
            userFlagsToolbar->setEnabled(true);

            // Enable map related actions
            foreach (QAction *a, restrictedMapActions)
                a->setEnabled(true);
        }
        // Enable all files actions first
        for (int i = 0; i < actionListFiles.size(); ++i)
            actionListFiles.at(i)->setEnabled(true);

        foreach (QAction *a, unrestrictedMapActions)
            a->setEnabled(true);

        // Disable other actions for now
        for (int i = 0; i < actionListBranches.size(); ++i)
            actionListBranches.at(i)->setEnabled(false);

        for (int i = 0; i < actionListItems.size(); ++i)
            actionListItems.at(i)->setEnabled(false);

        // Link style in context menu
        switch (m->getMapLinkStyle()) {
        case LinkableMapObj::Line:
            actionFormatLinkStyleLine->setChecked(true);
            break;
        case LinkableMapObj::Parabel:
            actionFormatLinkStyleParabel->setChecked(true);
            break;
        case LinkableMapObj::PolyLine:
            actionFormatLinkStylePolyLine->setChecked(true);
            break;
        case LinkableMapObj::PolyParabel:
            actionFormatLinkStylePolyParabel->setChecked(true);
            break;
        default:
            break;
        }

        // Update colors
        QPixmap pix(16, 16);
        pix.fill(m->getMapBackgroundColor());
        actionFormatBackColor->setIcon(pix);
        pix.fill(m->getSelectionBrushColor());
        actionFormatSelectionColor->setIcon(pix);
        pix.fill(m->getMapDefLinkColor());
        actionFormatLinkColor->setIcon(pix);

        // Selection history
        if (!m->canSelectPrevious())
            actionSelectPrevious->setEnabled(false);

        if (!m->canSelectNext())
            actionSelectNext->setEnabled(false);

        if (!m->getSelectedItem())
            actionSelectNothing->setEnabled(false);

        // Save
        if (!m->hasChanged())
            actionFileSave->setEnabled(false);

        // Undo/Redo
        if (!m->isUndoAvailable())
            actionUndo->setEnabled(false);

        if (!m->isRedoAvailable())
            actionRedo->setEnabled(false);

        // History window
        historyWindow->setWindowTitle(
            vymName + " - " +
            tr("History for %1", "Window Caption").arg(m->getFileName()));

        // Expanding/collapsing
        actionExpandAll->setEnabled(true);
        actionExpandOneLevel->setEnabled(true);
        actionCollapseOneLevel->setEnabled(true);
        actionCollapseUnselected->setEnabled(true);

        if (m->getMapLinkColorHint() == LinkableMapObj::HeadingColor)
            actionFormatLinkColorHint->setChecked(true);
        else
            actionFormatLinkColorHint->setChecked(false);

        // Export last
        QString desc, com, dest;
        if (m && m->exportLastAvailable(desc, com, dest))
            actionFileExportLast->setEnabled(true);
        else {
            actionFileExportLast->setEnabled(false);
            com = dest = "";
            desc = " - ";
        }
        actionFileExportLast->setText(
            tr("Export in last used format: %1\n%2", "status tip")
                .arg(desc)
                .arg(dest));


        if (seltis.count() > 0) { // Tree Item selected
            if (selti) actionToggleTarget->setChecked(selti->isTarget());
            actionDelete->setEnabled(true);
            actionDeleteAlt->setEnabled(true);
            actionDeleteChildren->setEnabled(true);

            if (selti && selti->getType() == TreeItem::Image) {
                actionFormatHideLinkUnselected->setChecked(
                    ((MapItem *)selti)->getHideLinkUnselected());
                actionFormatHideLinkUnselected->setEnabled(true);
            }

            if (selbis.count() > 0) { // Branch Item selected
                for (int i = 0; i < actionListBranches.size(); ++i)
                    actionListBranches.at(i)->setEnabled(true);

                actionHeading2URL->setEnabled(true);

                // Note
                if (selbi) actionGetURLsFromNote->setEnabled(!selbi->getNote().isEmpty());

                // Take care of xlinks
                // FIXME-4 similar code in mapeditor mousePressEvent
                bool b = false;
                if (selbi && selbi->xlinkCount() > 0)
                    b = true;

                branchXLinksContextMenuEdit->setEnabled(b);
                branchXLinksContextMenuFollow->setEnabled(b);
                branchXLinksContextMenuEdit->clear();
                branchXLinksContextMenuFollow->clear();
                if (b) {
                    BranchItem *bi;
                    QString s;
                    for (int i = 0; i < selbi->xlinkCount(); ++i) {
                        bi = selbi->getXLinkItemNum(i)->getPartnerBranch();
                        if (bi) {
                            s = bi->getHeadingPlain();
                            if (s.length() > xLinkMenuWidth)
                                s = s.left(xLinkMenuWidth) + "...";
                            branchXLinksContextMenuEdit->addAction(s);
                            branchXLinksContextMenuFollow->addAction(s);
                        }
                    }
                }
                // Standard and user flags
                if (selbi)
                {
                    standardFlagsMaster->updateToolBar(selbi->activeFlagUids());
                    userFlagsMaster->updateToolBar(selbi->activeFlagUids());
                }

                // System Flags
                actionToggleScroll->setEnabled(true);
                if (selbi && selbi->isScrolled())
                    actionToggleScroll->setChecked(true);
                else
                    actionToggleScroll->setChecked(false);

                QString url;
                if (selti) url = selti->getURL();
                if (url.isEmpty()) {
                    actionOpenURL->setEnabled(false);
                    actionOpenURLTab->setEnabled(false);
                    actionGetConfluencePageName->setEnabled(false);
                }
                else {
                    actionOpenURL->setEnabled(true);
                    actionOpenURLTab->setEnabled(true);
                    if (ConfluenceAgent::available())
                        actionGetConfluencePageName->setEnabled(true);
                    else
                        actionGetConfluencePageName->setEnabled(false);
                }

                if (selti && selti->getVymLink().isEmpty()) {
                    actionOpenVymLink->setEnabled(false);
                    actionOpenVymLinkBackground->setEnabled(false);
                    actionDeleteVymLink->setEnabled(false);
                }
                else {
                    actionOpenVymLink->setEnabled(true);
                    actionOpenVymLinkBackground->setEnabled(true);
                    actionDeleteVymLink->setEnabled(true);
                }

                if ((selbi && !selbi->canMoveUp()) || selbis.count() > 1)
                    actionMoveUp->setEnabled(false);

                if ((selbi && !selbi->canMoveDown()) || selbis.count() > 1)
                    actionMoveDown->setEnabled(false);

                if ((selbi && !selbi->canMoveUp()) || selbis.count() > 1)
                    actionMoveUpDiagonally->setEnabled(false);  // FIXME-2 add check for moveDiagonalUp

                if ((selbi && selbi->depth() == 0) || selbis.count() > 1)
                    actionMoveDownDiagonally->setEnabled(false);

                if (selbi && selbi->getLMO()->getOrientation() == LinkableMapObj::LeftOfCenter)
                {
                    actionMoveDownDiagonally->setIcon(QPixmap(":down-diagonal-right.png"));
                    actionMoveUpDiagonally->setIcon(QPixmap(":up-diagonal-left.png"));
                }
                else
                {
                    actionMoveDownDiagonally->setIcon(QPixmap(":down-diagonal-left.png"));
                    actionMoveUpDiagonally->setIcon(QPixmap(":up-diagonal-right.png"));
                }

                if ((selbi && selbi->branchCount() < 2)  || selbis.count() > 1) { 
                    actionSortChildren->setEnabled(false);
                    actionSortBackChildren->setEnabled(false);
                }

                if (selbi) {
                    actionToggleHideExport->setEnabled(true);
                    actionToggleHideExport->setChecked(selbi->hideInExport());

                    actionToggleTask->setEnabled(true);
                    if (!selbi->getTask())
                        actionToggleTask->setChecked(false);
                    else
                        actionToggleTask->setChecked(true);
                } else
                {
                    actionToggleHideExport->setEnabled(false);
                    actionToggleTask->setEnabled(false);
                }


                const QClipboard *clipboard = QApplication::clipboard();
                const QMimeData *mimeData = clipboard->mimeData();
                if (mimeData->formats().contains("application/x-vym") ||
                    mimeData->hasImage())
                    actionPaste->setEnabled(true);
                else
                    actionPaste->setEnabled(false);

                actionToggleTarget->setEnabled(true);
            } // end of BranchItem

            if (selti && selti->getType() == TreeItem::Image) {
                for (int i = 0; i < actionListBranches.size(); ++i)
                    actionListBranches.at(i)->setEnabled(false);

                standardFlagsMaster->setEnabled(false);
                userFlagsMaster->setEnabled(false);

                actionOpenURL->setEnabled(false);
                actionOpenVymLink->setEnabled(false);
                actionOpenVymLinkBackground->setEnabled(false);
                actionDeleteVymLink->setEnabled(false);
                actionToggleHideExport->setEnabled(true);
                actionToggleHideExport->setChecked(selti->hideInExport());

                actionToggleTarget->setEnabled(true);

                actionPaste->setEnabled(false);
                actionDelete->setEnabled(true);
                actionDeleteAlt->setEnabled(true);

                actionGrowSelectionSize->setEnabled(true);
                actionShrinkSelectionSize->setEnabled(true);
                actionResetSelectionSize->setEnabled(true);
            } // Image
        } // TreeItem
        else
        {
            actionToggleHideExport->setEnabled(false);
        }

        // Check (at least for some) multiple selection //FIXME-4
        if (seltis.count() > 0) {
            actionDelete->setEnabled(true);
            actionDeleteAlt->setEnabled(true);
        }

        if (selbis.count() > 0)
        {
            actionFormatColorBranch->setEnabled(true);
            actionFormatColorSubtree->setEnabled(true);
        }
    }
    else {
        // No map available
        for (int i = 0; i < actionListFiles.size(); ++i)
            actionListFiles.at(i)->setEnabled(false);

        foreach (QAction *a, unrestrictedMapActions)
            a->setEnabled(false);

        // Disable toolbars
        standardFlagsMaster->setEnabled(false);
        userFlagsMaster->setEnabled(false);
        clipboardToolbar->setEnabled(false);
        editActionsToolbar->setEnabled(false);
        selectionToolbar->setEnabled(false);
        editorsToolbar->setEnabled(false);
        colorsToolbar->setEnabled(false);
        zoomToolbar->setEnabled(false);
        modModesToolbar->setEnabled(false);
        referencesToolbar->setEnabled(false);
        standardFlagsToolbar->setEnabled(false);
        userFlagsToolbar->setEnabled(false);
    }
}

Main::ModMode Main::getModMode()
{
    if (actionModModePoint->isChecked())
        return ModModePoint;
    if (actionModModeColor->isChecked())
        return ModModeColor;
    if (actionModModeXLink->isChecked())
        return ModModeXLink;
    if (actionModModeMoveObject->isChecked())
        return ModModeMoveObject;
    if (actionModModeMoveView->isChecked())
        return ModModeMoveView;
    return ModModeUndefined;
}

bool Main::autoSelectNewBranch()
{
    return actionSettingsAutoSelectNewBranch->isChecked();
}

QScriptValue scriptPrint(QScriptContext *context, QScriptEngine *)
{
    scriptOutput->append(context->argument(0).toString());
    cout << context->argument(0).toString().toStdString() << endl;
    return QScriptValue();
}

QScriptValue scriptAbort(QScriptContext *context, QScriptEngine *engine)
{
    scriptOutput->append("Abort called: " + context->argument(0).toString());
    engine->abortEvaluation();
    return QScriptValue();
}

QScriptValue scriptStatusMessage(QScriptContext *context, QScriptEngine *)
{
    mainWindow->statusMessage(context->argument(0).toString());
    return QScriptValue();
}

QVariant Main::runScript(const QString &script)
{
    scriptEngine.globalObject().setProperty(
        "print", scriptEngine.newFunction(scriptPrint));
    scriptEngine.globalObject().setProperty(
        "abort", scriptEngine.newFunction(scriptAbort));
    scriptEngine.globalObject().setProperty(
        "statusMessage", scriptEngine.newFunction(scriptStatusMessage));

    // Create Wrapper object for VymModel
    // QScriptValue val1 = scriptEngine.newQObject( m->getWrapper() );
    // scriptEngine.globalObject().setProperty("model", val1);

    // Create Wrapper object for vym itself (mainwindow)
    VymWrapper vymWrapper;
    QScriptValue val2 = scriptEngine.newQObject(&vymWrapper);
    scriptEngine.globalObject().setProperty("vym", val2);

    // Create wrapper object for selection
    Selection selection;
    QScriptValue val3 = scriptEngine.newQObject(&selection);
    scriptEngine.globalObject().setProperty("selection", val3);

    if (debug) {
        cout << "MainWindow::runScript starting to execute:" << endl;
        cout << qPrintable(script) << endl;
    }

    // Run script
    QScriptValue result = scriptEngine.evaluate(script);

    if (debug) {
        qDebug() << "MainWindow::runScript finished:";
        qDebug() << "   hasException: " << scriptEngine.hasUncaughtException();
        qDebug() << "         result: "
                 << result.toString(); // not used so far...
        qDebug()
            << "     lastResult: "
            << scriptEngine.globalObject().property("lastResult").toVariant();
    }

    if (scriptEngine.hasUncaughtException()) {
        // Warnings, in case that output window is not visible...
        statusMessage("Script execution failed");
        qWarning() << "Script execution failed";

        int line = scriptEngine.uncaughtExceptionLineNumber();
        scriptOutput->append(QString("uncaught exception at line %1: %2")
                                 .arg(line)
                                 .arg(result.toString()));
    }
    else
        return scriptEngine.globalObject().property("lastResult").toVariant();

    return QVariant("");
}

QObject *Main::getCurrentModelWrapper()
{
    // Called from VymWrapper to find out current model in a script
    VymModel *m = currentModel();
    if (m)
        return m->getWrapper();
    else
        return NULL;
}

bool Main::gotoWindow(const int &n)
{
    if (n < tabWidget->count() && n >= 0) {
        tabWidget->setCurrentIndex(n);
        return true;
    }
    return false;
}

void Main::windowNextEditor()
{
    if (tabWidget->currentIndex() < tabWidget->count())
        tabWidget->setCurrentIndex(tabWidget->currentIndex() + 1);
}

void Main::windowPreviousEditor()
{
    if (tabWidget->currentIndex() > 0)
        tabWidget->setCurrentIndex(tabWidget->currentIndex() - 1);
}

void Main::nextSlide()
{
    VymView *cv = currentView();
    if (cv)
        cv->nextSlide();
}

void Main::previousSlide()
{
    VymView *cv = currentView();
    if (cv)
        cv->previousSlide();
}

void Main::flagChanged()
{
    MapEditor *me = currentMapEditor();
    VymModel *m = currentModel();
    if (me && m && me->getState() != MapEditor::EditingHeading) {
        m->toggleFlagByUid(QUuid(sender()->objectName()),
                           actionSettingsUseFlagGroups->isChecked());
        updateActions();
    }
}

void Main::testFunction1()
{
    // Avail. styles:
    // Linux (KDE): Breeze,bb10dark,bb10bright,cleanlooks,gtk2,cde,motif,plastique,Windows,Fusion
    // Windows: windowsvista,Windows,Fusion
    //#include <QStyleFactory>
    //qApp->setStyle(QStyleFactory::create("windowsvista"));

    VymModel *m = currentModel();
    if (m) {
        qDebug() << "ME::vp->width()=" << m->getMapEditor()->viewport()->width();
    }
}

void Main::testFunction2()
{
    VymModel *m = currentModel();
    if (m) {
        //m->repeatLastCommand();
    }
}

void Main::toggleWinter()
{
    if (!currentMapEditor())
        return;
    currentMapEditor()->toggleWinter();
}

void Main::toggleHideExport()
{
    VymModel *m = currentModel();
    if (!m)
        return;
    if (actionToggleHideMode->isChecked())
        m->setHideTmpMode(TreeItem::HideExport);
    else
        m->setHideTmpMode(TreeItem::HideNone);
}

void Main::testCommand()
{
    if (!currentMapEditor())
        return;
    scriptEditor->show();
}

void Main::helpDoc()
{
    QString locale = QLocale::system().name();
    QString docname;
    if (locale.left(2) == "es")
        docname = "vym_es.pdf";
    else
        docname = "vym.pdf";

    QStringList searchList;
    QDir docdir;
#if defined(Q_OS_MACX)
    searchList << vymBaseDir.path() + "/doc";
#elif defined(Q_OS_WIN32)
    searchList << vymInstallDir.path() + "doc/" + docname;
#else
#if defined(VYM_DOCDIR)
    searchList << VYM_DOCDIR;
#endif
    // default path in SUSE LINUX
    searchList << "/usr/share/doc/packages/vym";
#endif

    searchList << "doc"; // relative path for easy testing in tarball
    searchList << "/usr/share/doc/vym";      // Debian
    searchList << "/usr/share/doc/packages"; // Knoppix

    bool found = false;
    QFile docfile;
    for (int i = 0; i < searchList.count(); ++i) {
        docfile.setFileName(searchList.at(i) + "/" + docname);
        if (docfile.exists()) {
            found = true;
            break;
        }
    }

    if (!found) {
        QMessageBox::critical(0, tr("Critcal error"),
                              tr("Couldn't find the documentation %1 in:\n%2")
                                  .arg(docname)
                                  .arg(searchList.join("\n")));
        return;
    }

    QStringList args;
    VymProcess *pdfProc = new VymProcess();
    args << QDir::toNativeSeparators(docfile.fileName());

    if (!pdfProc->startDetached(settings.value("/system/readerPDF").toString(),
                                args)) {
        // error handling
        QMessageBox::warning(
            0, tr("Warning"),
            tr("Couldn't find a viewer to open %1.\n").arg(docfile.fileName()) +
                tr("Please use Settings->") +
                tr("Set application to open PDF files"));
        settingsPDF();
        return;
    }
}

void Main::helpDemo()
{
    QStringList filters;
    filters << "VYM example map (*.vym)";
    QFileDialog fd;
    fd.setDirectory(vymBaseDir.path() + "/demos");
    fd.setFileMode(QFileDialog::ExistingFiles);
    fd.setNameFilters(filters);
    fd.setWindowTitle(vymName + " - " + tr("Load vym example map"));
    fd.setAcceptMode(QFileDialog::AcceptOpen);

    QString fn;
    if (fd.exec() == QDialog::Accepted) {
        lastMapDir = fd.directory();
        QStringList flist = fd.selectedFiles();
        QStringList::Iterator it = flist.begin();
        initProgressCounter(flist.count());
        while (it != flist.end()) {
            fn = *it;
            fileLoad(*it, NewMap, VymMap);
            ++it;
        }
        removeProgressCounter();
    }
}

void Main::helpShortcuts()
{
    ShowTextDialog dia;
    dia.useFixedFont(true);
    dia.setText(switchboard.getASCII());
    dia.exec();
}

void Main::helpMacros()
{
    ShowTextDialog dia;
    dia.useFixedFont(true);
    dia.setText(macros.help());
    dia.exec();
}

void Main::helpScriptingCommands()
{
    ShowTextDialog dia;
    dia.useFixedFont(true);
    QString s;
    s = "Available commands in map:\n";
    s += "=========================:\n";
    foreach (Command *c, modelCommands) {
        s += c->getDescription();
        s += "\n";
    }

    s += "Available commands in vym:\n";
    s += "=========================:\n";
    foreach (Command *c, vymCommands) {
        s += c->getDescription();
        s += "\n";
    }

    dia.setText(s);
    dia.exec();
}

void Main::helpDebugInfo()
{
    ShowTextDialog dia;
    dia.useFixedFont(true);
    dia.setText(debugInfo());
    dia.setMinimumWidth(900);
    dia.exec();
}

void Main::helpAbout()
{
    AboutDialog ad;
    ad.setMinimumSize(900, 700);
    ad.resize(QSize(900, 700));
    ad.exec();
}

void Main::helpAboutQT()
{
    QMessageBox::aboutQt(this, "Qt Application Example");
}

void Main::callMacro()
{
    QAction *action = qobject_cast<QAction *>(sender());
    int i = -1;
    if (action) {
        QString s = macros.get();
        QString modifiers;

        i = action->data().toInt();

        if (i > 11 && i < 24) {
            modifiers = "shift_";
            i = i - 12;
        } else if (i > 23 && i < 36) {
            modifiers = "ctrl_";
            i = i - 24;
        } else if (i > 35) {
            modifiers = "ctrl_shift_";
            i = i - 36;
        }

        // Function keys start at "1", not "0"
        i++;

        s += QString("macro_%1f%2();").arg(modifiers).arg(i);

        VymModel *m = currentModel();
        if (m)
            m->execute(s);
    }
}

void Main::downloadReleaseNotesFinished()
{
    DownloadAgent *agent = static_cast<DownloadAgent *>(sender());
    QString s;

    if (agent->isSuccess()) {
        QString page;
        if (agent->isSuccess()) {
            if (loadStringFromDisk(agent->getDestination(), page)) {
                ShowTextDialog dia(this);
                dia.setText(page);
                dia.exec();

                // Don't load the release notes automatically again
                settings.setValue("/downloads/releaseNotes/shownVersion",
                                  vymVersion);
            }
        }
    }
    else {
        statusMessage("Downloading release notes failed.");
        if (debug) {
            qDebug() << "Main::downloadReleaseNotesFinished ";
            qDebug() << "  result: failed";
            qDebug() << "     msg: " << agent->getResultMessage();
        }
    }
    agent->deleteLater();

    if (checkUpdatesAfterReleaseNotes)
    {
        // After startup we want to check also for updates, but only after
        // releasenotes are there (and we have a cookie already)
        checkUpdatesAfterReleaseNotes = false;
        checkUpdates();
    }
}

QUrl Main::serverUrl(const QString &scriptName)
{
    // Local URL for testing only
    // QString("http://localhost/release-notes.php?vymVersion=%1") /
    return QUrl(
        QString("http://www.insilmaril.de/vym/%1?"
                    "vymVersion=%2"
                    "&config=darkTheme=%3+localeName=%4+buildDate=%5+codeQuality='%6'+codeName='%7'")
            .arg(scriptName)
            .arg(vymVersion)
            .arg(usingDarkTheme)
            .arg(localeName)
            .arg(vymBuildDate)
            .arg(vymCodeQuality)
            .arg(vymCodeName)
            );
}

void Main::checkReleaseNotesAndUpdates ()
{
    // Called once after startup
    // checkUpdatesAfterReleaseNotes is already true then
    checkReleaseNotes();
}

void Main::checkReleaseNotes ()
{
    bool userTriggered;
    if (qobject_cast<QAction *>(sender()))
        userTriggered = true;
    else
        userTriggered = false;

    if (downloadsEnabled()) {
        if (userTriggered ||
            versionLowerThanVym(
                settings.value("/downloads/releaseNotes/shownVersion", "0.0.1")
                    .toString())) {
            DownloadAgent *agent = new DownloadAgent(serverUrl("release-notes.php"));
            connect(agent, SIGNAL(downloadFinished()), this,
                    SLOT(downloadReleaseNotesFinished()));
            QTimer::singleShot(0, agent, SLOT(execute()));
        }
    }
    else {
        // No downloads enabled
        if (userTriggered) {
            // Notification: vym could not download release notes
            QMessageBox::warning(
                0, tr("Warning"),
                tr("Please allow vym to download release notes!"));
            if (downloadsEnabled(userTriggered))
                checkUpdates();
        }
    }
}

bool Main::downloadsEnabled(bool userTriggered)
{
    bool result;
    if (!userTriggered &&
        settings.value("/downloads/enabled", false).toBool()) {
        result = true;
    }
    else {
        QDate lastAsked =
            settings.value("/downloads/permissionLastAsked", QDate(1970, 1, 1))
                .toDate();
        if (userTriggered ||
            !settings.contains("/downloads/permissionLastAsked") ||
            lastAsked.daysTo(QDate::currentDate()) > 7) {
            QString infotext;
            infotext =
                tr("<html>"
                   "<h3>Do you allow vym to check online for updates or "
                   "release notes?</h3>"
                   "If you allow, vym will "
                   "<ul>"
                   "<li>check once for release notes</li>"
                   "<li>check regulary for updates and notify you in case you "
                   "should update, e.g. if there are "
                   "important bug fixes available</li>"
                   "<li>receive a cookie with a random ID and send some anonymous data, like:"
                   "<ul>"
                   "<li>vym version</li>"
                   "<li>platform name and the ID (e.g. \"Windows\" or \"Linux\")</li>"
                   "<li>if you are using dark theme</li>"
                   "</ul>"
                   "This data is sent to me, Uwe Drechsel."
                   "<p>As vym developer I am motivated to see "
                   "many people using vym. Of course I am curious to see, on "
                   "which system vym is used. Maintaining each "
                   "of the systems requires a lot of my (spare) time.</p> "
                   "<p>No other data than above will be sent, especially no "
                   "private data will be collected or sent."
                   "(Check the source code, if you don't believe.)"
                   "</p>"
                   "</li>"
                   "</ul>"
                   "If you do not allow, "
                   "<ul>"
                   "<li>nothing will be downloaded and especially I will "
                   "<b>not be motivated</b> "
                   "to spend some more thousands of hours on developing a free "
                   "software tool."
                   "</ul>"
                   "Please allow vym to check for updates :-)");
            QMessageBox mb(vymName, infotext, QMessageBox::Information,
                           QMessageBox::Yes | QMessageBox::Default,
                           QMessageBox::No | QMessageBox::Escape,
                           QMessageBox::NoButton);

            mb.setButtonText(QMessageBox::Yes, tr("Allow"));
            mb.setButtonText(QMessageBox::No, tr("Do not allow"));
            switch (mb.exec()) {
            case QMessageBox::Yes: {
                result = true;
                QMessageBox msgBox;
                msgBox.setText(tr("Thank you for enabling downloads!"));
                msgBox.setStandardButtons(QMessageBox::Close);
                msgBox.setIconPixmap(QPixmap(":/flag-face-smile.svg"));
                msgBox.exec();
                break;
                                   }
            default:
                result = false;
                QMessageBox msgBox;
                msgBox.setText(tr("That's ok, though I would be happy to see many users working with vym and also on which platforms."));
                msgBox.setStandardButtons(QMessageBox::Close);
                msgBox.setIconPixmap(QPixmap(":/flag-face-sad.svg"));
                msgBox.exec();
                break;
            }
        }
        else
            result = false;
        actionSettingsToggleDownloads->setChecked(result);
        settings.setValue("/downloads/enabled", result);
        settings.setValue("/downloads/permissionLastAsked",
                          QDate::currentDate().toString(Qt::ISODate));
    }
    return result;
}

void Main::downloadUpdatesFinished(bool userTriggered)
{
    DownloadAgent *agent = static_cast<DownloadAgent *>(sender());
    QString s;

    if (agent->isSuccess()) {
        ShowTextDialog dia;
        dia.setWindowTitle(vymName + " - " + tr("Update information"));
        QString page;
        if (loadStringFromDisk(agent->getDestination(), page)) {
            if (page.contains("vymisuptodate")) {
                statusMessage(tr("vym is up to date.", "MainWindow"));
                if (userTriggered) {
                    // Notification: vym is up to date!
                    dia.setHtml(page);
                    dia.exec();
                }
            }
            else if (page.contains("vymneedsupdate")) {
                // Notification: updates available
                dia.setHtml(page);
                dia.exec();
            }
            else {
                // Notification: Unknown version found
                dia.setHtml(page);
                dia.exec();
            }

            // Prepare to check again later
            settings.setValue("/downloads/updates/lastChecked",
                              QDate::currentDate().toString(Qt::ISODate));
        }
        else
            statusMessage("Couldn't load update page from " +
                          agent->getDestination());
    }
    else {
        statusMessage("Check for updates failed.");
        if (debug) {
            qDebug() << "Main::downloadUpdatesFinished ";
            qDebug() << "  result: failed";
            qDebug() << "     msg: " << agent->getResultMessage();
        }
    }
    agent->deleteLater();
}

void Main::downloadUpdatesFinishedInt() { downloadUpdatesFinished(true); }

void Main::downloadUpdates(bool userTriggered)
{
    DownloadAgent *agent = new DownloadAgent(serverUrl("updates.php"));
    if (userTriggered)
        connect(agent, SIGNAL(downloadFinished()), this,
                SLOT(downloadUpdatesFinishedInt()));
    else
        connect(agent, SIGNAL(downloadFinished()), this,
                SLOT(downloadUpdatesFinished()));
    statusMessage(tr("Checking for updates...", "MainWindow"));
    QTimer::singleShot(0, agent, SLOT(execute()));
}

void Main::checkUpdates()
{
    bool userTriggered;
    if (qobject_cast<QAction *>(sender()))
        userTriggered = true;
    else
        userTriggered = false;

    if (downloadsEnabled()) {
        // Too much time passed since last update check?
        QDate lastChecked =
            settings.value("/downloads/updates/lastChecked", QDate(1970, 1, 1))
                .toDate();
        if (!lastChecked.isValid())
            lastChecked = QDate(1970, 1, 1);
        if (lastChecked.daysTo(QDate::currentDate()) >
                settings.value("/downloads/updates/checkInterval", 3).toInt() ||
            userTriggered == true) {
            downloadUpdates(userTriggered);
        }
    }
    else {
        // No downloads enabled
        if (userTriggered) {
            // Notification: vym could not check for updates
            QMessageBox::warning(0, tr("Warning"),
                                 tr("Please allow vym to check for updates!"));
            if (downloadsEnabled(userTriggered))
                checkUpdates();
        }
    }
}

void Main::escapePressed()
{
    if (presentationMode)
        togglePresentationMode();
    else
        setFocusMapEditor();
}

void Main::togglePresentationMode()
{
    QMap<QToolBar *, bool>::const_iterator i = toolbarStates.constBegin();
    if (!presentationMode) {

        presentationMode = true;
        while (i != toolbarStates.constEnd()) {
            toolbarStates[i.key()] = i.key()->isVisible();
            i.key()->hide();
            ++i;
        }
        menuBar()->hide();
    }
    else {
        presentationMode = false;
        while (i != toolbarStates.constEnd()) {
            i.key()->setVisible(i.value());
            ++i;
        }
        menuBar()->show();
    }
}
