autosave fix
authorinsilmaril
Wed, 27 Feb 2008 16:09:06 +0000
changeset 6763dabc6424d73
parent 675 e524edc45aff
child 677 3472b93efb0c
autosave fix
demos/vym-projectplan.vym
mainwindow.cpp
mapeditor.cpp
mapeditor.h
version.h
vym.pro
vymmodel.cpp
xml-vym.cpp
     1.1 Binary file demos/vym-projectplan.vym has changed
     2.1 --- a/mainwindow.cpp	Wed Feb 27 16:09:06 2008 +0000
     2.2 +++ b/mainwindow.cpp	Wed Feb 27 16:09:06 2008 +0000
     2.3 @@ -1469,18 +1469,15 @@
     2.4      a = new QAction( "Test function 1" , this);
     2.5      a->setStatusTip( "Call test function 1" );
     2.6  	testMenu->addAction (a);
     2.7 -	//a->setShortcut (Qt::Key_F4 );
     2.8      connect( a, SIGNAL( triggered() ), this, SLOT( testFunction1() ) );
     2.9  
    2.10      a = new QAction( "Test function 2" , this);
    2.11      a->setStatusTip( "Call test function 2" );
    2.12 -	//a->setShortcut (Qt::Key_F4 );
    2.13  	testMenu->addAction (a);
    2.14      connect( a, SIGNAL( triggered() ), this, SLOT( testFunction2() ) );
    2.15  
    2.16      a = new QAction( "Command" , this);
    2.17      a->setStatusTip( "Enter command to call in editor" );
    2.18 -	//a->setShortcut (Qt::Key_F5 );
    2.19      connect( a, SIGNAL( triggered() ), this, SLOT( testCommand() ) );
    2.20  	testMenu->addAction (a);
    2.21  }
    2.22 @@ -1835,70 +1832,14 @@
    2.23  		tabWidget->showPage(me);
    2.24  		me->viewport()->setFocus();
    2.25  
    2.26 -		// Create temporary directory for packing
    2.27 -		bool ok;
    2.28 -		QString tmpZipDir=makeTmpDir (ok,"vym-pack");
    2.29 -		if (!ok)
    2.30 -		{
    2.31 -			QMessageBox::critical( 0, tr( "Critical Load Error" ),
    2.32 -			   tr("Couldn't create temporary directory before load\n"));
    2.33 -			return aborted; 
    2.34 -		}
    2.35 -
    2.36 -		// Try to unzip file
    2.37 -		err=unzipDir (tmpZipDir,fn);
    2.38 -		if (err==nozip)
    2.39 -		{
    2.40 -			mapfile=fn;
    2.41 -			me->setZipped(false);
    2.42 -		} else
    2.43 -		{
    2.44 -			me->setZipped(true);
    2.45 -			
    2.46 -			// Look for mapname.xml
    2.47 -			mapfile= fn.left(fn.findRev(".",-1,true));
    2.48 -			mapfile=mapfile.section( '/', -1 );
    2.49 -			QFile file( tmpZipDir + "/" + mapfile + ".xml");
    2.50 -			if (!file.exists() )
    2.51 -			{
    2.52 -				// mapname.xml does not exist, well, 
    2.53 -				// maybe someone renamed the mapname.vym file...
    2.54 -				// Try to find any .xml in the toplevel 
    2.55 -				// directory of the .vym file
    2.56 -				QStringList flist=QDir (tmpZipDir).entryList("*.xml");
    2.57 -				if (flist.count()==1) 
    2.58 -				{
    2.59 -					// Only one entry, take this one
    2.60 -					mapfile=tmpZipDir + "/"+flist.first();
    2.61 -				} else
    2.62 -				{
    2.63 -					for ( QStringList::Iterator it = flist.begin(); it != flist.end(); ++it ) 
    2.64 -						*it=tmpZipDir + "/" + *it;
    2.65 -					// TODO Multiple entries, load all (but only the first one into this ME)
    2.66 -					//mainWindow->fileLoadFromTmp (flist);
    2.67 -					//returnCode=1;	// Silently forget this attempt to load
    2.68 -					qWarning ("MainWindow::load (fn)  multimap found...");
    2.69 -				}	
    2.70 -					
    2.71 -				if (flist.isEmpty() )
    2.72 -				{
    2.73 -					QMessageBox::critical( 0, tr( "Critical Load Error" ),
    2.74 -							   tr("Couldn't find a map (*.xml) in .vym archive.\n"));
    2.75 -					err=aborted;				   
    2.76 -				}	
    2.77 -			} //file doesn't exist	
    2.78 -			else
    2.79 -				mapfile=file.name();
    2.80 -		}
    2.81 -
    2.82  		if (err!=aborted)
    2.83  		{
    2.84  			// Save existing filename in case  we import
    2.85  			QString fn_org=me->getFilePath();
    2.86  
    2.87  			// Finally load map into mapEditor
    2.88 -			me->setFilePath (mapfile,fn);
    2.89 -			err=me->load(mapfile,lmode,ftype);
    2.90 +			me->setFilePath (fn);
    2.91 +			err=me->load(fn,lmode,ftype);
    2.92  
    2.93  			// Restore old (maybe empty) filepath, if this is an import
    2.94  			if (lmode!=NewMap)
    2.95 @@ -1926,9 +1867,6 @@
    2.96  			}	
    2.97  			statusBar()->message( "Loaded " + fn, statusbarTime );
    2.98  		}	
    2.99 -
   2.100 -		// Delete tmpDir
   2.101 -		removeDir (QDir(tmpZipDir));
   2.102  	}
   2.103  	return err;
   2.104  }
   2.105 @@ -2000,125 +1938,133 @@
   2.106  
   2.107  void Main::fileSave(MapEditor *me, const SaveMode &savemode)
   2.108  {
   2.109 +	/* FIXME moved to ME
   2.110 +	// Error codes
   2.111 +	ErrorCode err=success;
   2.112 +
   2.113 +	QString safeFilePath;
   2.114 +
   2.115 +	if (!me) return;
   2.116 +	bool saveZipped=me->saveZipped();
   2.117 +
   2.118  	// tmp dir for zipping 
   2.119  	QString tmpZipDir;
   2.120  	
   2.121 -	// Error codes
   2.122 -	ErrorCode err=success;
   2.123 +	*/
   2.124  	
   2.125 -	QString safeFilePath;
   2.126 -
   2.127 -	bool saveZipped=me->saveZipped();
   2.128 -
   2.129 -	if (me)
   2.130 -	{
   2.131 -		QString fn=me->getFilePath();
   2.132 -		// filename=unnamed, filepath="" in constructor of mapEditor
   2.133 -		if ( !fn.isEmpty() ) 
   2.134 -		{	
   2.135 -			// We have a filepath, go on saving			
   2.136 -
   2.137 -			// Look, if we should zip the data:
   2.138 -			if (!saveZipped)
   2.139 +
   2.140 +	if (!me) return;
   2.141 +
   2.142 +	// filename=unnamed, filepath="" in constructor of mapEditor
   2.143 +
   2.144 +	/* FIXME moved to ME
   2.145 +	if ( !fn.isEmpty() ) 
   2.146 +	{	
   2.147 +		// We have a filepath, go on saving			
   2.148 +
   2.149 +		// Look, if we should zip the data:
   2.150 +		if (!saveZipped)
   2.151 +		{
   2.152 +			QMessageBox mb( vymName,
   2.153 +				tr("The map %1\ndid not use the compressed "
   2.154 +				"vym file format.\nWriting it uncompressed will also write images \n"
   2.155 +				"and flags and thus may overwrite files in the "
   2.156 +				"given directory\n\nDo you want to write the map").arg(fn),
   2.157 +				QMessageBox::Warning,
   2.158 +				QMessageBox::Yes | QMessageBox::Default,
   2.159 +				QMessageBox::No ,
   2.160 +				QMessageBox::Cancel | QMessageBox::Escape);
   2.161 +			mb.setButtonText( QMessageBox::Yes, tr("compressed (vym default)") );
   2.162 +			mb.setButtonText( QMessageBox::No, tr("uncompressed") );
   2.163 +			mb.setButtonText( QMessageBox::Cancel, tr("Cancel"));
   2.164 +			switch( mb.exec() ) 
   2.165  			{
   2.166 -				QMessageBox mb( vymName,
   2.167 -					tr("The map %1\ndid not use the compressed "
   2.168 -					"vym file format.\nWriting it uncompressed will also write images \n"
   2.169 -					"and flags and thus may overwrite files in the "
   2.170 -					"given directory\n\nDo you want to write the map").arg(fn),
   2.171 -					QMessageBox::Warning,
   2.172 -					QMessageBox::Yes | QMessageBox::Default,
   2.173 -					QMessageBox::No ,
   2.174 -					QMessageBox::Cancel | QMessageBox::Escape);
   2.175 -				mb.setButtonText( QMessageBox::Yes, tr("compressed (vym default)") );
   2.176 -				mb.setButtonText( QMessageBox::No, tr("uncompressed") );
   2.177 -				mb.setButtonText( QMessageBox::Cancel, tr("Cancel"));
   2.178 -				switch( mb.exec() ) 
   2.179 +				case QMessageBox::Yes:
   2.180 +					// save compressed (default file format)
   2.181 +					saveZipped=true;
   2.182 +					break;
   2.183 +				case QMessageBox::No:
   2.184 +					// save uncompressed
   2.185 +					saveZipped=false;
   2.186 +					break;
   2.187 +				case QMessageBox::Cancel:
   2.188 +					// do nothing
   2.189 +					return;
   2.190 +					break;
   2.191 +			}
   2.192 +			me->setZipped (saveZipped);
   2.193 +		}
   2.194 +
   2.195 +		// First backup existing file, we 
   2.196 +		// don't want to add to old zip archives
   2.197 +		QFile f(fn);
   2.198 +		if (f.exists())
   2.199 +		{
   2.200 +			if (actionSettingsWriteBackupFile->isOn())
   2.201 +			{
   2.202 +				QString bfn(fn + "~");
   2.203 +				QFile bf(bfn);
   2.204 +				if (bf.exists() && !bf.remove())
   2.205  				{
   2.206 -					case QMessageBox::Yes:
   2.207 -						// save compressed (default file format)
   2.208 -						saveZipped=true;
   2.209 -						break;
   2.210 -					case QMessageBox::No:
   2.211 -						// save uncompressed
   2.212 -						saveZipped=false;
   2.213 -						break;
   2.214 -					case QMessageBox::Cancel:
   2.215 -						// do nothing
   2.216 -						return;
   2.217 -						break;
   2.218 +					QMessageBox::warning(0, tr("Save Error"),
   2.219 +										 bfn + tr("\ncould not be removed before saving"));
   2.220  				}
   2.221 -				me->setZipped (saveZipped);
   2.222 +				else if (!f.rename(bfn))
   2.223 +				{
   2.224 +					QMessageBox::warning(0, tr("Save Error"),
   2.225 +										 fn + tr("\ncould not be renamed before saving"));
   2.226 +				}
   2.227  			}
   2.228 -
   2.229 -			// First backup existing file, we 
   2.230 -			// don't want to add to old zip archives
   2.231 -			QFile f(fn);
   2.232 -			if (f.exists())
   2.233 -            {
   2.234 -				if (actionSettingsWriteBackupFile->isOn())
   2.235 -				{
   2.236 -					QString bfn(fn + "~");
   2.237 -					QFile bf(bfn);
   2.238 -					if (bf.exists() && !bf.remove())
   2.239 -					{
   2.240 -						QMessageBox::warning(0, tr("Save Error"),
   2.241 -											 bfn + tr("\ncould not be removed before saving"));
   2.242 -					}
   2.243 -					else if (!f.rename(bfn))
   2.244 -					{
   2.245 -						QMessageBox::warning(0, tr("Save Error"),
   2.246 -											 fn + tr("\ncould not be renamed before saving"));
   2.247 -					}
   2.248 -				}
   2.249 -            }
   2.250 -
   2.251 -			if (saveZipped)
   2.252 +		}
   2.253 +
   2.254 +		if (saveZipped)
   2.255 +		{
   2.256 +			// Create temporary directory for packing
   2.257 +			bool ok;
   2.258 +			tmpZipDir=makeTmpDir (ok,"vym-zip");
   2.259 +			if (!ok)
   2.260  			{
   2.261 -				// Create temporary directory for packing
   2.262 -				bool ok;
   2.263 -				tmpZipDir=makeTmpDir (ok,"vym-zip");
   2.264 -				if (!ok)
   2.265 -				{
   2.266 -					QMessageBox::critical( 0, tr( "Critical Load Error" ),
   2.267 -					   tr("Couldn't create temporary directory before save\n"));
   2.268 -					return; 
   2.269 -				}
   2.270 -
   2.271 -				safeFilePath=me->getFilePath();
   2.272 -				me->setFilePath (tmpZipDir+"/"+
   2.273 -					me->getMapName()+ ".xml",
   2.274 -					safeFilePath);
   2.275 -				me->save (savemode);
   2.276 -				me->setFilePath (safeFilePath);
   2.277 -				
   2.278 -				zipDir (tmpZipDir,fn);
   2.279 -			} // save zipped
   2.280 -			else
   2.281 -			{
   2.282 -				// Save unzipped. 
   2.283 -				safeFilePath=me->getFilePath();
   2.284 -				me->setFilePath (fn, safeFilePath);
   2.285 -				me->save (savemode);
   2.286 -				me->setFilePath (safeFilePath);
   2.287 -			} // save zipped 	
   2.288 -		} // filepath available
   2.289 +				QMessageBox::critical( 0, tr( "Critical Load Error" ),
   2.290 +				   tr("Couldn't create temporary directory before save\n"));
   2.291 +				return; 
   2.292 +			}
   2.293 +
   2.294 +			safeFilePath=me->getFilePath();
   2.295 +			me->setFilePath (tmpZipDir+"/"+
   2.296 +				me->getMapName()+ ".xml",
   2.297 +				safeFilePath);
   2.298 +			me->save (savemode);
   2.299 +			me->setFilePath (safeFilePath);
   2.300 +			
   2.301 +			zipDir (tmpZipDir,fn);
   2.302 +		} // save zipped
   2.303  		else
   2.304  		{
   2.305 -			// We have  no filepath yet,
   2.306 -			// call fileSaveAs() now, this will call fileSave() 
   2.307 -			// again.
   2.308 -			// First switch to editor
   2.309 -			tabWidget->setCurrentWidget (me);
   2.310 -			fileSaveAs(savemode);
   2.311 -		}
   2.312 -    }
   2.313 -
   2.314 +			// Save unzipped. 
   2.315 +			safeFilePath=me->getFilePath();
   2.316 +			me->setFilePath (fn, safeFilePath);
   2.317 +			me->save (savemode);
   2.318 +			me->setFilePath (safeFilePath);
   2.319 +		} // save zipped 	
   2.320 +	} // filepath available
   2.321 +	else
   2.322 +	*/
   2.323 +	if ( me->getFilePath().isEmpty() ) 
   2.324 +	{
   2.325 +		// We have  no filepath yet,
   2.326 +		// call fileSaveAs() now, this will call fileSave() 
   2.327 +		// again.
   2.328 +		// First switch to editor
   2.329 +		tabWidget->setCurrentWidget (me);
   2.330 +		fileSaveAs(savemode);
   2.331 +	}
   2.332 +
   2.333 +/* FIXME moved to ME
   2.334  	if (saveZipped && !tmpZipDir.isEmpty())
   2.335  		// Delete tmpDir
   2.336  		removeDir (QDir(tmpZipDir));
   2.337 -
   2.338 -	if (err==success)
   2.339 +*/
   2.340 +	if (me->save (savemode)==success)
   2.341  	{
   2.342  		statusBar()->message( 
   2.343  			tr("Saved  %1").arg(me->getFilePath()), 
   2.344 @@ -3438,9 +3384,7 @@
   2.345  		tr("QInputDialog::getInteger()"),
   2.346  	    tr("Number of seconds before autosave:"), settings.value("/mapeditor/autosave/ms").toInt() / 1000, 10, 10000, 1, &ok);
   2.347  	if (ok)
   2.348 -	{
   2.349  		settings.setValue ("/mapeditor/autosave/ms",i * 1000);
   2.350 -    }	
   2.351  }
   2.352  
   2.353  void Main::settingsWriteBackupFileToggle()
   2.354 @@ -3801,8 +3745,8 @@
   2.355  void Main::testFunction1()
   2.356  {
   2.357  	if (!currentMapEditor()) return;
   2.358 -	currentMapEditor()->testFunction1();
   2.359 -	//editAttribute();
   2.360 +	//currentMapEditor()->testFunction1();
   2.361 +	editAttribute();
   2.362  }
   2.363  
   2.364  void Main::testFunction2()
     3.1 --- a/mapeditor.cpp	Wed Feb 27 16:09:06 2008 +0000
     3.2 +++ b/mapeditor.cpp	Wed Feb 27 16:09:06 2008 +0000
     3.3 @@ -145,6 +145,10 @@
     3.4  	autosaveTimer=new QTimer (this);
     3.5  	connect(autosaveTimer, SIGNAL(timeout()), this, SLOT(autosave()));
     3.6  
     3.7 +	fileChangedTimer=new QTimer (this);
     3.8 +	fileChangedTimer->start(3000);
     3.9 +	connect(fileChangedTimer, SIGNAL(timeout()), this, SLOT(fileChanged()));
    3.10 +
    3.11  	// Network
    3.12  	netstate=Offline;
    3.13  
    3.14 @@ -185,6 +189,7 @@
    3.15  {
    3.16  	//cout <<"Destructor MapEditor\n";
    3.17  	autosaveTimer->stop();
    3.18 +	fileChangedTimer->stop();
    3.19  
    3.20  	// tmpMapDir is in tmpVymDir, so it gets removed automagically when vym closes
    3.21  	
    3.22 @@ -1498,7 +1503,7 @@
    3.23  	{
    3.24  		filePath=fpath;		// becomes absolute path
    3.25  		fileName=fpath;		// gets stripped of path
    3.26 -		destPath=destname;	// needed for vymlinks
    3.27 +		destPath=destname;	// needed for vymlinks and during load to reset fileChangedTime
    3.28  
    3.29  		// If fpath is not an absolute path, complete it
    3.30  		filePath=QDir(fpath).absPath();
    3.31 @@ -1543,7 +1548,8 @@
    3.32  	ErrorCode err=success;
    3.33  
    3.34  	parseBaseHandler *handler;
    3.35 -	switch (ftype)
    3.36 +	fileType=ftype;
    3.37 +	switch (fileType)
    3.38  	{
    3.39  		case VymMap: handler=new parseVYMHandler; break;
    3.40  		case FreemindMap : handler=new parseFreemindHandler; break;
    3.41 @@ -1575,14 +1581,72 @@
    3.42  				QString("Add map %1 to %2").arg(fname).arg(getName(bo)));
    3.43  	}	
    3.44      
    3.45 -	QFile file( fname );
    3.46 +
    3.47 +	// Create temporary directory for packing
    3.48 +	bool ok;
    3.49 +	QString tmpZipDir=makeTmpDir (ok,"vym-pack");
    3.50 +	if (!ok)
    3.51 +	{
    3.52 +		QMessageBox::critical( 0, tr( "Critical Load Error" ),
    3.53 +		   tr("Couldn't create temporary directory before load\n"));
    3.54 +		return aborted; 
    3.55 +	}
    3.56 +
    3.57 +	// Try to unzip file
    3.58 +	err=unzipDir (tmpZipDir,fname);
    3.59 +	QString xmlfile;
    3.60 +	if (err==nozip)
    3.61 +	{
    3.62 +		xmlfile=fname;
    3.63 +		zipped=false;
    3.64 +	} else
    3.65 +	{
    3.66 +		zipped=true;
    3.67 +		
    3.68 +		// Look for mapname.xml
    3.69 +		xmlfile= fname.left(fname.findRev(".",-1,true));
    3.70 +		xmlfile=xmlfile.section( '/', -1 );
    3.71 +		QFile mfile( tmpZipDir + "/" + xmlfile + ".xml");
    3.72 +		if (!mfile.exists() )
    3.73 +		{
    3.74 +			// mapname.xml does not exist, well, 
    3.75 +			// maybe someone renamed the mapname.vym file...
    3.76 +			// Try to find any .xml in the toplevel 
    3.77 +			// directory of the .vym file
    3.78 +			QStringList flist=QDir (tmpZipDir).entryList("*.xml");
    3.79 +			if (flist.count()==1) 
    3.80 +			{
    3.81 +				// Only one entry, take this one
    3.82 +				xmlfile=tmpZipDir + "/"+flist.first();
    3.83 +			} else
    3.84 +			{
    3.85 +				for ( QStringList::Iterator it = flist.begin(); it != flist.end(); ++it ) 
    3.86 +					*it=tmpZipDir + "/" + *it;
    3.87 +				// TODO Multiple entries, load all (but only the first one into this ME)
    3.88 +				//mainWindow->fileLoadFromTmp (flist);
    3.89 +				//returnCode=1;	// Silently forget this attempt to load
    3.90 +				qWarning ("MainWindow::load (fn)  multimap found...");
    3.91 +			}	
    3.92 +				
    3.93 +			if (flist.isEmpty() )
    3.94 +			{
    3.95 +				QMessageBox::critical( 0, tr( "Critical Load Error" ),
    3.96 +						   tr("Couldn't find a map (*.xml) in .vym archive.\n"));
    3.97 +				err=aborted;				   
    3.98 +			}	
    3.99 +		} //file doesn't exist	
   3.100 +		else
   3.101 +			xmlfile=mfile.name();
   3.102 +	}
   3.103 +
   3.104 +	QFile file( xmlfile);
   3.105  
   3.106  	// I am paranoid: file should exist anyway
   3.107  	// according to check in mainwindow.
   3.108  	if (!file.exists() )
   3.109  	{
   3.110  		QMessageBox::critical( 0, tr( "Critical Parse Error" ),
   3.111 -				   tr("Couldn't open map " +fname)+".");
   3.112 +				   tr(QString("Couldn't open map %1").arg(file.name())));
   3.113  		err=aborted;	
   3.114  	} else
   3.115  	{
   3.116 @@ -1607,7 +1671,7 @@
   3.117  		file.close();
   3.118  		if ( ok ) 
   3.119  		{
   3.120 -			model->reposition();
   3.121 +			model->reposition();	// FIXME reposition the view instead...
   3.122  			xelection.update();
   3.123  			if (lmode==NewMap)
   3.124  			{
   3.125 @@ -1616,6 +1680,9 @@
   3.126  				mapUnsaved=false;
   3.127  				autosaveTimer->stop();
   3.128  			}
   3.129 +
   3.130 +			// Reset timestamp to check for later updates of file
   3.131 +			fileChangedTime=QFileInfo (destPath).lastModified();
   3.132  		} else 
   3.133  		{
   3.134  			QMessageBox::critical( 0, tr( "Critical Parse Error" ),
   3.135 @@ -1625,22 +1692,102 @@
   3.136  			// partially read by the parser
   3.137  		}	
   3.138  	}	
   3.139 +
   3.140 +	// Delete tmpDir
   3.141 +	removeDir (QDir(tmpZipDir));
   3.142 +
   3.143  	updateActions();
   3.144  	return err;
   3.145  }
   3.146  
   3.147 -int MapEditor::save (const SaveMode &savemode)
   3.148 -{
   3.149 +ErrorCode MapEditor::save (const SaveMode &savemode)
   3.150 +{
   3.151 +	cout <<"ME::save zipped="<<zipped<<endl;
   3.152  	// Create mapName and fileDir
   3.153  	makeSubDirs (fileDir);
   3.154 -	QString fname;
   3.155 -	if (saveZipped())
   3.156 +	QString tmpZipDir;
   3.157 +	QString mapFileName;
   3.158 +	QString safeFilePath;
   3.159 +
   3.160 +	ErrorCode err=success;
   3.161 +
   3.162 +	if (zipped)
   3.163  		// save as .xml
   3.164 -		fname=mapName+".xml";
   3.165 +		mapFileName=mapName+".xml";
   3.166  	else
   3.167  		// use name given by user, even if he chooses .doc
   3.168 -		fname=fileName;
   3.169 -
   3.170 +		mapFileName=fileName;
   3.171 +
   3.172 +	// Look, if we should zip the data:
   3.173 +	if (!zipped)
   3.174 +	{
   3.175 +		QMessageBox mb( vymName,
   3.176 +			tr("The map %1\ndid not use the compressed "
   3.177 +			"vym file format.\nWriting it uncompressed will also write images \n"
   3.178 +			"and flags and thus may overwrite files in the "
   3.179 +			"given directory\n\nDo you want to write the map").arg(filePath),
   3.180 +			QMessageBox::Warning,
   3.181 +			QMessageBox::Yes | QMessageBox::Default,
   3.182 +			QMessageBox::No ,
   3.183 +			QMessageBox::Cancel | QMessageBox::Escape);
   3.184 +		mb.setButtonText( QMessageBox::Yes, tr("compressed (vym default)") );
   3.185 +		mb.setButtonText( QMessageBox::No, tr("uncompressed") );
   3.186 +		mb.setButtonText( QMessageBox::Cancel, tr("Cancel"));
   3.187 +		switch( mb.exec() ) 
   3.188 +		{
   3.189 +			case QMessageBox::Yes:
   3.190 +				// save compressed (default file format)
   3.191 +				zipped=true;
   3.192 +				break;
   3.193 +			case QMessageBox::No:
   3.194 +				// save uncompressed
   3.195 +				zipped=false;
   3.196 +				break;
   3.197 +			case QMessageBox::Cancel:
   3.198 +				// do nothing
   3.199 +				return aborted;
   3.200 +				break;
   3.201 +		}
   3.202 +	}
   3.203 +
   3.204 +	// First backup existing file, we 
   3.205 +	// don't want to add to old zip archives
   3.206 +	QFile f(destPath);
   3.207 +	if (f.exists())
   3.208 +	{
   3.209 +		if ( settings.value ("/mapeditor/writeBackupFile").toBool())
   3.210 +		{
   3.211 +			cout << "ME::doing backup...\n";//FIXME
   3.212 +			QString backupFileName(destPath + "~");
   3.213 +			QFile backupFile(backupFileName);
   3.214 +			if (backupFile.exists() && !backupFile.remove())
   3.215 +			{
   3.216 +				QMessageBox::warning(0, tr("Save Error"),
   3.217 +									 tr("%1\ncould not be removed before saving").arg(backupFileName));
   3.218 +			}
   3.219 +			else if (!f.rename(backupFileName))
   3.220 +			{
   3.221 +				QMessageBox::warning(0, tr("Save Error"),
   3.222 +									 tr("%1\ncould not be renamed before saving").arg(destPath));
   3.223 +			}
   3.224 +		}
   3.225 +	}
   3.226 +
   3.227 +	if (zipped)
   3.228 +	{
   3.229 +		// Create temporary directory for packing
   3.230 +		bool ok;
   3.231 +		tmpZipDir=makeTmpDir (ok,"vym-zip");
   3.232 +		if (!ok)
   3.233 +		{
   3.234 +			QMessageBox::critical( 0, tr( "Critical Load Error" ),
   3.235 +			   tr("Couldn't create temporary directory before save\n"));
   3.236 +			return aborted; 
   3.237 +		}
   3.238 +
   3.239 +		safeFilePath=filePath;
   3.240 +		setFilePath (tmpZipDir+"/"+ mapName+ ".xml", safeFilePath);
   3.241 +	} // zipped
   3.242  
   3.243  	QString saveFile;
   3.244  	if (savemode==CompleteMap || xelection.isEmpty())
   3.245 @@ -1661,11 +1808,27 @@
   3.246  		// TODO take care of multiselections
   3.247  	}	
   3.248  
   3.249 -	if (!saveStringToDisk(fileDir+fname,saveFile))
   3.250 -		return 1;
   3.251 +	if (!saveStringToDisk(fileDir+mapFileName,saveFile))
   3.252 +	{
   3.253 +		err=aborted;
   3.254 +		qWarning ("ME::saveStringToDisk failed!");
   3.255 +	}
   3.256 +
   3.257 +	if (zipped)
   3.258 +	{
   3.259 +		// zip
   3.260 +		if (err==success) err=zipDir (tmpZipDir,destPath);
   3.261 +
   3.262 +		// Delete tmpDir
   3.263 +		removeDir (QDir(tmpZipDir));
   3.264 +
   3.265 +		// Restore original filepath outside of tmp zip dir
   3.266 +		setFilePath (safeFilePath);
   3.267 +	}
   3.268  
   3.269  	updateActions();
   3.270 -	return 0;
   3.271 +	fileChangedTime=QFileInfo (destPath).lastModified();
   3.272 +	return err;
   3.273  }
   3.274  
   3.275  void MapEditor::setZipped (bool z)
   3.276 @@ -3937,7 +4100,7 @@
   3.277  				{
   3.278  					case QMessageBox::Yes:
   3.279  						// save 
   3.280 -						break;;
   3.281 +						break;
   3.282  					case QMessageBox::Cancel:
   3.283  						// do nothing
   3.284  						delete (fd);
   3.285 @@ -5046,13 +5209,65 @@
   3.286  
   3.287  void MapEditor::autosave()
   3.288  {
   3.289 +	QDateTime now=QDateTime().currentDateTime();
   3.290 +	/* FIXME debug
   3.291 +	*/
   3.292 +	cout << "ME::autosave checking "<<qPrintable(filePath)<<"...\n"; 
   3.293 +	cout << "fsaved: "<<qPrintable (fileChangedTime.toString())<<endl;
   3.294 +	cout << "  fnow: "<<qPrintable (QFileInfo(filePath).lastModified().toString())<<endl;
   3.295 +	cout << "  time: "<<qPrintable (now.toString())<<endl;
   3.296  	// Disable autosave, while we have gone back in history
   3.297  	int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
   3.298  	if (redosAvail>0) return;
   3.299  
   3.300  
   3.301  	if (mapUnsaved &&mapChanged && settings.value ("/mapeditor/autosave/use",true).toBool() )
   3.302 -		mainWindow->fileSave (this);
   3.303 +	{
   3.304 +		if (QFileInfo(filePath).lastModified()<=fileChangedTime) 
   3.305 +			mainWindow->fileSave (this);
   3.306 +		else
   3.307 +			if (debug)
   3.308 +				cout <<"  ME::autosave  rejected, file on disk is newer than last save.\n"; 
   3.309 +
   3.310 +	}	
   3.311 +}
   3.312 +
   3.313 +void MapEditor::fileChanged()
   3.314 +{
   3.315 +	// Check if file on disk has changed meanwhile
   3.316 +	if (!filePath.isEmpty())
   3.317 +	{
   3.318 +		QDateTime tmod=QFileInfo (filePath).lastModified();
   3.319 +		if (tmod>fileChangedTime)
   3.320 +		{
   3.321 +			
   3.322 +			/* FIXME debug message, sometimes there's a glitch in the metrics...
   3.323 +			cout << "ME::fileChanged()\n" 
   3.324 +			     << "  last saved:     "<<qPrintable (fileChangedTime.toString())<<endl
   3.325 +				 << "  last modififed: "<<qPrintable (tmod.toString())<<endl;
   3.326 +			*/	 
   3.327 +			// FIXME switch to current mapeditor and finish lineedits...
   3.328 +			QMessageBox mb( vymName,
   3.329 +				tr("The file of the map  on disk has changed:\n\n"  
   3.330 +				   "   %1\n\nDo you want to reload this map with the new file?").arg(filePath),
   3.331 +				QMessageBox::Question,
   3.332 +				QMessageBox::Yes ,
   3.333 +				QMessageBox::Cancel | QMessageBox::Default,
   3.334 +				QMessageBox::NoButton );
   3.335 +
   3.336 +			mb.setButtonText( QMessageBox::Yes, tr("Reload"));
   3.337 +			mb.setButtonText( QMessageBox::No, tr("Ignore"));
   3.338 +			switch( mb.exec() ) 
   3.339 +			{
   3.340 +				case QMessageBox::Yes:
   3.341 +					// Reload map
   3.342 +					load (filePath,NewMap,fileType);
   3.343 +		        case QMessageBox::Cancel:
   3.344 +					fileChangedTime=tmod; // allow autosave to overwrite newer file!
   3.345 +			}
   3.346 +		}
   3.347 +	}	
   3.348 +
   3.349  }
   3.350  
   3.351  
     4.1 --- a/mapeditor.h	Wed Feb 27 16:09:06 2008 +0000
     4.2 +++ b/mapeditor.h	Wed Feb 27 16:09:06 2008 +0000
     4.3 @@ -164,7 +164,7 @@
     4.4      ErrorCode load (QString, const LoadMode &, const FileType& );	// newmap, import/replace selection
     4.5  public:
     4.6  	/*! \brief Save the map to file */
     4.7 -    int save(const SaveMode &);	
     4.8 +    ErrorCode save(const SaveMode &);	
     4.9  	void setZipped(bool);		//!< Set or unset compression of map with zip save map zipped
    4.10  	bool saveZipped();			//!< True, if file will be saved zipped
    4.11      void print();				//!< Print the map
    4.12 @@ -386,12 +386,15 @@
    4.13  	void displayNetworkError (QAbstractSocket::SocketError);
    4.14  
    4.15  	void autosave ();
    4.16 +	void fileChanged();
    4.17  
    4.18  private:
    4.19  	State state;				// State of MapEditor
    4.20  	QGraphicsScene *mapScene;
    4.21  	VymModel *model;					// Vym Map, includding several mapCenters
    4.22  	QTimer *autosaveTimer;
    4.23 +	QTimer *fileChangedTimer;
    4.24 +	QDateTime fileChangedTime;
    4.25  
    4.26  	bool adjustCanvasRequested;	// collect requests until end of user event
    4.27  	BranchObj *editingBO;		// entering Text into BO
    4.28 @@ -437,6 +440,7 @@
    4.29  
    4.30  	bool zipped;				// should map be zipped
    4.31  	static	int mapNum;			// unique number for Editor
    4.32 +	FileType fileType;			// type of file, e.g. vym, freemind...
    4.33  	QString fileName;			// short name of file (for tab)
    4.34  	QString filePath;			// path to file which will be saved
    4.35  	QString fileDir;			// dir where file is saved
     5.1 --- a/version.h	Wed Feb 27 16:09:06 2008 +0000
     5.2 +++ b/version.h	Wed Feb 27 16:09:06 2008 +0000
     5.3 @@ -4,10 +4,10 @@
     5.4  #include <QString>
     5.5  
     5.6  #define __VYM_NAME "VYM"
     5.7 -#define __VYM_VERSION "1.11.5"
     5.8 +#define __VYM_VERSION "1.11.6"
     5.9  //#define __VYM_CODENAME "Codename: 1.10.0-RC-3"
    5.10  #define __VYM_CODENAME "Codename: development version"
    5.11 -#define __VYM_BUILD_DATE "2008-01-15"
    5.12 +#define __VYM_BUILD_DATE "2008-02-27"
    5.13  
    5.14  
    5.15  bool checkVersion(const QString &);
     6.1 --- a/vym.pro	Wed Feb 27 16:09:06 2008 +0000
     6.2 +++ b/vym.pro	Wed Feb 27 16:09:06 2008 +0000
     6.3 @@ -27,8 +27,9 @@
     6.4  	aboutdialog.h \
     6.5  	animpoint.h \
     6.6  	attribute.h \
     6.7 +	attributedelegate.h\
     6.8 +	attributedialog.h \
     6.9  	attributewidget.h \
    6.10 -	attributedialog.h \
    6.11  	branchobj.h \
    6.12  	branchpropwindow.h\
    6.13  	editxlinkdialog.h \
    6.14 @@ -79,8 +80,9 @@
    6.15  	aboutdialog.cpp \
    6.16  	animpoint.cpp \
    6.17  	attribute.cpp \
    6.18 +	attributedelegate.cpp \
    6.19 +	attributedialog.cpp \
    6.20  	attributewidget.cpp \
    6.21 -	attributedialog.cpp \
    6.22  	branchobj.cpp \
    6.23  	branchpropwindow.cpp \
    6.24  	editxlinkdialog.cpp \
     7.1 --- a/vymmodel.cpp	Wed Feb 27 16:09:06 2008 +0000
     7.2 +++ b/vymmodel.cpp	Wed Feb 27 16:09:06 2008 +0000
     7.3 @@ -192,18 +192,6 @@
     7.4  // View related
     7.5  //////////////////////////////////////////////
     7.6  
     7.7 -	/* FIXME copied from MCO, still needed?
     7.8 -void VymModel::updateLink()
     7.9 -{
    7.10 -	// set childPos to middle of MapCenterObj
    7.11 -	childPos.setX( clickBox.topLeft().x() + (int)(clickBox.width())/2 );
    7.12 -	childPos.setY( clickBox.topLeft().y() + (int)(clickBox.height())/2 );
    7.13 -	parPos=childPos;		
    7.14 -	for (int i=0; i<branch.size(); ++i)
    7.15 -		branch.at(i)->updateLink();
    7.16 -}
    7.17 -
    7.18 -*/
    7.19  void VymModel::updateRelPositions()
    7.20  {
    7.21  	for (int i=0; i<mapCenters.count(); i++)
     8.1 --- a/xml-vym.cpp	Wed Feb 27 16:09:06 2008 +0000
     8.2 +++ b/xml-vym.cpp	Wed Feb 27 16:09:06 2008 +0000
     8.3 @@ -144,9 +144,7 @@
     8.4  		{	
     8.5  			// Really use the found mapcenter as MCO in a new map
     8.6  
     8.7 -			// FIXME not working for multiple mapCenters yet:
     8.8 -			lastBranch=model->addMapCenter();
     8.9 -			//lastBranch=model->first();	// avoid empty pointer
    8.10 +			lastBranch=model->addMapCenter(); 
    8.11  		} else
    8.12  		{
    8.13  			// Treat the found mapcenter as a branch