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);
141 autosaveTimer=new QTimer (this);
142 connect(autosaveTimer, SIGNAL(timeout()), this, SLOT(autosave()));
144 fileChangedTimer=new QTimer (this);
145 fileChangedTimer->start(3000);
146 connect(fileChangedTimer, SIGNAL(timeout()), this, SLOT(fileChanged()));
151 // Attributes //FIXME testing only...
154 attrTable= new AttributeTable();
156 ad=attrTable->addKey (k,StringList);
160 sl <<"val 1"<<"val 2"<< "val 3";
161 ad->setValue (QVariant (sl));
163 //attrTable->addValue ("Key A","P 1");
164 //attrTable->addValue ("Key A","P 2");
165 //attrTable->addValue ("Key A","P 3");
166 //attrTable->addValue ("Key A","P 4");
168 ad=attrTable->addKey (k,FreeString);
171 //attrTable->addValue ("Key B","w1");
172 //attrTable->addValue ("Key B","w2");
174 k="C - UniqueString";
175 ad=attrTable->addKey (k,UniqueString);
178 //attrTable->addKey ("Key Prio");
179 //attrTable->addValue ("Key Prio","Prio 1");
180 //attrTable->addValue ("Key Prio","Prio 2");
184 MapEditor::~MapEditor()
186 //cout <<"Destructor MapEditor\n";
187 autosaveTimer->stop();
188 fileChangedTimer->stop();
190 // tmpMapDir is in tmpVymDir, so it gets removed automagically when vym closes
192 //removeDir(QDir(tmpMapDir));
196 VymModel* MapEditor::getModel()
201 QGraphicsScene * MapEditor::getScene()
206 MapEditor::State MapEditor::getState()
211 void MapEditor::setStateEditHeading(bool s)
215 if (state==Idle) state=EditHeading;
221 bool MapEditor::isRepositionBlocked()
223 return blockReposition;
226 void MapEditor::setSaveStateBlocked(bool b)
231 bool MapEditor::isSelectBlocked()
233 if (state==EditHeading)
239 QString MapEditor::getName (const LinkableMapObj *lmo)
242 if (!lmo) return QString("Error: NULL has no name!");
244 if ((typeid(*lmo) == typeid(BranchObj) ||
245 typeid(*lmo) == typeid(MapCenterObj)))
248 s=(((BranchObj*)lmo)->getHeading());
249 if (s=="") s="unnamed";
250 return QString("branch (%1)").arg(s);
252 if ((typeid(*lmo) == typeid(FloatImageObj) ))
253 return QString ("floatimage [%1]").arg(((FloatImageObj*)lmo)->getOriginalFilename());
254 return QString("Unknown type has no name!");
257 void MapEditor::makeTmpDirs()
259 // Create unique temporary directories
260 tmpMapDir = tmpVymDir+QString("/mapeditor-%1").arg(mapNum);
261 histPath = tmpMapDir+"/history";
266 QString MapEditor::saveToDir(const QString &tmpdir, const QString &prefix, bool writeflags, const QPointF &offset, LinkableMapObj *saveSel)
268 // tmpdir temporary directory to which data will be written
269 // prefix mapname, which will be appended to images etc.
270 // writeflags Only write flags for "real" save of map, not undo
271 // offset offset of bbox of whole map in scene.
272 // Needed for XML export
278 case LinkableMapObj::Line:
281 case LinkableMapObj::Parabel:
284 case LinkableMapObj::PolyLine:
288 ls="StylePolyParabel";
292 QString s="<?xml version=\"1.0\" encoding=\"utf-8\"?><!DOCTYPE vymmap>\n";
294 if (linkcolorhint==LinkableMapObj::HeadingColor)
295 colhint=attribut("linkColorHint","HeadingColor");
297 QString mapAttr=attribut("version",vymVersion);
299 mapAttr+= attribut("author",model->getAuthor()) +
300 attribut("comment",model->getComment()) +
301 attribut("date",model->getDate()) +
302 attribut("backgroundColor", mapScene->backgroundBrush().color().name() ) +
303 attribut("selectionColor", xelection.getColor().name() ) +
304 attribut("linkStyle", ls ) +
305 attribut("linkColor", defLinkColor.name() ) +
306 attribut("defXLinkColor", defXLinkColor.name() ) +
307 attribut("defXLinkWidth", QString().setNum(defXLinkWidth,10) ) +
309 s+=beginElement("vymmap",mapAttr);
312 // Find the used flags while traversing the tree
313 standardFlagsDefault->resetUsedCounter();
315 // Reset the counters before saving
316 // TODO constr. of FIO creates lots of objects, better do this in some other way...
317 FloatImageObj (mapScene).resetSaveCounter();
319 // Build xml recursivly
320 if (!saveSel || typeid (*saveSel) == typeid (MapCenterObj))
321 // Save complete map, if saveSel not set
322 s+=model->saveToDir(tmpdir,prefix,writeflags,offset);
325 if ( typeid(*saveSel) == typeid(BranchObj) )
327 s+=((BranchObj*)(saveSel))->saveToDir(tmpdir,prefix,offset);
328 else if ( typeid(*saveSel) == typeid(FloatImageObj) )
330 s+=((FloatImageObj*)(saveSel))->saveToDir(tmpdir,prefix);
333 // Save local settings
334 s+=settings.getDataXML (destPath);
337 if (!xelection.isEmpty() && !saveSel )
338 s+=valueElement("select",xelection.getSelectString());
341 s+=endElement("vymmap");
344 standardFlagsDefault->saveToDir (tmpdir+"/flags/","",writeflags);
348 QString MapEditor::getHistoryDir()
350 QString histName(QString("history-%1").arg(curStep));
351 return (tmpMapDir+"/"+histName);
354 void MapEditor::saveState(const SaveMode &savemode, const QString &undoSelection, const QString &undoCom, const QString &redoSelection, const QString &redoCom, const QString &comment, LinkableMapObj *saveSel)
356 sendData(redoCom); //FIXME testing
361 if (blockSaveState) return;
363 if (debug) cout << "ME::saveState() for "<<qPrintable (mapName)<<endl;
365 // Find out current undo directory
366 if (undosAvail<stepsTotal) undosAvail++;
368 if (curStep>stepsTotal) curStep=1;
370 QString backupXML="";
371 QString histDir=getHistoryDir();
372 QString bakMapPath=histDir+"/map.xml";
374 // Create histDir if not available
377 makeSubDirs (histDir);
379 // Save depending on how much needs to be saved
381 backupXML=saveToDir (histDir,mapName+"-",false, QPointF (),saveSel);
383 QString undoCommand="";
384 if (savemode==UndoCommand)
388 else if (savemode==PartOfMap )
391 undoCommand.replace ("PATH",bakMapPath);
394 if (!backupXML.isEmpty())
395 // Write XML Data to disk
396 saveStringToDisk (bakMapPath,backupXML);
398 // We would have to save all actions in a tree, to keep track of
399 // possible redos after a action. Possible, but we are too lazy: forget about redos.
402 // Write the current state to disk
403 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
404 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
405 undoSet.setEntry ("/history/curStep",QString::number(curStep));
406 undoSet.setEntry (QString("/history/step-%1/undoCommand").arg(curStep),undoCommand);
407 undoSet.setEntry (QString("/history/step-%1/undoSelection").arg(curStep),undoSelection);
408 undoSet.setEntry (QString("/history/step-%1/redoCommand").arg(curStep),redoCom);
409 undoSet.setEntry (QString("/history/step-%1/redoSelection").arg(curStep),redoSelection);
410 undoSet.setEntry (QString("/history/step-%1/comment").arg(curStep),comment);
411 undoSet.setEntry (QString("/history/version"),vymVersion);
412 undoSet.writeSettings(histPath);
416 // TODO remove after testing
417 //cout << " into="<< histPath.toStdString()<<endl;
418 cout << " stepsTotal="<<stepsTotal<<
419 ", undosAvail="<<undosAvail<<
420 ", redosAvail="<<redosAvail<<
421 ", curStep="<<curStep<<endl;
422 cout << " ---------------------------"<<endl;
423 cout << " comment="<<comment.toStdString()<<endl;
424 cout << " undoCom="<<undoCommand.toStdString()<<endl;
425 cout << " undoSel="<<undoSelection.toStdString()<<endl;
426 cout << " redoCom="<<redoCom.toStdString()<<endl;
427 cout << " redoSel="<<redoSelection.toStdString()<<endl;
428 if (saveSel) cout << " saveSel="<<qPrintable (model->getSelectString(saveSel))<<endl;
429 cout << " ---------------------------"<<endl;
432 mainWindow->updateHistory (undoSet);
438 void MapEditor::saveStateChangingPart(LinkableMapObj *undoSel, LinkableMapObj* redoSel, const QString &rc, const QString &comment)
440 // save the selected part of the map, Undo will replace part of map
441 QString undoSelection="";
443 undoSelection=model->getSelectString(undoSel);
445 qWarning ("MapEditor::saveStateChangingPart no undoSel given!");
446 QString redoSelection="";
448 redoSelection=model->getSelectString(undoSel);
450 qWarning ("MapEditor::saveStateChangingPart no redoSel given!");
453 saveState (PartOfMap,
454 undoSelection, "addMapReplace (\"PATH\")",
460 void MapEditor::saveStateRemovingPart(LinkableMapObj *redoSel, const QString &comment)
464 qWarning ("MapEditor::saveStateRemovingPart no redoSel given!");
467 QString undoSelection=model->getSelectString (redoSel->getParObj());
468 QString redoSelection=model->getSelectString(redoSel);
469 if (typeid(*redoSel) == typeid(BranchObj) )
471 // save the selected branch of the map, Undo will insert part of map
472 saveState (PartOfMap,
473 undoSelection, QString("addMapInsert (\"PATH\",%1)").arg(((BranchObj*)redoSel)->getNum()),
474 redoSelection, "delete ()",
481 void MapEditor::saveState(LinkableMapObj *undoSel, const QString &uc, LinkableMapObj *redoSel, const QString &rc, const QString &comment)
483 // "Normal" savestate: save commands, selections and comment
484 // so just save commands for undo and redo
485 // and use current selection
487 QString redoSelection="";
488 if (redoSel) redoSelection=model->getSelectString(redoSel);
489 QString undoSelection="";
490 if (undoSel) undoSelection=model->getSelectString(undoSel);
492 saveState (UndoCommand,
499 void MapEditor::saveState(const QString &undoSel, const QString &uc, const QString &redoSel, const QString &rc, const QString &comment)
501 // "Normal" savestate: save commands, selections and comment
502 // so just save commands for undo and redo
503 // and use current selection
504 saveState (UndoCommand,
511 void MapEditor::saveState(const QString &uc, const QString &rc, const QString &comment)
513 // "Normal" savestate applied to model (no selection needed):
514 // save commands and comment
515 saveState (UndoCommand,
523 void MapEditor::parseAtom(const QString &atom)
525 BranchObj *selb=xelection.getBranch();
531 // Split string s into command and parameters
532 parser.parseAtom (atom);
533 QString com=parser.getCommand();
536 /////////////////////////////////////////////////////////////////////
537 if (com=="addBranch")
539 if (xelection.isEmpty())
541 parser.setError (Aborted,"Nothing selected");
544 parser.setError (Aborted,"Type of selection is not a branch");
549 if (parser.checkParCount(pl))
551 if (parser.parCount()==0)
555 n=parser.parInt (ok,0);
556 if (ok ) addNewBranch (n);
560 /////////////////////////////////////////////////////////////////////
561 } else if (com=="addBranchBefore")
563 if (xelection.isEmpty())
565 parser.setError (Aborted,"Nothing selected");
568 parser.setError (Aborted,"Type of selection is not a branch");
571 if (parser.parCount()==0)
573 addNewBranchBefore ();
576 /////////////////////////////////////////////////////////////////////
577 } else if (com==QString("addMapCenter"))
579 if (parser.checkParCount(2))
581 x=parser.parDouble (ok,0);
584 y=parser.parDouble (ok,1);
585 if (ok) model->addMapCenter (QPointF(x,y));
588 /////////////////////////////////////////////////////////////////////
589 } else if (com==QString("addMapReplace"))
591 if (xelection.isEmpty())
593 parser.setError (Aborted,"Nothing selected");
596 parser.setError (Aborted,"Type of selection is not a branch");
597 } else if (parser.checkParCount(1))
599 //s=parser.parString (ok,0); // selection
600 t=parser.parString (ok,0); // path to map
601 if (QDir::isRelativePath(t)) t=(tmpMapDir + "/"+t);
602 addMapReplaceInt(model->getSelectString(selb),t);
604 /////////////////////////////////////////////////////////////////////
605 } else if (com==QString("addMapInsert"))
607 if (xelection.isEmpty())
609 parser.setError (Aborted,"Nothing selected");
612 parser.setError (Aborted,"Type of selection is not a branch");
615 if (parser.checkParCount(2))
617 t=parser.parString (ok,0); // path to map
618 n=parser.parInt(ok,1); // position
619 if (QDir::isRelativePath(t)) t=(tmpMapDir + "/"+t);
620 addMapInsertInt(t,n);
623 /////////////////////////////////////////////////////////////////////
624 } else if (com=="clearFlags")
626 if (xelection.isEmpty() )
628 parser.setError (Aborted,"Nothing selected");
631 parser.setError (Aborted,"Type of selection is not a branch");
632 } else if (parser.checkParCount(0))
634 selb->clearStandardFlags();
635 selb->updateFlagsToolbar();
637 /////////////////////////////////////////////////////////////////////
638 } else if (com=="colorBranch")
640 if (xelection.isEmpty())
642 parser.setError (Aborted,"Nothing selected");
645 parser.setError (Aborted,"Type of selection is not a branch");
646 } else if (parser.checkParCount(1))
648 QColor c=parser.parColor (ok,0);
649 if (ok) colorBranch (c);
651 /////////////////////////////////////////////////////////////////////
652 } else if (com=="colorSubtree")
654 if (xelection.isEmpty())
656 parser.setError (Aborted,"Nothing selected");
659 parser.setError (Aborted,"Type of selection is not a branch");
660 } else if (parser.checkParCount(1))
662 QColor c=parser.parColor (ok,0);
663 if (ok) colorSubtree (c);
665 /////////////////////////////////////////////////////////////////////
666 } else if (com=="copy")
668 if (xelection.isEmpty())
670 parser.setError (Aborted,"Nothing selected");
673 parser.setError (Aborted,"Type of selection is not a branch");
674 } else if (parser.checkParCount(0))
676 //FIXME missing action for copy
678 /////////////////////////////////////////////////////////////////////
679 } else if (com=="cut")
681 if (xelection.isEmpty())
683 parser.setError (Aborted,"Nothing selected");
684 } else if ( xelection.type()!=Selection::Branch &&
685 xelection.type()!=Selection::MapCenter &&
686 xelection.type()!=Selection::FloatImage )
688 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
689 } else if (parser.checkParCount(0))
693 /////////////////////////////////////////////////////////////////////
694 } else if (com=="delete")
696 if (xelection.isEmpty())
698 parser.setError (Aborted,"Nothing selected");
700 /*else if (xelection.type() != Selection::Branch && xelection.type() != Selection::FloatImage )
702 parser.setError (Aborted,"Type of selection is wrong.");
705 else if (parser.checkParCount(0))
709 /////////////////////////////////////////////////////////////////////
710 } else if (com=="deleteKeepChilds")
712 if (xelection.isEmpty())
714 parser.setError (Aborted,"Nothing selected");
717 parser.setError (Aborted,"Type of selection is not a branch");
718 } else if (parser.checkParCount(0))
722 /////////////////////////////////////////////////////////////////////
723 } else if (com=="deleteChilds")
725 if (xelection.isEmpty())
727 parser.setError (Aborted,"Nothing selected");
730 parser.setError (Aborted,"Type of selection is not a branch");
731 } else if (parser.checkParCount(0))
735 /////////////////////////////////////////////////////////////////////
736 } else if (com=="exportASCII")
740 if (parser.parCount()>=1)
741 // Hey, we even have a filename
742 fname=parser.parString(ok,0);
745 parser.setError (Aborted,"Could not read filename");
748 exportASCII (fname,false);
750 /////////////////////////////////////////////////////////////////////
751 } else if (com=="exportImage")
755 if (parser.parCount()>=2)
756 // Hey, we even have a filename
757 fname=parser.parString(ok,0);
760 parser.setError (Aborted,"Could not read filename");
763 QString format="PNG";
764 if (parser.parCount()>=2)
766 format=parser.parString(ok,1);
768 exportImage (fname,false,format);
770 /////////////////////////////////////////////////////////////////////
771 } else if (com=="exportXHTML")
775 if (parser.parCount()>=2)
776 // Hey, we even have a filename
777 fname=parser.parString(ok,1);
780 parser.setError (Aborted,"Could not read filename");
783 exportXHTML (fname,false);
785 /////////////////////////////////////////////////////////////////////
786 } else if (com=="exportXML")
790 if (parser.parCount()>=2)
791 // Hey, we even have a filename
792 fname=parser.parString(ok,1);
795 parser.setError (Aborted,"Could not read filename");
798 exportXML (fname,false);
800 /////////////////////////////////////////////////////////////////////
801 } else if (com=="importDir")
803 if (xelection.isEmpty())
805 parser.setError (Aborted,"Nothing selected");
808 parser.setError (Aborted,"Type of selection is not a branch");
809 } else if (parser.checkParCount(1))
811 s=parser.parString(ok,0);
812 if (ok) importDirInt(s);
814 /////////////////////////////////////////////////////////////////////
815 } else if (com=="linkTo")
817 if (xelection.isEmpty())
819 parser.setError (Aborted,"Nothing selected");
822 if (parser.checkParCount(4))
824 // 0 selectstring of parent
825 // 1 num in parent (for branches)
826 // 2,3 x,y of mainbranch or mapcenter
827 s=parser.parString(ok,0);
828 LinkableMapObj *dst=model->findObjBySelect (s);
831 if (typeid(*dst) == typeid(BranchObj) )
833 // Get number in parent
834 n=parser.parInt (ok,1);
837 selb->linkTo ((BranchObj*)(dst),n);
840 } else if (typeid(*dst) == typeid(MapCenterObj) )
842 selb->linkTo ((BranchObj*)(dst),-1);
843 // Get coordinates of mainbranch
844 x=parser.parDouble(ok,2);
847 y=parser.parDouble(ok,3);
857 } else if ( xelection.type() == Selection::FloatImage)
859 if (parser.checkParCount(1))
861 // 0 selectstring of parent
862 s=parser.parString(ok,0);
863 LinkableMapObj *dst=model->findObjBySelect (s);
866 if (typeid(*dst) == typeid(BranchObj) ||
867 typeid(*dst) == typeid(MapCenterObj))
868 linkTo (model->getSelectString(dst));
870 parser.setError (Aborted,"Destination is not a branch");
873 parser.setError (Aborted,"Type of selection is not a floatimage or branch");
874 /////////////////////////////////////////////////////////////////////
875 } else if (com=="loadImage")
877 if (xelection.isEmpty())
879 parser.setError (Aborted,"Nothing selected");
882 parser.setError (Aborted,"Type of selection is not a branch");
883 } else if (parser.checkParCount(1))
885 s=parser.parString(ok,0);
886 if (ok) loadFloatImageInt (s);
888 /////////////////////////////////////////////////////////////////////
889 } else if (com=="moveBranchUp")
891 if (xelection.isEmpty() )
893 parser.setError (Aborted,"Nothing selected");
896 parser.setError (Aborted,"Type of selection is not a branch");
897 } else if (parser.checkParCount(0))
901 /////////////////////////////////////////////////////////////////////
902 } else if (com=="moveBranchDown")
904 if (xelection.isEmpty() )
906 parser.setError (Aborted,"Nothing selected");
909 parser.setError (Aborted,"Type of selection is not a branch");
910 } else if (parser.checkParCount(0))
914 /////////////////////////////////////////////////////////////////////
915 } else if (com=="move")
917 if (xelection.isEmpty() )
919 parser.setError (Aborted,"Nothing selected");
920 } else if ( xelection.type()!=Selection::Branch &&
921 xelection.type()!=Selection::MapCenter &&
922 xelection.type()!=Selection::FloatImage )
924 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
925 } else if (parser.checkParCount(2))
927 x=parser.parDouble (ok,0);
930 y=parser.parDouble (ok,1);
934 /////////////////////////////////////////////////////////////////////
935 } else if (com=="moveRel")
937 if (xelection.isEmpty() )
939 parser.setError (Aborted,"Nothing selected");
940 } else if ( xelection.type()!=Selection::Branch &&
941 xelection.type()!=Selection::MapCenter &&
942 xelection.type()!=Selection::FloatImage )
944 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
945 } else if (parser.checkParCount(2))
947 x=parser.parDouble (ok,0);
950 y=parser.parDouble (ok,1);
951 if (ok) moveRel (x,y);
954 /////////////////////////////////////////////////////////////////////
955 } else if (com=="nop")
957 /////////////////////////////////////////////////////////////////////
958 } else if (com=="paste")
960 if (xelection.isEmpty() )
962 parser.setError (Aborted,"Nothing selected");
965 parser.setError (Aborted,"Type of selection is not a branch");
966 } else if (parser.checkParCount(1))
968 n=parser.parInt (ok,0);
969 if (ok) pasteNoSave(n);
971 /////////////////////////////////////////////////////////////////////
972 } else if (com=="qa")
974 if (xelection.isEmpty() )
976 parser.setError (Aborted,"Nothing selected");
979 parser.setError (Aborted,"Type of selection is not a branch");
980 } else if (parser.checkParCount(4))
983 c=parser.parString (ok,0);
986 parser.setError (Aborted,"No comment given");
989 s=parser.parString (ok,1);
992 parser.setError (Aborted,"First parameter is not a string");
995 t=parser.parString (ok,2);
998 parser.setError (Aborted,"Condition is not a string");
1001 u=parser.parString (ok,3);
1004 parser.setError (Aborted,"Third parameter is not a string");
1009 parser.setError (Aborted,"Unknown type: "+s);
1014 parser.setError (Aborted,"Unknown operator: "+t);
1019 parser.setError (Aborted,"Type of selection is not a branch");
1022 if (selb->getHeading() == u)
1024 cout << "PASSED: " << qPrintable (c) << endl;
1027 cout << "FAILED: " << qPrintable (c) << endl;
1037 /////////////////////////////////////////////////////////////////////
1038 } else if (com=="saveImage")
1040 FloatImageObj *fio=xelection.getFloatImage();
1043 parser.setError (Aborted,"Type of selection is not an image");
1044 } else if (parser.checkParCount(2))
1046 s=parser.parString(ok,0);
1049 t=parser.parString(ok,1);
1050 if (ok) saveFloatImageInt (fio,t,s);
1053 /////////////////////////////////////////////////////////////////////
1054 } else if (com=="scroll")
1056 if (xelection.isEmpty() )
1058 parser.setError (Aborted,"Nothing selected");
1061 parser.setError (Aborted,"Type of selection is not a branch");
1062 } else if (parser.checkParCount(0))
1064 if (!scrollBranch (selb))
1065 parser.setError (Aborted,"Could not scroll branch");
1067 /////////////////////////////////////////////////////////////////////
1068 } else if (com=="select")
1070 if (parser.checkParCount(1))
1072 s=parser.parString(ok,0);
1075 /////////////////////////////////////////////////////////////////////
1076 } else if (com=="selectLastBranch")
1078 if (xelection.isEmpty() )
1080 parser.setError (Aborted,"Nothing selected");
1083 parser.setError (Aborted,"Type of selection is not a branch");
1084 } else if (parser.checkParCount(0))
1086 BranchObj *bo=selb->getLastBranch();
1088 parser.setError (Aborted,"Could not select last branch");
1092 /////////////////////////////////////////////////////////////////////
1093 } else if (com=="selectLastImage")
1095 if (xelection.isEmpty() )
1097 parser.setError (Aborted,"Nothing selected");
1100 parser.setError (Aborted,"Type of selection is not a branch");
1101 } else if (parser.checkParCount(0))
1103 FloatImageObj *fio=selb->getLastFloatImage();
1105 parser.setError (Aborted,"Could not select last image");
1109 /////////////////////////////////////////////////////////////////////
1110 } else if (com=="selectLatestAdded")
1112 if (latestSelection.isEmpty() )
1114 parser.setError (Aborted,"No latest added object");
1117 if (!select (latestSelection))
1118 parser.setError (Aborted,"Could not select latest added object "+latestSelection);
1120 /////////////////////////////////////////////////////////////////////
1121 } else if (com=="setFrameType")
1123 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
1125 parser.setError (Aborted,"Type of selection does not allow setting frame type");
1127 else if (parser.checkParCount(1))
1129 s=parser.parString(ok,0);
1130 if (ok) setFrameType (s);
1132 /////////////////////////////////////////////////////////////////////
1133 } else if (com=="setFramePenColor")
1135 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
1137 parser.setError (Aborted,"Type of selection does not allow setting of pen color");
1139 else if (parser.checkParCount(1))
1141 QColor c=parser.parColor(ok,0);
1142 if (ok) setFramePenColor (c);
1144 /////////////////////////////////////////////////////////////////////
1145 } else if (com=="setFrameBrushColor")
1147 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
1149 parser.setError (Aborted,"Type of selection does not allow setting brush color");
1151 else if (parser.checkParCount(1))
1153 QColor c=parser.parColor(ok,0);
1154 if (ok) setFrameBrushColor (c);
1156 /////////////////////////////////////////////////////////////////////
1157 } else if (com=="setFramePadding")
1159 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
1161 parser.setError (Aborted,"Type of selection does not allow setting frame padding");
1163 else if (parser.checkParCount(1))
1165 n=parser.parInt(ok,0);
1166 if (ok) setFramePadding(n);
1168 /////////////////////////////////////////////////////////////////////
1169 } else if (com=="setFrameBorderWidth")
1171 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
1173 parser.setError (Aborted,"Type of selection does not allow setting frame border width");
1175 else if (parser.checkParCount(1))
1177 n=parser.parInt(ok,0);
1178 if (ok) setFrameBorderWidth (n);
1180 /////////////////////////////////////////////////////////////////////
1181 } else if (com=="setMapAuthor")
1183 if (parser.checkParCount(1))
1185 s=parser.parString(ok,0);
1186 if (ok) setMapAuthor (s);
1188 /////////////////////////////////////////////////////////////////////
1189 } else if (com=="setMapComment")
1191 if (parser.checkParCount(1))
1193 s=parser.parString(ok,0);
1194 if (ok) setMapComment(s);
1196 /////////////////////////////////////////////////////////////////////
1197 } else if (com=="setMapBackgroundColor")
1199 if (xelection.isEmpty() )
1201 parser.setError (Aborted,"Nothing selected");
1202 } else if (! xelection.getBranch() )
1204 parser.setError (Aborted,"Type of selection is not a branch");
1205 } else if (parser.checkParCount(1))
1207 QColor c=parser.parColor (ok,0);
1208 if (ok) setMapBackgroundColor (c);
1210 /////////////////////////////////////////////////////////////////////
1211 } else if (com=="setMapDefLinkColor")
1213 if (xelection.isEmpty() )
1215 parser.setError (Aborted,"Nothing selected");
1218 parser.setError (Aborted,"Type of selection is not a branch");
1219 } else if (parser.checkParCount(1))
1221 QColor c=parser.parColor (ok,0);
1222 if (ok) setMapDefLinkColor (c);
1224 /////////////////////////////////////////////////////////////////////
1225 } else if (com=="setMapLinkStyle")
1227 if (parser.checkParCount(1))
1229 s=parser.parString (ok,0);
1230 if (ok) setMapLinkStyle(s);
1232 /////////////////////////////////////////////////////////////////////
1233 } else if (com=="setHeading")
1235 if (xelection.isEmpty() )
1237 parser.setError (Aborted,"Nothing selected");
1240 parser.setError (Aborted,"Type of selection is not a branch");
1241 } else if (parser.checkParCount(1))
1243 s=parser.parString (ok,0);
1247 /////////////////////////////////////////////////////////////////////
1248 } else if (com=="setHideExport")
1250 if (xelection.isEmpty() )
1252 parser.setError (Aborted,"Nothing selected");
1253 } else if (xelection.type()!=Selection::Branch && xelection.type() != Selection::MapCenter &&xelection.type()!=Selection::FloatImage)
1255 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
1256 } else if (parser.checkParCount(1))
1258 b=parser.parBool(ok,0);
1259 if (ok) setHideExport (b);
1261 /////////////////////////////////////////////////////////////////////
1262 } else if (com=="setIncludeImagesHorizontally")
1264 if (xelection.isEmpty() )
1266 parser.setError (Aborted,"Nothing selected");
1269 parser.setError (Aborted,"Type of selection is not a branch");
1270 } else if (parser.checkParCount(1))
1272 b=parser.parBool(ok,0);
1273 if (ok) setIncludeImagesHor(b);
1275 /////////////////////////////////////////////////////////////////////
1276 } else if (com=="setIncludeImagesVertically")
1278 if (xelection.isEmpty() )
1280 parser.setError (Aborted,"Nothing selected");
1283 parser.setError (Aborted,"Type of selection is not a branch");
1284 } else if (parser.checkParCount(1))
1286 b=parser.parBool(ok,0);
1287 if (ok) setIncludeImagesVer(b);
1289 /////////////////////////////////////////////////////////////////////
1290 } else if (com=="setHideLinkUnselected")
1292 if (xelection.isEmpty() )
1294 parser.setError (Aborted,"Nothing selected");
1295 } else if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
1297 parser.setError (Aborted,"Type of selection does not allow hiding the link");
1298 } else if (parser.checkParCount(1))
1300 b=parser.parBool(ok,0);
1301 if (ok) setHideLinkUnselected(b);
1303 /////////////////////////////////////////////////////////////////////
1304 } else if (com=="setSelectionColor")
1306 if (parser.checkParCount(1))
1308 QColor c=parser.parColor (ok,0);
1309 if (ok) setSelectionColorInt (c);
1311 /////////////////////////////////////////////////////////////////////
1312 } else if (com=="setURL")
1314 if (xelection.isEmpty() )
1316 parser.setError (Aborted,"Nothing selected");
1319 parser.setError (Aborted,"Type of selection is not a branch");
1320 } else if (parser.checkParCount(1))
1322 s=parser.parString (ok,0);
1325 /////////////////////////////////////////////////////////////////////
1326 } else if (com=="setVymLink")
1328 if (xelection.isEmpty() )
1330 parser.setError (Aborted,"Nothing selected");
1333 parser.setError (Aborted,"Type of selection is not a branch");
1334 } else if (parser.checkParCount(1))
1336 s=parser.parString (ok,0);
1337 if (ok) setVymLinkInt(s);
1340 /////////////////////////////////////////////////////////////////////
1341 else if (com=="setFlag")
1343 if (xelection.isEmpty() )
1345 parser.setError (Aborted,"Nothing selected");
1348 parser.setError (Aborted,"Type of selection is not a branch");
1349 } else if (parser.checkParCount(1))
1351 s=parser.parString(ok,0);
1354 selb->activateStandardFlag(s);
1355 selb->updateFlagsToolbar();
1358 /////////////////////////////////////////////////////////////////////
1359 } else if (com=="setFrameType")
1361 if (xelection.isEmpty() )
1363 parser.setError (Aborted,"Nothing selected");
1366 parser.setError (Aborted,"Type of selection is not a branch");
1367 } else if (parser.checkParCount(1))
1369 s=parser.parString(ok,0);
1373 /////////////////////////////////////////////////////////////////////
1374 } else if (com=="sortChildren")
1376 if (xelection.isEmpty() )
1378 parser.setError (Aborted,"Nothing selected");
1381 parser.setError (Aborted,"Type of selection is not a branch");
1382 } else if (parser.checkParCount(0))
1386 /////////////////////////////////////////////////////////////////////
1387 } else if (com=="toggleFlag")
1389 if (xelection.isEmpty() )
1391 parser.setError (Aborted,"Nothing selected");
1394 parser.setError (Aborted,"Type of selection is not a branch");
1395 } else if (parser.checkParCount(1))
1397 s=parser.parString(ok,0);
1400 selb->toggleStandardFlag(s);
1401 selb->updateFlagsToolbar();
1404 /////////////////////////////////////////////////////////////////////
1405 } else if (com=="unscroll")
1407 if (xelection.isEmpty() )
1409 parser.setError (Aborted,"Nothing selected");
1412 parser.setError (Aborted,"Type of selection is not a branch");
1413 } else if (parser.checkParCount(0))
1415 if (!unscrollBranch (selb))
1416 parser.setError (Aborted,"Could not unscroll branch");
1418 /////////////////////////////////////////////////////////////////////
1419 } else if (com=="unscrollChilds")
1421 if (xelection.isEmpty() )
1423 parser.setError (Aborted,"Nothing selected");
1426 parser.setError (Aborted,"Type of selection is not a branch");
1427 } else if (parser.checkParCount(0))
1431 /////////////////////////////////////////////////////////////////////
1432 } else if (com=="unsetFlag")
1434 if (xelection.isEmpty() )
1436 parser.setError (Aborted,"Nothing selected");
1439 parser.setError (Aborted,"Type of selection is not a branch");
1440 } else if (parser.checkParCount(1))
1442 s=parser.parString(ok,0);
1445 selb->deactivateStandardFlag(s);
1446 selb->updateFlagsToolbar();
1450 parser.setError (Aborted,"Unknown command");
1453 if (parser.errorLevel()==NoError)
1455 // setChanged(); FIXME should not be called e.g. for export?!
1456 model->reposition();
1460 // TODO Error handling
1461 qWarning("MapEditor::parseAtom: Error!");
1462 qWarning(parser.errorMessage());
1466 void MapEditor::runScript (QString script)
1468 parser.setScript (script);
1470 while (parser.next() )
1471 parseAtom(parser.getAtom());
1474 bool MapEditor::isDefault()
1479 bool MapEditor::hasChanged()
1484 void MapEditor::setChanged()
1487 autosaveTimer->start(settings.value("/mapeditor/autosave/ms/",300000).toInt());
1495 void MapEditor::closeMap()
1497 // Unselect before disabling the toolbar actions
1498 if (!xelection.isEmpty() ) xelection.unselect();
1506 void MapEditor::setFilePath(QString fpath, QString destname)
1508 if (fpath.isEmpty() || fpath=="")
1515 filePath=fpath; // becomes absolute path
1516 fileName=fpath; // gets stripped of path
1517 destPath=destname; // needed for vymlinks and during load to reset fileChangedTime
1519 // If fpath is not an absolute path, complete it
1520 filePath=QDir(fpath).absPath();
1521 fileDir=filePath.left (1+filePath.findRev ("/"));
1523 // Set short name, too. Search from behind:
1524 int i=fileName.findRev("/");
1525 if (i>=0) fileName=fileName.remove (0,i+1);
1527 // Forget the .vym (or .xml) for name of map
1528 mapName=fileName.left(fileName.findRev(".",-1,true) );
1532 void MapEditor::setFilePath(QString fpath)
1534 setFilePath (fpath,fpath);
1537 QString MapEditor::getFilePath()
1542 QString MapEditor::getFileName()
1547 QString MapEditor::getMapName()
1552 QString MapEditor::getDestPath()
1557 ErrorCode MapEditor::load (QString fname, const LoadMode &lmode, const FileType &ftype)
1559 ErrorCode err=success;
1561 parseBaseHandler *handler;
1565 case VymMap: handler=new parseVYMHandler; break;
1566 case FreemindMap : handler=new parseFreemindHandler; break;
1568 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
1569 "Unknown FileType in MapEditor::load()");
1575 model->setMapEditor(this);
1576 // (map state is set later at end of load...)
1579 BranchObj *bo=xelection.getBranch();
1580 if (!bo) return aborted;
1581 if (lmode==ImportAdd)
1582 saveStateChangingPart(
1585 QString("addMapInsert (%1)").arg(fname),
1586 QString("Add map %1 to %2").arg(fname).arg(getName(bo)));
1588 saveStateChangingPart(
1591 QString("addMapReplace(%1)").arg(fname),
1592 QString("Add map %1 to %2").arg(fname).arg(getName(bo)));
1596 // Create temporary directory for packing
1598 QString tmpZipDir=makeTmpDir (ok,"vym-pack");
1601 QMessageBox::critical( 0, tr( "Critical Load Error" ),
1602 tr("Couldn't create temporary directory before load\n"));
1606 // Try to unzip file
1607 err=unzipDir (tmpZipDir,fname);
1617 // Look for mapname.xml
1618 xmlfile= fname.left(fname.findRev(".",-1,true));
1619 xmlfile=xmlfile.section( '/', -1 );
1620 QFile mfile( tmpZipDir + "/" + xmlfile + ".xml");
1621 if (!mfile.exists() )
1623 // mapname.xml does not exist, well,
1624 // maybe someone renamed the mapname.vym file...
1625 // Try to find any .xml in the toplevel
1626 // directory of the .vym file
1627 QStringList flist=QDir (tmpZipDir).entryList("*.xml");
1628 if (flist.count()==1)
1630 // Only one entry, take this one
1631 xmlfile=tmpZipDir + "/"+flist.first();
1634 for ( QStringList::Iterator it = flist.begin(); it != flist.end(); ++it )
1635 *it=tmpZipDir + "/" + *it;
1636 // TODO Multiple entries, load all (but only the first one into this ME)
1637 //mainWindow->fileLoadFromTmp (flist);
1638 //returnCode=1; // Silently forget this attempt to load
1639 qWarning ("MainWindow::load (fn) multimap found...");
1642 if (flist.isEmpty() )
1644 QMessageBox::critical( 0, tr( "Critical Load Error" ),
1645 tr("Couldn't find a map (*.xml) in .vym archive.\n"));
1648 } //file doesn't exist
1650 xmlfile=mfile.name();
1653 QFile file( xmlfile);
1655 // I am paranoid: file should exist anyway
1656 // according to check in mainwindow.
1657 if (!file.exists() )
1659 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
1660 tr(QString("Couldn't open map %1").arg(file.name())));
1664 bool blockSaveStateOrg=blockSaveState;
1665 blockReposition=true;
1666 blockSaveState=true;
1667 QXmlInputSource source( file);
1668 QXmlSimpleReader reader;
1669 reader.setContentHandler( handler );
1670 reader.setErrorHandler( handler );
1671 handler->setModel ( model);
1674 // We need to set the tmpDir in order to load files with rel. path
1679 tmpdir=fname.left(fname.findRev("/",-1));
1680 handler->setTmpDir (tmpdir);
1681 handler->setInputFile (file.name());
1682 handler->setLoadMode (lmode);
1683 bool ok = reader.parse( source );
1684 blockReposition=false;
1685 blockSaveState=blockSaveStateOrg;
1689 model->reposition(); // FIXME reposition the view instead...
1696 autosaveTimer->stop();
1699 // Reset timestamp to check for later updates of file
1700 fileChangedTime=QFileInfo (destPath).lastModified();
1703 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
1704 tr( handler->errorProtocol() ) );
1706 // Still return "success": the map maybe at least
1707 // partially read by the parser
1712 removeDir (QDir(tmpZipDir));
1719 ErrorCode MapEditor::save (const SaveMode &savemode)
1722 QString mapFileName;
1723 QString safeFilePath;
1725 ErrorCode err=success;
1729 mapFileName=mapName+".xml";
1731 // use name given by user, even if he chooses .doc
1732 mapFileName=fileName;
1734 // Look, if we should zip the data:
1737 QMessageBox mb( vymName,
1738 tr("The map %1\ndid not use the compressed "
1739 "vym file format.\nWriting it uncompressed will also write images \n"
1740 "and flags and thus may overwrite files in the "
1741 "given directory\n\nDo you want to write the map").arg(filePath),
1742 QMessageBox::Warning,
1743 QMessageBox::Yes | QMessageBox::Default,
1745 QMessageBox::Cancel | QMessageBox::Escape);
1746 mb.setButtonText( QMessageBox::Yes, tr("compressed (vym default)") );
1747 mb.setButtonText( QMessageBox::No, tr("uncompressed") );
1748 mb.setButtonText( QMessageBox::Cancel, tr("Cancel"));
1751 case QMessageBox::Yes:
1752 // save compressed (default file format)
1755 case QMessageBox::No:
1756 // save uncompressed
1759 case QMessageBox::Cancel:
1766 // First backup existing file, we
1767 // don't want to add to old zip archives
1771 if ( settings.value ("/mapeditor/writeBackupFile").toBool())
1773 QString backupFileName(destPath + "~");
1774 QFile backupFile(backupFileName);
1775 if (backupFile.exists() && !backupFile.remove())
1777 QMessageBox::warning(0, tr("Save Error"),
1778 tr("%1\ncould not be removed before saving").arg(backupFileName));
1780 else if (!f.rename(backupFileName))
1782 QMessageBox::warning(0, tr("Save Error"),
1783 tr("%1\ncould not be renamed before saving").arg(destPath));
1790 // Create temporary directory for packing
1792 tmpZipDir=makeTmpDir (ok,"vym-zip");
1795 QMessageBox::critical( 0, tr( "Critical Load Error" ),
1796 tr("Couldn't create temporary directory before save\n"));
1800 safeFilePath=filePath;
1801 setFilePath (tmpZipDir+"/"+ mapName+ ".xml", safeFilePath);
1804 // Create mapName and fileDir
1805 makeSubDirs (fileDir);
1808 if (savemode==CompleteMap || xelection.isEmpty())
1810 // Save complete map
1811 saveFile=saveToDir (fileDir,mapName+"-",true,QPointF(),NULL);
1814 autosaveTimer->stop();
1819 if (xelection.type()==Selection::FloatImage)
1822 saveFile=saveToDir (fileDir,mapName+"-",true,QPointF(),xelection.getBranch());
1823 // TODO take care of multiselections
1826 if (!saveStringToDisk(fileDir+mapFileName,saveFile))
1829 qWarning ("ME::saveStringToDisk failed!");
1835 if (err==success) err=zipDir (tmpZipDir,destPath);
1838 removeDir (QDir(tmpZipDir));
1840 // Restore original filepath outside of tmp zip dir
1841 setFilePath (safeFilePath);
1845 fileChangedTime=QFileInfo (destPath).lastModified();
1850 void MapEditor::print()
1854 printer = new QPrinter;
1855 printer->setColorMode (QPrinter::Color);
1856 printer->setPrinterName (settings.value("/mainwindow/printerName",printer->printerName()).toString());
1857 printer->setOutputFormat((QPrinter::OutputFormat)settings.value("/mainwindow/printerFormat",printer->outputFormat()).toInt());
1858 printer->setOutputFileName(settings.value("/mainwindow/printerFileName",printer->outputFileName()).toString());
1861 QRectF totalBBox=model->getTotalBBox();
1863 // Try to set orientation automagically
1864 // Note: Interpretation of generated postscript is amibiguous, if
1865 // there are problems with landscape mode, see
1866 // http://sdb.suse.de/de/sdb/html/jsmeix_print-cups-landscape-81.html
1868 if (totalBBox.width()>totalBBox.height())
1869 // recommend landscape
1870 printer->setOrientation (QPrinter::Landscape);
1872 // recommend portrait
1873 printer->setOrientation (QPrinter::Portrait);
1875 if ( printer->setup(this) )
1876 // returns false, if printing is canceled
1878 QPainter pp(printer);
1880 pp.setRenderHint(QPainter::Antialiasing,true);
1882 // Don't print the visualisation of selection
1883 xelection.unselect();
1885 QRectF mapRect=totalBBox;
1886 QGraphicsRectItem *frame=NULL;
1890 // Print frame around map
1891 mapRect.setRect (totalBBox.x()-10, totalBBox.y()-10,
1892 totalBBox.width()+20, totalBBox.height()+20);
1893 frame=mapScene->addRect (mapRect, QPen(Qt::black),QBrush(Qt::NoBrush));
1894 frame->setZValue(0);
1899 double paperAspect = (double)printer->width() / (double)printer->height();
1900 double mapAspect = (double)mapRect.width() / (double)mapRect.height();
1902 if (mapAspect>=paperAspect)
1904 // Fit horizontally to paper width
1905 //pp.setViewport(0,0, printer->width(),(int)(printer->width()/mapAspect) );
1906 viewBottom=(int)(printer->width()/mapAspect);
1909 // Fit vertically to paper height
1910 //pp.setViewport(0,0,(int)(printer->height()*mapAspect),printer->height());
1911 viewBottom=printer->height();
1916 // Print footer below map
1918 font.setPointSize(10);
1920 QRectF footerBox(0,viewBottom,printer->width(),15);
1921 pp.drawText ( footerBox,Qt::AlignLeft,"VYM - " +fileName);
1922 pp.drawText ( footerBox, Qt::AlignRight, QDate::currentDate().toString(Qt::TextDate));
1926 QRectF (0,0,printer->width(),printer->height()-15),
1927 QRectF(mapRect.x(),mapRect.y(),mapRect.width(),mapRect.height())
1930 // Viewport has paper dimension
1931 if (frame) delete (frame);
1933 // Restore selection
1934 xelection.reselect();
1936 // Save settings in vymrc
1937 settings.writeEntry("/mainwindow/printerName",printer->printerName());
1938 settings.writeEntry("/mainwindow/printerFormat",printer->outputFormat());
1939 settings.writeEntry("/mainwindow/printerFileName",printer->outputFileName());
1943 void MapEditor::setAntiAlias (bool b)
1945 setRenderHint(QPainter::Antialiasing,b);
1948 void MapEditor::setSmoothPixmap(bool b)
1950 setRenderHint(QPainter::SmoothPixmapTransform,b);
1953 QPixmap MapEditor::getPixmap()
1955 QRectF mapRect=model->getTotalBBox();
1956 QPixmap pix((int)mapRect.width()+2,(int)mapRect.height()+1);
1959 pp.setRenderHints(renderHints());
1961 // Don't print the visualisation of selection
1962 xelection.unselect();
1964 mapScene->render ( &pp,
1965 QRectF(0,0,mapRect.width()+2,mapRect.height()+2),
1966 QRectF(mapRect.x(),mapRect.y(),mapRect.width(),mapRect.height() ));
1968 // Restore selection
1969 xelection.reselect();
1974 void MapEditor::setHideTmpMode (HideTmpMode mode)
1977 model->setHideTmp (hidemode);
1978 model->reposition();
1982 HideTmpMode MapEditor::getHideTmpMode()
1987 void MapEditor::setExportMode (bool b)
1989 // should be called before and after exports
1990 // depending on the settings
1991 if (b && settings.value("/export/useHideExport","true")=="true")
1992 setHideTmpMode (HideExport);
1994 setHideTmpMode (HideNone);
1997 void MapEditor::exportASCII(QString fname,bool askName)
2000 ex.setModel (model);
2002 ex.setFile (mapName+".txt");
2008 //ex.addFilter ("TXT (*.txt)");
2009 ex.setDir(lastImageDir);
2010 //ex.setCaption(vymName+ " -" +tr("Export as ASCII")+" "+tr("(still experimental)"));
2015 setExportMode(true);
2017 setExportMode(false);
2021 void MapEditor::exportImage(QString fname, bool askName, QString format)
2025 fname=mapName+".png";
2032 QFileDialog *fd=new QFileDialog (this);
2033 fd->setCaption (tr("Export map as image"));
2034 fd->setDirectory (lastImageDir);
2035 fd->setFileMode(QFileDialog::AnyFile);
2036 fd->setFilters (imageIO.getFilters() );
2039 fl=fd->selectedFiles();
2041 format=imageIO.getType(fd->selectedFilter());
2045 setExportMode (true);
2046 QPixmap pix (getPixmap());
2047 pix.save(fname, format);
2048 setExportMode (false);
2051 void MapEditor::exportOOPresentation(const QString &fn, const QString &cf)
2055 ex.setModel (model);
2056 if (ex.setConfigFile(cf))
2058 setExportMode (true);
2059 ex.exportPresentation();
2060 setExportMode (false);
2064 void MapEditor::exportXHTML (const QString &dir, bool askForName)
2066 ExportXHTMLDialog dia(this);
2067 dia.setFilePath (filePath );
2068 dia.setMapName (mapName );
2070 if (dir!="") dia.setDir (dir);
2076 if (dia.exec()!=QDialog::Accepted)
2080 QDir d (dia.getDir());
2081 // Check, if warnings should be used before overwriting
2082 // the output directory
2083 if (d.exists() && d.count()>0)
2086 warn.showCancelButton (true);
2087 warn.setText(QString(
2088 "The directory %1 is not empty.\n"
2089 "Do you risk to overwrite some of its contents?").arg(d.path() ));
2090 warn.setCaption("Warning: Directory not empty");
2091 warn.setShowAgainName("mainwindow/overwrite-dir-xhtml");
2093 if (warn.exec()!=QDialog::Accepted) ok=false;
2100 exportXML (dia.getDir(),false );
2101 dia.doExport(mapName );
2102 //if (dia.hasChanged()) setChanged();
2106 void MapEditor::exportXML(QString dir, bool askForName)
2110 dir=browseDirectory(this,tr("Export XML to directory"));
2111 if (dir =="" && !reallyWriteDirectory(dir) )
2115 // Hide stuff during export, if settings want this
2116 setExportMode (true);
2118 // Create subdirectories
2121 // write to directory
2122 QString saveFile=saveToDir (dir,mapName+"-",true,model->getTotalBBox().topLeft() ,NULL);
2125 file.setName ( dir + "/"+mapName+".xml");
2126 if ( !file.open( QIODevice::WriteOnly ) )
2128 // This should neverever happen
2129 QMessageBox::critical (0,tr("Critical Export Error"),tr("MapEditor::exportXML couldn't open %1").arg(file.name()));
2133 // Write it finally, and write in UTF8, no matter what
2134 QTextStream ts( &file );
2135 ts.setEncoding (QTextStream::UnicodeUTF8);
2139 // Now write image, too
2140 exportImage (dir+"/images/"+mapName+".png",false,"PNG");
2142 setExportMode (false);
2145 void MapEditor::clear()
2147 xelection.unselect();
2151 void MapEditor::copy()
2153 LinkableMapObj *sel=xelection.single();
2156 if (redosAvail == 0)
2159 QString s=model->getSelectString(sel);
2160 saveState (PartOfMap, s, "nop ()", s, "copy ()","Copy selection to clipboard",sel );
2161 curClipboard=curStep;
2164 // Copy also to global clipboard, because we are at last step in history
2165 QString bakMapName(QString("history-%1").arg(curStep));
2166 QString bakMapDir(tmpMapDir +"/"+bakMapName);
2167 copyDir (bakMapDir,clipboardDir );
2169 clipboardEmpty=false;
2174 void MapEditor::redo()
2176 // Can we undo at all?
2177 if (redosAvail<1) return;
2179 bool blockSaveStateOrg=blockSaveState;
2180 blockSaveState=true;
2184 if (undosAvail<stepsTotal) undosAvail++;
2186 if (curStep>stepsTotal) curStep=1;
2187 QString undoCommand= undoSet.readEntry (QString("/history/step-%1/undoCommand").arg(curStep));
2188 QString undoSelection=undoSet.readEntry (QString("/history/step-%1/undoSelection").arg(curStep));
2189 QString redoCommand= undoSet.readEntry (QString("/history/step-%1/redoCommand").arg(curStep));
2190 QString redoSelection=undoSet.readEntry (QString("/history/step-%1/redoSelection").arg(curStep));
2191 QString comment=undoSet.readEntry (QString("/history/step-%1/comment").arg(curStep));
2192 QString version=undoSet.readEntry ("/history/version");
2194 /* TODO Maybe check for version, if we save the history
2195 if (!checkVersion(version))
2196 QMessageBox::warning(0,tr("Warning"),
2197 tr("Version %1 of saved undo/redo data\ndoes not match current vym version %2.").arg(version).arg(vymVersion));
2200 // Find out current undo directory
2201 QString bakMapDir(QString(tmpMapDir+"/undo-%1").arg(curStep));
2205 cout << "ME::redo() begin\n";
2206 cout << " undosAvail="<<undosAvail<<endl;
2207 cout << " redosAvail="<<redosAvail<<endl;
2208 cout << " curStep="<<curStep<<endl;
2209 cout << " ---------------------------"<<endl;
2210 cout << " comment="<<comment.toStdString()<<endl;
2211 cout << " undoCom="<<undoCommand.toStdString()<<endl;
2212 cout << " undoSel="<<undoSelection.toStdString()<<endl;
2213 cout << " redoCom="<<redoCommand.toStdString()<<endl;
2214 cout << " redoSel="<<redoSelection.toStdString()<<endl;
2215 cout << " ---------------------------"<<endl<<endl;
2218 // select object before redo
2219 if (!redoSelection.isEmpty())
2220 select (redoSelection);
2223 parseAtom (redoCommand);
2224 model->reposition();
2226 blockSaveState=blockSaveStateOrg;
2228 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
2229 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
2230 undoSet.setEntry ("/history/curStep",QString::number(curStep));
2231 undoSet.writeSettings(histPath);
2233 mainWindow->updateHistory (undoSet);
2236 /* TODO remove testing
2237 cout << "ME::redo() end\n";
2238 cout << " undosAvail="<<undosAvail<<endl;
2239 cout << " redosAvail="<<redosAvail<<endl;
2240 cout << " curStep="<<curStep<<endl;
2241 cout << " ---------------------------"<<endl<<endl;
2247 bool MapEditor::isRedoAvailable()
2249 if (undoSet.readNumEntry("/history/redosAvail",0)>0)
2255 void MapEditor::undo()
2257 // Can we undo at all?
2258 if (undosAvail<1) return;
2260 mainWindow->statusMessage (tr("Autosave disabled during undo."));
2262 bool blockSaveStateOrg=blockSaveState;
2263 blockSaveState=true;
2265 QString undoCommand= undoSet.readEntry (QString("/history/step-%1/undoCommand").arg(curStep));
2266 QString undoSelection=undoSet.readEntry (QString("/history/step-%1/undoSelection").arg(curStep));
2267 QString redoCommand= undoSet.readEntry (QString("/history/step-%1/redoCommand").arg(curStep));
2268 QString redoSelection=undoSet.readEntry (QString("/history/step-%1/redoSelection").arg(curStep));
2269 QString comment=undoSet.readEntry (QString("/history/step-%1/comment").arg(curStep));
2270 QString version=undoSet.readEntry ("/history/version");
2272 /* TODO Maybe check for version, if we save the history
2273 if (!checkVersion(version))
2274 QMessageBox::warning(0,tr("Warning"),
2275 tr("Version %1 of saved undo/redo data\ndoes not match current vym version %2.").arg(version).arg(vymVersion));
2278 // Find out current undo directory
2279 QString bakMapDir(QString(tmpMapDir+"/undo-%1").arg(curStep));
2281 // select object before undo
2282 if (!undoSelection.isEmpty())
2283 select (undoSelection);
2287 cout << "ME::undo() begin\n";
2288 cout << " undosAvail="<<undosAvail<<endl;
2289 cout << " redosAvail="<<redosAvail<<endl;
2290 cout << " curStep="<<curStep<<endl;
2291 cout << " ---------------------------"<<endl;
2292 cout << " comment="<<comment.toStdString()<<endl;
2293 cout << " undoCom="<<undoCommand.toStdString()<<endl;
2294 cout << " undoSel="<<undoSelection.toStdString()<<endl;
2295 cout << " redoCom="<<redoCommand.toStdString()<<endl;
2296 cout << " redoSel="<<redoSelection.toStdString()<<endl;
2297 cout << " ---------------------------"<<endl<<endl;
2299 parseAtom (undoCommand);
2300 model->reposition();
2304 if (curStep<1) curStep=stepsTotal;
2308 blockSaveState=blockSaveStateOrg;
2309 /* TODO remove testing
2310 cout << "ME::undo() end\n";
2311 cout << " undosAvail="<<undosAvail<<endl;
2312 cout << " redosAvail="<<redosAvail<<endl;
2313 cout << " curStep="<<curStep<<endl;
2314 cout << " ---------------------------"<<endl<<endl;
2317 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
2318 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
2319 undoSet.setEntry ("/history/curStep",QString::number(curStep));
2320 undoSet.writeSettings(histPath);
2322 mainWindow->updateHistory (undoSet);
2325 ensureSelectionVisible();
2328 bool MapEditor::isUndoAvailable()
2330 if (undoSet.readNumEntry("/history/undosAvail",0)>0)
2336 void MapEditor::gotoHistoryStep (int i)
2338 // Restore variables
2339 int undosAvail=undoSet.readNumEntry (QString("/history/undosAvail"));
2340 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
2342 if (i<0) i=undosAvail+redosAvail;
2344 // Clicking above current step makes us undo things
2347 for (int j=0; j<undosAvail-i; j++) undo();
2350 // Clicking below current step makes us redo things
2352 for (int j=undosAvail; j<i; j++)
2354 if (debug) cout << "ME::gotoHistoryStep redo "<<j<<"/"<<undosAvail<<" i="<<i<<endl;
2358 // And ignore clicking the current row ;-)
2361 void MapEditor::addMapReplaceInt(const QString &undoSel, const QString &path)
2363 QString pathDir=path.left(path.findRev("/"));
2369 // We need to parse saved XML data
2370 parseVYMHandler handler;
2371 QXmlInputSource source( file);
2372 QXmlSimpleReader reader;
2373 reader.setContentHandler( &handler );
2374 reader.setErrorHandler( &handler );
2375 handler.setModel ( model);
2376 handler.setTmpDir ( pathDir ); // needed to load files with rel. path
2377 if (undoSel.isEmpty())
2381 handler.setLoadMode (NewMap);
2385 handler.setLoadMode (ImportReplace);
2387 blockReposition=true;
2388 bool ok = reader.parse( source );
2389 blockReposition=false;
2392 // This should never ever happen
2393 QMessageBox::critical( 0, tr( "Critical Parse Error while reading %1").arg(path),
2394 handler.errorProtocol());
2397 QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
2400 void MapEditor::addMapInsertInt (const QString &path, int pos)
2402 BranchObj *sel=xelection.getBranch();
2405 QString pathDir=path.left(path.findRev("/"));
2411 // We need to parse saved XML data
2412 parseVYMHandler handler;
2413 QXmlInputSource source( file);
2414 QXmlSimpleReader reader;
2415 reader.setContentHandler( &handler );
2416 reader.setErrorHandler( &handler );
2417 handler.setModel (model);
2418 handler.setTmpDir ( pathDir ); // needed to load files with rel. path
2419 handler.setLoadMode (ImportAdd);
2420 blockReposition=true;
2421 bool ok = reader.parse( source );
2422 blockReposition=false;
2425 // This should never ever happen
2426 QMessageBox::critical( 0, tr( "Critical Parse Error while reading %1").arg(path),
2427 handler.errorProtocol());
2429 if (sel->getDepth()>0)
2430 sel->getLastBranch()->linkTo (sel,pos);
2432 QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
2436 void MapEditor::pasteNoSave(const int &n)
2438 bool old=blockSaveState;
2439 blockSaveState=true;
2440 bool zippedOrg=zipped;
2441 if (redosAvail > 0 || n!=0)
2443 // Use the "historical" buffer
2444 QString bakMapName(QString("history-%1").arg(n));
2445 QString bakMapDir(tmpMapDir +"/"+bakMapName);
2446 load (bakMapDir+"/"+clipboardFile,ImportAdd, VymMap);
2448 // Use the global buffer
2449 load (clipboardDir+"/"+clipboardFile,ImportAdd, VymMap);
2454 void MapEditor::paste()
2456 BranchObj *sel=xelection.getBranch();
2459 saveStateChangingPart(
2462 QString ("paste (%1)").arg(curClipboard),
2463 QString("Paste to %1").arg( getName(sel))
2466 model->reposition();
2470 void MapEditor::cut()
2472 LinkableMapObj *sel=xelection.single();
2473 if ( sel && (xelection.type() == Selection::Branch ||
2474 xelection.type()==Selection::MapCenter ||
2475 xelection.type()==Selection::FloatImage))
2477 /* No savestate! savestate is called in cutNoSave
2478 saveStateChangingPart(
2482 QString("Cut %1").arg(getName(sel ))
2487 model->reposition();
2491 void MapEditor::move(const double &x, const double &y)
2493 LinkableMapObj *sel=xelection.single();
2496 QPointF ap(sel->getAbsPos());
2500 QString ps=qpointfToString(ap);
2501 QString s=xelection.getSelectString();
2504 s, "move "+qpointfToString(to),
2505 QString("Move %1 to %2").arg(getName(sel)).arg(ps));
2507 model->reposition();
2513 void MapEditor::moveRel (const double &x, const double &y)
2515 LinkableMapObj *sel=xelection.single();
2518 QPointF rp(sel->getRelPos());
2522 QString ps=qpointfToString (sel->getRelPos());
2523 QString s=model->getSelectString(sel);
2526 s, "moveRel "+qpointfToString(to),
2527 QString("Move %1 to relative position %2").arg(getName(sel)).arg(ps));
2528 ((OrnamentedObj*)sel)->move2RelPos (x,y);
2529 model->reposition();
2536 void MapEditor::moveBranchUp()
2538 BranchObj* bo=xelection.getBranch();
2542 if (!bo->canMoveBranchUp()) return;
2543 par=(BranchObj*)(bo->getParObj());
2544 BranchObj *obo=par->moveBranchUp (bo); // bo will be the one below selection
2545 saveState (model->getSelectString(bo),"moveBranchDown ()",model->getSelectString(obo),"moveBranchUp ()",QString("Move up %1").arg(getName(bo)));
2546 model->reposition();
2549 ensureSelectionVisible();
2553 void MapEditor::moveBranchDown()
2555 BranchObj* bo=xelection.getBranch();
2559 if (!bo->canMoveBranchDown()) return;
2560 par=(BranchObj*)(bo->getParObj());
2561 BranchObj *obo=par->moveBranchDown(bo); // bo will be the one above selection
2562 saveState(model->getSelectString(bo),"moveBranchUp ()",model->getSelectString(obo),"moveBranchDown ()",QString("Move down %1").arg(getName(bo)));
2563 model->reposition();
2566 ensureSelectionVisible();
2570 void MapEditor::sortChildren()
2572 BranchObj* bo=xelection.getBranch();
2575 if(bo->countBranches()>1)
2577 saveStateChangingPart(bo,bo, "sortChildren ()",QString("Sort children of %1").arg(getName(bo)));
2579 model->reposition();
2580 ensureSelectionVisible();
2585 void MapEditor::linkTo(const QString &dstString)
2587 FloatImageObj *fio=xelection.getFloatImage();
2590 BranchObj *dst=(BranchObj*)(model->findObjBySelect(dstString));
2591 if (dst && (typeid(*dst)==typeid (BranchObj) ||
2592 typeid(*dst)==typeid (MapCenterObj)))
2594 LinkableMapObj *dstPar=dst->getParObj();
2595 QString parString=model->getSelectString(dstPar);
2596 QString fioPreSelectString=model->getSelectString(fio);
2597 QString fioPreParentSelectString=model->getSelectString (fio->getParObj());
2598 ((BranchObj*)(dst))->addFloatImage (fio);
2599 xelection.unselect();
2600 ((BranchObj*)(fio->getParObj()))->removeFloatImage (fio);
2601 fio=((BranchObj*)(dst))->getLastFloatImage();
2604 xelection.select(fio);
2606 model->getSelectString(fio),
2607 QString("linkTo (\"%1\")").arg(fioPreParentSelectString),
2609 QString ("linkTo (\"%1\")").arg(dstString),
2610 QString ("Link floatimage to %1").arg(getName(dst)));
2615 QString MapEditor::getHeading(bool &ok, QPoint &p)
2617 BranchObj *bo=xelection.getBranch();
2621 p=mapFromScene(bo->getAbsPos());
2622 return bo->getHeading();
2628 void MapEditor::setHeading(const QString &s)
2630 BranchObj *sel=xelection.getBranch();
2635 "setHeading (\""+sel->getHeading()+"\")",
2637 "setHeading (\""+s+"\")",
2638 QString("Set heading of %1 to \"%2\"").arg(getName(sel)).arg(s) );
2639 sel->setHeading(s );
2640 model->reposition();
2642 ensureSelectionVisible();
2646 void MapEditor::setHeadingInt(const QString &s)
2648 BranchObj *bo=xelection.getBranch();
2652 model->reposition();
2654 ensureSelectionVisible();
2658 void MapEditor::setVymLinkInt (const QString &s)
2660 // Internal function, no saveState needed
2661 BranchObj *bo=xelection.getBranch();
2665 model->reposition();
2668 ensureSelectionVisible();
2672 BranchObj* MapEditor::addMapCenter ()
2674 MapCenterObj *mco= model->addMapCenter(contextMenuPos);
2675 xelection.select (mco);
2677 ensureSelectionVisible();
2682 QString ("addMapCenter (%1,%2)").arg (contextMenuPos.x()).arg(contextMenuPos.y()),
2683 QString ("Adding MapCenter to (%1,%2").arg (contextMenuPos.x()).arg(contextMenuPos.y())
2688 BranchObj* MapEditor::addNewBranchInt(int num)
2690 // Depending on pos:
2691 // -3 insert in childs of parent above selection
2692 // -2 add branch to selection
2693 // -1 insert in childs of parent below selection
2694 // 0..n insert in childs of parent at pos
2695 BranchObj *newbo=NULL;
2696 BranchObj *bo=xelection.getBranch();
2701 // save scroll state. If scrolled, automatically select
2702 // new branch in order to tmp unscroll parent...
2703 newbo=bo->addBranch();
2708 bo=(BranchObj*)bo->getParObj();
2709 if (bo) newbo=bo->insertBranch(num);
2713 bo=(BranchObj*)bo->getParObj();
2714 if (bo) newbo=bo->insertBranch(num);
2716 if (!newbo) return NULL;
2721 BranchObj* MapEditor::addNewBranch(int pos)
2723 // Different meaning than num in addNewBranchInt!
2727 BranchObj *bo = xelection.getBranch();
2728 BranchObj *newbo=NULL;
2732 setCursor (Qt::ArrowCursor);
2734 newbo=addNewBranchInt (pos-2);
2742 QString ("addBranch (%1)").arg(pos),
2743 QString ("Add new branch to %1").arg(getName(bo)));
2745 model->reposition();
2747 latestSelection=model->getSelectString(newbo);
2748 // In Network mode, the client needs to know where the new branch is,
2749 // so we have to pass on this information via saveState.
2750 // TODO: Get rid of this positioning workaround
2751 QString ps=qpointfToString (newbo->getAbsPos());
2752 sendData ("selectLatestAdded ()");
2753 sendData (QString("move %1").arg(ps));
2761 BranchObj* MapEditor::addNewBranchBefore()
2763 BranchObj *newbo=NULL;
2764 BranchObj *bo = xelection.getBranch();
2765 if (bo && xelection.type()==Selection::Branch)
2766 // We accept no MapCenterObj here, so we _have_ a parent
2768 QPointF p=bo->getRelPos();
2771 BranchObj *parbo=(BranchObj*)(bo->getParObj());
2773 // add below selection
2774 newbo=parbo->insertBranch(bo->getNum()+1);
2777 newbo->move2RelPos (p);
2779 // Move selection to new branch
2780 bo->linkTo (newbo,-1);
2782 saveState (newbo, "deleteKeepChilds ()", newbo, "addBranchBefore ()",
2783 QString ("Add branch before %1").arg(getName(bo)));
2785 model->reposition();
2789 latestSelection=xelection.getSelectString();
2793 void MapEditor::deleteSelection()
2795 BranchObj *bo = xelection.getBranch();
2796 if (bo && xelection.type()==Selection::MapCenter)
2798 // BranchObj* par=(BranchObj*)(bo->getParObj());
2799 xelection.unselect();
2800 /* FIXME Note: does saveStateRemovingPart work for MCO? (No parent!)
2801 saveStateRemovingPart (bo, QString ("Delete %1").arg(getName(bo)));
2803 bo=model->removeMapCenter ((MapCenterObj*)bo);
2806 xelection.select (bo);
2807 ensureSelectionVisible();
2810 model->reposition();
2813 if (bo && xelection.type()==Selection::Branch)
2815 BranchObj* par=(BranchObj*)bo->getParObj();
2816 xelection.unselect();
2817 saveStateRemovingPart (bo, QString ("Delete %1").arg(getName(bo)));
2818 par->removeBranch(bo);
2819 xelection.select (par);
2820 ensureSelectionVisible();
2821 model->reposition();
2822 // xelection.update();
2826 FloatImageObj *fio=xelection.getFloatImage();
2829 BranchObj* par=(BranchObj*)fio->getParObj();
2830 saveStateChangingPart(
2834 QString("Delete %1").arg(getName(fio))
2836 xelection.unselect();
2837 par->removeFloatImage(fio);
2838 xelection.select (par);
2839 model->reposition();
2841 ensureSelectionVisible();
2846 LinkableMapObj* MapEditor::getSelection()
2848 return xelection.single();
2851 BranchObj* MapEditor::getSelectedBranch()
2853 return xelection.getBranch();
2856 FloatImageObj* MapEditor::getSelectedFloatImage()
2858 return xelection.getFloatImage();
2861 void MapEditor::unselect()
2863 xelection.unselect();
2866 void MapEditor::reselect()
2868 xelection.reselect();
2871 bool MapEditor::select (const QString &s)
2873 if (xelection.select(s))
2876 ensureSelectionVisible();
2883 bool MapEditor::select (LinkableMapObj *lmo)
2885 if (xelection.select(lmo))
2888 ensureSelectionVisible();
2895 QString MapEditor::getSelectString()
2897 return xelection.getSelectString();
2900 void MapEditor::selectInt (LinkableMapObj *lmo)
2902 if (lmo && xelection.single()!= lmo && isSelectBlocked()==false )
2904 xelection.select(lmo);
2910 void MapEditor::selectNextBranchInt()
2912 // Increase number of branch
2913 LinkableMapObj *sel=xelection.single();
2916 QString s=xelection.getSelectString();
2922 part=s.section(",",-1);
2924 num=part.right(part.length() - 3);
2926 s=s.left (s.length() -num.length());
2929 num=QString ("%1").arg(num.toUInt()+1);
2933 // Try to select this one
2934 if (select (s)) return;
2936 // We have no direct successor,
2937 // try to increase the parental number in order to
2938 // find a successor with same depth
2940 int d=xelection.single()->getDepth();
2945 while (!found && d>0)
2947 s=s.section (",",0,d-1);
2948 // replace substring of current depth in s with "1"
2949 part=s.section(",",-1);
2951 num=part.right(part.length() - 3);
2955 // increase number of parent
2956 num=QString ("%1").arg(num.toUInt()+1);
2957 s=s.section (",",0,d-2) + ","+ typ+num;
2960 // Special case, look at orientation
2961 if (xelection.single()->getOrientation()==LinkableMapObj::RightOfCenter)
2962 num=QString ("%1").arg(num.toUInt()+1);
2964 num=QString ("%1").arg(num.toUInt()-1);
2969 // pad to oldDepth, select the first branch for each depth
2970 for (i=d;i<oldDepth;i++)
2975 if ( xelection.getBranch()->countBranches()>0)
2983 // try to select the freshly built string
2991 void MapEditor::selectPrevBranchInt()
2993 // Decrease number of branch
2994 BranchObj *bo=xelection.getBranch();
2997 QString s=xelection.getSelectString();
3003 part=s.section(",",-1);
3005 num=part.right(part.length() - 3);
3007 s=s.left (s.length() -num.length());
3009 int n=num.toInt()-1;
3012 num=QString ("%1").arg(n);
3015 // Try to select this one
3016 if (n>=0 && select (s)) return;
3018 // We have no direct precessor,
3019 // try to decrease the parental number in order to
3020 // find a precessor with same depth
3022 int d=xelection.single()->getDepth();
3027 while (!found && d>0)
3029 s=s.section (",",0,d-1);
3030 // replace substring of current depth in s with "1"
3031 part=s.section(",",-1);
3033 num=part.right(part.length() - 3);
3037 // decrease number of parent
3038 num=QString ("%1").arg(num.toInt()-1);
3039 s=s.section (",",0,d-2) + ","+ typ+num;
3042 // Special case, look at orientation
3043 if (xelection.single()->getOrientation()==LinkableMapObj::RightOfCenter)
3044 num=QString ("%1").arg(num.toInt()-1);
3046 num=QString ("%1").arg(num.toInt()+1);
3051 // pad to oldDepth, select the last branch for each depth
3052 for (i=d;i<oldDepth;i++)
3056 if ( xelection.getBranch()->countBranches()>0)
3057 s+=",bo:"+ QString ("%1").arg( xelection.getBranch()->countBranches()-1 );
3064 // try to select the freshly built string
3072 void MapEditor::selectUpperBranch()
3074 if (isSelectBlocked() ) return;
3076 BranchObj *bo=xelection.getBranch();
3077 if (bo && xelection.type()==Selection::Branch)
3079 if (bo->getOrientation()==LinkableMapObj::RightOfCenter)
3080 selectPrevBranchInt();
3082 if (bo->getDepth()==1)
3083 selectNextBranchInt();
3085 selectPrevBranchInt();
3089 void MapEditor::selectLowerBranch()
3091 if (isSelectBlocked() ) return;
3093 BranchObj *bo=xelection.getBranch();
3094 if (bo && xelection.type()==Selection::Branch)
3095 if (bo->getOrientation()==LinkableMapObj::RightOfCenter)
3096 selectNextBranchInt();
3098 if (bo->getDepth()==1)
3099 selectPrevBranchInt();
3101 selectNextBranchInt();
3105 void MapEditor::selectLeftBranch()
3107 if (isSelectBlocked() ) return;
3111 LinkableMapObj *sel=xelection.single();
3114 if (xelection.type()== Selection::MapCenter)
3116 par=xelection.getBranch();
3117 bo=par->getLastSelectedBranch();
3120 // Workaround for reselecting on left and right side
3121 if (bo->getOrientation()==LinkableMapObj::RightOfCenter)
3122 bo=par->getLastBranch();
3125 bo=par->getLastBranch();
3126 xelection.select(bo);
3128 ensureSelectionVisible();
3134 par=(BranchObj*)(sel->getParObj());
3135 if (sel->getOrientation()==LinkableMapObj::RightOfCenter)
3137 if (xelection.type() == Selection::Branch ||
3138 xelection.type() == Selection::FloatImage)
3140 xelection.select(par);
3142 ensureSelectionVisible();
3147 if (xelection.type() == Selection::Branch )
3149 bo=xelection.getBranch()->getLastSelectedBranch();
3152 xelection.select(bo);
3154 ensureSelectionVisible();
3163 void MapEditor::selectRightBranch()
3165 if (isSelectBlocked() ) return;
3169 LinkableMapObj *sel=xelection.single();
3172 if (xelection.type()==Selection::MapCenter)
3174 par=xelection.getBranch();
3175 bo=par->getLastSelectedBranch();
3178 // Workaround for reselecting on left and right side
3179 if (bo->getOrientation()==LinkableMapObj::LeftOfCenter)
3180 bo=par->getFirstBranch();
3183 xelection.select(bo);
3185 ensureSelectionVisible();
3191 par=(BranchObj*)(xelection.single()->getParObj());
3192 if (xelection.single()->getOrientation()==LinkableMapObj::LeftOfCenter)
3194 if (xelection.type() == Selection::Branch ||
3195 xelection.type() == Selection::FloatImage)
3197 xelection.select(par);
3199 ensureSelectionVisible();
3204 if (xelection.type() == Selection::Branch)
3206 bo=xelection.getBranch()->getLastSelectedBranch();
3209 xelection.select(bo);
3211 ensureSelectionVisible();
3220 void MapEditor::selectFirstBranch()
3222 BranchObj *bo1=xelection.getBranch();
3227 par=(BranchObj*)(bo1->getParObj());
3229 bo2=par->getFirstBranch();
3231 xelection.select(bo2);
3233 ensureSelectionVisible();
3239 void MapEditor::selectLastBranch()
3241 BranchObj *bo1=xelection.getBranch();
3246 par=(BranchObj*)(bo1->getParObj());
3248 bo2=par->getLastBranch();
3251 xelection.select(bo2);
3253 ensureSelectionVisible();
3259 void MapEditor::selectMapBackgroundImage ()
3261 Q3FileDialog *fd=new Q3FileDialog( this);
3262 fd->setMode (Q3FileDialog::ExistingFile);
3263 fd->addFilter (QString (tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)"));
3264 ImagePreview *p =new ImagePreview (fd);
3265 fd->setContentsPreviewEnabled( TRUE );
3266 fd->setContentsPreview( p, p );
3267 fd->setPreviewMode( Q3FileDialog::Contents );
3268 fd->setCaption(vymName+" - " +tr("Load background image"));
3269 fd->setDir (lastImageDir);
3272 if ( fd->exec() == QDialog::Accepted )
3274 // TODO selectMapBackgroundImg in QT4 use: lastImageDir=fd->directory();
3275 lastImageDir=QDir (fd->dirPath());
3276 setMapBackgroundImage (fd->selectedFile());
3280 void MapEditor::setMapBackgroundImage (const QString &fn) //FIXME missing savestate
3282 QColor oldcol=mapScene->backgroundBrush().color();
3286 QString ("setMapBackgroundImage (%1)").arg(oldcol.name()),
3288 QString ("setMapBackgroundImage (%1)").arg(col.name()),
3289 QString("Set background color of map to %1").arg(col.name()));
3292 brush.setTextureImage (QPixmap (fn));
3293 mapScene->setBackgroundBrush(brush);
3296 void MapEditor::selectMapBackgroundColor()
3298 QColor col = QColorDialog::getColor( mapScene->backgroundBrush().color(), this );
3299 if ( !col.isValid() ) return;
3300 setMapBackgroundColor( col );
3304 void MapEditor::setMapBackgroundColor(QColor col)
3306 QColor oldcol=mapScene->backgroundBrush().color();
3308 QString ("setMapBackgroundColor (\"%1\")").arg(oldcol.name()),
3309 QString ("setMapBackgroundColor (\"%1\")").arg(col.name()),
3310 QString("Set background color of map to %1").arg(col.name()));
3311 mapScene->setBackgroundBrush(col);
3314 QColor MapEditor::getMapBackgroundColor()
3316 return mapScene->backgroundBrush().color();
3319 QColor MapEditor::getCurrentHeadingColor()
3321 BranchObj *bo=xelection.getBranch();
3322 if (bo) return bo->getColor();
3324 QMessageBox::warning(0,tr("Warning"),tr("Can't get color of heading,\nthere's no branch selected"));
3328 void MapEditor::colorBranch (QColor c)
3330 BranchObj *bo=xelection.getBranch();
3335 QString ("colorBranch (\"%1\")").arg(bo->getColor().name()),
3337 QString ("colorBranch (\"%1\")").arg(c.name()),
3338 QString("Set color of %1 to %2").arg(getName(bo)).arg(c.name())
3340 bo->setColor(c); // color branch
3344 void MapEditor::colorSubtree (QColor c)
3346 BranchObj *bo=xelection.getBranch();
3349 saveStateChangingPart(
3352 QString ("colorSubtree (\"%1\")").arg(c.name()),
3353 QString ("Set color of %1 and childs to %2").arg(getName(bo)).arg(c.name())
3355 bo->setColorSubtree (c); // color links, color childs
3360 void MapEditor::toggleStandardFlag(QString f)
3362 BranchObj *bo=xelection.getBranch();
3366 if (bo->isSetStandardFlag(f))
3378 QString("%1 (\"%2\")").arg(u).arg(f),
3380 QString("%1 (\"%2\")").arg(r).arg(f),
3381 QString("Toggling standard flag \"%1\" of %2").arg(f).arg(getName(bo)));
3382 bo->toggleStandardFlag (f,mainWindow->useFlagGroups());
3388 BranchObj* MapEditor::findText (QString s, bool cs)
3390 QTextDocument::FindFlags flags=0;
3391 if (cs) flags=QTextDocument::FindCaseSensitively;
3394 { // Nothing found or new find process
3396 // nothing found, start again
3398 itFind=model->first();
3400 bool searching=true;
3401 bool foundNote=false;
3402 while (searching && !EOFind)
3406 // Searching in Note
3407 if (itFind->getNote().contains(s,cs))
3409 if (xelection.single()!=itFind)
3411 xelection.select(itFind);
3412 ensureSelectionVisible();
3414 if (textEditor->findText(s,flags))
3420 // Searching in Heading
3421 if (searching && itFind->getHeading().contains (s,cs) )
3423 xelection.select(itFind);
3424 ensureSelectionVisible();
3430 itFind=model->next(itFind);
3431 if (!itFind) EOFind=true;
3433 //cout <<"still searching... "<<qPrintable( itFind->getHeading())<<endl;
3436 return xelection.getBranch();
3441 void MapEditor::findReset()
3442 { // Necessary if text to find changes during a find process
3446 void MapEditor::setURL(const QString &url)
3448 BranchObj *bo=xelection.getBranch();
3451 QString oldurl=bo->getURL();
3455 QString ("setURL (\"%1\")").arg(oldurl),
3457 QString ("setURL (\"%1\")").arg(url),
3458 QString ("set URL of %1 to %2").arg(getName(bo)).arg(url)
3461 model->reposition();
3463 ensureSelectionVisible();
3467 void MapEditor::editURL()
3469 BranchObj *bo=xelection.getBranch();
3473 QString text = QInputDialog::getText(
3474 "VYM", tr("Enter URL:"), QLineEdit::Normal,
3475 bo->getURL(), &ok, this );
3477 // user entered something and pressed OK
3482 void MapEditor::editLocalURL()
3484 BranchObj *bo=xelection.getBranch();
3487 QStringList filters;
3488 filters <<"All files (*)";
3489 filters << tr("Text","Filedialog") + " (*.txt)";
3490 filters << tr("Spreadsheet","Filedialog") + " (*.odp,*.sxc)";
3491 filters << tr("Textdocument","Filedialog") +" (*.odw,*.sxw)";
3492 filters << tr("Images","Filedialog") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)";
3493 QFileDialog *fd=new QFileDialog( this,vymName+" - " +tr("Set URL to a local file"));
3494 fd->setFilters (filters);
3495 fd->setCaption(vymName+" - " +tr("Set URL to a local file"));
3496 fd->setDirectory (lastFileDir);
3497 if (! bo->getVymLink().isEmpty() )
3498 fd->selectFile( bo->getURL() );
3501 if ( fd->exec() == QDialog::Accepted )
3503 lastFileDir=QDir (fd->directory().path());
3504 setURL (fd->selectedFile() );
3509 QString MapEditor::getURL()
3511 BranchObj *bo=xelection.getBranch();
3513 return bo->getURL();
3518 QStringList MapEditor::getURLs()
3521 BranchObj *bo=xelection.getBranch();
3527 if (!bo->getURL().isEmpty()) urls.append( bo->getURL());
3535 void MapEditor::editHeading2URL()
3537 BranchObj *bo=xelection.getBranch();
3539 setURL (bo->getHeading());
3542 void MapEditor::editBugzilla2URL()
3544 BranchObj *bo=xelection.getBranch();
3547 QString url= "https://bugzilla.novell.com/show_bug.cgi?id="+bo->getHeading();
3552 void MapEditor::editFATE2URL()
3554 BranchObj *bo=xelection.getBranch();
3557 QString url= "http://keeper.suse.de:8080/webfate/match/id?value=ID"+bo->getHeading();
3560 "setURL (\""+bo->getURL()+"\")",
3562 "setURL (\""+url+"\")",
3563 QString("Use heading of %1 as link to FATE").arg(getName(bo))
3570 void MapEditor::editVymLink()
3572 BranchObj *bo=xelection.getBranch();
3575 QStringList filters;
3576 filters <<"VYM map (*.vym)";
3577 QFileDialog *fd=new QFileDialog( this,vymName+" - " +tr("Link to another map"));
3578 fd->setFilters (filters);
3579 fd->setCaption(vymName+" - " +tr("Link to another map"));
3580 fd->setDirectory (lastFileDir);
3581 if (! bo->getVymLink().isEmpty() )
3582 fd->selectFile( bo->getVymLink() );
3586 if ( fd->exec() == QDialog::Accepted )
3588 lastFileDir=QDir (fd->directory().path());
3591 "setVymLink (\""+bo->getVymLink()+"\")",
3593 "setVymLink (\""+fd->selectedFile()+"\")",
3594 QString("Set vymlink of %1 to %2").arg(getName(bo)).arg(fd->selectedFile())
3596 setVymLinkInt (fd->selectedFile() );
3601 void MapEditor::deleteVymLink()
3603 BranchObj *bo=xelection.getBranch();
3608 "setVymLink (\""+bo->getVymLink()+"\")",
3610 "setVymLink (\"\")",
3611 QString("Unset vymlink of %1").arg(getName(bo))
3613 bo->setVymLink ("" );
3615 model->reposition();
3620 void MapEditor::setHideExport(bool b)
3622 BranchObj *bo=xelection.getBranch();
3625 bo->setHideInExport (b);
3626 QString u= b ? "false" : "true";
3627 QString r=!b ? "false" : "true";
3631 QString ("setHideExport (%1)").arg(u),
3633 QString ("setHideExport (%1)").arg(r),
3634 QString ("Set HideExport flag of %1 to %2").arg(getName(bo)).arg (r)
3637 model->reposition();
3643 void MapEditor::toggleHideExport()
3645 BranchObj *bo=xelection.getBranch();
3647 setHideExport ( !bo->hideInExport() );
3650 QString MapEditor::getVymLink()
3652 BranchObj *bo=xelection.getBranch();
3654 return bo->getVymLink();
3660 QStringList MapEditor::getVymLinks()
3663 BranchObj *bo=xelection.getBranch();
3669 if (!bo->getVymLink().isEmpty()) links.append( bo->getVymLink());
3677 void MapEditor::deleteKeepChilds()
3679 BranchObj *bo=xelection.getBranch();
3683 par=(BranchObj*)(bo->getParObj());
3684 QPointF p=bo->getRelPos();
3685 saveStateChangingPart(
3688 "deleteKeepChilds ()",
3689 QString("Remove %1 and keep its childs").arg(getName(bo))
3692 QString sel=model->getSelectString(bo);
3694 par->removeBranchHere(bo);
3695 model->reposition();
3697 xelection.getBranch()->move2RelPos (p);
3698 model->reposition();
3702 void MapEditor::deleteChilds()
3704 BranchObj *bo=xelection.getBranch();
3707 saveStateChangingPart(
3711 QString( "Remove childs of branch %1").arg(getName(bo))
3714 model->reposition();
3718 void MapEditor::editMapInfo()
3720 ExtraInfoDialog dia;
3721 dia.setMapName (getFileName() );
3722 dia.setAuthor (model->getAuthor() );
3723 dia.setComment(model->getComment() );
3727 stats+=tr("%1 items on map\n","Info about map").arg (mapScene->items().size(),6);
3737 if (!bo->getNote().isEmpty() ) n++;
3738 f+= bo->countFloatImages();
3740 xl+=bo->countXLinks();
3743 stats+=QString ("%1 branches\n").arg (b-1,6);
3744 stats+=QString ("%1 xLinks \n").arg (xl,6);
3745 stats+=QString ("%1 notes\n").arg (n,6);
3746 stats+=QString ("%1 images\n").arg (f,6);
3747 dia.setStats (stats);
3749 // Finally show dialog
3750 if (dia.exec() == QDialog::Accepted)
3752 setMapAuthor (dia.getAuthor() );
3753 setMapComment (dia.getComment() );
3757 void MapEditor::ensureSelectionVisible()
3759 LinkableMapObj *lmo=xelection.single();
3760 if (lmo) ensureVisible (lmo->getBBox() );
3764 void MapEditor::updateSelection()
3766 // Tell selection to update geometries
3770 void MapEditor::updateActions()
3772 // Tell mainwindow to update states of actions
3773 mainWindow->updateActions();
3774 // TODO maybe don't update if blockReposition is set
3777 void MapEditor::updateNoteFlag()
3780 BranchObj *bo=xelection.getBranch();
3783 bo->updateNoteFlag();
3784 mainWindow->updateActions();
3788 void MapEditor::setMapAuthor (const QString &s)
3791 QString ("setMapAuthor (\"%1\")").arg(model->getAuthor()),
3792 QString ("setMapAuthor (\"%1\")").arg(s),
3793 QString ("Set author of map to \"%1\"").arg(s)
3795 model->setAuthor (s);
3798 void MapEditor::setMapComment (const QString &s)
3801 QString ("setMapComment (\"%1\")").arg(model->getComment()),
3802 QString ("setMapComment (\"%1\")").arg(s),
3803 QString ("Set comment of map")
3805 model->setComment (s);
3808 void MapEditor::setMapLinkStyle (const QString & s)
3811 if (linkstyle==LinkableMapObj::Line)
3813 else if (linkstyle==LinkableMapObj::Parabel)
3814 snow="StyleParabel";
3815 else if (linkstyle==LinkableMapObj::PolyLine)
3816 snow="StylePolyLine";
3817 else if (linkstyle==LinkableMapObj::PolyParabel)
3818 snow="StyleParabel";
3821 QString("setMapLinkStyle (\"%1\")").arg(s),
3822 QString("setMapLinkStyle (\"%1\")").arg(snow),
3823 QString("Set map link style (\"%1\")").arg(s)
3827 linkstyle=LinkableMapObj::Line;
3828 else if (s=="StyleParabel")
3829 linkstyle=LinkableMapObj::Parabel;
3830 else if (s=="StylePolyLine")
3831 linkstyle=LinkableMapObj::PolyLine;
3833 linkstyle=LinkableMapObj::PolyParabel;
3840 bo->setLinkStyle(bo->getDefLinkStyle());
3843 model->reposition();
3846 LinkableMapObj::Style MapEditor::getMapLinkStyle ()
3851 void MapEditor::setMapDefLinkColor(QColor c)
3864 void MapEditor::setMapLinkColorHintInt()
3866 // called from setMapLinkColorHint(lch) or at end of parse
3876 void MapEditor::setMapLinkColorHint(LinkableMapObj::ColorHint lch)
3879 setMapLinkColorHintInt();
3882 void MapEditor::toggleMapLinkColorHint()
3884 if (linkcolorhint==LinkableMapObj::HeadingColor)
3885 linkcolorhint=LinkableMapObj::DefaultColor;
3887 linkcolorhint=LinkableMapObj::HeadingColor;
3897 LinkableMapObj::ColorHint MapEditor::getMapLinkColorHint()
3899 return linkcolorhint;
3902 QColor MapEditor::getMapDefLinkColor()
3904 return defLinkColor;
3907 void MapEditor::setMapDefXLinkColor(QColor col)
3912 QColor MapEditor::getMapDefXLinkColor()
3914 return defXLinkColor;
3917 void MapEditor::setMapDefXLinkWidth (int w)
3922 int MapEditor::getMapDefXLinkWidth()
3924 return defXLinkWidth;
3927 void MapEditor::selectMapLinkColor()
3929 QColor col = QColorDialog::getColor( defLinkColor, this );
3930 if ( !col.isValid() ) return;
3932 QString("setMapDefLinkColor (\"%1\")").arg(getMapDefLinkColor().name()),
3933 QString("setMapDefLinkColor (\"%1\")").arg(col.name()),
3934 QString("Set map link color to %1").arg(col.name())
3936 setMapDefLinkColor( col );
3939 void MapEditor::selectMapSelectionColor()
3941 QColor col = QColorDialog::getColor( defLinkColor, this );
3942 setSelectionColor (col);
3945 void MapEditor::setSelectionColorInt (QColor col)
3947 if ( !col.isValid() ) return;
3948 xelection.setColor (col);
3951 void MapEditor::setSelectionColor(QColor col)
3953 if ( !col.isValid() ) return;
3955 QString("setSelectionColor (%1)").arg(xelection.getColor().name()),
3956 QString("setSelectionColor (%1)").arg(col.name()),
3957 QString("Set color of selection box to %1").arg(col.name())
3959 setSelectionColorInt (col);
3962 QColor MapEditor::getSelectionColor()
3964 return xelection.getColor();
3967 bool MapEditor::scrollBranch(BranchObj *bo)
3971 if (bo->isScrolled()) return false;
3972 if (bo->countBranches()==0) return false;
3973 if (bo->getDepth()==0) return false;
3979 QString ("%1 ()").arg(u),
3981 QString ("%1 ()").arg(r),
3982 QString ("%1 %2").arg(r).arg(getName(bo))
3992 bool MapEditor::unscrollBranch(BranchObj *bo)
3996 if (!bo->isScrolled()) return false;
3997 if (bo->countBranches()==0) return false;
3998 if (bo->getDepth()==0) return false;
4004 QString ("%1 ()").arg(u),
4006 QString ("%1 ()").arg(r),
4007 QString ("%1 %2").arg(r).arg(getName(bo))
4017 void MapEditor::toggleScroll()
4019 BranchObj *bo=xelection.getBranch();
4020 if (xelection.type()==Selection::Branch )
4022 if (bo->isScrolled())
4023 unscrollBranch (bo);
4029 void MapEditor::unscrollChilds()
4031 BranchObj *bo=xelection.getBranch();
4037 if (bo->isScrolled()) unscrollBranch (bo);
4043 FloatImageObj* MapEditor::loadFloatImageInt (QString fn)
4045 BranchObj *bo=xelection.getBranch();
4049 bo->addFloatImage();
4050 fio=bo->getLastFloatImage();
4052 model->reposition();
4059 void MapEditor::loadFloatImage ()
4061 BranchObj *bo=xelection.getBranch();
4065 Q3FileDialog *fd=new Q3FileDialog( this);
4066 fd->setMode (Q3FileDialog::ExistingFiles);
4067 fd->addFilter (QString (tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)"));
4068 ImagePreview *p =new ImagePreview (fd);
4069 fd->setContentsPreviewEnabled( TRUE );
4070 fd->setContentsPreview( p, p );
4071 fd->setPreviewMode( Q3FileDialog::Contents );
4072 fd->setCaption(vymName+" - " +tr("Load image"));
4073 fd->setDir (lastImageDir);
4076 if ( fd->exec() == QDialog::Accepted )
4078 // TODO loadFIO in QT4 use: lastImageDir=fd->directory();
4079 lastImageDir=QDir (fd->dirPath());
4082 for (int j=0; j<fd->selectedFiles().count(); j++)
4084 s=fd->selectedFiles().at(j);
4085 fio=loadFloatImageInt (s);
4088 (LinkableMapObj*)fio,
4091 QString ("loadImage (%1)").arg(s ),
4092 QString("Add image %1 to %2").arg(s).arg(getName(bo))
4095 // TODO loadFIO error handling
4096 qWarning ("Failed to load "+s);
4104 void MapEditor::saveFloatImageInt (FloatImageObj *fio, const QString &type, const QString &fn)
4106 fio->save (fn,type);
4109 void MapEditor::saveFloatImage ()
4111 FloatImageObj *fio=xelection.getFloatImage();
4114 QFileDialog *fd=new QFileDialog( this);
4115 fd->setFilters (imageIO.getFilters());
4116 fd->setCaption(vymName+" - " +tr("Save image"));
4117 fd->setFileMode( QFileDialog::AnyFile );
4118 fd->setDirectory (lastImageDir);
4119 // fd->setSelection (fio->getOriginalFilename());
4123 if ( fd->exec() == QDialog::Accepted && fd->selectedFiles().count()==1)
4125 fn=fd->selectedFiles().at(0);
4126 if (QFile (fn).exists() )
4128 QMessageBox mb( vymName,
4129 tr("The file %1 exists already.\n"
4130 "Do you want to overwrite it?").arg(fn),
4131 QMessageBox::Warning,
4132 QMessageBox::Yes | QMessageBox::Default,
4133 QMessageBox::Cancel | QMessageBox::Escape,
4134 QMessageBox::NoButton );
4136 mb.setButtonText( QMessageBox::Yes, tr("Overwrite") );
4137 mb.setButtonText( QMessageBox::No, tr("Cancel"));
4140 case QMessageBox::Yes:
4143 case QMessageBox::Cancel:
4150 saveFloatImageInt (fio,fd->selectedFilter(),fn );
4156 void MapEditor::setFrameType(const FrameObj::FrameType &t)
4158 BranchObj *bo=xelection.getBranch();
4161 QString s=bo->getFrameTypeName();
4162 bo->setFrameType (t);
4163 saveState (bo, QString("setFrameType (\"%1\")").arg(s),
4164 bo, QString ("setFrameType (\"%1\")").arg(bo->getFrameTypeName()),QString ("set type of frame to %1").arg(s));
4165 model->reposition();
4170 void MapEditor::setFrameType(const QString &s)
4172 BranchObj *bo=xelection.getBranch();
4175 saveState (bo, QString("setFrameType (\"%1\")").arg(bo->getFrameTypeName()),
4176 bo, QString ("setFrameType (\"%1\")").arg(s),QString ("set type of frame to %1").arg(s));
4177 bo->setFrameType (s);
4178 model->reposition();
4183 void MapEditor::setFramePenColor(const QColor &c)
4185 BranchObj *bo=xelection.getBranch();
4188 saveState (bo, QString("setFramePenColor (\"%1\")").arg(bo->getFramePenColor().name() ),
4189 bo, QString ("setFramePenColor (\"%1\")").arg(c.name() ),QString ("set pen color of frame to %1").arg(c.name() ));
4190 bo->setFramePenColor (c);
4194 void MapEditor::setFrameBrushColor(const QColor &c)
4196 BranchObj *bo=xelection.getBranch();
4199 saveState (bo, QString("setFrameBrushColor (\"%1\")").arg(bo->getFrameBrushColor().name() ),
4200 bo, QString ("setFrameBrushColor (\"%1\")").arg(c.name() ),QString ("set brush color of frame to %1").arg(c.name() ));
4201 bo->setFrameBrushColor (c);
4205 void MapEditor::setFramePadding (const int &i)
4207 BranchObj *bo=xelection.getBranch();
4210 saveState (bo, QString("setFramePadding (\"%1\")").arg(bo->getFramePadding() ),
4211 bo, QString ("setFramePadding (\"%1\")").arg(i),QString ("set brush color of frame to %1").arg(i));
4212 bo->setFramePadding (i);
4213 model->reposition();
4218 void MapEditor::setFrameBorderWidth(const int &i)
4220 BranchObj *bo=xelection.getBranch();
4223 saveState (bo, QString("setFrameBorderWidth (\"%1\")").arg(bo->getFrameBorderWidth() ),
4224 bo, QString ("setFrameBorderWidth (\"%1\")").arg(i),QString ("set border width of frame to %1").arg(i));
4225 bo->setFrameBorderWidth (i);
4226 model->reposition();
4231 void MapEditor::setIncludeImagesVer(bool b)
4233 BranchObj *bo=xelection.getBranch();
4236 QString u= b ? "false" : "true";
4237 QString r=!b ? "false" : "true";
4241 QString("setIncludeImagesVertically (%1)").arg(u),
4243 QString("setIncludeImagesVertically (%1)").arg(r),
4244 QString("Include images vertically in %1").arg(getName(bo))
4246 bo->setIncludeImagesVer(b);
4247 model->reposition();
4251 void MapEditor::setIncludeImagesHor(bool b)
4253 BranchObj *bo=xelection.getBranch();
4256 QString u= b ? "false" : "true";
4257 QString r=!b ? "false" : "true";
4261 QString("setIncludeImagesHorizontally (%1)").arg(u),
4263 QString("setIncludeImagesHorizontally (%1)").arg(r),
4264 QString("Include images horizontally in %1").arg(getName(bo))
4266 bo->setIncludeImagesHor(b);
4267 model->reposition();
4271 void MapEditor::setHideLinkUnselected (bool b)
4273 LinkableMapObj *sel=xelection.single();
4275 (xelection.type() == Selection::Branch ||
4276 xelection.type() == Selection::MapCenter ||
4277 xelection.type() == Selection::FloatImage ))
4279 QString u= b ? "false" : "true";
4280 QString r=!b ? "false" : "true";
4284 QString("setHideLinkUnselected (%1)").arg(u),
4286 QString("setHideLinkUnselected (%1)").arg(r),
4287 QString("Hide link of %1 if unselected").arg(getName(sel))
4289 sel->setHideLinkUnselected(b);
4293 void MapEditor::importDirInt(BranchObj *dst, QDir d)
4295 BranchObj *bo=xelection.getBranch();
4298 // Traverse directories
4299 d.setFilter( QDir::Dirs| QDir::Hidden | QDir::NoSymLinks );
4300 QFileInfoList list = d.entryInfoList();
4303 for (int i = 0; i < list.size(); ++i)
4306 if (fi.fileName() != "." && fi.fileName() != ".." )
4309 bo=dst->getLastBranch();
4310 bo->setHeading (fi.fileName() );
4311 bo->setColor (QColor("blue"));
4313 if ( !d.cd(fi.fileName()) )
4314 QMessageBox::critical (0,tr("Critical Import Error"),tr("Cannot find the directory %1").arg(fi.fileName()));
4317 // Recursively add subdirs
4318 importDirInt (bo,d);
4324 d.setFilter( QDir::Files| QDir::Hidden | QDir::NoSymLinks );
4325 list = d.entryInfoList();
4327 for (int i = 0; i < list.size(); ++i)
4331 bo=dst->getLastBranch();
4332 bo->setHeading (fi.fileName() );
4333 bo->setColor (QColor("black"));
4334 if (fi.fileName().right(4) == ".vym" )
4335 bo->setVymLink (fi.filePath());
4340 void MapEditor::importDirInt (const QString &s)
4342 BranchObj *bo=xelection.getBranch();
4345 saveStateChangingPart (bo,bo,QString ("importDir (\"%1\")").arg(s),QString("Import directory structure from %1").arg(s));
4348 importDirInt (bo,d);
4352 void MapEditor::importDir()
4354 BranchObj *bo=xelection.getBranch();
4357 QStringList filters;
4358 filters <<"VYM map (*.vym)";
4359 QFileDialog *fd=new QFileDialog( this,vymName+ " - " +tr("Choose directory structure to import"));
4360 fd->setMode (QFileDialog::DirectoryOnly);
4361 fd->setFilters (filters);
4362 fd->setCaption(vymName+" - " +tr("Choose directory structure to import"));
4366 if ( fd->exec() == QDialog::Accepted )
4368 importDirInt (fd->selectedFile() );
4369 model->reposition();
4375 void MapEditor::followXLink(int i)
4377 BranchObj *bo=xelection.getBranch();
4380 bo=bo->XLinkTargetAt(i);
4383 xelection.select(bo);
4384 ensureSelectionVisible();
4389 void MapEditor::editXLink(int i) // FIXME missing saveState
4391 BranchObj *bo=xelection.getBranch();
4394 XLinkObj *xlo=bo->XLinkAt(i);
4397 EditXLinkDialog dia;
4399 dia.setSelection(bo);
4400 if (dia.exec() == QDialog::Accepted)
4402 if (dia.useSettingsGlobal() )
4404 setMapDefXLinkColor (xlo->getColor() );
4405 setMapDefXLinkWidth (xlo->getWidth() );
4407 if (dia.deleteXLink())
4408 bo->deleteXLinkAt(i);
4414 AttributeTable* MapEditor::attributeTable()
4419 void MapEditor::testFunction1()
4421 BranchObj *bo=xelection.getBranch();
4422 if (bo) model->moveAway (bo);
4424 /* TODO Hide hidden stuff temporary, maybe add this as regular function somewhere
4425 if (hidemode==HideNone)
4427 setHideTmpMode (HideExport);
4428 mapCenter->calcBBoxSizeWithChilds();
4429 QRectF totalBBox=mapCenter->getTotalBBox();
4430 QRectF mapRect=totalBBox;
4431 QCanvasRectangle *frame=NULL;
4433 cout << " map has =("<<totalBBox.x()<<","<<totalBBox.y()<<","<<totalBBox.width()<<","<<totalBBox.height()<<")\n";
4435 mapRect.setRect (totalBBox.x(), totalBBox.y(),
4436 totalBBox.width(), totalBBox.height());
4437 frame=new QCanvasRectangle (mapRect,mapScene);
4438 frame->setBrush (QColor(white));
4439 frame->setPen (QColor(black));
4440 frame->setZValue(0);
4445 setHideTmpMode (HideNone);
4447 cout <<" hidemode="<<hidemode<<endl;
4451 void MapEditor::testFunction2()
4456 if (hidemode==HideExport)
4457 setHideTmpMode (HideNone);
4459 setHideTmpMode (HideExport);
4463 void MapEditor::contextMenuEvent ( QContextMenuEvent * e )
4465 // Lineedits are already closed by preceding
4466 // mouseEvent, we don't need to close here.
4468 QPointF p = mapToScene(e->pos());
4469 LinkableMapObj* lmo=model->findMapObj(p, NULL);
4472 { // MapObj was found
4473 if (xelection.single() != lmo)
4475 // select the MapObj
4476 xelection.select(lmo);
4479 if (xelection.getBranch() )
4481 // Context Menu on branch or mapcenter
4483 branchContextMenu->popup(e->globalPos() );
4486 if (xelection.getFloatImage() )
4488 // Context Menu on floatimage
4490 floatimageContextMenu->popup(e->globalPos() );
4494 { // No MapObj found, we are on the Canvas itself
4495 // Context Menu on scene
4498 canvasContextMenu->popup(e->globalPos() );
4503 void MapEditor::keyPressEvent(QKeyEvent* e)
4505 if (e->modifiers() & Qt::ControlModifier)
4507 switch (mainWindow->getModMode())
4509 case Main::ModModeColor:
4510 setCursor (PickColorCursor);
4512 case Main::ModModeCopy:
4513 setCursor (CopyCursor);
4515 case Main::ModModeXLink:
4516 setCursor (XLinkCursor);
4519 setCursor (Qt::ArrowCursor);
4525 void MapEditor::keyReleaseEvent(QKeyEvent* e)
4527 if (!(e->modifiers() & Qt::ControlModifier))
4528 setCursor (Qt::ArrowCursor);
4531 void MapEditor::mousePressEvent(QMouseEvent* e)
4533 // Ignore right clicks, these will go to context menus
4534 if (e->button() == Qt::RightButton )
4540 //Ignore clicks while editing heading
4541 if (isSelectBlocked() )
4547 QPointF p = mapToScene(e->pos());
4548 LinkableMapObj* lmo=model->findMapObj(p, NULL);
4552 //Take care of system flags _or_ modifier modes
4554 if (lmo && (typeid(*lmo)==typeid(BranchObj) ||
4555 typeid(*lmo)==typeid(MapCenterObj) ))
4557 QString foname=((BranchObj*)lmo)->getSystemFlagName(p);
4558 if (!foname.isEmpty())
4560 // systemFlag clicked
4564 if (e->state() & Qt::ControlModifier)
4565 mainWindow->editOpenURLTab();
4567 mainWindow->editOpenURL();
4569 else if (foname=="vymLink")
4571 mainWindow->editOpenVymLink();
4572 // tabWidget may change, better return now
4573 // before segfaulting...
4574 } else if (foname=="note")
4575 mainWindow->windowToggleNoteEditor();
4576 else if (foname=="hideInExport")
4583 // No system flag clicked, take care of modmodes (CTRL-Click)
4584 if (e->state() & Qt::ControlModifier)
4586 if (mainWindow->getModMode()==Main::ModModeColor)
4589 setCursor (PickColorCursor);
4592 if (mainWindow->getModMode()==Main::ModModeXLink)
4594 BranchObj *bo_begin=NULL;
4596 bo_begin=(BranchObj*)(lmo);
4598 if (xelection.getBranch() )
4599 bo_begin=xelection.getBranch();
4603 linkingObj_src=bo_begin;
4604 tmpXLink=new XLinkObj (mapScene);
4605 tmpXLink->setBegin (bo_begin);
4606 tmpXLink->setEnd (p);
4607 tmpXLink->setColor(defXLinkColor);
4608 tmpXLink->setWidth(defXLinkWidth);
4609 tmpXLink->updateXLink();
4610 tmpXLink->setVisibility (true);
4614 } // End of modmodes
4618 // Select the clicked object
4621 // Left Button Move Branches
4622 if (e->button() == Qt::LeftButton )
4624 //movingObj_start.setX( p.x() - selection->x() );// TODO replaced selection->lmo here
4625 //movingObj_start.setY( p.y() - selection->y() );
4626 movingObj_start.setX( p.x() - lmo->x() );
4627 movingObj_start.setY( p.y() - lmo->y() );
4628 movingObj_orgPos.setX (lmo->x() );
4629 movingObj_orgPos.setY (lmo->y() );
4630 movingObj_orgRelPos=lmo->getRelPos();
4632 // If modMode==copy, then we want to "move" the _new_ object around
4633 // then we need the offset from p to the _old_ selection, because of tmp
4634 if (mainWindow->getModMode()==Main::ModModeCopy &&
4635 e->state() & Qt::ControlModifier)
4637 BranchObj *bo=xelection.getBranch();
4641 bo->addBranch ((BranchObj*)xelection.single());
4643 xelection.select(bo->getLastBranch());
4644 model->reposition();
4648 movingObj=xelection.single();
4650 // Middle Button Toggle Scroll
4651 // (On Mac OS X this won't work, but we still have
4652 // a button in the toolbar)
4653 if (e->button() == Qt::MidButton )
4658 { // No MapObj found, we are on the scene itself
4659 // Left Button move Pos of sceneView
4660 if (e->button() == Qt::LeftButton )
4662 movingObj=NULL; // move Content not Obj
4663 movingObj_start=e->globalPos();
4664 movingCont_start=QPointF (
4665 horizontalScrollBar()->value(),
4666 verticalScrollBar()->value());
4667 movingVec=QPointF(0,0);
4668 setCursor(HandOpenCursor);
4673 void MapEditor::mouseMoveEvent(QMouseEvent* e)
4675 QPointF p = mapToScene(e->pos());
4676 LinkableMapObj *lmosel=xelection.single();
4678 // Move the selected MapObj
4679 if ( lmosel && movingObj)
4681 // reset cursor if we are moving and don't copy
4682 if (mainWindow->getModMode()!=Main::ModModeCopy)
4683 setCursor (Qt::ArrowCursor);
4685 // To avoid jumping of the sceneView, only
4686 // ensureSelectionVisible, if not tmp linked
4687 if (!lmosel->hasParObjTmp())
4688 ensureSelectionVisible ();
4690 // Now move the selection, but add relative position
4691 // (movingObj_start) where selection was chosen with
4692 // mousepointer. (This avoids flickering resp. jumping
4693 // of selection back to absPos)
4695 // Check if we could link
4696 LinkableMapObj* lmo=model->findMapObj(p, lmosel);
4699 FloatObj *fio=xelection.getFloatImage();
4702 fio->move (p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
4704 fio->updateLink(); //no need for reposition, if we update link here
4707 // Relink float to new mapcenter or branch, if shift is pressed
4708 // Only relink, if selection really has a new parent
4709 if ( (e->modifiers()==Qt::ShiftModifier) && lmo &&
4710 ( (typeid(*lmo)==typeid(BranchObj)) ||
4711 (typeid(*lmo)==typeid(MapCenterObj)) ) &&
4712 ( lmo != fio->getParObj())
4715 if (typeid(*fio) == typeid(FloatImageObj) &&
4716 ( (typeid(*lmo)==typeid(BranchObj) ||
4717 typeid(*lmo)==typeid(MapCenterObj)) ))
4720 // Also save the move which was done so far
4721 QString pold=qpointfToString(movingObj_orgRelPos);
4722 QString pnow=qpointfToString(fio->getRelPos());
4728 QString("Move %1 to relative position %2").arg(getName(fio)).arg(pnow));
4729 fio->getParObj()->requestReposition();
4730 model->reposition();
4732 linkTo (model->getSelectString(lmo));
4734 //movingObj_orgRelPos=lmosel->getRelPos();
4736 model->reposition();
4740 { // selection != a FloatObj
4741 if (lmosel->getDepth()==0)
4744 if (e->buttons()== Qt::LeftButton && e->modifiers()==Qt::ShiftModifier)
4745 ((MapCenterObj*)lmosel)->moveAll(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
4747 lmosel->move (p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
4748 model->updateRelPositions();
4751 if (lmosel->getDepth()==1)
4754 lmosel->move(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
4755 lmosel->setRelPos();
4758 // Move ordinary branch
4759 if (lmosel->getOrientation() == LinkableMapObj::LeftOfCenter)
4760 // Add width of bbox here, otherwise alignRelTo will cause jumping around
4761 lmosel->move(p.x() -movingObj_start.x()+lmosel->getBBox().width(),
4762 p.y()-movingObj_start.y() +lmosel->getTopPad() );
4764 lmosel->move(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() -lmosel->getTopPad());
4767 // Maybe we can relink temporary?
4768 if (lmo && (lmo!=lmosel) && xelection.getBranch() &&
4769 (typeid(*lmo)==typeid(BranchObj) ||
4770 typeid(*lmo)==typeid(MapCenterObj)) )
4773 if (e->modifiers()==Qt::ControlModifier)
4775 // Special case: CTRL to link below lmo
4776 lmosel->setParObjTmp (lmo,p,+1);
4778 else if (e->modifiers()==Qt::ShiftModifier)
4779 lmosel->setParObjTmp (lmo,p,-1);
4781 lmosel->setParObjTmp (lmo,p,0);
4784 lmosel->unsetParObjTmp();
4786 // reposition subbranch
4787 lmosel->reposition();
4791 } // no FloatImageObj
4795 } // selection && moving_obj
4797 // Draw a link from one branch to another
4800 tmpXLink->setEnd (p);
4801 tmpXLink->updateXLink();
4805 if (!movingObj && !pickingColor &&!drawingLink && e->buttons() == Qt::LeftButton )
4807 QPointF p=e->globalPos();
4808 movingVec.setX(-p.x() + movingObj_start.x() );
4809 movingVec.setY(-p.y() + movingObj_start.y() );
4810 horizontalScrollBar()->setSliderPosition((int)( movingCont_start.x()+movingVec.x() ));
4811 verticalScrollBar()->setSliderPosition((int)( movingCont_start.y()+movingVec.y() ) );
4816 void MapEditor::mouseReleaseEvent(QMouseEvent* e)
4818 QPointF p = mapToScene(e->pos());
4819 LinkableMapObj *dst;
4820 LinkableMapObj *lmosel=xelection.single();
4821 // Have we been picking color?
4825 setCursor (Qt::ArrowCursor);
4826 // Check if we are over another branch
4827 dst=model->findMapObj(p, NULL);
4830 if (e->state() & Qt::ShiftModifier)
4831 colorBranch (((BranchObj*)dst)->getColor());
4833 colorSubtree (((BranchObj*)dst)->getColor());
4838 // Have we been drawing a link?
4842 // Check if we are over another branch
4843 dst=model->findMapObj(p, NULL);
4846 tmpXLink->setEnd ( ((BranchObj*)(dst)) );
4847 tmpXLink->updateXLink();
4848 tmpXLink->activate(); //FIXME savestate missing
4849 //saveStateComplete(QString("Activate xLink from %1 to %2").arg(getName(tmpXLink->getBegin())).arg(getName(tmpXLink->getEnd())) );
4858 // Have we been moving something?
4859 if ( lmosel && movingObj )
4861 FloatImageObj *fo=xelection.getFloatImage();
4864 // Moved FloatObj. Maybe we need to reposition
4865 QString pold=qpointfToString(movingObj_orgRelPos);
4866 QString pnow=qpointfToString(fo->getRelPos());
4872 QString("Move %1 to relative position %2").arg(getName(fo)).arg(pnow));
4874 fo->getParObj()->requestReposition();
4875 model->reposition();
4878 // Check if we are over another branch, but ignore
4879 // any found LMOs, which are FloatObjs
4880 dst=model->findMapObj(mapToScene(e->pos() ), lmosel);
4882 if (dst && (typeid(*dst)!=typeid(BranchObj) && typeid(*dst)!=typeid(MapCenterObj)))
4885 BranchObj *bo=xelection.getBranch();
4886 if (bo && bo->getDepth()==0)
4888 if (movingObj_orgPos != bo->getAbsPos())
4890 QString pold=qpointfToString(movingObj_orgPos);
4891 QString pnow=qpointfToString(bo->getAbsPos());
4897 QString("Move mapcenter %1 to position %2").arg(getName(bo)).arg(pnow));
4901 if (xelection.type() == Selection::Branch )
4902 { // A branch was moved
4904 // save the position in case we link to mapcenter
4905 QPointF savePos=QPointF (lmosel->getAbsPos() );
4907 // Reset the temporary drawn link to the original one
4908 lmosel->unsetParObjTmp();
4910 // For Redo we may need to save original selection
4911 QString preSelStr=model->getSelectString(lmosel);
4916 // We have a destination, relink to that
4918 BranchObj* bsel=xelection.getBranch();
4919 BranchObj* bdst=(BranchObj*)dst;
4921 QString preParStr=model->getSelectString (bsel->getParObj());
4922 QString preNum=QString::number (bsel->getNum(),10);
4923 QString preDstParStr;
4925 if (e->state() & Qt::ShiftModifier && dst->getParObj())
4927 preDstParStr=model->getSelectString (dst->getParObj());
4928 bsel->linkTo ( (BranchObj*)(bdst->getParObj()), bdst->getNum());
4930 if (e->state() & Qt::ControlModifier && dst->getParObj())
4933 preDstParStr=model->getSelectString (dst->getParObj());
4934 bsel->linkTo ( (BranchObj*)(bdst->getParObj()), bdst->getNum()+1);
4937 preDstParStr=model->getSelectString(dst);
4938 bsel->linkTo (bdst,-1);
4939 if (dst->getDepth()==0) bsel->move (savePos);
4941 QString postSelStr=model->getSelectString(lmosel);
4942 QString postNum=QString::number (bsel->getNum(),10);
4944 QString undoCom="linkTo (\""+
4945 preParStr+ "\"," + preNum +"," +
4946 QString ("%1,%2").arg(movingObj_orgPos.x()).arg(movingObj_orgPos.y())+ ")";
4948 QString redoCom="linkTo (\""+
4949 preDstParStr + "\"," + postNum + "," +
4950 QString ("%1,%2").arg(savePos.x()).arg(savePos.y())+ ")";
4955 QString("Relink %1 to %2").arg(getName(bsel)).arg(getName(dst)) );
4957 model->reposition(); // not necessary if we undo temporary move below
4960 // No destination, undo temporary move
4962 if (lmosel->getDepth()==1)
4964 // The select string might be different _after_ moving around.
4965 // Therefor reposition and then use string of old selection, too
4966 model->reposition();
4968 QPointF rp(lmosel->getRelPos());
4969 if (rp != movingObj_orgRelPos)
4971 QString ps=qpointfToString(rp);
4973 model->getSelectString(lmosel), "moveRel "+qpointfToString(movingObj_orgRelPos),
4974 preSelStr, "moveRel "+ps,
4975 QString("Move %1 to relative position %2").arg(getName(lmosel)).arg(ps));
4979 // Draw the original link, before selection was moved around
4980 if (settings.value("/animation/use",false).toBool() && lmosel->getDepth()>1)
4982 QPointF p=bo->getParObj()->getChildPos();
4983 lmosel->setRelPos(); // calc relPos first
4984 model->startAnimation(
4985 lmosel->getRelPos(),
4986 QPointF (movingObj_orgPos.x() - p.x(), movingObj_orgPos.y() - p.y() )
4989 model->reposition();
4993 // Finally resize scene, if needed
4997 // Just make sure, that actions are still ok,e.g. the move branch up/down buttons...
5000 // maybe we moved View: set old cursor
5001 setCursor (Qt::ArrowCursor);
5005 void MapEditor::mouseDoubleClickEvent(QMouseEvent* e)
5007 if (isSelectBlocked() )
5013 if (e->button() == Qt::LeftButton )
5015 QPointF p = mapToScene(e->pos());
5016 LinkableMapObj *lmo=model->findMapObj(p, NULL);
5017 if (lmo) { // MapObj was found
5018 // First select the MapObj than edit heading
5019 xelection.select(lmo);
5020 mainWindow->editHeading();
5025 void MapEditor::resizeEvent (QResizeEvent* e)
5027 QGraphicsView::resizeEvent( e );
5030 void MapEditor::dragEnterEvent(QDragEnterEvent *event)
5032 //for (unsigned int i=0;event->format(i);i++) // Debug mime type
5033 // cerr << event->format(i) << endl;
5035 if (event->mimeData()->hasImage())
5036 event->acceptProposedAction();
5038 if (event->mimeData()->hasUrls())
5039 event->acceptProposedAction();
5042 void MapEditor::dragMoveEvent(QDragMoveEvent *)
5046 void MapEditor::dragLeaveEvent(QDragLeaveEvent *event)
5051 void MapEditor::dropEvent(QDropEvent *event)
5053 BranchObj *sel=xelection.getBranch();
5057 foreach (QString format,event->mimeData()->formats())
5058 cout << "MapEditor: Dropped format: "<<qPrintable (format)<<endl;
5062 if (event->mimeData()->hasImage())
5064 QVariant imageData = event->mimeData()->imageData();
5065 addFloatImageInt (qvariant_cast<QPixmap>(imageData));
5067 if (event->mimeData()->hasUrls())
5068 uris=event->mimeData()->urls();
5076 for (int i=0; i<uris.count();i++)
5078 // Workaround to avoid adding empty branches
5079 if (!uris.at(i).toString().isEmpty())
5081 bo=sel->addBranch();
5084 s=uris.at(i).toLocalFile();
5087 QString file = QDir::fromNativeSeparators(s);
5088 heading = QFileInfo(file).baseName();
5090 if (file.endsWith(".vym", false))
5091 bo->setVymLink(file);
5093 bo->setURL(uris.at(i).toString());
5096 bo->setURL(uris.at(i).toString());
5099 if (!heading.isEmpty())
5100 bo->setHeading(heading);
5102 bo->setHeading(uris.at(i).toString());
5106 model->reposition();
5109 event->acceptProposedAction();
5113 void MapEditor::sendSelection()
5115 if (netstate!=Server) return;
5116 sendData (QString("select (\"%1\")").arg(xelection.getSelectString()) );
5119 void MapEditor::newServer()
5123 tcpServer = new QTcpServer(this);
5124 if (!tcpServer->listen(QHostAddress::Any,port)) {
5125 QMessageBox::critical(this, "vym server",
5126 QString("Unable to start the server: %1.").arg(tcpServer->errorString()));
5130 connect(tcpServer, SIGNAL(newConnection()), this, SLOT(newClient()));
5132 cout<<"Server is running on port "<<tcpServer->serverPort()<<endl;
5135 void MapEditor::connectToServer()
5138 server="salam.suse.de";
5140 clientSocket = new QTcpSocket (this);
5141 clientSocket->abort();
5142 clientSocket->connectToHost(server ,port);
5143 connect(clientSocket, SIGNAL(readyRead()), this, SLOT(readData()));
5144 connect(clientSocket, SIGNAL(error(QAbstractSocket::SocketError)),
5145 this, SLOT(displayNetworkError(QAbstractSocket::SocketError)));
5147 cout<<"connected to "<<qPrintable (server)<<" port "<<port<<endl;
5152 void MapEditor::newClient()
5154 QTcpSocket *newClient = tcpServer->nextPendingConnection();
5155 connect(newClient, SIGNAL(disconnected()),
5156 newClient, SLOT(deleteLater()));
5158 cout <<"ME::newClient at "<<qPrintable( newClient->peerAddress().toString() )<<endl;
5160 clientList.append (newClient);
5164 void MapEditor::sendData(const QString &s)
5166 if (clientList.size()==0) return;
5168 // Create bytearray to send
5170 QDataStream out(&block, QIODevice::WriteOnly);
5171 out.setVersion(QDataStream::Qt_4_0);
5173 // Reserve some space for blocksize
5176 // Write sendCounter
5177 out << sendCounter++;
5182 // Go back and write blocksize so far
5183 out.device()->seek(0);
5184 quint16 bs=(quint16)(block.size() - 2*sizeof(quint16));
5188 cout << "ME::sendData bs="<<bs<<" counter="<<sendCounter<<" s="<<qPrintable(s)<<endl;
5190 for (int i=0; i<clientList.size(); ++i)
5192 //cout << "Sending \""<<qPrintable (s)<<"\" to "<<qPrintable (clientList.at(i)->peerAddress().toString())<<endl;
5193 clientList.at(i)->write (block);
5197 void MapEditor::readData ()
5199 while (clientSocket->bytesAvailable() >=(int)sizeof(quint16) )
5202 cout <<"readData bytesAvail="<<clientSocket->bytesAvailable();
5206 QDataStream in(clientSocket);
5207 in.setVersion(QDataStream::Qt_4_0);
5215 cout << " t="<<qPrintable (t)<<endl;
5221 void MapEditor::displayNetworkError(QAbstractSocket::SocketError socketError)
5223 switch (socketError) {
5224 case QAbstractSocket::RemoteHostClosedError:
5226 case QAbstractSocket::HostNotFoundError:
5227 QMessageBox::information(this, vymName +" Network client",
5228 "The host was not found. Please check the "
5229 "host name and port settings.");
5231 case QAbstractSocket::ConnectionRefusedError:
5232 QMessageBox::information(this, vymName + " Network client",
5233 "The connection was refused by the peer. "
5234 "Make sure the fortune server is running, "
5235 "and check that the host name and port "
5236 "settings are correct.");
5239 QMessageBox::information(this, vymName + " Network client",
5240 QString("The following error occurred: %1.")
5241 .arg(clientSocket->errorString()));
5245 void MapEditor::autosave()
5247 QDateTime now=QDateTime().currentDateTime();
5249 cout << "ME::autosave checking "<<qPrintable(filePath)<<"...\n";
5250 cout << "fsaved: "<<qPrintable (fileChangedTime.toString())<<endl;
5251 cout << " fnow: "<<qPrintable (QFileInfo(filePath).lastModified().toString())<<endl;
5252 cout << " time: "<<qPrintable (now.toString())<<endl;
5253 cout << " zipped="<<zipped<<endl;
5255 // Disable autosave, while we have gone back in history
5256 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
5257 if (redosAvail>0) return;
5259 // Also disable autosave for new map without filename
5260 if (filePath.isEmpty()) return;
5263 if (mapUnsaved &&mapChanged && settings.value ("/mapeditor/autosave/use",true).toBool() )
5265 if (QFileInfo(filePath).lastModified()<=fileChangedTime)
5266 mainWindow->fileSave (this);
5269 cout <<" ME::autosave rejected, file on disk is newer than last save.\n";
5274 void MapEditor::fileChanged()
5276 // Check if file on disk has changed meanwhile
5277 if (!filePath.isEmpty())
5279 QDateTime tmod=QFileInfo (filePath).lastModified();
5280 if (tmod>fileChangedTime)
5283 /* FIXME debug message, sometimes there's a glitch in the metrics...
5284 cout << "ME::fileChanged()\n"
5285 << " last saved: "<<qPrintable (fileChangedTime.toString())<<endl
5286 << " last modififed: "<<qPrintable (tmod.toString())<<endl;
5288 // FIXME switch to current mapeditor and finish lineedits...
5289 QMessageBox mb( vymName,
5290 tr("The file of the map on disk has changed:\n\n"
5291 " %1\n\nDo you want to reload that map with the new file?").arg(filePath),
5292 QMessageBox::Question,
5294 QMessageBox::Cancel | QMessageBox::Default,
5295 QMessageBox::NoButton );
5297 mb.setButtonText( QMessageBox::Yes, tr("Reload"));
5298 mb.setButtonText( QMessageBox::No, tr("Ignore"));
5301 case QMessageBox::Yes:
5303 load (filePath,NewMap,fileType);
5304 case QMessageBox::Cancel:
5305 fileChangedTime=tmod; // allow autosave to overwrite newer file!
5313 /*TODO not needed? void MapEditor::contentsDropEvent(QDropEvent *event)
5316 } else if (event->provides("application/x-moz-file-promise-url") &&
5317 event->provides("application/x-moz-nativeimage"))
5319 // Contains url to the img src in unicode16
5320 QByteArray d = event->encodedData("application/x-moz-file-promise-url");
5321 QString url = QString((const QChar*)d.data(),d.size()/2);
5325 } else if (event->provides ("text/uri-list"))
5326 { // Uris provided e.g. by konqueror
5327 Q3UriDrag::decode (event,uris);
5328 } else if (event->provides ("_NETSCAPE_URL"))
5329 { // Uris provided by Mozilla
5330 QStringList l = QStringList::split("\n", event->encodedData("_NETSCAPE_URL"));
5333 } else if (event->provides("text/html")) {
5335 // Handels text mime types
5336 // Look like firefox allways handle text as unicode16 (2 bytes per char.)
5337 QByteArray d = event->encodedData("text/html");
5340 text = QString((const QChar*)d.data(),d.size()/2);
5344 textEditor->setText(text);
5348 } else if (event->provides("text/plain")) {
5349 QByteArray d = event->encodedData("text/plain");
5352 text = QString((const QChar*)d.data(),d.size()/2);
5356 textEditor->setText(text);
5366 bool isUnicode16(const QByteArray &d)
5368 // TODO: make more precise check for unicode 16.
5369 // Guess unicode16 if any of second bytes are zero
5370 unsigned int length = max(0,d.size()-2)/2;
5371 for (unsigned int i = 0; i<length ; i++)
5372 if (d.at(i*2+1)==0) return true;
5376 void MapEditor::addFloatImageInt (const QPixmap &img)
5378 BranchObj *bo=xelection.getBranch();
5381 FloatImageObj *fio=bo->addFloatImage();
5383 fio->setOriginalFilename("No original filename (image added by dropevent)");
5384 QString s=model->getSelectString(bo);
5385 saveState (PartOfMap, s, "nop ()", s, "copy ()","Copy dropped image to clipboard",fio );
5386 saveState (fio,"delete ()", bo,QString("paste(%1)").arg(curStep),"Pasting dropped image");
5387 model->reposition();
5394 void MapEditor::imageDataFetched(const QByteArray &a, Q3NetworkOperation * / *nop* /)
5396 if (!imageBuffer) imageBuffer = new QBuffer();
5397 if (!imageBuffer->isOpen()) {
5398 imageBuffer->open(QIODevice::WriteOnly | QIODevice::Append);
5400 imageBuffer->at(imageBuffer->at()+imageBuffer->writeBlock(a));
5404 void MapEditor::imageDataFinished(Q3NetworkOperation *nop)
5406 if (nop->state()==Q3NetworkProtocol::StDone) {
5407 QPixmap img(imageBuffer->buffer());
5408 addFloatImageInt (img);
5412 imageBuffer->close();
5414 imageBuffer->close();
5421 void MapEditor::fetchImage(const QString &url)
5424 urlOperator->stop();
5425 disconnect(urlOperator);
5429 urlOperator = new Q3UrlOperator(url);
5430 connect(urlOperator, SIGNAL(finished(Q3NetworkOperation *)),
5431 this, SLOT(imageDataFinished(Q3NetworkOperation*)));
5433 connect(urlOperator, SIGNAL(data(const QByteArray &, Q3NetworkOperation *)),
5434 this, SLOT(imageDataFetched(const QByteArray &, Q3NetworkOperation *)));