3 #include <q3dragobject.h>
4 #include <q3urloperator.h>
5 #include <q3networkprotocol.h>
6 #include <q3paintdevicemetrics.h>
7 #include <q3filedialog.h>
16 #include "editxlinkdialog.h"
18 #include "extrainfodialog.h"
20 #include "linkablemapobj.h"
21 #include "mainwindow.h"
23 #include "texteditor.h"
24 #include "warningdialog.h"
28 extern TextEditor *textEditor;
29 extern int statusbarTime;
30 extern Main *mainWindow;
31 extern QString tmpVymDir;
32 extern QString clipboardDir;
33 extern bool clipboardEmpty;
34 extern FlagRowObj *standardFlagsDefault;
36 extern QMenu* branchContextMenu;
37 extern QMenu* branchAddContextMenu;
38 extern QMenu* branchRemoveContextMenu;
39 extern QMenu* branchLinksContextMenu;
40 extern QMenu* branchXLinksContextMenuEdit;
41 extern QMenu* branchXLinksContextMenuFollow;
42 extern QMenu* floatimageContextMenu;
43 extern QMenu* saveImageFormatMenu;
44 extern QMenu* canvasContextMenu;
45 extern QMenu* lastMapsMenu;
46 extern QMenu* importMenu;
47 extern QMenu* exportMenu;
50 extern Settings settings;
51 extern ImageIO imageIO;
53 extern QString iconPath;
54 extern QDir vymBaseDir;
55 extern QDir lastImageDir;
57 int MapEditor::mapNum=0; // make instance
59 ///////////////////////////////////////////////////////////////////////
60 ///////////////////////////////////////////////////////////////////////
62 QWidget* parent, const char* name, Qt::WFlags f) :
63 Q3CanvasView(parent,name,f), urlOperator(0), imageBuffer(0)
65 //cout << "Constructor ME "<<this<<endl;
68 viewport()->setAcceptDrops(true);
70 mapCanvas = new Q3Canvas(width(),height());
71 mapCanvas->setAdvancePeriod(30);
72 mapCanvas->setBackgroundColor (Qt::white);
74 setCanvas (mapCanvas);
76 // Always show scroll bars (automatic would flicker sometimes)
77 setVScrollBarMode ( Q3ScrollView::AlwaysOn );
78 setHScrollBarMode ( Q3ScrollView::AlwaysOn );
80 mapCenter = new MapCenterObj(mapCanvas);
81 mapCenter->setVisibility (true);
82 mapCenter->setMapEditor (this);
83 mapCenter->setHeading (tr("New Map","Heading of mapcenter in new map"));
84 mapCenter->move(mapCanvas->width()/2-mapCenter->width()/2,mapCanvas->height()/2-mapCenter->height()/2);
88 actColor=Qt::black; setColor (actColor);
89 defLinkColor=QColor (0,0,255);
90 defXLinkColor=QColor (180,180,180);
91 linkcolorhint=DefaultColor;
92 linkstyle=StylePolyParabel;
94 // Create bitmap cursors, platform dependant
95 #if defined(Q_OS_MACX)
96 handOpenCursor=QCursor ( QPixmap(iconPath+"cursorhandopen16.png"),1,1 );
97 pickColorCursor=QCursor ( QPixmap (iconPath+"cursorcolorpicker16.png"), 1,15 );
99 handOpenCursor=QCursor (QPixmap(iconPath+"cursorhandopen.png"),1,1);
100 pickColorCursor=QCursor ( QPixmap(iconPath+"cursorcolorpicker.png"), 5,27 );
112 xelection.setMapCenter (mapCenter);
115 defXLinkColor=QColor (230,230,230);
123 fileName=tr("unnamed");
126 stepsTotal=settings.readNumEntry("/mapeditor/stepsTotal",50);
127 undoSet.setEntry ("/history/stepsTotal",QString::number(stepsTotal));
129 // Initialize find routine
136 blockReposition=false;
137 blockSaveState=false;
141 // Create temporary files
144 // Initially set movingCentre
147 mapCenter->reposition(); // for positioning heading
149 // Initialize history window;
150 historyWindow.setME(this);
151 historyWindow.setStepsTotal(stepsTotal);
152 historyWindow.update (undoSet);
155 MapEditor::~MapEditor()
157 if (imageBuffer) delete imageBuffer;
163 //cout <<"Destructor MapEditor\n";
166 QColor MapEditor::getColor()
171 QColor MapEditor::getBackgroundColor()
173 return mapCanvas->backgroundColor();
176 MapCenterObj* MapEditor::getMapCenter()
181 Q3Canvas* MapEditor::getCanvas()
186 void MapEditor::adjustCanvasSize()
188 // To adjust the canvas to map, viewport size and position, we have to
189 // do some coordinate magic...
191 // Get rectangle of (scroll-)view.
192 // We want to be in canvas coords, so
193 // we map. Important if view is zoomed...
194 QRect view = inverseWorldMatrix().mapRect( QRect( contentsX(), contentsY(),
195 visibleWidth(), visibleHeight()) );
197 // Now we need the bounding box of view AND map to calc the correct canvas size.
198 // Why? Because if the map itself is moved out of view, the view has to be enlarged
199 // to avoid jumping aroung...
200 QRect map=mapCenter->getTotalBBox();
202 // right edge - left edge
203 int cw= max(map.x() + map.width(), view.x() + view.width()) - min(map.x(), view.x());
204 int ch= max(map.y() + map.height(), view.y() + view.height()) - min(map.y(), view.y());
207 if ( (cw!=mapCanvas->width()) || (ch!=mapCanvas->height()) ||
208 !mapCanvas->onCanvas (map.topLeft()) || !mapCanvas->onCanvas (map.bottomRight())
211 // move the map on canvas (in order to not move it on screen) this is neccessary
212 // a) if topleft corner of canvas is left or above topleft corner of view and also left of
213 // above topleft corner of map. E.g. if map is completly inside view, but it would be possible
214 // to scroll to an empty area of canvas to the left.
215 // b) if topleft corner of map left of or above topleft of canvas
219 if (cw > mapCanvas->width() )
221 if (map.x()<0) dx=-map.x();
223 if (cw < mapCanvas->width() )
224 dx=-min (view.x(),map.x());
225 if (ch > mapCanvas->height() )
227 if (map.y()<0) dy=-map.y();
229 if (ch < mapCanvas->height() )
231 dy=-min (view.y(),map.y());
233 // We really have to resize now. Let's go...
234 mapCanvas->resize (cw,ch);
235 if ( (dx!=0) || (dy!=0) )
237 mapCenter->moveAllBy(dx,dy);
238 mapCenter->reposition();
239 // mapCenter->positionBBox(); // To move float
241 // scroll the view (in order to not move map on screen)
247 bool MapEditor::isRepositionBlocked()
249 return blockReposition;
252 QString MapEditor::getName (LinkableMapObj *lmo)
255 if (!lmo) return QString("Error: NULL has no name!");
257 if ((typeid(*lmo) == typeid(BranchObj) ||
258 typeid(*lmo) == typeid(MapCenterObj)))
261 s=(((BranchObj*)lmo)->getHeading());
262 if (s=="") s="unnamed";
263 return QString("branch (%1)").arg(s);
264 //return QString("branch (<font color=\"#0000ff\">%1</font>)").arg(s);
266 if ((typeid(*lmo) == typeid(FloatImageObj) ))
267 return QString ("floatimage [%1]").arg(((FloatImageObj*)lmo)->getOriginalFilename());
268 //return QString ("floatimage [<font color=\"#0000ff\">%1</font>]").arg(((FloatImageObj*)lmo)->getOriginalFilename());
269 return QString("Unknown type has no name!");
272 void MapEditor::makeTmpDirs()
274 // Create unique temporary directories
275 tmpMapDir=QDir::convertSeparators (tmpVymDir+QString("/mapeditor-%1").arg(mapNum));
276 histPath=QDir::convertSeparators (tmpMapDir+"/history");
281 QString MapEditor::saveToDir(const QString &tmpdir, const QString &prefix, bool writeflags, const QPoint &offset, LinkableMapObj *saveSel)
283 // tmpdir temporary directory to which data will be written
284 // prefix mapname, which will be appended to images etc.
285 // writeflags Only write flags for "real" save of map, not undo
286 // offset offset of bbox of whole map in canvas.
287 // Needed for XML export
303 ls="StylePolyParabel";
307 QString s="<?xml version=\"1.0\" encoding=\"utf-8\"?><!DOCTYPE vymmap>\n";
309 if (linkcolorhint==HeadingColor)
310 colhint=attribut("linkColorHint","HeadingColor");
312 QString mapAttr=attribut("version",__VYM_VERSION);
314 mapAttr+= attribut("author",mapCenter->getAuthor()) +
315 attribut("comment",mapCenter->getComment()) +
316 attribut("date",mapCenter->getDate()) +
317 attribut("backgroundColor", mapCanvas->backgroundColor().name() ) +
318 attribut("linkStyle", ls ) +
319 attribut("linkColor", defLinkColor.name() ) +
320 attribut("defXLinkColor", defXLinkColor.name() ) +
321 attribut("defXLinkWidth", QString().setNum(defXLinkWidth,10) ) +
323 s+=beginElement("vymmap",mapAttr);
326 // Find the used flags while traversing the tree
327 standardFlagsDefault->resetUsedCounter();
329 // Reset the counters before saving
330 FloatImageObj (mapCanvas).resetSaveCounter();
332 // Build xml recursivly
334 // Save complete map, if saveSel not set
335 s+=mapCenter->saveToDir(tmpdir,prefix,writeflags,offset);
338 if ( typeid(*saveSel) == typeid(BranchObj) )
340 s+=((BranchObj*)(saveSel))->saveToDir(tmpdir,prefix,offset);
341 else if ( typeid(*saveSel) == typeid(FloatImageObj) )
343 s+=((FloatImageObj*)(saveSel))->saveToDir(tmpdir,prefix);
345 else if (selection && typeid(*selection)==typeid(BranchObj))
346 // Save selected branch is saved from mainwindow //FIXME maybe use "subtree" above?
347 s+=((BranchObj*)selection)->saveToDir(tmpdir,prefix,offset);
350 // Save local settings
351 s+=settings.getXMLData (destPath);
354 if (selection && !saveSel )
355 s+=valueElement("select",selection->getSelectString());
358 s+=endElement("vymmap");
361 standardFlagsDefault->saveToDir (tmpdir+"/flags/","",writeflags);
365 void MapEditor::saveStateComplete(const QString &comment)
367 // Save complete map, Undo will replace whole map
368 saveState (CompleteMap,
375 void MapEditor::saveStatePart(LinkableMapObj *undoSel, const QString &comment)
377 // save the selected part of the map, Undo will replace part of map
378 QString undoSelection="";
379 if (undoSel) undoSelection=undoSel->getSelectString();
381 saveState (PartOfMap,
388 void MapEditor::saveStateConstSelection(const QString &uc, const QString &rc, const QString &comment)
390 // selection does not change during action,
391 // so just save commands for undo and redo
392 // and use current selection
395 if (selection) sel=selection->getSelectString();
397 saveState (UndoCommand,
405 void MapEditor::saveStateComData(LinkableMapObj *undoSel, const QString &uc, LinkableMapObj *redoSel, const QString &rc, const QString &comment, LinkableMapObj *saveSel)
407 QString redoSelection="";
408 if (redoSel) redoSelection=redoSel->getSelectString();
409 QString undoSelection="";
410 if (undoSel) undoSelection=undoSel->getSelectString();
412 saveState (UndoCommand,
414 redoSelection, "FIXME-redoCom", //FIXME
420 void MapEditor::saveState(LinkableMapObj *undoSel, const QString &uc, LinkableMapObj *redoSel, const QString &rc, const QString &comment)
422 // "Normal" savestate: save commands, selections and comment
423 // so just save commands for undo and redo
424 // and use current selection
426 QString redoSelection="";
427 if (redoSel) redoSelection=redoSel->getSelectString();
428 QString undoSelection="";
429 if (undoSel) undoSelection=undoSel->getSelectString();
431 saveState (UndoCommand,
438 void MapEditor::saveState(const QString &undoSel, const QString &uc, const QString &redoSel, const QString &rc, const QString &comment)
440 // "Normal" savestate: save commands, selections and comment
441 // so just save commands for undo and redo
442 // and use current selection
443 saveState (UndoCommand,
451 void MapEditor::saveState(const SaveMode &savemode, const QString &undoSelection, const QString &undoCom, const QString &redoSelection, const QString &redoCom, const QString &comment, LinkableMapObj *saveSel)
455 if (blockSaveState) return;
457 /* TODO remove after testing
459 cout << "ME::saveState() "<<endl;
463 int undosAvail=undoSet.readNumEntry ("/history/undosAvail",0);
464 int redosAvail=undoSet.readNumEntry ("/history/redosAvail",0);
465 int curStep=undoSet.readNumEntry ("/history/curStep",0);
466 // Find out current undo directory
467 if (undosAvail<stepsTotal) undosAvail++;
469 if (curStep>stepsTotal) curStep=1;
472 QString bakMapName=QDir::convertSeparators (QString("history-%1").arg(curStep));
473 QString bakMapDir=QDir::convertSeparators (tmpMapDir +"/"+bakMapName);
474 QString bakMapPath=QDir::convertSeparators(bakMapDir+"/map.xml");
476 // Create bakMapDir if not available
479 makeSubDirs (bakMapDir);
481 // Save depending on how much needs to be saved
485 backupXML=saveToDir (bakMapDir,mapName+"-",false, QPoint (),saveSel);
487 QString undoCommand="";
488 if (savemode==UndoCommand)
492 else if (savemode==PartOfMap )
494 undoCommand="undoPart (\""+ undoSelection+"\",\""+bakMapPath+"\")";
497 undoCommand="undoMap (\""+bakMapPath+"\")";
499 if (!backupXML.isEmpty())
500 // Write XML Data to disk
501 saveStringToDisk (QString(bakMapPath),backupXML);
503 // We would have to save all actions in a tree, to keep track of
504 // possible redos after a action. Too complex, forget about redos.
507 // Write the current state to disk
508 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
509 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
510 undoSet.setEntry ("/history/curStep",QString::number(curStep));
511 undoSet.setEntry (QString("/history/step-%1/undoCommand").arg(curStep),undoCommand);
512 undoSet.setEntry (QString("/history/step-%1/undoSelection").arg(curStep),undoSelection);
513 undoSet.setEntry (QString("/history/step-%1/redoCommand").arg(curStep),redoCom);
514 undoSet.setEntry (QString("/history/step-%1/redoSelection").arg(curStep),redoSelection);
515 undoSet.setEntry (QString("/history/step-%1/comment").arg(curStep),comment);
516 undoSet.writeSettings(histPath);
518 /* TODO remove after testing
520 //cout << " into="<< histPath.toStdString()<<endl;
521 cout << " stepsTotal="<<stepsTotal<<
522 ", undosAvail="<<undosAvail<<
523 ", redosAvail="<<redosAvail<<
524 ", curStep="<<curStep<<endl;
525 cout << " ---------------------------"<<endl;
526 cout << " comment="<<comment.toStdString()<<endl;
527 cout << " undoCom="<<undoCommand.toStdString()<<endl;
528 cout << " undoSel="<<undoSelection.toStdString()<<endl;
529 cout << " redoCom="<<redoCom.toStdString()<<endl;
530 cout << " redoSel="<<redoSelection.toStdString()<<endl;
531 cout << " ---------------------------"<<endl;
533 historyWindow.update (undoSet);
536 void MapEditor::parseAtom(const QString &atom)
543 // Split string s into command and parameters
544 api.parseCommand (atom);
545 QString com=api.command();
548 if (com=="moveBranchUp")
550 else if (com=="moveBranchDown")
552 else if (com=="move")
554 if (api.checkParamCount(2) && selection )
564 else if (com=="moveRel")
566 if (api.checkParamCount(2) && selection )
572 if (ok) moveRel (x,y);
576 else if (com=="delete")
578 if (api.checkParamCount(1) && selection )
580 s=api.parString(ok,0);
581 if (ok &&select (s)) deleteSelection();
584 else if (com=="addBranch")
586 if (api.checkParamCount(1) && selection )
589 if (ok ) addNewBranchInt (y);
592 else if (com=="linkBranchToPos")
594 if (selection && typeid(*selection) == typeid(BranchObj) )
596 if (api.checkParamCount(4))
598 // 0 selectstring of parent
599 // 1 num in parent (for branches)
600 // 2,3 x,y of mainbranch or mapcenter
601 s=api.parString(ok,0);
602 LinkableMapObj *dst=mapCenter->findObjBySelect (s);
605 if (typeid(*dst) == typeid(BranchObj) )
607 // Get number in parent
610 ((BranchObj*)selection)->moveBranchTo ((BranchObj*)(dst),x);
611 } else if (typeid(*dst) == typeid(MapCenterObj) )
613 ((BranchObj*)selection)->moveBranchTo ((BranchObj*)(dst),-1);
614 // Get coordinates of mainbranch
619 if (ok) ((BranchObj*)selection)->move (x,y);
625 } else if (com=="setHeading")
627 if (api.checkParamCount(1))
629 s=api.parString (ok,0);
633 } else if (com=="setURL")
635 if (api.checkParamCount(1))
637 s=api.parString (ok,0);
638 if (ok) setURLInt(s);
640 } else if (com=="setVymLink")
642 if (api.checkParamCount(1))
644 s=api.parString (ok,0);
645 if (ok) setVymLinkInt(s);
648 else if (com=="setFlag")
650 if (selection && typeid(*selection) == typeid(BranchObj) )
652 if (api.checkParamCount(1) )
654 s=api.parString(ok,0);
657 BranchObj* bo=(BranchObj*)selection;
658 bo->activateStandardFlag(s);
659 bo->updateFlagsToolbar();
664 else if (com=="unsetFlag")
666 if (selection && typeid(*selection) == typeid(BranchObj) )
668 if (api.checkParamCount(1) )
670 s=api.parString(ok,0);
673 BranchObj* bo=(BranchObj*)selection;
674 bo->deactivateStandardFlag(s);
675 bo->updateFlagsToolbar();
680 // Internal commands, used for undo etc.
681 else if (com==QString("undoMap"))
683 if (api.checkParamCount(1))
684 undoXML("",api.parString (ok,0));
685 } else if (com==QString("undoPart"))
687 if (api.checkParamCount(2))
689 s=api.parString (ok,0); // undo selection
690 t=api.parString (ok,1); // backup dir
691 if (QDir::isRelativePath(t)) t=QDir::convertSeparators (tmpMapDir + "/"+t);
692 cout <<t.ascii()<<endl;
695 } else if (com=="select")
697 if (api.checkParamCount(1))
699 s=api.parString(ok,0);
705 api.setError ("Unknown command in: "+atom);
711 // TODO Error handling
712 qWarning("MapEditor::parseAtom: Error!");
713 qWarning(api.errorDesc());
717 void MapEditor::toggleHistoryWindow()
719 if (historyWindow.isVisible())
720 historyWindow.hide();
722 historyWindow.show();
726 bool MapEditor::isDefault()
731 bool MapEditor::isUnsaved()
736 bool MapEditor::hasChanged()
741 void MapEditor::setChanged()
749 void MapEditor::closeMap()
751 // Unselect before disabling the toolbar actions
752 if (selection) selection->unselect();
760 void MapEditor::setFilePath(QString fname)
762 setFilePath (fname,fname);
765 void MapEditor::setFilePath(QString fname, QString destname)
767 if (fname.isEmpty() || fname=="")
774 filePath=fname; // becomes absolute path
775 fileName=fname; // gets stripped of path
776 destPath=destname; // needed for vymlinks
778 // If fname is not an absolute path, complete it
779 filePath=QDir(fname).absPath();
780 fileDir=filePath.left (1+filePath.findRev ("/"));
782 // Set short name, too. Search from behind:
783 int i=fileName.findRev("/");
784 if (i>=0) fileName=fileName.remove (0,i+1);
786 // Forget the .vym (or .xml) for name of map
787 mapName=fileName.left(fileName.findRev(".",-1,true) );
789 // Adjust history window
790 historyWindow.setCaption (__VYM " - " +tr("History for ")+fileName);
794 QString MapEditor::getFilePath()
799 QString MapEditor::getFileName()
804 QString MapEditor::getMapName()
809 QString MapEditor::getDestPath()
814 ErrorCode MapEditor::load (QString fname, LoadMode lmode)
816 ErrorCode err=success;
820 if (selection) selection->unselect();
823 mapCenter->setMapEditor(this);
824 // (map state is set later at end of load...)
827 saveStatePart(selection,"Load map");
831 mapBuilderHandler handler;
834 // I am paranoid: file should exist anyway
835 // according to check in mainwindow.
838 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
839 tr("Couldn't open map " +fname)+".");
843 blockReposition=true;
844 QXmlInputSource source( file);
845 QXmlSimpleReader reader;
846 reader.setContentHandler( &handler );
847 reader.setErrorHandler( &handler );
848 handler.setMapEditor( this );
849 handler.setTmpDir (filePath.left(filePath.findRev("/",-1))); // needed to load files with rel. path
850 handler.setInputFile (file.name());
851 handler.setLoadMode (lmode);
853 bool ok = reader.parse( source );
854 blockReposition=false;
855 blockSaveState=false;
859 mapCenter->reposition();
869 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
870 tr( handler.errorProtocol() ) );
872 // Still return "success": the map maybe at least
873 // partially read by the parser
880 int MapEditor::save (const SaveMode &savemode)
884 // The SaveMode UndoCommand is not supported here
885 if (savemode==UndoCommand) return 1;
887 // Create mapName and fileDir
888 makeSubDirs (fileDir);
892 fname=mapName+".xml";
894 // use name given by user, even if he chooses .doc
899 if (savemode==CompleteMap || selection==NULL)
900 saveFile=saveToDir (fileDir,mapName+"-",true,QPoint(),NULL);
902 saveFile=saveToDir (fileDir,mapName+"-",true,QPoint(),selection);
904 if (!saveStringToDisk(fileDir+fname,saveFile))
917 void MapEditor::setZipped (bool z)
922 bool MapEditor::saveZipped ()
927 void MapEditor::print()
931 printer = new QPrinter;
932 printer->setColorMode (QPrinter::Color);
933 printer->setPrinterName (settings.value("/mainwindow/printerName",printer->printerName()).toString());
936 QRect totalBBox=mapCenter->getTotalBBox();
938 // Try to set orientation automagically
939 // Note: Interpretation of generated postscript is amibiguous, if
940 // there are problems with landscape mode, see
941 // http://sdb.suse.de/de/sdb/html/jsmeix_print-cups-landscape-81.html
943 if (totalBBox.width()>totalBBox.height())
944 // recommend landscape
945 printer->setOrientation (QPrinter::Landscape);
947 // recommend portrait
948 printer->setOrientation (QPrinter::Portrait);
950 if ( printer->setup(this) )
951 // returns false, if printing is canceled
953 QPainter pp(printer);
955 // Don't print the visualisation of selection
956 LinkableMapObj *oldselection=NULL;
959 oldselection=selection;
960 selection->unselect();
963 // Handle sizes of map and paper:
965 // setWindow defines which part of the canvas will be transformed
966 // setViewport defines area on paper in device coordinates (dpi)
967 // e.g. (0,50,700,700) is upper part on A4
968 // see also /usr/lib/qt3/doc/html/coordsys.html
970 Q3PaintDeviceMetrics metrics (printer);
972 double paperAspect = (double)metrics.width() / (double)metrics.height();
973 double mapAspect = (double)totalBBox.width() / (double)totalBBox.height();
975 QRect mapRect=totalBBox;
976 Q3CanvasRectangle *frame=NULL;
977 Q3CanvasText *footerFN=NULL;
978 Q3CanvasText *footerDate=NULL;
979 if (printFrame || printFooter)
984 // Print frame around map
985 mapRect.setRect (totalBBox.x()-10, totalBBox.y()-10,
986 totalBBox.width()+20, totalBBox.height()+20);
987 frame=new Q3CanvasRectangle (mapRect,mapCanvas);
988 frame->setBrush (QColor(Qt::white));
989 frame->setPen (QColor(Qt::black));
993 /* TODO remove after testing
994 QCanvasLine *l=new QCanvasLine (mapCanvas);
995 l->setPoints (0,0,mapRect.width(),mapRect.height());
996 l->setPen (QPen(QColor(black), 1));
1003 // Print footer below map
1005 font.setPointSize(10);
1006 footerFN=new Q3CanvasText (mapCanvas);
1007 footerFN->setText ("VYM - " + fileName);
1008 footerFN->setFont(font);
1009 footerFN->move (mapRect.x(), mapRect.y() + mapRect.height() );
1010 footerFN->setZ(Z_TEXT);
1012 footerDate=new Q3CanvasText (mapCanvas);
1013 footerDate->setText (QDate::currentDate().toString(Qt::TextDate));
1014 footerDate->setFont(font);
1015 footerDate->move (mapRect.x()+mapRect.width()-footerDate->boundingRect().width(), mapRect.y() + mapRect.height() );
1016 footerDate->setZ(Z_TEXT);
1019 pp.setWindow (mapRect.x(), mapRect.y(), mapRect.width(), mapRect.height()+20);
1022 pp.setWindow (mapRect);
1025 if (mapAspect>=paperAspect)
1027 // Fit horizontally to paper width
1028 pp.setViewport(0,0, metrics.width(),(int)(metrics.width()/mapAspect) );
1031 // Fit vertically to paper height
1032 pp.setViewport(0,0,(int)(metrics.height()*mapAspect),metrics.height());
1035 mapCanvas->drawArea(mapRect, &pp); // draw Canvas to printer
1037 // Delete Frame and footer
1041 delete (footerDate);
1043 if (frame) delete (frame);
1045 // Restore selection
1048 selection=oldselection;
1049 selection->select();
1052 // Save settings in vymrc
1053 settings.writeEntry("/mainwindow/printerName",printer->printerName());
1057 QPixmap MapEditor::getPixmap()
1059 QRect mapRect=mapCenter->getTotalBBox();
1060 QPixmap pix (mapRect.size());
1063 // Don't print the visualisation of selection
1064 LinkableMapObj *oldselection=NULL;
1067 oldselection=selection;
1068 selection->unselect();
1071 pp.setWindow (mapRect);
1073 mapCanvas->drawArea(mapRect, &pp); // draw Canvas to painter
1076 // Restore selection
1079 selection=oldselection;
1080 selection->select();
1086 void MapEditor::setHideTmpMode (HideTmpMode mode)
1089 mapCenter->setHideTmp (hidemode);
1090 mapCenter->reposition();
1095 HideTmpMode MapEditor::getHideTmpMode()
1100 void MapEditor::exportImage(QString fn)
1102 setExportMode (true);
1103 QPixmap pix (getPixmap());
1104 pix.save(fn, "PNG");
1105 setExportMode (false);
1108 void MapEditor::setExportMode (bool b)
1110 // should be called before and after exports
1111 // depending on the settings
1112 if (b && settings.value("/export/useHideExport","yes")=="yes")
1113 setHideTmpMode (HideExport);
1115 setHideTmpMode (HideNone);
1118 void MapEditor::exportImage(QString fn, QString format)
1120 setExportMode (true);
1121 QPixmap pix (getPixmap());
1122 pix.save(fn, format);
1123 setExportMode (false);
1126 void MapEditor::exportOOPresentation(const QString &fn, const QString &cf)
1130 ex.setMapCenter(mapCenter);
1131 if (ex.setConfigFile(cf))
1133 setExportMode (true);
1134 ex.exportPresentation();
1135 setExportMode (false);
1141 void MapEditor::exportXML(const QString &dir)
1143 // Hide stuff during export, if settings want this
1144 setExportMode (true);
1146 // Create subdirectories
1149 // write to directory
1150 QString saveFile=saveToDir (dir,mapName+"-",true,mapCenter->getTotalBBox().topLeft() ,NULL);
1153 file.setName ( dir + "/"+mapName+".xml");
1154 if ( !file.open( QIODevice::WriteOnly ) )
1156 // This should neverever happen
1157 QMessageBox::critical (0,tr("Critical Export Error"),tr("MapEditor::exportXML couldn't open %1").arg(file.name()));
1161 // Write it finally, and write in UTF8, no matter what
1162 QTextStream ts( &file );
1163 ts.setEncoding (QTextStream::UnicodeUTF8);
1167 // Now write image, too
1168 exportImage (dir+"/images/"+mapName+".png");
1170 setExportMode (false);
1173 void MapEditor::clear()
1177 selection->unselect();
1184 void MapEditor::copy()
1188 // write to directory
1189 QString clipfile="part";
1190 QString saveFile=saveToDir (fileDir,clipfile+"-",true,QPoint(),selection);
1193 file.setName ( clipboardDir + "/"+clipfile+".xml");
1194 if ( !file.open( QIODevice::WriteOnly ) )
1196 // This should neverever happen
1197 QMessageBox::critical (0,tr("Critical Export Error"),tr("MapEditor::exportXML couldn't open %1").arg(file.name()));
1201 // Write it finally, and write in UTF8, no matter what
1202 QTextStream ts( &file );
1203 ts.setEncoding (QTextStream::UnicodeUTF8);
1207 clipboardEmpty=false;
1212 void MapEditor::redo()
1214 blockSaveState=true;
1216 // Restore variables
1217 int curStep=undoSet.readNumEntry (QString("/history/curStep"));
1218 int undosAvail=undoSet.readNumEntry (QString("/history/undosAvail"));
1219 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
1220 // Can we undo at all?
1221 if (redosAvail<1) return;
1224 if (undosAvail<stepsTotal) undosAvail++;
1226 if (curStep>stepsTotal) curStep=1;
1227 QString undoCommand= undoSet.readEntry (QString("/history/step-%1/undoCommand").arg(curStep));
1228 QString undoSelection=undoSet.readEntry (QString("/history/step-%1/undoSelection").arg(curStep));
1229 QString redoCommand= undoSet.readEntry (QString("/history/step-%1/redoCommand").arg(curStep));
1230 QString redoSelection=undoSet.readEntry (QString("/history/step-%1/redoSelection").arg(curStep));
1231 QString comment=undoSet.readEntry (QString("/history/step-%1/comment").arg(curStep));
1233 // Find out current undo directory
1234 QString bakMapDir=QDir::convertSeparators (QString(tmpMapDir+"/undo-%1").arg(curStep));
1236 /* TODO remove testing
1238 cout << "ME::redo() begin\n";
1239 cout << " undosAvail="<<undosAvail<<endl;
1240 cout << " redosAvail="<<redosAvail<<endl;
1241 cout << " curStep="<<curStep<<endl;
1242 cout << " ---------------------------"<<endl;
1243 cout << " comment="<<comment.toStdString()<<endl;
1244 cout << " undoCom="<<undoCommand.toStdString()<<endl;
1245 cout << " undoSel="<<undoSelection.toStdString()<<endl;
1246 cout << " redoCom="<<redoCommand.toStdString()<<endl;
1247 cout << " redoSel="<<redoSelection.toStdString()<<endl;
1248 cout << " ---------------------------"<<endl<<endl;
1250 // select object before redo
1251 // FIXME better give up if no selection there...
1252 if (!redoSelection.isEmpty())
1253 select (redoSelection);
1256 parseAtom (redoCommand);
1257 mapCenter->reposition();
1259 blockSaveState=false;
1261 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
1262 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
1263 undoSet.setEntry ("/history/curStep",QString::number(curStep));
1264 undoSet.writeSettings(histPath);
1266 historyWindow.update (undoSet);
1269 /* TODO remove testing
1271 cout << "ME::redo() end\n";
1272 cout << " undosAvail="<<undosAvail<<endl;
1273 cout << " redosAvail="<<redosAvail<<endl;
1274 cout << " curStep="<<curStep<<endl;
1275 cout << " ---------------------------"<<endl<<endl;
1280 bool MapEditor::isRedoAvailable()
1282 if (undoSet.readNumEntry("/history/undosAvail",0)>0)
1288 void MapEditor::undo()
1290 blockSaveState=true;
1292 // Restore variables
1293 int curStep=undoSet.readNumEntry (QString("/history/curStep"));
1294 int undosAvail=undoSet.readNumEntry (QString("/history/undosAvail"));
1295 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
1297 // Can we undo at all?
1298 if (undosAvail<1) return;
1300 QString undoCommand= undoSet.readEntry (QString("/history/step-%1/undoCommand").arg(curStep));
1301 QString undoSelection=undoSet.readEntry (QString("/history/step-%1/undoSelection").arg(curStep));
1302 QString redoCommand= undoSet.readEntry (QString("/history/step-%1/redoCommand").arg(curStep));
1303 QString redoSelection=undoSet.readEntry (QString("/history/step-%1/redoSelection").arg(curStep));
1304 QString comment=undoSet.readEntry (QString("/history/step-%1/comment").arg(curStep));
1306 // Find out current undo directory
1307 QString bakMapDir=QDir::convertSeparators (QString(tmpMapDir+"/undo-%1").arg(curStep));
1309 // select object before undo
1310 if (!undoSelection.isEmpty())
1311 select (undoSelection);
1315 cout << "ME::undo() begin\n";
1316 cout << " undosAvail="<<undosAvail<<endl;
1317 cout << " redosAvail="<<redosAvail<<endl;
1318 cout << " curStep="<<curStep<<endl;
1319 cout << " ---------------------------"<<endl;
1320 cout << " comment="<<comment.toStdString()<<endl;
1321 cout << " undoCom="<<undoCommand.toStdString()<<endl;
1322 cout << " undoSel="<<undoSelection.toStdString()<<endl;
1323 cout << " redoCom="<<redoCommand.toStdString()<<endl;
1324 cout << " redoSel="<<redoSelection.toStdString()<<endl;
1325 cout << " ---------------------------"<<endl<<endl;
1326 parseAtom (undoCommand);
1327 mapCenter->reposition();
1331 if (curStep<1) curStep=stepsTotal;
1335 blockSaveState=false;
1336 /* TODO remove testing
1338 cout << "ME::undo() end\n";
1339 cout << " undosAvail="<<undosAvail<<endl;
1340 cout << " redosAvail="<<redosAvail<<endl;
1341 cout << " curStep="<<curStep<<endl;
1342 cout << " ---------------------------"<<endl<<endl;
1344 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
1345 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
1346 undoSet.setEntry ("/history/curStep",QString::number(curStep));
1347 undoSet.writeSettings(histPath);
1349 historyWindow.update (undoSet);
1353 bool MapEditor::isUndoAvailable()
1355 if (undoSet.readNumEntry("/history/undosAvail",0)>0)
1361 void MapEditor::gotoStep (int i)
1363 // Restore variables
1364 int undosAvail=undoSet.readNumEntry (QString("/history/undosAvail"));
1365 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
1367 cout << "ME::goto "<<i<<endl;
1369 if (i<0) i=undosAvail+redosAvail;
1371 // Clicking above current step makes us undo things
1374 for (int j=0; j<undosAvail-i; j++) undo();
1377 // Clicking below current step makes us redo things
1379 for (int j=undosAvail; j<i; j++) redo();
1381 // And ignore clicking the current row ;-)
1384 void MapEditor::undoXML(const QString &undoSel, const QString &bakMapPath)
1386 QString bakMapDir=bakMapPath.left(bakMapPath.findRev("/"));
1388 QFile file (bakMapPath);
1392 // We need to parse saved XML data
1393 mapBuilderHandler handler;
1394 QXmlInputSource source( file);
1395 QXmlSimpleReader reader;
1396 reader.setContentHandler( &handler );
1397 reader.setErrorHandler( &handler );
1398 handler.setMapEditor( this );
1399 handler.setTmpDir ( bakMapDir ); // needed to load files with rel. path
1400 if (undoSel.isEmpty())
1404 handler.setLoadMode (NewMap);
1408 handler.setLoadMode (ImportReplace);
1410 blockReposition=true;
1411 bool ok = reader.parse( source );
1412 blockReposition=false;
1415 // This should never ever happen
1416 QMessageBox::critical( 0, tr( "Critical Parse Error by reading backupFile" ),
1417 tr( handler.errorProtocol() )+" in "+bakMapDir );
1421 QMessageBox::critical( 0, tr( "Critical Error" ),
1422 tr("Temporary directory %1 used for undo is gone. \n"
1423 "I will create a new one, but at the moment no undo is available.\n"
1424 "Maybe you want to reload your original data.\n\n"
1425 "Sorry for any inconveniences.").arg(bakMapDir) );
1430 void MapEditor::pasteNoSave()
1432 load (clipboardDir+"/part.xml",ImportAdd);
1435 void MapEditor::cutNoSave()
1441 void MapEditor::paste()
1443 if (selection && (typeid(*selection) == typeid(BranchObj) ||
1444 typeid(*selection) == typeid(MapCenterObj)))
1446 saveStatePart(selection,QString("Paste to %1").arg( getName(selection)));
1448 mapCenter->reposition();
1453 void MapEditor::cut()
1455 saveStatePart(selection->getParObj(),QString("Cut %1").arg(getName(selection)));
1458 mapCenter->reposition();
1462 void MapEditor::move(const int &x, const int &y)
1466 QString ps=qpointToString (selection->getAbsPos());
1467 QString s=selection->getSelectString();
1470 s, "move "+qpointToString (QPoint (x,y)),
1471 QString("Move %1 to %2").arg(getName(selection)).arg(ps));
1472 selection->move(x,y);
1473 mapCenter->reposition();
1479 void MapEditor::moveRel (const int &x, const int &y)
1481 if (selection && (typeid(*selection) == typeid(BranchObj) ||
1482 typeid(*selection) == typeid(MapCenterObj) ||
1483 typeid(*selection) == typeid (FloatImageObj)))
1485 QString ps=qpointToString (selection->getRelPos());
1486 QString s=selection->getSelectString();
1489 s, "moveRel "+qpointToString (QPoint (x,y)),
1490 QString("Move %1 to relativ position %2").arg(getName(selection)).arg(ps));
1491 ((OrnamentedObj*)selection)->move2RelPos (x,y);
1492 mapCenter->reposition();
1497 void MapEditor::moveBranchUp()
1501 if (typeid(*selection) == typeid(BranchObj) )
1503 bo=(BranchObj*)selection;
1504 if (!bo->canMoveBranchUp()) return;
1505 par=(BranchObj*)(bo->getParObj());
1506 selection->unselect();
1507 bo=par->moveBranchUp (bo); // bo will be the one below selection
1508 selection->select();
1509 saveState (selection,"moveBranchDown ()",bo,"moveBranchUp ()",QString("Move up %1").arg(getName(bo)));
1510 mapCenter->reposition();
1511 ensureSelectionVisible();
1515 void MapEditor::moveBranchDown()
1519 if (typeid(*selection) == typeid(BranchObj) )
1521 bo=(BranchObj*)selection;
1522 if (!bo->canMoveBranchDown()) return;
1523 par=(BranchObj*)(bo->getParObj());
1524 selection->unselect();
1525 bo=par->moveBranchDown(bo); // bo will be the one above selection
1526 selection->select();
1527 saveState(selection,"moveBranchUp ()",bo,"moveBranchDown ()",QString("Move down %1").arg(getName(bo)));
1528 mapCenter->reposition();
1529 ensureSelectionVisible();
1533 QString MapEditor::getHeading(bool &ok, QPoint &p)
1536 (typeid(*selection) == typeid(BranchObj) ||
1537 typeid(*selection) == typeid(MapCenterObj) ) )
1540 ensureSelectionVisible();
1541 p = ((BranchObj*)selection)->getAbsPos();
1542 p.setX (p.x() - contentsX());
1543 p.setY (p.y() - contentsY() + ((BranchObj*)selection)->height()/2);
1544 return ((BranchObj*)selection)->getHeading();
1550 void MapEditor::setHeading(const QString &s)
1553 (typeid(*selection) == typeid(BranchObj) ||
1554 typeid(*selection) == typeid(MapCenterObj) ) )
1556 editingBO=(BranchObj*)selection;
1557 saveStateConstSelection(
1558 "setHeading (\""+editingBO->getHeading()+"\")",
1559 "setHeading (\""+s+"\")",
1560 QString("Set heading of %1 to \"%2\"").arg(getName(editingBO)).arg(s) );
1561 editingBO->setHeading(s );
1563 mapCenter->reposition();
1565 ensureSelectionVisible();
1569 void MapEditor::setURLInt (const QString &s)
1571 // Internal function, no saveState needed
1573 (typeid(*selection) == typeid(BranchObj) ||
1574 typeid(*selection) == typeid(MapCenterObj) ) )
1576 ((BranchObj*)selection)->setURL(s);
1577 mapCenter->reposition();
1579 ensureSelectionVisible();
1583 void MapEditor::setHeadingInt(const QString &s)
1586 (typeid(*selection) == typeid(BranchObj) ||
1587 typeid(*selection) == typeid(MapCenterObj) ) )
1589 ((BranchObj*)selection)->setHeading(s);
1590 mapCenter->reposition();
1592 ensureSelectionVisible();
1596 void MapEditor::setVymLinkInt (const QString &s)
1598 // Internal function, no saveState needed
1600 (typeid(*selection) == typeid(BranchObj) ||
1601 typeid(*selection) == typeid(MapCenterObj) ) )
1603 ((BranchObj*)selection)->setVymLink(s);
1604 mapCenter->reposition();
1606 ensureSelectionVisible();
1610 BranchObj* MapEditor::addNewBranchInt(int num)
1612 // Depending on pos:
1613 // -3 insert in childs of parent above selection
1614 // -2 add branch to selection
1615 // -1 insert in childs of parent below selection
1616 // 0..n insert in childs of parent at pos
1617 BranchObj *newbo=NULL;
1619 (typeid(*selection) == typeid(BranchObj) ||
1620 typeid(*selection) == typeid(MapCenterObj) ) )
1622 BranchObj* bo = (BranchObj*) selection;
1625 // save scroll state. If scrolled, automatically select
1626 // new branch in order to tmp unscroll parent...
1627 return bo->addBranch();
1632 bo=(BranchObj*)bo->getParObj();
1636 bo=(BranchObj*)bo->getParObj();
1639 newbo=bo->insertBranch(num);
1644 void MapEditor::addNewBranch(int pos)
1646 // Different meaning than num in addNewBranchInt!
1651 (typeid(*selection) == typeid(BranchObj) ||
1652 typeid(*selection) == typeid(MapCenterObj) ) )
1654 BranchObj *bo = (BranchObj*) selection;
1656 newbo=addNewBranchInt (pos-2);
1660 saveStateConstSelection (
1661 QString ("delete (\"%1\")").arg(newbo->getSelectString()),
1662 QString ("addBranch (%1)").arg(pos-2),
1663 QString ("Add new branch to %1").arg(getName(bo))); //TODO undoCommand
1665 LinkableMapObj *oldselection=selection;
1667 mapCenter->reposition();
1671 if (mainWindow->autoEdit() ||
1672 mainWindow->autoSelectHeading() )
1674 selection->unselect();
1676 selection->select();
1677 if (mainWindow->autoEdit() )
1678 mainWindow->editHeading();
1679 if (!mainWindow->autoSelectHeading()
1680 )//&& !wasScrolled) //FIXME wasScrolled was moved to addNewBranchInt
1682 selection->unselect();
1683 selection=oldselection;
1684 selection->select();
1692 void MapEditor::addNewBranchHere()
1695 (typeid(*selection) == typeid(BranchObj) ) )
1697 BranchObj* bo1 = (BranchObj*) selection;
1698 saveStatePart(selection, QString("Add new branch here").arg(getName(bo1)));
1700 bool wasScrolled=false;
1701 BranchObj *newbo=NULL;
1702 BranchObj *parbo=(BranchObj*)(selection->getParObj());
1705 // add below selection
1706 newbo=parbo->insertBranch(bo1->getNum()+1);
1709 LinkableMapObj *oldselection=selection;
1710 ((BranchObj*)selection)->moveBranchTo (newbo,-1);
1712 mapCenter->reposition();
1714 if (mainWindow->autoEdit() ||
1715 mainWindow->autoSelectHeading() )
1717 selection->unselect();
1719 selection->select();
1720 if (mainWindow->autoEdit() )
1721 mainWindow->editHeading();
1722 if (!mainWindow->autoSelectHeading()
1725 selection->unselect();
1726 selection=oldselection;
1727 selection->select();
1733 void MapEditor::deleteSelection()
1735 if (selection && typeid(*selection) ==typeid(BranchObj) )
1737 BranchObj* bo=(BranchObj*)selection;
1738 BranchObj* par=(BranchObj*)(bo->getParObj());
1740 if (selection->getDepth()>1)
1741 // Normal branch, save parent with childs
1742 saveStatePart(par,QString("Delete %1").arg(getName(bo)));
1743 // naveState (UndoCom, par, QString("insertBranchAt (%1)", bo, "", QString ("Delete %1").arg(getName(bo))));
1745 // Mainbranch, save whole map
1746 // TODO Better would be to insert mainbranch again at pos
1747 // But undoCommand is missing right now
1748 saveStateComplete(QString("Delete %1").arg(getName(bo)));
1750 par->removeBranch(bo);
1752 selection->select();
1753 ensureSelectionVisible();
1754 mapCenter->reposition();
1757 if (selection && typeid(*selection) ==typeid(FloatImageObj) )
1759 FloatImageObj* fio=(FloatImageObj*)selection;
1760 BranchObj* par=(BranchObj*)(fio->getParObj());
1761 saveStatePart(par, QString("Delete %1").arg(getName(fio)));
1764 par->removeFloatImage(fio);
1766 selection->select();
1767 ensureSelectionVisible();
1768 mapCenter->reposition();
1773 LinkableMapObj* MapEditor::getSelection()
1778 void MapEditor::unselect()
1782 selectionLast=selection;
1783 selection->unselect();
1788 void MapEditor::reselect()
1792 selection=selectionLast;
1793 selection->select();
1798 bool MapEditor::select (const QString &s)
1800 LinkableMapObj *lmo=mapCenter->findObjBySelect(s);
1802 // Finally select the found object
1805 if (selection) unselect();
1807 selection->select();
1809 ensureSelectionVisible();
1815 QString MapEditor::getSelectString()
1817 if (selection) return selection->getSelectString();
1821 void MapEditor::selectInt (LinkableMapObj *lmo)
1823 if (lmo && selection != lmo)
1825 // select the MapObj
1826 if (selection) selection->unselect();
1828 selection->select();
1834 void MapEditor::selectNextBranchInt()
1836 // Increase number of branch
1839 QString s=selection->getSelectString();
1845 part=s.section(",",-1);
1847 num=part.right(part.length() - 3);
1849 s=s.left (s.length() -num.length());
1852 num=QString ("%1").arg(num.toUInt()+1);
1856 // Try to select this one
1857 if (select (s)) return;
1859 // We have no direct successor,
1860 // try to increase the parental number in order to
1861 // find a successor with same depth
1863 int d=selection->getDepth();
1868 while (!found && d>0)
1870 s=s.section (",",0,d-1);
1871 // replace substring of current depth in s with "1"
1872 part=s.section(",",-1);
1874 num=part.right(part.length() - 3);
1878 // increase number of parent
1879 num=QString ("%1").arg(num.toUInt()+1);
1880 s=s.section (",",0,d-2) + ","+ typ+num;
1883 // Special case, look at orientation
1884 if (selection->getOrientation()==OrientRightOfCenter)
1885 num=QString ("%1").arg(num.toUInt()+1);
1887 num=QString ("%1").arg(num.toUInt()-1);
1892 // pad to oldDepth, select the first branch for each depth
1893 for (i=d;i<oldDepth;i++)
1898 if ( ((BranchObj*)selection)->countBranches()>0)
1906 // try to select the freshly built string
1914 void MapEditor::selectPrevBranchInt()
1916 // Decrease number of branch
1919 QString s=selection->getSelectString();
1925 part=s.section(",",-1);
1927 num=part.right(part.length() - 3);
1929 s=s.left (s.length() -num.length());
1932 num=QString ("%1").arg(num.toUInt()-1);
1936 // Try to select this one
1937 if (select (s)) return;
1939 // We have no direct precessor,
1940 // try to decrease the parental number in order to
1941 // find a precessor with same depth
1943 int d=selection->getDepth();
1948 while (!found && d>0)
1950 s=s.section (",",0,d-1);
1951 // replace substring of current depth in s with "1"
1952 part=s.section(",",-1);
1954 num=part.right(part.length() - 3);
1958 // decrease number of parent
1959 num=QString ("%1").arg(num.toUInt()-1);
1960 s=s.section (",",0,d-2) + ","+ typ+num;
1963 // Special case, look at orientation
1964 if (selection->getOrientation()==OrientRightOfCenter)
1965 num=QString ("%1").arg(num.toUInt()-1);
1967 num=QString ("%1").arg(num.toUInt()+1);
1972 // pad to oldDepth, select the last branch for each depth
1973 for (i=d;i<oldDepth;i++)
1977 if ( ((BranchObj*)selection)->countBranches()>0)
1978 s+=",bo:"+ QString ("%1").arg( ((BranchObj*)selection)->countBranches()-1 );
1985 // try to select the freshly built string
1993 void MapEditor::selectUpperBranch()
1997 if (typeid(*selection) == typeid(BranchObj))
1999 if (selection->getOrientation()==OrientRightOfCenter)
2000 selectPrevBranchInt();
2002 if (selection->getDepth()==1)
2003 selectNextBranchInt();
2005 selectPrevBranchInt();
2010 void MapEditor::selectLowerBranch()
2014 if (typeid(*selection) == typeid(BranchObj))
2016 if (selection->getOrientation()==OrientRightOfCenter)
2017 selectNextBranchInt();
2019 if (selection->getDepth()==1)
2020 selectPrevBranchInt();
2022 selectNextBranchInt();
2028 void MapEditor::selectLeftBranch()
2034 if (typeid(*selection) == typeid(MapCenterObj))
2036 par= (BranchObj*) selection;
2037 bo=par->getLastSelectedBranch();
2040 // Workaround for reselecting on left and right side
2041 if (bo->getOrientation()==OrientRightOfCenter)
2043 bo=par->getLastBranch();
2049 selection->select();
2051 ensureSelectionVisible();
2056 par=(BranchObj*)(selection->getParObj());
2057 if (selection->getOrientation()==OrientRightOfCenter)
2059 if (typeid(*selection) == typeid(BranchObj) ||
2060 typeid(*selection) == typeid(FloatImageObj))
2062 selection->unselect();
2064 selection->select();
2066 ensureSelectionVisible();
2070 if (typeid(*selection) == typeid(BranchObj) )
2072 bo=((BranchObj*)selection)->getLastSelectedBranch();
2075 selection->unselect();
2077 selection->select();
2079 ensureSelectionVisible();
2087 void MapEditor::selectRightBranch()
2094 if (typeid(*selection) == typeid(MapCenterObj))
2096 par= (BranchObj*) selection;
2097 bo=par->getLastSelectedBranch();
2100 // Workaround for reselecting on left and right side
2101 if (bo->getOrientation()==OrientLeftOfCenter)
2102 bo=par->getFirstBranch();
2107 selection->select();
2108 ensureSelectionVisible();
2113 par=(BranchObj*)(selection->getParObj());
2114 if (selection->getOrientation()==OrientLeftOfCenter)
2116 if (typeid(*selection) == typeid(BranchObj) ||
2117 typeid(*selection) == typeid(FloatImageObj))
2119 selection->unselect();
2121 selection->select();
2123 ensureSelectionVisible();
2127 if (typeid(*selection) == typeid(BranchObj) )
2129 bo=((BranchObj*)selection)->getLastSelectedBranch();
2132 selection->unselect();
2134 selection->select();
2136 ensureSelectionVisible();
2144 void MapEditor::selectFirstBranch()
2150 if (typeid(*selection) == typeid(BranchObj))
2152 bo1= (BranchObj*) selection;
2153 par=(BranchObj*)(bo1->getParObj());
2154 bo2=par->getFirstBranch();
2158 selection->select();
2159 ensureSelectionVisible();
2166 void MapEditor::selectLastBranch()
2172 if (typeid(*selection) == typeid(BranchObj))
2174 bo1= (BranchObj*) selection;
2175 par=(BranchObj*)(bo1->getParObj());
2176 bo2=par->getLastBranch();
2180 selection->select();
2181 ensureSelectionVisible();
2188 void MapEditor::setColor(QColor c)
2193 void MapEditor::selectBackgroundColor()
2195 QColor col = QColorDialog::getColor( mapCanvas->backgroundColor(), this );
2196 if ( !col.isValid() ) return;
2197 setBackgroundColor( col );
2199 saveStateComplete(QString("Set background color of map to %1").arg(col.name()));
2202 void MapEditor::setBackgroundColor(QColor c)
2204 mapCanvas->setBackgroundColor (c);
2207 QColor MapEditor::pickColor()
2211 if (typeid(*selection) == typeid(BranchObj) ||
2212 typeid(*selection) == typeid(MapCenterObj))
2214 BranchObj *bo=(BranchObj*)selection;
2215 actColor=bo->getColor();
2221 void MapEditor::colorItem()
2225 if (typeid(*selection) == typeid(BranchObj) ||
2226 typeid(*selection) == typeid(MapCenterObj))
2228 BranchObj *bo=(BranchObj*)selection;
2229 saveStatePart(selection, QString("Set color of %1 to %2").arg(getName(bo)).arg(actColor.name())); //TODO undoCommand
2230 bo->setColor(actColor); // color branch
2235 void MapEditor::colorBranch()
2239 if (typeid(*selection) == typeid(BranchObj) ||
2240 typeid(*selection) == typeid(MapCenterObj))
2242 BranchObj *bo=(BranchObj*)selection;
2243 saveStatePart(selection, QString ("Set color of %1 and childs to %2").arg(getName(bo)).arg(actColor.name())); //TODO undoCommand
2244 bo->setColorChilds(actColor); // color links, color childs
2250 void MapEditor::toggleStandardFlag(QString f)
2254 if (typeid(*selection) == typeid(BranchObj) ||
2255 typeid(*selection) == typeid(MapCenterObj))
2257 BranchObj *bo=(BranchObj*)selection;
2259 if (bo->isSetStandardFlag(f))
2269 saveStateConstSelection(QString("%1 (\"%2\")").arg(u).arg(f),
2270 QString("%1 (\"%2\")").arg(r).arg(f),
2271 QString("Toggling standard flag \"%1\" of %2").arg(f).arg(getName(bo)));
2272 bo->toggleStandardFlag (f,mainWindow->useFlagGroups());
2278 void MapEditor::setViewCenter()
2280 // transform to CanvasView Coord:
2281 QPoint p=worldMatrix().map(movingCenter);
2282 center ( p.x(), p.y());
2286 BranchObj* MapEditor::findText (QString s, bool cs)
2288 QTextDocument::FindFlags flags=0;
2289 if (cs) flags=QTextDocument::FindCaseSensitively;
2292 { // Nothing found or new find process
2294 // nothing found, start again
2296 itFind=mapCenter->first();
2298 bool searching=true;
2299 bool foundNote=false;
2300 while (searching && !EOFind)
2304 // Searching in Note
2305 if (itFind->getNote().contains(s,cs))
2307 if (selection!=itFind)
2309 if (selection) ((BranchObj*)selection)->unselect();
2311 selection->select();
2313 ensureSelectionVisible();
2315 if (textEditor->findText(s,flags))
2321 // Searching in Heading
2322 if (searching && itFind->getHeading().contains (s,cs) )
2324 if (selection) ((BranchObj*)selection)->unselect();
2326 selection->select();
2328 ensureSelectionVisible();
2334 itFind=itFind->next();
2335 if (!itFind) EOFind=true;
2341 return (BranchObj*)selection;
2346 void MapEditor::findReset()
2347 { // Necessary if text to find changes during a find process
2352 void MapEditor::editURL()
2354 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2355 typeid(*selection) == typeid(MapCenterObj)) )
2358 BranchObj *bo=(BranchObj*)selection;
2359 QString text = QInputDialog::getText(
2360 "VYM", tr("Enter URL:"), QLineEdit::Normal,
2361 bo->getURL(), &ok, this );
2364 // user entered something and pressed OK
2365 saveStateConstSelection("setURL (\""+bo->getURL()+"\")","setURL (\""+text+"\")", QString("Set URL of %1 to %21").arg(getName(bo)).arg(text));
2372 QString MapEditor::getURL()
2374 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2375 typeid(*selection) == typeid(MapCenterObj)) )
2376 return ((BranchObj*)selection)->getURL();
2381 QStringList MapEditor::getURLs()
2384 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2385 typeid(*selection) == typeid(MapCenterObj)) )
2387 BranchObj *bo=(BranchObj*)selection;
2391 if (!bo->getURL().isEmpty()) urls.append( bo->getURL());
2399 void MapEditor::editHeading2URL()
2401 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2402 typeid(*selection) == typeid(MapCenterObj)) )
2404 BranchObj *bo=(BranchObj*)selection;
2405 saveStateConstSelection("setURL (\""+bo->getURL()+"\")","setURL (\""+bo->getHeading()+"\")",QString("Copy heading of %1 to URL").arg(getName(bo)));
2406 bo->setURL (bo->getHeading());
2411 void MapEditor::editBugzilla2URL()
2413 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2414 typeid(*selection) == typeid(MapCenterObj)) )
2416 BranchObj *bo=(BranchObj*)selection;
2417 QString url= "https://bugzilla.novell.com/show_bug.cgi?id="+bo->getHeading();
2418 saveStateConstSelection("setURL (\""+bo->getURL()+"\")","setURL (\""+url+"\")",QString("Use heading of %1 as link to Novell Bugzilla").arg(getName(bo)));
2424 void MapEditor::editFATE2URL()
2426 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2427 typeid(*selection) == typeid(MapCenterObj)) )
2429 BranchObj *bo=(BranchObj*)selection;
2430 QString url= "http://keeper.suse.de:8080/webfate/match/id?value=ID"+bo->getHeading();
2431 saveStateConstSelection("setURL (\""+bo->getURL()+"\")","setURL (\""+url+"\")",QString("Use heading of %1 as link to FATE").arg(getName(bo)));
2437 void MapEditor::editVymLink()
2439 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2440 typeid(*selection) == typeid(MapCenterObj)) )
2442 BranchObj *bo=(BranchObj*)selection;
2443 Q3FileDialog *fd=new Q3FileDialog( this,__VYM " - " +tr("Link to another map"));
2444 fd->addFilter (QString (tr("vym map") + " (*.vym)"));
2445 fd->setCaption(__VYM " - " +tr("Link to another map"));
2446 if (! bo->getVymLink().isEmpty() )
2447 fd->setSelection( bo->getVymLink() );
2451 if ( fd->exec() == QDialog::Accepted )
2453 saveStateConstSelection("setVymLink (\""+bo->getVymLink()+"\")","setVymLink (\""+fd->selectedFile()+"\")",QString("Set vymlink of %1 to %2").arg(getName(bo)).arg(fd->selectedFile()));
2454 bo->setVymLink (fd->selectedFile() );
2456 mapCenter->reposition();
2463 void MapEditor::deleteVymLink()
2465 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2466 typeid(*selection) == typeid(MapCenterObj)) )
2468 BranchObj *bo=(BranchObj*)selection;
2469 saveStateConstSelection("setVymLink (\""+bo->getVymLink()+"\")","setVymLink (\"\")",QString("Unset vymlink of %1").arg(getName(bo)));
2470 bo->setVymLink ("" );
2472 mapCenter->reposition();
2478 void MapEditor::toggleHideExport()
2480 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2481 typeid(*selection) == typeid(MapCenterObj)) ||
2482 (typeid(*selection)==typeid(FloatImageObj))
2485 OrnamentedObj *oo=(OrnamentedObj*)selection;
2487 if (oo->hideInExport())
2489 oo->setHideInExport(false);
2494 oo->setHideInExport(true);
2497 saveStateComplete(QString ("%1 hide export flag of %2").arg(s).arg(getName(selection))); //TODO undoCommand
2499 mapCenter->reposition();
2505 QString MapEditor::getVymLink()
2507 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2508 typeid(*selection) == typeid(MapCenterObj)) )
2510 return ((BranchObj*)selection)->getVymLink();
2516 QStringList MapEditor::getVymLinks()
2519 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2520 typeid(*selection) == typeid(MapCenterObj)) )
2522 BranchObj *bo=(BranchObj*)selection;
2526 if (!bo->getVymLink().isEmpty()) links.append( bo->getVymLink());
2534 void MapEditor::removeBranchKeepChilds()
2536 if (selection && (typeid(*selection) == typeid(BranchObj) ))
2538 BranchObj* bo=(BranchObj*)selection;
2539 BranchObj* par=(BranchObj*)(bo->getParObj());
2540 QString s=QString("Remove %1 and keep its childs").arg(getName(bo));
2541 if (bo->getDepth()==1)
2542 saveStateComplete(s);
2544 saveStatePart(selection->getParObj(),s); // TODO undoCommand
2545 QString sel=selection->getSelectString();
2547 par->removeBranchHere(bo);
2548 mapCenter->reposition();
2553 void MapEditor::removeChilds()
2555 if (selection && (typeid(*selection) == typeid(BranchObj) ))
2557 saveStatePart(selection->getParObj(), QString("Remove childs of branch %1").arg(getName(selection)));
2558 ((BranchObj*)selection)->removeChilds();
2559 mapCenter->reposition();
2563 void MapEditor::editMapInfo()
2565 ExtraInfoDialog dia;
2566 dia.setMapName (getFileName() );
2567 dia.setAuthor (mapCenter->getAuthor() );
2568 dia.setComment(mapCenter->getComment() );
2573 Q3CanvasItemList l=canvas()->allItems();
2574 for (Q3CanvasItemList::Iterator it=l.begin(); it!=l.end(); ++it)
2576 stats+=QString ("%1 items on canvas\n").arg (i,6);
2583 bo=mapCenter->first();
2586 if (!bo->getNote().isEmpty() ) n++;
2587 f+= bo->countFloatImages();
2589 xl+=bo->countXLinks();
2592 stats+=QString ("%1 branches\n").arg (b-1,6);
2593 stats+=QString ("%1 xLinks \n").arg (xl,6);
2594 stats+=QString ("%1 notes\n").arg (n,6);
2595 stats+=QString ("%1 images\n").arg (f,6);
2596 dia.setStats (stats);
2598 // Finally show dialog
2599 if (dia.exec() == QDialog::Accepted)
2601 saveStateComplete("Edit info about map"); //TODO undoCommand
2602 mapCenter->setAuthor (dia.getAuthor() );
2603 mapCenter->setComment (dia.getComment() );
2607 void MapEditor::updateActions()
2609 mainWindow->updateActions();
2610 // FIXME maybe don't update if blockReposition is set
2613 void MapEditor::updateNoteFlag()
2616 if ( (typeid(*selection) == typeid(BranchObj)) ||
2617 (typeid(*selection) == typeid(MapCenterObj)) )
2618 ((BranchObj*)selection)->updateNoteFlag();
2621 void MapEditor::setLinkStyle (LinkStyle ls)
2625 saveStateComplete("Set link style"); // TODO undoCommand
2627 bo=mapCenter->first();
2631 bo->setLinkStyle(bo->getDefLinkStyle());
2634 mapCenter->reposition();
2637 LinkStyle MapEditor::getLinkStyle ()
2642 void MapEditor::setLinkColor(QColor c)
2648 void MapEditor::setLinkColorHint()
2650 // called from setLinkColorHint(lch) or at end of parse
2652 bo=mapCenter->first();
2660 void MapEditor::setLinkColorHint(LinkColorHint lch)
2666 void MapEditor::toggleLinkColorHint()
2668 if (linkcolorhint==HeadingColor)
2669 linkcolorhint=DefaultColor;
2671 linkcolorhint=HeadingColor;
2673 bo=mapCenter->first();
2681 LinkColorHint MapEditor::getLinkColorHint()
2683 return linkcolorhint;
2686 QColor MapEditor::getDefLinkColor()
2688 return defLinkColor;
2691 void MapEditor::setDefXLinkColor(QColor col)
2696 QColor MapEditor::getDefXLinkColor()
2698 return defXLinkColor;
2701 void MapEditor::setDefXLinkWidth (int w)
2706 int MapEditor::getDefXLinkWidth()
2708 return defXLinkWidth;
2711 void MapEditor::selectLinkColor()
2713 QColor col = QColorDialog::getColor( defLinkColor, this );
2714 if ( !col.isValid() ) return;
2715 setLinkColor( col );
2716 saveStateComplete(QString("Set link color to %1").arg(col.name())); //TODO undoCommand
2720 void MapEditor::toggleScroll()
2722 if (selection && (typeid(*selection) == typeid(BranchObj)) )
2724 BranchObj *bo=((BranchObj*)selection);
2725 if (bo->countBranches()==0) return;
2726 if (bo->getDepth()==0) return;
2728 if (bo->isScrolled())
2732 saveStatePart(selection, QString ("%1 %2").arg(s).arg(getName(bo)));
2739 void MapEditor::unScrollAll()
2742 bo=mapCenter->first();
2745 if (bo->isScrolled()) bo->toggleScroll();
2750 void MapEditor::loadFloatImage ()
2753 (typeid(*selection) == typeid(BranchObj)) ||
2754 (typeid(*selection) == typeid(MapCenterObj)) )
2756 BranchObj *bo=((BranchObj*)selection);
2758 Q3FileDialog *fd=new Q3FileDialog( this);
2759 fd->setMode (Q3FileDialog::ExistingFiles);
2760 fd->addFilter (QString (tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)"));
2761 ImagePreview *p =new ImagePreview (fd);
2762 fd->setContentsPreviewEnabled( TRUE );
2763 fd->setContentsPreview( p, p );
2764 fd->setPreviewMode( Q3FileDialog::Contents );
2765 fd->setCaption(__VYM " - " +tr("Load image"));
2766 fd->setDir (lastImageDir);
2770 if ( fd->exec() == QDialog::Accepted )
2772 saveStatePart(selection, QString("Add floatimage to %1").arg(getName(selection)));
2773 // FIXME in QT4 use: lastImageDir=fd->directory();
2774 lastImageDir=QDir (fd->dirPath());
2775 QStringList flist = fd->selectedFiles();
2776 QStringList::Iterator it = flist.begin();
2777 while( it != flist.end() )
2780 bo->addFloatImage();
2781 // TODO check if load was successful
2782 bo->getLastFloatImage()->load(*it);
2783 bo->getLastFloatImage()->setOriginalFilename(fn);
2787 mapCenter->reposition();
2796 void MapEditor::saveFloatImage ()
2799 (typeid(*selection) == typeid(FloatImageObj)) )
2801 FloatImageObj *fio=((FloatImageObj*)selection);
2802 QFileDialog *fd=new QFileDialog( this);
2803 fd->setFilters (imageIO.getFilters());
2804 fd->setCaption(__VYM " - " +tr("Save image"));
2805 fd->setFileMode( QFileDialog::AnyFile );
2806 fd->setDirectory (lastImageDir);
2807 // fd->setSelection (fio->getOriginalFilename());
2811 if ( fd->exec() == QDialog::Accepted )
2813 if (QFile (fd->selectedFile()).exists() )
2815 QMessageBox mb( __VYM,
2816 tr("The file %1 exists already.\n"
2817 "Do you want to overwrite it?").arg(fd->selectedFile()),
2818 QMessageBox::Warning,
2819 QMessageBox::Yes | QMessageBox::Default,
2820 QMessageBox::Cancel | QMessageBox::Escape,
2821 QMessageBox::QMessageBox::NoButton );
2823 mb.setButtonText( QMessageBox::Yes, tr("Overwrite") );
2824 mb.setButtonText( QMessageBox::No, tr("Cancel"));
2827 case QMessageBox::Yes:
2830 case QMessageBox::Cancel:
2837 fio->save (fd->selectedFile(),imageIO.getType (fd->selectedFilter() ) );
2843 void MapEditor::setFrame(const FrameType &t)
2846 (typeid(*selection) == typeid(BranchObj)) ||
2847 (typeid(*selection) == typeid(MapCenterObj)) )
2849 selection->setFrameType (t);
2850 mapCenter->reposition();
2851 selection->updateLink();
2855 void MapEditor::setIncludeImagesVer(bool b)
2858 (typeid(*selection) == typeid(BranchObj)) ||
2859 (typeid(*selection) == typeid(MapCenterObj)) )
2860 ((BranchObj*)selection)->setIncludeImagesVer(b);
2861 mapCenter->reposition();
2864 void MapEditor::setIncludeImagesHor(bool b)
2867 (typeid(*selection) == typeid(BranchObj)) ||
2868 (typeid(*selection) == typeid(MapCenterObj)) )
2869 ((BranchObj*)selection)->setIncludeImagesHor(b);
2870 mapCenter->reposition();
2873 void MapEditor::setHideLinkUnselected (bool b)
2876 (typeid(*selection) == typeid(BranchObj)) ||
2877 (typeid(*selection) == typeid(MapCenterObj)) ||
2878 (typeid(*selection) == typeid(FloatImageObj)) )
2879 selection->setHideLinkUnselected(b);
2882 void MapEditor::importDirInt(BranchObj *dst, QDir d)
2885 (typeid(*selection) == typeid(BranchObj)) ||
2886 (typeid(*selection) == typeid(MapCenterObj)) )
2890 // Traverse directories
2891 d.setFilter( QDir::Dirs| QDir::Hidden | QDir::NoSymLinks );
2892 QFileInfoList list = d.entryInfoList();
2895 for (int i = 0; i < list.size(); ++i)
2898 if (fi.fileName() != "." && fi.fileName() != ".." )
2901 bo=dst->getLastBranch();
2902 bo->setHeading (fi.fileName() );
2903 bo->setColor (QColor("blue"));
2905 if ( !d.cd(fi.fileName()) )
2906 QMessageBox::critical (0,tr("Critical Import Error"),tr("Cannot find the directory %1").arg(fi.fileName()));
2909 // Recursively add subdirs
2910 importDirInt (bo,d);
2916 d.setFilter( QDir::Files| QDir::Hidden | QDir::NoSymLinks );
2917 list = d.entryInfoList();
2919 for (int i = 0; i < list.size(); ++i)
2923 bo=dst->getLastBranch();
2924 bo->setHeading (fi.fileName() );
2925 bo->setColor (QColor("black"));
2926 if (fi.fileName().right(4) == ".vym" )
2927 bo->setVymLink (fi.filePath());
2932 void MapEditor::importDir()
2935 (typeid(*selection) == typeid(BranchObj)) ||
2936 (typeid(*selection) == typeid(MapCenterObj)) )
2938 Q3FileDialog *fd=new Q3FileDialog( this,__VYM " - " +tr("Choose directory structure to import"));
2939 fd->setMode (Q3FileDialog::DirectoryOnly);
2940 fd->addFilter (QString (tr("vym map") + " (*.vym)"));
2941 fd->setCaption(__VYM " - " +tr("Choose directory structure to import"));
2945 if ( fd->exec() == QDialog::Accepted )
2947 BranchObj *bo=((BranchObj*)selection);
2948 importDirInt (bo,QDir(fd->selectedFile()) );
2949 mapCenter->reposition();
2956 void MapEditor::followXLink(int i)
2959 (typeid(*selection) == typeid(BranchObj)) ||
2960 (typeid(*selection) == typeid(MapCenterObj)) )
2962 BranchObj *bo=((BranchObj*)selection)->XLinkTargetAt(i);
2965 selection->unselect();
2967 selection->select();
2968 ensureSelectionVisible();
2973 void MapEditor::editXLink(int i)
2976 (typeid(*selection) == typeid(BranchObj)) ||
2977 (typeid(*selection) == typeid(MapCenterObj)) )
2979 XLinkObj *xlo=((BranchObj*)selection)->XLinkAt(i);
2982 EditXLinkDialog dia;
2984 dia.setSelection(selection);
2985 if (dia.exec() == QDialog::Accepted)
2987 if (dia.useSettingsGlobal() )
2989 setDefXLinkColor (xlo->getColor() );
2990 setDefXLinkWidth (xlo->getWidth() );
2992 if (dia.deleteXLink())
2993 ((BranchObj*)selection)->deleteXLinkAt(i);
2994 saveStateComplete("Edit xLink"); //TODO undoCommand
3000 void MapEditor::testFunction()
3002 cout << "MapEditor::testFunction() called\n";
3005 dia.showCancelButton (true);
3006 dia.setText("This is a longer \nWarning");
3008 dia.setCaption("Warning: Flux problem");
3009 dia.setShowAgainName("/warnings/mapeditor");
3011 if (dia.exec()==QDialog::Accepted)
3012 cout << "accepted!\n";
3014 cout << "canceled!\n";
3017 /* Hide hidden stuff temporary, maybe add this as regular function somewhere
3018 if (hidemode==HideNone)
3020 setHideTmpMode (HideExport);
3021 mapCenter->calcBBoxSizeWithChilds();
3022 QRect totalBBox=mapCenter->getTotalBBox();
3023 QRect mapRect=totalBBox;
3024 QCanvasRectangle *frame=NULL;
3026 cout << " map has =("<<totalBBox.x()<<","<<totalBBox.y()<<","<<totalBBox.width()<<","<<totalBBox.height()<<")\n";
3028 mapRect.setRect (totalBBox.x(), totalBBox.y(),
3029 totalBBox.width(), totalBBox.height());
3030 frame=new QCanvasRectangle (mapRect,mapCanvas);
3031 frame->setBrush (QColor(white));
3032 frame->setPen (QColor(black));
3038 setHideTmpMode (HideNone);
3040 cout <<" hidemode="<<hidemode<<endl;
3044 void MapEditor::ensureSelectionVisible()
3048 LinkableMapObj* lmo= dynamic_cast <LinkableMapObj*> (selection);
3050 if (selection->getOrientation() == OrientLeftOfCenter)
3051 p= worldMatrix().map(QPoint (lmo->x(),lmo->y()));
3053 p= worldMatrix().map(QPoint (lmo->x()+lmo->width(),lmo->y()+lmo->height()));
3054 ensureVisible (p.x(), p.y() );
3059 void MapEditor::updateViewCenter()
3061 // Update movingCenter, so that we can zoom comfortably later
3062 QRect rc = QRect( contentsX(), contentsY(),
3063 visibleWidth(), visibleHeight() );
3064 QRect canvasRect = inverseWorldMatrix().mapRect(rc);
3065 movingCenter.setX((canvasRect.right() + canvasRect.left())/2);
3066 movingCenter.setY((canvasRect.top() + canvasRect.bottom())/2);
3069 void MapEditor::contentsContextMenuEvent ( QContextMenuEvent * e )
3071 // Lineedits are already closed by preceding
3072 // mouseEvent, we don't need to close here.
3074 QPoint p = inverseWorldMatrix().map(e->pos());
3075 LinkableMapObj* lmo=mapCenter->findMapObj(p, NULL);
3078 { // MapObj was found
3079 if (selection != lmo)
3081 // select the MapObj
3082 if (selection) selection->unselect();
3084 selection->select();
3090 if (typeid(*selection)==typeid(BranchObj) ||
3091 typeid(*selection)==typeid(MapCenterObj) )
3093 // Context Menu on branch or mapcenter
3095 branchContextMenu->popup(e->globalPos() );
3097 if (typeid(*selection)==typeid(FloatImageObj))
3099 // Context Menu on floatimage
3101 floatimageContextMenu->popup(e->globalPos() );
3105 { // No MapObj found, we are on the Canvas itself
3106 // Context Menu on Canvas
3108 canvasContextMenu->popup(e->globalPos() );
3113 void MapEditor::contentsMousePressEvent(QMouseEvent* e)
3115 // Ignore right clicks, these will go to context menus
3116 if (e->button() == Qt::RightButton )
3122 QPoint p = inverseWorldMatrix().map(e->pos());
3123 LinkableMapObj* lmo=mapCenter->findMapObj(p, NULL);
3127 //Take care of clickdesystem flags _or_ modifier modes
3129 if (lmo && (typeid(*lmo)==typeid(BranchObj) ||
3130 typeid(*lmo)==typeid(MapCenterObj) ))
3132 QString foname=((BranchObj*)lmo)->getSystemFlagName(p);
3133 if (!foname.isEmpty())
3135 // systemFlag clicked
3139 if (e->state() & Qt::ControlModifier)
3140 mainWindow->editOpenURLTab();
3142 mainWindow->editOpenURL();
3144 else if (foname=="vymLink")
3146 mainWindow->editOpenVymLink();
3147 // tabWidget may change, better return now
3148 // before segfaulting...
3149 } else if (foname=="note")
3150 mainWindow->windowToggleNoteEditor();
3151 else if (foname=="hideInExport")
3156 // No system flag clicked, take care of modmodes
3158 // Special case: CTRL is pressed
3159 if (e->state() & Qt::ControlModifier)
3161 if (mainWindow->getModMode()==ModModeColor)
3164 setCursor (pickColorCursor);
3167 if (mainWindow->getModMode()==ModModeXLink)
3169 BranchObj *bo_begin=NULL;
3171 bo_begin=(BranchObj*)(lmo);
3174 ((typeid(*selection) == typeid(BranchObj)) ||
3175 (typeid(*selection) == typeid(MapCenterObj))) )
3176 bo_begin=(BranchObj*)selection;
3180 linkingObj_src=bo_begin;
3181 tmpXLink=new XLinkObj (mapCanvas);
3182 tmpXLink->setBegin (bo_begin);
3183 tmpXLink->setEnd (p);
3184 tmpXLink->setColor(defXLinkColor);
3185 tmpXLink->setWidth(defXLinkWidth);
3186 tmpXLink->updateXLink();
3187 tmpXLink->setVisibility (true);
3195 // Left Button Move Branches
3196 if (e->button() == Qt::LeftButton )
3198 movingObj_start.setX( p.x() - selection->x() );
3199 movingObj_start.setY( p.y() - selection->y() );
3200 movingObj_orgPos.setX (lmo->x() );
3201 movingObj_orgPos.setY (lmo->y() );
3202 movingObj_orgRelPos=lmo->getRelPos();
3204 // If modMode==copy, then we want to "move" the _new_ object around
3205 // then we need the offset from p to the _old_ selection, because of tmp
3206 if (mainWindow->getModMode()==ModModeCopy &&
3207 e->state() & Qt::ControlModifier)
3209 if (typeid(*selection)==typeid(BranchObj) )
3212 mapCenter->addBranch ((BranchObj*)selection);
3214 selection=mapCenter->getLastBranch();
3215 selection->select();
3216 mapCenter->reposition();
3219 movingObj=selection;
3221 // Middle Button Toggle Scroll
3222 // (On Mac OS X this won't work, but we still have
3223 // a button in the toolbar)
3224 if (e->button() == Qt::MidButton )
3228 { // No MapObj found, we are on the Canvas itself
3229 // Left Button move Pos of CanvasView
3230 if (e->button() == Qt::LeftButton )
3232 movingObj=NULL; // move Content not Obj
3233 movingObj_start=e->globalPos();
3234 movingCont_start=QPoint (contentsX(), contentsY() );
3235 movingVec=QPoint(0,0);
3236 setCursor(handOpenCursor);
3241 void MapEditor::contentsMouseMoveEvent(QMouseEvent* e)
3243 QPoint p = inverseWorldMatrix().map(e->pos());
3245 // Move the selected MapObj
3246 if ( selection && movingObj)
3248 // To avoid jumping of the CanvasView, only
3249 // ensureSelectionVisible, if not tmp linked
3250 if (!selection->hasParObjTmp())
3251 ensureSelectionVisible ();
3253 // Now move the selection, but add relative position
3254 // (movingObj_start) where selection was chosen with
3255 // mousepointer. (This avoids flickering resp. jumping
3256 // of selection back to absPos)
3258 LinkableMapObj *lmosel;
3259 lmosel = dynamic_cast <LinkableMapObj*> (selection);
3261 // Check if we could link
3262 LinkableMapObj* lmo=mapCenter->findMapObj(p, lmosel);
3265 if (typeid(*selection) == typeid(FloatImageObj))
3267 FloatObj *fo=(FloatObj*)selection;
3268 fo->move (p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
3272 // Relink float to new mapcenter or branch, if shift is pressed
3273 // Only relink, if selection really has a new parent
3274 if ( (e->modifiers()==Qt::ShiftModifier) && lmo &&
3275 ( (typeid(*lmo)==typeid(BranchObj)) ||
3276 (typeid(*lmo)==typeid(MapCenterObj)) ) &&
3277 ( lmo != fo->getParObj())
3280 if (typeid(*fo) == typeid(FloatImageObj))
3283 saveStateComplete(QString("Relink %1 to %2").arg(getName(fo)).arg(getName(lmo) ) );
3284 FloatImageObj *fio=(FloatImageObj*)(fo);
3285 ((BranchObj*)(lmo))->addFloatImage (fio);
3287 ((BranchObj*)(fio->getParObj()))->removeFloatImage (fio);
3288 fio=((BranchObj*)(lmo))->getLastFloatImage();
3291 selection=(LinkableMapObj*)(fio);
3292 selection->select();
3293 movingObj=(MapObj*)(fio);
3297 { // selection != a FloatObj
3298 if (lmosel->getDepth()==0)
3301 if (e->buttons()== Qt::LeftButton && e->modifiers()==Qt::ShiftModifier)
3302 mapCenter->moveAll(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
3304 mapCenter->move (p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
3305 mapCenter->updateRelPositions();
3308 if (lmosel->getDepth()==1)
3311 lmosel->move(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
3312 lmosel->setRelPos();
3315 // Move ordinary branch
3316 if (lmosel->getOrientation() == OrientLeftOfCenter)
3317 // Add width of bbox here, otherwise alignRelTo will cause jumping around
3318 lmosel->move(p.x() -movingObj_start.x()+lmosel->getBBox().width(),
3319 p.y()-movingObj_start.y() +lmosel->getTopPad() );
3321 lmosel->move(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() -lmosel->getTopPad());
3323 // reposition subbranch
3324 lmosel->reposition();
3326 if (lmo && (lmo!=selection) &&
3327 (typeid(*lmo) == typeid(BranchObj) ||
3328 (typeid(*lmo) == typeid(MapCenterObj) )
3331 if (e->modifiers()==Qt::ControlModifier)
3333 // Special case: CTRL to link below lmo
3334 lmosel->setParObjTmp (lmo,p,+1);
3336 else if (e->modifiers()==Qt::ShiftModifier)
3337 lmosel->setParObjTmp (lmo,p,-1);
3339 lmosel->setParObjTmp (lmo,p,0);
3342 lmosel->unsetParObjTmp();
3346 } // no FloatImageObj
3350 } // selection && moving_obj
3352 // Draw a link from one branch to another
3355 tmpXLink->setEnd (p);
3356 tmpXLink->updateXLink();
3360 if (!movingObj && !pickingColor &&!drawingLink)
3362 QPoint p=e->globalPos();
3363 movingVec.setX(-p.x() + movingObj_start.x() );
3364 movingVec.setY(-p.y() + movingObj_start.y() );
3365 setContentsPos( movingCont_start.x() + movingVec.x(),
3366 movingCont_start.y() + movingVec.y());
3373 void MapEditor::contentsMouseReleaseEvent(QMouseEvent* e)
3375 LinkableMapObj *dst;
3376 // Have we been picking color?
3380 setCursor (Qt::ArrowCursor);
3381 // Check if we are over another branch
3382 dst=mapCenter->findMapObj(inverseWorldMatrix().map(e->pos() ), NULL);
3383 if (dst && selection)
3385 if (e->state() & Qt::ShiftModifier)
3387 ((BranchObj*)selection)->setColor (((BranchObj*)(dst))->getColor());
3388 ((BranchObj*)selection)->setLinkColor ();
3392 ((BranchObj*)selection)->setColorChilds (((BranchObj*)(dst))->getColor());
3393 ((BranchObj*)selection)->setLinkColor ();
3399 // Have we been drawing a link?
3403 // Check if we are over another branch
3404 dst=mapCenter->findMapObj(inverseWorldMatrix().map(e->pos() ), NULL);
3405 if (dst && selection)
3407 tmpXLink->setEnd ( ((BranchObj*)(dst)) );
3408 tmpXLink->updateXLink();
3409 tmpXLink->activate();
3410 saveStateComplete(QString("Activate xLink from %1 to %2").arg(getName(tmpXLink->getBegin())).arg(getName(tmpXLink->getEnd())) ); //TODO undoCommand
3419 // Have we been moving something?
3420 if ( selection && movingObj )
3422 if(typeid(*selection)==typeid (FloatImageObj))
3424 // Moved FloatObj. Maybe we need to reposition
3425 FloatImageObj *fo=(FloatImageObj*)selection;
3426 QString pold=qpointToString(movingObj_orgRelPos);
3427 QString pnow=qpointToString(fo->getRelPos());
3428 saveStateConstSelection(
3431 QString("Move %1 to relativ position %2").arg(getName(selection)).arg(pnow));
3433 // FIXME Why calling parObj here?
3434 selection->getParObj()->requestReposition();
3435 mapCenter->reposition();
3438 // Check if we are over another branch, but ignore
3439 // any found LMOs, which are FloatObjs
3440 dst=mapCenter->findMapObj(inverseWorldMatrix().map(e->pos() ),
3441 ((LinkableMapObj*)selection) );
3443 if (dst && (typeid(*dst)!=typeid(BranchObj) && typeid(*dst)!=typeid(MapCenterObj)))
3446 if (typeid(*selection) == typeid(MapCenterObj) )
3447 { // The MapCenter was moved
3448 cout << "FIXME missing savestate...\n";
3451 if (typeid(*selection) == typeid(BranchObj) )
3452 { // A branch was moved
3454 // save the position in case we link to mapcenter
3455 QPoint savePos=QPoint (selection->x(),selection->y() );
3457 // Reset the temporary drawn link to the original one
3458 ((LinkableMapObj*)selection)->unsetParObjTmp();
3460 // For Redo we may need to save original selection
3461 QString preSelStr=selection->getSelectString();
3466 BranchObj* bsel=(BranchObj*)selection;
3467 BranchObj* bdst=(BranchObj*)dst;
3469 QString preParStr=(bsel->getParObj())->getSelectString();
3470 QString preNum=QString::number (bsel->getNum(),10);
3471 QString preDstParStr;
3473 if (e->state() & Qt::ShiftModifier && dst->getParObj())
3475 preDstParStr=dst->getParObj()->getSelectString();
3476 bsel->moveBranchTo ( (BranchObj*)(bdst->getParObj()), bdst->getNum());
3478 if (e->state() & Qt::ControlModifier && dst->getParObj())
3481 preDstParStr=dst->getParObj()->getSelectString();
3482 bsel->moveBranchTo ( (BranchObj*)(bdst->getParObj()), bdst->getNum()+1);
3485 preDstParStr=dst->getSelectString();
3486 bsel->moveBranchTo (bdst,-1);
3487 if (dst->getDepth()==0) bsel->move (savePos);
3489 QString postSelStr=selection->getSelectString();
3490 QString postNum=QString::number (bsel->getNum(),10);
3492 QString undoCom="linkBranchToPos (\""+
3493 preParStr+ "\"," + preNum +"," +
3494 QString ("%1,%2").arg(movingObj_orgPos.x()).arg(movingObj_orgPos.y())+ ")";
3496 QString redoCom="linkBranchToPos (\""+
3497 preDstParStr + "\"," + postNum + "," +
3498 QString ("%1,%2").arg(savePos.x()).arg(savePos.y())+ ")";
3503 QString("Relink %1 to %2").arg(getName(bsel)).arg(getName(dst)) );
3505 if (selection->getDepth()==1)
3507 // The select string might be different _after_ moving around.
3508 // Therefor reposition and then use string of old selection, too
3509 mapCenter->reposition();
3511 QString ps=qpointToString ( ((BranchObj*)selection)->getRelPos() );
3513 selection->getSelectString(), "moveRel "+qpointToString(movingObj_orgRelPos),
3514 preSelStr, "moveRel "+ps,
3515 QString("Move %1 to relative position %2").arg(getName(selection)).arg(ps));
3518 // Draw the original link, before selection was moved around
3519 mapCenter->reposition();
3521 // Finally resize canvas, if needed
3526 // Just make sure, that actions are still ok,e.g. the move branch up/down buttons...
3529 // maybe we moved View: set old cursor
3530 setCursor (Qt::ArrowCursor);
3534 void MapEditor::contentsMouseDoubleClickEvent(QMouseEvent* e)
3536 if (e->button() == Qt::LeftButton )
3538 QPoint p = inverseWorldMatrix().map(e->pos());
3539 LinkableMapObj *lmo=mapCenter->findMapObj(p, NULL);
3540 if (lmo) { // MapObj was found
3541 // First select the MapObj than edit heading
3542 if (selection) selection->unselect();
3544 selection->select();
3545 mainWindow->editHeading();
3550 void MapEditor::resizeEvent (QResizeEvent* e)
3552 Q3CanvasView::resizeEvent( e );
3556 void MapEditor::contentsDragEnterEvent(QDragEnterEvent *event)
3559 // for (unsigned int i=0;event->format(i);i++) // Debug mime type
3560 // cerr << event->format(i) << endl;
3563 (typeid(*selection) == typeid(BranchObj)) ||
3564 (typeid(*selection) == typeid(MapCenterObj))) {
3566 // If QImageDrag can decode mime type
3567 if (Q3ImageDrag::canDecode(event)) {
3572 // If image are dragged from firefox
3573 if (event->provides("application/x-moz-file-promise-url") &&
3574 event->provides("application/x-moz-nativeimage")) {
3575 event->accept(true);
3579 // If QUriDrag can decode mime type
3580 if (Q3UriDrag::canDecode(event)) {
3585 // If Uri are dragged from firefox
3586 if (event->provides("_NETSCAPE_URL")){
3591 // If QTextDrag can decode mime type
3592 if (Q3TextDrag::canDecode(event)) {
3601 bool isUnicode16(const QByteArray &d)
3603 // TODO: make more precise check for unicode 16.
3604 // Guess unicode16 if any of second bytes are zero
3605 unsigned int length = max(0,d.size()-2)/2;
3606 for (unsigned int i = 0; i<length ; i++)
3607 if (d.at(i*2+1)==0) return true;
3611 void MapEditor::contentsDropEvent(QDropEvent *event)
3614 (typeid(*selection) == typeid(BranchObj)) ||
3615 (typeid(*selection) == typeid(MapCenterObj)))
3620 if (event->provides("image/png"))
3623 if (Q3ImageDrag::decode(event, pix))
3631 } else if (event->provides("application/x-moz-file-promise-url") &&
3632 event->provides("application/x-moz-nativeimage"))
3634 // Contains url to the img src in unicode16
3635 QByteArray d = event->encodedData("application/x-moz-file-promise-url");
3636 QString url = QString((const QChar*)d.data(),d.size()/2);
3640 } else if (event->provides ("text/uri-list"))
3641 { // Uris provided e.g. by konqueror
3642 Q3UriDrag::decode (event,uris);
3643 } else if (event->provides ("_NETSCAPE_URL"))
3644 { // Uris provided by Mozilla
3645 QStringList l = QStringList::split("\n", event->encodedData("_NETSCAPE_URL"));
3648 } else if (event->provides("text/html")) {
3650 // Handels text mime types
3651 // Look like firefox allways handle text as unicode16 (2 bytes per char.)
3652 QByteArray d = event->encodedData("text/html");
3655 text = QString((const QChar*)d.data(),d.size()/2);
3659 textEditor->setText(text);
3663 } else if (event->provides("text/plain")) {
3664 QByteArray d = event->encodedData("text/plain");
3667 text = QString((const QChar*)d.data(),d.size()/2);
3671 textEditor->setText(text);
3683 for (const char* u=uris.first(); u; u=uris.next())
3685 bo=((BranchObj*)selection)->addBranch();
3688 s=Q3UriDrag::uriToLocalFile(u);
3691 QString file = QDir::convertSeparators(s);
3692 heading = QFileInfo(file).baseName();
3694 if (file.endsWith(".vym", false))
3695 bo->setVymLink(file);
3704 if (!heading.isEmpty())
3705 bo->setHeading(heading);
3715 //FIXME saveState has to be called earlier for each of the drops...
3716 saveStateComplete("Drop Event"); //TODO undo Command
3717 mapCenter->reposition();
3724 void MapEditor::addFloatImage(const QPixmap &img)
3727 (typeid(*selection) == typeid(BranchObj)) ||
3728 (typeid(*selection) == typeid(MapCenterObj)) )
3730 BranchObj *bo=((BranchObj*)selection);
3731 saveStatePart(selection,QString("Add floatimage to %1").arg(getName(bo)));
3732 //QString fn=fd->selectedFile();
3733 //lastImageDir=fn.left(fn.findRev ("/"));
3734 bo->addFloatImage();
3735 // FIXME check if load was successful
3736 bo->getLastFloatImage()->load(img);
3737 //bo->getLastFloatImage()->setOriginalFilename(fn);
3738 mapCenter->reposition();
3745 void MapEditor::imageDataFetched(const QByteArray &a, Q3NetworkOperation */*nop*/)
3747 if (!imageBuffer) imageBuffer = new QBuffer();
3748 if (!imageBuffer->isOpen()) {
3749 imageBuffer->open(QIODevice::WriteOnly | QIODevice::Append);
3751 imageBuffer->at(imageBuffer->at()+imageBuffer->writeBlock(a));
3755 void MapEditor::imageDataFinished(Q3NetworkOperation *nop)
3757 if (nop->state()==Q3NetworkProtocol::StDone) {
3758 QPixmap img(imageBuffer->buffer());
3763 imageBuffer->close();
3765 imageBuffer->close();
3772 void MapEditor::fetchImage(const QString &url)
3775 urlOperator->stop();
3776 disconnect(urlOperator);
3780 urlOperator = new Q3UrlOperator(url);
3781 connect(urlOperator, SIGNAL(finished(Q3NetworkOperation *)),
3782 this, SLOT(imageDataFinished(Q3NetworkOperation*)));
3784 connect(urlOperator, SIGNAL(data(const QByteArray &, Q3NetworkOperation *)),
3785 this, SLOT(imageDataFetched(const QByteArray &, Q3NetworkOperation *)));