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 (saveSel->getSelectString())<<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=undoSel->getSelectString();
449 qWarning ("MapEditor::saveStateChangingPart no undoSel given!");
450 QString redoSelection="";
452 redoSelection=undoSel->getSelectString();
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=redoSel->getParObj()->getSelectString();
472 QString redoSelection=redoSel->getSelectString();
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=redoSel->getSelectString();
493 QString undoSelection="";
494 if (undoSel) undoSelection=undoSel->getSelectString();
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("addMapReplace"))
583 if (xelection.isEmpty())
585 parser.setError (Aborted,"Nothing selected");
588 parser.setError (Aborted,"Type of selection is not a branch");
589 } else if (parser.checkParCount(1))
591 //s=parser.parString (ok,0); // selection
592 t=parser.parString (ok,0); // path to map
593 if (QDir::isRelativePath(t)) t=(tmpMapDir + "/"+t);
594 addMapReplaceInt(selb->getSelectString(),t);
596 /////////////////////////////////////////////////////////////////////
597 } else if (com==QString("addMapInsert"))
599 if (xelection.isEmpty())
601 parser.setError (Aborted,"Nothing selected");
604 parser.setError (Aborted,"Type of selection is not a branch");
607 if (parser.checkParCount(2))
609 t=parser.parString (ok,0); // path to map
610 n=parser.parInt(ok,1); // position
611 if (QDir::isRelativePath(t)) t=(tmpMapDir + "/"+t);
612 addMapInsertInt(t,n);
615 /////////////////////////////////////////////////////////////////////
616 } else if (com=="clearFlags")
618 if (xelection.isEmpty() )
620 parser.setError (Aborted,"Nothing selected");
623 parser.setError (Aborted,"Type of selection is not a branch");
624 } else if (parser.checkParCount(0))
626 selb->clearStandardFlags();
627 selb->updateFlagsToolbar();
629 /////////////////////////////////////////////////////////////////////
630 } else if (com=="colorBranch")
632 if (xelection.isEmpty())
634 parser.setError (Aborted,"Nothing selected");
637 parser.setError (Aborted,"Type of selection is not a branch");
638 } else if (parser.checkParCount(1))
640 QColor c=parser.parColor (ok,0);
641 if (ok) colorBranch (c);
643 /////////////////////////////////////////////////////////////////////
644 } else if (com=="colorSubtree")
646 if (xelection.isEmpty())
648 parser.setError (Aborted,"Nothing selected");
651 parser.setError (Aborted,"Type of selection is not a branch");
652 } else if (parser.checkParCount(1))
654 QColor c=parser.parColor (ok,0);
655 if (ok) colorSubtree (c);
657 /////////////////////////////////////////////////////////////////////
658 } else if (com=="copy")
660 if (xelection.isEmpty())
662 parser.setError (Aborted,"Nothing selected");
665 parser.setError (Aborted,"Type of selection is not a branch");
666 } else if (parser.checkParCount(0))
668 //FIXME missing action for copy
670 /////////////////////////////////////////////////////////////////////
671 } else if (com=="cut")
673 if (xelection.isEmpty())
675 parser.setError (Aborted,"Nothing selected");
676 } else if ( xelection.type()!=Selection::Branch &&
677 xelection.type()!=Selection::MapCenter &&
678 xelection.type()!=Selection::FloatImage )
680 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
681 } else if (parser.checkParCount(0))
685 /////////////////////////////////////////////////////////////////////
686 } else if (com=="delete")
688 if (xelection.isEmpty())
690 parser.setError (Aborted,"Nothing selected");
691 } else if (xelection.type() != Selection::Branch && xelection.type() != Selection::FloatImage )
693 parser.setError (Aborted,"Type of selection is wrong.");
694 } else if (parser.checkParCount(0))
698 /////////////////////////////////////////////////////////////////////
699 } else if (com=="deleteKeepChilds")
701 if (xelection.isEmpty())
703 parser.setError (Aborted,"Nothing selected");
706 parser.setError (Aborted,"Type of selection is not a branch");
707 } else if (parser.checkParCount(0))
711 /////////////////////////////////////////////////////////////////////
712 } else if (com=="deleteChilds")
714 if (xelection.isEmpty())
716 parser.setError (Aborted,"Nothing selected");
719 parser.setError (Aborted,"Type of selection is not a branch");
720 } else if (parser.checkParCount(0))
724 /////////////////////////////////////////////////////////////////////
725 } else if (com=="exportASCII")
729 if (parser.parCount()>=1)
730 // Hey, we even have a filename
731 fname=parser.parString(ok,0);
734 parser.setError (Aborted,"Could not read filename");
737 exportASCII (fname,false);
739 /////////////////////////////////////////////////////////////////////
740 } else if (com=="exportImage")
744 if (parser.parCount()>=2)
745 // Hey, we even have a filename
746 fname=parser.parString(ok,0);
749 parser.setError (Aborted,"Could not read filename");
752 QString format="PNG";
753 if (parser.parCount()>=2)
755 format=parser.parString(ok,1);
757 exportImage (fname,false,format);
759 /////////////////////////////////////////////////////////////////////
760 } else if (com=="exportXHTML")
764 if (parser.parCount()>=2)
765 // Hey, we even have a filename
766 fname=parser.parString(ok,1);
769 parser.setError (Aborted,"Could not read filename");
772 exportXHTML (fname,false);
774 /////////////////////////////////////////////////////////////////////
775 } else if (com=="exportXML")
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 exportXML (fname,false);
789 /////////////////////////////////////////////////////////////////////
790 } else if (com=="importDir")
792 if (xelection.isEmpty())
794 parser.setError (Aborted,"Nothing selected");
797 parser.setError (Aborted,"Type of selection is not a branch");
798 } else if (parser.checkParCount(1))
800 s=parser.parString(ok,0);
801 if (ok) importDirInt(s);
803 /////////////////////////////////////////////////////////////////////
804 } else if (com=="linkTo")
806 if (xelection.isEmpty())
808 parser.setError (Aborted,"Nothing selected");
811 if (parser.checkParCount(4))
813 // 0 selectstring of parent
814 // 1 num in parent (for branches)
815 // 2,3 x,y of mainbranch or mapcenter
816 s=parser.parString(ok,0);
817 LinkableMapObj *dst=model->findObjBySelect (s);
820 if (typeid(*dst) == typeid(BranchObj) )
822 // Get number in parent
823 n=parser.parInt (ok,1);
826 selb->linkTo ((BranchObj*)(dst),n);
829 } else if (typeid(*dst) == typeid(MapCenterObj) )
831 selb->linkTo ((BranchObj*)(dst),-1);
832 // Get coordinates of mainbranch
833 x=parser.parDouble(ok,2);
836 y=parser.parDouble(ok,3);
846 } else if ( xelection.type() == Selection::FloatImage)
848 if (parser.checkParCount(1))
850 // 0 selectstring of parent
851 s=parser.parString(ok,0);
852 LinkableMapObj *dst=model->findObjBySelect (s);
855 if (typeid(*dst) == typeid(BranchObj) ||
856 typeid(*dst) == typeid(MapCenterObj))
857 linkTo (dst->getSelectString());
859 parser.setError (Aborted,"Destination is not a branch");
862 parser.setError (Aborted,"Type of selection is not a floatimage or branch");
863 /////////////////////////////////////////////////////////////////////
864 } else if (com=="loadImage")
866 if (xelection.isEmpty())
868 parser.setError (Aborted,"Nothing selected");
871 parser.setError (Aborted,"Type of selection is not a branch");
872 } else if (parser.checkParCount(1))
874 s=parser.parString(ok,0);
875 if (ok) loadFloatImageInt (s);
877 /////////////////////////////////////////////////////////////////////
878 } else if (com=="moveBranchUp")
880 if (xelection.isEmpty() )
882 parser.setError (Aborted,"Nothing selected");
885 parser.setError (Aborted,"Type of selection is not a branch");
886 } else if (parser.checkParCount(0))
890 /////////////////////////////////////////////////////////////////////
891 } else if (com=="moveBranchDown")
893 if (xelection.isEmpty() )
895 parser.setError (Aborted,"Nothing selected");
898 parser.setError (Aborted,"Type of selection is not a branch");
899 } else if (parser.checkParCount(0))
903 /////////////////////////////////////////////////////////////////////
904 } else if (com=="move")
906 if (xelection.isEmpty() )
908 parser.setError (Aborted,"Nothing selected");
909 } else if ( xelection.type()!=Selection::Branch &&
910 xelection.type()!=Selection::MapCenter &&
911 xelection.type()!=Selection::FloatImage )
913 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
914 } else if (parser.checkParCount(2))
916 x=parser.parDouble (ok,0);
919 y=parser.parDouble (ok,1);
923 /////////////////////////////////////////////////////////////////////
924 } else if (com=="moveRel")
926 if (xelection.isEmpty() )
928 parser.setError (Aborted,"Nothing selected");
929 } else if ( xelection.type()!=Selection::Selection::Branch &&
930 xelection.type()!=Selection::Selection::MapCenter &&
931 xelection.type()!=Selection::Selection::FloatImage )
933 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
934 } else if (parser.checkParCount(2))
936 x=parser.parDouble (ok,0);
939 y=parser.parDouble (ok,1);
940 if (ok) moveRel (x,y);
943 /////////////////////////////////////////////////////////////////////
944 } else if (com=="nop")
946 /////////////////////////////////////////////////////////////////////
947 } else if (com=="paste")
949 if (xelection.isEmpty() )
951 parser.setError (Aborted,"Nothing selected");
954 parser.setError (Aborted,"Type of selection is not a branch");
955 } else if (parser.checkParCount(1))
957 n=parser.parInt (ok,0);
958 if (ok) pasteNoSave(n);
960 /////////////////////////////////////////////////////////////////////
961 } else if (com=="qa")
963 if (xelection.isEmpty() )
965 parser.setError (Aborted,"Nothing selected");
968 parser.setError (Aborted,"Type of selection is not a branch");
969 } else if (parser.checkParCount(4))
972 c=parser.parString (ok,0);
975 parser.setError (Aborted,"No comment given");
978 s=parser.parString (ok,1);
981 parser.setError (Aborted,"First parameter is not a string");
984 t=parser.parString (ok,2);
987 parser.setError (Aborted,"Condition is not a string");
990 u=parser.parString (ok,3);
993 parser.setError (Aborted,"Third parameter is not a string");
998 parser.setError (Aborted,"Unknown type: "+s);
1003 parser.setError (Aborted,"Unknown operator: "+t);
1008 parser.setError (Aborted,"Type of selection is not a branch");
1011 if (selb->getHeading() == u)
1013 cout << "PASSED: " << qPrintable (c) << endl;
1016 cout << "FAILED: " << qPrintable (c) << endl;
1026 /////////////////////////////////////////////////////////////////////
1027 } else if (com=="saveImage")
1029 FloatImageObj *fio=xelection.getFloatImage();
1032 parser.setError (Aborted,"Type of selection is not an image");
1033 } else if (parser.checkParCount(2))
1035 s=parser.parString(ok,0);
1038 t=parser.parString(ok,1);
1039 if (ok) saveFloatImageInt (fio,t,s);
1042 /////////////////////////////////////////////////////////////////////
1043 } else if (com=="scroll")
1045 if (xelection.isEmpty() )
1047 parser.setError (Aborted,"Nothing selected");
1050 parser.setError (Aborted,"Type of selection is not a branch");
1051 } else if (parser.checkParCount(0))
1053 if (!scrollBranch (selb))
1054 parser.setError (Aborted,"Could not scroll branch");
1056 /////////////////////////////////////////////////////////////////////
1057 } else if (com=="select")
1059 if (parser.checkParCount(1))
1061 s=parser.parString(ok,0);
1064 /////////////////////////////////////////////////////////////////////
1065 } else if (com=="selectLastBranch")
1067 if (xelection.isEmpty() )
1069 parser.setError (Aborted,"Nothing selected");
1072 parser.setError (Aborted,"Type of selection is not a branch");
1073 } else if (parser.checkParCount(0))
1075 BranchObj *bo=selb->getLastBranch();
1077 parser.setError (Aborted,"Could not select last branch");
1081 /////////////////////////////////////////////////////////////////////
1082 } else if (com=="selectLastImage")
1084 if (xelection.isEmpty() )
1086 parser.setError (Aborted,"Nothing selected");
1089 parser.setError (Aborted,"Type of selection is not a branch");
1090 } else if (parser.checkParCount(0))
1092 FloatImageObj *fio=selb->getLastFloatImage();
1094 parser.setError (Aborted,"Could not select last image");
1098 /////////////////////////////////////////////////////////////////////
1099 } else if (com=="selectLatestAdded")
1101 if (latestSelection.isEmpty() )
1103 parser.setError (Aborted,"No latest added object");
1106 if (!select (latestSelection))
1107 parser.setError (Aborted,"Could not select latest added object "+latestSelection);
1109 /////////////////////////////////////////////////////////////////////
1110 } else if (com=="setFrameType")
1112 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
1114 parser.setError (Aborted,"Type of selection does not allow setting frame type");
1116 else if (parser.checkParCount(1))
1118 s=parser.parString(ok,0);
1119 if (ok) setFrameType (s);
1121 /////////////////////////////////////////////////////////////////////
1122 } else if (com=="setFramePenColor")
1124 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
1126 parser.setError (Aborted,"Type of selection does not allow setting of pen color");
1128 else if (parser.checkParCount(1))
1130 QColor c=parser.parColor(ok,0);
1131 if (ok) setFramePenColor (c);
1133 /////////////////////////////////////////////////////////////////////
1134 } else if (com=="setFrameBrushColor")
1136 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
1138 parser.setError (Aborted,"Type of selection does not allow setting brush color");
1140 else if (parser.checkParCount(1))
1142 QColor c=parser.parColor(ok,0);
1143 if (ok) setFrameBrushColor (c);
1145 /////////////////////////////////////////////////////////////////////
1146 } else if (com=="setFramePadding")
1148 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
1150 parser.setError (Aborted,"Type of selection does not allow setting frame padding");
1152 else if (parser.checkParCount(1))
1154 n=parser.parInt(ok,0);
1155 if (ok) setFramePadding(n);
1157 /////////////////////////////////////////////////////////////////////
1158 } else if (com=="setFrameBorderWidth")
1160 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
1162 parser.setError (Aborted,"Type of selection does not allow setting frame border width");
1164 else if (parser.checkParCount(1))
1166 n=parser.parInt(ok,0);
1167 if (ok) setFrameBorderWidth (n);
1169 /////////////////////////////////////////////////////////////////////
1170 } else if (com=="setMapAuthor")
1172 if (parser.checkParCount(1))
1174 s=parser.parString(ok,0);
1175 if (ok) setMapAuthor (s);
1177 /////////////////////////////////////////////////////////////////////
1178 } else if (com=="setMapComment")
1180 if (parser.checkParCount(1))
1182 s=parser.parString(ok,0);
1183 if (ok) setMapComment(s);
1185 /////////////////////////////////////////////////////////////////////
1186 } else if (com=="setMapBackgroundColor")
1188 if (xelection.isEmpty() )
1190 parser.setError (Aborted,"Nothing selected");
1191 } else if (! xelection.getBranch() )
1193 parser.setError (Aborted,"Type of selection is not a branch");
1194 } else if (parser.checkParCount(1))
1196 QColor c=parser.parColor (ok,0);
1197 if (ok) setMapBackgroundColor (c);
1199 /////////////////////////////////////////////////////////////////////
1200 } else if (com=="setMapDefLinkColor")
1202 if (xelection.isEmpty() )
1204 parser.setError (Aborted,"Nothing selected");
1207 parser.setError (Aborted,"Type of selection is not a branch");
1208 } else if (parser.checkParCount(1))
1210 QColor c=parser.parColor (ok,0);
1211 if (ok) setMapDefLinkColor (c);
1213 /////////////////////////////////////////////////////////////////////
1214 } else if (com=="setMapLinkStyle")
1216 if (parser.checkParCount(1))
1218 s=parser.parString (ok,0);
1219 if (ok) setMapLinkStyle(s);
1221 /////////////////////////////////////////////////////////////////////
1222 } else if (com=="setHeading")
1224 if (xelection.isEmpty() )
1226 parser.setError (Aborted,"Nothing selected");
1229 parser.setError (Aborted,"Type of selection is not a branch");
1230 } else if (parser.checkParCount(1))
1232 s=parser.parString (ok,0);
1236 /////////////////////////////////////////////////////////////////////
1237 } else if (com=="setHideExport")
1239 if (xelection.isEmpty() )
1241 parser.setError (Aborted,"Nothing selected");
1242 } else if (xelection.type()!=Selection::Branch && xelection.type() != Selection::MapCenter &&xelection.type()!=Selection::FloatImage)
1244 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
1245 } else if (parser.checkParCount(1))
1247 b=parser.parBool(ok,0);
1248 if (ok) setHideExport (b);
1250 /////////////////////////////////////////////////////////////////////
1251 } else if (com=="setIncludeImagesHorizontally")
1253 if (xelection.isEmpty() )
1255 parser.setError (Aborted,"Nothing selected");
1258 parser.setError (Aborted,"Type of selection is not a branch");
1259 } else if (parser.checkParCount(1))
1261 b=parser.parBool(ok,0);
1262 if (ok) setIncludeImagesHor(b);
1264 /////////////////////////////////////////////////////////////////////
1265 } else if (com=="setIncludeImagesVertically")
1267 if (xelection.isEmpty() )
1269 parser.setError (Aborted,"Nothing selected");
1272 parser.setError (Aborted,"Type of selection is not a branch");
1273 } else if (parser.checkParCount(1))
1275 b=parser.parBool(ok,0);
1276 if (ok) setIncludeImagesVer(b);
1278 /////////////////////////////////////////////////////////////////////
1279 } else if (com=="setHideLinkUnselected")
1281 if (xelection.isEmpty() )
1283 parser.setError (Aborted,"Nothing selected");
1284 } else if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
1286 parser.setError (Aborted,"Type of selection does not allow hiding the link");
1287 } else if (parser.checkParCount(1))
1289 b=parser.parBool(ok,0);
1290 if (ok) setHideLinkUnselected(b);
1292 /////////////////////////////////////////////////////////////////////
1293 } else if (com=="setSelectionColor")
1295 if (parser.checkParCount(1))
1297 QColor c=parser.parColor (ok,0);
1298 if (ok) setSelectionColorInt (c);
1300 /////////////////////////////////////////////////////////////////////
1301 } else if (com=="setURL")
1303 if (xelection.isEmpty() )
1305 parser.setError (Aborted,"Nothing selected");
1308 parser.setError (Aborted,"Type of selection is not a branch");
1309 } else if (parser.checkParCount(1))
1311 s=parser.parString (ok,0);
1314 /////////////////////////////////////////////////////////////////////
1315 } else if (com=="setVymLink")
1317 if (xelection.isEmpty() )
1319 parser.setError (Aborted,"Nothing selected");
1322 parser.setError (Aborted,"Type of selection is not a branch");
1323 } else if (parser.checkParCount(1))
1325 s=parser.parString (ok,0);
1326 if (ok) setVymLinkInt(s);
1329 /////////////////////////////////////////////////////////////////////
1330 else if (com=="setFlag")
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);
1343 selb->activateStandardFlag(s);
1344 selb->updateFlagsToolbar();
1347 /////////////////////////////////////////////////////////////////////
1348 } else if (com=="setFrameType")
1350 if (xelection.isEmpty() )
1352 parser.setError (Aborted,"Nothing selected");
1355 parser.setError (Aborted,"Type of selection is not a branch");
1356 } else if (parser.checkParCount(1))
1358 s=parser.parString(ok,0);
1362 /////////////////////////////////////////////////////////////////////
1363 } else if (com=="sortChildren")
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(0))
1375 /////////////////////////////////////////////////////////////////////
1376 } else if (com=="toggleFlag")
1378 if (xelection.isEmpty() )
1380 parser.setError (Aborted,"Nothing selected");
1383 parser.setError (Aborted,"Type of selection is not a branch");
1384 } else if (parser.checkParCount(1))
1386 s=parser.parString(ok,0);
1389 selb->toggleStandardFlag(s);
1390 selb->updateFlagsToolbar();
1393 /////////////////////////////////////////////////////////////////////
1394 } else if (com=="unscroll")
1396 if (xelection.isEmpty() )
1398 parser.setError (Aborted,"Nothing selected");
1401 parser.setError (Aborted,"Type of selection is not a branch");
1402 } else if (parser.checkParCount(0))
1404 if (!unscrollBranch (selb))
1405 parser.setError (Aborted,"Could not unscroll branch");
1407 /////////////////////////////////////////////////////////////////////
1408 } else if (com=="unscrollChilds")
1410 if (xelection.isEmpty() )
1412 parser.setError (Aborted,"Nothing selected");
1415 parser.setError (Aborted,"Type of selection is not a branch");
1416 } else if (parser.checkParCount(0))
1420 /////////////////////////////////////////////////////////////////////
1421 } else if (com=="unsetFlag")
1423 if (xelection.isEmpty() )
1425 parser.setError (Aborted,"Nothing selected");
1428 parser.setError (Aborted,"Type of selection is not a branch");
1429 } else if (parser.checkParCount(1))
1431 s=parser.parString(ok,0);
1434 selb->deactivateStandardFlag(s);
1435 selb->updateFlagsToolbar();
1439 parser.setError (Aborted,"Unknown command");
1442 if (parser.errorLevel()==NoError)
1444 // setChanged(); FIXME should not be called e.g. for export?!
1445 model->reposition();
1449 // TODO Error handling
1450 qWarning("MapEditor::parseAtom: Error!");
1451 qWarning(parser.errorMessage());
1455 void MapEditor::runScript (QString script)
1457 parser.setScript (script);
1459 while (parser.next() )
1460 parseAtom(parser.getAtom());
1463 bool MapEditor::isDefault()
1468 bool MapEditor::hasChanged()
1473 void MapEditor::setChanged()
1476 autosaveTimer->start(settings.value("/mapeditor/autosave/ms/",300000).toInt());
1484 void MapEditor::closeMap()
1486 // Unselect before disabling the toolbar actions
1487 if (!xelection.isEmpty() ) xelection.unselect();
1495 void MapEditor::setFilePath(QString fpath, QString destname)
1497 if (fpath.isEmpty() || fpath=="")
1504 filePath=fpath; // becomes absolute path
1505 fileName=fpath; // gets stripped of path
1506 destPath=destname; // needed for vymlinks and during load to reset fileChangedTime
1508 // If fpath is not an absolute path, complete it
1509 filePath=QDir(fpath).absPath();
1510 fileDir=filePath.left (1+filePath.findRev ("/"));
1512 // Set short name, too. Search from behind:
1513 int i=fileName.findRev("/");
1514 if (i>=0) fileName=fileName.remove (0,i+1);
1516 // Forget the .vym (or .xml) for name of map
1517 mapName=fileName.left(fileName.findRev(".",-1,true) );
1521 void MapEditor::setFilePath(QString fpath)
1523 setFilePath (fpath,fpath);
1526 QString MapEditor::getFilePath()
1531 QString MapEditor::getFileName()
1536 QString MapEditor::getMapName()
1541 QString MapEditor::getDestPath()
1546 ErrorCode MapEditor::load (QString fname, const LoadMode &lmode, const FileType &ftype)
1548 ErrorCode err=success;
1550 parseBaseHandler *handler;
1554 case VymMap: handler=new parseVYMHandler; break;
1555 case FreemindMap : handler=new parseFreemindHandler; break;
1557 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
1558 "Unknown FileType in MapEditor::load()");
1564 model->setMapEditor(this);
1565 // (map state is set later at end of load...)
1568 BranchObj *bo=xelection.getBranch();
1569 if (!bo) return aborted;
1570 if (lmode==ImportAdd)
1571 saveStateChangingPart(
1574 QString("addMapInsert (%1)").arg(fname),
1575 QString("Add map %1 to %2").arg(fname).arg(getName(bo)));
1577 saveStateChangingPart(
1580 QString("addMapReplace(%1)").arg(fname),
1581 QString("Add map %1 to %2").arg(fname).arg(getName(bo)));
1585 // Create temporary directory for packing
1587 QString tmpZipDir=makeTmpDir (ok,"vym-pack");
1590 QMessageBox::critical( 0, tr( "Critical Load Error" ),
1591 tr("Couldn't create temporary directory before load\n"));
1595 // Try to unzip file
1596 err=unzipDir (tmpZipDir,fname);
1606 // Look for mapname.xml
1607 xmlfile= fname.left(fname.findRev(".",-1,true));
1608 xmlfile=xmlfile.section( '/', -1 );
1609 QFile mfile( tmpZipDir + "/" + xmlfile + ".xml");
1610 if (!mfile.exists() )
1612 // mapname.xml does not exist, well,
1613 // maybe someone renamed the mapname.vym file...
1614 // Try to find any .xml in the toplevel
1615 // directory of the .vym file
1616 QStringList flist=QDir (tmpZipDir).entryList("*.xml");
1617 if (flist.count()==1)
1619 // Only one entry, take this one
1620 xmlfile=tmpZipDir + "/"+flist.first();
1623 for ( QStringList::Iterator it = flist.begin(); it != flist.end(); ++it )
1624 *it=tmpZipDir + "/" + *it;
1625 // TODO Multiple entries, load all (but only the first one into this ME)
1626 //mainWindow->fileLoadFromTmp (flist);
1627 //returnCode=1; // Silently forget this attempt to load
1628 qWarning ("MainWindow::load (fn) multimap found...");
1631 if (flist.isEmpty() )
1633 QMessageBox::critical( 0, tr( "Critical Load Error" ),
1634 tr("Couldn't find a map (*.xml) in .vym archive.\n"));
1637 } //file doesn't exist
1639 xmlfile=mfile.name();
1642 QFile file( xmlfile);
1644 // I am paranoid: file should exist anyway
1645 // according to check in mainwindow.
1646 if (!file.exists() )
1648 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
1649 tr(QString("Couldn't open map %1").arg(file.name())));
1653 bool blockSaveStateOrg=blockSaveState;
1654 blockReposition=true;
1655 blockSaveState=true;
1656 QXmlInputSource source( file);
1657 QXmlSimpleReader reader;
1658 reader.setContentHandler( handler );
1659 reader.setErrorHandler( handler );
1660 handler->setModel ( model);
1663 // We need to set the tmpDir in order to load files with rel. path
1664 QString tmpdir= fname.left(fname.findRev("/",-1));
1665 handler->setTmpDir (tmpdir);
1666 handler->setInputFile (file.name());
1667 handler->setLoadMode (lmode);
1668 bool ok = reader.parse( source );
1669 blockReposition=false;
1670 blockSaveState=blockSaveStateOrg;
1674 model->reposition(); // FIXME reposition the view instead...
1681 autosaveTimer->stop();
1684 // Reset timestamp to check for later updates of file
1685 fileChangedTime=QFileInfo (destPath).lastModified();
1688 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
1689 tr( handler->errorProtocol() ) );
1691 // Still return "success": the map maybe at least
1692 // partially read by the parser
1697 removeDir (QDir(tmpZipDir));
1703 ErrorCode MapEditor::save (const SaveMode &savemode)
1705 cout <<"ME::save "<<qPrintable (mapName)<<" zipped="<<zipped<<endl; // FIXME debug
1706 // Create mapName and fileDir
1707 makeSubDirs (fileDir);
1709 QString mapFileName;
1710 QString safeFilePath;
1712 ErrorCode err=success;
1716 mapFileName=mapName+".xml";
1718 // use name given by user, even if he chooses .doc
1719 mapFileName=fileName;
1721 // Look, if we should zip the data:
1724 QMessageBox mb( vymName,
1725 tr("The map %1\ndid not use the compressed "
1726 "vym file format.\nWriting it uncompressed will also write images \n"
1727 "and flags and thus may overwrite files in the "
1728 "given directory\n\nDo you want to write the map").arg(filePath),
1729 QMessageBox::Warning,
1730 QMessageBox::Yes | QMessageBox::Default,
1732 QMessageBox::Cancel | QMessageBox::Escape);
1733 mb.setButtonText( QMessageBox::Yes, tr("compressed (vym default)") );
1734 mb.setButtonText( QMessageBox::No, tr("uncompressed") );
1735 mb.setButtonText( QMessageBox::Cancel, tr("Cancel"));
1738 case QMessageBox::Yes:
1739 // save compressed (default file format)
1742 case QMessageBox::No:
1743 // save uncompressed
1746 case QMessageBox::Cancel:
1753 // First backup existing file, we
1754 // don't want to add to old zip archives
1758 if ( settings.value ("/mapeditor/writeBackupFile").toBool())
1760 cout << "ME::doing backup...\n";//FIXME
1761 QString backupFileName(destPath + "~");
1762 QFile backupFile(backupFileName);
1763 if (backupFile.exists() && !backupFile.remove())
1765 QMessageBox::warning(0, tr("Save Error"),
1766 tr("%1\ncould not be removed before saving").arg(backupFileName));
1768 else if (!f.rename(backupFileName))
1770 QMessageBox::warning(0, tr("Save Error"),
1771 tr("%1\ncould not be renamed before saving").arg(destPath));
1778 // Create temporary directory for packing
1780 tmpZipDir=makeTmpDir (ok,"vym-zip");
1783 QMessageBox::critical( 0, tr( "Critical Load Error" ),
1784 tr("Couldn't create temporary directory before save\n"));
1788 safeFilePath=filePath;
1789 setFilePath (tmpZipDir+"/"+ mapName+ ".xml", safeFilePath);
1793 if (savemode==CompleteMap || xelection.isEmpty())
1795 // Save complete map
1796 saveFile=saveToDir (fileDir,mapName+"-",true,QPointF(),NULL);
1799 autosaveTimer->stop();
1804 if (xelection.type()==Selection::FloatImage)
1807 saveFile=saveToDir (fileDir,mapName+"-",true,QPointF(),xelection.getBranch());
1808 // TODO take care of multiselections
1811 if (!saveStringToDisk(fileDir+mapFileName,saveFile))
1814 qWarning ("ME::saveStringToDisk failed!");
1820 if (err==success) err=zipDir (tmpZipDir,destPath);
1823 removeDir (QDir(tmpZipDir));
1825 // Restore original filepath outside of tmp zip dir
1826 setFilePath (safeFilePath);
1830 fileChangedTime=QFileInfo (destPath).lastModified();
1834 /* FIXME not needed any longer
1835 void MapEditor::setZipped (bool z)
1840 bool MapEditor::saveZipped ()
1846 void MapEditor::print()
1850 printer = new QPrinter;
1851 printer->setColorMode (QPrinter::Color);
1852 printer->setPrinterName (settings.value("/mainwindow/printerName",printer->printerName()).toString());
1853 printer->setOutputFormat((QPrinter::OutputFormat)settings.value("/mainwindow/printerFormat",printer->outputFormat()).toInt());
1854 printer->setOutputFileName(settings.value("/mainwindow/printerFileName",printer->outputFileName()).toString());
1857 QRectF totalBBox=model->getTotalBBox();
1859 // Try to set orientation automagically
1860 // Note: Interpretation of generated postscript is amibiguous, if
1861 // there are problems with landscape mode, see
1862 // http://sdb.suse.de/de/sdb/html/jsmeix_print-cups-landscape-81.html
1864 if (totalBBox.width()>totalBBox.height())
1865 // recommend landscape
1866 printer->setOrientation (QPrinter::Landscape);
1868 // recommend portrait
1869 printer->setOrientation (QPrinter::Portrait);
1871 if ( printer->setup(this) )
1872 // returns false, if printing is canceled
1874 QPainter pp(printer);
1876 pp.setRenderHint(QPainter::Antialiasing,true);
1878 // Don't print the visualisation of selection
1879 xelection.unselect();
1881 QRectF mapRect=totalBBox;
1882 QGraphicsRectItem *frame=NULL;
1886 // Print frame around map
1887 mapRect.setRect (totalBBox.x()-10, totalBBox.y()-10,
1888 totalBBox.width()+20, totalBBox.height()+20);
1889 frame=mapScene->addRect (mapRect, QPen(Qt::black),QBrush(Qt::NoBrush));
1890 frame->setZValue(0);
1895 double paperAspect = (double)printer->width() / (double)printer->height();
1896 double mapAspect = (double)mapRect.width() / (double)mapRect.height();
1898 if (mapAspect>=paperAspect)
1900 // Fit horizontally to paper width
1901 //pp.setViewport(0,0, printer->width(),(int)(printer->width()/mapAspect) );
1902 viewBottom=(int)(printer->width()/mapAspect);
1905 // Fit vertically to paper height
1906 //pp.setViewport(0,0,(int)(printer->height()*mapAspect),printer->height());
1907 viewBottom=printer->height();
1912 // Print footer below map
1914 font.setPointSize(10);
1916 QRectF footerBox(0,viewBottom,printer->width(),15);
1917 pp.drawText ( footerBox,Qt::AlignLeft,"VYM - " +fileName);
1918 pp.drawText ( footerBox, Qt::AlignRight, QDate::currentDate().toString(Qt::TextDate));
1922 QRectF (0,0,printer->width(),printer->height()-15),
1923 QRectF(mapRect.x(),mapRect.y(),mapRect.width(),mapRect.height())
1926 // Viewport has paper dimension
1927 if (frame) delete (frame);
1929 // Restore selection
1930 xelection.reselect();
1932 // Save settings in vymrc
1933 settings.writeEntry("/mainwindow/printerName",printer->printerName());
1934 settings.writeEntry("/mainwindow/printerFormat",printer->outputFormat());
1935 settings.writeEntry("/mainwindow/printerFileName",printer->outputFileName());
1939 void MapEditor::setAntiAlias (bool b)
1941 setRenderHint(QPainter::Antialiasing,b);
1944 void MapEditor::setSmoothPixmap(bool b)
1946 setRenderHint(QPainter::SmoothPixmapTransform,b);
1949 QPixmap MapEditor::getPixmap()
1951 QRectF mapRect=model->getTotalBBox();
1952 QPixmap pix((int)mapRect.width()+2,(int)mapRect.height()+1);
1955 pp.setRenderHints(renderHints());
1957 // Don't print the visualisation of selection
1958 xelection.unselect();
1960 mapScene->render ( &pp,
1961 QRectF(0,0,mapRect.width()+2,mapRect.height()+2),
1962 QRectF(mapRect.x(),mapRect.y(),mapRect.width(),mapRect.height() ));
1964 // Restore selection
1965 xelection.reselect();
1970 void MapEditor::setHideTmpMode (HideTmpMode mode)
1973 model->setHideTmp (hidemode);
1974 model->reposition();
1978 HideTmpMode MapEditor::getHideTmpMode()
1983 void MapEditor::setExportMode (bool b)
1985 // should be called before and after exports
1986 // depending on the settings
1987 if (b && settings.value("/export/useHideExport","true")=="true")
1988 setHideTmpMode (HideExport);
1990 setHideTmpMode (HideNone);
1993 void MapEditor::exportASCII(QString fname,bool askName)
1996 ex.setModel (model);
1998 ex.setFile (mapName+".txt");
2004 //ex.addFilter ("TXT (*.txt)");
2005 ex.setDir(lastImageDir);
2006 //ex.setCaption(vymName+ " -" +tr("Export as ASCII")+" "+tr("(still experimental)"));
2011 setExportMode(true);
2013 setExportMode(false);
2017 void MapEditor::exportImage(QString fname, bool askName, QString format)
2021 fname=mapName+".png";
2028 QFileDialog *fd=new QFileDialog (this);
2029 fd->setCaption (tr("Export map as image"));
2030 fd->setDirectory (lastImageDir);
2031 fd->setFileMode(QFileDialog::AnyFile);
2032 fd->setFilters (imageIO.getFilters() );
2035 fl=fd->selectedFiles();
2037 format=imageIO.getType(fd->selectedFilter());
2041 setExportMode (true);
2042 QPixmap pix (getPixmap());
2043 pix.save(fname, format);
2044 setExportMode (false);
2047 void MapEditor::exportOOPresentation(const QString &fn, const QString &cf)
2051 ex.setModel (model);
2052 if (ex.setConfigFile(cf))
2054 setExportMode (true);
2055 ex.exportPresentation();
2056 setExportMode (false);
2060 void MapEditor::exportXHTML (const QString &dir, bool askForName)
2062 ExportXHTMLDialog dia(this);
2063 dia.setFilePath (filePath );
2064 dia.setMapName (mapName );
2066 if (dir!="") dia.setDir (dir);
2072 if (dia.exec()!=QDialog::Accepted)
2076 QDir d (dia.getDir());
2077 // Check, if warnings should be used before overwriting
2078 // the output directory
2079 if (d.exists() && d.count()>0)
2082 warn.showCancelButton (true);
2083 warn.setText(QString(
2084 "The directory %1 is not empty.\n"
2085 "Do you risk to overwrite some of its contents?").arg(d.path() ));
2086 warn.setCaption("Warning: Directory not empty");
2087 warn.setShowAgainName("mainwindow/overwrite-dir-xhtml");
2089 if (warn.exec()!=QDialog::Accepted) ok=false;
2096 exportXML (dia.getDir(),false );
2097 dia.doExport(mapName );
2098 //if (dia.hasChanged()) setChanged();
2102 void MapEditor::exportXML(QString dir, bool askForName)
2106 dir=browseDirectory(this,tr("Export XML to directory"));
2107 if (dir =="" && !reallyWriteDirectory(dir) )
2111 // Hide stuff during export, if settings want this
2112 setExportMode (true);
2114 // Create subdirectories
2117 // write to directory
2118 QString saveFile=saveToDir (dir,mapName+"-",true,model->getTotalBBox().topLeft() ,NULL);
2121 file.setName ( dir + "/"+mapName+".xml");
2122 if ( !file.open( QIODevice::WriteOnly ) )
2124 // This should neverever happen
2125 QMessageBox::critical (0,tr("Critical Export Error"),tr("MapEditor::exportXML couldn't open %1").arg(file.name()));
2129 // Write it finally, and write in UTF8, no matter what
2130 QTextStream ts( &file );
2131 ts.setEncoding (QTextStream::UnicodeUTF8);
2135 // Now write image, too
2136 exportImage (dir+"/images/"+mapName+".png",false,"PNG");
2138 setExportMode (false);
2141 void MapEditor::clear()
2143 xelection.unselect();
2147 void MapEditor::copy()
2149 LinkableMapObj *sel=xelection.single();
2152 if (redosAvail == 0)
2155 QString s=sel->getSelectString();
2156 saveState (PartOfMap, s, "nop ()", s, "copy ()","Copy selection to clipboard",sel );
2157 curClipboard=curStep;
2160 // Copy also to global clipboard, because we are at last step in history
2161 QString bakMapName(QString("history-%1").arg(curStep));
2162 QString bakMapDir(tmpMapDir +"/"+bakMapName);
2163 copyDir (bakMapDir,clipboardDir );
2165 clipboardEmpty=false;
2170 void MapEditor::redo()
2172 // Can we undo at all?
2173 if (redosAvail<1) return;
2175 bool blockSaveStateOrg=blockSaveState;
2176 blockSaveState=true;
2180 if (undosAvail<stepsTotal) undosAvail++;
2182 if (curStep>stepsTotal) curStep=1;
2183 QString undoCommand= undoSet.readEntry (QString("/history/step-%1/undoCommand").arg(curStep));
2184 QString undoSelection=undoSet.readEntry (QString("/history/step-%1/undoSelection").arg(curStep));
2185 QString redoCommand= undoSet.readEntry (QString("/history/step-%1/redoCommand").arg(curStep));
2186 QString redoSelection=undoSet.readEntry (QString("/history/step-%1/redoSelection").arg(curStep));
2187 QString comment=undoSet.readEntry (QString("/history/step-%1/comment").arg(curStep));
2188 QString version=undoSet.readEntry ("/history/version");
2190 /* TODO Maybe check for version, if we save the history
2191 if (!checkVersion(version))
2192 QMessageBox::warning(0,tr("Warning"),
2193 tr("Version %1 of saved undo/redo data\ndoes not match current vym version %2.").arg(version).arg(vymVersion));
2196 // Find out current undo directory
2197 QString bakMapDir(QString(tmpMapDir+"/undo-%1").arg(curStep));
2201 cout << "ME::redo() begin\n";
2202 cout << " undosAvail="<<undosAvail<<endl;
2203 cout << " redosAvail="<<redosAvail<<endl;
2204 cout << " curStep="<<curStep<<endl;
2205 cout << " ---------------------------"<<endl;
2206 cout << " comment="<<comment.toStdString()<<endl;
2207 cout << " undoCom="<<undoCommand.toStdString()<<endl;
2208 cout << " undoSel="<<undoSelection.toStdString()<<endl;
2209 cout << " redoCom="<<redoCommand.toStdString()<<endl;
2210 cout << " redoSel="<<redoSelection.toStdString()<<endl;
2211 cout << " ---------------------------"<<endl<<endl;
2214 // select object before redo
2215 if (!redoSelection.isEmpty())
2216 select (redoSelection);
2219 parseAtom (redoCommand);
2220 model->reposition();
2222 blockSaveState=blockSaveStateOrg;
2224 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
2225 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
2226 undoSet.setEntry ("/history/curStep",QString::number(curStep));
2227 undoSet.writeSettings(histPath);
2229 mainWindow->updateHistory (undoSet);
2232 /* TODO remove testing
2233 cout << "ME::redo() end\n";
2234 cout << " undosAvail="<<undosAvail<<endl;
2235 cout << " redosAvail="<<redosAvail<<endl;
2236 cout << " curStep="<<curStep<<endl;
2237 cout << " ---------------------------"<<endl<<endl;
2243 bool MapEditor::isRedoAvailable()
2245 if (undoSet.readNumEntry("/history/redosAvail",0)>0)
2251 void MapEditor::undo()
2253 // Can we undo at all?
2254 if (undosAvail<1) return;
2256 mainWindow->statusMessage (tr("Autosave disabled during undo."));
2258 bool blockSaveStateOrg=blockSaveState;
2259 blockSaveState=true;
2261 QString undoCommand= undoSet.readEntry (QString("/history/step-%1/undoCommand").arg(curStep));
2262 QString undoSelection=undoSet.readEntry (QString("/history/step-%1/undoSelection").arg(curStep));
2263 QString redoCommand= undoSet.readEntry (QString("/history/step-%1/redoCommand").arg(curStep));
2264 QString redoSelection=undoSet.readEntry (QString("/history/step-%1/redoSelection").arg(curStep));
2265 QString comment=undoSet.readEntry (QString("/history/step-%1/comment").arg(curStep));
2266 QString version=undoSet.readEntry ("/history/version");
2268 /* TODO Maybe check for version, if we save the history
2269 if (!checkVersion(version))
2270 QMessageBox::warning(0,tr("Warning"),
2271 tr("Version %1 of saved undo/redo data\ndoes not match current vym version %2.").arg(version).arg(vymVersion));
2274 // Find out current undo directory
2275 QString bakMapDir(QString(tmpMapDir+"/undo-%1").arg(curStep));
2277 // select object before undo
2278 if (!undoSelection.isEmpty())
2279 select (undoSelection);
2283 cout << "ME::undo() begin\n";
2284 cout << " undosAvail="<<undosAvail<<endl;
2285 cout << " redosAvail="<<redosAvail<<endl;
2286 cout << " curStep="<<curStep<<endl;
2287 cout << " ---------------------------"<<endl;
2288 cout << " comment="<<comment.toStdString()<<endl;
2289 cout << " undoCom="<<undoCommand.toStdString()<<endl;
2290 cout << " undoSel="<<undoSelection.toStdString()<<endl;
2291 cout << " redoCom="<<redoCommand.toStdString()<<endl;
2292 cout << " redoSel="<<redoSelection.toStdString()<<endl;
2293 cout << " ---------------------------"<<endl<<endl;
2295 parseAtom (undoCommand);
2296 model->reposition();
2300 if (curStep<1) curStep=stepsTotal;
2304 blockSaveState=blockSaveStateOrg;
2305 /* TODO remove testing
2306 cout << "ME::undo() end\n";
2307 cout << " undosAvail="<<undosAvail<<endl;
2308 cout << " redosAvail="<<redosAvail<<endl;
2309 cout << " curStep="<<curStep<<endl;
2310 cout << " ---------------------------"<<endl<<endl;
2313 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
2314 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
2315 undoSet.setEntry ("/history/curStep",QString::number(curStep));
2316 undoSet.writeSettings(histPath);
2318 mainWindow->updateHistory (undoSet);
2321 ensureSelectionVisible();
2324 bool MapEditor::isUndoAvailable()
2326 if (undoSet.readNumEntry("/history/undosAvail",0)>0)
2332 void MapEditor::gotoHistoryStep (int i)
2334 // Restore variables
2335 int undosAvail=undoSet.readNumEntry (QString("/history/undosAvail"));
2336 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
2338 if (i<0) i=undosAvail+redosAvail;
2340 // Clicking above current step makes us undo things
2343 for (int j=0; j<undosAvail-i; j++) undo();
2346 // Clicking below current step makes us redo things
2348 for (int j=undosAvail; j<i; j++)
2350 cout << "redo "<<j<<"/"<<undosAvail<<" i="<<i<<endl;
2354 // And ignore clicking the current row ;-)
2357 void MapEditor::addMapReplaceInt(const QString &undoSel, const QString &path)
2359 QString pathDir=path.left(path.findRev("/"));
2365 // We need to parse saved XML data
2366 parseVYMHandler handler;
2367 QXmlInputSource source( file);
2368 QXmlSimpleReader reader;
2369 reader.setContentHandler( &handler );
2370 reader.setErrorHandler( &handler );
2371 handler.setModel ( model);
2372 handler.setTmpDir ( pathDir ); // needed to load files with rel. path
2373 if (undoSel.isEmpty())
2377 handler.setLoadMode (NewMap);
2381 handler.setLoadMode (ImportReplace);
2383 blockReposition=true;
2384 bool ok = reader.parse( source );
2385 blockReposition=false;
2388 // This should never ever happen
2389 QMessageBox::critical( 0, tr( "Critical Parse Error while reading %1").arg(path),
2390 handler.errorProtocol());
2393 QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
2396 void MapEditor::addMapInsertInt (const QString &path, int pos)
2398 BranchObj *sel=xelection.getBranch();
2401 QString pathDir=path.left(path.findRev("/"));
2407 // We need to parse saved XML data
2408 parseVYMHandler handler;
2409 QXmlInputSource source( file);
2410 QXmlSimpleReader reader;
2411 reader.setContentHandler( &handler );
2412 reader.setErrorHandler( &handler );
2413 handler.setModel (model);
2414 handler.setTmpDir ( pathDir ); // needed to load files with rel. path
2415 handler.setLoadMode (ImportAdd);
2416 blockReposition=true;
2417 bool ok = reader.parse( source );
2418 blockReposition=false;
2421 // This should never ever happen
2422 QMessageBox::critical( 0, tr( "Critical Parse Error while reading %1").arg(path),
2423 handler.errorProtocol());
2425 if (sel->getDepth()>0)
2426 sel->getLastBranch()->linkTo (sel,pos);
2428 QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
2432 void MapEditor::pasteNoSave(const int &n)
2434 bool old=blockSaveState;
2435 blockSaveState=true;
2436 if (redosAvail > 0 || n!=0)
2438 // Use the "historical" buffer
2439 QString bakMapName(QString("history-%1").arg(n));
2440 QString bakMapDir(tmpMapDir +"/"+bakMapName);
2441 load (bakMapDir+"/"+clipboardFile,ImportAdd, VymMap);
2443 // Use the global buffer
2444 load (clipboardDir+"/"+clipboardFile,ImportAdd, VymMap);
2448 void MapEditor::paste()
2450 BranchObj *sel=xelection.getBranch();
2453 saveStateChangingPart(
2456 QString ("paste (%1)").arg(curClipboard),
2457 QString("Paste to %1").arg( getName(sel))
2460 model->reposition();
2464 void MapEditor::cut()
2466 LinkableMapObj *sel=xelection.single();
2467 if ( sel && (xelection.type() == Selection::Branch ||
2468 xelection.type()==Selection::MapCenter ||
2469 xelection.type()==Selection::FloatImage))
2471 /* No savestate! savestate is called in cutNoSave
2472 saveStateChangingPart(
2476 QString("Cut %1").arg(getName(sel ))
2481 model->reposition();
2485 void MapEditor::move(const double &x, const double &y)
2487 LinkableMapObj *sel=xelection.single();
2490 QPointF ap(sel->getAbsPos());
2494 QString ps=qpointfToString(ap);
2495 QString s=xelection.single()->getSelectString();
2498 s, "move "+qpointfToString(to),
2499 QString("Move %1 to %2").arg(getName(sel)).arg(ps));
2501 model->reposition();
2507 void MapEditor::moveRel (const double &x, const double &y)
2509 LinkableMapObj *sel=xelection.single();
2512 QPointF rp(sel->getRelPos());
2516 QString ps=qpointfToString (sel->getRelPos());
2517 QString s=sel->getSelectString();
2520 s, "moveRel "+qpointfToString(to),
2521 QString("Move %1 to relative position %2").arg(getName(sel)).arg(ps));
2522 ((OrnamentedObj*)sel)->move2RelPos (x,y);
2523 model->reposition();
2530 void MapEditor::moveBranchUp()
2532 BranchObj* bo=xelection.getBranch();
2536 if (!bo->canMoveBranchUp()) return;
2537 par=(BranchObj*)(bo->getParObj());
2538 BranchObj *obo=par->moveBranchUp (bo); // bo will be the one below selection
2539 saveState (bo->getSelectString(),"moveBranchDown ()",obo->getSelectString(),"moveBranchUp ()",QString("Move up %1").arg(getName(bo)));
2540 model->reposition();
2543 ensureSelectionVisible();
2547 void MapEditor::moveBranchDown()
2549 BranchObj* bo=xelection.getBranch();
2553 if (!bo->canMoveBranchDown()) return;
2554 par=(BranchObj*)(bo->getParObj());
2555 BranchObj *obo=par->moveBranchDown(bo); // bo will be the one above selection
2556 saveState(bo->getSelectString(),"moveBranchUp ()",obo->getSelectString(),"moveBranchDown ()",QString("Move down %1").arg(getName(bo)));
2557 model->reposition();
2560 ensureSelectionVisible();
2564 void MapEditor::sortChildren()
2566 BranchObj* bo=xelection.getBranch();
2569 if(bo->countBranches()>1)
2571 saveStateChangingPart(bo,bo, "sortChildren ()",QString("Sort children of %1").arg(getName(bo)));
2573 model->reposition();
2574 ensureSelectionVisible();
2579 void MapEditor::linkTo(const QString &dstString)
2581 FloatImageObj *fio=xelection.getFloatImage();
2584 BranchObj *dst=(BranchObj*)(model->findObjBySelect(dstString));
2585 if (dst && (typeid(*dst)==typeid (BranchObj) ||
2586 typeid(*dst)==typeid (MapCenterObj)))
2588 LinkableMapObj *dstPar=dst->getParObj();
2589 QString parString=dstPar->getSelectString();
2590 QString fioPreSelectString=fio->getSelectString();
2591 QString fioPreParentSelectString=fio->getParObj()->getSelectString();
2592 ((BranchObj*)(dst))->addFloatImage (fio);
2593 xelection.unselect();
2594 ((BranchObj*)(fio->getParObj()))->removeFloatImage (fio);
2595 fio=((BranchObj*)(dst))->getLastFloatImage();
2598 xelection.select(fio);
2600 fio->getSelectString(),
2601 QString("linkTo (\"%1\")").arg(fioPreParentSelectString),
2603 QString ("linkTo (\"%1\")").arg(dstString),
2604 QString ("Link floatimage to %1").arg(getName(dst)));
2609 QString MapEditor::getHeading(bool &ok, QPoint &p)
2611 BranchObj *bo=xelection.getBranch();
2615 p=mapFromScene(bo->getAbsPos());
2616 return bo->getHeading();
2622 void MapEditor::setHeading(const QString &s)
2624 BranchObj *sel=xelection.getBranch();
2629 "setHeading (\""+sel->getHeading()+"\")",
2631 "setHeading (\""+s+"\")",
2632 QString("Set heading of %1 to \"%2\"").arg(getName(sel)).arg(s) );
2633 sel->setHeading(s );
2634 model->reposition();
2636 ensureSelectionVisible();
2640 void MapEditor::setHeadingInt(const QString &s)
2642 BranchObj *bo=xelection.getBranch();
2646 model->reposition();
2648 ensureSelectionVisible();
2652 void MapEditor::setVymLinkInt (const QString &s)
2654 // Internal function, no saveState needed
2655 BranchObj *bo=xelection.getBranch();
2659 model->reposition();
2662 ensureSelectionVisible();
2666 BranchObj* MapEditor::addNewBranchInt(int num)
2668 // Depending on pos:
2669 // -3 insert in childs of parent above selection
2670 // -2 add branch to selection
2671 // -1 insert in childs of parent below selection
2672 // 0..n insert in childs of parent at pos
2673 BranchObj *newbo=NULL;
2674 BranchObj *bo=xelection.getBranch();
2679 // save scroll state. If scrolled, automatically select
2680 // new branch in order to tmp unscroll parent...
2681 newbo=bo->addBranch();
2686 bo=(BranchObj*)bo->getParObj();
2687 if (bo) newbo=bo->insertBranch(num);
2691 bo=(BranchObj*)bo->getParObj();
2692 if (bo) newbo=bo->insertBranch(num);
2694 if (!newbo) return NULL;
2699 BranchObj* MapEditor::addNewBranch(int pos)
2701 // Different meaning than num in addNewBranchInt!
2705 BranchObj *bo = xelection.getBranch();
2706 BranchObj *newbo=NULL;
2710 setCursor (Qt::ArrowCursor);
2712 newbo=addNewBranchInt (pos-2);
2720 QString ("addBranch (%1)").arg(pos),
2721 QString ("Add new branch to %1").arg(getName(bo)));
2723 model->reposition();
2725 latestSelection=newbo->getSelectString();
2726 // In Network mode, the client needs to know where the new branch is,
2727 // so we have to pass on this information via saveState.
2728 // TODO: Get rid of this positioning workaround
2729 QString ps=qpointfToString (newbo->getAbsPos());
2730 sendData ("selectLatestAdded ()");
2731 sendData (QString("move %1").arg(ps));
2739 BranchObj* MapEditor::addNewBranchBefore()
2741 BranchObj *newbo=NULL;
2742 BranchObj *bo = xelection.getBranch();
2743 if (bo && xelection.type()==Selection::Branch)
2744 // We accept no MapCenterObj here, so we _have_ a parent
2746 QPointF p=bo->getRelPos();
2749 BranchObj *parbo=(BranchObj*)(bo->getParObj());
2751 // add below selection
2752 newbo=parbo->insertBranch(bo->getNum()+1);
2755 newbo->move2RelPos (p);
2757 // Move selection to new branch
2758 bo->linkTo (newbo,-1);
2760 saveState (newbo, "deleteKeepChilds ()", newbo, "addBranchBefore ()",
2761 QString ("Add branch before %1").arg(getName(bo)));
2763 model->reposition();
2767 latestSelection=xelection.getSelectString();
2771 void MapEditor::deleteSelection()
2773 BranchObj *bo = xelection.getBranch();
2774 if (bo && xelection.type()==Selection::MapCenter)
2776 // BranchObj* par=(BranchObj*)(bo->getParObj());
2777 xelection.unselect();
2778 /* FIXME Note: does saveStateRemovingPart work for MCO? (No parent!)
2779 saveStateRemovingPart (bo, QString ("Delete %1").arg(getName(bo)));
2781 bo=model->removeMapCenter ((MapCenterObj*)bo);
2784 xelection.select (bo);
2785 ensureSelectionVisible();
2788 model->reposition();
2791 if (bo && xelection.type()==Selection::Branch)
2793 BranchObj* par=(BranchObj*)(bo->getParObj());
2794 xelection.unselect();
2795 saveStateRemovingPart (bo, QString ("Delete %1").arg(getName(bo)));
2796 par->removeBranch(bo);
2797 xelection.select (par);
2798 ensureSelectionVisible();
2799 model->reposition();
2804 FloatImageObj *fio=xelection.getFloatImage();
2807 BranchObj* par=(BranchObj*)(fio->getParObj());
2808 saveStateChangingPart(
2812 QString("Delete %1").arg(getName(fio))
2814 xelection.unselect();
2815 par->removeFloatImage(fio);
2816 xelection.select (par);
2817 model->reposition();
2819 ensureSelectionVisible();
2824 LinkableMapObj* MapEditor::getSelection()
2826 return xelection.single();
2829 BranchObj* MapEditor::getSelectedBranch()
2831 return xelection.getBranch();
2834 FloatImageObj* MapEditor::getSelectedFloatImage()
2836 return xelection.getFloatImage();
2839 void MapEditor::unselect()
2841 xelection.unselect();
2844 void MapEditor::reselect()
2846 xelection.reselect();
2849 bool MapEditor::select (const QString &s)
2851 if (xelection.select(s))
2854 ensureSelectionVisible();
2861 QString MapEditor::getSelectString()
2863 return xelection.getSelectString();
2866 void MapEditor::selectInt (LinkableMapObj *lmo)
2868 if (lmo && xelection.single()!= lmo && isSelectBlocked()==false )
2870 xelection.select(lmo);
2876 void MapEditor::selectNextBranchInt()
2878 // Increase number of branch
2879 LinkableMapObj *sel=xelection.single();
2882 QString s=sel->getSelectString();
2888 part=s.section(",",-1);
2890 num=part.right(part.length() - 3);
2892 s=s.left (s.length() -num.length());
2895 num=QString ("%1").arg(num.toUInt()+1);
2899 // Try to select this one
2900 if (select (s)) return;
2902 // We have no direct successor,
2903 // try to increase the parental number in order to
2904 // find a successor with same depth
2906 int d=xelection.single()->getDepth();
2911 while (!found && d>0)
2913 s=s.section (",",0,d-1);
2914 // replace substring of current depth in s with "1"
2915 part=s.section(",",-1);
2917 num=part.right(part.length() - 3);
2921 // increase number of parent
2922 num=QString ("%1").arg(num.toUInt()+1);
2923 s=s.section (",",0,d-2) + ","+ typ+num;
2926 // Special case, look at orientation
2927 if (xelection.single()->getOrientation()==LinkableMapObj::RightOfCenter)
2928 num=QString ("%1").arg(num.toUInt()+1);
2930 num=QString ("%1").arg(num.toUInt()-1);
2935 // pad to oldDepth, select the first branch for each depth
2936 for (i=d;i<oldDepth;i++)
2941 if ( xelection.getBranch()->countBranches()>0)
2949 // try to select the freshly built string
2957 void MapEditor::selectPrevBranchInt()
2959 // Decrease number of branch
2960 BranchObj *bo=xelection.getBranch();
2963 QString s=bo->getSelectString();
2969 part=s.section(",",-1);
2971 num=part.right(part.length() - 3);
2973 s=s.left (s.length() -num.length());
2975 int n=num.toInt()-1;
2978 num=QString ("%1").arg(n);
2981 // Try to select this one
2982 if (n>=0 && select (s)) return;
2984 // We have no direct precessor,
2985 // try to decrease the parental number in order to
2986 // find a precessor with same depth
2988 int d=xelection.single()->getDepth();
2993 while (!found && d>0)
2995 s=s.section (",",0,d-1);
2996 // replace substring of current depth in s with "1"
2997 part=s.section(",",-1);
2999 num=part.right(part.length() - 3);
3003 // decrease number of parent
3004 num=QString ("%1").arg(num.toInt()-1);
3005 s=s.section (",",0,d-2) + ","+ typ+num;
3008 // Special case, look at orientation
3009 if (xelection.single()->getOrientation()==LinkableMapObj::RightOfCenter)
3010 num=QString ("%1").arg(num.toInt()-1);
3012 num=QString ("%1").arg(num.toInt()+1);
3017 // pad to oldDepth, select the last branch for each depth
3018 for (i=d;i<oldDepth;i++)
3022 if ( xelection.getBranch()->countBranches()>0)
3023 s+=",bo:"+ QString ("%1").arg( xelection.getBranch()->countBranches()-1 );
3030 // try to select the freshly built string
3038 void MapEditor::selectUpperBranch()
3040 if (isSelectBlocked() ) return;
3042 BranchObj *bo=xelection.getBranch();
3043 if (bo && xelection.type()==Selection::Branch)
3045 if (bo->getOrientation()==LinkableMapObj::RightOfCenter)
3046 selectPrevBranchInt();
3048 if (bo->getDepth()==1)
3049 selectNextBranchInt();
3051 selectPrevBranchInt();
3055 void MapEditor::selectLowerBranch()
3057 if (isSelectBlocked() ) return;
3059 BranchObj *bo=xelection.getBranch();
3060 if (bo && xelection.type()==Selection::Branch)
3061 if (bo->getOrientation()==LinkableMapObj::RightOfCenter)
3062 selectNextBranchInt();
3064 if (bo->getDepth()==1)
3065 selectPrevBranchInt();
3067 selectNextBranchInt();
3071 void MapEditor::selectLeftBranch()
3073 if (isSelectBlocked() ) return;
3077 LinkableMapObj *sel=xelection.single();
3080 if (xelection.type()== Selection::MapCenter)
3082 par=xelection.getBranch();
3083 bo=par->getLastSelectedBranch();
3086 // Workaround for reselecting on left and right side
3087 if (bo->getOrientation()==LinkableMapObj::RightOfCenter)
3088 bo=par->getLastBranch();
3091 bo=par->getLastBranch();
3092 xelection.select(bo);
3094 ensureSelectionVisible();
3100 par=(BranchObj*)(sel->getParObj());
3101 if (sel->getOrientation()==LinkableMapObj::RightOfCenter)
3103 if (xelection.type() == Selection::Branch ||
3104 xelection.type() == Selection::FloatImage)
3106 xelection.select(par);
3108 ensureSelectionVisible();
3113 if (xelection.type() == Selection::Branch )
3115 bo=xelection.getBranch()->getLastSelectedBranch();
3118 xelection.select(bo);
3120 ensureSelectionVisible();
3129 void MapEditor::selectRightBranch()
3131 if (isSelectBlocked() ) return;
3135 LinkableMapObj *sel=xelection.single();
3138 if (xelection.type()==Selection::MapCenter)
3140 par=xelection.getBranch();
3141 bo=par->getLastSelectedBranch();
3144 // Workaround for reselecting on left and right side
3145 if (bo->getOrientation()==LinkableMapObj::LeftOfCenter)
3146 bo=par->getFirstBranch();
3149 xelection.select(bo);
3151 ensureSelectionVisible();
3157 par=(BranchObj*)(xelection.single()->getParObj());
3158 if (xelection.single()->getOrientation()==LinkableMapObj::LeftOfCenter)
3160 if (xelection.type() == Selection::Branch ||
3161 xelection.type() == Selection::FloatImage)
3163 xelection.select(par);
3165 ensureSelectionVisible();
3170 if (xelection.type() == Selection::Branch)
3172 bo=xelection.getBranch()->getLastSelectedBranch();
3175 xelection.select(bo);
3177 ensureSelectionVisible();
3186 void MapEditor::selectFirstBranch()
3188 BranchObj *bo1=xelection.getBranch();
3193 par=(BranchObj*)(bo1->getParObj());
3194 bo2=par->getFirstBranch();
3196 xelection.select(bo2);
3198 ensureSelectionVisible();
3204 void MapEditor::selectLastBranch()
3206 BranchObj *bo1=xelection.getBranch();
3211 par=(BranchObj*)(bo1->getParObj());
3212 bo2=par->getLastBranch();
3215 xelection.select(bo2);
3217 ensureSelectionVisible();
3223 void MapEditor::selectMapBackgroundImage ()
3225 Q3FileDialog *fd=new Q3FileDialog( this);
3226 fd->setMode (Q3FileDialog::ExistingFile);
3227 fd->addFilter (QString (tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)"));
3228 ImagePreview *p =new ImagePreview (fd);
3229 fd->setContentsPreviewEnabled( TRUE );
3230 fd->setContentsPreview( p, p );
3231 fd->setPreviewMode( Q3FileDialog::Contents );
3232 fd->setCaption(vymName+" - " +tr("Load background image"));
3233 fd->setDir (lastImageDir);
3236 if ( fd->exec() == QDialog::Accepted )
3238 // TODO selectMapBackgroundImg in QT4 use: lastImageDir=fd->directory();
3239 lastImageDir=QDir (fd->dirPath());
3240 setMapBackgroundImage (fd->selectedFile());
3244 void MapEditor::setMapBackgroundImage (const QString &fn) //FIXME missing savestate
3246 QColor oldcol=mapScene->backgroundBrush().color();
3250 QString ("setMapBackgroundImage (%1)").arg(oldcol.name()),
3252 QString ("setMapBackgroundImage (%1)").arg(col.name()),
3253 QString("Set background color of map to %1").arg(col.name()));
3256 brush.setTextureImage (QPixmap (fn));
3257 mapScene->setBackgroundBrush(brush);
3260 void MapEditor::selectMapBackgroundColor()
3262 QColor col = QColorDialog::getColor( mapScene->backgroundBrush().color(), this );
3263 if ( !col.isValid() ) return;
3264 setMapBackgroundColor( col );
3268 void MapEditor::setMapBackgroundColor(QColor col)
3270 QColor oldcol=mapScene->backgroundBrush().color();
3272 QString ("setMapBackgroundColor (\"%1\")").arg(oldcol.name()),
3273 QString ("setMapBackgroundColor (\"%1\")").arg(col.name()),
3274 QString("Set background color of map to %1").arg(col.name()));
3275 mapScene->setBackgroundBrush(col);
3278 QColor MapEditor::getMapBackgroundColor()
3280 return mapScene->backgroundBrush().color();
3283 QColor MapEditor::getCurrentHeadingColor()
3285 BranchObj *bo=xelection.getBranch();
3286 if (bo) return bo->getColor();
3288 QMessageBox::warning(0,tr("Warning"),tr("Can't get color of heading,\nthere's no branch selected"));
3292 void MapEditor::colorBranch (QColor c)
3294 BranchObj *bo=xelection.getBranch();
3299 QString ("colorBranch (\"%1\")").arg(bo->getColor().name()),
3301 QString ("colorBranch (\"%1\")").arg(c.name()),
3302 QString("Set color of %1 to %2").arg(getName(bo)).arg(c.name())
3304 bo->setColor(c); // color branch
3308 void MapEditor::colorSubtree (QColor c)
3310 BranchObj *bo=xelection.getBranch();
3313 saveStateChangingPart(
3316 QString ("colorSubtree (\"%1\")").arg(c.name()),
3317 QString ("Set color of %1 and childs to %2").arg(getName(bo)).arg(c.name())
3319 bo->setColorSubtree (c); // color links, color childs
3324 void MapEditor::toggleStandardFlag(QString f)
3326 BranchObj *bo=xelection.getBranch();
3330 if (bo->isSetStandardFlag(f))
3342 QString("%1 (\"%2\")").arg(u).arg(f),
3344 QString("%1 (\"%2\")").arg(r).arg(f),
3345 QString("Toggling standard flag \"%1\" of %2").arg(f).arg(getName(bo)));
3346 bo->toggleStandardFlag (f,mainWindow->useFlagGroups());
3352 BranchObj* MapEditor::findText (QString s, bool cs)
3354 QTextDocument::FindFlags flags=0;
3355 if (cs) flags=QTextDocument::FindCaseSensitively;
3358 { // Nothing found or new find process
3360 // nothing found, start again
3362 itFind=model->first();
3364 bool searching=true;
3365 bool foundNote=false;
3366 while (searching && !EOFind)
3370 // Searching in Note
3371 if (itFind->getNote().contains(s,cs))
3373 if (xelection.single()!=itFind)
3375 xelection.select(itFind);
3376 ensureSelectionVisible();
3378 if (textEditor->findText(s,flags))
3384 // Searching in Heading
3385 if (searching && itFind->getHeading().contains (s,cs) )
3387 xelection.select(itFind);
3388 ensureSelectionVisible();
3394 itFind=model->next(itFind);
3395 if (!itFind) EOFind=true;
3399 return xelection.getBranch();
3404 void MapEditor::findReset()
3405 { // Necessary if text to find changes during a find process
3409 void MapEditor::setURL(const QString &url)
3411 BranchObj *bo=xelection.getBranch();
3414 QString oldurl=bo->getURL();
3418 QString ("setURL (\"%1\")").arg(oldurl),
3420 QString ("setURL (\"%1\")").arg(url),
3421 QString ("set URL of %1 to %2").arg(getName(bo)).arg(url)
3424 model->reposition();
3426 ensureSelectionVisible();
3430 void MapEditor::editURL()
3432 BranchObj *bo=xelection.getBranch();
3436 QString text = QInputDialog::getText(
3437 "VYM", tr("Enter URL:"), QLineEdit::Normal,
3438 bo->getURL(), &ok, this );
3440 // user entered something and pressed OK
3445 void MapEditor::editLocalURL()
3447 BranchObj *bo=xelection.getBranch();
3450 QStringList filters;
3451 filters <<"All files (*)";
3452 filters << tr("Text","Filedialog") + " (*.txt)";
3453 filters << tr("Spreadsheet","Filedialog") + " (*.odp,*.sxc)";
3454 filters << tr("Textdocument","Filedialog") +" (*.odw,*.sxw)";
3455 filters << tr("Images","Filedialog") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)";
3456 QFileDialog *fd=new QFileDialog( this,vymName+" - " +tr("Set URL to a local file"));
3457 fd->setFilters (filters);
3458 fd->setCaption(vymName+" - " +tr("Set URL to a local file"));
3459 fd->setDirectory (lastFileDir);
3460 if (! bo->getVymLink().isEmpty() )
3461 fd->selectFile( bo->getURL() );
3464 if ( fd->exec() == QDialog::Accepted )
3466 lastFileDir=QDir (fd->directory().path());
3467 setURL (fd->selectedFile() );
3472 QString MapEditor::getURL()
3474 BranchObj *bo=xelection.getBranch();
3476 return bo->getURL();
3481 QStringList MapEditor::getURLs()
3484 BranchObj *bo=xelection.getBranch();
3490 if (!bo->getURL().isEmpty()) urls.append( bo->getURL());
3498 void MapEditor::editHeading2URL()
3500 BranchObj *bo=xelection.getBranch();
3502 setURL (bo->getHeading());
3505 void MapEditor::editBugzilla2URL()
3507 BranchObj *bo=xelection.getBranch();
3510 QString url= "https://bugzilla.novell.com/show_bug.cgi?id="+bo->getHeading();
3515 void MapEditor::editFATE2URL()
3517 BranchObj *bo=xelection.getBranch();
3520 QString url= "http://keeper.suse.de:8080/webfate/match/id?value=ID"+bo->getHeading();
3523 "setURL (\""+bo->getURL()+"\")",
3525 "setURL (\""+url+"\")",
3526 QString("Use heading of %1 as link to FATE").arg(getName(bo))
3533 void MapEditor::editVymLink()
3535 BranchObj *bo=xelection.getBranch();
3538 QStringList filters;
3539 filters <<"VYM map (*.vym)";
3540 QFileDialog *fd=new QFileDialog( this,vymName+" - " +tr("Link to another map"));
3541 fd->setFilters (filters);
3542 fd->setCaption(vymName+" - " +tr("Link to another map"));
3543 fd->setDirectory (lastFileDir);
3544 if (! bo->getVymLink().isEmpty() )
3545 fd->selectFile( bo->getVymLink() );
3549 if ( fd->exec() == QDialog::Accepted )
3551 lastFileDir=QDir (fd->directory().path());
3554 "setVymLink (\""+bo->getVymLink()+"\")",
3556 "setVymLink (\""+fd->selectedFile()+"\")",
3557 QString("Set vymlink of %1 to %2").arg(getName(bo)).arg(fd->selectedFile())
3559 setVymLinkInt (fd->selectedFile() );
3564 void MapEditor::deleteVymLink()
3566 BranchObj *bo=xelection.getBranch();
3571 "setVymLink (\""+bo->getVymLink()+"\")",
3573 "setVymLink (\"\")",
3574 QString("Unset vymlink of %1").arg(getName(bo))
3576 bo->setVymLink ("" );
3578 model->reposition();
3583 void MapEditor::setHideExport(bool b)
3585 BranchObj *bo=xelection.getBranch();
3588 bo->setHideInExport (b);
3589 QString u= b ? "false" : "true";
3590 QString r=!b ? "false" : "true";
3594 QString ("setHideExport (%1)").arg(u),
3596 QString ("setHideExport (%1)").arg(r),
3597 QString ("Set HideExport flag of %1 to %2").arg(getName(bo)).arg (r)
3600 model->reposition();
3606 void MapEditor::toggleHideExport()
3608 BranchObj *bo=xelection.getBranch();
3610 setHideExport ( !bo->hideInExport() );
3613 QString MapEditor::getVymLink()
3615 BranchObj *bo=xelection.getBranch();
3617 return bo->getVymLink();
3623 QStringList MapEditor::getVymLinks()
3626 BranchObj *bo=xelection.getBranch();
3632 if (!bo->getVymLink().isEmpty()) links.append( bo->getVymLink());
3640 void MapEditor::deleteKeepChilds()
3642 BranchObj *bo=xelection.getBranch();
3646 par=(BranchObj*)(bo->getParObj());
3647 QPointF p=bo->getRelPos();
3648 saveStateChangingPart(
3651 "deleteKeepChilds ()",
3652 QString("Remove %1 and keep its childs").arg(getName(bo))
3655 QString sel=bo->getSelectString();
3657 par->removeBranchHere(bo);
3658 model->reposition();
3660 xelection.getBranch()->move2RelPos (p);
3661 model->reposition();
3665 void MapEditor::deleteChilds()
3667 BranchObj *bo=xelection.getBranch();
3670 saveStateChangingPart(
3674 QString( "Remove childs of branch %1").arg(getName(bo))
3677 model->reposition();
3681 void MapEditor::editMapInfo()
3683 ExtraInfoDialog dia;
3684 dia.setMapName (getFileName() );
3685 dia.setAuthor (model->getAuthor() );
3686 dia.setComment(model->getComment() );
3690 stats+=tr("%1 items on map\n","Info about map").arg (mapScene->items().size(),6);
3700 if (!bo->getNote().isEmpty() ) n++;
3701 f+= bo->countFloatImages();
3703 xl+=bo->countXLinks();
3706 stats+=QString ("%1 branches\n").arg (b-1,6);
3707 stats+=QString ("%1 xLinks \n").arg (xl,6);
3708 stats+=QString ("%1 notes\n").arg (n,6);
3709 stats+=QString ("%1 images\n").arg (f,6);
3710 dia.setStats (stats);
3712 // Finally show dialog
3713 if (dia.exec() == QDialog::Accepted)
3715 setMapAuthor (dia.getAuthor() );
3716 setMapComment (dia.getComment() );
3720 void MapEditor::ensureSelectionVisible()
3722 LinkableMapObj *lmo=xelection.single();
3723 if (lmo) ensureVisible (lmo->getBBox() );
3727 void MapEditor::updateSelection()
3729 // Tell selection to update geometries
3733 void MapEditor::updateActions()
3735 // Tell mainwindow to update states of actions
3736 mainWindow->updateActions();
3737 // TODO maybe don't update if blockReposition is set
3740 void MapEditor::updateNoteFlag()
3743 BranchObj *bo=xelection.getBranch();
3746 bo->updateNoteFlag();
3747 mainWindow->updateActions();
3751 void MapEditor::setMapAuthor (const QString &s)
3754 QString ("setMapAuthor (\"%1\")").arg(model->getAuthor()),
3755 QString ("setMapAuthor (\"%1\")").arg(s),
3756 QString ("Set author of map to \"%1\"").arg(s)
3758 model->setAuthor (s);
3761 void MapEditor::setMapComment (const QString &s)
3764 QString ("setMapComment (\"%1\")").arg(model->getComment()),
3765 QString ("setMapComment (\"%1\")").arg(s),
3766 QString ("Set comment of map")
3768 model->setComment (s);
3771 void MapEditor::setMapLinkStyle (const QString & s)
3774 if (linkstyle==LinkableMapObj::Line)
3776 else if (linkstyle==LinkableMapObj::Parabel)
3777 snow="StyleParabel";
3778 else if (linkstyle==LinkableMapObj::PolyLine)
3779 snow="StylePolyLine";
3780 else if (linkstyle==LinkableMapObj::PolyParabel)
3781 snow="StyleParabel";
3784 QString("setMapLinkStyle (\"%1\")").arg(s),
3785 QString("setMapLinkStyle (\"%1\")").arg(snow),
3786 QString("Set map link style (\"%1\")").arg(s)
3790 linkstyle=LinkableMapObj::Line;
3791 else if (s=="StyleParabel")
3792 linkstyle=LinkableMapObj::Parabel;
3793 else if (s=="StylePolyLine")
3794 linkstyle=LinkableMapObj::PolyLine;
3796 linkstyle=LinkableMapObj::PolyParabel;
3803 bo->setLinkStyle(bo->getDefLinkStyle());
3806 model->reposition();
3809 LinkableMapObj::Style MapEditor::getMapLinkStyle ()
3814 void MapEditor::setMapDefLinkColor(QColor c)
3827 void MapEditor::setMapLinkColorHintInt()
3829 // called from setMapLinkColorHint(lch) or at end of parse
3839 void MapEditor::setMapLinkColorHint(LinkableMapObj::ColorHint lch)
3842 setMapLinkColorHintInt();
3845 void MapEditor::toggleMapLinkColorHint()
3847 if (linkcolorhint==LinkableMapObj::HeadingColor)
3848 linkcolorhint=LinkableMapObj::DefaultColor;
3850 linkcolorhint=LinkableMapObj::HeadingColor;
3860 LinkableMapObj::ColorHint MapEditor::getMapLinkColorHint()
3862 return linkcolorhint;
3865 QColor MapEditor::getMapDefLinkColor()
3867 return defLinkColor;
3870 void MapEditor::setMapDefXLinkColor(QColor col)
3875 QColor MapEditor::getMapDefXLinkColor()
3877 return defXLinkColor;
3880 void MapEditor::setMapDefXLinkWidth (int w)
3885 int MapEditor::getMapDefXLinkWidth()
3887 return defXLinkWidth;
3890 void MapEditor::selectMapLinkColor()
3892 QColor col = QColorDialog::getColor( defLinkColor, this );
3893 if ( !col.isValid() ) return;
3895 QString("setMapDefLinkColor (\"%1\")").arg(getMapDefLinkColor().name()),
3896 QString("setMapDefLinkColor (\"%1\")").arg(col.name()),
3897 QString("Set map link color to %1").arg(col.name())
3899 setMapDefLinkColor( col );
3902 void MapEditor::selectMapSelectionColor()
3904 QColor col = QColorDialog::getColor( defLinkColor, this );
3905 setSelectionColor (col);
3908 void MapEditor::setSelectionColorInt (QColor col)
3910 if ( !col.isValid() ) return;
3911 xelection.setColor (col);
3914 void MapEditor::setSelectionColor(QColor col)
3916 if ( !col.isValid() ) return;
3918 QString("setSelectionColor (%1)").arg(xelection.getColor().name()),
3919 QString("setSelectionColor (%1)").arg(col.name()),
3920 QString("Set color of selection box to %1").arg(col.name())
3922 setSelectionColorInt (col);
3925 QColor MapEditor::getSelectionColor()
3927 return xelection.getColor();
3930 bool MapEditor::scrollBranch(BranchObj *bo)
3934 if (bo->isScrolled()) return false;
3935 if (bo->countBranches()==0) return false;
3936 if (bo->getDepth()==0) return false;
3942 QString ("%1 ()").arg(u),
3944 QString ("%1 ()").arg(r),
3945 QString ("%1 %2").arg(r).arg(getName(bo))
3955 bool MapEditor::unscrollBranch(BranchObj *bo)
3959 if (!bo->isScrolled()) return false;
3960 if (bo->countBranches()==0) return false;
3961 if (bo->getDepth()==0) return false;
3967 QString ("%1 ()").arg(u),
3969 QString ("%1 ()").arg(r),
3970 QString ("%1 %2").arg(r).arg(getName(bo))
3980 void MapEditor::toggleScroll()
3982 BranchObj *bo=xelection.getBranch();
3983 if (xelection.type()==Selection::Branch )
3985 if (bo->isScrolled())
3986 unscrollBranch (bo);
3992 void MapEditor::unscrollChilds()
3994 BranchObj *bo=xelection.getBranch();
4000 if (bo->isScrolled()) unscrollBranch (bo);
4006 FloatImageObj* MapEditor::loadFloatImageInt (QString fn)
4008 BranchObj *bo=xelection.getBranch();
4012 bo->addFloatImage();
4013 fio=bo->getLastFloatImage();
4015 model->reposition();
4022 void MapEditor::loadFloatImage ()
4024 BranchObj *bo=xelection.getBranch();
4028 Q3FileDialog *fd=new Q3FileDialog( this);
4029 fd->setMode (Q3FileDialog::ExistingFiles);
4030 fd->addFilter (QString (tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)"));
4031 ImagePreview *p =new ImagePreview (fd);
4032 fd->setContentsPreviewEnabled( TRUE );
4033 fd->setContentsPreview( p, p );
4034 fd->setPreviewMode( Q3FileDialog::Contents );
4035 fd->setCaption(vymName+" - " +tr("Load image"));
4036 fd->setDir (lastImageDir);
4039 if ( fd->exec() == QDialog::Accepted )
4041 // TODO loadFIO in QT4 use: lastImageDir=fd->directory();
4042 lastImageDir=QDir (fd->dirPath());
4045 for (int j=0; j<fd->selectedFiles().count(); j++)
4047 s=fd->selectedFiles().at(j);
4048 fio=loadFloatImageInt (s);
4051 (LinkableMapObj*)fio,
4054 QString ("loadImage (%1)").arg(s ),
4055 QString("Add image %1 to %2").arg(s).arg(getName(bo))
4058 // TODO loadFIO error handling
4059 qWarning ("Failed to load "+s);
4067 void MapEditor::saveFloatImageInt (FloatImageObj *fio, const QString &type, const QString &fn)
4069 fio->save (fn,type);
4072 void MapEditor::saveFloatImage ()
4074 FloatImageObj *fio=xelection.getFloatImage();
4077 QFileDialog *fd=new QFileDialog( this);
4078 fd->setFilters (imageIO.getFilters());
4079 fd->setCaption(vymName+" - " +tr("Save image"));
4080 fd->setFileMode( QFileDialog::AnyFile );
4081 fd->setDirectory (lastImageDir);
4082 // fd->setSelection (fio->getOriginalFilename());
4086 if ( fd->exec() == QDialog::Accepted && fd->selectedFiles().count()==1)
4088 fn=fd->selectedFiles().at(0);
4089 if (QFile (fn).exists() )
4091 QMessageBox mb( vymName,
4092 tr("The file %1 exists already.\n"
4093 "Do you want to overwrite it?").arg(fn),
4094 QMessageBox::Warning,
4095 QMessageBox::Yes | QMessageBox::Default,
4096 QMessageBox::Cancel | QMessageBox::Escape,
4097 QMessageBox::QMessageBox::NoButton );
4099 mb.setButtonText( QMessageBox::Yes, tr("Overwrite") );
4100 mb.setButtonText( QMessageBox::No, tr("Cancel"));
4103 case QMessageBox::Yes:
4106 case QMessageBox::Cancel:
4113 saveFloatImageInt (fio,fd->selectedFilter(),fn );
4119 void MapEditor::setFrameType(const FrameObj::FrameType &t)
4121 BranchObj *bo=xelection.getBranch();
4124 QString s=bo->getFrameTypeName();
4125 bo->setFrameType (t);
4126 saveState (bo, QString("setFrameType (\"%1\")").arg(s),
4127 bo, QString ("setFrameType (\"%1\")").arg(bo->getFrameTypeName()),QString ("set type of frame to %1").arg(s));
4128 model->reposition();
4133 void MapEditor::setFrameType(const QString &s)
4135 BranchObj *bo=xelection.getBranch();
4138 saveState (bo, QString("setFrameType (\"%1\")").arg(bo->getFrameTypeName()),
4139 bo, QString ("setFrameType (\"%1\")").arg(s),QString ("set type of frame to %1").arg(s));
4140 bo->setFrameType (s);
4141 model->reposition();
4146 void MapEditor::setFramePenColor(const QColor &c)
4148 BranchObj *bo=xelection.getBranch();
4151 saveState (bo, QString("setFramePenColor (\"%1\")").arg(bo->getFramePenColor().name() ),
4152 bo, QString ("setFramePenColor (\"%1\")").arg(c.name() ),QString ("set pen color of frame to %1").arg(c.name() ));
4153 bo->setFramePenColor (c);
4157 void MapEditor::setFrameBrushColor(const QColor &c)
4159 BranchObj *bo=xelection.getBranch();
4162 saveState (bo, QString("setFrameBrushColor (\"%1\")").arg(bo->getFrameBrushColor().name() ),
4163 bo, QString ("setFrameBrushColor (\"%1\")").arg(c.name() ),QString ("set brush color of frame to %1").arg(c.name() ));
4164 bo->setFrameBrushColor (c);
4168 void MapEditor::setFramePadding (const int &i)
4170 BranchObj *bo=xelection.getBranch();
4173 saveState (bo, QString("setFramePadding (\"%1\")").arg(bo->getFramePadding() ),
4174 bo, QString ("setFramePadding (\"%1\")").arg(i),QString ("set brush color of frame to %1").arg(i));
4175 bo->setFramePadding (i);
4176 model->reposition();
4181 void MapEditor::setFrameBorderWidth(const int &i)
4183 BranchObj *bo=xelection.getBranch();
4186 saveState (bo, QString("setFrameBorderWidth (\"%1\")").arg(bo->getFrameBorderWidth() ),
4187 bo, QString ("setFrameBorderWidth (\"%1\")").arg(i),QString ("set border width of frame to %1").arg(i));
4188 bo->setFrameBorderWidth (i);
4189 model->reposition();
4194 void MapEditor::setIncludeImagesVer(bool b)
4196 BranchObj *bo=xelection.getBranch();
4199 QString u= b ? "false" : "true";
4200 QString r=!b ? "false" : "true";
4204 QString("setIncludeImagesVertically (%1)").arg(u),
4206 QString("setIncludeImagesVertically (%1)").arg(r),
4207 QString("Include images vertically in %1").arg(getName(bo))
4209 bo->setIncludeImagesVer(b);
4210 model->reposition();
4214 void MapEditor::setIncludeImagesHor(bool b)
4216 BranchObj *bo=xelection.getBranch();
4219 QString u= b ? "false" : "true";
4220 QString r=!b ? "false" : "true";
4224 QString("setIncludeImagesHorizontally (%1)").arg(u),
4226 QString("setIncludeImagesHorizontally (%1)").arg(r),
4227 QString("Include images horizontally in %1").arg(getName(bo))
4229 bo->setIncludeImagesHor(b);
4230 model->reposition();
4234 void MapEditor::setHideLinkUnselected (bool b)
4236 LinkableMapObj *sel=xelection.single();
4238 (xelection.type() == Selection::Branch ||
4239 xelection.type() == Selection::MapCenter ||
4240 xelection.type() == Selection::FloatImage ))
4242 QString u= b ? "false" : "true";
4243 QString r=!b ? "false" : "true";
4247 QString("setHideLinkUnselected (%1)").arg(u),
4249 QString("setHideLinkUnselected (%1)").arg(r),
4250 QString("Hide link of %1 if unselected").arg(getName(sel))
4252 sel->setHideLinkUnselected(b);
4256 void MapEditor::importDirInt(BranchObj *dst, QDir d)
4258 BranchObj *bo=xelection.getBranch();
4261 // Traverse directories
4262 d.setFilter( QDir::Dirs| QDir::Hidden | QDir::NoSymLinks );
4263 QFileInfoList list = d.entryInfoList();
4266 for (int i = 0; i < list.size(); ++i)
4269 if (fi.fileName() != "." && fi.fileName() != ".." )
4272 bo=dst->getLastBranch();
4273 bo->setHeading (fi.fileName() );
4274 bo->setColor (QColor("blue"));
4276 if ( !d.cd(fi.fileName()) )
4277 QMessageBox::critical (0,tr("Critical Import Error"),tr("Cannot find the directory %1").arg(fi.fileName()));
4280 // Recursively add subdirs
4281 importDirInt (bo,d);
4287 d.setFilter( QDir::Files| QDir::Hidden | QDir::NoSymLinks );
4288 list = d.entryInfoList();
4290 for (int i = 0; i < list.size(); ++i)
4294 bo=dst->getLastBranch();
4295 bo->setHeading (fi.fileName() );
4296 bo->setColor (QColor("black"));
4297 if (fi.fileName().right(4) == ".vym" )
4298 bo->setVymLink (fi.filePath());
4303 void MapEditor::importDirInt (const QString &s)
4305 BranchObj *bo=xelection.getBranch();
4308 saveStateChangingPart (bo,bo,QString ("importDir (\"%1\")").arg(s),QString("Import directory structure from %1").arg(s));
4311 importDirInt (bo,d);
4315 void MapEditor::importDir()
4317 BranchObj *bo=xelection.getBranch();
4320 QStringList filters;
4321 filters <<"VYM map (*.vym)";
4322 QFileDialog *fd=new QFileDialog( this,vymName+ " - " +tr("Choose directory structure to import"));
4323 fd->setMode (QFileDialog::DirectoryOnly);
4324 fd->setFilters (filters);
4325 fd->setCaption(vymName+" - " +tr("Choose directory structure to import"));
4329 if ( fd->exec() == QDialog::Accepted )
4331 importDirInt (fd->selectedFile() );
4332 model->reposition();
4338 void MapEditor::followXLink(int i)
4340 BranchObj *bo=xelection.getBranch();
4343 bo=bo->XLinkTargetAt(i);
4346 xelection.select(bo);
4347 ensureSelectionVisible();
4352 void MapEditor::editXLink(int i) // FIXME missing saveState
4354 BranchObj *bo=xelection.getBranch();
4357 XLinkObj *xlo=bo->XLinkAt(i);
4360 EditXLinkDialog dia;
4362 dia.setSelection(bo);
4363 if (dia.exec() == QDialog::Accepted)
4365 if (dia.useSettingsGlobal() )
4367 setMapDefXLinkColor (xlo->getColor() );
4368 setMapDefXLinkWidth (xlo->getWidth() );
4370 if (dia.deleteXLink())
4371 bo->deleteXLinkAt(i);
4377 AttributeTable* MapEditor::attributeTable()
4382 void MapEditor::testFunction1()
4384 BranchObj *bo=xelection.getBranch();
4385 if (bo) model->moveAway (bo);
4389 BranchObj *bo=xelection.getBranch();
4390 if (bo) animObjList.append( bo );
4393 /* TODO Hide hidden stuff temporary, maybe add this as regular function somewhere
4394 if (hidemode==HideNone)
4396 setHideTmpMode (HideExport);
4397 mapCenter->calcBBoxSizeWithChilds();
4398 QRectF totalBBox=mapCenter->getTotalBBox();
4399 QRectF mapRect=totalBBox;
4400 QCanvasRectangle *frame=NULL;
4402 cout << " map has =("<<totalBBox.x()<<","<<totalBBox.y()<<","<<totalBBox.width()<<","<<totalBBox.height()<<")\n";
4404 mapRect.setRect (totalBBox.x(), totalBBox.y(),
4405 totalBBox.width(), totalBBox.height());
4406 frame=new QCanvasRectangle (mapRect,mapScene);
4407 frame->setBrush (QColor(white));
4408 frame->setPen (QColor(black));
4409 frame->setZValue(0);
4414 setHideTmpMode (HideNone);
4416 cout <<" hidemode="<<hidemode<<endl;
4420 void MapEditor::testFunction2()
4423 xelection.select (model->addMapCenter());
4424 ensureSelectionVisible();
4428 if (hidemode==HideExport)
4429 setHideTmpMode (HideNone);
4431 setHideTmpMode (HideExport);
4435 void MapEditor::contextMenuEvent ( QContextMenuEvent * e )
4437 // Lineedits are already closed by preceding
4438 // mouseEvent, we don't need to close here.
4440 QPointF p = mapToScene(e->pos());
4441 LinkableMapObj* lmo=model->findMapObj(p, NULL);
4444 { // MapObj was found
4445 if (xelection.single() != lmo)
4447 // select the MapObj
4448 xelection.select(lmo);
4451 if (xelection.getBranch() )
4453 // Context Menu on branch or mapcenter
4455 branchContextMenu->popup(e->globalPos() );
4458 if (xelection.getFloatImage() )
4460 // Context Menu on floatimage
4462 floatimageContextMenu->popup(e->globalPos() );
4466 { // No MapObj found, we are on the Canvas itself
4467 // Context Menu on scene
4469 canvasContextMenu->popup(e->globalPos() );
4474 void MapEditor::keyPressEvent(QKeyEvent* e)
4476 if (e->modifiers() & Qt::ControlModifier)
4478 switch (mainWindow->getModMode())
4480 case Main::ModModeColor:
4481 setCursor (PickColorCursor);
4483 case Main::ModModeCopy:
4484 setCursor (CopyCursor);
4486 case Main::ModModeXLink:
4487 setCursor (XLinkCursor);
4490 setCursor (Qt::ArrowCursor);
4496 void MapEditor::keyReleaseEvent(QKeyEvent* e)
4498 if (!(e->modifiers() & Qt::ControlModifier))
4499 setCursor (Qt::ArrowCursor);
4502 void MapEditor::mousePressEvent(QMouseEvent* e)
4504 // Ignore right clicks, these will go to context menus
4505 if (e->button() == Qt::RightButton )
4511 //Ignore clicks while editing heading
4512 if (isSelectBlocked() )
4518 QPointF p = mapToScene(e->pos());
4519 LinkableMapObj* lmo=model->findMapObj(p, NULL);
4523 //Take care of system flags _or_ modifier modes
4525 if (lmo && (typeid(*lmo)==typeid(BranchObj) ||
4526 typeid(*lmo)==typeid(MapCenterObj) ))
4528 QString foname=((BranchObj*)lmo)->getSystemFlagName(p);
4529 if (!foname.isEmpty())
4531 // systemFlag clicked
4535 if (e->state() & Qt::ControlModifier)
4536 mainWindow->editOpenURLTab();
4538 mainWindow->editOpenURL();
4540 else if (foname=="vymLink")
4542 mainWindow->editOpenVymLink();
4543 // tabWidget may change, better return now
4544 // before segfaulting...
4545 } else if (foname=="note")
4546 mainWindow->windowToggleNoteEditor();
4547 else if (foname=="hideInExport")
4554 // No system flag clicked, take care of modmodes (CTRL-Click)
4555 if (e->state() & Qt::ControlModifier)
4557 if (mainWindow->getModMode()==Main::ModModeColor)
4560 setCursor (PickColorCursor);
4563 if (mainWindow->getModMode()==Main::ModModeXLink)
4565 BranchObj *bo_begin=NULL;
4567 bo_begin=(BranchObj*)(lmo);
4569 if (xelection.getBranch() )
4570 bo_begin=xelection.getBranch();
4574 linkingObj_src=bo_begin;
4575 tmpXLink=new XLinkObj (mapScene);
4576 tmpXLink->setBegin (bo_begin);
4577 tmpXLink->setEnd (p);
4578 tmpXLink->setColor(defXLinkColor);
4579 tmpXLink->setWidth(defXLinkWidth);
4580 tmpXLink->updateXLink();
4581 tmpXLink->setVisibility (true);
4585 } // End of modmodes
4589 // Select the clicked object
4592 // Left Button Move Branches
4593 if (e->button() == Qt::LeftButton )
4595 //movingObj_start.setX( p.x() - selection->x() );// TODO replaced selection->lmo here
4596 //movingObj_start.setY( p.y() - selection->y() );
4597 movingObj_start.setX( p.x() - lmo->x() );
4598 movingObj_start.setY( p.y() - lmo->y() );
4599 movingObj_orgPos.setX (lmo->x() );
4600 movingObj_orgPos.setY (lmo->y() );
4601 movingObj_orgRelPos=lmo->getRelPos();
4603 // If modMode==copy, then we want to "move" the _new_ object around
4604 // then we need the offset from p to the _old_ selection, because of tmp
4605 if (mainWindow->getModMode()==Main::ModModeCopy &&
4606 e->state() & Qt::ControlModifier)
4608 BranchObj *bo=xelection.getBranch();
4612 bo->addBranch ((BranchObj*)xelection.single());
4614 xelection.select(bo->getLastBranch());
4615 model->reposition();
4619 movingObj=xelection.single();
4621 // Middle Button Toggle Scroll
4622 // (On Mac OS X this won't work, but we still have
4623 // a button in the toolbar)
4624 if (e->button() == Qt::MidButton )
4629 { // No MapObj found, we are on the scene itself
4630 // Left Button move Pos of sceneView
4631 if (e->button() == Qt::LeftButton )
4633 movingObj=NULL; // move Content not Obj
4634 movingObj_start=e->globalPos();
4635 movingCont_start=QPointF (
4636 horizontalScrollBar()->value(),
4637 verticalScrollBar()->value());
4638 movingVec=QPointF(0,0);
4639 setCursor(HandOpenCursor);
4644 void MapEditor::mouseMoveEvent(QMouseEvent* e)
4646 QPointF p = mapToScene(e->pos());
4647 LinkableMapObj *lmosel=xelection.single();
4649 // Move the selected MapObj
4650 if ( lmosel && movingObj)
4652 // reset cursor if we are moving and don't copy
4653 if (mainWindow->getModMode()!=Main::ModModeCopy)
4654 setCursor (Qt::ArrowCursor);
4656 // To avoid jumping of the sceneView, only
4657 // ensureSelectionVisible, if not tmp linked
4658 if (!lmosel->hasParObjTmp())
4659 ensureSelectionVisible ();
4661 // Now move the selection, but add relative position
4662 // (movingObj_start) where selection was chosen with
4663 // mousepointer. (This avoids flickering resp. jumping
4664 // of selection back to absPos)
4666 // Check if we could link
4667 LinkableMapObj* lmo=model->findMapObj(p, lmosel);
4670 FloatObj *fio=xelection.getFloatImage();
4673 fio->move (p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
4675 fio->updateLink(); //no need for reposition, if we update link here
4678 // Relink float to new mapcenter or branch, if shift is pressed
4679 // Only relink, if selection really has a new parent
4680 if ( (e->modifiers()==Qt::ShiftModifier) && lmo &&
4681 ( (typeid(*lmo)==typeid(BranchObj)) ||
4682 (typeid(*lmo)==typeid(MapCenterObj)) ) &&
4683 ( lmo != fio->getParObj())
4686 if (typeid(*fio) == typeid(FloatImageObj) &&
4687 ( (typeid(*lmo)==typeid(BranchObj) ||
4688 typeid(*lmo)==typeid(MapCenterObj)) ))
4691 // Also save the move which was done so far
4692 QString pold=qpointfToString(movingObj_orgRelPos);
4693 QString pnow=qpointfToString(fio->getRelPos());
4699 QString("Move %1 to relative position %2").arg(getName(fio)).arg(pnow));
4700 fio->getParObj()->requestReposition();
4701 model->reposition();
4703 linkTo (lmo->getSelectString());
4705 //movingObj_orgRelPos=lmosel->getRelPos();
4707 model->reposition();
4711 { // selection != a FloatObj
4712 if (lmosel->getDepth()==0)
4715 if (e->buttons()== Qt::LeftButton && e->modifiers()==Qt::ShiftModifier)
4716 ((MapCenterObj*)lmosel)->moveAll(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
4718 lmosel->move (p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
4719 model->updateRelPositions();
4722 if (lmosel->getDepth()==1)
4725 lmosel->move(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
4726 lmosel->setRelPos();
4729 // Move ordinary branch
4730 if (lmosel->getOrientation() == LinkableMapObj::LeftOfCenter)
4731 // Add width of bbox here, otherwise alignRelTo will cause jumping around
4732 lmosel->move(p.x() -movingObj_start.x()+lmosel->getBBox().width(),
4733 p.y()-movingObj_start.y() +lmosel->getTopPad() );
4735 lmosel->move(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() -lmosel->getTopPad());
4738 // Maybe we can relink temporary?
4739 if (lmo && (lmo!=lmosel) && xelection.getBranch() &&
4740 (typeid(*lmo)==typeid(BranchObj) ||
4741 typeid(*lmo)==typeid(MapCenterObj)) )
4744 if (e->modifiers()==Qt::ControlModifier)
4746 // Special case: CTRL to link below lmo
4747 lmosel->setParObjTmp (lmo,p,+1);
4749 else if (e->modifiers()==Qt::ShiftModifier)
4750 lmosel->setParObjTmp (lmo,p,-1);
4752 lmosel->setParObjTmp (lmo,p,0);
4755 lmosel->unsetParObjTmp();
4757 // reposition subbranch
4758 lmosel->reposition();
4762 } // no FloatImageObj
4766 } // selection && moving_obj
4768 // Draw a link from one branch to another
4771 tmpXLink->setEnd (p);
4772 tmpXLink->updateXLink();
4776 if (!movingObj && !pickingColor &&!drawingLink && e->buttons() == Qt::LeftButton )
4778 QPointF p=e->globalPos();
4779 movingVec.setX(-p.x() + movingObj_start.x() );
4780 movingVec.setY(-p.y() + movingObj_start.y() );
4781 horizontalScrollBar()->setSliderPosition((int)( movingCont_start.x()+movingVec.x() ));
4782 verticalScrollBar()->setSliderPosition((int)( movingCont_start.y()+movingVec.y() ) );
4787 void MapEditor::mouseReleaseEvent(QMouseEvent* e)
4789 QPointF p = mapToScene(e->pos());
4790 LinkableMapObj *dst;
4791 LinkableMapObj *lmosel=xelection.single();
4792 // Have we been picking color?
4796 setCursor (Qt::ArrowCursor);
4797 // Check if we are over another branch
4798 dst=model->findMapObj(p, NULL);
4801 if (e->state() & Qt::ShiftModifier)
4802 colorBranch (((BranchObj*)dst)->getColor());
4804 colorSubtree (((BranchObj*)dst)->getColor());
4809 // Have we been drawing a link?
4813 // Check if we are over another branch
4814 dst=model->findMapObj(p, NULL);
4817 tmpXLink->setEnd ( ((BranchObj*)(dst)) );
4818 tmpXLink->updateXLink();
4819 tmpXLink->activate(); //FIXME savestate missing
4820 //saveStateComplete(QString("Activate xLink from %1 to %2").arg(getName(tmpXLink->getBegin())).arg(getName(tmpXLink->getEnd())) );
4829 // Have we been moving something?
4830 if ( lmosel && movingObj )
4832 FloatImageObj *fo=xelection.getFloatImage();
4835 // Moved FloatObj. Maybe we need to reposition
4836 QString pold=qpointfToString(movingObj_orgRelPos);
4837 QString pnow=qpointfToString(fo->getRelPos());
4843 QString("Move %1 to relative position %2").arg(getName(fo)).arg(pnow));
4845 fo->getParObj()->requestReposition();
4846 model->reposition();
4849 // Check if we are over another branch, but ignore
4850 // any found LMOs, which are FloatObjs
4851 dst=model->findMapObj(mapToScene(e->pos() ), lmosel);
4853 if (dst && (typeid(*dst)!=typeid(BranchObj) && typeid(*dst)!=typeid(MapCenterObj)))
4856 BranchObj *bo=xelection.getBranch();
4857 if (bo && bo->getDepth()==0)
4859 if (movingObj_orgPos != bo->getAbsPos())
4861 QString pold=qpointfToString(movingObj_orgPos);
4862 QString pnow=qpointfToString(bo->getAbsPos());
4868 QString("Move mapcenter %1 to position %2").arg(getName(bo)).arg(pnow));
4872 if (xelection.type() == Selection::Branch )
4873 { // A branch was moved
4875 // save the position in case we link to mapcenter
4876 QPointF savePos=QPointF (lmosel->getAbsPos() );
4878 // Reset the temporary drawn link to the original one
4879 lmosel->unsetParObjTmp();
4881 // For Redo we may need to save original selection
4882 QString preSelStr=lmosel->getSelectString();
4887 BranchObj* bsel=xelection.getBranch();
4888 BranchObj* bdst=(BranchObj*)dst;
4890 QString preParStr=(bsel->getParObj())->getSelectString();
4891 QString preNum=QString::number (bsel->getNum(),10);
4892 QString preDstParStr;
4894 if (e->state() & Qt::ShiftModifier && dst->getParObj())
4896 preDstParStr=dst->getParObj()->getSelectString();
4897 bsel->linkTo ( (BranchObj*)(bdst->getParObj()), bdst->getNum());
4899 if (e->state() & Qt::ControlModifier && dst->getParObj())
4902 preDstParStr=dst->getParObj()->getSelectString();
4903 bsel->linkTo ( (BranchObj*)(bdst->getParObj()), bdst->getNum()+1);
4906 preDstParStr=dst->getSelectString();
4907 bsel->linkTo (bdst,-1);
4908 if (dst->getDepth()==0) bsel->move (savePos);
4910 QString postSelStr=lmosel->getSelectString();
4911 QString postNum=QString::number (bsel->getNum(),10);
4913 QString undoCom="linkTo (\""+
4914 preParStr+ "\"," + preNum +"," +
4915 QString ("%1,%2").arg(movingObj_orgPos.x()).arg(movingObj_orgPos.y())+ ")";
4917 QString redoCom="linkTo (\""+
4918 preDstParStr + "\"," + postNum + "," +
4919 QString ("%1,%2").arg(savePos.x()).arg(savePos.y())+ ")";
4924 QString("Relink %1 to %2").arg(getName(bsel)).arg(getName(dst)) );
4926 if (lmosel->getDepth()==1)
4928 // The select string might be different _after_ moving around.
4929 // Therefor reposition and then use string of old selection, too
4930 model->reposition();
4932 QPointF rp(lmosel->getRelPos());
4933 if (rp != movingObj_orgRelPos)
4935 QString ps=qpointfToString(rp);
4937 lmosel->getSelectString(), "moveRel "+qpointfToString(movingObj_orgRelPos),
4938 preSelStr, "moveRel "+ps,
4939 QString("Move %1 to relative position %2").arg(getName(lmosel)).arg(ps));
4942 // Draw the original link, before selection was moved around
4943 model->reposition();
4946 // Finally resize scene, if needed
4950 // Just make sure, that actions are still ok,e.g. the move branch up/down buttons...
4953 // maybe we moved View: set old cursor
4954 setCursor (Qt::ArrowCursor);
4958 void MapEditor::mouseDoubleClickEvent(QMouseEvent* e)
4960 if (isSelectBlocked() )
4966 if (e->button() == Qt::LeftButton )
4968 QPointF p = mapToScene(e->pos());
4969 LinkableMapObj *lmo=model->findMapObj(p, NULL);
4970 if (lmo) { // MapObj was found
4971 // First select the MapObj than edit heading
4972 xelection.select(lmo);
4973 mainWindow->editHeading();
4978 void MapEditor::resizeEvent (QResizeEvent* e)
4980 QGraphicsView::resizeEvent( e );
4983 void MapEditor::dragEnterEvent(QDragEnterEvent *event)
4985 //for (unsigned int i=0;event->format(i);i++) // Debug mime type
4986 // cerr << event->format(i) << endl;
4988 if (event->mimeData()->hasImage())
4989 event->acceptProposedAction();
4991 if (event->mimeData()->hasUrls())
4992 event->acceptProposedAction();
4995 void MapEditor::dragMoveEvent(QDragMoveEvent *)
4999 void MapEditor::dragLeaveEvent(QDragLeaveEvent *event)
5004 void MapEditor::dropEvent(QDropEvent *event)
5006 BranchObj *sel=xelection.getBranch();
5010 foreach (QString format,event->mimeData()->formats())
5011 cout << "MapEditor: Dropped format: "<<qPrintable (format)<<endl;
5015 if (event->mimeData()->hasImage())
5017 QVariant imageData = event->mimeData()->imageData();
5018 addFloatImageInt (qvariant_cast<QPixmap>(imageData));
5020 if (event->mimeData()->hasUrls())
5021 uris=event->mimeData()->urls();
5029 for (int i=0; i<uris.count();i++)
5031 // Workaround to avoid adding empty branches
5032 if (!uris.at(i).toString().isEmpty())
5034 bo=sel->addBranch();
5037 s=uris.at(i).toLocalFile();
5040 QString file = QDir::fromNativeSeparators(s);
5041 heading = QFileInfo(file).baseName();
5043 if (file.endsWith(".vym", false))
5044 bo->setVymLink(file);
5046 bo->setURL(uris.at(i).toString());
5049 bo->setURL(uris.at(i).toString());
5052 if (!heading.isEmpty())
5053 bo->setHeading(heading);
5055 bo->setHeading(uris.at(i).toString());
5059 model->reposition();
5062 event->acceptProposedAction();
5065 void MapEditor::timerEvent(QTimerEvent *event) //TODO animation
5069 cout << "ME::timerEvent\n";
5071 for (int i=0; i<animObjList.size(); ++i)
5073 animObjList.at(i)->animate();
5074 ((BranchObj*)animObjList.at(i))->move2RelPos (((BranchObj*)animObjList.at(i))->getRelPos() );
5076 model->reposition();
5080 void MapEditor::sendSelection()
5082 if (netstate!=Server) return;
5083 sendData (QString("select (\"%1\")").arg(xelection.getSelectString()) );
5086 void MapEditor::newServer()
5090 tcpServer = new QTcpServer(this);
5091 if (!tcpServer->listen(QHostAddress::Any,port)) {
5092 QMessageBox::critical(this, "vym server",
5093 QString("Unable to start the server: %1.").arg(tcpServer->errorString()));
5097 connect(tcpServer, SIGNAL(newConnection()), this, SLOT(newClient()));
5099 cout<<"Server is running on port "<<tcpServer->serverPort()<<endl;
5102 void MapEditor::connectToServer()
5105 server="salam.suse.de";
5107 clientSocket = new QTcpSocket (this);
5108 clientSocket->abort();
5109 clientSocket->connectToHost(server ,port);
5110 connect(clientSocket, SIGNAL(readyRead()), this, SLOT(readData()));
5111 connect(clientSocket, SIGNAL(error(QAbstractSocket::SocketError)),
5112 this, SLOT(displayNetworkError(QAbstractSocket::SocketError)));
5114 cout<<"connected to "<<qPrintable (server)<<" port "<<port<<endl;
5119 void MapEditor::newClient()
5121 QTcpSocket *newClient = tcpServer->nextPendingConnection();
5122 connect(newClient, SIGNAL(disconnected()),
5123 newClient, SLOT(deleteLater()));
5125 cout <<"ME::newClient at "<<qPrintable( newClient->peerAddress().toString() )<<endl;
5127 clientList.append (newClient);
5131 void MapEditor::sendData(const QString &s)
5133 if (clientList.size()==0) return;
5135 // Create bytearray to send
5137 QDataStream out(&block, QIODevice::WriteOnly);
5138 out.setVersion(QDataStream::Qt_4_0);
5140 // Reserve some space for blocksize
5143 // Write sendCounter
5144 out << sendCounter++;
5149 // Go back and write blocksize so far
5150 out.device()->seek(0);
5151 quint16 bs=(quint16)(block.size() - 2*sizeof(quint16));
5155 cout << "ME::sendData bs="<<bs<<" counter="<<sendCounter<<" s="<<qPrintable(s)<<endl;
5157 for (int i=0; i<clientList.size(); ++i)
5159 //cout << "Sending \""<<qPrintable (s)<<"\" to "<<qPrintable (clientList.at(i)->peerAddress().toString())<<endl;
5160 clientList.at(i)->write (block);
5164 void MapEditor::readData ()
5166 while (clientSocket->bytesAvailable() >=(int)sizeof(quint16) )
5169 cout <<"readData bytesAvail="<<clientSocket->bytesAvailable();
5173 QDataStream in(clientSocket);
5174 in.setVersion(QDataStream::Qt_4_0);
5182 cout << " t="<<qPrintable (t)<<endl;
5188 void MapEditor::displayNetworkError(QAbstractSocket::SocketError socketError)
5190 switch (socketError) {
5191 case QAbstractSocket::RemoteHostClosedError:
5193 case QAbstractSocket::HostNotFoundError:
5194 QMessageBox::information(this, vymName +" Network client",
5195 "The host was not found. Please check the "
5196 "host name and port settings.");
5198 case QAbstractSocket::ConnectionRefusedError:
5199 QMessageBox::information(this, vymName + " Network client",
5200 "The connection was refused by the peer. "
5201 "Make sure the fortune server is running, "
5202 "and check that the host name and port "
5203 "settings are correct.");
5206 QMessageBox::information(this, vymName + " Network client",
5207 QString("The following error occurred: %1.")
5208 .arg(clientSocket->errorString()));
5212 void MapEditor::autosave()
5214 QDateTime now=QDateTime().currentDateTime();
5216 cout << "ME::autosave checking "<<qPrintable(filePath)<<"...\n";
5217 cout << "fsaved: "<<qPrintable (fileChangedTime.toString())<<endl;
5218 cout << " fnow: "<<qPrintable (QFileInfo(filePath).lastModified().toString())<<endl;
5219 cout << " time: "<<qPrintable (now.toString())<<endl;
5221 // Disable autosave, while we have gone back in history
5222 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
5223 if (redosAvail>0) return;
5226 if (mapUnsaved &&mapChanged && settings.value ("/mapeditor/autosave/use",true).toBool() )
5228 if (QFileInfo(filePath).lastModified()<=fileChangedTime)
5229 mainWindow->fileSave (this);
5232 cout <<" ME::autosave rejected, file on disk is newer than last save.\n";
5237 void MapEditor::fileChanged()
5239 // Check if file on disk has changed meanwhile
5240 if (!filePath.isEmpty())
5242 QDateTime tmod=QFileInfo (filePath).lastModified();
5243 if (tmod>fileChangedTime)
5246 /* FIXME debug message, sometimes there's a glitch in the metrics...
5247 cout << "ME::fileChanged()\n"
5248 << " last saved: "<<qPrintable (fileChangedTime.toString())<<endl
5249 << " last modififed: "<<qPrintable (tmod.toString())<<endl;
5251 // FIXME switch to current mapeditor and finish lineedits...
5252 QMessageBox mb( vymName,
5253 tr("The file of the map on disk has changed:\n\n"
5254 " %1\n\nDo you want to reload this map with the new file?").arg(filePath),
5255 QMessageBox::Question,
5257 QMessageBox::Cancel | QMessageBox::Default,
5258 QMessageBox::NoButton );
5260 mb.setButtonText( QMessageBox::Yes, tr("Reload"));
5261 mb.setButtonText( QMessageBox::No, tr("Ignore"));
5264 case QMessageBox::Yes:
5266 load (filePath,NewMap,fileType);
5267 case QMessageBox::Cancel:
5268 fileChangedTime=tmod; // allow autosave to overwrite newer file!
5276 /*TODO not needed? void MapEditor::contentsDropEvent(QDropEvent *event)
5279 } else if (event->provides("application/x-moz-file-promise-url") &&
5280 event->provides("application/x-moz-nativeimage"))
5282 // Contains url to the img src in unicode16
5283 QByteArray d = event->encodedData("application/x-moz-file-promise-url");
5284 QString url = QString((const QChar*)d.data(),d.size()/2);
5288 } else if (event->provides ("text/uri-list"))
5289 { // Uris provided e.g. by konqueror
5290 Q3UriDrag::decode (event,uris);
5291 } else if (event->provides ("_NETSCAPE_URL"))
5292 { // Uris provided by Mozilla
5293 QStringList l = QStringList::split("\n", event->encodedData("_NETSCAPE_URL"));
5296 } else if (event->provides("text/html")) {
5298 // Handels text mime types
5299 // Look like firefox allways handle text as unicode16 (2 bytes per char.)
5300 QByteArray d = event->encodedData("text/html");
5303 text = QString((const QChar*)d.data(),d.size()/2);
5307 textEditor->setText(text);
5311 } else if (event->provides("text/plain")) {
5312 QByteArray d = event->encodedData("text/plain");
5315 text = QString((const QChar*)d.data(),d.size()/2);
5319 textEditor->setText(text);
5329 bool isUnicode16(const QByteArray &d)
5331 // TODO: make more precise check for unicode 16.
5332 // Guess unicode16 if any of second bytes are zero
5333 unsigned int length = max(0,d.size()-2)/2;
5334 for (unsigned int i = 0; i<length ; i++)
5335 if (d.at(i*2+1)==0) return true;
5339 void MapEditor::addFloatImageInt (const QPixmap &img)
5341 BranchObj *bo=xelection.getBranch();
5344 FloatImageObj *fio=bo->addFloatImage();
5346 fio->setOriginalFilename("No original filename (image added by dropevent)");
5347 QString s=bo->getSelectString();
5348 saveState (PartOfMap, s, "nop ()", s, "copy ()","Copy dropped image to clipboard",fio );
5349 saveState (fio,"delete ()", bo,QString("paste(%1)").arg(curStep),"Pasting dropped image");
5350 model->reposition();
5357 void MapEditor::imageDataFetched(const QByteArray &a, Q3NetworkOperation * / *nop* /)
5359 if (!imageBuffer) imageBuffer = new QBuffer();
5360 if (!imageBuffer->isOpen()) {
5361 imageBuffer->open(QIODevice::WriteOnly | QIODevice::Append);
5363 imageBuffer->at(imageBuffer->at()+imageBuffer->writeBlock(a));
5367 void MapEditor::imageDataFinished(Q3NetworkOperation *nop)
5369 if (nop->state()==Q3NetworkProtocol::StDone) {
5370 QPixmap img(imageBuffer->buffer());
5371 addFloatImageInt (img);
5375 imageBuffer->close();
5377 imageBuffer->close();
5384 void MapEditor::fetchImage(const QString &url)
5387 urlOperator->stop();
5388 disconnect(urlOperator);
5392 urlOperator = new Q3UrlOperator(url);
5393 connect(urlOperator, SIGNAL(finished(Q3NetworkOperation *)),
5394 this, SLOT(imageDataFinished(Q3NetworkOperation*)));
5396 connect(urlOperator, SIGNAL(data(const QByteArray &, Q3NetworkOperation *)),
5397 this, SLOT(imageDataFetched(const QByteArray &, Q3NetworkOperation *)));