1 #include <QApplication>
6 #include "attributeitem.h"
8 #include "branchitem.h"
9 #include "editxlinkdialog.h"
11 #include "exportxhtmldialog.h"
13 #include "geometry.h" // for addBBox
14 #include "mainwindow.h"
18 #include "warningdialog.h"
19 #include "xlinkitem.h"
20 #include "xml-freemind.h"
26 extern Main *mainWindow;
27 extern QDBusConnection dbusConnection;
29 extern Settings settings;
30 extern QString tmpVymDir;
32 extern TextEditor *textEditor;
33 extern FlagRow *standardFlagsMaster;
35 extern QString clipboardDir;
36 extern QString clipboardFile;
37 extern bool clipboardEmpty;
39 extern ImageIO imageIO;
41 extern QString vymName;
42 extern QString vymVersion;
43 extern QDir vymBaseDir;
45 extern QDir lastImageDir;
46 extern QDir lastFileDir;
48 extern Settings settings;
52 int VymModel::mapNum=0; // make instance
56 // cout << "Const VymModel\n";
58 rootItem->setModel (this);
64 cout << "Destr VymModel\n";
65 autosaveTimer->stop();
66 fileChangedTimer->stop();
70 void VymModel::clear()
72 selModel->clearSelection();
74 //QModelIndex ri=index(rootItem);
75 //removeRows (0, rowCount(ri),ri); // FIXME-3 here should be at least a beginRemoveRows...
78 void VymModel::init ()
80 // We should have at least one map center to start with
81 // addMapCenter(); FIXME-2 VM create this in MapEditor as long as model is part of that
86 // Also no scene yet (should not be needed anyway) FIXME-3 VM
99 stepsTotal=settings.readNumEntry("/history/stepsTotal",100);
100 undoSet.setEntry ("/history/stepsTotal",QString::number(stepsTotal));
101 mainWindow->updateHistory (undoSet);
104 makeTmpDirectories();
109 fileName=tr("unnamed");
111 blockReposition=false;
112 blockSaveState=false;
114 autosaveTimer=new QTimer (this);
115 connect(autosaveTimer, SIGNAL(timeout()), this, SLOT(autosave()));
117 fileChangedTimer=new QTimer (this);
118 fileChangedTimer->start(3000);
119 connect(fileChangedTimer, SIGNAL(timeout()), this, SLOT(fileChanged()));
124 selectionBlocked=false;
131 // animations // FIXME-3 switch to new animation system
132 animationUse=settings.readBoolEntry("/animation/use",false); // FIXME-3 add options to control _what_ is animated
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);
147 hidemode=TreeItem::HideNone;
153 // addMapCenter(); FIXME-2 VM create this in MapEditor until BO and MCO are independent of scene
156 adaptorModel=new AdaptorModel(this); // Created and not deleted as documented in Qt
157 //adaptor->setModel (this);
158 //connection.registerObject("/Car", car);
159 dbusConnection.registerService("org.insilmaril.VymModel");
160 dbusConnection.sessionBus().registerObject ("/Object1",this);
163 void VymModel::makeTmpDirectories()
165 // Create unique temporary directories
166 tmpMapDir = tmpVymDir+QString("/model-%1").arg(mapNum);
167 histPath = tmpMapDir+"/history";
173 MapEditor* VymModel::getMapEditor() // FIXME-3 VM better return favourite editor here
178 bool VymModel::isRepositionBlocked()
180 return blockReposition;
183 void VymModel::updateActions() // FIXME-2 maybe don't update if blockReposition is set
185 //cout << "VM::updateActions \n";
186 // Tell mainwindow to update states of actions
187 mainWindow->updateActions();
192 QString VymModel::saveToDir(const QString &tmpdir, const QString &prefix, bool writeflags, const QPointF &offset, TreeItem *saveSel)
194 // tmpdir temporary directory to which data will be written
195 // prefix mapname, which will be appended to images etc.
196 // writeflags Only write flags for "real" save of map, not undo
197 // offset offset of bbox of whole map in scene.
198 // Needed for XML export
207 case LinkableMapObj::Line:
210 case LinkableMapObj::Parabel:
213 case LinkableMapObj::PolyLine:
217 ls="StylePolyParabel";
221 QString s="<?xml version=\"1.0\" encoding=\"utf-8\"?><!DOCTYPE vymmap>\n";
223 if (linkcolorhint==LinkableMapObj::HeadingColor)
224 colhint=xml.attribut("linkColorHint","HeadingColor");
226 QString mapAttr=xml.attribut("version",vymVersion);
228 mapAttr+= xml.attribut("author",author) +
229 xml.attribut("comment",comment) +
230 xml.attribut("date",getDate()) +
231 xml.attribut("branchCount", QString().number(branchCount())) +
232 xml.attribut("backgroundColor", mapScene->backgroundBrush().color().name() ) +
233 xml.attribut("selectionColor", mapEditor->getSelectionColor().name() ) +
234 xml.attribut("linkStyle", ls ) +
235 xml.attribut("linkColor", defLinkColor.name() ) +
236 xml.attribut("defXLinkColor", defXLinkColor.name() ) +
237 xml.attribut("defXLinkWidth", QString().setNum(defXLinkWidth,10) ) +
239 s+=xml.beginElement("vymmap",mapAttr);
242 // Find the used flags while traversing the tree // FIXME-3 this can be done local to vymmodel maybe...
243 standardFlagsMaster->resetUsedCounter();
245 // Build xml recursivly
247 // Save all mapcenters as complete map, if saveSel not set
248 s+=saveTreeToDir(tmpdir,prefix,writeflags,offset);
251 switch (saveSel->getType())
253 case TreeItem::Branch:
255 s+=((BranchItem*)saveSel)->saveToDir(tmpdir,prefix,offset);
257 case TreeItem::MapCenter:
259 s+=((BranchItem*)saveSel)->saveToDir(tmpdir,prefix,offset);
261 case TreeItem::Image:
263 s+=((ImageItem*)saveSel)->saveToDir(tmpdir,prefix);
266 // other types shouldn't be safed directly...
271 // Save local settings
272 s+=settings.getDataXML (destPath);
275 if (getSelectedItem() && !saveSel )
276 s+=xml.valueElement("select",getSelectString());
279 s+=xml.endElement("vymmap");
281 //cout << s.toStdString() << endl;
283 if (writeflags) standardFlagsMaster->saveToDir (tmpdir+"/flags/","",writeflags);
287 QString VymModel::saveTreeToDir (const QString &tmpdir,const QString &prefix, int verbose, const QPointF &offset) // FIXME-4 verbose not needed (used to write icons)
291 for (int i=0; i<rootItem->branchCount(); i++)
292 s+=rootItem->getBranchNum(i)->saveToDir (tmpdir,prefix,offset);
296 void VymModel::setFilePath(QString fpath, QString destname)
298 if (fpath.isEmpty() || fpath=="")
305 filePath=fpath; // becomes absolute path
306 fileName=fpath; // gets stripped of path
307 destPath=destname; // needed for vymlinks and during load to reset fileChangedTime
309 // If fpath is not an absolute path, complete it
310 filePath=QDir(fpath).absPath();
311 fileDir=filePath.left (1+filePath.findRev ("/"));
313 // Set short name, too. Search from behind:
314 int i=fileName.findRev("/");
315 if (i>=0) fileName=fileName.remove (0,i+1);
317 // Forget the .vym (or .xml) for name of map
318 mapName=fileName.left(fileName.findRev(".",-1,true) );
322 void VymModel::setFilePath(QString fpath)
324 setFilePath (fpath,fpath);
327 QString VymModel::getFilePath()
332 QString VymModel::getFileName()
337 QString VymModel::getMapName()
342 QString VymModel::getDestPath()
347 ErrorCode VymModel::load (QString fname, const LoadMode &lmode, const FileType &ftype)
349 ErrorCode err=success;
351 parseBaseHandler *handler;
355 case VymMap: handler=new parseVYMHandler; break;
356 case FreemindMap : handler=new parseFreemindHandler; break;
358 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
359 "Unknown FileType in VymModel::load()");
363 bool zipped_org=zipped;
367 selModel->clearSelection();
368 // FIXME-2 VM not needed??? model->setMapEditor(this);
369 // (map state is set later at end of load...)
372 BranchItem *bi=getSelectedBranch();
373 if (!bi) return aborted;
374 if (lmode==ImportAdd)
375 saveStateChangingPart(
378 QString("addMapInsert (%1)").arg(fname),
379 QString("Add map %1 to %2").arg(fname).arg(getObjectName(bi)));
381 saveStateChangingPart(
384 QString("addMapReplace(%1)").arg(fname),
385 QString("Add map %1 to %2").arg(fname).arg(getObjectName(bi)));
389 // Create temporary directory for packing
391 QString tmpZipDir=makeTmpDir (ok,"vym-pack");
394 QMessageBox::critical( 0, tr( "Critical Load Error" ),
395 tr("Couldn't create temporary directory before load\n"));
400 err=unzipDir (tmpZipDir,fname);
410 // Look for mapname.xml
411 xmlfile= fname.left(fname.findRev(".",-1,true));
412 xmlfile=xmlfile.section( '/', -1 );
413 QFile mfile( tmpZipDir + "/" + xmlfile + ".xml");
414 if (!mfile.exists() )
416 // mapname.xml does not exist, well,
417 // maybe someone renamed the mapname.vym file...
418 // Try to find any .xml in the toplevel
419 // directory of the .vym file
420 QStringList flist=QDir (tmpZipDir).entryList("*.xml");
421 if (flist.count()==1)
423 // Only one entry, take this one
424 xmlfile=tmpZipDir + "/"+flist.first();
427 for ( QStringList::Iterator it = flist.begin(); it != flist.end(); ++it )
428 *it=tmpZipDir + "/" + *it;
429 // TODO Multiple entries, load all (but only the first one into this ME)
430 //mainWindow->fileLoadFromTmp (flist);
431 //returnCode=1; // Silently forget this attempt to load
432 qWarning ("MainWindow::load (fn) multimap found...");
435 if (flist.isEmpty() )
437 QMessageBox::critical( 0, tr( "Critical Load Error" ),
438 tr("Couldn't find a map (*.xml) in .vym archive.\n"));
441 } //file doesn't exist
443 xmlfile=mfile.name();
446 QFile file( xmlfile);
448 // I am paranoid: file should exist anyway
449 // according to check in mainwindow.
452 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
453 tr(QString("Couldn't open map %1").arg(file.name())));
457 bool blockSaveStateOrg=blockSaveState;
458 blockReposition=true;
460 mapEditor->setViewportUpdateMode (QGraphicsView::NoViewportUpdate);
461 QXmlInputSource source( file);
462 QXmlSimpleReader reader;
463 reader.setContentHandler( handler );
464 reader.setErrorHandler( handler );
465 handler->setModel ( this);
468 // We need to set the tmpDir in order to load files with rel. path
473 tmpdir=fname.left(fname.findRev("/",-1));
474 handler->setTmpDir (tmpdir);
475 handler->setInputFile (file.name());
476 handler->setLoadMode (lmode);
477 bool ok = reader.parse( source );
478 blockReposition=false;
479 blockSaveState=blockSaveStateOrg;
480 mapEditor->setViewportUpdateMode (QGraphicsView::MinimalViewportUpdate);
484 reposition(); // FIXME-2 VM reposition the view instead...
485 emitSelectionChanged();
491 autosaveTimer->stop();
494 // Reset timestamp to check for later updates of file
495 fileChangedTime=QFileInfo (destPath).lastModified();
498 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
499 tr( handler->errorProtocol() ) );
501 // Still return "success": the map maybe at least
502 // partially read by the parser
507 removeDir (QDir(tmpZipDir));
509 // Restore original zip state
516 ErrorCode VymModel::save (const SaveMode &savemode)
520 QString safeFilePath;
522 ErrorCode err=success;
526 mapFileName=mapName+".xml";
528 // use name given by user, even if he chooses .doc
529 mapFileName=fileName;
531 // Look, if we should zip the data:
534 QMessageBox mb( vymName,
535 tr("The map %1\ndid not use the compressed "
536 "vym file format.\nWriting it uncompressed will also write images \n"
537 "and flags and thus may overwrite files in the "
538 "given directory\n\nDo you want to write the map").arg(filePath),
539 QMessageBox::Warning,
540 QMessageBox::Yes | QMessageBox::Default,
542 QMessageBox::Cancel | QMessageBox::Escape);
543 mb.setButtonText( QMessageBox::Yes, tr("compressed (vym default)") );
544 mb.setButtonText( QMessageBox::No, tr("uncompressed") );
545 mb.setButtonText( QMessageBox::Cancel, tr("Cancel"));
548 case QMessageBox::Yes:
549 // save compressed (default file format)
552 case QMessageBox::No:
556 case QMessageBox::Cancel:
563 // First backup existing file, we
564 // don't want to add to old zip archives
568 if ( settings.value ("/mapeditor/writeBackupFile").toBool())
570 QString backupFileName(destPath + "~");
571 QFile backupFile(backupFileName);
572 if (backupFile.exists() && !backupFile.remove())
574 QMessageBox::warning(0, tr("Save Error"),
575 tr("%1\ncould not be removed before saving").arg(backupFileName));
577 else if (!f.rename(backupFileName))
579 QMessageBox::warning(0, tr("Save Error"),
580 tr("%1\ncould not be renamed before saving").arg(destPath));
587 // Create temporary directory for packing
589 tmpZipDir=makeTmpDir (ok,"vym-zip");
592 QMessageBox::critical( 0, tr( "Critical Load Error" ),
593 tr("Couldn't create temporary directory before save\n"));
597 safeFilePath=filePath;
598 setFilePath (tmpZipDir+"/"+ mapName+ ".xml", safeFilePath);
601 // Create mapName and fileDir
602 makeSubDirs (fileDir);
605 if (savemode==CompleteMap || selModel->selection().isEmpty())
608 saveFile=saveToDir (fileDir,mapName+"-",true,QPointF(),NULL);
611 autosaveTimer->stop();
616 if (selectionType()==TreeItem::Image)
619 saveFile=saveToDir (fileDir,mapName+"-",true,QPointF(),getSelectedBranch());
620 // TODO take care of multiselections
623 if (!saveStringToDisk(fileDir+mapFileName,saveFile))
626 qWarning ("ME::saveStringToDisk failed!");
632 if (err==success) err=zipDir (tmpZipDir,destPath);
635 removeDir (QDir(tmpZipDir));
637 // Restore original filepath outside of tmp zip dir
638 setFilePath (safeFilePath);
642 fileChangedTime=QFileInfo (destPath).lastModified();
646 void VymModel::addMapReplaceInt(const QString &undoSel, const QString &path) // FIXME-1 test e.g. with undo color subtree
648 QString pathDir=path.left(path.findRev("/"));
654 // We need to parse saved XML data
655 parseVYMHandler handler;
656 QXmlInputSource source( file);
657 QXmlSimpleReader reader;
658 reader.setContentHandler( &handler );
659 reader.setErrorHandler( &handler );
660 handler.setModel ( this);
661 handler.setTmpDir ( pathDir ); // needed to load files with rel. path
662 if (undoSel.isEmpty())
666 handler.setLoadMode (NewMap);
670 handler.setLoadMode (ImportReplace);
672 blockReposition=true;
673 bool ok = reader.parse( source );
674 blockReposition=false;
677 // This should never ever happen
678 QMessageBox::critical( 0, tr( "Critical Parse Error while reading %1").arg(path),
679 handler.errorProtocol());
682 QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
685 bool VymModel::addMapInsertInt (const QString &path)
687 QString pathDir=path.left(path.findRev("/"));
693 // We need to parse saved XML data
694 parseVYMHandler handler;
695 QXmlInputSource source( file);
696 QXmlSimpleReader reader;
697 reader.setContentHandler( &handler );
698 reader.setErrorHandler( &handler );
699 handler.setModel (this);
700 handler.setTmpDir ( pathDir ); // needed to load files with rel. path
701 handler.setLoadMode (ImportAdd);
702 blockReposition=true;
703 bool ok = reader.parse( source );
704 blockReposition=false;
705 if ( ok ) return true;
707 // This should never ever happen
708 QMessageBox::critical( 0, tr( "Critical Parse Error while reading %1").arg(path),
709 handler.errorProtocol());
712 QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
716 bool VymModel::addMapInsertInt (const QString &path, int pos)
718 BranchItem *selbi=getSelectedBranch();
721 if (addMapInsertInt (path))
723 if (selbi->depth()>0)
724 relinkBranch (selbi->getLastBranch(), selbi,pos);
728 QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
732 qWarning ("ME::addMapInsertInt nothing selected");
736 ImageItem* VymModel::loadFloatImageInt (BranchItem *dst,QString fn)
738 ImageItem *ii=createImage(dst);
748 void VymModel::loadFloatImage ()
750 BranchItem *selbi=getSelectedBranch();
754 Q3FileDialog *fd=new Q3FileDialog( NULL); // FIXME-4 get rid of Q3FileDialog
755 fd->setMode (Q3FileDialog::ExistingFiles);
756 fd->addFilter (QString (tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)"));
757 ImagePreview *p =new ImagePreview (fd);
758 fd->setContentsPreviewEnabled( TRUE );
759 fd->setContentsPreview( p, p );
760 fd->setPreviewMode( Q3FileDialog::Contents );
761 fd->setCaption(vymName+" - " +tr("Load image"));
762 fd->setDir (lastImageDir);
765 if ( fd->exec() == QDialog::Accepted )
767 // TODO loadFIO in QT4 use: lastImageDir=fd->directory();
768 lastImageDir=QDir (fd->dirPath());
771 for (int j=0; j<fd->selectedFiles().count(); j++)
773 s=fd->selectedFiles().at(j);
774 ii=loadFloatImageInt (selbi,s);
775 //FIXME-3 check savestate for loadImage
781 QString ("loadImage (%1)").arg(s ),
782 QString("Add image %1 to %2").arg(s).arg(getObjectName(selbi))
785 // TODO loadFIO error handling
786 qWarning ("Failed to load "+s);
794 void VymModel::saveFloatImageInt (ImageItem *ii, const QString &type, const QString &fn)
799 void VymModel::saveFloatImage ()
801 ImageItem *ii=getSelectedImage();
804 QFileDialog *fd=new QFileDialog( NULL);
805 fd->setFilters (imageIO.getFilters());
806 fd->setCaption(vymName+" - " +tr("Save image"));
807 fd->setFileMode( QFileDialog::AnyFile );
808 fd->setDirectory (lastImageDir);
809 // fd->setSelection (fio->getOriginalFilename());
813 if ( fd->exec() == QDialog::Accepted && fd->selectedFiles().count()==1)
815 fn=fd->selectedFiles().at(0);
816 if (QFile (fn).exists() )
818 QMessageBox mb( vymName,
819 tr("The file %1 exists already.\n"
820 "Do you want to overwrite it?").arg(fn),
821 QMessageBox::Warning,
822 QMessageBox::Yes | QMessageBox::Default,
823 QMessageBox::Cancel | QMessageBox::Escape,
824 QMessageBox::NoButton );
826 mb.setButtonText( QMessageBox::Yes, tr("Overwrite") );
827 mb.setButtonText( QMessageBox::No, tr("Cancel"));
830 case QMessageBox::Yes:
833 case QMessageBox::Cancel:
840 saveFloatImageInt (ii,fd->selectedFilter(),fn );
847 void VymModel::importDirInt(BranchObj *dst, QDir d)
849 /* FIXME-2 importDirInt not ported yet
850 BranchObj *bo=getSelectedBranch();
853 // Traverse directories
854 d.setFilter( QDir::Dirs| QDir::Hidden | QDir::NoSymLinks );
855 QFileInfoList list = d.entryInfoList();
858 for (int i = 0; i < list.size(); ++i)
861 if (fi.fileName() != "." && fi.fileName() != ".." )
864 bo=dst->getLastBranch();
865 BranchItem *bi=(BranchItem*)(bo->getTreeItem());
866 bi->setHeading (fi.fileName() ); // FIXME-3 check this
867 bo->setColor (QColor("blue"));
869 if ( !d.cd(fi.fileName()) )
870 QMessageBox::critical (0,tr("Critical Import Error"),tr("Cannot find the directory %1").arg(fi.fileName()));
873 // Recursively add subdirs
880 d.setFilter( QDir::Files| QDir::Hidden | QDir::NoSymLinks );
881 list = d.entryInfoList();
883 for (int i = 0; i < list.size(); ++i)
887 bo=dst->getLastBranch();
888 bo->setHeading (fi.fileName() );
889 bo->setColor (QColor("black"));
890 if (fi.fileName().right(4) == ".vym" )
891 bo->setVymLink (fi.filePath());
897 void VymModel::importDirInt (const QString &s) // FIXME-2
900 BranchObj *bo=getSelectedBranch();
903 saveStateChangingPart (bo,bo,QString ("importDir (\"%1\")").arg(s),QString("Import directory structure from %1").arg(s));
911 void VymModel::importDir() //FIXME-2
914 BranchObj *bo=getSelectedBranch();
918 filters <<"VYM map (*.vym)";
919 QFileDialog *fd=new QFileDialog( NULL,vymName+ " - " +tr("Choose directory structure to import"));
920 fd->setMode (QFileDialog::DirectoryOnly);
921 fd->setFilters (filters);
922 fd->setCaption(vymName+" - " +tr("Choose directory structure to import"));
926 if ( fd->exec() == QDialog::Accepted )
928 importDirInt (fd->selectedFile() );
930 //FIXME-3 VM needed? scene()->update();
937 void VymModel::autosave()
942 cout << "VymModel::autosave rejected due to missing filePath\n";
945 QDateTime now=QDateTime().currentDateTime();
947 // Disable autosave, while we have gone back in history
948 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
949 if (redosAvail>0) return;
951 // Also disable autosave for new map without filename
952 if (filePath.isEmpty()) return;
955 if (mapUnsaved &&mapChanged && settings.value ("/mainwindow/autosave/use",true).toBool() )
957 if (QFileInfo(filePath).lastModified()<=fileChangedTime)
958 mainWindow->fileSave (this);
961 cout <<" ME::autosave rejected, file on disk is newer than last save.\n";
966 void VymModel::fileChanged()
968 // Check if file on disk has changed meanwhile
969 if (!filePath.isEmpty())
971 QDateTime tmod=QFileInfo (filePath).lastModified();
972 if (tmod>fileChangedTime)
974 // FIXME-2 VM switch to current mapeditor and finish lineedits...
975 QMessageBox mb( vymName,
976 tr("The file of the map on disk has changed:\n\n"
977 " %1\n\nDo you want to reload that map with the new file?").arg(filePath),
978 QMessageBox::Question,
980 QMessageBox::Cancel | QMessageBox::Default,
981 QMessageBox::NoButton );
983 mb.setButtonText( QMessageBox::Yes, tr("Reload"));
984 mb.setButtonText( QMessageBox::No, tr("Ignore"));
987 case QMessageBox::Yes:
989 load (filePath,NewMap,fileType);
990 case QMessageBox::Cancel:
991 fileChangedTime=tmod; // allow autosave to overwrite newer file!
997 bool VymModel::isDefault()
1002 void VymModel::makeDefault()
1008 bool VymModel::hasChanged()
1013 void VymModel::setChanged()
1016 autosaveTimer->start(settings.value("/mainwindow/autosave/ms/",300000).toInt());
1020 latestAddedItem=NULL;
1024 QString VymModel::getObjectName (LinkableMapObj *lmo) // FIXME-3 should be obsolete
1026 if (!lmo || !lmo->getTreeItem() ) return QString();
1027 return getObjectName (lmo->getTreeItem() );
1031 QString VymModel::getObjectName (TreeItem *ti)
1034 if (!ti) return QString("Error: NULL has no name!");
1036 if (s=="") s="unnamed";
1038 return QString ("%1 (%2)").arg(ti->getTypeName()).arg(s);
1041 void VymModel::redo()
1043 // Can we undo at all?
1044 if (redosAvail<1) return;
1046 bool blockSaveStateOrg=blockSaveState;
1047 blockSaveState=true;
1051 if (undosAvail<stepsTotal) undosAvail++;
1053 if (curStep>stepsTotal) curStep=1;
1054 QString undoCommand= undoSet.readEntry (QString("/history/step-%1/undoCommand").arg(curStep));
1055 QString undoSelection=undoSet.readEntry (QString("/history/step-%1/undoSelection").arg(curStep));
1056 QString redoCommand= undoSet.readEntry (QString("/history/step-%1/redoCommand").arg(curStep));
1057 QString redoSelection=undoSet.readEntry (QString("/history/step-%1/redoSelection").arg(curStep));
1058 QString comment=undoSet.readEntry (QString("/history/step-%1/comment").arg(curStep));
1059 QString version=undoSet.readEntry ("/history/version");
1061 /* TODO Maybe check for version, if we save the history
1062 if (!checkVersion(version))
1063 QMessageBox::warning(0,tr("Warning"),
1064 tr("Version %1 of saved undo/redo data\ndoes not match current vym version %2.").arg(version).arg(vymVersion));
1067 // Find out current undo directory
1068 QString bakMapDir(QString(tmpMapDir+"/undo-%1").arg(curStep));
1072 cout << "VymModel::redo() begin\n";
1073 cout << " undosAvail="<<undosAvail<<endl;
1074 cout << " redosAvail="<<redosAvail<<endl;
1075 cout << " curStep="<<curStep<<endl;
1076 cout << " ---------------------------"<<endl;
1077 cout << " comment="<<comment.toStdString()<<endl;
1078 cout << " undoCom="<<undoCommand.toStdString()<<endl;
1079 cout << " undoSel="<<undoSelection.toStdString()<<endl;
1080 cout << " redoCom="<<redoCommand.toStdString()<<endl;
1081 cout << " redoSel="<<redoSelection.toStdString()<<endl;
1082 cout << " ---------------------------"<<endl<<endl;
1085 // select object before redo
1086 if (!redoSelection.isEmpty())
1087 select (redoSelection);
1090 parseAtom (redoCommand);
1093 blockSaveState=blockSaveStateOrg;
1095 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
1096 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
1097 undoSet.setEntry ("/history/curStep",QString::number(curStep));
1098 undoSet.writeSettings(histPath);
1100 mainWindow->updateHistory (undoSet);
1103 /* TODO remove testing
1104 cout << "ME::redo() end\n";
1105 cout << " undosAvail="<<undosAvail<<endl;
1106 cout << " redosAvail="<<redosAvail<<endl;
1107 cout << " curStep="<<curStep<<endl;
1108 cout << " ---------------------------"<<endl<<endl;
1114 bool VymModel::isRedoAvailable()
1116 if (undoSet.readNumEntry("/history/redosAvail",0)>0)
1122 void VymModel::undo()
1124 // Can we undo at all?
1125 if (undosAvail<1) return;
1127 mainWindow->statusMessage (tr("Autosave disabled during undo."));
1129 bool blockSaveStateOrg=blockSaveState;
1130 blockSaveState=true;
1132 QString undoCommand= undoSet.readEntry (QString("/history/step-%1/undoCommand").arg(curStep));
1133 QString undoSelection=undoSet.readEntry (QString("/history/step-%1/undoSelection").arg(curStep));
1134 QString redoCommand= undoSet.readEntry (QString("/history/step-%1/redoCommand").arg(curStep));
1135 QString redoSelection=undoSet.readEntry (QString("/history/step-%1/redoSelection").arg(curStep));
1136 QString comment=undoSet.readEntry (QString("/history/step-%1/comment").arg(curStep));
1137 QString version=undoSet.readEntry ("/history/version");
1139 /* TODO Maybe check for version, if we save the history
1140 if (!checkVersion(version))
1141 QMessageBox::warning(0,tr("Warning"),
1142 tr("Version %1 of saved undo/redo data\ndoes not match current vym version %2.").arg(version).arg(vymVersion));
1145 // Find out current undo directory
1146 QString bakMapDir(QString(tmpMapDir+"/undo-%1").arg(curStep));
1148 // select object before undo
1149 select (undoSelection);
1153 cout << "VymModel::undo() begin\n";
1154 cout << " undosAvail="<<undosAvail<<endl;
1155 cout << " redosAvail="<<redosAvail<<endl;
1156 cout << " curStep="<<curStep<<endl;
1157 cout << " ---------------------------"<<endl;
1158 cout << " comment="<<comment.toStdString()<<endl;
1159 cout << " undoCom="<<undoCommand.toStdString()<<endl;
1160 cout << " undoSel="<<undoSelection.toStdString()<<endl;
1161 cout << " redoCom="<<redoCommand.toStdString()<<endl;
1162 cout << " redoSel="<<redoSelection.toStdString()<<endl;
1163 cout << " ---------------------------"<<endl<<endl;
1165 parseAtom (undoCommand);
1170 if (curStep<1) curStep=stepsTotal;
1174 blockSaveState=blockSaveStateOrg;
1176 cout << "VymModel::undo() end\n";
1177 cout << " undosAvail="<<undosAvail<<endl;
1178 cout << " redosAvail="<<redosAvail<<endl;
1179 cout << " curStep="<<curStep<<endl;
1180 cout << " ---------------------------"<<endl<<endl;
1183 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
1184 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
1185 undoSet.setEntry ("/history/curStep",QString::number(curStep));
1186 undoSet.writeSettings(histPath);
1188 mainWindow->updateHistory (undoSet);
1190 emitSelectionChanged();
1193 bool VymModel::isUndoAvailable()
1195 if (undoSet.readNumEntry("/history/undosAvail",0)>0)
1201 void VymModel::gotoHistoryStep (int i)
1203 // Restore variables
1204 int undosAvail=undoSet.readNumEntry (QString("/history/undosAvail"));
1205 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
1207 if (i<0) i=undosAvail+redosAvail;
1209 // Clicking above current step makes us undo things
1212 for (int j=0; j<undosAvail-i; j++) undo();
1215 // Clicking below current step makes us redo things
1217 for (int j=undosAvail; j<i; j++)
1219 if (debug) cout << "VymModel::gotoHistoryStep redo "<<j<<"/"<<undosAvail<<" i="<<i<<endl;
1223 // And ignore clicking the current row ;-)
1227 QString VymModel::getHistoryPath()
1229 QString histName(QString("history-%1").arg(curStep));
1230 return (tmpMapDir+"/"+histName);
1233 void VymModel::saveState(const SaveMode &savemode, const QString &undoSelection, const QString &undoCom, const QString &redoSelection, const QString &redoCom, const QString &comment, TreeItem *saveSel)
1235 sendData(redoCom); //FIXME-3 testing
1240 if (blockSaveState) return;
1242 if (debug) cout << "VM::saveState() for "<<qPrintable (mapName)<<endl;
1244 // Find out current undo directory
1245 if (undosAvail<stepsTotal) undosAvail++;
1247 if (curStep>stepsTotal) curStep=1;
1249 QString backupXML="";
1250 QString histDir=getHistoryPath();
1251 QString bakMapPath=histDir+"/map.xml";
1253 // Create histDir if not available
1256 makeSubDirs (histDir);
1258 // Save depending on how much needs to be saved
1260 backupXML=saveToDir (histDir,mapName+"-",false, QPointF (),saveSel);
1262 QString undoCommand="";
1263 if (savemode==UndoCommand)
1265 undoCommand=undoCom;
1267 else if (savemode==PartOfMap )
1269 undoCommand=undoCom;
1270 undoCommand.replace ("PATH",bakMapPath);
1274 if (!backupXML.isEmpty())
1275 // Write XML Data to disk
1276 saveStringToDisk (bakMapPath,backupXML);
1278 // We would have to save all actions in a tree, to keep track of
1279 // possible redos after a action. Possible, but we are too lazy: forget about redos.
1282 // Write the current state to disk
1283 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
1284 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
1285 undoSet.setEntry ("/history/curStep",QString::number(curStep));
1286 undoSet.setEntry (QString("/history/step-%1/undoCommand").arg(curStep),undoCommand);
1287 undoSet.setEntry (QString("/history/step-%1/undoSelection").arg(curStep),undoSelection);
1288 undoSet.setEntry (QString("/history/step-%1/redoCommand").arg(curStep),redoCom);
1289 undoSet.setEntry (QString("/history/step-%1/redoSelection").arg(curStep),redoSelection);
1290 undoSet.setEntry (QString("/history/step-%1/comment").arg(curStep),comment);
1291 undoSet.setEntry (QString("/history/version"),vymVersion);
1292 undoSet.writeSettings(histPath);
1296 // TODO remove after testing
1297 //cout << " into="<< histPath.toStdString()<<endl;
1298 cout << " stepsTotal="<<stepsTotal<<
1299 ", undosAvail="<<undosAvail<<
1300 ", redosAvail="<<redosAvail<<
1301 ", curStep="<<curStep<<endl;
1302 cout << " ---------------------------"<<endl;
1303 cout << " comment="<<comment.toStdString()<<endl;
1304 cout << " undoCom="<<undoCommand.toStdString()<<endl;
1305 cout << " undoSel="<<undoSelection.toStdString()<<endl;
1306 cout << " redoCom="<<redoCom.toStdString()<<endl;
1307 cout << " redoSel="<<redoSelection.toStdString()<<endl;
1308 if (saveSel) cout << " saveSel="<<qPrintable (getSelectString(saveSel))<<endl;
1309 cout << " ---------------------------"<<endl;
1312 mainWindow->updateHistory (undoSet);
1318 void VymModel::saveStateChangingPart(TreeItem *undoSel, TreeItem* redoSel, const QString &rc, const QString &comment)
1320 // save the selected part of the map, Undo will replace part of map
1321 QString undoSelection="";
1323 undoSelection=getSelectString(undoSel);
1325 qWarning ("VymModel::saveStateChangingPart no undoSel given!");
1326 QString redoSelection="";
1328 redoSelection=getSelectString(undoSel);
1330 qWarning ("VymModel::saveStateChangingPart no redoSel given!");
1333 saveState (PartOfMap,
1334 undoSelection, "addMapReplace (\"PATH\")",
1340 void VymModel::saveStateRemovingPart(TreeItem* redoSel, const QString &comment)
1344 qWarning ("VymModel::saveStateRemovingPart no redoSel given!");
1347 QString undoSelection;
1348 QString redoSelection=getSelectString(redoSel);
1349 if (redoSel->getType()==TreeItem::Branch)
1351 undoSelection=getSelectString (redoSel->parent());
1352 // save the selected branch of the map, Undo will insert part of map
1353 saveState (PartOfMap,
1354 undoSelection, QString("addMapInsert (\"PATH\",%1)").arg(redoSel->num()),
1355 redoSelection, "delete ()",
1359 if (redoSel->getType()==TreeItem::MapCenter)
1361 // save the selected branch of the map, Undo will insert part of map
1362 saveState (PartOfMap,
1363 undoSelection, QString("addMapInsert (\"PATH\")"),
1364 redoSelection, "delete ()",
1371 void VymModel::saveState(TreeItem *undoSel, const QString &uc, TreeItem *redoSel, const QString &rc, const QString &comment)
1373 // "Normal" savestate: save commands, selections and comment
1374 // so just save commands for undo and redo
1375 // and use current selection
1377 QString redoSelection="";
1378 if (redoSel) redoSelection=getSelectString(redoSel);
1379 QString undoSelection="";
1380 if (undoSel) undoSelection=getSelectString(undoSel);
1382 saveState (UndoCommand,
1389 void VymModel::saveState(const QString &undoSel, const QString &uc, const QString &redoSel, const QString &rc, const QString &comment)
1391 // "Normal" savestate: save commands, selections and comment
1392 // so just save commands for undo and redo
1393 // and use current selection
1394 saveState (UndoCommand,
1401 void VymModel::saveState(const QString &uc, const QString &rc, const QString &comment)
1403 // "Normal" savestate applied to model (no selection needed):
1404 // save commands and comment
1405 saveState (UndoCommand,
1413 QGraphicsScene* VymModel::getScene ()
1418 TreeItem* VymModel::findBySelectString(QString s)
1420 if (s.isEmpty() ) return NULL;
1422 // Old maps don't have multiple mapcenters and don't save full path
1423 if (s.left(2) !="mc")
1426 QStringList parts=s.split (",");
1429 TreeItem *ti=rootItem;
1431 while (!parts.isEmpty() )
1433 typ=parts.first().left(2);
1434 n=parts.first().right(parts.first().length() - 3).toInt();
1435 parts.removeFirst();
1436 if (typ=="mc" || typ=="bo")
1437 ti=ti->getBranchNum (n);
1441 ti=ti->getImageNum (n);
1447 TreeItem* VymModel::findID (const QString &s)
1449 BranchItem *cur=NULL;
1450 BranchItem *prev=NULL;
1454 if (s==cur->getID() ) return cur;
1460 //////////////////////////////////////////////
1462 //////////////////////////////////////////////
1463 void VymModel::setVersion (const QString &s)
1468 void VymModel::setAuthor (const QString &s)
1471 QString ("setMapAuthor (\"%1\")").arg(author),
1472 QString ("setMapAuthor (\"%1\")").arg(s),
1473 QString ("Set author of map to \"%1\"").arg(s)
1478 QString VymModel::getAuthor()
1483 void VymModel::setComment (const QString &s)
1486 QString ("setMapComment (\"%1\")").arg(comment),
1487 QString ("setMapComment (\"%1\")").arg(s),
1488 QString ("Set comment of map")
1493 QString VymModel::getComment ()
1498 QString VymModel::getDate ()
1500 return QDate::currentDate().toString ("yyyy-MM-dd");
1503 int VymModel::branchCount() // FIXME-4 Optimize this: use internal counter instead of going through whole map each time...
1506 BranchItem *cur=NULL;
1507 BranchItem *prev=NULL;
1517 void VymModel::setHeading(const QString &s)
1519 BranchItem *selbi=getSelectedBranch();
1524 "setHeading (\""+selbi->getHeading()+"\")",
1526 "setHeading (\""+s+"\")",
1527 QString("Set heading of %1 to \"%2\"").arg(getObjectName(selbi)).arg(s) );
1528 selbi->setHeading(s );
1529 emitDataHasChanged ( selbi); //FIXME-3 maybe emit signal from TreeItem?
1531 emitSelectionChanged();
1535 QString VymModel::getHeading()
1537 TreeItem *selti=getSelectedItem();
1539 return selti->getHeading();
1544 BranchItem* VymModel::findText (QString s, bool cs)
1546 QTextDocument::FindFlags flags=0;
1547 if (cs) flags=QTextDocument::FindCaseSensitively;
1550 { // Nothing found or new find process
1552 // nothing found, start again
1556 next (findCurrent,findPrevious);
1558 bool searching=true;
1559 bool foundNote=false;
1560 while (searching && !EOFind)
1564 // Searching in Note
1565 if (findCurrent->getNote().contains(s,cs))
1567 select (findCurrent);
1569 if (getSelectedBranch()!=itFind)
1572 emitShowSelection();
1575 if (textEditor->findText(s,flags))
1581 // Searching in Heading
1582 if (searching && findCurrent->getHeading().contains (s,cs) )
1584 select(findCurrent);
1590 if (!next(findCurrent,findPrevious) )
1593 //cout <<"still searching... "<<qPrintable( itFind->getHeading())<<endl;
1596 return getSelectedBranch();
1601 void VymModel::findReset()
1602 { // Necessary if text to find changes during a find process
1608 void VymModel::setScene (QGraphicsScene *s)
1610 mapScene=s; // FIXME-2 VM should not be necessary anymore, move all occurences to MapEditor
1611 //init(); // Here we have a mapScene set,
1612 // which is (still) needed to create MapCenters
1615 void VymModel::setURL(const QString &url)
1617 TreeItem *selti=getSelectedItem();
1620 QString oldurl=selti->getURL();
1621 selti->setURL (url);
1624 QString ("setURL (\"%1\")").arg(oldurl),
1626 QString ("setURL (\"%1\")").arg(url),
1627 QString ("set URL of %1 to %2").arg(getObjectName(selti)).arg(url)
1630 emitDataHasChanged (selti);
1631 emitShowSelection();
1635 QString VymModel::getURL()
1637 TreeItem *selti=getSelectedItem();
1639 return selti->getURL();
1644 QStringList VymModel::getURLs()
1647 BranchItem *selbi=getSelectedBranch();
1648 BranchItem *cur=selbi;
1649 BranchItem *prev=NULL;
1652 if (!cur->getURL().isEmpty()) urls.append( cur->getURL());
1653 cur=next (cur,prev,selbi);
1659 void VymModel::setFrameType(const FrameObj::FrameType &t) //FIXME-4 not saved if there is no LMO
1661 BranchItem *bi=getSelectedBranch();
1664 BranchObj *bo=(BranchObj*)(bi->getLMO());
1667 QString s=bo->getFrameTypeName();
1668 bo->setFrameType (t);
1669 saveState (bi, QString("setFrameType (\"%1\")").arg(s),
1670 bi, QString ("setFrameType (\"%1\")").arg(bo->getFrameTypeName()),QString ("set type of frame to %1").arg(s));
1672 bo->updateLinkGeometry();
1677 void VymModel::setFrameType(const QString &s) //FIXME-4 not saved if there is no LMO
1679 BranchItem *bi=getSelectedBranch();
1682 BranchObj *bo=(BranchObj*)(bi->getLMO());
1685 saveState (bi, QString("setFrameType (\"%1\")").arg(bo->getFrameTypeName()),
1686 bi, QString ("setFrameType (\"%1\")").arg(s),QString ("set type of frame to %1").arg(s));
1687 bo->setFrameType (s);
1689 bo->updateLinkGeometry();
1694 void VymModel::setFramePenColor(const QColor &c) //FIXME-4 not saved if there is no LMO
1697 BranchItem *bi=getSelectedBranch();
1700 BranchObj *bo=(BranchObj*)(bi->getLMO());
1703 saveState (bi, QString("setFramePenColor (\"%1\")").arg(bo->getFramePenColor().name() ),
1704 bi, QString ("setFramePenColor (\"%1\")").arg(c.name() ),QString ("set pen color of frame to %1").arg(c.name() ));
1705 bo->setFramePenColor (c);
1710 void VymModel::setFrameBrushColor(const QColor &c) //FIXME-4 not saved if there is no LMO
1712 BranchItem *bi=getSelectedBranch();
1715 BranchObj *bo=(BranchObj*)(bi->getLMO());
1718 saveState (bi, QString("setFrameBrushColor (\"%1\")").arg(bo->getFrameBrushColor().name() ),
1719 bi, QString ("setFrameBrushColor (\"%1\")").arg(c.name() ),QString ("set brush color of frame to %1").arg(c.name() ));
1720 bo->setFrameBrushColor (c);
1725 void VymModel::setFramePadding (const int &i) //FIXME-4 not saved if there is no LMO
1727 BranchItem *bi=getSelectedBranch();
1730 BranchObj *bo=(BranchObj*)(bi->getLMO());
1733 saveState (bi, QString("setFramePadding (\"%1\")").arg(bo->getFramePadding() ),
1734 bi, QString ("setFramePadding (\"%1\")").arg(i),QString ("set brush color of frame to %1").arg(i));
1735 bo->setFramePadding (i);
1737 bo->updateLinkGeometry();
1742 void VymModel::setFrameBorderWidth(const int &i) //FIXME-4 not saved if there is no LMO
1744 BranchItem *bi=getSelectedBranch();
1747 BranchObj *bo=(BranchObj*)(bi->getLMO());
1750 saveState (bi, QString("setFrameBorderWidth (\"%1\")").arg(bo->getFrameBorderWidth() ),
1751 bi, QString ("setFrameBorderWidth (\"%1\")").arg(i),QString ("set border width of frame to %1").arg(i));
1752 bo->setFrameBorderWidth (i);
1754 bo->updateLinkGeometry();
1759 void VymModel::setIncludeImagesVer(bool b)
1761 BranchItem *bi=getSelectedBranch();
1764 QString u= b ? "false" : "true";
1765 QString r=!b ? "false" : "true";
1769 QString("setIncludeImagesVertically (%1)").arg(u),
1771 QString("setIncludeImagesVertically (%1)").arg(r),
1772 QString("Include images vertically in %1").arg(getObjectName(bi))
1774 bi->setIncludeImagesVer(b);
1775 emitDataHasChanged ( bi);
1780 void VymModel::setIncludeImagesHor(bool b)
1782 BranchItem *bi=getSelectedBranch();
1785 QString u= b ? "false" : "true";
1786 QString r=!b ? "false" : "true";
1790 QString("setIncludeImagesHorizontally (%1)").arg(u),
1792 QString("setIncludeImagesHorizontally (%1)").arg(r),
1793 QString("Include images horizontally in %1").arg(getObjectName(bi))
1795 bi->setIncludeImagesHor(b);
1796 emitDataHasChanged ( bi);
1801 void VymModel::setHideLinkUnselected (bool b)//FIXME-2
1803 TreeItem *ti=getSelectedItem();
1804 if (ti && (ti->getType()==TreeItem::Image ||ti->isBranchLikeType()))
1806 QString u= b ? "false" : "true";
1807 QString r=!b ? "false" : "true";
1811 QString("setHideLinkUnselected (%1)").arg(u),
1813 QString("setHideLinkUnselected (%1)").arg(r),
1814 QString("Hide link of %1 if unselected").arg(getObjectName(ti))
1816 ((MapItem*)ti)->setHideLinkUnselected(b);
1820 void VymModel::setHideExport(bool b)
1822 TreeItem *ti=getSelectedItem();
1824 (ti->getType()==TreeItem::Image ||ti->isBranchLikeType()))
1826 ti->setHideInExport (b);
1827 QString u= b ? "false" : "true";
1828 QString r=!b ? "false" : "true";
1832 QString ("setHideExport (%1)").arg(u),
1834 QString ("setHideExport (%1)").arg(r),
1835 QString ("Set HideExport flag of %1 to %2").arg(getObjectName(ti)).arg (r)
1837 emitDataHasChanged(ti);
1838 emitSelectionChanged();
1841 // emitSelectionChanged();
1842 // FIXME-3 VM needed? scene()->update();
1846 void VymModel::toggleHideExport()
1848 TreeItem *selti=getSelectedItem();
1850 setHideExport ( !selti->hideInExport() );
1854 void VymModel::copy()
1856 TreeItem *selti=getSelectedItem();
1858 (selti->getType() == TreeItem::Branch ||
1859 selti->getType() == TreeItem::MapCenter ||
1860 selti->getType() == TreeItem::Image ))
1862 if (redosAvail == 0)
1865 QString s=getSelectString(selti);
1866 saveState (PartOfMap, s, "nop ()", s, "copy ()","Copy selection to clipboard",selti );
1867 curClipboard=curStep;
1870 // Copy also to global clipboard, because we are at last step in history
1871 QString bakMapName(QString("history-%1").arg(curStep));
1872 QString bakMapDir(tmpMapDir +"/"+bakMapName);
1873 copyDir (bakMapDir,clipboardDir );
1875 clipboardEmpty=false;
1881 void VymModel::pasteNoSave(const int &n)
1883 bool old=blockSaveState;
1884 blockSaveState=true;
1885 bool zippedOrg=zipped;
1886 if (redosAvail > 0 || n!=0)
1888 // Use the "historical" buffer
1889 QString bakMapName(QString("history-%1").arg(n));
1890 QString bakMapDir(tmpMapDir +"/"+bakMapName);
1891 load (bakMapDir+"/"+clipboardFile,ImportAdd, VymMap);
1893 // Use the global buffer
1894 load (clipboardDir+"/"+clipboardFile,ImportAdd, VymMap);
1899 void VymModel::paste()
1901 BranchItem *selbi=getSelectedBranch();
1904 saveStateChangingPart(
1907 QString ("paste (%1)").arg(curClipboard),
1908 QString("Paste to %1").arg( getObjectName(selbi))
1915 void VymModel::cut()
1917 TreeItem *selti=getSelectedItem();
1918 if ( selti && (selti->isBranchLikeType() ||selti->getType()==TreeItem::Image))
1926 void VymModel::moveUp()
1928 BranchItem *selbi=getSelectedBranch();
1931 if (!selbi->canMoveUp()) return;
1932 QString oldsel=getSelectString();
1933 if (relinkBranch (selbi,(BranchItem*)selbi->parent(),selbi->num()-1) )
1935 saveState (getSelectString(),"moveDown ()",oldsel,"moveUp ()",QString("Move up %1").arg(getObjectName(selbi)));
1939 void VymModel::moveDown()
1941 BranchItem *selbi=getSelectedBranch();
1944 if (!selbi->canMoveDown()) return;
1945 QString oldsel=getSelectString();
1946 if ( relinkBranch (selbi,(BranchItem*)selbi->parent(),selbi->num()+1) )
1948 saveState (getSelectString(),"moveUp ()",oldsel,"moveDown ()",QString("Move down %1").arg(getObjectName(selbi)));
1952 void VymModel::sortChildren() // FIXME-2 not implemented yet
1955 BranchObj* bo=getSelectedBranch();
1958 if(treeItem->branchCount()>1)
1960 saveStateChangingPart(bo,bo, "sortChildren ()",QString("Sort children of %1").arg(getObjectName(bo)));
1963 emitShowSelection();
1969 BranchItem* VymModel::createMapCenter()
1971 BranchItem *newbi=addMapCenter (QPointF (0,0) );
1975 BranchItem* VymModel::createBranch(BranchItem *dst)
1978 return addNewBranchInt (dst,-2);
1983 ImageItem* VymModel::createImage(BranchItem *dst)
1990 QList<QVariant> cData;
1991 cData << "new" << "undef";
1993 ImageItem *newii=new ImageItem(cData) ;
1994 //newii->setHeading (QApplication::translate("Heading of new image in map", "new image"));
1996 emit (layoutAboutToBeChanged() );
1999 n=dst->getRowNumAppend(newii);
2000 beginInsertRows (parix,n,n+1);
2001 dst->appendChild (newii);
2004 emit (layoutChanged() );
2006 // save scroll state. If scrolled, automatically select
2007 // new branch in order to tmp unscroll parent...
2008 newii->createMapObj(mapScene);
2015 XLinkItem* VymModel::createXLink(BranchItem *bi,bool createMO)
2022 QList<QVariant> cData;
2023 cData << "new xLink"<<"undef";
2025 XLinkItem *newxli=new XLinkItem(cData) ;
2027 emit (layoutAboutToBeChanged() );
2030 n=bi->getRowNumAppend(newxli);
2031 beginInsertRows (parix,n,n+1);
2032 bi->appendChild (newxli);
2035 emit (layoutChanged() );
2037 // save scroll state. If scrolled, automatically select
2038 // new branch in order to tmp unscroll parent...
2039 newxli->setBegin (bi);
2042 newxli->createMapObj(mapScene);
2050 AttributeItem* VymModel::addAttribute() // FIXME-2 savestate missing
2052 BranchItem *selbi=getSelectedBranch();
2055 QList<QVariant> cData;
2056 cData << "new attribute" << "undef";
2057 AttributeItem *a=new AttributeItem (cData);
2059 emit (layoutAboutToBeChanged() );
2061 QModelIndex parix=index(selbi);
2062 int n=selbi->getRowNumAppend (a);
2063 beginInsertRows (parix,n,n+1);
2064 selbi->appendChild (a);
2067 emit (layoutChanged() );
2075 BranchItem* VymModel::addMapCenter ()
2077 BranchItem *bi=addMapCenter (contextPos);
2079 emitShowSelection();
2084 QString ("addMapCenter (%1,%2)").arg (contextPos.x()).arg(contextPos.y()),
2085 QString ("Adding MapCenter to (%1,%2)").arg (contextPos.x()).arg(contextPos.y())
2090 BranchItem* VymModel::addMapCenter(QPointF absPos) //FIXME-2 absPos not used in context menu?!
2091 // createMapCenter could then probably be merged with createBranch
2095 QModelIndex parix=index(rootItem);
2097 int n=rootItem->branchCount();
2099 emit (layoutAboutToBeChanged() );
2100 beginInsertRows (parix,n,n+1);
2102 QList<QVariant> cData;
2103 cData << "VM:addMapCenter" << "undef";
2104 BranchItem *newbi=new BranchItem (cData,rootItem);
2105 newbi->setHeading (QApplication::translate("Heading of mapcenter in new map", "New map"));
2106 rootItem->appendChild (newbi);
2109 emit (layoutChanged() );
2112 newbi->setPositionMode (MapItem::Absolute);
2113 newbi->createMapObj(mapScene);
2118 BranchItem* VymModel::addNewBranchInt(BranchItem *dst,int num)
2120 // Depending on pos:
2121 // -3 insert in children of parent above selection
2122 // -2 add branch to selection
2123 // -1 insert in children of parent below selection
2124 // 0..n insert in children of parent at pos
2127 QList<QVariant> cData;
2128 cData << "new" << "undef";
2133 BranchItem *newbi=new BranchItem (cData);
2134 newbi->setHeading (QApplication::translate("Heading of new branch in map", "new"));
2136 emit (layoutAboutToBeChanged() );
2142 n=parbi->getRowNumAppend (newbi);
2143 beginInsertRows (parix,n,n+1);
2144 parbi->appendChild (newbi);
2146 }else if (num==-1 || num==-3)
2148 // insert below selection
2149 parbi=(BranchItem*)dst->parent();
2152 n=dst->childNumber() + (3+num)/2; //-1 |-> 1;-3 |-> 0
2153 beginInsertRows (parix,n,n);
2154 parbi->insertBranch(n,newbi);
2157 emit (layoutChanged() );
2159 // save scroll state. If scrolled, automatically select
2160 // new branch in order to tmp unscroll parent...
2161 newbi->createMapObj(mapScene);
2166 BranchItem* VymModel::addNewBranch(int pos)
2168 // Different meaning than num in addNewBranchInt!
2172 BranchItem *newbi=NULL;
2173 BranchItem *selbi=getSelectedBranch();
2177 // FIXME-3 setCursor (Qt::ArrowCursor); //Still needed?
2179 newbi=addNewBranchInt (selbi,pos-2);
2187 QString ("addBranch (%1)").arg(pos),
2188 QString ("Add new branch to %1").arg(getObjectName(selbi)));
2191 // emitSelectionChanged(); FIXME-3
2192 latestAddedItem=newbi;
2193 // In Network mode, the client needs to know where the new branch is,
2194 // so we have to pass on this information via saveState.
2195 // TODO: Get rid of this positioning workaround
2196 /* FIXME-4 network problem: QString ps=qpointfToString (newbo->getAbsPos());
2197 sendData ("selectLatestAdded ()");
2198 sendData (QString("move %1").arg(ps));
2207 BranchItem* VymModel::addNewBranchBefore()
2209 BranchItem *newbi=NULL;
2210 BranchItem *selbi=getSelectedBranch();
2211 if (selbi && selbi->getType()==TreeItem::Branch)
2212 // We accept no MapCenter here, so we _have_ a parent
2214 //QPointF p=bo->getRelPos();
2217 // add below selection
2218 newbi=addNewBranchInt (selbi,-1);
2222 //newbi->move2RelPos (p);
2224 // Move selection to new branch
2225 relinkBranch (selbi,newbi,0);
2227 saveState (newbi, "deleteKeepChildren ()", newbi, "addBranchBefore ()",
2228 QString ("Add branch before %1").arg(getObjectName(selbi)));
2230 // FIXME-3 needed? reposition();
2231 // emitSelectionChanged(); FIXME-3
2237 bool VymModel::relinkBranch (BranchItem *branch, BranchItem *dst, int pos)
2241 if (branch->depth()==0)
2243 cout <<"VM::relinkBranch d=0 for "<<branch->getHeadingStd()<<endl;
2245 emit (layoutAboutToBeChanged() );
2246 BranchItem *branchpi=(BranchItem*)branch->parent();
2247 // Remove at current position
2248 int n=branch->childNum();
2249 beginRemoveRows (index(branchpi),n,n);
2250 branchpi->removeChild (n);
2253 if (pos<0 ||pos>dst->branchCount() ) pos=dst->branchCount();
2255 // Append as last branch to dst
2256 if (dst->branchCount()==0)
2259 n=dst->getFirstBranch()->childNumber();
2260 beginInsertRows (index(dst),n+pos,n+pos);
2261 dst->insertBranch (pos,branch);
2264 // Correct type if necessesary
2265 if (branch->getType()==TreeItem::MapCenter)
2266 branch->setType(TreeItem::Branch);
2268 // reset parObj, fonts, frame, etc in related LMO or other view-objects
2269 branch->updateStyles();
2271 emit (layoutChanged() );
2272 reposition(); // both for moveUp/Down and relinking
2273 if (dst->isScrolled() )
2276 branch->updateVisibility();
2285 bool VymModel::relinkImage (ImageItem *image, BranchItem *dst)
2289 emit (layoutAboutToBeChanged() );
2291 BranchItem *pi=(BranchItem*)(image->parent());
2292 QString oldParString=getSelectString (pi);
2293 // Remove at current position
2294 int n=image->childNum();
2295 beginRemoveRows (index(pi),n,n);
2296 pi->removeChild (n);
2300 QModelIndex dstix=index(dst);
2301 n=dst->getRowNumAppend (image);
2302 beginInsertRows (dstix,n,n+1);
2303 dst->appendChild (image);
2306 // Set new parent also for lmo
2307 if (image->getLMO() && dst->getLMO() )
2308 image->getLMO()->setParObj (dst->getLMO() );
2310 emit (layoutChanged() );
2313 QString("relinkTo (\"%1\")").arg(oldParString),
2315 QString ("relinkTo (\"%1\")").arg(getSelectString (dst)),
2316 QString ("Relink floatimage to %1").arg(getObjectName(dst)));
2322 void VymModel::deleteSelection()
2324 BranchItem *selbi=getSelectedBranch();
2329 saveStateRemovingPart (selbi, QString ("Delete %1").arg(getObjectName(selbi)));
2331 TreeItem *pi=deleteItem (selbi);
2335 emitShowSelection();
2339 TreeItem *ti=getSelectedItem();
2342 TreeItem *pi=ti->parent();
2344 if (ti->getType()==TreeItem::Image || ti->getType()==TreeItem::Attribute)
2346 saveStateChangingPart(
2350 QString("Delete %1").arg(getObjectName(ti))
2353 // FIXME-0 savestate missing for deletion of other times
2356 emitDataHasChanged (pi);
2359 emitShowSelection();
2364 void VymModel::deleteKeepChildren() //FIXME-3 does not work yet for mapcenters
2367 BranchItem *selbi=getSelectedBranch();
2371 // Don't use this on mapcenter
2372 if (selbi->depth()<2) return;
2374 pi=(BranchItem*)(selbi->parent());
2375 // Check if we have childs at all to keep
2376 if (selbi->branchCount()==0)
2383 if (selbi->getLMO()) p=selbi->getLMO()->getRelPos();
2384 saveStateChangingPart(
2387 "deleteKeepChildren ()",
2388 QString("Remove %1 and keep its children").arg(getObjectName(selbi))
2391 QString sel=getSelectString(selbi);
2393 int pos=selbi->num();
2394 BranchItem *bi=selbi->getFirstBranch();
2397 relinkBranch (bi,pi,pos);
2398 bi=selbi->getFirstBranch();
2404 BranchObj *bo=getSelectedBranchObj();
2407 bo->move2RelPos (p);
2413 void VymModel::deleteChildren()
2416 BranchItem *selbi=getSelectedBranch();
2419 saveStateChangingPart(
2422 "deleteChildren ()",
2423 QString( "Remove children of branch %1").arg(getObjectName(selbi))
2425 emit (layoutAboutToBeChanged() );
2427 QModelIndex ix=index (selbi);
2428 int n=selbi->branchCount()-1;
2429 beginRemoveRows (ix,0,n);
2430 removeRows (0,n+1,ix);
2432 if (selbi->isScrolled()) selbi->unScroll();
2433 emit (layoutChanged() );
2438 TreeItem* VymModel::deleteItem (TreeItem *ti)
2440 cout << "VM::deleteItem "<<ti<<endl;
2443 TreeItem *pi=ti->parent();
2444 QModelIndex parentIndex=index(pi);
2446 emit (layoutAboutToBeChanged() );
2448 int n=ti->childNum();
2449 beginRemoveRows (parentIndex,n,n);
2450 removeRows (n,1,parentIndex);
2454 emit (layoutChanged() );
2455 if (pi->depth()>=0) return pi;
2460 bool VymModel::scrollBranch(BranchItem *bi)
2464 if (bi->isScrolled()) return false;
2465 if (bi->branchCount()==0) return false;
2466 if (bi->depth()==0) return false;
2467 if (bi->toggleScroll())
2474 QString ("%1 ()").arg(u),
2476 QString ("%1 ()").arg(r),
2477 QString ("%1 %2").arg(r).arg(getObjectName(bi))
2479 emitDataHasChanged(bi);
2480 emitSelectionChanged();
2481 mapScene->update(); //Needed for _quick_ update, even in 1.13.x //FIXME-3 force update via signal...
2488 bool VymModel::unscrollBranch(BranchItem *bi)
2492 if (!bi->isScrolled()) return false;
2493 if (bi->branchCount()==0) return false;
2494 if (bi->depth()==0) return false;
2501 QString ("%1 ()").arg(u),
2503 QString ("%1 ()").arg(r),
2504 QString ("%1 %2").arg(r).arg(getObjectName(bi))
2507 emitDataHasChanged(bi);
2508 emitSelectionChanged();
2510 mapScene->update(); //Needed for _quick_ update, even in 1.13.x //FIXME-3 force update via signal...
2516 void VymModel::toggleScroll()
2518 BranchItem *bi=(BranchItem*)getSelectedBranch();
2519 if (bi && bi->isBranchLikeType() )
2521 if (bi->isScrolled())
2522 unscrollBranch (bi);
2526 // saveState is called in above functions
2529 void VymModel::unscrollChildren() // FIXME-2 first, next moved to vymmodel
2533 BranchObj *bo=getSelectedBranch();
2539 if (bo->isScrolled()) unscrollBranch (bo);
2546 void VymModel::emitExpandAll()
2548 emit (expandAll() );
2551 void VymModel::toggleStandardFlag (const QString &name, FlagRow *master)
2553 BranchItem *bi=getSelectedBranch();
2557 if (bi->isActiveStandardFlag(name))
2569 QString("%1 (\"%2\")").arg(u).arg(name),
2571 QString("%1 (\"%2\")").arg(r).arg(name),
2572 QString("Toggling standard flag \"%1\" of %2").arg(name).arg(getObjectName(bi)));
2573 bi->toggleStandardFlag (name, master);
2575 emitSelectionChanged();
2579 void VymModel::addFloatImage (const QPixmap &img) //FIXME-2 drag & drop
2582 BranchObj *bo=getSelectedBranch();
2585 FloatImageObj *fio=bo->addFloatImage();
2587 fio->setOriginalFilename("No original filename (image added by dropevent)");
2588 QString s=getSelectString(bo);
2589 saveState (PartOfMap, s, "nop ()", s, "copy ()","Copy dropped image to clipboard",fio );
2590 saveState (fio,"delete ()", bo,QString("paste(%1)").arg(curStep),"Pasting dropped image");
2592 // FIXME-3 VM needed? scene()->update();
2598 void VymModel::colorBranch (QColor c)
2600 BranchItem *selbi=getSelectedBranch();
2605 QString ("colorBranch (\"%1\")").arg(selbi->getHeadingColor().name()),
2607 QString ("colorBranch (\"%1\")").arg(c.name()),
2608 QString("Set color of %1 to %2").arg(getObjectName(selbi)).arg(c.name())
2610 selbi->setHeadingColor(c); // color branch
2614 void VymModel::colorSubtree (QColor c)
2616 BranchItem *selbi=getSelectedBranch();
2619 saveStateChangingPart(
2622 QString ("colorSubtree (\"%1\")").arg(c.name()),
2623 QString ("Set color of %1 and children to %2").arg(getObjectName(selbi)).arg(c.name())
2625 BranchItem *prev=NULL;
2626 BranchItem *cur=selbi;
2629 cur->setHeadingColor(c); // color links, color children
2630 cur=next (cur,prev,selbi);
2636 QColor VymModel::getCurrentHeadingColor()
2638 BranchItem *selbi=getSelectedBranch();
2639 if (selbi) return selbi->getHeadingColor();
2641 QMessageBox::warning(0,"Warning","Can't get color of heading,\nthere's no branch selected");
2647 void VymModel::editURL()
2649 TreeItem *selti=getSelectedItem();
2653 QString text = QInputDialog::getText(
2654 "VYM", tr("Enter URL:"), QLineEdit::Normal,
2655 selti->getURL(), &ok, NULL);
2657 // user entered something and pressed OK
2662 void VymModel::editLocalURL()
2664 TreeItem *selti=getSelectedItem();
2667 QStringList filters;
2668 filters <<"All files (*)";
2669 filters << tr("Text","Filedialog") + " (*.txt)";
2670 filters << tr("Spreadsheet","Filedialog") + " (*.odp,*.sxc)";
2671 filters << tr("Textdocument","Filedialog") +" (*.odw,*.sxw)";
2672 filters << tr("Images","Filedialog") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)";
2673 QFileDialog *fd=new QFileDialog( NULL,vymName+" - " +tr("Set URL to a local file"));
2674 fd->setFilters (filters);
2675 fd->setCaption(vymName+" - " +tr("Set URL to a local file"));
2676 fd->setDirectory (lastFileDir);
2677 if (! selti->getVymLink().isEmpty() )
2678 fd->selectFile( selti->getURL() );
2681 if ( fd->exec() == QDialog::Accepted )
2683 lastFileDir=QDir (fd->directory().path());
2684 setURL (fd->selectedFile() );
2690 void VymModel::editHeading2URL()
2692 TreeItem *selti=getSelectedItem();
2694 setURL (selti->getHeading());
2697 void VymModel::editBugzilla2URL()
2699 TreeItem *selti=getSelectedItem();
2702 QString url= "https://bugzilla.novell.com/show_bug.cgi?id="+selti->getHeading();
2707 void VymModel::editFATE2URL()
2709 TreeItem *selti=getSelectedItem();
2712 QString url= "http://keeper.suse.de:8080/webfate/match/id?value=ID"+selti->getHeading();
2715 "setURL (\""+selti->getURL()+"\")",
2717 "setURL (\""+url+"\")",
2718 QString("Use heading of %1 as link to FATE").arg(getObjectName(selti))
2720 selti->setURL (url);
2721 // FIXME-4 updateActions();
2725 void VymModel::editVymLink()
2727 BranchItem *bi=getSelectedBranch();
2730 QStringList filters;
2731 filters <<"VYM map (*.vym)";
2732 QFileDialog *fd=new QFileDialog( NULL,vymName+" - " +tr("Link to another map"));
2733 fd->setFilters (filters);
2734 fd->setCaption(vymName+" - " +tr("Link to another map"));
2735 fd->setDirectory (lastFileDir);
2736 if (! bi->getVymLink().isEmpty() )
2737 fd->selectFile( bi->getVymLink() );
2741 if ( fd->exec() == QDialog::Accepted )
2743 lastFileDir=QDir (fd->directory().path());
2746 "setVymLink (\""+bi->getVymLink()+"\")",
2748 "setVymLink (\""+fd->selectedFile()+"\")",
2749 QString("Set vymlink of %1 to %2").arg(getObjectName(bi)).arg(fd->selectedFile())
2751 setVymLink (fd->selectedFile() ); // FIXME-2 ok?
2756 void VymModel::setVymLink (const QString &s) // FIXME-3 no savestate?
2758 // Internal function, no saveState needed
2759 TreeItem *selti=getSelectedItem();
2762 selti->setVymLink(s);
2764 emitDataHasChanged (selti);
2765 emitShowSelection();
2769 void VymModel::deleteVymLink()
2771 BranchItem *bi=getSelectedBranch();
2776 "setVymLink (\""+bi->getVymLink()+"\")",
2778 "setVymLink (\"\")",
2779 QString("Unset vymlink of %1").arg(getObjectName(bi))
2781 bi->setVymLink ("" );
2787 QString VymModel::getVymLink()
2789 BranchItem *bi=getSelectedBranch();
2791 return bi->getVymLink();
2797 QStringList VymModel::getVymLinks()
2800 BranchItem *selbi=getSelectedBranch();
2801 BranchItem *cur=selbi;
2802 BranchItem *prev=NULL;
2805 if (!cur->getVymLink().isEmpty()) links.append( cur->getVymLink());
2806 cur=next (cur,prev,selbi);
2812 void VymModel::followXLink(int i)
2815 BranchItem *selbi=getSelectedBranch();
2818 selbi=selbi->getXLinkNum(i)->getPartnerBranch();
2819 if (selbi) select (selbi);
2823 void VymModel::editXLink(int i)
2826 BranchItem *selbi=getSelectedBranch();
2829 XLinkItem *xli=selbi->getXLinkNum(i);
2832 EditXLinkDialog dia;
2834 dia.setSelection(selbi);
2835 if (dia.exec() == QDialog::Accepted)
2837 if (dia.useSettingsGlobal() )
2839 setMapDefXLinkColor (xli->getColor() );
2840 setMapDefXLinkWidth (xli->getWidth() );
2842 if (dia.deleteXLink()) deleteItem (xli);
2852 //////////////////////////////////////////////
2854 //////////////////////////////////////////////
2856 void VymModel::parseAtom(const QString &atom)
2858 TreeItem* selti=getSelectedItem();
2859 BranchItem *selbi=getSelectedBranch();
2865 // Split string s into command and parameters
2866 parser.parseAtom (atom);
2867 QString com=parser.getCommand();
2869 // External commands
2870 /////////////////////////////////////////////////////////////////////
2871 if (com=="addBranch")
2875 parser.setError (Aborted,"Nothing selected");
2876 } else if (! selbi )
2878 parser.setError (Aborted,"Type of selection is not a branch");
2883 if (parser.checkParCount(pl))
2885 if (parser.parCount()==0)
2889 n=parser.parInt (ok,0);
2890 if (ok ) addNewBranch (n);
2894 /////////////////////////////////////////////////////////////////////
2895 } else if (com=="addBranchBefore")
2899 parser.setError (Aborted,"Nothing selected");
2900 } else if (! selbi )
2902 parser.setError (Aborted,"Type of selection is not a branch");
2905 if (parser.parCount()==0)
2907 addNewBranchBefore ();
2910 /////////////////////////////////////////////////////////////////////
2911 } else if (com==QString("addMapCenter"))
2913 if (parser.checkParCount(2))
2915 x=parser.parDouble (ok,0);
2918 y=parser.parDouble (ok,1);
2919 if (ok) addMapCenter (QPointF(x,y));
2922 /////////////////////////////////////////////////////////////////////
2923 } else if (com==QString("addMapReplace"))
2927 parser.setError (Aborted,"Nothing selected");
2928 } else if (! selbi )
2930 parser.setError (Aborted,"Type of selection is not a branch");
2931 } else if (parser.checkParCount(1))
2933 //s=parser.parString (ok,0); // selection
2934 t=parser.parString (ok,0); // path to map
2935 if (QDir::isRelativePath(t)) t=(tmpMapDir + "/"+t);
2936 addMapReplaceInt(getSelectString(selbi),t);
2938 /////////////////////////////////////////////////////////////////////
2939 } else if (com==QString("addMapInsert"))
2941 if (parser.parCount()==2)
2946 parser.setError (Aborted,"Nothing selected");
2947 } else if (! selbi )
2949 parser.setError (Aborted,"Type of selection is not a branch");
2952 t=parser.parString (ok,0); // path to map
2953 n=parser.parInt(ok,1); // position
2954 if (QDir::isRelativePath(t)) t=(tmpMapDir + "/"+t);
2955 addMapInsertInt(t,n);
2957 } else if (parser.parCount()==1)
2959 t=parser.parString (ok,0); // path to map
2960 if (QDir::isRelativePath(t)) t=(tmpMapDir + "/"+t);
2963 parser.setError (Aborted,"Wrong number of parameters");
2964 /////////////////////////////////////////////////////////////////////
2965 } else if (com=="clearFlags")
2969 parser.setError (Aborted,"Nothing selected");
2970 } else if (! selbi )
2972 parser.setError (Aborted,"Type of selection is not a branch");
2973 } else if (parser.checkParCount(0))
2975 selbi->deactivateAllStandardFlags();
2977 /////////////////////////////////////////////////////////////////////
2978 } else if (com=="colorBranch")
2982 parser.setError (Aborted,"Nothing selected");
2983 } else if (! selbi )
2985 parser.setError (Aborted,"Type of selection is not a branch");
2986 } else if (parser.checkParCount(1))
2988 QColor c=parser.parColor (ok,0);
2989 if (ok) colorBranch (c);
2991 /////////////////////////////////////////////////////////////////////
2992 } else if (com=="colorSubtree")
2996 parser.setError (Aborted,"Nothing selected");
2997 } else if (! selbi )
2999 parser.setError (Aborted,"Type of selection is not a branch");
3000 } else if (parser.checkParCount(1))
3002 QColor c=parser.parColor (ok,0);
3003 if (ok) colorSubtree (c);
3005 /////////////////////////////////////////////////////////////////////
3006 } else if (com=="copy")
3010 parser.setError (Aborted,"Nothing selected");
3011 } else if ( selectionType()!=TreeItem::Branch &&
3012 selectionType()!=TreeItem::MapCenter &&
3013 selectionType()!=TreeItem::Image )
3015 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
3016 } else if (parser.checkParCount(0))
3020 /////////////////////////////////////////////////////////////////////
3021 } else if (com=="cut")
3025 parser.setError (Aborted,"Nothing selected");
3026 } else if ( selectionType()!=TreeItem::Branch &&
3027 selectionType()!=TreeItem::MapCenter &&
3028 selectionType()!=TreeItem::Image )
3030 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
3031 } else if (parser.checkParCount(0))
3035 /////////////////////////////////////////////////////////////////////
3036 } else if (com=="delete")
3040 parser.setError (Aborted,"Nothing selected");
3042 /*else if (selectionType() != TreeItem::Branch && selectionType() != TreeItem::Image )
3044 parser.setError (Aborted,"Type of selection is wrong.");
3047 else if (parser.checkParCount(0))
3051 /////////////////////////////////////////////////////////////////////
3052 } else if (com=="deleteKeepChildren")
3056 parser.setError (Aborted,"Nothing selected");
3057 } else if (! selbi )
3059 parser.setError (Aborted,"Type of selection is not a branch");
3060 } else if (parser.checkParCount(0))
3062 deleteKeepChildren();
3064 /////////////////////////////////////////////////////////////////////
3065 } else if (com=="deleteChildren")
3069 parser.setError (Aborted,"Nothing selected");
3072 parser.setError (Aborted,"Type of selection is not a branch");
3073 } else if (parser.checkParCount(0))
3077 /////////////////////////////////////////////////////////////////////
3078 } else if (com=="exportASCII")
3082 if (parser.parCount()>=1)
3083 // Hey, we even have a filename
3084 fname=parser.parString(ok,0);
3087 parser.setError (Aborted,"Could not read filename");
3090 exportASCII (fname,false);
3092 /////////////////////////////////////////////////////////////////////
3093 } else if (com=="exportImage")
3097 if (parser.parCount()>=2)
3098 // Hey, we even have a filename
3099 fname=parser.parString(ok,0);
3102 parser.setError (Aborted,"Could not read filename");
3105 QString format="PNG";
3106 if (parser.parCount()>=2)
3108 format=parser.parString(ok,1);
3110 exportImage (fname,false,format);
3112 /////////////////////////////////////////////////////////////////////
3113 } else if (com=="exportXHTML")
3117 if (parser.parCount()>=2)
3118 // Hey, we even have a filename
3119 fname=parser.parString(ok,1);
3122 parser.setError (Aborted,"Could not read filename");
3125 exportXHTML (fname,false);
3127 /////////////////////////////////////////////////////////////////////
3128 } else if (com=="exportXML")
3132 if (parser.parCount()>=2)
3133 // Hey, we even have a filename
3134 fname=parser.parString(ok,1);
3137 parser.setError (Aborted,"Could not read filename");
3140 exportXML (fname,false);
3142 /////////////////////////////////////////////////////////////////////
3143 } else if (com=="importDir")
3147 parser.setError (Aborted,"Nothing selected");
3148 } else if (! selbi )
3150 parser.setError (Aborted,"Type of selection is not a branch");
3151 } else if (parser.checkParCount(1))
3153 s=parser.parString(ok,0);
3154 if (ok) importDirInt(s);
3156 /////////////////////////////////////////////////////////////////////
3157 } else if (com=="relinkTo")
3161 parser.setError (Aborted,"Nothing selected");
3164 if (parser.checkParCount(4))
3166 // 0 selectstring of parent
3167 // 1 num in parent (for branches)
3168 // 2,3 x,y of mainbranch or mapcenter
3169 s=parser.parString(ok,0);
3170 TreeItem *dst=findBySelectString (s);
3173 if (dst->getType()==TreeItem::Branch)
3175 // Get number in parent
3176 n=parser.parInt (ok,1);
3179 relinkBranch (selbi,(BranchItem*)dst,n);
3180 emitSelectionChanged();
3182 } else if (dst->getType()==TreeItem::MapCenter)
3184 relinkBranch (selbi,(BranchItem*)dst);
3185 // Get coordinates of mainbranch
3186 x=parser.parDouble(ok,2);
3189 y=parser.parDouble(ok,3);
3192 if (selbi->getLMO()) selbi->getLMO()->move (x,y);
3193 emitSelectionChanged();
3199 } else if ( selti->getType() == TreeItem::Image)
3201 if (parser.checkParCount(1))
3203 // 0 selectstring of parent
3204 s=parser.parString(ok,0);
3205 TreeItem *dst=findBySelectString (s);
3208 if (dst->isBranchLikeType())
3209 relinkImage ( ((ImageItem*)selti),(BranchItem*)dst);
3211 parser.setError (Aborted,"Destination is not a branch");
3214 parser.setError (Aborted,"Type of selection is not a floatimage or branch");
3215 /////////////////////////////////////////////////////////////////////
3216 } else if (com=="loadImage")
3220 parser.setError (Aborted,"Nothing selected");
3221 } else if (! selbi )
3223 parser.setError (Aborted,"Type of selection is not a branch");
3224 } else if (parser.checkParCount(1))
3226 s=parser.parString(ok,0);
3227 if (ok) loadFloatImageInt (selbi,s);
3229 /////////////////////////////////////////////////////////////////////
3230 } else if (com=="moveUp")
3234 parser.setError (Aborted,"Nothing selected");
3235 } else if (! selbi )
3237 parser.setError (Aborted,"Type of selection is not a branch");
3238 } else if (parser.checkParCount(0))
3242 /////////////////////////////////////////////////////////////////////
3243 } else if (com=="moveDown")
3247 parser.setError (Aborted,"Nothing selected");
3248 } else if (! selbi )
3250 parser.setError (Aborted,"Type of selection is not a branch");
3251 } else if (parser.checkParCount(0))
3255 /////////////////////////////////////////////////////////////////////
3256 } else if (com=="move")
3260 parser.setError (Aborted,"Nothing selected");
3261 } else if ( selectionType()!=TreeItem::Branch &&
3262 selectionType()!=TreeItem::MapCenter &&
3263 selectionType()!=TreeItem::Image )
3265 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
3266 } else if (parser.checkParCount(2))
3268 x=parser.parDouble (ok,0);
3271 y=parser.parDouble (ok,1);
3275 /////////////////////////////////////////////////////////////////////
3276 } else if (com=="moveRel")
3280 parser.setError (Aborted,"Nothing selected");
3281 } else if ( selectionType()!=TreeItem::Branch &&
3282 selectionType()!=TreeItem::MapCenter &&
3283 selectionType()!=TreeItem::Image )
3285 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
3286 } else if (parser.checkParCount(2))
3288 x=parser.parDouble (ok,0);
3291 y=parser.parDouble (ok,1);
3292 if (ok) moveRel (x,y);
3295 /////////////////////////////////////////////////////////////////////
3296 } else if (com=="nop")
3298 /////////////////////////////////////////////////////////////////////
3299 } else if (com=="paste")
3303 parser.setError (Aborted,"Nothing selected");
3304 } else if (! selbi )
3306 parser.setError (Aborted,"Type of selection is not a branch");
3307 } else if (parser.checkParCount(1))
3309 n=parser.parInt (ok,0);
3310 if (ok) pasteNoSave(n);
3312 /////////////////////////////////////////////////////////////////////
3313 } else if (com=="qa")
3317 parser.setError (Aborted,"Nothing selected");
3318 } else if (! selbi )
3320 parser.setError (Aborted,"Type of selection is not a branch");
3321 } else if (parser.checkParCount(4))
3324 c=parser.parString (ok,0);
3327 parser.setError (Aborted,"No comment given");
3330 s=parser.parString (ok,1);
3333 parser.setError (Aborted,"First parameter is not a string");
3336 t=parser.parString (ok,2);
3339 parser.setError (Aborted,"Condition is not a string");
3342 u=parser.parString (ok,3);
3345 parser.setError (Aborted,"Third parameter is not a string");
3350 parser.setError (Aborted,"Unknown type: "+s);
3355 parser.setError (Aborted,"Unknown operator: "+t);
3360 parser.setError (Aborted,"Type of selection is not a branch");
3363 if (selbi->getHeading() == u)
3365 cout << "PASSED: " << qPrintable (c) << endl;
3368 cout << "FAILED: " << qPrintable (c) << endl;
3378 /////////////////////////////////////////////////////////////////////
3379 } else if (com=="saveImage")
3381 ImageItem *ii=getSelectedImage();
3384 parser.setError (Aborted,"No image selected");
3385 } else if (parser.checkParCount(2))
3387 s=parser.parString(ok,0);
3390 t=parser.parString(ok,1);
3391 if (ok) saveFloatImageInt (ii,t,s);
3394 /////////////////////////////////////////////////////////////////////
3395 } else if (com=="scroll")
3399 parser.setError (Aborted,"Nothing selected");
3400 } else if (! selbi )
3402 parser.setError (Aborted,"Type of selection is not a branch");
3403 } else if (parser.checkParCount(0))
3405 if (!scrollBranch (selbi))
3406 parser.setError (Aborted,"Could not scroll branch");
3408 /////////////////////////////////////////////////////////////////////
3409 } else if (com=="select")
3411 if (parser.checkParCount(1))
3413 s=parser.parString(ok,0);
3416 /////////////////////////////////////////////////////////////////////
3417 } else if (com=="selectLastBranch")
3421 parser.setError (Aborted,"Nothing selected");
3422 } else if (! selbi )
3424 parser.setError (Aborted,"Type of selection is not a branch");
3425 } else if (parser.checkParCount(0))
3427 BranchItem *bi=selbi->getLastBranch();
3429 parser.setError (Aborted,"Could not select last branch");
3430 select (bi); // FIXME-3 was selectInt
3433 /////////////////////////////////////////////////////////////////////
3434 } else /* FIXME-2 if (com=="selectLastImage")
3438 parser.setError (Aborted,"Nothing selected");
3439 } else if (! selbi )
3441 parser.setError (Aborted,"Type of selection is not a branch");
3442 } else if (parser.checkParCount(0))
3444 FloatImageObj *fio=selb->getLastFloatImage();
3446 parser.setError (Aborted,"Could not select last image");
3447 select (fio); // FIXME-3 was selectInt
3450 /////////////////////////////////////////////////////////////////////
3451 } else */ if (com=="selectLatestAdded")
3453 if (!latestAddedItem)
3455 parser.setError (Aborted,"No latest added object");
3458 if (!select (latestAddedItem))
3459 parser.setError (Aborted,"Could not select latest added object ");
3461 /////////////////////////////////////////////////////////////////////
3462 } else if (com=="setFrameType")
3464 if ( selectionType()!=TreeItem::Branch && selectionType()!= TreeItem::MapCenter && selectionType()!=TreeItem::Image)
3466 parser.setError (Aborted,"Type of selection does not allow setting frame type");
3468 else if (parser.checkParCount(1))
3470 s=parser.parString(ok,0);
3471 if (ok) setFrameType (s);
3473 /////////////////////////////////////////////////////////////////////
3474 } else if (com=="setFramePenColor")
3476 if ( selectionType()!=TreeItem::Branch && selectionType()!= TreeItem::MapCenter && selectionType()!=TreeItem::Image)
3478 parser.setError (Aborted,"Type of selection does not allow setting of pen color");
3480 else if (parser.checkParCount(1))
3482 QColor c=parser.parColor(ok,0);
3483 if (ok) setFramePenColor (c);
3485 /////////////////////////////////////////////////////////////////////
3486 } else if (com=="setFrameBrushColor")
3488 if ( selectionType()!=TreeItem::Branch && selectionType()!= TreeItem::MapCenter && selectionType()!=TreeItem::Image)
3490 parser.setError (Aborted,"Type of selection does not allow setting brush color");
3492 else if (parser.checkParCount(1))
3494 QColor c=parser.parColor(ok,0);
3495 if (ok) setFrameBrushColor (c);
3497 /////////////////////////////////////////////////////////////////////
3498 } else if (com=="setFramePadding")
3500 if ( selectionType()!=TreeItem::Branch && selectionType()!= TreeItem::MapCenter && selectionType()!=TreeItem::Image)
3502 parser.setError (Aborted,"Type of selection does not allow setting frame padding");
3504 else if (parser.checkParCount(1))
3506 n=parser.parInt(ok,0);
3507 if (ok) setFramePadding(n);
3509 /////////////////////////////////////////////////////////////////////
3510 } else if (com=="setFrameBorderWidth")
3512 if ( selectionType()!=TreeItem::Branch && selectionType()!= TreeItem::MapCenter && selectionType()!=TreeItem::Image)
3514 parser.setError (Aborted,"Type of selection does not allow setting frame border width");
3516 else if (parser.checkParCount(1))
3518 n=parser.parInt(ok,0);
3519 if (ok) setFrameBorderWidth (n);
3521 /////////////////////////////////////////////////////////////////////
3522 } else if (com=="setMapAuthor")
3524 if (parser.checkParCount(1))
3526 s=parser.parString(ok,0);
3527 if (ok) setAuthor (s);
3529 /////////////////////////////////////////////////////////////////////
3530 } else if (com=="setMapComment")
3532 if (parser.checkParCount(1))
3534 s=parser.parString(ok,0);
3535 if (ok) setComment(s);
3537 /////////////////////////////////////////////////////////////////////
3538 } else if (com=="setMapBackgroundColor")
3542 parser.setError (Aborted,"Nothing selected");
3543 } else if (! selbi )
3545 parser.setError (Aborted,"Type of selection is not a branch");
3546 } else if (parser.checkParCount(1))
3548 QColor c=parser.parColor (ok,0);
3549 if (ok) setMapBackgroundColor (c);
3551 /////////////////////////////////////////////////////////////////////
3552 } else if (com=="setMapDefLinkColor")
3556 parser.setError (Aborted,"Nothing selected");
3557 } else if (! selbi )
3559 parser.setError (Aborted,"Type of selection is not a branch");
3560 } else if (parser.checkParCount(1))
3562 QColor c=parser.parColor (ok,0);
3563 if (ok) setMapDefLinkColor (c);
3565 /////////////////////////////////////////////////////////////////////
3566 } else if (com=="setMapLinkStyle")
3568 if (parser.checkParCount(1))
3570 s=parser.parString (ok,0);
3571 if (ok) setMapLinkStyle(s);
3573 /////////////////////////////////////////////////////////////////////
3574 } else if (com=="setHeading")
3578 parser.setError (Aborted,"Nothing selected");
3579 } else if (! selbi )
3581 parser.setError (Aborted,"Type of selection is not a branch");
3582 } else if (parser.checkParCount(1))
3584 s=parser.parString (ok,0);
3588 /////////////////////////////////////////////////////////////////////
3589 } else if (com=="setHideExport")
3593 parser.setError (Aborted,"Nothing selected");
3594 } else if (selectionType()!=TreeItem::Branch && selectionType() != TreeItem::MapCenter &&selectionType()!=TreeItem::Image)
3596 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
3597 } else if (parser.checkParCount(1))
3599 b=parser.parBool(ok,0);
3600 if (ok) setHideExport (b);
3602 /////////////////////////////////////////////////////////////////////
3603 } else if (com=="setIncludeImagesHorizontally")
3607 parser.setError (Aborted,"Nothing selected");
3610 parser.setError (Aborted,"Type of selection is not a branch");
3611 } else if (parser.checkParCount(1))
3613 b=parser.parBool(ok,0);
3614 if (ok) setIncludeImagesHor(b);
3616 /////////////////////////////////////////////////////////////////////
3617 } else if (com=="setIncludeImagesVertically")
3621 parser.setError (Aborted,"Nothing selected");
3624 parser.setError (Aborted,"Type of selection is not a branch");
3625 } else if (parser.checkParCount(1))
3627 b=parser.parBool(ok,0);
3628 if (ok) setIncludeImagesVer(b);
3630 /////////////////////////////////////////////////////////////////////
3631 } else if (com=="setHideLinkUnselected")
3635 parser.setError (Aborted,"Nothing selected");
3636 } else if ( selectionType()!=TreeItem::Branch && selectionType()!= TreeItem::MapCenter && selectionType()!=TreeItem::Image)
3638 parser.setError (Aborted,"Type of selection does not allow hiding the link");
3639 } else if (parser.checkParCount(1))
3641 b=parser.parBool(ok,0);
3642 if (ok) setHideLinkUnselected(b);
3644 /////////////////////////////////////////////////////////////////////
3645 } else if (com=="setSelectionColor")
3647 if (parser.checkParCount(1))
3649 QColor c=parser.parColor (ok,0);
3650 if (ok) setSelectionColorInt (c);
3652 /////////////////////////////////////////////////////////////////////
3653 } else if (com=="setURL")
3657 parser.setError (Aborted,"Nothing selected");
3658 } else if (! selbi )
3660 parser.setError (Aborted,"Type of selection is not a branch");
3661 } else if (parser.checkParCount(1))
3663 s=parser.parString (ok,0);
3666 /////////////////////////////////////////////////////////////////////
3667 } else if (com=="setVymLink")
3671 parser.setError (Aborted,"Nothing selected");
3672 } else if (! selbi )
3674 parser.setError (Aborted,"Type of selection is not a branch");
3675 } else if (parser.checkParCount(1))
3677 s=parser.parString (ok,0);
3678 if (ok) setVymLink(s);
3681 /////////////////////////////////////////////////////////////////////
3682 else if (com=="setFlag")
3686 parser.setError (Aborted,"Nothing selected");
3687 } else if (! selbi )
3689 parser.setError (Aborted,"Type of selection is not a branch");
3690 } else if (parser.checkParCount(1))
3692 s=parser.parString(ok,0);
3694 selbi->activateStandardFlag(s);
3696 /////////////////////////////////////////////////////////////////////
3697 } else /* FIXME-2 if (com=="setFrameType")
3701 parser.setError (Aborted,"Nothing selected");
3704 parser.setError (Aborted,"Type of selection is not a branch");
3705 } else if (parser.checkParCount(1))
3707 s=parser.parString(ok,0);
3711 /////////////////////////////////////////////////////////////////////
3712 } else*/ if (com=="sortChildren")
3716 parser.setError (Aborted,"Nothing selected");
3717 } else if (! selbi )
3719 parser.setError (Aborted,"Type of selection is not a branch");
3720 } else if (parser.checkParCount(0))
3724 /////////////////////////////////////////////////////////////////////
3725 } else if (com=="toggleFlag")
3729 parser.setError (Aborted,"Nothing selected");
3730 } else if (! selbi )
3732 parser.setError (Aborted,"Type of selection is not a branch");
3733 } else if (parser.checkParCount(1))
3735 s=parser.parString(ok,0);
3737 selbi->toggleStandardFlag(s);
3739 /////////////////////////////////////////////////////////////////////
3740 } else if (com=="unscroll")
3744 parser.setError (Aborted,"Nothing selected");
3745 } else if (! selbi )
3747 parser.setError (Aborted,"Type of selection is not a branch");
3748 } else if (parser.checkParCount(0))
3750 if (!unscrollBranch (selbi))
3751 parser.setError (Aborted,"Could not unscroll branch");
3753 /////////////////////////////////////////////////////////////////////
3754 } else if (com=="unscrollChildren")
3758 parser.setError (Aborted,"Nothing selected");
3759 } else if (! selbi )
3761 parser.setError (Aborted,"Type of selection is not a branch");
3762 } else if (parser.checkParCount(0))
3764 unscrollChildren ();
3766 /////////////////////////////////////////////////////////////////////
3767 } else if (com=="unsetFlag")
3771 parser.setError (Aborted,"Nothing selected");
3772 } else if (! selbi )
3774 parser.setError (Aborted,"Type of selection is not a branch");
3775 } else if (parser.checkParCount(1))
3777 s=parser.parString(ok,0);
3779 selbi->deactivateStandardFlag(s);
3782 parser.setError (Aborted,"Unknown command");
3785 if (parser.errorLevel()==NoError)
3787 // setChanged(); FIXME-2 should not be called e.g. for export?!
3792 // TODO Error handling
3793 qWarning("VymModel::parseAtom: Error!");
3794 qWarning(parser.errorMessage());
3798 void VymModel::runScript (QString script)
3800 parser.setScript (script);
3802 while (parser.next() )
3803 parseAtom(parser.getAtom());
3806 void VymModel::setExportMode (bool b)
3808 // should be called before and after exports
3809 // depending on the settings
3810 if (b && settings.value("/export/useHideExport","true")=="true")
3811 setHideTmpMode (TreeItem::HideExport);
3813 setHideTmpMode (TreeItem::HideNone);
3816 void VymModel::exportImage(QString fname, bool askName, QString format)
3818 /* FIXME-2 export as image, but directly from mapEditor?!
3821 fname=getMapName()+".png";
3828 QFileDialog *fd=new QFileDialog (NULL);
3829 fd->setCaption (tr("Export map as image"));
3830 fd->setDirectory (lastImageDir);
3831 fd->setFileMode(QFileDialog::AnyFile);
3832 fd->setFilters (imageIO.getFilters() );
3835 fl=fd->selectedFiles();
3837 format=imageIO.getType(fd->selectedFilter());
3841 setExportMode (true);
3842 QPixmap pix (mapEditor->getPixmap());
3843 pix.save(fname, format);
3844 setExportMode (false);
3849 void VymModel::exportXML(QString dir, bool askForName)
3853 dir=browseDirectory(NULL,tr("Export XML to directory"));
3854 if (dir =="" && !reallyWriteDirectory(dir) )
3858 // Hide stuff during export, if settings want this
3859 setExportMode (true);
3861 // Create subdirectories
3864 // write to directory //FIXME-4 check totalBBox here...
3865 QString saveFile=saveToDir (dir,mapName+"-",true,mapEditor->getTotalBBox().topLeft() ,NULL);
3868 file.setName ( dir + "/"+mapName+".xml");
3869 if ( !file.open( QIODevice::WriteOnly ) )
3871 // This should neverever happen
3872 QMessageBox::critical (0,tr("Critical Export Error"),tr("VymModel::exportXML couldn't open %1").arg(file.name()));
3876 // Write it finally, and write in UTF8, no matter what
3877 QTextStream ts( &file );
3878 ts.setEncoding (QTextStream::UnicodeUTF8);
3882 // Now write image, too
3883 exportImage (dir+"/images/"+mapName+".png",false,"PNG");
3885 setExportMode (false);
3888 void VymModel::exportASCII(QString fname,bool askName)
3893 ex.setFile (mapName+".txt");
3899 //ex.addFilter ("TXT (*.txt)");
3900 ex.setDir(lastImageDir);
3901 //ex.setCaption(vymName+ " -" +tr("Export as ASCII")+" "+tr("(still experimental)"));
3906 setExportMode(true);
3908 setExportMode(false);
3912 void VymModel::exportXHTML (const QString &dir, bool askForName)
3914 ExportXHTMLDialog dia(NULL);
3915 dia.setFilePath (filePath );
3916 dia.setMapName (mapName );
3918 if (dir!="") dia.setDir (dir);
3924 if (dia.exec()!=QDialog::Accepted)
3928 QDir d (dia.getDir());
3929 // Check, if warnings should be used before overwriting
3930 // the output directory
3931 if (d.exists() && d.count()>0)
3934 warn.showCancelButton (true);
3935 warn.setText(QString(
3936 "The directory %1 is not empty.\n"
3937 "Do you risk to overwrite some of its contents?").arg(d.path() ));
3938 warn.setCaption("Warning: Directory not empty");
3939 warn.setShowAgainName("mainwindow/overwrite-dir-xhtml");
3941 if (warn.exec()!=QDialog::Accepted) ok=false;
3948 exportXML (dia.getDir(),false );
3949 dia.doExport(mapName );
3950 //if (dia.hasChanged()) setChanged();
3954 void VymModel::exportOOPresentation(const QString &fn, const QString &cf)
3959 if (ex.setConfigFile(cf))
3961 setExportMode (true);
3962 ex.exportPresentation();
3963 setExportMode (false);
3970 //////////////////////////////////////////////
3972 //////////////////////////////////////////////
3974 void VymModel::registerEditor(QWidget *me)
3976 mapEditor=(MapEditor*)me;
3979 void VymModel::unregisterEditor(QWidget *)
3984 void VymModel::setContextPos(QPointF p)
3989 void VymModel::unsetContextPos()
3991 contextPos=QPointF();
3994 void VymModel::updateNoteFlag()
3997 TreeItem *selti=getSelectedItem();
4000 if (textEditor->isEmpty())
4003 selti->setNote (textEditor->getText());
4004 emitDataHasChanged(selti);
4005 emitSelectionChanged();
4010 void VymModel::updateRelPositions() //FIXME-3 VM should have no need to updateRelPos
4013 for (int i=0; i<rootItem->branchCount(); i++)
4014 ((MapCenterObj*)rootItem->getBranchObjNum(i))->updateRelPositions();
4017 void MapCenterObj::updateRelPositions()
4019 if (repositionRequest) unsetAllRepositionRequests();
4021 // update relative Positions of branches and floats
4022 for (int i=0; i<treeItem->branchCount(); ++i)
4024 treeItem->getBranchObjNum(i)->setRelPos();
4025 treeItem->getBranchObjNum(i)->setOrientation();
4028 for (int i=0; i<floatimage.size(); ++i)
4029 floatimage.at(i)->setRelPos();
4031 if (repositionRequest) reposition();
4036 void VymModel::reposition() //FIXME-3 VM should have no need to reposition, this is done in views???
4038 //cout << "VM::reposition blocked="<<blockReposition<<endl;
4039 if (blockReposition) return;
4041 for (int i=0;i<rootItem->branchCount(); i++)
4042 rootItem->getBranchObjNum(i)->reposition(); // for positioning heading
4046 QPolygonF VymModel::shape(BranchObj *bo) //FIXME-4
4048 return QPolygonF ();
4049 // Creating (arbitrary) shapes
4052 QRectF rb=bo->getBBox();
4053 if (bo->getDepth()==0)
4055 // Just take BBox of this mapCenter
4056 p<<rb.topLeft()<<rb.topRight()<<rb.bottomRight()<<rb.bottomLeft();
4060 // Take union of BBox and TotalBBox
4062 QRectF ra=bo->getTotalBBox();
4063 if (bo->getOrientation()==LinkableMapObj::LeftOfCenter)
4066 <<QPointF (rb.topLeft().x(), ra.topLeft().y() )
4069 <<QPointF (rb.bottomLeft().x(), ra.bottomLeft().y() ) ;
4071 p <<ra.bottomRight()
4073 <<QPointF (rb.topRight().x(), ra.topRight().y() )
4076 <<QPointF (rb.bottomRight().x(), ra.bottomRight().y() ) ;
4082 void VymModel::moveAway(LinkableMapObj *lmo) //FIXME-5
4086 // Move all branches and MapCenters away from lmo
4087 // to avoid collisions
4092 BranchObj *boA=(BranchObj*)lmo;
4094 for (int i=0; i<rootItem->branchCount(); i++)
4096 boB=rootItem->getBranchNum(i);
4099 PolygonCollisionResult r = PolygonCollision(pA, pB, QPoint(0,0));
4102 <<" ("<<qPrintable(boA->getHeading() )<<")"
4103 <<" with ("<< qPrintable (boB->getHeading() )
4106 <<" minT="<<r.minTranslation<<endl<<endl;
4112 void VymModel::setMapLinkStyle (const QString & s)
4117 case LinkableMapObj::Line :
4120 case LinkableMapObj::Parabel:
4121 snow="StyleParabel";
4123 case LinkableMapObj::PolyLine:
4124 snow="StylePolyLine";
4126 case LinkableMapObj::PolyParabel:
4127 snow="StylePolyParabel";
4130 snow="UndefinedStyle";
4135 QString("setMapLinkStyle (\"%1\")").arg(s),
4136 QString("setMapLinkStyle (\"%1\")").arg(snow),
4137 QString("Set map link style (\"%1\")").arg(s)
4141 linkstyle=LinkableMapObj::Line;
4142 else if (s=="StyleParabel")
4143 linkstyle=LinkableMapObj::Parabel;
4144 else if (s=="StylePolyLine")
4145 linkstyle=LinkableMapObj::PolyLine;
4146 else if (s=="StylePolyParabel")
4147 linkstyle=LinkableMapObj::PolyParabel;
4149 linkstyle=LinkableMapObj::UndefinedStyle;
4151 BranchItem *cur=NULL;
4152 BranchItem *prev=NULL;
4157 bo=(BranchObj*)(cur->getLMO() );
4158 bo->setLinkStyle(bo->getDefLinkStyle(cur->parent() )); //FIXME-3 better emit dataCHanged and leave the changes to View
4164 LinkableMapObj::Style VymModel::getMapLinkStyle ()
4169 void VymModel::setMapDefLinkColor(QColor col)
4171 if ( !col.isValid() ) return;
4173 QString("setMapDefLinkColor (\"%1\")").arg(getMapDefLinkColor().name()),
4174 QString("setMapDefLinkColor (\"%1\")").arg(col.name()),
4175 QString("Set map link color to %1").arg(col.name())
4179 BranchItem *cur=NULL;
4180 BranchItem *prev=NULL;
4185 bo=(BranchObj*)(cur->getLMO() );
4192 void VymModel::setMapLinkColorHintInt()
4194 // called from setMapLinkColorHint(lch) or at end of parse
4195 BranchItem *cur=NULL;
4196 BranchItem *prev=NULL;
4201 bo=(BranchObj*)(cur->getLMO() );
4207 void VymModel::setMapLinkColorHint(LinkableMapObj::ColorHint lch)
4210 setMapLinkColorHintInt();
4213 void VymModel::toggleMapLinkColorHint()
4215 if (linkcolorhint==LinkableMapObj::HeadingColor)
4216 linkcolorhint=LinkableMapObj::DefaultColor;
4218 linkcolorhint=LinkableMapObj::HeadingColor;
4219 BranchItem *cur=NULL;
4220 BranchItem *prev=NULL;
4225 bo=(BranchObj*)(cur->getLMO() );
4231 void VymModel::selectMapBackgroundImage () // FIXME-2 move to ME
4233 Q3FileDialog *fd=new Q3FileDialog( NULL);
4234 fd->setMode (Q3FileDialog::ExistingFile);
4235 fd->addFilter (QString (tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)"));
4236 ImagePreview *p =new ImagePreview (fd);
4237 fd->setContentsPreviewEnabled( TRUE );
4238 fd->setContentsPreview( p, p );
4239 fd->setPreviewMode( Q3FileDialog::Contents );
4240 fd->setCaption(vymName+" - " +tr("Load background image"));
4241 fd->setDir (lastImageDir);
4244 if ( fd->exec() == QDialog::Accepted )
4246 // TODO selectMapBackgroundImg in QT4 use: lastImageDir=fd->directory();
4247 lastImageDir=QDir (fd->dirPath());
4248 setMapBackgroundImage (fd->selectedFile());
4252 void VymModel::setMapBackgroundImage (const QString &fn) //FIXME-2 missing savestate, move to ME
4254 QColor oldcol=mapScene->backgroundBrush().color();
4258 QString ("setMapBackgroundImage (%1)").arg(oldcol.name()),
4260 QString ("setMapBackgroundImage (%1)").arg(col.name()),
4261 QString("Set background color of map to %1").arg(col.name()));
4264 brush.setTextureImage (QPixmap (fn));
4265 mapScene->setBackgroundBrush(brush);
4268 void VymModel::selectMapBackgroundColor() // FIXME-3 move to ME
4270 QColor col = QColorDialog::getColor( mapScene->backgroundBrush().color(), NULL);
4271 if ( !col.isValid() ) return;
4272 setMapBackgroundColor( col );
4276 void VymModel::setMapBackgroundColor(QColor col) // FIXME-3 move to ME
4278 QColor oldcol=mapScene->backgroundBrush().color();
4280 QString ("setMapBackgroundColor (\"%1\")").arg(oldcol.name()),
4281 QString ("setMapBackgroundColor (\"%1\")").arg(col.name()),
4282 QString("Set background color of map to %1").arg(col.name()));
4283 mapScene->setBackgroundBrush(col);
4286 QColor VymModel::getMapBackgroundColor() // FIXME-3 move to ME
4288 return mapScene->backgroundBrush().color();
4292 LinkableMapObj::ColorHint VymModel::getMapLinkColorHint() // FIXME-3 move to ME
4294 return linkcolorhint;
4297 QColor VymModel::getMapDefLinkColor() // FIXME-3 move to ME
4299 return defLinkColor;
4302 void VymModel::setMapDefXLinkColor(QColor col) // FIXME-3 move to ME
4307 QColor VymModel::getMapDefXLinkColor() // FIXME-3 move to ME
4309 return defXLinkColor;
4312 void VymModel::setMapDefXLinkWidth (int w) // FIXME-3 move to ME
4317 int VymModel::getMapDefXLinkWidth() // FIXME-3 move to ME
4319 return defXLinkWidth;
4322 void VymModel::move(const double &x, const double &y) // FIXME-3
4326 BranchObj *bo = getSelectedBranch();
4328 (selectionType()==TreeItem::Branch ||
4329 selectionType()==TreeItem::MapCenter ||
4330 selectionType()==TreeItem::Image
4333 QPointF ap(bo->getAbsPos());
4337 QString ps=qpointfToString(ap);
4338 QString s=getSelectString();
4341 s, "move "+qpointfToString(to),
4342 QString("Move %1 to %2").arg(getObjectName(bo)).arg(ps));
4345 emitSelectionChanged();
4351 void VymModel::moveRel (const double &x, const double &y) // FIXME-3
4355 BranchObj *bo = getSelectedBranch();
4357 (selectionType()==TreeItem::Branch ||
4358 selectionType()==TreeItem::MapCenter ||
4359 selectionType()==TreeItem::Image
4363 QPointF rp(bo->getRelPos());
4367 QString ps=qpointfToString (bo->getRelPos());
4368 QString s=getSelectString(bo);
4371 s, "moveRel "+qpointfToString(to),
4372 QString("Move %1 to relative position %2").arg(getObjectName(bo)).arg(ps));
4373 ((OrnamentedObj*)bo)->move2RelPos (x,y);
4375 bo->updateLinkGeometry();
4376 emitSelectionChanged();
4383 void VymModel::animate()
4385 animationTimer->stop();
4388 while (i<animObjList.size() )
4390 bo=(BranchObj*)animObjList.at(i);
4395 animObjList.removeAt(i);
4402 QItemSelection sel=selModel->selection();
4403 emit (selectionChanged(sel,sel));
4406 if (!animObjList.isEmpty()) animationTimer->start();
4410 void VymModel::startAnimation(BranchObj *bo, const QPointF &start, const QPointF &dest)
4412 if (bo && bo->getTreeItem()->depth()>0)
4415 ap.setStart (start);
4417 ap.setTicks (animationTicks);
4418 ap.setAnimated (true);
4419 bo->setAnimation (ap);
4420 animObjList.append( bo );
4421 animationTimer->setSingleShot (true);
4422 animationTimer->start(animationInterval);
4426 void VymModel::stopAnimation (MapObj *mo)
4428 int i=animObjList.indexOf(mo);
4430 animObjList.removeAt (i);
4433 void VymModel::sendSelection()
4435 if (netstate!=Server) return;
4436 sendData (QString("select (\"%1\")").arg(getSelectString()) );
4439 void VymModel::newServer()
4443 tcpServer = new QTcpServer(this);
4444 if (!tcpServer->listen(QHostAddress::Any,port)) {
4445 QMessageBox::critical(NULL, "vym server",
4446 QString("Unable to start the server: %1.").arg(tcpServer->errorString()));
4447 //FIXME-3 needed? we are no widget any longer... close();
4450 connect(tcpServer, SIGNAL(newConnection()), this, SLOT(newClient()));
4452 cout<<"Server is running on port "<<tcpServer->serverPort()<<endl;
4455 void VymModel::connectToServer()
4458 server="salam.suse.de";
4460 clientSocket = new QTcpSocket (this);
4461 clientSocket->abort();
4462 clientSocket->connectToHost(server ,port);
4463 connect(clientSocket, SIGNAL(readyRead()), this, SLOT(readData()));
4464 connect(clientSocket, SIGNAL(error(QAbstractSocket::SocketError)),
4465 this, SLOT(displayNetworkError(QAbstractSocket::SocketError)));
4467 cout<<"connected to "<<qPrintable (server)<<" port "<<port<<endl;
4472 void VymModel::newClient()
4474 QTcpSocket *newClient = tcpServer->nextPendingConnection();
4475 connect(newClient, SIGNAL(disconnected()),
4476 newClient, SLOT(deleteLater()));
4478 cout <<"ME::newClient at "<<qPrintable( newClient->peerAddress().toString() )<<endl;
4480 clientList.append (newClient);
4484 void VymModel::sendData(const QString &s)
4486 if (clientList.size()==0) return;
4488 // Create bytearray to send
4490 QDataStream out(&block, QIODevice::WriteOnly);
4491 out.setVersion(QDataStream::Qt_4_0);
4493 // Reserve some space for blocksize
4496 // Write sendCounter
4497 out << sendCounter++;
4502 // Go back and write blocksize so far
4503 out.device()->seek(0);
4504 quint16 bs=(quint16)(block.size() - 2*sizeof(quint16));
4508 cout << "ME::sendData bs="<<bs<<" counter="<<sendCounter<<" s="<<qPrintable(s)<<endl;
4510 for (int i=0; i<clientList.size(); ++i)
4512 //cout << "Sending \""<<qPrintable (s)<<"\" to "<<qPrintable (clientList.at(i)->peerAddress().toString())<<endl;
4513 clientList.at(i)->write (block);
4517 void VymModel::readData ()
4519 while (clientSocket->bytesAvailable() >=(int)sizeof(quint16) )
4522 cout <<"readData bytesAvail="<<clientSocket->bytesAvailable();
4526 QDataStream in(clientSocket);
4527 in.setVersion(QDataStream::Qt_4_0);
4535 cout << " t="<<qPrintable (t)<<endl;
4541 void VymModel::displayNetworkError(QAbstractSocket::SocketError socketError)
4543 switch (socketError) {
4544 case QAbstractSocket::RemoteHostClosedError:
4546 case QAbstractSocket::HostNotFoundError:
4547 QMessageBox::information(NULL, vymName +" Network client",
4548 "The host was not found. Please check the "
4549 "host name and port settings.");
4551 case QAbstractSocket::ConnectionRefusedError:
4552 QMessageBox::information(NULL, vymName + " Network client",
4553 "The connection was refused by the peer. "
4554 "Make sure the fortune server is running, "
4555 "and check that the host name and port "
4556 "settings are correct.");
4559 QMessageBox::information(NULL, vymName + " Network client",
4560 QString("The following error occurred: %1.")
4561 .arg(clientSocket->errorString()));
4565 /* FIXME-3 Playing with DBUS...
4566 QDBusVariant VymModel::query (const QString &query)
4568 TreeItem *selti=getSelectedItem();
4570 return QDBusVariant (selti->getHeading());
4572 return QDBusVariant ("Nothing selected.");
4576 void VymModel::testslot() //FIXME-3
4578 cout << "VM::testslot called\n";
4581 void VymModel::selectMapSelectionColor()
4583 QColor col = QColorDialog::getColor( defLinkColor, NULL);
4584 setSelectionColor (col);
4587 void VymModel::setSelectionColorInt (QColor col)
4589 if ( !col.isValid() ) return;
4591 QString("setSelectionColor (%1)").arg(mapEditor->getSelectionColor().name()),
4592 QString("setSelectionColor (%1)").arg(col.name()),
4593 QString("Set color of selection box to %1").arg(col.name())
4596 mapEditor->setSelectionColor (col);
4600 void VymModel::changeSelection (const QItemSelection &newsel,const QItemSelection &oldsel)
4602 cout << "VymModel::changeSelection (";
4603 if (!newsel.indexes().isEmpty() )
4604 cout << getItem(newsel.indexes().first() )->getHeading().toStdString();
4606 if (!oldsel.indexes().isEmpty() )
4607 cout << getItem(oldsel.indexes().first() )->getHeading().toStdString();
4612 void VymModel::updateSelection (const QItemSelection &newsel,const QItemSelection &oldsel) //FIXME-4 connected but not used so far
4616 void VymModel::emitSelectionChanged(const QItemSelection &newsel)
4618 emit (selectionChanged(newsel,newsel)); // needed e.g. to update geometry in editor
4619 emitShowSelection();
4623 void VymModel::emitSelectionChanged()
4625 QItemSelection newsel=selModel->selection();
4626 emitSelectionChanged (newsel);
4629 void VymModel::setSelectionColor(QColor col)
4631 if ( !col.isValid() ) return;
4633 QString("setSelectionColor (%1)").arg(mapEditor->getSelectionColor().name()),
4634 QString("setSelectionColor (%1)").arg(col.name()),
4635 QString("Set color of selection box to %1").arg(col.name())
4637 setSelectionColorInt (col);
4640 QColor VymModel::getSelectionColor()
4642 return mapEditor->getSelectionColor();
4645 void VymModel::setHideTmpMode (TreeItem::HideTmpMode mode)
4648 for (int i=0;i<rootItem->childCount();i++)
4649 rootItem->child(i)->setHideTmp (mode);
4651 // FIXME-3 needed? scene()->update();
4654 //////////////////////////////////////////////
4655 // Selection related
4656 //////////////////////////////////////////////
4658 void VymModel::setSelectionModel (QItemSelectionModel *sm)
4663 QItemSelectionModel* VymModel::getSelectionModel()
4668 void VymModel::setSelectionBlocked (bool b)
4673 bool VymModel::isSelectionBlocked()
4675 return selectionBlocked;
4678 bool VymModel::select ()
4680 return select (selModel->selectedIndexes().first()); // TODO no multiselections yet
4683 bool VymModel::select (const QString &s)
4690 TreeItem *ti=findBySelectString(s);
4691 if (ti) return select (index(ti));
4695 bool VymModel::select (LinkableMapObj *lmo)
4697 QItemSelection oldsel=selModel->selection();
4700 return select (index (lmo->getTreeItem()) );
4705 bool VymModel::select (TreeItem *ti)
4707 if (ti) return select (index(ti));
4711 bool VymModel::select (const QModelIndex &index)
4713 if (index.isValid() )
4715 selModel->select (index,QItemSelectionModel::ClearAndSelect );
4716 BranchItem *bi=getSelectedBranch();
4717 if (bi) bi->setLastSelectedBranch();
4723 void VymModel::unselect()
4725 lastSelectString=getSelectString();
4726 selModel->clearSelection();
4729 bool VymModel::reselect()
4731 return select (lastSelectString);
4734 void VymModel::emitShowSelection()
4736 if (!blockReposition)
4737 emit (showSelection() );
4740 void VymModel::emitNoteHasChanged (TreeItem *ti)
4742 QModelIndex ix=index(ti);
4743 emit (noteHasChanged (ix) );
4746 void VymModel::emitDataHasChanged (TreeItem *ti)
4748 QModelIndex ix=index(ti);
4749 emit (dataChanged (ix,ix) );
4753 //bool VymModel::selectInt (LinkableMapObj *lmo) // FIXME-3 still needed?
4756 if (selection.select(lmo))
4758 //emitSelectionChanged();
4762 bool VymModel::selectInt (TreeItem *ti)
4764 if (selection.select(lmo))
4766 //emitSelectionChanged();
4771 bool VymModel::selectFirstBranch()
4773 TreeItem *ti=getSelectedBranch();
4776 TreeItem *par=ti->parent();
4779 TreeItem *ti2=par->getFirstBranch();
4780 if (ti2) return select(ti2);
4786 bool VymModel::selectLastBranch()
4788 TreeItem *ti=getSelectedBranch();
4791 TreeItem *par=ti->parent();
4794 TreeItem *ti2=par->getLastBranch();
4795 if (ti2) return select(ti2);
4801 bool VymModel::selectLastSelectedBranch()
4803 BranchItem *bi=getSelectedBranch();
4806 bi=bi->getLastSelectedBranch();
4807 if (bi) return select (bi);
4812 bool VymModel::selectParent()
4814 TreeItem *ti=getSelectedItem();
4825 TreeItem::Type VymModel::selectionType()
4827 QModelIndexList list=selModel->selectedIndexes();
4828 if (list.isEmpty()) return TreeItem::Undefined;
4829 TreeItem *ti = getItem (list.first() );
4830 return ti->getType();
4834 LinkableMapObj* VymModel::getSelectedLMO()
4836 QModelIndexList list=selModel->selectedIndexes();
4837 if (!list.isEmpty() )
4839 TreeItem *ti = getItem (list.first() );
4840 TreeItem::Type type=ti->getType();
4841 if (type ==TreeItem::Branch || type==TreeItem::MapCenter || type==TreeItem::Image)
4842 return ((MapItem*)ti)->getLMO();
4847 BranchObj* VymModel::getSelectedBranchObj() // FIXME-3 this should not be needed in the end!!!
4849 TreeItem *ti = getSelectedBranch();
4851 return (BranchObj*)( ((MapItem*)ti)->getLMO());
4856 BranchItem* VymModel::getSelectedBranch()
4858 QModelIndexList list=selModel->selectedIndexes();
4859 if (!list.isEmpty() )
4861 TreeItem *ti = getItem (list.first() );
4862 TreeItem::Type type=ti->getType();
4863 if (type ==TreeItem::Branch || type==TreeItem::MapCenter)
4864 return (BranchItem*)ti;
4869 ImageItem* VymModel::getSelectedImage()
4871 QModelIndexList list=selModel->selectedIndexes();
4872 if (!list.isEmpty())
4874 TreeItem *ti=getItem (list.first());
4875 if (ti && ti->getType()==TreeItem::Image)
4876 return (ImageItem*)ti;
4881 AttributeItem* VymModel::getSelectedAttribute()
4883 QModelIndexList list=selModel->selectedIndexes();
4884 if (!list.isEmpty() )
4886 TreeItem *ti = getItem (list.first() );
4887 TreeItem::Type type=ti->getType();
4888 if (type ==TreeItem::Attribute)
4889 return (AttributeItem*)ti;
4894 TreeItem* VymModel::getSelectedItem()
4896 QModelIndexList list=selModel->selectedIndexes();
4897 if (!list.isEmpty() )
4898 return getItem (list.first() );
4903 QModelIndex VymModel::getSelectedIndex()
4905 QModelIndexList list=selModel->selectedIndexes();
4906 if (list.isEmpty() )
4907 return QModelIndex();
4909 return list.first();
4912 QString VymModel::getSelectString ()
4914 return getSelectString (getSelectedItem());
4917 QString VymModel::getSelectString (LinkableMapObj *lmo) // FIXME-2 VM needs to use TreeModel. Port all calls to this funtion to the one using TreeItem below...
4919 if (!lmo) return QString();
4920 return getSelectString (lmo->getTreeItem() );
4923 QString VymModel::getSelectString (TreeItem *ti) //FIXME-1 does not return "mc:"
4927 switch (ti->getType())
4929 case TreeItem::MapCenter: s="mc:"; break;
4930 case TreeItem::Branch: s="bo:";break;
4931 case TreeItem::Image: s="fi:";break;
4932 case TreeItem::Attribute: s="ai:";break;
4935 s= s + QString("%1").arg(ti->num());
4937 // call myself recursively
4938 s= getSelectString(ti->parent()) +","+s;