1 #include <QApplication>
6 #include "editxlinkdialog.h"
8 #include "exportxhtmldialog.h"
10 #include "geometry.h" // for addBBox
11 #include "mainwindow.h"
12 #include "mapcenterobj.h"
15 #include "selection.h"
18 #include "warningdialog.h"
19 #include "xml-freemind.h"
25 extern Main *mainWindow;
26 extern Settings settings;
27 extern QString tmpVymDir;
29 extern TextEditor *textEditor;
31 extern QString clipboardDir;
32 extern QString clipboardFile;
33 extern bool clipboardEmpty;
35 extern ImageIO imageIO;
37 extern QString vymName;
38 extern QString vymVersion;
39 extern QDir vymBaseDir;
41 extern QDir lastImageDir;
42 extern QDir lastFileDir;
44 extern FlagRowObj *standardFlagsDefault;
46 extern Settings settings;
50 int VymModel::mapNum=0; // make instance
54 // cout << "Const VymModel\n";
61 // cout << "Destr VymModel\n";
62 autosaveTimer->stop();
63 fileChangedTimer->stop();
67 void VymModel::clear()
69 selModel->clearSelection();
72 while (!mapCenters.isEmpty()) // FIXME VM needs to be in treemodel only...
73 delete mapCenters.takeFirst();
75 QModelIndex ri=index(rootItem);
76 //removeRows (0, rowCount(ri),ri); // FIXME here should be at least a beginRemoveRows...
79 void VymModel::init ()
81 // We should have at least one map center to start with
82 // addMapCenter(); FIXME VM create this in MapEditor as long as model is part of that
87 // Also no scene yet (should not be needed anyway) FIXME VM
100 stepsTotal=settings.readNumEntry("/history/stepsTotal",100);
101 undoSet.setEntry ("/history/stepsTotal",QString::number(stepsTotal));
102 mainWindow->updateHistory (undoSet);
105 makeTmpDirectories();
110 fileName=tr("unnamed");
112 blockReposition=false;
113 blockSaveState=false;
115 autosaveTimer=new QTimer (this);
116 connect(autosaveTimer, SIGNAL(timeout()), this, SLOT(autosave()));
118 fileChangedTimer=new QTimer (this);
119 fileChangedTimer->start(3000);
120 connect(fileChangedTimer, SIGNAL(timeout()), this, SLOT(fileChanged()));
132 animationUse=settings.readBoolEntry("/animation/use",false);
133 animationTicks=settings.readNumEntry("/animation/ticks",10);
134 animationInterval=settings.readNumEntry("/animation/interval",50);
136 animationTimer=new QTimer (this);
137 connect(animationTimer, SIGNAL(timeout()), this, SLOT(animate()));
140 defLinkColor=QColor (0,0,255);
141 defXLinkColor=QColor (180,180,180);
142 linkcolorhint=LinkableMapObj::DefaultColor;
143 linkstyle=LinkableMapObj::PolyParabel;
145 defXLinkColor=QColor (230,230,230);
153 // addMapCenter(); FIXME VM create this in MapEditor until BO and MCO are independent of scene
157 void VymModel::makeTmpDirectories()
159 // Create unique temporary directories
160 tmpMapDir = tmpVymDir+QString("/model-%1").arg(mapNum);
161 histPath = tmpMapDir+"/history";
167 MapEditor* VymModel::getMapEditor() // FIXME VM better return favourite editor here
172 bool VymModel::isRepositionBlocked()
174 return blockReposition;
177 void VymModel::updateActions() // FIXME maybe don't update if blockReposition is set
179 cout << "VymModel::updateActions \n";
180 // Tell mainwindow to update states of actions
181 mainWindow->updateActions();
186 QString VymModel::saveToDir(const QString &tmpdir, const QString &prefix, bool writeflags, const QPointF &offset, LinkableMapObj *saveSel)
188 // tmpdir temporary directory to which data will be written
189 // prefix mapname, which will be appended to images etc.
190 // writeflags Only write flags for "real" save of map, not undo
191 // offset offset of bbox of whole map in scene.
192 // Needed for XML export
201 case LinkableMapObj::Line:
204 case LinkableMapObj::Parabel:
207 case LinkableMapObj::PolyLine:
211 ls="StylePolyParabel";
215 QString s="<?xml version=\"1.0\" encoding=\"utf-8\"?><!DOCTYPE vymmap>\n";
217 if (linkcolorhint==LinkableMapObj::HeadingColor)
218 colhint=xml.attribut("linkColorHint","HeadingColor");
220 QString mapAttr=xml.attribut("version",vymVersion);
222 mapAttr+= xml.attribut("author",author) +
223 xml.attribut("comment",comment) +
224 xml.attribut("date",getDate()) +
225 xml.attribut("countBranches", QString().number(countBranches())) +
226 xml.attribut("backgroundColor", mapScene->backgroundBrush().color().name() ) +
227 xml.attribut("selectionColor", mapEditor->getSelectionColor().name() ) +
228 xml.attribut("linkStyle", ls ) +
229 xml.attribut("linkColor", defLinkColor.name() ) +
230 xml.attribut("defXLinkColor", defXLinkColor.name() ) +
231 xml.attribut("defXLinkWidth", QString().setNum(defXLinkWidth,10) ) +
233 s+=xml.beginElement("vymmap",mapAttr);
236 // Find the used flags while traversing the tree // FIXME this can be done local to vymmodel maybe...
237 standardFlagsDefault->resetUsedCounter();
239 // Reset the counters before saving
240 // TODO constr. of FIO creates lots of objects, better do this in some other way...
241 FloatImageObj (mapScene).resetSaveCounter();// FIXME this can be done local to vymmodel maybe...
243 // Build xml recursivly
244 if (!saveSel || typeid (*saveSel) == typeid (MapCenterObj))
245 // Save all mapcenters as complete map, if saveSel not set
246 s+=saveTreeToDir(tmpdir,prefix,writeflags,offset);
249 if ( typeid(*saveSel) == typeid(BranchObj) )
251 s+=((BranchObj*)(saveSel))->saveToDir(tmpdir,prefix,offset);
252 else if ( typeid(*saveSel) == typeid(FloatImageObj) )
254 s+=((FloatImageObj*)(saveSel))->saveToDir(tmpdir,prefix);
257 // Save local settings
258 s+=settings.getDataXML (destPath);
261 if (!selection.isEmpty() && !saveSel )
262 s+=xml.valueElement("select",selection.getSelectString());
265 s+=xml.endElement("vymmap");
268 standardFlagsDefault->saveToDir (tmpdir+"/flags/","",writeflags);
272 QString VymModel::saveTreeToDir (const QString &tmpdir,const QString &prefix, int verbose, const QPointF &offset)
276 for (int i=0; i<mapCenters.count(); i++)
277 s+=mapCenters.at(i)->saveToDir (tmpdir,prefix,verbose,offset);
281 void VymModel::setFilePath(QString fpath, QString destname)
283 if (fpath.isEmpty() || fpath=="")
290 filePath=fpath; // becomes absolute path
291 fileName=fpath; // gets stripped of path
292 destPath=destname; // needed for vymlinks and during load to reset fileChangedTime
294 // If fpath is not an absolute path, complete it
295 filePath=QDir(fpath).absPath();
296 fileDir=filePath.left (1+filePath.findRev ("/"));
298 // Set short name, too. Search from behind:
299 int i=fileName.findRev("/");
300 if (i>=0) fileName=fileName.remove (0,i+1);
302 // Forget the .vym (or .xml) for name of map
303 mapName=fileName.left(fileName.findRev(".",-1,true) );
307 void VymModel::setFilePath(QString fpath)
309 setFilePath (fpath,fpath);
312 QString VymModel::getFilePath()
317 QString VymModel::getFileName()
322 QString VymModel::getMapName()
327 QString VymModel::getDestPath()
332 ErrorCode VymModel::load (QString fname, const LoadMode &lmode, const FileType &ftype)
334 ErrorCode err=success;
336 parseBaseHandler *handler;
340 case VymMap: handler=new parseVYMHandler; break;
341 case FreemindMap : handler=new parseFreemindHandler; break;
343 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
344 "Unknown FileType in VymModel::load()");
348 bool zipped_org=zipped;
352 selModel->clearSelection();
353 // FIXME VM not needed??? model->setMapEditor(this);
354 // (map state is set later at end of load...)
357 BranchObj *bo=getSelectedBranch();
358 if (!bo) return aborted;
359 if (lmode==ImportAdd)
360 saveStateChangingPart(
363 QString("addMapInsert (%1)").arg(fname),
364 QString("Add map %1 to %2").arg(fname).arg(getObjectName(bo)));
366 saveStateChangingPart(
369 QString("addMapReplace(%1)").arg(fname),
370 QString("Add map %1 to %2").arg(fname).arg(getObjectName(bo)));
374 // Create temporary directory for packing
376 QString tmpZipDir=makeTmpDir (ok,"vym-pack");
379 QMessageBox::critical( 0, tr( "Critical Load Error" ),
380 tr("Couldn't create temporary directory before load\n"));
385 err=unzipDir (tmpZipDir,fname);
395 // Look for mapname.xml
396 xmlfile= fname.left(fname.findRev(".",-1,true));
397 xmlfile=xmlfile.section( '/', -1 );
398 QFile mfile( tmpZipDir + "/" + xmlfile + ".xml");
399 if (!mfile.exists() )
401 // mapname.xml does not exist, well,
402 // maybe someone renamed the mapname.vym file...
403 // Try to find any .xml in the toplevel
404 // directory of the .vym file
405 QStringList flist=QDir (tmpZipDir).entryList("*.xml");
406 if (flist.count()==1)
408 // Only one entry, take this one
409 xmlfile=tmpZipDir + "/"+flist.first();
412 for ( QStringList::Iterator it = flist.begin(); it != flist.end(); ++it )
413 *it=tmpZipDir + "/" + *it;
414 // TODO Multiple entries, load all (but only the first one into this ME)
415 //mainWindow->fileLoadFromTmp (flist);
416 //returnCode=1; // Silently forget this attempt to load
417 qWarning ("MainWindow::load (fn) multimap found...");
420 if (flist.isEmpty() )
422 QMessageBox::critical( 0, tr( "Critical Load Error" ),
423 tr("Couldn't find a map (*.xml) in .vym archive.\n"));
426 } //file doesn't exist
428 xmlfile=mfile.name();
431 QFile file( xmlfile);
433 // I am paranoid: file should exist anyway
434 // according to check in mainwindow.
437 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
438 tr(QString("Couldn't open map %1").arg(file.name())));
442 bool blockSaveStateOrg=blockSaveState;
443 blockReposition=true;
445 QXmlInputSource source( file);
446 QXmlSimpleReader reader;
447 reader.setContentHandler( handler );
448 reader.setErrorHandler( handler );
449 handler->setModel ( this);
452 // We need to set the tmpDir in order to load files with rel. path
457 tmpdir=fname.left(fname.findRev("/",-1));
458 handler->setTmpDir (tmpdir);
459 handler->setInputFile (file.name());
460 handler->setLoadMode (lmode);
461 bool ok = reader.parse( source );
462 blockReposition=false;
463 blockSaveState=blockSaveStateOrg;
467 reposition(); // FIXME VM reposition the view instead...
474 autosaveTimer->stop();
477 // Reset timestamp to check for later updates of file
478 fileChangedTime=QFileInfo (destPath).lastModified();
481 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
482 tr( handler->errorProtocol() ) );
484 // Still return "success": the map maybe at least
485 // partially read by the parser
490 removeDir (QDir(tmpZipDir));
492 // Restore original zip state
499 ErrorCode VymModel::save (const SaveMode &savemode)
503 QString safeFilePath;
505 ErrorCode err=success;
509 mapFileName=mapName+".xml";
511 // use name given by user, even if he chooses .doc
512 mapFileName=fileName;
514 // Look, if we should zip the data:
517 QMessageBox mb( vymName,
518 tr("The map %1\ndid not use the compressed "
519 "vym file format.\nWriting it uncompressed will also write images \n"
520 "and flags and thus may overwrite files in the "
521 "given directory\n\nDo you want to write the map").arg(filePath),
522 QMessageBox::Warning,
523 QMessageBox::Yes | QMessageBox::Default,
525 QMessageBox::Cancel | QMessageBox::Escape);
526 mb.setButtonText( QMessageBox::Yes, tr("compressed (vym default)") );
527 mb.setButtonText( QMessageBox::No, tr("uncompressed") );
528 mb.setButtonText( QMessageBox::Cancel, tr("Cancel"));
531 case QMessageBox::Yes:
532 // save compressed (default file format)
535 case QMessageBox::No:
539 case QMessageBox::Cancel:
546 // First backup existing file, we
547 // don't want to add to old zip archives
551 if ( settings.value ("/mapeditor/writeBackupFile").toBool())
553 QString backupFileName(destPath + "~");
554 QFile backupFile(backupFileName);
555 if (backupFile.exists() && !backupFile.remove())
557 QMessageBox::warning(0, tr("Save Error"),
558 tr("%1\ncould not be removed before saving").arg(backupFileName));
560 else if (!f.rename(backupFileName))
562 QMessageBox::warning(0, tr("Save Error"),
563 tr("%1\ncould not be renamed before saving").arg(destPath));
570 // Create temporary directory for packing
572 tmpZipDir=makeTmpDir (ok,"vym-zip");
575 QMessageBox::critical( 0, tr( "Critical Load Error" ),
576 tr("Couldn't create temporary directory before save\n"));
580 safeFilePath=filePath;
581 setFilePath (tmpZipDir+"/"+ mapName+ ".xml", safeFilePath);
584 // Create mapName and fileDir
585 makeSubDirs (fileDir);
588 if (savemode==CompleteMap || selection.isEmpty())
591 saveFile=saveToDir (fileDir,mapName+"-",true,QPointF(),NULL);
594 autosaveTimer->stop();
599 if (selectionType()==TreeItem::Image)
602 saveFile=saveToDir (fileDir,mapName+"-",true,QPointF(),getSelectedBranch());
603 // TODO take care of multiselections
606 if (!saveStringToDisk(fileDir+mapFileName,saveFile))
609 qWarning ("ME::saveStringToDisk failed!");
615 if (err==success) err=zipDir (tmpZipDir,destPath);
618 removeDir (QDir(tmpZipDir));
620 // Restore original filepath outside of tmp zip dir
621 setFilePath (safeFilePath);
625 fileChangedTime=QFileInfo (destPath).lastModified();
629 void VymModel::addMapReplaceInt(const QString &undoSel, const QString &path)
631 QString pathDir=path.left(path.findRev("/"));
637 // We need to parse saved XML data
638 parseVYMHandler handler;
639 QXmlInputSource source( file);
640 QXmlSimpleReader reader;
641 reader.setContentHandler( &handler );
642 reader.setErrorHandler( &handler );
643 handler.setModel ( this);
644 handler.setTmpDir ( pathDir ); // needed to load files with rel. path
645 if (undoSel.isEmpty())
649 handler.setLoadMode (NewMap);
653 handler.setLoadMode (ImportReplace);
655 blockReposition=true;
656 bool ok = reader.parse( source );
657 blockReposition=false;
660 // This should never ever happen
661 QMessageBox::critical( 0, tr( "Critical Parse Error while reading %1").arg(path),
662 handler.errorProtocol());
665 QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
668 void VymModel::addMapInsertInt (const QString &path, int pos)
670 BranchObj *sel=getSelectedBranch();
673 QString pathDir=path.left(path.findRev("/"));
679 // We need to parse saved XML data
680 parseVYMHandler handler;
681 QXmlInputSource source( file);
682 QXmlSimpleReader reader;
683 reader.setContentHandler( &handler );
684 reader.setErrorHandler( &handler );
685 handler.setModel (this);
686 handler.setTmpDir ( pathDir ); // needed to load files with rel. path
687 handler.setLoadMode (ImportAdd);
688 blockReposition=true;
689 bool ok = reader.parse( source );
690 blockReposition=false;
693 // This should never ever happen
694 QMessageBox::critical( 0, tr( "Critical Parse Error while reading %1").arg(path),
695 handler.errorProtocol());
697 if (sel->getDepth()>0)
698 sel->getLastBranch()->linkTo (sel,pos);
700 QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
704 FloatImageObj* VymModel::loadFloatImageInt (QString fn)
706 TreeItem *fi=createImage();
709 FloatImageObj *fio= ((FloatImageObj*)fi->getLMO());
717 void VymModel::loadFloatImage ()
719 BranchObj *bo=getSelectedBranch();
723 Q3FileDialog *fd=new Q3FileDialog( NULL);
724 fd->setMode (Q3FileDialog::ExistingFiles);
725 fd->addFilter (QString (tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)"));
726 ImagePreview *p =new ImagePreview (fd);
727 fd->setContentsPreviewEnabled( TRUE );
728 fd->setContentsPreview( p, p );
729 fd->setPreviewMode( Q3FileDialog::Contents );
730 fd->setCaption(vymName+" - " +tr("Load image"));
731 fd->setDir (lastImageDir);
734 if ( fd->exec() == QDialog::Accepted )
736 // TODO loadFIO in QT4 use: lastImageDir=fd->directory();
737 lastImageDir=QDir (fd->dirPath());
740 for (int j=0; j<fd->selectedFiles().count(); j++)
742 s=fd->selectedFiles().at(j);
743 fio=loadFloatImageInt (s);
746 (LinkableMapObj*)fio,
749 QString ("loadImage (%1)").arg(s ),
750 QString("Add image %1 to %2").arg(s).arg(getObjectName(bo))
753 // TODO loadFIO error handling
754 qWarning ("Failed to load "+s);
762 void VymModel::saveFloatImageInt (FloatImageObj *fio, const QString &type, const QString &fn)
767 void VymModel::saveFloatImage ()
769 FloatImageObj *fio=selection.getFloatImage();
772 QFileDialog *fd=new QFileDialog( NULL);
773 fd->setFilters (imageIO.getFilters());
774 fd->setCaption(vymName+" - " +tr("Save image"));
775 fd->setFileMode( QFileDialog::AnyFile );
776 fd->setDirectory (lastImageDir);
777 // fd->setSelection (fio->getOriginalFilename());
781 if ( fd->exec() == QDialog::Accepted && fd->selectedFiles().count()==1)
783 fn=fd->selectedFiles().at(0);
784 if (QFile (fn).exists() )
786 QMessageBox mb( vymName,
787 tr("The file %1 exists already.\n"
788 "Do you want to overwrite it?").arg(fn),
789 QMessageBox::Warning,
790 QMessageBox::Yes | QMessageBox::Default,
791 QMessageBox::Cancel | QMessageBox::Escape,
792 QMessageBox::NoButton );
794 mb.setButtonText( QMessageBox::Yes, tr("Overwrite") );
795 mb.setButtonText( QMessageBox::No, tr("Cancel"));
798 case QMessageBox::Yes:
801 case QMessageBox::Cancel:
808 saveFloatImageInt (fio,fd->selectedFilter(),fn );
815 void VymModel::importDirInt(BranchObj *dst, QDir d)
817 BranchObj *bo=getSelectedBranch();
820 // Traverse directories
821 d.setFilter( QDir::Dirs| QDir::Hidden | QDir::NoSymLinks );
822 QFileInfoList list = d.entryInfoList();
825 for (int i = 0; i < list.size(); ++i)
828 if (fi.fileName() != "." && fi.fileName() != ".." )
831 bo=dst->getLastBranch();
832 bo->setHeading (fi.fileName() );
833 bo->setColor (QColor("blue"));
835 if ( !d.cd(fi.fileName()) )
836 QMessageBox::critical (0,tr("Critical Import Error"),tr("Cannot find the directory %1").arg(fi.fileName()));
839 // Recursively add subdirs
846 d.setFilter( QDir::Files| QDir::Hidden | QDir::NoSymLinks );
847 list = d.entryInfoList();
849 for (int i = 0; i < list.size(); ++i)
853 bo=dst->getLastBranch();
854 bo->setHeading (fi.fileName() );
855 bo->setColor (QColor("black"));
856 if (fi.fileName().right(4) == ".vym" )
857 bo->setVymLink (fi.filePath());
862 void VymModel::importDirInt (const QString &s)
864 BranchObj *bo=getSelectedBranch();
867 saveStateChangingPart (bo,bo,QString ("importDir (\"%1\")").arg(s),QString("Import directory structure from %1").arg(s));
874 void VymModel::importDir()
876 BranchObj *bo=getSelectedBranch();
880 filters <<"VYM map (*.vym)";
881 QFileDialog *fd=new QFileDialog( NULL,vymName+ " - " +tr("Choose directory structure to import"));
882 fd->setMode (QFileDialog::DirectoryOnly);
883 fd->setFilters (filters);
884 fd->setCaption(vymName+" - " +tr("Choose directory structure to import"));
888 if ( fd->exec() == QDialog::Accepted )
890 importDirInt (fd->selectedFile() );
892 //FIXME VM needed? scene()->update();
898 void VymModel::autosave()
903 cout << "VymModel::autosave rejected due to missing filePath\n";
906 QDateTime now=QDateTime().currentDateTime();
908 // Disable autosave, while we have gone back in history
909 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
910 if (redosAvail>0) return;
912 // Also disable autosave for new map without filename
913 if (filePath.isEmpty()) return;
916 if (mapUnsaved &&mapChanged && settings.value ("/mainwindow/autosave/use",true).toBool() )
918 if (QFileInfo(filePath).lastModified()<=fileChangedTime)
919 mainWindow->fileSave (this);
922 cout <<" ME::autosave rejected, file on disk is newer than last save.\n";
927 void VymModel::fileChanged()
929 // Check if file on disk has changed meanwhile
930 if (!filePath.isEmpty())
932 QDateTime tmod=QFileInfo (filePath).lastModified();
933 if (tmod>fileChangedTime)
935 // FIXME VM switch to current mapeditor and finish lineedits...
936 QMessageBox mb( vymName,
937 tr("The file of the map on disk has changed:\n\n"
938 " %1\n\nDo you want to reload that map with the new file?").arg(filePath),
939 QMessageBox::Question,
941 QMessageBox::Cancel | QMessageBox::Default,
942 QMessageBox::NoButton );
944 mb.setButtonText( QMessageBox::Yes, tr("Reload"));
945 mb.setButtonText( QMessageBox::No, tr("Ignore"));
948 case QMessageBox::Yes:
950 load (filePath,NewMap,fileType);
951 case QMessageBox::Cancel:
952 fileChangedTime=tmod; // allow autosave to overwrite newer file!
958 bool VymModel::isDefault()
963 void VymModel::makeDefault()
969 bool VymModel::hasChanged()
974 void VymModel::setChanged()
976 cout << "VM::setChanged()\n";
979 autosaveTimer->start(settings.value("/mainwindow/autosave/ms/",300000).toInt());
980 cout <<" timer started with "<<settings.value("/mainwindow/autosave/ms/",300000).toInt()<<endl;
989 QString VymModel::getObjectName (const LinkableMapObj *lmo)
992 if (!lmo) return QString("Error: NULL has no name!");
994 if ((typeid(*lmo) == typeid(BranchObj) ||
995 typeid(*lmo) == typeid(MapCenterObj)))
998 s=(((BranchObj*)lmo)->getHeading());
999 if (s=="") s="unnamed";
1000 return QString("branch (%1)").arg(s);
1002 if ((typeid(*lmo) == typeid(FloatImageObj) ))
1003 return QString ("floatimage [%1]").arg(((FloatImageObj*)lmo)->getOriginalFilename());
1004 return QString("Unknown type has no name!");
1007 void VymModel::redo()
1009 // Can we undo at all?
1010 if (redosAvail<1) return;
1012 bool blockSaveStateOrg=blockSaveState;
1013 blockSaveState=true;
1017 if (undosAvail<stepsTotal) undosAvail++;
1019 if (curStep>stepsTotal) curStep=1;
1020 QString undoCommand= undoSet.readEntry (QString("/history/step-%1/undoCommand").arg(curStep));
1021 QString undoSelection=undoSet.readEntry (QString("/history/step-%1/undoSelection").arg(curStep));
1022 QString redoCommand= undoSet.readEntry (QString("/history/step-%1/redoCommand").arg(curStep));
1023 QString redoSelection=undoSet.readEntry (QString("/history/step-%1/redoSelection").arg(curStep));
1024 QString comment=undoSet.readEntry (QString("/history/step-%1/comment").arg(curStep));
1025 QString version=undoSet.readEntry ("/history/version");
1027 /* TODO Maybe check for version, if we save the history
1028 if (!checkVersion(version))
1029 QMessageBox::warning(0,tr("Warning"),
1030 tr("Version %1 of saved undo/redo data\ndoes not match current vym version %2.").arg(version).arg(vymVersion));
1033 // Find out current undo directory
1034 QString bakMapDir(QString(tmpMapDir+"/undo-%1").arg(curStep));
1038 cout << "VymModel::redo() begin\n";
1039 cout << " undosAvail="<<undosAvail<<endl;
1040 cout << " redosAvail="<<redosAvail<<endl;
1041 cout << " curStep="<<curStep<<endl;
1042 cout << " ---------------------------"<<endl;
1043 cout << " comment="<<comment.toStdString()<<endl;
1044 cout << " undoCom="<<undoCommand.toStdString()<<endl;
1045 cout << " undoSel="<<undoSelection.toStdString()<<endl;
1046 cout << " redoCom="<<redoCommand.toStdString()<<endl;
1047 cout << " redoSel="<<redoSelection.toStdString()<<endl;
1048 cout << " ---------------------------"<<endl<<endl;
1051 // select object before redo
1052 if (!redoSelection.isEmpty())
1053 select (redoSelection);
1056 parseAtom (redoCommand);
1059 blockSaveState=blockSaveStateOrg;
1061 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
1062 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
1063 undoSet.setEntry ("/history/curStep",QString::number(curStep));
1064 undoSet.writeSettings(histPath);
1066 mainWindow->updateHistory (undoSet);
1069 /* TODO remove testing
1070 cout << "ME::redo() end\n";
1071 cout << " undosAvail="<<undosAvail<<endl;
1072 cout << " redosAvail="<<redosAvail<<endl;
1073 cout << " curStep="<<curStep<<endl;
1074 cout << " ---------------------------"<<endl<<endl;
1080 bool VymModel::isRedoAvailable()
1082 if (undoSet.readNumEntry("/history/redosAvail",0)>0)
1088 void VymModel::undo()
1090 // Can we undo at all?
1091 if (undosAvail<1) return;
1093 mainWindow->statusMessage (tr("Autosave disabled during undo."));
1095 bool blockSaveStateOrg=blockSaveState;
1096 blockSaveState=true;
1098 QString undoCommand= undoSet.readEntry (QString("/history/step-%1/undoCommand").arg(curStep));
1099 QString undoSelection=undoSet.readEntry (QString("/history/step-%1/undoSelection").arg(curStep));
1100 QString redoCommand= undoSet.readEntry (QString("/history/step-%1/redoCommand").arg(curStep));
1101 QString redoSelection=undoSet.readEntry (QString("/history/step-%1/redoSelection").arg(curStep));
1102 QString comment=undoSet.readEntry (QString("/history/step-%1/comment").arg(curStep));
1103 QString version=undoSet.readEntry ("/history/version");
1105 /* TODO Maybe check for version, if we save the history
1106 if (!checkVersion(version))
1107 QMessageBox::warning(0,tr("Warning"),
1108 tr("Version %1 of saved undo/redo data\ndoes not match current vym version %2.").arg(version).arg(vymVersion));
1111 // Find out current undo directory
1112 QString bakMapDir(QString(tmpMapDir+"/undo-%1").arg(curStep));
1114 // select object before undo
1115 if (!undoSelection.isEmpty())
1116 select (undoSelection);
1120 cout << "VymModel::undo() begin\n";
1121 cout << " undosAvail="<<undosAvail<<endl;
1122 cout << " redosAvail="<<redosAvail<<endl;
1123 cout << " curStep="<<curStep<<endl;
1124 cout << " ---------------------------"<<endl;
1125 cout << " comment="<<comment.toStdString()<<endl;
1126 cout << " undoCom="<<undoCommand.toStdString()<<endl;
1127 cout << " undoSel="<<undoSelection.toStdString()<<endl;
1128 cout << " redoCom="<<redoCommand.toStdString()<<endl;
1129 cout << " redoSel="<<redoSelection.toStdString()<<endl;
1130 cout << " ---------------------------"<<endl<<endl;
1132 parseAtom (undoCommand);
1137 if (curStep<1) curStep=stepsTotal;
1141 blockSaveState=blockSaveStateOrg;
1142 /* TODO remove testing
1143 cout << "VymModel::undo() end\n";
1144 cout << " undosAvail="<<undosAvail<<endl;
1145 cout << " redosAvail="<<redosAvail<<endl;
1146 cout << " curStep="<<curStep<<endl;
1147 cout << " ---------------------------"<<endl<<endl;
1150 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
1151 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
1152 undoSet.setEntry ("/history/curStep",QString::number(curStep));
1153 undoSet.writeSettings(histPath);
1155 mainWindow->updateHistory (undoSet);
1158 ensureSelectionVisible();
1161 bool VymModel::isUndoAvailable()
1163 if (undoSet.readNumEntry("/history/undosAvail",0)>0)
1169 void VymModel::gotoHistoryStep (int i)
1171 // Restore variables
1172 int undosAvail=undoSet.readNumEntry (QString("/history/undosAvail"));
1173 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
1175 if (i<0) i=undosAvail+redosAvail;
1177 // Clicking above current step makes us undo things
1180 for (int j=0; j<undosAvail-i; j++) undo();
1183 // Clicking below current step makes us redo things
1185 for (int j=undosAvail; j<i; j++)
1187 if (debug) cout << "VymModel::gotoHistoryStep redo "<<j<<"/"<<undosAvail<<" i="<<i<<endl;
1191 // And ignore clicking the current row ;-)
1195 QString VymModel::getHistoryPath()
1197 QString histName(QString("history-%1").arg(curStep));
1198 return (tmpMapDir+"/"+histName);
1201 void VymModel::saveState(const SaveMode &savemode, const QString &undoSelection, const QString &undoCom, const QString &redoSelection, const QString &redoCom, const QString &comment, LinkableMapObj *saveSel)
1203 sendData(redoCom); //FIXME testing
1208 if (blockSaveState) return;
1210 if (debug) cout << "ME::saveState() for "<<qPrintable (mapName)<<endl;
1212 // Find out current undo directory
1213 if (undosAvail<stepsTotal) undosAvail++;
1215 if (curStep>stepsTotal) curStep=1;
1217 QString backupXML="";
1218 QString histDir=getHistoryPath();
1219 QString bakMapPath=histDir+"/map.xml";
1221 // Create histDir if not available
1224 makeSubDirs (histDir);
1226 // Save depending on how much needs to be saved
1228 backupXML=saveToDir (histDir,mapName+"-",false, QPointF (),saveSel);
1230 QString undoCommand="";
1231 if (savemode==UndoCommand)
1233 undoCommand=undoCom;
1235 else if (savemode==PartOfMap )
1237 undoCommand=undoCom;
1238 undoCommand.replace ("PATH",bakMapPath);
1241 if (!backupXML.isEmpty())
1242 // Write XML Data to disk
1243 saveStringToDisk (bakMapPath,backupXML);
1245 // We would have to save all actions in a tree, to keep track of
1246 // possible redos after a action. Possible, but we are too lazy: forget about redos.
1249 // Write the current state to disk
1250 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
1251 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
1252 undoSet.setEntry ("/history/curStep",QString::number(curStep));
1253 undoSet.setEntry (QString("/history/step-%1/undoCommand").arg(curStep),undoCommand);
1254 undoSet.setEntry (QString("/history/step-%1/undoSelection").arg(curStep),undoSelection);
1255 undoSet.setEntry (QString("/history/step-%1/redoCommand").arg(curStep),redoCom);
1256 undoSet.setEntry (QString("/history/step-%1/redoSelection").arg(curStep),redoSelection);
1257 undoSet.setEntry (QString("/history/step-%1/comment").arg(curStep),comment);
1258 undoSet.setEntry (QString("/history/version"),vymVersion);
1259 undoSet.writeSettings(histPath);
1263 // TODO remove after testing
1264 //cout << " into="<< histPath.toStdString()<<endl;
1265 cout << " stepsTotal="<<stepsTotal<<
1266 ", undosAvail="<<undosAvail<<
1267 ", redosAvail="<<redosAvail<<
1268 ", curStep="<<curStep<<endl;
1269 cout << " ---------------------------"<<endl;
1270 cout << " comment="<<comment.toStdString()<<endl;
1271 cout << " undoCom="<<undoCommand.toStdString()<<endl;
1272 cout << " undoSel="<<undoSelection.toStdString()<<endl;
1273 cout << " redoCom="<<redoCom.toStdString()<<endl;
1274 cout << " redoSel="<<redoSelection.toStdString()<<endl;
1275 if (saveSel) cout << " saveSel="<<qPrintable (getSelectString(saveSel))<<endl;
1276 cout << " ---------------------------"<<endl;
1279 mainWindow->updateHistory (undoSet);
1285 void VymModel::saveStateChangingPart(LinkableMapObj *undoSel, LinkableMapObj* redoSel, const QString &rc, const QString &comment)
1287 // save the selected part of the map, Undo will replace part of map
1288 QString undoSelection="";
1290 undoSelection=getSelectString(undoSel);
1292 qWarning ("VymModel::saveStateChangingPart no undoSel given!");
1293 QString redoSelection="";
1295 redoSelection=getSelectString(undoSel);
1297 qWarning ("VymModel::saveStateChangingPart no redoSel given!");
1300 saveState (PartOfMap,
1301 undoSelection, "addMapReplace (\"PATH\")",
1307 void VymModel::saveStateRemovingPart(LinkableMapObj *redoSel, const QString &comment)
1311 qWarning ("VymModel::saveStateRemovingPart no redoSel given!");
1314 QString undoSelection=getSelectString (redoSel->getParObj());
1315 QString redoSelection=getSelectString(redoSel);
1316 if (typeid(*redoSel) == typeid(BranchObj) )
1318 // save the selected branch of the map, Undo will insert part of map
1319 saveState (PartOfMap,
1320 undoSelection, QString("addMapInsert (\"PATH\",%1)").arg(((BranchObj*)redoSel)->getNum()),
1321 redoSelection, "delete ()",
1328 void VymModel::saveState(LinkableMapObj *undoSel, const QString &uc, LinkableMapObj *redoSel, const QString &rc, const QString &comment)
1330 // "Normal" savestate: save commands, selections and comment
1331 // so just save commands for undo and redo
1332 // and use current selection
1334 QString redoSelection="";
1335 if (redoSel) redoSelection=getSelectString(redoSel);
1336 QString undoSelection="";
1337 if (undoSel) undoSelection=getSelectString(undoSel);
1339 saveState (UndoCommand,
1346 void VymModel::saveState(const QString &undoSel, const QString &uc, const QString &redoSel, const QString &rc, const QString &comment)
1348 // "Normal" savestate: save commands, selections and comment
1349 // so just save commands for undo and redo
1350 // and use current selection
1351 saveState (UndoCommand,
1358 void VymModel::saveState(const QString &uc, const QString &rc, const QString &comment)
1360 // "Normal" savestate applied to model (no selection needed):
1361 // save commands and comment
1362 saveState (UndoCommand,
1370 QGraphicsScene* VymModel::getScene ()
1375 LinkableMapObj* VymModel::findMapObj(QPointF p, LinkableMapObj *excludeLMO)
1377 LinkableMapObj *lmo;
1379 for (int i=0;i<mapCenters.count(); i++)
1381 lmo=mapCenters.at(i)->findMapObj (p,excludeLMO);
1382 if (lmo) return lmo;
1387 LinkableMapObj* VymModel::findObjBySelect(const QString &s)
1389 LinkableMapObj *lmo;
1395 part=s.section(",",0,0);
1397 num=part.right(part.length() - 3);
1398 if (typ=="mc" && num.toInt()>=0 && num.toInt() <mapCenters.count() )
1399 return mapCenters.at(num.toInt() );
1402 for (int i=0; i<mapCenters.count(); i++)
1404 lmo=mapCenters.at(i)->findObjBySelect(s);
1405 if (lmo) return lmo;
1410 LinkableMapObj* VymModel::findID (const QString &s)
1412 LinkableMapObj *lmo;
1413 for (int i=0; i<mapCenters.count(); i++)
1415 lmo=mapCenters.at(i)->findID (s);
1416 if (lmo) return lmo;
1421 //////////////////////////////////////////////
1423 //////////////////////////////////////////////
1424 void VymModel::setVersion (const QString &s)
1429 void VymModel::setAuthor (const QString &s)
1432 QString ("setMapAuthor (\"%1\")").arg(author),
1433 QString ("setMapAuthor (\"%1\")").arg(s),
1434 QString ("Set author of map to \"%1\"").arg(s)
1440 QString VymModel::getAuthor()
1445 void VymModel::setComment (const QString &s)
1448 QString ("setMapComment (\"%1\")").arg(comment),
1449 QString ("setMapComment (\"%1\")").arg(s),
1450 QString ("Set comment of map")
1456 QString VymModel::getComment ()
1461 QString VymModel::getDate ()
1463 return QDate::currentDate().toString ("yyyy-MM-dd");
1466 int VymModel::countBranches() // FIXME Optimize this: use internal counter instead of going through whole map each time...
1470 TreeItem *prev=NULL;
1482 void VymModel::setHeading(const QString &s)
1484 BranchObj *sel=getSelectedBranch();
1489 "setHeading (\""+sel->getHeading()+"\")",
1491 "setHeading (\""+s+"\")",
1492 QString("Set heading of %1 to \"%2\"").arg(getObjectName(sel)).arg(s) );
1493 sel->setHeading(s );
1494 /* FIXME testing only
1496 TreeItem *ti=getSelectedItem();
1500 //FIXME VM ix is wrong ModelIndex below, ix2 is (hopefully) correct:
1501 //QModelIndex ix=index( ti->row(), ti->column(), index (0,0,QModelIndex()) );
1502 //FIXME VM testing only cout <<"VM::setHeading s="<<s.toStdString()<<" ti="<<ti<<" r,c=("<<ti->row()<<","<<ti->column()<<")"<<endl;
1503 QModelIndex ix2=index (ti);
1504 emit (dataChanged ( ix2,ix2));
1508 cout << "Warning: VM::setHeading ti==NULL\n";
1511 //cout <<" (r,c)=("<<ix2.row()<<","<<ix2.column()<<")"<<endl;
1515 ensureSelectionVisible();
1519 BranchObj* VymModel::findText (QString s, bool cs)
1522 QTextDocument::FindFlags flags=0;
1523 if (cs) flags=QTextDocument::FindCaseSensitively;
1526 { // Nothing found or new find process
1528 // nothing found, start again
1532 next (findCurrent,findPrevious,d);
1534 bool searching=true;
1535 bool foundNote=false;
1536 while (searching && !EOFind)
1540 // Searching in Note
1541 if (findCurrent->getNote().contains(s,cs))
1543 select (findCurrent);
1545 if (getSelectedBranch()!=itFind)
1548 ensureSelectionVisible();
1551 if (textEditor->findText(s,flags))
1557 // Searching in Heading
1558 if (searching && findCurrent->getHeading().contains (s,cs) )
1560 select(findCurrent);
1566 if (!next(findCurrent,findPrevious,d) )
1569 //cout <<"still searching... "<<qPrintable( itFind->getHeading())<<endl;
1572 return getSelectedBranch();
1577 void VymModel::findReset()
1578 { // Necessary if text to find changes during a find process
1586 void VymModel::setScene (QGraphicsScene *s)
1588 cout << "VM::setscene scene="<<s<<endl;
1589 mapScene=s; // FIXME VM should not be necessary anymore, move all occurences to MapEditor
1590 //init(); // Here we have a mapScene set,
1591 // which is (still) needed to create MapCenters
1594 void VymModel::setURL(const QString &url)
1596 BranchObj *bo=getSelectedBranch();
1599 QString oldurl=bo->getURL();
1603 QString ("setURL (\"%1\")").arg(oldurl),
1605 QString ("setURL (\"%1\")").arg(url),
1606 QString ("set URL of %1 to %2").arg(getObjectName(bo)).arg(url)
1611 ensureSelectionVisible();
1615 QString VymModel::getURL()
1617 BranchObj *bo=getSelectedBranch();
1619 return bo->getURL();
1624 QStringList VymModel::getURLs()
1627 BranchObj *bo=getSelectedBranch();
1633 if (!bo->getURL().isEmpty()) urls.append( bo->getURL());
1640 void VymModel::linkFloatImageTo(const QString &dstString)
1642 FloatImageObj *fio=selection.getFloatImage();
1645 BranchObj *dst=(BranchObj*)findObjBySelect(dstString);
1646 if (dst && (typeid(*dst)==typeid (BranchObj) ||
1647 typeid(*dst)==typeid (MapCenterObj)))
1649 LinkableMapObj *dstPar=dst->getParObj();
1650 QString parString=getSelectString(dstPar);
1651 QString fioPreSelectString=getSelectString(fio);
1652 QString fioPreParentSelectString=getSelectString (fio->getParObj());
1653 ((BranchObj*)dst)->addFloatImage (fio);
1654 selection.unselect();
1655 ((BranchObj*)(fio->getParObj()))->removeFloatImage (fio);
1656 fio=((BranchObj*)dst)->getLastFloatImage();
1659 selection.select(fio);
1661 getSelectString(fio),
1662 QString("linkTo (\"%1\")").arg(fioPreParentSelectString),
1664 QString ("linkTo (\"%1\")").arg(dstString),
1665 QString ("Link floatimage to %1").arg(getObjectName(dst)));
1671 void VymModel::setFrameType(const FrameObj::FrameType &t)
1673 BranchObj *bo=getSelectedBranch();
1676 QString s=bo->getFrameTypeName();
1677 bo->setFrameType (t);
1678 saveState (bo, QString("setFrameType (\"%1\")").arg(s),
1679 bo, QString ("setFrameType (\"%1\")").arg(bo->getFrameTypeName()),QString ("set type of frame to %1").arg(s));
1685 void VymModel::setFrameType(const QString &s)
1687 BranchObj *bo=getSelectedBranch();
1690 saveState (bo, QString("setFrameType (\"%1\")").arg(bo->getFrameTypeName()),
1691 bo, QString ("setFrameType (\"%1\")").arg(s),QString ("set type of frame to %1").arg(s));
1692 bo->setFrameType (s);
1698 void VymModel::setFramePenColor(const QColor &c)
1700 BranchObj *bo=getSelectedBranch();
1703 saveState (bo, QString("setFramePenColor (\"%1\")").arg(bo->getFramePenColor().name() ),
1704 bo, QString ("setFramePenColor (\"%1\")").arg(c.name() ),QString ("set pen color of frame to %1").arg(c.name() ));
1705 bo->setFramePenColor (c);
1709 void VymModel::setFrameBrushColor(const QColor &c)
1711 BranchObj *bo=getSelectedBranch();
1714 saveState (bo, QString("setFrameBrushColor (\"%1\")").arg(bo->getFrameBrushColor().name() ),
1715 bo, QString ("setFrameBrushColor (\"%1\")").arg(c.name() ),QString ("set brush color of frame to %1").arg(c.name() ));
1716 bo->setFrameBrushColor (c);
1720 void VymModel::setFramePadding (const int &i)
1722 BranchObj *bo=getSelectedBranch();
1725 saveState (bo, QString("setFramePadding (\"%1\")").arg(bo->getFramePadding() ),
1726 bo, QString ("setFramePadding (\"%1\")").arg(i),QString ("set brush color of frame to %1").arg(i));
1727 bo->setFramePadding (i);
1733 void VymModel::setFrameBorderWidth(const int &i)
1735 BranchObj *bo=getSelectedBranch();
1738 saveState (bo, QString("setFrameBorderWidth (\"%1\")").arg(bo->getFrameBorderWidth() ),
1739 bo, QString ("setFrameBorderWidth (\"%1\")").arg(i),QString ("set border width of frame to %1").arg(i));
1740 bo->setFrameBorderWidth (i);
1746 void VymModel::setIncludeImagesVer(bool b)
1748 BranchObj *bo=getSelectedBranch();
1751 QString u= b ? "false" : "true";
1752 QString r=!b ? "false" : "true";
1756 QString("setIncludeImagesVertically (%1)").arg(u),
1758 QString("setIncludeImagesVertically (%1)").arg(r),
1759 QString("Include images vertically in %1").arg(getObjectName(bo))
1761 bo->setIncludeImagesVer(b);
1766 void VymModel::setIncludeImagesHor(bool b)
1768 BranchObj *bo=getSelectedBranch();
1771 QString u= b ? "false" : "true";
1772 QString r=!b ? "false" : "true";
1776 QString("setIncludeImagesHorizontally (%1)").arg(u),
1778 QString("setIncludeImagesHorizontally (%1)").arg(r),
1779 QString("Include images horizontally in %1").arg(getObjectName(bo))
1781 bo->setIncludeImagesHor(b);
1786 void VymModel::setHideLinkUnselected (bool b)
1788 LinkableMapObj *sel=getSelectedLMO();
1790 (selectionType() == TreeItem::Branch ||
1791 selectionType() == TreeItem::MapCenter ||
1792 selectionType() == TreeItem::Image ))
1794 QString u= b ? "false" : "true";
1795 QString r=!b ? "false" : "true";
1799 QString("setHideLinkUnselected (%1)").arg(u),
1801 QString("setHideLinkUnselected (%1)").arg(r),
1802 QString("Hide link of %1 if unselected").arg(getObjectName(sel))
1804 sel->setHideLinkUnselected(b);
1808 void VymModel::setHideExport(bool b)
1810 BranchObj *bo=getSelectedBranch();
1813 bo->setHideInExport (b);
1814 QString u= b ? "false" : "true";
1815 QString r=!b ? "false" : "true";
1819 QString ("setHideExport (%1)").arg(u),
1821 QString ("setHideExport (%1)").arg(r),
1822 QString ("Set HideExport flag of %1 to %2").arg(getObjectName(bo)).arg (r)
1827 // FIXME VM needed? scene()->update();
1831 void VymModel::toggleHideExport()
1833 BranchObj *bo=getSelectedBranch();
1835 setHideExport ( !bo->hideInExport() );
1839 void VymModel::copy()
1841 LinkableMapObj *sel=getSelectedLMO();
1843 (selectionType() == TreeItem::Branch ||
1844 selectionType() == TreeItem::MapCenter ||
1845 selectionType() == TreeItem::Image ))
1847 if (redosAvail == 0)
1850 QString s=getSelectString(sel);
1851 saveState (PartOfMap, s, "nop ()", s, "copy ()","Copy selection to clipboard",sel );
1852 curClipboard=curStep;
1855 // Copy also to global clipboard, because we are at last step in history
1856 QString bakMapName(QString("history-%1").arg(curStep));
1857 QString bakMapDir(tmpMapDir +"/"+bakMapName);
1858 copyDir (bakMapDir,clipboardDir );
1860 clipboardEmpty=false;
1866 void VymModel::pasteNoSave(const int &n)
1868 bool old=blockSaveState;
1869 blockSaveState=true;
1870 bool zippedOrg=zipped;
1871 if (redosAvail > 0 || n!=0)
1873 // Use the "historical" buffer
1874 QString bakMapName(QString("history-%1").arg(n));
1875 QString bakMapDir(tmpMapDir +"/"+bakMapName);
1876 load (bakMapDir+"/"+clipboardFile,ImportAdd, VymMap);
1878 // Use the global buffer
1879 load (clipboardDir+"/"+clipboardFile,ImportAdd, VymMap);
1884 void VymModel::paste()
1886 BranchObj *sel=getSelectedBranch();
1889 saveStateChangingPart(
1892 QString ("paste (%1)").arg(curClipboard),
1893 QString("Paste to %1").arg( getObjectName(sel))
1900 void VymModel::cut()
1902 LinkableMapObj *sel=getSelectedLMO();
1903 if ( sel && (selectionType() == TreeItem::Branch ||
1904 selectionType()==TreeItem::MapCenter ||
1905 selectionType()==TreeItem::Image))
1907 /* No savestate! savestate is called in cutNoSave
1908 saveStateChangingPart(
1912 QString("Cut %1").arg(getObjectName(sel ))
1921 void VymModel::moveBranchUp()
1923 BranchObj* bo=getSelectedBranch();
1927 if (!bo->canMoveBranchUp()) return;
1928 par=(BranchObj*)(bo->getParObj());
1929 BranchObj *obo=par->moveBranchUp (bo); // bo will be the one below selection
1930 saveState (getSelectString(bo),"moveBranchDown ()",getSelectString(obo),"moveBranchUp ()",QString("Move up %1").arg(getObjectName(bo)));
1932 //FIXME VM needed? scene()->update();
1934 ensureSelectionVisible();
1938 void VymModel::moveBranchDown()
1940 BranchObj* bo=getSelectedBranch();
1944 if (!bo->canMoveBranchDown()) return;
1945 par=(BranchObj*)(bo->getParObj());
1946 BranchObj *obo=par->moveBranchDown(bo); // bo will be the one above selection
1947 saveState(getSelectString(bo),"moveBranchUp ()",getSelectString(obo),"moveBranchDown ()",QString("Move down %1").arg(getObjectName(bo)));
1949 //FIXME VM needed? scene()->update();
1951 ensureSelectionVisible();
1955 void VymModel::sortChildren()
1957 BranchObj* bo=getSelectedBranch();
1960 if(bo->countBranches()>1)
1962 saveStateChangingPart(bo,bo, "sortChildren ()",QString("Sort children of %1").arg(getObjectName(bo)));
1965 ensureSelectionVisible();
1970 void VymModel::createMapCenter()
1972 MapCenterObj *mco=addMapCenter (QPointF (0,0) );
1976 void VymModel::createBranch()
1978 addNewBranchInt (-2);
1982 TreeItem* VymModel::createImage()
1984 BranchObj *bo=getSelectedBranch();
1987 FloatImageObj *newfio=bo->addFloatImage(); // FIXME VM Old model, merge with below
1990 QList<QVariant> cData;
1991 cData << "VM:createImage" << "undef"<<"undef";
1992 TreeItem *parti=bo->getTreeItem();
1993 TreeItem *ti=new TreeItem (cData,parti);
1994 ti->setLMO (newfio);
1995 ti->setType (TreeItem::Image);
1996 parti->appendChild (ti);
2000 newfio->setTreeItem (ti);
2001 select (newfio); // FIXME VM really needed here?
2008 MapCenterObj* VymModel::addMapCenter ()
2010 MapCenterObj *mco=addMapCenter (contextPos);
2011 cout <<"VM::addMCO () mapScene="<<mapScene<<endl;
2012 //FIXME selection.select (mco);
2014 ensureSelectionVisible();
2019 QString ("addMapCenter (%1,%2)").arg (contextPos.x()).arg(contextPos.y()),
2020 QString ("Adding MapCenter to (%1,%2)").arg (contextPos.x()).arg(contextPos.y())
2025 MapCenterObj* VymModel::addMapCenter(QPointF absPos)
2027 MapCenterObj *mapCenter = new MapCenterObj(mapScene,this);
2028 mapCenter->setMapEditor(mapEditor); //FIXME VM needed to get defLinkStyle, mapLinkColorHint ... for later added objects
2029 mapCenter->move (absPos);
2030 mapCenter->setVisibility (true);
2031 mapCenter->setHeading (QApplication::translate("Heading of mapcenter in new map", "New map"));
2032 mapCenters.append(mapCenter);
2035 QModelIndex parix=index(rootItem);
2037 int n=rootItem->branchCount();
2038 cout << "VM::addMapCenter n="<<n<<endl;
2040 emit (layoutAboutToBeChanged() );
2041 beginInsertRows (parix,n,n+1);
2043 QList<QVariant> cData;
2044 cData << "VM:addMapCenter" << "undef"<<"undef";
2045 TreeItem *ti=new TreeItem (cData,rootItem);
2046 ti->setLMO (mapCenter);
2047 ti->setType (TreeItem::MapCenter);
2048 mapCenter->setTreeItem (ti);
2049 rootItem->appendChild (ti);
2052 emit (newChildObject (parix));
2053 emit (layoutChanged() );
2057 qWarning ("MW::insertRow a");
2058 if (!insertRow(0, parix))
2060 std::cout << " war nix...\n";
2062 qWarning ("MW::insertRow b");
2068 MapCenterObj* VymModel::removeMapCenter(MapCenterObj* mco)
2070 int i=mapCenters.indexOf (mco);
2073 mapCenters.removeAt (i);
2075 if (i>0) return mapCenters.at(i-1); // Return previous MCO
2080 MapCenterObj* VymModel::getLastMapCenter()
2082 if (mapCenters.size()>0)
2083 return mapCenters.last();
2090 BranchObj* VymModel::addNewBranchInt(int num)
2092 // Depending on pos:
2093 // -3 insert in children of parent above selection
2094 // -2 add branch to selection
2095 // -1 insert in children of parent below selection
2096 // 0..n insert in children of parent at pos
2097 BranchObj *newbo=NULL;
2098 BranchObj *bo=getSelectedBranch();
2103 // save scroll state. If scrolled, automatically select
2104 // new branch in order to tmp unscroll parent...
2105 newbo=bo->addBranch();
2108 QList<QVariant> cData;
2109 cData << "new" << "undef"<<"undef";
2111 TreeItem *parti=bo->getTreeItem();
2112 QModelIndex parix=index(parti);
2113 int n=parti->branchCount();
2115 emit (layoutAboutToBeChanged() );
2116 beginInsertRows (parix,n,n+1);
2117 TreeItem *ti=new TreeItem (cData,parti);
2119 ti->setType (TreeItem::Branch);
2121 parti->appendChild (ti);
2123 emit (newChildObject (parix));
2124 emit (layoutChanged() );
2128 newbo->setTreeItem (ti);
2129 select (newbo); // FIXME VM really needed here?
2135 bo=(BranchObj*)bo->getParObj();
2136 if (bo) newbo=bo->insertBranch(num); //FIXME VM still missing
2140 bo=(BranchObj*)bo->getParObj();
2141 if (bo) newbo=bo->insertBranch(num); //FIXME VM still missing
2147 BranchObj* VymModel::addNewBranch(int pos)
2149 // Different meaning than num in addNewBranchInt!
2153 BranchObj *bo = getSelectedBranch();
2154 BranchObj *newbo=NULL;
2158 // FIXME VM do we still need this in model? setCursor (Qt::ArrowCursor);
2160 newbo=addNewBranchInt (pos-2);
2168 QString ("addBranch (%1)").arg(pos),
2169 QString ("Add new branch to %1").arg(getObjectName(bo)));
2172 // selection.update(); FIXME
2173 latestSelectionString=getSelectString(newbo);
2174 // In Network mode, the client needs to know where the new branch is,
2175 // so we have to pass on this information via saveState.
2176 // TODO: Get rid of this positioning workaround
2177 QString ps=qpointfToString (newbo->getAbsPos());
2178 sendData ("selectLatestAdded ()");
2179 sendData (QString("move %1").arg(ps));
2187 BranchObj* VymModel::addNewBranchBefore()
2189 BranchObj *newbo=NULL;
2190 BranchObj *bo = getSelectedBranch();
2191 if (bo && selectionType()==TreeItem::Branch)
2192 // We accept no MapCenterObj here, so we _have_ a parent
2194 QPointF p=bo->getRelPos();
2197 BranchObj *parbo=(BranchObj*)(bo->getParObj());
2199 // add below selection
2200 newbo=parbo->insertBranch(bo->getNum()+1); //FIXME VM still missing
2204 newbo->move2RelPos (p);
2206 // Move selection to new branch
2207 bo->linkTo (newbo,-1);
2209 saveState (newbo, "deleteKeepChildren ()", newbo, "addBranchBefore ()",
2210 QString ("Add branch before %1").arg(getObjectName(bo)));
2213 // selection.update(); FIXME
2216 latestSelectionString=selection.getSelectString();
2220 void VymModel::deleteSelection()
2222 BranchObj *bo = getSelectedBranch(); // FIXME VM should not be necessary
2225 QModelIndex ix=getSelectedIndex();
2226 if (!ix.isValid() ) return;
2228 QModelIndex parentIndex=parent(ix);
2229 if (!parentIndex.isValid()) return;
2230 TreeItem *ti=bo->getTreeItem();
2232 if (selectionType()==TreeItem::MapCenter) //FIXME VM still missing
2234 // BranchObj* par=(BranchObj*)(bo->getParObj());
2235 //selection.unselect();
2236 /* FIXME VM Note: does saveStateRemovingPart work for MCO? (No parent!)
2237 saveStateRemovingPart (bo, QString ("Delete %1").arg(getObjectName(bo)));
2240 bo=removeMapCenter ((MapCenterObj*)bo);
2243 selection.select (bo);
2244 ensureSelectionVisible();
2251 if (selectionType()==TreeItem::Branch)
2253 int n=ti->branchCount();
2255 BranchObj* par=(BranchObj*)bo->getParObj();
2257 saveStateRemovingPart (bo, QString ("Delete %1").arg(getObjectName(bo)));
2259 emit (layoutAboutToBeChanged() );
2261 cout << "VM::delete ti="<<ti<<" row="<<ix.row()<<endl;
2262 parentIndex=parent(index(ti));
2263 cout << " valid parentIndex="<<parentIndex.isValid()<<endl;
2264 beginRemoveRows (parentIndex,n,n);
2265 removeRows (ix.row(),1,parentIndex);
2267 par->removeBranch(bo);
2269 ensureSelectionVisible();
2272 emit (layoutChanged() );
2275 FloatImageObj *fio=selection.getFloatImage(); //FIXME VM still missing
2279 BranchObj* par=(BranchObj*)fio->getParObj();
2280 saveStateChangingPart(
2284 QString("Delete %1").arg(getObjectName(fio))
2287 par->removeFloatImage(fio);
2290 ensureSelectionVisible();
2295 void VymModel::deleteKeepChildren() //FIXME VM still missing
2298 BranchObj *bo=getSelectedBranch();
2302 par=(BranchObj*)(bo->getParObj());
2304 // Don't use this on mapcenter
2307 // Check if we have childs at all to keep
2308 if (bo->countBranches()==0)
2314 QPointF p=bo->getRelPos();
2315 saveStateChangingPart(
2318 "deleteKeepChildren ()",
2319 QString("Remove %1 and keep its children").arg(getObjectName(bo))
2322 QString sel=getSelectString(bo);
2324 par->removeBranchHere(bo);
2327 getSelectedBranch()->move2RelPos (p);
2332 void VymModel::deleteChildren() //FIXME VM still missing
2335 BranchObj *bo=getSelectedBranch();
2338 saveStateChangingPart(
2341 "deleteChildren ()",
2342 QString( "Remove children of branch %1").arg(getObjectName(bo))
2344 bo->removeChildren();
2350 bool VymModel::scrollBranch(BranchObj *bo)
2354 if (bo->isScrolled()) return false;
2355 if (bo->countBranches()==0) return false;
2356 if (bo->getDepth()==0) return false;
2362 QString ("%1 ()").arg(u),
2364 QString ("%1 ()").arg(r),
2365 QString ("%1 %2").arg(r).arg(getObjectName(bo))
2369 // FIXME VM needed? scene()->update();
2375 bool VymModel::unscrollBranch(BranchObj *bo)
2379 if (!bo->isScrolled()) return false;
2380 if (bo->countBranches()==0) return false;
2381 if (bo->getDepth()==0) return false;
2387 QString ("%1 ()").arg(u),
2389 QString ("%1 ()").arg(r),
2390 QString ("%1 %2").arg(r).arg(getObjectName(bo))
2394 // FIXME VM needed? scene()->update();
2400 void VymModel::toggleScroll()
2402 BranchObj *bo=getSelectedBranch();
2403 if (selectionType()==TreeItem::Branch )
2405 if (bo->isScrolled())
2406 unscrollBranch (bo);
2412 void VymModel::unscrollChildren()
2414 BranchObj *bo=getSelectedBranch();
2420 if (bo->isScrolled()) unscrollBranch (bo);
2425 void VymModel::addFloatImage (const QPixmap &img)
2427 BranchObj *bo=getSelectedBranch();
2430 FloatImageObj *fio=bo->addFloatImage();
2432 fio->setOriginalFilename("No original filename (image added by dropevent)");
2433 QString s=getSelectString(bo);
2434 saveState (PartOfMap, s, "nop ()", s, "copy ()","Copy dropped image to clipboard",fio );
2435 saveState (fio,"delete ()", bo,QString("paste(%1)").arg(curStep),"Pasting dropped image");
2437 // FIXME VM needed? scene()->update();
2442 void VymModel::colorBranch (QColor c)
2444 BranchObj *bo=getSelectedBranch();
2449 QString ("colorBranch (\"%1\")").arg(bo->getColor().name()),
2451 QString ("colorBranch (\"%1\")").arg(c.name()),
2452 QString("Set color of %1 to %2").arg(getObjectName(bo)).arg(c.name())
2454 bo->setColor(c); // color branch
2458 void VymModel::colorSubtree (QColor c)
2460 BranchObj *bo=getSelectedBranch();
2463 saveStateChangingPart(
2466 QString ("colorSubtree (\"%1\")").arg(c.name()),
2467 QString ("Set color of %1 and children to %2").arg(getObjectName(bo)).arg(c.name())
2469 bo->setColorSubtree (c); // color links, color children
2473 QColor VymModel::getCurrentHeadingColor()
2475 BranchObj *bo=getSelectedBranch();
2476 if (bo) return bo->getColor();
2478 QMessageBox::warning(0,"Warning","Can't get color of heading,\nthere's no branch selected");
2484 void VymModel::editURL()
2486 BranchObj *bo=getSelectedBranch();
2490 QString text = QInputDialog::getText(
2491 "VYM", tr("Enter URL:"), QLineEdit::Normal,
2492 bo->getURL(), &ok, NULL);
2494 // user entered something and pressed OK
2499 void VymModel::editLocalURL()
2501 BranchObj *bo=getSelectedBranch();
2504 QStringList filters;
2505 filters <<"All files (*)";
2506 filters << tr("Text","Filedialog") + " (*.txt)";
2507 filters << tr("Spreadsheet","Filedialog") + " (*.odp,*.sxc)";
2508 filters << tr("Textdocument","Filedialog") +" (*.odw,*.sxw)";
2509 filters << tr("Images","Filedialog") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)";
2510 QFileDialog *fd=new QFileDialog( NULL,vymName+" - " +tr("Set URL to a local file"));
2511 fd->setFilters (filters);
2512 fd->setCaption(vymName+" - " +tr("Set URL to a local file"));
2513 fd->setDirectory (lastFileDir);
2514 if (! bo->getVymLink().isEmpty() )
2515 fd->selectFile( bo->getURL() );
2518 if ( fd->exec() == QDialog::Accepted )
2520 lastFileDir=QDir (fd->directory().path());
2521 setURL (fd->selectedFile() );
2527 void VymModel::editHeading2URL()
2529 BranchObj *bo=getSelectedBranch();
2531 setURL (bo->getHeading());
2534 void VymModel::editBugzilla2URL()
2536 BranchObj *bo=getSelectedBranch();
2539 QString url= "https://bugzilla.novell.com/show_bug.cgi?id="+bo->getHeading();
2544 void VymModel::editFATE2URL()
2546 BranchObj *bo=getSelectedBranch();
2549 QString url= "http://keeper.suse.de:8080/webfate/match/id?value=ID"+bo->getHeading();
2552 "setURL (\""+bo->getURL()+"\")",
2554 "setURL (\""+url+"\")",
2555 QString("Use heading of %1 as link to FATE").arg(getObjectName(bo))
2562 void VymModel::editVymLink()
2564 BranchObj *bo=getSelectedBranch();
2567 QStringList filters;
2568 filters <<"VYM map (*.vym)";
2569 QFileDialog *fd=new QFileDialog( NULL,vymName+" - " +tr("Link to another map"));
2570 fd->setFilters (filters);
2571 fd->setCaption(vymName+" - " +tr("Link to another map"));
2572 fd->setDirectory (lastFileDir);
2573 if (! bo->getVymLink().isEmpty() )
2574 fd->selectFile( bo->getVymLink() );
2578 if ( fd->exec() == QDialog::Accepted )
2580 lastFileDir=QDir (fd->directory().path());
2583 "setVymLink (\""+bo->getVymLink()+"\")",
2585 "setVymLink (\""+fd->selectedFile()+"\")",
2586 QString("Set vymlink of %1 to %2").arg(getObjectName(bo)).arg(fd->selectedFile())
2588 setVymLink (fd->selectedFile() ); // FIXME ok?
2593 void VymModel::setVymLink (const QString &s)
2595 // Internal function, no saveState needed
2596 BranchObj *bo=getSelectedBranch();
2603 ensureSelectionVisible();
2607 void VymModel::deleteVymLink()
2609 BranchObj *bo=getSelectedBranch();
2614 "setVymLink (\""+bo->getVymLink()+"\")",
2616 "setVymLink (\"\")",
2617 QString("Unset vymlink of %1").arg(getObjectName(bo))
2619 bo->setVymLink ("" );
2622 // FIXME VM needed? scene()->update();
2626 QString VymModel::getVymLink()
2628 BranchObj *bo=getSelectedBranch();
2630 return bo->getVymLink();
2636 QStringList VymModel::getVymLinks()
2639 BranchObj *bo=getSelectedBranch();
2645 if (!bo->getVymLink().isEmpty()) links.append( bo->getVymLink());
2653 void VymModel::followXLink(int i)
2655 BranchObj *bo=getSelectedBranch();
2658 bo=bo->XLinkTargetAt(i);
2661 selection.select(bo);
2662 ensureSelectionVisible();
2667 void VymModel::editXLink(int i) // FIXME VM missing saveState
2669 BranchObj *bo=getSelectedBranch();
2672 XLinkObj *xlo=bo->XLinkAt(i);
2675 EditXLinkDialog dia;
2677 dia.setSelection(bo);
2678 if (dia.exec() == QDialog::Accepted)
2680 if (dia.useSettingsGlobal() )
2682 setMapDefXLinkColor (xlo->getColor() );
2683 setMapDefXLinkWidth (xlo->getWidth() );
2685 if (dia.deleteXLink())
2686 bo->deleteXLinkAt(i);
2696 //////////////////////////////////////////////
2698 //////////////////////////////////////////////
2700 void VymModel::parseAtom(const QString &atom)
2702 BranchObj *selb=getSelectedBranch();
2708 // Split string s into command and parameters
2709 parser.parseAtom (atom);
2710 QString com=parser.getCommand();
2712 // External commands
2713 /////////////////////////////////////////////////////////////////////
2714 if (com=="addBranch")
2716 if (selection.isEmpty())
2718 parser.setError (Aborted,"Nothing selected");
2721 parser.setError (Aborted,"Type of selection is not a branch");
2726 if (parser.checkParCount(pl))
2728 if (parser.parCount()==0)
2732 n=parser.parInt (ok,0);
2733 if (ok ) addNewBranch (n);
2737 /////////////////////////////////////////////////////////////////////
2738 } else if (com=="addBranchBefore")
2740 if (selection.isEmpty())
2742 parser.setError (Aborted,"Nothing selected");
2745 parser.setError (Aborted,"Type of selection is not a branch");
2748 if (parser.parCount()==0)
2750 addNewBranchBefore ();
2753 /////////////////////////////////////////////////////////////////////
2754 } else if (com==QString("addMapCenter"))
2756 if (parser.checkParCount(2))
2758 x=parser.parDouble (ok,0);
2761 y=parser.parDouble (ok,1);
2762 if (ok) addMapCenter (QPointF(x,y));
2765 /////////////////////////////////////////////////////////////////////
2766 } else if (com==QString("addMapReplace"))
2768 if (selection.isEmpty())
2770 parser.setError (Aborted,"Nothing selected");
2773 parser.setError (Aborted,"Type of selection is not a branch");
2774 } else if (parser.checkParCount(1))
2776 //s=parser.parString (ok,0); // selection
2777 t=parser.parString (ok,0); // path to map
2778 if (QDir::isRelativePath(t)) t=(tmpMapDir + "/"+t);
2779 addMapReplaceInt(getSelectString(selb),t);
2781 /////////////////////////////////////////////////////////////////////
2782 } else if (com==QString("addMapInsert"))
2784 if (selection.isEmpty())
2786 parser.setError (Aborted,"Nothing selected");
2789 parser.setError (Aborted,"Type of selection is not a branch");
2792 if (parser.checkParCount(2))
2794 t=parser.parString (ok,0); // path to map
2795 n=parser.parInt(ok,1); // position
2796 if (QDir::isRelativePath(t)) t=(tmpMapDir + "/"+t);
2797 addMapInsertInt(t,n);
2800 /////////////////////////////////////////////////////////////////////
2801 } else if (com=="clearFlags")
2803 if (selection.isEmpty() )
2805 parser.setError (Aborted,"Nothing selected");
2808 parser.setError (Aborted,"Type of selection is not a branch");
2809 } else if (parser.checkParCount(0))
2811 selb->clearStandardFlags();
2812 selb->updateFlagsToolbar();
2814 /////////////////////////////////////////////////////////////////////
2815 } else if (com=="colorBranch")
2817 if (selection.isEmpty())
2819 parser.setError (Aborted,"Nothing selected");
2822 parser.setError (Aborted,"Type of selection is not a branch");
2823 } else if (parser.checkParCount(1))
2825 QColor c=parser.parColor (ok,0);
2826 if (ok) colorBranch (c);
2828 /////////////////////////////////////////////////////////////////////
2829 } else if (com=="colorSubtree")
2831 if (selection.isEmpty())
2833 parser.setError (Aborted,"Nothing selected");
2836 parser.setError (Aborted,"Type of selection is not a branch");
2837 } else if (parser.checkParCount(1))
2839 QColor c=parser.parColor (ok,0);
2840 if (ok) colorSubtree (c);
2842 /////////////////////////////////////////////////////////////////////
2843 } else if (com=="copy")
2845 if (selection.isEmpty())
2847 parser.setError (Aborted,"Nothing selected");
2850 parser.setError (Aborted,"Type of selection is not a branch");
2851 } else if (parser.checkParCount(0))
2853 //FIXME missing action for copy
2855 /////////////////////////////////////////////////////////////////////
2856 } else if (com=="cut")
2858 if (selection.isEmpty())
2860 parser.setError (Aborted,"Nothing selected");
2861 } else if ( selectionType()!=TreeItem::Branch &&
2862 selectionType()!=TreeItem::MapCenter &&
2863 selectionType()!=TreeItem::Image )
2865 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
2866 } else if (parser.checkParCount(0))
2870 /////////////////////////////////////////////////////////////////////
2871 } else if (com=="delete")
2873 if (selection.isEmpty())
2875 parser.setError (Aborted,"Nothing selected");
2877 /*else if (selectionType() != TreeItem::Branch && selectionType() != TreeItem::Image )
2879 parser.setError (Aborted,"Type of selection is wrong.");
2882 else if (parser.checkParCount(0))
2886 /////////////////////////////////////////////////////////////////////
2887 } else if (com=="deleteKeepChildren")
2889 if (selection.isEmpty())
2891 parser.setError (Aborted,"Nothing selected");
2894 parser.setError (Aborted,"Type of selection is not a branch");
2895 } else if (parser.checkParCount(0))
2897 deleteKeepChildren();
2899 /////////////////////////////////////////////////////////////////////
2900 } else if (com=="deleteChildren")
2902 if (selection.isEmpty())
2904 parser.setError (Aborted,"Nothing selected");
2907 parser.setError (Aborted,"Type of selection is not a branch");
2908 } else if (parser.checkParCount(0))
2912 /////////////////////////////////////////////////////////////////////
2913 } else if (com=="exportASCII")
2917 if (parser.parCount()>=1)
2918 // Hey, we even have a filename
2919 fname=parser.parString(ok,0);
2922 parser.setError (Aborted,"Could not read filename");
2925 exportASCII (fname,false);
2927 /////////////////////////////////////////////////////////////////////
2928 } else if (com=="exportImage")
2932 if (parser.parCount()>=2)
2933 // Hey, we even have a filename
2934 fname=parser.parString(ok,0);
2937 parser.setError (Aborted,"Could not read filename");
2940 QString format="PNG";
2941 if (parser.parCount()>=2)
2943 format=parser.parString(ok,1);
2945 exportImage (fname,false,format);
2947 /////////////////////////////////////////////////////////////////////
2948 } else if (com=="exportXHTML")
2952 if (parser.parCount()>=2)
2953 // Hey, we even have a filename
2954 fname=parser.parString(ok,1);
2957 parser.setError (Aborted,"Could not read filename");
2960 exportXHTML (fname,false);
2962 /////////////////////////////////////////////////////////////////////
2963 } else if (com=="exportXML")
2967 if (parser.parCount()>=2)
2968 // Hey, we even have a filename
2969 fname=parser.parString(ok,1);
2972 parser.setError (Aborted,"Could not read filename");
2975 exportXML (fname,false);
2977 /////////////////////////////////////////////////////////////////////
2978 } else if (com=="importDir")
2980 if (selection.isEmpty())
2982 parser.setError (Aborted,"Nothing selected");
2985 parser.setError (Aborted,"Type of selection is not a branch");
2986 } else if (parser.checkParCount(1))
2988 s=parser.parString(ok,0);
2989 if (ok) importDirInt(s);
2991 /////////////////////////////////////////////////////////////////////
2992 } else if (com=="linkTo")
2994 if (selection.isEmpty())
2996 parser.setError (Aborted,"Nothing selected");
2999 if (parser.checkParCount(4))
3001 // 0 selectstring of parent
3002 // 1 num in parent (for branches)
3003 // 2,3 x,y of mainbranch or mapcenter
3004 s=parser.parString(ok,0);
3005 LinkableMapObj *dst=findObjBySelect (s);
3008 if (typeid(*dst) == typeid(BranchObj) )
3010 // Get number in parent
3011 n=parser.parInt (ok,1);
3014 selb->linkTo ((BranchObj*)(dst),n);
3017 } else if (typeid(*dst) == typeid(MapCenterObj) )
3019 selb->linkTo ((BranchObj*)(dst),-1);
3020 // Get coordinates of mainbranch
3021 x=parser.parDouble(ok,2);
3024 y=parser.parDouble(ok,3);
3034 } else if ( selectionType() == TreeItem::Image)
3036 if (parser.checkParCount(1))
3038 // 0 selectstring of parent
3039 s=parser.parString(ok,0);
3040 LinkableMapObj *dst=findObjBySelect (s);
3043 if (typeid(*dst) == typeid(BranchObj) ||
3044 typeid(*dst) == typeid(MapCenterObj))
3045 linkFloatImageTo (getSelectString(dst));
3047 parser.setError (Aborted,"Destination is not a branch");
3050 parser.setError (Aborted,"Type of selection is not a floatimage or branch");
3051 /////////////////////////////////////////////////////////////////////
3052 } else if (com=="loadImage")
3054 if (selection.isEmpty())
3056 parser.setError (Aborted,"Nothing selected");
3059 parser.setError (Aborted,"Type of selection is not a branch");
3060 } else if (parser.checkParCount(1))
3062 s=parser.parString(ok,0);
3063 if (ok) loadFloatImageInt (s);
3065 /////////////////////////////////////////////////////////////////////
3066 } else if (com=="moveBranchUp")
3068 if (selection.isEmpty() )
3070 parser.setError (Aborted,"Nothing selected");
3073 parser.setError (Aborted,"Type of selection is not a branch");
3074 } else if (parser.checkParCount(0))
3078 /////////////////////////////////////////////////////////////////////
3079 } else if (com=="moveBranchDown")
3081 if (selection.isEmpty() )
3083 parser.setError (Aborted,"Nothing selected");
3086 parser.setError (Aborted,"Type of selection is not a branch");
3087 } else if (parser.checkParCount(0))
3091 /////////////////////////////////////////////////////////////////////
3092 } else if (com=="move")
3094 if (selection.isEmpty() )
3096 parser.setError (Aborted,"Nothing selected");
3097 } else if ( selectionType()!=TreeItem::Branch &&
3098 selectionType()!=TreeItem::MapCenter &&
3099 selectionType()!=TreeItem::Image )
3101 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
3102 } else if (parser.checkParCount(2))
3104 x=parser.parDouble (ok,0);
3107 y=parser.parDouble (ok,1);
3111 /////////////////////////////////////////////////////////////////////
3112 } else if (com=="moveRel")
3114 if (selection.isEmpty() )
3116 parser.setError (Aborted,"Nothing selected");
3117 } else if ( selectionType()!=TreeItem::Branch &&
3118 selectionType()!=TreeItem::MapCenter &&
3119 selectionType()!=TreeItem::Image )
3121 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
3122 } else if (parser.checkParCount(2))
3124 x=parser.parDouble (ok,0);
3127 y=parser.parDouble (ok,1);
3128 if (ok) moveRel (x,y);
3131 /////////////////////////////////////////////////////////////////////
3132 } else if (com=="nop")
3134 /////////////////////////////////////////////////////////////////////
3135 } else if (com=="paste")
3137 if (selection.isEmpty() )
3139 parser.setError (Aborted,"Nothing selected");
3142 parser.setError (Aborted,"Type of selection is not a branch");
3143 } else if (parser.checkParCount(1))
3145 n=parser.parInt (ok,0);
3146 if (ok) pasteNoSave(n);
3148 /////////////////////////////////////////////////////////////////////
3149 } else if (com=="qa")
3151 if (selection.isEmpty() )
3153 parser.setError (Aborted,"Nothing selected");
3156 parser.setError (Aborted,"Type of selection is not a branch");
3157 } else if (parser.checkParCount(4))
3160 c=parser.parString (ok,0);
3163 parser.setError (Aborted,"No comment given");
3166 s=parser.parString (ok,1);
3169 parser.setError (Aborted,"First parameter is not a string");
3172 t=parser.parString (ok,2);
3175 parser.setError (Aborted,"Condition is not a string");
3178 u=parser.parString (ok,3);
3181 parser.setError (Aborted,"Third parameter is not a string");
3186 parser.setError (Aborted,"Unknown type: "+s);
3191 parser.setError (Aborted,"Unknown operator: "+t);
3196 parser.setError (Aborted,"Type of selection is not a branch");
3199 if (selb->getHeading() == u)
3201 cout << "PASSED: " << qPrintable (c) << endl;
3204 cout << "FAILED: " << qPrintable (c) << endl;
3214 /////////////////////////////////////////////////////////////////////
3215 } else if (com=="saveImage")
3217 FloatImageObj *fio=selection.getFloatImage();
3220 parser.setError (Aborted,"Type of selection is not an image");
3221 } else if (parser.checkParCount(2))
3223 s=parser.parString(ok,0);
3226 t=parser.parString(ok,1);
3227 if (ok) saveFloatImageInt (fio,t,s);
3230 /////////////////////////////////////////////////////////////////////
3231 } else if (com=="scroll")
3233 if (selection.isEmpty() )
3235 parser.setError (Aborted,"Nothing selected");
3238 parser.setError (Aborted,"Type of selection is not a branch");
3239 } else if (parser.checkParCount(0))
3241 if (!scrollBranch (selb))
3242 parser.setError (Aborted,"Could not scroll branch");
3244 /////////////////////////////////////////////////////////////////////
3245 } else if (com=="select")
3247 if (parser.checkParCount(1))
3249 s=parser.parString(ok,0);
3252 /////////////////////////////////////////////////////////////////////
3253 } else if (com=="selectLastBranch")
3255 if (selection.isEmpty() )
3257 parser.setError (Aborted,"Nothing selected");
3260 parser.setError (Aborted,"Type of selection is not a branch");
3261 } else if (parser.checkParCount(0))
3263 BranchObj *bo=selb->getLastBranch();
3265 parser.setError (Aborted,"Could not select last branch");
3269 /////////////////////////////////////////////////////////////////////
3270 } else if (com=="selectLastImage")
3272 if (selection.isEmpty() )
3274 parser.setError (Aborted,"Nothing selected");
3277 parser.setError (Aborted,"Type of selection is not a branch");
3278 } else if (parser.checkParCount(0))
3280 FloatImageObj *fio=selb->getLastFloatImage();
3282 parser.setError (Aborted,"Could not select last image");
3286 /////////////////////////////////////////////////////////////////////
3287 } else if (com=="selectLatestAdded")
3289 if (latestSelectionString.isEmpty() )
3291 parser.setError (Aborted,"No latest added object");
3294 if (!select (latestSelectionString))
3295 parser.setError (Aborted,"Could not select latest added object "+latestSelectionString);
3297 /////////////////////////////////////////////////////////////////////
3298 } else if (com=="setFrameType")
3300 if ( selectionType()!=TreeItem::Branch && selectionType()!= TreeItem::MapCenter && selectionType()!=TreeItem::Image)
3302 parser.setError (Aborted,"Type of selection does not allow setting frame type");
3304 else if (parser.checkParCount(1))
3306 s=parser.parString(ok,0);
3307 if (ok) setFrameType (s);
3309 /////////////////////////////////////////////////////////////////////
3310 } else if (com=="setFramePenColor")
3312 if ( selectionType()!=TreeItem::Branch && selectionType()!= TreeItem::MapCenter && selectionType()!=TreeItem::Image)
3314 parser.setError (Aborted,"Type of selection does not allow setting of pen color");
3316 else if (parser.checkParCount(1))
3318 QColor c=parser.parColor(ok,0);
3319 if (ok) setFramePenColor (c);
3321 /////////////////////////////////////////////////////////////////////
3322 } else if (com=="setFrameBrushColor")
3324 if ( selectionType()!=TreeItem::Branch && selectionType()!= TreeItem::MapCenter && selectionType()!=TreeItem::Image)
3326 parser.setError (Aborted,"Type of selection does not allow setting brush color");
3328 else if (parser.checkParCount(1))
3330 QColor c=parser.parColor(ok,0);
3331 if (ok) setFrameBrushColor (c);
3333 /////////////////////////////////////////////////////////////////////
3334 } else if (com=="setFramePadding")
3336 if ( selectionType()!=TreeItem::Branch && selectionType()!= TreeItem::MapCenter && selectionType()!=TreeItem::Image)
3338 parser.setError (Aborted,"Type of selection does not allow setting frame padding");
3340 else if (parser.checkParCount(1))
3342 n=parser.parInt(ok,0);
3343 if (ok) setFramePadding(n);
3345 /////////////////////////////////////////////////////////////////////
3346 } else if (com=="setFrameBorderWidth")
3348 if ( selectionType()!=TreeItem::Branch && selectionType()!= TreeItem::MapCenter && selectionType()!=TreeItem::Image)
3350 parser.setError (Aborted,"Type of selection does not allow setting frame border width");
3352 else if (parser.checkParCount(1))
3354 n=parser.parInt(ok,0);
3355 if (ok) setFrameBorderWidth (n);
3357 /////////////////////////////////////////////////////////////////////
3358 } else if (com=="setMapAuthor")
3360 if (parser.checkParCount(1))
3362 s=parser.parString(ok,0);
3363 if (ok) setAuthor (s);
3365 /////////////////////////////////////////////////////////////////////
3366 } else if (com=="setMapComment")
3368 if (parser.checkParCount(1))
3370 s=parser.parString(ok,0);
3371 if (ok) setComment(s);
3373 /////////////////////////////////////////////////////////////////////
3374 } else if (com=="setMapBackgroundColor")
3376 if (selection.isEmpty() )
3378 parser.setError (Aborted,"Nothing selected");
3379 } else if (! getSelectedBranch() )
3381 parser.setError (Aborted,"Type of selection is not a branch");
3382 } else if (parser.checkParCount(1))
3384 QColor c=parser.parColor (ok,0);
3385 if (ok) setMapBackgroundColor (c);
3387 /////////////////////////////////////////////////////////////////////
3388 } else if (com=="setMapDefLinkColor")
3390 if (selection.isEmpty() )
3392 parser.setError (Aborted,"Nothing selected");
3395 parser.setError (Aborted,"Type of selection is not a branch");
3396 } else if (parser.checkParCount(1))
3398 QColor c=parser.parColor (ok,0);
3399 if (ok) setMapDefLinkColor (c);
3401 /////////////////////////////////////////////////////////////////////
3402 } else if (com=="setMapLinkStyle")
3404 if (parser.checkParCount(1))
3406 s=parser.parString (ok,0);
3407 if (ok) setMapLinkStyle(s);
3409 /////////////////////////////////////////////////////////////////////
3410 } else if (com=="setHeading")
3412 if (selection.isEmpty() )
3414 parser.setError (Aborted,"Nothing selected");
3417 parser.setError (Aborted,"Type of selection is not a branch");
3418 } else if (parser.checkParCount(1))
3420 s=parser.parString (ok,0);
3424 /////////////////////////////////////////////////////////////////////
3425 } else if (com=="setHideExport")
3427 if (selection.isEmpty() )
3429 parser.setError (Aborted,"Nothing selected");
3430 } else if (selectionType()!=TreeItem::Branch && selectionType() != TreeItem::MapCenter &&selectionType()!=TreeItem::Image)
3432 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
3433 } else if (parser.checkParCount(1))
3435 b=parser.parBool(ok,0);
3436 if (ok) setHideExport (b);
3438 /////////////////////////////////////////////////////////////////////
3439 } else if (com=="setIncludeImagesHorizontally")
3441 if (selection.isEmpty() )
3443 parser.setError (Aborted,"Nothing selected");
3446 parser.setError (Aborted,"Type of selection is not a branch");
3447 } else if (parser.checkParCount(1))
3449 b=parser.parBool(ok,0);
3450 if (ok) setIncludeImagesHor(b);
3452 /////////////////////////////////////////////////////////////////////
3453 } else if (com=="setIncludeImagesVertically")
3455 if (selection.isEmpty() )
3457 parser.setError (Aborted,"Nothing selected");
3460 parser.setError (Aborted,"Type of selection is not a branch");
3461 } else if (parser.checkParCount(1))
3463 b=parser.parBool(ok,0);
3464 if (ok) setIncludeImagesVer(b);
3466 /////////////////////////////////////////////////////////////////////
3467 } else if (com=="setHideLinkUnselected")
3469 if (selection.isEmpty() )
3471 parser.setError (Aborted,"Nothing selected");
3472 } else if ( selectionType()!=TreeItem::Branch && selectionType()!= TreeItem::MapCenter && selectionType()!=TreeItem::Image)
3474 parser.setError (Aborted,"Type of selection does not allow hiding the link");
3475 } else if (parser.checkParCount(1))
3477 b=parser.parBool(ok,0);
3478 if (ok) setHideLinkUnselected(b);
3480 /////////////////////////////////////////////////////////////////////
3481 } else if (com=="setSelectionColor")
3483 if (parser.checkParCount(1))
3485 QColor c=parser.parColor (ok,0);
3486 if (ok) setSelectionColorInt (c);
3488 /////////////////////////////////////////////////////////////////////
3489 } else if (com=="setURL")
3491 if (selection.isEmpty() )
3493 parser.setError (Aborted,"Nothing selected");
3496 parser.setError (Aborted,"Type of selection is not a branch");
3497 } else if (parser.checkParCount(1))
3499 s=parser.parString (ok,0);
3502 /////////////////////////////////////////////////////////////////////
3503 } else if (com=="setVymLink")
3505 if (selection.isEmpty() )
3507 parser.setError (Aborted,"Nothing selected");
3510 parser.setError (Aborted,"Type of selection is not a branch");
3511 } else if (parser.checkParCount(1))
3513 s=parser.parString (ok,0);
3514 if (ok) setVymLink(s);
3517 /////////////////////////////////////////////////////////////////////
3518 else if (com=="setFlag")
3520 if (selection.isEmpty() )
3522 parser.setError (Aborted,"Nothing selected");
3525 parser.setError (Aborted,"Type of selection is not a branch");
3526 } else if (parser.checkParCount(1))
3528 s=parser.parString(ok,0);
3531 selb->activateStandardFlag(s);
3532 selb->updateFlagsToolbar();
3535 /////////////////////////////////////////////////////////////////////
3536 } else if (com=="setFrameType")
3538 if (selection.isEmpty() )
3540 parser.setError (Aborted,"Nothing selected");
3543 parser.setError (Aborted,"Type of selection is not a branch");
3544 } else if (parser.checkParCount(1))
3546 s=parser.parString(ok,0);
3550 /////////////////////////////////////////////////////////////////////
3551 } else if (com=="sortChildren")
3553 if (selection.isEmpty() )
3555 parser.setError (Aborted,"Nothing selected");
3558 parser.setError (Aborted,"Type of selection is not a branch");
3559 } else if (parser.checkParCount(0))
3563 /////////////////////////////////////////////////////////////////////
3564 } else if (com=="toggleFlag")
3566 if (selection.isEmpty() )
3568 parser.setError (Aborted,"Nothing selected");
3571 parser.setError (Aborted,"Type of selection is not a branch");
3572 } else if (parser.checkParCount(1))
3574 s=parser.parString(ok,0);
3577 selb->toggleStandardFlag(s);
3578 selb->updateFlagsToolbar();
3581 /////////////////////////////////////////////////////////////////////
3582 } else if (com=="unscroll")
3584 if (selection.isEmpty() )
3586 parser.setError (Aborted,"Nothing selected");
3589 parser.setError (Aborted,"Type of selection is not a branch");
3590 } else if (parser.checkParCount(0))
3592 if (!unscrollBranch (selb))
3593 parser.setError (Aborted,"Could not unscroll branch");
3595 /////////////////////////////////////////////////////////////////////
3596 } else if (com=="unscrollChildren")
3598 if (selection.isEmpty() )
3600 parser.setError (Aborted,"Nothing selected");
3603 parser.setError (Aborted,"Type of selection is not a branch");
3604 } else if (parser.checkParCount(0))
3606 unscrollChildren ();
3608 /////////////////////////////////////////////////////////////////////
3609 } else if (com=="unsetFlag")
3611 if (selection.isEmpty() )
3613 parser.setError (Aborted,"Nothing selected");
3616 parser.setError (Aborted,"Type of selection is not a branch");
3617 } else if (parser.checkParCount(1))
3619 s=parser.parString(ok,0);
3622 selb->deactivateStandardFlag(s);
3623 selb->updateFlagsToolbar();
3627 parser.setError (Aborted,"Unknown command");
3630 if (parser.errorLevel()==NoError)
3632 // setChanged(); FIXME should not be called e.g. for export?!
3637 // TODO Error handling
3638 qWarning("VymModel::parseAtom: Error!");
3639 qWarning(parser.errorMessage());
3643 void VymModel::runScript (QString script)
3645 parser.setScript (script);
3647 while (parser.next() )
3648 parseAtom(parser.getAtom());
3651 void VymModel::setExportMode (bool b)
3653 // should be called before and after exports
3654 // depending on the settings
3655 if (b && settings.value("/export/useHideExport","true")=="true")
3656 setHideTmpMode (HideExport);
3658 setHideTmpMode (HideNone);
3661 void VymModel::exportImage(QString fname, bool askName, QString format)
3665 fname=getMapName()+".png";
3672 QFileDialog *fd=new QFileDialog (NULL);
3673 fd->setCaption (tr("Export map as image"));
3674 fd->setDirectory (lastImageDir);
3675 fd->setFileMode(QFileDialog::AnyFile);
3676 fd->setFilters (imageIO.getFilters() );
3679 fl=fd->selectedFiles();
3681 format=imageIO.getType(fd->selectedFilter());
3685 setExportMode (true);
3686 QPixmap pix (getPixmap());
3687 pix.save(fname, format);
3688 setExportMode (false);
3692 void VymModel::exportXML(QString dir, bool askForName)
3696 dir=browseDirectory(NULL,tr("Export XML to directory"));
3697 if (dir =="" && !reallyWriteDirectory(dir) )
3701 // Hide stuff during export, if settings want this
3702 setExportMode (true);
3704 // Create subdirectories
3707 // write to directory
3708 QString saveFile=saveToDir (dir,mapName+"-",true,getTotalBBox().topLeft() ,NULL);
3711 file.setName ( dir + "/"+mapName+".xml");
3712 if ( !file.open( QIODevice::WriteOnly ) )
3714 // This should neverever happen
3715 QMessageBox::critical (0,tr("Critical Export Error"),tr("VymModel::exportXML couldn't open %1").arg(file.name()));
3719 // Write it finally, and write in UTF8, no matter what
3720 QTextStream ts( &file );
3721 ts.setEncoding (QTextStream::UnicodeUTF8);
3725 // Now write image, too
3726 exportImage (dir+"/images/"+mapName+".png",false,"PNG");
3728 setExportMode (false);
3731 void VymModel::exportASCII(QString fname,bool askName)
3736 ex.setFile (mapName+".txt");
3742 //ex.addFilter ("TXT (*.txt)");
3743 ex.setDir(lastImageDir);
3744 //ex.setCaption(vymName+ " -" +tr("Export as ASCII")+" "+tr("(still experimental)"));
3749 setExportMode(true);
3751 setExportMode(false);
3755 void VymModel::exportXHTML (const QString &dir, bool askForName)
3757 ExportXHTMLDialog dia(NULL);
3758 dia.setFilePath (filePath );
3759 dia.setMapName (mapName );
3761 if (dir!="") dia.setDir (dir);
3767 if (dia.exec()!=QDialog::Accepted)
3771 QDir d (dia.getDir());
3772 // Check, if warnings should be used before overwriting
3773 // the output directory
3774 if (d.exists() && d.count()>0)
3777 warn.showCancelButton (true);
3778 warn.setText(QString(
3779 "The directory %1 is not empty.\n"
3780 "Do you risk to overwrite some of its contents?").arg(d.path() ));
3781 warn.setCaption("Warning: Directory not empty");
3782 warn.setShowAgainName("mainwindow/overwrite-dir-xhtml");
3784 if (warn.exec()!=QDialog::Accepted) ok=false;
3791 exportXML (dia.getDir(),false );
3792 dia.doExport(mapName );
3793 //if (dia.hasChanged()) setChanged();
3797 void VymModel::exportOOPresentation(const QString &fn, const QString &cf)
3802 if (ex.setConfigFile(cf))
3804 setExportMode (true);
3805 ex.exportPresentation();
3806 setExportMode (false);
3813 //////////////////////////////////////////////
3815 //////////////////////////////////////////////
3817 void VymModel::registerEditor(QWidget *me)
3819 mapEditor=(MapEditor*)me;
3820 for (int i=0; i<mapCenters.count(); i++)
3821 mapCenters.at(i)->setMapEditor(mapEditor);
3824 void VymModel::unregisterEditor(QWidget *)
3829 void VymModel::setContextPos(QPointF p)
3834 void VymModel::unsetContextPos()
3836 contextPos=QPointF();
3839 void VymModel::updateNoteFlag()
3842 BranchObj *bo=getSelectedBranch();
3845 bo->updateNoteFlag();
3846 mainWindow->updateActions();
3850 void VymModel::updateRelPositions()
3852 for (int i=0; i<mapCenters.count(); i++)
3853 mapCenters.at(i)->updateRelPositions();
3856 void VymModel::reposition()
3858 for (int i=0;i<mapCenters.count(); i++)
3859 mapCenters.at(i)->reposition(); // for positioning heading
3862 QPolygonF VymModel::shape(BranchObj *bo)
3864 // Creating (arbitrary) shapes
3867 QRectF rb=bo->getBBox();
3868 if (bo->getDepth()==0)
3870 // Just take BBox of this mapCenter
3871 p<<rb.topLeft()<<rb.topRight()<<rb.bottomRight()<<rb.bottomLeft();
3875 // Take union of BBox and TotalBBox
3877 QRectF ra=bo->getTotalBBox();
3878 if (bo->getOrientation()==LinkableMapObj::LeftOfCenter)
3881 <<QPointF (rb.topLeft().x(), ra.topLeft().y() )
3884 <<QPointF (rb.bottomLeft().x(), ra.bottomLeft().y() ) ;
3886 p <<ra.bottomRight()
3888 <<QPointF (rb.topRight().x(), ra.topRight().y() )
3891 <<QPointF (rb.bottomRight().x(), ra.bottomRight().y() ) ;
3896 void VymModel::moveAway(LinkableMapObj *lmo)
3900 // Move all branches and MapCenters away from lmo
3901 // to avoid collisions
3906 BranchObj *boA=(BranchObj*)lmo;
3908 for (int i=0; i<mapCenters.count(); i++)
3910 boB=mapCenters.at(i);
3913 PolygonCollisionResult r = PolygonCollision(pA, pB, QPoint(0,0));
3916 <<" ("<<qPrintable(boA->getHeading() )<<")"
3917 <<" with ("<< qPrintable (boB->getHeading() )
3920 <<" minT="<<r.minTranslation<<endl<<endl;
3924 QPixmap VymModel::getPixmap()
3926 QRectF mapRect=getTotalBBox();
3927 QPixmap pix((int)mapRect.width()+2,(int)mapRect.height()+1);
3930 pp.setRenderHints(mapEditor->renderHints());
3932 // Don't print the visualisation of selection
3933 selection.unselect();
3935 mapScene->render ( &pp,
3936 QRectF(0,0,mapRect.width()+2,mapRect.height()+2),
3937 QRectF(mapRect.x(),mapRect.y(),mapRect.width(),mapRect.height() ));
3939 // Restore selection
3940 selection.reselect();
3946 void VymModel::setMapLinkStyle (const QString & s)
3951 case LinkableMapObj::Line :
3954 case LinkableMapObj::Parabel:
3955 snow="StyleParabel";
3957 case LinkableMapObj::PolyLine:
3958 snow="StylePolyLine";
3960 case LinkableMapObj::PolyParabel:
3961 snow="StylePolyParabel";
3964 snow="UndefinedStyle";
3969 QString("setMapLinkStyle (\"%1\")").arg(s),
3970 QString("setMapLinkStyle (\"%1\")").arg(snow),
3971 QString("Set map link style (\"%1\")").arg(s)
3975 linkstyle=LinkableMapObj::Line;
3976 else if (s=="StyleParabel")
3977 linkstyle=LinkableMapObj::Parabel;
3978 else if (s=="StylePolyLine")
3979 linkstyle=LinkableMapObj::PolyLine;
3980 else if (s=="StylePolyParabel")
3981 linkstyle=LinkableMapObj::PolyParabel;
3983 linkstyle=LinkableMapObj::UndefinedStyle;
3986 TreeItem *prev=NULL;
3992 bo=(BranchObj*)(cur->getLMO() );
3993 bo->setLinkStyle(bo->getDefLinkStyle());
3994 cur=next(cur,prev,d);
3999 LinkableMapObj::Style VymModel::getMapLinkStyle ()
4004 void VymModel::setMapDefLinkColor(QColor col)
4006 if ( !col.isValid() ) return;
4008 QString("setMapDefLinkColor (\"%1\")").arg(getMapDefLinkColor().name()),
4009 QString("setMapDefLinkColor (\"%1\")").arg(col.name()),
4010 QString("Set map link color to %1").arg(col.name())
4015 TreeItem *prev=NULL;
4018 cur=next(cur,prev,d);
4021 bo=(BranchObj*)(cur->getLMO() );
4028 void VymModel::setMapLinkColorHintInt()
4030 // called from setMapLinkColorHint(lch) or at end of parse
4032 TreeItem *prev=NULL;
4035 cur=next(cur,prev,d);
4038 bo=(BranchObj*)(cur->getLMO() );
4040 cur=next(cur,prev,d);
4044 void VymModel::setMapLinkColorHint(LinkableMapObj::ColorHint lch)
4047 setMapLinkColorHintInt();
4050 void VymModel::toggleMapLinkColorHint()
4052 if (linkcolorhint==LinkableMapObj::HeadingColor)
4053 linkcolorhint=LinkableMapObj::DefaultColor;
4055 linkcolorhint=LinkableMapObj::HeadingColor;
4057 TreeItem *prev=NULL;
4060 cur=next(cur,prev,d);
4063 bo=(BranchObj*)(cur->getLMO() );
4069 void VymModel::selectMapBackgroundImage () // FIXME move to ME
4071 Q3FileDialog *fd=new Q3FileDialog( NULL);
4072 fd->setMode (Q3FileDialog::ExistingFile);
4073 fd->addFilter (QString (tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)"));
4074 ImagePreview *p =new ImagePreview (fd);
4075 fd->setContentsPreviewEnabled( TRUE );
4076 fd->setContentsPreview( p, p );
4077 fd->setPreviewMode( Q3FileDialog::Contents );
4078 fd->setCaption(vymName+" - " +tr("Load background image"));
4079 fd->setDir (lastImageDir);
4082 if ( fd->exec() == QDialog::Accepted )
4084 // TODO selectMapBackgroundImg in QT4 use: lastImageDir=fd->directory();
4085 lastImageDir=QDir (fd->dirPath());
4086 setMapBackgroundImage (fd->selectedFile());
4090 void VymModel::setMapBackgroundImage (const QString &fn) //FIXME missing savestate
4092 QColor oldcol=mapScene->backgroundBrush().color();
4096 QString ("setMapBackgroundImage (%1)").arg(oldcol.name()),
4098 QString ("setMapBackgroundImage (%1)").arg(col.name()),
4099 QString("Set background color of map to %1").arg(col.name()));
4102 brush.setTextureImage (QPixmap (fn));
4103 mapScene->setBackgroundBrush(brush);
4106 void VymModel::selectMapBackgroundColor() // FIXME move to ME
4108 QColor col = QColorDialog::getColor( mapScene->backgroundBrush().color(), NULL);
4109 if ( !col.isValid() ) return;
4110 setMapBackgroundColor( col );
4114 void VymModel::setMapBackgroundColor(QColor col) // FIXME move to ME
4116 QColor oldcol=mapScene->backgroundBrush().color();
4118 QString ("setMapBackgroundColor (\"%1\")").arg(oldcol.name()),
4119 QString ("setMapBackgroundColor (\"%1\")").arg(col.name()),
4120 QString("Set background color of map to %1").arg(col.name()));
4121 mapScene->setBackgroundBrush(col);
4124 QColor VymModel::getMapBackgroundColor() // FIXME move to ME
4126 return mapScene->backgroundBrush().color();
4130 LinkableMapObj::ColorHint VymModel::getMapLinkColorHint() // FIXME move to ME
4132 return linkcolorhint;
4135 QColor VymModel::getMapDefLinkColor() // FIXME move to ME
4137 return defLinkColor;
4140 void VymModel::setMapDefXLinkColor(QColor col) // FIXME move to ME
4145 QColor VymModel::getMapDefXLinkColor() // FIXME move to ME
4147 return defXLinkColor;
4150 void VymModel::setMapDefXLinkWidth (int w) // FIXME move to ME
4155 int VymModel::getMapDefXLinkWidth() // FIXME move to ME
4157 return defXLinkWidth;
4160 void VymModel::move(const double &x, const double &y)
4162 BranchObj *bo = getSelectedBranch();
4164 (selectionType()==TreeItem::Branch ||
4165 selectionType()==TreeItem::MapCenter ||
4166 selectionType()==TreeItem::Image
4169 QPointF ap(bo->getAbsPos());
4173 QString ps=qpointfToString(ap);
4174 QString s=getSelectString();
4177 s, "move "+qpointfToString(to),
4178 QString("Move %1 to %2").arg(getObjectName(bo)).arg(ps));
4186 void VymModel::moveRel (const double &x, const double &y)
4188 BranchObj *bo = getSelectedBranch();
4190 (selectionType()==TreeItem::Branch ||
4191 selectionType()==TreeItem::MapCenter ||
4192 selectionType()==TreeItem::Image
4196 QPointF rp(bo->getRelPos());
4200 QString ps=qpointfToString (bo->getRelPos());
4201 QString s=getSelectString(bo);
4204 s, "moveRel "+qpointfToString(to),
4205 QString("Move %1 to relative position %2").arg(getObjectName(bo)).arg(ps));
4206 ((OrnamentedObj*)bo)->move2RelPos (x,y);
4215 void VymModel::animate()
4217 animationTimer->stop();
4220 while (i<animObjList.size() )
4222 bo=(BranchObj*)animObjList.at(i);
4227 animObjList.removeAt(i);
4234 QItemSelection sel=selModel->selection();
4235 emit (selectionChanged(sel,sel));
4238 if (!animObjList.isEmpty()) animationTimer->start();
4242 void VymModel::startAnimation(BranchObj *bo, const QPointF &start, const QPointF &dest)
4244 if (bo && bo->getDepth()>0)
4247 ap.setStart (start);
4249 ap.setTicks (animationTicks);
4250 ap.setAnimated (true);
4251 bo->setAnimation (ap);
4252 animObjList.append( bo );
4253 animationTimer->setSingleShot (true);
4254 animationTimer->start(animationInterval);
4258 void VymModel::stopAnimation (MapObj *mo)
4260 int i=animObjList.indexOf(mo);
4262 animObjList.removeAt (i);
4265 void VymModel::sendSelection()
4267 if (netstate!=Server) return;
4268 sendData (QString("select (\"%1\")").arg(selection.getSelectString()) );
4271 void VymModel::newServer()
4275 tcpServer = new QTcpServer(this);
4276 if (!tcpServer->listen(QHostAddress::Any,port)) {
4277 QMessageBox::critical(NULL, "vym server",
4278 QString("Unable to start the server: %1.").arg(tcpServer->errorString()));
4279 //FIXME needed? we are no widget any longer... close();
4282 connect(tcpServer, SIGNAL(newConnection()), this, SLOT(newClient()));
4284 cout<<"Server is running on port "<<tcpServer->serverPort()<<endl;
4287 void VymModel::connectToServer()
4290 server="salam.suse.de";
4292 clientSocket = new QTcpSocket (this);
4293 clientSocket->abort();
4294 clientSocket->connectToHost(server ,port);
4295 connect(clientSocket, SIGNAL(readyRead()), this, SLOT(readData()));
4296 connect(clientSocket, SIGNAL(error(QAbstractSocket::SocketError)),
4297 this, SLOT(displayNetworkError(QAbstractSocket::SocketError)));
4299 cout<<"connected to "<<qPrintable (server)<<" port "<<port<<endl;
4304 void VymModel::newClient()
4306 QTcpSocket *newClient = tcpServer->nextPendingConnection();
4307 connect(newClient, SIGNAL(disconnected()),
4308 newClient, SLOT(deleteLater()));
4310 cout <<"ME::newClient at "<<qPrintable( newClient->peerAddress().toString() )<<endl;
4312 clientList.append (newClient);
4316 void VymModel::sendData(const QString &s)
4318 if (clientList.size()==0) return;
4320 // Create bytearray to send
4322 QDataStream out(&block, QIODevice::WriteOnly);
4323 out.setVersion(QDataStream::Qt_4_0);
4325 // Reserve some space for blocksize
4328 // Write sendCounter
4329 out << sendCounter++;
4334 // Go back and write blocksize so far
4335 out.device()->seek(0);
4336 quint16 bs=(quint16)(block.size() - 2*sizeof(quint16));
4340 cout << "ME::sendData bs="<<bs<<" counter="<<sendCounter<<" s="<<qPrintable(s)<<endl;
4342 for (int i=0; i<clientList.size(); ++i)
4344 //cout << "Sending \""<<qPrintable (s)<<"\" to "<<qPrintable (clientList.at(i)->peerAddress().toString())<<endl;
4345 clientList.at(i)->write (block);
4349 void VymModel::readData ()
4351 while (clientSocket->bytesAvailable() >=(int)sizeof(quint16) )
4354 cout <<"readData bytesAvail="<<clientSocket->bytesAvailable();
4358 QDataStream in(clientSocket);
4359 in.setVersion(QDataStream::Qt_4_0);
4367 cout << " t="<<qPrintable (t)<<endl;
4373 void VymModel::displayNetworkError(QAbstractSocket::SocketError socketError)
4375 switch (socketError) {
4376 case QAbstractSocket::RemoteHostClosedError:
4378 case QAbstractSocket::HostNotFoundError:
4379 QMessageBox::information(NULL, vymName +" Network client",
4380 "The host was not found. Please check the "
4381 "host name and port settings.");
4383 case QAbstractSocket::ConnectionRefusedError:
4384 QMessageBox::information(NULL, vymName + " Network client",
4385 "The connection was refused by the peer. "
4386 "Make sure the fortune server is running, "
4387 "and check that the host name and port "
4388 "settings are correct.");
4391 QMessageBox::information(NULL, vymName + " Network client",
4392 QString("The following error occurred: %1.")
4393 .arg(clientSocket->errorString()));
4400 void VymModel::selectMapSelectionColor()
4402 QColor col = QColorDialog::getColor( defLinkColor, NULL);
4403 setSelectionColor (col);
4406 void VymModel::setSelectionColorInt (QColor col)
4408 if ( !col.isValid() ) return;
4410 QString("setSelectionColor (%1)").arg(mapEditor->getSelectionColor().name()),
4411 QString("setSelectionColor (%1)").arg(col.name()),
4412 QString("Set color of selection box to %1").arg(col.name())
4415 mapEditor->setSelectionColor (col);
4418 void VymModel::updateSelection()
4420 QItemSelection newsel=selModel->selection();
4421 updateSelection (newsel);
4424 void VymModel::updateSelection(const QItemSelection &newsel)
4426 emit (selectionChanged(newsel,newsel)); // needed e.g. to update geometry in editor
4427 ensureSelectionVisible();
4431 void VymModel::setSelectionColor(QColor col)
4433 if ( !col.isValid() ) return;
4435 QString("setSelectionColor (%1)").arg(mapEditor->getSelectionColor().name()),
4436 QString("setSelectionColor (%1)").arg(col.name()),
4437 QString("Set color of selection box to %1").arg(col.name())
4439 setSelectionColorInt (col);
4442 QColor VymModel::getSelectionColor()
4444 return mapEditor->getSelectionColor();
4447 void VymModel::setHideTmpMode (HideTmpMode mode)
4450 for (int i=0;i<mapCenters.count(); i++)
4451 mapCenters.at(i)->setHideTmp (mode);
4453 // FIXME needed? scene()->update();
4457 QRectF VymModel::getTotalBBox()
4460 for (int i=0;i<mapCenters.count(); i++)
4461 r=addBBox (mapCenters.at(i)->getTotalBBox(), r);
4465 //////////////////////////////////////////////
4466 // Selection related
4467 //////////////////////////////////////////////
4469 void VymModel::setSelectionModel (QItemSelectionModel *sm)
4472 cout << "VM::setSelModel selModel="<<selModel<<endl;
4475 QItemSelectionModel* VymModel::getSelectionModel()
4480 void VymModel::setSelectionBlocked (bool b)
4485 selection.unblock();
4488 bool VymModel::isSelectionBlocked()
4490 return selection.isBlocked();
4493 bool VymModel::select ()
4495 QModelIndex index=selModel->selectedIndexes().first(); // TODO no multiselections yet
4497 TreeItem *item = getItem (index);
4498 return select (item->getLMO() );
4501 bool VymModel::select (const QString &s)
4503 LinkableMapObj *lmo=findObjBySelect(s);
4505 // Finally select the found object
4515 bool VymModel::select (LinkableMapObj *lmo)
4517 QItemSelection oldsel=selModel->selection();
4520 return select (lmo->getTreeItem() );
4525 bool VymModel::select (TreeItem *ti)
4529 QModelIndex ix=index(ti);
4530 selModel->select (ix,QItemSelectionModel::ClearAndSelect );
4531 ti->setLastSelectedBranch();
4532 //updateSelection(oldsel); //FIXME needed?
4538 void VymModel::unselect()
4540 selModel->clearSelection();
4543 void VymModel::reselect()
4545 selection.reselect();
4548 void VymModel::ensureSelectionVisible()
4550 LinkableMapObj *lmo=getSelectedLMO();
4551 if (lmo &&mapEditor) mapEditor->ensureVisible (lmo->getBBox() );
4555 void VymModel::selectInt (LinkableMapObj *lmo)
4557 if (selection.select(lmo))
4559 //selection.update();
4560 sendSelection (); // FIXME VM use signal
4565 void VymModel::selectNextBranchInt()
4567 // Increase number of branch
4568 LinkableMapObj *sel=getSelectedBranch();
4571 QString s=getSelectString();
4577 part=s.section(",",-1);
4579 num=part.right(part.length() - 3);
4581 s=s.left (s.length() -num.length());
4584 num=QString ("%1").arg(num.toUInt()+1);
4588 // Try to select this one
4589 if (select (s)) return;
4591 // We have no direct successor,
4592 // try to increase the parental number in order to
4593 // find a successor with same depth
4595 int d=getSelectedLMO()->getDepth();
4600 while (!found && d>0)
4602 s=s.section (",",0,d-1);
4603 // replace substring of current depth in s with "1"
4604 part=s.section(",",-1);
4606 num=part.right(part.length() - 3);
4610 // increase number of parent
4611 num=QString ("%1").arg(num.toUInt()+1);
4612 s=s.section (",",0,d-2) + ","+ typ+num;
4615 // Special case, look at orientation
4616 if (getSelectedLMO()->getOrientation()==LinkableMapObj::RightOfCenter)
4617 num=QString ("%1").arg(num.toUInt()+1);
4619 num=QString ("%1").arg(num.toUInt()-1);
4624 // pad to oldDepth, select the first branch for each depth
4625 for (i=d;i<oldDepth;i++)
4630 if ( getSelectedBranch()->countBranches()>0)
4638 // try to select the freshly built string
4646 void VymModel::selectPrevBranchInt()
4648 // Decrease number of branch
4649 if (selectionType()==TreeItem::Branch)
4651 QString s=getSelectString();
4657 part=s.section(",",-1);
4659 num=part.right(part.length() - 3);
4661 s=s.left (s.length() -num.length());
4663 int n=num.toInt()-1;
4666 num=QString ("%1").arg(n);
4669 // Try to select this one
4670 if (n>=0 && select (s)) return;
4672 // We have no direct precessor,
4673 // try to decrease the parental number in order to
4674 // find a precessor with same depth
4676 int d=getSelectedLMO()->getDepth();
4681 while (!found && d>0)
4683 s=s.section (",",0,d-1);
4684 // replace substring of current depth in s with "1"
4685 part=s.section(",",-1);
4687 num=part.right(part.length() - 3);
4691 // decrease number of parent
4692 num=QString ("%1").arg(num.toInt()-1);
4693 s=s.section (",",0,d-2) + ","+ typ+num;
4696 // Special case, look at orientation
4697 if (getSelectedLMO()->getOrientation()==LinkableMapObj::RightOfCenter)
4698 num=QString ("%1").arg(num.toInt()-1);
4700 num=QString ("%1").arg(num.toInt()+1);
4705 // pad to oldDepth, select the last branch for each depth
4706 for (i=d;i<oldDepth;i++)
4710 if ( getSelectedBranch()->countBranches()>0)
4711 s+=",bo:"+ QString ("%1").arg( getSelectedBranch()->countBranches()-1 );
4718 // try to select the freshly built string
4726 void VymModel::selectUpperBranch()
4728 if (selection.isBlocked() ) return;
4730 BranchObj *bo=getSelectedBranch();
4731 if (bo && selectionType()==TreeItem::Branch)
4733 if (bo->getOrientation()==LinkableMapObj::RightOfCenter)
4734 selectPrevBranchInt();
4736 if (bo->getDepth()==1)
4737 selectNextBranchInt();
4739 selectPrevBranchInt();
4743 void VymModel::selectLowerBranch()
4745 if (selection.isBlocked() ) return;
4747 BranchObj *bo=getSelectedBranch();
4748 if (bo && selectionType()==TreeItem::Branch)
4750 if (bo->getOrientation()==LinkableMapObj::RightOfCenter)
4751 selectNextBranchInt();
4753 if (bo->getDepth()==1)
4754 selectPrevBranchInt();
4756 selectNextBranchInt();
4761 void VymModel::selectLeftBranch()
4763 if (selection.isBlocked() ) return;
4765 QItemSelection oldsel=selModel->selection();
4768 LinkableMapObj *sel=getSelectedBranch();
4771 if (selectionType()== TreeItem::MapCenter)
4773 QModelIndex ix=getSelectedIndex();
4774 selModel->select (index (rowCount(ix)-1,0,ix),QItemSelectionModel::ClearAndSelect );
4777 par=(BranchObj*)(sel->getParObj());
4778 if (sel->getOrientation()==LinkableMapObj::RightOfCenter)
4781 if (selectionType() == TreeItem::Branch ||
4782 selectionType() == TreeItem::Image)
4784 QModelIndex ix=getSelectedIndex();
4786 selModel->select (ix,QItemSelectionModel::ClearAndSelect );
4791 if (selectionType() == TreeItem::Branch )
4793 selectLastSelectedBranch();
4798 updateSelection (oldsel);
4802 void VymModel::selectRightBranch()
4804 if (selection.isBlocked() ) return;
4806 QItemSelection oldsel=selModel->selection();
4809 LinkableMapObj *sel=getSelectedBranch();
4812 if (selectionType()== TreeItem::MapCenter)
4814 QModelIndex ix=getSelectedIndex();
4815 selModel->select (index (0,0,ix),QItemSelectionModel::ClearAndSelect );
4818 par=(BranchObj*)(sel->getParObj());
4819 if (sel->getOrientation()==LinkableMapObj::RightOfCenter)
4822 if (selectionType() == TreeItem::Branch )
4824 selectLastSelectedBranch();
4830 if (selectionType() == TreeItem::Branch ||
4831 selectionType() == TreeItem::Image)
4833 QModelIndex ix=getSelectedIndex();
4835 selModel->select (ix,QItemSelectionModel::ClearAndSelect );
4839 updateSelection (oldsel);
4843 void VymModel::selectFirstBranch()
4845 TreeItem *ti=getSelectedBranchItem();
4848 TreeItem *par=ti->parent();
4850 TreeItem *ti2=par->getFirstBranch();
4854 ensureSelectionVisible();
4860 void VymModel::selectLastBranch()
4862 TreeItem *ti=getSelectedBranchItem();
4865 TreeItem *par=ti->parent();
4867 TreeItem *ti2=par->getLastBranch();
4871 ensureSelectionVisible();
4877 void VymModel::selectLastSelectedBranch()
4879 TreeItem *ti=getSelectedBranchItem();
4882 ti=ti->getLastSelectedBranch();
4883 if (ti) select (ti);
4887 void VymModel::selectParent()
4889 TreeItem *ti=getSelectedItem();
4897 ensureSelectionVisible();
4902 TreeItem::Type VymModel::selectionType()
4904 QModelIndexList list=selModel->selectedIndexes();
4905 if (list.isEmpty()) return TreeItem::Undefined;
4906 TreeItem *ti = getItem (list.first() );
4907 return ti->getType();
4911 LinkableMapObj* VymModel::getSelectedLMO()
4913 QModelIndexList list=selModel->selectedIndexes();
4914 if (!list.isEmpty() )
4916 TreeItem *ti = getItem (list.first() );
4917 TreeItem::Type type=ti->getType();
4918 if (type ==TreeItem::Branch || type==TreeItem::MapCenter || type==TreeItem::Image)
4920 return ti->getLMO();
4926 BranchObj* VymModel::getSelectedBranch()
4928 TreeItem *ti = getSelectedBranchItem();
4930 return (BranchObj*)ti->getLMO();
4935 TreeItem* VymModel::getSelectedBranchItem()
4937 QModelIndexList list=selModel->selectedIndexes();
4938 if (!list.isEmpty() )
4940 TreeItem *ti = getItem (list.first() );
4941 TreeItem::Type type=ti->getType();
4942 if (type ==TreeItem::Branch || type==TreeItem::MapCenter)
4948 TreeItem* VymModel::getSelectedItem()
4950 // FIXME this may not only be branch, but also float etc...
4951 BranchObj* bo=getSelectedBranch();
4952 if (bo) return bo->getTreeItem(); // FIXME VM get directly from treemodl
4956 QModelIndex VymModel::getSelectedIndex()
4958 QModelIndexList list=selModel->selectedIndexes();
4959 if (list.isEmpty() )
4960 return QModelIndex();
4962 return list.first();
4965 FloatImageObj* VymModel::getSelectedFloatImage()
4967 return selection.getFloatImage();
4970 QString VymModel::getSelectString ()
4972 LinkableMapObj *lmo=getSelectedLMO();
4974 return getSelectString(lmo);
4979 QString VymModel::getSelectString (LinkableMapObj *lmo) // FIXME VM needs to use TreeModel
4983 if (typeid(*lmo)==typeid(BranchObj) ||
4984 typeid(*lmo)==typeid(MapCenterObj) )
4986 LinkableMapObj *par=lmo->getParObj();
4989 if (lmo->getDepth() ==1)
4990 // Mainbranch, return
4991 s= "bo:" + QString("%1").arg(((BranchObj*)lmo)->getNum());
4993 // Branch, call myself recursively
4994 s= getSelectString(par) + ",bo:" + QString("%1").arg(((BranchObj*)lmo)->getNum());
4998 int i=mapCenters.indexOf ((MapCenterObj*)lmo);
4999 if (i>=0) s=QString("mc:%1").arg(i);