kivio

kivio_doc.cpp
1/*
2 * Kivio - Visual Modelling and Flowcharting
3 * Copyright (C) 2000-2001 theKompany.com & Dave Marotti
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19#include <tqdom.h>
20#include <tqtextstream.h>
21#include <tqbuffer.h>
22#include <tqtabwidget.h>
23#include <tqpaintdevicemetrics.h>
24
25#include "kivio_doc.h"
26#include "kivio_page.h"
27#include "kivio_map.h"
28#include "kivio_view.h"
29#include "kivio_factory.h"
30#include "export_page_dialog.h"
31#include "kivio_common.h"
32#include "kivio_group_stencil.h"
33#include "kivio_icon_view.h"
34#include "kivio_layer.h"
35#include "kivio_painter.h"
36#include "kivio_screen_painter.h"
37#include "kivio_stencil.h"
38#include "kivio_stencil_spawner_set.h"
39#include "kivioglobal.h"
40#include "kivio_config.h"
41#include "polylineconnectorspawner.h"
42#include "kivio_canvas.h"
43
44#include "stencilbarbutton.h"
45
46#include <unistd.h>
47#include <tdemessagebox.h>
48#include <tdelocale.h>
49#include <kprinter.h>
50#include <kdebug.h>
51#include <kurl.h>
52#include <tdeapplication.h>
53#include <assert.h>
54#include <tqdatetime.h>
55#include <sys/types.h>
56#include <dirent.h>
57#include <sys/stat.h>
58#include <pwd.h>
59#include <tqdir.h>
60#include <tqfileinfo.h>
61#include <tqfile.h>
62#include <tqpixmap.h>
63
64#include <tqpainter.h>
65#include <tqpen.h>
66#include <tqfont.h>
67#include <tqvaluelist.h>
68
69
70#include <kstandarddirs.h>
71#include <tdepopupmenu.h>
72#include <tdemenubar.h>
73#include <kiconloader.h>
74#include <khelpmenu.h>
75#include <tdeconfig.h>
76#include <KoTemplateChooseDia.h>
77#include <KoFilterManager.h>
78#include <KoStoreDevice.h>
79#include "KIvioDocIface.h"
80#include <kcommand.h>
81#include <KoZoomHandler.h>
82#include <KoApplication.h>
83#include <tdeglobal.h>
84#include <KoCommandHistory.h>
85#include <KoXmlWriter.h>
86#include <KoGenStyles.h>
87#include <KoOasisSettings.h>
88#include <KoDom.h>
89#include <KoXmlNS.h>
90
91//using namespace std;
92
93/*****************************************************************************
94 *
95 * KivioDoc
96 *
97 *****************************************************************************/
98
99TQPtrList<KivioDoc>* KivioDoc::s_docs = 0;
100int KivioDoc::s_docId = 0;
101
102KivioDoc::KivioDoc( TQWidget *parentWidget, const char* widgetName, TQObject* parent, const char* name, bool singleViewMode )
103: KoDocument( parentWidget, widgetName, parent, name, singleViewMode )
104{
105 dcop = 0;
106 if (!s_docs)
107 s_docs = new TQPtrList<KivioDoc>;
108
109 s_docs->append(this);
110
111 m_pLstSpawnerSets = new TQPtrList<KivioStencilSpawnerSet>;
112 m_pLstSpawnerSets->setAutoDelete(true);
113 m_loadTimer = 0;
114 m_currentFile = 0;
115
116 setInstance( KivioFactory::global(), false );
117 setTemplateType("kivio_template");
118
119 if ( !name )
120 {
121 TQString tmp( "Document%1" ); //lukas: FIXME
122 tmp = tmp.arg( s_docId++ );
123 setName( tmp.latin1() );
124 }
125
126 m_iPageId = 1;
127 m_bLoading = false;
128 m_pMap = new KivioMap( this, "Map" );
129
130 // Load autoLoadStencils in internal StencilSpawnerSet
131 m_pInternalSet = new KivioStencilSpawnerSet("Kivio_Internal");
132 m_pInternalSet->setId("Kivio - Internal - Do Not Touch");
133 TQStringList list = instance()->dirs()->findAllResources("data",instance()->instanceName()+"/autoloadStencils/*",true,false);
134 TQStringList::ConstIterator pIt = list.begin();
135 TQStringList::ConstIterator pEnd = list.end();
136
137 for (; pIt != pEnd; ++pIt )
138 {
139 m_pInternalSet->loadFile(*pIt);
140 }
141
142 // Add the polyline connector spawner to the internal stencil set.
143 addInternalStencilSpawner(new Kivio::PolyLineConnectorSpawner(internalSpawnerSet()));
144
145 initConfig();
146
147 //laurent: Why don't use menu history for undo/redo command ? sync with other koffice application
148 m_commandHistory = new KoCommandHistory( actionCollection(), /*false*/true ) ;
149 connect( m_commandHistory, TQ_SIGNAL( documentRestored() ), this, TQ_SLOT( slotDocumentRestored() ) );
150 connect( m_commandHistory, TQ_SIGNAL( commandExecuted() ), this, TQ_SLOT( slotCommandExecuted() ) );
151
152
153 if ( name )
154 dcopObject();
155}
156
157DCOPObject* KivioDoc::dcopObject()
158{
159 if ( !dcop ) {
160 dcop = new KIvioDocIface( this );
161 }
162
163 return dcop;
164}
165
166TQPtrList<KivioDoc>& KivioDoc::documents()
167{
168 if ( s_docs == 0 ) {
169 s_docs = new TQPtrList<KivioDoc>;
170 }
171
172 return *s_docs;
173}
174
175bool KivioDoc::initDoc(InitDocFlags flags, TQWidget* parentWidget)
176{
177 KivioPage *t = createPage();
178 m_pMap->addPage( t );
179 m_docOpened = false; // Used to for a hack that make kivio not crash if you cancel startup dialog.
180
181 if(flags == KoDocument::InitDocEmpty) {
182 setEmpty();
183 m_docOpened = true; // Used to for a hack that make kivio not crash if you cancel startup dialog.
184 return true;
185 }
186
187 TQString f;
188 KoTemplateChooseDia::ReturnType ret;
189 KoTemplateChooseDia::DialogType dlgtype;
190
191 if(flags != KoDocument::InitDocFileNew) {
192 dlgtype = KoTemplateChooseDia::Everything;
193 initConfig();
194 } else {
195 dlgtype = KoTemplateChooseDia::OnlyTemplates;
196 }
197
198 ret = KoTemplateChooseDia::choose( KivioFactory::global(), f,
199 dlgtype, "kivio_template", parentWidget );
200
201 if( ret == KoTemplateChooseDia::File ) {
202 KURL url(f);
203 bool ok = openURL(url);
204 m_docOpened = ok; // Used to for a hack that make kivio not crash if you cancel startup dialog.
205 return ok;
206 } else if ( ret == KoTemplateChooseDia::Template ) {
207 TQFileInfo fileInfo( f );
208 TQString fileName( fileInfo.dirPath(true) + "/" + fileInfo.baseName() + ".kft" );
209 resetURL();
210 bool ok = loadNativeFormat( fileName );
211 if ( !ok )
212 showLoadingErrorDialog();
213 setEmpty();
214 m_docOpened = ok; // Used to for a hack that make kivio not crash if you cancel startup dialog.
215 return ok;
216 } else if ( ret == KoTemplateChooseDia::Empty ) {
217 setEmpty();
218 m_docOpened = true; // Used to for a hack that make kivio not crash if you cancel startup dialog.
219 return true;
220 } else {
221 return false;
222 }
223}
224
225void KivioDoc::openExistingFile( const TQString& file )
226{
227 KivioPage* t = createPage();
228 m_pMap->addPage(t);
229
230 KoDocument::openExistingFile(file);
231}
232
233void KivioDoc::openTemplate( const TQString& file )
234{
235 KivioPage* t = createPage();
236 m_pMap->addPage(t);
237
238 KoDocument::openTemplate(file);
239}
240
241void KivioDoc::initEmpty()
242{
243 KivioPage* t = createPage();
244 m_pMap->addPage(t);
245 KoDocument::initEmpty();
246}
247
248KoView* KivioDoc::createViewInstance( TQWidget* parent, const char* name )
249{
250 if (!name) {
251 name = "View";
252 }
253
254 return new KivioView( parent, name, this );
255}
256
257TQDomDocument KivioDoc::saveXML()
258{
259 TQDomDocument doc( "kiviodoc" );
260 doc.appendChild( doc.createProcessingInstruction( "xml", "version=\"1.0\" encoding=\"UTF-8\"" ) );
261 TQDomElement kivio = doc.createElement( "kiviosheet" );
262 kivio.setAttribute( "editor", "Kivio" );
263 kivio.setAttribute( "mime", MIME_TYPE );
264
265 kivio.setAttribute( "units", unitName() );
266 gridData.save(kivio,"grid");
267
268 TQDomElement viewItemsElement = doc.createElement("ViewItems");
269 kivio.appendChild(viewItemsElement);
270
271 doc.appendChild(kivio);
272
273 // Save the list of stencils spawners we have loaded.
274 // We save these as the following:
275 //
276 // <KivioStencilSpawnerSet id="whatever the id is">
277 // <KivioSMLStencilSpawner id="whatever the id is"/>
278 // <KivioSMLStencilSpawner id="whatever the id is"/>
279 // </KivioStencilSpawnerSet>
280 // ....
281 //
282 // This is so we can load them back in, and check that we actually
283 // have all these spawners on disk.
284 KivioStencilSpawnerSet *pSet = m_pLstSpawnerSets->first();
285 while( pSet )
286 {
287 if(checkStencilsForSpawnerSet(pSet)) {
288 kivio.appendChild(pSet->saveXML(doc));
289 }
290
291 pSet = m_pLstSpawnerSets->next();
292 }
293
294
295 TQDomElement e = m_pMap->save(doc);
296 kivio.appendChild(e);
297
298 setModified(false);
299 return doc;
300}
301
302bool KivioDoc::saveOasis(KoStore* store, KoXmlWriter* manifestWriter)
303{
304 KoStoreDevice storeDev(store);
305 KoGenStyles styles;
306
307 KoGenStyle pageLayout = Kivio::Config::defaultPageLayout().saveOasis();
308 TQString layoutName = styles.lookup(pageLayout, "PL");
309 KoGenStyle masterPage(KoGenStyle::STYLE_MASTER);
310 masterPage.addAttribute("style:page-layout-name", layoutName);
311 styles.lookup(masterPage, "Standard", false);
312
313 if(!store->open("content.xml")) {
314 return false;
315 }
316
317 KoXmlWriter* docWriter = createOasisXmlWriter(&storeDev, "office:document-content");
318
319 docWriter->startElement("office:body");
320 docWriter->startElement("office:drawing");
321
322 m_pMap->saveOasis(store, docWriter, &styles); // Save contents
323
324 docWriter->endElement(); // office:drawing
325 docWriter->endElement(); // office:body
326 docWriter->endElement(); // Root element
327 docWriter->endDocument();
328 delete docWriter;
329
330 if(!store->close()) {
331 return false;
332 }
333
334 manifestWriter->addManifestEntry("content.xml", "text/xml");
335
336 if(!store->open("styles.xml")) {
337 return false;
338 }
339
340 KoXmlWriter* styleWriter = createOasisXmlWriter(&storeDev, "office:document-styles");
341
342 styleWriter->startElement("office:automatic-styles");
343
344 TQValueList<KoGenStyles::NamedStyle> styleList = styles.styles(KoGenStyle::STYLE_PAGELAYOUT);
345 TQValueList<KoGenStyles::NamedStyle>::const_iterator it = styleList.begin();
346
347 for ( ; it != styleList.end(); ++it) {
348 (*it).style->writeStyle(styleWriter, styles, "style:page-layout", (*it).name, "style:page-layout-properties");
349 }
350
351 styleList = styles.styles(Kivio::STYLE_PAGE);
352 it = styleList.begin();
353
354 for ( ; it != styleList.end(); ++it) {
355 (*it).style->writeStyle(styleWriter, styles, "style:style", (*it).name, "style:properties");
356 }
357
358 styleWriter->endElement(); // office:automatic-styles
359
360 styleList = styles.styles(KoGenStyle::STYLE_MASTER);
361 it = styleList.begin();
362 styleWriter->startElement("office:master-styles");
363
364 for ( ; it != styleList.end(); ++it) {
365 (*it).style->writeStyle(styleWriter, styles, "style:master-page", (*it).name, "");
366 }
367
368 styleWriter->endElement(); // office:master-styles
369
370 styleWriter->endElement(); // Root element
371 styleWriter->endDocument();
372 delete styleWriter;
373
374 if(!store->close()) {
375 return false;
376 }
377
378 manifestWriter->addManifestEntry("styles.xml", "text/xml");
379
380 if(!store->open("settings.xml")) {
381 return false;
382 }
383
384
385 KoXmlWriter* settingsWriter = createOasisXmlWriter(&storeDev, "office:document-settings");
386 settingsWriter->startElement("office:settings");
387 settingsWriter->startElement("config:config-item-set");
388 settingsWriter->addAttribute("config:name", "view-settings");
389
390 KoUnit::saveOasis( settingsWriter, unit() );
391 saveOasisSettings( *settingsWriter );
392
393 settingsWriter->endElement(); // config:config-item-set
394 settingsWriter->endElement(); // office:settings
395 settingsWriter->endDocument();
396
397 delete settingsWriter;
398
399 if(!store->close()) {
400 return false;
401 }
402
403 manifestWriter->addManifestEntry("settings.xml", "text/xml");
404
405 setModified(false);
406 return true;
407}
408
409void KivioDoc::saveOasisSettings( KoXmlWriter &/*settingsWriter*/ )
410{
411 //todo
412}
413
414bool KivioDoc::loadOasis( const TQDomDocument& doc, KoOasisStyles& oasisStyles, const TQDomDocument& settings, KoStore* )
415{
416 kdDebug(43000) << "Start loading OASIS document..." << endl;
417 m_bLoading = true;
418
419 TQDomElement contents = doc.documentElement();
420 TQDomElement body(KoDom::namedItemNS( contents, KoXmlNS::office, "body"));
421
422 if(body.isNull()) {
423 kdDebug(43000) << "No office:body found!" << endl;
424 setErrorMessage(i18n("Invalid OASIS document. No office:body tag found."));
425 m_bLoading = false;
426 return false;
427 }
428
429 body = KoDom::namedItemNS( body, KoXmlNS::office, "drawing");
430
431 if(body.isNull()) {
432 kdDebug(43000) << "No office:drawing found!" << endl;
433 setErrorMessage(i18n("Invalid OASIS document. No office:drawing tag found."));
434 m_bLoading = false;
435 return false;
436 }
437
438 TQDomNode node = body.firstChild();
439 TQString localName;
440 m_pMap->clear();
441
442 // TODO: port to forEachElement
443 while(!node.isNull()) {
444 localName = node.localName();
445
446 if(localName == "page" /* && and namespace is KoXmlNS::draw*/) {
447 KivioPage* p = createPage();
448 addPage(p);
449
450 if(!p->loadOasis(node.toElement(), oasisStyles)) {
451 m_bLoading = false;
452 return false;
453 }
454 }
455
456 node = node.nextSibling();
457 }
458
459 loadOasisSettings( settings );
460
461 emit loadingFinished();
462 return true;
463}
464
465
466void KivioDoc::loadOasisSettings( const TQDomDocument&settingsDoc )
467{
468 if ( settingsDoc.isNull() )
469 return ; //not a error some file doesn't have settings.xml
470 KoOasisSettings settings( settingsDoc );
471 KoOasisSettings::Items viewSettings = settings.itemSet( "view-settings" );
472 if ( !viewSettings.isNull() )
473 {
474 setUnit(KoUnit::unit(viewSettings.parseConfigItemString("unit")));
475 //todo add other config here.
476 }
477}
478
479bool KivioDoc::loadXML( TQIODevice *, const TQDomDocument& doc )
480{
481 m_bLoading = true;
482
483 if ( doc.doctype().name() != "kiviodoc" ) {
484 m_bLoading = false;
485 return false;
486 }
487
488 TQDomElement kivio = doc.documentElement();
489 if ( kivio.attribute( "mime" ) != "application/x-kivio" &&
490 kivio.attribute( "mime" ) != "application/vnd.kde.kivio" )
491 {
492 kdDebug(43000) << "KivioDoc::loadXML() - Invalid mime type" << endl;
493 m_bLoading = false;
494 return false;
495 }
496
497 TQDomNode node = kivio.firstChild();
498 while( !node.isNull() )
499 {
500 TQString name = node.nodeName();
501 if( name == "KivioMap" )
502 {
503 if( !m_pMap->loadXML( node.toElement() ) )
504 {
505 m_bLoading = false;
506 return false;
507 }
508 }
509 else if( name == "KivioStencilSpawnerSet" )
510 {
511 TQString id = XmlReadString( node.toElement(), "id", "" );
512 bool hidden = (XmlReadString(node.toElement(), "hidden", "false") == "true");
513
514 if( id.isEmpty() )
515 {
516 kdDebug(43000) << "KivioDoc::loadXML() - Bad KivioStencilSpawnerSet found, it contains no id!" << endl;
517 }
518 else
519 {
520 loadStencilSpawnerSet(id, hidden);
521 }
522 }
523 else if( name == "Options" )
524 {
525 // Not used anymore use users default page instead from Settings to create new pages...
526 }
527 else
528 {
529 kdDebug(43000) << "KivioDoc::loadXML() - Unknown node " << name << endl;
530 }
531
532 node = node.nextSibling();
533 }
534
535 TQString us = kivio.attribute("units", Kivio::Config::unit());
536 bool isInt = false;
537 int u = us.toInt(&isInt);
538
539 if(!isInt) {
540 setUnit(KoUnit::unit(us));
541 } else {
542 setUnit(Kivio::convToKoUnit(u));
543 }
544
545 if(kivio.hasAttribute("gridIsShow")) {
546 gridData.load(kivio,"grid");
547 }
548
549 emit loadingFinished();
550 return true;
551}
552
553bool KivioDoc::loadStencilSpawnerSet(const TQString &id, bool hidden)
554{
555 TDEStandardDirs *dirs = TDEGlobal::dirs();
556 TQStringList dirList = dirs->findDirs("data", "kivio/stencils");
557 TQString rootDir;
558
559 // Iterate through all data directories
560 for( TQStringList::Iterator it = dirList.begin(); it != dirList.end(); ++it )
561 {
562 rootDir = (*it);
563
564 // Within each data directory, iterate through all directories looking
565 // for a filename (dir) that matches the parameter
566 TQDir d(rootDir);
567 d.setFilter( TQDir::Dirs );
568 d.setSorting( TQDir::Name );
569
570 const TQFileInfoList *list = d.entryInfoList();
571 TQFileInfoListIterator listIT( *list );
572 TQFileInfo *fi;
573
574 // Loop through the outer directories (like BasicFlowcharting)
575 while( (fi=listIT.current()) )
576 {
577 if( fi->fileName() != "." &&
578 fi->fileName() != ".." )
579 {
580 TQDir innerD(fi->absFilePath() );
581 innerD.setFilter( TQDir::Dirs );
582 innerD.setSorting( TQDir::Name );
583
584 const TQFileInfoList *innerList = innerD.entryInfoList();
585 TQFileInfoListIterator innerIT( *innerList );
586 TQFileInfo *innerFI;
587
588 // Loop through the inner directories (like FlowChartingShapes1)
589 while( (innerFI = innerIT.current()) )
590 {
591 if( innerFI->fileName() != ".." &&
592 innerFI->fileName() != "." )
593 {
594 // Compare the descriptions
595 TQString foundId;
596
597 // TODO: use ID system here for loading
598 foundId = KivioStencilSpawnerSet::readId(innerFI->absFilePath());
599 if( foundId == id)
600 {
601
602 // Load the spawner set with rootDir + "/" + fi.fileName()
603 addSpawnerSetDuringLoad(innerFI->absFilePath(), hidden);
604 return true;
605 }
606 }
607
608 ++innerIT;
609 }
610 }
611
612 ++listIT;
613 }
614 }
615
616 return false;
617}
618
619bool KivioDoc::completeLoading( KoStore* )
620{
621 m_bLoading = false;
622 m_pMap->update();
623 setModified( false );
624 return true;
625}
626
627KivioPage* KivioDoc::createPage()
628{
629 TQString s( i18n("Page%1") );
630 s = s.arg( m_iPageId++ );
631
632 KivioPage* t = new KivioPage(m_pMap, s);
633 t->setPageName(s,true);
634
635 return t;
636}
637
638void KivioDoc::addPage( KivioPage* page )
639{
640 m_pMap->addPage(page);
641 setModified(true);
642 emit sig_addPage(page);
643}
644
645void KivioDoc::insertPage( KivioPage * page )
646{
647 TQPtrListIterator<KoView> it( views() );
648 for (; it.current(); ++it )
649 ((KivioView*)it.current())->insertPage( page );
650}
651
652void KivioDoc::takePage( KivioPage * page )
653{
654 TQPtrListIterator<KoView> it( views() );
655 for (; it.current(); ++it )
656 ((KivioView*)it.current())->removePage( page );
657}
658
659
660void KivioDoc::paintContent( TQPainter& painter, const TQRect& rect, bool transparent, double /*zoomX*/, double /*zoomY*/ )
661{
662 KivioPage* page = m_pMap->firstPage();
663 if ( !page )
664 return;
665
666 KoZoomHandler zoom;
667 zoom.setZoomAndResolution(100, KoGlobal::dpiX(),
668 KoGlobal::dpiY());
669 KoRect r = page->getRectForAllStencils();
670
671 float zw = (float) rect.width() / (float)zoom.zoomItX(r.width());
672 float zh = (float) rect.height() / (float)zoom.zoomItY(r.height());
673 float z = TQMIN(zw, zh);
674 //kdDebug(43000) << "paintContent: w = " << rect.width() << " h = " << rect.height() << endl;
675
676 zoom.setZoomAndResolution(tqRound(z * 100), KoGlobal::dpiX(),
677 KoGlobal::dpiY());
678 KivioScreenPainter ksp(&painter);
679 ksp.painter()->translate( - zoom.zoomItX(r.x()), - zoom.zoomItY(r.y()) );
680 paintContent(ksp,rect,transparent,page, TQPoint(zoom.zoomItX(r.x()), zoom.zoomItY(r.y())), &zoom, false, false);
681 ksp.setPainter(0L); // Important! Don't delete the TQPainter!!!
682}
683
684void KivioDoc::paintContent( KivioPainter& painter, const TQRect& rect, bool transparent, KivioPage* page, TQPoint p0, KoZoomHandler* zoom, bool drawConnectorTargets, bool drawSelection )
685{
686 if ( isLoading() )
687 return;
688
689 page->paintContent(painter,rect,transparent,p0,zoom, drawConnectorTargets, drawSelection);
690}
691
692void KivioDoc::printContent( KPrinter &prn )
693{
694 KivioScreenPainter p;
695 TQValueList<int> pages = prn.pageList();
696 KivioPage *pPage;
697
698 // ### HACK: disable zooming-when-printing if embedded parts are used.
699 // No koffice app supports zooming in paintContent currently.
700 // Disable in ALL cases now
701 bool doZoom = false;
702 int dpiX = doZoom ? 300 : KoGlobal::dpiX();
703 int dpiY = doZoom ? 300 : KoGlobal::dpiY();
704
705 p.start(&prn);
706
707 TQPaintDeviceMetrics metrics( &prn );
708 p.painter()->scale( (double)metrics.logicalDpiX() / (double)dpiX,
709 (double)metrics.logicalDpiY() / (double)dpiY );
710
711 TQValueList<int>::iterator it;
712
713 for(it = pages.begin(); it != pages.end(); ++it) {
714 pPage = m_pMap->pageList().at((*it)-1);
715 pPage->printContent(p, dpiX, dpiY);
716
717 if( it != (--pages.end()) ) {
718 prn.newPage();
719 }
720 }
721
722 p.stop();
723}
724
725// TODO: Fix for id system
726KivioStencilSpawnerSet* KivioDoc::findSpawnerSet(const TQString& dirName, const TQString& id)
727{
728 KivioStencilSpawnerSet *pSet = m_pLstSpawnerSets->first();
729 while(pSet)
730 {
731 if( pSet->dir() == dirName || pSet->id() == id )
732 {
733 return pSet;
734 }
735
736 pSet = m_pLstSpawnerSets->next();
737 }
738
739 return 0;
740}
741
742void KivioDoc::addSpawnerSet( const TQString &dirName )
743{
744 TQString id = KivioStencilSpawnerSet::readId( dirName );
745 KivioStencilSpawnerSet* set = findSpawnerSet(dirName, id);
746
747 if(set)
748 {
749 // Unhide the set if it's only hidden
750 if(set->hidden()) {
751 set->setHidden(false);
752 emit sig_addSpawnerSet(set);
753 }
754
755 return;
756 }
757
758
759 set = new KivioStencilSpawnerSet();
760
761 if(!set->loadDir(dirName))
762 {
763 kdDebug(43000) << "KivioDoc::addSpawnerSet() - Error loading dir set" << endl;
764 delete set;
765 return;
766 }
767
768 // Queue set for loading stencils
769 m_stencilSetLoadQueue.append(set);
770
771 if(!m_loadTimer) {
772 m_loadTimer = new TQTimer(this);
773 connect(m_loadTimer, TQ_SIGNAL(timeout()), this, TQ_SLOT(loadStencil()));
774 }
775
776 if(!m_loadTimer->isActive()) {
777 emit initProgress();
778 m_loadTimer->start(0, false);
779 }
780}
781
782void KivioDoc::addSpawnerSetDuringLoad(const TQString& dirName, bool hidden)
783{
784 KivioStencilSpawnerSet *set;
785
786 set = new KivioStencilSpawnerSet();
787 set->setHidden(hidden);
788
789 if( set->loadDir(dirName)==false )
790 {
791 kdDebug(43000) << "KivioDoc::addSpawnerSetDuringLoad() - Error loading dir set" << endl;
792 delete set;
793 return;
794 }
795
796 TQStringList::iterator it;
797 TQStringList files = set->files();
798
799 for(it = files.begin(); it != files.end(); ++it) {
800 TQString fileName = set->dir() + "/" + (*it);
801 set->loadFile(fileName);
802 }
803
804 m_pLstSpawnerSets->append(set);
805}
806
807KivioDoc::~KivioDoc()
808{
809 if(m_docOpened) {
810 saveConfig();
811 }
812
813 // ***MUST*** Delete the pages first because they may
814 // contain plugins which will be unloaded soon. The stencils which are
815 // spawned by plugins NEED the plugins still loaded when their destructor
816 // is called or the program will slit it's throat.
817 delete m_pMap;
818 delete dcop;
819 delete m_commandHistory;
820
821 delete m_pLstSpawnerSets;
822 m_pLstSpawnerSets = 0;
823
824 s_docs->removeRef(this);
825}
826
827void KivioDoc::saveConfig()
828{
829 Kivio::Config::self()->writeConfig();
830}
831
832void KivioDoc::initConfig()
833{
834 setUnit( KoUnit::unit(Kivio::Config::unit()) );
835 m_font = Kivio::Config::font();
836 m_pageLayout = Kivio::Config::defaultPageLayout();
837}
838
839bool KivioDoc::removeSpawnerSet( KivioStencilSpawnerSet *pSet )
840{
841 return m_pLstSpawnerSets->removeRef( pSet );
842}
843
848void KivioDoc::slotDeleteStencilSet( DragBarButton *pBtn, TQWidget *w, KivioStackBar *pBar )
849{
850 KivioIconView* pIconView = static_cast<KivioIconView*>(w);
851 KivioStencilSpawnerSet* pSet = pIconView->spawnerSet();
852
853 // Only actually remove the set if it isn't used...
854 if(!checkStencilsForSpawnerSet(pSet)) {
855 removeSpawnerSet(pSet);
856 } else {
857 pSet->setHidden(true);
858 }
859
860 // And emit the signal to kill the set (page & button)
861 emit sig_deleteStencilSet(pBtn, w, pBar);
862}
863
867bool KivioDoc::checkStencilsForSpawnerSet(KivioStencilSpawnerSet* spawnerSet)
868{
869 KivioPage *pPage = m_pMap->firstPage();
870 KivioLayer *pLayer;
871 KivioStencil *pStencil;
872
873 // Iterate across all the pages
874 while(pPage) {
875 pLayer = pPage->layers()->first();
876
877 while(pLayer) {
878 pStencil = pLayer->stencilList()->first();
879
880 while(pStencil) {
881 // If this is a group stencil, then we must check all child stencils
882 if(pStencil->groupList() && pStencil->groupList()->count() > 0) {
883 if(checkGroupForSpawnerSet(pStencil, spawnerSet)) {
884 return true;
885 }
886 } else if(pStencil->spawner()->set() == spawnerSet) {
887 return true;
888 }
889
890 pStencil = pLayer->stencilList()->next();
891 }
892
893 pLayer = pPage->layers()->next();
894 }
895
896 pPage = m_pMap->nextPage();
897 }
898
899 return false;
900}
901
902bool KivioDoc::checkGroupForSpawnerSet(KivioStencil* pGroup, KivioStencilSpawnerSet* spawnerSet)
903{
904 KivioStencil *pStencil = pGroup->groupList()->first();
905
906 while(pStencil) {
907 if(pStencil->groupList() && pStencil->groupList()->count() > 0) {
908 if(checkGroupForSpawnerSet(pStencil, spawnerSet))
909 return true;
910 } else if(pStencil->spawner()->set() == spawnerSet) {
911 return true;
912 }
913
914 pStencil = pGroup->groupList()->next();
915 }
916
917 return false;
918}
919
920void KivioDoc::slotSelectionChanged()
921{
922 emit sig_selectionChanged();
923}
924
925KivioStencilSpawner* KivioDoc::findStencilSpawner( const TQString& setId, const TQString& stencilId )
926{
927 KivioStencilSpawnerSet *pSpawnerSet = m_pLstSpawnerSets->first();
928 while( pSpawnerSet )
929 {
930 if( pSpawnerSet->id() == setId && pSpawnerSet->find(stencilId) )
931 {
932 return pSpawnerSet->find(stencilId);
933 // return pSpawnerSet->find(name)
934 }
935 pSpawnerSet = m_pLstSpawnerSets->next();
936 }
937
938 if( m_pInternalSet->id() == setId && m_pInternalSet->find(stencilId) )
939 {
940 return m_pInternalSet->find(stencilId);
941 }
942
943 return NULL;
944}
945
946KivioStencilSpawner* KivioDoc::findInternalStencilSpawner( const TQString& stencilId )
947{
948 return m_pInternalSet->find(stencilId);
949}
950
951void KivioDoc::addInternalStencilSpawner(KivioStencilSpawner* spawner)
952{
953 m_pInternalSet->addSpawner(spawner);
954}
955
956void KivioDoc::updateView(KivioPage* page)
957{
958 emit sig_updateView(page);
959}
960
961void KivioDoc::updateButton()
962{
963 TQPtrListIterator<KoView> it( views() );
964 for (; it.current(); ++it )
965 ((KivioView*)it.current())->updateButton();
966}
967
968void KivioDoc::resetLayerPanel()
969{
970 TQPtrListIterator<KoView> it( views() );
971 for (; it.current(); ++it )
972 ((KivioView*)it.current())->resetLayerPanel();
973}
974
975void KivioDoc::addCommand( KCommand * cmd )
976{
977 kdDebug(43000) << "KivioDoc::addCommand " << cmd->name() << endl;
978 m_commandHistory->addCommand( cmd, false );
979 setModified( true );
980}
981
982int KivioDoc::undoRedoLimit() const
983{
984 return m_commandHistory->undoLimit();
985}
986
987void KivioDoc::setUndoRedoLimit(int val)
988{
989 m_commandHistory->setUndoLimit(val);
990 m_commandHistory->setRedoLimit(val);
991}
992
993void KivioDoc::slotDocumentRestored()
994{
995 setModified( false );
996}
997
998void KivioDoc::slotCommandExecuted()
999{
1000 setModified( true );
1001}
1002
1003void KivioDoc::updateProtectPanelCheckBox()
1004{
1005 TQPtrListIterator<KoView> it( views() );
1006 for (; it.current(); ++it )
1007 ((KivioView*)it.current())->updateProtectPanelCheckBox();
1008}
1009
1010void KivioDoc::loadStencil()
1011{
1012 KivioStencilSpawnerSet* set = m_stencilSetLoadQueue.first();
1013 TQString fileName = set->dir() + "/" + set->files()[m_currentFile];
1014 set->loadFile(fileName);
1015 m_currentFile++;
1016 emit progress(tqRound(((float)m_currentFile / (float)set->files().count()) * 100.0));
1017
1018 if(m_currentFile >= set->files().count()) {
1019 m_pLstSpawnerSets->append(set);
1020
1021 if(!m_bLoading) {
1022 setModified(true);
1023 emit sig_addSpawnerSet(set);
1024 }
1025
1026 m_currentFile = 0;
1027 set = 0;
1028 m_stencilSetLoadQueue.pop_front();
1029
1030 if(m_stencilSetLoadQueue.isEmpty()) {
1031 m_loadTimer->stop();
1032 emit endProgress();
1033 } else {
1034 emit initProgress();
1035 }
1036 }
1037}
1038
1039void KivioDoc::updateGuideLines(KoView* sender)
1040{
1041 TQValueList<double> hGuideLines;
1042 TQValueList<double> vGuideLines;
1043 KivioView* view = static_cast<KivioView*>(sender);
1044 view->canvasWidget()->guideLines().getGuideLines(hGuideLines, vGuideLines);
1045 view->activePage()->setGuideLines(hGuideLines, vGuideLines);
1046
1047 TQPtrListIterator<KoView> it(views());
1048 KivioView* itView = 0;
1049
1050 for (; it.current(); ++it ) {
1051 itView = static_cast<KivioView*>(it.current());
1052 if(it.current() != sender && (itView->activePage() == view->activePage())) {
1053 itView->canvasWidget()->guideLines().setGuideLines(hGuideLines, vGuideLines);
1054 }
1055 }
1056}
1057
1058void KivioDoc::updateGuideLines(KivioPage* page)
1059{
1060 TQValueList<double> hGuideLines = page->horizontalGuideLines();
1061 TQValueList<double> vGuideLines = page->verticalGuideLines();
1062 TQPtrListIterator<KoView> it(views());
1063 KivioView* itView = 0;
1064
1065 for (; it.current(); ++it ) {
1066 itView = static_cast<KivioView*>(it.current());
1067 if(itView->activePage() == page) {
1068 itView->canvasWidget()->guideLines().setGuideLines(hGuideLines, vGuideLines);
1069 }
1070 }
1071}
1072
1073#include "kivio_doc.moc"
static KoPageLayout defaultPageLayout()
Get the default page layout.