3 #include <q3filedialog.h>
10 #include "editxlinkdialog.h"
12 #include "exportxhtmldialog.h"
13 #include "extrainfodialog.h"
15 #include "linkablemapobj.h"
16 #include "mainwindow.h"
18 #include "texteditor.h"
19 #include "warningdialog.h"
20 #include "xml-freemind.h"
24 extern TextEditor *textEditor;
25 extern int statusbarTime;
26 extern Main *mainWindow;
27 extern QString tmpVymDir;
28 extern QString clipboardDir;
29 extern QString clipboardFile;
30 extern bool clipboardEmpty;
32 extern FlagRowObj *standardFlagsDefault;
34 extern QMenu* branchContextMenu;
35 extern QMenu* branchAddContextMenu;
36 extern QMenu* branchRemoveContextMenu;
37 extern QMenu* branchLinksContextMenu;
38 extern QMenu* branchXLinksContextMenuEdit;
39 extern QMenu* branchXLinksContextMenuFollow;
40 extern QMenu* floatimageContextMenu;
41 extern QMenu* canvasContextMenu;
44 extern Settings settings;
45 extern ImageIO imageIO;
47 extern QString vymName;
48 extern QString vymVersion;
50 extern QString iconPath;
51 extern QDir vymBaseDir;
52 extern QDir lastImageDir;
53 extern QDir lastFileDir;
55 int MapEditor::mapNum=0; // make instance
57 ///////////////////////////////////////////////////////////////////////
58 ///////////////////////////////////////////////////////////////////////
59 MapEditor::MapEditor( QWidget* parent) :
62 //cout << "Constructor ME "<<this<<endl;
66 mapScene= new QGraphicsScene(parent);
67 //mapScene= new QGraphicsScene(QRectF(0,0,width(),height()), parent);
68 mapScene->setBackgroundBrush (QBrush(Qt::white, Qt::SolidPattern));
71 model->setScene (mapScene);
72 model->setMapEditor (this);
78 defLinkColor=QColor (0,0,255);
79 defXLinkColor=QColor (180,180,180);
80 linkcolorhint=LinkableMapObj::DefaultColor;
81 linkstyle=LinkableMapObj::PolyParabel;
83 // Create bitmap cursors, platform dependant
84 HandOpenCursor=QCursor (QPixmap(iconPath+"cursorhandopen.png"),1,1);
85 PickColorCursor=QCursor ( QPixmap(iconPath+"cursorcolorpicker.png"), 5,27 );
86 CopyCursor=QCursor ( QPixmap(iconPath+"cursorcopy.png"), 1,1 );
87 XLinkCursor=QCursor ( QPixmap(iconPath+"cursorxlink.png"), 1,7 );
89 setFocusPolicy (Qt::StrongFocus);
98 xelection.setModel (model);
102 defXLinkColor=QColor (230,230,230);
110 fileName=tr("unnamed");
113 stepsTotal=settings.readNumEntry("/mapeditor/stepsTotal",100);
114 undoSet.setEntry ("/history/stepsTotal",QString::number(stepsTotal));
115 mainWindow->updateHistory (undoSet);
117 // Initialize find routine
124 blockReposition=false;
125 blockSaveState=false;
129 // Create temporary files
136 setAcceptDrops (true);
142 //timerId = startTimer(100);
145 autosaveTimer=new QTimer (this);
146 connect(autosaveTimer, SIGNAL(timeout()), this, SLOT(autosave()));
148 fileChangedTimer=new QTimer (this);
149 fileChangedTimer->start(3000);
150 connect(fileChangedTimer, SIGNAL(timeout()), this, SLOT(fileChanged()));
155 // Attributes //FIXME testing only...
158 attrTable= new AttributeTable();
160 ad=attrTable->addKey (k,StringList);
164 sl <<"val 1"<<"val 2"<< "val 3";
165 ad->setValue (QVariant (sl));
167 //attrTable->addValue ("Key A","P 1");
168 //attrTable->addValue ("Key A","P 2");
169 //attrTable->addValue ("Key A","P 3");
170 //attrTable->addValue ("Key A","P 4");
172 ad=attrTable->addKey (k,FreeString);
175 //attrTable->addValue ("Key B","w1");
176 //attrTable->addValue ("Key B","w2");
178 k="C - UniqueString";
179 ad=attrTable->addKey (k,UniqueString);
182 //attrTable->addKey ("Key Prio");
183 //attrTable->addValue ("Key Prio","Prio 1");
184 //attrTable->addValue ("Key Prio","Prio 2");
188 MapEditor::~MapEditor()
190 //cout <<"Destructor MapEditor\n";
191 autosaveTimer->stop();
192 fileChangedTimer->stop();
194 // tmpMapDir is in tmpVymDir, so it gets removed automagically when vym closes
196 //removeDir(QDir(tmpMapDir));
200 VymModel* MapEditor::getModel()
205 QGraphicsScene * MapEditor::getScene()
210 MapEditor::State MapEditor::getState()
215 void MapEditor::setStateEditHeading(bool s)
219 if (state==Idle) state=EditHeading;
225 bool MapEditor::isRepositionBlocked()
227 return blockReposition;
230 void MapEditor::setSaveStateBlocked(bool b)
235 bool MapEditor::isSelectBlocked()
237 if (state==EditHeading)
243 QString MapEditor::getName (const LinkableMapObj *lmo)
246 if (!lmo) return QString("Error: NULL has no name!");
248 if ((typeid(*lmo) == typeid(BranchObj) ||
249 typeid(*lmo) == typeid(MapCenterObj)))
252 s=(((BranchObj*)lmo)->getHeading());
253 if (s=="") s="unnamed";
254 return QString("branch (%1)").arg(s);
256 if ((typeid(*lmo) == typeid(FloatImageObj) ))
257 return QString ("floatimage [%1]").arg(((FloatImageObj*)lmo)->getOriginalFilename());
258 return QString("Unknown type has no name!");
261 void MapEditor::makeTmpDirs()
263 // Create unique temporary directories
264 tmpMapDir = tmpVymDir+QString("/mapeditor-%1").arg(mapNum);
265 histPath = tmpMapDir+"/history";
270 QString MapEditor::saveToDir(const QString &tmpdir, const QString &prefix, bool writeflags, const QPointF &offset, LinkableMapObj *saveSel)
272 // tmpdir temporary directory to which data will be written
273 // prefix mapname, which will be appended to images etc.
274 // writeflags Only write flags for "real" save of map, not undo
275 // offset offset of bbox of whole map in scene.
276 // Needed for XML export
282 case LinkableMapObj::Line:
285 case LinkableMapObj::Parabel:
288 case LinkableMapObj::PolyLine:
292 ls="StylePolyParabel";
296 QString s="<?xml version=\"1.0\" encoding=\"utf-8\"?><!DOCTYPE vymmap>\n";
298 if (linkcolorhint==LinkableMapObj::HeadingColor)
299 colhint=attribut("linkColorHint","HeadingColor");
301 QString mapAttr=attribut("version",vymVersion);
303 mapAttr+= attribut("author",model->getAuthor()) +
304 attribut("comment",model->getComment()) +
305 attribut("date",model->getDate()) +
306 attribut("backgroundColor", mapScene->backgroundBrush().color().name() ) +
307 attribut("selectionColor", xelection.getColor().name() ) +
308 attribut("linkStyle", ls ) +
309 attribut("linkColor", defLinkColor.name() ) +
310 attribut("defXLinkColor", defXLinkColor.name() ) +
311 attribut("defXLinkWidth", QString().setNum(defXLinkWidth,10) ) +
313 s+=beginElement("vymmap",mapAttr);
316 // Find the used flags while traversing the tree
317 standardFlagsDefault->resetUsedCounter();
319 // Reset the counters before saving
320 // TODO constr. of FIO creates lots of objects, better do this in some other way...
321 FloatImageObj (mapScene).resetSaveCounter();
323 // Build xml recursivly
324 if (!saveSel || typeid (*saveSel) == typeid (MapCenterObj))
325 // Save complete map, if saveSel not set
326 s+=model->saveToDir(tmpdir,prefix,writeflags,offset);
329 if ( typeid(*saveSel) == typeid(BranchObj) )
331 s+=((BranchObj*)(saveSel))->saveToDir(tmpdir,prefix,offset);
332 else if ( typeid(*saveSel) == typeid(FloatImageObj) )
334 s+=((FloatImageObj*)(saveSel))->saveToDir(tmpdir,prefix);
337 // Save local settings
338 s+=settings.getDataXML (destPath);
341 if (!xelection.isEmpty() && !saveSel )
342 s+=valueElement("select",xelection.getSelectString());
345 s+=endElement("vymmap");
348 standardFlagsDefault->saveToDir (tmpdir+"/flags/","",writeflags);
352 QString MapEditor::getHistoryDir()
354 QString histName(QString("history-%1").arg(curStep));
355 return (tmpMapDir+"/"+histName);
358 void MapEditor::saveState(const SaveMode &savemode, const QString &undoSelection, const QString &undoCom, const QString &redoSelection, const QString &redoCom, const QString &comment, LinkableMapObj *saveSel)
360 sendData(redoCom); //FIXME testing
365 if (blockSaveState) return;
367 if (debug) cout << "ME::saveState() for "<<qPrintable (mapName)<<endl;
369 // Find out current undo directory
370 if (undosAvail<stepsTotal) undosAvail++;
372 if (curStep>stepsTotal) curStep=1;
374 QString backupXML="";
375 QString histDir=getHistoryDir();
376 QString bakMapPath=histDir+"/map.xml";
378 // Create histDir if not available
381 makeSubDirs (histDir);
383 // Save depending on how much needs to be saved
385 backupXML=saveToDir (histDir,mapName+"-",false, QPointF (),saveSel);
387 QString undoCommand="";
388 if (savemode==UndoCommand)
392 else if (savemode==PartOfMap )
395 undoCommand.replace ("PATH",bakMapPath);
398 if (!backupXML.isEmpty())
399 // Write XML Data to disk
400 saveStringToDisk (bakMapPath,backupXML);
402 // We would have to save all actions in a tree, to keep track of
403 // possible redos after a action. Possible, but we are too lazy: forget about redos.
406 // Write the current state to disk
407 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
408 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
409 undoSet.setEntry ("/history/curStep",QString::number(curStep));
410 undoSet.setEntry (QString("/history/step-%1/undoCommand").arg(curStep),undoCommand);
411 undoSet.setEntry (QString("/history/step-%1/undoSelection").arg(curStep),undoSelection);
412 undoSet.setEntry (QString("/history/step-%1/redoCommand").arg(curStep),redoCom);
413 undoSet.setEntry (QString("/history/step-%1/redoSelection").arg(curStep),redoSelection);
414 undoSet.setEntry (QString("/history/step-%1/comment").arg(curStep),comment);
415 undoSet.setEntry (QString("/history/version"),vymVersion);
416 undoSet.writeSettings(histPath);
420 // TODO remove after testing
421 //cout << " into="<< histPath.toStdString()<<endl;
422 cout << " stepsTotal="<<stepsTotal<<
423 ", undosAvail="<<undosAvail<<
424 ", redosAvail="<<redosAvail<<
425 ", curStep="<<curStep<<endl;
426 cout << " ---------------------------"<<endl;
427 cout << " comment="<<comment.toStdString()<<endl;
428 cout << " undoCom="<<undoCommand.toStdString()<<endl;
429 cout << " undoSel="<<undoSelection.toStdString()<<endl;
430 cout << " redoCom="<<redoCom.toStdString()<<endl;
431 cout << " redoSel="<<redoSelection.toStdString()<<endl;
432 if (saveSel) cout << " saveSel="<<qPrintable (model->getSelectString(saveSel))<<endl;
433 cout << " ---------------------------"<<endl;
436 mainWindow->updateHistory (undoSet);
442 void MapEditor::saveStateChangingPart(LinkableMapObj *undoSel, LinkableMapObj* redoSel, const QString &rc, const QString &comment)
444 // save the selected part of the map, Undo will replace part of map
445 QString undoSelection="";
447 undoSelection=model->getSelectString(undoSel);
449 qWarning ("MapEditor::saveStateChangingPart no undoSel given!");
450 QString redoSelection="";
452 redoSelection=model->getSelectString(undoSel);
454 qWarning ("MapEditor::saveStateChangingPart no redoSel given!");
457 saveState (PartOfMap,
458 undoSelection, "addMapReplace (\"PATH\")",
464 void MapEditor::saveStateRemovingPart(LinkableMapObj *redoSel, const QString &comment)
468 qWarning ("MapEditor::saveStateRemovingPart no redoSel given!");
471 QString undoSelection=model->getSelectString (redoSel->getParObj());
472 QString redoSelection=model->getSelectString(redoSel);
473 if (typeid(*redoSel) == typeid(BranchObj) )
475 // save the selected branch of the map, Undo will insert part of map
476 saveState (PartOfMap,
477 undoSelection, QString("addMapInsert (\"PATH\",%1)").arg(((BranchObj*)redoSel)->getNum()),
478 redoSelection, "delete ()",
485 void MapEditor::saveState(LinkableMapObj *undoSel, const QString &uc, LinkableMapObj *redoSel, const QString &rc, const QString &comment)
487 // "Normal" savestate: save commands, selections and comment
488 // so just save commands for undo and redo
489 // and use current selection
491 QString redoSelection="";
492 if (redoSel) redoSelection=model->getSelectString(redoSel);
493 QString undoSelection="";
494 if (undoSel) undoSelection=model->getSelectString(undoSel);
496 saveState (UndoCommand,
503 void MapEditor::saveState(const QString &undoSel, const QString &uc, const QString &redoSel, const QString &rc, const QString &comment)
505 // "Normal" savestate: save commands, selections and comment
506 // so just save commands for undo and redo
507 // and use current selection
508 saveState (UndoCommand,
515 void MapEditor::saveState(const QString &uc, const QString &rc, const QString &comment)
517 // "Normal" savestate applied to model (no selection needed):
518 // save commands and comment
519 saveState (UndoCommand,
527 void MapEditor::parseAtom(const QString &atom)
529 BranchObj *selb=xelection.getBranch();
535 // Split string s into command and parameters
536 parser.parseAtom (atom);
537 QString com=parser.getCommand();
540 /////////////////////////////////////////////////////////////////////
541 if (com=="addBranch")
543 if (xelection.isEmpty())
545 parser.setError (Aborted,"Nothing selected");
548 parser.setError (Aborted,"Type of selection is not a branch");
553 if (parser.checkParCount(pl))
555 if (parser.parCount()==0)
559 n=parser.parInt (ok,0);
560 if (ok ) addNewBranch (n);
564 /////////////////////////////////////////////////////////////////////
565 } else if (com=="addBranchBefore")
567 if (xelection.isEmpty())
569 parser.setError (Aborted,"Nothing selected");
572 parser.setError (Aborted,"Type of selection is not a branch");
575 if (parser.parCount()==0)
577 addNewBranchBefore ();
580 /////////////////////////////////////////////////////////////////////
581 } else if (com==QString("addMapCenter"))
583 if (parser.checkParCount(2))
585 x=parser.parDouble (ok,0);
588 y=parser.parDouble (ok,1);
589 if (ok) model->addMapCenter (QPointF(x,y));
592 /////////////////////////////////////////////////////////////////////
593 } else if (com==QString("addMapReplace"))
595 if (xelection.isEmpty())
597 parser.setError (Aborted,"Nothing selected");
600 parser.setError (Aborted,"Type of selection is not a branch");
601 } else if (parser.checkParCount(1))
603 //s=parser.parString (ok,0); // selection
604 t=parser.parString (ok,0); // path to map
605 if (QDir::isRelativePath(t)) t=(tmpMapDir + "/"+t);
606 addMapReplaceInt(model->getSelectString(selb),t);
608 /////////////////////////////////////////////////////////////////////
609 } else if (com==QString("addMapInsert"))
611 if (xelection.isEmpty())
613 parser.setError (Aborted,"Nothing selected");
616 parser.setError (Aborted,"Type of selection is not a branch");
619 if (parser.checkParCount(2))
621 t=parser.parString (ok,0); // path to map
622 n=parser.parInt(ok,1); // position
623 if (QDir::isRelativePath(t)) t=(tmpMapDir + "/"+t);
624 addMapInsertInt(t,n);
627 /////////////////////////////////////////////////////////////////////
628 } else if (com=="clearFlags")
630 if (xelection.isEmpty() )
632 parser.setError (Aborted,"Nothing selected");
635 parser.setError (Aborted,"Type of selection is not a branch");
636 } else if (parser.checkParCount(0))
638 selb->clearStandardFlags();
639 selb->updateFlagsToolbar();
641 /////////////////////////////////////////////////////////////////////
642 } else if (com=="colorBranch")
644 if (xelection.isEmpty())
646 parser.setError (Aborted,"Nothing selected");
649 parser.setError (Aborted,"Type of selection is not a branch");
650 } else if (parser.checkParCount(1))
652 QColor c=parser.parColor (ok,0);
653 if (ok) colorBranch (c);
655 /////////////////////////////////////////////////////////////////////
656 } else if (com=="colorSubtree")
658 if (xelection.isEmpty())
660 parser.setError (Aborted,"Nothing selected");
663 parser.setError (Aborted,"Type of selection is not a branch");
664 } else if (parser.checkParCount(1))
666 QColor c=parser.parColor (ok,0);
667 if (ok) colorSubtree (c);
669 /////////////////////////////////////////////////////////////////////
670 } else if (com=="copy")
672 if (xelection.isEmpty())
674 parser.setError (Aborted,"Nothing selected");
677 parser.setError (Aborted,"Type of selection is not a branch");
678 } else if (parser.checkParCount(0))
680 //FIXME missing action for copy
682 /////////////////////////////////////////////////////////////////////
683 } else if (com=="cut")
685 if (xelection.isEmpty())
687 parser.setError (Aborted,"Nothing selected");
688 } else if ( xelection.type()!=Selection::Branch &&
689 xelection.type()!=Selection::MapCenter &&
690 xelection.type()!=Selection::FloatImage )
692 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
693 } else if (parser.checkParCount(0))
697 /////////////////////////////////////////////////////////////////////
698 } else if (com=="delete")
700 if (xelection.isEmpty())
702 parser.setError (Aborted,"Nothing selected");
704 /*else if (xelection.type() != Selection::Branch && xelection.type() != Selection::FloatImage )
706 parser.setError (Aborted,"Type of selection is wrong.");
709 else if (parser.checkParCount(0))
713 /////////////////////////////////////////////////////////////////////
714 } else if (com=="deleteKeepChilds")
716 if (xelection.isEmpty())
718 parser.setError (Aborted,"Nothing selected");
721 parser.setError (Aborted,"Type of selection is not a branch");
722 } else if (parser.checkParCount(0))
726 /////////////////////////////////////////////////////////////////////
727 } else if (com=="deleteChilds")
729 if (xelection.isEmpty())
731 parser.setError (Aborted,"Nothing selected");
734 parser.setError (Aborted,"Type of selection is not a branch");
735 } else if (parser.checkParCount(0))
739 /////////////////////////////////////////////////////////////////////
740 } else if (com=="exportASCII")
744 if (parser.parCount()>=1)
745 // Hey, we even have a filename
746 fname=parser.parString(ok,0);
749 parser.setError (Aborted,"Could not read filename");
752 exportASCII (fname,false);
754 /////////////////////////////////////////////////////////////////////
755 } else if (com=="exportImage")
759 if (parser.parCount()>=2)
760 // Hey, we even have a filename
761 fname=parser.parString(ok,0);
764 parser.setError (Aborted,"Could not read filename");
767 QString format="PNG";
768 if (parser.parCount()>=2)
770 format=parser.parString(ok,1);
772 exportImage (fname,false,format);
774 /////////////////////////////////////////////////////////////////////
775 } else if (com=="exportXHTML")
779 if (parser.parCount()>=2)
780 // Hey, we even have a filename
781 fname=parser.parString(ok,1);
784 parser.setError (Aborted,"Could not read filename");
787 exportXHTML (fname,false);
789 /////////////////////////////////////////////////////////////////////
790 } else if (com=="exportXML")
794 if (parser.parCount()>=2)
795 // Hey, we even have a filename
796 fname=parser.parString(ok,1);
799 parser.setError (Aborted,"Could not read filename");
802 exportXML (fname,false);
804 /////////////////////////////////////////////////////////////////////
805 } else if (com=="importDir")
807 if (xelection.isEmpty())
809 parser.setError (Aborted,"Nothing selected");
812 parser.setError (Aborted,"Type of selection is not a branch");
813 } else if (parser.checkParCount(1))
815 s=parser.parString(ok,0);
816 if (ok) importDirInt(s);
818 /////////////////////////////////////////////////////////////////////
819 } else if (com=="linkTo")
821 if (xelection.isEmpty())
823 parser.setError (Aborted,"Nothing selected");
826 if (parser.checkParCount(4))
828 // 0 selectstring of parent
829 // 1 num in parent (for branches)
830 // 2,3 x,y of mainbranch or mapcenter
831 s=parser.parString(ok,0);
832 LinkableMapObj *dst=model->findObjBySelect (s);
835 if (typeid(*dst) == typeid(BranchObj) )
837 // Get number in parent
838 n=parser.parInt (ok,1);
841 selb->linkTo ((BranchObj*)(dst),n);
844 } else if (typeid(*dst) == typeid(MapCenterObj) )
846 selb->linkTo ((BranchObj*)(dst),-1);
847 // Get coordinates of mainbranch
848 x=parser.parDouble(ok,2);
851 y=parser.parDouble(ok,3);
861 } else if ( xelection.type() == Selection::FloatImage)
863 if (parser.checkParCount(1))
865 // 0 selectstring of parent
866 s=parser.parString(ok,0);
867 LinkableMapObj *dst=model->findObjBySelect (s);
870 if (typeid(*dst) == typeid(BranchObj) ||
871 typeid(*dst) == typeid(MapCenterObj))
872 linkTo (model->getSelectString(dst));
874 parser.setError (Aborted,"Destination is not a branch");
877 parser.setError (Aborted,"Type of selection is not a floatimage or branch");
878 /////////////////////////////////////////////////////////////////////
879 } else if (com=="loadImage")
881 if (xelection.isEmpty())
883 parser.setError (Aborted,"Nothing selected");
886 parser.setError (Aborted,"Type of selection is not a branch");
887 } else if (parser.checkParCount(1))
889 s=parser.parString(ok,0);
890 if (ok) loadFloatImageInt (s);
892 /////////////////////////////////////////////////////////////////////
893 } else if (com=="moveBranchUp")
895 if (xelection.isEmpty() )
897 parser.setError (Aborted,"Nothing selected");
900 parser.setError (Aborted,"Type of selection is not a branch");
901 } else if (parser.checkParCount(0))
905 /////////////////////////////////////////////////////////////////////
906 } else if (com=="moveBranchDown")
908 if (xelection.isEmpty() )
910 parser.setError (Aborted,"Nothing selected");
913 parser.setError (Aborted,"Type of selection is not a branch");
914 } else if (parser.checkParCount(0))
918 /////////////////////////////////////////////////////////////////////
919 } else if (com=="move")
921 if (xelection.isEmpty() )
923 parser.setError (Aborted,"Nothing selected");
924 } else if ( xelection.type()!=Selection::Branch &&
925 xelection.type()!=Selection::MapCenter &&
926 xelection.type()!=Selection::FloatImage )
928 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
929 } else if (parser.checkParCount(2))
931 x=parser.parDouble (ok,0);
934 y=parser.parDouble (ok,1);
938 /////////////////////////////////////////////////////////////////////
939 } else if (com=="moveRel")
941 if (xelection.isEmpty() )
943 parser.setError (Aborted,"Nothing selected");
944 } else if ( xelection.type()!=Selection::Selection::Branch &&
945 xelection.type()!=Selection::Selection::MapCenter &&
946 xelection.type()!=Selection::Selection::FloatImage )
948 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
949 } else if (parser.checkParCount(2))
951 x=parser.parDouble (ok,0);
954 y=parser.parDouble (ok,1);
955 if (ok) moveRel (x,y);
958 /////////////////////////////////////////////////////////////////////
959 } else if (com=="nop")
961 /////////////////////////////////////////////////////////////////////
962 } else if (com=="paste")
964 if (xelection.isEmpty() )
966 parser.setError (Aborted,"Nothing selected");
969 parser.setError (Aborted,"Type of selection is not a branch");
970 } else if (parser.checkParCount(1))
972 n=parser.parInt (ok,0);
973 if (ok) pasteNoSave(n);
975 /////////////////////////////////////////////////////////////////////
976 } else if (com=="qa")
978 if (xelection.isEmpty() )
980 parser.setError (Aborted,"Nothing selected");
983 parser.setError (Aborted,"Type of selection is not a branch");
984 } else if (parser.checkParCount(4))
987 c=parser.parString (ok,0);
990 parser.setError (Aborted,"No comment given");
993 s=parser.parString (ok,1);
996 parser.setError (Aborted,"First parameter is not a string");
999 t=parser.parString (ok,2);
1002 parser.setError (Aborted,"Condition is not a string");
1005 u=parser.parString (ok,3);
1008 parser.setError (Aborted,"Third parameter is not a string");
1013 parser.setError (Aborted,"Unknown type: "+s);
1018 parser.setError (Aborted,"Unknown operator: "+t);
1023 parser.setError (Aborted,"Type of selection is not a branch");
1026 if (selb->getHeading() == u)
1028 cout << "PASSED: " << qPrintable (c) << endl;
1031 cout << "FAILED: " << qPrintable (c) << endl;
1041 /////////////////////////////////////////////////////////////////////
1042 } else if (com=="saveImage")
1044 FloatImageObj *fio=xelection.getFloatImage();
1047 parser.setError (Aborted,"Type of selection is not an image");
1048 } else if (parser.checkParCount(2))
1050 s=parser.parString(ok,0);
1053 t=parser.parString(ok,1);
1054 if (ok) saveFloatImageInt (fio,t,s);
1057 /////////////////////////////////////////////////////////////////////
1058 } else if (com=="scroll")
1060 if (xelection.isEmpty() )
1062 parser.setError (Aborted,"Nothing selected");
1065 parser.setError (Aborted,"Type of selection is not a branch");
1066 } else if (parser.checkParCount(0))
1068 if (!scrollBranch (selb))
1069 parser.setError (Aborted,"Could not scroll branch");
1071 /////////////////////////////////////////////////////////////////////
1072 } else if (com=="select")
1074 if (parser.checkParCount(1))
1076 s=parser.parString(ok,0);
1079 /////////////////////////////////////////////////////////////////////
1080 } else if (com=="selectLastBranch")
1082 if (xelection.isEmpty() )
1084 parser.setError (Aborted,"Nothing selected");
1087 parser.setError (Aborted,"Type of selection is not a branch");
1088 } else if (parser.checkParCount(0))
1090 BranchObj *bo=selb->getLastBranch();
1092 parser.setError (Aborted,"Could not select last branch");
1096 /////////////////////////////////////////////////////////////////////
1097 } else if (com=="selectLastImage")
1099 if (xelection.isEmpty() )
1101 parser.setError (Aborted,"Nothing selected");
1104 parser.setError (Aborted,"Type of selection is not a branch");
1105 } else if (parser.checkParCount(0))
1107 FloatImageObj *fio=selb->getLastFloatImage();
1109 parser.setError (Aborted,"Could not select last image");
1113 /////////////////////////////////////////////////////////////////////
1114 } else if (com=="selectLatestAdded")
1116 if (latestSelection.isEmpty() )
1118 parser.setError (Aborted,"No latest added object");
1121 if (!select (latestSelection))
1122 parser.setError (Aborted,"Could not select latest added object "+latestSelection);
1124 /////////////////////////////////////////////////////////////////////
1125 } else if (com=="setFrameType")
1127 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
1129 parser.setError (Aborted,"Type of selection does not allow setting frame type");
1131 else if (parser.checkParCount(1))
1133 s=parser.parString(ok,0);
1134 if (ok) setFrameType (s);
1136 /////////////////////////////////////////////////////////////////////
1137 } else if (com=="setFramePenColor")
1139 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
1141 parser.setError (Aborted,"Type of selection does not allow setting of pen color");
1143 else if (parser.checkParCount(1))
1145 QColor c=parser.parColor(ok,0);
1146 if (ok) setFramePenColor (c);
1148 /////////////////////////////////////////////////////////////////////
1149 } else if (com=="setFrameBrushColor")
1151 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
1153 parser.setError (Aborted,"Type of selection does not allow setting brush color");
1155 else if (parser.checkParCount(1))
1157 QColor c=parser.parColor(ok,0);
1158 if (ok) setFrameBrushColor (c);
1160 /////////////////////////////////////////////////////////////////////
1161 } else if (com=="setFramePadding")
1163 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
1165 parser.setError (Aborted,"Type of selection does not allow setting frame padding");
1167 else if (parser.checkParCount(1))
1169 n=parser.parInt(ok,0);
1170 if (ok) setFramePadding(n);
1172 /////////////////////////////////////////////////////////////////////
1173 } else if (com=="setFrameBorderWidth")
1175 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
1177 parser.setError (Aborted,"Type of selection does not allow setting frame border width");
1179 else if (parser.checkParCount(1))
1181 n=parser.parInt(ok,0);
1182 if (ok) setFrameBorderWidth (n);
1184 /////////////////////////////////////////////////////////////////////
1185 } else if (com=="setMapAuthor")
1187 if (parser.checkParCount(1))
1189 s=parser.parString(ok,0);
1190 if (ok) setMapAuthor (s);
1192 /////////////////////////////////////////////////////////////////////
1193 } else if (com=="setMapComment")
1195 if (parser.checkParCount(1))
1197 s=parser.parString(ok,0);
1198 if (ok) setMapComment(s);
1200 /////////////////////////////////////////////////////////////////////
1201 } else if (com=="setMapBackgroundColor")
1203 if (xelection.isEmpty() )
1205 parser.setError (Aborted,"Nothing selected");
1206 } else if (! xelection.getBranch() )
1208 parser.setError (Aborted,"Type of selection is not a branch");
1209 } else if (parser.checkParCount(1))
1211 QColor c=parser.parColor (ok,0);
1212 if (ok) setMapBackgroundColor (c);
1214 /////////////////////////////////////////////////////////////////////
1215 } else if (com=="setMapDefLinkColor")
1217 if (xelection.isEmpty() )
1219 parser.setError (Aborted,"Nothing selected");
1222 parser.setError (Aborted,"Type of selection is not a branch");
1223 } else if (parser.checkParCount(1))
1225 QColor c=parser.parColor (ok,0);
1226 if (ok) setMapDefLinkColor (c);
1228 /////////////////////////////////////////////////////////////////////
1229 } else if (com=="setMapLinkStyle")
1231 if (parser.checkParCount(1))
1233 s=parser.parString (ok,0);
1234 if (ok) setMapLinkStyle(s);
1236 /////////////////////////////////////////////////////////////////////
1237 } else if (com=="setHeading")
1239 if (xelection.isEmpty() )
1241 parser.setError (Aborted,"Nothing selected");
1244 parser.setError (Aborted,"Type of selection is not a branch");
1245 } else if (parser.checkParCount(1))
1247 s=parser.parString (ok,0);
1251 /////////////////////////////////////////////////////////////////////
1252 } else if (com=="setHideExport")
1254 if (xelection.isEmpty() )
1256 parser.setError (Aborted,"Nothing selected");
1257 } else if (xelection.type()!=Selection::Branch && xelection.type() != Selection::MapCenter &&xelection.type()!=Selection::FloatImage)
1259 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
1260 } else if (parser.checkParCount(1))
1262 b=parser.parBool(ok,0);
1263 if (ok) setHideExport (b);
1265 /////////////////////////////////////////////////////////////////////
1266 } else if (com=="setIncludeImagesHorizontally")
1268 if (xelection.isEmpty() )
1270 parser.setError (Aborted,"Nothing selected");
1273 parser.setError (Aborted,"Type of selection is not a branch");
1274 } else if (parser.checkParCount(1))
1276 b=parser.parBool(ok,0);
1277 if (ok) setIncludeImagesHor(b);
1279 /////////////////////////////////////////////////////////////////////
1280 } else if (com=="setIncludeImagesVertically")
1282 if (xelection.isEmpty() )
1284 parser.setError (Aborted,"Nothing selected");
1287 parser.setError (Aborted,"Type of selection is not a branch");
1288 } else if (parser.checkParCount(1))
1290 b=parser.parBool(ok,0);
1291 if (ok) setIncludeImagesVer(b);
1293 /////////////////////////////////////////////////////////////////////
1294 } else if (com=="setHideLinkUnselected")
1296 if (xelection.isEmpty() )
1298 parser.setError (Aborted,"Nothing selected");
1299 } else if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
1301 parser.setError (Aborted,"Type of selection does not allow hiding the link");
1302 } else if (parser.checkParCount(1))
1304 b=parser.parBool(ok,0);
1305 if (ok) setHideLinkUnselected(b);
1307 /////////////////////////////////////////////////////////////////////
1308 } else if (com=="setSelectionColor")
1310 if (parser.checkParCount(1))
1312 QColor c=parser.parColor (ok,0);
1313 if (ok) setSelectionColorInt (c);
1315 /////////////////////////////////////////////////////////////////////
1316 } else if (com=="setURL")
1318 if (xelection.isEmpty() )
1320 parser.setError (Aborted,"Nothing selected");
1323 parser.setError (Aborted,"Type of selection is not a branch");
1324 } else if (parser.checkParCount(1))
1326 s=parser.parString (ok,0);
1329 /////////////////////////////////////////////////////////////////////
1330 } else if (com=="setVymLink")
1332 if (xelection.isEmpty() )
1334 parser.setError (Aborted,"Nothing selected");
1337 parser.setError (Aborted,"Type of selection is not a branch");
1338 } else if (parser.checkParCount(1))
1340 s=parser.parString (ok,0);
1341 if (ok) setVymLinkInt(s);
1344 /////////////////////////////////////////////////////////////////////
1345 else if (com=="setFlag")
1347 if (xelection.isEmpty() )
1349 parser.setError (Aborted,"Nothing selected");
1352 parser.setError (Aborted,"Type of selection is not a branch");
1353 } else if (parser.checkParCount(1))
1355 s=parser.parString(ok,0);
1358 selb->activateStandardFlag(s);
1359 selb->updateFlagsToolbar();
1362 /////////////////////////////////////////////////////////////////////
1363 } else if (com=="setFrameType")
1365 if (xelection.isEmpty() )
1367 parser.setError (Aborted,"Nothing selected");
1370 parser.setError (Aborted,"Type of selection is not a branch");
1371 } else if (parser.checkParCount(1))
1373 s=parser.parString(ok,0);
1377 /////////////////////////////////////////////////////////////////////
1378 } else if (com=="sortChildren")
1380 if (xelection.isEmpty() )
1382 parser.setError (Aborted,"Nothing selected");
1385 parser.setError (Aborted,"Type of selection is not a branch");
1386 } else if (parser.checkParCount(0))
1390 /////////////////////////////////////////////////////////////////////
1391 } else if (com=="toggleFlag")
1393 if (xelection.isEmpty() )
1395 parser.setError (Aborted,"Nothing selected");
1398 parser.setError (Aborted,"Type of selection is not a branch");
1399 } else if (parser.checkParCount(1))
1401 s=parser.parString(ok,0);
1404 selb->toggleStandardFlag(s);
1405 selb->updateFlagsToolbar();
1408 /////////////////////////////////////////////////////////////////////
1409 } else if (com=="unscroll")
1411 if (xelection.isEmpty() )
1413 parser.setError (Aborted,"Nothing selected");
1416 parser.setError (Aborted,"Type of selection is not a branch");
1417 } else if (parser.checkParCount(0))
1419 if (!unscrollBranch (selb))
1420 parser.setError (Aborted,"Could not unscroll branch");
1422 /////////////////////////////////////////////////////////////////////
1423 } else if (com=="unscrollChilds")
1425 if (xelection.isEmpty() )
1427 parser.setError (Aborted,"Nothing selected");
1430 parser.setError (Aborted,"Type of selection is not a branch");
1431 } else if (parser.checkParCount(0))
1435 /////////////////////////////////////////////////////////////////////
1436 } else if (com=="unsetFlag")
1438 if (xelection.isEmpty() )
1440 parser.setError (Aborted,"Nothing selected");
1443 parser.setError (Aborted,"Type of selection is not a branch");
1444 } else if (parser.checkParCount(1))
1446 s=parser.parString(ok,0);
1449 selb->deactivateStandardFlag(s);
1450 selb->updateFlagsToolbar();
1454 parser.setError (Aborted,"Unknown command");
1457 if (parser.errorLevel()==NoError)
1459 // setChanged(); FIXME should not be called e.g. for export?!
1460 model->reposition();
1464 // TODO Error handling
1465 qWarning("MapEditor::parseAtom: Error!");
1466 qWarning(parser.errorMessage());
1470 void MapEditor::runScript (QString script)
1472 parser.setScript (script);
1474 while (parser.next() )
1475 parseAtom(parser.getAtom());
1478 bool MapEditor::isDefault()
1483 bool MapEditor::hasChanged()
1488 void MapEditor::setChanged()
1491 autosaveTimer->start(settings.value("/mapeditor/autosave/ms/",300000).toInt());
1499 void MapEditor::closeMap()
1501 // Unselect before disabling the toolbar actions
1502 if (!xelection.isEmpty() ) xelection.unselect();
1510 void MapEditor::setFilePath(QString fpath, QString destname)
1512 if (fpath.isEmpty() || fpath=="")
1519 filePath=fpath; // becomes absolute path
1520 fileName=fpath; // gets stripped of path
1521 destPath=destname; // needed for vymlinks and during load to reset fileChangedTime
1523 // If fpath is not an absolute path, complete it
1524 filePath=QDir(fpath).absPath();
1525 fileDir=filePath.left (1+filePath.findRev ("/"));
1527 // Set short name, too. Search from behind:
1528 int i=fileName.findRev("/");
1529 if (i>=0) fileName=fileName.remove (0,i+1);
1531 // Forget the .vym (or .xml) for name of map
1532 mapName=fileName.left(fileName.findRev(".",-1,true) );
1536 void MapEditor::setFilePath(QString fpath)
1538 setFilePath (fpath,fpath);
1541 QString MapEditor::getFilePath()
1546 QString MapEditor::getFileName()
1551 QString MapEditor::getMapName()
1556 QString MapEditor::getDestPath()
1561 ErrorCode MapEditor::load (QString fname, const LoadMode &lmode, const FileType &ftype)
1563 ErrorCode err=success;
1565 parseBaseHandler *handler;
1569 case VymMap: handler=new parseVYMHandler; break;
1570 case FreemindMap : handler=new parseFreemindHandler; break;
1572 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
1573 "Unknown FileType in MapEditor::load()");
1579 model->setMapEditor(this);
1580 // (map state is set later at end of load...)
1583 BranchObj *bo=xelection.getBranch();
1584 if (!bo) return aborted;
1585 if (lmode==ImportAdd)
1586 saveStateChangingPart(
1589 QString("addMapInsert (%1)").arg(fname),
1590 QString("Add map %1 to %2").arg(fname).arg(getName(bo)));
1592 saveStateChangingPart(
1595 QString("addMapReplace(%1)").arg(fname),
1596 QString("Add map %1 to %2").arg(fname).arg(getName(bo)));
1600 // Create temporary directory for packing
1602 QString tmpZipDir=makeTmpDir (ok,"vym-pack");
1605 QMessageBox::critical( 0, tr( "Critical Load Error" ),
1606 tr("Couldn't create temporary directory before load\n"));
1610 // Try to unzip file
1611 err=unzipDir (tmpZipDir,fname);
1621 // Look for mapname.xml
1622 xmlfile= fname.left(fname.findRev(".",-1,true));
1623 xmlfile=xmlfile.section( '/', -1 );
1624 QFile mfile( tmpZipDir + "/" + xmlfile + ".xml");
1625 if (!mfile.exists() )
1627 // mapname.xml does not exist, well,
1628 // maybe someone renamed the mapname.vym file...
1629 // Try to find any .xml in the toplevel
1630 // directory of the .vym file
1631 QStringList flist=QDir (tmpZipDir).entryList("*.xml");
1632 if (flist.count()==1)
1634 // Only one entry, take this one
1635 xmlfile=tmpZipDir + "/"+flist.first();
1638 for ( QStringList::Iterator it = flist.begin(); it != flist.end(); ++it )
1639 *it=tmpZipDir + "/" + *it;
1640 // TODO Multiple entries, load all (but only the first one into this ME)
1641 //mainWindow->fileLoadFromTmp (flist);
1642 //returnCode=1; // Silently forget this attempt to load
1643 qWarning ("MainWindow::load (fn) multimap found...");
1646 if (flist.isEmpty() )
1648 QMessageBox::critical( 0, tr( "Critical Load Error" ),
1649 tr("Couldn't find a map (*.xml) in .vym archive.\n"));
1652 } //file doesn't exist
1654 xmlfile=mfile.name();
1657 QFile file( xmlfile);
1659 // I am paranoid: file should exist anyway
1660 // according to check in mainwindow.
1661 if (!file.exists() )
1663 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
1664 tr(QString("Couldn't open map %1").arg(file.name())));
1668 bool blockSaveStateOrg=blockSaveState;
1669 blockReposition=true;
1670 blockSaveState=true;
1671 QXmlInputSource source( file);
1672 QXmlSimpleReader reader;
1673 reader.setContentHandler( handler );
1674 reader.setErrorHandler( handler );
1675 handler->setModel ( model);
1678 // We need to set the tmpDir in order to load files with rel. path
1683 tmpdir=fname.left(fname.findRev("/",-1));
1684 handler->setTmpDir (tmpdir);
1685 handler->setInputFile (file.name());
1686 handler->setLoadMode (lmode);
1687 bool ok = reader.parse( source );
1688 blockReposition=false;
1689 blockSaveState=blockSaveStateOrg;
1693 model->reposition(); // FIXME reposition the view instead...
1700 autosaveTimer->stop();
1703 // Reset timestamp to check for later updates of file
1704 fileChangedTime=QFileInfo (destPath).lastModified();
1707 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
1708 tr( handler->errorProtocol() ) );
1710 // Still return "success": the map maybe at least
1711 // partially read by the parser
1716 removeDir (QDir(tmpZipDir));
1723 ErrorCode MapEditor::save (const SaveMode &savemode)
1726 QString mapFileName;
1727 QString safeFilePath;
1729 ErrorCode err=success;
1733 mapFileName=mapName+".xml";
1735 // use name given by user, even if he chooses .doc
1736 mapFileName=fileName;
1738 // Look, if we should zip the data:
1741 QMessageBox mb( vymName,
1742 tr("The map %1\ndid not use the compressed "
1743 "vym file format.\nWriting it uncompressed will also write images \n"
1744 "and flags and thus may overwrite files in the "
1745 "given directory\n\nDo you want to write the map").arg(filePath),
1746 QMessageBox::Warning,
1747 QMessageBox::Yes | QMessageBox::Default,
1749 QMessageBox::Cancel | QMessageBox::Escape);
1750 mb.setButtonText( QMessageBox::Yes, tr("compressed (vym default)") );
1751 mb.setButtonText( QMessageBox::No, tr("uncompressed") );
1752 mb.setButtonText( QMessageBox::Cancel, tr("Cancel"));
1755 case QMessageBox::Yes:
1756 // save compressed (default file format)
1759 case QMessageBox::No:
1760 // save uncompressed
1763 case QMessageBox::Cancel:
1770 // First backup existing file, we
1771 // don't want to add to old zip archives
1775 if ( settings.value ("/mapeditor/writeBackupFile").toBool())
1777 QString backupFileName(destPath + "~");
1778 QFile backupFile(backupFileName);
1779 if (backupFile.exists() && !backupFile.remove())
1781 QMessageBox::warning(0, tr("Save Error"),
1782 tr("%1\ncould not be removed before saving").arg(backupFileName));
1784 else if (!f.rename(backupFileName))
1786 QMessageBox::warning(0, tr("Save Error"),
1787 tr("%1\ncould not be renamed before saving").arg(destPath));
1794 // Create temporary directory for packing
1796 tmpZipDir=makeTmpDir (ok,"vym-zip");
1799 QMessageBox::critical( 0, tr( "Critical Load Error" ),
1800 tr("Couldn't create temporary directory before save\n"));
1804 safeFilePath=filePath;
1805 setFilePath (tmpZipDir+"/"+ mapName+ ".xml", safeFilePath);
1808 // Create mapName and fileDir
1809 makeSubDirs (fileDir);
1812 if (savemode==CompleteMap || xelection.isEmpty())
1814 // Save complete map
1815 saveFile=saveToDir (fileDir,mapName+"-",true,QPointF(),NULL);
1818 autosaveTimer->stop();
1823 if (xelection.type()==Selection::FloatImage)
1826 saveFile=saveToDir (fileDir,mapName+"-",true,QPointF(),xelection.getBranch());
1827 // TODO take care of multiselections
1830 if (!saveStringToDisk(fileDir+mapFileName,saveFile))
1833 qWarning ("ME::saveStringToDisk failed!");
1839 if (err==success) err=zipDir (tmpZipDir,destPath);
1842 removeDir (QDir(tmpZipDir));
1844 // Restore original filepath outside of tmp zip dir
1845 setFilePath (safeFilePath);
1849 fileChangedTime=QFileInfo (destPath).lastModified();
1854 void MapEditor::print()
1858 printer = new QPrinter;
1859 printer->setColorMode (QPrinter::Color);
1860 printer->setPrinterName (settings.value("/mainwindow/printerName",printer->printerName()).toString());
1861 printer->setOutputFormat((QPrinter::OutputFormat)settings.value("/mainwindow/printerFormat",printer->outputFormat()).toInt());
1862 printer->setOutputFileName(settings.value("/mainwindow/printerFileName",printer->outputFileName()).toString());
1865 QRectF totalBBox=model->getTotalBBox();
1867 // Try to set orientation automagically
1868 // Note: Interpretation of generated postscript is amibiguous, if
1869 // there are problems with landscape mode, see
1870 // http://sdb.suse.de/de/sdb/html/jsmeix_print-cups-landscape-81.html
1872 if (totalBBox.width()>totalBBox.height())
1873 // recommend landscape
1874 printer->setOrientation (QPrinter::Landscape);
1876 // recommend portrait
1877 printer->setOrientation (QPrinter::Portrait);
1879 if ( printer->setup(this) )
1880 // returns false, if printing is canceled
1882 QPainter pp(printer);
1884 pp.setRenderHint(QPainter::Antialiasing,true);
1886 // Don't print the visualisation of selection
1887 xelection.unselect();
1889 QRectF mapRect=totalBBox;
1890 QGraphicsRectItem *frame=NULL;
1894 // Print frame around map
1895 mapRect.setRect (totalBBox.x()-10, totalBBox.y()-10,
1896 totalBBox.width()+20, totalBBox.height()+20);
1897 frame=mapScene->addRect (mapRect, QPen(Qt::black),QBrush(Qt::NoBrush));
1898 frame->setZValue(0);
1903 double paperAspect = (double)printer->width() / (double)printer->height();
1904 double mapAspect = (double)mapRect.width() / (double)mapRect.height();
1906 if (mapAspect>=paperAspect)
1908 // Fit horizontally to paper width
1909 //pp.setViewport(0,0, printer->width(),(int)(printer->width()/mapAspect) );
1910 viewBottom=(int)(printer->width()/mapAspect);
1913 // Fit vertically to paper height
1914 //pp.setViewport(0,0,(int)(printer->height()*mapAspect),printer->height());
1915 viewBottom=printer->height();
1920 // Print footer below map
1922 font.setPointSize(10);
1924 QRectF footerBox(0,viewBottom,printer->width(),15);
1925 pp.drawText ( footerBox,Qt::AlignLeft,"VYM - " +fileName);
1926 pp.drawText ( footerBox, Qt::AlignRight, QDate::currentDate().toString(Qt::TextDate));
1930 QRectF (0,0,printer->width(),printer->height()-15),
1931 QRectF(mapRect.x(),mapRect.y(),mapRect.width(),mapRect.height())
1934 // Viewport has paper dimension
1935 if (frame) delete (frame);
1937 // Restore selection
1938 xelection.reselect();
1940 // Save settings in vymrc
1941 settings.writeEntry("/mainwindow/printerName",printer->printerName());
1942 settings.writeEntry("/mainwindow/printerFormat",printer->outputFormat());
1943 settings.writeEntry("/mainwindow/printerFileName",printer->outputFileName());
1947 void MapEditor::setAntiAlias (bool b)
1949 setRenderHint(QPainter::Antialiasing,b);
1952 void MapEditor::setSmoothPixmap(bool b)
1954 setRenderHint(QPainter::SmoothPixmapTransform,b);
1957 QPixmap MapEditor::getPixmap()
1959 QRectF mapRect=model->getTotalBBox();
1960 QPixmap pix((int)mapRect.width()+2,(int)mapRect.height()+1);
1963 pp.setRenderHints(renderHints());
1965 // Don't print the visualisation of selection
1966 xelection.unselect();
1968 mapScene->render ( &pp,
1969 QRectF(0,0,mapRect.width()+2,mapRect.height()+2),
1970 QRectF(mapRect.x(),mapRect.y(),mapRect.width(),mapRect.height() ));
1972 // Restore selection
1973 xelection.reselect();
1978 void MapEditor::setHideTmpMode (HideTmpMode mode)
1981 model->setHideTmp (hidemode);
1982 model->reposition();
1986 HideTmpMode MapEditor::getHideTmpMode()
1991 void MapEditor::setExportMode (bool b)
1993 // should be called before and after exports
1994 // depending on the settings
1995 if (b && settings.value("/export/useHideExport","true")=="true")
1996 setHideTmpMode (HideExport);
1998 setHideTmpMode (HideNone);
2001 void MapEditor::exportASCII(QString fname,bool askName)
2004 ex.setModel (model);
2006 ex.setFile (mapName+".txt");
2012 //ex.addFilter ("TXT (*.txt)");
2013 ex.setDir(lastImageDir);
2014 //ex.setCaption(vymName+ " -" +tr("Export as ASCII")+" "+tr("(still experimental)"));
2019 setExportMode(true);
2021 setExportMode(false);
2025 void MapEditor::exportImage(QString fname, bool askName, QString format)
2029 fname=mapName+".png";
2036 QFileDialog *fd=new QFileDialog (this);
2037 fd->setCaption (tr("Export map as image"));
2038 fd->setDirectory (lastImageDir);
2039 fd->setFileMode(QFileDialog::AnyFile);
2040 fd->setFilters (imageIO.getFilters() );
2043 fl=fd->selectedFiles();
2045 format=imageIO.getType(fd->selectedFilter());
2049 setExportMode (true);
2050 QPixmap pix (getPixmap());
2051 pix.save(fname, format);
2052 setExportMode (false);
2055 void MapEditor::exportOOPresentation(const QString &fn, const QString &cf)
2059 ex.setModel (model);
2060 if (ex.setConfigFile(cf))
2062 setExportMode (true);
2063 ex.exportPresentation();
2064 setExportMode (false);
2068 void MapEditor::exportXHTML (const QString &dir, bool askForName)
2070 ExportXHTMLDialog dia(this);
2071 dia.setFilePath (filePath );
2072 dia.setMapName (mapName );
2074 if (dir!="") dia.setDir (dir);
2080 if (dia.exec()!=QDialog::Accepted)
2084 QDir d (dia.getDir());
2085 // Check, if warnings should be used before overwriting
2086 // the output directory
2087 if (d.exists() && d.count()>0)
2090 warn.showCancelButton (true);
2091 warn.setText(QString(
2092 "The directory %1 is not empty.\n"
2093 "Do you risk to overwrite some of its contents?").arg(d.path() ));
2094 warn.setCaption("Warning: Directory not empty");
2095 warn.setShowAgainName("mainwindow/overwrite-dir-xhtml");
2097 if (warn.exec()!=QDialog::Accepted) ok=false;
2104 exportXML (dia.getDir(),false );
2105 dia.doExport(mapName );
2106 //if (dia.hasChanged()) setChanged();
2110 void MapEditor::exportXML(QString dir, bool askForName)
2114 dir=browseDirectory(this,tr("Export XML to directory"));
2115 if (dir =="" && !reallyWriteDirectory(dir) )
2119 // Hide stuff during export, if settings want this
2120 setExportMode (true);
2122 // Create subdirectories
2125 // write to directory
2126 QString saveFile=saveToDir (dir,mapName+"-",true,model->getTotalBBox().topLeft() ,NULL);
2129 file.setName ( dir + "/"+mapName+".xml");
2130 if ( !file.open( QIODevice::WriteOnly ) )
2132 // This should neverever happen
2133 QMessageBox::critical (0,tr("Critical Export Error"),tr("MapEditor::exportXML couldn't open %1").arg(file.name()));
2137 // Write it finally, and write in UTF8, no matter what
2138 QTextStream ts( &file );
2139 ts.setEncoding (QTextStream::UnicodeUTF8);
2143 // Now write image, too
2144 exportImage (dir+"/images/"+mapName+".png",false,"PNG");
2146 setExportMode (false);
2149 void MapEditor::clear()
2151 xelection.unselect();
2155 void MapEditor::copy()
2157 LinkableMapObj *sel=xelection.single();
2160 if (redosAvail == 0)
2163 QString s=model->getSelectString(sel);
2164 saveState (PartOfMap, s, "nop ()", s, "copy ()","Copy selection to clipboard",sel );
2165 curClipboard=curStep;
2168 // Copy also to global clipboard, because we are at last step in history
2169 QString bakMapName(QString("history-%1").arg(curStep));
2170 QString bakMapDir(tmpMapDir +"/"+bakMapName);
2171 copyDir (bakMapDir,clipboardDir );
2173 clipboardEmpty=false;
2178 void MapEditor::redo()
2180 // Can we undo at all?
2181 if (redosAvail<1) return;
2183 bool blockSaveStateOrg=blockSaveState;
2184 blockSaveState=true;
2188 if (undosAvail<stepsTotal) undosAvail++;
2190 if (curStep>stepsTotal) curStep=1;
2191 QString undoCommand= undoSet.readEntry (QString("/history/step-%1/undoCommand").arg(curStep));
2192 QString undoSelection=undoSet.readEntry (QString("/history/step-%1/undoSelection").arg(curStep));
2193 QString redoCommand= undoSet.readEntry (QString("/history/step-%1/redoCommand").arg(curStep));
2194 QString redoSelection=undoSet.readEntry (QString("/history/step-%1/redoSelection").arg(curStep));
2195 QString comment=undoSet.readEntry (QString("/history/step-%1/comment").arg(curStep));
2196 QString version=undoSet.readEntry ("/history/version");
2198 /* TODO Maybe check for version, if we save the history
2199 if (!checkVersion(version))
2200 QMessageBox::warning(0,tr("Warning"),
2201 tr("Version %1 of saved undo/redo data\ndoes not match current vym version %2.").arg(version).arg(vymVersion));
2204 // Find out current undo directory
2205 QString bakMapDir(QString(tmpMapDir+"/undo-%1").arg(curStep));
2209 cout << "ME::redo() begin\n";
2210 cout << " undosAvail="<<undosAvail<<endl;
2211 cout << " redosAvail="<<redosAvail<<endl;
2212 cout << " curStep="<<curStep<<endl;
2213 cout << " ---------------------------"<<endl;
2214 cout << " comment="<<comment.toStdString()<<endl;
2215 cout << " undoCom="<<undoCommand.toStdString()<<endl;
2216 cout << " undoSel="<<undoSelection.toStdString()<<endl;
2217 cout << " redoCom="<<redoCommand.toStdString()<<endl;
2218 cout << " redoSel="<<redoSelection.toStdString()<<endl;
2219 cout << " ---------------------------"<<endl<<endl;
2222 // select object before redo
2223 if (!redoSelection.isEmpty())
2224 select (redoSelection);
2227 parseAtom (redoCommand);
2228 model->reposition();
2230 blockSaveState=blockSaveStateOrg;
2232 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
2233 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
2234 undoSet.setEntry ("/history/curStep",QString::number(curStep));
2235 undoSet.writeSettings(histPath);
2237 mainWindow->updateHistory (undoSet);
2240 /* TODO remove testing
2241 cout << "ME::redo() end\n";
2242 cout << " undosAvail="<<undosAvail<<endl;
2243 cout << " redosAvail="<<redosAvail<<endl;
2244 cout << " curStep="<<curStep<<endl;
2245 cout << " ---------------------------"<<endl<<endl;
2251 bool MapEditor::isRedoAvailable()
2253 if (undoSet.readNumEntry("/history/redosAvail",0)>0)
2259 void MapEditor::undo()
2261 // Can we undo at all?
2262 if (undosAvail<1) return;
2264 mainWindow->statusMessage (tr("Autosave disabled during undo."));
2266 bool blockSaveStateOrg=blockSaveState;
2267 blockSaveState=true;
2269 QString undoCommand= undoSet.readEntry (QString("/history/step-%1/undoCommand").arg(curStep));
2270 QString undoSelection=undoSet.readEntry (QString("/history/step-%1/undoSelection").arg(curStep));
2271 QString redoCommand= undoSet.readEntry (QString("/history/step-%1/redoCommand").arg(curStep));
2272 QString redoSelection=undoSet.readEntry (QString("/history/step-%1/redoSelection").arg(curStep));
2273 QString comment=undoSet.readEntry (QString("/history/step-%1/comment").arg(curStep));
2274 QString version=undoSet.readEntry ("/history/version");
2276 /* TODO Maybe check for version, if we save the history
2277 if (!checkVersion(version))
2278 QMessageBox::warning(0,tr("Warning"),
2279 tr("Version %1 of saved undo/redo data\ndoes not match current vym version %2.").arg(version).arg(vymVersion));
2282 // Find out current undo directory
2283 QString bakMapDir(QString(tmpMapDir+"/undo-%1").arg(curStep));
2285 // select object before undo
2286 if (!undoSelection.isEmpty())
2287 select (undoSelection);
2291 cout << "ME::undo() begin\n";
2292 cout << " undosAvail="<<undosAvail<<endl;
2293 cout << " redosAvail="<<redosAvail<<endl;
2294 cout << " curStep="<<curStep<<endl;
2295 cout << " ---------------------------"<<endl;
2296 cout << " comment="<<comment.toStdString()<<endl;
2297 cout << " undoCom="<<undoCommand.toStdString()<<endl;
2298 cout << " undoSel="<<undoSelection.toStdString()<<endl;
2299 cout << " redoCom="<<redoCommand.toStdString()<<endl;
2300 cout << " redoSel="<<redoSelection.toStdString()<<endl;
2301 cout << " ---------------------------"<<endl<<endl;
2303 parseAtom (undoCommand);
2304 model->reposition();
2308 if (curStep<1) curStep=stepsTotal;
2312 blockSaveState=blockSaveStateOrg;
2313 /* TODO remove testing
2314 cout << "ME::undo() end\n";
2315 cout << " undosAvail="<<undosAvail<<endl;
2316 cout << " redosAvail="<<redosAvail<<endl;
2317 cout << " curStep="<<curStep<<endl;
2318 cout << " ---------------------------"<<endl<<endl;
2321 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
2322 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
2323 undoSet.setEntry ("/history/curStep",QString::number(curStep));
2324 undoSet.writeSettings(histPath);
2326 mainWindow->updateHistory (undoSet);
2329 ensureSelectionVisible();
2332 bool MapEditor::isUndoAvailable()
2334 if (undoSet.readNumEntry("/history/undosAvail",0)>0)
2340 void MapEditor::gotoHistoryStep (int i)
2342 // Restore variables
2343 int undosAvail=undoSet.readNumEntry (QString("/history/undosAvail"));
2344 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
2346 if (i<0) i=undosAvail+redosAvail;
2348 // Clicking above current step makes us undo things
2351 for (int j=0; j<undosAvail-i; j++) undo();
2354 // Clicking below current step makes us redo things
2356 for (int j=undosAvail; j<i; j++)
2358 cout << "redo "<<j<<"/"<<undosAvail<<" i="<<i<<endl;
2362 // And ignore clicking the current row ;-)
2365 void MapEditor::addMapReplaceInt(const QString &undoSel, const QString &path)
2367 QString pathDir=path.left(path.findRev("/"));
2373 // We need to parse saved XML data
2374 parseVYMHandler handler;
2375 QXmlInputSource source( file);
2376 QXmlSimpleReader reader;
2377 reader.setContentHandler( &handler );
2378 reader.setErrorHandler( &handler );
2379 handler.setModel ( model);
2380 handler.setTmpDir ( pathDir ); // needed to load files with rel. path
2381 if (undoSel.isEmpty())
2385 handler.setLoadMode (NewMap);
2389 handler.setLoadMode (ImportReplace);
2391 blockReposition=true;
2392 bool ok = reader.parse( source );
2393 blockReposition=false;
2396 // This should never ever happen
2397 QMessageBox::critical( 0, tr( "Critical Parse Error while reading %1").arg(path),
2398 handler.errorProtocol());
2401 QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
2404 void MapEditor::addMapInsertInt (const QString &path, int pos)
2406 BranchObj *sel=xelection.getBranch();
2409 QString pathDir=path.left(path.findRev("/"));
2415 // We need to parse saved XML data
2416 parseVYMHandler handler;
2417 QXmlInputSource source( file);
2418 QXmlSimpleReader reader;
2419 reader.setContentHandler( &handler );
2420 reader.setErrorHandler( &handler );
2421 handler.setModel (model);
2422 handler.setTmpDir ( pathDir ); // needed to load files with rel. path
2423 handler.setLoadMode (ImportAdd);
2424 blockReposition=true;
2425 bool ok = reader.parse( source );
2426 blockReposition=false;
2429 // This should never ever happen
2430 QMessageBox::critical( 0, tr( "Critical Parse Error while reading %1").arg(path),
2431 handler.errorProtocol());
2433 if (sel->getDepth()>0)
2434 sel->getLastBranch()->linkTo (sel,pos);
2436 QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
2440 void MapEditor::pasteNoSave(const int &n)
2442 bool old=blockSaveState;
2443 blockSaveState=true;
2444 bool zippedOrg=zipped;
2445 if (redosAvail > 0 || n!=0)
2447 // Use the "historical" buffer
2448 QString bakMapName(QString("history-%1").arg(n));
2449 QString bakMapDir(tmpMapDir +"/"+bakMapName);
2450 load (bakMapDir+"/"+clipboardFile,ImportAdd, VymMap);
2452 // Use the global buffer
2453 load (clipboardDir+"/"+clipboardFile,ImportAdd, VymMap);
2458 void MapEditor::paste()
2460 BranchObj *sel=xelection.getBranch();
2463 saveStateChangingPart(
2466 QString ("paste (%1)").arg(curClipboard),
2467 QString("Paste to %1").arg( getName(sel))
2470 model->reposition();
2474 void MapEditor::cut()
2476 LinkableMapObj *sel=xelection.single();
2477 if ( sel && (xelection.type() == Selection::Branch ||
2478 xelection.type()==Selection::MapCenter ||
2479 xelection.type()==Selection::FloatImage))
2481 /* No savestate! savestate is called in cutNoSave
2482 saveStateChangingPart(
2486 QString("Cut %1").arg(getName(sel ))
2491 model->reposition();
2495 void MapEditor::move(const double &x, const double &y)
2497 LinkableMapObj *sel=xelection.single();
2500 QPointF ap(sel->getAbsPos());
2504 QString ps=qpointfToString(ap);
2505 QString s=xelection.getSelectString();
2508 s, "move "+qpointfToString(to),
2509 QString("Move %1 to %2").arg(getName(sel)).arg(ps));
2511 model->reposition();
2517 void MapEditor::moveRel (const double &x, const double &y)
2519 LinkableMapObj *sel=xelection.single();
2522 QPointF rp(sel->getRelPos());
2526 QString ps=qpointfToString (sel->getRelPos());
2527 QString s=model->getSelectString(sel);
2530 s, "moveRel "+qpointfToString(to),
2531 QString("Move %1 to relative position %2").arg(getName(sel)).arg(ps));
2532 ((OrnamentedObj*)sel)->move2RelPos (x,y);
2533 model->reposition();
2540 void MapEditor::moveBranchUp()
2542 BranchObj* bo=xelection.getBranch();
2546 if (!bo->canMoveBranchUp()) return;
2547 par=(BranchObj*)(bo->getParObj());
2548 BranchObj *obo=par->moveBranchUp (bo); // bo will be the one below selection
2549 saveState (model->getSelectString(bo),"moveBranchDown ()",model->getSelectString(obo),"moveBranchUp ()",QString("Move up %1").arg(getName(bo)));
2550 model->reposition();
2553 ensureSelectionVisible();
2557 void MapEditor::moveBranchDown()
2559 BranchObj* bo=xelection.getBranch();
2563 if (!bo->canMoveBranchDown()) return;
2564 par=(BranchObj*)(bo->getParObj());
2565 BranchObj *obo=par->moveBranchDown(bo); // bo will be the one above selection
2566 saveState(model->getSelectString(bo),"moveBranchUp ()",model->getSelectString(obo),"moveBranchDown ()",QString("Move down %1").arg(getName(bo)));
2567 model->reposition();
2570 ensureSelectionVisible();
2574 void MapEditor::sortChildren()
2576 BranchObj* bo=xelection.getBranch();
2579 if(bo->countBranches()>1)
2581 saveStateChangingPart(bo,bo, "sortChildren ()",QString("Sort children of %1").arg(getName(bo)));
2583 model->reposition();
2584 ensureSelectionVisible();
2589 void MapEditor::linkTo(const QString &dstString)
2591 FloatImageObj *fio=xelection.getFloatImage();
2594 BranchObj *dst=(BranchObj*)(model->findObjBySelect(dstString));
2595 if (dst && (typeid(*dst)==typeid (BranchObj) ||
2596 typeid(*dst)==typeid (MapCenterObj)))
2598 LinkableMapObj *dstPar=dst->getParObj();
2599 QString parString=model->getSelectString(dstPar);
2600 QString fioPreSelectString=model->getSelectString(fio);
2601 QString fioPreParentSelectString=model->getSelectString (fio->getParObj());
2602 ((BranchObj*)(dst))->addFloatImage (fio);
2603 xelection.unselect();
2604 ((BranchObj*)(fio->getParObj()))->removeFloatImage (fio);
2605 fio=((BranchObj*)(dst))->getLastFloatImage();
2608 xelection.select(fio);
2610 model->getSelectString(fio),
2611 QString("linkTo (\"%1\")").arg(fioPreParentSelectString),
2613 QString ("linkTo (\"%1\")").arg(dstString),
2614 QString ("Link floatimage to %1").arg(getName(dst)));
2619 QString MapEditor::getHeading(bool &ok, QPoint &p)
2621 BranchObj *bo=xelection.getBranch();
2625 p=mapFromScene(bo->getAbsPos());
2626 return bo->getHeading();
2632 void MapEditor::setHeading(const QString &s)
2634 BranchObj *sel=xelection.getBranch();
2639 "setHeading (\""+sel->getHeading()+"\")",
2641 "setHeading (\""+s+"\")",
2642 QString("Set heading of %1 to \"%2\"").arg(getName(sel)).arg(s) );
2643 sel->setHeading(s );
2644 model->reposition();
2646 ensureSelectionVisible();
2650 void MapEditor::setHeadingInt(const QString &s)
2652 BranchObj *bo=xelection.getBranch();
2656 model->reposition();
2658 ensureSelectionVisible();
2662 void MapEditor::setVymLinkInt (const QString &s)
2664 // Internal function, no saveState needed
2665 BranchObj *bo=xelection.getBranch();
2669 model->reposition();
2672 ensureSelectionVisible();
2676 BranchObj* MapEditor::addMapCenter ()
2678 MapCenterObj *mco= model->addMapCenter(contextMenuPos);
2679 xelection.select (mco);
2681 ensureSelectionVisible();
2686 QString ("addMapCenter (%1,%2)").arg (contextMenuPos.x()).arg(contextMenuPos.y()),
2687 QString ("Adding MapCenter to (%1,%2").arg (contextMenuPos.x()).arg(contextMenuPos.y())
2692 BranchObj* MapEditor::addNewBranchInt(int num)
2694 // Depending on pos:
2695 // -3 insert in childs of parent above selection
2696 // -2 add branch to selection
2697 // -1 insert in childs of parent below selection
2698 // 0..n insert in childs of parent at pos
2699 BranchObj *newbo=NULL;
2700 BranchObj *bo=xelection.getBranch();
2705 // save scroll state. If scrolled, automatically select
2706 // new branch in order to tmp unscroll parent...
2707 newbo=bo->addBranch();
2712 bo=(BranchObj*)bo->getParObj();
2713 if (bo) newbo=bo->insertBranch(num);
2717 bo=(BranchObj*)bo->getParObj();
2718 if (bo) newbo=bo->insertBranch(num);
2720 if (!newbo) return NULL;
2725 BranchObj* MapEditor::addNewBranch(int pos)
2727 // Different meaning than num in addNewBranchInt!
2731 BranchObj *bo = xelection.getBranch();
2732 BranchObj *newbo=NULL;
2736 setCursor (Qt::ArrowCursor);
2738 newbo=addNewBranchInt (pos-2);
2746 QString ("addBranch (%1)").arg(pos),
2747 QString ("Add new branch to %1").arg(getName(bo)));
2749 model->reposition();
2751 latestSelection=model->getSelectString(newbo);
2752 // In Network mode, the client needs to know where the new branch is,
2753 // so we have to pass on this information via saveState.
2754 // TODO: Get rid of this positioning workaround
2755 QString ps=qpointfToString (newbo->getAbsPos());
2756 sendData ("selectLatestAdded ()");
2757 sendData (QString("move %1").arg(ps));
2765 BranchObj* MapEditor::addNewBranchBefore()
2767 BranchObj *newbo=NULL;
2768 BranchObj *bo = xelection.getBranch();
2769 if (bo && xelection.type()==Selection::Branch)
2770 // We accept no MapCenterObj here, so we _have_ a parent
2772 QPointF p=bo->getRelPos();
2775 BranchObj *parbo=(BranchObj*)(bo->getParObj());
2777 // add below selection
2778 newbo=parbo->insertBranch(bo->getNum()+1);
2781 newbo->move2RelPos (p);
2783 // Move selection to new branch
2784 bo->linkTo (newbo,-1);
2786 saveState (newbo, "deleteKeepChilds ()", newbo, "addBranchBefore ()",
2787 QString ("Add branch before %1").arg(getName(bo)));
2789 model->reposition();
2793 latestSelection=xelection.getSelectString();
2797 void MapEditor::deleteSelection()
2799 BranchObj *bo = xelection.getBranch();
2800 if (bo && xelection.type()==Selection::MapCenter)
2802 // BranchObj* par=(BranchObj*)(bo->getParObj());
2803 xelection.unselect();
2804 /* FIXME Note: does saveStateRemovingPart work for MCO? (No parent!)
2805 saveStateRemovingPart (bo, QString ("Delete %1").arg(getName(bo)));
2807 bo=model->removeMapCenter ((MapCenterObj*)bo);
2810 xelection.select (bo);
2811 ensureSelectionVisible();
2814 model->reposition();
2817 if (bo && xelection.type()==Selection::Branch)
2819 BranchObj* par=(BranchObj*)(bo->getParObj());
2820 xelection.unselect();
2821 saveStateRemovingPart (bo, QString ("Delete %1").arg(getName(bo)));
2822 par->removeBranch(bo);
2823 xelection.select (par);
2824 ensureSelectionVisible();
2825 model->reposition();
2830 FloatImageObj *fio=xelection.getFloatImage();
2833 BranchObj* par=(BranchObj*)(fio->getParObj());
2834 saveStateChangingPart(
2838 QString("Delete %1").arg(getName(fio))
2840 xelection.unselect();
2841 par->removeFloatImage(fio);
2842 xelection.select (par);
2843 model->reposition();
2845 ensureSelectionVisible();
2850 LinkableMapObj* MapEditor::getSelection()
2852 return xelection.single();
2855 BranchObj* MapEditor::getSelectedBranch()
2857 return xelection.getBranch();
2860 FloatImageObj* MapEditor::getSelectedFloatImage()
2862 return xelection.getFloatImage();
2865 void MapEditor::unselect()
2867 xelection.unselect();
2870 void MapEditor::reselect()
2872 xelection.reselect();
2875 bool MapEditor::select (const QString &s)
2877 if (xelection.select(s))
2880 ensureSelectionVisible();
2887 bool MapEditor::select (LinkableMapObj *lmo)
2889 if (xelection.select(lmo))
2892 ensureSelectionVisible();
2899 QString MapEditor::getSelectString()
2901 return xelection.getSelectString();
2904 void MapEditor::selectInt (LinkableMapObj *lmo)
2906 if (lmo && xelection.single()!= lmo && isSelectBlocked()==false )
2908 xelection.select(lmo);
2914 void MapEditor::selectNextBranchInt()
2916 // Increase number of branch
2917 LinkableMapObj *sel=xelection.single();
2920 QString s=xelection.getSelectString();
2926 part=s.section(",",-1);
2928 num=part.right(part.length() - 3);
2930 s=s.left (s.length() -num.length());
2933 num=QString ("%1").arg(num.toUInt()+1);
2937 // Try to select this one
2938 if (select (s)) return;
2940 // We have no direct successor,
2941 // try to increase the parental number in order to
2942 // find a successor with same depth
2944 int d=xelection.single()->getDepth();
2949 while (!found && d>0)
2951 s=s.section (",",0,d-1);
2952 // replace substring of current depth in s with "1"
2953 part=s.section(",",-1);
2955 num=part.right(part.length() - 3);
2959 // increase number of parent
2960 num=QString ("%1").arg(num.toUInt()+1);
2961 s=s.section (",",0,d-2) + ","+ typ+num;
2964 // Special case, look at orientation
2965 if (xelection.single()->getOrientation()==LinkableMapObj::RightOfCenter)
2966 num=QString ("%1").arg(num.toUInt()+1);
2968 num=QString ("%1").arg(num.toUInt()-1);
2973 // pad to oldDepth, select the first branch for each depth
2974 for (i=d;i<oldDepth;i++)
2979 if ( xelection.getBranch()->countBranches()>0)
2987 // try to select the freshly built string
2995 void MapEditor::selectPrevBranchInt()
2997 // Decrease number of branch
2998 BranchObj *bo=xelection.getBranch();
3001 QString s=xelection.getSelectString();
3007 part=s.section(",",-1);
3009 num=part.right(part.length() - 3);
3011 s=s.left (s.length() -num.length());
3013 int n=num.toInt()-1;
3016 num=QString ("%1").arg(n);
3019 // Try to select this one
3020 if (n>=0 && select (s)) return;
3022 // We have no direct precessor,
3023 // try to decrease the parental number in order to
3024 // find a precessor with same depth
3026 int d=xelection.single()->getDepth();
3031 while (!found && d>0)
3033 s=s.section (",",0,d-1);
3034 // replace substring of current depth in s with "1"
3035 part=s.section(",",-1);
3037 num=part.right(part.length() - 3);
3041 // decrease number of parent
3042 num=QString ("%1").arg(num.toInt()-1);
3043 s=s.section (",",0,d-2) + ","+ typ+num;
3046 // Special case, look at orientation
3047 if (xelection.single()->getOrientation()==LinkableMapObj::RightOfCenter)
3048 num=QString ("%1").arg(num.toInt()-1);
3050 num=QString ("%1").arg(num.toInt()+1);
3055 // pad to oldDepth, select the last branch for each depth
3056 for (i=d;i<oldDepth;i++)
3060 if ( xelection.getBranch()->countBranches()>0)
3061 s+=",bo:"+ QString ("%1").arg( xelection.getBranch()->countBranches()-1 );
3068 // try to select the freshly built string
3076 void MapEditor::selectUpperBranch()
3078 if (isSelectBlocked() ) return;
3080 BranchObj *bo=xelection.getBranch();
3081 if (bo && xelection.type()==Selection::Branch)
3083 if (bo->getOrientation()==LinkableMapObj::RightOfCenter)
3084 selectPrevBranchInt();
3086 if (bo->getDepth()==1)
3087 selectNextBranchInt();
3089 selectPrevBranchInt();
3093 void MapEditor::selectLowerBranch()
3095 if (isSelectBlocked() ) return;
3097 BranchObj *bo=xelection.getBranch();
3098 if (bo && xelection.type()==Selection::Branch)
3099 if (bo->getOrientation()==LinkableMapObj::RightOfCenter)
3100 selectNextBranchInt();
3102 if (bo->getDepth()==1)
3103 selectPrevBranchInt();
3105 selectNextBranchInt();
3109 void MapEditor::selectLeftBranch()
3111 if (isSelectBlocked() ) return;
3115 LinkableMapObj *sel=xelection.single();
3118 if (xelection.type()== Selection::MapCenter)
3120 par=xelection.getBranch();
3121 bo=par->getLastSelectedBranch();
3124 // Workaround for reselecting on left and right side
3125 if (bo->getOrientation()==LinkableMapObj::RightOfCenter)
3126 bo=par->getLastBranch();
3129 bo=par->getLastBranch();
3130 xelection.select(bo);
3132 ensureSelectionVisible();
3138 par=(BranchObj*)(sel->getParObj());
3139 if (sel->getOrientation()==LinkableMapObj::RightOfCenter)
3141 if (xelection.type() == Selection::Branch ||
3142 xelection.type() == Selection::FloatImage)
3144 xelection.select(par);
3146 ensureSelectionVisible();
3151 if (xelection.type() == Selection::Branch )
3153 bo=xelection.getBranch()->getLastSelectedBranch();
3156 xelection.select(bo);
3158 ensureSelectionVisible();
3167 void MapEditor::selectRightBranch()
3169 if (isSelectBlocked() ) return;
3173 LinkableMapObj *sel=xelection.single();
3176 if (xelection.type()==Selection::MapCenter)
3178 par=xelection.getBranch();
3179 bo=par->getLastSelectedBranch();
3182 // Workaround for reselecting on left and right side
3183 if (bo->getOrientation()==LinkableMapObj::LeftOfCenter)
3184 bo=par->getFirstBranch();
3187 xelection.select(bo);
3189 ensureSelectionVisible();
3195 par=(BranchObj*)(xelection.single()->getParObj());
3196 if (xelection.single()->getOrientation()==LinkableMapObj::LeftOfCenter)
3198 if (xelection.type() == Selection::Branch ||
3199 xelection.type() == Selection::FloatImage)
3201 xelection.select(par);
3203 ensureSelectionVisible();
3208 if (xelection.type() == Selection::Branch)
3210 bo=xelection.getBranch()->getLastSelectedBranch();
3213 xelection.select(bo);
3215 ensureSelectionVisible();
3224 void MapEditor::selectFirstBranch()
3226 BranchObj *bo1=xelection.getBranch();
3231 par=(BranchObj*)(bo1->getParObj());
3233 bo2=par->getFirstBranch();
3235 xelection.select(bo2);
3237 ensureSelectionVisible();
3243 void MapEditor::selectLastBranch()
3245 BranchObj *bo1=xelection.getBranch();
3250 par=(BranchObj*)(bo1->getParObj());
3252 bo2=par->getLastBranch();
3255 xelection.select(bo2);
3257 ensureSelectionVisible();
3263 void MapEditor::selectMapBackgroundImage ()
3265 Q3FileDialog *fd=new Q3FileDialog( this);
3266 fd->setMode (Q3FileDialog::ExistingFile);
3267 fd->addFilter (QString (tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)"));
3268 ImagePreview *p =new ImagePreview (fd);
3269 fd->setContentsPreviewEnabled( TRUE );
3270 fd->setContentsPreview( p, p );
3271 fd->setPreviewMode( Q3FileDialog::Contents );
3272 fd->setCaption(vymName+" - " +tr("Load background image"));
3273 fd->setDir (lastImageDir);
3276 if ( fd->exec() == QDialog::Accepted )
3278 // TODO selectMapBackgroundImg in QT4 use: lastImageDir=fd->directory();
3279 lastImageDir=QDir (fd->dirPath());
3280 setMapBackgroundImage (fd->selectedFile());
3284 void MapEditor::setMapBackgroundImage (const QString &fn) //FIXME missing savestate
3286 QColor oldcol=mapScene->backgroundBrush().color();
3290 QString ("setMapBackgroundImage (%1)").arg(oldcol.name()),
3292 QString ("setMapBackgroundImage (%1)").arg(col.name()),
3293 QString("Set background color of map to %1").arg(col.name()));
3296 brush.setTextureImage (QPixmap (fn));
3297 mapScene->setBackgroundBrush(brush);
3300 void MapEditor::selectMapBackgroundColor()
3302 QColor col = QColorDialog::getColor( mapScene->backgroundBrush().color(), this );
3303 if ( !col.isValid() ) return;
3304 setMapBackgroundColor( col );
3308 void MapEditor::setMapBackgroundColor(QColor col)
3310 QColor oldcol=mapScene->backgroundBrush().color();
3312 QString ("setMapBackgroundColor (\"%1\")").arg(oldcol.name()),
3313 QString ("setMapBackgroundColor (\"%1\")").arg(col.name()),
3314 QString("Set background color of map to %1").arg(col.name()));
3315 mapScene->setBackgroundBrush(col);
3318 QColor MapEditor::getMapBackgroundColor()
3320 return mapScene->backgroundBrush().color();
3323 QColor MapEditor::getCurrentHeadingColor()
3325 BranchObj *bo=xelection.getBranch();
3326 if (bo) return bo->getColor();
3328 QMessageBox::warning(0,tr("Warning"),tr("Can't get color of heading,\nthere's no branch selected"));
3332 void MapEditor::colorBranch (QColor c)
3334 BranchObj *bo=xelection.getBranch();
3339 QString ("colorBranch (\"%1\")").arg(bo->getColor().name()),
3341 QString ("colorBranch (\"%1\")").arg(c.name()),
3342 QString("Set color of %1 to %2").arg(getName(bo)).arg(c.name())
3344 bo->setColor(c); // color branch
3348 void MapEditor::colorSubtree (QColor c)
3350 BranchObj *bo=xelection.getBranch();
3353 saveStateChangingPart(
3356 QString ("colorSubtree (\"%1\")").arg(c.name()),
3357 QString ("Set color of %1 and childs to %2").arg(getName(bo)).arg(c.name())
3359 bo->setColorSubtree (c); // color links, color childs
3364 void MapEditor::toggleStandardFlag(QString f)
3366 BranchObj *bo=xelection.getBranch();
3370 if (bo->isSetStandardFlag(f))
3382 QString("%1 (\"%2\")").arg(u).arg(f),
3384 QString("%1 (\"%2\")").arg(r).arg(f),
3385 QString("Toggling standard flag \"%1\" of %2").arg(f).arg(getName(bo)));
3386 bo->toggleStandardFlag (f,mainWindow->useFlagGroups());
3392 BranchObj* MapEditor::findText (QString s, bool cs)
3394 QTextDocument::FindFlags flags=0;
3395 if (cs) flags=QTextDocument::FindCaseSensitively;
3398 { // Nothing found or new find process
3400 // nothing found, start again
3402 itFind=model->first();
3404 bool searching=true;
3405 bool foundNote=false;
3406 while (searching && !EOFind)
3410 // Searching in Note
3411 if (itFind->getNote().contains(s,cs))
3413 if (xelection.single()!=itFind)
3415 xelection.select(itFind);
3416 ensureSelectionVisible();
3418 if (textEditor->findText(s,flags))
3424 // Searching in Heading
3425 if (searching && itFind->getHeading().contains (s,cs) )
3427 xelection.select(itFind);
3428 ensureSelectionVisible();
3434 itFind=model->next(itFind);
3435 if (!itFind) EOFind=true;
3437 //cout <<"still searching... "<<qPrintable( itFind->getHeading())<<endl;
3440 return xelection.getBranch();
3445 void MapEditor::findReset()
3446 { // Necessary if text to find changes during a find process
3450 void MapEditor::setURL(const QString &url)
3452 BranchObj *bo=xelection.getBranch();
3455 QString oldurl=bo->getURL();
3459 QString ("setURL (\"%1\")").arg(oldurl),
3461 QString ("setURL (\"%1\")").arg(url),
3462 QString ("set URL of %1 to %2").arg(getName(bo)).arg(url)
3465 model->reposition();
3467 ensureSelectionVisible();
3471 void MapEditor::editURL()
3473 BranchObj *bo=xelection.getBranch();
3477 QString text = QInputDialog::getText(
3478 "VYM", tr("Enter URL:"), QLineEdit::Normal,
3479 bo->getURL(), &ok, this );
3481 // user entered something and pressed OK
3486 void MapEditor::editLocalURL()
3488 BranchObj *bo=xelection.getBranch();
3491 QStringList filters;
3492 filters <<"All files (*)";
3493 filters << tr("Text","Filedialog") + " (*.txt)";
3494 filters << tr("Spreadsheet","Filedialog") + " (*.odp,*.sxc)";
3495 filters << tr("Textdocument","Filedialog") +" (*.odw,*.sxw)";
3496 filters << tr("Images","Filedialog") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)";
3497 QFileDialog *fd=new QFileDialog( this,vymName+" - " +tr("Set URL to a local file"));
3498 fd->setFilters (filters);
3499 fd->setCaption(vymName+" - " +tr("Set URL to a local file"));
3500 fd->setDirectory (lastFileDir);
3501 if (! bo->getVymLink().isEmpty() )
3502 fd->selectFile( bo->getURL() );
3505 if ( fd->exec() == QDialog::Accepted )
3507 lastFileDir=QDir (fd->directory().path());
3508 setURL (fd->selectedFile() );
3513 QString MapEditor::getURL()
3515 BranchObj *bo=xelection.getBranch();
3517 return bo->getURL();
3522 QStringList MapEditor::getURLs()
3525 BranchObj *bo=xelection.getBranch();
3531 if (!bo->getURL().isEmpty()) urls.append( bo->getURL());
3539 void MapEditor::editHeading2URL()
3541 BranchObj *bo=xelection.getBranch();
3543 setURL (bo->getHeading());
3546 void MapEditor::editBugzilla2URL()
3548 BranchObj *bo=xelection.getBranch();
3551 QString url= "https://bugzilla.novell.com/show_bug.cgi?id="+bo->getHeading();
3556 void MapEditor::editFATE2URL()
3558 BranchObj *bo=xelection.getBranch();
3561 QString url= "http://keeper.suse.de:8080/webfate/match/id?value=ID"+bo->getHeading();
3564 "setURL (\""+bo->getURL()+"\")",
3566 "setURL (\""+url+"\")",
3567 QString("Use heading of %1 as link to FATE").arg(getName(bo))
3574 void MapEditor::editVymLink()
3576 BranchObj *bo=xelection.getBranch();
3579 QStringList filters;
3580 filters <<"VYM map (*.vym)";
3581 QFileDialog *fd=new QFileDialog( this,vymName+" - " +tr("Link to another map"));
3582 fd->setFilters (filters);
3583 fd->setCaption(vymName+" - " +tr("Link to another map"));
3584 fd->setDirectory (lastFileDir);
3585 if (! bo->getVymLink().isEmpty() )
3586 fd->selectFile( bo->getVymLink() );
3590 if ( fd->exec() == QDialog::Accepted )
3592 lastFileDir=QDir (fd->directory().path());
3595 "setVymLink (\""+bo->getVymLink()+"\")",
3597 "setVymLink (\""+fd->selectedFile()+"\")",
3598 QString("Set vymlink of %1 to %2").arg(getName(bo)).arg(fd->selectedFile())
3600 setVymLinkInt (fd->selectedFile() );
3605 void MapEditor::deleteVymLink()
3607 BranchObj *bo=xelection.getBranch();
3612 "setVymLink (\""+bo->getVymLink()+"\")",
3614 "setVymLink (\"\")",
3615 QString("Unset vymlink of %1").arg(getName(bo))
3617 bo->setVymLink ("" );
3619 model->reposition();
3624 void MapEditor::setHideExport(bool b)
3626 BranchObj *bo=xelection.getBranch();
3629 bo->setHideInExport (b);
3630 QString u= b ? "false" : "true";
3631 QString r=!b ? "false" : "true";
3635 QString ("setHideExport (%1)").arg(u),
3637 QString ("setHideExport (%1)").arg(r),
3638 QString ("Set HideExport flag of %1 to %2").arg(getName(bo)).arg (r)
3641 model->reposition();
3647 void MapEditor::toggleHideExport()
3649 BranchObj *bo=xelection.getBranch();
3651 setHideExport ( !bo->hideInExport() );
3654 QString MapEditor::getVymLink()
3656 BranchObj *bo=xelection.getBranch();
3658 return bo->getVymLink();
3664 QStringList MapEditor::getVymLinks()
3667 BranchObj *bo=xelection.getBranch();
3673 if (!bo->getVymLink().isEmpty()) links.append( bo->getVymLink());
3681 void MapEditor::deleteKeepChilds()
3683 BranchObj *bo=xelection.getBranch();
3687 par=(BranchObj*)(bo->getParObj());
3688 QPointF p=bo->getRelPos();
3689 saveStateChangingPart(
3692 "deleteKeepChilds ()",
3693 QString("Remove %1 and keep its childs").arg(getName(bo))
3696 QString sel=model->getSelectString(bo);
3698 par->removeBranchHere(bo);
3699 model->reposition();
3701 xelection.getBranch()->move2RelPos (p);
3702 model->reposition();
3706 void MapEditor::deleteChilds()
3708 BranchObj *bo=xelection.getBranch();
3711 saveStateChangingPart(
3715 QString( "Remove childs of branch %1").arg(getName(bo))
3718 model->reposition();
3722 void MapEditor::editMapInfo()
3724 ExtraInfoDialog dia;
3725 dia.setMapName (getFileName() );
3726 dia.setAuthor (model->getAuthor() );
3727 dia.setComment(model->getComment() );
3731 stats+=tr("%1 items on map\n","Info about map").arg (mapScene->items().size(),6);
3741 if (!bo->getNote().isEmpty() ) n++;
3742 f+= bo->countFloatImages();
3744 xl+=bo->countXLinks();
3747 stats+=QString ("%1 branches\n").arg (b-1,6);
3748 stats+=QString ("%1 xLinks \n").arg (xl,6);
3749 stats+=QString ("%1 notes\n").arg (n,6);
3750 stats+=QString ("%1 images\n").arg (f,6);
3751 dia.setStats (stats);
3753 // Finally show dialog
3754 if (dia.exec() == QDialog::Accepted)
3756 setMapAuthor (dia.getAuthor() );
3757 setMapComment (dia.getComment() );
3761 void MapEditor::ensureSelectionVisible()
3763 LinkableMapObj *lmo=xelection.single();
3764 if (lmo) ensureVisible (lmo->getBBox() );
3768 void MapEditor::updateSelection()
3770 // Tell selection to update geometries
3774 void MapEditor::updateActions()
3776 // Tell mainwindow to update states of actions
3777 mainWindow->updateActions();
3778 // TODO maybe don't update if blockReposition is set
3781 void MapEditor::updateNoteFlag()
3784 BranchObj *bo=xelection.getBranch();
3787 bo->updateNoteFlag();
3788 mainWindow->updateActions();
3792 void MapEditor::setMapAuthor (const QString &s)
3795 QString ("setMapAuthor (\"%1\")").arg(model->getAuthor()),
3796 QString ("setMapAuthor (\"%1\")").arg(s),
3797 QString ("Set author of map to \"%1\"").arg(s)
3799 model->setAuthor (s);
3802 void MapEditor::setMapComment (const QString &s)
3805 QString ("setMapComment (\"%1\")").arg(model->getComment()),
3806 QString ("setMapComment (\"%1\")").arg(s),
3807 QString ("Set comment of map")
3809 model->setComment (s);
3812 void MapEditor::setMapLinkStyle (const QString & s)
3815 if (linkstyle==LinkableMapObj::Line)
3817 else if (linkstyle==LinkableMapObj::Parabel)
3818 snow="StyleParabel";
3819 else if (linkstyle==LinkableMapObj::PolyLine)
3820 snow="StylePolyLine";
3821 else if (linkstyle==LinkableMapObj::PolyParabel)
3822 snow="StyleParabel";
3825 QString("setMapLinkStyle (\"%1\")").arg(s),
3826 QString("setMapLinkStyle (\"%1\")").arg(snow),
3827 QString("Set map link style (\"%1\")").arg(s)
3831 linkstyle=LinkableMapObj::Line;
3832 else if (s=="StyleParabel")
3833 linkstyle=LinkableMapObj::Parabel;
3834 else if (s=="StylePolyLine")
3835 linkstyle=LinkableMapObj::PolyLine;
3837 linkstyle=LinkableMapObj::PolyParabel;
3844 bo->setLinkStyle(bo->getDefLinkStyle());
3847 model->reposition();
3850 LinkableMapObj::Style MapEditor::getMapLinkStyle ()
3855 void MapEditor::setMapDefLinkColor(QColor c)
3868 void MapEditor::setMapLinkColorHintInt()
3870 // called from setMapLinkColorHint(lch) or at end of parse
3880 void MapEditor::setMapLinkColorHint(LinkableMapObj::ColorHint lch)
3883 setMapLinkColorHintInt();
3886 void MapEditor::toggleMapLinkColorHint()
3888 if (linkcolorhint==LinkableMapObj::HeadingColor)
3889 linkcolorhint=LinkableMapObj::DefaultColor;
3891 linkcolorhint=LinkableMapObj::HeadingColor;
3901 LinkableMapObj::ColorHint MapEditor::getMapLinkColorHint()
3903 return linkcolorhint;
3906 QColor MapEditor::getMapDefLinkColor()
3908 return defLinkColor;
3911 void MapEditor::setMapDefXLinkColor(QColor col)
3916 QColor MapEditor::getMapDefXLinkColor()
3918 return defXLinkColor;
3921 void MapEditor::setMapDefXLinkWidth (int w)
3926 int MapEditor::getMapDefXLinkWidth()
3928 return defXLinkWidth;
3931 void MapEditor::selectMapLinkColor()
3933 QColor col = QColorDialog::getColor( defLinkColor, this );
3934 if ( !col.isValid() ) return;
3936 QString("setMapDefLinkColor (\"%1\")").arg(getMapDefLinkColor().name()),
3937 QString("setMapDefLinkColor (\"%1\")").arg(col.name()),
3938 QString("Set map link color to %1").arg(col.name())
3940 setMapDefLinkColor( col );
3943 void MapEditor::selectMapSelectionColor()
3945 QColor col = QColorDialog::getColor( defLinkColor, this );
3946 setSelectionColor (col);
3949 void MapEditor::setSelectionColorInt (QColor col)
3951 if ( !col.isValid() ) return;
3952 xelection.setColor (col);
3955 void MapEditor::setSelectionColor(QColor col)
3957 if ( !col.isValid() ) return;
3959 QString("setSelectionColor (%1)").arg(xelection.getColor().name()),
3960 QString("setSelectionColor (%1)").arg(col.name()),
3961 QString("Set color of selection box to %1").arg(col.name())
3963 setSelectionColorInt (col);
3966 QColor MapEditor::getSelectionColor()
3968 return xelection.getColor();
3971 bool MapEditor::scrollBranch(BranchObj *bo)
3975 if (bo->isScrolled()) return false;
3976 if (bo->countBranches()==0) return false;
3977 if (bo->getDepth()==0) return false;
3983 QString ("%1 ()").arg(u),
3985 QString ("%1 ()").arg(r),
3986 QString ("%1 %2").arg(r).arg(getName(bo))
3996 bool MapEditor::unscrollBranch(BranchObj *bo)
4000 if (!bo->isScrolled()) return false;
4001 if (bo->countBranches()==0) return false;
4002 if (bo->getDepth()==0) return false;
4008 QString ("%1 ()").arg(u),
4010 QString ("%1 ()").arg(r),
4011 QString ("%1 %2").arg(r).arg(getName(bo))
4021 void MapEditor::toggleScroll()
4023 BranchObj *bo=xelection.getBranch();
4024 if (xelection.type()==Selection::Branch )
4026 if (bo->isScrolled())
4027 unscrollBranch (bo);
4033 void MapEditor::unscrollChilds()
4035 BranchObj *bo=xelection.getBranch();
4041 if (bo->isScrolled()) unscrollBranch (bo);
4047 FloatImageObj* MapEditor::loadFloatImageInt (QString fn)
4049 BranchObj *bo=xelection.getBranch();
4053 bo->addFloatImage();
4054 fio=bo->getLastFloatImage();
4056 model->reposition();
4063 void MapEditor::loadFloatImage ()
4065 BranchObj *bo=xelection.getBranch();
4069 Q3FileDialog *fd=new Q3FileDialog( this);
4070 fd->setMode (Q3FileDialog::ExistingFiles);
4071 fd->addFilter (QString (tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)"));
4072 ImagePreview *p =new ImagePreview (fd);
4073 fd->setContentsPreviewEnabled( TRUE );
4074 fd->setContentsPreview( p, p );
4075 fd->setPreviewMode( Q3FileDialog::Contents );
4076 fd->setCaption(vymName+" - " +tr("Load image"));
4077 fd->setDir (lastImageDir);
4080 if ( fd->exec() == QDialog::Accepted )
4082 // TODO loadFIO in QT4 use: lastImageDir=fd->directory();
4083 lastImageDir=QDir (fd->dirPath());
4086 for (int j=0; j<fd->selectedFiles().count(); j++)
4088 s=fd->selectedFiles().at(j);
4089 fio=loadFloatImageInt (s);
4092 (LinkableMapObj*)fio,
4095 QString ("loadImage (%1)").arg(s ),
4096 QString("Add image %1 to %2").arg(s).arg(getName(bo))
4099 // TODO loadFIO error handling
4100 qWarning ("Failed to load "+s);
4108 void MapEditor::saveFloatImageInt (FloatImageObj *fio, const QString &type, const QString &fn)
4110 fio->save (fn,type);
4113 void MapEditor::saveFloatImage ()
4115 FloatImageObj *fio=xelection.getFloatImage();
4118 QFileDialog *fd=new QFileDialog( this);
4119 fd->setFilters (imageIO.getFilters());
4120 fd->setCaption(vymName+" - " +tr("Save image"));
4121 fd->setFileMode( QFileDialog::AnyFile );
4122 fd->setDirectory (lastImageDir);
4123 // fd->setSelection (fio->getOriginalFilename());
4127 if ( fd->exec() == QDialog::Accepted && fd->selectedFiles().count()==1)
4129 fn=fd->selectedFiles().at(0);
4130 if (QFile (fn).exists() )
4132 QMessageBox mb( vymName,
4133 tr("The file %1 exists already.\n"
4134 "Do you want to overwrite it?").arg(fn),
4135 QMessageBox::Warning,
4136 QMessageBox::Yes | QMessageBox::Default,
4137 QMessageBox::Cancel | QMessageBox::Escape,
4138 QMessageBox::QMessageBox::NoButton );
4140 mb.setButtonText( QMessageBox::Yes, tr("Overwrite") );
4141 mb.setButtonText( QMessageBox::No, tr("Cancel"));
4144 case QMessageBox::Yes:
4147 case QMessageBox::Cancel:
4154 saveFloatImageInt (fio,fd->selectedFilter(),fn );
4160 void MapEditor::setFrameType(const FrameObj::FrameType &t)
4162 BranchObj *bo=xelection.getBranch();
4165 QString s=bo->getFrameTypeName();
4166 bo->setFrameType (t);
4167 saveState (bo, QString("setFrameType (\"%1\")").arg(s),
4168 bo, QString ("setFrameType (\"%1\")").arg(bo->getFrameTypeName()),QString ("set type of frame to %1").arg(s));
4169 model->reposition();
4174 void MapEditor::setFrameType(const QString &s)
4176 BranchObj *bo=xelection.getBranch();
4179 saveState (bo, QString("setFrameType (\"%1\")").arg(bo->getFrameTypeName()),
4180 bo, QString ("setFrameType (\"%1\")").arg(s),QString ("set type of frame to %1").arg(s));
4181 bo->setFrameType (s);
4182 model->reposition();
4187 void MapEditor::setFramePenColor(const QColor &c)
4189 BranchObj *bo=xelection.getBranch();
4192 saveState (bo, QString("setFramePenColor (\"%1\")").arg(bo->getFramePenColor().name() ),
4193 bo, QString ("setFramePenColor (\"%1\")").arg(c.name() ),QString ("set pen color of frame to %1").arg(c.name() ));
4194 bo->setFramePenColor (c);
4198 void MapEditor::setFrameBrushColor(const QColor &c)
4200 BranchObj *bo=xelection.getBranch();
4203 saveState (bo, QString("setFrameBrushColor (\"%1\")").arg(bo->getFrameBrushColor().name() ),
4204 bo, QString ("setFrameBrushColor (\"%1\")").arg(c.name() ),QString ("set brush color of frame to %1").arg(c.name() ));
4205 bo->setFrameBrushColor (c);
4209 void MapEditor::setFramePadding (const int &i)
4211 BranchObj *bo=xelection.getBranch();
4214 saveState (bo, QString("setFramePadding (\"%1\")").arg(bo->getFramePadding() ),
4215 bo, QString ("setFramePadding (\"%1\")").arg(i),QString ("set brush color of frame to %1").arg(i));
4216 bo->setFramePadding (i);
4217 model->reposition();
4222 void MapEditor::setFrameBorderWidth(const int &i)
4224 BranchObj *bo=xelection.getBranch();
4227 saveState (bo, QString("setFrameBorderWidth (\"%1\")").arg(bo->getFrameBorderWidth() ),
4228 bo, QString ("setFrameBorderWidth (\"%1\")").arg(i),QString ("set border width of frame to %1").arg(i));
4229 bo->setFrameBorderWidth (i);
4230 model->reposition();
4235 void MapEditor::setIncludeImagesVer(bool b)
4237 BranchObj *bo=xelection.getBranch();
4240 QString u= b ? "false" : "true";
4241 QString r=!b ? "false" : "true";
4245 QString("setIncludeImagesVertically (%1)").arg(u),
4247 QString("setIncludeImagesVertically (%1)").arg(r),
4248 QString("Include images vertically in %1").arg(getName(bo))
4250 bo->setIncludeImagesVer(b);
4251 model->reposition();
4255 void MapEditor::setIncludeImagesHor(bool b)
4257 BranchObj *bo=xelection.getBranch();
4260 QString u= b ? "false" : "true";
4261 QString r=!b ? "false" : "true";
4265 QString("setIncludeImagesHorizontally (%1)").arg(u),
4267 QString("setIncludeImagesHorizontally (%1)").arg(r),
4268 QString("Include images horizontally in %1").arg(getName(bo))
4270 bo->setIncludeImagesHor(b);
4271 model->reposition();
4275 void MapEditor::setHideLinkUnselected (bool b)
4277 LinkableMapObj *sel=xelection.single();
4279 (xelection.type() == Selection::Branch ||
4280 xelection.type() == Selection::MapCenter ||
4281 xelection.type() == Selection::FloatImage ))
4283 QString u= b ? "false" : "true";
4284 QString r=!b ? "false" : "true";
4288 QString("setHideLinkUnselected (%1)").arg(u),
4290 QString("setHideLinkUnselected (%1)").arg(r),
4291 QString("Hide link of %1 if unselected").arg(getName(sel))
4293 sel->setHideLinkUnselected(b);
4297 void MapEditor::importDirInt(BranchObj *dst, QDir d)
4299 BranchObj *bo=xelection.getBranch();
4302 // Traverse directories
4303 d.setFilter( QDir::Dirs| QDir::Hidden | QDir::NoSymLinks );
4304 QFileInfoList list = d.entryInfoList();
4307 for (int i = 0; i < list.size(); ++i)
4310 if (fi.fileName() != "." && fi.fileName() != ".." )
4313 bo=dst->getLastBranch();
4314 bo->setHeading (fi.fileName() );
4315 bo->setColor (QColor("blue"));
4317 if ( !d.cd(fi.fileName()) )
4318 QMessageBox::critical (0,tr("Critical Import Error"),tr("Cannot find the directory %1").arg(fi.fileName()));
4321 // Recursively add subdirs
4322 importDirInt (bo,d);
4328 d.setFilter( QDir::Files| QDir::Hidden | QDir::NoSymLinks );
4329 list = d.entryInfoList();
4331 for (int i = 0; i < list.size(); ++i)
4335 bo=dst->getLastBranch();
4336 bo->setHeading (fi.fileName() );
4337 bo->setColor (QColor("black"));
4338 if (fi.fileName().right(4) == ".vym" )
4339 bo->setVymLink (fi.filePath());
4344 void MapEditor::importDirInt (const QString &s)
4346 BranchObj *bo=xelection.getBranch();
4349 saveStateChangingPart (bo,bo,QString ("importDir (\"%1\")").arg(s),QString("Import directory structure from %1").arg(s));
4352 importDirInt (bo,d);
4356 void MapEditor::importDir()
4358 BranchObj *bo=xelection.getBranch();
4361 QStringList filters;
4362 filters <<"VYM map (*.vym)";
4363 QFileDialog *fd=new QFileDialog( this,vymName+ " - " +tr("Choose directory structure to import"));
4364 fd->setMode (QFileDialog::DirectoryOnly);
4365 fd->setFilters (filters);
4366 fd->setCaption(vymName+" - " +tr("Choose directory structure to import"));
4370 if ( fd->exec() == QDialog::Accepted )
4372 importDirInt (fd->selectedFile() );
4373 model->reposition();
4379 void MapEditor::followXLink(int i)
4381 BranchObj *bo=xelection.getBranch();
4384 bo=bo->XLinkTargetAt(i);
4387 xelection.select(bo);
4388 ensureSelectionVisible();
4393 void MapEditor::editXLink(int i) // FIXME missing saveState
4395 BranchObj *bo=xelection.getBranch();
4398 XLinkObj *xlo=bo->XLinkAt(i);
4401 EditXLinkDialog dia;
4403 dia.setSelection(bo);
4404 if (dia.exec() == QDialog::Accepted)
4406 if (dia.useSettingsGlobal() )
4408 setMapDefXLinkColor (xlo->getColor() );
4409 setMapDefXLinkWidth (xlo->getWidth() );
4411 if (dia.deleteXLink())
4412 bo->deleteXLinkAt(i);
4418 AttributeTable* MapEditor::attributeTable()
4423 void MapEditor::testFunction1()
4425 BranchObj *bo=xelection.getBranch();
4426 if (bo) model->moveAway (bo);
4430 BranchObj *bo=xelection.getBranch();
4431 if (bo) animObjList.append( bo );
4434 /* TODO Hide hidden stuff temporary, maybe add this as regular function somewhere
4435 if (hidemode==HideNone)
4437 setHideTmpMode (HideExport);
4438 mapCenter->calcBBoxSizeWithChilds();
4439 QRectF totalBBox=mapCenter->getTotalBBox();
4440 QRectF mapRect=totalBBox;
4441 QCanvasRectangle *frame=NULL;
4443 cout << " map has =("<<totalBBox.x()<<","<<totalBBox.y()<<","<<totalBBox.width()<<","<<totalBBox.height()<<")\n";
4445 mapRect.setRect (totalBBox.x(), totalBBox.y(),
4446 totalBBox.width(), totalBBox.height());
4447 frame=new QCanvasRectangle (mapRect,mapScene);
4448 frame->setBrush (QColor(white));
4449 frame->setPen (QColor(black));
4450 frame->setZValue(0);
4455 setHideTmpMode (HideNone);
4457 cout <<" hidemode="<<hidemode<<endl;
4461 void MapEditor::testFunction2()
4465 if (hidemode==HideExport)
4466 setHideTmpMode (HideNone);
4468 setHideTmpMode (HideExport);
4471 void MapEditor::contextMenuEvent ( QContextMenuEvent * e )
4473 // Lineedits are already closed by preceding
4474 // mouseEvent, we don't need to close here.
4476 QPointF p = mapToScene(e->pos());
4477 LinkableMapObj* lmo=model->findMapObj(p, NULL);
4480 { // MapObj was found
4481 if (xelection.single() != lmo)
4483 // select the MapObj
4484 xelection.select(lmo);
4487 if (xelection.getBranch() )
4489 // Context Menu on branch or mapcenter
4491 branchContextMenu->popup(e->globalPos() );
4494 if (xelection.getFloatImage() )
4496 // Context Menu on floatimage
4498 floatimageContextMenu->popup(e->globalPos() );
4502 { // No MapObj found, we are on the Canvas itself
4503 // Context Menu on scene
4506 canvasContextMenu->popup(e->globalPos() );
4511 void MapEditor::keyPressEvent(QKeyEvent* e)
4513 if (e->modifiers() & Qt::ControlModifier)
4515 switch (mainWindow->getModMode())
4517 case Main::ModModeColor:
4518 setCursor (PickColorCursor);
4520 case Main::ModModeCopy:
4521 setCursor (CopyCursor);
4523 case Main::ModModeXLink:
4524 setCursor (XLinkCursor);
4527 setCursor (Qt::ArrowCursor);
4533 void MapEditor::keyReleaseEvent(QKeyEvent* e)
4535 if (!(e->modifiers() & Qt::ControlModifier))
4536 setCursor (Qt::ArrowCursor);
4539 void MapEditor::mousePressEvent(QMouseEvent* e)
4541 // Ignore right clicks, these will go to context menus
4542 if (e->button() == Qt::RightButton )
4548 //Ignore clicks while editing heading
4549 if (isSelectBlocked() )
4555 QPointF p = mapToScene(e->pos());
4556 LinkableMapObj* lmo=model->findMapObj(p, NULL);
4560 //Take care of system flags _or_ modifier modes
4562 if (lmo && (typeid(*lmo)==typeid(BranchObj) ||
4563 typeid(*lmo)==typeid(MapCenterObj) ))
4565 QString foname=((BranchObj*)lmo)->getSystemFlagName(p);
4566 if (!foname.isEmpty())
4568 // systemFlag clicked
4572 if (e->state() & Qt::ControlModifier)
4573 mainWindow->editOpenURLTab();
4575 mainWindow->editOpenURL();
4577 else if (foname=="vymLink")
4579 mainWindow->editOpenVymLink();
4580 // tabWidget may change, better return now
4581 // before segfaulting...
4582 } else if (foname=="note")
4583 mainWindow->windowToggleNoteEditor();
4584 else if (foname=="hideInExport")
4591 // No system flag clicked, take care of modmodes (CTRL-Click)
4592 if (e->state() & Qt::ControlModifier)
4594 if (mainWindow->getModMode()==Main::ModModeColor)
4597 setCursor (PickColorCursor);
4600 if (mainWindow->getModMode()==Main::ModModeXLink)
4602 BranchObj *bo_begin=NULL;
4604 bo_begin=(BranchObj*)(lmo);
4606 if (xelection.getBranch() )
4607 bo_begin=xelection.getBranch();
4611 linkingObj_src=bo_begin;
4612 tmpXLink=new XLinkObj (mapScene);
4613 tmpXLink->setBegin (bo_begin);
4614 tmpXLink->setEnd (p);
4615 tmpXLink->setColor(defXLinkColor);
4616 tmpXLink->setWidth(defXLinkWidth);
4617 tmpXLink->updateXLink();
4618 tmpXLink->setVisibility (true);
4622 } // End of modmodes
4626 // Select the clicked object
4629 // Left Button Move Branches
4630 if (e->button() == Qt::LeftButton )
4632 //movingObj_start.setX( p.x() - selection->x() );// TODO replaced selection->lmo here
4633 //movingObj_start.setY( p.y() - selection->y() );
4634 movingObj_start.setX( p.x() - lmo->x() );
4635 movingObj_start.setY( p.y() - lmo->y() );
4636 movingObj_orgPos.setX (lmo->x() );
4637 movingObj_orgPos.setY (lmo->y() );
4638 movingObj_orgRelPos=lmo->getRelPos();
4640 // If modMode==copy, then we want to "move" the _new_ object around
4641 // then we need the offset from p to the _old_ selection, because of tmp
4642 if (mainWindow->getModMode()==Main::ModModeCopy &&
4643 e->state() & Qt::ControlModifier)
4645 BranchObj *bo=xelection.getBranch();
4649 bo->addBranch ((BranchObj*)xelection.single());
4651 xelection.select(bo->getLastBranch());
4652 model->reposition();
4656 movingObj=xelection.single();
4658 // Middle Button Toggle Scroll
4659 // (On Mac OS X this won't work, but we still have
4660 // a button in the toolbar)
4661 if (e->button() == Qt::MidButton )
4666 { // No MapObj found, we are on the scene itself
4667 // Left Button move Pos of sceneView
4668 if (e->button() == Qt::LeftButton )
4670 movingObj=NULL; // move Content not Obj
4671 movingObj_start=e->globalPos();
4672 movingCont_start=QPointF (
4673 horizontalScrollBar()->value(),
4674 verticalScrollBar()->value());
4675 movingVec=QPointF(0,0);
4676 setCursor(HandOpenCursor);
4681 void MapEditor::mouseMoveEvent(QMouseEvent* e)
4683 QPointF p = mapToScene(e->pos());
4684 LinkableMapObj *lmosel=xelection.single();
4686 // Move the selected MapObj
4687 if ( lmosel && movingObj)
4689 // reset cursor if we are moving and don't copy
4690 if (mainWindow->getModMode()!=Main::ModModeCopy)
4691 setCursor (Qt::ArrowCursor);
4693 // To avoid jumping of the sceneView, only
4694 // ensureSelectionVisible, if not tmp linked
4695 if (!lmosel->hasParObjTmp())
4696 ensureSelectionVisible ();
4698 // Now move the selection, but add relative position
4699 // (movingObj_start) where selection was chosen with
4700 // mousepointer. (This avoids flickering resp. jumping
4701 // of selection back to absPos)
4703 // Check if we could link
4704 LinkableMapObj* lmo=model->findMapObj(p, lmosel);
4707 FloatObj *fio=xelection.getFloatImage();
4710 fio->move (p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
4712 fio->updateLink(); //no need for reposition, if we update link here
4715 // Relink float to new mapcenter or branch, if shift is pressed
4716 // Only relink, if selection really has a new parent
4717 if ( (e->modifiers()==Qt::ShiftModifier) && lmo &&
4718 ( (typeid(*lmo)==typeid(BranchObj)) ||
4719 (typeid(*lmo)==typeid(MapCenterObj)) ) &&
4720 ( lmo != fio->getParObj())
4723 if (typeid(*fio) == typeid(FloatImageObj) &&
4724 ( (typeid(*lmo)==typeid(BranchObj) ||
4725 typeid(*lmo)==typeid(MapCenterObj)) ))
4728 // Also save the move which was done so far
4729 QString pold=qpointfToString(movingObj_orgRelPos);
4730 QString pnow=qpointfToString(fio->getRelPos());
4736 QString("Move %1 to relative position %2").arg(getName(fio)).arg(pnow));
4737 fio->getParObj()->requestReposition();
4738 model->reposition();
4740 linkTo (model->getSelectString(lmo));
4742 //movingObj_orgRelPos=lmosel->getRelPos();
4744 model->reposition();
4748 { // selection != a FloatObj
4749 if (lmosel->getDepth()==0)
4752 if (e->buttons()== Qt::LeftButton && e->modifiers()==Qt::ShiftModifier)
4753 ((MapCenterObj*)lmosel)->moveAll(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
4755 lmosel->move (p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
4756 model->updateRelPositions();
4759 if (lmosel->getDepth()==1)
4762 lmosel->move(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
4763 lmosel->setRelPos();
4766 // Move ordinary branch
4767 if (lmosel->getOrientation() == LinkableMapObj::LeftOfCenter)
4768 // Add width of bbox here, otherwise alignRelTo will cause jumping around
4769 lmosel->move(p.x() -movingObj_start.x()+lmosel->getBBox().width(),
4770 p.y()-movingObj_start.y() +lmosel->getTopPad() );
4772 lmosel->move(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() -lmosel->getTopPad());
4775 // Maybe we can relink temporary?
4776 if (lmo && (lmo!=lmosel) && xelection.getBranch() &&
4777 (typeid(*lmo)==typeid(BranchObj) ||
4778 typeid(*lmo)==typeid(MapCenterObj)) )
4781 if (e->modifiers()==Qt::ControlModifier)
4783 // Special case: CTRL to link below lmo
4784 lmosel->setParObjTmp (lmo,p,+1);
4786 else if (e->modifiers()==Qt::ShiftModifier)
4787 lmosel->setParObjTmp (lmo,p,-1);
4789 lmosel->setParObjTmp (lmo,p,0);
4792 lmosel->unsetParObjTmp();
4794 // reposition subbranch
4795 lmosel->reposition();
4799 } // no FloatImageObj
4803 } // selection && moving_obj
4805 // Draw a link from one branch to another
4808 tmpXLink->setEnd (p);
4809 tmpXLink->updateXLink();
4813 if (!movingObj && !pickingColor &&!drawingLink && e->buttons() == Qt::LeftButton )
4815 QPointF p=e->globalPos();
4816 movingVec.setX(-p.x() + movingObj_start.x() );
4817 movingVec.setY(-p.y() + movingObj_start.y() );
4818 horizontalScrollBar()->setSliderPosition((int)( movingCont_start.x()+movingVec.x() ));
4819 verticalScrollBar()->setSliderPosition((int)( movingCont_start.y()+movingVec.y() ) );
4824 void MapEditor::mouseReleaseEvent(QMouseEvent* e)
4826 QPointF p = mapToScene(e->pos());
4827 LinkableMapObj *dst;
4828 LinkableMapObj *lmosel=xelection.single();
4829 // Have we been picking color?
4833 setCursor (Qt::ArrowCursor);
4834 // Check if we are over another branch
4835 dst=model->findMapObj(p, NULL);
4838 if (e->state() & Qt::ShiftModifier)
4839 colorBranch (((BranchObj*)dst)->getColor());
4841 colorSubtree (((BranchObj*)dst)->getColor());
4846 // Have we been drawing a link?
4850 // Check if we are over another branch
4851 dst=model->findMapObj(p, NULL);
4854 tmpXLink->setEnd ( ((BranchObj*)(dst)) );
4855 tmpXLink->updateXLink();
4856 tmpXLink->activate(); //FIXME savestate missing
4857 //saveStateComplete(QString("Activate xLink from %1 to %2").arg(getName(tmpXLink->getBegin())).arg(getName(tmpXLink->getEnd())) );
4866 // Have we been moving something?
4867 if ( lmosel && movingObj )
4869 FloatImageObj *fo=xelection.getFloatImage();
4872 // Moved FloatObj. Maybe we need to reposition
4873 QString pold=qpointfToString(movingObj_orgRelPos);
4874 QString pnow=qpointfToString(fo->getRelPos());
4880 QString("Move %1 to relative position %2").arg(getName(fo)).arg(pnow));
4882 fo->getParObj()->requestReposition();
4883 model->reposition();
4886 // Check if we are over another branch, but ignore
4887 // any found LMOs, which are FloatObjs
4888 dst=model->findMapObj(mapToScene(e->pos() ), lmosel);
4890 if (dst && (typeid(*dst)!=typeid(BranchObj) && typeid(*dst)!=typeid(MapCenterObj)))
4893 BranchObj *bo=xelection.getBranch();
4894 if (bo && bo->getDepth()==0)
4896 if (movingObj_orgPos != bo->getAbsPos())
4898 QString pold=qpointfToString(movingObj_orgPos);
4899 QString pnow=qpointfToString(bo->getAbsPos());
4905 QString("Move mapcenter %1 to position %2").arg(getName(bo)).arg(pnow));
4909 if (xelection.type() == Selection::Branch )
4910 { // A branch was moved
4912 // save the position in case we link to mapcenter
4913 QPointF savePos=QPointF (lmosel->getAbsPos() );
4915 // Reset the temporary drawn link to the original one
4916 lmosel->unsetParObjTmp();
4918 // For Redo we may need to save original selection
4919 QString preSelStr=model->getSelectString(lmosel);
4924 BranchObj* bsel=xelection.getBranch();
4925 BranchObj* bdst=(BranchObj*)dst;
4927 QString preParStr=model->getSelectString (bsel->getParObj());
4928 QString preNum=QString::number (bsel->getNum(),10);
4929 QString preDstParStr;
4931 if (e->state() & Qt::ShiftModifier && dst->getParObj())
4933 preDstParStr=model->getSelectString (dst->getParObj());
4934 bsel->linkTo ( (BranchObj*)(bdst->getParObj()), bdst->getNum());
4936 if (e->state() & Qt::ControlModifier && dst->getParObj())
4939 preDstParStr=model->getSelectString (dst->getParObj());
4940 bsel->linkTo ( (BranchObj*)(bdst->getParObj()), bdst->getNum()+1);
4943 preDstParStr=model->getSelectString(dst);
4944 bsel->linkTo (bdst,-1);
4945 if (dst->getDepth()==0) bsel->move (savePos);
4947 QString postSelStr=model->getSelectString(lmosel);
4948 QString postNum=QString::number (bsel->getNum(),10);
4950 QString undoCom="linkTo (\""+
4951 preParStr+ "\"," + preNum +"," +
4952 QString ("%1,%2").arg(movingObj_orgPos.x()).arg(movingObj_orgPos.y())+ ")";
4954 QString redoCom="linkTo (\""+
4955 preDstParStr + "\"," + postNum + "," +
4956 QString ("%1,%2").arg(savePos.x()).arg(savePos.y())+ ")";
4961 QString("Relink %1 to %2").arg(getName(bsel)).arg(getName(dst)) );
4963 if (lmosel->getDepth()==1)
4965 // The select string might be different _after_ moving around.
4966 // Therefor reposition and then use string of old selection, too
4967 model->reposition();
4969 QPointF rp(lmosel->getRelPos());
4970 if (rp != movingObj_orgRelPos)
4972 QString ps=qpointfToString(rp);
4974 model->getSelectString(lmosel), "moveRel "+qpointfToString(movingObj_orgRelPos),
4975 preSelStr, "moveRel "+ps,
4976 QString("Move %1 to relative position %2").arg(getName(lmosel)).arg(ps));
4979 // Draw the original link, before selection was moved around
4980 model->reposition();
4983 // Finally resize scene, if needed
4987 // Just make sure, that actions are still ok,e.g. the move branch up/down buttons...
4990 // maybe we moved View: set old cursor
4991 setCursor (Qt::ArrowCursor);
4995 void MapEditor::mouseDoubleClickEvent(QMouseEvent* e)
4997 if (isSelectBlocked() )
5003 if (e->button() == Qt::LeftButton )
5005 QPointF p = mapToScene(e->pos());
5006 LinkableMapObj *lmo=model->findMapObj(p, NULL);
5007 if (lmo) { // MapObj was found
5008 // First select the MapObj than edit heading
5009 xelection.select(lmo);
5010 mainWindow->editHeading();
5015 void MapEditor::resizeEvent (QResizeEvent* e)
5017 QGraphicsView::resizeEvent( e );
5020 void MapEditor::dragEnterEvent(QDragEnterEvent *event)
5022 //for (unsigned int i=0;event->format(i);i++) // Debug mime type
5023 // cerr << event->format(i) << endl;
5025 if (event->mimeData()->hasImage())
5026 event->acceptProposedAction();
5028 if (event->mimeData()->hasUrls())
5029 event->acceptProposedAction();
5032 void MapEditor::dragMoveEvent(QDragMoveEvent *)
5036 void MapEditor::dragLeaveEvent(QDragLeaveEvent *event)
5041 void MapEditor::dropEvent(QDropEvent *event)
5043 BranchObj *sel=xelection.getBranch();
5047 foreach (QString format,event->mimeData()->formats())
5048 cout << "MapEditor: Dropped format: "<<qPrintable (format)<<endl;
5052 if (event->mimeData()->hasImage())
5054 QVariant imageData = event->mimeData()->imageData();
5055 addFloatImageInt (qvariant_cast<QPixmap>(imageData));
5057 if (event->mimeData()->hasUrls())
5058 uris=event->mimeData()->urls();
5066 for (int i=0; i<uris.count();i++)
5068 // Workaround to avoid adding empty branches
5069 if (!uris.at(i).toString().isEmpty())
5071 bo=sel->addBranch();
5074 s=uris.at(i).toLocalFile();
5077 QString file = QDir::fromNativeSeparators(s);
5078 heading = QFileInfo(file).baseName();
5080 if (file.endsWith(".vym", false))
5081 bo->setVymLink(file);
5083 bo->setURL(uris.at(i).toString());
5086 bo->setURL(uris.at(i).toString());
5089 if (!heading.isEmpty())
5090 bo->setHeading(heading);
5092 bo->setHeading(uris.at(i).toString());
5096 model->reposition();
5099 event->acceptProposedAction();
5102 void MapEditor::timerEvent(QTimerEvent *event) //TODO animation
5106 cout << "ME::timerEvent\n";
5108 for (int i=0; i<animObjList.size(); ++i)
5110 animObjList.at(i)->animate();
5111 ((BranchObj*)animObjList.at(i))->move2RelPos (((BranchObj*)animObjList.at(i))->getRelPos() );
5113 model->reposition();
5117 void MapEditor::sendSelection()
5119 if (netstate!=Server) return;
5120 sendData (QString("select (\"%1\")").arg(xelection.getSelectString()) );
5123 void MapEditor::newServer()
5127 tcpServer = new QTcpServer(this);
5128 if (!tcpServer->listen(QHostAddress::Any,port)) {
5129 QMessageBox::critical(this, "vym server",
5130 QString("Unable to start the server: %1.").arg(tcpServer->errorString()));
5134 connect(tcpServer, SIGNAL(newConnection()), this, SLOT(newClient()));
5136 cout<<"Server is running on port "<<tcpServer->serverPort()<<endl;
5139 void MapEditor::connectToServer()
5142 server="salam.suse.de";
5144 clientSocket = new QTcpSocket (this);
5145 clientSocket->abort();
5146 clientSocket->connectToHost(server ,port);
5147 connect(clientSocket, SIGNAL(readyRead()), this, SLOT(readData()));
5148 connect(clientSocket, SIGNAL(error(QAbstractSocket::SocketError)),
5149 this, SLOT(displayNetworkError(QAbstractSocket::SocketError)));
5151 cout<<"connected to "<<qPrintable (server)<<" port "<<port<<endl;
5156 void MapEditor::newClient()
5158 QTcpSocket *newClient = tcpServer->nextPendingConnection();
5159 connect(newClient, SIGNAL(disconnected()),
5160 newClient, SLOT(deleteLater()));
5162 cout <<"ME::newClient at "<<qPrintable( newClient->peerAddress().toString() )<<endl;
5164 clientList.append (newClient);
5168 void MapEditor::sendData(const QString &s)
5170 if (clientList.size()==0) return;
5172 // Create bytearray to send
5174 QDataStream out(&block, QIODevice::WriteOnly);
5175 out.setVersion(QDataStream::Qt_4_0);
5177 // Reserve some space for blocksize
5180 // Write sendCounter
5181 out << sendCounter++;
5186 // Go back and write blocksize so far
5187 out.device()->seek(0);
5188 quint16 bs=(quint16)(block.size() - 2*sizeof(quint16));
5192 cout << "ME::sendData bs="<<bs<<" counter="<<sendCounter<<" s="<<qPrintable(s)<<endl;
5194 for (int i=0; i<clientList.size(); ++i)
5196 //cout << "Sending \""<<qPrintable (s)<<"\" to "<<qPrintable (clientList.at(i)->peerAddress().toString())<<endl;
5197 clientList.at(i)->write (block);
5201 void MapEditor::readData ()
5203 while (clientSocket->bytesAvailable() >=(int)sizeof(quint16) )
5206 cout <<"readData bytesAvail="<<clientSocket->bytesAvailable();
5210 QDataStream in(clientSocket);
5211 in.setVersion(QDataStream::Qt_4_0);
5219 cout << " t="<<qPrintable (t)<<endl;
5225 void MapEditor::displayNetworkError(QAbstractSocket::SocketError socketError)
5227 switch (socketError) {
5228 case QAbstractSocket::RemoteHostClosedError:
5230 case QAbstractSocket::HostNotFoundError:
5231 QMessageBox::information(this, vymName +" Network client",
5232 "The host was not found. Please check the "
5233 "host name and port settings.");
5235 case QAbstractSocket::ConnectionRefusedError:
5236 QMessageBox::information(this, vymName + " Network client",
5237 "The connection was refused by the peer. "
5238 "Make sure the fortune server is running, "
5239 "and check that the host name and port "
5240 "settings are correct.");
5243 QMessageBox::information(this, vymName + " Network client",
5244 QString("The following error occurred: %1.")
5245 .arg(clientSocket->errorString()));
5249 void MapEditor::autosave()
5251 QDateTime now=QDateTime().currentDateTime();
5253 cout << "ME::autosave checking "<<qPrintable(filePath)<<"...\n";
5254 cout << "fsaved: "<<qPrintable (fileChangedTime.toString())<<endl;
5255 cout << " fnow: "<<qPrintable (QFileInfo(filePath).lastModified().toString())<<endl;
5256 cout << " time: "<<qPrintable (now.toString())<<endl;
5257 cout << " zipped="<<zipped<<endl;
5259 // Disable autosave, while we have gone back in history
5260 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
5261 if (redosAvail>0) return;
5264 if (mapUnsaved &&mapChanged && settings.value ("/mapeditor/autosave/use",true).toBool() )
5266 if (QFileInfo(filePath).lastModified()<=fileChangedTime)
5267 mainWindow->fileSave (this);
5270 cout <<" ME::autosave rejected, file on disk is newer than last save.\n";
5275 void MapEditor::fileChanged()
5277 // Check if file on disk has changed meanwhile
5278 if (!filePath.isEmpty())
5280 QDateTime tmod=QFileInfo (filePath).lastModified();
5281 if (tmod>fileChangedTime)
5284 /* FIXME debug message, sometimes there's a glitch in the metrics...
5285 cout << "ME::fileChanged()\n"
5286 << " last saved: "<<qPrintable (fileChangedTime.toString())<<endl
5287 << " last modififed: "<<qPrintable (tmod.toString())<<endl;
5289 // FIXME switch to current mapeditor and finish lineedits...
5290 QMessageBox mb( vymName,
5291 tr("The file of the map on disk has changed:\n\n"
5292 " %1\n\nDo you want to reload this map with the new file?").arg(filePath),
5293 QMessageBox::Question,
5295 QMessageBox::Cancel | QMessageBox::Default,
5296 QMessageBox::NoButton );
5298 mb.setButtonText( QMessageBox::Yes, tr("Reload"));
5299 mb.setButtonText( QMessageBox::No, tr("Ignore"));
5302 case QMessageBox::Yes:
5304 load (filePath,NewMap,fileType);
5305 case QMessageBox::Cancel:
5306 fileChangedTime=tmod; // allow autosave to overwrite newer file!
5314 /*TODO not needed? void MapEditor::contentsDropEvent(QDropEvent *event)
5317 } else if (event->provides("application/x-moz-file-promise-url") &&
5318 event->provides("application/x-moz-nativeimage"))
5320 // Contains url to the img src in unicode16
5321 QByteArray d = event->encodedData("application/x-moz-file-promise-url");
5322 QString url = QString((const QChar*)d.data(),d.size()/2);
5326 } else if (event->provides ("text/uri-list"))
5327 { // Uris provided e.g. by konqueror
5328 Q3UriDrag::decode (event,uris);
5329 } else if (event->provides ("_NETSCAPE_URL"))
5330 { // Uris provided by Mozilla
5331 QStringList l = QStringList::split("\n", event->encodedData("_NETSCAPE_URL"));
5334 } else if (event->provides("text/html")) {
5336 // Handels text mime types
5337 // Look like firefox allways handle text as unicode16 (2 bytes per char.)
5338 QByteArray d = event->encodedData("text/html");
5341 text = QString((const QChar*)d.data(),d.size()/2);
5345 textEditor->setText(text);
5349 } else if (event->provides("text/plain")) {
5350 QByteArray d = event->encodedData("text/plain");
5353 text = QString((const QChar*)d.data(),d.size()/2);
5357 textEditor->setText(text);
5367 bool isUnicode16(const QByteArray &d)
5369 // TODO: make more precise check for unicode 16.
5370 // Guess unicode16 if any of second bytes are zero
5371 unsigned int length = max(0,d.size()-2)/2;
5372 for (unsigned int i = 0; i<length ; i++)
5373 if (d.at(i*2+1)==0) return true;
5377 void MapEditor::addFloatImageInt (const QPixmap &img)
5379 BranchObj *bo=xelection.getBranch();
5382 FloatImageObj *fio=bo->addFloatImage();
5384 fio->setOriginalFilename("No original filename (image added by dropevent)");
5385 QString s=model->getSelectString(bo);
5386 saveState (PartOfMap, s, "nop ()", s, "copy ()","Copy dropped image to clipboard",fio );
5387 saveState (fio,"delete ()", bo,QString("paste(%1)").arg(curStep),"Pasting dropped image");
5388 model->reposition();
5395 void MapEditor::imageDataFetched(const QByteArray &a, Q3NetworkOperation * / *nop* /)
5397 if (!imageBuffer) imageBuffer = new QBuffer();
5398 if (!imageBuffer->isOpen()) {
5399 imageBuffer->open(QIODevice::WriteOnly | QIODevice::Append);
5401 imageBuffer->at(imageBuffer->at()+imageBuffer->writeBlock(a));
5405 void MapEditor::imageDataFinished(Q3NetworkOperation *nop)
5407 if (nop->state()==Q3NetworkProtocol::StDone) {
5408 QPixmap img(imageBuffer->buffer());
5409 addFloatImageInt (img);
5413 imageBuffer->close();
5415 imageBuffer->close();
5422 void MapEditor::fetchImage(const QString &url)
5425 urlOperator->stop();
5426 disconnect(urlOperator);
5430 urlOperator = new Q3UrlOperator(url);
5431 connect(urlOperator, SIGNAL(finished(Q3NetworkOperation *)),
5432 this, SLOT(imageDataFinished(Q3NetworkOperation*)));
5434 connect(urlOperator, SIGNAL(data(const QByteArray &, Q3NetworkOperation *)),
5435 this, SLOT(imageDataFetched(const QByteArray &, Q3NetworkOperation *)));