exports.cpp
author insilmaril
Mon, 15 Mar 2010 15:32:37 +0000
changeset 836 62d621e3e550
parent 825 1ad892c1a709
child 843 2d36a7bb0867
permissions -rw-r--r--
Fix for animation of branches using relPos
     1 #include "exports.h"
     2 
     3 #include "branchitem.h"
     4 #include "file.h"
     5 #include "linkablemapobj.h"
     6 #include "misc.h"
     7 #include "mainwindow.h"
     8 #include "warningdialog.h"
     9 #include "xsltproc.h"
    10 
    11 
    12 extern Main *mainWindow;
    13 extern QDir vymBaseDir;
    14 extern QString vymName;
    15 
    16 ExportBase::ExportBase()
    17 {
    18 	init();
    19 }
    20 
    21 ExportBase::ExportBase(VymModel *m)
    22 {
    23 	init();
    24 	model=m;
    25 }
    26 
    27 ExportBase::~ExportBase()
    28 {
    29 	// Cleanup tmpdir
    30 	removeDir (tmpDir);
    31 }
    32 
    33 void ExportBase::init()
    34 {
    35 	indentPerDepth="  ";
    36 	bool ok;
    37     tmpDir.setPath (makeTmpDir(ok,"vym-export"));
    38 	if (!tmpDir.exists() || !ok)
    39 		QMessageBox::critical( 0, QObject::tr( "Error" ),
    40 					   QObject::tr("Couldn't access temporary directory\n"));
    41 	cancelFlag=false;				   
    42 }
    43 
    44 void ExportBase::setDir(const QDir &d)
    45 {
    46 	outDir=d;
    47 }
    48 
    49 void ExportBase::setFile (const QString &p)
    50 {
    51 	outputFile=p;
    52 }
    53 
    54 QString ExportBase::getFile ()
    55 {
    56 	return outputFile;
    57 }
    58 
    59 void ExportBase::setModel(VymModel *m)
    60 {
    61 	model=m;
    62 }
    63 
    64 void ExportBase::setCaption (const QString &s)
    65 {
    66 	caption=s;
    67 }
    68 
    69 void ExportBase::addFilter(const QString &s)
    70 {
    71 	filter=s;
    72 }
    73 
    74 bool ExportBase::execDialog()
    75 {
    76 	{
    77 		QFileDialog *fd=new QFileDialog( 0, caption);
    78 		fd->setFilter (filter);
    79 		fd->setCaption(caption);
    80 		fd->setMode( QFileDialog::AnyFile );
    81 		fd->setDir (outDir);
    82 		fd->show();
    83 
    84 		if ( fd->exec() == QDialog::Accepted )
    85 		{
    86 			if (QFile (fd->selectedFile()).exists() )
    87 			{
    88 				QMessageBox mb( vymName,
    89 					QObject::tr("The file %1 exists already.\nDo you want to overwrite it?").arg(fd->selectedFile()), 
    90 				QMessageBox::Warning,
    91 				QMessageBox::Yes | QMessageBox::Default,
    92 				QMessageBox::Cancel | QMessageBox::Escape,
    93 				Qt::NoButton );
    94 				mb.setButtonText( QMessageBox::Yes, QObject::tr("Overwrite") );
    95 				mb.setButtonText( QMessageBox::No, QObject::tr("Cancel"));
    96 				ExportBase ex;
    97 				switch( mb.exec() ) 
    98 				{
    99 					case QMessageBox::Yes:
   100 						// save 
   101 						break;;
   102 					case QMessageBox::Cancel:
   103 						cancelFlag=true;
   104 						return false;
   105 						break;
   106 				}
   107 			}
   108 			outputFile=fd->selectedFile();
   109 			cancelFlag=false;
   110 			return true;
   111 		}
   112 	}
   113 	return false;
   114 }
   115 
   116 bool ExportBase::canceled()
   117 {
   118 	return cancelFlag;
   119 }
   120 
   121 QString ExportBase::getSectionString(TreeItem *start)
   122 {
   123 	// Make prefix like "2.5.3" for "bo:2,bo:5,bo:3"
   124 	QString r;
   125 	TreeItem *ti=start;
   126 	int depth=ti->depth();
   127 	while (depth>0)
   128 	{
   129 		r=QString("%1").arg(1+ti->num(),0,10)+"." + r;
   130 		ti=ti->parent(); 
   131 		depth=ti->depth();
   132 	}	
   133 	if (r.isEmpty())
   134 		return r;
   135 	else	
   136 		return r + " ";
   137 }
   138 
   139 ////////////////////////////////////////////////////////////////////////
   140 ExportAO::ExportAO()
   141 {
   142 	filter="TXT (*.txt)";
   143 	caption=vymName+ " -" +QObject::tr("Export as ASCII")+" "+QObject::tr("(still experimental)");
   144 }
   145 
   146 void ExportAO::doExport()	
   147 {
   148 	QFile file (outputFile);
   149 	if ( !file.open( QIODevice::WriteOnly ) )
   150 	{
   151 		qWarning ("ExportAO::doExport couldn't open "+outputFile);
   152 		return;
   153 	}
   154 	QTextStream ts( &file );	// use LANG decoding here...
   155 
   156 	// Main loop over all branches
   157 	QString s;
   158 	QString curIndent;
   159 	int i;
   160 	BranchItem *cur=NULL;
   161 	BranchItem *prev=NULL;
   162 
   163 	QString colString;
   164 	QColor col;
   165 
   166 	cur=model->nextBranch (cur,prev);
   167 	while (cur) 
   168 	{
   169 		if (cur->getType()==TreeItem::Branch || cur->getType()==TreeItem::MapCenter)
   170 		{
   171 			// Make indentstring
   172 			curIndent="";
   173 			for (i=0;i<cur->depth()-1;i++) curIndent+= indentPerDepth;
   174 
   175 			if (!cur->hasHiddenExportParent() )
   176 			{
   177 				col=cur->getHeadingColor();
   178 				if (col==QColor (255,0,0))
   179 					colString="[R]";
   180 				else if (col==QColor (217,81,0))
   181 					colString="[O]";
   182 				else if (col==QColor (0,85,0))
   183 					colString="[G]";
   184 				else  	
   185 					colString="[?]";
   186 				switch (cur->depth())
   187 				{
   188 					case 0:
   189 						//ts << underline (cur->getHeading(),QString("="));
   190 						//ts << "\n";
   191 						break;
   192 					case 1:
   193 						//ts << "\n";
   194 						//ts << (underline ( cur->getHeading(), QString("-") ) );
   195 						//ts << "\n";
   196 						break;
   197 					case 2: // Main heading
   198 						ts << "\n";
   199 						ts << underline ( cur->getHeading(), QString("=") );
   200 						ts << "\n";
   201 						break;
   202 					case 3: // Achievement, Bonus, Objective ...
   203 						ts << "\n\n";
   204 						ts << underline ( cur->getHeading(), "-");
   205 						ts << "\n\n";
   206 						break;
   207 					case 4:	// That's the item we need to know
   208 						//ts << (curIndent + "* " + colString+" "+ cur->getHeading());
   209 						ts << colString+" "+ cur->getHeading();
   210 						if (cur->isActiveStandardFlag ("hook-green"))
   211 							ts << " [DONE] ";
   212 						else	if (cur->isActiveStandardFlag ("wip"))
   213 							ts << " [WIP] ";
   214 						else	if (cur->isActiveStandardFlag ("cross-red"))
   215 							ts << " [NOT STARTED] ";
   216 						ts << "\n";
   217 						break;
   218 					default:
   219 						ts << (curIndent + "- " + cur->getHeading());
   220 						ts << "\n";
   221 						break;
   222 				}
   223 
   224 				// If necessary, write note
   225 				if (!cur->getNoteObj().isEmpty())
   226 				{
   227 					curIndent +="  | ";
   228 					s=cur->getNoteASCII( curIndent, 80);
   229 					ts << s;
   230 				}
   231 			}
   232 		}
   233 		cur=model->nextBranch(cur,prev);
   234 	}
   235 	file.close();
   236 }
   237 
   238 QString ExportAO::underline (const QString &text, const QString &line)
   239 {
   240 	QString r=text + "\n";
   241 	for (int j=0;j<text.length();j++) r+=line;
   242 	return r;
   243 }
   244 
   245 
   246 ////////////////////////////////////////////////////////////////////////
   247 ExportASCII::ExportASCII()
   248 {
   249 	filter="TXT (*.txt)";
   250 	caption=vymName+ " -" +QObject::tr("Export as ASCII")+" "+QObject::tr("(still experimental)");
   251 }
   252 
   253 void ExportASCII::doExport()	
   254 {
   255 	QFile file (outputFile);
   256 	if ( !file.open( QIODevice::WriteOnly ) )
   257 	{
   258 		qWarning ("ExportASCII::doExport couldn't open "+outputFile);
   259 		return;
   260 	}
   261 	QTextStream ts( &file );	// use LANG decoding here...
   262 
   263 	// Main loop over all branches
   264 	QString s;
   265 	QString curIndent;
   266 	int i;
   267 	BranchItem *cur=NULL;
   268 	BranchItem *prev=NULL;
   269 
   270 	cur=model->nextBranch (cur,prev);
   271 	while (cur) 
   272 	{
   273 		if (cur->getType()==TreeItem::Branch || cur->getType()==TreeItem::MapCenter)
   274 		{
   275 			// Make indentstring
   276 			curIndent="";
   277 			for (i=1;i<cur->depth()-1;i++) curIndent+= indentPerDepth;
   278 
   279 			if (!cur->hasHiddenExportParent() )
   280 			{
   281 				//std::cout << "ExportASCII::  "<<curIndent.toStdString()<<cur->getHeading().toStdString()<<std::endl;
   282 				switch (cur->depth())
   283 				{
   284 					case 0:
   285 						ts << underline (cur->getHeading(),QString("="));
   286 						ts << "\n";
   287 						break;
   288 					case 1:
   289 						ts << "\n";
   290 						ts << (underline (getSectionString(cur) + cur->getHeading(), QString("-") ) );
   291 						ts << "\n";
   292 						break;
   293 					case 2:
   294 						ts << "\n";
   295 						ts << (curIndent + "* " + cur->getHeading());
   296 						ts << "\n";
   297 						break;
   298 					case 3:
   299 						ts << (curIndent + "- " + cur->getHeading());
   300 						ts << "\n";
   301 						break;
   302 					default:
   303 						ts << (curIndent + "- " + cur->getHeading());
   304 						ts << "\n";
   305 						break;
   306 				}
   307 
   308 				// If necessary, write note
   309 				if (!cur->getNoteObj().isEmpty())
   310 				{
   311 					curIndent +="  | ";
   312 					s=cur->getNoteASCII( curIndent, 80);
   313 					ts << s;
   314 				}
   315 			}
   316 		}
   317 		cur=model->nextBranch(cur,prev);
   318 	}
   319 	file.close();
   320 }
   321 
   322 QString ExportASCII::underline (const QString &text, const QString &line)
   323 {
   324 	QString r=text + "\n";
   325 	for (int j=0;j<text.length();j++) r+=line;
   326 	return r;
   327 }
   328 
   329 
   330 ////////////////////////////////////////////////////////////////////////
   331 void ExportCSV::doExport()
   332 {
   333 	QFile file (outputFile);
   334 	if ( !file.open( QIODevice::WriteOnly ) )
   335 	{
   336 		qWarning ("ExportBase::exportXML  couldn't open "+outputFile);
   337 		return;
   338 	}
   339 	QTextStream ts( &file );	// use LANG decoding here...
   340 
   341 	// Write header
   342 	ts << "\"Note\""  <<endl;
   343 
   344 	// Main loop over all branches
   345 	QString s;
   346 	QString curIndent("");
   347 	int i;
   348 	BranchItem *cur=NULL;
   349 	BranchItem *prev=NULL;
   350 	cur=model->nextBranch (cur,prev);
   351 	while (cur) 
   352 	{
   353 		if (!cur->hasHiddenExportParent() )
   354 		{
   355 			// If necessary, write note
   356 			if (!cur->getNoteObj().isEmpty())
   357 			{
   358 				s =cur->getNoteASCII();
   359 				s=s.replace ("\n","\n"+curIndent);
   360 				ts << ("\""+s+"\",");
   361 			} else
   362 				ts <<"\"\",";
   363 
   364 			// Make indentstring
   365 			for (i=0;i<cur->depth();i++) curIndent+= "\"\",";
   366 
   367 			// Write heading
   368 			ts << curIndent << "\"" << cur->getHeading()<<"\""<<endl;
   369 		}
   370 		
   371 		cur=model->nextBranch(cur,prev);
   372 		curIndent="";
   373 	}
   374 	file.close();
   375 }
   376 
   377 ////////////////////////////////////////////////////////////////////////
   378 void ExportKDE3Bookmarks::doExport() 
   379 {
   380 	WarningDialog dia;
   381 	dia.showCancelButton (true);
   382 	dia.setText(QObject::tr("Exporting the %1 bookmarks will overwrite\nyour existing bookmarks file.").arg("KDE"));
   383 	dia.setCaption(QObject::tr("Warning: Overwriting %1 bookmarks").arg("KDE 3"));
   384 	dia.setShowAgainName("/exports/KDE/overwriteKDEBookmarks");
   385 	if (dia.exec()==QDialog::Accepted)
   386 	{
   387 		model->exportXML(tmpDir.path(),false);
   388 
   389 		XSLTProc p;
   390 		p.setInputFile (tmpDir.path()+"/"+model->getMapName()+".xml");
   391 		p.setOutputFile (tmpDir.home().path()+"/.kde/share/apps/konqueror/bookmarks.xml");
   392 		p.setXSLFile (vymBaseDir.path()+"/styles/vym2kdebookmarks.xsl");
   393 		p.process();
   394 
   395 		QString ub=vymBaseDir.path()+"/scripts/update-bookmarks";
   396 		QProcess *proc= new QProcess ;
   397 		proc->start( ub);
   398 		if (!proc->waitForStarted())
   399 		{
   400 			QMessageBox::warning(0, 
   401 				QObject::tr("Warning"),
   402 				QObject::tr("Couldn't find script %1\nto notifiy Browsers of changed bookmarks.").arg(ub));
   403 		}	
   404 	}
   405 }
   406 
   407 ////////////////////////////////////////////////////////////////////////
   408 void ExportKDE4Bookmarks::doExport() 
   409 {
   410 	WarningDialog dia;
   411 	dia.showCancelButton (true);
   412 	dia.setText(QObject::tr("Exporting the %1 bookmarks will overwrite\nyour existing bookmarks file.").arg("KDE 4"));
   413 	dia.setCaption(QObject::tr("Warning: Overwriting %1 bookmarks").arg("KDE"));
   414 	dia.setShowAgainName("/exports/KDE/overwriteKDEBookmarks");
   415 	if (dia.exec()==QDialog::Accepted)
   416 	{
   417 		model->exportXML(tmpDir.path(),false);
   418 
   419 		XSLTProc p;
   420 		p.setInputFile (tmpDir.path()+"/"+model->getMapName()+".xml");
   421 		p.setOutputFile (tmpDir.home().path()+"/.kde4/share/apps/konqueror/bookmarks.xml");
   422 		p.setXSLFile (vymBaseDir.path()+"/styles/vym2kdebookmarks.xsl");
   423 		p.process();
   424 
   425 		QString ub=vymBaseDir.path()+"/scripts/update-bookmarks";
   426 		QProcess *proc= new QProcess ;
   427 		proc->start( ub);
   428 		if (!proc->waitForStarted())
   429 		{
   430 			QMessageBox::warning(0, 
   431 				QObject::tr("Warning"),
   432 				QObject::tr("Couldn't find script %1\nto notifiy Browsers of changed bookmarks.").arg(ub));
   433 		}	
   434 	}
   435 }
   436 
   437 ////////////////////////////////////////////////////////////////////////
   438 void ExportFirefoxBookmarks::doExport() 
   439 {
   440 	WarningDialog dia;
   441 	dia.showCancelButton (true);
   442 	dia.setText(QObject::tr("Exporting the %1 bookmarks will overwrite\nyour existing bookmarks file.").arg("Firefox"));
   443 	dia.setCaption(QObject::tr("Warning: Overwriting %1 bookmarks").arg("Firefox"));
   444 	dia.setShowAgainName("/vym/warnings/overwriteImportBookmarks");
   445 	if (dia.exec()==QDialog::Accepted)
   446 	{
   447 		model->exportXML(tmpDir.path(),false);
   448 
   449 /*
   450 		XSLTProc p;
   451 		p.setInputFile (tmpDir.path()+"/"+me->getMapName()+".xml");
   452 		p.setOutputFile (tmpDir.home().path()+"/.kde/share/apps/konqueror/bookmarks.xml");
   453 		p.setXSLFile (vymBaseDir.path()+"/styles/vym2kdebookmarks.xsl");
   454 		p.process();
   455 
   456 		QString ub=vymBaseDir.path()+"/scripts/update-bookmarks";
   457 		QProcess *proc = new QProcess( );
   458 		proc->addArgument(ub);
   459 
   460 		if ( !proc->start() ) 
   461 		{
   462 			QMessageBox::warning(0, 
   463 				QObject::tr("Warning"),
   464 				QObject::tr("Couldn't find script %1\nto notifiy Browsers of changed bookmarks.").arg(ub));
   465 		}	
   466 
   467 */
   468 	}
   469 }
   470 
   471 ////////////////////////////////////////////////////////////////////////
   472 ExportHTML::ExportHTML():ExportBase()
   473 {
   474 	init();
   475 }
   476 
   477 ExportHTML::ExportHTML(VymModel *m):ExportBase(m)
   478 {
   479 	init();
   480 }
   481 
   482 void ExportHTML::init()
   483 {
   484 	singularDelimiter=": ";
   485 	noSingulars=true;	
   486 	frameURLs=true;
   487 	cssFileName="vym.css";
   488 	cssOriginalPath="";	// Is set in VymModel, based on default setting in ExportHTMLDialog
   489 
   490 	if (model &&model->getMapEditor()) 
   491 		offset=model->getMapEditor()->getTotalBBox().topLeft();
   492 }
   493 
   494 QString ExportHTML::getBranchText(BranchItem *current)
   495 {
   496 	if (current)
   497 	{
   498 		bool vis=false;
   499 		QRectF hr;
   500 		LinkableMapObj *lmo=current->getLMO();
   501 		if (lmo)
   502 		{
   503 			hr=((BranchObj*)lmo)->getBBoxHeading();
   504 			if (lmo->isVisibleObj()) vis=true;
   505 		}
   506 		QString col;
   507 		QString id=model->getSelectString(current);
   508 		if (dia.useTextColor)
   509 			col=QString("style='color:%1'").arg(current->getHeadingColor().name());
   510 		QString s=QString("<span class='vym-branch%1' %2 id='%3'>")
   511 			.arg(current->depth())
   512 			.arg(col)
   513 			.arg(id);
   514 		QString url=current->getURL();	
   515 		if (!url.isEmpty())
   516 		{
   517 			s+=QString ("<a href=\"%1\">").arg(url);
   518 			s+=QString ("<img src=\"flags/flag-url-16x16.png\">%1</a>").arg(quotemeta(current->getHeading()));
   519 			s+="</a>";
   520 			
   521 			QRectF fbox=current->getBBoxURLFlag ();
   522 			if (vis)
   523 				imageMap+=QString("  <area shape='rect' coords='%1,%2,%3,%4' href='%5'>\n")
   524 					.arg(fbox.left()-offset.x())
   525 					.arg(fbox.top()-offset.y())
   526 					.arg(fbox.right()-offset.x())
   527 					.arg(fbox.bottom()-offset.y())
   528 					.arg(url);
   529 		} else	
   530 			s+=quotemeta(current->getHeading());
   531 		s+="</span>";
   532 
   533 		if (vis && dia.useImage)
   534 			imageMap+=QString("  <area shape='rect' coords='%1,%2,%3,%4' href='#%5'>\n")
   535 				.arg(hr.left()-offset.x())
   536 				.arg(hr.top()-offset.y())
   537 				.arg(hr.right()-offset.x())
   538 				.arg(hr.bottom()-offset.y())
   539 				.arg(id);
   540 
   541 		// Include note
   542 		if (!current->getNoteObj().isEmpty())
   543 			s+="<table border=1><tr><td>"+current->getNote()+"</td></tr></table>";
   544 
   545 		return s;
   546 	} 
   547 	return QString();
   548 }
   549 
   550 QString ExportHTML::buildList (BranchItem *current)
   551 {
   552     QString r;
   553 
   554     uint i=0;
   555 	BranchItem *bi=current->getFirstBranch();
   556 
   557 	// Only add itemized list, if we have more than one subitem.
   558 	// For only one subitem, just add a separator to keep page more compact
   559 	bool noSingularsHere=false;
   560 	if (current->branchCount()<2 && noSingulars) noSingularsHere=true;
   561 
   562 	if (bi)
   563     {
   564 		if (!noSingularsHere)
   565 			r+="<ul>\n";
   566 		else
   567 			r+=singularDelimiter;
   568 
   569 		while (bi)
   570 		{
   571 			if (!bi->hasHiddenExportParent() )	
   572 			{
   573 				if (!noSingularsHere) r+="<li>";
   574 				r+=getBranchText (bi);
   575 				if (!bi->getURL().isEmpty() && frameURLs && noSingularsHere)
   576 					// Add frame, if we have subitems to an URL
   577 					r+="<table border=1><tr><td>"+buildList (bi)+"</td></tr></table>";	// recursivly add deeper branches
   578 				else
   579 					r+=buildList (bi);	// recursivly add deeper branches
   580 				if (!noSingularsHere) r+="</li>";
   581 				r+="\n";
   582 			}
   583 			i++;
   584 			bi=current->getBranchNum(i);
   585 		}
   586 
   587 		if (!noSingularsHere) r+="</ul>\n";
   588 	}
   589     return r;
   590 }
   591 
   592 void ExportHTML::setCSSPath(const QString &p)
   593 {
   594 	cssOriginalPath=p;
   595 }
   596 
   597 void ExportHTML::doExport(bool useDialog) 
   598 {
   599 	// Execute dialog
   600 	dia.setFilePath (model->getFilePath());
   601 	dia.setMapName (model->getMapName());
   602 	dia.readSettings();
   603 	if (useDialog && dia.exec()!=QDialog::Accepted) return;
   604 
   605 	// Check if destination is not empty
   606 	QDir d=dia.getDir();
   607 	// Check, if warnings should be used before overwriting
   608 	// the output directory
   609 	if (d.exists() && d.count()>0)
   610 	{
   611 		WarningDialog warn;
   612 		warn.showCancelButton (true);
   613 		warn.setText(QString(
   614 			"The directory %1 is not empty.\n"
   615 			"Do you risk to overwrite some of its contents?").arg(d.path() ));
   616 		warn.setCaption("Warning: Directory not empty");
   617 		warn.setShowAgainName("mainwindow/export-XML-overwrite-dir");
   618 
   619 		if (warn.exec()!=QDialog::Accepted) 
   620 		{
   621 			mainWindow->statusMessage(QString(QObject::tr("Export aborted.")));
   622 			return;
   623 		}
   624 	}
   625 
   626 	setFile (d.path()+"/"+model->getMapName()+".html");
   627 	setCSSPath( dia.getCSSPath() );
   628 
   629 	// Copy CSS file
   630 	QFile css_src (cssOriginalPath);
   631 	QFile css_dst (outDir.path()+"/"+cssFileName);
   632 	if (!css_src.open ( QIODevice::ReadOnly))
   633 		QMessageBox::warning( 0, QObject::tr( "Warning","ExportHTML" ),QObject::tr("Could not open %1","ExportHTML").arg(cssOriginalPath));
   634 	else
   635 	{
   636 		if (!css_dst.open( QIODevice::WriteOnly))
   637 			QMessageBox::warning( 0, QObject::tr( "Warning" ), QObject::tr("Could not open %1").arg(css_dst.fileName()));
   638 		else
   639 		{	
   640 		
   641 			QTextStream tsout( &css_dst);
   642 			QTextStream tsin ( &css_src);
   643 			QString s= tsin.read();
   644 			tsout << s;
   645 			css_dst.close();
   646 		}	
   647 		css_src.close();
   648 	}
   649 
   650 
   651 
   652 	// Open file for writing
   653 	QFile file (outputFile);
   654 	if ( !file.open( QIODevice::WriteOnly ) ) 
   655 	{
   656 		QMessageBox::critical (0,QObject::tr("Critical Export Error"),QObject::tr("Could not write %1").arg(outputFile));
   657 		mainWindow->statusMessage(QString(QObject::tr("Export failed.")));
   658 		return;
   659 	}
   660 	QTextStream ts( &file );	// use LANG decoding here...
   661 	ts.setEncoding (QTextStream::UnicodeUTF8); // Force UTF8
   662 
   663 	// Hide stuff during export
   664 	model->setExportMode (true);
   665 
   666 	// Write header
   667 	ts<<"<html><title>"+model->getMapName()<<"</title><body>";
   668 	ts<<" <link rel='stylesheet' id='css.stylesheet' href='"<<cssFileName<<"' />\n";
   669 
   670 	// Include image
   671 	if (dia.useImage)
   672 	{
   673 		ts<<"<center><img src=\""<<model->getMapName()<<".png\" usemap='#imagemap'></center>\n";
   674 		model->exportImage (d.path()+"/"+model->getMapName()+".png",false,"PNG");
   675 	}
   676 
   677 	// Main loop over all mapcenters
   678 	QString s;
   679 	TreeItem *rootItem=model->getRootItem();
   680 	BranchItem *bi;
   681 	for (int i=0; i<rootItem->branchCount(); i++)
   682 	{
   683 		bi=rootItem->getBranchNum(i);
   684 		if (!bi->hasHiddenExportParent())
   685 		{
   686 			ts<<getBranchText (bi);
   687 			ts<<buildList (bi);
   688 		}
   689 	}	
   690 
   691 	// Imagemap
   692 	ts<<"<map name='imagemap'>\n"+imageMap+"</map>\n";
   693 
   694 	// Write footer 
   695 	ts<<"<hr/>\n";
   696 	ts<<"<table class=\"vym-footer\">   \n\
   697       <tr> \n\
   698         <td class=\"vym-footerL\">"+model->getFileName()+"</td> \n\
   699         <td class=\"vym-footerC\">"+model->getDate()+"</td> \n\
   700         <td class=\"vym-footerR\"> vym "+model->getVersion()+"</td> \n\
   701       </tr> \n \
   702     </table>\n";
   703 	ts<<"</body></html>";
   704 	file.close();
   705 
   706 	if (!dia.postscript.isEmpty()) 
   707 	{
   708 		Process p;
   709 		p.runScript (dia.postscript,d.path()+"/"+model->getMapName()+".html");
   710 	}
   711 
   712 
   713 	dia.saveSettings();
   714 	model->setExportMode (true);
   715 }
   716 
   717 ////////////////////////////////////////////////////////////////////////
   718 void ExportTaskjuggler::doExport() 
   719 {
   720 	model->exportXML(tmpDir.path(),false);
   721 
   722 	XSLTProc p;
   723 	p.setInputFile (tmpDir.path()+"/"+model->getMapName()+".xml");
   724 	p.setOutputFile (outputFile);
   725 	p.setXSLFile (vymBaseDir.path()+"/styles/vym2taskjuggler.xsl");
   726 	p.process();
   727 }
   728 
   729 ////////////////////////////////////////////////////////////////////////
   730 void ExportLaTeX::doExport() 
   731 {
   732 	// Exports a map to a LaTex file.  
   733 	// This file needs to be included 
   734 	// or inported into a LaTex document
   735 	// it will not add a preamble, or anything 
   736 	// that makes a full LaTex document.
   737   QFile file (outputFile);
   738   if ( !file.open( QIODevice::WriteOnly ) ) {
   739 	QMessageBox::critical (0,QObject::tr("Critical Export Error"),QObject::tr("Could not write %1").arg(outputFile));
   740 	mainWindow->statusMessage(QString(QObject::tr("Export failed.")));
   741     return;
   742   }
   743   QTextStream ts( &file );	// use LANG decoding here...
   744   ts.setEncoding (QTextStream::UnicodeUTF8); // Force UTF8
   745   
   746   // Main loop over all branches
   747   QString s;
   748   // QString curIndent("");
   749   // int i;
   750   BranchObj *bo;
   751   BranchItem *cur=NULL;
   752   BranchItem *prev=NULL;
   753   model->nextBranch(cur,prev);
   754   while (cur) 
   755   {
   756 	bo=(BranchObj*)(cur->getLMO());
   757 
   758 	if (!cur->hasHiddenExportParent() )
   759 	{
   760 		switch (cur->depth() ) 
   761 		{
   762 			case 0: break;
   763 			case 1: 
   764 			  ts << ("\\chapter{" + cur->getHeading()+ "}\n");
   765 			  break;
   766 			case 2: 
   767 			  ts << ("\\section{" + cur->getHeading()+ "}\n");
   768 			  break;
   769 			case 3: 
   770 			  ts << ("\\subsection{" + cur->getHeading()+ "}\n");
   771 			  break;
   772 			case 4: 
   773 			  ts << ("\\subsubsection{" + cur->getHeading()+ "}\n");
   774 			  break;
   775 			default:
   776 			  ts << ("\\paragraph*{" + cur->getHeading()+ "}\n");
   777 			
   778 		}
   779 		// If necessary, write note
   780 		if (!cur->getNoteObj().isEmpty()) {
   781 		  ts << (cur->getNoteASCII());
   782 		  ts << ("\n");
   783 		}
   784 	}
   785     cur=model->nextBranch(cur,prev);
   786    }
   787   file.close();
   788 }
   789 
   790 ////////////////////////////////////////////////////////////////////////
   791 ExportOO::ExportOO()
   792 {
   793 	useSections=false;
   794 }
   795 
   796 ExportOO::~ExportOO()
   797 {
   798 }	
   799 
   800 QString ExportOO::buildList (TreeItem *current)
   801 {
   802     QString r;
   803 
   804     uint i=0;
   805 	BranchItem *bi=current->getFirstBranch();
   806 	if (bi)
   807     {
   808 		// Start list
   809 		r+="<text:list text:style-name=\"vym-list\">\n";
   810 		while (bi)
   811 		{
   812 			if (!bi->hasHiddenExportParent() )	
   813 			{
   814 				r+="<text:list-item><text:p >";
   815 				r+=quotemeta(bi->getHeading());
   816 				// If necessary, write note
   817 				if (!bi->getNoteObj().isEmpty())
   818 					r+=bi->getNoteOpenDoc();
   819 				r+="</text:p>";
   820 				r+=buildList (bi);	// recursivly add deeper branches
   821 				r+="</text:list-item>\n";
   822 			}
   823 			i++;
   824 			bi=current->getBranchNum(i);
   825 		}
   826 		r+="</text:list>\n";
   827     }
   828     return r;
   829 }
   830 
   831 
   832 void ExportOO::exportPresentation()
   833 {
   834 	QString allPages;
   835 
   836 	BranchItem *firstMCO=(BranchItem*)(model->getRootItem()->getFirstBranch());
   837 	if (!firstMCO) 
   838 	{
   839 		QMessageBox::critical (0,QObject::tr("Critical Export Error"),QObject::tr("No objects in map!"));
   840 		return;
   841 	}
   842 
   843 	// Insert new content
   844 	// FIXME add extra title in mapinfo for vym 1.13.x
   845 	content.replace ("<!-- INSERT TITLE -->",quotemeta(firstMCO->getHeading()));
   846 	content.replace ("<!-- INSERT AUTHOR -->",quotemeta(model->getAuthor()));
   847 
   848 	QString	onePage;
   849 	QString list;
   850 	
   851 	BranchItem *sectionBI;	
   852     int i=0;
   853 	BranchItem *pagesBI;
   854     int j=0;
   855 
   856 	int mapcenters=model->getRootItem()->branchCount();
   857 
   858 	// useSections already has been set in setConfigFile 
   859 	if (mapcenters>1)	
   860 		sectionBI=firstMCO;
   861 	else
   862 		sectionBI=firstMCO->getFirstBranch();
   863 
   864 	// Walk sections
   865 	while (sectionBI && !sectionBI->hasHiddenExportParent() )
   866 	{
   867 		if (useSections)
   868 		{
   869 			// Add page with section title
   870 			onePage=sectionTemplate;
   871 			onePage.replace ("<!-- INSERT PAGE HEADING -->", quotemeta(sectionBI->getHeading() ) );
   872 			allPages+=onePage;
   873 			pagesBI=sectionBI->getFirstBranch();
   874 		} else
   875 		{
   876 			//i=-2;	// only use inner loop to 
   877 			        // turn mainbranches into pages
   878 			//sectionBI=firstMCO;
   879 			pagesBI=sectionBI;
   880 		}
   881 
   882 		j=0;
   883 		while (pagesBI && !pagesBI->hasHiddenExportParent() )
   884 		{
   885 			// Add page with list of items
   886 			onePage=pageTemplate;
   887 			onePage.replace ("<!-- INSERT PAGE HEADING -->", quotemeta (pagesBI->getHeading() ) );
   888 			list=buildList (pagesBI);
   889 			onePage.replace ("<!-- INSERT LIST -->", list);
   890 			allPages+=onePage;
   891 			if (pagesBI!=sectionBI)
   892 			{
   893 				j++;
   894 				pagesBI=((BranchItem*)pagesBI->parent())->getBranchNum(j);
   895 			} else
   896 				pagesBI=NULL;	// We are already iterating over the sectionBIs
   897 		}
   898 		i++;
   899 		if (mapcenters>1 )
   900 			sectionBI=model->getRootItem()->getBranchNum (i);
   901 		else
   902 			sectionBI=firstMCO->getBranchNum (i);
   903 	}
   904 	
   905 	content.replace ("<!-- INSERT PAGES -->",allPages);
   906 
   907 	// Write modified content
   908 	QFile f (contentFile);
   909     if ( !f.open( QIODevice::WriteOnly ) ) 
   910 	{
   911 		QMessageBox::critical (0,QObject::tr("Critical Export Error"),QObject::tr("Could not write %1").arg(contentFile));
   912 		mainWindow->statusMessage(QString(QObject::tr("Export failed.")));
   913 		return;
   914     }
   915 
   916     QTextStream t( &f );
   917     t << content;
   918     f.close();
   919 
   920 	// zip tmpdir to destination
   921 	zipDir (tmpDir,outputFile);	
   922 }
   923 
   924 bool ExportOO::setConfigFile (const QString &cf)
   925 {
   926 	configFile=cf;
   927 	int i=cf.findRev ("/");
   928 	if (i>=0) configDir=cf.left(i);
   929 	SimpleSettings set;
   930 	set.readSettings(configFile);
   931 
   932 	// set paths
   933 	templateDir=configDir+"/"+set.readEntry ("Template");
   934 
   935 	QDir d (templateDir);
   936 	if (!d.exists())
   937 	{
   938 		QMessageBox::critical (0,QObject::tr("Critical Export Error"),QObject::tr("Check \"%1\" in\n%2").arg("Template="+set.readEntry ("Template")).arg(configFile));
   939 		return false;
   940 
   941 	}
   942 
   943 	contentTemplateFile=templateDir+"content-template.xml";
   944 	contentFile=tmpDir.path()+"/content.xml";
   945 	pageTemplateFile=templateDir+"page-template.xml";
   946 	sectionTemplateFile=templateDir+"section-template.xml";
   947 
   948 	if (set.readEntry("useSections").contains("yes"))
   949 		useSections=true;
   950 
   951 	// Copy template to tmpdir
   952 	system ("cp -r "+templateDir+"* "+tmpDir.path());
   953 
   954 	// Read content-template
   955 	if (!loadStringFromDisk (contentTemplateFile,content))
   956 	{
   957 		QMessageBox::critical (0,QObject::tr("Critical Export Error"),QObject::tr("Could not read %1").arg(contentTemplateFile));
   958 		return false;
   959 	}
   960 
   961 	// Read page-template
   962 	if (!loadStringFromDisk (pageTemplateFile,pageTemplate))
   963 	{
   964 		QMessageBox::critical (0,QObject::tr("Critical Export Error"),QObject::tr("Could not read %1").arg(pageTemplateFile));
   965 		return false;
   966 	}
   967 	
   968 	// Read section-template
   969 	if (useSections && !loadStringFromDisk (sectionTemplateFile,sectionTemplate))
   970 	{
   971 		QMessageBox::critical (0,QObject::tr("Critical Export Error"),QObject::tr("Could not read %1").arg(sectionTemplateFile));
   972 		return false;
   973 	}
   974 	return true;
   975 }
   976