3 #include <q3filedialog.h>
12 #include "editxlinkdialog.h"
14 #include "exportxhtmldialog.h"
15 #include "extrainfodialog.h"
17 #include "linkablemapobj.h"
18 #include "mainwindow.h"
20 #include "texteditor.h"
21 #include "warningdialog.h"
25 extern TextEditor *textEditor;
26 extern int statusbarTime;
27 extern Main *mainWindow;
28 extern QString tmpVymDir;
29 extern QString clipboardDir;
30 extern QString clipboardFile;
31 extern bool clipboardEmpty;
33 extern FlagRowObj *standardFlagsDefault;
35 extern QMenu* branchContextMenu;
36 extern QMenu* branchAddContextMenu;
37 extern QMenu* branchRemoveContextMenu;
38 extern QMenu* branchLinksContextMenu;
39 extern QMenu* branchXLinksContextMenuEdit;
40 extern QMenu* branchXLinksContextMenuFollow;
41 extern QMenu* floatimageContextMenu;
42 extern QMenu* canvasContextMenu;
45 extern Settings settings;
46 extern ImageIO imageIO;
48 extern QString vymName;
49 extern QString vymVersion;
51 extern QString iconPath;
52 extern QDir vymBaseDir;
53 extern QDir lastImageDir;
54 extern QDir lastFileDir;
56 int MapEditor::mapNum=0; // make instance
58 ///////////////////////////////////////////////////////////////////////
59 ///////////////////////////////////////////////////////////////////////
60 MapEditor::MapEditor( QWidget* parent) :
63 //cout << "Constructor ME "<<this<<endl;
67 mapScene= new QGraphicsScene(parent);
68 //mapScene= new QGraphicsScene(QRectF(0,0,width(),height()), parent);
69 mapScene->setBackgroundBrush (QBrush(Qt::white, Qt::SolidPattern));
74 mapCenter = new MapCenterObj(mapScene);
75 mapCenter->setVisibility (true);
76 mapCenter->setMapEditor (this);
77 mapCenter->setHeading (tr("New Map","Heading of mapcenter in new map"));
78 //mapCenter->move(mapScene->width()/2-mapCenter->width()/2,mapScene->height()/2-mapCenter->height()/2);
83 defLinkColor=QColor (0,0,255);
84 defXLinkColor=QColor (180,180,180);
85 linkcolorhint=LinkableMapObj::DefaultColor;
86 linkstyle=LinkableMapObj::PolyParabel;
88 // Create bitmap cursors, platform dependant
89 HandOpenCursor=QCursor (QPixmap(iconPath+"cursorhandopen.png"),1,1);
90 PickColorCursor=QCursor ( QPixmap(iconPath+"cursorcolorpicker.png"), 5,27 );
91 CopyCursor=QCursor ( QPixmap(iconPath+"cursorcopy.png"), 1,1 );
92 XLinkCursor=QCursor ( QPixmap(iconPath+"cursorxlink.png"), 1,7 );
94 setFocusPolicy (Qt::StrongFocus);
103 xelection.setMapEditor (this);
104 xelection.unselect();
107 defXLinkColor=QColor (230,230,230);
115 fileName=tr("unnamed");
118 stepsTotal=settings.readNumEntry("/mapeditor/stepsTotal",100);
119 undoSet.setEntry ("/history/stepsTotal",QString::number(stepsTotal));
120 mainWindow->updateHistory (undoSet);
122 // Initialize find routine
129 blockReposition=false;
130 blockSaveState=false;
132 hidemode=BranchObj::HideNone;
134 // Create temporary files
141 setAcceptDrops (true);
143 mapCenter->reposition(); // for positioning heading
147 //timerId = startTimer(100);
150 autosaveTimer=new QTimer (this);
151 connect(autosaveTimer, SIGNAL(timeout()), this, SLOT(autosave()));
154 MapEditor::~MapEditor()
156 //cout <<"Destructor MapEditor\n";
157 autosaveTimer->stop();
160 MapCenterObj* MapEditor::getMapCenter()
165 QGraphicsScene * MapEditor::getScene()
170 MapEditor::State MapEditor::getState()
175 void MapEditor::setStateEditHeading(bool s)
179 if (state==Idle) state=EditHeading;
185 bool MapEditor::isRepositionBlocked()
187 return blockReposition;
190 void MapEditor::setSaveStateBlocked(bool b)
195 bool MapEditor::isSelectBlocked()
197 if (state==EditHeading)
203 QString MapEditor::getName (const LinkableMapObj *lmo)
206 if (!lmo) return QString("Error: NULL has no name!");
208 if ((typeid(*lmo) == typeid(BranchObj) ||
209 typeid(*lmo) == typeid(MapCenterObj)))
212 s=(((BranchObj*)lmo)->getHeading());
213 if (s=="") s="unnamed";
214 return QString("branch (%1)").arg(s);
215 //return QString("branch (<font color=\"#0000ff\">%1</font>)").arg(s);
217 if ((typeid(*lmo) == typeid(FloatImageObj) ))
218 return QString ("floatimage [%1]").arg(((FloatImageObj*)lmo)->getOriginalFilename());
219 //return QString ("floatimage [<font color=\"#0000ff\">%1</font>]").arg(((FloatImageObj*)lmo)->getOriginalFilename());
220 return QString("Unknown type has no name!");
223 void MapEditor::makeTmpDirs()
225 // Create unique temporary directories
226 tmpMapDir=QDir::convertSeparators (tmpVymDir+QString("/mapeditor-%1").arg(mapNum));
227 histPath=QDir::convertSeparators (tmpMapDir+"/history");
232 QString MapEditor::saveToDir(const QString &tmpdir, const QString &prefix, bool writeflags, const QPointF &offset, LinkableMapObj *saveSel)
234 // tmpdir temporary directory to which data will be written
235 // prefix mapname, which will be appended to images etc.
236 // writeflags Only write flags for "real" save of map, not undo
237 // offset offset of bbox of whole map in scene.
238 // Needed for XML export
244 case LinkableMapObj::Line:
247 case LinkableMapObj::Parabel:
250 case LinkableMapObj::PolyLine:
254 ls="StylePolyParabel";
258 QString s="<?xml version=\"1.0\" encoding=\"utf-8\"?><!DOCTYPE vymmap>\n";
260 if (linkcolorhint==LinkableMapObj::HeadingColor)
261 colhint=attribut("linkColorHint","HeadingColor");
263 QString mapAttr=attribut("version",vymVersion);
264 if (!saveSel || saveSel==mapCenter)
265 mapAttr+= attribut("author",mapCenter->getAuthor()) +
266 attribut("comment",mapCenter->getComment()) +
267 attribut("date",mapCenter->getDate()) +
268 attribut("backgroundColor", mapScene->backgroundBrush().color().name() ) +
269 attribut("selectionColor", xelection.getColor().name() ) +
270 attribut("linkStyle", ls ) +
271 attribut("linkColor", defLinkColor.name() ) +
272 attribut("defXLinkColor", defXLinkColor.name() ) +
273 attribut("defXLinkWidth", QString().setNum(defXLinkWidth,10) ) +
275 s+=beginElement("vymmap",mapAttr);
278 // Find the used flags while traversing the tree
279 standardFlagsDefault->resetUsedCounter();
281 // Reset the counters before saving
282 // TODO constr. of FIO creates lots of objects, better do this in some other way...
283 FloatImageObj (mapScene).resetSaveCounter();
285 // Build xml recursivly
286 if (!saveSel || typeid (*saveSel) == typeid (MapCenterObj))
287 // Save complete map, if saveSel not set
288 s+=mapCenter->saveToDir(tmpdir,prefix,writeflags,offset);
291 if ( typeid(*saveSel) == typeid(BranchObj) )
293 s+=((BranchObj*)(saveSel))->saveToDir(tmpdir,prefix,offset);
294 else if ( typeid(*saveSel) == typeid(FloatImageObj) )
296 s+=((FloatImageObj*)(saveSel))->saveToDir(tmpdir,prefix);
299 // Save local settings
300 s+=settings.getXMLData (destPath);
303 if (!xelection.isEmpty() && !saveSel )
304 s+=valueElement("select",xelection.getSelectString());
307 s+=endElement("vymmap");
310 standardFlagsDefault->saveToDir (tmpdir+"/flags/","",writeflags);
314 QString MapEditor::getHistoryDir()
316 QString histName=QDir::convertSeparators (QString("history-%1").arg(curStep));
317 return QDir::convertSeparators (tmpMapDir +"/"+histName);
320 void MapEditor::saveState(const SaveMode &savemode, const QString &undoSelection, const QString &undoCom, const QString &redoSelection, const QString &redoCom, const QString &comment, LinkableMapObj *saveSel)
324 if (blockSaveState) return;
326 if (debug) cout << "ME::saveState() for "<<mapName.ascii()<<endl;
328 // Find out current undo directory
329 if (undosAvail<stepsTotal) undosAvail++;
331 if (curStep>stepsTotal) curStep=1;
333 QString backupXML="";
334 QString histDir=getHistoryDir();
335 QString bakMapPath=QDir::convertSeparators(histDir+"/map.xml");
337 // Create histDir if not available
340 makeSubDirs (histDir);
342 // Save depending on how much needs to be saved
344 backupXML=saveToDir (histDir,mapName+"-",false, QPointF (),saveSel);
346 QString undoCommand="";
347 if (savemode==UndoCommand)
351 else if (savemode==PartOfMap )
354 undoCommand.replace ("PATH",bakMapPath);
357 if (!backupXML.isEmpty())
358 // Write XML Data to disk
359 saveStringToDisk (QString(bakMapPath),backupXML);
361 // We would have to save all actions in a tree, to keep track of
362 // possible redos after a action. Possible, but we are too lazy: forget about redos.
365 // Write the current state to disk
366 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
367 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
368 undoSet.setEntry ("/history/curStep",QString::number(curStep));
369 undoSet.setEntry (QString("/history/step-%1/undoCommand").arg(curStep),undoCommand);
370 undoSet.setEntry (QString("/history/step-%1/undoSelection").arg(curStep),undoSelection);
371 undoSet.setEntry (QString("/history/step-%1/redoCommand").arg(curStep),redoCom);
372 undoSet.setEntry (QString("/history/step-%1/redoSelection").arg(curStep),redoSelection);
373 undoSet.setEntry (QString("/history/step-%1/comment").arg(curStep),comment);
374 undoSet.setEntry (QString("/history/version"),vymVersion);
375 undoSet.writeSettings(histPath);
379 // TODO remove after testing
380 //cout << " into="<< histPath.toStdString()<<endl;
381 cout << " stepsTotal="<<stepsTotal<<
382 ", undosAvail="<<undosAvail<<
383 ", redosAvail="<<redosAvail<<
384 ", curStep="<<curStep<<endl;
385 cout << " ---------------------------"<<endl;
386 cout << " comment="<<comment.toStdString()<<endl;
387 cout << " undoCom="<<undoCommand.toStdString()<<endl;
388 cout << " undoSel="<<undoSelection.toStdString()<<endl;
389 cout << " redoCom="<<redoCom.toStdString()<<endl;
390 cout << " redoSel="<<redoSelection.toStdString()<<endl;
391 if (saveSel) cout << " saveSel="<<saveSel->getSelectString().ascii()<<endl;
392 cout << " ---------------------------"<<endl;
395 mainWindow->updateHistory (undoSet);
401 void MapEditor::saveStateChangingPart(LinkableMapObj *undoSel, LinkableMapObj* redoSel, const QString &rc, const QString &comment)
403 // save the selected part of the map, Undo will replace part of map
404 QString undoSelection="";
406 undoSelection=undoSel->getSelectString();
408 qWarning ("MapEditor::saveStateChangingPart no undoSel given!");
409 QString redoSelection="";
411 redoSelection=undoSel->getSelectString();
413 qWarning ("MapEditor::saveStateChangingPart no redoSel given!");
416 saveState (PartOfMap,
417 undoSelection, "addMapReplace (\"PATH\")",
423 void MapEditor::saveStateRemovingPart(LinkableMapObj *redoSel, const QString &comment)
427 qWarning ("MapEditor::saveStateRemovingPart no redoSel given!");
430 QString undoSelection=redoSel->getParObj()->getSelectString();
431 QString redoSelection=redoSel->getSelectString();
432 if (typeid(*redoSel) == typeid(BranchObj) )
434 // save the selected branch of the map, Undo will insert part of map
435 saveState (PartOfMap,
436 undoSelection, QString("addMapInsert (\"PATH\",%1)").arg(((BranchObj*)redoSel)->getNum()),
437 redoSelection, "delete ()",
444 void MapEditor::saveState(LinkableMapObj *undoSel, const QString &uc, LinkableMapObj *redoSel, const QString &rc, const QString &comment)
446 // "Normal" savestate: save commands, selections and comment
447 // so just save commands for undo and redo
448 // and use current selection
450 QString redoSelection="";
451 if (redoSel) redoSelection=redoSel->getSelectString();
452 QString undoSelection="";
453 if (undoSel) undoSelection=undoSel->getSelectString();
455 saveState (UndoCommand,
462 void MapEditor::saveState(const QString &undoSel, const QString &uc, const QString &redoSel, const QString &rc, const QString &comment)
464 // "Normal" savestate: save commands, selections and comment
465 // so just save commands for undo and redo
466 // and use current selection
467 saveState (UndoCommand,
475 void MapEditor::parseAtom(const QString &atom)
477 BranchObj *selb=xelection.getBranch();
482 // Split string s into command and parameters
483 parser.parseAtom (atom);
484 QString com=parser.getCommand();
487 /////////////////////////////////////////////////////////////////////
488 if (com=="addBranch")
490 if (xelection.isEmpty())
492 parser.setError (Aborted,"Nothing selected");
495 parser.setError (Aborted,"Type of selection is not a branch");
500 if (parser.checkParCount(pl))
502 if (parser.parCount()==0)
503 addNewBranchInt (-2);
506 y=parser.parInt (ok,0);
507 if (ok ) addNewBranchInt (y);
511 /////////////////////////////////////////////////////////////////////
512 } else if (com=="addBranchBefore")
514 if (xelection.isEmpty())
516 parser.setError (Aborted,"Nothing selected");
519 parser.setError (Aborted,"Type of selection is not a branch");
522 if (parser.parCount()==0)
524 addNewBranchBefore ();
527 /////////////////////////////////////////////////////////////////////
528 } else if (com==QString("addMapReplace"))
530 if (xelection.isEmpty())
532 parser.setError (Aborted,"Nothing selected");
535 parser.setError (Aborted,"Type of selection is not a branch");
536 } else if (parser.checkParCount(1))
538 //s=parser.parString (ok,0); // selection
539 t=parser.parString (ok,0); // path to map
540 if (QDir::isRelativePath(t)) t=QDir::convertSeparators (tmpMapDir + "/"+t);
541 addMapReplaceInt(selb->getSelectString(),t);
543 /////////////////////////////////////////////////////////////////////
544 } else if (com==QString("addMapInsert"))
546 if (xelection.isEmpty())
548 parser.setError (Aborted,"Nothing selected");
551 parser.setError (Aborted,"Type of selection is not a branch");
554 if (parser.checkParCount(2))
556 t=parser.parString (ok,0); // path to map
557 y=parser.parInt(ok,1); // position
558 if (QDir::isRelativePath(t)) t=QDir::convertSeparators (tmpMapDir + "/"+t);
559 addMapInsertInt(t,y);
562 /////////////////////////////////////////////////////////////////////
563 } else if (com=="clearFlags")
565 if (xelection.isEmpty() )
567 parser.setError (Aborted,"Nothing selected");
570 parser.setError (Aborted,"Type of selection is not a branch");
571 } else if (parser.checkParCount(0))
573 selb->clearStandardFlags();
574 selb->updateFlagsToolbar();
576 /////////////////////////////////////////////////////////////////////
577 } else if (com=="colorBranch")
579 if (xelection.isEmpty())
581 parser.setError (Aborted,"Nothing selected");
584 parser.setError (Aborted,"Type of selection is not a branch");
585 } else if (parser.checkParCount(1))
587 QColor c=parser.parColor (ok,0);
588 if (ok) colorBranch (c);
590 /////////////////////////////////////////////////////////////////////
591 } else if (com=="colorSubtree")
593 if (xelection.isEmpty())
595 parser.setError (Aborted,"Nothing selected");
598 parser.setError (Aborted,"Type of selection is not a branch");
599 } else if (parser.checkParCount(1))
601 QColor c=parser.parColor (ok,0);
602 if (ok) colorSubtree (c);
604 /////////////////////////////////////////////////////////////////////
605 } else if (com=="copy")
607 if (xelection.isEmpty())
609 parser.setError (Aborted,"Nothing selected");
612 parser.setError (Aborted,"Type of selection is not a branch");
613 } else if (parser.checkParCount(0))
615 //FIXME missing action for copy
617 /////////////////////////////////////////////////////////////////////
618 } else if (com=="cut")
620 if (xelection.isEmpty())
622 parser.setError (Aborted,"Nothing selected");
623 } else if ( xelection.type()!=Selection::Branch &&
624 xelection.type()!=Selection::MapCenter &&
625 xelection.type()!=Selection::FloatImage )
627 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
628 } else if (parser.checkParCount(0))
632 /////////////////////////////////////////////////////////////////////
633 } else if (com=="delete")
635 if (xelection.isEmpty())
637 parser.setError (Aborted,"Nothing selected");
638 } else if (xelection.type() != Selection::Branch && xelection.type() != Selection::FloatImage )
640 parser.setError (Aborted,"Type of selection is wrong.");
641 } else if (parser.checkParCount(0))
645 /////////////////////////////////////////////////////////////////////
646 } else if (com=="deleteKeepChilds")
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.checkParCount(0))
658 /////////////////////////////////////////////////////////////////////
659 } else if (com=="deleteChilds")
661 if (xelection.isEmpty())
663 parser.setError (Aborted,"Nothing selected");
666 parser.setError (Aborted,"Type of selection is not a branch");
667 } else if (parser.checkParCount(0))
671 /////////////////////////////////////////////////////////////////////
672 } else if (com=="exportASCII")
676 if (parser.parCount()>=2)
677 // Hey, we even have a filename
678 fname=parser.parString(ok,1);
681 parser.setError (Aborted,"Could not read filename");
684 exportASCII (fname,false);
686 /////////////////////////////////////////////////////////////////////
687 } else if (com=="exportImage")
691 if (parser.parCount()>=2)
692 // Hey, we even have a filename
693 fname=parser.parString(ok,1);
696 parser.setError (Aborted,"Could not read filename");
699 QString format="PNG";
700 if (parser.parCount()>2)
702 format=parser.parString(ok,2);
704 exportImage (fname,false,format);
706 /////////////////////////////////////////////////////////////////////
707 } else if (com=="exportXHTML")
711 if (parser.parCount()>=2)
712 // Hey, we even have a filename
713 fname=parser.parString(ok,1);
716 parser.setError (Aborted,"Could not read filename");
719 exportXHTML (fname,false);
721 /////////////////////////////////////////////////////////////////////
722 } else if (com=="exportXML")
726 if (parser.parCount()>=2)
727 // Hey, we even have a filename
728 fname=parser.parString(ok,1);
731 parser.setError (Aborted,"Could not read filename");
734 exportXML (fname,false);
736 /////////////////////////////////////////////////////////////////////
737 } else if (com=="importDir")
739 if (xelection.isEmpty())
741 parser.setError (Aborted,"Nothing selected");
744 parser.setError (Aborted,"Type of selection is not a branch");
745 } else if (parser.checkParCount(1))
747 s=parser.parString(ok,0);
748 if (ok) importDirInt(s);
750 /////////////////////////////////////////////////////////////////////
751 } else if (com=="linkTo")
753 if (xelection.isEmpty())
755 parser.setError (Aborted,"Nothing selected");
758 if (parser.checkParCount(4))
760 // 0 selectstring of parent
761 // 1 num in parent (for branches)
762 // 2,3 x,y of mainbranch or mapcenter
763 s=parser.parString(ok,0);
764 LinkableMapObj *dst=mapCenter->findObjBySelect (s);
767 if (typeid(*dst) == typeid(BranchObj) )
769 // Get number in parent
770 x=parser.parInt (ok,1);
772 selb->linkTo ((BranchObj*)(dst),x);
773 } else if (typeid(*dst) == typeid(MapCenterObj) )
775 selb->linkTo ((BranchObj*)(dst),-1);
776 // Get coordinates of mainbranch
777 x=parser.parInt (ok,2);
780 y=parser.parInt (ok,3);
781 if (ok) selb->move (x,y);
786 } else if ( xelection.type() == Selection::FloatImage)
788 if (parser.checkParCount(1))
790 // 0 selectstring of parent
791 s=parser.parString(ok,0);
792 LinkableMapObj *dst=mapCenter->findObjBySelect (s);
795 if (typeid(*dst) == typeid(BranchObj) ||
796 typeid(*dst) == typeid(MapCenterObj))
797 linkTo (dst->getSelectString());
799 parser.setError (Aborted,"Destination is not a branch");
802 parser.setError (Aborted,"Type of selection is not a floatimage or branch");
803 /////////////////////////////////////////////////////////////////////
804 } else if (com=="loadImage")
806 if (xelection.isEmpty())
808 parser.setError (Aborted,"Nothing selected");
811 parser.setError (Aborted,"Type of selection is not a branch");
812 } else if (parser.checkParCount(1))
814 s=parser.parString(ok,0);
815 if (ok) loadFloatImageInt (s);
817 /////////////////////////////////////////////////////////////////////
818 } else if (com=="moveBranchUp")
820 if (xelection.isEmpty() )
822 parser.setError (Aborted,"Nothing selected");
825 parser.setError (Aborted,"Type of selection is not a branch");
826 } else if (parser.checkParCount(0))
830 /////////////////////////////////////////////////////////////////////
831 } else if (com=="moveBranchDown")
833 if (xelection.isEmpty() )
835 parser.setError (Aborted,"Nothing selected");
838 parser.setError (Aborted,"Type of selection is not a branch");
839 } else if (parser.checkParCount(0))
843 /////////////////////////////////////////////////////////////////////
844 } else if (com=="move")
846 if (xelection.isEmpty() )
848 parser.setError (Aborted,"Nothing selected");
849 } else if ( xelection.type()!=Selection::Branch &&
850 xelection.type()!=Selection::MapCenter &&
851 xelection.type()!=Selection::FloatImage )
853 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
854 } else if (parser.checkParCount(2))
856 x=parser.parInt (ok,0);
859 y=parser.parInt (ok,1);
863 /////////////////////////////////////////////////////////////////////
864 } else if (com=="moveRel")
866 if (xelection.isEmpty() )
868 parser.setError (Aborted,"Nothing selected");
869 } else if ( xelection.type()!=Selection::Selection::Branch &&
870 xelection.type()!=Selection::Selection::MapCenter &&
871 xelection.type()!=Selection::Selection::FloatImage )
873 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
874 } else if (parser.checkParCount(2))
876 x=parser.parInt (ok,0);
879 y=parser.parInt (ok,1);
880 if (ok) moveRel (x,y);
883 /////////////////////////////////////////////////////////////////////
884 } else if (com=="nop")
886 /////////////////////////////////////////////////////////////////////
887 } else if (com=="paste")
889 if (xelection.isEmpty() )
891 parser.setError (Aborted,"Nothing selected");
894 parser.setError (Aborted,"Type of selection is not a branch");
895 } else if (parser.checkParCount(1))
897 x=parser.parInt (ok,0);
898 if (ok) pasteNoSave(x);
900 /////////////////////////////////////////////////////////////////////
901 } else if (com=="qa")
903 if (xelection.isEmpty() )
905 parser.setError (Aborted,"Nothing selected");
908 parser.setError (Aborted,"Type of selection is not a branch");
909 } else if (parser.checkParCount(4))
912 c=parser.parString (ok,0);
915 parser.setError (Aborted,"No comment given");
918 s=parser.parString (ok,1);
921 parser.setError (Aborted,"First parameter is not a string");
924 t=parser.parString (ok,2);
927 parser.setError (Aborted,"Condition is not a string");
930 u=parser.parString (ok,3);
933 parser.setError (Aborted,"Third parameter is not a string");
938 parser.setError (Aborted,"Unknown type: "+s);
943 parser.setError (Aborted,"Unknown operator: "+t);
948 parser.setError (Aborted,"Type of selection is not a branch");
951 if (selb->getHeading() == u)
953 cout << "PASSED: " << c.ascii() << endl;
956 cout << "FAILED: " << c.ascii() << endl;
966 /////////////////////////////////////////////////////////////////////
967 } else if (com=="saveImage")
969 FloatImageObj *fio=xelection.getFloatImage();
972 parser.setError (Aborted,"Type of selection is not an image");
973 } else if (parser.checkParCount(2))
975 s=parser.parString(ok,0);
978 t=parser.parString(ok,1);
979 if (ok) saveFloatImageInt (fio,t,s);
982 /////////////////////////////////////////////////////////////////////
983 } else if (com=="scroll")
985 if (xelection.isEmpty() )
987 parser.setError (Aborted,"Nothing selected");
990 parser.setError (Aborted,"Type of selection is not a branch");
991 } else if (parser.checkParCount(0))
993 if (!scrollBranch (selb))
994 parser.setError (Aborted,"Could not scroll branch");
996 /////////////////////////////////////////////////////////////////////
997 } else if (com=="select")
999 if (parser.checkParCount(1))
1001 s=parser.parString(ok,0);
1004 /////////////////////////////////////////////////////////////////////
1005 } else if (com=="selectLastBranch")
1007 if (xelection.isEmpty() )
1009 parser.setError (Aborted,"Nothing selected");
1012 parser.setError (Aborted,"Type of selection is not a branch");
1013 } else if (parser.checkParCount(0))
1015 BranchObj *bo=selb->getLastBranch();
1017 parser.setError (Aborted,"Could not select last branch");
1021 /////////////////////////////////////////////////////////////////////
1022 } else if (com=="selectLastImage")
1024 if (xelection.isEmpty() )
1026 parser.setError (Aborted,"Nothing selected");
1029 parser.setError (Aborted,"Type of selection is not a branch");
1030 } else if (parser.checkParCount(0))
1032 FloatImageObj *fio=selb->getLastFloatImage();
1034 parser.setError (Aborted,"Could not select last image");
1038 /////////////////////////////////////////////////////////////////////
1039 } else if (com=="setFrameType")
1041 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
1043 parser.setError (Aborted,"Type of selection does not allow setting frame type");
1045 else if (parser.checkParCount(1))
1047 s=parser.parString(ok,0);
1048 if (ok) setFrameType (s);
1050 /////////////////////////////////////////////////////////////////////
1051 } else if (com=="setFramePenColor")
1053 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
1055 parser.setError (Aborted,"Type of selection does not allow setting of pen color");
1057 else if (parser.checkParCount(1))
1059 QColor c=parser.parColor(ok,0);
1060 if (ok) setFramePenColor (c);
1062 /////////////////////////////////////////////////////////////////////
1063 } else if (com=="setFrameBrushColor")
1065 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
1067 parser.setError (Aborted,"Type of selection does not allow setting brush color");
1069 else if (parser.checkParCount(1))
1071 QColor c=parser.parColor(ok,0);
1072 if (ok) setFrameBrushColor (c);
1074 /////////////////////////////////////////////////////////////////////
1075 } else if (com=="setFramePadding")
1077 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
1079 parser.setError (Aborted,"Type of selection does not allow setting frame padding");
1081 else if (parser.checkParCount(1))
1083 x=parser.parInt(ok,0);
1084 if (ok) setFramePadding(x);
1086 /////////////////////////////////////////////////////////////////////
1087 } else if (com=="setFrameBorderWidth")
1089 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
1091 parser.setError (Aborted,"Type of selection does not allow setting frame border width");
1093 else if (parser.checkParCount(1))
1095 x=parser.parInt(ok,0);
1096 if (ok) setFrameBorderWidth (x);
1098 /////////////////////////////////////////////////////////////////////
1099 } else if (com=="setMapAuthor")
1101 if (parser.checkParCount(1))
1103 s=parser.parString(ok,0);
1104 if (ok) setMapAuthor (s);
1106 /////////////////////////////////////////////////////////////////////
1107 } else if (com=="setMapComment")
1109 if (parser.checkParCount(1))
1111 s=parser.parString(ok,0);
1112 if (ok) setMapComment(s);
1114 /////////////////////////////////////////////////////////////////////
1115 } else if (com=="setMapBackgroundColor")
1117 if (xelection.isEmpty() )
1119 parser.setError (Aborted,"Nothing selected");
1120 } else if (! xelection.getBranch() )
1122 parser.setError (Aborted,"Type of selection is not a branch");
1123 } else if (parser.checkParCount(1))
1125 QColor c=parser.parColor (ok,0);
1126 if (ok) setMapBackgroundColor (c);
1128 /////////////////////////////////////////////////////////////////////
1129 } else if (com=="setMapDefLinkColor")
1131 if (xelection.isEmpty() )
1133 parser.setError (Aborted,"Nothing selected");
1136 parser.setError (Aborted,"Type of selection is not a branch");
1137 } else if (parser.checkParCount(1))
1139 QColor c=parser.parColor (ok,0);
1140 if (ok) setMapDefLinkColor (c);
1142 /////////////////////////////////////////////////////////////////////
1143 } else if (com=="setMapLinkStyle")
1145 if (parser.checkParCount(1))
1147 s=parser.parString (ok,0);
1148 if (ok) setMapLinkStyle(s);
1150 /////////////////////////////////////////////////////////////////////
1151 } else if (com=="setHeading")
1153 if (xelection.isEmpty() )
1155 parser.setError (Aborted,"Nothing selected");
1158 parser.setError (Aborted,"Type of selection is not a branch");
1159 } else if (parser.checkParCount(1))
1161 s=parser.parString (ok,0);
1165 /////////////////////////////////////////////////////////////////////
1166 } else if (com=="setHideExport")
1168 if (xelection.isEmpty() )
1170 parser.setError (Aborted,"Nothing selected");
1171 } else if (xelection.type()!=Selection::Branch && xelection.type() != Selection::MapCenter &&xelection.type()!=Selection::FloatImage)
1173 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
1174 } else if (parser.checkParCount(1))
1176 b=parser.parBool(ok,0);
1177 if (ok) setHideExport (b);
1179 /////////////////////////////////////////////////////////////////////
1180 } else if (com=="setIncludeImagesHorizontally")
1182 if (xelection.isEmpty() )
1184 parser.setError (Aborted,"Nothing selected");
1187 parser.setError (Aborted,"Type of selection is not a branch");
1188 } else if (parser.checkParCount(1))
1190 b=parser.parBool(ok,0);
1191 if (ok) setIncludeImagesHor(b);
1193 /////////////////////////////////////////////////////////////////////
1194 } else if (com=="setIncludeImagesVertically")
1196 if (xelection.isEmpty() )
1198 parser.setError (Aborted,"Nothing selected");
1201 parser.setError (Aborted,"Type of selection is not a branch");
1202 } else if (parser.checkParCount(1))
1204 b=parser.parBool(ok,0);
1205 if (ok) setIncludeImagesVer(b);
1207 /////////////////////////////////////////////////////////////////////
1208 } else if (com=="setHideLinkUnselected")
1210 if (xelection.isEmpty() )
1212 parser.setError (Aborted,"Nothing selected");
1213 } else if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
1215 parser.setError (Aborted,"Type of selection does not allow hiding the link");
1216 } else if (parser.checkParCount(1))
1218 b=parser.parBool(ok,0);
1219 if (ok) setHideLinkUnselected(b);
1221 /////////////////////////////////////////////////////////////////////
1222 } else if (com=="setSelectionColor")
1224 if (parser.checkParCount(1))
1226 QColor c=parser.parColor (ok,0);
1227 if (ok) setSelectionColorInt (c);
1229 /////////////////////////////////////////////////////////////////////
1230 } else if (com=="setURL")
1232 if (xelection.isEmpty() )
1234 parser.setError (Aborted,"Nothing selected");
1237 parser.setError (Aborted,"Type of selection is not a branch");
1238 } else if (parser.checkParCount(1))
1240 s=parser.parString (ok,0);
1243 /////////////////////////////////////////////////////////////////////
1244 } else if (com=="setVymLink")
1246 if (xelection.isEmpty() )
1248 parser.setError (Aborted,"Nothing selected");
1251 parser.setError (Aborted,"Type of selection is not a branch");
1252 } else if (parser.checkParCount(1))
1254 s=parser.parString (ok,0);
1255 if (ok) setVymLinkInt(s);
1258 /////////////////////////////////////////////////////////////////////
1259 else if (com=="setFlag")
1261 if (xelection.isEmpty() )
1263 parser.setError (Aborted,"Nothing selected");
1266 parser.setError (Aborted,"Type of selection is not a branch");
1267 } else if (parser.checkParCount(1))
1269 s=parser.parString(ok,0);
1272 selb->activateStandardFlag(s);
1273 selb->updateFlagsToolbar();
1276 /////////////////////////////////////////////////////////////////////
1277 } else if (com=="setFrameType")
1279 if (xelection.isEmpty() )
1281 parser.setError (Aborted,"Nothing selected");
1284 parser.setError (Aborted,"Type of selection is not a branch");
1285 } else if (parser.checkParCount(1))
1287 s=parser.parString(ok,0);
1291 /////////////////////////////////////////////////////////////////////
1292 } else if (com=="toggleFlag")
1294 if (xelection.isEmpty() )
1296 parser.setError (Aborted,"Nothing selected");
1299 parser.setError (Aborted,"Type of selection is not a branch");
1300 } else if (parser.checkParCount(1))
1302 s=parser.parString(ok,0);
1305 selb->toggleStandardFlag(s);
1306 selb->updateFlagsToolbar();
1309 /////////////////////////////////////////////////////////////////////
1310 } else if (com=="unscroll")
1312 if (xelection.isEmpty() )
1314 parser.setError (Aborted,"Nothing selected");
1317 parser.setError (Aborted,"Type of selection is not a branch");
1318 } else if (parser.checkParCount(0))
1320 if (!unscrollBranch (selb))
1321 parser.setError (Aborted,"Could not unscroll branch");
1323 /////////////////////////////////////////////////////////////////////
1324 } else if (com=="unscrollChilds")
1326 if (xelection.isEmpty() )
1328 parser.setError (Aborted,"Nothing selected");
1331 parser.setError (Aborted,"Type of selection is not a branch");
1332 } else if (parser.checkParCount(0))
1336 /////////////////////////////////////////////////////////////////////
1337 } else if (com=="unsetFlag")
1339 if (xelection.isEmpty() )
1341 parser.setError (Aborted,"Nothing selected");
1344 parser.setError (Aborted,"Type of selection is not a branch");
1345 } else if (parser.checkParCount(1))
1347 s=parser.parString(ok,0);
1350 selb->deactivateStandardFlag(s);
1351 selb->updateFlagsToolbar();
1355 parser.setError (Aborted,"Unknown command");
1358 if (parser.errorLevel()==NoError)
1361 mapCenter->reposition();
1365 // TODO Error handling
1366 qWarning("MapEditor::parseAtom: Error!");
1367 qWarning(parser.errorMessage());
1371 void MapEditor::runScript (QString script)
1373 parser.setScript (script);
1375 while (parser.next() )
1376 parseAtom(parser.getAtom());
1379 bool MapEditor::isDefault()
1384 bool MapEditor::hasChanged()
1389 void MapEditor::setChanged()
1392 autosaveTimer->start(settings.value("/mapeditor/autosave/ms/",300000).toInt());
1400 void MapEditor::closeMap()
1402 // Unselect before disabling the toolbar actions
1403 if (!xelection.isEmpty() ) xelection.unselect();
1411 void MapEditor::setFilePath(QString fpath, QString destname)
1413 if (fpath.isEmpty() || fpath=="")
1420 filePath=fpath; // becomes absolute path
1421 fileName=fpath; // gets stripped of path
1422 destPath=destname; // needed for vymlinks
1424 // If fpath is not an absolute path, complete it
1425 filePath=QDir(fpath).absPath();
1426 fileDir=filePath.left (1+filePath.findRev ("/"));
1428 // Set short name, too. Search from behind:
1429 int i=fileName.findRev("/");
1430 if (i>=0) fileName=fileName.remove (0,i+1);
1432 // Forget the .vym (or .xml) for name of map
1433 mapName=fileName.left(fileName.findRev(".",-1,true) );
1437 void MapEditor::setFilePath(QString fpath)
1439 setFilePath (fpath,fpath);
1442 QString MapEditor::getFilePath()
1447 QString MapEditor::getFileName()
1452 QString MapEditor::getMapName()
1457 QString MapEditor::getDestPath()
1462 ErrorCode MapEditor::load (QString fname, LoadMode lmode)
1464 ErrorCode err=success;
1468 if (xelection.isEmpty() ) xelection.unselect();
1471 mapCenter->setMapEditor(this);
1472 // (map state is set later at end of load...)
1475 BranchObj *bo=xelection.getBranch();
1476 if (!bo) return aborted;
1477 if (lmode==ImportAdd)
1478 saveStateChangingPart(
1481 QString("addMapInsert (%1)").arg(fname),
1482 QString("Add map %1 to %2").arg(fname).arg(getName(bo)));
1484 saveStateChangingPart(
1487 QString("addMapReplace(%1)").arg(fname),
1488 QString("Add map %1 to %2").arg(fname).arg(getName(bo)));
1492 mapBuilderHandler handler;
1493 QFile file( fname );
1495 // I am paranoid: file should exist anyway
1496 // according to check in mainwindow.
1497 if (!file.exists() )
1499 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
1500 tr("Couldn't open map " +fname)+".");
1504 bool blockSaveStateOrg=blockSaveState;
1505 blockReposition=true;
1506 blockSaveState=true;
1507 QXmlInputSource source( file);
1508 QXmlSimpleReader reader;
1509 reader.setContentHandler( &handler );
1510 reader.setErrorHandler( &handler );
1511 handler.setMapEditor( this );
1514 // We need to set the tmpDir in order to load files with rel. path
1515 QString tmpdir= fname.left(fname.findRev("/",-1));
1516 handler.setTmpDir (tmpdir);
1517 handler.setInputFile (file.name());
1518 handler.setLoadMode (lmode);
1519 bool ok = reader.parse( source );
1520 blockReposition=false;
1521 blockSaveState=blockSaveStateOrg;
1525 mapCenter->reposition();
1532 autosaveTimer->stop();
1536 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
1537 tr( handler.errorProtocol() ) );
1539 // Still return "success": the map maybe at least
1540 // partially read by the parser
1547 int MapEditor::save (const SaveMode &savemode)
1551 // Create mapName and fileDir
1552 makeSubDirs (fileDir);
1556 fname=mapName+".xml";
1558 // use name given by user, even if he chooses .doc
1563 if (savemode==CompleteMap || xelection.isEmpty())
1564 saveFile=saveToDir (fileDir,mapName+"-",true,QPointF(),NULL);
1567 // TODO take care of multiselections
1568 if (xelection.type()==Selection::FloatImage)
1571 saveFile=saveToDir (fileDir,mapName+"-",true,QPointF(),xelection.getBranch());
1574 if (!saveStringToDisk(fileDir+fname,saveFile))
1581 autosaveTimer->stop();
1588 void MapEditor::setZipped (bool z)
1593 bool MapEditor::saveZipped ()
1598 void MapEditor::print()
1602 printer = new QPrinter;
1603 printer->setColorMode (QPrinter::Color);
1604 printer->setPrinterName (settings.value("/mainwindow/printerName",printer->printerName()).toString());
1605 printer->setOutputFormat((QPrinter::OutputFormat)settings.value("/mainwindow/printerFormat",printer->outputFormat()).toInt());
1606 printer->setOutputFileName(settings.value("/mainwindow/printerFileName",printer->outputFileName()).toString());
1609 QRectF totalBBox=mapCenter->getTotalBBox();
1611 // Try to set orientation automagically
1612 // Note: Interpretation of generated postscript is amibiguous, if
1613 // there are problems with landscape mode, see
1614 // http://sdb.suse.de/de/sdb/html/jsmeix_print-cups-landscape-81.html
1616 if (totalBBox.width()>totalBBox.height())
1617 // recommend landscape
1618 printer->setOrientation (QPrinter::Landscape);
1620 // recommend portrait
1621 printer->setOrientation (QPrinter::Portrait);
1623 if ( printer->setup(this) )
1624 // returns false, if printing is canceled
1626 QPainter pp(printer);
1628 pp.setRenderHint(QPainter::Antialiasing,true);
1630 // Don't print the visualisation of selection
1631 xelection.unselect();
1633 QRectF mapRect=totalBBox;
1634 QGraphicsRectItem *frame=NULL;
1638 // Print frame around map
1639 mapRect.setRect (totalBBox.x()-10, totalBBox.y()-10,
1640 totalBBox.width()+20, totalBBox.height()+20);
1641 frame=mapScene->addRect (mapRect, QPen(Qt::black),QBrush(Qt::NoBrush));
1642 frame->setZValue(0);
1647 double paperAspect = (double)printer->width() / (double)printer->height();
1648 double mapAspect = (double)mapRect.width() / (double)mapRect.height();
1650 if (mapAspect>=paperAspect)
1652 // Fit horizontally to paper width
1653 //pp.setViewport(0,0, printer->width(),(int)(printer->width()/mapAspect) );
1654 viewBottom=(int)(printer->width()/mapAspect);
1657 // Fit vertically to paper height
1658 //pp.setViewport(0,0,(int)(printer->height()*mapAspect),printer->height());
1659 viewBottom=printer->height();
1664 // Print footer below map
1666 font.setPointSize(10);
1668 QRectF footerBox(0,viewBottom,printer->width(),15);
1669 pp.drawText ( footerBox,Qt::AlignLeft,"VYM - " +fileName);
1670 pp.drawText ( footerBox, Qt::AlignRight, QDate::currentDate().toString(Qt::TextDate));
1674 QRectF (0,0,printer->width(),printer->height()-15),
1675 QRectF(mapRect.x(),mapRect.y(),mapRect.width(),mapRect.height())
1678 // Viewport has paper dimension
1679 if (frame) delete (frame);
1681 // Restore selection
1682 xelection.reselect();
1684 // Save settings in vymrc
1685 settings.writeEntry("/mainwindow/printerName",printer->printerName());
1686 settings.writeEntry("/mainwindow/printerFormat",printer->outputFormat());
1687 settings.writeEntry("/mainwindow/printerFileName",printer->outputFileName());
1691 void MapEditor::setAntiAlias (bool b)
1693 setRenderHint(QPainter::Antialiasing,b);
1696 void MapEditor::setSmoothPixmap(bool b)
1698 setRenderHint(QPainter::SmoothPixmapTransform,b);
1701 QPixmap MapEditor::getPixmap()
1703 QRectF mapRect=mapCenter->getTotalBBox();
1704 QPixmap pix((int)mapRect.width()+2,(int)mapRect.height()+2);
1707 pp.setRenderHints(renderHints());
1709 // Don't print the visualisation of selection
1710 xelection.unselect();
1712 mapScene->render ( &pp,
1713 QRectF(0,0,mapRect.width()+2,mapRect.height()+2),
1714 QRectF(mapRect.x(),mapRect.y(),mapRect.width(),mapRect.height() ));
1716 // Restore selection
1717 xelection.reselect();
1722 void MapEditor::setHideTmpMode (BranchObj::HideTmpMode mode)
1725 mapCenter->setHideTmp (hidemode);
1726 mapCenter->reposition();
1730 BranchObj::HideTmpMode MapEditor::getHideTmpMode()
1735 void MapEditor::setExportMode (bool b)
1737 // should be called before and after exports
1738 // depending on the settings
1739 if (b && settings.value("/export/useHideExport","yes")=="yes")
1740 setHideTmpMode (BranchObj::HideExport);
1742 setHideTmpMode (BranchObj::HideNone);
1745 void MapEditor::exportASCII(QString fname,bool askName)
1748 ex.setMapCenter(mapCenter);
1750 ex.setFile (mapName+".txt");
1756 //ex.addFilter ("TXT (*.txt)");
1757 ex.setDir(lastImageDir);
1758 //ex.setCaption(vymName+ " -" +tr("Export as ASCII")+" "+tr("(still experimental)"));
1763 setExportMode(true);
1765 setExportMode(false);
1769 void MapEditor::exportImage(QString fname, bool askName, QString format)
1773 fname=mapName+".png";
1780 QFileDialog *fd=new QFileDialog (this);
1781 fd->setCaption (tr("Export map as image"));
1782 fd->setDirectory (lastImageDir);
1783 fd->setFileMode(QFileDialog::AnyFile);
1784 fd->setFilters (imageIO.getFilters() );
1787 fl=fd->selectedFiles();
1789 format=imageIO.getType(fd->selectedFilter());
1793 setExportMode (true);
1794 QPixmap pix (getPixmap());
1795 pix.save(fname, format);
1796 setExportMode (false);
1799 void MapEditor::exportOOPresentation(const QString &fn, const QString &cf)
1803 ex.setMapCenter(mapCenter);
1804 if (ex.setConfigFile(cf))
1806 setExportMode (true);
1807 ex.exportPresentation();
1808 setExportMode (false);
1812 void MapEditor::exportXHTML (const QString &dir, bool askForName)
1814 ExportXHTMLDialog dia(this);
1815 dia.setFilePath (filePath );
1816 dia.setMapName (mapName );
1818 if (dir!="") dia.setDir (dir);
1824 if (dia.exec()!=QDialog::Accepted)
1828 QDir d (dia.getDir());
1829 // Check, if warnings should be used before overwriting
1830 // the output directory
1831 if (d.exists() && d.count()>0)
1834 warn.showCancelButton (true);
1835 warn.setText(QString(
1836 "The directory %1 is not empty.\n"
1837 "Do you risk to overwrite some of its contents?").arg(d.path() ));
1838 warn.setCaption("Warning: Directory not empty");
1839 warn.setShowAgainName("mainwindow/overwrite-dir-xhtml");
1841 if (warn.exec()!=QDialog::Accepted) ok=false;
1848 exportXML (dia.getDir(),false );
1849 dia.doExport(mapName );
1850 //if (dia.hasChanged()) setChanged();
1854 void MapEditor::exportXML(QString dir, bool askForName)
1858 dir=browseDirectory(this,tr("Export XML to directory"));
1859 if (dir =="" && !reallyWriteDirectory(dir) )
1863 // Hide stuff during export, if settings want this
1864 setExportMode (true);
1866 // Create subdirectories
1869 // write to directory
1870 QString saveFile=saveToDir (dir,mapName+"-",true,mapCenter->getTotalBBox().topLeft() ,NULL);
1873 file.setName ( dir + "/"+mapName+".xml");
1874 if ( !file.open( QIODevice::WriteOnly ) )
1876 // This should neverever happen
1877 QMessageBox::critical (0,tr("Critical Export Error"),tr("MapEditor::exportXML couldn't open %1").arg(file.name()));
1881 // Write it finally, and write in UTF8, no matter what
1882 QTextStream ts( &file );
1883 ts.setEncoding (QTextStream::UnicodeUTF8);
1887 // Now write image, too
1888 exportImage (dir+"/images/"+mapName+".png",false,"PNG");
1890 setExportMode (false);
1893 void MapEditor::clear()
1895 xelection.unselect();
1899 void MapEditor::copy()
1901 LinkableMapObj *sel=xelection.single();
1904 if (redosAvail == 0)
1907 QString s=sel->getSelectString();
1908 saveState (PartOfMap, s, "nop ()", s, "copy ()","Copy selection to clipboard",sel );
1909 curClipboard=curStep;
1912 // Copy also to global clipboard, because we are at last step in history
1913 QString bakMapName=QDir::convertSeparators (QString("history-%1").arg(curStep));
1914 QString bakMapDir=QDir::convertSeparators (tmpMapDir +"/"+bakMapName);
1915 copyDir (bakMapDir,clipboardDir );
1917 clipboardEmpty=false;
1922 void MapEditor::redo()
1924 // Can we undo at all?
1925 if (redosAvail<1) return;
1927 bool blockSaveStateOrg=blockSaveState;
1928 blockSaveState=true;
1932 if (undosAvail<stepsTotal) undosAvail++;
1934 if (curStep>stepsTotal) curStep=1;
1935 QString undoCommand= undoSet.readEntry (QString("/history/step-%1/undoCommand").arg(curStep));
1936 QString undoSelection=undoSet.readEntry (QString("/history/step-%1/undoSelection").arg(curStep));
1937 QString redoCommand= undoSet.readEntry (QString("/history/step-%1/redoCommand").arg(curStep));
1938 QString redoSelection=undoSet.readEntry (QString("/history/step-%1/redoSelection").arg(curStep));
1939 QString comment=undoSet.readEntry (QString("/history/step-%1/comment").arg(curStep));
1940 QString version=undoSet.readEntry ("/history/version");
1942 if (!checkVersion(version))
1943 QMessageBox::warning(0,tr("Warning"),
1944 tr("Version %1 of saved undo/redo data\ndoes not match current vym version %2.").arg(version).arg(vymVersion));
1947 // Find out current undo directory
1948 QString bakMapDir=QDir::convertSeparators (QString(tmpMapDir+"/undo-%1").arg(curStep));
1952 cout << "ME::redo() begin\n";
1953 cout << " undosAvail="<<undosAvail<<endl;
1954 cout << " redosAvail="<<redosAvail<<endl;
1955 cout << " curStep="<<curStep<<endl;
1956 cout << " ---------------------------"<<endl;
1957 cout << " comment="<<comment.toStdString()<<endl;
1958 cout << " undoCom="<<undoCommand.toStdString()<<endl;
1959 cout << " undoSel="<<undoSelection.toStdString()<<endl;
1960 cout << " redoCom="<<redoCommand.toStdString()<<endl;
1961 cout << " redoSel="<<redoSelection.toStdString()<<endl;
1962 cout << " ---------------------------"<<endl<<endl;
1965 // select object before redo
1966 if (!redoSelection.isEmpty())
1967 select (redoSelection);
1970 parseAtom (redoCommand);
1971 mapCenter->reposition();
1973 blockSaveState=blockSaveStateOrg;
1975 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
1976 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
1977 undoSet.setEntry ("/history/curStep",QString::number(curStep));
1978 undoSet.writeSettings(histPath);
1980 mainWindow->updateHistory (undoSet);
1983 /* TODO remove testing
1984 cout << "ME::redo() end\n";
1985 cout << " undosAvail="<<undosAvail<<endl;
1986 cout << " redosAvail="<<redosAvail<<endl;
1987 cout << " curStep="<<curStep<<endl;
1988 cout << " ---------------------------"<<endl<<endl;
1994 bool MapEditor::isRedoAvailable()
1996 if (undoSet.readNumEntry("/history/redosAvail",0)>0)
2002 void MapEditor::undo()
2004 // Can we undo at all?
2005 if (undosAvail<1) return;
2007 mainWindow->statusMessage (tr("Autosave disabled during undo."));
2009 bool blockSaveStateOrg=blockSaveState;
2010 blockSaveState=true;
2012 QString undoCommand= undoSet.readEntry (QString("/history/step-%1/undoCommand").arg(curStep));
2013 QString undoSelection=undoSet.readEntry (QString("/history/step-%1/undoSelection").arg(curStep));
2014 QString redoCommand= undoSet.readEntry (QString("/history/step-%1/redoCommand").arg(curStep));
2015 QString redoSelection=undoSet.readEntry (QString("/history/step-%1/redoSelection").arg(curStep));
2016 QString comment=undoSet.readEntry (QString("/history/step-%1/comment").arg(curStep));
2017 QString version=undoSet.readEntry ("/history/version");
2019 if (!checkVersion(version))
2020 QMessageBox::warning(0,tr("Warning"),
2021 tr("Version %1 of saved undo/redo data\ndoes not match current vym version %2.").arg(version).arg(vymVersion));
2023 // Find out current undo directory
2024 QString bakMapDir=QDir::convertSeparators (QString(tmpMapDir+"/undo-%1").arg(curStep));
2026 // select object before undo
2027 if (!undoSelection.isEmpty())
2028 select (undoSelection);
2032 cout << "ME::undo() begin\n";
2033 cout << " undosAvail="<<undosAvail<<endl;
2034 cout << " redosAvail="<<redosAvail<<endl;
2035 cout << " curStep="<<curStep<<endl;
2036 cout << " ---------------------------"<<endl;
2037 cout << " comment="<<comment.toStdString()<<endl;
2038 cout << " undoCom="<<undoCommand.toStdString()<<endl;
2039 cout << " undoSel="<<undoSelection.toStdString()<<endl;
2040 cout << " redoCom="<<redoCommand.toStdString()<<endl;
2041 cout << " redoSel="<<redoSelection.toStdString()<<endl;
2042 cout << " ---------------------------"<<endl<<endl;
2044 parseAtom (undoCommand);
2045 mapCenter->reposition();
2049 if (curStep<1) curStep=stepsTotal;
2053 blockSaveState=blockSaveStateOrg;
2054 /* TODO remove testing
2055 cout << "ME::undo() end\n";
2056 cout << " undosAvail="<<undosAvail<<endl;
2057 cout << " redosAvail="<<redosAvail<<endl;
2058 cout << " curStep="<<curStep<<endl;
2059 cout << " ---------------------------"<<endl<<endl;
2062 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
2063 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
2064 undoSet.setEntry ("/history/curStep",QString::number(curStep));
2065 undoSet.writeSettings(histPath);
2067 mainWindow->updateHistory (undoSet);
2070 ensureSelectionVisible();
2073 bool MapEditor::isUndoAvailable()
2075 if (undoSet.readNumEntry("/history/undosAvail",0)>0)
2081 void MapEditor::gotoHistoryStep (int i)
2083 // Restore variables
2084 int undosAvail=undoSet.readNumEntry (QString("/history/undosAvail"));
2085 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
2087 if (i<0) i=undosAvail+redosAvail;
2089 // Clicking above current step makes us undo things
2092 for (int j=0; j<undosAvail-i; j++) undo();
2095 // Clicking below current step makes us redo things
2097 for (int j=undosAvail; j<i; j++)
2099 cout << "redo "<<j<<"/"<<undosAvail<<" i="<<i<<endl;
2103 // And ignore clicking the current row ;-)
2106 void MapEditor::addMapReplaceInt(const QString &undoSel, const QString &path)
2108 QString pathDir=path.left(path.findRev("/"));
2114 // We need to parse saved XML data
2115 mapBuilderHandler handler;
2116 QXmlInputSource source( file);
2117 QXmlSimpleReader reader;
2118 reader.setContentHandler( &handler );
2119 reader.setErrorHandler( &handler );
2120 handler.setMapEditor( this );
2121 handler.setTmpDir ( pathDir ); // needed to load files with rel. path
2122 if (undoSel.isEmpty())
2126 handler.setLoadMode (NewMap);
2130 handler.setLoadMode (ImportReplace);
2132 blockReposition=true;
2133 bool ok = reader.parse( source );
2134 blockReposition=false;
2137 // This should never ever happen
2138 QMessageBox::critical( 0, tr( "Critical Parse Error while reading %1").arg(path),
2139 handler.errorProtocol());
2142 QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
2145 void MapEditor::addMapInsertInt (const QString &path, int pos)
2147 BranchObj *sel=xelection.getBranch();
2150 QString pathDir=path.left(path.findRev("/"));
2156 // We need to parse saved XML data
2157 mapBuilderHandler handler;
2158 QXmlInputSource source( file);
2159 QXmlSimpleReader reader;
2160 reader.setContentHandler( &handler );
2161 reader.setErrorHandler( &handler );
2162 handler.setMapEditor( this );
2163 handler.setTmpDir ( pathDir ); // needed to load files with rel. path
2164 handler.setLoadMode (ImportAdd);
2165 blockReposition=true;
2166 bool ok = reader.parse( source );
2167 blockReposition=false;
2170 // This should never ever happen
2171 QMessageBox::critical( 0, tr( "Critical Parse Error while reading %1").arg(path),
2172 handler.errorProtocol());
2175 sel->getLastBranch()->linkTo (sel,pos);
2177 QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
2181 void MapEditor::pasteNoSave(const int &n)
2183 bool old=blockSaveState;
2184 blockSaveState=true;
2185 if (redosAvail > 0 || n!=0)
2187 // Use the "historical" buffer
2188 QString bakMapName=QDir::convertSeparators (QString("history-%1").arg(n));
2189 QString bakMapDir=QDir::convertSeparators (tmpMapDir +"/"+bakMapName);
2190 load (bakMapDir+"/"+clipboardFile,ImportAdd);
2192 // Use the global buffer
2193 load (clipboardDir+"/"+clipboardFile,ImportAdd);
2197 void MapEditor::paste()
2199 BranchObj *sel=xelection.getBranch();
2202 saveStateChangingPart(
2205 QString ("paste (%1)").arg(curClipboard),
2206 QString("Paste to %1").arg( getName(sel))
2209 mapCenter->reposition();
2213 void MapEditor::cut()
2215 LinkableMapObj *sel=xelection.single();
2216 if ( sel && (xelection.type() == Selection::Branch ||
2217 xelection.type()==Selection::MapCenter ||
2218 xelection.type()==Selection::FloatImage))
2220 /* No savestate! savestate is called in cutNoSave
2221 saveStateChangingPart(
2225 QString("Cut %1").arg(getName(sel ))
2230 mapCenter->reposition();
2234 void MapEditor::move(const int &x, const int &y)
2236 LinkableMapObj *sel=xelection.single();
2239 QString ps=qpointfToString (sel->getAbsPos());
2240 QString s=xelection.single()->getSelectString();
2243 s, "move "+qpointfToString (QPointF (x,y)),
2244 QString("Move %1 to %2").arg(getName(sel)).arg(ps));
2246 mapCenter->reposition();
2252 void MapEditor::moveRel (const int &x, const int &y)
2254 LinkableMapObj *sel=xelection.single();
2257 QString ps=qpointfToString (sel->getRelPos());
2258 QString s=sel->getSelectString();
2261 s, "moveRel "+qpointfToString (QPointF (x,y)),
2262 QString("Move %1 to relativ position %2").arg(getName(sel)).arg(ps));
2263 ((OrnamentedObj*)sel)->move2RelPos (x,y);
2264 mapCenter->reposition();
2270 void MapEditor::moveBranchUp()
2272 BranchObj* bo=xelection.getBranch();
2276 if (!bo->canMoveBranchUp()) return;
2277 par=(BranchObj*)(bo->getParObj());
2278 BranchObj *obo=par->moveBranchUp (bo); // bo will be the one below selection
2279 saveState (bo->getSelectString(),"moveBranchDown ()",obo->getSelectString(),"moveBranchUp ()",QString("Move up %1").arg(getName(bo)));
2280 mapCenter->reposition();
2283 ensureSelectionVisible();
2287 void MapEditor::moveBranchDown()
2289 BranchObj* bo=xelection.getBranch();
2293 if (!bo->canMoveBranchDown()) return;
2294 par=(BranchObj*)(bo->getParObj());
2295 BranchObj *obo=par->moveBranchDown(bo); // bo will be the one above selection
2296 saveState(bo->getSelectString(),"moveBranchUp ()",obo->getSelectString(),"moveBranchDown ()",QString("Move down %1").arg(getName(bo)));
2297 mapCenter->reposition();
2300 ensureSelectionVisible();
2304 void MapEditor::linkTo(const QString &dstString)
2306 FloatImageObj *fio=xelection.getFloatImage();
2309 BranchObj *dst=(BranchObj*)(mapCenter->findObjBySelect(dstString));
2310 if (dst && (typeid(*dst)==typeid (BranchObj) ||
2311 typeid(*dst)==typeid (MapCenterObj)))
2313 LinkableMapObj *dstPar=dst->getParObj();
2314 QString parString=dstPar->getSelectString();
2315 QString fioPreSelectString=fio->getSelectString();
2316 QString fioPreParentSelectString=fio->getParObj()->getSelectString();
2317 ((BranchObj*)(dst))->addFloatImage (fio);
2318 xelection.unselect();
2319 ((BranchObj*)(fio->getParObj()))->removeFloatImage (fio);
2320 fio=((BranchObj*)(dst))->getLastFloatImage();
2323 xelection.select(fio);
2325 fio->getSelectString(),
2326 QString("linkTo (\"%1\")").arg(fioPreParentSelectString),
2328 QString ("linkTo (\"%1\")").arg(dstString),
2329 QString ("Link floatimage to %1").arg(getName(dst)));
2334 QString MapEditor::getHeading(bool &ok, QPoint &p)
2336 BranchObj *bo=xelection.getBranch();
2340 p=mapFromScene(bo->getAbsPos());
2341 return bo->getHeading();
2347 void MapEditor::setHeading(const QString &s)
2349 BranchObj *sel=xelection.getBranch();
2354 "setHeading (\""+sel->getHeading()+"\")",
2356 "setHeading (\""+s+"\")",
2357 QString("Set heading of %1 to \"%2\"").arg(getName(sel)).arg(s) );
2358 sel->setHeading(s );
2359 mapCenter->reposition();
2361 ensureSelectionVisible();
2365 void MapEditor::setHeadingInt(const QString &s)
2367 BranchObj *bo=xelection.getBranch();
2371 mapCenter->reposition();
2373 ensureSelectionVisible();
2377 void MapEditor::setVymLinkInt (const QString &s)
2379 // Internal function, no saveState needed
2380 BranchObj *bo=xelection.getBranch();
2384 mapCenter->reposition();
2387 ensureSelectionVisible();
2391 BranchObj* MapEditor::addNewBranchInt(int num)
2393 // Depending on pos:
2394 // -3 insert in childs of parent above selection
2395 // -2 add branch to selection
2396 // -1 insert in childs of parent below selection
2397 // 0..n insert in childs of parent at pos
2398 BranchObj *newbo=NULL;
2399 BranchObj *bo=xelection.getBranch();
2404 // save scroll state. If scrolled, automatically select
2405 // new branch in order to tmp unscroll parent...
2406 return bo->addBranch();
2411 bo=(BranchObj*)bo->getParObj();
2415 bo=(BranchObj*)bo->getParObj();
2418 newbo=bo->insertBranch(num);
2423 BranchObj* MapEditor::addNewBranch(int pos)
2425 // Different meaning than num in addNewBranchInt!
2429 BranchObj *bo = xelection.getBranch();
2430 BranchObj *newbo=NULL;
2434 setCursor (Qt::ArrowCursor);
2436 newbo=addNewBranchInt (pos-2);
2444 QString ("addBranch (%1)").arg(pos-2),
2445 QString ("Add new branch to %1").arg(getName(bo)));
2447 mapCenter->reposition();
2455 BranchObj* MapEditor::addNewBranchBefore()
2457 BranchObj *newbo=NULL;
2458 BranchObj *bo = xelection.getBranch();
2459 if (bo && xelection.type()==Selection::Branch)
2460 // We accept no MapCenterObj here, so we _have_ a parent
2462 QPointF p=bo->getRelPos();
2465 BranchObj *parbo=(BranchObj*)(bo->getParObj());
2467 // add below selection
2468 newbo=parbo->insertBranch(bo->getNum()+1);
2471 newbo->move2RelPos (p);
2473 // Move selection to new branch
2474 bo->linkTo (newbo,-1);
2476 saveState (newbo, "deleteKeepChilds ()", newbo, "addBranchBefore ()",
2477 QString ("Add branch before %1").arg(getName(bo)));
2479 mapCenter->reposition();
2486 void MapEditor::deleteSelection()
2488 BranchObj *bo = xelection.getBranch();
2489 if (bo && xelection.type()==Selection::Branch)
2491 BranchObj* par=(BranchObj*)(bo->getParObj());
2492 xelection.unselect();
2493 saveStateRemovingPart (bo, QString ("Delete %1").arg(getName(bo)));
2494 par->removeBranch(bo);
2495 xelection.select (par);
2496 ensureSelectionVisible();
2497 mapCenter->reposition();
2502 FloatImageObj *fio=xelection.getFloatImage();
2505 BranchObj* par=(BranchObj*)(fio->getParObj());
2506 saveStateChangingPart(
2510 QString("Delete %1").arg(getName(fio))
2512 xelection.unselect();
2513 par->removeFloatImage(fio);
2514 xelection.select (par);
2515 mapCenter->reposition();
2517 ensureSelectionVisible();
2522 LinkableMapObj* MapEditor::getSelection()
2524 return xelection.single();
2527 BranchObj* MapEditor::getSelectedBranch()
2529 return xelection.getBranch();
2532 FloatImageObj* MapEditor::getSelectedFloatImage()
2534 return xelection.getFloatImage();
2537 void MapEditor::unselect()
2539 xelection.unselect();
2542 void MapEditor::reselect()
2544 xelection.reselect();
2547 bool MapEditor::select (const QString &s)
2549 LinkableMapObj *lmo=mapCenter->findObjBySelect(s);
2551 // Finally select the found object
2554 xelection.unselect();
2555 xelection.select(lmo);
2557 ensureSelectionVisible();
2563 QString MapEditor::getSelectString()
2565 return xelection.getSelectString();
2568 void MapEditor::selectInt (LinkableMapObj *lmo)
2570 if (lmo && xelection.single()!= lmo && isSelectBlocked()==false )
2572 xelection.select(lmo);
2577 void MapEditor::selectNextBranchInt()
2579 // Increase number of branch
2580 LinkableMapObj *sel=xelection.single();
2583 QString s=sel->getSelectString();
2589 part=s.section(",",-1);
2591 num=part.right(part.length() - 3);
2593 s=s.left (s.length() -num.length());
2596 num=QString ("%1").arg(num.toUInt()+1);
2600 // Try to select this one
2601 if (select (s)) return;
2603 // We have no direct successor,
2604 // try to increase the parental number in order to
2605 // find a successor with same depth
2607 int d=xelection.single()->getDepth();
2612 while (!found && d>0)
2614 s=s.section (",",0,d-1);
2615 // replace substring of current depth in s with "1"
2616 part=s.section(",",-1);
2618 num=part.right(part.length() - 3);
2622 // increase number of parent
2623 num=QString ("%1").arg(num.toUInt()+1);
2624 s=s.section (",",0,d-2) + ","+ typ+num;
2627 // Special case, look at orientation
2628 if (xelection.single()->getOrientation()==LinkableMapObj::RightOfCenter)
2629 num=QString ("%1").arg(num.toUInt()+1);
2631 num=QString ("%1").arg(num.toUInt()-1);
2636 // pad to oldDepth, select the first branch for each depth
2637 for (i=d;i<oldDepth;i++)
2642 if ( xelection.getBranch()->countBranches()>0)
2650 // try to select the freshly built string
2658 void MapEditor::selectPrevBranchInt()
2660 // Decrease number of branch
2661 BranchObj *bo=xelection.getBranch();
2664 QString s=bo->getSelectString();
2670 part=s.section(",",-1);
2672 num=part.right(part.length() - 3);
2674 s=s.left (s.length() -num.length());
2676 int n=num.toInt()-1;
2679 num=QString ("%1").arg(n);
2682 // Try to select this one
2683 if (n>=0 && select (s)) return;
2685 // We have no direct precessor,
2686 // try to decrease the parental number in order to
2687 // find a precessor with same depth
2689 int d=xelection.single()->getDepth();
2694 while (!found && d>0)
2696 s=s.section (",",0,d-1);
2697 // replace substring of current depth in s with "1"
2698 part=s.section(",",-1);
2700 num=part.right(part.length() - 3);
2704 // decrease number of parent
2705 num=QString ("%1").arg(num.toInt()-1);
2706 s=s.section (",",0,d-2) + ","+ typ+num;
2709 // Special case, look at orientation
2710 if (xelection.single()->getOrientation()==LinkableMapObj::RightOfCenter)
2711 num=QString ("%1").arg(num.toInt()-1);
2713 num=QString ("%1").arg(num.toInt()+1);
2718 // pad to oldDepth, select the last branch for each depth
2719 for (i=d;i<oldDepth;i++)
2723 if ( xelection.getBranch()->countBranches()>0)
2724 s+=",bo:"+ QString ("%1").arg( xelection.getBranch()->countBranches()-1 );
2731 // try to select the freshly built string
2739 void MapEditor::selectUpperBranch()
2741 if (isSelectBlocked() ) return;
2743 BranchObj *bo=xelection.getBranch();
2744 if (bo && xelection.type()==Selection::Branch)
2746 if (bo->getOrientation()==LinkableMapObj::RightOfCenter)
2747 selectPrevBranchInt();
2749 if (bo->getDepth()==1)
2750 selectNextBranchInt();
2752 selectPrevBranchInt();
2756 void MapEditor::selectLowerBranch()
2758 if (isSelectBlocked() ) return;
2760 BranchObj *bo=xelection.getBranch();
2761 if (bo && xelection.type()==Selection::Branch)
2762 if (bo->getOrientation()==LinkableMapObj::RightOfCenter)
2763 selectNextBranchInt();
2765 if (bo->getDepth()==1)
2766 selectPrevBranchInt();
2768 selectNextBranchInt();
2772 void MapEditor::selectLeftBranch()
2774 if (isSelectBlocked() ) return;
2778 LinkableMapObj *sel=xelection.single();
2781 if (xelection.type()== Selection::MapCenter)
2783 par=xelection.getBranch();
2784 bo=par->getLastSelectedBranch();
2787 // Workaround for reselecting on left and right side
2788 if (bo->getOrientation()==LinkableMapObj::RightOfCenter)
2789 bo=par->getLastBranch();
2792 bo=par->getLastBranch();
2793 xelection.select(bo);
2795 ensureSelectionVisible();
2800 par=(BranchObj*)(sel->getParObj());
2801 if (sel->getOrientation()==LinkableMapObj::RightOfCenter)
2803 if (xelection.type() == Selection::Branch ||
2804 xelection.type() == Selection::FloatImage)
2806 xelection.select(par);
2808 ensureSelectionVisible();
2812 if (xelection.type() == Selection::Branch )
2814 bo=xelection.getBranch()->getLastSelectedBranch();
2817 xelection.select(bo);
2819 ensureSelectionVisible();
2827 void MapEditor::selectRightBranch()
2829 if (isSelectBlocked() ) return;
2833 LinkableMapObj *sel=xelection.single();
2836 if (xelection.type()==Selection::MapCenter)
2838 par=xelection.getBranch();
2839 bo=par->getLastSelectedBranch();
2842 // Workaround for reselecting on left and right side
2843 if (bo->getOrientation()==LinkableMapObj::LeftOfCenter)
2844 bo=par->getFirstBranch();
2847 xelection.select(bo);
2849 ensureSelectionVisible();
2854 par=(BranchObj*)(xelection.single()->getParObj());
2855 if (xelection.single()->getOrientation()==LinkableMapObj::LeftOfCenter)
2857 if (xelection.type() == Selection::Branch ||
2858 xelection.type() == Selection::FloatImage)
2860 xelection.select(par);
2862 ensureSelectionVisible();
2866 if (xelection.type() == Selection::Branch)
2868 bo=xelection.getBranch()->getLastSelectedBranch();
2871 xelection.select(bo);
2873 ensureSelectionVisible();
2881 void MapEditor::selectFirstBranch()
2883 BranchObj *bo1=xelection.getBranch();
2888 par=(BranchObj*)(bo1->getParObj());
2889 bo2=par->getFirstBranch();
2891 xelection.select(bo2);
2893 ensureSelectionVisible();
2898 void MapEditor::selectLastBranch()
2900 BranchObj *bo1=xelection.getBranch();
2905 par=(BranchObj*)(bo1->getParObj());
2906 bo2=par->getLastBranch();
2909 xelection.select(bo2);
2911 ensureSelectionVisible();
2916 void MapEditor::selectMapBackgroundImage ()
2918 Q3FileDialog *fd=new Q3FileDialog( this);
2919 fd->setMode (Q3FileDialog::ExistingFile);
2920 fd->addFilter (QString (tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)"));
2921 ImagePreview *p =new ImagePreview (fd);
2922 fd->setContentsPreviewEnabled( TRUE );
2923 fd->setContentsPreview( p, p );
2924 fd->setPreviewMode( Q3FileDialog::Contents );
2925 fd->setCaption(vymName+" - " +tr("Load background image"));
2926 fd->setDir (lastImageDir);
2929 if ( fd->exec() == QDialog::Accepted )
2931 // TODO selectMapBackgroundImg in QT4 use: lastImageDir=fd->directory();
2932 lastImageDir=QDir (fd->dirPath());
2933 setMapBackgroundImage (fd->selectedFile());
2937 void MapEditor::setMapBackgroundImage (const QString &fn) //FIXME missing savestate
2939 QColor oldcol=mapScene->backgroundBrush().color();
2943 QString ("setMapBackgroundImage (%1)").arg(oldcol.name()),
2945 QString ("setMapBackgroundImage (%1)").arg(col.name()),
2946 QString("Set background color of map to %1").arg(col.name()));
2949 brush.setTextureImage (QPixmap (fn));
2950 mapScene->setBackgroundBrush(brush);
2953 void MapEditor::selectMapBackgroundColor()
2955 QColor col = QColorDialog::getColor( mapScene->backgroundBrush().color(), this );
2956 if ( !col.isValid() ) return;
2957 setMapBackgroundColor( col );
2961 void MapEditor::setMapBackgroundColor(QColor col)
2963 QColor oldcol=mapScene->backgroundBrush().color();
2966 QString ("setMapBackgroundColor (\"%1\")").arg(oldcol.name()),
2968 QString ("setMapBackgroundColor (\"%1\")").arg(col.name()),
2969 QString("Set background color of map to %1").arg(col.name()));
2970 mapScene->setBackgroundBrush(col);
2973 QColor MapEditor::getMapBackgroundColor()
2975 return mapScene->backgroundBrush().color();
2978 QColor MapEditor::getCurrentHeadingColor()
2980 BranchObj *bo=xelection.getBranch();
2981 if (bo) return bo->getColor();
2983 QMessageBox::warning(0,tr("Warning"),tr("Can't get color of heading,\nthere's no branch selected"));
2987 void MapEditor::colorBranch (QColor c)
2989 BranchObj *bo=xelection.getBranch();
2994 QString ("colorBranch (\"%1\")").arg(bo->getColor().name()),
2996 QString ("colorBranch (\"%1\")").arg(c.name()),
2997 QString("Set color of %1 to %2").arg(getName(bo)).arg(c.name())
2999 bo->setColor(c); // color branch
3003 void MapEditor::colorSubtree (QColor c)
3005 BranchObj *bo=xelection.getBranch();
3008 saveStateChangingPart(
3011 QString ("colorSubtree (\"%1\")").arg(c.name()),
3012 QString ("Set color of %1 and childs to %2").arg(getName(bo)).arg(c.name())
3014 bo->setColorSubtree (c); // color links, color childs
3019 void MapEditor::toggleStandardFlag(QString f)
3021 BranchObj *bo=xelection.getBranch();
3025 if (bo->isSetStandardFlag(f))
3037 QString("%1 (\"%2\")").arg(u).arg(f),
3039 QString("%1 (\"%2\")").arg(r).arg(f),
3040 QString("Toggling standard flag \"%1\" of %2").arg(f).arg(getName(bo)));
3041 bo->toggleStandardFlag (f,mainWindow->useFlagGroups());
3047 BranchObj* MapEditor::findText (QString s, bool cs)
3049 QTextDocument::FindFlags flags=0;
3050 if (cs) flags=QTextDocument::FindCaseSensitively;
3053 { // Nothing found or new find process
3055 // nothing found, start again
3057 itFind=mapCenter->first();
3059 bool searching=true;
3060 bool foundNote=false;
3061 while (searching && !EOFind)
3065 // Searching in Note
3066 if (itFind->getNote().contains(s,cs))
3068 if (xelection.single()!=itFind)
3070 xelection.select(itFind);
3071 ensureSelectionVisible();
3073 if (textEditor->findText(s,flags))
3079 // Searching in Heading
3080 if (searching && itFind->getHeading().contains (s,cs) )
3082 xelection.select(itFind);
3083 ensureSelectionVisible();
3089 itFind=itFind->next();
3090 if (!itFind) EOFind=true;
3094 return xelection.getBranch();
3099 void MapEditor::findReset()
3100 { // Necessary if text to find changes during a find process
3104 void MapEditor::setURL(const QString &url)
3106 BranchObj *bo=xelection.getBranch();
3109 QString oldurl=bo->getURL();
3113 QString ("setURL (\"%1\")").arg(oldurl),
3115 QString ("setURL (\"%1\")").arg(url),
3116 QString ("set URL of %1 to %2").arg(getName(bo)).arg(url)
3119 mapCenter->reposition();
3121 ensureSelectionVisible();
3125 void MapEditor::editURL()
3127 BranchObj *bo=xelection.getBranch();
3131 QString text = QInputDialog::getText(
3132 "VYM", tr("Enter URL:"), QLineEdit::Normal,
3133 bo->getURL(), &ok, this );
3135 // user entered something and pressed OK
3140 QString MapEditor::getURL()
3142 BranchObj *bo=xelection.getBranch();
3144 return bo->getURL();
3149 QStringList MapEditor::getURLs()
3152 BranchObj *bo=xelection.getBranch();
3158 if (!bo->getURL().isEmpty()) urls.append( bo->getURL());
3166 void MapEditor::editHeading2URL()
3168 BranchObj *bo=xelection.getBranch();
3170 setURL (bo->getHeading());
3173 void MapEditor::editBugzilla2URL()
3175 BranchObj *bo=xelection.getBranch();
3178 QString url= "https://bugzilla.novell.com/show_bug.cgi?id="+bo->getHeading();
3183 void MapEditor::editFATE2URL()
3185 BranchObj *bo=xelection.getBranch();
3188 QString url= "http://keeper.suse.de:8080/webfate/match/id?value=ID"+bo->getHeading();
3191 "setURL (\""+bo->getURL()+"\")",
3193 "setURL (\""+url+"\")",
3194 QString("Use heading of %1 as link to FATE").arg(getName(bo))
3201 void MapEditor::editVymLink()
3203 BranchObj *bo=xelection.getBranch();
3206 QStringList filters;
3207 filters <<"VYM map (*.vym)";
3208 QFileDialog *fd=new QFileDialog( this,vymName+" - " +tr("Link to another map"));
3209 fd->setFilters (filters);
3210 fd->setCaption(vymName+" - " +tr("Link to another map"));
3211 fd->setDirectory (lastFileDir);
3212 if (! bo->getVymLink().isEmpty() )
3213 fd->selectFile( bo->getVymLink() );
3217 if ( fd->exec() == QDialog::Accepted )
3219 lastFileDir=QDir (fd->directory().path());
3222 "setVymLink (\""+bo->getVymLink()+"\")",
3224 "setVymLink (\""+fd->selectedFile()+"\")",
3225 QString("Set vymlink of %1 to %2").arg(getName(bo)).arg(fd->selectedFile())
3227 setVymLinkInt (fd->selectedFile() );
3232 void MapEditor::deleteVymLink()
3234 BranchObj *bo=xelection.getBranch();
3239 "setVymLink (\""+bo->getVymLink()+"\")",
3241 "setVymLink (\"\")",
3242 QString("Unset vymlink of %1").arg(getName(bo))
3244 bo->setVymLink ("" );
3246 mapCenter->reposition();
3251 void MapEditor::setHideExport(bool b)
3253 BranchObj *bo=xelection.getBranch();
3256 bo->setHideInExport (b);
3257 QString u= b ? "false" : "true";
3258 QString r=!b ? "false" : "true";
3262 QString ("setHideExport (%1)").arg(u),
3264 QString ("setHideExport (%1)").arg(r),
3265 QString ("Set HideExport flag of %1 to %2").arg(getName(bo)).arg (r)
3268 mapCenter->reposition();
3274 void MapEditor::toggleHideExport()
3276 BranchObj *bo=xelection.getBranch();
3278 setHideExport ( !bo->hideInExport() );
3281 QString MapEditor::getVymLink()
3283 BranchObj *bo=xelection.getBranch();
3285 return bo->getVymLink();
3291 QStringList MapEditor::getVymLinks()
3294 BranchObj *bo=xelection.getBranch();
3300 if (!bo->getVymLink().isEmpty()) links.append( bo->getVymLink());
3308 void MapEditor::deleteKeepChilds()
3310 BranchObj *bo=xelection.getBranch();
3314 par=(BranchObj*)(bo->getParObj());
3315 QPointF p=bo->getRelPos();
3316 saveStateChangingPart(
3319 "deleteKeepChilds ()",
3320 QString("Remove %1 and keep its childs").arg(getName(bo))
3323 QString sel=bo->getSelectString();
3325 par->removeBranchHere(bo);
3326 mapCenter->reposition();
3328 xelection.getBranch()->move2RelPos (p);
3329 mapCenter->reposition();
3333 void MapEditor::deleteChilds()
3335 BranchObj *bo=xelection.getBranch();
3338 saveStateChangingPart(
3342 QString( "Remove childs of branch %1").arg(getName(bo))
3345 mapCenter->reposition();
3349 void MapEditor::editMapInfo()
3351 ExtraInfoDialog dia;
3352 dia.setMapName (getFileName() );
3353 dia.setAuthor (mapCenter->getAuthor() );
3354 dia.setComment(mapCenter->getComment() );
3358 stats+=tr("%1 items on map\n","Info about map").arg (mapScene->items().size(),6);
3365 bo=mapCenter->first();
3368 if (!bo->getNote().isEmpty() ) n++;
3369 f+= bo->countFloatImages();
3371 xl+=bo->countXLinks();
3374 stats+=QString ("%1 branches\n").arg (b-1,6);
3375 stats+=QString ("%1 xLinks \n").arg (xl,6);
3376 stats+=QString ("%1 notes\n").arg (n,6);
3377 stats+=QString ("%1 images\n").arg (f,6);
3378 dia.setStats (stats);
3380 // Finally show dialog
3381 if (dia.exec() == QDialog::Accepted)
3383 setMapAuthor (dia.getAuthor() );
3384 setMapComment (dia.getComment() );
3388 void MapEditor::ensureSelectionVisible()
3390 LinkableMapObj *lmo=xelection.single();
3391 if (lmo) ensureVisible (lmo->getBBox() );
3395 void MapEditor::updateSelection()
3397 // Tell selection to update geometries
3401 void MapEditor::updateActions()
3403 // Tell mainwindow to update states of actions
3404 mainWindow->updateActions();
3405 // TODO maybe don't update if blockReposition is set
3408 void MapEditor::updateNoteFlag()
3411 BranchObj *bo=xelection.getBranch();
3414 bo->updateNoteFlag();
3415 mainWindow->updateActions();
3419 void MapEditor::setMapAuthor (const QString &s)
3423 QString ("setMapAuthor (\"%1\")").arg(mapCenter->getAuthor()),
3425 QString ("setMapAuthor (\"%1\")").arg(s),
3426 QString ("Set author of map to \"%1\"").arg(s)
3428 mapCenter->setAuthor (s);
3431 void MapEditor::setMapComment (const QString &s)
3435 QString ("setMapComment (\"%1\")").arg(mapCenter->getComment()),
3437 QString ("setMapComment (\"%1\")").arg(s),
3438 QString ("Set comment of map")
3440 mapCenter->setComment (s);
3443 void MapEditor::setMapLinkStyle (const QString & s)
3445 saveStateChangingPart (
3448 QString("setMapLinkStyle (\"%1\")").arg(s),
3449 QString("Set map link style (\"%1\")").arg(s)
3453 linkstyle=LinkableMapObj::Line;
3454 else if (s=="StyleParabel")
3455 linkstyle=LinkableMapObj::Parabel;
3456 else if (s=="StylePolyLine")
3457 linkstyle=LinkableMapObj::PolyLine;
3459 linkstyle=LinkableMapObj::PolyParabel;
3462 bo=mapCenter->first();
3466 bo->setLinkStyle(bo->getDefLinkStyle());
3469 mapCenter->reposition();
3472 LinkableMapObj::Style MapEditor::getMapLinkStyle ()
3477 void MapEditor::setMapDefLinkColor(QColor c)
3481 bo=mapCenter->first();
3490 void MapEditor::setMapLinkColorHintInt()
3492 // called from setMapLinkColorHint(lch) or at end of parse
3494 bo=mapCenter->first();
3502 void MapEditor::setMapLinkColorHint(LinkableMapObj::ColorHint lch)
3505 setMapLinkColorHintInt();
3508 void MapEditor::toggleMapLinkColorHint()
3510 if (linkcolorhint==LinkableMapObj::HeadingColor)
3511 linkcolorhint=LinkableMapObj::DefaultColor;
3513 linkcolorhint=LinkableMapObj::HeadingColor;
3515 bo=mapCenter->first();
3523 LinkableMapObj::ColorHint MapEditor::getMapLinkColorHint()
3525 return linkcolorhint;
3528 QColor MapEditor::getMapDefLinkColor()
3530 return defLinkColor;
3533 void MapEditor::setMapDefXLinkColor(QColor col)
3538 QColor MapEditor::getMapDefXLinkColor()
3540 return defXLinkColor;
3543 void MapEditor::setMapDefXLinkWidth (int w)
3548 int MapEditor::getMapDefXLinkWidth()
3550 return defXLinkWidth;
3553 void MapEditor::selectMapLinkColor()
3555 QColor col = QColorDialog::getColor( defLinkColor, this );
3556 if ( !col.isValid() ) return;
3559 QString("setMapDefLinkColor (\"%1\")").arg(getMapDefLinkColor().name()),
3561 QString("setMapDefLinkColor (\"%1\")").arg(col.name()),
3562 QString("Set map link color to %1").arg(col.name())
3564 setMapDefLinkColor( col );
3567 void MapEditor::selectMapSelectionColor()
3569 QColor col = QColorDialog::getColor( defLinkColor, this );
3570 setSelectionColor (col);
3573 void MapEditor::setSelectionColorInt (QColor col)
3575 if ( !col.isValid() ) return;
3576 xelection.setColor (col);
3579 void MapEditor::setSelectionColor(QColor col)
3581 if ( !col.isValid() ) return;
3584 QString("setSelectionColor (%1)").arg(xelection.getColor().name()),
3586 QString("setSelectionColor (%1)").arg(col.name()),
3587 QString("Set color of selection box to %1").arg(col.name())
3589 setSelectionColorInt (col);
3592 QColor MapEditor::getSelectionColor()
3594 return xelection.getColor();
3597 bool MapEditor::scrollBranch(BranchObj *bo)
3601 if (bo->isScrolled()) return false;
3602 if (bo->countBranches()==0) return false;
3603 if (bo->getDepth()==0) return false;
3609 QString ("%1 ()").arg(u),
3611 QString ("%1 ()").arg(r),
3612 QString ("%1 %2").arg(r).arg(getName(bo))
3622 bool MapEditor::unscrollBranch(BranchObj *bo)
3626 if (!bo->isScrolled()) return false;
3627 if (bo->countBranches()==0) return false;
3628 if (bo->getDepth()==0) return false;
3634 QString ("%1 ()").arg(u),
3636 QString ("%1 ()").arg(r),
3637 QString ("%1 %2").arg(r).arg(getName(bo))
3647 void MapEditor::toggleScroll()
3649 BranchObj *bo=xelection.getBranch();
3650 if (xelection.type()==Selection::Branch )
3652 if (bo->isScrolled())
3653 unscrollBranch (bo);
3659 void MapEditor::unscrollChilds()
3661 BranchObj *bo=xelection.getBranch();
3667 if (bo->isScrolled()) unscrollBranch (bo);
3673 FloatImageObj* MapEditor::loadFloatImageInt (QString fn)
3675 BranchObj *bo=xelection.getBranch();
3679 bo->addFloatImage();
3680 fio=bo->getLastFloatImage();
3682 mapCenter->reposition();
3689 void MapEditor::loadFloatImage ()
3691 BranchObj *bo=xelection.getBranch();
3695 Q3FileDialog *fd=new Q3FileDialog( this);
3696 fd->setMode (Q3FileDialog::ExistingFiles);
3697 fd->addFilter (QString (tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)"));
3698 ImagePreview *p =new ImagePreview (fd);
3699 fd->setContentsPreviewEnabled( TRUE );
3700 fd->setContentsPreview( p, p );
3701 fd->setPreviewMode( Q3FileDialog::Contents );
3702 fd->setCaption(vymName+" - " +tr("Load image"));
3703 fd->setDir (lastImageDir);
3706 if ( fd->exec() == QDialog::Accepted )
3708 // TODO loadFIO in QT4 use: lastImageDir=fd->directory();
3709 lastImageDir=QDir (fd->dirPath());
3712 for (int j=0; j<fd->selectedFiles().count(); j++)
3714 s=fd->selectedFiles().at(j);
3715 fio=loadFloatImageInt (s);
3718 (LinkableMapObj*)fio,
3721 QString ("loadImage (%1)").arg(s ),
3722 QString("Add image %1 to %2").arg(s).arg(getName(bo))
3725 // TODO loadFIO error handling
3726 qWarning ("Failed to load "+s);
3734 void MapEditor::saveFloatImageInt (FloatImageObj *fio, const QString &type, const QString &fn)
3736 fio->save (fn,type);
3739 void MapEditor::saveFloatImage ()
3741 FloatImageObj *fio=xelection.getFloatImage();
3744 QFileDialog *fd=new QFileDialog( this);
3745 fd->setFilters (imageIO.getFilters());
3746 fd->setCaption(vymName+" - " +tr("Save image"));
3747 fd->setFileMode( QFileDialog::AnyFile );
3748 fd->setDirectory (lastImageDir);
3749 // fd->setSelection (fio->getOriginalFilename());
3753 if ( fd->exec() == QDialog::Accepted && fd->selectedFiles().count()==1)
3755 fn=fd->selectedFiles().at(0);
3756 if (QFile (fn).exists() )
3758 QMessageBox mb( vymName,
3759 tr("The file %1 exists already.\n"
3760 "Do you want to overwrite it?").arg(fn),
3761 QMessageBox::Warning,
3762 QMessageBox::Yes | QMessageBox::Default,
3763 QMessageBox::Cancel | QMessageBox::Escape,
3764 QMessageBox::QMessageBox::NoButton );
3766 mb.setButtonText( QMessageBox::Yes, tr("Overwrite") );
3767 mb.setButtonText( QMessageBox::No, tr("Cancel"));
3770 case QMessageBox::Yes:
3773 case QMessageBox::Cancel:
3780 saveFloatImageInt (fio,fd->selectedFilter(),fn );
3786 void MapEditor::setFrameType(const FrameObj::FrameType &t)
3788 BranchObj *bo=xelection.getBranch();
3791 QString s=bo->getFrameTypeName();
3792 bo->setFrameType (t);
3793 saveState (bo, QString("setFrameType (\"%1\")").arg(s),
3794 bo, QString ("setFrameType (\"%1\")").arg(bo->getFrameTypeName()),QString ("set type of frame to %1").arg(s));
3795 mapCenter->reposition();
3800 void MapEditor::setFrameType(const QString &s)
3802 BranchObj *bo=xelection.getBranch();
3805 saveState (bo, QString("setFrameType (\"%1\")").arg(bo->getFrameTypeName()),
3806 bo, QString ("setFrameType (\"%1\")").arg(s),QString ("set type of frame to %1").arg(s));
3807 bo->setFrameType (s);
3808 mapCenter->reposition();
3813 void MapEditor::setFramePenColor(const QColor &c)
3815 BranchObj *bo=xelection.getBranch();
3818 saveState (bo, QString("setFramePenColor (\"%1\")").arg(bo->getFramePenColor().name() ),
3819 bo, QString ("setFramePenColor (\"%1\")").arg(c.name() ),QString ("set pen color of frame to %1").arg(c.name() ));
3820 bo->setFramePenColor (c);
3824 void MapEditor::setFrameBrushColor(const QColor &c)
3826 BranchObj *bo=xelection.getBranch();
3829 saveState (bo, QString("setFrameBrushColor (\"%1\")").arg(bo->getFrameBrushColor().name() ),
3830 bo, QString ("setFrameBrushColor (\"%1\")").arg(c.name() ),QString ("set brush color of frame to %1").arg(c.name() ));
3831 bo->setFrameBrushColor (c);
3835 void MapEditor::setFramePadding (const int &i)
3837 BranchObj *bo=xelection.getBranch();
3840 saveState (bo, QString("setFramePadding (\"%1\")").arg(bo->getFramePadding() ),
3841 bo, QString ("setFramePadding (\"%1\")").arg(i),QString ("set brush color of frame to %1").arg(i));
3842 bo->setFramePadding (i);
3843 mapCenter->reposition();
3848 void MapEditor::setFrameBorderWidth(const int &i)
3850 BranchObj *bo=xelection.getBranch();
3853 saveState (bo, QString("setFrameBorderWidth (\"%1\")").arg(bo->getFrameBorderWidth() ),
3854 bo, QString ("setFrameBorderWidth (\"%1\")").arg(i),QString ("set border width of frame to %1").arg(i));
3855 bo->setFrameBorderWidth (i);
3856 mapCenter->reposition();
3861 void MapEditor::setIncludeImagesVer(bool b)
3863 BranchObj *bo=xelection.getBranch();
3866 QString u= b ? "false" : "true";
3867 QString r=!b ? "false" : "true";
3871 QString("setIncludeImagesVertically (%1)").arg(u),
3873 QString("setIncludeImagesVertically (%1)").arg(r),
3874 QString("Include images vertically in %1").arg(getName(bo))
3876 bo->setIncludeImagesVer(b);
3877 mapCenter->reposition();
3881 void MapEditor::setIncludeImagesHor(bool b)
3883 BranchObj *bo=xelection.getBranch();
3886 QString u= b ? "false" : "true";
3887 QString r=!b ? "false" : "true";
3891 QString("setIncludeImagesHorizontally (%1)").arg(u),
3893 QString("setIncludeImagesHorizontally (%1)").arg(r),
3894 QString("Include images horizontally in %1").arg(getName(bo))
3896 bo->setIncludeImagesHor(b);
3897 mapCenter->reposition();
3901 void MapEditor::setHideLinkUnselected (bool b)
3903 LinkableMapObj *sel=xelection.single();
3905 (xelection.type() == Selection::Branch ||
3906 xelection.type() == Selection::MapCenter ||
3907 xelection.type() == Selection::FloatImage ))
3909 QString u= b ? "false" : "true";
3910 QString r=!b ? "false" : "true";
3914 QString("setHideLinkUnselected (%1)").arg(u),
3916 QString("setHideLinkUnselected (%1)").arg(r),
3917 QString("Hide link of %1 if unselected").arg(getName(sel))
3919 sel->setHideLinkUnselected(b);
3923 void MapEditor::importDirInt(BranchObj *dst, QDir d)
3925 BranchObj *bo=xelection.getBranch();
3928 // Traverse directories
3929 d.setFilter( QDir::Dirs| QDir::Hidden | QDir::NoSymLinks );
3930 QFileInfoList list = d.entryInfoList();
3933 for (int i = 0; i < list.size(); ++i)
3936 if (fi.fileName() != "." && fi.fileName() != ".." )
3939 bo=dst->getLastBranch();
3940 bo->setHeading (fi.fileName() );
3941 bo->setColor (QColor("blue"));
3943 if ( !d.cd(fi.fileName()) )
3944 QMessageBox::critical (0,tr("Critical Import Error"),tr("Cannot find the directory %1").arg(fi.fileName()));
3947 // Recursively add subdirs
3948 importDirInt (bo,d);
3954 d.setFilter( QDir::Files| QDir::Hidden | QDir::NoSymLinks );
3955 list = d.entryInfoList();
3957 for (int i = 0; i < list.size(); ++i)
3961 bo=dst->getLastBranch();
3962 bo->setHeading (fi.fileName() );
3963 bo->setColor (QColor("black"));
3964 if (fi.fileName().right(4) == ".vym" )
3965 bo->setVymLink (fi.filePath());
3970 void MapEditor::importDirInt (const QString &s)
3972 BranchObj *bo=xelection.getBranch();
3975 saveStateChangingPart (bo,bo,QString ("importDir (\"%1\")").arg(s),QString("Import directory structure from %1").arg(s));
3978 importDirInt (bo,d);
3982 void MapEditor::importDir()
3984 BranchObj *bo=xelection.getBranch();
3987 QStringList filters;
3988 filters <<"VYM map (*.vym)";
3989 QFileDialog *fd=new QFileDialog( this,vymName+ " - " +tr("Choose directory structure to import"));
3990 fd->setMode (QFileDialog::DirectoryOnly);
3991 fd->setFilters (filters);
3992 fd->setCaption(vymName+" - " +tr("Choose directory structure to import"));
3996 if ( fd->exec() == QDialog::Accepted )
3998 importDirInt (fd->selectedFile() );
3999 mapCenter->reposition();
4005 void MapEditor::followXLink(int i)
4007 BranchObj *bo=xelection.getBranch();
4010 bo=bo->XLinkTargetAt(i);
4013 xelection.select(bo);
4014 ensureSelectionVisible();
4019 void MapEditor::editXLink(int i) // FIXME missing saveState
4021 BranchObj *bo=xelection.getBranch();
4024 XLinkObj *xlo=bo->XLinkAt(i);
4027 EditXLinkDialog dia;
4029 dia.setSelection(bo);
4030 if (dia.exec() == QDialog::Accepted)
4032 if (dia.useSettingsGlobal() )
4034 setMapDefXLinkColor (xlo->getColor() );
4035 setMapDefXLinkWidth (xlo->getWidth() );
4037 if (dia.deleteXLink())
4038 bo->deleteXLinkAt(i);
4044 void MapEditor::testFunction()
4046 BranchObj *bo=xelection.getBranch();
4047 if (bo) animObjList.append( bo );
4051 dia.showCancelButton (true);
4052 dia.setText("This is a longer \nWarning");
4053 dia.setCaption("Warning: Flux problem");
4054 dia.setShowAgainName("mapeditor/testDialog");
4055 if (dia.exec()==QDialog::Accepted)
4056 cout << "accepted!\n";
4058 cout << "canceled!\n";
4062 /* TODO Hide hidden stuff temporary, maybe add this as regular function somewhere
4063 if (hidemode==HideNone)
4065 setHideTmpMode (HideExport);
4066 mapCenter->calcBBoxSizeWithChilds();
4067 QRectF totalBBox=mapCenter->getTotalBBox();
4068 QRectF mapRect=totalBBox;
4069 QCanvasRectangle *frame=NULL;
4071 cout << " map has =("<<totalBBox.x()<<","<<totalBBox.y()<<","<<totalBBox.width()<<","<<totalBBox.height()<<")\n";
4073 mapRect.setRect (totalBBox.x(), totalBBox.y(),
4074 totalBBox.width(), totalBBox.height());
4075 frame=new QCanvasRectangle (mapRect,mapScene);
4076 frame->setBrush (QColor(white));
4077 frame->setPen (QColor(black));
4078 frame->setZValue(0);
4083 setHideTmpMode (HideNone);
4085 cout <<" hidemode="<<hidemode<<endl;
4089 void MapEditor::contextMenuEvent ( QContextMenuEvent * e )
4091 // Lineedits are already closed by preceding
4092 // mouseEvent, we don't need to close here.
4094 QPointF p = mapToScene(e->pos());
4095 LinkableMapObj* lmo=mapCenter->findMapObj(p, NULL);
4098 { // MapObj was found
4099 if (xelection.single() != lmo)
4101 // select the MapObj
4102 xelection.select(lmo);
4105 if (xelection.getBranch() )
4107 // Context Menu on branch or mapcenter
4109 branchContextMenu->popup(e->globalPos() );
4112 if (xelection.getFloatImage() )
4114 // Context Menu on floatimage
4116 floatimageContextMenu->popup(e->globalPos() );
4120 { // No MapObj found, we are on the Canvas itself
4121 // Context Menu on scene
4123 canvasContextMenu->popup(e->globalPos() );
4128 void MapEditor::keyPressEvent(QKeyEvent* e)
4130 if (e->modifiers() & Qt::ControlModifier)
4132 switch (mainWindow->getModMode())
4134 case Main::ModModeColor:
4135 setCursor (PickColorCursor);
4137 case Main::ModModeCopy:
4138 setCursor (CopyCursor);
4140 case Main::ModModeXLink:
4141 setCursor (XLinkCursor);
4144 setCursor (Qt::ArrowCursor);
4150 void MapEditor::keyReleaseEvent(QKeyEvent* e)
4152 if (!(e->modifiers() & Qt::ControlModifier))
4153 setCursor (Qt::ArrowCursor);
4156 void MapEditor::mousePressEvent(QMouseEvent* e)
4158 // Ignore right clicks, these will go to context menus
4159 if (e->button() == Qt::RightButton )
4165 //Ignore clicks while editing heading
4166 if (isSelectBlocked() )
4172 QPointF p = mapToScene(e->pos());
4173 LinkableMapObj* lmo=mapCenter->findMapObj(p, NULL);
4177 //Take care of system flags _or_ modifier modes
4179 if (lmo && (typeid(*lmo)==typeid(BranchObj) ||
4180 typeid(*lmo)==typeid(MapCenterObj) ))
4182 QString foname=((BranchObj*)lmo)->getSystemFlagName(p);
4183 if (!foname.isEmpty())
4185 // systemFlag clicked
4189 if (e->state() & Qt::ControlModifier)
4190 mainWindow->editOpenURLTab();
4192 mainWindow->editOpenURL();
4194 else if (foname=="vymLink")
4196 mainWindow->editOpenVymLink();
4197 // tabWidget may change, better return now
4198 // before segfaulting...
4199 } else if (foname=="note")
4200 mainWindow->windowToggleNoteEditor();
4201 else if (foname=="hideInExport")
4208 // No system flag clicked, take care of modmodes (CTRL-Click)
4209 if (e->state() & Qt::ControlModifier)
4211 if (mainWindow->getModMode()==Main::ModModeColor)
4214 setCursor (PickColorCursor);
4217 if (mainWindow->getModMode()==Main::ModModeXLink)
4219 BranchObj *bo_begin=NULL;
4221 bo_begin=(BranchObj*)(lmo);
4223 if (xelection.getBranch() )
4224 bo_begin=xelection.getBranch();
4228 linkingObj_src=bo_begin;
4229 tmpXLink=new XLinkObj (mapScene);
4230 tmpXLink->setBegin (bo_begin);
4231 tmpXLink->setEnd (p);
4232 tmpXLink->setColor(defXLinkColor);
4233 tmpXLink->setWidth(defXLinkWidth);
4234 tmpXLink->updateXLink();
4235 tmpXLink->setVisibility (true);
4239 } // End of modmodes
4243 // Select the clicked object
4246 // Left Button Move Branches
4247 if (e->button() == Qt::LeftButton )
4249 //movingObj_start.setX( p.x() - selection->x() );// TODO replaced selection->lmo here
4250 //movingObj_start.setY( p.y() - selection->y() );
4251 movingObj_start.setX( p.x() - lmo->x() );
4252 movingObj_start.setY( p.y() - lmo->y() );
4253 movingObj_orgPos.setX (lmo->x() );
4254 movingObj_orgPos.setY (lmo->y() );
4255 movingObj_orgRelPos=lmo->getRelPos();
4257 // If modMode==copy, then we want to "move" the _new_ object around
4258 // then we need the offset from p to the _old_ selection, because of tmp
4259 if (mainWindow->getModMode()==Main::ModModeCopy &&
4260 e->state() & Qt::ControlModifier)
4262 if (xelection.type()==Selection::Branch)
4265 mapCenter->addBranch ((BranchObj*)xelection.single());
4267 xelection.select(mapCenter->getLastBranch());
4268 mapCenter->reposition();
4272 movingObj=xelection.single();
4274 // Middle Button Toggle Scroll
4275 // (On Mac OS X this won't work, but we still have
4276 // a button in the toolbar)
4277 if (e->button() == Qt::MidButton )
4282 { // No MapObj found, we are on the scene itself
4283 // Left Button move Pos of sceneView
4284 if (e->button() == Qt::LeftButton )
4286 movingObj=NULL; // move Content not Obj
4287 movingObj_start=e->globalPos();
4288 movingCont_start=QPointF (
4289 horizontalScrollBar()->value(),
4290 verticalScrollBar()->value());
4291 movingVec=QPointF(0,0);
4292 setCursor(HandOpenCursor);
4297 void MapEditor::mouseMoveEvent(QMouseEvent* e)
4299 QPointF p = mapToScene(e->pos());
4300 LinkableMapObj *lmosel=xelection.single();
4302 // Move the selected MapObj
4303 if ( lmosel && movingObj)
4305 // reset cursor if we are moving and don't copy
4306 if (mainWindow->getModMode()!=Main::ModModeCopy)
4307 setCursor (Qt::ArrowCursor);
4309 // To avoid jumping of the sceneView, only
4310 // ensureSelectionVisible, if not tmp linked
4311 if (!lmosel->hasParObjTmp())
4312 ensureSelectionVisible ();
4314 // Now move the selection, but add relative position
4315 // (movingObj_start) where selection was chosen with
4316 // mousepointer. (This avoids flickering resp. jumping
4317 // of selection back to absPos)
4319 // Check if we could link
4320 LinkableMapObj* lmo=mapCenter->findMapObj(p, lmosel);
4323 FloatObj *fio=xelection.getFloatImage();
4326 fio->move (p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
4328 fio->updateLink(); //no need for reposition, if we update link here
4331 // Relink float to new mapcenter or branch, if shift is pressed
4332 // Only relink, if selection really has a new parent
4333 if ( (e->modifiers()==Qt::ShiftModifier) && lmo &&
4334 ( (typeid(*lmo)==typeid(BranchObj)) ||
4335 (typeid(*lmo)==typeid(MapCenterObj)) ) &&
4336 ( lmo != fio->getParObj())
4339 if (typeid(*fio) == typeid(FloatImageObj) &&
4340 ( (typeid(*lmo)==typeid(BranchObj) ||
4341 typeid(*lmo)==typeid(MapCenterObj)) ))
4344 // Also save the move which was done so far
4345 QString pold=qpointfToString(movingObj_orgRelPos);
4346 QString pnow=qpointfToString(fio->getRelPos());
4352 QString("Move %1 to relativ position %2").arg(getName(fio)).arg(pnow));
4353 fio->getParObj()->requestReposition();
4354 mapCenter->reposition();
4356 linkTo (lmo->getSelectString());
4358 //movingObj_orgRelPos=lmosel->getRelPos();
4360 mapCenter->reposition();
4364 { // selection != a FloatObj
4365 if (lmosel->getDepth()==0)
4368 if (e->buttons()== Qt::LeftButton && e->modifiers()==Qt::ShiftModifier)
4369 mapCenter->moveAll(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
4371 mapCenter->move (p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
4372 mapCenter->updateRelPositions();
4375 if (lmosel->getDepth()==1)
4378 lmosel->move(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
4379 lmosel->setRelPos();
4382 // Move ordinary branch
4383 if (lmosel->getOrientation() == LinkableMapObj::LeftOfCenter)
4384 // Add width of bbox here, otherwise alignRelTo will cause jumping around
4385 lmosel->move(p.x() -movingObj_start.x()+lmosel->getBBox().width(),
4386 p.y()-movingObj_start.y() +lmosel->getTopPad() );
4388 lmosel->move(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() -lmosel->getTopPad());
4391 // Maybe we can relink temporary?
4392 if (lmo && (lmo!=lmosel) && xelection.getBranch() &&
4393 (typeid(*lmo)==typeid(BranchObj) ||
4394 typeid(*lmo)==typeid(MapCenterObj)) )
4397 if (e->modifiers()==Qt::ControlModifier)
4399 // Special case: CTRL to link below lmo
4400 lmosel->setParObjTmp (lmo,p,+1);
4402 else if (e->modifiers()==Qt::ShiftModifier)
4403 lmosel->setParObjTmp (lmo,p,-1);
4405 lmosel->setParObjTmp (lmo,p,0);
4408 lmosel->unsetParObjTmp();
4410 // reposition subbranch
4411 lmosel->reposition();
4415 } // no FloatImageObj
4419 } // selection && moving_obj
4421 // Draw a link from one branch to another
4424 tmpXLink->setEnd (p);
4425 tmpXLink->updateXLink();
4429 if (!movingObj && !pickingColor &&!drawingLink && e->buttons() == Qt::LeftButton )
4431 QPointF p=e->globalPos();
4432 movingVec.setX(-p.x() + movingObj_start.x() );
4433 movingVec.setY(-p.y() + movingObj_start.y() );
4434 horizontalScrollBar()->setSliderPosition((int)( movingCont_start.x()+movingVec.x() ));
4435 verticalScrollBar()->setSliderPosition((int)( movingCont_start.y()+movingVec.y() ) );
4440 void MapEditor::mouseReleaseEvent(QMouseEvent* e)
4442 QPointF p = mapToScene(e->pos());
4443 LinkableMapObj *dst;
4444 LinkableMapObj *lmosel=xelection.single();
4445 // Have we been picking color?
4449 setCursor (Qt::ArrowCursor);
4450 // Check if we are over another branch
4451 dst=mapCenter->findMapObj(p, NULL);
4454 if (e->state() & Qt::ShiftModifier)
4455 colorBranch (((BranchObj*)(dst))->getColor());
4457 colorSubtree (((BranchObj*)(dst))->getColor());
4462 // Have we been drawing a link?
4466 // Check if we are over another branch
4467 dst=mapCenter->findMapObj(p, NULL);
4470 tmpXLink->setEnd ( ((BranchObj*)(dst)) );
4471 tmpXLink->updateXLink();
4472 tmpXLink->activate(); //FIXME savestate missing
4473 //saveStateComplete(QString("Activate xLink from %1 to %2").arg(getName(tmpXLink->getBegin())).arg(getName(tmpXLink->getEnd())) );
4482 // Have we been moving something?
4483 if ( lmosel && movingObj )
4485 FloatImageObj *fo=xelection.getFloatImage();
4488 // Moved FloatObj. Maybe we need to reposition
4489 QString pold=qpointfToString(movingObj_orgRelPos);
4490 QString pnow=qpointfToString(fo->getRelPos());
4496 QString("Move %1 to relativ position %2").arg(getName(fo)).arg(pnow));
4498 fo->getParObj()->requestReposition();
4499 mapCenter->reposition();
4502 // Check if we are over another branch, but ignore
4503 // any found LMOs, which are FloatObjs
4504 dst=mapCenter->findMapObj(mapToScene(e->pos() ), lmosel);
4506 if (dst && (typeid(*dst)!=typeid(BranchObj) && typeid(*dst)!=typeid(MapCenterObj)))
4509 if (xelection.type() == Selection::MapCenter )
4511 // TODO: Check for problems if graphicsview is resized for
4513 QString pold=qpointfToString(movingObj_orgPos);
4514 QString pnow=qpointfToString(mapCenter->getAbsPos());
4520 QString("Move mapcenter %1 to position %2").arg(getName(mapCenter)).arg(pnow));
4523 if (xelection.type() == Selection::Branch )
4524 { // A branch was moved
4526 // save the position in case we link to mapcenter
4527 QPointF savePos=QPointF (lmosel->getAbsPos() );
4529 // Reset the temporary drawn link to the original one
4530 lmosel->unsetParObjTmp();
4532 // For Redo we may need to save original selection
4533 QString preSelStr=lmosel->getSelectString();
4538 BranchObj* bsel=xelection.getBranch();
4539 BranchObj* bdst=(BranchObj*)dst;
4541 QString preParStr=(bsel->getParObj())->getSelectString();
4542 QString preNum=QString::number (bsel->getNum(),10);
4543 QString preDstParStr;
4545 if (e->state() & Qt::ShiftModifier && dst->getParObj())
4547 preDstParStr=dst->getParObj()->getSelectString();
4548 bsel->linkTo ( (BranchObj*)(bdst->getParObj()), bdst->getNum());
4550 if (e->state() & Qt::ControlModifier && dst->getParObj())
4553 preDstParStr=dst->getParObj()->getSelectString();
4554 bsel->linkTo ( (BranchObj*)(bdst->getParObj()), bdst->getNum()+1);
4557 preDstParStr=dst->getSelectString();
4558 bsel->linkTo (bdst,-1);
4559 if (dst->getDepth()==0) bsel->move (savePos);
4561 QString postSelStr=lmosel->getSelectString();
4562 QString postNum=QString::number (bsel->getNum(),10);
4564 QString undoCom="linkTo (\""+
4565 preParStr+ "\"," + preNum +"," +
4566 QString ("%1,%2").arg(movingObj_orgPos.x()).arg(movingObj_orgPos.y())+ ")";
4568 QString redoCom="linkTo (\""+
4569 preDstParStr + "\"," + postNum + "," +
4570 QString ("%1,%2").arg(savePos.x()).arg(savePos.y())+ ")";
4575 QString("Relink %1 to %2").arg(getName(bsel)).arg(getName(dst)) );
4577 if (lmosel->getDepth()==1)
4579 // The select string might be different _after_ moving around.
4580 // Therefor reposition and then use string of old selection, too
4581 mapCenter->reposition();
4583 QString ps=qpointfToString ( lmosel->getRelPos() );
4585 lmosel->getSelectString(), "moveRel "+qpointfToString(movingObj_orgRelPos),
4586 preSelStr, "moveRel "+ps,
4587 QString("Move %1 to relative position %2").arg(getName(lmosel)).arg(ps));
4590 // Draw the original link, before selection was moved around
4591 mapCenter->reposition();
4594 // Finally resize scene, if needed
4598 // Just make sure, that actions are still ok,e.g. the move branch up/down buttons...
4601 // maybe we moved View: set old cursor
4602 setCursor (Qt::ArrowCursor);
4606 void MapEditor::mouseDoubleClickEvent(QMouseEvent* e)
4608 if (isSelectBlocked() )
4614 if (e->button() == Qt::LeftButton )
4616 QPointF p = mapToScene(e->pos());
4617 LinkableMapObj *lmo=mapCenter->findMapObj(p, NULL);
4618 if (lmo) { // MapObj was found
4619 // First select the MapObj than edit heading
4620 xelection.select(lmo);
4621 mainWindow->editHeading();
4626 void MapEditor::resizeEvent (QResizeEvent* e)
4628 QGraphicsView::resizeEvent( e );
4631 void MapEditor::dragEnterEvent(QDragEnterEvent *event)
4633 //for (unsigned int i=0;event->format(i);i++) // Debug mime type
4634 // cerr << event->format(i) << endl;
4636 if (event->mimeData()->hasImage())
4637 event->acceptProposedAction();
4639 if (event->mimeData()->hasUrls())
4640 event->acceptProposedAction();
4643 void MapEditor::dragMoveEvent(QDragMoveEvent *event)
4647 void MapEditor::dragLeaveEvent(QDragLeaveEvent *event)
4652 void MapEditor::dropEvent(QDropEvent *event)
4654 BranchObj *sel=xelection.getBranch();
4658 foreach (QString format,event->mimeData()->formats())
4659 cout << "MapEditor: Dropped format: "<<format.ascii()<<endl;
4663 if (event->mimeData()->hasImage())
4665 QVariant imageData = event->mimeData()->imageData();
4666 addFloatImageInt (qvariant_cast<QPixmap>(imageData));
4668 if (event->mimeData()->hasUrls())
4669 uris=event->mimeData()->urls();
4677 for (int i=0; i<uris.count();i++)
4679 // Workaround to avoid adding empty branches
4680 if (!uris.at(i).toString().isEmpty())
4682 bo=sel->addBranch();
4685 s=uris.at(i).toLocalFile();
4688 QString file = QDir::convertSeparators(s);
4689 heading = QFileInfo(file).baseName();
4691 if (file.endsWith(".vym", false))
4692 bo->setVymLink(file);
4694 bo->setURL(uris.at(i).toString());
4697 bo->setURL(uris.at(i).toString());
4700 if (!heading.isEmpty())
4701 bo->setHeading(heading);
4703 bo->setHeading(uris.at(i).toString());
4707 mapCenter->reposition();
4710 event->acceptProposedAction();
4713 void MapEditor::timerEvent(QTimerEvent *event) //TODO animation
4717 cout << "ME::timerEvent\n";
4719 for (int i=0; i<animObjList.size(); ++i)
4721 animObjList.at(i)->animate();
4722 ((BranchObj*)animObjList.at(i))->move2RelPos (((BranchObj*)animObjList.at(i))->getRelPos() );
4724 mapCenter->reposition();
4727 void MapEditor::autosave()
4729 // Disable autosave, while we have gone back in history
4730 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
4731 if (redosAvail>0) return;
4734 if (mapUnsaved &&mapChanged && settings.value ("/mapeditor/autosave/use",true).toBool() )
4735 mainWindow->fileSave (this);
4739 /*TODO not needed? void MapEditor::contentsDropEvent(QDropEvent *event)
4742 } else if (event->provides("application/x-moz-file-promise-url") &&
4743 event->provides("application/x-moz-nativeimage"))
4745 // Contains url to the img src in unicode16
4746 QByteArray d = event->encodedData("application/x-moz-file-promise-url");
4747 QString url = QString((const QChar*)d.data(),d.size()/2);
4751 } else if (event->provides ("text/uri-list"))
4752 { // Uris provided e.g. by konqueror
4753 Q3UriDrag::decode (event,uris);
4754 } else if (event->provides ("_NETSCAPE_URL"))
4755 { // Uris provided by Mozilla
4756 QStringList l = QStringList::split("\n", event->encodedData("_NETSCAPE_URL"));
4759 } else if (event->provides("text/html")) {
4761 // Handels text mime types
4762 // Look like firefox allways handle text as unicode16 (2 bytes per char.)
4763 QByteArray d = event->encodedData("text/html");
4766 text = QString((const QChar*)d.data(),d.size()/2);
4770 textEditor->setText(text);
4774 } else if (event->provides("text/plain")) {
4775 QByteArray d = event->encodedData("text/plain");
4778 text = QString((const QChar*)d.data(),d.size()/2);
4782 textEditor->setText(text);
4792 bool isUnicode16(const QByteArray &d)
4794 // TODO: make more precise check for unicode 16.
4795 // Guess unicode16 if any of second bytes are zero
4796 unsigned int length = max(0,d.size()-2)/2;
4797 for (unsigned int i = 0; i<length ; i++)
4798 if (d.at(i*2+1)==0) return true;
4802 void MapEditor::addFloatImageInt (const QPixmap &img)
4804 BranchObj *bo=xelection.getBranch();
4807 FloatImageObj *fio=bo->addFloatImage();
4809 fio->setOriginalFilename("No original filename (image added by dropevent)");
4810 QString s=bo->getSelectString();
4811 saveState (PartOfMap, s, "nop ()", s, "copy ()","Copy dropped image to clipboard",fio );
4812 saveState (fio,"delete ()", bo,QString("paste(%1)").arg(curStep),"Pasting dropped image");
4813 mapCenter->reposition();
4820 void MapEditor::imageDataFetched(const QByteArray &a, Q3NetworkOperation * / *nop* /)
4822 if (!imageBuffer) imageBuffer = new QBuffer();
4823 if (!imageBuffer->isOpen()) {
4824 imageBuffer->open(QIODevice::WriteOnly | QIODevice::Append);
4826 imageBuffer->at(imageBuffer->at()+imageBuffer->writeBlock(a));
4830 void MapEditor::imageDataFinished(Q3NetworkOperation *nop)
4832 if (nop->state()==Q3NetworkProtocol::StDone) {
4833 QPixmap img(imageBuffer->buffer());
4834 addFloatImageInt (img);
4838 imageBuffer->close();
4840 imageBuffer->close();
4847 void MapEditor::fetchImage(const QString &url)
4850 urlOperator->stop();
4851 disconnect(urlOperator);
4855 urlOperator = new Q3UrlOperator(url);
4856 connect(urlOperator, SIGNAL(finished(Q3NetworkOperation *)),
4857 this, SLOT(imageDataFinished(Q3NetworkOperation*)));
4859 connect(urlOperator, SIGNAL(data(const QByteArray &, Q3NetworkOperation *)),
4860 this, SLOT(imageDataFetched(const QByteArray &, Q3NetworkOperation *)));