3 #include <q3filedialog.h>
12 #include "editxlinkdialog.h"
14 #include "extrainfodialog.h"
16 #include "linkablemapobj.h"
17 #include "mainwindow.h"
19 #include "texteditor.h"
20 #include "warningdialog.h"
24 extern TextEditor *textEditor;
25 extern int statusbarTime;
26 extern Main *mainWindow;
27 extern QString tmpVymDir;
28 extern QString clipboardDir;
29 extern QString clipboardFile;
30 extern bool clipboardEmpty;
32 extern FlagRowObj *standardFlagsDefault;
34 extern QMenu* branchContextMenu;
35 extern QMenu* branchAddContextMenu;
36 extern QMenu* branchRemoveContextMenu;
37 extern QMenu* branchLinksContextMenu;
38 extern QMenu* branchXLinksContextMenuEdit;
39 extern QMenu* branchXLinksContextMenuFollow;
40 extern QMenu* floatimageContextMenu;
41 extern QMenu* canvasContextMenu;
44 extern Settings settings;
45 extern ImageIO imageIO;
47 extern QString vymName;
48 extern QString vymVersion;
50 extern QString iconPath;
51 extern QDir vymBaseDir;
52 extern QDir lastImageDir;
53 extern QDir lastFileDir;
55 int MapEditor::mapNum=0; // make instance
57 ///////////////////////////////////////////////////////////////////////
58 ///////////////////////////////////////////////////////////////////////
59 MapEditor::MapEditor( QWidget* parent) :
62 //cout << "Constructor ME "<<this<<endl;
66 mapScene= new QGraphicsScene(parent);
67 //mapScene= new QGraphicsScene(QRectF(0,0,width(),height()), parent);
68 mapScene->setBackgroundBrush (QBrush(Qt::white, Qt::SolidPattern));
73 mapCenter = new MapCenterObj(mapScene);
74 mapCenter->setVisibility (true);
75 mapCenter->setMapEditor (this);
76 mapCenter->setHeading (tr("New Map","Heading of mapcenter in new map"));
77 //mapCenter->move(mapScene->width()/2-mapCenter->width()/2,mapScene->height()/2-mapCenter->height()/2);
82 defLinkColor=QColor (0,0,255);
83 defXLinkColor=QColor (180,180,180);
84 linkcolorhint=LinkableMapObj::DefaultColor;
85 linkstyle=LinkableMapObj::PolyParabel;
87 // Create bitmap cursors, platform dependant
88 HandOpenCursor=QCursor (QPixmap(iconPath+"cursorhandopen.png"),1,1);
89 PickColorCursor=QCursor ( QPixmap(iconPath+"cursorcolorpicker.png"), 5,27 );
90 CopyCursor=QCursor ( QPixmap(iconPath+"cursorcopy.png"), 1,1 );
91 XLinkCursor=QCursor ( QPixmap(iconPath+"cursorxlink.png"), 1,7 );
93 setFocusPolicy (Qt::StrongFocus);
102 xelection.setMapEditor (this);
103 xelection.unselect();
106 defXLinkColor=QColor (230,230,230);
114 fileName=tr("unnamed");
117 stepsTotal=settings.readNumEntry("/mapeditor/stepsTotal",100);
118 undoSet.setEntry ("/history/stepsTotal",QString::number(stepsTotal));
119 mainWindow->updateHistory (undoSet);
121 // Initialize find routine
128 blockReposition=false;
129 blockSaveState=false;
131 hidemode=BranchObj::HideNone;
133 // Create temporary files
140 setAcceptDrops (true);
142 mapCenter->reposition(); // for positioning heading
146 //timerId = startTimer(100);
149 autosaveTimer=new QTimer (this);
150 connect(autosaveTimer, SIGNAL(timeout()), this, SLOT(autosave()));
153 MapEditor::~MapEditor()
155 //cout <<"Destructor MapEditor\n";
156 autosaveTimer->stop();
159 MapCenterObj* MapEditor::getMapCenter()
164 QGraphicsScene * MapEditor::getScene()
169 MapEditor::State MapEditor::getState()
174 void MapEditor::setStateEditHeading(bool s)
178 if (state==Idle) state=EditHeading;
184 bool MapEditor::isRepositionBlocked()
186 return blockReposition;
189 void MapEditor::setSaveStateBlocked(bool b)
194 bool MapEditor::isSelectBlocked()
196 if (state==EditHeading)
202 QString MapEditor::getName (const LinkableMapObj *lmo)
205 if (!lmo) return QString("Error: NULL has no name!");
207 if ((typeid(*lmo) == typeid(BranchObj) ||
208 typeid(*lmo) == typeid(MapCenterObj)))
211 s=(((BranchObj*)lmo)->getHeading());
212 if (s=="") s="unnamed";
213 return QString("branch (%1)").arg(s);
214 //return QString("branch (<font color=\"#0000ff\">%1</font>)").arg(s);
216 if ((typeid(*lmo) == typeid(FloatImageObj) ))
217 return QString ("floatimage [%1]").arg(((FloatImageObj*)lmo)->getOriginalFilename());
218 //return QString ("floatimage [<font color=\"#0000ff\">%1</font>]").arg(((FloatImageObj*)lmo)->getOriginalFilename());
219 return QString("Unknown type has no name!");
222 void MapEditor::makeTmpDirs()
224 // Create unique temporary directories
225 tmpMapDir=QDir::convertSeparators (tmpVymDir+QString("/mapeditor-%1").arg(mapNum));
226 histPath=QDir::convertSeparators (tmpMapDir+"/history");
231 QString MapEditor::saveToDir(const QString &tmpdir, const QString &prefix, bool writeflags, const QPointF &offset, LinkableMapObj *saveSel)
233 // tmpdir temporary directory to which data will be written
234 // prefix mapname, which will be appended to images etc.
235 // writeflags Only write flags for "real" save of map, not undo
236 // offset offset of bbox of whole map in scene.
237 // Needed for XML export
243 case LinkableMapObj::Line:
246 case LinkableMapObj::Parabel:
249 case LinkableMapObj::PolyLine:
253 ls="StylePolyParabel";
257 QString s="<?xml version=\"1.0\" encoding=\"utf-8\"?><!DOCTYPE vymmap>\n";
259 if (linkcolorhint==LinkableMapObj::HeadingColor)
260 colhint=attribut("linkColorHint","HeadingColor");
262 QString mapAttr=attribut("version",vymVersion);
263 if (!saveSel || saveSel==mapCenter)
264 mapAttr+= attribut("author",mapCenter->getAuthor()) +
265 attribut("comment",mapCenter->getComment()) +
266 attribut("date",mapCenter->getDate()) +
267 attribut("backgroundColor", mapScene->backgroundBrush().color().name() ) +
268 attribut("selectionColor", xelection.getColor().name() ) +
269 attribut("linkStyle", ls ) +
270 attribut("linkColor", defLinkColor.name() ) +
271 attribut("defXLinkColor", defXLinkColor.name() ) +
272 attribut("defXLinkWidth", QString().setNum(defXLinkWidth,10) ) +
274 s+=beginElement("vymmap",mapAttr);
277 // Find the used flags while traversing the tree
278 standardFlagsDefault->resetUsedCounter();
280 // Reset the counters before saving
281 // TODO constr. of FIO creates lots of objects, better do this in some other way...
282 FloatImageObj (mapScene).resetSaveCounter();
284 // Build xml recursivly
285 if (!saveSel || typeid (*saveSel) == typeid (MapCenterObj))
286 // Save complete map, if saveSel not set
287 s+=mapCenter->saveToDir(tmpdir,prefix,writeflags,offset);
290 if ( typeid(*saveSel) == typeid(BranchObj) )
292 s+=((BranchObj*)(saveSel))->saveToDir(tmpdir,prefix,offset);
293 else if ( typeid(*saveSel) == typeid(FloatImageObj) )
295 s+=((FloatImageObj*)(saveSel))->saveToDir(tmpdir,prefix);
298 // Save local settings
299 s+=settings.getXMLData (destPath);
302 if (!xelection.isEmpty() && !saveSel )
303 s+=valueElement("select",xelection.getSelectString());
306 s+=endElement("vymmap");
309 standardFlagsDefault->saveToDir (tmpdir+"/flags/","",writeflags);
313 QString MapEditor::getHistoryDir()
315 QString histName=QDir::convertSeparators (QString("history-%1").arg(curStep));
316 return QDir::convertSeparators (tmpMapDir +"/"+histName);
319 void MapEditor::saveState(const SaveMode &savemode, const QString &undoSelection, const QString &undoCom, const QString &redoSelection, const QString &redoCom, const QString &comment, LinkableMapObj *saveSel)
323 if (blockSaveState) return;
325 if (debug) cout << "ME::saveState() for "<<mapName.ascii()<<endl;
327 // Find out current undo directory
328 if (undosAvail<stepsTotal) undosAvail++;
330 if (curStep>stepsTotal) curStep=1;
332 QString backupXML="";
333 QString histDir=getHistoryDir();
334 QString bakMapPath=QDir::convertSeparators(histDir+"/map.xml");
336 // Create histDir if not available
339 makeSubDirs (histDir);
341 // Save depending on how much needs to be saved
343 backupXML=saveToDir (histDir,mapName+"-",false, QPointF (),saveSel);
345 QString undoCommand="";
346 if (savemode==UndoCommand)
350 else if (savemode==PartOfMap )
353 undoCommand.replace ("PATH",bakMapPath);
356 if (!backupXML.isEmpty())
357 // Write XML Data to disk
358 saveStringToDisk (QString(bakMapPath),backupXML);
360 // We would have to save all actions in a tree, to keep track of
361 // possible redos after a action. Possible, but we are too lazy: forget about redos.
364 // Write the current state to disk
365 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
366 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
367 undoSet.setEntry ("/history/curStep",QString::number(curStep));
368 undoSet.setEntry (QString("/history/step-%1/undoCommand").arg(curStep),undoCommand);
369 undoSet.setEntry (QString("/history/step-%1/undoSelection").arg(curStep),undoSelection);
370 undoSet.setEntry (QString("/history/step-%1/redoCommand").arg(curStep),redoCom);
371 undoSet.setEntry (QString("/history/step-%1/redoSelection").arg(curStep),redoSelection);
372 undoSet.setEntry (QString("/history/step-%1/comment").arg(curStep),comment);
373 undoSet.setEntry (QString("/history/version"),vymVersion);
374 undoSet.writeSettings(histPath);
378 // TODO remove after testing
379 //cout << " into="<< histPath.toStdString()<<endl;
380 cout << " stepsTotal="<<stepsTotal<<
381 ", undosAvail="<<undosAvail<<
382 ", redosAvail="<<redosAvail<<
383 ", curStep="<<curStep<<endl;
384 cout << " ---------------------------"<<endl;
385 cout << " comment="<<comment.toStdString()<<endl;
386 cout << " undoCom="<<undoCommand.toStdString()<<endl;
387 cout << " undoSel="<<undoSelection.toStdString()<<endl;
388 cout << " redoCom="<<redoCom.toStdString()<<endl;
389 cout << " redoSel="<<redoSelection.toStdString()<<endl;
390 if (saveSel) cout << " saveSel="<<saveSel->getSelectString().ascii()<<endl;
391 cout << " ---------------------------"<<endl;
394 mainWindow->updateHistory (undoSet);
400 void MapEditor::saveStateChangingPart(LinkableMapObj *undoSel, LinkableMapObj* redoSel, const QString &rc, const QString &comment)
402 // save the selected part of the map, Undo will replace part of map
403 QString undoSelection="";
405 undoSelection=undoSel->getSelectString();
407 qWarning ("MapEditor::saveStateChangingPart no undoSel given!");
408 QString redoSelection="";
410 redoSelection=undoSel->getSelectString();
412 qWarning ("MapEditor::saveStateChangingPart no redoSel given!");
415 saveState (PartOfMap,
416 undoSelection, "addMapReplace (\"PATH\")",
422 void MapEditor::saveStateRemovingPart(LinkableMapObj *redoSel, const QString &comment)
426 qWarning ("MapEditor::saveStateRemovingPart no redoSel given!");
429 QString undoSelection=redoSel->getParObj()->getSelectString();
430 QString redoSelection=redoSel->getSelectString();
431 if (typeid(*redoSel) == typeid(BranchObj) )
433 // save the selected branch of the map, Undo will insert part of map
434 saveState (PartOfMap,
435 undoSelection, QString("addMapInsert (\"PATH\",%1)").arg(((BranchObj*)redoSel)->getNum()),
436 redoSelection, "delete ()",
443 void MapEditor::saveState(LinkableMapObj *undoSel, const QString &uc, LinkableMapObj *redoSel, const QString &rc, const QString &comment)
445 // "Normal" savestate: save commands, selections and comment
446 // so just save commands for undo and redo
447 // and use current selection
449 QString redoSelection="";
450 if (redoSel) redoSelection=redoSel->getSelectString();
451 QString undoSelection="";
452 if (undoSel) undoSelection=undoSel->getSelectString();
454 saveState (UndoCommand,
461 void MapEditor::saveState(const QString &undoSel, const QString &uc, const QString &redoSel, const QString &rc, const QString &comment)
463 // "Normal" savestate: save commands, selections and comment
464 // so just save commands for undo and redo
465 // and use current selection
466 saveState (UndoCommand,
474 void MapEditor::parseAtom(const QString &atom)
476 BranchObj *selb=xelection.getBranch();
481 // Split string s into command and parameters
482 parser.parseAtom (atom);
483 QString com=parser.getCommand();
486 if (com=="addBranch")
488 if (xelection.isEmpty())
490 parser.setError (Aborted,"Nothing selected");
493 parser.setError (Aborted,"Type of selection is not a branch");
498 if (parser.checkParamCount(pl))
500 if (parser.paramCount()==0)
501 addNewBranchInt (-2);
504 y=parser.parInt (ok,0);
505 if (ok ) addNewBranchInt (y);
509 } else if (com=="addBranchBefore")
511 if (xelection.isEmpty())
513 parser.setError (Aborted,"Nothing selected");
516 parser.setError (Aborted,"Type of selection is not a branch");
519 if (parser.paramCount()==0)
521 addNewBranchBefore ();
524 } else if (com==QString("addMapReplace"))
526 if (xelection.isEmpty())
528 parser.setError (Aborted,"Nothing selected");
531 parser.setError (Aborted,"Type of selection is not a branch");
532 } else if (parser.checkParamCount(1))
534 //s=parser.parString (ok,0); // selection
535 t=parser.parString (ok,0); // path to map
536 if (QDir::isRelativePath(t)) t=QDir::convertSeparators (tmpMapDir + "/"+t);
537 addMapReplaceInt(selb->getSelectString(),t);
539 } else if (com==QString("addMapInsert"))
541 if (xelection.isEmpty())
543 parser.setError (Aborted,"Nothing selected");
546 parser.setError (Aborted,"Type of selection is not a branch");
549 if (parser.checkParamCount(2))
551 t=parser.parString (ok,0); // path to map
552 y=parser.parInt(ok,1); // position
553 if (QDir::isRelativePath(t)) t=QDir::convertSeparators (tmpMapDir + "/"+t);
554 addMapInsertInt(t,y);
557 } else if (com=="clearFlags")
559 if (xelection.isEmpty() )
561 parser.setError (Aborted,"Nothing selected");
564 parser.setError (Aborted,"Type of selection is not a branch");
565 } else if (parser.checkParamCount(0))
567 selb->clearStandardFlags();
568 selb->updateFlagsToolbar();
570 } else if (com=="colorBranch")
572 if (xelection.isEmpty())
574 parser.setError (Aborted,"Nothing selected");
577 parser.setError (Aborted,"Type of selection is not a branch");
578 } else if (parser.checkParamCount(1))
580 QColor c=parser.parColor (ok,0);
581 if (ok) colorBranch (c);
583 } else if (com=="colorSubtree")
585 if (xelection.isEmpty())
587 parser.setError (Aborted,"Nothing selected");
590 parser.setError (Aborted,"Type of selection is not a branch");
591 } else if (parser.checkParamCount(1))
593 QColor c=parser.parColor (ok,0);
594 if (ok) colorSubtree (c);
596 } else if (com=="copy")
598 if (xelection.isEmpty())
600 parser.setError (Aborted,"Nothing selected");
603 parser.setError (Aborted,"Type of selection is not a branch");
604 } else if (parser.checkParamCount(0))
606 //FIXME missing action for copy
608 } else if (com=="cut")
610 if (xelection.isEmpty())
612 parser.setError (Aborted,"Nothing selected");
613 } else if ( xelection.type()!=Selection::Branch &&
614 xelection.type()!=Selection::MapCenter &&
615 xelection.type()!=Selection::FloatImage )
617 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
618 } else if (parser.checkParamCount(0))
622 } else if (com=="delete")
624 if (xelection.isEmpty())
626 parser.setError (Aborted,"Nothing selected");
627 } else if (xelection.type() != Selection::Branch && xelection.type() != Selection::FloatImage )
629 parser.setError (Aborted,"Type of selection is wrong.");
630 } else if (parser.checkParamCount(0))
634 } else if (com=="deleteKeepChilds")
636 if (xelection.isEmpty())
638 parser.setError (Aborted,"Nothing selected");
641 parser.setError (Aborted,"Type of selection is not a branch");
642 } else if (parser.checkParamCount(0))
646 } else if (com=="deleteChilds")
648 if (xelection.isEmpty())
650 parser.setError (Aborted,"Nothing selected");
653 parser.setError (Aborted,"Type of selection is not a branch");
654 } else if (parser.checkParamCount(0))
658 } else if (com=="importDir")
660 if (xelection.isEmpty())
662 parser.setError (Aborted,"Nothing selected");
665 parser.setError (Aborted,"Type of selection is not a branch");
666 } else if (parser.checkParamCount(1))
668 s=parser.parString(ok,0);
669 if (ok) importDirInt(s);
671 } else if (com=="linkTo")
673 if (xelection.isEmpty())
675 parser.setError (Aborted,"Nothing selected");
678 if (parser.checkParamCount(4))
680 // 0 selectstring of parent
681 // 1 num in parent (for branches)
682 // 2,3 x,y of mainbranch or mapcenter
683 s=parser.parString(ok,0);
684 LinkableMapObj *dst=mapCenter->findObjBySelect (s);
687 if (typeid(*dst) == typeid(BranchObj) )
689 // Get number in parent
690 x=parser.parInt (ok,1);
692 selb->linkTo ((BranchObj*)(dst),x);
693 } else if (typeid(*dst) == typeid(MapCenterObj) )
695 selb->linkTo ((BranchObj*)(dst),-1);
696 // Get coordinates of mainbranch
697 x=parser.parInt (ok,2);
700 y=parser.parInt (ok,3);
701 if (ok) selb->move (x,y);
706 } else if ( xelection.type() == Selection::FloatImage)
708 if (parser.checkParamCount(1))
710 // 0 selectstring of parent
711 s=parser.parString(ok,0);
712 LinkableMapObj *dst=mapCenter->findObjBySelect (s);
715 if (typeid(*dst) == typeid(BranchObj) ||
716 typeid(*dst) == typeid(MapCenterObj))
717 linkTo (dst->getSelectString());
719 parser.setError (Aborted,"Destination is not a branch");
722 parser.setError (Aborted,"Type of selection is not a floatimage or branch");
723 } else if (com=="loadImage")
725 if (xelection.isEmpty())
727 parser.setError (Aborted,"Nothing selected");
730 parser.setError (Aborted,"Type of selection is not a branch");
731 } else if (parser.checkParamCount(1))
733 s=parser.parString(ok,0);
734 if (ok) loadFloatImageInt (s);
736 } else if (com=="moveBranchUp")
738 if (xelection.isEmpty() )
740 parser.setError (Aborted,"Nothing selected");
743 parser.setError (Aborted,"Type of selection is not a branch");
744 } else if (parser.checkParamCount(0))
748 } else if (com=="moveBranchDown")
750 if (xelection.isEmpty() )
752 parser.setError (Aborted,"Nothing selected");
755 parser.setError (Aborted,"Type of selection is not a branch");
756 } else if (parser.checkParamCount(0))
760 } else if (com=="move")
762 if (xelection.isEmpty() )
764 parser.setError (Aborted,"Nothing selected");
765 } else if ( xelection.type()!=Selection::Branch &&
766 xelection.type()!=Selection::MapCenter &&
767 xelection.type()!=Selection::FloatImage )
769 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
770 } else if (parser.checkParamCount(2))
772 x=parser.parInt (ok,0);
775 y=parser.parInt (ok,1);
779 } else if (com=="moveRel")
781 if (xelection.isEmpty() )
783 parser.setError (Aborted,"Nothing selected");
784 } else if ( xelection.type()!=Selection::Selection::Branch &&
785 xelection.type()!=Selection::Selection::MapCenter &&
786 xelection.type()!=Selection::Selection::FloatImage )
788 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
789 } else if (parser.checkParamCount(2))
791 x=parser.parInt (ok,0);
794 y=parser.parInt (ok,1);
795 if (ok) moveRel (x,y);
798 } else if (com=="nop")
800 } else if (com=="paste")
802 if (xelection.isEmpty() )
804 parser.setError (Aborted,"Nothing selected");
807 parser.setError (Aborted,"Type of selection is not a branch");
808 } else if (parser.checkParamCount(1))
810 x=parser.parInt (ok,0);
811 if (ok) pasteNoSave(x);
813 /////////////////////////////////////////////////////////////////////
814 } else if (com=="qa")
816 if (xelection.isEmpty() )
818 parser.setError (Aborted,"Nothing selected");
821 parser.setError (Aborted,"Type of selection is not a branch");
822 } else if (parser.checkParamCount(4))
825 c=parser.parString (ok,0);
828 parser.setError (Aborted,"No comment given");
831 s=parser.parString (ok,1);
834 parser.setError (Aborted,"First parameter is not a string");
837 t=parser.parString (ok,2);
840 parser.setError (Aborted,"Condition is not a string");
843 u=parser.parString (ok,3);
846 parser.setError (Aborted,"Third parameter is not a string");
851 parser.setError (Aborted,"Unknown type: "+s);
856 parser.setError (Aborted,"Unknown operator: "+t);
861 parser.setError (Aborted,"Type of selection is not a branch");
864 if (selb->getHeading() == u)
866 cout << "PASSED: " << c.ascii() << endl;
869 cout << "FAILED: " << c.ascii() << endl;
879 } else if (com=="saveImage")
881 FloatImageObj *fio=xelection.getFloatImage();
884 parser.setError (Aborted,"Type of selection is not an image");
885 } else if (parser.checkParamCount(2))
887 s=parser.parString(ok,0);
890 t=parser.parString(ok,1);
891 if (ok) saveFloatImageInt (fio,t,s);
894 } else if (com=="scroll")
896 if (xelection.isEmpty() )
898 parser.setError (Aborted,"Nothing selected");
901 parser.setError (Aborted,"Type of selection is not a branch");
902 } else if (parser.checkParamCount(0))
904 if (!scrollBranch (selb))
905 parser.setError (Aborted,"Could not scroll branch");
907 } else if (com=="select")
909 if (parser.checkParamCount(1))
911 s=parser.parString(ok,0);
914 } else if (com=="selectLastBranch")
916 if (xelection.isEmpty() )
918 parser.setError (Aborted,"Nothing selected");
921 parser.setError (Aborted,"Type of selection is not a branch");
922 } else if (parser.checkParamCount(0))
924 BranchObj *bo=selb->getLastBranch();
926 parser.setError (Aborted,"Could not select last branch");
930 } else if (com=="selectLastImage")
932 if (xelection.isEmpty() )
934 parser.setError (Aborted,"Nothing selected");
937 parser.setError (Aborted,"Type of selection is not a branch");
938 } else if (parser.checkParamCount(0))
940 FloatImageObj *fio=selb->getLastFloatImage();
942 parser.setError (Aborted,"Could not select last image");
946 } else if (com=="setFrameType")
948 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
950 parser.setError (Aborted,"Type of selection does not allow setting frame type");
952 else if (parser.checkParamCount(1))
954 s=parser.parString(ok,0);
955 if (ok) setFrameType (s);
957 } else if (com=="setFramePenColor")
959 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
961 parser.setError (Aborted,"Type of selection does not allow setting of pen color");
963 else if (parser.checkParamCount(1))
965 QColor c=parser.parColor(ok,0);
966 if (ok) setFramePenColor (c);
968 } else if (com=="setFrameBrushColor")
970 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
972 parser.setError (Aborted,"Type of selection does not allow setting brush color");
974 else if (parser.checkParamCount(1))
976 QColor c=parser.parColor(ok,0);
977 if (ok) setFrameBrushColor (c);
979 } else if (com=="setFramePadding")
981 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
983 parser.setError (Aborted,"Type of selection does not allow setting frame padding");
985 else if (parser.checkParamCount(1))
987 x=parser.parInt(ok,0);
988 if (ok) setFramePadding(x);
990 } else if (com=="setFrameBorderWidth")
992 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
994 parser.setError (Aborted,"Type of selection does not allow setting frame border width");
996 else if (parser.checkParamCount(1))
998 x=parser.parInt(ok,0);
999 if (ok) setFrameBorderWidth (x);
1001 } else if (com=="setMapAuthor")
1003 if (parser.checkParamCount(1))
1005 s=parser.parString(ok,0);
1006 if (ok) setMapAuthor (s);
1008 } else if (com=="setMapComment")
1010 if (parser.checkParamCount(1))
1012 s=parser.parString(ok,0);
1013 if (ok) setMapComment(s);
1015 } else if (com=="setMapBackgroundColor")
1017 if (xelection.isEmpty() )
1019 parser.setError (Aborted,"Nothing selected");
1020 } else if (! xelection.getBranch() )
1022 parser.setError (Aborted,"Type of selection is not a branch");
1023 } else if (parser.checkParamCount(1))
1025 QColor c=parser.parColor (ok,0);
1026 if (ok) setMapBackgroundColor (c);
1028 } else if (com=="setMapDefLinkColor")
1030 if (xelection.isEmpty() )
1032 parser.setError (Aborted,"Nothing selected");
1035 parser.setError (Aborted,"Type of selection is not a branch");
1036 } else if (parser.checkParamCount(1))
1038 QColor c=parser.parColor (ok,0);
1039 if (ok) setMapDefLinkColor (c);
1041 } else if (com=="setMapLinkStyle")
1043 if (parser.checkParamCount(1))
1045 s=parser.parString (ok,0);
1046 if (ok) setMapLinkStyle(s);
1048 } else if (com=="setHeading")
1050 if (xelection.isEmpty() )
1052 parser.setError (Aborted,"Nothing selected");
1055 parser.setError (Aborted,"Type of selection is not a branch");
1056 } else if (parser.checkParamCount(1))
1058 s=parser.parString (ok,0);
1062 } else if (com=="setHideExport")
1064 if (xelection.isEmpty() )
1066 parser.setError (Aborted,"Nothing selected");
1067 } else if (xelection.type()!=Selection::Branch && xelection.type() != Selection::MapCenter &&xelection.type()!=Selection::FloatImage)
1069 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
1070 } else if (parser.checkParamCount(1))
1072 b=parser.parBool(ok,0);
1073 if (ok) setHideExport (b);
1075 } else if (com=="setIncludeImagesHorizontally")
1077 if (xelection.isEmpty() )
1079 parser.setError (Aborted,"Nothing selected");
1082 parser.setError (Aborted,"Type of selection is not a branch");
1083 } else if (parser.checkParamCount(1))
1085 b=parser.parBool(ok,0);
1086 if (ok) setIncludeImagesHor(b);
1088 } else if (com=="setIncludeImagesVertically")
1090 if (xelection.isEmpty() )
1092 parser.setError (Aborted,"Nothing selected");
1095 parser.setError (Aborted,"Type of selection is not a branch");
1096 } else if (parser.checkParamCount(1))
1098 b=parser.parBool(ok,0);
1099 if (ok) setIncludeImagesVer(b);
1101 } else if (com=="setHideLinkUnselected")
1103 if (xelection.isEmpty() )
1105 parser.setError (Aborted,"Nothing selected");
1106 } else if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
1108 parser.setError (Aborted,"Type of selection does not allow hiding the link");
1109 } else if (parser.checkParamCount(1))
1111 b=parser.parBool(ok,0);
1112 if (ok) setHideLinkUnselected(b);
1114 } else if (com=="setSelectionColor")
1116 if (parser.checkParamCount(1))
1118 QColor c=parser.parColor (ok,0);
1119 if (ok) setSelectionColorInt (c);
1121 } else if (com=="setURL")
1123 if (xelection.isEmpty() )
1125 parser.setError (Aborted,"Nothing selected");
1128 parser.setError (Aborted,"Type of selection is not a branch");
1129 } else if (parser.checkParamCount(1))
1131 s=parser.parString (ok,0);
1134 } else if (com=="setVymLink")
1136 if (xelection.isEmpty() )
1138 parser.setError (Aborted,"Nothing selected");
1141 parser.setError (Aborted,"Type of selection is not a branch");
1142 } else if (parser.checkParamCount(1))
1144 s=parser.parString (ok,0);
1145 if (ok) setVymLinkInt(s);
1148 else if (com=="setFlag")
1150 if (xelection.isEmpty() )
1152 parser.setError (Aborted,"Nothing selected");
1155 parser.setError (Aborted,"Type of selection is not a branch");
1156 } else if (parser.checkParamCount(1))
1158 s=parser.parString(ok,0);
1161 selb->activateStandardFlag(s);
1162 selb->updateFlagsToolbar();
1165 } else if (com=="setFrameType")
1167 if (xelection.isEmpty() )
1169 parser.setError (Aborted,"Nothing selected");
1172 parser.setError (Aborted,"Type of selection is not a branch");
1173 } else if (parser.checkParamCount(1))
1175 s=parser.parString(ok,0);
1179 } else if (com=="toggleFlag")
1181 if (xelection.isEmpty() )
1183 parser.setError (Aborted,"Nothing selected");
1186 parser.setError (Aborted,"Type of selection is not a branch");
1187 } else if (parser.checkParamCount(1))
1189 s=parser.parString(ok,0);
1192 selb->toggleStandardFlag(s);
1193 selb->updateFlagsToolbar();
1196 } else if (com=="unscroll")
1198 if (xelection.isEmpty() )
1200 parser.setError (Aborted,"Nothing selected");
1203 parser.setError (Aborted,"Type of selection is not a branch");
1204 } else if (parser.checkParamCount(0))
1206 if (!unscrollBranch (selb))
1207 parser.setError (Aborted,"Could not unscroll branch");
1209 } else if (com=="unscrollChilds")
1211 if (xelection.isEmpty() )
1213 parser.setError (Aborted,"Nothing selected");
1216 parser.setError (Aborted,"Type of selection is not a branch");
1217 } else if (parser.checkParamCount(0))
1221 } else if (com=="unsetFlag")
1223 if (xelection.isEmpty() )
1225 parser.setError (Aborted,"Nothing selected");
1228 parser.setError (Aborted,"Type of selection is not a branch");
1229 } else if (parser.checkParamCount(1))
1231 s=parser.parString(ok,0);
1234 selb->deactivateStandardFlag(s);
1235 selb->updateFlagsToolbar();
1239 parser.setError (Aborted,"Unknown command");
1242 if (parser.errorLevel()==NoError)
1245 mapCenter->reposition();
1249 // TODO Error handling
1250 qWarning("MapEditor::parseAtom: Error!");
1251 qWarning(parser.errorMessage());
1255 void MapEditor::runScript (QString script)
1257 parser.setScript (script);
1259 while (parser.next() )
1260 parseAtom(parser.getAtom());
1263 bool MapEditor::isDefault()
1268 bool MapEditor::hasChanged()
1273 void MapEditor::setChanged()
1276 autosaveTimer->start(settings.value("/mapeditor/autosave/ms/",300000).toInt());
1284 void MapEditor::closeMap()
1286 // Unselect before disabling the toolbar actions
1287 if (!xelection.isEmpty() ) xelection.unselect();
1295 void MapEditor::setFilePath(QString fpath, QString destname)
1297 if (fpath.isEmpty() || fpath=="")
1304 filePath=fpath; // becomes absolute path
1305 fileName=fpath; // gets stripped of path
1306 destPath=destname; // needed for vymlinks
1308 // If fpath is not an absolute path, complete it
1309 filePath=QDir(fpath).absPath();
1310 fileDir=filePath.left (1+filePath.findRev ("/"));
1312 // Set short name, too. Search from behind:
1313 int i=fileName.findRev("/");
1314 if (i>=0) fileName=fileName.remove (0,i+1);
1316 // Forget the .vym (or .xml) for name of map
1317 mapName=fileName.left(fileName.findRev(".",-1,true) );
1321 void MapEditor::setFilePath(QString fpath)
1323 setFilePath (fpath,fpath);
1326 QString MapEditor::getFilePath()
1331 QString MapEditor::getFileName()
1336 QString MapEditor::getMapName()
1341 QString MapEditor::getDestPath()
1346 ErrorCode MapEditor::load (QString fname, LoadMode lmode)
1348 ErrorCode err=success;
1352 if (xelection.isEmpty() ) xelection.unselect();
1355 mapCenter->setMapEditor(this);
1356 // (map state is set later at end of load...)
1359 BranchObj *bo=xelection.getBranch();
1360 if (!bo) return aborted;
1361 if (lmode==ImportAdd)
1362 saveStateChangingPart(
1365 QString("addMapInsert (%1)").arg(fname),
1366 QString("Add map %1 to %2").arg(fname).arg(getName(bo)));
1368 saveStateChangingPart(
1371 QString("addMapReplace(%1)").arg(fname),
1372 QString("Add map %1 to %2").arg(fname).arg(getName(bo)));
1376 mapBuilderHandler handler;
1377 QFile file( fname );
1379 // I am paranoid: file should exist anyway
1380 // according to check in mainwindow.
1381 if (!file.exists() )
1383 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
1384 tr("Couldn't open map " +fname)+".");
1388 bool blockSaveStateOrg=blockSaveState;
1389 blockReposition=true;
1390 blockSaveState=true;
1391 QXmlInputSource source( file);
1392 QXmlSimpleReader reader;
1393 reader.setContentHandler( &handler );
1394 reader.setErrorHandler( &handler );
1395 handler.setMapEditor( this );
1398 // We need to set the tmpDir in order to load files with rel. path
1399 QString tmpdir= fname.left(fname.findRev("/",-1));
1400 handler.setTmpDir (tmpdir);
1401 handler.setInputFile (file.name());
1402 handler.setLoadMode (lmode);
1403 bool ok = reader.parse( source );
1404 blockReposition=false;
1405 blockSaveState=blockSaveStateOrg;
1409 mapCenter->reposition();
1416 autosaveTimer->stop();
1420 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
1421 tr( handler.errorProtocol() ) );
1423 // Still return "success": the map maybe at least
1424 // partially read by the parser
1431 int MapEditor::save (const SaveMode &savemode)
1435 // Create mapName and fileDir
1436 makeSubDirs (fileDir);
1440 fname=mapName+".xml";
1442 // use name given by user, even if he chooses .doc
1447 if (savemode==CompleteMap || xelection.isEmpty())
1448 saveFile=saveToDir (fileDir,mapName+"-",true,QPointF(),NULL);
1451 // TODO take care of multiselections
1452 if (xelection.type()==Selection::FloatImage)
1455 saveFile=saveToDir (fileDir,mapName+"-",true,QPointF(),xelection.getBranch());
1458 if (!saveStringToDisk(fileDir+fname,saveFile))
1465 autosaveTimer->stop();
1472 void MapEditor::setZipped (bool z)
1477 bool MapEditor::saveZipped ()
1482 void MapEditor::print()
1486 printer = new QPrinter;
1487 printer->setColorMode (QPrinter::Color);
1488 printer->setPrinterName (settings.value("/mainwindow/printerName",printer->printerName()).toString());
1489 printer->setOutputFormat((QPrinter::OutputFormat)settings.value("/mainwindow/printerFormat",printer->outputFormat()).toInt());
1490 printer->setOutputFileName(settings.value("/mainwindow/printerFileName",printer->outputFileName()).toString());
1493 QRectF totalBBox=mapCenter->getTotalBBox();
1495 // Try to set orientation automagically
1496 // Note: Interpretation of generated postscript is amibiguous, if
1497 // there are problems with landscape mode, see
1498 // http://sdb.suse.de/de/sdb/html/jsmeix_print-cups-landscape-81.html
1500 if (totalBBox.width()>totalBBox.height())
1501 // recommend landscape
1502 printer->setOrientation (QPrinter::Landscape);
1504 // recommend portrait
1505 printer->setOrientation (QPrinter::Portrait);
1507 if ( printer->setup(this) )
1508 // returns false, if printing is canceled
1510 QPainter pp(printer);
1512 pp.setRenderHint(QPainter::Antialiasing,true);
1514 // Don't print the visualisation of selection
1515 xelection.unselect();
1517 QRectF mapRect=totalBBox;
1518 QGraphicsRectItem *frame=NULL;
1522 // Print frame around map
1523 mapRect.setRect (totalBBox.x()-10, totalBBox.y()-10,
1524 totalBBox.width()+20, totalBBox.height()+20);
1525 frame=mapScene->addRect (mapRect, QPen(Qt::black),QBrush(Qt::NoBrush));
1526 frame->setZValue(0);
1531 double paperAspect = (double)printer->width() / (double)printer->height();
1532 double mapAspect = (double)mapRect.width() / (double)mapRect.height();
1534 if (mapAspect>=paperAspect)
1536 // Fit horizontally to paper width
1537 //pp.setViewport(0,0, printer->width(),(int)(printer->width()/mapAspect) );
1538 viewBottom=(int)(printer->width()/mapAspect);
1541 // Fit vertically to paper height
1542 //pp.setViewport(0,0,(int)(printer->height()*mapAspect),printer->height());
1543 viewBottom=printer->height();
1548 // Print footer below map
1550 font.setPointSize(10);
1552 QRectF footerBox(0,viewBottom,printer->width(),15);
1553 pp.drawText ( footerBox,Qt::AlignLeft,"VYM - " +fileName);
1554 pp.drawText ( footerBox, Qt::AlignRight, QDate::currentDate().toString(Qt::TextDate));
1558 QRectF (0,0,printer->width(),printer->height()-15),
1559 QRectF(mapRect.x(),mapRect.y(),mapRect.width(),mapRect.height())
1562 // Viewport has paper dimension
1563 if (frame) delete (frame);
1565 // Restore selection
1566 xelection.reselect();
1568 // Save settings in vymrc
1569 settings.writeEntry("/mainwindow/printerName",printer->printerName());
1570 settings.writeEntry("/mainwindow/printerFormat",printer->outputFormat());
1571 settings.writeEntry("/mainwindow/printerFileName",printer->outputFileName());
1575 void MapEditor::setAntiAlias (bool b)
1577 setRenderHint(QPainter::Antialiasing,b);
1580 void MapEditor::setSmoothPixmap(bool b)
1582 setRenderHint(QPainter::SmoothPixmapTransform,b);
1585 QPixmap MapEditor::getPixmap()
1587 QRectF mapRect=mapCenter->getTotalBBox();
1588 QPixmap pix((int)mapRect.width()+2,(int)mapRect.height()+2);
1591 pp.setRenderHints(renderHints());
1593 // Don't print the visualisation of selection
1594 xelection.unselect();
1596 mapScene->render ( &pp,
1597 QRectF(0,0,mapRect.width()+2,mapRect.height()+2),
1598 QRectF(mapRect.x(),mapRect.y(),mapRect.width(),mapRect.height() ));
1600 // Restore selection
1601 xelection.reselect();
1606 void MapEditor::setHideTmpMode (BranchObj::HideTmpMode mode)
1609 mapCenter->setHideTmp (hidemode);
1610 mapCenter->reposition();
1614 BranchObj::HideTmpMode MapEditor::getHideTmpMode()
1619 void MapEditor::exportImage(QString fn)
1621 setExportMode (true);
1622 QPixmap pix (getPixmap());
1623 pix.save(fn, "PNG");
1624 setExportMode (false);
1627 void MapEditor::setExportMode (bool b)
1629 // should be called before and after exports
1630 // depending on the settings
1631 if (b && settings.value("/export/useHideExport","yes")=="yes")
1632 setHideTmpMode (BranchObj::HideExport);
1634 setHideTmpMode (BranchObj::HideNone);
1637 void MapEditor::exportImage(QString fn, QString format)
1639 setExportMode (true);
1640 QPixmap pix (getPixmap());
1641 pix.save(fn, format);
1642 setExportMode (false);
1645 void MapEditor::exportOOPresentation(const QString &fn, const QString &cf)
1649 ex.setMapCenter(mapCenter);
1650 if (ex.setConfigFile(cf))
1652 setExportMode (true);
1653 ex.exportPresentation();
1654 setExportMode (false);
1660 void MapEditor::exportXML(const QString &dir)
1662 // Hide stuff during export, if settings want this
1663 setExportMode (true);
1665 // Create subdirectories
1668 // write to directory
1669 QString saveFile=saveToDir (dir,mapName+"-",true,mapCenter->getTotalBBox().topLeft() ,NULL);
1672 file.setName ( dir + "/"+mapName+".xml");
1673 if ( !file.open( QIODevice::WriteOnly ) )
1675 // This should neverever happen
1676 QMessageBox::critical (0,tr("Critical Export Error"),tr("MapEditor::exportXML couldn't open %1").arg(file.name()));
1680 // Write it finally, and write in UTF8, no matter what
1681 QTextStream ts( &file );
1682 ts.setEncoding (QTextStream::UnicodeUTF8);
1686 // Now write image, too
1687 exportImage (dir+"/images/"+mapName+".png");
1689 setExportMode (false);
1692 void MapEditor::clear()
1694 xelection.unselect();
1698 void MapEditor::copy()
1700 LinkableMapObj *sel=xelection.single();
1703 if (redosAvail == 0)
1706 QString s=sel->getSelectString();
1707 saveState (PartOfMap, s, "nop ()", s, "copy ()","Copy selection to clipboard",sel );
1708 curClipboard=curStep;
1711 // Copy also to global clipboard, because we are at last step in history
1712 QString bakMapName=QDir::convertSeparators (QString("history-%1").arg(curStep));
1713 QString bakMapDir=QDir::convertSeparators (tmpMapDir +"/"+bakMapName);
1714 copyDir (bakMapDir,clipboardDir );
1716 clipboardEmpty=false;
1721 void MapEditor::redo()
1723 // Can we undo at all?
1724 if (redosAvail<1) return;
1726 bool blockSaveStateOrg=blockSaveState;
1727 blockSaveState=true;
1731 if (undosAvail<stepsTotal) undosAvail++;
1733 if (curStep>stepsTotal) curStep=1;
1734 QString undoCommand= undoSet.readEntry (QString("/history/step-%1/undoCommand").arg(curStep));
1735 QString undoSelection=undoSet.readEntry (QString("/history/step-%1/undoSelection").arg(curStep));
1736 QString redoCommand= undoSet.readEntry (QString("/history/step-%1/redoCommand").arg(curStep));
1737 QString redoSelection=undoSet.readEntry (QString("/history/step-%1/redoSelection").arg(curStep));
1738 QString comment=undoSet.readEntry (QString("/history/step-%1/comment").arg(curStep));
1739 QString version=undoSet.readEntry ("/history/version");
1741 if (!checkVersion(version))
1742 QMessageBox::warning(0,tr("Warning"),
1743 tr("Version %1 of saved undo/redo data\ndoes not match current vym version %2.").arg(version).arg(vymVersion));
1746 // Find out current undo directory
1747 QString bakMapDir=QDir::convertSeparators (QString(tmpMapDir+"/undo-%1").arg(curStep));
1751 cout << "ME::redo() begin\n";
1752 cout << " undosAvail="<<undosAvail<<endl;
1753 cout << " redosAvail="<<redosAvail<<endl;
1754 cout << " curStep="<<curStep<<endl;
1755 cout << " ---------------------------"<<endl;
1756 cout << " comment="<<comment.toStdString()<<endl;
1757 cout << " undoCom="<<undoCommand.toStdString()<<endl;
1758 cout << " undoSel="<<undoSelection.toStdString()<<endl;
1759 cout << " redoCom="<<redoCommand.toStdString()<<endl;
1760 cout << " redoSel="<<redoSelection.toStdString()<<endl;
1761 cout << " ---------------------------"<<endl<<endl;
1764 // select object before redo
1765 if (!redoSelection.isEmpty())
1766 select (redoSelection);
1769 parseAtom (redoCommand);
1770 mapCenter->reposition();
1772 blockSaveState=blockSaveStateOrg;
1774 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
1775 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
1776 undoSet.setEntry ("/history/curStep",QString::number(curStep));
1777 undoSet.writeSettings(histPath);
1779 mainWindow->updateHistory (undoSet);
1782 /* TODO remove testing
1783 cout << "ME::redo() end\n";
1784 cout << " undosAvail="<<undosAvail<<endl;
1785 cout << " redosAvail="<<redosAvail<<endl;
1786 cout << " curStep="<<curStep<<endl;
1787 cout << " ---------------------------"<<endl<<endl;
1793 bool MapEditor::isRedoAvailable()
1795 if (undoSet.readNumEntry("/history/redosAvail",0)>0)
1801 void MapEditor::undo()
1803 // Can we undo at all?
1804 if (undosAvail<1) return;
1806 mainWindow->statusMessage (tr("Autosave disabled during undo."));
1808 bool blockSaveStateOrg=blockSaveState;
1809 blockSaveState=true;
1811 QString undoCommand= undoSet.readEntry (QString("/history/step-%1/undoCommand").arg(curStep));
1812 QString undoSelection=undoSet.readEntry (QString("/history/step-%1/undoSelection").arg(curStep));
1813 QString redoCommand= undoSet.readEntry (QString("/history/step-%1/redoCommand").arg(curStep));
1814 QString redoSelection=undoSet.readEntry (QString("/history/step-%1/redoSelection").arg(curStep));
1815 QString comment=undoSet.readEntry (QString("/history/step-%1/comment").arg(curStep));
1816 QString version=undoSet.readEntry ("/history/version");
1818 if (!checkVersion(version))
1819 QMessageBox::warning(0,tr("Warning"),
1820 tr("Version %1 of saved undo/redo data\ndoes not match current vym version %2.").arg(version).arg(vymVersion));
1822 // Find out current undo directory
1823 QString bakMapDir=QDir::convertSeparators (QString(tmpMapDir+"/undo-%1").arg(curStep));
1825 // select object before undo
1826 if (!undoSelection.isEmpty())
1827 select (undoSelection);
1831 cout << "ME::undo() begin\n";
1832 cout << " undosAvail="<<undosAvail<<endl;
1833 cout << " redosAvail="<<redosAvail<<endl;
1834 cout << " curStep="<<curStep<<endl;
1835 cout << " ---------------------------"<<endl;
1836 cout << " comment="<<comment.toStdString()<<endl;
1837 cout << " undoCom="<<undoCommand.toStdString()<<endl;
1838 cout << " undoSel="<<undoSelection.toStdString()<<endl;
1839 cout << " redoCom="<<redoCommand.toStdString()<<endl;
1840 cout << " redoSel="<<redoSelection.toStdString()<<endl;
1841 cout << " ---------------------------"<<endl<<endl;
1843 parseAtom (undoCommand);
1844 mapCenter->reposition();
1848 if (curStep<1) curStep=stepsTotal;
1852 blockSaveState=blockSaveStateOrg;
1853 /* TODO remove testing
1854 cout << "ME::undo() end\n";
1855 cout << " undosAvail="<<undosAvail<<endl;
1856 cout << " redosAvail="<<redosAvail<<endl;
1857 cout << " curStep="<<curStep<<endl;
1858 cout << " ---------------------------"<<endl<<endl;
1861 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
1862 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
1863 undoSet.setEntry ("/history/curStep",QString::number(curStep));
1864 undoSet.writeSettings(histPath);
1866 mainWindow->updateHistory (undoSet);
1869 ensureSelectionVisible();
1872 bool MapEditor::isUndoAvailable()
1874 if (undoSet.readNumEntry("/history/undosAvail",0)>0)
1880 void MapEditor::gotoHistoryStep (int i)
1882 // Restore variables
1883 int undosAvail=undoSet.readNumEntry (QString("/history/undosAvail"));
1884 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
1886 if (i<0) i=undosAvail+redosAvail;
1888 // Clicking above current step makes us undo things
1891 for (int j=0; j<undosAvail-i; j++) undo();
1894 // Clicking below current step makes us redo things
1896 for (int j=undosAvail; j<i; j++)
1898 cout << "redo "<<j<<"/"<<undosAvail<<" i="<<i<<endl;
1902 // And ignore clicking the current row ;-)
1905 void MapEditor::addMapReplaceInt(const QString &undoSel, const QString &path)
1907 QString pathDir=path.left(path.findRev("/"));
1913 // We need to parse saved XML data
1914 mapBuilderHandler handler;
1915 QXmlInputSource source( file);
1916 QXmlSimpleReader reader;
1917 reader.setContentHandler( &handler );
1918 reader.setErrorHandler( &handler );
1919 handler.setMapEditor( this );
1920 handler.setTmpDir ( pathDir ); // needed to load files with rel. path
1921 if (undoSel.isEmpty())
1925 handler.setLoadMode (NewMap);
1929 handler.setLoadMode (ImportReplace);
1931 blockReposition=true;
1932 bool ok = reader.parse( source );
1933 blockReposition=false;
1936 // This should never ever happen
1937 QMessageBox::critical( 0, tr( "Critical Parse Error while reading %1").arg(path),
1938 handler.errorProtocol());
1941 QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
1944 void MapEditor::addMapInsertInt (const QString &path, int pos)
1946 BranchObj *sel=xelection.getBranch();
1949 QString pathDir=path.left(path.findRev("/"));
1955 // We need to parse saved XML data
1956 mapBuilderHandler handler;
1957 QXmlInputSource source( file);
1958 QXmlSimpleReader reader;
1959 reader.setContentHandler( &handler );
1960 reader.setErrorHandler( &handler );
1961 handler.setMapEditor( this );
1962 handler.setTmpDir ( pathDir ); // needed to load files with rel. path
1963 handler.setLoadMode (ImportAdd);
1964 blockReposition=true;
1965 bool ok = reader.parse( source );
1966 blockReposition=false;
1969 // This should never ever happen
1970 QMessageBox::critical( 0, tr( "Critical Parse Error while reading %1").arg(path),
1971 handler.errorProtocol());
1974 sel->getLastBranch()->linkTo (sel,pos);
1976 QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
1980 void MapEditor::pasteNoSave(const int &n)
1982 bool old=blockSaveState;
1983 blockSaveState=true;
1984 if (redosAvail > 0 || n!=0)
1986 // Use the "historical" buffer
1987 QString bakMapName=QDir::convertSeparators (QString("history-%1").arg(n));
1988 QString bakMapDir=QDir::convertSeparators (tmpMapDir +"/"+bakMapName);
1989 load (bakMapDir+"/"+clipboardFile,ImportAdd);
1991 // Use the global buffer
1992 load (clipboardDir+"/"+clipboardFile,ImportAdd);
1996 void MapEditor::paste()
1998 BranchObj *sel=xelection.getBranch();
2001 saveStateChangingPart(
2004 QString ("paste (%1)").arg(curClipboard),
2005 QString("Paste to %1").arg( getName(sel))
2008 mapCenter->reposition();
2012 void MapEditor::cut()
2014 LinkableMapObj *sel=xelection.single();
2015 if ( sel && (xelection.type() == Selection::Branch ||
2016 xelection.type()==Selection::MapCenter ||
2017 xelection.type()==Selection::FloatImage))
2019 /* No savestate! savestate is called in cutNoSave
2020 saveStateChangingPart(
2024 QString("Cut %1").arg(getName(sel ))
2029 mapCenter->reposition();
2033 void MapEditor::move(const int &x, const int &y)
2035 LinkableMapObj *sel=xelection.single();
2038 QString ps=qpointfToString (sel->getAbsPos());
2039 QString s=xelection.single()->getSelectString();
2042 s, "move "+qpointfToString (QPointF (x,y)),
2043 QString("Move %1 to %2").arg(getName(sel)).arg(ps));
2045 mapCenter->reposition();
2051 void MapEditor::moveRel (const int &x, const int &y)
2053 LinkableMapObj *sel=xelection.single();
2056 QString ps=qpointfToString (sel->getRelPos());
2057 QString s=sel->getSelectString();
2060 s, "moveRel "+qpointfToString (QPointF (x,y)),
2061 QString("Move %1 to relativ position %2").arg(getName(sel)).arg(ps));
2062 ((OrnamentedObj*)sel)->move2RelPos (x,y);
2063 mapCenter->reposition();
2069 void MapEditor::moveBranchUp()
2071 BranchObj* bo=xelection.getBranch();
2075 if (!bo->canMoveBranchUp()) return;
2076 par=(BranchObj*)(bo->getParObj());
2077 BranchObj *obo=par->moveBranchUp (bo); // bo will be the one below selection
2078 saveState (bo->getSelectString(),"moveBranchDown ()",obo->getSelectString(),"moveBranchUp ()",QString("Move up %1").arg(getName(bo)));
2079 mapCenter->reposition();
2082 ensureSelectionVisible();
2086 void MapEditor::moveBranchDown()
2088 BranchObj* bo=xelection.getBranch();
2092 if (!bo->canMoveBranchDown()) return;
2093 par=(BranchObj*)(bo->getParObj());
2094 BranchObj *obo=par->moveBranchDown(bo); // bo will be the one above selection
2095 saveState(bo->getSelectString(),"moveBranchUp ()",obo->getSelectString(),"moveBranchDown ()",QString("Move down %1").arg(getName(bo)));
2096 mapCenter->reposition();
2099 ensureSelectionVisible();
2103 void MapEditor::linkTo(const QString &dstString)
2105 FloatImageObj *fio=xelection.getFloatImage();
2108 BranchObj *dst=(BranchObj*)(mapCenter->findObjBySelect(dstString));
2109 if (dst && (typeid(*dst)==typeid (BranchObj) ||
2110 typeid(*dst)==typeid (MapCenterObj)))
2112 LinkableMapObj *dstPar=dst->getParObj();
2113 QString parString=dstPar->getSelectString();
2114 QString fioPreSelectString=fio->getSelectString();
2115 QString fioPreParentSelectString=fio->getParObj()->getSelectString();
2116 ((BranchObj*)(dst))->addFloatImage (fio);
2117 xelection.unselect();
2118 ((BranchObj*)(fio->getParObj()))->removeFloatImage (fio);
2119 fio=((BranchObj*)(dst))->getLastFloatImage();
2122 xelection.select(fio);
2124 fio->getSelectString(),
2125 QString("linkTo (\"%1\")").arg(fioPreParentSelectString),
2127 QString ("linkTo (\"%1\")").arg(dstString),
2128 QString ("Link floatimage to %1").arg(getName(dst)));
2133 QString MapEditor::getHeading(bool &ok, QPoint &p)
2135 BranchObj *bo=xelection.getBranch();
2139 p=mapFromScene(bo->getAbsPos());
2140 return bo->getHeading();
2146 void MapEditor::setHeading(const QString &s)
2148 BranchObj *sel=xelection.getBranch();
2153 "setHeading (\""+sel->getHeading()+"\")",
2155 "setHeading (\""+s+"\")",
2156 QString("Set heading of %1 to \"%2\"").arg(getName(sel)).arg(s) );
2157 sel->setHeading(s );
2158 mapCenter->reposition();
2160 ensureSelectionVisible();
2164 void MapEditor::setHeadingInt(const QString &s)
2166 BranchObj *bo=xelection.getBranch();
2170 mapCenter->reposition();
2172 ensureSelectionVisible();
2176 void MapEditor::setVymLinkInt (const QString &s)
2178 // Internal function, no saveState needed
2179 BranchObj *bo=xelection.getBranch();
2183 mapCenter->reposition();
2186 ensureSelectionVisible();
2190 BranchObj* MapEditor::addNewBranchInt(int num)
2192 // Depending on pos:
2193 // -3 insert in childs of parent above selection
2194 // -2 add branch to selection
2195 // -1 insert in childs of parent below selection
2196 // 0..n insert in childs of parent at pos
2197 BranchObj *newbo=NULL;
2198 BranchObj *bo=xelection.getBranch();
2203 // save scroll state. If scrolled, automatically select
2204 // new branch in order to tmp unscroll parent...
2205 return bo->addBranch();
2210 bo=(BranchObj*)bo->getParObj();
2214 bo=(BranchObj*)bo->getParObj();
2217 newbo=bo->insertBranch(num);
2222 BranchObj* MapEditor::addNewBranch(int pos)
2224 // Different meaning than num in addNewBranchInt!
2228 BranchObj *bo = xelection.getBranch();
2229 BranchObj *newbo=NULL;
2233 setCursor (Qt::ArrowCursor);
2235 newbo=addNewBranchInt (pos-2);
2243 QString ("addBranch (%1)").arg(pos-2),
2244 QString ("Add new branch to %1").arg(getName(bo)));
2246 mapCenter->reposition();
2254 BranchObj* MapEditor::addNewBranchBefore()
2256 BranchObj *newbo=NULL;
2257 BranchObj *bo = xelection.getBranch();
2258 if (bo && xelection.type()==Selection::Branch)
2259 // We accept no MapCenterObj here, so we _have_ a parent
2261 QPointF p=bo->getRelPos();
2264 BranchObj *parbo=(BranchObj*)(bo->getParObj());
2266 // add below selection
2267 newbo=parbo->insertBranch(bo->getNum()+1);
2270 newbo->move2RelPos (p);
2272 // Move selection to new branch
2273 bo->linkTo (newbo,-1);
2275 saveState (newbo, "deleteKeepChilds ()", newbo, "addBranchBefore ()",
2276 QString ("Add branch before %1").arg(getName(bo)));
2278 mapCenter->reposition();
2285 void MapEditor::deleteSelection()
2287 BranchObj *bo = xelection.getBranch();
2288 if (bo && xelection.type()==Selection::Branch)
2290 BranchObj* par=(BranchObj*)(bo->getParObj());
2291 xelection.unselect();
2292 saveStateRemovingPart (bo, QString ("Delete %1").arg(getName(bo)));
2293 par->removeBranch(bo);
2294 xelection.select (par);
2295 ensureSelectionVisible();
2296 mapCenter->reposition();
2301 FloatImageObj *fio=xelection.getFloatImage();
2304 BranchObj* par=(BranchObj*)(fio->getParObj());
2305 saveStateChangingPart(
2309 QString("Delete %1").arg(getName(fio))
2311 xelection.unselect();
2312 par->removeFloatImage(fio);
2313 xelection.select (par);
2314 mapCenter->reposition();
2316 ensureSelectionVisible();
2321 LinkableMapObj* MapEditor::getSelection()
2323 return xelection.single();
2326 BranchObj* MapEditor::getSelectedBranch()
2328 return xelection.getBranch();
2331 FloatImageObj* MapEditor::getSelectedFloatImage()
2333 return xelection.getFloatImage();
2336 void MapEditor::unselect()
2338 xelection.unselect();
2341 void MapEditor::reselect()
2343 xelection.reselect();
2346 bool MapEditor::select (const QString &s)
2348 LinkableMapObj *lmo=mapCenter->findObjBySelect(s);
2350 // Finally select the found object
2353 xelection.unselect();
2354 xelection.select(lmo);
2356 ensureSelectionVisible();
2362 QString MapEditor::getSelectString()
2364 return xelection.getSelectString();
2367 void MapEditor::selectInt (LinkableMapObj *lmo)
2369 if (lmo && xelection.single()!= lmo && isSelectBlocked()==false )
2371 xelection.select(lmo);
2376 void MapEditor::selectNextBranchInt()
2378 // Increase number of branch
2379 LinkableMapObj *sel=xelection.single();
2382 QString s=sel->getSelectString();
2388 part=s.section(",",-1);
2390 num=part.right(part.length() - 3);
2392 s=s.left (s.length() -num.length());
2395 num=QString ("%1").arg(num.toUInt()+1);
2399 // Try to select this one
2400 if (select (s)) return;
2402 // We have no direct successor,
2403 // try to increase the parental number in order to
2404 // find a successor with same depth
2406 int d=xelection.single()->getDepth();
2411 while (!found && d>0)
2413 s=s.section (",",0,d-1);
2414 // replace substring of current depth in s with "1"
2415 part=s.section(",",-1);
2417 num=part.right(part.length() - 3);
2421 // increase number of parent
2422 num=QString ("%1").arg(num.toUInt()+1);
2423 s=s.section (",",0,d-2) + ","+ typ+num;
2426 // Special case, look at orientation
2427 if (xelection.single()->getOrientation()==LinkableMapObj::RightOfCenter)
2428 num=QString ("%1").arg(num.toUInt()+1);
2430 num=QString ("%1").arg(num.toUInt()-1);
2435 // pad to oldDepth, select the first branch for each depth
2436 for (i=d;i<oldDepth;i++)
2441 if ( xelection.getBranch()->countBranches()>0)
2449 // try to select the freshly built string
2457 void MapEditor::selectPrevBranchInt()
2459 // Decrease number of branch
2460 BranchObj *bo=xelection.getBranch();
2463 QString s=bo->getSelectString();
2469 part=s.section(",",-1);
2471 num=part.right(part.length() - 3);
2473 s=s.left (s.length() -num.length());
2475 int n=num.toInt()-1;
2478 num=QString ("%1").arg(n);
2481 // Try to select this one
2482 if (n>=0 && select (s)) return;
2484 // We have no direct precessor,
2485 // try to decrease the parental number in order to
2486 // find a precessor with same depth
2488 int d=xelection.single()->getDepth();
2493 while (!found && d>0)
2495 s=s.section (",",0,d-1);
2496 // replace substring of current depth in s with "1"
2497 part=s.section(",",-1);
2499 num=part.right(part.length() - 3);
2503 // decrease number of parent
2504 num=QString ("%1").arg(num.toInt()-1);
2505 s=s.section (",",0,d-2) + ","+ typ+num;
2508 // Special case, look at orientation
2509 if (xelection.single()->getOrientation()==LinkableMapObj::RightOfCenter)
2510 num=QString ("%1").arg(num.toInt()-1);
2512 num=QString ("%1").arg(num.toInt()+1);
2517 // pad to oldDepth, select the last branch for each depth
2518 for (i=d;i<oldDepth;i++)
2522 if ( xelection.getBranch()->countBranches()>0)
2523 s+=",bo:"+ QString ("%1").arg( xelection.getBranch()->countBranches()-1 );
2530 // try to select the freshly built string
2538 void MapEditor::selectUpperBranch()
2540 if (isSelectBlocked() ) return;
2542 BranchObj *bo=xelection.getBranch();
2543 if (bo && xelection.type()==Selection::Branch)
2545 if (bo->getOrientation()==LinkableMapObj::RightOfCenter)
2546 selectPrevBranchInt();
2548 if (bo->getDepth()==1)
2549 selectNextBranchInt();
2551 selectPrevBranchInt();
2555 void MapEditor::selectLowerBranch()
2557 if (isSelectBlocked() ) return;
2559 BranchObj *bo=xelection.getBranch();
2560 if (bo && xelection.type()==Selection::Branch)
2561 if (bo->getOrientation()==LinkableMapObj::RightOfCenter)
2562 selectNextBranchInt();
2564 if (bo->getDepth()==1)
2565 selectPrevBranchInt();
2567 selectNextBranchInt();
2571 void MapEditor::selectLeftBranch()
2573 if (isSelectBlocked() ) return;
2577 LinkableMapObj *sel=xelection.single();
2580 if (xelection.type()== Selection::MapCenter)
2582 par=xelection.getBranch();
2583 bo=par->getLastSelectedBranch();
2586 // Workaround for reselecting on left and right side
2587 if (bo->getOrientation()==LinkableMapObj::RightOfCenter)
2588 bo=par->getLastBranch();
2591 bo=par->getLastBranch();
2592 xelection.select(bo);
2594 ensureSelectionVisible();
2599 par=(BranchObj*)(sel->getParObj());
2600 if (sel->getOrientation()==LinkableMapObj::RightOfCenter)
2602 if (xelection.type() == Selection::Branch ||
2603 xelection.type() == Selection::FloatImage)
2605 xelection.select(par);
2607 ensureSelectionVisible();
2611 if (xelection.type() == Selection::Branch )
2613 bo=xelection.getBranch()->getLastSelectedBranch();
2616 xelection.select(bo);
2618 ensureSelectionVisible();
2626 void MapEditor::selectRightBranch()
2628 if (isSelectBlocked() ) return;
2632 LinkableMapObj *sel=xelection.single();
2635 if (xelection.type()==Selection::MapCenter)
2637 par=xelection.getBranch();
2638 bo=par->getLastSelectedBranch();
2641 // Workaround for reselecting on left and right side
2642 if (bo->getOrientation()==LinkableMapObj::LeftOfCenter)
2643 bo=par->getFirstBranch();
2646 xelection.select(bo);
2648 ensureSelectionVisible();
2653 par=(BranchObj*)(xelection.single()->getParObj());
2654 if (xelection.single()->getOrientation()==LinkableMapObj::LeftOfCenter)
2656 if (xelection.type() == Selection::Branch ||
2657 xelection.type() == Selection::FloatImage)
2659 xelection.select(par);
2661 ensureSelectionVisible();
2665 if (xelection.type() == Selection::Branch)
2667 bo=xelection.getBranch()->getLastSelectedBranch();
2670 xelection.select(bo);
2672 ensureSelectionVisible();
2680 void MapEditor::selectFirstBranch()
2682 BranchObj *bo1=xelection.getBranch();
2687 par=(BranchObj*)(bo1->getParObj());
2688 bo2=par->getFirstBranch();
2690 xelection.select(bo2);
2692 ensureSelectionVisible();
2697 void MapEditor::selectLastBranch()
2699 BranchObj *bo1=xelection.getBranch();
2704 par=(BranchObj*)(bo1->getParObj());
2705 bo2=par->getLastBranch();
2708 xelection.select(bo2);
2710 ensureSelectionVisible();
2715 void MapEditor::selectMapBackgroundImage ()
2717 Q3FileDialog *fd=new Q3FileDialog( this);
2718 fd->setMode (Q3FileDialog::ExistingFile);
2719 fd->addFilter (QString (tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)"));
2720 ImagePreview *p =new ImagePreview (fd);
2721 fd->setContentsPreviewEnabled( TRUE );
2722 fd->setContentsPreview( p, p );
2723 fd->setPreviewMode( Q3FileDialog::Contents );
2724 fd->setCaption(vymName+" - " +tr("Load background image"));
2725 fd->setDir (lastImageDir);
2728 if ( fd->exec() == QDialog::Accepted )
2730 // TODO selectMapBackgroundImg in QT4 use: lastImageDir=fd->directory();
2731 lastImageDir=QDir (fd->dirPath());
2732 setMapBackgroundImage (fd->selectedFile());
2736 void MapEditor::setMapBackgroundImage (const QString &fn) //FIXME missing savestate
2738 QColor oldcol=mapScene->backgroundBrush().color();
2742 QString ("setMapBackgroundImage (%1)").arg(oldcol.name()),
2744 QString ("setMapBackgroundImage (%1)").arg(col.name()),
2745 QString("Set background color of map to %1").arg(col.name()));
2748 brush.setTextureImage (QPixmap (fn));
2749 mapScene->setBackgroundBrush(brush);
2752 void MapEditor::selectMapBackgroundColor()
2754 QColor col = QColorDialog::getColor( mapScene->backgroundBrush().color(), this );
2755 if ( !col.isValid() ) return;
2756 setMapBackgroundColor( col );
2760 void MapEditor::setMapBackgroundColor(QColor col)
2762 QColor oldcol=mapScene->backgroundBrush().color();
2765 QString ("setMapBackgroundColor (\"%1\")").arg(oldcol.name()),
2767 QString ("setMapBackgroundColor (\"%1\")").arg(col.name()),
2768 QString("Set background color of map to %1").arg(col.name()));
2769 mapScene->setBackgroundBrush(col);
2772 QColor MapEditor::getMapBackgroundColor()
2774 return mapScene->backgroundBrush().color();
2777 QColor MapEditor::getCurrentHeadingColor()
2779 BranchObj *bo=xelection.getBranch();
2780 if (bo) return bo->getColor();
2782 QMessageBox::warning(0,tr("Warning"),tr("Can't get color of heading,\nthere's no branch selected"));
2786 void MapEditor::colorBranch (QColor c)
2788 BranchObj *bo=xelection.getBranch();
2793 QString ("colorBranch (\"%1\")").arg(bo->getColor().name()),
2795 QString ("colorBranch (\"%1\")").arg(c.name()),
2796 QString("Set color of %1 to %2").arg(getName(bo)).arg(c.name())
2798 bo->setColor(c); // color branch
2802 void MapEditor::colorSubtree (QColor c)
2804 BranchObj *bo=xelection.getBranch();
2807 saveStateChangingPart(
2810 QString ("colorSubtree (\"%1\")").arg(c.name()),
2811 QString ("Set color of %1 and childs to %2").arg(getName(bo)).arg(c.name())
2813 bo->setColorSubtree (c); // color links, color childs
2818 void MapEditor::toggleStandardFlag(QString f)
2820 BranchObj *bo=xelection.getBranch();
2824 if (bo->isSetStandardFlag(f))
2836 QString("%1 (\"%2\")").arg(u).arg(f),
2838 QString("%1 (\"%2\")").arg(r).arg(f),
2839 QString("Toggling standard flag \"%1\" of %2").arg(f).arg(getName(bo)));
2840 bo->toggleStandardFlag (f,mainWindow->useFlagGroups());
2846 BranchObj* MapEditor::findText (QString s, bool cs)
2848 QTextDocument::FindFlags flags=0;
2849 if (cs) flags=QTextDocument::FindCaseSensitively;
2852 { // Nothing found or new find process
2854 // nothing found, start again
2856 itFind=mapCenter->first();
2858 bool searching=true;
2859 bool foundNote=false;
2860 while (searching && !EOFind)
2864 // Searching in Note
2865 if (itFind->getNote().contains(s,cs))
2867 if (xelection.single()!=itFind)
2869 xelection.select(itFind);
2870 ensureSelectionVisible();
2872 if (textEditor->findText(s,flags))
2878 // Searching in Heading
2879 if (searching && itFind->getHeading().contains (s,cs) )
2881 xelection.select(itFind);
2882 ensureSelectionVisible();
2888 itFind=itFind->next();
2889 if (!itFind) EOFind=true;
2893 return xelection.getBranch();
2898 void MapEditor::findReset()
2899 { // Necessary if text to find changes during a find process
2903 void MapEditor::setURL(const QString &url)
2905 BranchObj *bo=xelection.getBranch();
2908 QString oldurl=bo->getURL();
2912 QString ("setURL (\"%1\")").arg(oldurl),
2914 QString ("setURL (\"%1\")").arg(url),
2915 QString ("set URL of %1 to %2").arg(getName(bo)).arg(url)
2918 mapCenter->reposition();
2920 ensureSelectionVisible();
2924 void MapEditor::editURL()
2926 BranchObj *bo=xelection.getBranch();
2930 QString text = QInputDialog::getText(
2931 "VYM", tr("Enter URL:"), QLineEdit::Normal,
2932 bo->getURL(), &ok, this );
2934 // user entered something and pressed OK
2939 QString MapEditor::getURL()
2941 BranchObj *bo=xelection.getBranch();
2943 return bo->getURL();
2948 QStringList MapEditor::getURLs()
2951 BranchObj *bo=xelection.getBranch();
2957 if (!bo->getURL().isEmpty()) urls.append( bo->getURL());
2965 void MapEditor::editHeading2URL()
2967 BranchObj *bo=xelection.getBranch();
2969 setURL (bo->getHeading());
2972 void MapEditor::editBugzilla2URL()
2974 BranchObj *bo=xelection.getBranch();
2977 QString url= "https://bugzilla.novell.com/show_bug.cgi?id="+bo->getHeading();
2982 void MapEditor::editFATE2URL()
2984 BranchObj *bo=xelection.getBranch();
2987 QString url= "http://keeper.suse.de:8080/webfate/match/id?value=ID"+bo->getHeading();
2990 "setURL (\""+bo->getURL()+"\")",
2992 "setURL (\""+url+"\")",
2993 QString("Use heading of %1 as link to FATE").arg(getName(bo))
3000 void MapEditor::editVymLink()
3002 BranchObj *bo=xelection.getBranch();
3005 QStringList filters;
3006 filters <<"VYM map (*.vym)";
3007 QFileDialog *fd=new QFileDialog( this,vymName+" - " +tr("Link to another map"));
3008 fd->setFilters (filters);
3009 fd->setCaption(vymName+" - " +tr("Link to another map"));
3010 fd->setDirectory (lastFileDir);
3011 if (! bo->getVymLink().isEmpty() )
3012 fd->selectFile( bo->getVymLink() );
3016 if ( fd->exec() == QDialog::Accepted )
3018 lastFileDir=QDir (fd->directory().path());
3021 "setVymLink (\""+bo->getVymLink()+"\")",
3023 "setVymLink (\""+fd->selectedFile()+"\")",
3024 QString("Set vymlink of %1 to %2").arg(getName(bo)).arg(fd->selectedFile())
3026 setVymLinkInt (fd->selectedFile() );
3031 void MapEditor::deleteVymLink()
3033 BranchObj *bo=xelection.getBranch();
3038 "setVymLink (\""+bo->getVymLink()+"\")",
3040 "setVymLink (\"\")",
3041 QString("Unset vymlink of %1").arg(getName(bo))
3043 bo->setVymLink ("" );
3045 mapCenter->reposition();
3050 void MapEditor::setHideExport(bool b)
3052 BranchObj *bo=xelection.getBranch();
3055 bo->setHideInExport (b);
3056 QString u= b ? "false" : "true";
3057 QString r=!b ? "false" : "true";
3061 QString ("setHideExport (%1)").arg(u),
3063 QString ("setHideExport (%1)").arg(r),
3064 QString ("Set HideExport flag of %1 to %2").arg(getName(bo)).arg (r)
3067 mapCenter->reposition();
3073 void MapEditor::toggleHideExport()
3075 BranchObj *bo=xelection.getBranch();
3077 setHideExport ( !bo->hideInExport() );
3080 QString MapEditor::getVymLink()
3082 BranchObj *bo=xelection.getBranch();
3084 return bo->getVymLink();
3090 QStringList MapEditor::getVymLinks()
3093 BranchObj *bo=xelection.getBranch();
3099 if (!bo->getVymLink().isEmpty()) links.append( bo->getVymLink());
3107 void MapEditor::deleteKeepChilds()
3109 BranchObj *bo=xelection.getBranch();
3113 par=(BranchObj*)(bo->getParObj());
3114 QPointF p=bo->getRelPos();
3115 saveStateChangingPart(
3118 "deleteKeepChilds ()",
3119 QString("Remove %1 and keep its childs").arg(getName(bo))
3122 QString sel=bo->getSelectString();
3124 par->removeBranchHere(bo);
3125 mapCenter->reposition();
3127 xelection.getBranch()->move2RelPos (p);
3128 mapCenter->reposition();
3132 void MapEditor::deleteChilds()
3134 BranchObj *bo=xelection.getBranch();
3137 saveStateChangingPart(
3141 QString( "Remove childs of branch %1").arg(getName(bo))
3144 mapCenter->reposition();
3148 void MapEditor::editMapInfo()
3150 ExtraInfoDialog dia;
3151 dia.setMapName (getFileName() );
3152 dia.setAuthor (mapCenter->getAuthor() );
3153 dia.setComment(mapCenter->getComment() );
3157 stats+=tr("%1 items on map\n","Info about map").arg (mapScene->items().size(),6);
3164 bo=mapCenter->first();
3167 if (!bo->getNote().isEmpty() ) n++;
3168 f+= bo->countFloatImages();
3170 xl+=bo->countXLinks();
3173 stats+=QString ("%1 branches\n").arg (b-1,6);
3174 stats+=QString ("%1 xLinks \n").arg (xl,6);
3175 stats+=QString ("%1 notes\n").arg (n,6);
3176 stats+=QString ("%1 images\n").arg (f,6);
3177 dia.setStats (stats);
3179 // Finally show dialog
3180 if (dia.exec() == QDialog::Accepted)
3182 setMapAuthor (dia.getAuthor() );
3183 setMapComment (dia.getComment() );
3187 void MapEditor::ensureSelectionVisible()
3189 LinkableMapObj *lmo=xelection.single();
3190 if (lmo) ensureVisible (lmo->getBBox() );
3194 void MapEditor::updateSelection()
3196 // Tell selection to update geometries
3200 void MapEditor::updateActions()
3202 // Tell mainwindow to update states of actions
3203 mainWindow->updateActions();
3204 // TODO maybe don't update if blockReposition is set
3207 void MapEditor::updateNoteFlag()
3210 BranchObj *bo=xelection.getBranch();
3213 bo->updateNoteFlag();
3214 mainWindow->updateActions();
3218 void MapEditor::setMapAuthor (const QString &s)
3222 QString ("setMapAuthor (\"%1\")").arg(mapCenter->getAuthor()),
3224 QString ("setMapAuthor (\"%1\")").arg(s),
3225 QString ("Set author of map to \"%1\"").arg(s)
3227 mapCenter->setAuthor (s);
3230 void MapEditor::setMapComment (const QString &s)
3234 QString ("setMapComment (\"%1\")").arg(mapCenter->getComment()),
3236 QString ("setMapComment (\"%1\")").arg(s),
3237 QString ("Set comment of map")
3239 mapCenter->setComment (s);
3242 void MapEditor::setMapLinkStyle (const QString & s)
3244 saveStateChangingPart (
3247 QString("setMapLinkStyle (\"%1\")").arg(s),
3248 QString("Set map link style (\"%1\")").arg(s)
3252 linkstyle=LinkableMapObj::Line;
3253 else if (s=="StyleParabel")
3254 linkstyle=LinkableMapObj::Parabel;
3255 else if (s=="StylePolyLine")
3256 linkstyle=LinkableMapObj::PolyLine;
3258 linkstyle=LinkableMapObj::PolyParabel;
3261 bo=mapCenter->first();
3265 bo->setLinkStyle(bo->getDefLinkStyle());
3268 mapCenter->reposition();
3271 LinkableMapObj::Style MapEditor::getMapLinkStyle ()
3276 void MapEditor::setMapDefLinkColor(QColor c)
3280 bo=mapCenter->first();
3289 void MapEditor::setMapLinkColorHintInt()
3291 // called from setMapLinkColorHint(lch) or at end of parse
3293 bo=mapCenter->first();
3301 void MapEditor::setMapLinkColorHint(LinkableMapObj::ColorHint lch)
3304 setMapLinkColorHintInt();
3307 void MapEditor::toggleMapLinkColorHint()
3309 if (linkcolorhint==LinkableMapObj::HeadingColor)
3310 linkcolorhint=LinkableMapObj::DefaultColor;
3312 linkcolorhint=LinkableMapObj::HeadingColor;
3314 bo=mapCenter->first();
3322 LinkableMapObj::ColorHint MapEditor::getMapLinkColorHint()
3324 return linkcolorhint;
3327 QColor MapEditor::getMapDefLinkColor()
3329 return defLinkColor;
3332 void MapEditor::setMapDefXLinkColor(QColor col)
3337 QColor MapEditor::getMapDefXLinkColor()
3339 return defXLinkColor;
3342 void MapEditor::setMapDefXLinkWidth (int w)
3347 int MapEditor::getMapDefXLinkWidth()
3349 return defXLinkWidth;
3352 void MapEditor::selectMapLinkColor()
3354 QColor col = QColorDialog::getColor( defLinkColor, this );
3355 if ( !col.isValid() ) return;
3358 QString("setMapDefLinkColor (\"%1\")").arg(getMapDefLinkColor().name()),
3360 QString("setMapDefLinkColor (\"%1\")").arg(col.name()),
3361 QString("Set map link color to %1").arg(col.name())
3363 setMapDefLinkColor( col );
3366 void MapEditor::selectMapSelectionColor()
3368 QColor col = QColorDialog::getColor( defLinkColor, this );
3369 setSelectionColor (col);
3372 void MapEditor::setSelectionColorInt (QColor col)
3374 if ( !col.isValid() ) return;
3375 xelection.setColor (col);
3378 void MapEditor::setSelectionColor(QColor col)
3380 if ( !col.isValid() ) return;
3383 QString("setSelectionColor (%1)").arg(xelection.getColor().name()),
3385 QString("setSelectionColor (%1)").arg(col.name()),
3386 QString("Set color of selection box to %1").arg(col.name())
3388 setSelectionColorInt (col);
3391 QColor MapEditor::getSelectionColor()
3393 return xelection.getColor();
3396 bool MapEditor::scrollBranch(BranchObj *bo)
3400 if (bo->isScrolled()) return false;
3401 if (bo->countBranches()==0) return false;
3402 if (bo->getDepth()==0) return false;
3408 QString ("%1 ()").arg(u),
3410 QString ("%1 ()").arg(r),
3411 QString ("%1 %2").arg(r).arg(getName(bo))
3421 bool MapEditor::unscrollBranch(BranchObj *bo)
3425 if (!bo->isScrolled()) return false;
3426 if (bo->countBranches()==0) return false;
3427 if (bo->getDepth()==0) return false;
3433 QString ("%1 ()").arg(u),
3435 QString ("%1 ()").arg(r),
3436 QString ("%1 %2").arg(r).arg(getName(bo))
3446 void MapEditor::toggleScroll()
3448 BranchObj *bo=xelection.getBranch();
3449 if (xelection.type()==Selection::Branch )
3451 if (bo->isScrolled())
3452 unscrollBranch (bo);
3458 void MapEditor::unscrollChilds()
3460 BranchObj *bo=xelection.getBranch();
3466 if (bo->isScrolled()) unscrollBranch (bo);
3472 FloatImageObj* MapEditor::loadFloatImageInt (QString fn)
3474 BranchObj *bo=xelection.getBranch();
3478 bo->addFloatImage();
3479 fio=bo->getLastFloatImage();
3481 mapCenter->reposition();
3488 void MapEditor::loadFloatImage ()
3490 BranchObj *bo=xelection.getBranch();
3494 Q3FileDialog *fd=new Q3FileDialog( this);
3495 fd->setMode (Q3FileDialog::ExistingFiles);
3496 fd->addFilter (QString (tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)"));
3497 ImagePreview *p =new ImagePreview (fd);
3498 fd->setContentsPreviewEnabled( TRUE );
3499 fd->setContentsPreview( p, p );
3500 fd->setPreviewMode( Q3FileDialog::Contents );
3501 fd->setCaption(vymName+" - " +tr("Load image"));
3502 fd->setDir (lastImageDir);
3505 if ( fd->exec() == QDialog::Accepted )
3507 // TODO loadFIO in QT4 use: lastImageDir=fd->directory();
3508 lastImageDir=QDir (fd->dirPath());
3511 for (int j=0; j<fd->selectedFiles().count(); j++)
3513 s=fd->selectedFiles().at(j);
3514 fio=loadFloatImageInt (s);
3517 (LinkableMapObj*)fio,
3520 QString ("loadImage (%1)").arg(s ),
3521 QString("Add image %1 to %2").arg(s).arg(getName(bo))
3524 // TODO loadFIO error handling
3525 qWarning ("Failed to load "+s);
3533 void MapEditor::saveFloatImageInt (FloatImageObj *fio, const QString &type, const QString &fn)
3535 fio->save (fn,type);
3538 void MapEditor::saveFloatImage ()
3540 FloatImageObj *fio=xelection.getFloatImage();
3543 QFileDialog *fd=new QFileDialog( this);
3544 fd->setFilters (imageIO.getFilters());
3545 fd->setCaption(vymName+" - " +tr("Save image"));
3546 fd->setFileMode( QFileDialog::AnyFile );
3547 fd->setDirectory (lastImageDir);
3548 // fd->setSelection (fio->getOriginalFilename());
3552 if ( fd->exec() == QDialog::Accepted && fd->selectedFiles().count()==1)
3554 fn=fd->selectedFiles().at(0);
3555 if (QFile (fn).exists() )
3557 QMessageBox mb( vymName,
3558 tr("The file %1 exists already.\n"
3559 "Do you want to overwrite it?").arg(fn),
3560 QMessageBox::Warning,
3561 QMessageBox::Yes | QMessageBox::Default,
3562 QMessageBox::Cancel | QMessageBox::Escape,
3563 QMessageBox::QMessageBox::NoButton );
3565 mb.setButtonText( QMessageBox::Yes, tr("Overwrite") );
3566 mb.setButtonText( QMessageBox::No, tr("Cancel"));
3569 case QMessageBox::Yes:
3572 case QMessageBox::Cancel:
3579 saveFloatImageInt (fio,fd->selectedFilter(),fn );
3585 void MapEditor::setFrameType(const FrameObj::FrameType &t)
3587 BranchObj *bo=xelection.getBranch();
3590 QString s=bo->getFrameTypeName();
3591 bo->setFrameType (t);
3592 saveState (bo, QString("setFrameType (\"%1\")").arg(s),
3593 bo, QString ("setFrameType (\"%1\")").arg(bo->getFrameTypeName()),QString ("set type of frame to %1").arg(s));
3594 mapCenter->reposition();
3599 void MapEditor::setFrameType(const QString &s)
3601 BranchObj *bo=xelection.getBranch();
3604 saveState (bo, QString("setFrameType (\"%1\")").arg(bo->getFrameTypeName()),
3605 bo, QString ("setFrameType (\"%1\")").arg(s),QString ("set type of frame to %1").arg(s));
3606 bo->setFrameType (s);
3607 mapCenter->reposition();
3612 void MapEditor::setFramePenColor(const QColor &c)
3614 BranchObj *bo=xelection.getBranch();
3617 saveState (bo, QString("setFramePenColor (\"%1\")").arg(bo->getFramePenColor().name() ),
3618 bo, QString ("setFramePenColor (\"%1\")").arg(c.name() ),QString ("set pen color of frame to %1").arg(c.name() ));
3619 bo->setFramePenColor (c);
3623 void MapEditor::setFrameBrushColor(const QColor &c)
3625 BranchObj *bo=xelection.getBranch();
3628 saveState (bo, QString("setFrameBrushColor (\"%1\")").arg(bo->getFrameBrushColor().name() ),
3629 bo, QString ("setFrameBrushColor (\"%1\")").arg(c.name() ),QString ("set brush color of frame to %1").arg(c.name() ));
3630 bo->setFrameBrushColor (c);
3634 void MapEditor::setFramePadding (const int &i)
3636 BranchObj *bo=xelection.getBranch();
3639 saveState (bo, QString("setFramePadding (\"%1\")").arg(bo->getFramePadding() ),
3640 bo, QString ("setFramePadding (\"%1\")").arg(i),QString ("set brush color of frame to %1").arg(i));
3641 bo->setFramePadding (i);
3642 mapCenter->reposition();
3647 void MapEditor::setFrameBorderWidth(const int &i)
3649 BranchObj *bo=xelection.getBranch();
3652 saveState (bo, QString("setFrameBorderWidth (\"%1\")").arg(bo->getFrameBorderWidth() ),
3653 bo, QString ("setFrameBorderWidth (\"%1\")").arg(i),QString ("set border width of frame to %1").arg(i));
3654 bo->setFrameBorderWidth (i);
3655 mapCenter->reposition();
3660 void MapEditor::setIncludeImagesVer(bool b)
3662 BranchObj *bo=xelection.getBranch();
3665 QString u= b ? "false" : "true";
3666 QString r=!b ? "false" : "true";
3670 QString("setIncludeImagesVertically (%1)").arg(u),
3672 QString("setIncludeImagesVertically (%1)").arg(r),
3673 QString("Include images vertically in %1").arg(getName(bo))
3675 bo->setIncludeImagesVer(b);
3676 mapCenter->reposition();
3680 void MapEditor::setIncludeImagesHor(bool b)
3682 BranchObj *bo=xelection.getBranch();
3685 QString u= b ? "false" : "true";
3686 QString r=!b ? "false" : "true";
3690 QString("setIncludeImagesHorizontally (%1)").arg(u),
3692 QString("setIncludeImagesHorizontally (%1)").arg(r),
3693 QString("Include images horizontally in %1").arg(getName(bo))
3695 bo->setIncludeImagesHor(b);
3696 mapCenter->reposition();
3700 void MapEditor::setHideLinkUnselected (bool b)
3702 LinkableMapObj *sel=xelection.single();
3704 (xelection.type() == Selection::Branch ||
3705 xelection.type() == Selection::MapCenter ||
3706 xelection.type() == Selection::FloatImage ))
3708 QString u= b ? "false" : "true";
3709 QString r=!b ? "false" : "true";
3713 QString("setHideLinkUnselected (%1)").arg(u),
3715 QString("setHideLinkUnselected (%1)").arg(r),
3716 QString("Hide link of %1 if unselected").arg(getName(sel))
3718 sel->setHideLinkUnselected(b);
3722 void MapEditor::importDirInt(BranchObj *dst, QDir d)
3724 BranchObj *bo=xelection.getBranch();
3727 // Traverse directories
3728 d.setFilter( QDir::Dirs| QDir::Hidden | QDir::NoSymLinks );
3729 QFileInfoList list = d.entryInfoList();
3732 for (int i = 0; i < list.size(); ++i)
3735 if (fi.fileName() != "." && fi.fileName() != ".." )
3738 bo=dst->getLastBranch();
3739 bo->setHeading (fi.fileName() );
3740 bo->setColor (QColor("blue"));
3742 if ( !d.cd(fi.fileName()) )
3743 QMessageBox::critical (0,tr("Critical Import Error"),tr("Cannot find the directory %1").arg(fi.fileName()));
3746 // Recursively add subdirs
3747 importDirInt (bo,d);
3753 d.setFilter( QDir::Files| QDir::Hidden | QDir::NoSymLinks );
3754 list = d.entryInfoList();
3756 for (int i = 0; i < list.size(); ++i)
3760 bo=dst->getLastBranch();
3761 bo->setHeading (fi.fileName() );
3762 bo->setColor (QColor("black"));
3763 if (fi.fileName().right(4) == ".vym" )
3764 bo->setVymLink (fi.filePath());
3769 void MapEditor::importDirInt (const QString &s)
3771 BranchObj *bo=xelection.getBranch();
3774 saveStateChangingPart (bo,bo,QString ("importDir (\"%1\")").arg(s),QString("Import directory structure from %1").arg(s));
3777 importDirInt (bo,d);
3781 void MapEditor::importDir()
3783 BranchObj *bo=xelection.getBranch();
3786 QStringList filters;
3787 filters <<"VYM map (*.vym)";
3788 QFileDialog *fd=new QFileDialog( this,vymName+ " - " +tr("Choose directory structure to import"));
3789 fd->setMode (QFileDialog::DirectoryOnly);
3790 fd->setFilters (filters);
3791 fd->setCaption(vymName+" - " +tr("Choose directory structure to import"));
3795 if ( fd->exec() == QDialog::Accepted )
3797 importDirInt (fd->selectedFile() );
3798 mapCenter->reposition();
3804 void MapEditor::followXLink(int i)
3806 BranchObj *bo=xelection.getBranch();
3809 bo=bo->XLinkTargetAt(i);
3812 xelection.select(bo);
3813 ensureSelectionVisible();
3818 void MapEditor::editXLink(int i) // FIXME missing saveState
3820 BranchObj *bo=xelection.getBranch();
3823 XLinkObj *xlo=bo->XLinkAt(i);
3826 EditXLinkDialog dia;
3828 dia.setSelection(bo);
3829 if (dia.exec() == QDialog::Accepted)
3831 if (dia.useSettingsGlobal() )
3833 setMapDefXLinkColor (xlo->getColor() );
3834 setMapDefXLinkWidth (xlo->getWidth() );
3836 if (dia.deleteXLink())
3837 bo->deleteXLinkAt(i);
3843 void MapEditor::testFunction()
3845 mainWindow->statusMessage("Biiiiiiiiiiiiiiing!");
3848 BranchObj *bo=xelection.getBranch();
3849 if (bo) animObjList.append( bo );
3853 dia.showCancelButton (true);
3854 dia.setText("This is a longer \nWarning");
3855 dia.setCaption("Warning: Flux problem");
3856 dia.setShowAgainName("mapeditor/testDialog");
3857 if (dia.exec()==QDialog::Accepted)
3858 cout << "accepted!\n";
3860 cout << "canceled!\n";
3864 /* TODO Hide hidden stuff temporary, maybe add this as regular function somewhere
3865 if (hidemode==HideNone)
3867 setHideTmpMode (HideExport);
3868 mapCenter->calcBBoxSizeWithChilds();
3869 QRectF totalBBox=mapCenter->getTotalBBox();
3870 QRectF mapRect=totalBBox;
3871 QCanvasRectangle *frame=NULL;
3873 cout << " map has =("<<totalBBox.x()<<","<<totalBBox.y()<<","<<totalBBox.width()<<","<<totalBBox.height()<<")\n";
3875 mapRect.setRect (totalBBox.x(), totalBBox.y(),
3876 totalBBox.width(), totalBBox.height());
3877 frame=new QCanvasRectangle (mapRect,mapScene);
3878 frame->setBrush (QColor(white));
3879 frame->setPen (QColor(black));
3880 frame->setZValue(0);
3885 setHideTmpMode (HideNone);
3887 cout <<" hidemode="<<hidemode<<endl;
3891 void MapEditor::contextMenuEvent ( QContextMenuEvent * e )
3893 // Lineedits are already closed by preceding
3894 // mouseEvent, we don't need to close here.
3896 QPointF p = mapToScene(e->pos());
3897 LinkableMapObj* lmo=mapCenter->findMapObj(p, NULL);
3900 { // MapObj was found
3901 if (xelection.single() != lmo)
3903 // select the MapObj
3904 xelection.select(lmo);
3907 if (xelection.getBranch() )
3909 // Context Menu on branch or mapcenter
3911 branchContextMenu->popup(e->globalPos() );
3914 if (xelection.getFloatImage() )
3916 // Context Menu on floatimage
3918 floatimageContextMenu->popup(e->globalPos() );
3922 { // No MapObj found, we are on the Canvas itself
3923 // Context Menu on scene
3925 canvasContextMenu->popup(e->globalPos() );
3930 void MapEditor::keyPressEvent(QKeyEvent* e)
3932 if (e->modifiers() & Qt::ControlModifier)
3934 switch (mainWindow->getModMode())
3936 case Main::ModModeColor:
3937 setCursor (PickColorCursor);
3939 case Main::ModModeCopy:
3940 setCursor (CopyCursor);
3942 case Main::ModModeXLink:
3943 setCursor (XLinkCursor);
3946 setCursor (Qt::ArrowCursor);
3952 void MapEditor::keyReleaseEvent(QKeyEvent* e)
3954 if (!(e->modifiers() & Qt::ControlModifier))
3955 setCursor (Qt::ArrowCursor);
3958 void MapEditor::mousePressEvent(QMouseEvent* e)
3960 // Ignore right clicks, these will go to context menus
3961 if (e->button() == Qt::RightButton )
3967 //Ignore clicks while editing heading
3968 if (isSelectBlocked() )
3974 QPointF p = mapToScene(e->pos());
3975 LinkableMapObj* lmo=mapCenter->findMapObj(p, NULL);
3979 //Take care of system flags _or_ modifier modes
3981 if (lmo && (typeid(*lmo)==typeid(BranchObj) ||
3982 typeid(*lmo)==typeid(MapCenterObj) ))
3984 QString foname=((BranchObj*)lmo)->getSystemFlagName(p);
3985 if (!foname.isEmpty())
3987 // systemFlag clicked
3991 if (e->state() & Qt::ControlModifier)
3992 mainWindow->editOpenURLTab();
3994 mainWindow->editOpenURL();
3996 else if (foname=="vymLink")
3998 mainWindow->editOpenVymLink();
3999 // tabWidget may change, better return now
4000 // before segfaulting...
4001 } else if (foname=="note")
4002 mainWindow->windowToggleNoteEditor();
4003 else if (foname=="hideInExport")
4010 // No system flag clicked, take care of modmodes (CTRL-Click)
4011 if (e->state() & Qt::ControlModifier)
4013 if (mainWindow->getModMode()==Main::ModModeColor)
4016 setCursor (PickColorCursor);
4019 if (mainWindow->getModMode()==Main::ModModeXLink)
4021 BranchObj *bo_begin=NULL;
4023 bo_begin=(BranchObj*)(lmo);
4025 if (xelection.getBranch() )
4026 bo_begin=xelection.getBranch();
4030 linkingObj_src=bo_begin;
4031 tmpXLink=new XLinkObj (mapScene);
4032 tmpXLink->setBegin (bo_begin);
4033 tmpXLink->setEnd (p);
4034 tmpXLink->setColor(defXLinkColor);
4035 tmpXLink->setWidth(defXLinkWidth);
4036 tmpXLink->updateXLink();
4037 tmpXLink->setVisibility (true);
4041 } // End of modmodes
4045 // Select the clicked object
4048 // Left Button Move Branches
4049 if (e->button() == Qt::LeftButton )
4051 //movingObj_start.setX( p.x() - selection->x() );// TODO replaced selection->lmo here
4052 //movingObj_start.setY( p.y() - selection->y() );
4053 movingObj_start.setX( p.x() - lmo->x() );
4054 movingObj_start.setY( p.y() - lmo->y() );
4055 movingObj_orgPos.setX (lmo->x() );
4056 movingObj_orgPos.setY (lmo->y() );
4057 movingObj_orgRelPos=lmo->getRelPos();
4059 // If modMode==copy, then we want to "move" the _new_ object around
4060 // then we need the offset from p to the _old_ selection, because of tmp
4061 if (mainWindow->getModMode()==Main::ModModeCopy &&
4062 e->state() & Qt::ControlModifier)
4064 if (xelection.type()==Selection::Branch)
4067 mapCenter->addBranch ((BranchObj*)xelection.single());
4069 xelection.select(mapCenter->getLastBranch());
4070 mapCenter->reposition();
4074 movingObj=xelection.single();
4076 // Middle Button Toggle Scroll
4077 // (On Mac OS X this won't work, but we still have
4078 // a button in the toolbar)
4079 if (e->button() == Qt::MidButton )
4084 { // No MapObj found, we are on the scene itself
4085 // Left Button move Pos of sceneView
4086 if (e->button() == Qt::LeftButton )
4088 movingObj=NULL; // move Content not Obj
4089 movingObj_start=e->globalPos();
4090 movingCont_start=QPointF (
4091 horizontalScrollBar()->value(),
4092 verticalScrollBar()->value());
4093 movingVec=QPointF(0,0);
4094 setCursor(HandOpenCursor);
4099 void MapEditor::mouseMoveEvent(QMouseEvent* e)
4101 QPointF p = mapToScene(e->pos());
4102 LinkableMapObj *lmosel=xelection.single();
4104 // Move the selected MapObj
4105 if ( lmosel && movingObj)
4107 // reset cursor if we are moving and don't copy
4108 if (mainWindow->getModMode()!=Main::ModModeCopy)
4109 setCursor (Qt::ArrowCursor);
4111 // To avoid jumping of the sceneView, only
4112 // ensureSelectionVisible, if not tmp linked
4113 if (!lmosel->hasParObjTmp())
4114 ensureSelectionVisible ();
4116 // Now move the selection, but add relative position
4117 // (movingObj_start) where selection was chosen with
4118 // mousepointer. (This avoids flickering resp. jumping
4119 // of selection back to absPos)
4121 // Check if we could link
4122 LinkableMapObj* lmo=mapCenter->findMapObj(p, lmosel);
4125 FloatObj *fio=xelection.getFloatImage();
4128 fio->move (p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
4130 fio->updateLink(); //no need for reposition, if we update link here
4133 // Relink float to new mapcenter or branch, if shift is pressed
4134 // Only relink, if selection really has a new parent
4135 if ( (e->modifiers()==Qt::ShiftModifier) && lmo &&
4136 ( (typeid(*lmo)==typeid(BranchObj)) ||
4137 (typeid(*lmo)==typeid(MapCenterObj)) ) &&
4138 ( lmo != fio->getParObj())
4141 if (typeid(*fio) == typeid(FloatImageObj) &&
4142 ( (typeid(*lmo)==typeid(BranchObj) ||
4143 typeid(*lmo)==typeid(MapCenterObj)) ))
4146 // Also save the move which was done so far
4147 QString pold=qpointfToString(movingObj_orgRelPos);
4148 QString pnow=qpointfToString(fio->getRelPos());
4154 QString("Move %1 to relativ position %2").arg(getName(fio)).arg(pnow));
4155 fio->getParObj()->requestReposition();
4156 mapCenter->reposition();
4158 linkTo (lmo->getSelectString());
4160 //movingObj_orgRelPos=lmosel->getRelPos();
4162 mapCenter->reposition();
4166 { // selection != a FloatObj
4167 if (lmosel->getDepth()==0)
4170 if (e->buttons()== Qt::LeftButton && e->modifiers()==Qt::ShiftModifier)
4171 mapCenter->moveAll(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
4173 mapCenter->move (p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
4174 mapCenter->updateRelPositions();
4177 if (lmosel->getDepth()==1)
4180 lmosel->move(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
4181 lmosel->setRelPos();
4184 // Move ordinary branch
4185 if (lmosel->getOrientation() == LinkableMapObj::LeftOfCenter)
4186 // Add width of bbox here, otherwise alignRelTo will cause jumping around
4187 lmosel->move(p.x() -movingObj_start.x()+lmosel->getBBox().width(),
4188 p.y()-movingObj_start.y() +lmosel->getTopPad() );
4190 lmosel->move(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() -lmosel->getTopPad());
4193 // Maybe we can relink temporary?
4194 if (lmo && (lmo!=lmosel) && xelection.getBranch() &&
4195 (typeid(*lmo)==typeid(BranchObj) ||
4196 typeid(*lmo)==typeid(MapCenterObj)) )
4199 if (e->modifiers()==Qt::ControlModifier)
4201 // Special case: CTRL to link below lmo
4202 lmosel->setParObjTmp (lmo,p,+1);
4204 else if (e->modifiers()==Qt::ShiftModifier)
4205 lmosel->setParObjTmp (lmo,p,-1);
4207 lmosel->setParObjTmp (lmo,p,0);
4210 lmosel->unsetParObjTmp();
4212 // reposition subbranch
4213 lmosel->reposition();
4217 } // no FloatImageObj
4221 } // selection && moving_obj
4223 // Draw a link from one branch to another
4226 tmpXLink->setEnd (p);
4227 tmpXLink->updateXLink();
4231 if (!movingObj && !pickingColor &&!drawingLink && e->buttons() == Qt::LeftButton )
4233 QPointF p=e->globalPos();
4234 movingVec.setX(-p.x() + movingObj_start.x() );
4235 movingVec.setY(-p.y() + movingObj_start.y() );
4236 horizontalScrollBar()->setSliderPosition((int)( movingCont_start.x()+movingVec.x() ));
4237 verticalScrollBar()->setSliderPosition((int)( movingCont_start.y()+movingVec.y() ) );
4242 void MapEditor::mouseReleaseEvent(QMouseEvent* e)
4244 QPointF p = mapToScene(e->pos());
4245 LinkableMapObj *dst;
4246 LinkableMapObj *lmosel=xelection.single();
4247 // Have we been picking color?
4251 setCursor (Qt::ArrowCursor);
4252 // Check if we are over another branch
4253 dst=mapCenter->findMapObj(p, NULL);
4256 if (e->state() & Qt::ShiftModifier)
4257 colorBranch (((BranchObj*)(dst))->getColor());
4259 colorSubtree (((BranchObj*)(dst))->getColor());
4264 // Have we been drawing a link?
4268 // Check if we are over another branch
4269 dst=mapCenter->findMapObj(p, NULL);
4272 tmpXLink->setEnd ( ((BranchObj*)(dst)) );
4273 tmpXLink->updateXLink();
4274 tmpXLink->activate(); //FIXME savestate missing
4275 //saveStateComplete(QString("Activate xLink from %1 to %2").arg(getName(tmpXLink->getBegin())).arg(getName(tmpXLink->getEnd())) );
4284 // Have we been moving something?
4285 if ( lmosel && movingObj )
4287 FloatImageObj *fo=xelection.getFloatImage();
4290 // Moved FloatObj. Maybe we need to reposition
4291 QString pold=qpointfToString(movingObj_orgRelPos);
4292 QString pnow=qpointfToString(fo->getRelPos());
4298 QString("Move %1 to relativ position %2").arg(getName(fo)).arg(pnow));
4300 fo->getParObj()->requestReposition();
4301 mapCenter->reposition();
4304 // Check if we are over another branch, but ignore
4305 // any found LMOs, which are FloatObjs
4306 dst=mapCenter->findMapObj(mapToScene(e->pos() ), lmosel);
4308 if (dst && (typeid(*dst)!=typeid(BranchObj) && typeid(*dst)!=typeid(MapCenterObj)))
4311 if (xelection.type() == Selection::MapCenter )
4313 // TODO: Check for problems if graphicsview is resized for
4315 QString pold=qpointfToString(movingObj_orgPos);
4316 QString pnow=qpointfToString(mapCenter->getAbsPos());
4322 QString("Move mapcenter %1 to position %2").arg(getName(mapCenter)).arg(pnow));
4325 if (xelection.type() == Selection::Branch )
4326 { // A branch was moved
4328 // save the position in case we link to mapcenter
4329 QPointF savePos=QPointF (lmosel->getAbsPos() );
4331 // Reset the temporary drawn link to the original one
4332 lmosel->unsetParObjTmp();
4334 // For Redo we may need to save original selection
4335 QString preSelStr=lmosel->getSelectString();
4340 BranchObj* bsel=xelection.getBranch();
4341 BranchObj* bdst=(BranchObj*)dst;
4343 QString preParStr=(bsel->getParObj())->getSelectString();
4344 QString preNum=QString::number (bsel->getNum(),10);
4345 QString preDstParStr;
4347 if (e->state() & Qt::ShiftModifier && dst->getParObj())
4349 preDstParStr=dst->getParObj()->getSelectString();
4350 bsel->linkTo ( (BranchObj*)(bdst->getParObj()), bdst->getNum());
4352 if (e->state() & Qt::ControlModifier && dst->getParObj())
4355 preDstParStr=dst->getParObj()->getSelectString();
4356 bsel->linkTo ( (BranchObj*)(bdst->getParObj()), bdst->getNum()+1);
4359 preDstParStr=dst->getSelectString();
4360 bsel->linkTo (bdst,-1);
4361 if (dst->getDepth()==0) bsel->move (savePos);
4363 QString postSelStr=lmosel->getSelectString();
4364 QString postNum=QString::number (bsel->getNum(),10);
4366 QString undoCom="linkTo (\""+
4367 preParStr+ "\"," + preNum +"," +
4368 QString ("%1,%2").arg(movingObj_orgPos.x()).arg(movingObj_orgPos.y())+ ")";
4370 QString redoCom="linkTo (\""+
4371 preDstParStr + "\"," + postNum + "," +
4372 QString ("%1,%2").arg(savePos.x()).arg(savePos.y())+ ")";
4377 QString("Relink %1 to %2").arg(getName(bsel)).arg(getName(dst)) );
4379 if (lmosel->getDepth()==1)
4381 // The select string might be different _after_ moving around.
4382 // Therefor reposition and then use string of old selection, too
4383 mapCenter->reposition();
4385 QString ps=qpointfToString ( lmosel->getRelPos() );
4387 lmosel->getSelectString(), "moveRel "+qpointfToString(movingObj_orgRelPos),
4388 preSelStr, "moveRel "+ps,
4389 QString("Move %1 to relative position %2").arg(getName(lmosel)).arg(ps));
4392 // Draw the original link, before selection was moved around
4393 mapCenter->reposition();
4396 // Finally resize scene, if needed
4400 // Just make sure, that actions are still ok,e.g. the move branch up/down buttons...
4403 // maybe we moved View: set old cursor
4404 setCursor (Qt::ArrowCursor);
4408 void MapEditor::mouseDoubleClickEvent(QMouseEvent* e)
4410 if (isSelectBlocked() )
4416 if (e->button() == Qt::LeftButton )
4418 QPointF p = mapToScene(e->pos());
4419 LinkableMapObj *lmo=mapCenter->findMapObj(p, NULL);
4420 if (lmo) { // MapObj was found
4421 // First select the MapObj than edit heading
4422 xelection.select(lmo);
4423 mainWindow->editHeading();
4428 void MapEditor::resizeEvent (QResizeEvent* e)
4430 QGraphicsView::resizeEvent( e );
4433 void MapEditor::dragEnterEvent(QDragEnterEvent *event)
4435 //for (unsigned int i=0;event->format(i);i++) // Debug mime type
4436 // cerr << event->format(i) << endl;
4438 if (event->mimeData()->hasImage())
4439 event->acceptProposedAction();
4441 if (event->mimeData()->hasUrls())
4442 event->acceptProposedAction();
4445 void MapEditor::dragMoveEvent(QDragMoveEvent *event)
4449 void MapEditor::dragLeaveEvent(QDragLeaveEvent *event)
4454 void MapEditor::dropEvent(QDropEvent *event)
4456 BranchObj *sel=xelection.getBranch();
4460 foreach (QString format,event->mimeData()->formats())
4461 cout << "MapEditor: Dropped format: "<<format.ascii()<<endl;
4465 if (event->mimeData()->hasImage())
4467 QVariant imageData = event->mimeData()->imageData();
4468 addFloatImageInt (qvariant_cast<QPixmap>(imageData));
4470 if (event->mimeData()->hasUrls())
4471 uris=event->mimeData()->urls();
4479 for (int i=0; i<uris.count();i++)
4481 // Workaround to avoid adding empty branches
4482 if (!uris.at(i).toString().isEmpty())
4484 bo=sel->addBranch();
4487 s=uris.at(i).toLocalFile();
4490 QString file = QDir::convertSeparators(s);
4491 heading = QFileInfo(file).baseName();
4493 if (file.endsWith(".vym", false))
4494 bo->setVymLink(file);
4496 bo->setURL(uris.at(i).toString());
4499 bo->setURL(uris.at(i).toString());
4502 if (!heading.isEmpty())
4503 bo->setHeading(heading);
4505 bo->setHeading(uris.at(i).toString());
4509 mapCenter->reposition();
4512 event->acceptProposedAction();
4515 void MapEditor::timerEvent(QTimerEvent *event) //TODO animation
4519 cout << "ME::timerEvent\n";
4521 for (int i=0; i<animObjList.size(); ++i)
4523 animObjList.at(i)->animate();
4524 ((BranchObj*)animObjList.at(i))->move2RelPos (((BranchObj*)animObjList.at(i))->getRelPos() );
4526 mapCenter->reposition();
4529 void MapEditor::autosave()
4531 // Disable autosave, while we have gone back in history
4532 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
4533 if (redosAvail>0) return;
4536 if (mapUnsaved &&mapChanged && settings.value ("/mapeditor/autosave/use",true).toBool() )
4537 mainWindow->fileSave (this);
4541 /*TODO not needed? void MapEditor::contentsDropEvent(QDropEvent *event)
4544 } else if (event->provides("application/x-moz-file-promise-url") &&
4545 event->provides("application/x-moz-nativeimage"))
4547 // Contains url to the img src in unicode16
4548 QByteArray d = event->encodedData("application/x-moz-file-promise-url");
4549 QString url = QString((const QChar*)d.data(),d.size()/2);
4553 } else if (event->provides ("text/uri-list"))
4554 { // Uris provided e.g. by konqueror
4555 Q3UriDrag::decode (event,uris);
4556 } else if (event->provides ("_NETSCAPE_URL"))
4557 { // Uris provided by Mozilla
4558 QStringList l = QStringList::split("\n", event->encodedData("_NETSCAPE_URL"));
4561 } else if (event->provides("text/html")) {
4563 // Handels text mime types
4564 // Look like firefox allways handle text as unicode16 (2 bytes per char.)
4565 QByteArray d = event->encodedData("text/html");
4568 text = QString((const QChar*)d.data(),d.size()/2);
4572 textEditor->setText(text);
4576 } else if (event->provides("text/plain")) {
4577 QByteArray d = event->encodedData("text/plain");
4580 text = QString((const QChar*)d.data(),d.size()/2);
4584 textEditor->setText(text);
4594 bool isUnicode16(const QByteArray &d)
4596 // TODO: make more precise check for unicode 16.
4597 // Guess unicode16 if any of second bytes are zero
4598 unsigned int length = max(0,d.size()-2)/2;
4599 for (unsigned int i = 0; i<length ; i++)
4600 if (d.at(i*2+1)==0) return true;
4604 void MapEditor::addFloatImageInt (const QPixmap &img)
4606 BranchObj *bo=xelection.getBranch();
4609 FloatImageObj *fio=bo->addFloatImage();
4611 fio->setOriginalFilename("No original filename (image added by dropevent)");
4612 QString s=bo->getSelectString();
4613 saveState (PartOfMap, s, "nop ()", s, "copy ()","Copy dropped image to clipboard",fio );
4614 saveState (fio,"delete ()", bo,QString("paste(%1)").arg(curStep),"Pasting dropped image");
4615 mapCenter->reposition();
4622 void MapEditor::imageDataFetched(const QByteArray &a, Q3NetworkOperation * / *nop* /)
4624 if (!imageBuffer) imageBuffer = new QBuffer();
4625 if (!imageBuffer->isOpen()) {
4626 imageBuffer->open(QIODevice::WriteOnly | QIODevice::Append);
4628 imageBuffer->at(imageBuffer->at()+imageBuffer->writeBlock(a));
4632 void MapEditor::imageDataFinished(Q3NetworkOperation *nop)
4634 if (nop->state()==Q3NetworkProtocol::StDone) {
4635 QPixmap img(imageBuffer->buffer());
4636 addFloatImageInt (img);
4640 imageBuffer->close();
4642 imageBuffer->close();
4649 void MapEditor::fetchImage(const QString &url)
4652 urlOperator->stop();
4653 disconnect(urlOperator);
4657 urlOperator = new Q3UrlOperator(url);
4658 connect(urlOperator, SIGNAL(finished(Q3NetworkOperation *)),
4659 this, SLOT(imageDataFinished(Q3NetworkOperation*)));
4661 connect(urlOperator, SIGNAL(data(const QByteArray &, Q3NetworkOperation *)),
4662 this, SLOT(imageDataFetched(const QByteArray &, Q3NetworkOperation *)));