kivio

kivio_doc.cpp

00001 /*
00002  * Kivio - Visual Modelling and Flowcharting
00003  * Copyright (C) 2000-2001 theKompany.com & Dave Marotti
00004  *
00005  * This program is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License
00007  * as published by the Free Software Foundation; either version 2
00008  * of the License, or (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00018  */
00019 #include <qdom.h>
00020 #include <qtextstream.h>
00021 #include <qbuffer.h>
00022 #include <qtabwidget.h>
00023 #include <qpaintdevicemetrics.h>
00024 
00025 #include "kivio_doc.h"
00026 #include "kivio_page.h"
00027 #include "kivio_map.h"
00028 #include "kivio_view.h"
00029 #include "kivio_factory.h"
00030 #include "export_page_dialog.h"
00031 #include "kivio_common.h"
00032 #include "kivio_group_stencil.h"
00033 #include "kivio_icon_view.h"
00034 #include "kivio_layer.h"
00035 #include "kivio_painter.h"
00036 #include "kivio_screen_painter.h"
00037 #include "kivio_stencil.h"
00038 #include "kivio_stencil_spawner_set.h"
00039 #include "kivioglobal.h"
00040 #include "kivio_config.h"
00041 #include "polylineconnectorspawner.h"
00042 #include "kivio_canvas.h"
00043 
00044 #include "stencilbarbutton.h"
00045 
00046 #include <unistd.h>
00047 #include <kmessagebox.h>
00048 #include <klocale.h>
00049 #include <kprinter.h>
00050 #include <kdebug.h>
00051 #include <kurl.h>
00052 #include <kapplication.h>
00053 #include <assert.h>
00054 #include <qdatetime.h>
00055 #include <sys/types.h>
00056 #include <dirent.h>
00057 #include <sys/stat.h>
00058 #include <pwd.h>
00059 #include <qdir.h>
00060 #include <qfileinfo.h>
00061 #include <qfile.h>
00062 #include <qpixmap.h>
00063 
00064 #include <qpainter.h>
00065 #include <qpen.h>
00066 #include <qfont.h>
00067 #include <qvaluelist.h>
00068 
00069 
00070 #include <kstandarddirs.h>
00071 #include <kpopupmenu.h>
00072 #include <kmenubar.h>
00073 #include <kiconloader.h>
00074 #include <khelpmenu.h>
00075 #include <kconfig.h>
00076 #include <KoTemplateChooseDia.h>
00077 #include <KoFilterManager.h>
00078 #include <KoStoreDevice.h>
00079 #include "KIvioDocIface.h"
00080 #include <kcommand.h>
00081 #include <KoZoomHandler.h>
00082 #include <KoApplication.h>
00083 #include <kglobal.h>
00084 #include <KoCommandHistory.h>
00085 #include <KoXmlWriter.h>
00086 #include <KoGenStyles.h>
00087 #include <KoOasisSettings.h>
00088 #include <KoDom.h>
00089 #include <KoXmlNS.h>
00090 
00091 //using namespace std;
00092 
00093 /*****************************************************************************
00094  *
00095  * KivioDoc
00096  *
00097  *****************************************************************************/
00098 
00099 QPtrList<KivioDoc>* KivioDoc::s_docs = 0;
00100 int KivioDoc::s_docId = 0;
00101 
00102 KivioDoc::KivioDoc( QWidget *parentWidget, const char* widgetName, QObject* parent, const char* name, bool singleViewMode )
00103 : KoDocument( parentWidget, widgetName, parent, name, singleViewMode )
00104 {
00105   dcop = 0;
00106   if (!s_docs)
00107     s_docs = new QPtrList<KivioDoc>;
00108 
00109   s_docs->append(this);
00110 
00111   m_pLstSpawnerSets = new QPtrList<KivioStencilSpawnerSet>;
00112   m_pLstSpawnerSets->setAutoDelete(true);
00113   m_loadTimer = 0;
00114   m_currentFile = 0;
00115 
00116   setInstance( KivioFactory::global(), false );
00117   setTemplateType("kivio_template");
00118 
00119   if ( !name )
00120   {
00121     QString tmp( "Document%1" );    //lukas: FIXME
00122     tmp = tmp.arg( s_docId++ );
00123     setName( tmp.latin1() );
00124   }
00125 
00126   m_iPageId = 1;
00127   m_bLoading = false;
00128   m_pMap = new KivioMap( this, "Map" );
00129 
00130   // Load autoLoadStencils in internal StencilSpawnerSet
00131   m_pInternalSet = new KivioStencilSpawnerSet("Kivio_Internal");
00132   m_pInternalSet->setId("Kivio - Internal - Do Not Touch");
00133   QStringList list = instance()->dirs()->findAllResources("data",instance()->instanceName()+"/autoloadStencils/*",true,false);
00134   QStringList::ConstIterator pIt = list.begin();
00135   QStringList::ConstIterator pEnd = list.end();
00136 
00137   for (; pIt != pEnd; ++pIt )
00138   {
00139     m_pInternalSet->loadFile(*pIt);
00140   }
00141 
00142   // Add the polyline connector spawner to the internal stencil set.
00143   addInternalStencilSpawner(new Kivio::PolyLineConnectorSpawner(internalSpawnerSet()));
00144 
00145   initConfig();
00146 
00147   //laurent: Why don't use menu history for undo/redo command ? sync with other koffice application
00148   m_commandHistory = new KoCommandHistory( actionCollection(),  /*false*/true  ) ;
00149   connect( m_commandHistory, SIGNAL( documentRestored() ), this, SLOT( slotDocumentRestored() ) );
00150   connect( m_commandHistory, SIGNAL( commandExecuted() ), this, SLOT( slotCommandExecuted() ) );
00151 
00152 
00153   if ( name )
00154     dcopObject();
00155 }
00156 
00157 DCOPObject* KivioDoc::dcopObject()
00158 {
00159   if ( !dcop ) {
00160     dcop = new KIvioDocIface( this );
00161   }
00162 
00163   return dcop;
00164 }
00165 
00166 QPtrList<KivioDoc>& KivioDoc::documents()
00167 {
00168   if ( s_docs == 0 ) {
00169     s_docs = new QPtrList<KivioDoc>;
00170   }
00171 
00172   return *s_docs;
00173 }
00174 
00175 bool KivioDoc::initDoc(InitDocFlags flags, QWidget* parentWidget)
00176 {
00177   KivioPage *t = createPage();
00178   m_pMap->addPage( t );
00179   m_docOpened = false; // Used to for a hack that make kivio not crash if you cancel startup dialog.
00180 
00181   if(flags == KoDocument::InitDocEmpty) {
00182     setEmpty();
00183     m_docOpened = true; // Used to for a hack that make kivio not crash if you cancel startup dialog.
00184     return true;
00185   }
00186 
00187   QString f;
00188   KoTemplateChooseDia::ReturnType ret;
00189   KoTemplateChooseDia::DialogType dlgtype;
00190 
00191   if(flags != KoDocument::InitDocFileNew) {
00192     dlgtype = KoTemplateChooseDia::Everything;
00193     initConfig();
00194   } else {
00195     dlgtype = KoTemplateChooseDia::OnlyTemplates;
00196   }
00197 
00198   ret = KoTemplateChooseDia::choose( KivioFactory::global(), f,
00199                                      dlgtype, "kivio_template", parentWidget );
00200 
00201   if( ret == KoTemplateChooseDia::File ) {
00202     KURL url(f);
00203     bool ok = openURL(url);
00204     m_docOpened = ok; // Used to for a hack that make kivio not crash if you cancel startup dialog.
00205     return ok;
00206   } else if ( ret == KoTemplateChooseDia::Template ) {
00207     QFileInfo fileInfo( f );
00208     QString fileName( fileInfo.dirPath(true) + "/" + fileInfo.baseName() + ".kft" );
00209     resetURL();
00210     bool ok = loadNativeFormat( fileName );
00211     if ( !ok )
00212         showLoadingErrorDialog();
00213     setEmpty();
00214     m_docOpened = ok; // Used to for a hack that make kivio not crash if you cancel startup dialog.
00215     return ok;
00216   } else if ( ret == KoTemplateChooseDia::Empty ) {
00217     setEmpty();
00218     m_docOpened = true; // Used to for a hack that make kivio not crash if you cancel startup dialog.
00219     return true;
00220   } else {
00221     return false;
00222   }
00223 }
00224 
00225 void KivioDoc::openExistingFile( const QString& file )
00226 {
00227   KivioPage* t = createPage();
00228   m_pMap->addPage(t);
00229 
00230   KoDocument::openExistingFile(file);
00231 }
00232 
00233 void KivioDoc::openTemplate( const QString& file )
00234 {
00235   KivioPage* t = createPage();
00236   m_pMap->addPage(t);
00237 
00238   KoDocument::openTemplate(file);
00239 }
00240 
00241 void KivioDoc::initEmpty()
00242 {
00243   KivioPage* t = createPage();
00244   m_pMap->addPage(t);
00245   KoDocument::initEmpty();
00246 }
00247 
00248 KoView* KivioDoc::createViewInstance( QWidget* parent, const char* name )
00249 {
00250   if (!name) {
00251     name = "View";
00252   }
00253 
00254   return new KivioView( parent, name, this );
00255 }
00256 
00257 QDomDocument KivioDoc::saveXML()
00258 {
00259   QDomDocument doc( "kiviodoc" );
00260   doc.appendChild( doc.createProcessingInstruction( "xml", "version=\"1.0\" encoding=\"UTF-8\"" ) );
00261   QDomElement kivio = doc.createElement( "kiviosheet" );
00262   kivio.setAttribute( "editor", "Kivio" );
00263   kivio.setAttribute( "mime", MIME_TYPE );
00264 
00265   kivio.setAttribute( "units", unitName() );
00266   gridData.save(kivio,"grid");
00267 
00268   QDomElement viewItemsElement = doc.createElement("ViewItems");
00269   kivio.appendChild(viewItemsElement);
00270 
00271   doc.appendChild(kivio);
00272 
00273   // Save the list of stencils spawners we have loaded.
00274   // We save these as the following:
00275   //
00276   // <KivioStencilSpawnerSet  id="whatever the id is">
00277   //   <KivioSMLStencilSpawner id="whatever the id is"/>
00278   //   <KivioSMLStencilSpawner id="whatever the id is"/>
00279   // </KivioStencilSpawnerSet>
00280   // ....
00281   //
00282   // This is so we can load them back in, and check that we actually
00283   // have all these spawners on disk.
00284   KivioStencilSpawnerSet *pSet = m_pLstSpawnerSets->first();
00285   while( pSet )
00286   {
00287     if(checkStencilsForSpawnerSet(pSet)) {
00288       kivio.appendChild(pSet->saveXML(doc));
00289     }
00290 
00291     pSet = m_pLstSpawnerSets->next();
00292   }
00293 
00294 
00295   QDomElement e = m_pMap->save(doc);
00296   kivio.appendChild(e);
00297 
00298   setModified(false);
00299   return doc;
00300 }
00301 
00302 bool KivioDoc::saveOasis(KoStore* store, KoXmlWriter* manifestWriter)
00303 {
00304     KoStoreDevice storeDev(store);
00305     KoGenStyles styles;
00306 
00307     KoGenStyle pageLayout = Kivio::Config::defaultPageLayout().saveOasis();
00308     QString layoutName = styles.lookup(pageLayout, "PL");
00309     KoGenStyle masterPage(KoGenStyle::STYLE_MASTER);
00310     masterPage.addAttribute("style:page-layout-name", layoutName);
00311     styles.lookup(masterPage, "Standard", false);
00312 
00313     if(!store->open("content.xml")) {
00314         return false;
00315     }
00316 
00317     KoXmlWriter* docWriter = createOasisXmlWriter(&storeDev, "office:document-content");
00318 
00319     docWriter->startElement("office:body");
00320     docWriter->startElement("office:drawing");
00321 
00322     m_pMap->saveOasis(store, docWriter, &styles); // Save contents
00323 
00324     docWriter->endElement(); // office:drawing
00325     docWriter->endElement(); // office:body
00326     docWriter->endElement(); // Root element
00327     docWriter->endDocument();
00328     delete docWriter;
00329 
00330     if(!store->close()) {
00331         return false;
00332     }
00333 
00334     manifestWriter->addManifestEntry("content.xml", "text/xml");
00335 
00336     if(!store->open("styles.xml")) {
00337         return false;
00338     }
00339 
00340     KoXmlWriter* styleWriter = createOasisXmlWriter(&storeDev, "office:document-styles");
00341 
00342     styleWriter->startElement("office:automatic-styles");
00343 
00344     QValueList<KoGenStyles::NamedStyle> styleList = styles.styles(KoGenStyle::STYLE_PAGELAYOUT);
00345     QValueList<KoGenStyles::NamedStyle>::const_iterator it = styleList.begin();
00346 
00347     for ( ; it != styleList.end(); ++it) {
00348         (*it).style->writeStyle(styleWriter, styles, "style:page-layout", (*it).name, "style:page-layout-properties");
00349     }
00350 
00351     styleList = styles.styles(Kivio::STYLE_PAGE);
00352     it = styleList.begin();
00353 
00354     for ( ; it != styleList.end(); ++it) {
00355         (*it).style->writeStyle(styleWriter, styles, "style:style", (*it).name, "style:properties");
00356     }
00357 
00358     styleWriter->endElement(); // office:automatic-styles
00359 
00360     styleList = styles.styles(KoGenStyle::STYLE_MASTER);
00361     it = styleList.begin();
00362     styleWriter->startElement("office:master-styles");
00363 
00364     for ( ; it != styleList.end(); ++it) {
00365         (*it).style->writeStyle(styleWriter, styles, "style:master-page", (*it).name, "");
00366     }
00367 
00368     styleWriter->endElement(); // office:master-styles
00369 
00370     styleWriter->endElement(); // Root element
00371     styleWriter->endDocument();
00372     delete styleWriter;
00373 
00374     if(!store->close()) {
00375         return false;
00376     }
00377 
00378     manifestWriter->addManifestEntry("styles.xml", "text/xml");
00379 
00380     if(!store->open("settings.xml")) {
00381         return false;
00382     }
00383 
00384 
00385     KoXmlWriter* settingsWriter = createOasisXmlWriter(&storeDev, "office:document-settings");
00386     settingsWriter->startElement("office:settings");
00387     settingsWriter->startElement("config:config-item-set");
00388     settingsWriter->addAttribute("config:name", "view-settings");
00389 
00390     KoUnit::saveOasis( settingsWriter, unit() );
00391     saveOasisSettings( *settingsWriter );
00392 
00393     settingsWriter->endElement(); // config:config-item-set
00394     settingsWriter->endElement(); // office:settings
00395     settingsWriter->endDocument();
00396 
00397     delete settingsWriter;
00398 
00399     if(!store->close()) {
00400         return false;
00401     }
00402 
00403     manifestWriter->addManifestEntry("settings.xml", "text/xml");
00404 
00405     setModified(false);
00406     return true;
00407 }
00408 
00409 void KivioDoc::saveOasisSettings( KoXmlWriter &/*settingsWriter*/ )
00410 {
00411     //todo
00412 }
00413 
00414 bool KivioDoc::loadOasis( const QDomDocument& doc, KoOasisStyles& oasisStyles, const QDomDocument& settings, KoStore* )
00415 {
00416   kdDebug(43000) << "Start loading OASIS document..." << endl;
00417   m_bLoading = true;
00418 
00419   QDomElement contents = doc.documentElement();
00420   QDomElement body(KoDom::namedItemNS( contents, KoXmlNS::office, "body"));
00421 
00422   if(body.isNull()) {
00423     kdDebug(43000) << "No office:body found!" << endl;
00424     setErrorMessage(i18n("Invalid OASIS document. No office:body tag found."));
00425     m_bLoading = false;
00426     return false;
00427   }
00428 
00429   body = KoDom::namedItemNS( body, KoXmlNS::office, "drawing");
00430 
00431   if(body.isNull()) {
00432     kdDebug(43000) << "No office:drawing found!" << endl;
00433     setErrorMessage(i18n("Invalid OASIS document. No office:drawing tag found."));
00434     m_bLoading = false;
00435     return false;
00436   }
00437 
00438   QDomNode node = body.firstChild();
00439   QString localName;
00440   m_pMap->clear();
00441 
00442   // TODO: port to forEachElement
00443   while(!node.isNull()) {
00444     localName = node.localName();
00445 
00446     if(localName == "page" /* && and namespace is KoXmlNS::draw*/) {
00447       KivioPage* p = createPage();
00448       addPage(p);
00449 
00450       if(!p->loadOasis(node.toElement(), oasisStyles)) {
00451         m_bLoading = false;
00452         return false;
00453       }
00454     }
00455 
00456     node = node.nextSibling();
00457   }
00458 
00459   loadOasisSettings( settings );
00460 
00461   emit loadingFinished();
00462   return true;
00463 }
00464 
00465 
00466 void KivioDoc::loadOasisSettings( const QDomDocument&settingsDoc )
00467 {
00468     if ( settingsDoc.isNull() )
00469         return ; //not a error some file doesn't have settings.xml
00470     KoOasisSettings settings( settingsDoc );
00471     KoOasisSettings::Items viewSettings = settings.itemSet( "view-settings" );
00472     if ( !viewSettings.isNull() )
00473     {
00474         setUnit(KoUnit::unit(viewSettings.parseConfigItemString("unit")));
00475         //todo add other config here.
00476     }
00477 }
00478 
00479 bool KivioDoc::loadXML( QIODevice *, const QDomDocument& doc )
00480 {
00481   m_bLoading = true;
00482 
00483   if ( doc.doctype().name() != "kiviodoc" ) {
00484     m_bLoading = false;
00485     return false;
00486   }
00487 
00488   QDomElement kivio = doc.documentElement();
00489   if ( kivio.attribute( "mime" ) != "application/x-kivio" &&
00490     kivio.attribute( "mime" ) != "application/vnd.kde.kivio" )
00491   {
00492     kdDebug(43000) << "KivioDoc::loadXML() - Invalid mime type" << endl;
00493     m_bLoading = false;
00494     return false;
00495   }
00496 
00497   QDomNode node = kivio.firstChild();
00498   while( !node.isNull() )
00499   {
00500     QString name = node.nodeName();
00501     if( name == "KivioMap" )
00502     {
00503         if( !m_pMap->loadXML( node.toElement() ) )
00504         {
00505             m_bLoading = false;
00506             return false;
00507         }
00508     }
00509     else if( name == "KivioStencilSpawnerSet" )
00510     {
00511         QString id = XmlReadString( node.toElement(), "id", "" );
00512         bool hidden = (XmlReadString(node.toElement(), "hidden", "false") == "true");
00513 
00514         if( id.isEmpty() )
00515         {
00516             kdDebug(43000) << "KivioDoc::loadXML() - Bad KivioStencilSpawnerSet found, it contains no id!" << endl;
00517         }
00518         else
00519         {
00520             loadStencilSpawnerSet(id, hidden);
00521         }
00522     }
00523     else if( name == "Options" )
00524     {
00525         // Not used anymore use users default page instead from Settings to create new pages...
00526     }
00527     else
00528     {
00529        kdDebug(43000) << "KivioDoc::loadXML() - Unknown node " <<  name << endl;
00530     }
00531 
00532     node = node.nextSibling();
00533   }
00534 
00535   QString us = kivio.attribute("units", Kivio::Config::unit());
00536   bool isInt = false;
00537   int u = us.toInt(&isInt);
00538 
00539   if(!isInt) {
00540     setUnit(KoUnit::unit(us));
00541   } else {
00542     setUnit(Kivio::convToKoUnit(u));
00543   }
00544 
00545   if(kivio.hasAttribute("gridIsShow")) {
00546     gridData.load(kivio,"grid");
00547   }
00548 
00549   emit loadingFinished();
00550   return true;
00551 }
00552 
00553 bool KivioDoc::loadStencilSpawnerSet(const QString &id, bool hidden)
00554 {
00555   KStandardDirs *dirs = KGlobal::dirs();
00556   QStringList dirList = dirs->findDirs("data", "kivio/stencils");
00557   QString rootDir;
00558 
00559   // Iterate through all data directories
00560   for( QStringList::Iterator it = dirList.begin(); it != dirList.end(); ++it )
00561   {
00562     rootDir = (*it);
00563 
00564     // Within each data directory, iterate through all directories looking
00565     // for a filename (dir) that matches the parameter
00566     QDir d(rootDir);
00567     d.setFilter( QDir::Dirs );
00568     d.setSorting( QDir::Name );
00569 
00570     const QFileInfoList *list = d.entryInfoList();
00571     QFileInfoListIterator listIT( *list );
00572     QFileInfo *fi;
00573 
00574     // Loop through the outer directories (like BasicFlowcharting)
00575     while( (fi=listIT.current()) )
00576     {
00577       if( fi->fileName() != "." &&
00578           fi->fileName() != ".." )
00579       {
00580         QDir innerD(fi->absFilePath() );
00581         innerD.setFilter( QDir::Dirs );
00582         innerD.setSorting( QDir::Name );
00583 
00584         const QFileInfoList *innerList = innerD.entryInfoList();
00585         QFileInfoListIterator innerIT( *innerList );
00586         QFileInfo *innerFI;
00587 
00588         // Loop through the inner directories (like FlowChartingShapes1)
00589         while( (innerFI = innerIT.current()) )
00590         {
00591           if( innerFI->fileName() != ".." &&
00592               innerFI->fileName() != "." )
00593           {
00594             // Compare the descriptions
00595             QString foundId;
00596 
00597             // TODO: use ID system here for loading
00598             foundId = KivioStencilSpawnerSet::readId(innerFI->absFilePath());
00599             if( foundId == id)
00600             {
00601 
00602               // Load the spawner set with  rootDir + "/" + fi.fileName()
00603               addSpawnerSetDuringLoad(innerFI->absFilePath(), hidden);
00604               return true;
00605             }
00606           }
00607 
00608           ++innerIT;
00609         }
00610       }
00611 
00612       ++listIT;
00613     }
00614   }
00615 
00616   return false;
00617 }
00618 
00619 bool KivioDoc::completeLoading( KoStore* )
00620 {
00621   m_bLoading = false;
00622   m_pMap->update();
00623   setModified( false );
00624   return true;
00625 }
00626 
00627 KivioPage* KivioDoc::createPage()
00628 {
00629   QString s( i18n("Page%1") );
00630   s = s.arg( m_iPageId++ );
00631 
00632   KivioPage* t = new KivioPage(m_pMap, s);
00633   t->setPageName(s,true);
00634 
00635   return t;
00636 }
00637 
00638 void KivioDoc::addPage( KivioPage* page )
00639 {
00640   m_pMap->addPage(page);
00641   setModified(true);
00642   emit sig_addPage(page);
00643 }
00644 
00645 void KivioDoc::insertPage( KivioPage * page )
00646 {
00647     QPtrListIterator<KoView> it( views() );
00648     for (; it.current(); ++it )
00649     ((KivioView*)it.current())->insertPage( page );
00650 }
00651 
00652 void KivioDoc::takePage( KivioPage * page )
00653 {
00654     QPtrListIterator<KoView> it( views() );
00655     for (; it.current(); ++it )
00656     ((KivioView*)it.current())->removePage( page );
00657 }
00658 
00659 
00660 void KivioDoc::paintContent( QPainter& painter, const QRect& rect, bool transparent, double /*zoomX*/, double /*zoomY*/ )
00661 {
00662   KivioPage* page = m_pMap->firstPage();
00663   if ( !page )
00664     return;
00665 
00666   KoZoomHandler zoom;
00667   zoom.setZoomAndResolution(100, KoGlobal::dpiX(),
00668     KoGlobal::dpiY());
00669   KoRect r = page->getRectForAllStencils();
00670 
00671   float zw = (float) rect.width() / (float)zoom.zoomItX(r.width());
00672   float zh = (float) rect.height() / (float)zoom.zoomItY(r.height());
00673   float z = QMIN(zw, zh);
00674   //kdDebug(43000) << "paintContent: w = " << rect.width() << " h = " << rect.height() << endl;
00675 
00676   zoom.setZoomAndResolution(qRound(z * 100), KoGlobal::dpiX(),
00677     KoGlobal::dpiY());
00678   KivioScreenPainter ksp(&painter);
00679   ksp.painter()->translate( - zoom.zoomItX(r.x()), - zoom.zoomItY(r.y()) );
00680   paintContent(ksp,rect,transparent,page, QPoint(zoom.zoomItX(r.x()), zoom.zoomItY(r.y())), &zoom, false, false);
00681   ksp.setPainter(0L); // Important! Don't delete the QPainter!!!
00682 }
00683 
00684 void KivioDoc::paintContent( KivioPainter& painter, const QRect& rect, bool transparent, KivioPage* page, QPoint p0, KoZoomHandler* zoom, bool drawConnectorTargets, bool drawSelection )
00685 {
00686   if ( isLoading() )
00687     return;
00688 
00689   page->paintContent(painter,rect,transparent,p0,zoom, drawConnectorTargets, drawSelection);
00690 }
00691 
00692 void KivioDoc::printContent( KPrinter &prn )
00693 {
00694   KivioScreenPainter p;
00695   QValueList<int> pages = prn.pageList();
00696   KivioPage *pPage;
00697 
00698   // ### HACK: disable zooming-when-printing if embedded parts are used.
00699   // No koffice app supports zooming in paintContent currently.
00700   // Disable in ALL cases now
00701   bool doZoom = false;
00702   int dpiX = doZoom ? 300 : KoGlobal::dpiX();
00703   int dpiY = doZoom ? 300 : KoGlobal::dpiY();
00704 
00705   p.start(&prn);
00706 
00707   QPaintDeviceMetrics metrics( &prn );
00708   p.painter()->scale( (double)metrics.logicalDpiX() / (double)dpiX,
00709     (double)metrics.logicalDpiY() / (double)dpiY );
00710 
00711   QValueList<int>::iterator it;
00712 
00713   for(it = pages.begin(); it != pages.end(); ++it) {
00714     pPage = m_pMap->pageList().at((*it)-1);
00715     pPage->printContent(p, dpiX, dpiY);
00716 
00717     if( it != (--pages.end()) ) {
00718       prn.newPage();
00719     }
00720   }
00721 
00722   p.stop();
00723 }
00724 
00725 // TODO: Fix for id system
00726 KivioStencilSpawnerSet* KivioDoc::findSpawnerSet(const QString& dirName, const QString& id)
00727 {
00728     KivioStencilSpawnerSet *pSet = m_pLstSpawnerSets->first();
00729     while(pSet)
00730     {
00731         if( pSet->dir() == dirName || pSet->id() == id )
00732         {
00733             return pSet;
00734         }
00735 
00736         pSet = m_pLstSpawnerSets->next();
00737     }
00738 
00739     return 0;
00740 }
00741 
00742 void KivioDoc::addSpawnerSet( const QString &dirName )
00743 {
00744   QString id = KivioStencilSpawnerSet::readId( dirName );
00745   KivioStencilSpawnerSet* set = findSpawnerSet(dirName, id);
00746 
00747   if(set)
00748   {
00749     // Unhide the set if it's only hidden
00750     if(set->hidden()) {
00751       set->setHidden(false);
00752       emit sig_addSpawnerSet(set);
00753     }
00754 
00755     return;
00756   }
00757 
00758 
00759   set = new KivioStencilSpawnerSet();
00760 
00761   if(!set->loadDir(dirName))
00762   {
00763     kdDebug(43000) << "KivioDoc::addSpawnerSet() - Error loading dir set" << endl;
00764     delete set;
00765     return;
00766   }
00767 
00768   // Queue set for loading stencils
00769   m_stencilSetLoadQueue.append(set);
00770 
00771   if(!m_loadTimer) {
00772     m_loadTimer = new QTimer(this);
00773     connect(m_loadTimer, SIGNAL(timeout()), this, SLOT(loadStencil()));
00774   }
00775 
00776   if(!m_loadTimer->isActive()) {
00777     emit initProgress();
00778     m_loadTimer->start(0, false);
00779   }
00780 }
00781 
00782 void KivioDoc::addSpawnerSetDuringLoad(const QString& dirName, bool hidden)
00783 {
00784   KivioStencilSpawnerSet *set;
00785 
00786   set = new KivioStencilSpawnerSet();
00787   set->setHidden(hidden);
00788 
00789   if( set->loadDir(dirName)==false )
00790   {
00791     kdDebug(43000) << "KivioDoc::addSpawnerSetDuringLoad() - Error loading dir set" << endl;
00792     delete set;
00793     return;
00794   }
00795 
00796   QStringList::iterator it;
00797   QStringList files = set->files();
00798 
00799   for(it = files.begin(); it != files.end(); ++it) {
00800     QString fileName = set->dir() + "/" + (*it);
00801     set->loadFile(fileName);
00802   }
00803 
00804   m_pLstSpawnerSets->append(set);
00805 }
00806 
00807 KivioDoc::~KivioDoc()
00808 {
00809   if(m_docOpened) {
00810     saveConfig();
00811   }
00812 
00813   // ***MUST*** Delete the pages first because they may
00814   // contain plugins which will be unloaded soon.  The stencils which are
00815   // spawned by plugins NEED the plugins still loaded when their destructor
00816   // is called or the program will slit it's throat.
00817   delete m_pMap;
00818   delete dcop;
00819   delete m_commandHistory;
00820 
00821   delete m_pLstSpawnerSets;
00822   m_pLstSpawnerSets = 0;
00823 
00824   s_docs->removeRef(this);
00825 }
00826 
00827 void KivioDoc::saveConfig()
00828 {
00829   Kivio::Config::self()->writeConfig();
00830 }
00831 
00832 void KivioDoc::initConfig()
00833 {
00834   setUnit( KoUnit::unit(Kivio::Config::unit()) );
00835   m_font = Kivio::Config::font();
00836   m_pageLayout = Kivio::Config::defaultPageLayout();
00837 }
00838 
00839 bool KivioDoc::removeSpawnerSet( KivioStencilSpawnerSet *pSet )
00840 {
00841     return m_pLstSpawnerSets->removeRef( pSet );
00842 }
00843 
00848 void KivioDoc::slotDeleteStencilSet( DragBarButton *pBtn, QWidget *w, KivioStackBar *pBar )
00849 {
00850   KivioIconView* pIconView = static_cast<KivioIconView*>(w);
00851   KivioStencilSpawnerSet* pSet = pIconView->spawnerSet();
00852 
00853   // Only actually remove the set if it isn't used...
00854   if(!checkStencilsForSpawnerSet(pSet)) {
00855     removeSpawnerSet(pSet);
00856   } else {
00857     pSet->setHidden(true);
00858   }
00859 
00860   // And emit the signal to kill the set (page & button)
00861   emit sig_deleteStencilSet(pBtn, w, pBar);
00862 }
00863 
00867 bool KivioDoc::checkStencilsForSpawnerSet(KivioStencilSpawnerSet* spawnerSet)
00868 {
00869   KivioPage *pPage = m_pMap->firstPage();
00870   KivioLayer *pLayer;
00871   KivioStencil *pStencil;
00872 
00873   // Iterate across all the pages
00874   while(pPage) {
00875     pLayer = pPage->layers()->first();
00876 
00877     while(pLayer) {
00878       pStencil = pLayer->stencilList()->first();
00879 
00880       while(pStencil) {
00881         // If this is a group stencil, then we must check all child stencils
00882         if(pStencil->groupList() && pStencil->groupList()->count() > 0) {
00883           if(checkGroupForSpawnerSet(pStencil, spawnerSet)) {
00884             return true;
00885           }
00886         } else if(pStencil->spawner()->set() == spawnerSet) {
00887           return true;
00888         }
00889 
00890         pStencil = pLayer->stencilList()->next();
00891       }
00892 
00893       pLayer = pPage->layers()->next();
00894     }
00895 
00896     pPage = m_pMap->nextPage();
00897   }
00898 
00899   return false;
00900 }
00901 
00902 bool KivioDoc::checkGroupForSpawnerSet(KivioStencil* pGroup, KivioStencilSpawnerSet* spawnerSet)
00903 {
00904   KivioStencil *pStencil = pGroup->groupList()->first();
00905 
00906   while(pStencil) {
00907     if(pStencil->groupList() && pStencil->groupList()->count() > 0) {
00908       if(checkGroupForSpawnerSet(pStencil, spawnerSet))
00909         return true;
00910     } else if(pStencil->spawner()->set() == spawnerSet) {
00911       return true;
00912     }
00913 
00914     pStencil = pGroup->groupList()->next();
00915   }
00916 
00917   return false;
00918 }
00919 
00920 void KivioDoc::slotSelectionChanged()
00921 {
00922     emit sig_selectionChanged();
00923 }
00924 
00925 KivioStencilSpawner* KivioDoc::findStencilSpawner( const QString& setId, const QString& stencilId )
00926 {
00927     KivioStencilSpawnerSet *pSpawnerSet = m_pLstSpawnerSets->first();
00928     while( pSpawnerSet )
00929     {
00930         if( pSpawnerSet->id() == setId && pSpawnerSet->find(stencilId) )
00931         {
00932             return pSpawnerSet->find(stencilId);
00933         // return pSpawnerSet->find(name)
00934         }
00935         pSpawnerSet = m_pLstSpawnerSets->next();
00936     }
00937 
00938     if( m_pInternalSet->id() == setId && m_pInternalSet->find(stencilId) )
00939     {
00940         return m_pInternalSet->find(stencilId);
00941     }
00942 
00943     return NULL;
00944 }
00945 
00946 KivioStencilSpawner* KivioDoc::findInternalStencilSpawner( const QString& stencilId )
00947 {
00948     return m_pInternalSet->find(stencilId);
00949 }
00950 
00951 void KivioDoc::addInternalStencilSpawner(KivioStencilSpawner* spawner)
00952 {
00953   m_pInternalSet->addSpawner(spawner);
00954 }
00955 
00956 void KivioDoc::updateView(KivioPage* page)
00957 {
00958   emit sig_updateView(page);
00959 }
00960 
00961 void KivioDoc::updateButton()
00962 {
00963     QPtrListIterator<KoView> it( views() );
00964     for (; it.current(); ++it )
00965     ((KivioView*)it.current())->updateButton();
00966 }
00967 
00968 void KivioDoc::resetLayerPanel()
00969 {
00970     QPtrListIterator<KoView> it( views() );
00971     for (; it.current(); ++it )
00972     ((KivioView*)it.current())->resetLayerPanel();
00973 }
00974 
00975 void KivioDoc::addCommand( KCommand * cmd )
00976 {
00977     kdDebug(43000) << "KivioDoc::addCommand " << cmd->name() << endl;
00978     m_commandHistory->addCommand( cmd, false );
00979     setModified( true );
00980 }
00981 
00982 int KivioDoc::undoRedoLimit() const
00983 {
00984     return m_commandHistory->undoLimit();
00985 }
00986 
00987 void KivioDoc::setUndoRedoLimit(int val)
00988 {
00989     m_commandHistory->setUndoLimit(val);
00990     m_commandHistory->setRedoLimit(val);
00991 }
00992 
00993 void KivioDoc::slotDocumentRestored()
00994 {
00995     setModified( false );
00996 }
00997 
00998 void KivioDoc::slotCommandExecuted()
00999 {
01000     setModified( true );
01001 }
01002 
01003 void KivioDoc::updateProtectPanelCheckBox()
01004 {
01005     QPtrListIterator<KoView> it( views() );
01006     for (; it.current(); ++it )
01007       ((KivioView*)it.current())->updateProtectPanelCheckBox();
01008 }
01009 
01010 void KivioDoc::loadStencil()
01011 {
01012   KivioStencilSpawnerSet* set = m_stencilSetLoadQueue.first();
01013   QString fileName = set->dir() + "/" + set->files()[m_currentFile];
01014   set->loadFile(fileName);
01015   m_currentFile++;
01016   emit progress(qRound(((float)m_currentFile / (float)set->files().count()) * 100.0));
01017 
01018   if(m_currentFile >= set->files().count()) {
01019     m_pLstSpawnerSets->append(set);
01020 
01021     if(!m_bLoading) {
01022       setModified(true);
01023       emit sig_addSpawnerSet(set);
01024     }
01025 
01026     m_currentFile = 0;
01027     set = 0;
01028     m_stencilSetLoadQueue.pop_front();
01029 
01030     if(m_stencilSetLoadQueue.isEmpty()) {
01031       m_loadTimer->stop();
01032       emit endProgress();
01033     } else {
01034       emit initProgress();
01035     }
01036   }
01037 }
01038 
01039 void KivioDoc::updateGuideLines(KoView* sender)
01040 {
01041   QValueList<double> hGuideLines;
01042   QValueList<double> vGuideLines;
01043   KivioView* view = static_cast<KivioView*>(sender);
01044   view->canvasWidget()->guideLines().getGuideLines(hGuideLines, vGuideLines);
01045   view->activePage()->setGuideLines(hGuideLines, vGuideLines);
01046 
01047   QPtrListIterator<KoView> it(views());
01048   KivioView* itView = 0;
01049 
01050   for (; it.current(); ++it ) {
01051     itView = static_cast<KivioView*>(it.current());
01052     if(it.current() != sender && (itView->activePage() == view->activePage())) {
01053       itView->canvasWidget()->guideLines().setGuideLines(hGuideLines, vGuideLines);
01054     }
01055   }
01056 }
01057 
01058 void KivioDoc::updateGuideLines(KivioPage* page)
01059 {
01060   QValueList<double> hGuideLines = page->horizontalGuideLines();
01061   QValueList<double> vGuideLines = page->verticalGuideLines();
01062   QPtrListIterator<KoView> it(views());
01063   KivioView* itView = 0;
01064 
01065   for (; it.current(); ++it ) {
01066     itView = static_cast<KivioView*>(it.current());
01067     if(itView->activePage() == page) {
01068       itView->canvasWidget()->guideLines().setGuideLines(hGuideLines, vGuideLines);
01069     }
01070   }
01071 }
01072 
01073 #include "kivio_doc.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys