]> git.sven.stormbind.net Git - sven/vym.git/blob - src/mainwindow.cpp
New upstream version 2.9.22
[sven/vym.git] / src / mainwindow.cpp
1 #include "mainwindow.h"
2
3 #include <iostream>
4 using namespace std;
5
6 #include <typeinfo>
7
8 #if defined(VYM_DBUS)
9 #include "adaptorvym.h"
10 #endif
11
12 #include <QColorDialog>
13 #include <QDockWidget>
14 #include <QFileDialog>
15 #include <QFontDialog>
16 #include <QInputDialog>
17 #include <QMenuBar>
18 #include <QScriptEngine>
19 #include <QSslSocket>
20 #include <QStatusBar>
21 #include <QTextStream>
22
23 #include "aboutdialog.h"
24 #include "attributeitem.h"
25 #include "branchitem.h"
26 #include "branchpropeditor.h"
27 #include "command.h"
28 #include "confluence-agent.h"
29 #include "confluence-user.h"
30 #include "confluence-userdialog.h"
31 #include "confluence-settings-dialog.h"
32 #include "darktheme-settings-dialog.h"
33 #include "debuginfo.h"
34 #include "default-map-settings-dialog.h"
35 #include "download-agent.h"
36 #include "file.h"
37 #include "findresultmodel.h"
38 #include "findresultwidget.h"
39 #include "flagrow.h"
40 #include "headingeditor.h"
41 #include "historywindow.h"
42 #include "imports.h"
43 #include "jira-agent.h"
44 #include "jira-settings-dialog.h"
45 #include "lineeditdialog.h"
46 #include "macros.h"
47 #include "mapeditor.h"
48 #include "misc.h"
49 #include "noteeditor.h"
50 #include "options.h"
51 #include "scripteditor.h"
52 #include "scripting.h"
53 #include "scriptoutput.h"
54 #include "settings.h"
55 #include "shortcuts.h"
56 #include "showtextdialog.h"
57 #include "task.h"
58 #include "taskeditor.h"
59 #include "taskmodel.h"
60 #include "treeeditor.h"
61 #include "vymprocess.h"
62 #include "warningdialog.h"
63 #include "xlinkitem.h"
64 #include "zip-settings-dialog.h"
65
66 QPrinter *printer = NULL;
67
68 //#include <modeltest.h>
69
70 #if defined(VYM_DBUS)
71 #include <QDBusConnection>
72 #endif
73
74 extern NoteEditor *noteEditor;
75 extern HeadingEditor *headingEditor;
76 extern BranchPropertyEditor *branchPropertyEditor;
77 extern ScriptEditor *scriptEditor;
78 extern ScriptOutput *scriptOutput;
79 extern Main *mainWindow;
80 extern FindResultWidget *findResultWidget;
81 extern TaskEditor *taskEditor;
82 extern TaskModel *taskModel;
83 extern Macros macros;
84 extern QDir tmpVymDir;
85 extern QDir cacheDir;
86 extern QString clipboardDir;
87 extern QString clipboardFile;
88 extern int statusbarTime;
89 extern FlagRowMaster *standardFlagsMaster;
90 extern FlagRowMaster *userFlagsMaster;
91 extern FlagRowMaster *systemFlagsMaster;
92 extern QString vymName;
93 extern QString vymVersion;
94 extern QString vymPlatform;
95 extern QString vymCodeQuality;
96 extern QString vymCodeName;
97 extern QString vymBuildDate;
98 extern QString localeName;
99 extern bool debug;
100 extern bool testmode;
101 extern QTextStream vout;
102 extern Switchboard switchboard;
103
104 extern bool restoreMode;
105 extern QStringList ignoredLockedFiles;
106 extern QStringList lastSessionFiles;
107
108 extern QList<Command *> modelCommands;
109 extern QList<Command *> vymCommands;
110
111 extern bool usingDarkTheme;
112
113 QMenu *branchAddContextMenu;
114 QMenu *branchContextMenu;
115 QMenu *branchLinksContextMenu;
116 QMenu *branchRemoveContextMenu;
117 QMenu *branchXLinksContextMenuEdit;
118 QMenu *branchXLinksContextMenuFollow;
119 QMenu *canvasContextMenu;
120 QMenu *floatimageContextMenu;
121 QMenu *targetsContextMenu;
122 QMenu *taskContextMenu;
123 QMenu *fileLastMapsMenu;
124 QMenu *fileImportMenu;
125 QMenu *fileExportMenu;
126
127 extern Settings settings;
128 extern Options options;
129 extern ImageIO imageIO;
130
131 extern QDir vymBaseDir;
132 extern QDir vymTranslationsDir;
133 extern QDir lastImageDir;
134 extern QDir lastMapDir;
135 #if defined(Q_OS_WIN32)
136 extern QDir vymInstallDir;
137 #endif
138 extern QString zipToolPath;
139
140 extern QColor vymBlue;
141
142 Main::Main(QWidget *parent) : QMainWindow(parent)
143 {
144     mainWindow = this;
145
146     setWindowTitle("VYM - View Your Mind");
147
148     shortcutScope = tr("Main window", "Shortcut scope");
149
150 // Load window settings
151 #if defined(Q_OS_WIN32)
152     if (settings.value("/mainwindow/geometry/maximized", false).toBool()) {
153         setWindowState(Qt::WindowMaximized);
154     }
155     else
156 #endif
157     {
158         resize(settings.value("/mainwindow/geometry/size", QSize(1024, 900))
159                    .toSize());
160         move(settings.value("/mainwindow/geometry/pos", QPoint(50, 50))
161                  .toPoint());
162     }
163
164     // Sometimes we may need to remember old selections
165     prevSelection = "";
166
167     // Create unique temporary directory
168     bool ok;
169     QString tmpVymDirPath = makeTmpDir(ok, "vym");
170     if (!ok) {
171         qWarning("Mainwindow: Could not create temporary directory, failed to "
172                  "start vym");
173         exit(1);
174     }
175     if (debug)
176         qDebug() << "tmpVymDirPath = " << tmpVymDirPath;
177     tmpVymDir.setPath(tmpVymDirPath);
178
179     // Create direcctory for clipboard
180     clipboardDir = tmpVymDirPath + "/clipboard";
181     clipboardFile = "clipboard";
182     QDir d(clipboardDir);
183     d.mkdir(clipboardDir);
184     makeSubDirs(clipboardDir);
185
186     // Create directory for cached files, e.g. svg images
187     if (!tmpVymDir.mkdir("cache")) {
188         qWarning(
189             "Mainwindow: Could not create cache directory, failed to start vym");
190         exit(1);
191     }
192     cacheDir = QDir(tmpVymDirPath + "/cache");
193
194     // Remember PID of our friendly webbrowser
195     browserPID = new qint64;
196     *browserPID = 0;
197
198     // Define commands in API (used globally)
199     setupAPI();
200
201     // Initialize some settings, which are platform dependant
202     QString p, s;
203
204     // application to open URLs
205     p = "/system/readerURL";
206 #if defined(Q_OS_WIN)
207     // Assume that system has been set up so that
208     // Explorer automagically opens up the URL
209     // in the user's preferred browser.
210     s = settings.value(p, "explorer").toString();
211 #elif defined(Q_OS_MACX)
212     s = settings.value(p, "/usr/bin/open").toString();
213 #else
214     s = settings.value(p, "xdg-open").toString();
215 #endif
216     settings.setValue(p, s);
217
218     // application to open PDFs
219     p = "/system/readerPDF";
220 #if defined(Q_OS_WIN)
221     s = settings.value(p, "explorer").toString();
222 #elif defined(Q_OS_MACX)
223     s = settings.value(p, "/usr/bin/open").toString();
224 #else
225     s = settings.value(p, "xdg-open").toString();
226 #endif
227     settings.setValue(p, s);
228
229     // width of xLinksMenu
230     xLinkMenuWidth = 60;
231
232     // Create Layout
233     QWidget *centralWidget = new QWidget(this);
234     QVBoxLayout *layout = new QVBoxLayout(centralWidget);
235     setCentralWidget(centralWidget);
236
237     // Create tab widget which holds the maps
238     tabWidget = new QTabWidget(centralWidget);
239     connect(tabWidget, SIGNAL(currentChanged(int)), this,
240             SLOT(editorChanged()));
241
242     // Allow closing of tabs (introduced in Qt 4.5)
243     tabWidget->setTabsClosable(true);
244     connect(tabWidget, SIGNAL(tabCloseRequested(int)), this,
245             SLOT(fileCloseMap(int)));
246
247     tabWidget->setMovable(true);
248
249     layout->addWidget(tabWidget);
250
251     switchboard.addGroup("MainWindow", tr("Main window", "Shortcut group"));
252     switchboard.addGroup("MapEditor", tr("Map Editors", "Shortcut group"));
253     switchboard.addGroup("TextEditor", tr("Text Editors", "Shortcut group"));
254
255     // Setup actions
256     setupFileActions();
257     setupEditActions();
258     setupSelectActions();
259     setupFormatActions();
260     setupViewActions();
261     setupModeActions();
262     setupNetworkActions();
263     setupSettingsActions();
264     setupConnectActions();
265     setupContextMenus();
266     setupMacros();
267     setupToolbars();
268     setupFlagActions();
269
270     // Dock widgets ///////////////////////////////////////////////
271     QDockWidget *dw;
272     dw = new QDockWidget();
273     dw->setWidget(noteEditor);
274     dw->setObjectName("NoteEditor");
275     dw->setWindowTitle(noteEditor->getEditorTitle());
276     dw->hide();
277     noteEditorDW = dw;
278     addDockWidget(Qt::LeftDockWidgetArea, dw);
279
280     dw = new QDockWidget();
281     dw->setWidget(headingEditor);
282     dw->setObjectName("HeadingEditor");
283     dw->setWindowTitle(headingEditor->getEditorTitle());
284     dw->hide();
285     headingEditorDW = dw;
286     addDockWidget(Qt::BottomDockWidgetArea, dw);
287
288     findResultWidget = new FindResultWidget();
289     dw = new QDockWidget(tr("Search results list", "FindResultWidget"));
290     dw->setWidget(findResultWidget);
291     dw->setObjectName("FindResultWidget");
292     dw->hide();
293     addDockWidget(Qt::RightDockWidgetArea, dw);
294     connect(findResultWidget, SIGNAL(noteSelected(QString, int)), this,
295             SLOT(selectInNoteEditor(QString, int)));
296     connect(findResultWidget, SIGNAL(findPressed(QString, bool)), this,
297             SLOT(editFindNext(QString, bool)));
298
299     scriptEditor = new ScriptEditor(this);
300     dw = new QDockWidget(tr("Script Editor", "ScriptEditor"));
301     dw->setWidget(scriptEditor);
302     dw->setObjectName("ScriptEditor");
303     dw->hide();
304     addDockWidget(Qt::LeftDockWidgetArea, dw);
305
306     scriptOutput = new ScriptOutput(this);
307     dw = new QDockWidget(tr("Script output window"));
308     dw->setWidget(scriptOutput);
309     dw->setObjectName("ScriptOutput");
310     dw->hide();
311     addDockWidget(Qt::BottomDockWidgetArea, dw);
312
313     dw = new QDockWidget(tr("Property Editor", "PropertyEditor"));
314     dw->setWidget(branchPropertyEditor);
315     dw->setObjectName("PropertyEditor");
316     dw->hide();
317     addDockWidget(Qt::LeftDockWidgetArea, dw);
318     branchPropertyEditorDW = dw;
319
320     historyWindow = new HistoryWindow();
321     dw = new QDockWidget(tr("History window", "HistoryWidget"));
322     dw->setWidget(historyWindow);
323     dw->setObjectName("HistoryWidget");
324     dw->hide();
325     addDockWidget(Qt::RightDockWidgetArea, dw);
326     connect(dw, SIGNAL(visibilityChanged(bool)), this, SLOT(updateActions()));
327
328     // Connect NoteEditor, so that we can update flags if text changes
329     connect(noteEditor, SIGNAL(textHasChanged(const VymText &)), this,
330             SLOT(updateNoteText(const VymText &)));
331     connect(noteEditor, SIGNAL(windowClosed()), this, SLOT(updateActions()));
332
333     // Connect heading editor
334     connect(headingEditor, SIGNAL(textHasChanged(const VymText &)), this,
335             SLOT(updateHeading(const VymText &)));
336
337     connect(scriptEditor, SIGNAL(runScript(QString)), this,
338             SLOT(runScript(QString)));
339
340     // Switch back  to MapEditor using Esc  or end presentation mode
341     QAction *a = new QAction(this);
342     a->setShortcut(Qt::Key_Escape);
343     a->setShortcutContext(Qt::ApplicationShortcut);
344     a->setCheckable(false);
345     a->setEnabled(true);
346     addAction(a);
347     connect(a, SIGNAL(triggered()), this, SLOT(escapePressed()));
348
349     // Create TaskEditor after setting up above actions, allow cloning
350     taskEditor = new TaskEditor();
351     dw = new QDockWidget(tr("Task list", "TaskEditor"));
352     dw->setWidget(taskEditor);
353     dw->setObjectName("TaskEditor");
354     dw->hide();
355     addDockWidget(Qt::TopDockWidgetArea, dw);
356     connect(dw, SIGNAL(visibilityChanged(bool)), this, SLOT(updateActions()));
357     // FIXME -0 connect (taskEditor, SIGNAL (focusReleased() ), this, SLOT
358     // (setFocusMapEditor()));
359
360     if (options.isOn("shortcutsLaTeX"))
361         switchboard.printLaTeX();
362
363     if (settings.value("/mainwindow/showTestMenu", false).toBool())
364         setupTestActions();
365     setupHelpActions();
366
367     // Status bar and progress bar there
368     statusBar();
369     progressMax = 0;
370     progressCounter = 0;
371     progressCounterTotal = 0;
372
373     progressDialog.setAutoReset(false);
374     progressDialog.setAutoClose(false);
375     progressDialog.setMinimumWidth(600);
376     // progressDialog.setWindowModality (Qt::WindowModal);   // That forces
377     // mainwindo to update and slows down
378     progressDialog.setCancelButton(NULL);
379
380     restoreState(settings.value("/mainwindow/state", 0).toByteArray());
381
382     updateGeometry();
383
384     // After startup, schedule looking for updates AFTER
385     // release notes have been downloaded
386     // (avoid race condition with simultanously receiving cookies)
387     checkUpdatesAfterReleaseNotes = true;
388
389 #if defined(VYM_DBUS)
390     // Announce myself on DBUS
391     new AdaptorVym(this); // Created and not deleted as documented in Qt
392     if (!QDBusConnection::sessionBus().registerObject("/vym", this))
393         qWarning("MainWindow: Couldn't register DBUS object!");
394 #endif
395 }
396
397 Main::~Main()
398 {
399     // qDebug()<<"Destr Mainwindow"<<flush;
400
401     // Save Settings
402
403     if (!testmode) {
404 #if defined(Q_OS_WIN32)
405         settings.setValue("/mainwindow/geometry/maximized", isMaximized());
406 #endif
407         settings.setValue("/mainwindow/geometry/size", size());
408         settings.setValue("/mainwindow/geometry/pos", pos());
409         settings.setValue("/mainwindow/state", saveState(0));
410
411         settings.setValue("/mainwindow/view/AntiAlias",
412                           actionViewToggleAntiAlias->isChecked());
413         settings.setValue("/mainwindow/view/SmoothPixmapTransform",
414                           actionViewToggleSmoothPixmapTransform->isChecked());
415         settings.setValue("/system/autosave/use",
416                           actionSettingsToggleAutosave->isChecked());
417         settings.setValue("/system/autosave/ms",
418                           settings.value("/system/autosave/ms", 60000));
419         settings.setValue("/mainwindow/autoLayout/use",
420                           actionSettingsToggleAutoLayout->isChecked());
421         settings.setValue("/mapeditor/editmode/autoSelectNewBranch",
422                           actionSettingsAutoSelectNewBranch->isChecked());
423         settings.setValue("/system/writeBackupFile",
424                           actionSettingsWriteBackupFile->isChecked());
425
426         if (printer) {
427             settings.setValue("/system/printerName", printer->printerName());
428             settings.setValue("/system/printerFormat", printer->outputFormat());
429             settings.setValue("/system/printerFileName",
430                               printer->outputFileName());
431         }
432         settings.setValue("/mapeditor/editmode/autoSelectText",
433                           actionSettingsAutoSelectText->isChecked());
434         settings.setValue("/mapeditor/editmode/useFlagGroups",
435                           actionSettingsUseFlagGroups->isChecked());
436         settings.setValue("/export/useHideExport",
437                           actionSettingsUseHideExport->isChecked());
438         settings.setValue("/system/version", vymVersion);
439         settings.setValue("/system/builddate", vymBuildDate);
440     }
441
442     // call the destructors
443     delete noteEditorDW;
444     delete historyWindow;
445     delete branchPropertyEditorDW;
446
447     delete standardFlagsMaster;
448     delete userFlagsMaster;
449     delete systemFlagsMaster;
450
451     // Remove temporary directory
452     removeDir(tmpVymDir);
453 }
454
455 void Main::loadCmdLine()
456 {
457     QStringList flist = options.getFileList();
458     QStringList::Iterator it = flist.begin();
459
460     initProgressCounter(flist.count());
461     while (it != flist.end()) {
462         FileType type = getMapType(*it);
463         fileLoad(*it, NewMap, type);
464         *it++;
465     }
466     removeProgressCounter();
467 }
468
469 void Main::statusMessage(const QString &s)
470 {
471     // Surpress messages while progressdialog during
472     // load is active
473     statusBar()->showMessage(s, statusbarTime);
474 }
475
476 void Main::setProgressMaximum(int max)
477 {
478     if (progressCounter == 0) {
479         // Init range only on first time, when progressCounter still 0
480         // Normalize range to 1000
481         progressDialog.setRange(0, 1000);
482         progressDialog.setValue(1);
483     }
484     progressCounter++; // Another map is loaded
485
486     progressMax = max * 1000;
487     QApplication::processEvents();
488 }
489
490 void Main::addProgressValue(float v)
491
492 {
493     int progress_value =
494         (v + progressCounter - 1) * 1000 / progressCounterTotal;
495     /*
496         qDebug() << "addVal v="<<v
497          <<"  cur="<<progressDialog.value()
498          <<"  pCounter="<<progressCounter
499          <<"  pCounterTotal="<<progressCounterTotal
500              <<"  newv="<< progress_value
501          ;
502          */
503
504     // Make sure the progress dialog shows, even if value == 0
505     if (progress_value < 1)
506         progress_value = 1;
507     progressDialog.setValue(progress_value);
508     if (progress_value == 1)
509         QApplication::processEvents();
510 }
511
512 void Main::initProgressCounter(uint n) { progressCounterTotal = n; }
513
514 void Main::removeProgressCounter()
515 {
516     // Hide dialog again
517     progressCounter = 0;
518     progressCounterTotal = 0;
519     progressDialog.reset();
520     progressDialog.hide();
521 }
522
523 void Main::closeEvent(QCloseEvent *event)
524 {
525     if (fileExitVYM())
526         event->ignore();
527     else
528         event->accept();
529 }
530
531 QPrinter *Main::setupPrinter()
532 {
533     // Global Printer
534     printer = new QPrinter(QPrinter::HighResolution);
535     return printer;
536 }
537
538 // Define commands for models
539 void Main::setupAPI()
540 {
541     Command *c = new Command("addBranch", Command::Branch);
542     c->addPar(Command::Int, true, "Index of new branch");
543     modelCommands.append(c);
544
545     c = new Command("addBranchBefore", Command::Branch);
546     modelCommands.append(c);
547
548     c = new Command("addMapCenter", Command::Any);
549     c->addPar(Command::Double, false, "Position x");
550     c->addPar(Command::Double, false, "Position y");
551     modelCommands.append(c);
552
553     c = new Command("addMapInsert", Command::Any);
554     c->addPar(Command::String, false, "Filename of map to load");
555     c->addPar(Command::Int, true, "Index where map is inserted");
556     c->addPar(Command::Int, true, "Content filter");
557     modelCommands.append(c);
558
559     c = new Command("addMapReplace", Command::Branch);
560     c->addPar(Command::String, false, "Filename of map to load");
561     modelCommands.append(c);
562
563     c = new Command("addSlide", Command::Branch);
564     modelCommands.append(c);
565
566     c = new Command("addXLink", Command::BranchLike);
567     c->addPar(Command::String, false, "Begin of XLink");
568     c->addPar(Command::String, false, "End of XLink");
569     c->addPar(Command::Int, true, "Width of XLink");
570     c->addPar(Command::Color, true, "Color of XLink");
571     c->addPar(Command::String, true, "Penstyle of XLink");
572     modelCommands.append(c);
573
574     c = new Command("branchCount", Command::Any, Command::Int);
575     modelCommands.append(c);
576
577     c = new Command("centerCount", Command::BranchLike, Command::Int);
578     modelCommands.append(c);
579
580     c = new Command("centerOnID", Command::Any);
581     c->addPar(Command::String, false, "UUID of object to center on");
582     modelCommands.append(c);
583
584     c = new Command("clearFlags", Command::BranchLike);
585     modelCommands.append(c);
586
587     c = new Command("colorBranch", Command::Branch);
588     c->addPar(Command::Color, true, "New color");
589     modelCommands.append(c);
590
591     c = new Command("colorSubtree", Command::Branch);
592     c->addPar(Command::Color, true, "New color");
593     modelCommands.append(c);
594
595     c = new Command("copy", Command::BranchOrImage);
596     modelCommands.append(c);
597
598     c = new Command("cut", Command::BranchOrImage);
599     modelCommands.append(c);
600
601     c = new Command("cycleTask", Command::BranchOrImage);
602     c->addPar(Command::Bool, true, "True, if cycling in reverse order");
603     modelCommands.append(c);
604
605     c = new Command("depth", Command::BranchOrImage, Command::Int);
606     modelCommands.append(c);
607
608     c = new Command("exportMap", Command::Any, Command::Bool);
609     c->addPar(Command::String, false,
610               "Format (AO, ASCII, CONFLUENCE, CSV, HTML, Image, Impress, Last, "
611               "LaTeX, Markdown, OrgMode, PDF, SVG, XML)");
612     modelCommands.append(c);
613
614     c = new Command("getDestPath", Command::Any, Command::String);
615     modelCommands.append(c);
616
617     c = new Command("getFileDir", Command::Any, Command::String);
618     modelCommands.append(c);
619
620     c = new Command("getFileName", Command::Any, Command::String);
621     modelCommands.append(c);
622
623     c = new Command("getFrameType", Command::Branch, Command::String);
624     modelCommands.append(c);
625
626     c = new Command("getHeadingPlainText", Command::TreeItem, Command::String);
627     modelCommands.append(c);
628
629     c = new Command("getHeadingXML", Command::TreeItem, Command::String);
630     modelCommands.append(c);
631
632     c = new Command("getMapAuthor", Command::Any, Command::String);
633     modelCommands.append(c);
634
635     c = new Command("getMapComment", Command::Any, Command::String);
636     modelCommands.append(c);
637
638     c = new Command("getMapTitle", Command::Any, Command::String);
639     modelCommands.append(c);
640
641     c = new Command("getNotePlainText", Command::TreeItem, Command::String);
642     modelCommands.append(c);
643
644     c = new Command("getNoteXML", Command::TreeItem, Command::String);
645     modelCommands.append(c);
646
647     c = new Command("getSelectionString", Command::TreeItem, Command::String);
648     modelCommands.append(c);
649
650     c = new Command("getTaskPriorityDelta", Command::Branch, Command::Int);
651     modelCommands.append(c);
652
653     c = new Command("getTaskSleep", Command::Branch, Command::String);
654     modelCommands.append(c);
655
656     c = new Command("getTaskSleepDays", Command::Branch, Command::Int);
657     modelCommands.append(c);
658
659     c = new Command("getURL", Command::TreeItem, Command::String);
660     modelCommands.append(c);
661
662     c = new Command("getVymLink", Command::Branch, Command::String);
663     modelCommands.append(c);
664
665     c = new Command("getXLinkColor", Command::XLink, Command::String);
666     modelCommands.append(c);
667
668     c = new Command("getXLinkWidth", Command::XLink, Command::Int);
669     modelCommands.append(c);
670
671     c = new Command("getXLinkPenStyle", Command::XLink, Command::String);
672     modelCommands.append(c);
673
674     c = new Command("getXLinkStyleBegin", Command::XLink, Command::String);
675     modelCommands.append(c);
676
677     c = new Command("getXLinkStyleEnd", Command::XLink, Command::String);
678     modelCommands.append(c);
679
680     c = new Command("hasActiveFlag", Command::TreeItem, Command::Bool);
681     c->addPar(Command::String, false, "Name of flag");
682     modelCommands.append(c);
683
684     c = new Command("hasNote", Command::Branch, Command::Bool);
685     modelCommands.append(c);
686
687     c = new Command("hasRichTextNote", Command::Branch, Command::Bool);
688     modelCommands.append(c);
689
690     c = new Command("hasTask", Command::Branch, Command::Bool);
691     modelCommands.append(c);
692
693     c = new Command("importDir", Command::Branch);
694     c->addPar(Command::String, false, "Directory name to import");
695     modelCommands.append(c);
696
697     c = new Command("initIterator", Command::Branch, Command::Bool);
698     c->addPar(Command::String, false, "Name of iterator");
699     c->addPar(Command::Bool, true, "Flag to go deep levels first");
700     modelCommands.append(c);
701
702     c = new Command("isScrolled", Command::Branch, Command::Bool);
703     modelCommands.append(c);
704
705     c = new Command("loadImage", Command::Branch);
706     c->addPar(Command::String, false, "Filename of image");
707     modelCommands.append(c);
708
709     c = new Command("loadNote", Command::Branch);
710     c->addPar(Command::String, false, "Filename of note");
711     modelCommands.append(c);
712
713     c = new Command("moveDown", Command::Branch);
714     modelCommands.append(c);
715
716     c = new Command("moveUp", Command::Branch);
717     modelCommands.append(c);
718
719     c = new Command("moveSlideDown", Command::Any);
720     modelCommands.append(c);
721
722     c = new Command("moveSlideUp", Command::Any);
723     modelCommands.append(c);
724
725     c = new Command("move", Command::BranchOrImage);
726     c->addPar(Command::Double, false, "Position x");
727     c->addPar(Command::Double, false, "Position y");
728     modelCommands.append(c);
729
730     c = new Command("moveRel", Command::BranchOrImage);
731     c->addPar(Command::Double, false, "Position x");
732     c->addPar(Command::Double, false, "Position y");
733     modelCommands.append(c);
734
735     c = new Command("nextIterator", Command::Branch, Command::Bool);
736     c->addPar(Command::String, false, "Name of iterator");
737     modelCommands.append(c);
738
739     c = new Command("nop", Command::Any);
740     modelCommands.append(c);
741
742     c = new Command("note2URLs", Command::Branch);
743     modelCommands.append(c);
744
745     // internally required for undo/redo of changing VymText:
746     c = new Command("parseVymText", Command::Branch, Command::Bool);
747     c->addPar(Command::String, false,
748               "parse XML of VymText, e.g for Heading or VymNote");
749     modelCommands.append(c);
750
751     c = new Command("paste", Command::Branch);
752     modelCommands.append(c);
753
754     c = new Command("redo", Command::Any);
755     modelCommands.append(c);
756
757     c = new Command("relinkTo",
758                     Command::TreeItem,
759                     Command::Bool); // FIXME different number of parameters for Image or Branch
760     c->addPar(Command::String, false, "Selection string of parent");
761     c->addPar(Command::Int, false, "Index position");
762     c->addPar(Command::Double, true, "Position x");
763     c->addPar(Command::Double, true, "Position y");
764     modelCommands.append(c);
765
766     c = new Command("remove", Command::TreeItem);
767     modelCommands.append(c);
768
769     c = new Command("removeChildren", Command::Branch);
770     modelCommands.append(c);
771
772     c = new Command("removeKeepChildren", Command::Branch);
773     modelCommands.append(c);
774
775     c = new Command("removeSlide", Command::Any);
776     c->addPar(Command::Int, false, "Index of slide to remove");
777     modelCommands.append(c);
778
779     c = new Command("repeatLastCommand", Command::Any);
780     modelCommands.append(c);
781
782     c = new Command("saveImage", Command::Image);
783     c->addPar(Command::String, false, "Filename of image to save");
784     c->addPar(Command::String, false, "Format of image to save");
785     modelCommands.append(c);
786
787     c = new Command("saveNote", Command::Branch);
788     c->addPar(Command::String, false, "Filename of note to save");
789     modelCommands.append(c);
790
791     c = new Command("scroll", Command::Branch);
792     modelCommands.append(c);
793
794     c = new Command("select", Command::Any, Command::Bool);
795     c->addPar(Command::String, false, "Selection string");
796     modelCommands.append(c);
797
798     c = new Command("selectFirstBranch", Command::Branch, Command::Bool);
799     modelCommands.append(c);
800
801     c = new Command("selectFirstChildBranch", Command::Branch, Command::Bool);
802     modelCommands.append(c);
803
804     c = new Command("selectID", Command::Any, Command::Bool);
805     c->addPar(Command::String, false, "Unique ID");
806     modelCommands.append(c);
807
808     c = new Command("selectLastBranch", Command::Branch, Command::Bool);
809     modelCommands.append(c);
810
811     c = new Command("selectLastChildBranch", Command::Branch, Command::Bool);
812     modelCommands.append(c);
813
814     c = new Command("selectLastImage", Command::Branch, Command::Bool);
815     modelCommands.append(c);
816
817     c = new Command("selectLatestAdded", Command::Any, Command::Bool);
818     modelCommands.append(c);
819
820     c = new Command("selectParent", Command::Branch, Command::Bool);
821     modelCommands.append(c);
822
823     c = new Command("selectToggle", Command::BranchOrImage, Command::Bool);
824     modelCommands.append(c);
825
826     c = new Command("setFlagByName", Command::TreeItem);
827     c->addPar(Command::String, false, "Name of flag");
828     modelCommands.append(c);
829
830     c = new Command("setTaskPriorityDelta", Command::Branch);
831     c->addPar(Command::String, false, "Manually add value to priority of task");
832     modelCommands.append(c);
833
834     c = new Command("setTaskSleep", Command::Branch);
835     c->addPar(Command::String, false, "Days to sleep");
836     modelCommands.append(c);
837
838     c = new Command("setFrameIncludeChildren", Command::BranchOrImage);
839     c->addPar(Command::Bool, false,
840               "Include or don't include children in frame");
841     modelCommands.append(c);
842
843     c = new Command("setFrameType", Command::BranchOrImage);
844     c->addPar(Command::String, false, "Type of frame");
845     modelCommands.append(c);
846
847     c = new Command("setFramePenColor", Command::BranchOrImage);
848     c->addPar(Command::Color, false, "Color of frame border line");
849     modelCommands.append(c);
850
851     c = new Command("setFrameBrushColor", Command::BranchOrImage);
852     c->addPar(Command::Color, false, "Color of frame background");
853     modelCommands.append(c);
854
855     c = new Command("setFramePadding", Command::BranchOrImage);
856     c->addPar(Command::Int, false, "Padding around frame");
857     modelCommands.append(c);
858
859     c = new Command("setFrameBorderWidth", Command::BranchOrImage);
860     c->addPar(Command::Int, false, "Width of frame borderline");
861     modelCommands.append(c);
862
863     c = new Command("setHeadingConfluencePageName", Command::Branch);
864     modelCommands.append(c);
865
866     c = new Command("setHeadingPlainText", Command::TreeItem);
867     c->addPar(Command::String, false, "New heading");
868     modelCommands.append(c);
869
870     c = new Command("setHideExport", Command::BranchOrImage);
871     c->addPar(Command::Bool, false, "Set if item should be visible in export");
872     modelCommands.append(c);
873
874     c = new Command("setIncludeImagesHorizontally", Command::Branch);
875     c->addPar(Command::Bool, false,
876               "Set if images should be included horizontally in parent branch");
877     modelCommands.append(c);
878
879     c = new Command("setIncludeImagesVertically", Command::Branch);
880     c->addPar(Command::Bool, false,
881               "Set if images should be included vertically in parent branch");
882     modelCommands.append(c);
883
884     c = new Command("setHideLinksUnselected", Command::BranchOrImage);
885     c->addPar(Command::Bool, false,
886               "Set if links of items should be visible for unselected items");
887     modelCommands.append(c);
888
889     c = new Command("setMapAnimCurve", Command::Any);
890     c->addPar(Command::Int, false,
891               "EasingCurve used in animation in MapEditor");
892     modelCommands.append(c);
893
894     c = new Command("setMapAuthor", Command::Any);
895     c->addPar(Command::String, false, "");
896     modelCommands.append(c);
897
898     c = new Command("setMapAnimDuration", Command::Any);
899     c->addPar(Command::Int, false,
900               "Duration of animation in MapEditor in milliseconds");
901     modelCommands.append(c);
902
903     c = new Command("setMapBackgroundColor", Command::Any);
904     c->addPar(Command::Color, false, "Color of map background");
905     modelCommands.append(c);
906
907     c = new Command("setMapComment", Command::Any);
908     c->addPar(Command::String, false, "");
909     modelCommands.append(c);
910
911     c = new Command("setMapTitle", Command::Any);
912     c->addPar(Command::String, false, "");
913     modelCommands.append(c);
914
915     c = new Command("setMapDefLinkColor", Command::Any);
916     c->addPar(Command::Color, false, "Default color of links");
917     modelCommands.append(c);
918
919     c = new Command("setMapLinkStyle", Command::Any);
920     c->addPar(Command::String, false, "Link style in map");
921     modelCommands.append(c);
922
923     c = new Command("setMapRotation", Command::Any);
924     c->addPar(Command::Double, false, "Rotation of map");
925     modelCommands.append(c);
926
927     c = new Command("setMapTitle", Command::Any);
928     c->addPar(Command::String, false, "");
929     modelCommands.append(c);
930
931     c = new Command("setMapZoom", Command::Any);
932     c->addPar(Command::Double, false, "Zoomfactor of map");
933     modelCommands.append(c);
934
935     c = new Command("setNotePlainText", Command::Branch);
936     c->addPar(Command::String, false, "Note of branch");
937     modelCommands.append(c);
938
939     c = new Command("setScaleFactor", Command::Image);
940     c->addPar(Command::Double, false, "Scale image by factor f");
941     modelCommands.append(c);
942
943     c = new Command("setSelectionColor", Command::Any);
944     c->addPar(Command::Color, false, "Color of selection box");
945     modelCommands.append(c);
946
947     c = new Command("setSelectionPenColor", Command::Any);
948     c->addPar(Command::Color, false, "Color of selection box border");
949     modelCommands.append(c);
950
951     c = new Command("setSelectionPenWidth", Command::Any);
952     c->addPar(Command::Int, false, "Selection box border width ");
953     modelCommands.append(c);
954
955     c = new Command("setSelectionBrushColor", Command::Any);
956     c->addPar(Command::Color, false, "Color of selection box background");
957     modelCommands.append(c);
958
959     c = new Command("setTaskPriority", Command::Branch);
960     c->addPar(Command::Int, false, "Priority of task");
961     modelCommands.append(c);
962
963     c = new Command("setTaskSleep", Command::Branch, Command::Bool);
964     c->addPar(Command::String, false, "Sleep time of task");
965     modelCommands.append(c);
966
967     c = new Command("setURL", Command::TreeItem);
968     c->addPar(Command::String, false, "URL of TreeItem");
969     modelCommands.append(c);
970
971     c = new Command("setVymLink", Command::Branch);
972     c->addPar(Command::String, false, "Vymlink of branch");
973     modelCommands.append(c);
974
975     c = new Command("setXLinkColor", Command::XLink);
976     c->addPar(Command::String, false, "Color of xlink");
977     modelCommands.append(c);
978
979     c = new Command("setXLinkStyle", Command::XLink);
980     c->addPar(Command::String, false, "Style of xlink");
981     modelCommands.append(c);
982
983     c = new Command("setXLinkStyleBegin", Command::XLink);
984     c->addPar(Command::String, false, "Style of xlink begin");
985     modelCommands.append(c);
986
987     c = new Command("setXLinkStyleEnd", Command::XLink);
988     c->addPar(Command::String, false, "Style of xlink end");
989     modelCommands.append(c);
990
991     c = new Command("setXLinkWidth", Command::XLink);
992     c->addPar(Command::Int, false, "Width of xlink");
993     modelCommands.append(c);
994
995     c = new Command("sleep", Command::Any);
996     c->addPar(Command::Int, false, "Sleep (seconds)");
997     modelCommands.append(c);
998
999     c = new Command("sortChildren", Command::Branch);
1000     c->addPar(Command::Bool, true,
1001               "Sort children of branch in revers order if set");
1002     modelCommands.append(c);
1003
1004     c = new Command("toggleFlagByUid", Command::Branch);
1005     c->addPar(Command::String, false, "Uid of flag to toggle");
1006     modelCommands.append(c);
1007
1008     c = new Command("toggleFlagByName", Command::Branch);
1009     c->addPar(Command::String, false, "Name of flag to toggle");
1010     modelCommands.append(c);
1011
1012     c = new Command("toggleFrameIncludeChildren", Command::Branch);
1013     modelCommands.append(c);
1014
1015     c = new Command("toggleScroll", Command::Branch);
1016     modelCommands.append(c);
1017
1018     c = new Command("toggleTarget", Command::Branch);
1019     modelCommands.append(c);
1020
1021     c = new Command("toggleTask", Command::Branch);
1022     modelCommands.append(c);
1023
1024     c = new Command("undo", Command::Any);
1025     modelCommands.append(c);
1026
1027     c = new Command("unscroll", Command::Branch, Command::Bool);
1028     modelCommands.append(c);
1029
1030     c = new Command("unscrollChildren", Command::Branch);
1031     modelCommands.append(c);
1032
1033     c = new Command("unselectAll", Command::Any);
1034     modelCommands.append(c);
1035
1036     c = new Command("unsetFlagByName", Command::Branch);
1037     c->addPar(Command::String, false, "Name of flag to unset");
1038     modelCommands.append(c);
1039
1040     //
1041     // Below are the commands for vym itself:
1042     //
1043
1044     c = new Command("clearConsole", Command::Any);
1045     vymCommands.append(c);
1046
1047     c = new Command("closeMapWithID", Command::Any);
1048     c->addPar(Command::Int, false, "ID of map (unsigned int)");
1049     vymCommands.append(c);
1050
1051     c = new Command("currentMap", Command::Any);
1052     vymCommands.append(c);
1053
1054     c = new Command("currentMapIndex", Command::Any);
1055     vymCommands.append(c);
1056
1057     c = new Command("editHeading", Command::Branch);
1058     vymCommands.append(c);
1059
1060     c = new Command("loadMap", Command::Any);
1061     c->addPar(Command::String, false, "Path to map");
1062     vymCommands.append(c);
1063
1064     c = new Command("mapCount", Command::Any);
1065     vymCommands.append(c);
1066
1067     c = new Command("gotoMap", Command::Any);
1068     c->addPar(Command::Int, false, "Index of map");
1069     vymCommands.append(c);
1070
1071     c = new Command("selectQuickColor", Command::Any);
1072     c->addPar(Command::Int, false, "Index of quick color [0..6]");
1073     vymCommands.append(c);
1074
1075     c = new Command("currentColor", Command::Any);
1076     vymCommands.append(c);
1077
1078     c = new Command("toggleTreeEditor", Command::Any);
1079     vymCommands.append(c);
1080
1081     c = new Command("version", Command::Any);
1082     vymCommands.append(c);
1083 }
1084
1085 void Main::cloneActionMapEditor(QAction *a, QKeySequence ks)
1086 {
1087     a->setShortcut(ks);
1088     a->setShortcutContext(Qt::WidgetShortcut);
1089     mapEditorActions.append(a);
1090 }
1091
1092 // File Actions
1093 void Main::setupFileActions()
1094 {
1095     QString tag = tr("&Map", "Menu for file actions");
1096     QMenu *fileMenu = menuBar()->addMenu(tag);
1097
1098     QAction *a;
1099     a = new QAction(QPixmap(":/filenew.png"), tr("&New map", "File menu"),
1100                     this);
1101     switchboard.addSwitch("fileMapNew", shortcutScope, a, tag);
1102     connect(a, SIGNAL(triggered()), this, SLOT(fileNew()));
1103     cloneActionMapEditor(a, Qt::CTRL + Qt::Key_N);
1104     fileMenu->addAction(a);
1105     actionFileNew = a;
1106
1107     a = new QAction(QPixmap(":/filenewcopy.png"),
1108                     tr("&Copy to new map", "File menu"), this);
1109     switchboard.addSwitch("fileMapNewCopy", shortcutScope, a, tag);
1110     connect(a, SIGNAL(triggered()), this, SLOT(fileNewCopy()));
1111     cloneActionMapEditor(a, Qt::CTRL + Qt::SHIFT + Qt::Key_C);
1112     fileMenu->addAction(a);
1113     actionFileNewCopy = a;
1114
1115     a = new QAction(QPixmap(":/fileopen.png"), tr("&Open...", "File menu"),
1116                     this);
1117     switchboard.addSwitch("fileMapOpen", shortcutScope, a, tag);
1118     connect(a, SIGNAL(triggered()), this, SLOT(fileLoad()));
1119     cloneActionMapEditor(a, Qt::CTRL + Qt::Key_L);
1120     fileMenu->addAction(a);
1121     actionFileOpen = a;
1122
1123     a = new QAction(tr("&Restore last session", "Edit menu"), this);
1124     a->setShortcut(Qt::ALT + Qt::Key_R);
1125     switchboard.addSwitch("fileMapRestore", shortcutScope, a, tag);
1126     connect(a, SIGNAL(triggered()), this, SLOT(fileRestoreSession()));
1127     fileMenu->addAction(a);
1128     actionListFiles.append(a);
1129     actionCopy = a;
1130
1131     fileLastMapsMenu = fileMenu->addMenu(tr("Open Recent", "File menu"));
1132     fileMenu->addSeparator();
1133
1134     a = new QAction(QPixmap(":/filesave.svg"), tr("&Save...", "File menu"),
1135                     this);
1136     switchboard.addSwitch("fileMapSave", shortcutScope, a, tag);
1137     cloneActionMapEditor(a, Qt::CTRL + Qt::Key_S);
1138     fileMenu->addAction(a);
1139     restrictedMapActions.append(a);
1140     connect(a, SIGNAL(triggered()), this, SLOT(fileSave()));
1141     actionFileSave = a;
1142
1143     a = new QAction(QPixmap(":/filesaveas.png"), tr("Save &As...", "File menu"),
1144                     this);
1145     fileMenu->addAction(a);
1146     connect(a, SIGNAL(triggered()), this, SLOT(fileSaveAs()));
1147
1148     a = new QAction(tr("Save as default map", "File menu"), this);
1149     fileMenu->addAction(a);
1150     connect(a, SIGNAL(triggered()), this, SLOT(fileSaveAsDefault()));
1151
1152     fileMenu->addSeparator();
1153
1154     fileImportMenu = fileMenu->addMenu(tr("Import", "File menu"));
1155
1156     a = new QAction( tr("Firefox Bookmarks", "Import filters") + 
1157                         tr("(experimental)"),
1158                     this);
1159     connect(a, SIGNAL(triggered()), this,
1160             SLOT(fileImportFirefoxBookmarks()));
1161     fileImportMenu->addAction(a);
1162
1163     a = new QAction("Freemind...", this);
1164     connect(a, SIGNAL(triggered()), this, SLOT(fileImportFreemind()));
1165     fileImportMenu->addAction(a);
1166
1167     a = new QAction("Mind Manager...", this);
1168     connect(a, SIGNAL(triggered()), this, SLOT(fileImportMM()));
1169     fileImportMenu->addAction(a);
1170
1171     a = new QAction(tr("Import Dir...", "Import Filters") + " " +
1172                         tr("(still experimental)"),
1173                     this);
1174     connect(a, SIGNAL(triggered()), this, SLOT(fileImportDir()));
1175     fileImportMenu->addAction(a);
1176
1177     fileExportMenu = fileMenu->addMenu(tr("Export", "File menu"));
1178
1179     a = new QAction(QPixmap(":/file-document-export.png"),
1180                     tr("Repeat last export (%1)").arg("-"), this);
1181     switchboard.addSwitch("fileExportLast", shortcutScope, a, tag);
1182     connect(a, SIGNAL(triggered()), this, SLOT(fileExportLast()));
1183     cloneActionMapEditor(a, Qt::ALT + Qt::Key_E);
1184     fileExportMenu->addAction(a);
1185     actionFileExportLast = a;
1186     actionListFiles.append(a);
1187
1188     a = new QAction(tr("Webpage (HTML)...", "File export menu"), this);
1189     connect(a, SIGNAL(triggered()), this, SLOT(fileExportHTML()));
1190     fileExportMenu->addAction(a);
1191     actionListFiles.append(a);
1192
1193     a = new QAction(tr("Confluence (HTML)...", "File export menu") + " " + " " +
1194                         tr("(still experimental)"),
1195                     this);
1196     connect(a, SIGNAL(triggered()), this, SLOT(fileExportConfluence()));
1197     fileExportMenu->addAction(a);
1198     actionListFiles.append(a);
1199     actionFileExportConfluence = a;
1200
1201     a = new QAction( tr("Firefox Bookmarks", "File export menu") + 
1202                         tr("(still experimental)"),
1203                     this);
1204     connect(a, SIGNAL(triggered()), this,
1205             SLOT(fileExportFirefoxBookmarks()));
1206     fileExportMenu->addAction(a);
1207     actionListFiles.append(a);
1208
1209     a = new QAction(tr("Text (ASCII)...", "File export menu"), this);
1210     connect(a, SIGNAL(triggered()), this, SLOT(fileExportASCII()));
1211     fileExportMenu->addAction(a);
1212     actionListFiles.append(a);
1213
1214     a = new QAction(tr("Text (Markdown)...", "File export menu") + " " +
1215                         tr("(still experimental)"),
1216                     this);
1217     connect(a, SIGNAL(triggered()), this, SLOT(fileExportMarkdown()));
1218     fileExportMenu->addAction(a);
1219     actionListFiles.append(a);
1220
1221     a = new QAction(tr("Text with tasks", "File export menu") + " " +
1222                         tr("(still experimental)"),
1223                     this);
1224     connect(a, SIGNAL(triggered()), this, SLOT(fileExportASCIITasks()));
1225     fileExportMenu->addAction(a);
1226     actionListFiles.append(a);
1227
1228     a = new QAction(tr("Text (A&O report)...", "Export format"), this);
1229     connect(a, SIGNAL(triggered()), this, SLOT(fileExportAO()));
1230     fileExportMenu->addAction(a);
1231     actionListFiles.append(a);
1232
1233     a = new QAction(tr("Image%1", "File export menu").arg("..."), this);
1234     connect(a, SIGNAL(triggered()), this, SLOT(fileExportImage()));
1235     fileExportMenu->addAction(a);
1236     actionListFiles.append(a);
1237
1238     a = new QAction(tr("PDF%1", "File export menu").arg("..."), this);
1239     connect(a, SIGNAL(triggered()), this, SLOT(fileExportPDF()));
1240     fileExportMenu->addAction(a);
1241     actionListFiles.append(a);
1242
1243     a = new QAction(tr("SVG%1", "File export menu").arg("..."), this);
1244     connect(a, SIGNAL(triggered()), this, SLOT(fileExportSVG()));
1245     fileExportMenu->addAction(a);
1246     actionListFiles.append(a);
1247
1248     a = new QAction("LibreOffice...", this);
1249     connect(a, SIGNAL(triggered()), this, SLOT(fileExportImpress()));
1250     fileExportMenu->addAction(a);
1251     actionListFiles.append(a);
1252
1253     a = new QAction("XML...", this);
1254     connect(a, SIGNAL(triggered()), this, SLOT(fileExportXML()));
1255     fileExportMenu->addAction(a);
1256     actionListFiles.append(a);
1257
1258     a = new QAction(tr("CSV...") + " " + tr("(still experimental)"), this);
1259     connect(a, SIGNAL(triggered()), this, SLOT(fileExportCSV()));
1260     fileExportMenu->addAction(a);
1261     actionListFiles.append(a);
1262
1263     a = new QAction("Taskjuggler... " + tr("(still experimental)"), this);
1264     connect(a, SIGNAL(triggered()), this, SLOT(fileExportTaskjuggler()));
1265     fileExportMenu->addAction(a);
1266     actionListFiles.append(a);
1267
1268     a = new QAction("OrgMode... " + tr("(still experimental)"), this);
1269     connect(a, SIGNAL(triggered()), this, SLOT(fileExportOrgMode()));
1270     fileExportMenu->addAction(a);
1271     actionListFiles.append(a);
1272
1273     a = new QAction("LaTeX... " + tr("(still experimental)"), this);
1274     connect(a, SIGNAL(triggered()), this, SLOT(fileExportLaTeX()));
1275     fileExportMenu->addAction(a);
1276     actionListFiles.append(a);
1277
1278     fileMenu->addSeparator();
1279
1280     a = new QAction(tr("Properties"), this);
1281     switchboard.addSwitch("editMapProperties", shortcutScope, a, tag);
1282     connect(a, SIGNAL(triggered()), this, SLOT(editMapProperties()));
1283     fileMenu->addAction(a);
1284     actionListFiles.append(a);
1285     actionMapProperties = a;
1286
1287     fileMenu->addSeparator();
1288
1289     a = new QAction(QPixmap(":/fileprint.png"), tr("&Print") + QString("..."),
1290                     this);
1291     a->setShortcut(Qt::CTRL + Qt::Key_P);
1292     switchboard.addSwitch("fileMapPrint", shortcutScope, a, tag);
1293     connect(a, SIGNAL(triggered()), this, SLOT(filePrint()));
1294     fileMenu->addAction(a);
1295     unrestrictedMapActions.append(a);
1296     actionFilePrint = a;
1297
1298     a = new QAction(QPixmap(":/fileclose.png"), tr("&Close Map", "File menu"),
1299                     this);
1300     a->setShortcut(Qt::CTRL + Qt::Key_W);
1301     switchboard.addSwitch("fileMapClose", shortcutScope, a, tag);
1302     connect(a, SIGNAL(triggered()), this, SLOT(fileCloseMap()));
1303     fileMenu->addAction(a);
1304
1305     a = new QAction(QPixmap(":/exit.png"), tr("E&xit", "File menu"), this);
1306     a->setShortcut(Qt::CTRL + Qt::Key_Q);
1307     switchboard.addSwitch("fileExit", shortcutScope, a, tag);
1308     connect(a, SIGNAL(triggered()), this, SLOT(fileExitVYM()));
1309     fileMenu->addAction(a);
1310
1311     a = new QAction("Toggle winter mode", this);
1312     a->setShortcut(Qt::CTRL + Qt::Key_Asterisk);
1313     a->setShortcutContext(Qt::WidgetShortcut);
1314
1315     if (settings.value("/mainwindow/showTestMenu", false).toBool()) {
1316         addAction(a);
1317         mapEditorActions.append(a);
1318         switchboard.addSwitch("mapWinterMode", shortcutScope, a, tag);
1319     }
1320     connect(a, SIGNAL(triggered()), this, SLOT(toggleWinter()));
1321     actionToggleWinter = a;
1322 }
1323
1324 // Edit Actions
1325 void Main::setupEditActions()
1326 {
1327     QString tag = tr("E&dit", "Edit menu");
1328     QMenu *editMenu = menuBar()->addMenu(tag);
1329
1330     QAction *a;
1331     a = new QAction(QPixmap(":/undo.png"), tr("&Undo", "Edit menu"), this);
1332     a->setShortcut(Qt::CTRL + Qt::Key_Z);
1333     a->setShortcutContext(Qt::WidgetShortcut);
1334     a->setEnabled(false);
1335     editMenu->addAction(a);
1336     mapEditorActions.append(a);
1337     restrictedMapActions.append(a);
1338     switchboard.addSwitch("mapUndo", shortcutScope, a, tag);
1339     connect(a, SIGNAL(triggered()), this, SLOT(editUndo()));
1340     actionUndo = a;
1341
1342     a = new QAction(QPixmap(":/redo.png"), tr("&Redo", "Edit menu"), this);
1343     a->setShortcut(Qt::CTRL + Qt::Key_Y);
1344     a->setShortcutContext(Qt::WidgetShortcut);
1345     editMenu->addAction(a);
1346     restrictedMapActions.append(a);
1347     mapEditorActions.append(a);
1348     switchboard.addSwitch("mapRedo", shortcutScope, a, tag);
1349     connect(a, SIGNAL(triggered()), this, SLOT(editRedo()));
1350     actionRedo = a;
1351
1352     editMenu->addSeparator();
1353     a = new QAction(QPixmap(":/editcopy.png"), tr("&Copy", "Edit menu"), this);
1354     a->setShortcut(Qt::CTRL + Qt::Key_C);
1355     a->setShortcutContext(Qt::WidgetShortcut);
1356     a->setEnabled(false);
1357     editMenu->addAction(a);
1358     unrestrictedMapActions.append(a);
1359     mapEditorActions.append(a);
1360     switchboard.addSwitch("mapCopy", shortcutScope, a, tag);
1361     connect(a, SIGNAL(triggered()), this, SLOT(editCopy()));
1362     actionCopy = a;
1363
1364     a = new QAction(QPixmap(":/editcut.png"), tr("Cu&t", "Edit menu"), this);
1365     a->setShortcut(Qt::CTRL + Qt::Key_X);
1366     a->setEnabled(false);
1367     a->setShortcutContext(Qt::WidgetShortcut);
1368     editMenu->addAction(a);
1369     restrictedMapActions.append(a);
1370     mapEditorActions.append(a);
1371     restrictedMapActions.append(a);
1372     switchboard.addSwitch("mapCut", shortcutScope, a, tag);
1373     connect(a, SIGNAL(triggered()), this, SLOT(editCut()));
1374     addAction(a);
1375     actionCut = a;
1376
1377     a = new QAction(QPixmap(":/editpaste.png"), tr("&Paste", "Edit menu"),
1378                     this);
1379     connect(a, SIGNAL(triggered()), this, SLOT(editPaste()));
1380     a->setShortcut(Qt::CTRL + Qt::Key_V);
1381     a->setShortcutContext(Qt::WidgetShortcut);
1382     a->setEnabled(false);
1383     editMenu->addAction(a);
1384     restrictedMapActions.append(a);
1385     mapEditorActions.append(a);
1386     switchboard.addSwitch("mapPaste", shortcutScope, a, tag);
1387     actionPaste = a;
1388
1389     // Shortcut to delete selection
1390     a = new QAction(tr("Delete Selection", "Edit menu"), this);
1391     a->setShortcut(Qt::Key_Delete);
1392     a->setShortcutContext(Qt::WindowShortcut);
1393     switchboard.addSwitch("mapDelete", shortcutScope, a, tag);
1394     addAction(a);
1395     editMenu->addAction(a);
1396     actionListItems.append(a);
1397     actionDelete = a;
1398
1399     connect(a, SIGNAL(triggered()), this, SLOT(editDeleteSelection()));
1400     a = new QAction(tr("Delete Selection", "Edit menu"), this);
1401     a->setShortcut(Qt::Key_D);
1402     a->setShortcutContext(Qt::WindowShortcut);
1403     switchboard.addSwitch("mapDelete", shortcutScope, a, tag);
1404     addAction(a);
1405     connect(a, SIGNAL(triggered()), this, SLOT(editDeleteSelection()));
1406     editMenu->addAction(a);
1407     actionListItems.append(a);
1408     actionDeleteAlt = a;
1409
1410     // Shortcut to add attribute
1411     a = new QAction(tr("Add attribute") + " (test)", this);
1412     if (settings.value("/mainwindow/showTestMenu", false).toBool()) {
1413         a->setShortcutContext(Qt::WindowShortcut);
1414         switchboard.addSwitch("mapAddAttribute", shortcutScope, a, tag);
1415         connect(a, SIGNAL(triggered()), this, SLOT(editAddAttribute()));
1416         editMenu->addAction(a);
1417     }
1418     actionAddAttribute = a;
1419
1420     // Shortcut to add mapcenter
1421     a = new QAction(QPixmap(":/newmapcenter.png"),
1422                     tr("Add mapcenter", "Canvas context menu"), this);
1423     a->setShortcut(Qt::Key_C);
1424     a->setShortcutContext(Qt::WindowShortcut);
1425     switchboard.addSwitch("mapAddCenter", shortcutScope, a, tag);
1426     connect(a, SIGNAL(triggered()), this, SLOT(editAddMapCenter()));
1427     editMenu->addAction(a);
1428     actionListFiles.append(a);
1429     actionAddMapCenter = a;
1430
1431     // Shortcut to add branch
1432     a = new QAction(QPixmap(":/newbranch.png"),
1433                     tr("Add branch as child", "Edit menu"), this);
1434     switchboard.addSwitch("mapEditNewBranch", shortcutScope, a, tag);
1435     connect(a, SIGNAL(triggered()), this, SLOT(editNewBranch()));
1436     cloneActionMapEditor(a, Qt::Key_A);
1437     taskEditorActions.append(a);
1438     actionListBranches.append(a);
1439     actionAddBranch = a;
1440
1441     // Add branch by inserting it at selection
1442     a = new QAction(tr("Add branch (insert)", "Edit menu"), this);
1443     a->setShortcut(Qt::ALT + Qt::Key_A);
1444     a->setShortcutContext(Qt::WindowShortcut);
1445     switchboard.addSwitch("mapEditAddBranchBefore", shortcutScope, a, tag);
1446     connect(a, SIGNAL(triggered()), this, SLOT(editNewBranchBefore()));
1447     editMenu->addAction(a);
1448     actionListBranches.append(a);
1449     actionAddBranchBefore = a;
1450
1451     // Add branch above
1452     a = new QAction(tr("Add branch above", "Edit menu"), this);
1453     a->setShortcut(Qt::SHIFT + Qt::Key_Insert);
1454     a->setShortcutContext(Qt::WindowShortcut);
1455     switchboard.addSwitch("mapEditAddBranchAbove", shortcutScope, a, tag);
1456     addAction(a);
1457     connect(a, SIGNAL(triggered()), this, SLOT(editNewBranchAbove()));
1458     a->setEnabled(false);
1459     actionListBranches.append(a);
1460     actionAddBranchAbove = a;
1461
1462     a = new QAction(tr("Add branch above", "Edit menu"), this);
1463     a->setShortcut(Qt::SHIFT + Qt::Key_A);
1464     a->setShortcutContext(Qt::WindowShortcut);
1465     switchboard.addSwitch("mapEditAddBranchAboveAlt", shortcutScope, a, tag);
1466     addAction(a);
1467     connect(a, SIGNAL(triggered()), this, SLOT(editNewBranchAbove()));
1468     actionListBranches.append(a);
1469     editMenu->addAction(a);
1470
1471     // Add branch below
1472     a = new QAction(tr("Add branch below", "Edit menu"), this);
1473     a->setShortcut(Qt::CTRL + Qt::Key_Insert);
1474     a->setShortcutContext(Qt::WindowShortcut);
1475     switchboard.addSwitch("mapEditAddBranchBelow", shortcutScope, a, tag);
1476     addAction(a);
1477     connect(a, SIGNAL(triggered()), this, SLOT(editNewBranchBelow()));
1478     a->setEnabled(false);
1479     actionListBranches.append(a);
1480
1481     a = new QAction(tr("Add branch below", "Edit menu"), this);
1482     a->setShortcut(Qt::CTRL + Qt::Key_A);
1483     a->setShortcutContext(Qt::WindowShortcut);
1484     switchboard.addSwitch("mapEditAddBranchBelowAlt", shortcutScope, a, tag);
1485     addAction(a);
1486     connect(a, SIGNAL(triggered()), this, SLOT(editNewBranchBelow()));
1487     actionListBranches.append(a);
1488     actionAddBranchBelow = a;
1489
1490     a = new QAction(QPixmap(":/up.png"), tr("Move branch up", "Edit menu"),
1491                     this);
1492     a->setShortcut(Qt::Key_PageUp);
1493     a->setShortcutContext(Qt::WidgetShortcut);
1494     mapEditorActions.append(a);
1495     taskEditorActions.append(a);
1496     restrictedMapActions.append(a);
1497     actionListBranches.append(a);
1498     editMenu->addAction(a);
1499     switchboard.addSwitch("mapEditMoveBranchUp", shortcutScope, a, tag);
1500     connect(a, SIGNAL(triggered()), this, SLOT(editMoveUp()));
1501     actionMoveUp = a;
1502
1503     a = new QAction(QPixmap(":/down.png"), tr("Move branch down", "Edit menu"),
1504                     this);
1505     a->setShortcut(Qt::Key_PageDown);
1506     a->setShortcutContext(Qt::WidgetShortcut);
1507     mapEditorActions.append(a);
1508     taskEditorActions.append(a);
1509     restrictedMapActions.append(a);
1510     actionListBranches.append(a);
1511     editMenu->addAction(a);
1512     switchboard.addSwitch("mapEditMoveBranchDown", shortcutScope, a, tag);
1513     connect(a, SIGNAL(triggered()), this, SLOT(editMoveDown()));
1514     actionMoveDown = a;
1515
1516     a = new QAction(QPixmap(":up-diagonal-right.png"), tr("Move branch diagonally up", "Edit menu"),
1517                     this);
1518     a->setShortcut(Qt::CTRL + Qt::Key_PageUp);
1519     a->setShortcutContext(Qt::WidgetShortcut);
1520     mapEditorActions.append(a);
1521     taskEditorActions.append(a);
1522     restrictedMapActions.append(a);
1523     actionListBranches.append(a);
1524     editMenu->addAction(a);
1525     switchboard.addSwitch("mapEditMoveBranchUpDiagonally", shortcutScope, a, tag);
1526     connect(a, SIGNAL(triggered()), this, SLOT(editMoveUpDiagonally()));
1527     actionMoveUpDiagonally = a;
1528
1529     a = new QAction(QPixmap(":down-diagonal-left.png"), tr("Move branch diagonally down", "Edit menu"),
1530                     this);
1531     a->setShortcut(Qt::CTRL + Qt::Key_PageDown);
1532     a->setShortcutContext(Qt::WidgetShortcut);
1533     mapEditorActions.append(a);
1534     taskEditorActions.append(a);
1535     restrictedMapActions.append(a);
1536     actionListBranches.append(a);
1537     editMenu->addAction(a);
1538     switchboard.addSwitch("mapEditMoveBranchDownDiagonally", shortcutScope, a, tag);
1539     connect(a, SIGNAL(triggered()), this, SLOT(editMoveDownDiagonally()));
1540     actionMoveDownDiagonally = a;
1541
1542     a = new QAction(QPixmap(), tr("&Detach", "Context menu"), this);
1543     a->setStatusTip(tr("Detach branch and use as mapcenter", "Context menu"));
1544     a->setShortcut(Qt::Key_D + Qt::SHIFT);
1545     switchboard.addSwitch("mapDetachBranch", shortcutScope, a, tag);
1546     connect(a, SIGNAL(triggered()), this, SLOT(editDetach()));
1547     editMenu->addAction(a);
1548     actionListBranches.append(a);
1549     actionDetach = a;
1550
1551     a = new QAction(QPixmap(":/editsort.png"), tr("Sort children", "Edit menu"),
1552                     this);
1553     a->setEnabled(true);
1554     a->setShortcut(Qt::Key_O);
1555     switchboard.addSwitch("mapSortBranches", shortcutScope, a, tag);
1556     connect(a, SIGNAL(triggered()), this, SLOT(editSortChildren()));
1557     editMenu->addAction(a);
1558     actionListBranches.append(a);
1559     actionSortChildren = a;
1560
1561     a = new QAction(QPixmap(":/editsortback.png"),
1562                     tr("Sort children backwards", "Edit menu"), this);
1563     a->setEnabled(true);
1564     a->setShortcut(Qt::SHIFT + Qt::Key_O);
1565     switchboard.addSwitch("mapSortBranchesReverse", shortcutScope, a, tag);
1566     connect(a, SIGNAL(triggered()), this, SLOT(editSortBackChildren()));
1567     editMenu->addAction(a);
1568     actionListBranches.append(a);
1569     actionSortBackChildren = a;
1570
1571     a = new QAction(QPixmap(":/flag-scrolled-right.png"),
1572                     tr("Scroll branch", "Edit menu"), this);
1573     a->setShortcut(Qt::Key_S);
1574     switchboard.addSwitch("mapToggleScroll", shortcutScope, a, tag);
1575     connect(a, SIGNAL(triggered()), this, SLOT(editToggleScroll()));
1576     editMenu->addAction(a);
1577     actionListBranches.append(a);
1578     a->setEnabled(false);
1579     a->setCheckable(true);
1580     addAction(a);
1581     actionListBranches.append(a);
1582     actionToggleScroll = a;
1583
1584     a = new QAction(tr("Unscroll children", "Edit menu"), this);
1585     editMenu->addAction(a);
1586     connect(a, SIGNAL(triggered()), this, SLOT(editUnscrollChildren()));
1587     actionListBranches.append(a);
1588
1589     a = new QAction(tr("Grow selection", "Edit menu"), this);
1590     a->setShortcut(Qt::CTRL + Qt::Key_Plus);
1591     switchboard.addSwitch("mapGrowSelection", shortcutScope, a, tag);
1592     connect(a, SIGNAL(triggered()), this, SLOT(editGrowSelectionSize()));
1593     editMenu->addAction(a);
1594     actionListBranches.append(a);
1595     actionListItems.append(a);
1596     actionGrowSelectionSize = a;
1597
1598     a = new QAction(tr("Shrink selection", "Edit menu"), this);
1599     a->setShortcut(Qt::CTRL + Qt::Key_Minus);
1600     switchboard.addSwitch("mapShrinkSelection", shortcutScope, a, tag);
1601     connect(a, SIGNAL(triggered()), this, SLOT(editShrinkSelectionSize()));
1602     editMenu->addAction(a);
1603     actionListBranches.append(a);
1604     actionListItems.append(a);
1605     actionShrinkSelectionSize = a;
1606
1607     a = new QAction(tr("Reset selection size", "Edit menu"), this);
1608     a->setShortcut(Qt::CTRL + Qt::Key_0);
1609     switchboard.addSwitch("mapResetSelectionSize", shortcutScope, a, tag);
1610     connect(a, SIGNAL(triggered()), this, SLOT(editResetSelectionSize()));
1611     editMenu->addAction(a);
1612     actionListBranches.append(a);
1613     actionListItems.append(a);
1614     actionResetSelectionSize = a;
1615
1616     editMenu->addSeparator();
1617
1618     a = new QAction(QPixmap(), "TE: " + tr("Collapse one level", "Edit menu"),
1619                     this);
1620     a->setShortcut(Qt::Key_Less + Qt::CTRL);
1621     switchboard.addSwitch("mapCollapseOneLevel", shortcutScope, a, tag);
1622     connect(a, SIGNAL(triggered()), this, SLOT(editCollapseOneLevel()));
1623     editMenu->addAction(a);
1624     a->setEnabled(false);
1625     a->setCheckable(false);
1626     actionListBranches.append(a);
1627     addAction(a);
1628     actionCollapseOneLevel = a;
1629
1630     a = new QAction(QPixmap(),
1631                     "TE: " + tr("Collapse unselected levels", "Edit menu"),
1632                     this);
1633     a->setShortcut(Qt::Key_Less);
1634     switchboard.addSwitch("mapCollapseUnselectedLevels", shortcutScope, a, tag);
1635     connect(a, SIGNAL(triggered()), this, SLOT(editCollapseUnselected()));
1636     editMenu->addAction(a);
1637     a->setEnabled(false);
1638     a->setCheckable(false);
1639     actionListBranches.append(a);
1640     addAction(a);
1641     actionCollapseUnselected = a;
1642
1643     a = new QAction(QPixmap(), tr("Expand all branches", "Edit menu"), this);
1644     connect(a, SIGNAL(triggered()), this, SLOT(editExpandAll()));
1645     actionExpandAll = a;
1646     actionExpandAll->setEnabled(false);
1647     actionExpandAll->setCheckable(false);
1648     actionListBranches.append(actionExpandAll);
1649     addAction(a);
1650
1651     a = new QAction(QPixmap(), tr("Expand one level", "Edit menu"), this);
1652     a->setShortcut(Qt::Key_Greater);
1653     switchboard.addSwitch("mapExpandOneLevel", shortcutScope, a, tag);
1654     connect(a, SIGNAL(triggered()), this, SLOT(editExpandOneLevel()));
1655     a->setEnabled(false);
1656     a->setCheckable(false);
1657     addAction(a);
1658     actionListBranches.append(a);
1659     actionExpandOneLevel = a;
1660
1661     tag = tr("References Context menu", "Shortcuts");
1662     a = new QAction(QPixmap(":/flag-url.svg"), tr("Open URL", "Edit menu"),
1663                     this);
1664     a->setShortcut(Qt::SHIFT + Qt::Key_U);
1665     switchboard.addSwitch("mapOpenUrl", shortcutScope, a, tag);
1666     addAction(a);
1667     connect(a, SIGNAL(triggered()), this, SLOT(editOpenURL()));
1668     actionListBranches.append(a);
1669     actionOpenURL = a;
1670
1671     a = new QAction(tr("Open URL in new tab", "Edit menu"), this);
1672     // a->setShortcut (Qt::CTRL+Qt::Key_U );
1673     switchboard.addSwitch("mapOpenUrlTab", shortcutScope, a, tag);
1674     addAction(a);
1675     connect(a, SIGNAL(triggered()), this, SLOT(editOpenURLTab()));
1676     actionListBranches.append(a);
1677     actionOpenURLTab = a;
1678
1679     a = new QAction(tr("Open all URLs in subtree (including scrolled branches)",
1680                        "Edit menu"),
1681                     this);
1682     a->setShortcut(Qt::CTRL + Qt::Key_U);
1683     switchboard.addSwitch("mapOpenUrlsSubTree", shortcutScope, a, tag);
1684     addAction(a);
1685     connect(a, SIGNAL(triggered()), this, SLOT(editOpenMultipleVisURLTabs()));
1686     actionListBranches.append(a);
1687     actionOpenMultipleVisURLTabs = a;
1688
1689     a = new QAction(tr("Open all URLs in subtree", "Edit menu"), this);
1690     switchboard.addSwitch("mapOpenMultipleUrlTabs", shortcutScope, a, tag);
1691     addAction(a);
1692     connect(a, SIGNAL(triggered()), this, SLOT(editOpenMultipleURLTabs()));
1693     actionListBranches.append(a);
1694     actionOpenMultipleURLTabs = a;
1695
1696     a = new QAction(QPixmap(), tr("Extract URLs from note", "Edit menu"), this);
1697     a->setShortcut(Qt::SHIFT + Qt::Key_N);
1698     a->setShortcutContext(Qt::WindowShortcut);
1699     switchboard.addSwitch("mapUrlsFromNote", shortcutScope, a, tag);
1700     addAction(a);
1701     connect(a, SIGNAL(triggered()), this, SLOT(editNote2URLs()));
1702     actionListBranches.append(a);
1703     actionGetURLsFromNote = a;
1704
1705     a = new QAction(QPixmap(":/flag-urlnew.svg"),
1706                     tr("Edit URL...", "Edit menu"), this);
1707     a->setShortcut(Qt::Key_U);
1708     a->setShortcutContext(Qt::WindowShortcut);
1709     switchboard.addSwitch("mapEditURL", shortcutScope, a, tag);
1710     addAction(a);
1711     connect(a, SIGNAL(triggered()), this, SLOT(editURL()));
1712     actionListBranches.append(a);
1713     actionURLNew = a;
1714
1715     a = new QAction(QPixmap(), tr("Edit local URL...", "Edit menu"), this);
1716     // a->setShortcut (Qt::SHIFT +  Qt::Key_U );
1717     a->setShortcutContext(Qt::WindowShortcut);
1718     switchboard.addSwitch("mapEditLocalURL", shortcutScope, a, tag);
1719     addAction(a);
1720     connect(a, SIGNAL(triggered()), this, SLOT(editLocalURL()));
1721     actionListBranches.append(a);
1722     actionLocalURL = a;
1723
1724     a = new QAction(tr("Use heading for URL", "Edit menu"), this);
1725     a->setShortcut(Qt::ALT + Qt::Key_U);
1726     a->setShortcutContext(Qt::ApplicationShortcut);
1727     a->setEnabled(false);
1728     switchboard.addSwitch("mapHeading2URL", shortcutScope, a, tag);
1729     addAction(a);
1730     connect(a, SIGNAL(triggered()), this, SLOT(editHeading2URL()));
1731     actionListBranches.append(a);
1732     actionHeading2URL = a;
1733
1734     tag = "JIRA";
1735     a = new QAction(tr("Get data from JIRA for subtree", "Edit menu"),
1736                     this);
1737     a->setShortcut(Qt::Key_J + Qt::SHIFT);
1738     a->setShortcutContext(Qt::WindowShortcut);
1739     switchboard.addSwitch("mapUpdateSubTreeFromJira", shortcutScope, a, tag);
1740     addAction(a);
1741     connect(a, SIGNAL(triggered()), this, SLOT(getJiraDataSubtree()));
1742     actionGetJiraDataSubtree = a;
1743
1744     a = new QAction(tr("Get page name from Confluence", "Edit menu"),
1745                     this);
1746     //    a->setShortcut ( Qt::Key_J + Qt::CTRL);
1747     //    a->setShortcutContext (Qt::WindowShortcut);
1748     //    switchboard.addSwitch ("mapUpdateSubTreeFromJira", shortcutScope, a,
1749     //    tag);
1750     addAction(a);
1751     connect(a, SIGNAL(triggered()), this, SLOT(setHeadingConfluencePageName()));
1752     actionListBranches.append(a);
1753     actionGetConfluencePageName = a;
1754
1755     tag = tr("vymlinks - linking maps", "Shortcuts");
1756     a = new QAction(QPixmap(":/flag-vymlink.png"),
1757                     tr("Open linked map", "Edit menu"), this);
1758     a->setShortcut(Qt::SHIFT + Qt::Key_V);
1759     a->setEnabled(false);
1760     switchboard.addSwitch("mapOpenVymLink", shortcutScope, a, tag);
1761     addAction(a);
1762     connect(a, SIGNAL(triggered()), this, SLOT(editOpenVymLink()));
1763     actionListBranches.append(a);
1764     actionOpenVymLink = a;
1765
1766     a = new QAction(QPixmap(":/flag-vymlink.png"),
1767                     tr("Open linked map in background tab", "Edit menu"), this);
1768     a->setEnabled(false);
1769     switchboard.addSwitch("mapOpenVymLink", shortcutScope, a, tag);
1770     connect(a, SIGNAL(triggered()), this, SLOT(editOpenVymLinkBackground()));
1771     actionListBranches.append(a);
1772     actionOpenVymLinkBackground = a;
1773
1774     a = new QAction(QPixmap(), tr("Open all vym links in subtree", "Edit menu"),
1775                     this);
1776     a->setEnabled(false);
1777     switchboard.addSwitch("mapOpenMultipleVymLinks", shortcutScope, a, tag);
1778     connect(a, SIGNAL(triggered()), this, SLOT(editOpenMultipleVymLinks()));
1779     actionListBranches.append(a);
1780     actionOpenMultipleVymLinks = a;
1781
1782     a = new QAction(QPixmap(":/flag-vymlinknew.png"),
1783                     tr("Edit vym link...", "Edit menu"), this);
1784     a->setShortcut(Qt::Key_V);
1785     a->setShortcutContext(Qt::WindowShortcut);
1786     a->setEnabled(false);
1787     switchboard.addSwitch("mapEditVymLink", shortcutScope, a, tag);
1788     connect(a, SIGNAL(triggered()), this, SLOT(editVymLink()));
1789     actionListBranches.append(a);
1790     actionEditVymLink = a;
1791
1792     a = new QAction(tr("Delete vym link", "Edit menu"), this);
1793     a->setEnabled(false);
1794     switchboard.addSwitch("mapDeleteVymLink", shortcutScope, a, tag);
1795     connect(a, SIGNAL(triggered()), this, SLOT(editDeleteVymLink()));
1796     actionListBranches.append(a);
1797     actionDeleteVymLink = a;
1798
1799     tag = tr("Exports", "Shortcuts");
1800     a = new QAction(QPixmap(":/flag-hideexport.png"),
1801                     tr("Hide in exports", "Edit menu"), this);
1802     a->setShortcut(Qt::Key_H);
1803     a->setShortcutContext(Qt::WindowShortcut);
1804     a->setCheckable(true);
1805     a->setEnabled(false);
1806     addAction(a);
1807     switchboard.addSwitch("mapToggleHideExport", shortcutScope, a, tag);
1808     connect(a, SIGNAL(triggered()), this, SLOT(editToggleHideExport()));
1809     actionListItems.append(a);
1810     actionToggleHideExport = a;
1811
1812     tag = tr("Tasks", "Shortcuts");
1813     a = new QAction(QPixmap(":/taskeditor.png"), tr("Toggle task", "Edit menu"),
1814                     this);
1815     a->setShortcut(Qt::Key_W + Qt::SHIFT);
1816     a->setShortcutContext(Qt::WindowShortcut);
1817     a->setCheckable(true);
1818     a->setEnabled(false);
1819     addAction(a);
1820     switchboard.addSwitch("mapToggleTask", shortcutScope, a, tag);
1821     connect(a, SIGNAL(triggered()), this, SLOT(editToggleTask()));
1822     actionListBranches.append(a);
1823     actionToggleTask = a;
1824
1825     a = new QAction(QPixmap(), tr("Cycle task status", "Edit menu"), this);
1826     a->setShortcut(Qt::Key_W);
1827     a->setShortcutContext(Qt::WindowShortcut);
1828     a->setCheckable(false);
1829     a->setEnabled(false);
1830     addAction(a);
1831     switchboard.addSwitch("mapCycleTaskStatus", shortcutScope, a, tag);
1832     connect(a, SIGNAL(triggered()), this, SLOT(editCycleTaskStatus()));
1833     actionListBranches.append(a);
1834     actionCycleTaskStatus = a;
1835
1836     a = new QAction(QPixmap(), tr("Reset delta priority for visible tasks", "Reset delta"), this);
1837     a->setShortcutContext(Qt::WindowShortcut);
1838     a->setCheckable(false);
1839     a->setEnabled(false);
1840     addAction(a);
1841     switchboard.addSwitch("mapResetTaskDeltaPrio", shortcutScope, a, tag);
1842     connect(a, SIGNAL(triggered()), this, SLOT(editTaskResetDeltaPrio()));
1843     actionListBranches.append(a);
1844     actionTaskResetDeltaPrio = a;
1845
1846     a = new QAction(QPixmap(), tr("Reset sleep", "Task sleep"), this);
1847     a->setShortcutContext(Qt::WindowShortcut);
1848     a->setCheckable(false);
1849     a->setEnabled(false);
1850     a->setData(0);
1851     addAction(a);
1852     switchboard.addSwitch("mapResetSleep", shortcutScope, a, tag);
1853     connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
1854     actionListBranches.append(a);
1855     actionTaskSleep0 = a;
1856
1857     a = new QAction(QPixmap(),
1858                     tr("Sleep %1 days", "Task sleep").arg("n") + "...", this);
1859     a->setShortcutContext(Qt::WindowShortcut);
1860     a->setShortcut(Qt::Key_Q + Qt::SHIFT);
1861     a->setCheckable(false);
1862     a->setEnabled(false);
1863     a->setData(-1);
1864     addAction(a);
1865     switchboard.addSwitch("mapTaskSleepN", shortcutScope, a, tag);
1866     connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
1867     actionListBranches.append(a);
1868     actionTaskSleepN = a;
1869
1870     a = new QAction(QPixmap(), tr("Sleep %1 day", "Task sleep").arg(1), this);
1871     a->setShortcutContext(Qt::WindowShortcut);
1872     a->setCheckable(false);
1873     a->setEnabled(false);
1874     a->setData(1);
1875     addAction(a);
1876     switchboard.addSwitch("mapTaskSleep1", shortcutScope, a, tag);
1877     connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
1878     actionListBranches.append(a);
1879     actionTaskSleep1 = a;
1880
1881     a = new QAction(QPixmap(), tr("Sleep %1 days", "Task sleep").arg(2), this);
1882     a->setShortcutContext(Qt::WindowShortcut);
1883     a->setCheckable(false);
1884     a->setEnabled(false);
1885     a->setData(2);
1886     addAction(a);
1887     switchboard.addSwitch("mapTaskSleep2", shortcutScope, a, tag);
1888     connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
1889     actionListBranches.append(a);
1890     actionTaskSleep2 = a;
1891
1892     a = new QAction(QPixmap(), tr("Sleep %1 days", "Task sleep").arg(3), this);
1893     a->setShortcutContext(Qt::WindowShortcut);
1894     a->setCheckable(false);
1895     a->setEnabled(false);
1896     a->setData(3);
1897     addAction(a);
1898     switchboard.addSwitch("mapTaskSleep3", shortcutScope, a, tag);
1899     connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
1900     actionListBranches.append(a);
1901     actionTaskSleep3 = a;
1902
1903     a = new QAction(QPixmap(), tr("Sleep %1 days", "Task sleep").arg(4), this);
1904     a->setShortcutContext(Qt::WindowShortcut);
1905     a->setCheckable(false);
1906     a->setEnabled(false);
1907     a->setData(4);
1908     addAction(a);
1909     switchboard.addSwitch("mapTaskSleep4", shortcutScope, a, tag);
1910     connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
1911     actionListBranches.append(a);
1912     actionTaskSleep4 = a;
1913
1914     a = new QAction(QPixmap(), tr("Sleep %1 days", "Task sleep").arg(5), this);
1915     a->setShortcutContext(Qt::WindowShortcut);
1916     a->setCheckable(false);
1917     a->setEnabled(false);
1918     a->setData(5);
1919     addAction(a);
1920     switchboard.addSwitch("mapTaskSleep5", shortcutScope, a, tag);
1921     connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
1922     actionListBranches.append(a);
1923     actionTaskSleep5 = a;
1924
1925     a = new QAction(QPixmap(), tr("Sleep %1 days", "Task sleep").arg(7), this);
1926     a->setShortcutContext(Qt::WindowShortcut);
1927     a->setCheckable(false);
1928     a->setEnabled(false);
1929     a->setData(7);
1930     addAction(a);
1931     switchboard.addSwitch("mapTaskSleep7", shortcutScope, a, tag);
1932     connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
1933     actionListBranches.append(a);
1934     actionTaskSleep7 = a;
1935
1936     a = new QAction(QPixmap(), tr("Sleep %1 weeks", "Task sleep").arg(2), this);
1937     a->setShortcutContext(Qt::WindowShortcut);
1938     a->setCheckable(false);
1939     a->setEnabled(false);
1940     a->setData(14);
1941     addAction(a);
1942     switchboard.addSwitch("mapTaskSleep14", shortcutScope, a, tag);
1943     connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
1944     actionListBranches.append(a);
1945     actionTaskSleep14 = a;
1946
1947     a = new QAction(QPixmap(), tr("Sleep %1 weeks", "Task sleep").arg(4), this);
1948     a->setShortcutContext(Qt::WindowShortcut);
1949     a->setCheckable(false);
1950     a->setEnabled(false);
1951     a->setData(28);
1952     addAction(a);
1953     switchboard.addSwitch("mapTaskSleep28", shortcutScope, a, tag);
1954     connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
1955     actionListBranches.append(a);
1956     actionTaskSleep28 = a;
1957
1958     // Import at selection (adding to selection)
1959     a = new QAction(tr("Add map (insert)", "Edit menu"), this);
1960     connect(a, SIGNAL(triggered()), this, SLOT(editImportAdd()));
1961     a->setEnabled(false);
1962     actionListBranches.append(a);
1963     actionImportAdd = a;
1964
1965     // Import at selection (replacing selection)
1966     a = new QAction(tr("Add map (replace)", "Edit menu"), this);
1967     connect(a, SIGNAL(triggered()), this, SLOT(editImportReplace()));
1968     a->setEnabled(false);
1969     actionListBranches.append(a);
1970     actionImportReplace = a;
1971
1972     // Save selection
1973     a = new QAction(tr("Save selection", "Edit menu"), this);
1974     connect(a, SIGNAL(triggered()), this, SLOT(editSaveBranch()));
1975     a->setEnabled(false);
1976     actionListBranches.append(a);
1977     actionSaveBranch = a;
1978
1979     tag = tr("Removing parts of a map", "Shortcuts");
1980
1981     // Only remove branch, not its children
1982     a = new QAction(
1983         tr("Remove only branch and keep its children ", "Edit menu"), this);
1984     a->setShortcut(Qt::ALT + Qt::Key_X);
1985     connect(a, SIGNAL(triggered()), this, SLOT(editDeleteKeepChildren()));
1986     a->setEnabled(false);
1987     addAction(a);
1988     switchboard.addSwitch("mapDeleteKeepChildren", shortcutScope, a, tag);
1989     actionListBranches.append(a);
1990     actionDeleteKeepChildren = a;
1991
1992     // Only remove children of a branch
1993     a = new QAction(tr("Remove children", "Edit menu"), this);
1994     a->setShortcut(Qt::SHIFT + Qt::Key_X);
1995     addAction(a);
1996     switchboard.addSwitch("mapDeleteChildren", shortcutScope, a, tag);
1997     connect(a, SIGNAL(triggered()), this, SLOT(editDeleteChildren()));
1998     a->setEnabled(false);
1999     addAction(a);
2000     actionListBranches.append(a);
2001     actionDeleteChildren = a;
2002
2003     tag = tr("Various", "Shortcuts");
2004     a = new QAction(tr("Add timestamp", "Edit menu"), this);
2005     a->setEnabled(false);
2006     actionListBranches.append(a);
2007     a->setShortcut(Qt::Key_T);
2008     a->setShortcutContext(Qt::WindowShortcut);
2009     addAction(a);
2010     switchboard.addSwitch("mapAddTimestamp", shortcutScope, a, tag);
2011     connect(a, SIGNAL(triggered()), this, SLOT(editAddTimestamp()));
2012     actionListBranches.append(a);
2013     actionAddTimestamp = a;
2014
2015     a = new QAction(tr("Map properties...", "Edit menu"), this);
2016     a->setEnabled(true);
2017     connect(a, SIGNAL(triggered()), this, SLOT(editMapProperties()));
2018     actionListFiles.append(a);
2019     actionMapInfo = a;
2020
2021     a = new QAction(tr("Add image...", "Edit menu"), this);
2022     a->setShortcutContext(Qt::WindowShortcut);
2023     a->setShortcut(Qt::Key_I + Qt::SHIFT);
2024     addAction(a);
2025     switchboard.addSwitch("mapLoadImage", shortcutScope, a, tag);
2026     connect(a, SIGNAL(triggered()), this, SLOT(editLoadImage()));
2027     actionLoadImage = a;
2028
2029     a = new QAction(
2030         tr("Property window", "Dialog to edit properties of selection") +
2031             QString("..."),
2032         this);
2033     a->setShortcut(Qt::Key_P);
2034     a->setShortcutContext(Qt::WindowShortcut);
2035     a->setCheckable(true);
2036     addAction(a);
2037     switchboard.addSwitch("mapTogglePropertEditor", shortcutScope, a, tag);
2038     connect(a, SIGNAL(triggered()), this, SLOT(windowToggleProperty()));
2039     actionViewTogglePropertyEditor = a;
2040 }
2041
2042 // Select Actions
2043 void Main::setupSelectActions()
2044 {
2045     QString tag = tr("Selections", "Shortcuts");
2046     QMenu *selectMenu = menuBar()->addMenu(tr("Select", "Select menu"));
2047     QAction *a;
2048     a = new QAction(QPixmap(":/flag-target.svg"),
2049                     tr("Toggle target...", "Edit menu"), this);
2050     a->setShortcut(Qt::SHIFT + Qt::Key_T);
2051     a->setCheckable(true);
2052     selectMenu->addAction(a);
2053     switchboard.addSwitch("mapToggleTarget", shortcutScope, a, tag);
2054     connect(a, SIGNAL(triggered()), this, SLOT(editToggleTarget()));
2055     actionListBranches.append(a);
2056     actionToggleTarget = a;
2057
2058     a = new QAction(QPixmap(":/flag-target.svg"),
2059                     tr("Goto target...", "Edit menu"), this);
2060     a->setShortcut(Qt::Key_G);
2061     selectMenu->addAction(a);
2062     switchboard.addSwitch("mapGotoTarget", shortcutScope, a, tag);
2063     connect(a, SIGNAL(triggered()), this, SLOT(editGoToTarget()));
2064     actionListBranches.append(a);
2065     actionGoToTarget = a;
2066
2067     a = new QAction(QPixmap(":/flag-target.svg"),
2068                     tr("Move to target...", "Edit menu"), this);
2069     a->setShortcut(Qt::Key_M);
2070     selectMenu->addAction(a);
2071     switchboard.addSwitch("mapMoveToTarget", shortcutScope, a, tag);
2072     connect(a, SIGNAL(triggered()), this, SLOT(editMoveToTarget()));
2073     actionListBranches.append(a);
2074     actionMoveToTarget = a;
2075
2076     a = new QAction(QPixmap(":/flag-vymlink.png"),
2077                     tr("Goto linked map...", "Edit menu"), this);
2078     a->setShortcut(Qt::Key_G + Qt::SHIFT);
2079     selectMenu->addAction(a);
2080     switchboard.addSwitch("gotoLinkedMap", shortcutScope, a, tag);
2081     connect(a, SIGNAL(triggered()), this, SLOT(editGoToLinkedMap()));
2082     actionListBranches.append(a);
2083     actionGoToTargetLinkedMap = a;
2084
2085     a = new QAction(QPixmap(":/selectprevious.png"),
2086                     tr("Select previous", "Edit menu"), this);
2087     a->setShortcut(Qt::CTRL + Qt::Key_O);
2088     a->setShortcutContext(Qt::WidgetShortcut);
2089     selectMenu->addAction(a);
2090     actionListFiles.append(a);
2091     mapEditorActions.append(a);
2092     switchboard.addSwitch("mapSelectPrevious", shortcutScope, a, tag);
2093     connect(a, SIGNAL(triggered()), this, SLOT(editSelectPrevious()));
2094     actionSelectPrevious = a;
2095
2096     a = new QAction(QPixmap(":/selectnext.png"), tr("Select next", "Edit menu"),
2097                     this);
2098     a->setShortcut(Qt::CTRL + Qt::Key_I);
2099     a->setShortcutContext(Qt::WidgetShortcut);
2100     selectMenu->addAction(a);
2101     actionListFiles.append(a);
2102     mapEditorActions.append(a);
2103     switchboard.addSwitch("mapSelectNext", shortcutScope, a, tag);
2104     connect(a, SIGNAL(triggered()), this, SLOT(editSelectNext()));
2105     actionSelectNext = a;
2106
2107     a = new QAction(tr("Unselect all", "Edit menu"), this);
2108     // a->setShortcut (Qt::CTRL + Qt::Key_I );
2109     selectMenu->addAction(a);
2110     switchboard.addSwitch("mapSelectNothing", shortcutScope, a, tag);
2111     connect(a, SIGNAL(triggered()), this, SLOT(editSelectNothing()));
2112     actionListFiles.append(a);
2113     actionSelectNothing = a;
2114
2115     tag = tr("Search functions", "Shortcuts");
2116     a = new QAction(QPixmap(":/find.png"), tr("Find...", "Edit menu"), this);
2117     a->setShortcut(Qt::CTRL + Qt::Key_F);
2118     selectMenu->addAction(a);
2119     switchboard.addSwitch("mapFind", shortcutScope, a, tag);
2120     connect(a, SIGNAL(triggered()), this, SLOT(editOpenFindResultWidget()));
2121     actionListFiles.append(a);
2122     actionFind = a;
2123
2124     a = new QAction(QPixmap(":/find.png"), tr("Find...", "Edit menu"), this);
2125     a->setShortcut(Qt::Key_Slash);
2126     selectMenu->addAction(a);
2127     switchboard.addSwitch("mapFindAlt", shortcutScope, a, tag);
2128     connect(a, SIGNAL(triggered()), this, SLOT(editOpenFindResultWidget()));
2129     actionListFiles.append(a);
2130
2131     a = new QAction(tr("Find duplicate URLs", "Edit menu") + " (test)", this);
2132     a->setShortcut(Qt::SHIFT + Qt::Key_F);
2133     switchboard.addSwitch("mapFindDuplicates", shortcutScope, a, tag);
2134     if (settings.value("/mainwindow/showTestMenu", false).toBool())
2135         selectMenu->addAction(a);
2136     connect(a, SIGNAL(triggered()), this, SLOT(editFindDuplicateURLs()));
2137 }
2138
2139 // Format Actions
2140 void Main::setupFormatActions()
2141 {
2142     QMenu *formatMenu = menuBar()->addMenu(tr("F&ormat", "Format menu"));
2143
2144     QString tag = tr("Formatting", "Shortcuts");
2145
2146     QAction* a;
2147
2148     a = new QAction(QPixmap(":/formatcolorpicker.png"),
2149                     tr("Pic&k color", "Edit menu"), this);
2150     // a->setShortcut (Qt::CTRL + Qt::Key_K );
2151     formatMenu->addAction(a);
2152     switchboard.addSwitch("mapFormatColorPicker", shortcutScope, a, tag);
2153     connect(a, SIGNAL(triggered()), this, SLOT(formatPickColor()));
2154     a->setEnabled(false);
2155     actionListBranches.append(a);
2156     actionFormatPickColor = a;
2157
2158     a = new QAction(QPixmap(":/formatcolorbranch.png"),
2159                     tr("Color &branch", "Edit menu"), this);
2160     // a->setShortcut (Qt::CTRL + Qt::Key_B + Qt::SHIFT);
2161     formatMenu->addAction(a);
2162     switchboard.addSwitch("mapFormatColorBranch", shortcutScope, a, tag);
2163     connect(a, SIGNAL(triggered()), this, SLOT(formatColorBranch()));
2164     a->setEnabled(false);
2165     actionListBranches.append(a);
2166     actionFormatColorBranch = a;
2167
2168     a = new QAction(QPixmap(":/formatcolorsubtree.png"),
2169                     tr("Color sub&tree", "Edit menu"), this);
2170     // a->setShortcut (Qt::CTRL + Qt::Key_B);   // Color subtree
2171     formatMenu->addAction(a);
2172     switchboard.addSwitch("mapFormatColorSubtree", shortcutScope, a, tag);
2173     connect(a, SIGNAL(triggered()), this, SLOT(formatColorSubtree()));
2174     a->setEnabled(false);
2175     actionListBranches.append(a);
2176     actionFormatColorSubtree = a;
2177
2178     formatMenu->addSeparator();
2179
2180     a = new QAction(tr("Select default font", "Branch attribute") + "...",
2181                     this);
2182     a->setCheckable(false);
2183     connect(a, SIGNAL(triggered()), this, SLOT(formatSelectFont()));
2184     formatMenu->addAction(a);
2185     actionFormatFont = a;
2186
2187     formatMenu->addSeparator();
2188
2189     actionGroupFormatLinkStyles = new QActionGroup(this);
2190     actionGroupFormatLinkStyles->setExclusive(true);
2191     a = new QAction(tr("Linkstyle Line"), actionGroupFormatLinkStyles);
2192     a->setCheckable(true);
2193     restrictedMapActions.append(a);
2194     formatMenu->addAction(a);
2195     connect(a, SIGNAL(triggered()), this, SLOT(formatLinkStyleLine()));
2196     actionFormatLinkStyleLine = a;
2197
2198     a = new QAction(tr("Linkstyle Curve"), actionGroupFormatLinkStyles);
2199     a->setCheckable(true);
2200     restrictedMapActions.append(a);
2201     formatMenu->addAction(a);
2202     connect(a, SIGNAL(triggered()), this, SLOT(formatLinkStyleParabel()));
2203     actionFormatLinkStyleParabel = a;
2204
2205     a = new QAction(tr("Linkstyle Thick Line"), actionGroupFormatLinkStyles);
2206     a->setCheckable(true);
2207     restrictedMapActions.append(a);
2208     formatMenu->addAction(a);
2209     connect(a, SIGNAL(triggered()), this, SLOT(formatLinkStylePolyLine()));
2210     actionFormatLinkStylePolyLine = a;
2211
2212     a = new QAction(tr("Linkstyle Thick Curve"), actionGroupFormatLinkStyles);
2213     a->setCheckable(true);
2214     a->setChecked(true);
2215     restrictedMapActions.append(a);
2216     formatMenu->addAction(a);
2217     formatMenu->addSeparator();
2218     connect(a, SIGNAL(triggered()), this, SLOT(formatLinkStylePolyParabel()));
2219     actionFormatLinkStylePolyParabel = a;
2220
2221     a = new QAction(
2222         tr("Hide link if object is not selected", "Branch attribute"), this);
2223     a->setCheckable(true);
2224     connect(a, SIGNAL(triggered()), this, SLOT(formatHideLinkUnselected()));
2225     actionListBranches.append(a);
2226     actionFormatHideLinkUnselected = a;
2227
2228     a = new QAction(tr("&Use color of heading for link", "Branch attribute"),
2229                     this);
2230     a->setCheckable(true);
2231     connect(a, SIGNAL(triggered()), this, SLOT(formatToggleLinkColorHint()));
2232     formatMenu->addAction(a);
2233     actionFormatLinkColorHint = a;
2234
2235     QPixmap pix(16, 16);
2236     pix.fill(Qt::white);
2237     a = new QAction(pix, tr("Set &Link Color") + "...", this);
2238     formatMenu->addAction(a);
2239     connect(a, SIGNAL(triggered()), this, SLOT(formatSelectLinkColor()));
2240     actionFormatLinkColor = a;
2241
2242     a = new QAction(pix, tr("Set &Selection Color") + "...", this);
2243     formatMenu->addAction(a);
2244     connect(a, SIGNAL(triggered()), this, SLOT(formatSelectSelectionColor()));
2245     actionFormatSelectionColor = a;
2246
2247     a = new QAction(pix, tr("Set &Background Color") + "...", this);
2248     formatMenu->addAction(a);
2249     connect(a, SIGNAL(triggered()), this, SLOT(formatSelectBackColor()));
2250     actionFormatBackColor = a;
2251
2252     a = new QAction(pix, tr("Set &Background image") + "...", this);
2253     formatMenu->addAction(a);
2254     connect(a, SIGNAL(triggered()), this, SLOT(formatSelectBackImage()));
2255     actionFormatBackImage = a;
2256 }
2257
2258 // View Actions
2259 void Main::setupViewActions()
2260 {
2261     QMenu *viewMenu = menuBar()->addMenu(tr("&View"));
2262     toolbarsMenu =
2263         viewMenu->addMenu(tr("Toolbars", "Toolbars overview in view menu"));
2264     QString tag = tr("Views", "Shortcuts");
2265
2266     viewMenu->addSeparator();
2267
2268     QAction *a;
2269
2270     a = new QAction(QPixmap(":view-video-projector.png"), 
2271             tr("Toggle Presentation mode", "View action") + " " +
2272             tr("(still experimental)"),
2273             this);
2274     // a->setShortcut(Qt::Key_Plus);
2275     viewMenu->addAction(a);
2276     switchboard.addSwitch ("presentationMode", shortcutScope, a, tag);
2277     connect(a, SIGNAL(triggered()), this, SLOT(togglePresentationMode()));
2278     actionTogglePresentationMode = a;
2279
2280     a = new QAction(QPixmap(":/viewmag+.png"), tr("Zoom in", "View action"),
2281                     this);
2282     a->setShortcut(Qt::Key_Plus);
2283     viewMenu->addAction(a);
2284     switchboard.addSwitch("mapZoomIn", shortcutScope, a, tag);
2285     connect(a, SIGNAL(triggered()), this, SLOT(viewZoomIn()));
2286     actionZoomIn = a;
2287
2288     a = new QAction(QPixmap(":/viewmag-.png"), tr("Zoom out", "View action"),
2289                     this);
2290     a->setShortcut(Qt::Key_Minus);
2291     viewMenu->addAction(a);
2292     switchboard.addSwitch("mapZoomOut", shortcutScope, a, tag);
2293     connect(a, SIGNAL(triggered()), this, SLOT(viewZoomOut()));
2294     actionZoomOut = a;
2295
2296     a = new QAction(QPixmap(":/transform-rotate-ccw.svg"),
2297                     tr("Rotate counterclockwise", "View action"), this);
2298     a->setShortcut(Qt::SHIFT + Qt::Key_R);
2299     viewMenu->addAction(a);
2300     switchboard.addSwitch("mapRotateCounterClockwise", shortcutScope, a, tag);
2301     connect(a, SIGNAL(triggered()), this, SLOT(viewRotateCounterClockwise()));
2302     actionRotateCounterClockwise = a;
2303
2304     a = new QAction(QPixmap(":/transform-rotate-cw.svg"),
2305                     tr("Rotate rclockwise", "View action"), this);
2306     a->setShortcut(Qt::Key_R);
2307     viewMenu->addAction(a);
2308     switchboard.addSwitch("mapRotateClockwise", shortcutScope, a, tag);
2309     connect(a, SIGNAL(triggered()), this, SLOT(viewRotateClockwise()));
2310     actionRotateClockwise = a;
2311
2312     a = new QAction(QPixmap(":/viewmag-reset.png"),
2313                     tr("reset Zoom", "View action"), this);
2314     a->setShortcut(Qt::Key_Comma);
2315     switchboard.addSwitch("mapZoomReset", shortcutScope, a, tag);
2316     viewMenu->addAction(a);
2317     connect(a, SIGNAL(triggered()), this, SLOT(viewZoomReset()));
2318     actionZoomReset = a;
2319
2320     a = new QAction(QPixmap(":/viewshowsel.png"),
2321                     tr("Center on selection", "View action"), this);
2322     a->setShortcut(Qt::Key_Period);
2323     viewMenu->addAction(a);
2324     switchboard.addSwitch("mapCenterOn", shortcutScope, a, tag);
2325     connect(a, SIGNAL(triggered()), this, SLOT(viewCenter()));
2326     actionCenterOn = a;
2327
2328     a = new QAction(QPixmap(),
2329                     tr("Fit view to selection", "View action"), this);
2330     a->setShortcut(Qt::Key_Period + Qt::SHIFT);
2331     viewMenu->addAction(a);
2332     switchboard.addSwitch("mapCenterAndFitView", shortcutScope, a, tag);
2333     connect(a, SIGNAL(triggered()), this, SLOT(viewCenterScaled()));
2334     actionFitToSelection = a;
2335
2336     viewMenu->addSeparator();
2337
2338     // a=noteEditorDW->toggleViewAction();
2339     a = new QAction(QPixmap(":/flag-note.svg"),
2340                     tr("Note editor", "View action"), this);
2341     a->setShortcut(Qt::Key_N);
2342     a->setShortcutContext(Qt::WidgetShortcut);
2343     a->setCheckable(true);
2344     viewMenu->addAction(a);
2345     mapEditorActions.append(a);
2346     switchboard.addSwitch("mapToggleNoteEditor", shortcutScope, a, tag);
2347     connect(a, SIGNAL(triggered()), this, SLOT(windowToggleNoteEditor()));
2348     actionViewToggleNoteEditor = a;
2349
2350     // a=headingEditorDW->toggleViewAction();
2351     a = new QAction(QPixmap(":/headingeditor.png"),
2352                     tr("Heading editor", "View action"), this);
2353     a->setCheckable(true);
2354     a->setIcon(QPixmap(":/headingeditor.png"));
2355     a->setShortcut(Qt::Key_E);
2356     a->setShortcutContext(Qt::WidgetShortcut);
2357     mapEditorActions.append(a);
2358     viewMenu->addAction(a);
2359     switchboard.addSwitch("mapToggleHeadingEditor", shortcutScope, a, tag);
2360     connect(a, SIGNAL(triggered()), this, SLOT(windowToggleHeadingEditor()));
2361     actionViewToggleHeadingEditor = a;
2362
2363     // Original icon is "category" from KDE
2364     a = new QAction(QPixmap(":/treeeditor.png"),
2365                     tr("Tree editor", "View action"), this);
2366     a->setShortcut(Qt::CTRL + Qt::Key_T);
2367     a->setCheckable(true);
2368     viewMenu->addAction(a);
2369     switchboard.addSwitch("mapToggleTreeEditor", shortcutScope, a, tag);
2370     connect(a, SIGNAL(triggered()), this, SLOT(windowToggleTreeEditor()));
2371     actionViewToggleTreeEditor = a;
2372
2373     a = new QAction(QPixmap(":/taskeditor.png"),
2374                     tr("Task editor", "View action"), this);
2375     a->setCheckable(true);
2376     a->setShortcut(Qt::Key_Q);
2377     a->setShortcutContext(Qt::WidgetShortcut);
2378     mapEditorActions.append(a);
2379     viewMenu->addAction(a);
2380     switchboard.addSwitch("mapToggleTaskEditor", shortcutScope, a, tag);
2381     connect(a, SIGNAL(triggered()), this, SLOT(windowToggleTaskEditor()));
2382     actionViewToggleTaskEditor = a;
2383
2384     a = new QAction(QPixmap(":/slideeditor.png"),
2385                     tr("Slide editor", "View action"), this);
2386     a->setShortcut(Qt::SHIFT + Qt::Key_S);
2387     a->setCheckable(true);
2388     viewMenu->addAction(a);
2389     switchboard.addSwitch("mapToggleSlideEditor", shortcutScope, a, tag);
2390     connect(a, SIGNAL(triggered()), this, SLOT(windowToggleSlideEditor()));
2391     actionViewToggleSlideEditor = a;
2392
2393     a = new QAction(QPixmap(":/scripteditor.png"),
2394                     tr("Script editor", "View action"), this);
2395     a->setShortcut(Qt::ALT + Qt::Key_S);
2396     a->setCheckable(true);
2397     viewMenu->addAction(a);
2398     switchboard.addSwitch("mapToggleScriptEditor", shortcutScope, a, tag);
2399     connect(a, SIGNAL(triggered()), this, SLOT(windowToggleScriptEditor()));
2400     actionViewToggleScriptEditor = a;
2401
2402     a = new QAction(QPixmap(), tr("Script output window", "View action"), this);
2403     a->setShortcut(Qt::ALT + Qt::SHIFT + Qt::Key_S);
2404     a->setCheckable(true);
2405     viewMenu->addAction(a);
2406     switchboard.addSwitch("mapToggleScriptOutput", shortcutScope, a, tag);
2407     connect(a, SIGNAL(triggered()), this, SLOT(windowToggleScriptOutput()));
2408     actionViewToggleScriptOutput = a;
2409
2410     a = new QAction(QPixmap(":/history.png"),
2411                     tr("History Window", "View action"), this);
2412     a->setShortcut(Qt::CTRL + Qt::Key_H);
2413     a->setShortcutContext(Qt::WidgetShortcut);
2414     a->setCheckable(true);
2415     viewMenu->addAction(a);
2416     mapEditorActions.append(a);
2417     switchboard.addSwitch("mapToggleHistoryWindow", shortcutScope, a, tag);
2418     connect(a, SIGNAL(triggered()), this, SLOT(windowToggleHistory()));
2419     actionViewToggleHistoryWindow = a;
2420
2421     viewMenu->addAction(actionViewTogglePropertyEditor);
2422
2423     viewMenu->addSeparator();
2424
2425     a = new QAction(tr("Antialiasing", "View action"), this);
2426     a->setCheckable(true);
2427     a->setChecked(settings.value("/mainwindow/view/AntiAlias", true).toBool());
2428     viewMenu->addAction(a);
2429     connect(a, SIGNAL(triggered()), this, SLOT(windowToggleAntiAlias()));
2430     actionViewToggleAntiAlias = a;
2431
2432     a = new QAction(tr("Smooth pixmap transformations", "View action"), this);
2433     a->setStatusTip(a->text());
2434     a->setCheckable(true);
2435     a->setChecked(
2436         settings.value("/mainwindow/view/SmoothPixmapTransformation", true)
2437             .toBool());
2438     viewMenu->addAction(a);
2439     connect(a, SIGNAL(triggered()), this, SLOT(windowToggleSmoothPixmap()));
2440     actionViewToggleSmoothPixmapTransform = a;
2441
2442     a = new QAction(tr("Next Map", "View action"), this);
2443     a->setStatusTip(a->text());
2444     a->setShortcut(Qt::SHIFT + Qt::Key_Right);
2445     viewMenu->addAction(a);
2446     switchboard.addSwitch("mapPrevious", shortcutScope, a, tag);
2447     connect(a, SIGNAL(triggered()), this, SLOT(windowNextEditor()));
2448
2449     a = new QAction(tr("Previous Map", "View action"), this);
2450     a->setStatusTip(a->text());
2451     a->setShortcut(Qt::SHIFT + Qt::Key_Left);
2452     viewMenu->addAction(a);
2453     switchboard.addSwitch("mapNext", shortcutScope, a, tag);
2454     connect(a, SIGNAL(triggered()), this, SLOT(windowPreviousEditor()));
2455
2456     a = new QAction(tr("Next slide", "View action"), this);
2457     a->setStatusTip(a->text());
2458     a->setShortcut(Qt::Key_Space);
2459     viewMenu->addAction(a);
2460     switchboard.addSwitch("mapNextSlide", shortcutScope, a, tag);
2461     connect(a, SIGNAL(triggered()), this, SLOT(nextSlide()));
2462
2463     a = new QAction(tr("Previous slide", "View action"), this);
2464     a->setStatusTip(a->text());
2465     a->setShortcut(Qt::Key_Backspace);
2466     viewMenu->addAction(a);
2467     switchboard.addSwitch("mapPreviousSlide", shortcutScope, a, tag);
2468     connect(a, SIGNAL(triggered()), this, SLOT(previousSlide()));
2469 }
2470
2471 // Connect Actions
2472 void Main::setupConnectActions()
2473 {
2474     QMenu *connectMenu = menuBar()->addMenu(tr("&Connect"));
2475     QString tag = tr("Connect", "Shortcuts");
2476
2477     QAction *a;
2478
2479     a = new QAction( tr("Get Confluence user data", "Connect action"), this);
2480     a->setShortcut(Qt::SHIFT + Qt::Key_C);
2481     connectMenu->addAction(a);
2482     switchboard.addSwitch ("confluenceUser", shortcutScope, a, tag);
2483     connect(a, SIGNAL(triggered()), this, SLOT(getConfluenceUser()));
2484     actionConnectGetConfluenceUser = a;
2485
2486     connectMenu->addAction(actionGetConfluencePageName);
2487     connectMenu->addAction(actionGetJiraDataSubtree);
2488
2489     connectMenu->addSeparator();
2490
2491     connectMenu->addAction(actionSettingsJIRA);
2492     connectMenu->addAction(actionSettingsConfluence);
2493 }
2494
2495 // Mode Actions
2496 void Main::setupModeActions()
2497 {
2498     // QPopupMenu *menu = new QPopupMenu( this );
2499     // menuBar()->insertItem( tr( "&Mode (using modifiers)" ), menu );
2500
2501     QString tag = tr("Modifier modes", "Shortcuts");
2502     QAction *a;
2503     actionGroupModModes = new QActionGroup(this);
2504     actionGroupModModes->setExclusive(true);
2505
2506     a = new QAction(
2507         QIcon(":/mode-select.svg"),
2508         tr("Use modifier to select and reorder objects", "Mode modifier"),
2509         actionGroupModModes);
2510     a->setShortcut(Qt::Key_J);
2511     addAction(a);
2512     switchboard.addSwitch("mapModModePoint", shortcutScope, a, tag);
2513     a->setCheckable(true);
2514     a->setChecked(true);
2515     actionListFiles.append(a);
2516     actionModModePoint = a;
2517
2518     a = new QAction(
2519         QPixmap(":/mode-color.png"),
2520         tr("Format painter: pick color from another branch and apply",
2521            "Mode modifier"),
2522         actionGroupModModes);
2523     a->setShortcut(Qt::Key_K);
2524     addAction(a);
2525     switchboard.addSwitch("mapModModeColor", shortcutScope, a, tag);
2526     a->setCheckable(true);
2527     actionListFiles.append(a);
2528     actionModModeColor = a;
2529
2530     a = new QAction(QPixmap(":/mode-xlink.png"),
2531                     tr("Use modifier to draw xLinks", "Mode modifier"),
2532                     actionGroupModModes);
2533     a->setShortcut(Qt::Key_L);
2534     addAction(a);
2535     switchboard.addSwitch("mapModModeXLink", shortcutScope, a, tag);
2536     a->setCheckable(true);
2537     actionListFiles.append(a);
2538     actionModModeXLink = a;
2539
2540     a = new QAction(
2541         QPixmap(":/mode-move-object.svg"),
2542         tr("Use modifier to move branches without linking", "Mode modifier"),
2543         actionGroupModModes);
2544     a->setShortcut(Qt::Key_Odiaeresis);
2545     addAction(a);
2546     switchboard.addSwitch("mapModModeMoveObject", shortcutScope, a, tag);
2547     a->setCheckable(true);
2548     actionListFiles.append(a);
2549     actionModModeMoveObject = a;
2550
2551     a = new QAction(
2552         QPixmap(":/mode-move-view.png"),
2553         tr("Use modifier to move view without selecting", "Mode modifier"),
2554         actionGroupModModes);
2555     a->setShortcut(Qt::Key_Adiaeresis);
2556     addAction(a);
2557     switchboard.addSwitch("mapModModeMoveView", shortcutScope, a, tag);
2558     a->setCheckable(true);
2559     actionListFiles.append(a);
2560     actionModModeMoveView = a;
2561 }
2562
2563 void Main::addUserFlag()
2564 {
2565     VymModel *m = currentModel();
2566
2567     if (m) {
2568         QFileDialog fd;
2569         QStringList filters;
2570         filters << tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif "
2571                                   "*.pnm *.svg *.svgz)";
2572         filters << tr("All", "Filedialog") + " (*.*)";
2573         fd.setFileMode(QFileDialog::ExistingFiles);
2574         fd.setNameFilters(filters);
2575         fd.setWindowTitle(vymName + " - " + "Load user flag");
2576         fd.setAcceptMode(QFileDialog::AcceptOpen);
2577
2578         QString fn;
2579         if (fd.exec() == QDialog::Accepted) {
2580             lastMapDir = fd.directory();
2581             QStringList flist = fd.selectedFiles();
2582             QStringList::Iterator it = flist.begin();
2583             initProgressCounter(flist.count());
2584             while (it != flist.end()) {
2585                 fn = *it;
2586                 setupFlag(*it, Flag::UserFlag, *it, "");
2587                 ++it;
2588             }
2589         }
2590     }
2591 }
2592
2593 void Main::setupFlagActions()
2594 {
2595     Flag *flag;
2596
2597     // Create System Flags
2598
2599     // Tasks
2600     // Origin: ./share/icons/oxygen/48x48/status/task-reject.png
2601     flag = setupFlag(":/flag-task-new.svg", Flag::SystemFlag, "system-task-new",
2602                      tr("Note", "SystemFlag"));
2603     flag->setGroup("system-tasks");
2604
2605     flag = setupFlag(":/flag-task-new-morning.svg", Flag::SystemFlag,
2606                      "system-task-new-morning", tr("Note", "SystemFlag"));
2607     flag->setGroup("system-tasks");
2608
2609     flag = setupFlag(":/flag-task-new-sleeping.svg", Flag::SystemFlag,
2610                      "system-task-new-sleeping", tr("Note", "SystemFlag"));
2611     flag->setGroup("system-tasks");
2612
2613     // Origin: ./share/icons/oxygen/48x48/status/task-reject.png
2614     flag = setupFlag(":/flag-task-wip.svg", Flag::SystemFlag, "system-task-wip",
2615                      tr("Note", "SystemFlag"));
2616     flag->setGroup("system-tasks");
2617
2618     flag = setupFlag(":/flag-task-wip-morning.svg", Flag::SystemFlag,
2619                      "system-task-wip-morning", tr("Note", "SystemFlag"));
2620     flag->setGroup("system-tasks");
2621
2622     flag = setupFlag(":/flag-task-wip-sleeping.svg", Flag::SystemFlag,
2623                      "system-task-wip-sleeping", tr("Note", "SystemFlag"));
2624     flag->setGroup("system-tasks");
2625
2626     // Origin: ./share/icons/oxygen/48x48/status/task-complete.png
2627     flag = setupFlag(":/flag-task-finished.svg", Flag::SystemFlag,
2628                      "system-task-finished", tr("Note", "SystemFlag"));
2629     flag->setGroup("system-tasks");
2630
2631     setupFlag(":/flag-note.svg", Flag::SystemFlag, "system-note",
2632               tr("Note", "SystemFlag"));
2633
2634     setupFlag(":/flag-url.svg", Flag::SystemFlag, "system-url",
2635               tr("URL", "SystemFlag"));
2636
2637     setupFlag(":/flag-target.svg", Flag::SystemFlag, "system-target",
2638               tr("Map target", "SystemFlag"));
2639
2640     setupFlag(":/flag-vymlink.png", Flag::SystemFlag, "system-vymLink",
2641               tr("Link to another vym map", "SystemFlag"));
2642
2643     setupFlag(":/flag-scrolled-right.png", Flag::SystemFlag,
2644               "system-scrolledright", tr("subtree is scrolled", "SystemFlag"));
2645
2646     setupFlag(":/flag-tmpUnscrolled-right.png", Flag::SystemFlag,
2647               "system-tmpUnscrolledRight",
2648               tr("subtree is temporary scrolled", "SystemFlag"));
2649
2650     setupFlag(":/flag-hideexport", Flag::SystemFlag, "system-hideInExport",
2651               tr("Hide object in exported maps", "SystemFlag"));
2652
2653     addToolBarBreak();
2654
2655     // Add entry now, to avoid chicken and egg problem and position toolbar
2656     // after all others:
2657     setupFlag(":/flag-stopsign.svg", Flag::StandardFlag, "stopsign",
2658                   tr("This won't work!", "Standardflag"), QUuid(), Qt::Key_1);
2659
2660     flag = setupFlag(":/flag-hook-green.svg",
2661                   // flag = setupFlag ( "flags/standard/dialog-ok-apply.svg",
2662                   Flag::StandardFlag, "hook-green",
2663                   tr("Status - ok,done", "Standardflag"), QUuid(), Qt::Key_2);
2664     flag->setGroup("standard-status");
2665
2666     flag = setupFlag(":/flag-wip.svg", Flag::StandardFlag, "wip",
2667                      tr("Status - work in progress", "Standardflag"), QUuid(),
2668                      Qt::Key_3);
2669     flag->setGroup("standard-status");
2670
2671     flag = setupFlag(":/flag-cross-red.svg", Flag::StandardFlag, "cross-red",
2672                      tr("Status - missing, not started", "Standardflag"),
2673                      QUuid(), Qt::Key_4);
2674     flag->setGroup("standard-status");
2675
2676     flag = setupFlag(":/flag-exclamation-mark.svg", Flag::StandardFlag,
2677                      "exclamationmark", tr("Take care!", "Standardflag"),
2678                      QUuid(), Qt::Key_Exclam);
2679     flag->setGroup("standard-mark");
2680
2681     flag = setupFlag(":/flag-question-mark.svg", Flag::StandardFlag,
2682                      "questionmark", tr("Really?", "Standardflag"), QUuid(),
2683                      Qt::Key_Question);
2684     flag->setGroup("standard-mark");
2685
2686     setupFlag(":/flag-info.svg", Flag::StandardFlag, "info",
2687                      tr("Info", "Standardflag"), QUuid(), Qt::Key_I);
2688
2689     setupFlag(":/flag-lamp.svg", Flag::StandardFlag, "lamp",
2690                      tr("Idea!", "Standardflag"), QUuid(), Qt::Key_Asterisk);
2691
2692     setupFlag(":/flag-heart.svg", Flag::StandardFlag, "heart",
2693                      tr("I just love...", "Standardflag"));
2694
2695     flag = setupFlag(":/flag-face-smile.svg", Flag::StandardFlag, "smiley-good",
2696                      tr("Good", "Standardflag"), QUuid(), Qt::Key_ParenRight);
2697     flag->setGroup("standard-faces");
2698
2699     flag = setupFlag(":/flag-face-sad.svg", Flag::StandardFlag, "smiley-sad",
2700                      tr("Bad", "Standardflag"), QUuid(), Qt::Key_ParenLeft);
2701     flag->setGroup("standard-faces");
2702
2703     flag = setupFlag(":/flag-face-plain.svg", Flag::StandardFlag,
2704                      "smiley-plain", tr("Hm...", "Standardflag"), QUuid());
2705     flag->setGroup("standard-faces");
2706
2707     flag = setupFlag(":/flag-face-surprise.svg", Flag::StandardFlag,
2708                      "smiley-omb", tr("Oh no!", "Standardflag"), QUuid());
2709     flag->setGroup("standard-faces");
2710
2711     setupFlag(":/flag-flash.svg", Flag::StandardFlag, "flash",
2712                      tr("Dangerous", "Standardflag"));
2713
2714     flag = setupFlag(":/flag-arrow-up.svg", Flag::StandardFlag, "arrow-up",
2715                      tr("Important", "Standardflag"), QUuid(),
2716                      Qt::SHIFT + Qt::Key_PageUp);
2717     flag->setGroup("standard-arrow");
2718
2719     flag = setupFlag(":/flag-arrow-down.svg", Flag::StandardFlag, "arrow-down",
2720                      tr("Unimportant", "Standardflag"), QUuid(),
2721                      Qt::SHIFT + Qt::Key_PageDown);
2722     flag->setGroup("standard-arrow");
2723
2724     flag = setupFlag(":/flag-arrow-2up.svg", Flag::StandardFlag, "2arrow-up",
2725                      tr("Very important!", "Standardflag"), QUuid(),
2726                      Qt::SHIFT + Qt::CTRL + Qt::Key_PageUp);
2727     flag->setGroup("standard-arrow");
2728
2729     flag = setupFlag(":/flag-arrow-2down.svg", Flag::StandardFlag,
2730                      "2arrow-down", tr("Very unimportant!", "Standardflag"),
2731                      QUuid(), Qt::SHIFT + Qt::CTRL + Qt::Key_PageDown);
2732     flag->setGroup("standard-arrow");
2733
2734     setupFlag(":/flag-thumb-up.png", Flag::StandardFlag, "thumb-up",
2735                      tr("I like this", "Standardflag"));
2736
2737     setupFlag(":/flag-thumb-down.png", Flag::StandardFlag, "thumb-down",
2738                      tr("I do not like this", "Standardflag"));
2739
2740     // Original khelpcenter.png
2741     setupFlag(":/flag-lifebelt.svg", Flag::StandardFlag, "lifebelt",
2742                      tr("This will help", "Standardflag"));
2743
2744     setupFlag(":/flag-phone.svg", Flag::StandardFlag, "phone",
2745                      tr("Call...", "Standardflag"));
2746
2747     setupFlag(":/flag-clock.svg", Flag::StandardFlag, "clock",
2748                      tr("Time critical", "Standardflag"));
2749
2750     setupFlag(":/flag-present.png", Flag::StandardFlag, "present",
2751                      tr("Surprise!", "Standardflag"));
2752
2753     setupFlag(":/flag-rose.png", Flag::StandardFlag, "rose",
2754                      tr("Rose", "Standardflag"));
2755
2756     // Freemind flags
2757     setupFlag(":/freemind/warning.png", Flag::FreemindFlag,
2758                      "freemind-warning", tr("Important", "Freemind flag"));
2759
2760     for (int i = 1; i < 8; i++) {
2761         setupFlag(QString(":/freemind/priority-%1.png").arg(i),
2762                          Flag::FreemindFlag,
2763                          QString("freemind-priority-%1").arg(i),
2764                          tr("Important", "Freemind flag"));
2765         flag->setGroup("freemind-priority");
2766     }
2767
2768     setupFlag(":/freemind/back.png", Flag::FreemindFlag, "freemind-back",
2769                      tr("Back", "Freemind flag"));
2770
2771     setupFlag(":/freemind/forward.png", Flag::FreemindFlag,
2772                      "freemind-forward", tr("Forward", "Freemind flag"));
2773
2774     setupFlag(":/freemind/attach.png", Flag::FreemindFlag,
2775                      "freemind-attach", tr("Look here", "Freemind flag"));
2776
2777     setupFlag(":/freemind/clanbomber.png", Flag::FreemindFlag,
2778                      "freemind-clanbomber", tr("Dangerous", "Freemind flag"));
2779
2780     setupFlag(":/freemind/desktopnew.png", Flag::FreemindFlag,
2781                   "freemind-desktopnew", tr("Don't forget", "Freemind flag"));
2782
2783     setupFlag(":/freemind/flag.png", Flag::FreemindFlag, "freemind-flag",
2784                      tr("Flag", "Freemind flag"));
2785
2786     setupFlag(":/freemind/gohome.png", Flag::FreemindFlag,
2787                      "freemind-gohome", tr("Home", "Freemind flag"));
2788
2789     setupFlag(":/freemind/kaddressbook.png", Flag::FreemindFlag,
2790                      "freemind-kaddressbook", tr("Telephone", "Freemind flag"));
2791
2792     setupFlag(":/freemind/knotify.png", Flag::FreemindFlag,
2793                      "freemind-knotify", tr("Music", "Freemind flag"));
2794
2795     setupFlag(":/freemind/korn.png", Flag::FreemindFlag, "freemind-korn",
2796                      tr("Mailbox", "Freemind flag"));
2797
2798     setupFlag(":/freemind/mail.png", Flag::FreemindFlag, "freemind-mail",
2799                      tr("Mail", "Freemind flag"));
2800
2801     setupFlag(":/freemind/password.png", Flag::FreemindFlag,
2802                      "freemind-password", tr("Password", "Freemind flag"));
2803
2804     setupFlag(":/freemind/pencil.png", Flag::FreemindFlag,
2805                      "freemind-pencil", tr("To be improved", "Freemind flag"));
2806
2807     setupFlag(":/freemind/stop.png", Flag::FreemindFlag, "freemind-stop",
2808                      tr("Stop", "Freemind flag"));
2809
2810     setupFlag(":/freemind/wizard.png", Flag::FreemindFlag,
2811                      "freemind-wizard", tr("Magic", "Freemind flag"));
2812
2813     setupFlag(":/freemind/xmag.png", Flag::FreemindFlag, "freemind-xmag",
2814                      tr("To be discussed", "Freemind flag"));
2815
2816     setupFlag(":/freemind/bell.png", Flag::FreemindFlag, "freemind-bell",
2817                      tr("Reminder", "Freemind flag"));
2818
2819     setupFlag(":/freemind/bookmark.png", Flag::FreemindFlag,
2820                      "freemind-bookmark", tr("Excellent", "Freemind flag"));
2821
2822     setupFlag(":/freemind/penguin.png", Flag::FreemindFlag,
2823                      "freemind-penguin", tr("Linux", "Freemind flag"));
2824
2825     setupFlag(":/freemind/licq.png", Flag::FreemindFlag, "freemind-licq",
2826                      tr("Sweet", "Freemind flag"));
2827 }
2828
2829 Flag *Main::setupFlag(const QString &path, Flag::FlagType type,
2830                       const QString &name, const QString &tooltip,
2831                       const QUuid &uid, const QKeySequence &keyseq)
2832 {
2833     Flag *flag = nullptr;
2834
2835     // Create flag in toolbar
2836     switch (type) {
2837     case Flag::FreemindFlag:
2838         // Maybe introduce dedicated toolbar later,
2839         // so for now switch to standard flag
2840         flag = standardFlagsMaster->createFlag(path);
2841         break;
2842
2843     case Flag::StandardFlag:
2844         flag = standardFlagsMaster->createFlag(path);
2845         break;
2846
2847     case Flag::UserFlag:
2848         flag = userFlagsMaster->createFlag(path);
2849
2850         // User flags read from file already have a Uuid - use it
2851         if (!uid.isNull())
2852             flag->setUuid(uid);
2853         break;
2854
2855     case Flag::SystemFlag:
2856         flag = systemFlagsMaster->createFlag(path);
2857         break;
2858
2859     default:
2860         qWarning() << "Unknown flag type in MainWindow::setupFlag";
2861         break;
2862     }
2863
2864     if (!flag)
2865         return flag;
2866
2867     flag->setName(name);
2868     flag->setToolTip(tooltip);
2869     flag->setType(type);
2870
2871     if (type == Flag::SystemFlag)
2872         return flag;
2873
2874     // StandardFlag or user flag
2875
2876     QAction *a;
2877
2878     // Set icon for action
2879     ImageObj *image = flag->getImageObj();
2880     a = new QAction(image->getIcon(), flag->getUuid().toString(), this);
2881
2882     flag->setAction(a);
2883     a->setCheckable(true);
2884     a->setObjectName(flag->getUuid().toString());
2885     if (tooltip.isEmpty())
2886         a->setToolTip(flag->getName()); // Stripped name
2887     else
2888         a->setToolTip(tooltip);
2889
2890     if (keyseq != 0) {
2891         a->setShortcut(keyseq);
2892         a->setShortcutContext(Qt::WidgetShortcut);
2893
2894         // Allow mapEditors to actually trigger this action
2895         mapEditorActions.append(a);
2896         taskEditorActions.append(a);
2897     }
2898
2899     switch (type) {
2900     case Flag::FreemindFlag:
2901         // Hide freemind flags per default
2902         // Maybe introduce dedicate toolbar later,
2903         // so for now switch to standard flag
2904         flag->setVisible(false);
2905         type = Flag::StandardFlag;
2906         standardFlagsMaster->addActionToToolbar(a);
2907
2908         connect(a, SIGNAL(triggered()), this, SLOT(flagChanged()));
2909         break;
2910     case Flag::StandardFlag:
2911         // Hide some old flags, if not used
2912         if (name == "present" || name == "rose" || name == "phone" ||
2913             name == "clock")
2914             flag->setVisible(false);
2915         standardFlagsMaster->addActionToToolbar(a);
2916         connect(a, SIGNAL(triggered()), this, SLOT(flagChanged()));
2917         break;
2918     case Flag::UserFlag:
2919         userFlagsMaster->addActionToToolbar(a);
2920         connect(a, SIGNAL(triggered()), this, SLOT(flagChanged()));
2921         break;
2922     default:
2923         qWarning() << "Unknown flag type in MainWindow::setupFlag";
2924     }
2925
2926     a->setVisible(flag->isVisible());
2927
2928     return flag;
2929 }
2930
2931 // Network Actions
2932 void Main::setupNetworkActions()
2933 {
2934     if (!settings.value("/mainwindow/showTestMenu", false).toBool())
2935         return;
2936
2937     QAction *a;
2938
2939     a = new QAction("Start TCPserver for MapEditor", this);
2940     // a->setShortcut ( Qt::ALT + Qt::Key_T );
2941     connect(a, SIGNAL(triggered()), this, SLOT(networkStartServer()));
2942
2943     a = new QAction("Connect MapEditor to server", this);
2944     // a->setShortcut ( Qt::ALT + Qt::Key_C );
2945     connect(a, SIGNAL(triggered()), this, SLOT(networkConnect()));
2946 }
2947
2948 // Settings Actions
2949 void Main::setupSettingsActions()
2950 {
2951     QMenu *settingsMenu = menuBar()->addMenu(tr("Settings"));
2952
2953     QAction *a;
2954
2955     a = new QAction(
2956         tr("Check for release notes and updates", "Settings action"), this);
2957     a->setCheckable(true);
2958     a->setChecked(settings.value("/downloads/enabled", true).toBool());
2959     connect(a, SIGNAL(triggered()), this, SLOT(settingsToggleDownloads()));
2960     settingsMenu->addAction(a);
2961     actionSettingsToggleDownloads = a;
2962
2963     a = new QAction(tr("Set author for new maps", "Settings action") + "...",
2964                     this);
2965     connect(a, SIGNAL(triggered()), this, SLOT(settingsDefaultMapAuthor()));
2966     settingsMenu->addAction(a);
2967
2968     settingsMenu->addSeparator();
2969
2970     a = new QAction(tr("Set application to open pdf files", "Settings action") +
2971                         "...",
2972                     this);
2973     connect(a, SIGNAL(triggered()), this, SLOT(settingsPDF()));
2974     settingsMenu->addAction(a);
2975
2976     a = new QAction(
2977         tr("Set application to open external links", "Settings action") + "...",
2978         this);
2979     connect(a, SIGNAL(triggered()), this, SLOT(settingsURL()));
2980     settingsMenu->addAction(a);
2981
2982     a = new QAction(
2983         tr("Set application to zip/unzip files", "Settings action") + "...",
2984         this);
2985     connect(a, SIGNAL(triggered()), this, SLOT(settingsZipTool()));
2986     // FIXME-2 Disabled for now  settingsMenu->addAction(a);
2987
2988     a = new QAction(tr("Confluence Credentials", "Settings action") + "...",
2989                     this);
2990     connect(a, SIGNAL(triggered()), this, SLOT(settingsConfluence()));
2991     settingsMenu->addAction(a);
2992     actionSettingsConfluence = a;
2993
2994     a = new QAction(tr("JIRA Credentials", "Settings action") + "...",
2995                     this);
2996     connect(a, SIGNAL(triggered()), this, SLOT(settingsJIRA()));
2997     settingsMenu->addAction(a);
2998     actionSettingsJIRA = a;
2999
3000     a = new QAction(tr("Set path for new maps", "Settings action") + "...",
3001                     this);
3002     connect(a, SIGNAL(triggered()), this, SLOT(settingsDefaultMapPath()));
3003     settingsMenu->addAction(a);
3004
3005     a = new QAction(tr("Set path for macros", "Settings action") + "...", this);
3006     connect(a, SIGNAL(triggered()), this, SLOT(settingsMacroPath()));
3007     settingsMenu->addAction(a);
3008
3009     a = new QAction(tr("Set number of undo levels", "Settings action") + "...",
3010                     this);
3011     connect(a, SIGNAL(triggered()), this, SLOT(settingsUndoLevels()));
3012     settingsMenu->addAction(a);
3013
3014     settingsMenu->addSeparator();
3015
3016     a = new QAction(tr("Autosave", "Settings action"), this);
3017     a->setCheckable(true);
3018     a->setChecked(settings.value("/system/autosave/use", true).toBool());
3019     settingsMenu->addAction(a);
3020     actionSettingsToggleAutosave = a;
3021
3022     a = new QAction(tr("Autosave time", "Settings action") + "...", this);
3023     connect(a, SIGNAL(triggered()), this, SLOT(settingsAutosaveTime()));
3024     settingsMenu->addAction(a);
3025     actionSettingsAutosaveTime = a;
3026
3027     // Disable certain actions during testing
3028     if (testmode) {
3029         actionSettingsToggleAutosave->setChecked(false);
3030         actionSettingsToggleAutosave->setEnabled(false);
3031         actionSettingsAutosaveTime->setEnabled(false);
3032     }
3033
3034     a = new QAction(tr("Write backup file on save", "Settings action"), this);
3035     a->setCheckable(true);
3036     a->setChecked(settings.value("/system/writeBackupFile", false).toBool());
3037     connect(a, SIGNAL(triggered()), this,
3038             SLOT(settingsToggleWriteBackupFile()));
3039     settingsMenu->addAction(a);
3040     actionSettingsWriteBackupFile = a;
3041
3042     settingsMenu->addSeparator();
3043
3044     a = new QAction(tr("Select branch after adding it", "Settings action"),
3045                     this);
3046     a->setCheckable(true);
3047     a->setChecked(
3048         settings.value("/mapeditor/editmode/autoSelectNewBranch", false)
3049             .toBool());
3050     settingsMenu->addAction(a);
3051     actionSettingsAutoSelectNewBranch = a;
3052
3053     a = new QAction(tr("Select existing heading", "Settings action"), this);
3054     a->setCheckable(true);
3055     a->setChecked(
3056         settings.value("/mapeditor/editmode/autoSelectText", true).toBool());
3057     settingsMenu->addAction(a);
3058     actionSettingsAutoSelectText = a;
3059
3060     a = new QAction(tr("Exclusive flags", "Settings action"), this);
3061     a->setCheckable(true);
3062     a->setChecked(
3063         settings.value("/mapeditor/editmode/useFlagGroups", true).toBool());
3064     settingsMenu->addAction(a);
3065     actionSettingsUseFlagGroups = a;
3066
3067     a = new QAction(tr("Use hide flags", "Settings action"), this);
3068     a->setCheckable(true);
3069     a->setChecked(settings.value("/export/useHideExport", true).toBool());
3070     settingsMenu->addAction(a);
3071     actionSettingsUseHideExport = a;
3072
3073     settingsMenu->addSeparator();
3074
3075     a = new QAction(
3076         tr("Dark theme", "Settings action") + "...",
3077         this);
3078     connect(a, SIGNAL(triggered()), this,
3079             SLOT(settingsDarkTheme()));
3080     settingsMenu->addAction(a);
3081     actionSettingsDarkTheme= a;
3082
3083     a = new QAction(
3084         tr("Number of visible parents in task editor", "Settings action") + "...",
3085         this);
3086     connect(a, SIGNAL(triggered()), this,
3087             SLOT(settingsShowParentsLevelTasks()));
3088     settingsMenu->addAction(a);
3089     actionSettingsShowParentsLevelTasks = a;
3090
3091     a = new QAction(tr("Number of visible parents in find results window",
3092                        "Settings action") + "...",
3093                     this);
3094     connect(a, SIGNAL(triggered()), this,
3095             SLOT(settingsShowParentsLevelFindResults()));
3096     settingsMenu->addAction(a);
3097     actionSettingsShowParentsLevelFindResults = a;
3098
3099     a = new QAction(tr("Animation", "Settings action"), this);
3100     a->setCheckable(true);
3101     a->setChecked(settings.value("/animation/use", true).toBool());
3102     connect(a, SIGNAL(triggered()), this, SLOT(settingsToggleAnimation()));
3103     settingsMenu->addAction(a);
3104     actionSettingsUseAnimation = a;
3105
3106     a = new QAction(tr("Automatic layout", "Settings action"), this);
3107     a->setCheckable(true);
3108     a->setChecked(settings.value("/mainwindow/autoLayout/use", true).toBool());
3109     connect(a, SIGNAL(triggered()), this, SLOT(settingsToggleAutoLayout()));
3110     settingsMenu->addAction(a);
3111     actionSettingsToggleAutoLayout = a;
3112 }
3113
3114 // Test Actions
3115 void Main::setupTestActions()
3116 {
3117     QMenu *testMenu = menuBar()->addMenu(tr("Test"));
3118
3119     QString tag = "Testing";
3120     QAction *a;
3121     a = new QAction("Test function 1", this);
3122     a->setShortcut(Qt::ALT + Qt::Key_T);
3123     testMenu->addAction(a);
3124     switchboard.addSwitch("mapTest1", shortcutScope, a, tag);
3125     connect(a, SIGNAL(triggered()), this, SLOT(testFunction1()));
3126
3127     a = new QAction("Test function 2", this);
3128     // a->setShortcut (Qt::ALT + Qt::Key_T);
3129     testMenu->addAction(a);
3130     connect(a, SIGNAL(triggered()), this, SLOT(testFunction2()));
3131
3132     a = new QAction("Toggle hide export mode", this);
3133     a->setCheckable(true);
3134     a->setChecked(false);
3135     testMenu->addAction(a);
3136     connect(a, SIGNAL(triggered()), this, SLOT(toggleHideExport()));
3137     actionToggleHideMode = a;
3138
3139     testMenu->addAction(actionToggleWinter);
3140 }
3141
3142 // Help Actions
3143 void Main::setupHelpActions()
3144 {
3145     QMenu *helpMenu = menuBar()->addMenu(tr("&Help", "Help menubar entry"));
3146
3147     QAction *a;
3148     a = new QAction(tr("Open VYM Documentation (pdf) ", "Help action"), this);
3149     helpMenu->addAction(a);
3150     connect(a, SIGNAL(triggered()), this, SLOT(helpDoc()));
3151
3152     a = new QAction(tr("Open VYM example maps ", "Help action"), this);
3153     helpMenu->addAction(a);
3154     connect(a, SIGNAL(triggered()), this, SLOT(helpDemo()));
3155     helpMenu->addSeparator();
3156
3157     a = new QAction(tr("Download and show release notes", "Help action"), this);
3158     helpMenu->addAction(a);
3159     connect(a, SIGNAL(triggered()), this, SLOT(checkReleaseNotes()));
3160
3161     a = new QAction(tr("Check, if updates are available", "Help action"), this);
3162     helpMenu->addAction(a);
3163     connect(a, SIGNAL(triggered()), this, SLOT(checkUpdates()));
3164     helpMenu->addSeparator();
3165
3166     a = new QAction(tr("Show keyboard shortcuts", "Help action"), this);
3167     helpMenu->addAction(a);
3168     connect(a, SIGNAL(triggered()), this, SLOT(helpShortcuts()));
3169
3170     a = new QAction(tr("Show keyboard macros", "Help action"), this);
3171     helpMenu->addAction(a);
3172     connect(a, SIGNAL(triggered()), this, SLOT(helpMacros()));
3173
3174     a = new QAction(tr("Show scripting commands", "Help action"), this);
3175     helpMenu->addAction(a);
3176     connect(a, SIGNAL(triggered()), this, SLOT(helpScriptingCommands()));
3177
3178     a = new QAction(tr("Debug info", "Option to show debugging info"), this);
3179     helpMenu->addAction(a);
3180     connect(a, SIGNAL(triggered()), this, SLOT(helpDebugInfo()));
3181
3182     a = new QAction(tr("About QT", "Help action"), this);
3183     connect(a, SIGNAL(triggered()), this, SLOT(helpAboutQT()));
3184     helpMenu->addAction(a);
3185
3186     a = new QAction(tr("About VYM", "Help action"), this);
3187     connect(a, SIGNAL(triggered()), this, SLOT(helpAbout()));
3188     helpMenu->addAction(a);
3189 }
3190
3191 // Context Menus
3192 void Main::setupContextMenus()
3193 {
3194     // Context menu for goto/move targets  (populated on demand)
3195     targetsContextMenu = new QMenu(this);
3196
3197     // Context Menu for branch or mapcenter
3198     branchContextMenu = new QMenu(this);
3199     branchContextMenu->addAction(actionViewTogglePropertyEditor);
3200     branchContextMenu->addSeparator();
3201
3202     // Submenu "Add"
3203     branchAddContextMenu = branchContextMenu->addMenu(tr("Add"));
3204     branchAddContextMenu->addAction(actionPaste);
3205     branchAddContextMenu->addAction(actionAddMapCenter);
3206     branchAddContextMenu->addAction(actionAddBranch);
3207     branchAddContextMenu->addAction(actionAddBranchBefore);
3208     branchAddContextMenu->addAction(actionAddBranchAbove);
3209     branchAddContextMenu->addAction(actionAddBranchBelow);
3210     branchAddContextMenu->addSeparator();
3211     branchAddContextMenu->addAction(actionImportAdd);
3212     branchAddContextMenu->addAction(actionImportReplace);
3213
3214     // Submenu "Remove"
3215     branchRemoveContextMenu =
3216         branchContextMenu->addMenu(tr("Remove", "Context menu name"));
3217     branchRemoveContextMenu->addAction(actionCut);
3218     branchRemoveContextMenu->addAction(actionDelete);
3219     branchRemoveContextMenu->addAction(actionDeleteKeepChildren);
3220     branchRemoveContextMenu->addAction(actionDeleteChildren);
3221
3222     branchContextMenu->addAction(actionSaveBranch);
3223     branchContextMenu->addAction(actionFileNewCopy);
3224     branchContextMenu->addAction(actionDetach);
3225
3226     branchContextMenu->addSeparator();
3227     branchContextMenu->addAction(actionLoadImage);
3228     if (settings.value("/mainwindow/showTestMenu", false).toBool())
3229         branchContextMenu->addAction(actionAddAttribute);
3230
3231     branchContextMenu->addSeparator();
3232
3233     // Context menu for tasks
3234     taskContextMenu = branchContextMenu->addMenu(tr("Tasks", "Context menu"));
3235     taskContextMenu->addAction(actionToggleTask);
3236     taskContextMenu->addAction(actionCycleTaskStatus);
3237     taskContextMenu->addAction(actionTaskResetDeltaPrio);
3238     taskContextMenu->addSeparator();
3239     taskContextMenu->addAction(actionTaskSleep0);
3240     taskContextMenu->addAction(actionTaskSleepN);
3241     taskContextMenu->addAction(actionTaskSleep1);
3242     taskContextMenu->addAction(actionTaskSleep2);
3243     taskContextMenu->addAction(actionTaskSleep3);
3244     taskContextMenu->addAction(actionTaskSleep4);
3245     taskContextMenu->addAction(actionTaskSleep5);
3246     taskContextMenu->addAction(actionTaskSleep7);
3247     taskContextMenu->addAction(actionTaskSleep14);
3248     taskContextMenu->addAction(actionTaskSleep28);
3249
3250     // Submenu for Links (URLs, vymLinks)
3251     branchLinksContextMenu = new QMenu(this);
3252
3253     branchLinksContextMenu = branchContextMenu->addMenu(
3254         tr("References (URLs, vymLinks, ...)", "Context menu name"));
3255     branchLinksContextMenu->addAction(actionOpenURL);
3256     branchLinksContextMenu->addAction(actionOpenURLTab);
3257     branchLinksContextMenu->addAction(actionOpenMultipleVisURLTabs);
3258     branchLinksContextMenu->addAction(actionOpenMultipleURLTabs);
3259     branchLinksContextMenu->addAction(actionURLNew);
3260     branchLinksContextMenu->addAction(actionLocalURL);
3261     branchLinksContextMenu->addAction(actionGetURLsFromNote);
3262     branchLinksContextMenu->addAction(actionHeading2URL);
3263     branchLinksContextMenu->addAction(actionGetJiraDataSubtree);
3264     branchLinksContextMenu->addAction(actionGetConfluencePageName);
3265     branchLinksContextMenu->addSeparator();
3266     branchLinksContextMenu->addAction(actionOpenVymLink);
3267     branchLinksContextMenu->addAction(actionOpenVymLinkBackground);
3268     branchLinksContextMenu->addAction(actionOpenMultipleVymLinks);
3269     branchLinksContextMenu->addAction(actionEditVymLink);
3270     branchLinksContextMenu->addAction(actionDeleteVymLink);
3271
3272     // Context Menu for XLinks in a branch menu
3273     // This will be populated "on demand" in updateActions
3274     QString tag = tr("XLinks", "Menu for file actions");
3275     branchContextMenu->addSeparator();
3276     branchXLinksContextMenuEdit =
3277         branchContextMenu->addMenu(tr("Edit XLink", "Context menu name"));
3278     connect(branchXLinksContextMenuEdit, SIGNAL(triggered(QAction *)), this,
3279             SLOT(editEditXLink(QAction *)));
3280     QAction *a;
3281     a = new QAction(tr("Follow XLink", "Context menu"), this);
3282     a->setShortcut(Qt::Key_F);
3283     addAction(a);
3284     switchboard.addSwitch("mapFollowXLink", shortcutScope, a, tag);
3285     connect(a, SIGNAL(triggered()), this, SLOT(popupFollowXLink()));
3286
3287     branchXLinksContextMenuFollow =
3288         branchContextMenu->addMenu(tr("Follow XLink", "Context menu name"));
3289     connect(branchXLinksContextMenuFollow, SIGNAL(triggered(QAction *)), this,
3290             SLOT(editFollowXLink(QAction *)));
3291
3292     // Context menu for floatimage
3293     floatimageContextMenu = new QMenu(this);
3294     a = new QAction(tr("Save image", "Context action"), this);
3295     connect(a, SIGNAL(triggered()), this, SLOT(editSaveImage()));
3296     floatimageContextMenu->addAction(a);
3297
3298     floatimageContextMenu->addSeparator();
3299     floatimageContextMenu->addAction(actionCopy);
3300     floatimageContextMenu->addAction(actionCut);
3301
3302     floatimageContextMenu->addSeparator();
3303     floatimageContextMenu->addAction(actionGrowSelectionSize);
3304     floatimageContextMenu->addAction(actionShrinkSelectionSize);
3305     floatimageContextMenu->addAction(actionFormatHideLinkUnselected);
3306
3307     // Context menu for canvas
3308     canvasContextMenu = new QMenu(this);
3309
3310     canvasContextMenu->addAction(actionAddMapCenter);
3311
3312     canvasContextMenu->addSeparator();
3313
3314     canvasContextMenu->addAction(actionMapProperties);
3315     canvasContextMenu->addAction(actionFormatFont);
3316
3317     canvasContextMenu->addSeparator();
3318
3319     canvasContextMenu->addActions(actionGroupFormatLinkStyles->actions());
3320
3321     canvasContextMenu->addSeparator();
3322
3323     canvasContextMenu->addAction(actionFormatLinkColorHint);
3324
3325     canvasContextMenu->addSeparator();
3326
3327     canvasContextMenu->addAction(actionFormatLinkColor);
3328     canvasContextMenu->addAction(actionFormatSelectionColor);
3329     canvasContextMenu->addAction(actionFormatBackColor);
3330     // if (settings.value( "/mainwindow/showTestMenu",false).toBool() )
3331     //    canvasContextMenu->addAction( actionFormatBackImage );  //FIXME-3
3332     //    makes vym too slow: postponed for later version
3333
3334     // Menu for last opened files
3335     // Create actions
3336     for (int i = 0; i < MaxRecentFiles; ++i) {
3337         recentFileActions[i] = new QAction(this);
3338         recentFileActions[i]->setVisible(false);
3339         fileLastMapsMenu->addAction(recentFileActions[i]);
3340         connect(recentFileActions[i], SIGNAL(triggered()), this,
3341                 SLOT(fileLoadRecent()));
3342     }
3343     setupRecentMapsMenu();
3344 }
3345
3346 void Main::setupRecentMapsMenu()
3347 {
3348     QStringList files =
3349         settings.value("/mainwindow/recentFileList").toStringList();
3350
3351     int numRecentFiles = qMin(files.size(), (int)MaxRecentFiles);
3352
3353     for (int i = 0; i < numRecentFiles; ++i) {
3354         QString text = QString("&%1 %2").arg(i + 1).arg(files[i]);
3355         recentFileActions[i]->setText(text);
3356         recentFileActions[i]->setData(files[i]);
3357         recentFileActions[i]->setVisible(true);
3358     }
3359     for (int j = numRecentFiles; j < MaxRecentFiles; ++j)
3360         recentFileActions[j]->setVisible(false);
3361 }
3362
3363 void Main::setupMacros()
3364 {
3365     for (int i = 0; i <= 23; i++) {
3366         macroActions[i] = new QAction(this);
3367         macroActions[i]->setData(i);
3368         addAction(macroActions[i]);
3369         connect(macroActions[i], SIGNAL(triggered()), this, SLOT(callMacro()));
3370     }
3371     macroActions[0]->setShortcut(Qt::Key_F1);
3372     macroActions[1]->setShortcut(Qt::Key_F2);
3373     macroActions[2]->setShortcut(Qt::Key_F3);
3374     macroActions[3]->setShortcut(Qt::Key_F4);
3375     macroActions[4]->setShortcut(Qt::Key_F5);
3376     macroActions[5]->setShortcut(Qt::Key_F6);
3377     macroActions[6]->setShortcut(Qt::Key_F7);
3378     macroActions[7]->setShortcut(Qt::Key_F8);
3379     macroActions[8]->setShortcut(Qt::Key_F9);
3380     macroActions[9]->setShortcut(Qt::Key_F10);
3381     macroActions[10]->setShortcut(Qt::Key_F11);
3382     macroActions[11]->setShortcut(Qt::Key_F12);
3383
3384     macroActions[12]->setShortcut(Qt::Key_F1 + Qt::SHIFT);
3385     macroActions[13]->setShortcut(Qt::Key_F2 + Qt::SHIFT);
3386     macroActions[14]->setShortcut(Qt::Key_F3 + Qt::SHIFT);
3387     macroActions[15]->setShortcut(Qt::Key_F4 + Qt::SHIFT);
3388     macroActions[16]->setShortcut(Qt::Key_F5 + Qt::SHIFT);
3389     macroActions[17]->setShortcut(Qt::Key_F6 + Qt::SHIFT);
3390     macroActions[18]->setShortcut(Qt::Key_F7 + Qt::SHIFT);
3391     macroActions[19]->setShortcut(Qt::Key_F8 + Qt::SHIFT);
3392     macroActions[20]->setShortcut(Qt::Key_F9 + Qt::SHIFT);
3393     macroActions[21]->setShortcut(Qt::Key_F10 + Qt::SHIFT);
3394     macroActions[22]->setShortcut(Qt::Key_F11 + Qt::SHIFT);
3395     macroActions[23]->setShortcut(Qt::Key_F12 + Qt::SHIFT);
3396 }
3397
3398 void Main::setupToolbars()
3399 {
3400     // File actions
3401     fileToolbar =
3402         addToolBar(tr("File actions toolbar", "Toolbar for file actions"));
3403     fileToolbar->setObjectName("fileTB");
3404     fileToolbar->addAction(actionFileNew);
3405     fileToolbar->addAction(actionFileOpen);
3406     fileToolbar->addAction(actionFileSave);
3407     fileToolbar->addAction(actionFileExportLast);
3408     fileToolbar->addAction(actionFilePrint);
3409
3410     // Undo/Redo and clipboard
3411     clipboardToolbar = addToolBar(tr("Undo and clipboard toolbar",
3412                                      "Toolbar for redo/undo and clipboard"));
3413     clipboardToolbar->setObjectName("clipboard toolbar");
3414     clipboardToolbar->addAction(actionUndo);
3415     clipboardToolbar->addAction(actionRedo);
3416     clipboardToolbar->addAction(actionCopy);
3417     clipboardToolbar->addAction(actionCut);
3418     clipboardToolbar->addAction(actionPaste);
3419
3420     // Basic edits
3421     editActionsToolbar = addToolBar(tr("Edit actions toolbar", "Toolbar name"));
3422     editActionsToolbar->setObjectName("basic edit actions TB");
3423     editActionsToolbar->addAction(actionAddMapCenter);
3424     editActionsToolbar->addAction(actionAddBranch);
3425     editActionsToolbar->addAction(actionMoveUp);
3426     editActionsToolbar->addAction(actionMoveDown);
3427     editActionsToolbar->addAction(actionMoveDownDiagonally);
3428     editActionsToolbar->addAction(actionMoveUpDiagonally);
3429     editActionsToolbar->addAction(actionSortChildren);
3430     editActionsToolbar->addAction(actionSortBackChildren);
3431     editActionsToolbar->addAction(actionToggleScroll);
3432     editActionsToolbar->addAction(actionToggleHideExport);
3433     editActionsToolbar->addAction(actionToggleTask);
3434     // editActionsToolbar->addAction (actionExpandAll);
3435     // editActionsToolbar->addAction (actionExpandOneLevel);
3436     // editActionsToolbar->addAction (actionCollapseOneLevel);
3437     // editActionsToolbar->addAction (actionCollapseUnselected);
3438
3439     // Selections
3440     selectionToolbar = addToolBar(tr("Selection toolbar", "Toolbar name"));
3441     selectionToolbar->setObjectName("toolbar for selecting items");
3442     selectionToolbar->addAction(actionToggleTarget);
3443     selectionToolbar->addAction(actionSelectPrevious);
3444     selectionToolbar->addAction(actionSelectNext);
3445     selectionToolbar->addAction(actionFind);
3446
3447     // URLs and vymLinks
3448     referencesToolbar = addToolBar(
3449         tr("URLs and vymLinks toolbar", "Toolbar for URLs and vymlinks"));
3450     referencesToolbar->setObjectName("URLs and vymlinks toolbar");
3451     referencesToolbar->addAction(actionURLNew);
3452     referencesToolbar->addAction(actionEditVymLink);
3453
3454     // Format and colors
3455     colorsToolbar = new QToolBar(tr("Colors toolbar", "Colors toolbar name"));
3456     colorsToolbar->setObjectName("colorsTB");
3457
3458     actionGroupQuickColors = new QActionGroup(this);
3459     actionGroupQuickColors->setExclusive(true);
3460
3461     // Define quickColors
3462     QColor c;
3463     c.setNamedColor ("#ff0000"); quickColors << c;  // Red
3464     c.setNamedColor ("#d95100"); quickColors << c;  // Orange
3465     c.setNamedColor ("#009900"); quickColors << c;  // Green
3466     c.setNamedColor ("#aa00ff"); quickColors << c;  // Purple
3467     c.setNamedColor ("#0000ff"); quickColors << c;  // Blue
3468     c.setNamedColor ("#00aaff"); quickColors << c;  // LightBlue
3469     usingDarkTheme ? vymBlue = c : vymBlue = quickColors.count() - 2;
3470     c.setNamedColor ("#000000"); quickColors << c;  // Black
3471     c.setNamedColor ("#444444"); quickColors << c;  // Dark gray
3472     c.setNamedColor ("#aaaaaa"); quickColors << c;  // Light gray
3473     c.setNamedColor ("#ffffff"); quickColors << c;  // White
3474     //c.setNamedColor ("#00aa7f"); quickColors << c;  // Light green
3475     //c.setNamedColor ("#c466ff"); quickColors << c;  // Light purple
3476
3477     QPixmap pix(16, 16);
3478     QAction *a;
3479     int n = 0;
3480     foreach (c, quickColors) {
3481         pix.fill(c);
3482         a = new QAction(pix, tr("Select color (Press Shift for more options)") + QString("..."), actionGroupQuickColors);
3483         a->setCheckable(true);
3484         a->setData(n);
3485         //formatMenu->addAction(a);
3486         // switchboard.addSwitch("mapFormatColor", shortcutScope, a, tag);
3487         connect(a, SIGNAL(triggered()), this, SLOT(quickColorPressed()));
3488         colorsToolbar->addAction(a);
3489         n++;
3490     }
3491     actionGroupQuickColors->actions().first()->setChecked(true);
3492
3493     colorsToolbar->addAction(actionFormatPickColor);
3494     colorsToolbar->addAction(actionFormatColorBranch);
3495     colorsToolbar->addAction(actionFormatColorSubtree);
3496     // Only place toolbar on very first startup
3497     if (settings.value("/mainwindow/recentFileList").toStringList().isEmpty())
3498         addToolBar (Qt::RightToolBarArea, colorsToolbar);
3499     else
3500         addToolBar (colorsToolbar);
3501
3502     // Zoom
3503     zoomToolbar = addToolBar(tr("View toolbar", "View Toolbar name"));
3504     zoomToolbar->setObjectName("viewTB");
3505     zoomToolbar->addAction(actionTogglePresentationMode);
3506     zoomToolbar->addAction(actionZoomIn);
3507     zoomToolbar->addAction(actionZoomOut);
3508     zoomToolbar->addAction(actionZoomReset);
3509     zoomToolbar->addAction(actionCenterOn);
3510     zoomToolbar->addAction(actionRotateCounterClockwise);
3511     zoomToolbar->addAction(actionRotateClockwise);
3512
3513     // Editors
3514     editorsToolbar = addToolBar(tr("Editors toolbar", "Editor Toolbar name"));
3515     editorsToolbar->setObjectName("editorsTB");
3516     editorsToolbar->addAction(actionViewToggleNoteEditor);
3517     editorsToolbar->addAction(actionViewToggleHeadingEditor);
3518     editorsToolbar->addAction(actionViewToggleTreeEditor);
3519     editorsToolbar->addAction(actionViewToggleTaskEditor);
3520     editorsToolbar->addAction(actionViewToggleSlideEditor);
3521     editorsToolbar->addAction(actionViewToggleScriptEditor);
3522     editorsToolbar->addAction(actionViewToggleHistoryWindow);
3523
3524     // Modifier modes
3525     modModesToolbar =
3526         addToolBar(tr("Modifier modes toolbar", "Modifier Toolbar name"));
3527     modModesToolbar->setObjectName("modesTB");
3528     modModesToolbar->addAction(actionModModePoint);
3529     modModesToolbar->addAction(actionModModeColor);
3530     modModesToolbar->addAction(actionModModeXLink);
3531     modModesToolbar->addAction(actionModModeMoveObject);
3532     modModesToolbar->addAction(actionModModeMoveView);
3533
3534     // Create flag toolbars (initialized later in setupFlagActions() )
3535     addToolBarBreak();
3536     standardFlagsToolbar =
3537         addToolBar(tr("Standard Flags toolbar", "Standard Flag Toolbar"));
3538     standardFlagsToolbar->setObjectName("standardFlagTB");
3539     standardFlagsMaster->setToolBar(standardFlagsToolbar);
3540
3541     userFlagsToolbar =
3542         addToolBar(tr("User Flags toolbar", "user Flags Toolbar"));
3543     userFlagsToolbar->setObjectName("userFlagsTB");
3544     userFlagsMaster->setToolBar(userFlagsToolbar);
3545     userFlagsMaster->createConfigureAction();
3546
3547     // Add all toolbars to View menu
3548     toolbarsMenu->addAction(fileToolbar->toggleViewAction());
3549     toolbarsMenu->addAction(clipboardToolbar->toggleViewAction());
3550     toolbarsMenu->addAction(editActionsToolbar->toggleViewAction());
3551     toolbarsMenu->addAction(selectionToolbar->toggleViewAction());
3552     toolbarsMenu->addAction(colorsToolbar->toggleViewAction());
3553     toolbarsMenu->addAction(zoomToolbar->toggleViewAction());
3554     toolbarsMenu->addAction(modModesToolbar->toggleViewAction());
3555     toolbarsMenu->addAction(referencesToolbar->toggleViewAction());
3556     toolbarsMenu->addAction(editorsToolbar->toggleViewAction());
3557     toolbarsMenu->addAction(userFlagsToolbar->toggleViewAction());
3558     toolbarsMenu->addAction(standardFlagsToolbar->toggleViewAction());
3559
3560     // Initialize toolbarStates for presentation mode
3561     toolbarStates[fileToolbar] = true;
3562     toolbarStates[clipboardToolbar] = true;
3563     toolbarStates[editActionsToolbar] = true;
3564     toolbarStates[selectionToolbar] = false;
3565     toolbarStates[colorsToolbar] = true;
3566     toolbarStates[zoomToolbar] = true;
3567     toolbarStates[modModesToolbar] = false;
3568     toolbarStates[referencesToolbar] = true;
3569     toolbarStates[editorsToolbar] = false;
3570     toolbarStates[standardFlagsToolbar] = true;
3571     toolbarStates[userFlagsToolbar] = true;
3572
3573     // Initialize toolbar visibilities and switch off presentation mode
3574     presentationMode = true;
3575     togglePresentationMode();
3576 }
3577
3578 VymView *Main::currentView() const
3579 {
3580     if (tabWidget->currentWidget())
3581         return (VymView *)tabWidget->currentWidget();
3582     else
3583         return nullptr;
3584 }
3585
3586 VymView *Main::view(const int i) { return (VymView *)tabWidget->widget(i); }
3587
3588 MapEditor *Main::currentMapEditor() const
3589 {
3590     if (tabWidget->currentWidget())
3591         return currentView()->getMapEditor();
3592     return nullptr;
3593 }
3594
3595 uint Main::currentMapID() const
3596 {
3597     VymModel *m = currentModel();
3598     if (m)
3599         return m->getModelID();
3600     else
3601         return 0;
3602 }
3603
3604 int Main::currentMapIndex() const { return tabWidget->currentIndex(); }
3605
3606 VymModel *Main::currentModel() const
3607 {
3608     VymView *vv = currentView();
3609     if (vv)
3610         return vv->getModel();
3611     else
3612         return NULL;
3613 }
3614
3615 VymModel *Main::getModel(uint id) // Used in BugAgent
3616 {
3617     if (id <= 0)
3618         return NULL;
3619
3620     for (int i = 0; i < tabWidget->count(); i++) {
3621         if (view(i)->getModel()->getModelID() == id)
3622             return view(i)->getModel();
3623     }
3624     return NULL;
3625 }
3626
3627 void Main::gotoModel(VymModel *m)
3628 {
3629     for (int i = 0; i < tabWidget->count(); i++)
3630         if (view(i)->getModel() == m) {
3631             tabWidget->setCurrentIndex(i);
3632             return;
3633         }
3634 }
3635
3636 void Main::gotoModelWithID(uint id)
3637 {
3638     VymModel *vm;
3639     for (int i = 0; i < tabWidget->count(); i++) {
3640         vm = view(i)->getModel();
3641         if (vm && vm->getModelID() == id) {
3642             tabWidget->setCurrentIndex(i);
3643             return;
3644         }
3645     }
3646 }
3647
3648 bool Main::closeModelWithID(uint id)
3649 {
3650     VymModel *vm;
3651     for (int i = 0; i < tabWidget->count(); i++) {
3652         vm = view(i)->getModel();
3653         if (vm && vm->getModelID() == id) {
3654             tabWidget->removeTab(i);
3655
3656             // Destroy stuff, order is important
3657             delete (vm->getMapEditor());
3658             delete (view(i));
3659             delete (vm);
3660
3661             updateActions();
3662             return true;
3663         }
3664     }
3665     return false;
3666 }
3667
3668 int Main::modelCount() { return tabWidget->count(); }
3669
3670 void Main::updateTabName(VymModel *vm)
3671 {
3672     if (!vm) {
3673         qWarning() << "Main::updateTabName   vm == NULL";
3674         return;
3675     }
3676
3677     for (int i = 0; i < tabWidget->count(); i++)
3678         if (view(i)->getModel() == vm) {
3679             if (vm->isReadOnly())
3680                 tabWidget->setTabText(i, vm->getFileName() + " " +
3681                                              tr("(readonly)"));
3682             else
3683                 tabWidget->setTabText(i, vm->getFileName());
3684             return;
3685         }
3686 }
3687
3688 void Main::editorChanged()
3689 {
3690     VymModel *vm = currentModel();
3691     if (vm) {
3692         BranchItem *bi = vm->getSelectedBranch();
3693         updateNoteEditor(bi);
3694         updateHeadingEditor(bi);
3695         updateQueries(vm);
3696         taskEditor->setMapName(vm->getMapName());
3697         updateDockWidgetTitles(vm);
3698     }
3699
3700     // Update actions to in menus and toolbars according to editor
3701     updateActions();
3702 }
3703
3704 void Main::fileNew()
3705 {
3706     VymModel *vm;
3707
3708     // Don't show counter while loading default map
3709     removeProgressCounter();
3710
3711     if (File::Success != fileLoad(newMapPath(), DefaultMap, VymMap)) {
3712         QMessageBox::critical(0, tr("Critical Error"),
3713                               tr("Couldn't load default map:\n\n%1\n\nvym will "
3714                                  "create an empty map now.",
3715                                  "Mainwindow: Failed to load default map")
3716                                   .arg(newMapPath()));
3717
3718         vm = currentModel();
3719
3720         // Create MapCenter for empty map  
3721         vm->addMapCenter(false);
3722         vm->makeDefault();
3723
3724         // For the very first map we do not have flagrows yet...
3725         vm->select("mc:");
3726
3727         // Set name to "unnamed"
3728         updateTabName(vm);
3729     }
3730     else {
3731         vm = currentModel();
3732     }
3733     
3734     // Switch to new tab    
3735     tabWidget->setCurrentIndex(tabWidget->count() - 1);
3736 }
3737
3738 void Main::fileNewCopy()
3739 {
3740     QString fn = "unnamed";
3741     VymModel *srcModel = currentModel();
3742     if (srcModel) {
3743         srcModel->copy();
3744         fileNew();
3745         VymModel *dstModel = view(tabWidget->count() - 1)->getModel();
3746         if (dstModel && dstModel->select("mc:0"))
3747             dstModel->paste();
3748         else
3749             qWarning() << "Main::fileNewCopy couldn't select mapcenter";
3750     }
3751 }
3752
3753 File::ErrorCode Main::fileLoad(QString fn, const LoadMode &lmode,
3754                                const FileType &ftype)
3755 {
3756     File::ErrorCode err = File::Success;
3757
3758     // fn is usually the archive, mapfile the file after uncompressing
3759     QString mapfile;
3760
3761     // Make fn absolute (needed for unzip)
3762     fn = QDir(fn).absolutePath();
3763
3764     VymModel *vm;
3765
3766     if (lmode == NewMap) {
3767         // Check, if map is already loaded
3768         int i = 0;
3769         while (i <= tabWidget->count() - 1) {
3770             if (view(i)->getModel()->getFilePath() == fn) {
3771                 // Already there, ask for confirmation
3772                 QMessageBox mb(
3773                     vymName,
3774                     tr("The map %1\nis already opened."
3775                        "Opening the same map in multiple editors may lead \n"
3776                        "to confusion when finishing working with vym."
3777                        "Do you want to")
3778                         .arg(fn),
3779                     QMessageBox::Warning,
3780                     QMessageBox::Yes | QMessageBox::Default,
3781                     QMessageBox::Cancel | QMessageBox::Escape,
3782                     QMessageBox::NoButton);
3783                 mb.setButtonText(QMessageBox::Yes, tr("Open anyway"));
3784                 mb.setButtonText(QMessageBox::Cancel, tr("Cancel"));
3785                 switch (mb.exec()) {
3786                 case QMessageBox::Yes:
3787                     // end loop and load anyway
3788                     i = tabWidget->count();
3789                     break;
3790                 case QMessageBox::Cancel:
3791                     // do nothing
3792                     return File::Aborted;
3793                     break;
3794                 }
3795             }
3796             i++;
3797         }
3798     }
3799
3800     bool createModel;
3801
3802     // Try to load map
3803     if (!fn.isEmpty()) {
3804         // Find out, if we need to create a new map model
3805
3806         vm = currentModel();
3807
3808         if (lmode == NewMap) {
3809             if (vm && vm->isDefault()) {
3810                 // There is a map model already and it still the default map,
3811                 // use it.
3812                 createModel = false;
3813             }
3814             else
3815                 createModel = true;
3816         }
3817         else if (lmode == DefaultMap) {
3818             createModel = true;
3819         }
3820         else if (lmode == ImportAdd || lmode == ImportReplace) {
3821             if (!vm) {
3822                 QMessageBox::warning(0, "Warning",
3823                                      "Trying to import into non existing map");
3824                 return File::Aborted;
3825             }
3826             else
3827                 createModel = false;
3828         }
3829         else
3830             createModel = true;
3831
3832         if (createModel) {
3833             vm = new VymModel;
3834             VymView *vv = new VymView(vm);
3835
3836             tabWidget->addTab(vv, fn);
3837             vv->initFocus();
3838         }
3839
3840         // Check, if file exists (important for creating new files
3841         // from command line
3842         if (!QFile(fn).exists()) {
3843             if (lmode == DefaultMap) {
3844                 return File::Aborted;
3845             }
3846
3847             if (lmode == NewMap) {
3848                 QMessageBox mb(vymName,
3849                                tr("This map does not exist:\n  %1\nDo you want "
3850                                   "to create a new one?")
3851                                    .arg(fn),
3852                                QMessageBox::Question, QMessageBox::Yes,
3853                                QMessageBox::Cancel | QMessageBox::Default,
3854                                QMessageBox::NoButton);
3855
3856                 mb.setButtonText(QMessageBox::Yes, tr("Create"));
3857                 mb.setButtonText(QMessageBox::No, tr("Cancel"));
3858
3859                 vm = currentMapEditor()->getModel();
3860                 switch (mb.exec()) {
3861                 case QMessageBox::Yes:
3862                     // Create new map
3863                     vm->setFilePath(fn);
3864                     updateTabName(vm);
3865                     statusBar()->showMessage("Created " + fn, statusbarTime);
3866                     return File::Success;
3867
3868                 case QMessageBox::Cancel:
3869                     // don't create new map
3870                     statusBar()->showMessage("Loading " + fn + " failed!",
3871                                              statusbarTime);
3872                     int cur = tabWidget->currentIndex();
3873                     tabWidget->setCurrentIndex(tabWidget->count() - 1);
3874                     fileCloseMap();
3875                     tabWidget->setCurrentIndex(cur);
3876                     return File::Aborted;
3877                 }
3878
3879                 // ImportAdd or ImportReplace
3880                 qWarning() << QString("Warning:  Could not import %1 into %2")
3881                                   .arg(fn)
3882                                   .arg(vm->getFilePath());
3883                 return File::Aborted;
3884             }
3885         }
3886
3887         if (err != File::Aborted) {
3888             // Save existing filename in case  we import
3889             QString fn_org = vm->getFilePath();
3890
3891             if (lmode != DefaultMap) {
3892
3893                 vm->setFilePath(fn);
3894                 vm->saveStateBeforeLoad(lmode, fn);
3895
3896                 progressDialog.setLabelText(
3897                     tr("Loading: %1", "Progress dialog while loading maps")
3898                         .arg(fn));
3899             }
3900
3901             // Finally load map into mapEditor
3902             err = vm->loadMap(fn, lmode, ftype);
3903
3904             // Restore old (maybe empty) filepath, if this is an import
3905             if (lmode == ImportAdd || lmode == ImportReplace)
3906                 vm->setFilePath(fn_org);
3907         }
3908
3909         // Finally check for errors and go home
3910         if (err == File::Aborted) {
3911             if (lmode == NewMap)
3912                 fileCloseMap();
3913             statusBar()->showMessage("Could not load " + fn, statusbarTime);
3914         }
3915         else {
3916             if (lmode == NewMap) {
3917                 vm->setFilePath(fn);
3918                 updateTabName(vm);
3919                 actionFilePrint->setEnabled(true);
3920                 addRecentMap(fn);
3921             }
3922             else if (lmode == DefaultMap) {
3923                 vm->makeDefault();
3924                 updateTabName(vm);
3925             }
3926             editorChanged();
3927             vm->emitShowSelection();
3928             statusBar()->showMessage("Loaded " + fn, statusbarTime);
3929         }
3930     }
3931
3932     fileSaveSession();
3933
3934     return err;
3935 }
3936
3937 void Main::fileLoad(const LoadMode &lmode)
3938 {
3939     QString caption;
3940     switch (lmode) {
3941     case NewMap:
3942         caption = vymName + " - " + tr("Load vym map");
3943         break;
3944     case DefaultMap:
3945         // Not used directly
3946         return;
3947     case ImportAdd:
3948         caption = vymName + " - " + tr("Import: Add vym map to selection");
3949         break;
3950     case ImportReplace:
3951         caption =
3952             vymName + " - " + tr("Import: Replace selection with vym map");
3953         break;
3954     }
3955
3956     QString filter;
3957     filter += "VYM map " + tr("or", "File Dialog") + " Freemind map" +
3958               " (*.xml *.vym *.vyp *.mm);;";
3959     filter += "VYM map (*.vym *.vyp);;";
3960     filter += "VYM Backups (*.vym~);;";
3961     filter += "Freemind map (*.mm);;";
3962     filter += "XML (*.xml);;";
3963     filter += "All (* *.*)";
3964     QStringList fns =
3965         QFileDialog::getOpenFileNames(this, caption, lastMapDir.path(), filter);
3966
3967     if (!fns.isEmpty()) {
3968         initProgressCounter(fns.count());
3969         lastMapDir.setPath(fns.first().left(fns.first().lastIndexOf("/")));
3970         foreach (QString fn, fns)
3971             fileLoad(fn, lmode, getMapType(fn));
3972     }
3973     removeProgressCounter();
3974 }
3975
3976 void Main::fileLoad()
3977 {
3978     fileLoad(NewMap);
3979     tabWidget->setCurrentIndex(tabWidget->count() - 1);
3980 }
3981
3982 void Main::fileSaveSession()
3983 {
3984     QStringList flist;
3985     for (int i = 0; i < tabWidget->count(); i++)
3986         flist.append(view(i)->getModel()->getFilePath());
3987
3988     settings.setValue("/mainwindow/sessionFileList", flist);
3989
3990     // Also called by event loop regulary, but apparently not often enough
3991     settings.sync();
3992 }
3993
3994 void Main::fileRestoreSession()
3995 {
3996     restoreMode = true;
3997
3998     QStringList::Iterator it = lastSessionFiles.begin();
3999
4000     initProgressCounter(lastSessionFiles.count());
4001     while (it != lastSessionFiles.end()) {
4002         FileType type = getMapType(*it);
4003         fileLoad(*it, NewMap, type);
4004         *it++;
4005     }
4006     removeProgressCounter();
4007
4008     // By now all files should have been loaded
4009     // Reset the restore flag and display message if needed
4010     if (ignoredLockedFiles.count() > 0) {
4011         QString msg(
4012             QObject::tr("Existing lockfiles have been ignored for the maps "
4013                         "listed below. Please check, if the maps might be "
4014                         "openend in another instance of vym:\n\n"));
4015         WarningDialog warn;
4016         warn.setMinimumWidth(800);
4017         warn.setMinimumHeight(350);
4018         warn.showCancelButton(false);
4019         warn.setCaption("Existing lockfiles ignored");
4020         warn.setText(msg + ignoredLockedFiles.join("\n"));
4021         warn.exec();
4022     }
4023
4024     restoreMode = false;
4025     ignoredLockedFiles.clear();
4026 }
4027
4028 void Main::fileLoadRecent()
4029 {
4030     QAction *action = qobject_cast<QAction *>(sender());
4031     if (action) {
4032         initProgressCounter();
4033         QString fn = action->data().toString();
4034         FileType type = getMapType(fn);
4035         fileLoad(fn, NewMap, type);
4036         removeProgressCounter();
4037         tabWidget->setCurrentIndex(tabWidget->count() - 1);
4038     }
4039 }
4040
4041 void Main::addRecentMap(const QString &fileName)
4042 {
4043
4044     QStringList files =
4045         settings.value("/mainwindow/recentFileList").toStringList();
4046     files.removeAll(fileName);
4047     files.prepend(fileName);
4048     while (files.size() > MaxRecentFiles)
4049         files.removeLast();
4050
4051     settings.setValue("/mainwindow/recentFileList", files);
4052
4053     setupRecentMapsMenu();
4054 }
4055
4056 void Main::fileSave(VymModel *m, const SaveMode &savemode)
4057 {
4058     if (!m)
4059         return;
4060
4061     if (m->isReadOnly())
4062         return;
4063
4064     if (m->getFilePath().isEmpty()) {
4065         // We have  no filepath yet,
4066         // call fileSaveAs() now, this will call fileSave()
4067         // again.  First switch to editor
4068         fileSaveAs(savemode);
4069         return; // avoid saving twice...
4070     }
4071
4072     if (m->save(savemode) == File::Success) {
4073         statusBar()->showMessage(tr("Saved  %1").arg(m->getFilePath()),
4074                                  statusbarTime);
4075     }
4076     else
4077         statusBar()->showMessage(tr("Couldn't save ").arg(m->getFilePath()),
4078                                  statusbarTime);
4079 }
4080
4081 void Main::fileSave() { fileSave(currentModel(), CompleteMap); }
4082
4083 void Main::fileSave(VymModel *m) { fileSave(m, CompleteMap); }
4084
4085 void Main::fileSaveAs(const SaveMode &savemode)
4086 {
4087     VymModel *m = currentModel();
4088     if (!m) return;
4089
4090     if (currentMapEditor()) {   // FIXME-2 this check is not needed
4091         QString filter;
4092         if (savemode == CompleteMap)
4093             filter = "VYM map (*.vym)";
4094         else
4095             filter = "VYM part of map (*vyp)";
4096         filter += ";;All (* *.*)";
4097
4098         // Get destination path
4099         QString fn = QFileDialog::getSaveFileName(
4100             this, tr("Save map as"), lastMapDir.path(), filter, NULL,
4101             QFileDialog::DontConfirmOverwrite);
4102         if (!fn.isEmpty()) {
4103             // Check for existing file
4104             if (QFile(fn).exists()) {
4105                 // Check if the existing file is writable
4106                 if (!QFileInfo(fn).isWritable()) {
4107                     QMessageBox::critical(0, tr("Critical Error"),
4108                                           tr("Couldn't save %1,\nbecause file "
4109                                              "exists and cannot be changed.")
4110                                               .arg(fn));
4111                     return;
4112                 }
4113
4114                 QMessageBox mb(
4115                     vymName,
4116                     tr("The file %1\nexists already. Do you want to").arg(fn),
4117                     QMessageBox::Warning,
4118                     QMessageBox::Yes | QMessageBox::Default,
4119                     QMessageBox::Cancel | QMessageBox::Escape,
4120                     QMessageBox::NoButton);
4121                 mb.setButtonText(QMessageBox::Yes, tr("Overwrite"));
4122                 mb.setButtonText(QMessageBox::Cancel, tr("Cancel"));
4123                 switch (mb.exec()) {
4124                 case QMessageBox::Yes:
4125                     // save
4126                     break;
4127                 case QMessageBox::Cancel:
4128                     // do nothing
4129                     return;
4130                     break;
4131                 }
4132                 lastMapDir.setPath(fn.left(fn.lastIndexOf("/")));
4133             }
4134             else {
4135                 // New file, add extension to filename, if missing
4136                 // This is always .vym or .vyp, depending on savemode
4137                 if (savemode == CompleteMap) {
4138                     if (!fn.contains(".vym") && !fn.contains(".xml"))
4139                         fn += ".vym";
4140                 }
4141                 else {
4142                     if (!fn.contains(".vyp") && !fn.contains(".xml"))
4143                         fn += ".vyp";
4144                 }
4145             }
4146
4147             // Save original filepath, might want to restore after saving
4148             QString fn_org = m->getFilePath();
4149
4150             // Check for existing lockfile
4151             QFile lockFile(fn + ".lock");
4152             if (lockFile.exists()) {
4153                 QMessageBox::critical(0, tr("Critical Error"),
4154                                       tr("Couldn't save %1,\nbecause of "
4155                                          "existing lockfile:\n\n%2")
4156                                           .arg(fn)
4157                                           .arg(lockFile.fileName()));
4158                 return;
4159             }
4160
4161             if (!m->renameMap(fn)) {
4162                 QMessageBox::critical(0, tr("Critical Error"),
4163                                       tr("Saving the map failed:\nCouldn't rename map to %1").arg(fn));
4164                 return; // FIXME-3 Check: If saved part of map and this error occurs?
4165             }
4166
4167             fileSave(m, savemode);
4168
4169             // Set name of tab
4170             if (savemode == CompleteMap)
4171                 updateTabName(m);
4172             else { // Renaming map to original name, because we only saved the
4173                    // selected part of it
4174                 m->setFilePath(fn_org);
4175                 if (!m->renameMap(fn_org)) {
4176                     QMessageBox::critical(0, "Critical Error",
4177                                           "Couldn't rename map back to " + fn_org);
4178                 }
4179             }
4180             return;
4181         }
4182     }
4183 }
4184
4185 void Main::fileSaveAs() { fileSaveAs(CompleteMap); }
4186
4187 void Main::fileSaveAsDefault()
4188 {
4189     if (currentMapEditor()) {
4190         QString fn = QFileDialog::getSaveFileName(
4191             this, tr("Save map as new default map"), newMapPath(),
4192             "VYM map (*.vym)", NULL, QFileDialog::DontConfirmOverwrite);
4193
4194         if (!fn.isEmpty()) {
4195             // Check for existing file
4196             if (QFile(fn).exists()) {
4197                 // Check if the existing file is writable
4198                 if (!QFileInfo(fn).isWritable()) {
4199                     QMessageBox::critical(
4200                         0, tr("Warning"),
4201                         tr("You have no permissions to write to ") + fn);
4202                     return;
4203                 }
4204
4205                 // Confirm overwrite of existing file
4206                 QMessageBox mb(
4207                     vymName,
4208                     tr("The file %1\nexists already. Do you want to").arg(fn),
4209                     QMessageBox::Warning,
4210                     QMessageBox::Yes | QMessageBox::Default,
4211                     QMessageBox::Cancel | QMessageBox::Escape,
4212                     QMessageBox::NoButton);
4213                 mb.setButtonText(QMessageBox::Yes,
4214                                  tr("Overwrite as new default map"));
4215                 mb.setButtonText(QMessageBox::Cancel, tr("Cancel"));
4216                 switch (mb.exec()) {
4217                 case QMessageBox::Yes:
4218                     // save
4219                     break;
4220                 case QMessageBox::Cancel:
4221                     // do nothing
4222                     return;
4223                     break;
4224                 }
4225             }
4226
4227             // Save now as new default
4228             VymModel *m = currentModel();
4229             QString fn_org = m->getFilePath(); // Restore fn later, if savemode
4230                                                // != CompleteMap
4231             // Check for existing lockfile
4232             QFile lockFile(fn + ".lock");
4233             if (lockFile.exists()) {
4234                 QMessageBox::critical(
4235                     0, tr("Critical Error"),
4236                     tr("Couldn't save %1,\nbecause of existing lockfile:\n\n%2")
4237                         .arg(fn)
4238                         .arg(lockFile.fileName()));
4239                 return;
4240             }
4241
4242             if (!m->renameMap(fn)) {
4243                 QMessageBox::critical(0, tr("Critical Error"),
4244                                       tr("Couldn't save as default, failed to rename to\n%1").arg(fn));
4245                 return;
4246             }
4247
4248             fileSave(m, CompleteMap);
4249
4250             // Set name of tab
4251             updateTabName(m);
4252
4253             // Set new default path
4254             settings.setValue("/system/defaultMap/auto", false);
4255             settings.setValue("/system/defaultMap/path", fn);
4256         }
4257     }
4258 }
4259
4260 void Main::fileImportFirefoxBookmarks()
4261 {
4262     VymModel *m = currentModel();
4263     if (!m) {
4264         fileNew();
4265         m = currentModel();
4266         if (!m) return;
4267     } else {
4268         if (!m->isDefault())
4269             // Import into new map
4270             fileNew();
4271     }
4272
4273     if (m) {
4274         // Try to select first mapcenter of default map
4275         if (!m->select("mc:0")) return;
4276
4277         m->setHeadingPlainText("Firefox");
4278
4279         // Try to add one branch and select it
4280         /*
4281         if (!m->addNewBranch()) return;
4282
4283         m->selectLatestAdded();
4284         m->setHeadingPlainText("Bookmarks");
4285         */
4286
4287         // Open file dialog
4288         QFileDialog fd;
4289         fd.setDirectory(vymBaseDir.homePath());
4290         fd.setFileMode(QFileDialog::ExistingFiles);
4291         QStringList filters;
4292         filters << tr("Firefox Bookmarks") + " (*.json)";
4293         fd.setNameFilters(filters);
4294         fd.setAcceptMode(QFileDialog::AcceptOpen);
4295         fd.setWindowTitle(tr("Import Firefox Bookmarks into new map"));
4296         fd.setLabelText( QFileDialog::Accept, tr("Import"));
4297
4298         if (fd.exec() == QDialog::Accepted) {
4299             qApp->processEvents(); // close QFileDialog
4300             ImportFirefoxBookmarks im(m);
4301             QStringList flist = fd.selectedFiles();
4302             QStringList::Iterator it = flist.begin();
4303             while (it != flist.end()) {
4304                 im.setFile(*it);
4305                 im.transform(); 
4306                 ++it;
4307             }
4308         }
4309     }
4310 }
4311
4312 void Main::fileImportFreemind()
4313 {
4314     QStringList filters;
4315     filters << "Freemind map (*.mm)"
4316             << "All files (*)";
4317     QFileDialog fd;
4318     fd.setDirectory(lastMapDir);
4319     fd.setFileMode(QFileDialog::ExistingFiles);
4320     fd.setNameFilters(filters);
4321     fd.setWindowTitle(vymName + " - " + tr("Open Freemind map"));
4322     fd.setAcceptMode(QFileDialog::AcceptOpen);
4323
4324     QString fn;
4325     if (fd.exec() == QDialog::Accepted) {
4326         lastMapDir = fd.directory();
4327         QStringList flist = fd.selectedFiles();
4328         QStringList::Iterator it = flist.begin();
4329         while (it != flist.end()) {
4330             fn = *it;
4331             if (fileLoad(fn, NewMap, FreemindMap)) {
4332                 currentMapEditor()->getModel()->setFilePath("");
4333             }
4334             ++it;
4335         }
4336     }
4337 }
4338
4339 void Main::fileImportMM()
4340 {
4341     ImportMM im;
4342
4343     QFileDialog fd;
4344     fd.setDirectory(lastMapDir);
4345     fd.setFileMode(QFileDialog::ExistingFiles);
4346     QStringList filters;
4347     filters << "Mind Manager (*.mmap)";
4348     fd.setNameFilters(filters);
4349     fd.setAcceptMode(QFileDialog::AcceptOpen);
4350     fd.setWindowTitle(tr("Import") + " " + "Mind Manager");
4351     fd.setLabelText( QFileDialog::Accept, tr("Import"));
4352
4353     if (fd.exec() == QDialog::Accepted) {
4354         lastMapDir = fd.directory();
4355         QStringList flist = fd.selectedFiles();
4356         QStringList::Iterator it = flist.begin();
4357         while (it != flist.end()) {
4358             im.setFile(*it);
4359             if (im.transform() &&
4360                 File::Success ==
4361                     fileLoad(im.getTransformedFile(), NewMap, VymMap) &&
4362                 currentMapEditor())
4363                 currentMapEditor()->getModel()->setFilePath("");
4364             ++it;
4365         }
4366     }
4367 }
4368
4369 void Main::fileImportDir()
4370 {
4371     VymModel *m = currentModel();
4372     if (m)
4373         m->importDir();
4374 }
4375
4376 void Main::fileExportAO()
4377 {
4378     VymModel *m = currentModel();
4379     if (m)
4380         m->exportAO();
4381 }
4382
4383 void Main::fileExportASCII()
4384 {
4385     VymModel *m = currentModel();
4386     if (m)
4387         m->exportASCII();
4388 }
4389
4390 void Main::fileExportASCIITasks()
4391 {
4392     VymModel *m = currentModel();
4393     if (m)
4394         m->exportASCII("", true);
4395 }
4396
4397 void Main::fileExportConfluence()
4398 {
4399     VymModel *m = currentModel();
4400     if (m)
4401         m->exportConfluence();
4402 }
4403
4404 #include "export-csv.h"
4405 void Main::fileExportCSV() // FIXME-3 not scriptable yet
4406 {
4407     VymModel *m = currentModel();
4408     if (m) {
4409         ExportCSV ex;
4410         ex.setModel(m);
4411         ex.addFilter("CSV (*.csv)");
4412         ex.setDirPath(lastImageDir.absolutePath());
4413         ex.setWindowTitle(vymName + " -" + tr("Export as CSV") + " " +
4414                           tr("(still experimental)"));
4415         if (ex.execDialog()) {
4416             m->setExportMode(true);
4417             ex.doExport();
4418             m->setExportMode(false);
4419         }
4420     }
4421 }
4422
4423 void Main::fileExportFirefoxBookmarks()
4424 {
4425     VymModel *m = currentModel();
4426     if (m)
4427         m->exportFirefoxBookmarks();
4428 }
4429
4430 void Main::fileExportHTML()
4431 {
4432     VymModel *m = currentModel();
4433     if (m)
4434         m->exportHTML();
4435 }
4436
4437 void Main::fileExportImage()
4438 {
4439     VymModel *m = currentModel();
4440     if (m)
4441         m->exportImage();
4442 }
4443
4444 #include "export-impress.h"
4445 #include "exportoofiledialog.h"
4446 void Main::fileExportImpress()
4447 {
4448     ExportOOFileDialog fd;
4449     // TODO add preview in dialog
4450     fd.setWindowTitle(vymName + " - " + tr("Export to") + " LibreOffice");
4451     fd.setDirectory(QDir().current());
4452     fd.setAcceptMode(QFileDialog::AcceptSave);
4453     fd.setFileMode(QFileDialog::AnyFile);
4454     if (fd.foundConfig()) {
4455         if (fd.exec() == QDialog::Accepted) {
4456             if (!fd.selectedFiles().isEmpty()) {
4457                 QString fn = fd.selectedFiles().first();
4458                 if (!fn.contains(".odp"))
4459                     fn += ".odp";
4460
4461                 // lastImageDir=fn.left(fn.findRev ("/"));
4462                 VymModel *m = currentModel();
4463                 if (m)
4464                     m->exportImpress(fn, fd.selectedConfig());
4465             }
4466         }
4467     }
4468     else {
4469         QMessageBox::warning(
4470             0, tr("Warning"),
4471             tr("Couldn't find configuration for export to LibreOffice\n"));
4472     }
4473 }
4474
4475 #include "export-latex.h"
4476 void Main::fileExportLaTeX()
4477 {
4478     VymModel *m = currentModel();
4479     if (m)
4480         m->exportLaTeX();
4481 }
4482
4483 void Main::fileExportMarkdown()
4484 {
4485     VymModel *m = currentModel();
4486     if (m)
4487         m->exportMarkdown();
4488 }
4489
4490 void Main::fileExportOrgMode()
4491 {
4492     VymModel *m = currentModel();
4493     if (m)
4494         m->exportOrgMode();
4495 }
4496
4497 void Main::fileExportPDF()
4498 {
4499     VymModel *m = currentModel();
4500     if (m)
4501         m->exportPDF();
4502 }
4503
4504 void Main::fileExportSVG()
4505 {
4506     VymModel *m = currentModel();
4507     if (m)
4508         m->exportSVG();
4509 }
4510
4511 #include "export-taskjuggler.h"
4512 void Main::fileExportTaskjuggler() // FIXME-3 not scriptable yet
4513 {
4514     ExportTaskjuggler ex;
4515     VymModel *m = currentModel();
4516     if (m) {
4517         ex.setModel(m);
4518         ex.setWindowTitle(vymName + " - " + tr("Export to") + " Taskjuggler" +
4519                           tr("(still experimental)"));
4520         ex.setDirPath(lastImageDir.absolutePath());
4521         ex.addFilter("Taskjuggler (*.tjp)");
4522
4523         if (ex.execDialog()) {
4524             m->setExportMode(true);
4525             ex.doExport();
4526             m->setExportMode(false);
4527         }
4528     }
4529 }
4530
4531 void Main::fileExportXML()
4532 {
4533     VymModel *m = currentModel();
4534     if (m)
4535         m->exportXML();
4536 }
4537
4538 void Main::fileExportLast()
4539 {
4540     VymModel *m = currentModel();
4541     if (m)
4542         m->exportLast();
4543 }
4544
4545 bool Main::fileCloseMap(int i)
4546 {
4547     VymModel *m;
4548     VymView *vv;
4549     if (i < 0)
4550         i = tabWidget->currentIndex();
4551
4552     vv = view(i);
4553     m = vv->getModel();
4554
4555     if (m) {
4556         if (m->hasChanged()) {
4557             QMessageBox mb(
4558                 vymName,
4559                 tr("The map %1 has been modified but not saved yet. Do you "
4560                    "want to")
4561                     .arg(m->getFileName()),
4562                 QMessageBox::Warning, QMessageBox::Yes | QMessageBox::Default,
4563                 QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape);
4564             mb.setButtonText(QMessageBox::Yes,
4565                              tr("Save modified map before closing it"));
4566             mb.setButtonText(QMessageBox::No, tr("Discard changes"));
4567             mb.setModal(true);
4568             mb.show();
4569             switch (mb.exec()) {
4570             case QMessageBox::Yes:
4571                 // save and close
4572                 fileSave(m, CompleteMap);
4573                 break;
4574             case QMessageBox::No:
4575                 // close  without saving
4576                 break;
4577             case QMessageBox::Cancel:
4578                 // do nothing
4579                 return true;
4580             }
4581         }
4582
4583         tabWidget->removeTab(i);
4584
4585         // Destroy stuff, order is important
4586         delete (m->getMapEditor());
4587         delete (vv);
4588         delete (m);
4589
4590         updateActions();
4591         return false;
4592     }
4593     return true; // Better don't exit vym if there is no currentModel()...
4594 }
4595
4596 void Main::filePrint()
4597 {
4598     if (currentMapEditor())
4599         currentMapEditor()->print();
4600 }
4601
4602 bool Main::fileExitVYM()
4603 {
4604     fileSaveSession();
4605
4606     // Check if one or more editors have changed
4607     while (tabWidget->count() > 0) {
4608         tabWidget->setCurrentIndex(0);
4609         if (fileCloseMap())
4610             return true;
4611         qApp->processEvents(); // Update widgets to show progress
4612     }
4613     qApp->quit();
4614     return false;
4615 }
4616
4617 void Main::editUndo()
4618 {
4619     VymModel *m = currentModel();
4620     if (m)
4621         m->undo();
4622 }
4623
4624 void Main::editRedo()
4625 {
4626     VymModel *m = currentModel();
4627     if (m)
4628         m->redo();
4629 }
4630
4631 void Main::gotoHistoryStep(int i)
4632 {
4633     VymModel *m = currentModel();
4634     if (m)
4635         m->gotoHistoryStep(i);
4636 }
4637
4638 void Main::editCopy()
4639 {
4640     VymModel *m = currentModel();
4641     if (m)
4642         m->copy();
4643 }
4644
4645 void Main::editPaste()
4646 {
4647     VymModel *m = currentModel();
4648     if (m)
4649         m->paste();
4650 }
4651
4652 void Main::editCut()
4653 {
4654     VymModel *m = currentModel();
4655     if (m)
4656         m->cut();
4657 }
4658
4659 bool Main::openURL(const QString &url)
4660 {
4661     if (url.isEmpty())
4662         return false;
4663
4664     QString browser = settings.value("/system/readerURL").toString();
4665     QStringList args;
4666     args << url;
4667     if (!QProcess::startDetached(browser, args, QDir::currentPath(),
4668                                  browserPID)) {
4669         // try to set path to browser
4670         QMessageBox::warning(
4671             0, tr("Warning"),
4672             tr("Couldn't find a viewer to open %1.\n").arg(url) +
4673                 tr("Please use Settings->") +
4674                 tr("Set application to open an URL"));
4675         settingsURL();
4676         return false;
4677     }
4678     return true;
4679 }
4680
4681 void Main::openTabs(QStringList urls)
4682 {
4683     if (urls.isEmpty())
4684         return;
4685
4686     // Other browser, e.g. xdg-open
4687     // Just open all urls and leave it to the system to cope with it
4688     foreach (QString u, urls)
4689         openURL(u);
4690 }
4691
4692 void Main::editOpenURL()
4693 {
4694     // Open new browser
4695     VymModel *m = currentModel();
4696     if (m) {
4697         QString url = m->getURL();
4698         if (url == "")
4699             return;
4700         openURL(url);
4701     }
4702 }
4703 void Main::editOpenURLTab()
4704 {
4705     VymModel *m = currentModel();
4706     if (m) {
4707         QStringList urls;
4708         urls.append(m->getURL());
4709         openTabs(urls);
4710     }
4711 }
4712
4713 void Main::editOpenMultipleVisURLTabs(bool ignoreScrolled)
4714 {
4715     VymModel *m = currentModel();
4716     if (m) {
4717         QStringList urls;
4718         urls = m->getURLs(ignoreScrolled);
4719         openTabs(urls);
4720     }
4721 }
4722
4723 void Main::editOpenMultipleURLTabs() { editOpenMultipleVisURLTabs(false); }
4724
4725 void Main::editNote2URLs()
4726 {
4727     VymModel *m = currentModel();
4728     if (m)
4729         m->note2URLs();
4730 }
4731
4732 void Main::editURL()
4733 {
4734     VymModel *m = currentModel();
4735     if (m) {
4736         QInputDialog *dia = new QInputDialog(this);
4737         dia->setLabelText(tr("Enter URL:"));
4738         dia->setWindowTitle(vymName);
4739         dia->setInputMode(QInputDialog::TextInput);
4740         TreeItem *selti = m->getSelectedItem();
4741         if (selti)
4742             dia->setTextValue(selti->getURL());
4743         dia->resize(width() * 0.6, 80);
4744         centerDialog(dia);
4745
4746         if (dia->exec())
4747             m->setURL(dia->textValue());
4748         delete dia;
4749     }
4750 }
4751
4752 void Main::editLocalURL()
4753 {
4754     VymModel *m = currentModel();
4755     if (m) {
4756         TreeItem *selti = m->getSelectedItem();
4757         if (selti) {
4758             QString filter;
4759             filter += "All files (*);;";
4760             filter += tr("HTML", "Filedialog") + " (*.html,*.htm);;";
4761             filter += tr("Text", "Filedialog") + " (*.txt);;";
4762             filter += tr("Spreadsheet", "Filedialog") + " (*.odp,*.sxc);;";
4763             filter += tr("Textdocument", "Filedialog") + " (*.odw,*.sxw);;";
4764             filter += tr("Images", "Filedialog") +
4765                       " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)";
4766
4767             QString fn = QFileDialog::getOpenFileName(
4768                 this, vymName + " - " + tr("Set URL to a local file"),
4769                 lastMapDir.path(), filter);
4770
4771             if (!fn.isEmpty()) {
4772                 lastMapDir.setPath(fn.left(fn.lastIndexOf("/")));
4773                 if (!fn.startsWith("file://"))
4774                     fn = "file://" + fn;
4775                 m->setURL(fn);
4776             }
4777         }
4778     }
4779 }
4780
4781 void Main::editHeading2URL()
4782 {
4783     VymModel *m = currentModel();
4784     if (m)
4785         m->editHeading2URL();
4786 }
4787
4788 void Main::getJiraDataSubtree()
4789 {
4790     VymModel *m = currentModel();
4791     if (m)
4792         m->getJiraData(true);
4793 }
4794
4795 void Main::setHeadingConfluencePageName()
4796 {
4797     VymModel *m = currentModel();
4798     if (m)
4799         m->setHeadingConfluencePageName();
4800 }
4801
4802 void Main::getConfluenceUser()
4803 {
4804     VymModel *m = currentModel();
4805     if (m) {
4806         BranchItem *selbi = m->getSelectedBranch();
4807         if (selbi) {
4808             ConfluenceUserDialog *dia = new ConfluenceUserDialog;
4809             centerDialog(dia);
4810             if (dia->exec() > 0) {
4811                 BranchItem *bi = m->addNewBranch();
4812                 if (!bi) return;
4813                 if (!m->select(bi)) return;
4814                 selbi = m->getSelectedBranch();
4815
4816                 ConfluenceUser user = dia->getSelectedUser();
4817
4818                 AttributeItem *ai;
4819
4820                 ai = new AttributeItem();
4821                 ai->setKey("ConfluenceUser.displayName");
4822                 ai->setValue(user.getDisplayName());
4823                 m->setAttribute(selbi, ai);
4824
4825                 ai = new AttributeItem();
4826                 ai->setKey("ConfluenceUser.userKey");
4827                 ai->setValue(user.getUserKey());
4828                 m->setAttribute(selbi, ai);
4829
4830                 ai = new AttributeItem();
4831                 ai->setKey("ConfluenceUser.userName");
4832                 ai->setValue(user.getUserName());
4833                 m->setAttribute(selbi, ai);
4834
4835                 ai = new AttributeItem();
4836                 ai->setKey("ConfluenceUser.url");
4837                 ai->setValue(user.getURL());
4838                 m->setAttribute(selbi, ai);
4839
4840                 m->setURL(user.getURL(), false);
4841                 m->setHeading(user.getDisplayName());
4842
4843                 m->selectParent();
4844             }
4845             dia->clearFocus();
4846             delete dia;
4847             m->getMapEditor()->activateWindow();
4848             m->getMapEditor()->setFocus();
4849         }
4850     }
4851 }
4852
4853 void Main::editHeading()
4854 {
4855     MapEditor *me = currentMapEditor();
4856     if (me)
4857         me->editHeading();
4858 }
4859
4860 void Main::editHeadingFinished(VymModel *m)
4861 {
4862     if (m) {
4863         if (!actionSettingsAutoSelectNewBranch->isChecked() &&
4864             !prevSelection.isEmpty())
4865             m->select(prevSelection);
4866         prevSelection = "";
4867     }
4868 }
4869
4870 void Main::openVymLinks(const QStringList &vl, bool background)
4871 {
4872     QStringList vlmin;
4873     int index = -1;
4874     for (int j = 0; j < vl.size(); ++j) {
4875         // compare path with already loaded maps
4876         QString absPath = QFileInfo(vl.at(j)).absoluteFilePath();
4877         index = -1;
4878         for (int i = 0; i <= tabWidget->count() - 1; i++) {
4879             if (absPath == view(i)->getModel()->getFilePath()) {
4880                 index = i;
4881                 break;
4882             }
4883         }
4884         if (index < 0)
4885             vlmin.append(absPath);
4886     }
4887
4888     progressCounterTotal = vlmin.size();
4889     for (int j = 0; j < vlmin.size(); j++) {
4890         // Load map
4891         if (!QFile(vlmin.at(j)).exists())
4892             QMessageBox::critical(0, tr("Critical Error"),
4893                                   tr("Couldn't open map %1").arg(vlmin.at(j)));
4894         else {
4895             fileLoad(vlmin.at(j), NewMap, VymMap);
4896             if (!background)
4897                 tabWidget->setCurrentIndex(tabWidget->count() - 1);
4898         }
4899     }
4900     // Go to tab containing the map
4901     if (index >= 0)
4902         tabWidget->setCurrentIndex(index);
4903     removeProgressCounter();
4904 }
4905
4906 void Main::editOpenVymLink(bool background)
4907 {
4908     VymModel *m = currentModel();
4909     if (m) {
4910         QStringList vl;
4911         vl.append(m->getVymLink());
4912         openVymLinks(vl, background);
4913     }
4914 }
4915
4916 void Main::editOpenVymLinkBackground() { editOpenVymLink(true); }
4917
4918 void Main::editOpenMultipleVymLinks()
4919 {
4920     QString currentVymLink;
4921     VymModel *m = currentModel();
4922     if (m) {
4923         QStringList vl = m->getVymLinks();
4924         openVymLinks(vl, true);
4925     }
4926 }
4927
4928 void Main::editVymLink()
4929 {
4930     VymModel *m = currentModel();
4931     if (m) {
4932         BranchItem *bi = m->getSelectedBranch();
4933         if (bi) {
4934             QStringList filters;
4935             filters << "VYM map (*.vym)";
4936             QFileDialog fd;
4937             fd.setWindowTitle(vymName + " - " + tr("Link to another vym map"));
4938             fd.setNameFilters(filters);
4939             fd.setLabelText( QFileDialog::Accept, tr("Set as link to vym map"));
4940             fd.setDirectory(lastMapDir);
4941             fd.setAcceptMode(QFileDialog::AcceptOpen);
4942             if (!bi->getVymLink().isEmpty())
4943                 fd.selectFile(bi->getVymLink());
4944             fd.show();
4945
4946             QString fn;
4947             if (fd.exec() == QDialog::Accepted &&
4948                 !fd.selectedFiles().isEmpty()) {
4949                 QString fn = fd.selectedFiles().first();
4950                 lastMapDir = QDir(fd.directory().path());
4951                 m->setVymLink(fn);
4952             }
4953         }
4954     }
4955 }
4956
4957 void Main::editDeleteVymLink()
4958 {
4959     VymModel *m = currentModel();
4960     if (m)
4961         m->deleteVymLink();
4962 }
4963
4964 void Main::editToggleHideExport()
4965 {
4966     VymModel *m = currentModel();
4967     if (m)
4968         m->toggleHideExport();
4969 }
4970
4971 void Main::editToggleTask()
4972 {
4973     VymModel *m = currentModel();
4974     if (m)
4975         m->toggleTask();
4976 }
4977
4978 void Main::editCycleTaskStatus()
4979 {
4980     VymModel *m = currentModel();
4981     if (m)
4982         m->cycleTaskStatus();
4983 }
4984
4985 void Main::editTaskResetDeltaPrio() // FIXME-2 With multiple selections enabled, old selection should be restored
4986 {
4987     QList <Task*> tasks;
4988     QList <VymModel*> models;
4989     for (int i = 0; i < taskModel->count(); i++)
4990     {
4991         Task *task = taskModel->getTask(i);
4992         if (taskEditor->taskVisible(task) && task->getPriorityDelta() != 0) {
4993             tasks << task;
4994             VymModel *m = task->getBranch()->getModel();
4995             if (!models.contains(m))
4996                 models << m;
4997         }
4998     }
4999
5000     foreach (VymModel *model, models) {
5001         // Unselect everything
5002         model->unselectAll();
5003
5004         // Select all branches, where tasks whill be updated
5005         foreach (Task *task, tasks) {
5006             BranchItem *bi = task->getBranch();
5007             if (bi->getModel() == model) {
5008                 model->selectToggle(bi);
5009             }
5010         }
5011
5012         // Bulk update all branches in this model
5013         model->setTaskPriorityDelta(0);
5014     }
5015 }
5016
5017 void Main::editTaskSleepN()
5018 {
5019     VymModel *m = currentModel();
5020     if (m) {
5021         qint64 n = ((QAction *)sender())->data().toInt();
5022         Task *task = m->getSelectedTask();
5023         if (task) {
5024             bool ok = true;
5025             QString s;
5026             if (n < 0) {
5027                 QString currentSleep;
5028                 QDateTime d = task->getSleep();
5029                 n = task->getSecsSleep();
5030                 if (n <= 0)
5031                     currentSleep = "0";
5032                 else if (n < 60)
5033                     currentSleep = QString("%1s").arg(n);
5034                 else if (n < 24 * 3600) {
5035                     currentSleep = d.time().toString("hh:mm");
5036                 }
5037                 else if (d.time().hour() == 0 && d.time().minute() == 0) {
5038                     currentSleep = d.date().toString("dd.MM.yyyy");
5039                 }
5040                 else
5041                     currentSleep = d.toString(Qt::ISODate);
5042
5043                 LineEditDialog *dia = new LineEditDialog(this);
5044                 dia->setLabel(tr("Enter sleep time (number of days, hours with "
5045                                  "'h' or date YYYY-MM-DD or DD.MM[.YYYY]",
5046                                  "task sleep time dialog"));
5047                 dia->setText(currentSleep);
5048                 centerDialog(dia);
5049                 if (dia->exec() == QDialog::Accepted) {
5050                     ok = true;
5051                     s = dia->getText();
5052                 }
5053                 else
5054                     ok = false;
5055
5056                 delete dia;
5057             }
5058             else
5059                 s = QString("%1").arg(n);
5060
5061             if (ok && !m->setTaskSleep(s))
5062                 QMessageBox::warning(
5063                     0, tr("Warning"),
5064                     tr("Couldn't set sleep time to %1.\n").arg(s));
5065         }
5066     }
5067 }
5068
5069 void Main::editAddTimestamp()
5070 {
5071     VymModel *m = currentModel();
5072     if (m)
5073         m->addTimestamp();
5074 }
5075
5076 void Main::editMapProperties()
5077 {
5078     VymModel *m = currentModel();
5079     if (!m)
5080         return;
5081
5082     ExtraInfoDialog dia;
5083     dia.setMapName(m->getFileName());
5084     dia.setFileLocation(m->getFilePath());
5085     dia.setMapTitle(m->getTitle());
5086     dia.setAuthor(m->getAuthor());
5087     dia.setComment(m->getComment());
5088     dia.setReadOnly(m->isReadOnly());
5089
5090     // Calc some stats
5091     QString stats;
5092     stats += tr("%1 items on map\n", "Info about map")
5093                  .arg(m->getScene()->items().size(), 6);
5094
5095     uint b = 0;
5096     uint f = 0;
5097     uint n = 0;
5098     uint xl = 0;
5099     BranchItem *cur = NULL;
5100     BranchItem *prev = NULL;
5101     m->nextBranch(cur, prev);
5102     while (cur) {
5103         if (!cur->getNote().isEmpty())
5104             n++;
5105         f += cur->imageCount();
5106         b++;
5107         xl += cur->xlinkCount();
5108         m->nextBranch(cur, prev);
5109     }
5110
5111     stats += QString("%1 %2\n")
5112                  .arg(m->branchCount(), 6)
5113                  .arg(tr("branches", "Info about map"));
5114     stats += QString("%1 %2\n")
5115                  .arg(taskModel->count(), 6)
5116                  .arg(tr("tasks total", "Info about map"));
5117     stats += QString("%1 %2\n")
5118                  .arg(taskModel->count(m), 6)
5119                  .arg(tr("tasks in map", "Info about map"));
5120     stats += QString("%1 %2\n").arg(n, 6).arg(tr("notes", "Info about map"));
5121     stats += QString("%1 %2\n").arg(f, 6).arg(tr("images", "Info about map"));
5122     stats += QString("%1 %2\n")
5123                  .arg(m->slideCount(), 6)
5124                  .arg(tr("slides", "Info about map"));
5125     stats +=
5126         QString("%1 %2\n").arg(xl / 2, 6).arg(tr("xLinks", "Info about map"));
5127     dia.setStats(stats);
5128
5129     // Finally show dialog
5130     if (dia.exec() == QDialog::Accepted) {
5131         m->setAuthor(dia.getAuthor());
5132         m->setComment(dia.getComment());
5133         m->setTitle(dia.getMapTitle());
5134     }
5135 }
5136
5137 void Main::editMoveUp()
5138 {
5139     MapEditor *me = currentMapEditor();
5140     VymModel *m = currentModel();
5141     if (me && m && me->getState() != MapEditor::EditingHeading)
5142         m->moveUp();
5143 }
5144
5145 void Main::editMoveDown()
5146 {
5147     MapEditor *me = currentMapEditor();
5148     VymModel *m = currentModel();
5149     if (me && m && me->getState() != MapEditor::EditingHeading)
5150         m->moveDown();
5151 }
5152
5153 void Main::editMoveDownDiagonally()
5154 {
5155     MapEditor *me = currentMapEditor();
5156     VymModel *m = currentModel();
5157     if (me && m && me->getState() != MapEditor::EditingHeading)
5158         m->moveDownDiagonally();
5159 }
5160
5161 void Main::editMoveUpDiagonally()
5162 {
5163     MapEditor *me = currentMapEditor();
5164     VymModel *m = currentModel();
5165     if (me && m && me->getState() != MapEditor::EditingHeading)
5166         m->moveUpDiagonally();
5167 }
5168
5169 void Main::editDetach()
5170 {
5171     VymModel *m = currentModel();
5172     if (m)
5173         m->detach();
5174 }
5175
5176 void Main::editSortChildren()
5177 {
5178     VymModel *m = currentModel();
5179     if (m)
5180         m->sortChildren(false);
5181 }
5182
5183 void Main::editSortBackChildren()
5184 {
5185     VymModel *m = currentModel();
5186     if (m)
5187         m->sortChildren(true);
5188 }
5189
5190 void Main::editToggleScroll()
5191 {
5192     VymModel *m = currentModel();
5193     if (m)
5194         m->toggleScroll();
5195 }
5196
5197 void Main::editExpandAll()
5198 {
5199     VymModel *m = currentModel();
5200     if (m)
5201         m->emitExpandAll();
5202 }
5203
5204 void Main::editExpandOneLevel()
5205 {
5206     VymModel *m = currentModel();
5207     if (m)
5208         m->emitExpandOneLevel();
5209 }
5210
5211 void Main::editCollapseOneLevel()
5212 {
5213     VymModel *m = currentModel();
5214     if (m)
5215         m->emitCollapseOneLevel();
5216 }
5217
5218 void Main::editCollapseUnselected()
5219 {
5220     VymModel *m = currentModel();
5221     if (m)
5222         m->emitCollapseUnselected();
5223 }
5224
5225 void Main::editUnscrollChildren()
5226 {
5227     VymModel *m = currentModel();
5228     if (m)
5229         m->unscrollChildren();
5230 }
5231
5232 void Main::editGrowSelectionSize()
5233 {
5234     VymModel *m = currentModel();
5235     if (m)
5236         m->growSelectionSize();
5237 }
5238
5239 void Main::editShrinkSelectionSize()
5240 {
5241     VymModel *m = currentModel();
5242     if (m)
5243         m->shrinkSelectionSize();
5244 }
5245
5246 void Main::editResetSelectionSize()
5247 {
5248     VymModel *m = currentModel();
5249     if (m)
5250         m->resetSelectionSize();
5251 }
5252
5253 void Main::editAddAttribute()
5254 {
5255     VymModel *m = currentModel();
5256     if (m) {
5257
5258         m->setAttribute();
5259     }
5260 }
5261
5262 void Main::editAddMapCenter()
5263 {
5264     VymModel *m = currentModel();
5265     if (m) {
5266         m->select(m->addMapCenter());
5267         MapEditor *me = currentMapEditor();
5268         if (me) {
5269             m->setHeadingPlainText("");
5270             me->editHeading();
5271         }
5272     }
5273 }
5274
5275 void Main::editNewBranch()
5276 {
5277     VymModel *m = currentModel();
5278     if (m) {
5279         BranchItem *bi = m->addNewBranch();
5280         if (!bi)
5281             return;
5282
5283         if (!actionSettingsAutoSelectNewBranch->isChecked())
5284             prevSelection = m->getSelectString();
5285
5286         m->select(bi);
5287         currentMapEditor()->editHeading();
5288     }
5289 }
5290
5291 void Main::editNewBranchBefore()
5292 {
5293     VymModel *m = currentModel();
5294     if (m) {
5295         if (!actionSettingsAutoSelectNewBranch->isChecked())
5296             prevSelection = m->getSelectString();
5297
5298         BranchItem *bi = m->addNewBranchBefore();
5299
5300         if (bi)
5301             m->select(bi);
5302         else
5303             return;
5304
5305         currentMapEditor()->editHeading();
5306     }
5307 }
5308
5309 void Main::editNewBranchAbove()
5310 {
5311     VymModel *m = currentModel();
5312     if (m) {
5313         if (!actionSettingsAutoSelectNewBranch->isChecked())
5314             prevSelection = m->getSelectString();
5315
5316         BranchItem *selbi = m->getSelectedBranch();
5317         if (selbi) {
5318             BranchItem *bi = m->addNewBranch(selbi, -3);
5319
5320             if (bi)
5321                 m->select(bi);
5322             else
5323                 return;
5324
5325             currentMapEditor()->editHeading();
5326         }
5327     }
5328 }
5329
5330 void Main::editNewBranchBelow()
5331 {
5332     VymModel *m = currentModel();
5333     if (m) {
5334         BranchItem *selbi = m->getSelectedBranch();
5335         if (selbi) {
5336             BranchItem *bi = m->addNewBranch(selbi, -1);
5337
5338             if (bi)
5339                 m->select(bi);
5340             else
5341                 return;
5342
5343             if (!actionSettingsAutoSelectNewBranch->isChecked())
5344                 prevSelection = m->getSelectString(bi);
5345
5346             currentMapEditor()->editHeading();
5347         }
5348     }
5349 }
5350
5351 void Main::editImportAdd() { fileLoad(ImportAdd); }
5352
5353 void Main::editImportReplace() { fileLoad(ImportReplace); }
5354
5355 void Main::editSaveBranch() { fileSaveAs(PartOfMap); }
5356
5357 void Main::editDeleteKeepChildren()
5358 {
5359     VymModel *m = currentModel();
5360     if (m)
5361         m->deleteKeepChildren();
5362 }
5363
5364 void Main::editDeleteChildren()
5365 {
5366     VymModel *m = currentModel();
5367     if (m)
5368         m->deleteChildren();
5369 }
5370
5371 void Main::editDeleteSelection()
5372 {
5373     VymModel *m = currentModel();
5374     if (m)
5375         m->deleteSelection();
5376 }
5377
5378 void Main::editLoadImage()
5379 {
5380     VymModel *m = currentModel();
5381     if (m)
5382         m->loadImage();
5383 }
5384
5385 void Main::editSaveImage()
5386 {
5387     VymModel *m = currentModel();
5388     if (m)
5389         m->saveImage();
5390 }
5391
5392 void Main::editEditXLink(QAction *a)
5393 {
5394     VymModel *m = currentModel();
5395     if (m) {
5396         BranchItem *selbi = m->getSelectedBranch();
5397         if (selbi) {
5398             Link *l = selbi
5399                           ->getXLinkItemNum(
5400                               branchXLinksContextMenuEdit->actions().indexOf(a))
5401                           ->getLink();
5402             if (l && m->select(l->getBeginLinkItem()))
5403                 m->editXLink();
5404         }
5405     }
5406 }
5407
5408 void Main::popupFollowXLink()
5409 {
5410     branchXLinksContextMenuFollow->exec(QCursor::pos());
5411 }
5412
5413 void Main::editFollowXLink(QAction *a)
5414 {
5415     VymModel *m = currentModel();
5416
5417     if (m)
5418         m->followXLink(branchXLinksContextMenuFollow->actions().indexOf(a));
5419 }
5420
5421 bool Main::initLinkedMapsMenu(VymModel *model, QMenu *menu)
5422 {
5423     if (model) {
5424         ItemList targets = model->getLinkedMaps();
5425
5426         menu->clear();
5427
5428         QStringList targetNames;
5429         QList<uint> targetIDs;
5430
5431         // Build QStringList with all names of targets
5432         QMap<uint, QStringList>::const_iterator i;
5433         i = targets.constBegin();
5434         while (i != targets.constEnd()) {
5435             targetNames.append(i.value().first());
5436             targetIDs.append(i.key());
5437             ++i;
5438         }
5439
5440         // Sort list of names
5441         targetNames.sort(Qt::CaseInsensitive);
5442
5443         // Build menu based on sorted names
5444         while (!targetNames.isEmpty()) {
5445             // Find target by value
5446             i = targets.constBegin();
5447             while (i != targets.constEnd()) {
5448                 if (i.value().first() == targetNames.first())
5449                     break;
5450                 ++i;
5451             }
5452
5453             menu->addAction(targetNames.first())->setData(i.value().last());
5454             targetNames.removeFirst();
5455             targets.remove(i.key());
5456         }
5457         return true;
5458     }
5459     return false;
5460 }
5461
5462 void Main::editGoToLinkedMap()
5463 {
5464     VymModel *model = currentModel();
5465     if (initLinkedMapsMenu(model, targetsContextMenu)) {
5466         QAction *a = targetsContextMenu->exec(QCursor::pos());
5467         if (a) {
5468             QStringList sl;
5469             sl << a->data().toString();
5470             openVymLinks(sl);
5471         }
5472     }
5473 }
5474
5475 void Main::editToggleTarget()
5476 {
5477     VymModel *m = currentModel();
5478     if (m)
5479         m->toggleTarget();
5480 }
5481
5482 bool Main::initTargetsMenu(VymModel *model, QMenu *menu)
5483 {
5484     if (model) {
5485         ItemList targets = model->getTargets();
5486
5487         menu->clear();
5488
5489         QStringList targetNames;
5490         QList<uint> targetIDs;
5491
5492         // Build QStringList with all names of targets
5493         QMap<uint, QStringList>::const_iterator i;
5494         i = targets.constBegin();
5495         while (i != targets.constEnd()) {
5496             targetNames.append(i.value().first());
5497             targetIDs.append(i.key());
5498             ++i;
5499         }
5500
5501         // Sort list of names
5502         targetNames.sort(Qt::CaseInsensitive);
5503
5504         // Build menu based on sorted names
5505         while (!targetNames.isEmpty()) {
5506             // Find target by value
5507             i = targets.constBegin();
5508             while (i != targets.constEnd()) {
5509                 if (i.value().first() == targetNames.first())
5510                     break;
5511                 ++i;
5512             }
5513
5514             menu->addAction(targetNames.first())->setData(i.key());
5515             targetNames.removeFirst();
5516             targets.remove(i.key());
5517         }
5518         return true;
5519     }
5520     return false;
5521 }
5522
5523 void Main::editGoToTarget()
5524 {
5525     VymModel *model = currentModel();
5526     if (initTargetsMenu(model, targetsContextMenu)) {
5527         QAction *a = targetsContextMenu->exec(QCursor::pos());
5528         if (a)
5529             model->select(model->findID(a->data().toUInt()));
5530     }
5531 }
5532
5533 void Main::editMoveToTarget()
5534 {
5535     VymModel *model = currentModel();
5536     if (initTargetsMenu(model, targetsContextMenu)) {
5537         QAction *a = targetsContextMenu->exec(QCursor::pos());
5538         if (a) {
5539             TreeItem *dsti = model->findID(a->data().toUInt());
5540             /*
5541             BranchItem *selbi = model->getSelectedBranch();
5542             if (!selbi)
5543                 return;
5544             */
5545
5546             QList<TreeItem *> itemList = model->getSelectedItems();
5547             if (itemList.count() < 1) return;
5548
5549             if (dsti && dsti->isBranchLikeType() ) {
5550                 BranchItem *selbi;
5551                 BranchItem *pi;
5552                 foreach (TreeItem *ti, itemList) {
5553                     if (ti->isBranchLikeType() )
5554                     {
5555                         selbi = (BranchItem*)ti;
5556                         pi = selbi->parentBranch();
5557                         
5558                         // If branch below exists, select that one
5559                         // Makes it easier to quickly resort using the MoveTo function
5560                         BranchItem *below = pi->getBranchNum(selbi->num() + 1);
5561                         LinkableMapObj *lmo = selbi->getLMO();
5562                         QPointF orgPos;
5563                         if (lmo)
5564                             orgPos = lmo->getAbsPos();
5565
5566                         if (model->relinkBranch(selbi, (BranchItem *)dsti, -1, true,
5567                                                 orgPos)) {
5568                             if (below)
5569                                 model->select(below);
5570                             else if (pi)
5571                                 model->select(pi);
5572                         }
5573                     }
5574                 }
5575             }
5576         }
5577     }
5578 }
5579
5580 void Main::editSelectPrevious()
5581 {
5582     VymModel *m = currentModel();
5583     if (m)
5584         m->selectPrevious();
5585 }
5586
5587 void Main::editSelectNext()
5588 {
5589     VymModel *m = currentModel();
5590     if (m)
5591         m->selectNext();
5592 }
5593
5594 void Main::editSelectNothing()
5595 {
5596     VymModel *m = currentModel();
5597     if (m)
5598         m->unselectAll();
5599 }
5600
5601 void Main::editOpenFindResultWidget()
5602 {
5603     if (!findResultWidget->parentWidget()->isVisible()) {
5604         //      findResultWidget->parentWidget()->show();
5605         findResultWidget->popup();
5606     }
5607     else
5608         findResultWidget->parentWidget()->hide();
5609 }
5610
5611 #include "findwidget.h" // FIXME-4 Integrated FRW and FW
5612 void Main::editFindNext(QString s, bool searchNotesFlag)
5613 {
5614     Qt::CaseSensitivity cs = Qt::CaseInsensitive;
5615     VymModel *m = currentModel();
5616     if (m) {
5617         if (m->findAll(findResultWidget->getResultModel(), s, cs,
5618                        searchNotesFlag))
5619             findResultWidget->setStatus(FindWidget::Success);
5620         else
5621             findResultWidget->setStatus(FindWidget::Failed);
5622     }
5623 }
5624
5625 void Main::editFindDuplicateURLs() // FIXME-4 feature: use FindResultWidget for
5626                                    // display
5627 {
5628     VymModel *m = currentModel();
5629     if (m)
5630         m->findDuplicateURLs();
5631 }
5632
5633 void Main::updateQueries(
5634     VymModel *) // FIXME-4 disabled for now to avoid selection in FRW
5635 {
5636     return;
5637     /*
5638         qDebug() << "MW::updateQueries m="<<m<<"   cM="<<currentModel();
5639         if (m && currentModel()==m)
5640         {
5641         QString s=findResultWidget->getFindText();
5642         if (!s.isEmpty() ) editFindNext (s);
5643         }
5644     */
5645 }
5646
5647 void Main::selectQuickColor(int n)
5648 {
5649     if (n < 0 || n > quickColors.count() - 1) return;
5650
5651     actionGroupQuickColors->actions().at(n)->setChecked(true);
5652     setCurrentColor(quickColors.at(n));
5653 }
5654
5655 void Main::setQuickColor(QColor col)
5656 {
5657     int i = getCurrentColorIndex();
5658     if (i < 0) return;
5659
5660     QPixmap pix(16, 16);
5661     pix.fill(col);
5662     actionGroupQuickColors->checkedAction()->setIcon(pix);
5663     quickColors.replace(i, col);
5664 }
5665
5666 void Main::quickColorPressed()
5667 {
5668     int i = getCurrentColorIndex();
5669
5670     if (i < 0) return;
5671
5672     if (QApplication::keyboardModifiers() == Qt::ShiftModifier) {
5673         QColor col = getCurrentColor();
5674         col = QColorDialog::getColor((col), this);
5675         if (!col.isValid()) return;
5676
5677         setQuickColor(col);
5678     } else
5679         selectQuickColor(i);
5680 }
5681
5682 void Main::formatPickColor()
5683 {
5684     VymModel *m = currentModel();
5685     if (m)
5686         setQuickColor( m->getCurrentHeadingColor());
5687 }
5688
5689 QColor Main::getCurrentColor() 
5690
5691     int i = getCurrentColorIndex();
5692
5693     if (i < 0) return QColor();
5694
5695     return quickColors.at(i);
5696 }
5697
5698 int Main::getCurrentColorIndex()
5699 {
5700     QAction* a = actionGroupQuickColors->checkedAction();
5701
5702     if (a == nullptr) return -1;
5703
5704     return actionGroupQuickColors->actions().indexOf(a);
5705 }
5706
5707 void Main::setCurrentColor(QColor c)
5708 {
5709     int i = getCurrentColorIndex();
5710
5711     if (i < 0) return;
5712
5713     QPixmap pix(16, 16);
5714     pix.fill(c);
5715
5716     actionGroupQuickColors->actions().at(i)->setIcon(pix);
5717 }
5718
5719 void Main::formatColorBranch()
5720 {
5721     VymModel *m = currentModel();
5722     if (m)
5723         m->colorBranch(getCurrentColor());
5724 }
5725
5726 void Main::formatColorSubtree()
5727 {
5728     VymModel *m = currentModel();
5729     if (m)
5730         m->colorSubtree(getCurrentColor());
5731 }
5732
5733 void Main::formatLinkStyleLine()
5734 {
5735     VymModel *m = currentModel();
5736     if (m) {
5737         m->setMapLinkStyle("StyleLine");
5738         actionFormatLinkStyleLine->setChecked(true);
5739     }
5740 }
5741
5742 void Main::formatLinkStyleParabel()
5743 {
5744     VymModel *m = currentModel();
5745     if (m) {
5746         m->setMapLinkStyle("StyleParabel");
5747         actionFormatLinkStyleParabel->setChecked(true);
5748     }
5749 }
5750
5751 void Main::formatLinkStylePolyLine()
5752 {
5753     VymModel *m = currentModel();
5754     if (m) {
5755         m->setMapLinkStyle("StylePolyLine");
5756         actionFormatLinkStylePolyLine->setChecked(true);
5757     }
5758 }
5759
5760 void Main::formatLinkStylePolyParabel()
5761 {
5762     VymModel *m = currentModel();
5763     if (m) {
5764         m->setMapLinkStyle("StylePolyParabel");
5765         actionFormatLinkStylePolyParabel->setChecked(true);
5766     }
5767 }
5768
5769 void Main::formatSelectBackColor()
5770 {
5771     VymModel *m = currentModel();
5772     if (m)
5773         m->selectMapBackgroundColor();
5774 }
5775
5776 void Main::formatSelectBackImage()
5777 {
5778     VymModel *m = currentModel();
5779     if (m)
5780         m->selectMapBackgroundImage();
5781 }
5782
5783 void Main::formatSelectLinkColor()
5784 {
5785     VymModel *m = currentModel();
5786     if (m) {
5787         QColor col = QColorDialog::getColor(m->getMapDefLinkColor(), this);
5788         m->setMapDefLinkColor(col);
5789     }
5790 }
5791
5792 void Main::formatSelectSelectionColor() // FIXME-2 no Pen/Brush support yet
5793 {
5794     VymModel *m = currentModel();
5795     if (m) {
5796         QColor col = QColorDialog::getColor(
5797                 m->getSelectionBrushColor(),
5798                 this,
5799                 tr("Color of selection box","Mainwindow"),
5800                 QColorDialog::ShowAlphaChannel);
5801         m->setSelectionPenColor(col);
5802         m->setSelectionBrushColor(col);
5803     }
5804 }
5805
5806 void Main::formatSelectFont()
5807 {
5808     VymModel *m = currentModel();
5809     if (m) {
5810         bool ok;
5811         QFont font = QFontDialog::getFont(&ok, m->getMapDefaultFont(), this);
5812         if (ok)
5813             m->setMapDefaultFont(font);
5814     }
5815 }
5816
5817 void Main::formatToggleLinkColorHint()
5818 {
5819     VymModel *m = currentModel();
5820     if (m)
5821         m->toggleMapLinkColorHint();
5822 }
5823
5824 void Main::formatHideLinkUnselected() // FIXME-4 get rid of this with
5825                                       // imagepropertydialog
5826 {
5827     VymModel *m = currentModel();
5828     if (m)
5829         m->setHideLinkUnselected(actionFormatHideLinkUnselected->isChecked());
5830 }
5831
5832 void Main::viewZoomReset()
5833 {
5834     MapEditor *me = currentMapEditor();
5835     if (me)
5836         me->setViewCenterTarget();
5837 }
5838
5839 void Main::viewZoomIn()
5840 {
5841     MapEditor *me = currentMapEditor();
5842     if (me)
5843         me->setZoomFactorTarget(me->getZoomFactorTarget() * 1.15);
5844 }
5845
5846 void Main::viewZoomOut()
5847 {
5848     MapEditor *me = currentMapEditor();
5849     if (me)
5850         me->setZoomFactorTarget(me->getZoomFactorTarget() * 0.85);
5851 }
5852
5853 void Main::viewRotateCounterClockwise() // FIXME-3 move to ME
5854 {
5855     MapEditor *me = currentMapEditor();
5856     if (me)
5857         me->setAngleTarget(me->getAngleTarget() - 10);
5858 }
5859
5860 void Main::viewRotateClockwise() // FIXME-3 move to ME
5861 {
5862     MapEditor *me = currentMapEditor();
5863     if (me)
5864         me->setAngleTarget(me->getAngleTarget() + 10);
5865 }
5866
5867 void Main::viewCenter()
5868 {
5869     VymModel *m = currentModel();
5870     if (m)
5871         m->emitShowSelection(false);
5872 }
5873
5874 void Main::viewCenterScaled()
5875 {
5876     VymModel *m = currentModel();
5877     if (m)
5878         m->emitShowSelection(true);
5879 }
5880
5881 void Main::networkStartServer()
5882 {
5883     VymModel *m = currentModel();
5884     if (m)
5885         m->newServer();
5886 }
5887
5888 void Main::networkConnect()
5889 {
5890     VymModel *m = currentModel();
5891     if (m)
5892         m->connectToServer();
5893 }
5894
5895 void Main::downloadFinished() // only used for drop events in mapeditor and
5896                               // VM::downloadImage
5897 {
5898     QString s;
5899     DownloadAgent *agent = static_cast<DownloadAgent *>(sender());
5900     agent->isSuccess() ? s = "Success" : s = "Error  ";
5901
5902     /*
5903     qDebug()<<"Main::downloadFinished ";
5904     qDebug()<<"  result" <<  s;
5905     qDebug()<<"     msg" << agent->getResultMessage();
5906     */
5907
5908     QString script = agent->getFinishedScript();
5909     VymModel *model = getModel(agent->getFinishedScriptModelID());
5910     if (!script.isEmpty() && model) {
5911         script.replace("$TMPFILE", agent->getDestination());
5912         model->execute(script);
5913     }
5914     agent->deleteLater();
5915 }
5916
5917 bool Main::settingsPDF()
5918 {
5919     // Default browser is set in constructor
5920     bool ok;
5921     QString text = QInputDialog::getText(
5922         this, "VYM", tr("Set application to open PDF files") + ":",
5923         QLineEdit::Normal, settings.value("/system/readerPDF").toString(), &ok);
5924     if (ok)
5925         settings.setValue("/system/readerPDF", text);
5926     return ok;
5927 }
5928
5929 bool Main::settingsURL()
5930 {
5931     // Default browser is set in constructor
5932     bool ok;
5933     QString text = QInputDialog::getText(
5934         this, "VYM", tr("Set application to open an URL") + ":",
5935         QLineEdit::Normal, settings.value("/system/readerURL").toString(), &ok);
5936     if (ok)
5937         settings.setValue("/system/readerURL", text);
5938     return ok;
5939 }
5940
5941 void Main::settingsZipTool()    // FIXME-2 Disabled for now, to be removed completely in 2.9.1
5942 {
5943     // Default zip tool is tar on Windows 10, zip/unzip elsewhere
5944     ZipSettingsDialog dia;
5945     dia.exec();
5946 }
5947
5948 void Main::settingsMacroPath()
5949 {
5950     QString macroPath = macros.getPath();
5951
5952     QStringList filters;
5953     filters << "VYM script files (*.vys)";
5954     QFileDialog fd;
5955     fd.setDirectory(dirname(macroPath));
5956     fd.selectFile(basename(macroPath));
5957     fd.setFileMode(QFileDialog::ExistingFile);
5958     fd.setNameFilters(filters);
5959     fd.setWindowTitle(vymName + " - " + tr("Load vym script"));
5960     fd.setAcceptMode(QFileDialog::AcceptOpen);
5961
5962     QString fn;
5963     if (fd.exec() == QDialog::Accepted) {
5964         if (macros.setPath( fd.selectedFiles().first()))
5965             settings.setValue("/macros/path", macros.getPath());
5966     }
5967 }
5968
5969 void Main::settingsUndoLevels()
5970 {
5971     bool ok;
5972     int i = QInputDialog::getInt(
5973         this, "QInputDialog::getInt()", tr("Number of undo/redo levels:"),
5974         settings.value("/history/stepsTotal", 1000).toInt(), 0, 100000, 1, &ok);
5975     if (ok) {
5976         settings.setValue("/history/stepsTotal", i);
5977         QMessageBox::information(this, tr("VYM -Information:"),
5978                                  tr("Settings have been changed. The next map "
5979                                     "opened will have \"%1\" undo/redo levels")
5980                                      .arg(i));
5981     }
5982 }
5983
5984 void Main::settingsDefaultMapPath()
5985 {
5986     DefaultMapSettingsDialog dia;
5987     dia.exec();
5988 }
5989
5990 QString Main::defaultMapPath()
5991 {
5992     // Define default automatical path (also as fallback)
5993     QString ext_dark;
5994     if (usingDarkTheme)
5995         ext_dark = "-dark";
5996
5997     return vymBaseDir.path() + QString("/demos/default%1.vym").arg(ext_dark);
5998 }
5999
6000 QString Main::newMapPath()
6001 {
6002     if (settings.value("/system/defaultMap/auto", true).toBool())
6003         return defaultMapPath();
6004     else
6005         return settings
6006            .value("/system/defaultMap/path", defaultMapPath())
6007            .toString();
6008 }
6009
6010 bool Main::useAutosave() { return actionSettingsToggleAutosave->isChecked(); }
6011
6012 void Main::setAutosave(bool b) { actionSettingsToggleAutosave->setChecked(b); }
6013
6014 void Main::settingsAutosaveTime()
6015 {
6016     bool ok;
6017     int i = QInputDialog::getInt(
6018         this, vymName, tr("Number of seconds before autosave:"),
6019         settings.value("/system/autosave/ms").toInt() / 1000, 10, 60000, 1,
6020         &ok);
6021     if (ok)
6022         settings.setValue("/system/autosave/ms", i * 1000);
6023 }
6024
6025 void Main::settingsDefaultMapAuthor()
6026 {
6027     bool ok;
6028     QString s = QInputDialog::getText(
6029         this, vymName, tr("Set author for new maps (used in lockfile)") + ":",
6030         QLineEdit::Normal,
6031         settings
6032             .value("/user/name", tr("unknown user",
6033                                     "default name for map author in settings"))
6034             .toString(),
6035         &ok);
6036     if (ok)
6037         settings.setValue("/user/name", s);
6038 }
6039
6040 void Main::settingsDarkTheme()
6041 {
6042     DarkThemeSettingsDialog dia;
6043     QString settingDarkTheme = settings.value("/system/darkTheme", "system").toString();
6044     if (settingDarkTheme == "always")
6045         dia.ui.alwaysUseDarkThemeButton->setChecked(true);
6046     else 
6047         if (settingDarkTheme == "never")
6048             dia.ui.neverUseDarkThemeButton->setChecked(true);
6049         else
6050             dia.ui.systemUseDarkThemeButton->setChecked(true);
6051     dia.exec();
6052
6053     QString newSetting;
6054     if (dia.ui.alwaysUseDarkThemeButton->isChecked())
6055             newSetting = "always";
6056     else
6057         if (dia.ui.neverUseDarkThemeButton->isChecked())
6058             newSetting = "never";
6059         else
6060             newSetting = "system";
6061
6062     if (settingDarkTheme != newSetting) {
6063         settings.setValue("/system/darkTheme", newSetting);
6064         QMessageBox::information(
6065             0, tr("Information"),
6066             tr("Restart vym to apply the changed dark theme setting"));
6067     }
6068 }
6069
6070 void Main::settingsShowParentsLevelFindResults()
6071 {
6072     bool ok;
6073     int i = QInputDialog::getInt(
6074         this, vymName, tr("Number of parents shown in find results:"),
6075         findResultWidget->getResultModel()->getShowParentsLevel(), 0, 10, 0,
6076         &ok);
6077     if (ok)
6078         findResultWidget->getResultModel()->setShowParentsLevel(i);
6079 }
6080
6081 void Main::settingsShowParentsLevelTasks()
6082 {
6083     bool ok;
6084     int i = QInputDialog::getInt(
6085         this, vymName, tr("Number of parents shown for a task:"),
6086         taskModel->getShowParentsLevel(), 0, 10, 0, &ok);
6087     if (ok)
6088         taskModel->setShowParentsLevel(i);
6089 }
6090
6091 void Main::settingsToggleAutoLayout()
6092 {
6093     settings.setValue("/mainwindow/autoLayout/use",
6094                       actionSettingsToggleAutoLayout->isChecked());
6095 }
6096
6097 void Main::settingsToggleWriteBackupFile()
6098 {
6099     settings.setValue("/system/writeBackupFile",
6100                       actionSettingsWriteBackupFile->isChecked());
6101 }
6102
6103 void Main::settingsToggleAnimation()
6104 {
6105     settings.setValue("/animation/use",
6106                       actionSettingsUseAnimation->isChecked());
6107 }
6108
6109 void Main::settingsToggleDownloads() { downloadsEnabled(true); }
6110
6111 bool Main::settingsConfluence()
6112 {
6113     if (!QSslSocket::supportsSsl())
6114     {
6115         QMessageBox::warning(
6116             0, tr("Warning"),
6117             tr("No SSL support available for this build of vym"));
6118         helpDebugInfo();
6119         return false;
6120     }
6121
6122     ConfluenceSettingsDialog dia;
6123     dia.exec();
6124
6125     if (dia.result() > 0)
6126         return true;
6127     else
6128         return false;
6129 }
6130
6131 bool Main::settingsJIRA()
6132 {
6133     if (!QSslSocket::supportsSsl())
6134     {
6135         QMessageBox::warning(
6136             0, tr("Warning"),
6137             tr("No SSL support available for this build of vym"));
6138         helpDebugInfo();
6139         return false;
6140     }
6141
6142     JiraSettingsDialog dia;
6143     dia.exec();
6144
6145     if (dia.result() > 0)
6146         return true;
6147     else
6148         return false;
6149 }
6150
6151 void Main::windowToggleNoteEditor()
6152 {
6153     if (noteEditor->parentWidget()->isVisible())
6154         noteEditor->parentWidget()->hide();
6155     else {
6156         noteEditor->parentWidget()->show();
6157         noteEditor->setFocus();
6158     }
6159 }
6160
6161 void Main::windowToggleTreeEditor()
6162 {
6163     if (tabWidget->currentWidget())
6164         currentView()->toggleTreeEditor();
6165 }
6166
6167 void Main::windowToggleTaskEditor()
6168 {
6169     if (taskEditor->parentWidget()->isVisible()) {
6170         taskEditor->parentWidget()->hide();
6171         actionViewToggleTaskEditor->setChecked(false);
6172     }
6173     else {
6174         taskEditor->parentWidget()->show();
6175         actionViewToggleTaskEditor->setChecked(true);
6176     }
6177 }
6178
6179 void Main::windowToggleSlideEditor()
6180 {
6181     if (tabWidget->currentWidget())
6182         currentView()->toggleSlideEditor();
6183 }
6184
6185 void Main::windowToggleScriptEditor()
6186 {
6187     if (scriptEditor->parentWidget()->isVisible()) {
6188         scriptEditor->parentWidget()->hide();
6189         actionViewToggleScriptEditor->setChecked(false);
6190     }
6191     else {
6192         scriptEditor->parentWidget()->show();
6193         actionViewToggleScriptEditor->setChecked(true);
6194     }
6195 }
6196
6197 void Main::windowToggleScriptOutput()
6198 {
6199     if (scriptOutput->parentWidget()->isVisible()) {
6200         scriptOutput->parentWidget()->hide();
6201         actionViewToggleScriptOutput->setChecked(false);
6202     }
6203     else {
6204         scriptOutput->parentWidget()->show();
6205         actionViewToggleScriptOutput->setChecked(true);
6206     }
6207 }
6208
6209 void Main::windowToggleHistory()
6210 {
6211     if (historyWindow->parentWidget()->isVisible())
6212         historyWindow->parentWidget()->hide();
6213     else
6214         historyWindow->parentWidget()->show();
6215 }
6216
6217 void Main::windowToggleProperty()
6218 {
6219     if (branchPropertyEditor->parentWidget()->isVisible())
6220         branchPropertyEditor->parentWidget()->hide();
6221     else
6222         branchPropertyEditor->parentWidget()->show();
6223     branchPropertyEditor->setModel(currentModel());
6224 }
6225
6226 void Main::windowShowHeadingEditor() { headingEditorDW->show(); }
6227
6228 void Main::windowToggleHeadingEditor()
6229 {
6230     if (headingEditor->parentWidget()->isVisible())
6231         headingEditor->parentWidget()->hide();
6232     else {
6233         headingEditor->parentWidget()->show();
6234         headingEditor->setFocus();
6235     }
6236 }
6237
6238 void Main::windowToggleAntiAlias()
6239 {
6240     bool b = actionViewToggleAntiAlias->isChecked();
6241     MapEditor *me;
6242     for (int i = 0; i < tabWidget->count(); i++) {
6243         me = view(i)->getMapEditor();
6244         if (me)
6245             me->setAntiAlias(b);
6246     }
6247 }
6248
6249 bool Main::isAliased() { return actionViewToggleAntiAlias->isChecked(); }
6250
6251 bool Main::hasSmoothPixmapTransform()
6252 {
6253     return actionViewToggleSmoothPixmapTransform->isChecked();
6254 }
6255
6256 void Main::windowToggleSmoothPixmap()
6257 {
6258     bool b = actionViewToggleSmoothPixmapTransform->isChecked();
6259     MapEditor *me;
6260     for (int i = 0; i < tabWidget->count(); i++) {
6261
6262         me = view(i)->getMapEditor();
6263         if (me)
6264             me->setSmoothPixmap(b);
6265     }
6266 }
6267
6268 void Main::clearScriptOutput() { scriptOutput->clear(); }
6269
6270 void Main::updateHistory(SimpleSettings &undoSet)
6271 {
6272     historyWindow->update(undoSet);
6273 }
6274
6275 void Main::updateHeading(const VymText &vt)
6276 {
6277     VymModel *m = currentModel();
6278     if (m)
6279         m->setHeading(vt);
6280 }
6281
6282 void Main::updateNoteText(const VymText &vt)
6283 {
6284     // this slot is connected to noteEditor::textHasChanged()
6285     VymModel *m = currentModel();
6286     if (m)
6287         m->updateNoteText(vt);
6288 }
6289
6290 void Main::updateNoteEditor(TreeItem *ti)
6291 {
6292     if (ti) {
6293         if (!ti->hasEmptyNote())
6294             noteEditor->setNote(ti->getNote());
6295         else
6296             noteEditor->clear(); // Also sets empty state
6297         return;
6298     }
6299     noteEditor->setInactive();
6300 }
6301
6302 void Main::updateHeadingEditor(BranchItem *bi)  // FIXME-3 move to HeadingEditor
6303 {
6304     if (!bi) {
6305         VymModel *m = currentModel();
6306         if (!m) return;
6307
6308         bi = m->getSelectedBranch();
6309     }
6310
6311     // Give up, if not a single branch is selected
6312     if (!bi) return;
6313
6314     // Color settings, also to prepare switching to RichText later
6315     headingEditor->setColorMapBackground(bi->getBackgroundColor(bi));
6316     headingEditor->setColorRichTextDefaultForeground(bi->getHeadingColor());
6317
6318     headingEditor->setVymText(bi->getHeading());
6319     headingEditor->setEditorTitle();
6320
6321 }
6322
6323 void Main::selectInNoteEditor(QString s, int i)
6324 {
6325     // TreeItem is already selected at this time, therefor
6326     // the note is already in the editor
6327     noteEditor->findText(s, QTextDocument::FindFlags(), i);
6328 }
6329
6330 void Main::setFocusMapEditor()
6331 {
6332     VymView *vv = currentView();
6333     if (vv)
6334         vv->setFocusMapEditor();
6335 }
6336
6337 void Main::changeSelection(VymModel *model, const QItemSelection &,
6338                            const QItemSelection &)
6339 {
6340     // Setting the model in BPE implicitely
6341     // also sets treeItem and updates content in BPE
6342     branchPropertyEditor->setModel(model);
6343
6344     if (model && model == currentModel()) {
6345         int selectedCount = model->getSelectionModel()->selectedIndexes().count();
6346
6347         if (selectedCount == 0 || selectedCount > 1) {
6348             noteEditor->setInactive();
6349             headingEditor->setInactive();
6350             taskEditor->clearSelection();
6351
6352         } else {
6353             BranchItem *bi = model->getSelectedBranch();
6354             if (!bi) return;
6355
6356             // Update note editor
6357             updateNoteEditor(bi);
6358
6359             // Show URL and link in statusbar
6360             QString status;
6361             QString s = bi->getURL();
6362             if (!s.isEmpty())
6363                 status += "URL: " + s + "  ";
6364             s = bi->getVymLink();
6365             if (!s.isEmpty())
6366                 status += "Link: " + s;
6367             if (!status.isEmpty())
6368                 statusMessage(status);
6369
6370             // Update text in HeadingEditor
6371             updateHeadingEditor(bi);
6372
6373             // Select in TaskEditor, if necessary
6374             Task *t = bi->getTask();
6375
6376             if (t)
6377                 taskEditor->select(t);
6378             else
6379                 taskEditor->clearSelection();
6380         }
6381     }
6382
6383     updateActions();
6384 }
6385
6386 void Main::updateDockWidgetTitles(VymModel *model)
6387 {
6388     QString s;
6389     if (model && !model->isRepositionBlocked()) {
6390         BranchItem *bi = model->getSelectedBranch();
6391         if (bi) {
6392             s = bi->getHeadingPlain();
6393             noteEditor->setVymText(bi->getNote());
6394         }
6395
6396         noteEditor->setEditorTitle(s);
6397         branchPropertyEditor->setModel(model);
6398     }
6399 }
6400
6401 void Main::updateActions()
6402 {
6403     // updateActions is also called when satellites are closed
6404     actionViewToggleNoteEditor->setChecked(
6405         noteEditor->parentWidget()->isVisible());
6406     actionViewToggleTaskEditor->setChecked(
6407         taskEditor->parentWidget()->isVisible());
6408     actionViewToggleHistoryWindow->setChecked(
6409         historyWindow->parentWidget()->isVisible());
6410     actionViewTogglePropertyEditor->setChecked(
6411         branchPropertyEditor->parentWidget()->isVisible());
6412     actionViewToggleScriptEditor->setChecked(
6413         scriptEditor->parentWidget()->isVisible());
6414
6415     if (JiraAgent::available())
6416         actionGetJiraDataSubtree->setEnabled(true);
6417     else
6418         actionGetJiraDataSubtree->setEnabled(false);
6419
6420     if (ConfluenceAgent::available())
6421     {
6422         actionGetConfluencePageName->setEnabled(true);
6423         actionConnectGetConfluenceUser->setEnabled(true);
6424         actionFileExportConfluence->setEnabled(true);
6425     } else
6426     {
6427         actionGetConfluencePageName->setEnabled(false);
6428         actionConnectGetConfluenceUser->setEnabled(false);
6429         actionFileExportConfluence->setEnabled(false);
6430     }
6431
6432     VymView *vv = currentView();
6433     if (vv) {
6434         actionViewToggleTreeEditor->setChecked(vv->treeEditorIsVisible());
6435         actionViewToggleSlideEditor->setChecked(vv->slideEditorIsVisible());
6436     }
6437     else {
6438         actionViewToggleTreeEditor->setChecked(false);
6439         actionViewToggleSlideEditor->setChecked(false);
6440     }
6441
6442     VymModel *m = currentModel();
6443     if (m) {
6444         QList<TreeItem *> seltis = m->getSelectedItems();
6445         QList<BranchItem *> selbis = m->getSelectedBranches();
6446         TreeItem *selti;
6447         selti = (seltis.count() == 1) ? seltis.first() : nullptr;
6448
6449         BranchItem *selbi;
6450         selbi = (selbis.count() == 1) ? selbis.first() : nullptr;
6451
6452         // readonly mode
6453         if (m->isReadOnly()) {
6454             // Disable toolbars
6455             standardFlagsMaster->setEnabled(false);
6456             userFlagsMaster->setEnabled(false);
6457             clipboardToolbar->setEnabled(false);
6458             editActionsToolbar->setEnabled(false);
6459             selectionToolbar->setEnabled(false);
6460             editorsToolbar->setEnabled(false);
6461             colorsToolbar->setEnabled(false);
6462             zoomToolbar->setEnabled(false);
6463             modModesToolbar->setEnabled(false);
6464             referencesToolbar->setEnabled(false);
6465             standardFlagsToolbar->setEnabled(false);
6466             userFlagsToolbar->setEnabled(false);
6467
6468             // Disable map related actions in readonly mode // FIXME-2 not all actions disabled 
6469             foreach (QAction *a, restrictedMapActions)
6470                 a->setEnabled(false);
6471
6472         }
6473         else { // not readonly     
6474
6475             // Enable toolbars
6476             standardFlagsMaster->setEnabled(true);
6477             userFlagsMaster->setEnabled(true);
6478             clipboardToolbar->setEnabled(true);
6479             editActionsToolbar->setEnabled(true);
6480             selectionToolbar->setEnabled(true);
6481             editorsToolbar->setEnabled(true);
6482             colorsToolbar->setEnabled(true);
6483             zoomToolbar->setEnabled(true);
6484             modModesToolbar->setEnabled(true);
6485             referencesToolbar->setEnabled(true);
6486             standardFlagsToolbar->setEnabled(true);
6487             userFlagsToolbar->setEnabled(true);
6488
6489             // Enable map related actions
6490             foreach (QAction *a, restrictedMapActions)
6491                 a->setEnabled(true);
6492         }
6493         // Enable all files actions first
6494         for (int i = 0; i < actionListFiles.size(); ++i)
6495             actionListFiles.at(i)->setEnabled(true);
6496
6497         foreach (QAction *a, unrestrictedMapActions)
6498             a->setEnabled(true);
6499
6500         // Disable other actions for now
6501         for (int i = 0; i < actionListBranches.size(); ++i)
6502             actionListBranches.at(i)->setEnabled(false);
6503
6504         for (int i = 0; i < actionListItems.size(); ++i)
6505             actionListItems.at(i)->setEnabled(false);
6506
6507         // Link style in context menu
6508         switch (m->getMapLinkStyle()) {
6509         case LinkableMapObj::Line:
6510             actionFormatLinkStyleLine->setChecked(true);
6511             break;
6512         case LinkableMapObj::Parabel:
6513             actionFormatLinkStyleParabel->setChecked(true);
6514             break;
6515         case LinkableMapObj::PolyLine:
6516             actionFormatLinkStylePolyLine->setChecked(true);
6517             break;
6518         case LinkableMapObj::PolyParabel:
6519             actionFormatLinkStylePolyParabel->setChecked(true);
6520             break;
6521         default:
6522             break;
6523         }
6524
6525         // Update colors
6526         QPixmap pix(16, 16);
6527         pix.fill(m->getMapBackgroundColor());
6528         actionFormatBackColor->setIcon(pix);
6529         pix.fill(m->getSelectionBrushColor());
6530         actionFormatSelectionColor->setIcon(pix);
6531         pix.fill(m->getMapDefLinkColor());
6532         actionFormatLinkColor->setIcon(pix);
6533
6534         // Selection history
6535         if (!m->canSelectPrevious())
6536             actionSelectPrevious->setEnabled(false);
6537
6538         if (!m->canSelectNext())
6539             actionSelectNext->setEnabled(false);
6540
6541         if (!m->getSelectedItem())
6542             actionSelectNothing->setEnabled(false);
6543
6544         // Save
6545         if (!m->hasChanged())
6546             actionFileSave->setEnabled(false);
6547
6548         // Undo/Redo
6549         if (!m->isUndoAvailable())
6550             actionUndo->setEnabled(false);
6551
6552         if (!m->isRedoAvailable())
6553             actionRedo->setEnabled(false);
6554
6555         // History window
6556         historyWindow->setWindowTitle(
6557             vymName + " - " +
6558             tr("History for %1", "Window Caption").arg(m->getFileName()));
6559
6560         // Expanding/collapsing
6561         actionExpandAll->setEnabled(true);
6562         actionExpandOneLevel->setEnabled(true);
6563         actionCollapseOneLevel->setEnabled(true);
6564         actionCollapseUnselected->setEnabled(true);
6565
6566         if (m->getMapLinkColorHint() == LinkableMapObj::HeadingColor)
6567             actionFormatLinkColorHint->setChecked(true);
6568         else
6569             actionFormatLinkColorHint->setChecked(false);
6570
6571         // Export last
6572         QString desc, com, dest;
6573         if (m && m->exportLastAvailable(desc, com, dest))
6574             actionFileExportLast->setEnabled(true);
6575         else {
6576             actionFileExportLast->setEnabled(false);
6577             com = dest = "";
6578             desc = " - ";
6579         }
6580         actionFileExportLast->setText(
6581             tr("Export in last used format (%1) to: %2", "status tip")
6582                 .arg(desc)
6583                 .arg(dest));
6584
6585
6586         if (seltis.count() > 0) { // Tree Item selected
6587             if (selti) actionToggleTarget->setChecked(selti->isTarget());
6588             actionDelete->setEnabled(true);
6589             actionDeleteAlt->setEnabled(true);
6590             actionDeleteChildren->setEnabled(true);
6591
6592             if (selti && selti->getType() == TreeItem::Image) {
6593                 actionFormatHideLinkUnselected->setChecked(
6594                     ((MapItem *)selti)->getHideLinkUnselected());
6595                 actionFormatHideLinkUnselected->setEnabled(true);
6596             }
6597
6598             if (selbis.count() > 0) { // Branch Item selected
6599                 for (int i = 0; i < actionListBranches.size(); ++i)
6600                     actionListBranches.at(i)->setEnabled(true);
6601
6602                 actionHeading2URL->setEnabled(true);
6603
6604                 // Note
6605                 if (selbi) actionGetURLsFromNote->setEnabled(!selbi->getNote().isEmpty());
6606
6607                 // Take care of xlinks
6608                 // FIXME-4 similar code in mapeditor mousePressEvent
6609                 bool b = false;
6610                 if (selbi && selbi->xlinkCount() > 0)
6611                     b = true;
6612
6613                 branchXLinksContextMenuEdit->setEnabled(b);
6614                 branchXLinksContextMenuFollow->setEnabled(b);
6615                 branchXLinksContextMenuEdit->clear();
6616                 branchXLinksContextMenuFollow->clear();
6617                 if (b) {
6618                     BranchItem *bi;
6619                     QString s;
6620                     for (int i = 0; i < selbi->xlinkCount(); ++i) {
6621                         bi = selbi->getXLinkItemNum(i)->getPartnerBranch();
6622                         if (bi) {
6623                             s = bi->getHeadingPlain();
6624                             if (s.length() > xLinkMenuWidth)
6625                                 s = s.left(xLinkMenuWidth) + "...";
6626                             branchXLinksContextMenuEdit->addAction(s);
6627                             branchXLinksContextMenuFollow->addAction(s);
6628                         }
6629                     }
6630                 }
6631                 // Standard and user flags
6632                 if (selbi)
6633                 {
6634                     standardFlagsMaster->updateToolBar(selbi->activeFlagUids());
6635                     userFlagsMaster->updateToolBar(selbi->activeFlagUids());
6636                 }
6637
6638                 // System Flags
6639                 actionToggleScroll->setEnabled(true);
6640                 if (selbi && selbi->isScrolled())
6641                     actionToggleScroll->setChecked(true);
6642                 else
6643                     actionToggleScroll->setChecked(false);
6644
6645                 QString url;
6646                 if (selti) url = selti->getURL();
6647                 if (url.isEmpty()) {
6648                     actionOpenURL->setEnabled(false);
6649                     actionOpenURLTab->setEnabled(false);
6650                     actionGetConfluencePageName->setEnabled(false);
6651                 }
6652                 else {
6653                     actionOpenURL->setEnabled(true);
6654                     actionOpenURLTab->setEnabled(true);
6655                     if (ConfluenceAgent::available())
6656                         actionGetConfluencePageName->setEnabled(true);
6657                     else
6658                         actionGetConfluencePageName->setEnabled(false);
6659                 }
6660
6661                 if (selti && selti->getVymLink().isEmpty()) {
6662                     actionOpenVymLink->setEnabled(false);
6663                     actionOpenVymLinkBackground->setEnabled(false);
6664                     actionDeleteVymLink->setEnabled(false);
6665                 }
6666                 else {
6667                     actionOpenVymLink->setEnabled(true);
6668                     actionOpenVymLinkBackground->setEnabled(true);
6669                     actionDeleteVymLink->setEnabled(true);
6670                 }
6671
6672                 if ((selbi && !selbi->canMoveUp()) || selbis.count() > 1)
6673                     actionMoveUp->setEnabled(false);
6674
6675                 if ((selbi && !selbi->canMoveDown()) || selbis.count() > 1)
6676                     actionMoveDown->setEnabled(false);
6677
6678                 if ((selbi && !selbi->canMoveUp()) || selbis.count() > 1)
6679                     actionMoveUpDiagonally->setEnabled(false);  // FIXME-2 add check for moveDiagonalUp
6680
6681                 if ((selbi && selbi->depth() == 0) || selbis.count() > 1)
6682                     actionMoveDownDiagonally->setEnabled(false);
6683
6684                 if (selbi && selbi->getLMO()->getOrientation() == LinkableMapObj::LeftOfCenter)
6685                 {
6686                     actionMoveDownDiagonally->setIcon(QPixmap(":down-diagonal-right.png"));
6687                     actionMoveUpDiagonally->setIcon(QPixmap(":up-diagonal-left.png"));
6688                 }
6689                 else
6690                 {
6691                     actionMoveDownDiagonally->setIcon(QPixmap(":down-diagonal-left.png"));
6692                     actionMoveUpDiagonally->setIcon(QPixmap(":up-diagonal-right.png"));
6693                 }
6694
6695                 if ((selbi && selbi->branchCount() < 2)  || selbis.count() > 1) { 
6696                     actionSortChildren->setEnabled(false);
6697                     actionSortBackChildren->setEnabled(false);
6698                 }
6699
6700                 if (selbi) {
6701                     actionToggleHideExport->setEnabled(true);
6702                     actionToggleHideExport->setChecked(selbi->hideInExport());
6703
6704                     actionToggleTask->setEnabled(true);
6705                     if (!selbi->getTask())
6706                         actionToggleTask->setChecked(false);
6707                     else
6708                         actionToggleTask->setChecked(true);
6709                 } else
6710                 {
6711                     actionToggleHideExport->setEnabled(false);
6712                     actionToggleTask->setEnabled(false);
6713                 }
6714
6715
6716                 const QClipboard *clipboard = QApplication::clipboard();
6717                 const QMimeData *mimeData = clipboard->mimeData();
6718                 if (mimeData->formats().contains("application/x-vym") ||
6719                     mimeData->hasImage())
6720                     actionPaste->setEnabled(true);
6721                 else
6722                     actionPaste->setEnabled(false);
6723
6724                 actionToggleTarget->setEnabled(true);
6725             } // end of BranchItem
6726
6727             if (selti && selti->getType() == TreeItem::Image) {
6728                 for (int i = 0; i < actionListBranches.size(); ++i)
6729                     actionListBranches.at(i)->setEnabled(false);
6730
6731                 standardFlagsMaster->setEnabled(false);
6732                 userFlagsMaster->setEnabled(false);
6733
6734                 actionOpenURL->setEnabled(false);
6735                 actionOpenVymLink->setEnabled(false);
6736                 actionOpenVymLinkBackground->setEnabled(false);
6737                 actionDeleteVymLink->setEnabled(false);
6738                 actionToggleHideExport->setEnabled(true);
6739                 actionToggleHideExport->setChecked(selti->hideInExport());
6740
6741                 actionToggleTarget->setEnabled(true);
6742
6743                 actionPaste->setEnabled(false);
6744                 actionDelete->setEnabled(true);
6745                 actionDeleteAlt->setEnabled(true);
6746
6747                 actionGrowSelectionSize->setEnabled(true);
6748                 actionShrinkSelectionSize->setEnabled(true);
6749                 actionResetSelectionSize->setEnabled(true);
6750             } // Image
6751         } // TreeItem
6752         else
6753         {
6754             actionToggleHideExport->setEnabled(false);
6755         }
6756
6757         // Check (at least for some) multiple selection //FIXME-4
6758         if (seltis.count() > 0) {
6759             actionDelete->setEnabled(true);
6760             actionDeleteAlt->setEnabled(true);
6761         }
6762
6763         if (selbis.count() > 0)
6764         {
6765             actionFormatColorBranch->setEnabled(true);
6766             actionFormatColorSubtree->setEnabled(true);
6767         }
6768     }
6769     else {
6770         // No map available
6771         for (int i = 0; i < actionListFiles.size(); ++i)
6772             actionListFiles.at(i)->setEnabled(false);
6773
6774         foreach (QAction *a, unrestrictedMapActions)
6775             a->setEnabled(false);
6776
6777         // Disable toolbars
6778         standardFlagsMaster->setEnabled(false);
6779         userFlagsMaster->setEnabled(false);
6780         clipboardToolbar->setEnabled(false);
6781         editActionsToolbar->setEnabled(false);
6782         selectionToolbar->setEnabled(false);
6783         editorsToolbar->setEnabled(false);
6784         colorsToolbar->setEnabled(false);
6785         zoomToolbar->setEnabled(false);
6786         modModesToolbar->setEnabled(false);
6787         referencesToolbar->setEnabled(false);
6788         standardFlagsToolbar->setEnabled(false);
6789         userFlagsToolbar->setEnabled(false);
6790     }
6791 }
6792
6793 Main::ModMode Main::getModMode()
6794 {
6795     if (actionModModePoint->isChecked())
6796         return ModModePoint;
6797     if (actionModModeColor->isChecked())
6798         return ModModeColor;
6799     if (actionModModeXLink->isChecked())
6800         return ModModeXLink;
6801     if (actionModModeMoveObject->isChecked())
6802         return ModModeMoveObject;
6803     if (actionModModeMoveView->isChecked())
6804         return ModModeMoveView;
6805     return ModModeUndefined;
6806 }
6807
6808 bool Main::autoSelectNewBranch()
6809 {
6810     return actionSettingsAutoSelectNewBranch->isChecked();
6811 }
6812
6813 QScriptValue scriptPrint(QScriptContext *context, QScriptEngine *)
6814 {
6815     scriptOutput->append(context->argument(0).toString());
6816     cout << context->argument(0).toString().toStdString() << endl;
6817     return QScriptValue();
6818 }
6819
6820 QScriptValue scriptAbort(QScriptContext *context, QScriptEngine *engine)
6821 {
6822     scriptOutput->append("Abort called: " + context->argument(0).toString());
6823     engine->abortEvaluation();
6824     return QScriptValue();
6825 }
6826
6827 QScriptValue scriptStatusMessage(QScriptContext *context, QScriptEngine *)
6828 {
6829     mainWindow->statusMessage(context->argument(0).toString());
6830     return QScriptValue();
6831 }
6832
6833 QVariant Main::runScript(const QString &script)
6834 {
6835     scriptEngine.globalObject().setProperty(
6836         "print", scriptEngine.newFunction(scriptPrint));
6837     scriptEngine.globalObject().setProperty(
6838         "abort", scriptEngine.newFunction(scriptAbort));
6839     scriptEngine.globalObject().setProperty(
6840         "statusMessage", scriptEngine.newFunction(scriptStatusMessage));
6841
6842     // Create Wrapper object for VymModel
6843     // QScriptValue val1 = scriptEngine.newQObject( m->getWrapper() );
6844     // scriptEngine.globalObject().setProperty("model", val1);
6845
6846     // Create Wrapper object for vym itself (mainwindow)
6847     VymWrapper vymWrapper;
6848     QScriptValue val2 = scriptEngine.newQObject(&vymWrapper);
6849     scriptEngine.globalObject().setProperty("vym", val2);
6850
6851     // Create wrapper object for selection
6852     Selection selection;
6853     QScriptValue val3 = scriptEngine.newQObject(&selection);
6854     scriptEngine.globalObject().setProperty("selection", val3);
6855
6856     if (debug) {
6857         cout << "MainWindow::runScript starting to execute:" << endl;
6858         cout << qPrintable(script) << endl;
6859     }
6860
6861     // Run script
6862     QScriptValue result = scriptEngine.evaluate(script);
6863
6864     if (debug) {
6865         qDebug() << "MainWindow::runScript finished:";
6866         qDebug() << "   hasException: " << scriptEngine.hasUncaughtException();
6867         qDebug() << "         result: "
6868                  << result.toString(); // not used so far...
6869         qDebug()
6870             << "     lastResult: "
6871             << scriptEngine.globalObject().property("lastResult").toVariant();
6872     }
6873
6874     if (scriptEngine.hasUncaughtException()) {
6875         // Warnings, in case that output window is not visible...
6876         statusMessage("Script execution failed");
6877         qWarning() << "Script execution failed";
6878
6879         int line = scriptEngine.uncaughtExceptionLineNumber();
6880         scriptOutput->append(QString("uncaught exception at line %1: %2")
6881                                  .arg(line)
6882                                  .arg(result.toString()));
6883     }
6884     else
6885         return scriptEngine.globalObject().property("lastResult").toVariant();
6886
6887     return QVariant("");
6888 }
6889
6890 QObject *Main::getCurrentModelWrapper()
6891 {
6892     // Called from VymWrapper to find out current model in a script
6893     VymModel *m = currentModel();
6894     if (m)
6895         return m->getWrapper();
6896     else
6897         return NULL;
6898 }
6899
6900 bool Main::gotoWindow(const int &n)
6901 {
6902     if (n < tabWidget->count() && n >= 0) {
6903         tabWidget->setCurrentIndex(n);
6904         return true;
6905     }
6906     return false;
6907 }
6908
6909 void Main::windowNextEditor()
6910 {
6911     if (tabWidget->currentIndex() < tabWidget->count())
6912         tabWidget->setCurrentIndex(tabWidget->currentIndex() + 1);
6913 }
6914
6915 void Main::windowPreviousEditor()
6916 {
6917     if (tabWidget->currentIndex() > 0)
6918         tabWidget->setCurrentIndex(tabWidget->currentIndex() - 1);
6919 }
6920
6921 void Main::nextSlide()
6922 {
6923     VymView *cv = currentView();
6924     if (cv)
6925         cv->nextSlide();
6926 }
6927
6928 void Main::previousSlide()
6929 {
6930     VymView *cv = currentView();
6931     if (cv)
6932         cv->previousSlide();
6933 }
6934
6935 void Main::flagChanged()
6936 {
6937     MapEditor *me = currentMapEditor();
6938     VymModel *m = currentModel();
6939     if (me && m && me->getState() != MapEditor::EditingHeading) {
6940         m->toggleFlagByUid(QUuid(sender()->objectName()),
6941                            actionSettingsUseFlagGroups->isChecked());
6942         updateActions();
6943     }
6944 }
6945
6946 void Main::testFunction1()
6947 {
6948     // Avail. styles:
6949     // Linux (KDE): Breeze,bb10dark,bb10bright,cleanlooks,gtk2,cde,motif,plastique,Windows,Fusion
6950     // Windows: windowsvista,Windows,Fusion
6951     //#include <QStyleFactory>
6952     //qApp->setStyle(QStyleFactory::create("windowsvista"));
6953
6954     VymModel *m = currentModel();
6955     if (m) {
6956         qDebug() << "ME::vp->width()=" << m->getMapEditor()->viewport()->width();
6957     }
6958 }
6959
6960 void Main::testFunction2()
6961 {
6962     VymModel *m = currentModel();
6963     if (m) {
6964         //m->repeatLastCommand();
6965     }
6966 }
6967
6968 void Main::toggleWinter()
6969 {
6970     if (!currentMapEditor())
6971         return;
6972     currentMapEditor()->toggleWinter();
6973 }
6974
6975 void Main::toggleHideExport()
6976 {
6977     VymModel *m = currentModel();
6978     if (!m)
6979         return;
6980     if (actionToggleHideMode->isChecked())
6981         m->setHideTmpMode(TreeItem::HideExport);
6982     else
6983         m->setHideTmpMode(TreeItem::HideNone);
6984 }
6985
6986 void Main::testCommand()
6987 {
6988     if (!currentMapEditor())
6989         return;
6990     scriptEditor->show();
6991 }
6992
6993 void Main::helpDoc()
6994 {
6995     QString locale = QLocale::system().name();
6996     QString docname;
6997     if (locale.left(2) == "es")
6998         docname = "vym_es.pdf";
6999     else
7000         docname = "vym.pdf";
7001
7002     QStringList searchList;
7003     QDir docdir;
7004 #if defined(Q_OS_MACX)
7005     searchList << vymBaseDir.path() + "/doc";
7006 #elif defined(Q_OS_WIN32)
7007     searchList << vymInstallDir.path() + "doc/" + docname;
7008 #else
7009 #if defined(VYM_DOCDIR)
7010     searchList << VYM_DOCDIR;
7011 #endif
7012     // default path in SUSE LINUX
7013     searchList << "/usr/share/doc/packages/vym";
7014 #endif
7015
7016     searchList << "doc"; // relative path for easy testing in tarball
7017     searchList << "/usr/share/doc/vym";      // Debian
7018     searchList << "/usr/share/doc/packages"; // Knoppix
7019
7020     bool found = false;
7021     QFile docfile;
7022     for (int i = 0; i < searchList.count(); ++i) {
7023         docfile.setFileName(searchList.at(i) + "/" + docname);
7024         if (docfile.exists()) {
7025             found = true;
7026             break;
7027         }
7028     }
7029
7030     if (!found) {
7031         QMessageBox::critical(0, tr("Critcal error"),
7032                               tr("Couldn't find the documentation %1 in:\n%2")
7033                                   .arg(docname)
7034                                   .arg(searchList.join("\n")));
7035         return;
7036     }
7037
7038     QStringList args;
7039     VymProcess *pdfProc = new VymProcess();
7040     args << QDir::toNativeSeparators(docfile.fileName());
7041
7042     if (!pdfProc->startDetached(settings.value("/system/readerPDF").toString(),
7043                                 args)) {
7044         // error handling
7045         QMessageBox::warning(
7046             0, tr("Warning"),
7047             tr("Couldn't find a viewer to open %1.\n").arg(docfile.fileName()) +
7048                 tr("Please use Settings->") +
7049                 tr("Set application to open PDF files"));
7050         settingsPDF();
7051         return;
7052     }
7053 }
7054
7055 void Main::helpDemo()
7056 {
7057     QStringList filters;
7058     filters << "VYM example map (*.vym)";
7059     QFileDialog fd;
7060     fd.setDirectory(vymBaseDir.path() + "/demos");
7061     fd.setFileMode(QFileDialog::ExistingFiles);
7062     fd.setNameFilters(filters);
7063     fd.setWindowTitle(vymName + " - " + tr("Load vym example map"));
7064     fd.setAcceptMode(QFileDialog::AcceptOpen);
7065
7066     QString fn;
7067     if (fd.exec() == QDialog::Accepted) {
7068         lastMapDir = fd.directory();
7069         QStringList flist = fd.selectedFiles();
7070         QStringList::Iterator it = flist.begin();
7071         initProgressCounter(flist.count());
7072         while (it != flist.end()) {
7073             fn = *it;
7074             fileLoad(*it, NewMap, VymMap);
7075             ++it;
7076         }
7077         removeProgressCounter();
7078     }
7079 }
7080
7081 void Main::helpShortcuts()
7082 {
7083     ShowTextDialog dia;
7084     dia.useFixedFont(true);
7085     dia.setText(switchboard.getASCII());
7086     dia.exec();
7087 }
7088
7089 void Main::helpMacros()
7090 {
7091     ShowTextDialog dia;
7092     dia.useFixedFont(true);
7093     dia.setText(macros.help());
7094     dia.exec();
7095 }
7096
7097 void Main::helpScriptingCommands()
7098 {
7099     ShowTextDialog dia;
7100     dia.useFixedFont(true);
7101     QString s;
7102     s = "Available commands in map:\n";
7103     s += "=========================:\n";
7104     foreach (Command *c, modelCommands) {
7105         s += c->getDescription();
7106         s += "\n";
7107     }
7108
7109     s += "Available commands in vym:\n";
7110     s += "=========================:\n";
7111     foreach (Command *c, vymCommands) {
7112         s += c->getDescription();
7113         s += "\n";
7114     }
7115
7116     dia.setText(s);
7117     dia.exec();
7118 }
7119
7120 void Main::helpDebugInfo()
7121 {
7122     ShowTextDialog dia;
7123     dia.useFixedFont(true);
7124     dia.setText(debugInfo());
7125     dia.setMinimumWidth(900);
7126     dia.exec();
7127 }
7128
7129 void Main::helpAbout()
7130 {
7131     AboutDialog ad;
7132     ad.setMinimumSize(900, 700);
7133     ad.resize(QSize(900, 700));
7134     ad.exec();
7135 }
7136
7137 void Main::helpAboutQT()
7138 {
7139     QMessageBox::aboutQt(this, "Qt Application Example");
7140 }
7141
7142 void Main::callMacro()
7143 {
7144     QAction *action = qobject_cast<QAction *>(sender());
7145     int i = -1;
7146     if (action) {
7147         QString s = macros.get();
7148         QString shift;
7149
7150         i = action->data().toInt() + 1;
7151
7152         if (i > 12) {
7153             shift = "shift_";
7154             i = i - 12;
7155         }
7156
7157         s += QString("macro_%1f%2();").arg(shift).arg(i);
7158
7159         VymModel *m = currentModel();
7160         if (m)
7161             m->execute(s);
7162     }
7163 }
7164
7165 void Main::downloadReleaseNotesFinished()
7166 {
7167     DownloadAgent *agent = static_cast<DownloadAgent *>(sender());
7168     QString s;
7169
7170     if (agent->isSuccess()) {
7171         QString page;
7172         if (agent->isSuccess()) {
7173             if (loadStringFromDisk(agent->getDestination(), page)) {
7174                 ShowTextDialog dia(this);
7175                 dia.setText(page);
7176                 dia.exec();
7177
7178                 // Don't load the release notes automatically again
7179                 settings.setValue("/downloads/releaseNotes/shownVersion",
7180                                   vymVersion);
7181             }
7182         }
7183     }
7184     else {
7185         statusMessage("Downloading release notes failed.");
7186         if (debug) {
7187             qDebug() << "Main::downloadReleaseNotesFinished ";
7188             qDebug() << "  result: failed";
7189             qDebug() << "     msg: " << agent->getResultMessage();
7190         }
7191     }
7192     agent->deleteLater();
7193
7194     if (checkUpdatesAfterReleaseNotes)
7195     {
7196         // After startup we want to check also for updates, but only after
7197         // releasenotes are there (and we have a cookie already)
7198         checkUpdatesAfterReleaseNotes = false;
7199         checkUpdates();
7200     }
7201 }
7202
7203 QUrl Main::serverUrl(const QString &scriptName)
7204 {
7205     // Local URL for testing only
7206     // QString("http://localhost/release-notes.php?vymVersion=%1") /
7207     return QUrl(
7208         QString("http://www.insilmaril.de/vym/%1?"
7209                     "vymVersion=%2"
7210                     "&config=darkTheme=%3+localeName=%4+buildDate=%5+codeQuality='%6'+codeName='%7'")
7211             .arg(scriptName)
7212             .arg(vymVersion)
7213             .arg(usingDarkTheme)
7214             .arg(localeName)
7215             .arg(vymBuildDate)
7216             .arg(vymCodeQuality)
7217             .arg(vymCodeName)
7218             );
7219 }
7220
7221 void Main::checkReleaseNotesAndUpdates ()
7222 {
7223     // Called once after startup
7224     // checkUpdatesAfterReleaseNotes is already true then
7225     checkReleaseNotes();
7226 }
7227
7228 void Main::checkReleaseNotes ()
7229 {
7230     bool userTriggered;
7231     if (qobject_cast<QAction *>(sender()))
7232         userTriggered = true;
7233     else
7234         userTriggered = false;
7235
7236     if (downloadsEnabled()) {
7237         if (userTriggered ||
7238             versionLowerThanVym(
7239                 settings.value("/downloads/releaseNotes/shownVersion", "0.0.1")
7240                     .toString())) {
7241             DownloadAgent *agent = new DownloadAgent(serverUrl("release-notes.php"));
7242             connect(agent, SIGNAL(downloadFinished()), this,
7243                     SLOT(downloadReleaseNotesFinished()));
7244             QTimer::singleShot(0, agent, SLOT(execute()));
7245         }
7246     }
7247     else {
7248         // No downloads enabled
7249         if (userTriggered) {
7250             // Notification: vym could not download release notes
7251             QMessageBox::warning(
7252                 0, tr("Warning"),
7253                 tr("Please allow vym to download release notes!"));
7254             if (downloadsEnabled(userTriggered))
7255                 checkUpdates();
7256         }
7257     }
7258 }
7259
7260 bool Main::downloadsEnabled(bool userTriggered)
7261 {
7262     bool result;
7263     if (!userTriggered &&
7264         settings.value("/downloads/enabled", false).toBool()) {
7265         result = true;
7266     }
7267     else {
7268         QDate lastAsked =
7269             settings.value("/downloads/permissionLastAsked", QDate(1970, 1, 1))
7270                 .toDate();
7271         if (userTriggered ||
7272             !settings.contains("/downloads/permissionLastAsked") ||
7273             lastAsked.daysTo(QDate::currentDate()) > 7) {
7274             QString infotext;
7275             infotext =
7276                 tr("<html>"
7277                    "<h3>Do you allow vym to check online for updates or "
7278                    "release notes?</h3>"
7279                    "If you allow, vym will "
7280                    "<ul>"
7281                    "<li>check once for release notes</li>"
7282                    "<li>check regulary for updates and notify you in case you "
7283                    "should update, e.g. if there are "
7284                    "important bug fixes available</li>"
7285                    "<li>receive a cookie with a random ID and send some anonymous data, like:"
7286                    "<ul>"
7287                    "<li>vym version</li>"
7288                    "<li>platform name and the ID (e.g. \"Windows\" or \"Linux\")</li>"
7289                    "<li>if you are using dark theme</li>"
7290                    "</ul>"
7291                    "This data is sent to me, Uwe Drechsel."
7292                    "<p>As vym developer I am motivated to see "
7293                    "many people using vym. Of course I am curious to see, on "
7294                    "which system vym is used. Maintaining each "
7295                    "of the systems requires a lot of my (spare) time.</p> "
7296                    "<p>No other data than above will be sent, especially no "
7297                    "private data will be collected or sent."
7298                    "(Check the source code, if you don't believe.)"
7299                    "</p>"
7300                    "</li>"
7301                    "</ul>"
7302                    "If you do not allow, "
7303                    "<ul>"
7304                    "<li>nothing will be downloaded and especially I will "
7305                    "<b>not be motivated</b> "
7306                    "to spend some more thousands of hours on developing a free "
7307                    "software tool."
7308                    "</ul>"
7309                    "Please allow vym to check for updates :-)");
7310             QMessageBox mb(vymName, infotext, QMessageBox::Information,
7311                            QMessageBox::Yes | QMessageBox::Default,
7312                            QMessageBox::No | QMessageBox::Escape,
7313                            QMessageBox::NoButton);
7314
7315             mb.setButtonText(QMessageBox::Yes, tr("Allow"));
7316             mb.setButtonText(QMessageBox::No, tr("Do not allow"));
7317             switch (mb.exec()) {
7318             case QMessageBox::Yes: {
7319                 result = true;
7320                 QMessageBox msgBox;
7321                 msgBox.setText(tr("Thank you for enabling downloads!"));
7322                 msgBox.setStandardButtons(QMessageBox::Close);
7323                 msgBox.setIconPixmap(QPixmap(":/flag-face-smile.svg"));
7324                 msgBox.exec();
7325                 break;
7326                                    }
7327             default:
7328                 result = false;
7329                 QMessageBox msgBox;
7330                 msgBox.setText(tr("That's ok, though I would be happy to see many users working with vym and also on which platforms."));
7331                 msgBox.setStandardButtons(QMessageBox::Close);
7332                 msgBox.setIconPixmap(QPixmap(":/flag-face-sad.svg"));
7333                 msgBox.exec();
7334                 break;
7335             }
7336         }
7337         else
7338             result = false;
7339         actionSettingsToggleDownloads->setChecked(result);
7340         settings.setValue("/downloads/enabled", result);
7341         settings.setValue("/downloads/permissionLastAsked",
7342                           QDate::currentDate().toString(Qt::ISODate));
7343     }
7344     return result;
7345 }
7346
7347 void Main::downloadUpdatesFinished(bool userTriggered)
7348 {
7349     DownloadAgent *agent = static_cast<DownloadAgent *>(sender());
7350     QString s;
7351
7352     if (agent->isSuccess()) {
7353         ShowTextDialog dia;
7354         dia.setWindowTitle(vymName + " - " + tr("Update information"));
7355         QString page;
7356         if (loadStringFromDisk(agent->getDestination(), page)) {
7357             if (page.contains("vymisuptodate")) {
7358                 statusMessage(tr("vym is up to date.", "MainWindow"));
7359                 if (userTriggered) {
7360                     // Notification: vym is up to date!
7361                     dia.setHtml(page);
7362                     dia.exec();
7363                 }
7364             }
7365             else if (page.contains("vymneedsupdate")) {
7366                 // Notification: updates available
7367                 dia.setHtml(page);
7368                 dia.exec();
7369             }
7370             else {
7371                 // Notification: Unknown version found
7372                 dia.setHtml(page);
7373                 dia.exec();
7374             }
7375
7376             // Prepare to check again later
7377             settings.setValue("/downloads/updates/lastChecked",
7378                               QDate::currentDate().toString(Qt::ISODate));
7379         }
7380         else
7381             statusMessage("Couldn't load update page from " +
7382                           agent->getDestination());
7383     }
7384     else {
7385         statusMessage("Check for updates failed.");
7386         if (debug) {
7387             qDebug() << "Main::downloadUpdatesFinished ";
7388             qDebug() << "  result: failed";
7389             qDebug() << "     msg: " << agent->getResultMessage();
7390         }
7391     }
7392     agent->deleteLater();
7393 }
7394
7395 void Main::downloadUpdatesFinishedInt() { downloadUpdatesFinished(true); }
7396
7397 void Main::downloadUpdates(bool userTriggered)
7398 {
7399     DownloadAgent *agent = new DownloadAgent(serverUrl("updates.php"));
7400     if (userTriggered)
7401         connect(agent, SIGNAL(downloadFinished()), this,
7402                 SLOT(downloadUpdatesFinishedInt()));
7403     else
7404         connect(agent, SIGNAL(downloadFinished()), this,
7405                 SLOT(downloadUpdatesFinished()));
7406     statusMessage(tr("Checking for updates...", "MainWindow"));
7407     QTimer::singleShot(0, agent, SLOT(execute()));
7408 }
7409
7410 void Main::checkUpdates()
7411 {
7412     bool userTriggered;
7413     if (qobject_cast<QAction *>(sender()))
7414         userTriggered = true;
7415     else
7416         userTriggered = false;
7417
7418     if (downloadsEnabled()) {
7419         // Too much time passed since last update check?
7420         QDate lastChecked =
7421             settings.value("/downloads/updates/lastChecked", QDate(1970, 1, 1))
7422                 .toDate();
7423         if (!lastChecked.isValid())
7424             lastChecked = QDate(1970, 1, 1);
7425         if (lastChecked.daysTo(QDate::currentDate()) >
7426                 settings.value("/downloads/updates/checkInterval", 3).toInt() ||
7427             userTriggered == true) {
7428             downloadUpdates(userTriggered);
7429         }
7430     }
7431     else {
7432         // No downloads enabled
7433         if (userTriggered) {
7434             // Notification: vym could not check for updates
7435             QMessageBox::warning(0, tr("Warning"),
7436                                  tr("Please allow vym to check for updates!"));
7437             if (downloadsEnabled(userTriggered))
7438                 checkUpdates();
7439         }
7440     }
7441 }
7442
7443 void Main::escapePressed()
7444 {
7445     if (presentationMode)
7446         togglePresentationMode();
7447     else
7448         setFocusMapEditor();
7449 }
7450
7451 void Main::togglePresentationMode()
7452 {
7453     QMap<QToolBar *, bool>::const_iterator i = toolbarStates.constBegin();
7454     if (!presentationMode) {
7455
7456         presentationMode = true;
7457         while (i != toolbarStates.constEnd()) {
7458             toolbarStates[i.key()] = i.key()->isVisible();
7459             i.key()->hide();
7460             ++i;
7461         }
7462         menuBar()->hide();
7463     }
7464     else {
7465         presentationMode = false;
7466         while (i != toolbarStates.constEnd()) {
7467             i.key()->setVisible(i.value());
7468             ++i;
7469         }
7470         menuBar()->show();
7471     }
7472 }