KoDocument.cpp
1/* This file is part of the KDE project
2 Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
3 Copyright (C) 2000-2005 David Faure <faure@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library 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 GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19*/
20
21#include "KoDocument.h"
22
23#include "KoDocument_p.h"
24#include "KoDocumentIface.h"
25#include "KoDocumentChild.h"
26#include "KoView.h"
27#include "KoMainWindow.h"
28#include "KoFilterManager.h"
29#include "KoDocumentInfo.h"
30#include "KoOasisStyles.h"
31#include "KoOasisStore.h"
32#include "KoXmlNS.h"
33#include "KoOpenPane.h"
34
35#include <KoStoreDevice.h>
36#include <KoXmlWriter.h>
37
38#include <tdeapplication.h>
39#include <kdebug.h>
40#include <tdeversion.h>
41#include <tdefileitem.h>
42#include <kiconloader.h>
43#include <tdeio/job.h>
44#include <tdeio/netaccess.h>
45#include <tdelocale.h>
46#include <tdemessagebox.h>
47#include <kmimetype.h>
48#include <tdeparts/partmanager.h>
49#include <kprinter.h>
50#include <ksavefile.h>
51
52#include <tqbuffer.h>
53#include <tqcursor.h>
54#include <tqdir.h>
55#include <tqfile.h>
56#include <tqfileinfo.h>
57#include <tqimage.h>
58#include <tqmap.h>
59#include <tqpainter.h>
60#include <tqtimer.h>
61#include <tqxml.h>
62#include <tqlayout.h>
63
64#include <config.h>
65#include <assert.h>
66#include <locale.h>
67
68
69// Define the protocol used here for embedded documents' URL
70// This used to "store" but KURL didn't like it,
71// so let's simply make it "tar" !
72#define STORE_PROTOCOL "tar"
73// The internal path is a hack to make KURL happy and still pass
74// some kind of relative path to KoDocumentChild
75#define INTERNAL_PROTOCOL "intern"
76#define INTERNAL_PREFIX "intern:/"
77// Warning, keep it sync in koStore.cpp and koDocumentChild.cpp
78
79TQPtrList<KoDocument> *KoDocument::s_documentList=0L;
80
81using namespace std;
82class KoViewWrapperWidget;
83
84/**********************************************************
85 *
86 * KoDocument
87 *
88 **********************************************************/
89
90const int KoDocument::s_defaultAutoSave = 300; // 5 minutes
91
92class KoDocument::Private
93{
94public:
95 Private() :
96 m_dcopObject( 0L ),
97 filterManager( 0L ),
98 m_specialOutputFlag( 0 ), // default is native format
99 m_isImporting( false ), m_isExporting( false ),
100 m_numOperations( 0 ),
101 modifiedAfterAutosave( false ),
102 m_autosaving( false ),
103 m_shouldCheckAutoSaveFile( true ),
104 m_autoErrorHandlingEnabled( true ),
105 m_backupFile( true ),
106 m_backupPath( TQString() ),
107 m_doNotSaveExtDoc( false ),
108 m_current( false ),
109 m_storeInternal( false ),
110 m_bLoading( false ),
111 m_startUpWidget( 0 )
112 {
113 m_confirmNonNativeSave[0] = true;
114 m_confirmNonNativeSave[1] = true;
115 if ( TDEGlobal::locale()->measureSystem() == TDELocale::Imperial ) {
116 m_unit = KoUnit::U_INCH;
117 } else {
118 m_unit = KoUnit::U_CM;
119 }
120 }
121
122 TQPtrList<KoView> m_views;
123 TQPtrList<KoDocumentChild> m_children;
124 TQPtrList<KoMainWindow> m_shells;
125 TQValueList<TQDomDocument> m_viewBuildDocuments;
126
127 KoViewWrapperWidget *m_wrapperWidget;
128 KoDocumentIface * m_dcopObject;
129 KoDocumentInfo *m_docInfo;
130 KoView* hitTestView;
131
132 KoUnit::Unit m_unit;
133
134 KoFilterManager * filterManager; // The filter-manager to use when loading/saving [for the options]
135
136 TQCString mimeType; // The actual mimetype of the document
137 TQCString outputMimeType; // The mimetype to use when saving
138 bool m_confirmNonNativeSave [2]; // used to pop up a dialog when saving for the
139 // first time if the file is in a foreign format
140 // (Save/Save As, Export)
141 int m_specialOutputFlag; // See KoFileDialog in koMainWindow.cpp
142 bool m_isImporting, m_isExporting; // File --> Import/Export vs File --> Open/Save
143
144 TQTimer m_autoSaveTimer;
145 TQString lastErrorMessage; // see openFile()
146 int m_autoSaveDelay; // in seconds, 0 to disable.
147 int m_numOperations;
148 bool modifiedAfterAutosave;
149 bool m_bSingleViewMode;
150 bool m_autosaving;
151 bool m_shouldCheckAutoSaveFile; // usually true
152 bool m_autoErrorHandlingEnabled; // usually true
153 bool m_backupFile;
154 TQString m_backupPath;
155 bool m_doNotSaveExtDoc; // makes it possible to save only internally stored child documents
156 bool m_current;
157 bool m_storeInternal; // Store this doc internally even if url is external
158 bool m_bLoading; // True while loading (openURL is async)
159
160 KoOpenPane* m_startUpWidget;
161 TQString m_templateType;
162};
163
164// Used in singleViewMode
165class KoViewWrapperWidget : public TQWidget
166{
167public:
168 KoViewWrapperWidget( TQWidget *parent, const char *name )
169 : TQWidget( parent, name )
170 {
171 TDEGlobal::locale()->insertCatalogue("koffice");
172 // Tell the iconloader about share/apps/koffice/icons
173 TDEGlobal::iconLoader()->addAppDir("koffice");
174 m_view = 0L;
175 // Avoid warning from KParts - we'll have the KoView as focus proxy anyway
176 setFocusPolicy( TQWidget::ClickFocus );
177 }
178
179 virtual ~KoViewWrapperWidget() {
180 setFocusProxy( 0 ); // to prevent a crash due to clearFocus (#53466)
181 }
182
183 virtual void resizeEvent( TQResizeEvent * )
184 {
185 TQObject *wid = child( 0, "TQWidget" );
186 if ( wid )
187 static_cast<TQWidget*>(wid)->setGeometry( 0, 0, width(), height() );
188 }
189
190 virtual void childEvent( TQChildEvent *ev )
191 {
192 if ( ev->type() == TQEvent::ChildInserted )
193 resizeEvent( 0L );
194 }
195
196 // Called by openFile()
197 void setKoView( KoView * view ) {
198 m_view = view;
199 setFocusProxy( m_view );
200 }
201 KoView * koView() const { return m_view; }
202private:
203 KoView* m_view;
204};
205
206KoBrowserExtension::KoBrowserExtension( KoDocument * doc, const char * name )
207 : KParts::BrowserExtension( doc, name )
208{
209 emit enableAction( "print", true );
210}
211
212void KoBrowserExtension::print()
213{
214 KoDocument * doc = static_cast<KoDocument *>( parent() );
215 KoViewWrapperWidget * wrapper = static_cast<KoViewWrapperWidget *>( doc->widget() );
216 KoView * view = wrapper->koView();
217 // TODO remove code duplication (KoMainWindow), by moving this to KoView
218 KPrinter printer;
219 // ### TODO: apply global koffice settings here
220 view->setupPrinter( printer );
221 if ( printer.setup( view ) )
222 view->print( printer );
223}
224
225KoDocument::KoDocument( TQWidget * parentWidget, const char *widgetName, TQObject* parent, const char* name, bool singleViewMode )
226 : KParts::ReadWritePart( parent, name )
227{
228 if(s_documentList==0L)
229 s_documentList=new TQPtrList<KoDocument>;
230 s_documentList->append(this);
231
232 d = new Private;
233 m_bEmpty = true;
234 connect( &d->m_autoSaveTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( slotAutoSave() ) );
235 setAutoSave( s_defaultAutoSave );
236 d->m_bSingleViewMode = singleViewMode;
237
238
239 // the parent setting *always* overrides! (Simon)
240 if ( parent )
241 {
242 if ( parent->inherits( "KoDocument" ) )
243 d->m_bSingleViewMode = ((KoDocument *)parent)->isSingleViewMode();
244 else if ( parent->inherits( "KParts::Part" ) )
245 d->m_bSingleViewMode = true;
246 }
247
248 if ( singleViewMode )
249 {
250 d->m_wrapperWidget = new KoViewWrapperWidget( parentWidget, widgetName );
251 setWidget( d->m_wrapperWidget );
252 kdDebug(30003) << "creating KoBrowserExtension" << endl;
253 (void) new KoBrowserExtension( this ); // ## only if embedded into a browser?
254 }
255
256 d->m_docInfo = new KoDocumentInfo( this, "document info" );
257
258 m_pageLayout.ptWidth = 0;
259 m_pageLayout.ptHeight = 0;
260 m_pageLayout.ptTop = 0;
261 m_pageLayout.ptBottom = 0;
262 m_pageLayout.ptLeft = 0;
263 m_pageLayout.ptRight = 0;
264
265 // A way to 'fix' the job's window, since we have no widget known to KParts
266 if ( !singleViewMode )
267 connect( this, TQ_SIGNAL( started( TDEIO::Job* ) ), TQ_SLOT( slotStarted( TDEIO::Job* ) ) );
268}
269
271{
272 if (!d) {
273 return;
274 }
275
276 d->m_autoSaveTimer.stop();
277
278 TQPtrListIterator<KoDocumentChild> childIt( d->m_children );
279 for (; childIt.current(); ++childIt )
280 disconnect( childIt.current(), TQ_SIGNAL( destroyed() ),
281 this, TQ_SLOT( slotChildDestroyed() ) );
282
283 // Tell our views that the document is already destroyed and
284 // that they shouldn't try to access it.
285 TQPtrListIterator<KoView> vIt( d->m_views );
286 for (; vIt.current(); ++vIt )
287 vIt.current()->setDocumentDeleted();
288
289 delete d->m_startUpWidget;
290 d->m_startUpWidget = 0;
291
292 d->m_children.setAutoDelete( true );
293 d->m_children.clear();
294
295 d->m_shells.clear();
296
297 delete d->m_dcopObject;
298 delete d->filterManager;
299 delete d;
300 d=0L;
301 s_documentList->removeRef(this);
302 // last one?
303 if(s_documentList->isEmpty()) {
304 delete s_documentList;
305 s_documentList=0;
306 }
307}
308
310{
311 return d->m_bSingleViewMode;
312}
313
315{
316 return dynamic_cast<KoDocument *>( parent() ) != 0;
317}
318
319KoView *KoDocument::createView( TQWidget *parent, const char *name )
320{
321 KoView *view=createViewInstance(parent, name);
322 addView(view);
323 return view;
324}
325
326bool KoDocument::exp0rt( const KURL & _url )
327{
328 bool ret;
329
330 d->m_isExporting = true;
331
332 //
333 // Preserve a lot of state here because we need to restore it in order to
334 // be able to fake a File --> Export. Can't do this in saveFile() because,
335 // for a start, KParts has already set m_url and m_file and because we need
336 // to restore the modified flag etc. and don't want to put a load on anyone
337 // reimplementing saveFile() (Note: import() and export() will remain
338 // non-virtual).
339 //
340 KURL oldURL = m_url;
341 TQString oldFile = m_file;
342
343 bool wasModified = isModified ();
344 TQCString oldMimeType = mimeType ();
345
346
347 // save...
348 ret = saveAs( _url );
349
350
351 //
352 // This is sooooo hacky :(
353 // Hopefully we will restore enough state.
354 //
355 kdDebug(30003) << "Restoring KoDocument state to before export" << endl;
356
357 // always restore m_url & m_file because KParts has changed them
358 // (regardless of failure or success)
359 m_url = oldURL;
360 m_file = oldFile;
361
362 // on successful export we need to restore modified etc. too
363 // on failed export, mimetype/modified hasn't changed anyway
364 if (ret)
365 {
366 setModified (wasModified);
367 d->mimeType = oldMimeType;
368 }
369
370
371 d->m_isExporting = false;
372
373 return ret;
374}
375
377{
378 kdDebug(30003) << "KoDocument::saveFile() doc='" << url().url() <<"'"<< endl;
379
380 // set local again as it can happen that it gets resetted
381 // so that all saved numbers have a . and not e.g a , as a
382 // decimal seperator
383 setlocale( LC_NUMERIC, "C" );
384
385 // Save it to be able to restore it after a failed save
386 const bool wasModified = isModified ();
387
388 // The output format is set by koMainWindow, and by openFile
389 TQCString outputMimeType = d->outputMimeType;
390 //Q_ASSERT( !outputMimeType.isEmpty() ); // happens when using the DCOP method saveAs
391 if ( outputMimeType.isEmpty() )
392 outputMimeType = d->outputMimeType = nativeFormatMimeType();
393
394 TQApplication::setOverrideCursor( waitCursor );
395
396 if ( backupFile() ) {
397 if ( url().isLocalFile() )
398 KSaveFile::backupFile( url().path(), d->m_backupPath );
399 else {
400 TDEIO::UDSEntry entry;
401 if ( TDEIO::NetAccess::stat( url(), entry, shells().current() ) ) { // this file exists => backup
402 emit sigStatusBarMessage( i18n("Making backup...") );
403 KURL backup;
404 if ( d->m_backupPath.isEmpty())
405 backup = url();
406 else
407 backup = d->m_backupPath +"/"+url().fileName();
408 backup.setPath( backup.path() + TQString::fromLatin1("~") );
409 KFileItem item( entry, url() );
410 Q_ASSERT( item.name() == url().fileName() );
411 TDEIO::NetAccess::file_copy( url(), backup, item.permissions(), true /*overwrite*/, false /*resume*/, shells().current() );
412 }
413 }
414 }
415
416 emit sigStatusBarMessage( i18n("Saving...") );
417 bool ret = false;
418 bool suppressErrorDialog = false;
419 if ( !isNativeFormat( outputMimeType ) ) {
420 kdDebug(30003) << "Saving to format " << outputMimeType << " in " << m_file << endl;
421 // Not native format : save using export filter
422 if ( !d->filterManager )
423 d->filterManager = new KoFilterManager( this );
424
425 KoFilter::ConversionStatus status = d->filterManager->exp0rt( m_file, outputMimeType );
426 ret = status == KoFilter::OK;
427 suppressErrorDialog = (status == KoFilter::UserCancelled || status == KoFilter::BadConversionGraph );
428 } else {
429 // Native format => normal save
430 Q_ASSERT( !m_file.isEmpty() );
431 ret = saveNativeFormat( m_file );
432 }
433
434 if ( ret ) {
436 // Restart the autosave timer
437 // (we don't want to autosave again 2 seconds after a real save)
438 setAutoSave( d->m_autoSaveDelay );
439 }
440
441 TQApplication::restoreOverrideCursor();
442 if ( !ret )
443 {
444 if ( !suppressErrorDialog )
445 {
447 }
448
449 // couldn't save file so this new URL is invalid
450 // FIXME: we should restore the current document's true URL instead of
451 // setting it to nothing otherwise anything that depends on the URL
452 // being correct will not work (i.e. the document will be called
453 // "Untitled" which may not be true)
454 //
455 // Update: now the URL is restored in KoMainWindow but really, this
456 // should still be fixed in KoDocument/KParts (ditto for m_file).
457 // We still resetURL() here since we may or may not have been called
458 // by KoMainWindow - Clarence
459 resetURL();
460
461 // As we did not save, restore the "was modified" status
462 setModified( wasModified );
463 }
464
465 if ( ret )
466 {
467 d->mimeType = outputMimeType;
468 setConfirmNonNativeSave ( isExporting (), false );
469 }
471
472 return ret;
473}
474
475TQCString KoDocument::mimeType() const
476{
477 return d->mimeType;
478}
479
480void KoDocument::setMimeType( const TQCString & mimeType )
481{
482 d->mimeType = mimeType;
483}
484
485void KoDocument::setOutputMimeType( const TQCString & mimeType, int specialOutputFlag )
486{
487 d->outputMimeType = mimeType;
488 d->m_specialOutputFlag = specialOutputFlag;
489}
490
491TQCString KoDocument::outputMimeType() const
492{
493 return d->outputMimeType;
494}
495
496int KoDocument::specialOutputFlag() const
497{
498 return d->m_specialOutputFlag;
499}
500
501bool KoDocument::confirmNonNativeSave( const bool exporting ) const
502{
503 // "exporting ? 1 : 0" is different from "exporting" because a bool is
504 // usually implemented like an "int", not "unsigned : 1"
505 return d->m_confirmNonNativeSave [ exporting ? 1 : 0 ];
506}
507
508void KoDocument::setConfirmNonNativeSave( const bool exporting, const bool on )
509{
510 d->m_confirmNonNativeSave [ exporting ? 1 : 0] = on;
511}
512
513bool KoDocument::wantExportConfirmation() const
514{
515 return true;
516}
517
519{
520 return d->m_isImporting;
521}
522
524{
525 return d->m_isExporting;
526}
527
529{
530 d->m_shouldCheckAutoSaveFile = b;
531}
532
534{
535 d->m_autoErrorHandlingEnabled = b;
536}
537
539{
540 return d->m_autoErrorHandlingEnabled;
541}
542
543void KoDocument::slotAutoSave()
544{
545 if ( isModified() && d->modifiedAfterAutosave && !d->m_bLoading )
546 {
547 connect( this, TQ_SIGNAL( sigProgress( int ) ), shells().current(), TQ_SLOT( slotProgress( int ) ) );
548 emit sigStatusBarMessage( i18n("Autosaving...") );
549 d->m_autosaving = true;
550 bool ret = saveNativeFormat( autoSaveFile( m_file ) );
551 setModified( true );
552 if ( ret ) {
553 d->modifiedAfterAutosave = false;
554 d->m_autoSaveTimer.stop(); // until the next change
555 }
556 d->m_autosaving = false;
558 disconnect( this, TQ_SIGNAL( sigProgress( int ) ), shells().current(), TQ_SLOT( slotProgress( int ) ) );
559 if ( !ret )
560 emit sigStatusBarMessage( i18n("Error during autosave! Partition full?") );
561 }
562}
563
564TDEAction *KoDocument::action( const TQDomElement &element ) const
565{
566 // First look in the document itself
568 if ( act )
569 return act;
570
571 Q_ASSERT( d->m_bSingleViewMode );
572 // Then look in the first view (this is for the single view mode)
573 if ( !d->m_views.isEmpty() )
574 return d->m_views.getFirst()->action( element );
575 else
576 return 0L;
577}
578
579TQDomDocument KoDocument::domDocument() const
580{
581 // When embedded into e.g. konqueror, we want the view's GUI (hopefully a reduced one)
582 // to be used.
583 Q_ASSERT( d->m_bSingleViewMode );
584 if ( d->m_views.isEmpty() )
585 return TQDomDocument();
586 else
587 return d->m_views.getFirst()->domDocument();
588}
589
590void KoDocument::setManager( KParts::PartManager *manager )
591{
592 KParts::ReadWritePart::setManager( manager );
593 if ( d->m_bSingleViewMode && d->m_views.count() == 1 )
594 d->m_views.getFirst()->setPartManager( manager );
595
596 if ( manager )
597 {
598 TQPtrListIterator<KoDocumentChild> it( d->m_children );
599 for (; it.current(); ++it )
600 if ( it.current()->document() )
601 manager->addPart( it.current()->document(), false );
602 }
603}
604
605void KoDocument::setReadWrite( bool readwrite )
606{
608
609 TQPtrListIterator<KoView> vIt( d->m_views );
610 for (; vIt.current(); ++vIt )
611 vIt.current()->updateReadWrite( readwrite );
612
613 TQPtrListIterator<KoDocumentChild> dIt( d->m_children );
614 for (; dIt.current(); ++dIt )
615 if ( dIt.current()->document() )
616 dIt.current()->document()->setReadWrite( readwrite );
617
618 setAutoSave( d->m_autoSaveDelay );
619}
620
621void KoDocument::setAutoSave( int delay )
622{
623 d->m_autoSaveDelay = delay;
624 if ( isReadWrite() && !isEmbedded() && d->m_autoSaveDelay > 0 )
625 d->m_autoSaveTimer.start( d->m_autoSaveDelay * 1000 );
626 else
627 d->m_autoSaveTimer.stop();
628}
629
631{
632 if ( !view )
633 return;
634
635 d->m_views.append( view );
636 view->updateReadWrite( isReadWrite() );
637}
638
640{
641 d->m_views.removeRef( view );
642}
643
644const TQPtrList<KoView>& KoDocument::views() const
645{
646 return d->m_views;
647}
648
650{
651 return d->m_views.count();
652}
653
655{
656 setModified( true );
657
658 d->m_children.append( child );
659
660 connect( child, TQ_SIGNAL( changed( KoChild * ) ),
661 this, TQ_SLOT( slotChildChanged( KoChild * ) ) );
662 connect( child, TQ_SIGNAL( destroyed() ),
663 this, TQ_SLOT( slotChildDestroyed() ) );
664
665 // It may be that insertChild is called without the KoDocumentChild
666 // having a KoDocument attached, yet. This happens for example
667 // when KPresenter loads a document with embedded objects. For those
668 // KPresenterChild objects are allocated and insertChild is called.
669 // Later in loadChildren() KPresenter iterates over the child list
670 // and calls loadDocument for each child. That's exactly where we
671 // will try to do what we cannot do now: Register the child document
672 // at the partmanager (Simon)
673 if ( manager() && !isSingleViewMode() && child->document() )
674 manager()->addPart( child->document(), false );
675}
676
677void KoDocument::slotChildChanged( KoChild *c )
678{
679 assert( c->inherits( "KoDocumentChild" ) );
680 emit childChanged( static_cast<KoDocumentChild *>( c ) );
681}
682
683void KoDocument::slotChildDestroyed()
684{
685 setModified( true );
686
687 const KoDocumentChild *child = static_cast<const KoDocumentChild *>( sender() );
688 d->m_children.removeRef( child );
689}
690
691const TQPtrList<KoDocumentChild>& KoDocument::children() const
692{
693 return d->m_children;
694}
695
696KParts::Part *KoDocument::hitTest( TQWidget *widget, const TQPoint &globalPos )
697{
698 TQPtrListIterator<KoView> it( d->m_views );
699 for (; it.current(); ++it )
700 if ( static_cast<TQWidget *>(it.current()) == widget )
701 {
702 KoView* view = it.current();
703 d->hitTestView = view; // koffice-1.x hack
704 TQPoint canvasPos( view->canvas()->mapFromGlobal( globalPos ) );
705 canvasPos.rx() += view->canvasXOffset();
706 canvasPos.ry() += view->canvasYOffset();
707
708 KParts::Part *part = view->hitTest( canvasPos );
709 d->hitTestView = 0;
710 if ( part )
711 return part;
712 }
713
714 return 0L;
715}
716
718{
719 return d->hitTestView;
720}
721
722KoDocument* KoDocument::hitTest( const TQPoint &pos, const TQWMatrix &matrix )
723{
724 // Call KoDocumentChild::hitTest for any child document
725 TQPtrListIterator<KoDocumentChild> it( d->m_children );
726 for (; it.current(); ++it )
727 {
728 KoDocument *doc = it.current()->hitTest( pos, matrix );
729 if ( doc )
730 return doc;
731 }
732
733 // Unless we hit an embedded document, the hit is on this document itself.
734 return this;
735}
736
738{
739 TQPtrListIterator<KoDocumentChild> it( d->m_children );
740 for (; it.current(); ++it )
741 if ( it.current()->document() == doc )
742 return it.current();
743
744 return 0L;
745}
746
747KoDocumentInfo *KoDocument::documentInfo() const
748{
749 return d->m_docInfo;
750}
751
752void KoDocument::setViewBuildDocument( KoView *view, const TQDomDocument &doc )
753{
754 if ( d->m_views.find( view ) == -1 )
755 return;
756
757 uint viewIdx = d->m_views.at();
758
759 if ( d->m_viewBuildDocuments.count() == viewIdx )
760 d->m_viewBuildDocuments.append( doc );
761 else if ( d->m_viewBuildDocuments.count() > viewIdx )
762 d->m_viewBuildDocuments[ viewIdx ] = doc;
763}
764
765TQDomDocument KoDocument::viewBuildDocument( KoView *view )
766{
767 TQDomDocument res;
768
769 if ( d->m_views.find( view ) == -1 )
770 return res;
771
772 uint viewIdx = d->m_views.at();
773
774 if ( viewIdx >= d->m_viewBuildDocuments.count() )
775 return res;
776
777 res = d->m_viewBuildDocuments[ viewIdx ];
778
779 // make this entry empty. otherwise we get a segfault in TQMap ;-(
780 d->m_viewBuildDocuments[ viewIdx ] = TQDomDocument();
781
782 return res;
783}
784
785void KoDocument::paintEverything( TQPainter &painter, const TQRect &rect, bool transparent, KoView *view, double zoomX, double zoomY )
786{
787 paintContent( painter, rect, transparent, zoomX, zoomY );
788 paintChildren( painter, rect, view, zoomX, zoomY );
789}
790
791void KoDocument::paintChildren( TQPainter &painter, const TQRect &/*rect*/, KoView *view, double zoomX, double zoomY )
792{
793 TQPtrListIterator<KoDocumentChild> it( d->m_children );
794 for (; it.current(); ++it )
795 {
796 // #### todo: paint only if child is visible inside rect
797 painter.save();
798 paintChild( it.current(), painter, view, zoomX, zoomY );
799 painter.restore();
800 }
801}
802
803void KoDocument::paintChild( KoDocumentChild *child, TQPainter &painter, KoView *view, double zoomX, double zoomY )
804{
805 if ( child->isDeleted() )
806 return;
807
808 // TQRegion rgn = painter.clipRegion();
809
810 child->transform( painter );
811 child->document()->paintEverything( painter, child->contentRect(), child->isTransparent(), view, zoomX, zoomY );
812
813 if ( view && view->partManager() )
814 {
815 // ### do we need to apply zoomX and zoomY here ?
816 KParts::PartManager *manager = view->partManager();
817
818 painter.scale( 1.0 / child->xScaling(), 1.0 / child->yScaling() );
819
820 int w = int( (double)child->contentRect().width() * child->xScaling() );
821 int h = int( (double)child->contentRect().height() * child->yScaling() );
822 if ( ( manager->selectedPart() == (KParts::Part *)child->document() &&
823 manager->selectedWidget() == (TQWidget *)view ) ||
825 manager->activeWidget() == (TQWidget *)view ) )
826 {
827 // painter.setClipRegion( rgn );
828 painter.setClipping( false );
829
830 painter.setPen( black );
831 painter.fillRect( -5, -5, w + 10, 5, white );
832 painter.fillRect( -5, h, w + 10, 5, white );
833 painter.fillRect( -5, -5, 5, h + 10, white );
834 painter.fillRect( w, -5, 5, h + 10, white );
835 painter.fillRect( -5, -5, w + 10, 5, BDiagPattern );
836 painter.fillRect( -5, h, w + 10, 5, BDiagPattern );
837 painter.fillRect( -5, -5, 5, h + 10, BDiagPattern );
838 painter.fillRect( w, -5, 5, h + 10, BDiagPattern );
839
841 manager->selectedWidget() == (TQWidget *)view )
842 {
843 TQColor color;
844 if ( view->koDocument() == this )
845 color = black;
846 else
847 color = gray;
848 painter.fillRect( -5, -5, 5, 5, color );
849 painter.fillRect( -5, h, 5, 5, color );
850 painter.fillRect( w, h, 5, 5, color );
851 painter.fillRect( w, -5, 5, 5, color );
852 painter.fillRect( w / 2 - 3, -5, 5, 5, color );
853 painter.fillRect( w / 2 - 3, h, 5, 5, color );
854 painter.fillRect( -5, h / 2 - 3, 5, 5, color );
855 painter.fillRect( w, h / 2 - 3, 5, 5, color );
856 }
857
858 painter.setClipping( true );
859 }
860 }
861}
862
864{
866 {
867 //kdDebug(30003)<<k_funcinfo<<" Modified doc='"<<url().url()<<"' extern="<<isStoredExtern()<<endl;
868 return true;
869 }
870 // Then go through internally stored children (considered to be part of this doc)
871 TQPtrListIterator<KoDocumentChild> it = children();
872 for (; it.current(); ++it )
873 {
874 KoDocument *doc = it.current()->document();
875 if ( doc && !it.current()->isStoredExtern() && !it.current()->isDeleted() && doc->isModified() )
876 return true;
877 }
878 return false;
879}
880
882{
883 //kdDebug(30003)<<k_funcinfo<<" checking children of doc='"<<url().url()<<"'"<<endl;
884 int i = 0;
885 TQPtrListIterator<KoDocumentChild> it( children() );
886 for( ; it.current(); ++it ) {
887 KoDocument* childDoc = it.current()->document();
888 if (childDoc && !it.current()->isDeleted())
889 {
890 if ( !childDoc->isStoredExtern() )
891 {
892 //kdDebug(30003) << "KoDocument::saveChildren internal url: /" << i << endl;
893 if ( !childDoc->saveToStore( _store, TQString::number( i++ ) ) )
894 return false;
895
896 if (!isExporting ())
897 childDoc->setModified( false );
898 }
899 //else kdDebug(30003)<<k_funcinfo<<" external (don't save) url:" << childDoc->url().url()<<endl;
900 }
901 }
902 return true;
903}
904
905bool KoDocument::saveChildrenOasis( KoStore* store, KoXmlWriter* manifestWriter )
906{
907 //kdDebug(30003)<<k_funcinfo<<" checking children of doc='"<<url().url()<<"'"<<endl;
908 TQPtrListIterator<KoDocumentChild> it( children() );
909 for( ; it.current(); ++it ) {
910 KoDocument* childDoc = it.current()->document();
911 if ( childDoc && !it.current()->isDeleted() )
912 {
913 if ( !it.current()->saveOasis( store, manifestWriter ) )
914 return false;
915 if ( !childDoc->isStoredExtern() && !isExporting () )
916 childDoc->setModified( false );
917 }
918 }
919 return true;
920}
921
923{
924 if ( d->m_doNotSaveExtDoc )
925 {
926 //kdDebug(30003)<<k_funcinfo<<" Don't save external docs in doc='"<<url().url()<<"'"<<endl;
927 d->m_doNotSaveExtDoc = false;
928 return true;
929 }
930
931 //kdDebug(30003)<<k_funcinfo<<" checking children of doc='"<<url().url()<<"'"<<endl;
932 KoDocumentChild *ch;
933 TQPtrListIterator<KoDocumentChild> it = children();
934 for (; (ch = it.current()); ++it )
935 {
936 if ( !ch->isDeleted() )
937 {
938 KoDocument* doc = ch->document();
939 if ( doc && doc->isStoredExtern() && doc->isModified() )
940 {
941 kdDebug(30003)<<" save external doc='"<<url().url()<<"'"<<endl;
942 doc->setDoNotSaveExtDoc(); // Only save doc + it's internal children
943 if ( !doc->save() )
944 return false; // error
945 }
946 //kdDebug(30003)<<k_funcinfo<<" not modified doc='"<<url().url()<<"'"<<endl;
947 // save possible external docs inside doc
948 if ( doc && !doc->saveExternalChildren() )
949 return false;
950 }
951 }
952 return true;
953}
954
955bool KoDocument::saveNativeFormat( const TQString & file )
956{
957 d->lastErrorMessage = TQString();
958 //kdDebug(30003) << "Saving to store" << endl;
959
960 KoStore::Backend backend = KoStore::Auto;
961#if 0
962 if ( d->m_specialOutputFlag == SaveAsKOffice1dot1 )
963 {
964 kdDebug(30003) << "Saving as KOffice-1.1 format, using a tar.gz" << endl;
965 backend = KoStore::Tar; // KOffice-1.0/1.1 used tar.gz for the native mimetype
967 }
968 else
969#endif
970 if ( d->m_specialOutputFlag == SaveAsDirectoryStore )
971 {
972 backend = KoStore::Directory;
973 kdDebug(30003) << "Saving as uncompressed XML, using directory store." << endl;
974 }
975 else if ( d->m_specialOutputFlag == SaveAsFlatXML )
976 {
977 kdDebug(30003) << "Saving as a flat XML file." << endl;
978 TQFile f( file );
979 if ( f.open( IO_WriteOnly | IO_Translate ) )
980 {
981 bool success = saveToStream( &f );
982 f.close();
983 return success;
984 }
985 else
986 return false;
987 }
988
989 kdDebug(30003) << "KoDocument::saveNativeFormat nativeFormatMimeType=" << nativeFormatMimeType() << endl;
990 // OLD: bool oasis = d->m_specialOutputFlag == SaveAsOASIS;
991 // OLD: TQCString mimeType = oasis ? nativeOasisMimeType() : nativeFormatMimeType();
992 TQCString mimeType = d->outputMimeType;
993 TQCString nativeOasisMime = nativeOasisMimeType();
994 bool oasis = !mimeType.isEmpty() && ( mimeType == nativeOasisMime || mimeType == nativeOasisMime + "-template" );
995 // TODO: use std::unique_ptr or create store on stack [needs API fixing],
996 // to remove all the 'delete store' in all the branches
997 KoStore* store = KoStore::createStore( file, KoStore::Write, mimeType, backend );
998 if ( store->bad() )
999 {
1000 d->lastErrorMessage = i18n( "Could not create the file for saving" ); // more details needed?
1001 delete store;
1002 return false;
1003 }
1004
1005 if ( oasis )
1006 {
1007 kdDebug(30003) << "Saving to OASIS format" << endl;
1008 // Tell KoStore not to touch the file names
1009 store->disallowNameExpansion();
1010 KoOasisStore oasisStore( store );
1011 KoXmlWriter* manifestWriter = oasisStore.manifestWriter( mimeType );
1012
1013 if ( !saveOasis( store, manifestWriter ) )
1014 {
1015 kdDebug(30003) << "saveOasis failed" << endl;
1016 delete store;
1017 return false;
1018 }
1019
1020 // Save embedded objects
1021 if ( !saveChildrenOasis( store, manifestWriter ) )
1022 {
1023 kdDebug(30003) << "saveChildrenOasis failed" << endl;
1024 delete store;
1025 return false;
1026 }
1027
1028 if ( store->open( "meta.xml" ) )
1029 {
1030 if ( !d->m_docInfo->saveOasis( store ) || !store->close() ) {
1031 delete store;
1032 return false;
1033 }
1034 manifestWriter->addManifestEntry( "meta.xml", "text/xml" );
1035 }
1036 else
1037 {
1038 d->lastErrorMessage = i18n( "Not able to write '%1'. Partition full?" ).arg( "meta.xml" );
1039 delete store;
1040 return false;
1041 }
1042
1043 if ( store->open( "Thumbnails/thumbnail.png" ) )
1044 {
1045 if ( !saveOasisPreview( store, manifestWriter ) || !store->close() ) {
1046 d->lastErrorMessage = i18n( "Error while trying to write '%1'. Partition full?" ).arg( "Thumbnails/thumbnail.png" );
1047 delete store;
1048 return false;
1049 }
1050 // No manifest entry!
1051 }
1052 else
1053 {
1054 d->lastErrorMessage = i18n( "Not able to write '%1'. Partition full?" ).arg( "Thumbnails/thumbnail.png" );
1055 delete store;
1056 return false;
1057 }
1058
1059 // Write out manifest file
1060 if ( !oasisStore.closeManifestWriter() )
1061 {
1062 d->lastErrorMessage = i18n( "Error while trying to write '%1'. Partition full?" ).arg( "META-INF/manifest.xml" );
1063 delete store;
1064 return false;
1065 }
1066
1067 delete store;
1068 }
1069 else
1070 {
1071 // Save internal children first since they might get a new url
1072 if ( !saveChildren( store ) && !oasis )
1073 {
1074 if ( d->lastErrorMessage.isEmpty() )
1075 d->lastErrorMessage = i18n( "Error while saving embedded documents" ); // more details needed
1076 delete store;
1077 return false;
1078 }
1079
1080 kdDebug(30003) << "Saving root" << endl;
1081 if ( store->open( "root" ) )
1082 {
1083 KoStoreDevice dev( store );
1084 if ( !saveToStream( &dev ) || !store->close() )
1085 {
1086 kdDebug(30003) << "saveToStream failed" << endl;
1087 delete store;
1088 return false;
1089 }
1090 }
1091 else
1092 {
1093 d->lastErrorMessage = i18n( "Not able to write '%1'. Partition full?" ).arg( "maindoc.xml" );
1094 delete store;
1095 return false;
1096 }
1097 if ( store->open( "documentinfo.xml" ) )
1098 {
1099 TQDomDocument doc = d->m_docInfo->save();
1100 KoStoreDevice dev( store );
1101
1102 TQCString s = doc.toCString(); // this is already Utf8!
1103 (void)dev.writeBlock( s.data(), s.size()-1 );
1104 (void)store->close();
1105 }
1106
1107 if ( store->open( "preview.png" ) )
1108 {
1109 // ### TODO: missing error checking (The partition could be full!)
1110 savePreview( store );
1111 (void)store->close();
1112 }
1113
1114 if ( !completeSaving( store ) )
1115 {
1116 delete store;
1117 return false;
1118 }
1119 kdDebug(30003) << "Saving done of url: " << url().url() << endl;
1120 delete store;
1121 }
1122 if ( !saveExternalChildren() )
1123 {
1124 return false;
1125 }
1126 return true;
1127}
1128
1129bool KoDocument::saveToStream( TQIODevice * dev )
1130{
1131 TQDomDocument doc = saveXML();
1132 // Save to buffer
1133 TQCString s = doc.toCString(); // utf8 already
1134 // We use TQCString::size()-1 here, not the official TQCString::length
1135 // It works here, as we are not modifying TQCString as TQByteArray
1136 int nwritten = dev->writeBlock( s.data(), s.size()-1 );
1137 if ( nwritten != (int)s.size()-1 )
1138 kdWarning(30003) << "KoDocument::saveToStream wrote " << nwritten << " - expected " << s.size()-1 << endl;
1139 return nwritten == (int)s.size()-1;
1140}
1141
1142// Called for embedded documents
1143bool KoDocument::saveToStore( KoStore* _store, const TQString & _path )
1144{
1145 kdDebug(30003) << "Saving document to store " << _path << endl;
1146
1147 // Use the path as the internal url
1148 if ( _path.startsWith( STORE_PROTOCOL ) )
1149 m_url = KURL( _path );
1150 else // ugly hack to pass a relative URI
1151 m_url = KURL( INTERNAL_PREFIX + _path );
1152
1153 // To make the children happy cd to the correct directory
1154 _store->pushDirectory();
1155 _store->enterDirectory( _path );
1156
1157 // Save childen first since they might get a new url
1158 if ( !saveChildren( _store ) )
1159 return false;
1160
1161 // In the current directory we're the king :-)
1162 if ( _store->open( "root" ) )
1163 {
1164 KoStoreDevice dev( _store );
1165 if ( !saveToStream( &dev ) )
1166 {
1167 _store->close();
1168 return false;
1169 }
1170 if ( !_store->close() )
1171 return false;
1172 }
1173
1174 if ( !completeSaving( _store ) )
1175 return false;
1176
1177 // Now that we're done leave the directory again
1178 _store->popDirectory();
1179
1180 kdDebug(30003) << "Saved document to store" << endl;
1181
1182 return true;
1183}
1184
1185bool KoDocument::saveOasisPreview( KoStore* store, KoXmlWriter* manifestWriter )
1186{
1187 const TQPixmap pix = generatePreview( TQSize( 128, 128 ) );
1188 TQImage preview ( pix.convertToImage().convertDepth( 32, TQt::ColorOnly ) );
1189 if ( !preview.hasAlphaBuffer() )
1190 {
1191 preview.setAlphaBuffer( true );
1192 }
1193 // ### TODO: freedesktop.org Thumbnail specification (date...)
1194 KoStoreDevice io ( store );
1195 if ( !io.open( IO_WriteOnly ) )
1196 return false;
1197 if ( ! preview.save( &io, "PNG", 0 ) )
1198 return false;
1199 io.close();
1200 manifestWriter->addManifestEntry( "Thumbnails/", "" );
1201 manifestWriter->addManifestEntry( "Thumbnails/thumbnail.png", "" );
1202 return true;
1203}
1204
1205bool KoDocument::savePreview( KoStore* store )
1206{
1207 TQPixmap pix = generatePreview(TQSize(256, 256));
1208 // Reducing to 8bpp reduces file sizes quite a lot.
1209 const TQImage preview ( pix.convertToImage().convertDepth( 8, TQt::AvoidDither | TQt::DiffuseDither) );
1210 KoStoreDevice io ( store );
1211 if ( !io.open( IO_WriteOnly ) )
1212 return false;
1213 if ( ! preview.save( &io, "PNG" ) ) // ### TODO What is -9 in quality terms?
1214 return false;
1215 io.close();
1216 return true;
1217}
1218
1219TQPixmap KoDocument::generatePreview( const TQSize& size )
1220{
1221 double docWidth, docHeight;
1222 int pixmapSize = TQMAX(size.width(), size.height());
1223
1224 if (m_pageLayout.ptWidth > 1.0) {
1225 docWidth = m_pageLayout.ptWidth / 72 * KoGlobal::dpiX();
1226 docHeight = m_pageLayout.ptHeight / 72 * KoGlobal::dpiY();
1227
1228 } else {
1229 // If we don't have a page layout, just draw the top left hand corner
1230 docWidth = 500.0;
1231 docHeight = 500.0;
1232 }
1233
1234 double ratio = docWidth / docHeight;
1235
1236 TQPixmap pix;
1237 int previewWidth, previewHeight;
1238 if (ratio > 1.0)
1239 {
1240 previewWidth = (int) pixmapSize;
1241 previewHeight = (int) (pixmapSize / ratio);
1242 }
1243 else
1244 {
1245 previewWidth = (int) (pixmapSize * ratio);
1246 previewHeight = (int) pixmapSize;
1247 }
1248
1249 pix.resize((int)docWidth, (int)docHeight);
1250
1251 pix.fill( TQColor( 245, 245, 245 ) );
1252
1253 TQRect rc(0, 0, pix.width(), pix.height());
1254
1255 TQPainter p;
1256 p.begin(&pix);
1257 paintEverything(p, rc, false);
1258 p.end();
1259
1260 // ### TODO: why re-convert it to a TQPixmap, when mostly it will be re-converted back to a TQImage in the calling function
1261 pix.convertFromImage(pix.convertToImage().smoothScale(previewWidth, previewHeight));
1262
1263 return pix;
1264}
1265
1266TQString KoDocument::autoSaveFile( const TQString & path ) const
1267{
1268 // set local again as it can happen that it gets resetted
1269 // so that all saved numbers have a . and not e.g a , as a
1270 // decimal seperator
1271 setlocale( LC_NUMERIC, "C" );
1272
1273 // Using the extension allows to avoid relying on the mime magic when opening
1274 KMimeType::Ptr mime = KMimeType::mimeType( nativeFormatMimeType() );
1275 TQString extension = mime->property( "X-TDE-NativeExtension" ).toString();
1276 if ( path.isEmpty() )
1277 {
1278 // Never saved? Use a temp file in $HOME then
1279 // Yes, two open unnamed docs will overwrite each other's autosave file,
1280 // but hmm, we can only do something if that's in the same process anyway...
1281 TQString ret = TQDir::homeDirPath() + "/." + TQString::fromLatin1(instance()->instanceName()) + ".autosave" + extension;
1282 return ret;
1283 }
1284 else
1285 {
1286 KURL url( path );
1287 Q_ASSERT( url.isLocalFile() );
1288 TQString dir = url.directory(false);
1289 TQString filename = url.fileName();
1290 return dir + "." + filename + ".autosave" + extension;
1291 }
1292}
1293
1295{
1296 TQString asf = autoSaveFile( TQString() ); // the one in $HOME
1297 //kdDebug(30003) << "asf=" << asf << endl;
1298 if ( TQFile::exists( asf ) )
1299 {
1300 TQDateTime date = TQFileInfo(asf).lastModified();
1301 TQString dateStr = date.toString(TQt::LocalDate);
1303 0, i18n( "An autosaved file for an unnamed document exists in %1.\nThis file is dated %2\nDo you want to open it?" )
1304 .arg(asf, dateStr) );
1305 switch(res) {
1306 case KMessageBox::Yes : {
1307 KURL url;
1308 url.setPath( asf );
1309 bool ret = openURL( url );
1310 if ( ret )
1311 resetURL();
1312 return ret;
1313 }
1314 case KMessageBox::No :
1315 TQFile::remove( asf );
1316 return false;
1317 default: // Cancel
1318 return false;
1319 }
1320 }
1321 return false;
1322}
1323
1324bool KoDocument::import( const KURL & _url )
1325{
1326 bool ret;
1327
1328 kdDebug (30003) << "KoDocument::import url=" << _url.url() << endl;
1329 d->m_isImporting = true;
1330
1331 // open...
1332 ret = openURL (_url);
1333
1334 // reset m_url & m_file (kindly? set by KParts::openURL()) to simulate a
1335 // File --> Import
1336 if (ret)
1337 {
1338 kdDebug (30003) << "KoDocument::import success, resetting url" << endl;
1339 resetURL ();
1341 }
1342
1343 d->m_isImporting = false;
1344
1345 return ret;
1346}
1347
1348bool KoDocument::openURL( const KURL & _url )
1349{
1350 kdDebug(30003) << "KoDocument::openURL url=" << _url.url() << endl;
1351 d->lastErrorMessage = TQString();
1352
1353 // Reimplemented, to add a check for autosave files and to improve error reporting
1354 if ( !_url.isValid() )
1355 {
1356 d->lastErrorMessage = i18n( "Malformed URL\n%1" ).arg( _url.url() ); // ## used anywhere ?
1357 return false;
1358 }
1359 if ( !closeURL() )
1360 return false;
1361
1362 KURL url( _url );
1363 bool autosaveOpened = false;
1364 d->m_bLoading = true;
1365 if ( url.isLocalFile() && d->m_shouldCheckAutoSaveFile )
1366 {
1367 TQString file = url.path();
1368 TQString asf = autoSaveFile( file );
1369 if ( TQFile::exists( asf ) )
1370 {
1371 //kdDebug(30003) << "KoDocument::openURL asf=" << asf << endl;
1372 // ## TODO compare timestamps ?
1374 i18n( "An autosaved file exists for this document.\nDo you want to open it instead?" ));
1375 switch(res) {
1376 case KMessageBox::Yes :
1377 url.setPath( asf );
1378 autosaveOpened = true;
1379 break;
1380 case KMessageBox::No :
1381 TQFile::remove( asf );
1382 break;
1383 default: // Cancel
1384 d->m_bLoading = false;
1385 return false;
1386 }
1387 }
1388 }
1389
1390 bool ret = KParts::ReadWritePart::openURL( url );
1391
1392 if ( autosaveOpened )
1393 resetURL(); // Force save to act like 'Save As'
1394 else
1395 {
1396 // We have no koffice shell when we are being embedded as a readonly part.
1397 //if ( d->m_shells.isEmpty() )
1398 // kdWarning(30003) << "KoDocument::openURL no shell yet !" << endl;
1399 // Add to recent actions list in our shells
1400 TQPtrListIterator<KoMainWindow> it( d->m_shells );
1401 for (; it.current(); ++it )
1402 it.current()->addRecentURL( _url );
1403 }
1404 return ret;
1405}
1406
1408{
1409 //kdDebug(30003) << "KoDocument::openFile for " << m_file << endl;
1410 if ( !TQFile::exists(m_file) )
1411 {
1412 TQApplication::restoreOverrideCursor();
1413 if ( d->m_autoErrorHandlingEnabled )
1414 // Maybe offer to create a new document with that name ?
1415 KMessageBox::error(0L, i18n("The file %1 does not exist.").arg(m_file) );
1416 d->m_bLoading = false;
1417 return false;
1418 }
1419
1420 TQApplication::setOverrideCursor( waitCursor );
1421
1422 d->m_specialOutputFlag = 0;
1423 TQCString _native_format = nativeFormatMimeType();
1424
1425 KURL u;
1426 u.setPath( m_file );
1427 TQString typeName = KMimeType::findByURL( u, 0, true )->name();
1428
1429 // Allow to open backup files, don't keep the mimetype application/x-trash.
1430 if ( typeName == "application/x-trash" )
1431 {
1432 TQString path = u.path();
1433 TQStringList patterns = KMimeType::mimeType( typeName )->patterns();
1434 // Find the extension that makes it a backup file, and remove it
1435 for( TQStringList::Iterator it = patterns.begin(); it != patterns.end(); ++it ) {
1436 TQString ext = *it;
1437 if ( !ext.isEmpty() && ext[0] == '*' )
1438 {
1439 ext.remove(0, 1);
1440 if ( path.endsWith( ext ) ) {
1441 path.truncate( path.length() - ext.length() );
1442 break;
1443 }
1444 }
1445 }
1446 typeName = KMimeType::findByPath( path, 0, true )->name();
1447 }
1448
1449 // Special case for flat XML files (e.g. using directory store)
1450 if ( u.fileName() == "maindoc.xml" || u.fileName() == "content.xml" || typeName == "inode/directory" )
1451 {
1452 typeName = _native_format; // Hmm, what if it's from another app? ### Check mimetype
1453 d->m_specialOutputFlag = SaveAsDirectoryStore;
1454 kdDebug(30003) << "KoDocument::openFile loading " << u.fileName() << ", using directory store for " << m_file << "; typeName=" << typeName << endl;
1455 }
1456 kdDebug(30003) << "KoDocument::openFile " << m_file << " type:" << typeName << endl;
1457
1458 TQString importedFile = m_file;
1459
1460 if ( !isNativeFormat( typeName.latin1() ) ) {
1461 if ( !d->filterManager )
1462 d->filterManager = new KoFilterManager( this );
1464 importedFile = d->filterManager->import( m_file, status );
1465 if ( status != KoFilter::OK )
1466 {
1467 TQApplication::restoreOverrideCursor();
1468
1469 TQString msg;
1470 switch( status )
1471 {
1472 case KoFilter::OK: break;
1473
1474 case KoFilter::CreationError:
1475 msg = i18n( "Creation error" ); break;
1476
1477 case KoFilter::FileNotFound:
1478 msg = i18n( "File not found" ); break;
1479
1480 case KoFilter::StorageCreationError:
1481 msg = i18n( "Cannot create storage" ); break;
1482
1483 case KoFilter::BadMimeType:
1484 msg = i18n( "Bad MIME type" ); break;
1485
1486 case KoFilter::EmbeddedDocError:
1487 msg = i18n( "Error in embedded document" ); break;
1488
1489 case KoFilter::WrongFormat:
1490 msg = i18n( "Format not recognized" ); break;
1491
1492 case KoFilter::NotImplemented:
1493 msg = i18n( "Not implemented" ); break;
1494
1495 case KoFilter::ParsingError:
1496 msg = i18n( "Parsing error" ); break;
1497
1498 case KoFilter::PasswordProtected:
1499 msg = i18n( "Document is password protected" ); break;
1500
1501 case KoFilter::InternalError:
1502 case KoFilter::UnexpectedEOF:
1503 case KoFilter::UnexpectedOpcode:
1504 case KoFilter::StupidError: // ?? what is this ??
1505 case KoFilter::UsageError:
1506 msg = i18n( "Internal error" ); break;
1507
1508 case KoFilter::OutOfMemory:
1509 msg = i18n( "Out of memory" ); break;
1510
1511 case KoFilter::UserCancelled:
1512 case KoFilter::BadConversionGraph:
1513 // intentionally we do not prompt the error message here
1514 break;
1515
1516 default: msg = i18n( "Unknown error" ); break;
1517 }
1518
1519 if( d->m_autoErrorHandlingEnabled && !msg.isEmpty())
1520 {
1521 TQString errorMsg( i18n( "Could not open\n%2.\nReason: %1" ) );
1522 TQString docUrl = url().prettyURL( 0, KURL::StripFileProtocol );
1523 KMessageBox::error( 0L, errorMsg.arg(msg).arg(docUrl) );
1524 }
1525
1526 d->m_bLoading = false;
1527 return false;
1528 }
1529 kdDebug(30003) << "KoDocument::openFile - importedFile '" << importedFile
1530 << "', status: " << static_cast<int>( status ) << endl;
1531 }
1532
1533 TQApplication::restoreOverrideCursor();
1534
1535 bool ok = true;
1536
1537 if (!importedFile.isEmpty()) // Something to load (tmp or native file) ?
1538 {
1539 // The filter, if any, has been applied. It's all native format now.
1540 if ( !loadNativeFormat( importedFile ) )
1541 {
1542 ok = false;
1543 if ( d->m_autoErrorHandlingEnabled )
1544 {
1546 }
1547 }
1548 }
1549
1550 if ( importedFile != m_file )
1551 {
1552 // We opened a temporary file (result of an import filter)
1553 // Set document URL to empty - we don't want to save in /tmp !
1554 // But only if in readwrite mode (no saving problem otherwise)
1555 // --
1556 // But this isn't true at all. If this is the result of an
1557 // import, then importedFile=temporary_file.kwd and
1558 // m_file/m_url=foreignformat.ext so m_url is correct!
1559 // So don't resetURL() or else the caption won't be set when
1560 // foreign files are opened (an annoying bug).
1561 // - Clarence
1562 //
1563#if 0
1564 if ( isReadWrite() )
1565 resetURL();
1566#endif
1567
1568 // remove temp file - uncomment this to debug import filters
1569 if(!importedFile.isEmpty()) {
1570 TQFile::remove( importedFile );
1571 }
1572 }
1573
1574 if ( ok && d->m_bSingleViewMode )
1575 {
1576 // See addClient below
1577 KXMLGUIFactory* guiFactory = factory();
1578 if( guiFactory ) // 0L when splitting views in konq, for some reason
1579 guiFactory->removeClient( this );
1580
1581 if ( !d->m_views.isEmpty() )
1582 {
1583 // We already had a view (this happens when doing reload in konqueror)
1584 KoView* v = d->m_views.first();
1585 if( guiFactory )
1586 guiFactory->removeClient( v );
1587 removeView( v );
1588 delete v;
1589 Q_ASSERT( d->m_views.isEmpty() );
1590 }
1591
1592 KoView *view = createView( d->m_wrapperWidget );
1593 d->m_wrapperWidget->setKoView( view );
1594 view->show();
1595
1596 // Ok, now we have a view, so action() and domDocument() will work as expected
1597 // -> rebuild GUI
1598 if ( guiFactory )
1599 guiFactory->addClient( this );
1600 }
1601
1602 if ( ok )
1603 {
1604 setMimeTypeAfterLoading( typeName );
1605 }
1606 d->m_bLoading = false;
1607 return ok;
1608}
1609
1610// shared between openFile and koMainWindow's "create new empty document" code
1611void KoDocument::setMimeTypeAfterLoading( const TQString& mimeType )
1612{
1613 d->mimeType = mimeType.latin1();
1614
1615 d->outputMimeType = d->mimeType;
1616
1617 const bool needConfirm = !isNativeFormat( d->mimeType );
1618 setConfirmNonNativeSave( false, needConfirm );
1619 setConfirmNonNativeSave( true, needConfirm );
1620}
1621
1622// The caller must call store->close() if loadAndParse returns true.
1623bool KoDocument::oldLoadAndParse(KoStore* store, const TQString& filename, TQDomDocument& doc)
1624{
1625 //kdDebug(30003) << "oldLoadAndParse: Trying to open " << filename << endl;
1626
1627 if (!store->open(filename))
1628 {
1629 kdWarning(30003) << "Entry " << filename << " not found!" << endl;
1630 d->lastErrorMessage = i18n( "Could not find %1" ).arg( filename );
1631 return false;
1632 }
1633 // Error variables for TQDomDocument::setContent
1634 TQString errorMsg;
1635 int errorLine, errorColumn;
1636 bool ok = doc.setContent( store->device(), &errorMsg, &errorLine, &errorColumn );
1637 if ( !ok )
1638 {
1639 kdError(30003) << "Parsing error in " << filename << "! Aborting!" << endl
1640 << " In line: " << errorLine << ", column: " << errorColumn << endl
1641 << " Error message: " << errorMsg << endl;
1642 d->lastErrorMessage = i18n( "Parsing error in %1 at line %2, column %3\nError message: %4" )
1643 .arg( filename ).arg( errorLine ).arg( errorColumn )
1644 .arg( i18n ( "TQXml", errorMsg.utf8() ) );
1645 store->close();
1646 return false;
1647 }
1648 kdDebug(30003) << "File " << filename << " loaded and parsed" << endl;
1649 return true;
1650}
1651
1652bool KoDocument::loadNativeFormat( const TQString & file )
1653{
1654 TQFileInfo fileInfo( file );
1655 if ( !fileInfo.exists() ) // check duplicated from openURL, but this is useful for templates
1656 {
1657 d->lastErrorMessage = i18n("The file %1 does not exist.").arg(file);
1658 return false;
1659 }
1660 if ( !fileInfo.isFile() )
1661 {
1662 d->lastErrorMessage = i18n( "%1 is not a file." ).arg(file);
1663 return false;
1664 }
1665
1666 TQApplication::setOverrideCursor( waitCursor );
1667
1668 kdDebug(30003) << "KoDocument::loadNativeFormat( " << file << " )" << endl;
1669
1670 TQFile in;
1671 bool isRawXML = false;
1672 if ( d->m_specialOutputFlag != SaveAsDirectoryStore ) // Don't try to open a directory ;)
1673 {
1674 in.setName(file);
1675 if ( !in.open( IO_ReadOnly ) )
1676 {
1677 TQApplication::restoreOverrideCursor();
1678 d->lastErrorMessage = i18n( "Could not open the file for reading (check read permissions)." );
1679 return false;
1680 }
1681
1682 // Try to find out whether it is a mime multi part file
1683 char buf[5];
1684 if ( in.readBlock( buf, 4 ) < 4 )
1685 {
1686 TQApplication::restoreOverrideCursor();
1687 in.close();
1688 d->lastErrorMessage = i18n( "Could not read the beginning of the file." );
1689 return false;
1690 }
1691 // ### TODO: allow UTF-16
1692 isRawXML = (strncasecmp( buf, "<?xm", 4 ) == 0);
1693 if ( !isRawXML ) {
1694 // Still check for broken MathML files, which seem to be rather common
1695 in.reset();
1696 // Remove spaces
1697 do {
1698 if ( in.readBlock( buf , 1 ) < 1 )
1699 {
1700 TQApplication::restoreOverrideCursor();
1701 in.close();
1702 d->lastErrorMessage = i18n( "Could not read the beginning of the file." );
1703 return false;
1704 }
1705 } while ( TQChar( buf[0] ).isSpace() );
1706 if ( buf[0] == '<' ) { // First not-space character
1707 if ( in.readBlock( buf , 4 ) < 4 )
1708 {
1709 TQApplication::restoreOverrideCursor();
1710 in.close();
1711 d->lastErrorMessage = i18n( "Could not read the beginning of the file." );
1712 return false;
1713 }
1714 isRawXML = (strncasecmp( buf, "math", 4 ) == 0); // file begins with <math ?
1715 }
1716 }
1717 //kdDebug(30003) << "PATTERN=" << buf << endl;
1718 }
1719 // Is it plain XML?
1720 if ( isRawXML )
1721 {
1722 in.at(0);
1723 TQString errorMsg;
1724 int errorLine;
1725 int errorColumn;
1726 TQDomDocument doc;
1727 bool res;
1728 if ( doc.setContent( &in, true, &errorMsg, &errorLine, &errorColumn ) )
1729 {
1730 res = loadXML( &in, doc );
1731 if ( res )
1732 res = completeLoading( 0L );
1733 }
1734 else
1735 {
1736 kdError (30003) << "Parsing Error! Aborting! (in KoDocument::loadNativeFormat (TQFile))" << endl
1737 << " Line: " << errorLine << " Column: " << errorColumn << endl
1738 << " Message: " << errorMsg << endl;
1739 d->lastErrorMessage = i18n( "parsing error in the main document at line %1, column %2\nError message: %3" )
1740 .arg( errorLine ).arg( errorColumn ).arg( i18n ( errorMsg.utf8() ) );
1741 res=false;
1742 }
1743
1744 TQApplication::restoreOverrideCursor();
1745 in.close();
1746 m_bEmpty = false;
1747 return res;
1748 } else
1749 { // It's a koffice store (tar.gz, zip, directory, etc.)
1750 in.close();
1751
1752 return loadNativeFormatFromStore( file );
1753 }
1754}
1755
1756bool KoDocument::loadNativeFormatFromStore( const TQString& file )
1757{
1758 KoStore::Backend backend = (d->m_specialOutputFlag == SaveAsDirectoryStore) ? KoStore::Directory : KoStore::Auto;
1759 KoStore * store = KoStore::createStore( file, KoStore::Read, "", backend );
1760
1761 if ( store->bad() )
1762 {
1763 d->lastErrorMessage = i18n( "Not a valid KOffice file: %1" ).arg( file );
1764 delete store;
1765 TQApplication::restoreOverrideCursor();
1766 return false;
1767 }
1768
1769 bool oasis = true;
1770 // OASIS/OOo file format?
1771 if ( store->hasFile( "content.xml" ) )
1772 {
1773 store->disallowNameExpansion();
1774
1775 KoOasisStore oasisStore( store );
1776 // We could check the 'mimetype' file, but let's skip that and be tolerant.
1777
1778 if ( !loadOasisFromStore( store ) ) {
1779 delete store;
1780 TQApplication::restoreOverrideCursor();
1781 return false;
1782 }
1783
1784 } else if ( store->hasFile( "root" ) ) // Fallback to "old" file format (maindoc.xml)
1785 {
1786 oasis = false;
1787
1788 TQDomDocument doc;
1789 bool ok = oldLoadAndParse( store, "root", doc );
1790 if ( ok )
1791 ok = loadXML( store->device(), doc );
1792 if ( !ok )
1793 {
1794 delete store;
1795 TQApplication::restoreOverrideCursor();
1796 return false;
1797 }
1798 store->close();
1799
1800 if ( !loadChildren( store ) )
1801 {
1802 kdError(30003) << "ERROR: Could not load children" << endl;
1803 // Don't abort, proceed nonetheless
1804 }
1805
1806 } else
1807 {
1808 kdError(30003) << "ERROR: No maindoc.xml" << endl;
1809 d->lastErrorMessage = i18n( "Invalid document: no file 'maindoc.xml'." );
1810 delete store;
1811 TQApplication::restoreOverrideCursor();
1812 return false;
1813 }
1814
1815 if ( oasis && store->hasFile( "meta.xml" ) ) {
1816 TQDomDocument metaDoc;
1817 KoOasisStore oasisStore( store );
1818 if ( oasisStore.loadAndParse( "meta.xml", metaDoc, d->lastErrorMessage ) ) {
1819 d->m_docInfo->loadOasis( metaDoc );
1820 }
1821 }
1822 else if ( !oasis && store->hasFile( "documentinfo.xml" ) )
1823 {
1824 TQDomDocument doc;
1825 if ( oldLoadAndParse( store, "documentinfo.xml", doc ) ) {
1826 store->close();
1827 d->m_docInfo->load( doc );
1828 }
1829 }
1830 else
1831 {
1832 //kdDebug( 30003 ) << "cannot open document info" << endl;
1833 delete d->m_docInfo;
1834 d->m_docInfo = new KoDocumentInfo( this, "document info" );
1835 }
1836
1837 bool res = completeLoading( store );
1838 delete store;
1839 TQApplication::restoreOverrideCursor();
1840 m_bEmpty = false;
1841 return res;
1842}
1843
1844// For embedded documents
1845bool KoDocument::loadFromStore( KoStore* _store, const TQString& url )
1846{
1847 if ( _store->open( url ) )
1848 {
1849 TQDomDocument doc;
1850 doc.setContent( _store->device() );
1851 if ( !loadXML( _store->device(), doc ) )
1852 {
1853 _store->close();
1854 return false;
1855 }
1856 _store->close();
1857 } else {
1858 kdWarning() << "couldn't open " << url << endl;
1859 }
1860
1861 _store->pushDirectory();
1862 // Store as document URL
1863 if ( url.startsWith( STORE_PROTOCOL ) ) {
1864 m_url = KURL( url );
1865 } else {
1866 m_url = KURL( INTERNAL_PREFIX + url );
1867 _store->enterDirectory( url );
1868 }
1869
1870 if ( !loadChildren( _store ) )
1871 {
1872 kdError(30003) << "ERROR: Could not load children" << endl;
1873#if 0
1874 return false;
1875#endif
1876 }
1877
1878 bool result = completeLoading( _store );
1879
1880 // Restore the "old" path
1881 _store->popDirectory();
1882
1883 return result;
1884}
1885
1887{
1888 KoOasisStyles oasisStyles;
1889 TQDomDocument contentDoc;
1890 TQDomDocument settingsDoc;
1891 KoOasisStore oasisStore( store );
1892 bool ok = oasisStore.loadAndParse( "content.xml", contentDoc, d->lastErrorMessage );
1893 if ( !ok )
1894 return false;
1895
1896 TQDomDocument stylesDoc;
1897 (void)oasisStore.loadAndParse( "styles.xml", stylesDoc, d->lastErrorMessage );
1898 // Load styles from style.xml
1899 oasisStyles.createStyleMap( stylesDoc, true );
1900 // Also load styles from content.xml
1901 oasisStyles.createStyleMap( contentDoc, false );
1902
1903 // TODO post 1.4, pass manifestDoc to the apps so that they don't have to do it themselves
1904 // (when calling KoDocumentChild::loadOasisDocument)
1905 //TQDomDocument manifestDoc;
1906 //KoOasisStore oasisStore( store );
1907 //if ( !oasisStore.loadAndParse( "tar:/META-INF/manifest.xml", manifestDoc, d->lastErrorMessage ) )
1908 // return false;
1909
1910 if ( store->hasFile( "settings.xml" ) ) {
1911 (void)oasisStore.loadAndParse( "settings.xml", settingsDoc, d->lastErrorMessage );
1912 }
1913 if ( !loadOasis( contentDoc, oasisStyles, settingsDoc, store ) )
1914 return false;
1915
1916 return true;
1917}
1918
1919bool KoDocument::isInOperation() const
1920{
1921 return d->m_numOperations > 0;
1922}
1923
1924void KoDocument::emitBeginOperation()
1925{
1926
1927 /* if we're already in an operation, don't send the signal again */
1928 if (!isInOperation())
1929 emit sigBeginOperation();
1930 d->m_numOperations++;
1931}
1932
1933void KoDocument::emitEndOperation()
1934{
1935 d->m_numOperations--;
1936
1937 /* don't end the operation till we've cleared all the nested operations */
1938 if (d->m_numOperations == 0)
1939 emit sigEndOperation();
1940 else if (d->m_numOperations < 0)
1941 /* ignore 'end' calls with no matching 'begin' call */
1942 d->m_numOperations = 0;
1943}
1944
1945
1947{
1948 return !storeInternal() && hasExternURL();
1949}
1950
1952{
1953 if ( isAutosaving() ) // ignore setModified calls due to autosaving
1954 return;
1955
1956 //kdDebug(30003)<<k_funcinfo<<" url:" << m_url.path() << endl;
1957 //kdDebug(30003)<<k_funcinfo<<" mod="<<mod<<" MParts mod="<<KParts::ReadWritePart::isModified()<<" isModified="<<isModified()<<endl;
1958
1959 if ( mod && !d->modifiedAfterAutosave ) {
1960 // First change since last autosave -> start the autosave timer
1961 setAutoSave( d->m_autoSaveDelay );
1962 }
1963 d->modifiedAfterAutosave = mod;
1964
1965 if ( mod == isModified() )
1966 return;
1967
1969
1970 if ( mod ) {
1971 m_bEmpty = false;
1972 } else {
1973 // When saving this document, all non-external child documents get saved too.
1974 TQPtrListIterator<KoDocumentChild> it = children();
1975 for (; it.current(); ++it )
1976 {
1977 KoDocument *doc = it.current()->document();
1978 if ( doc && !it.current()->isStoredExtern() && !it.current()->isDeleted() && doc->isModified() )
1979 doc->setModified( false );
1980 }
1981 }
1982
1983 // This influences the title
1985 emit modified( mod );
1986}
1987
1989{
1990 d->m_doNotSaveExtDoc = on;
1991}
1992
1993int KoDocument::queryCloseDia()
1994{
1995 //kdDebug(30003)<<k_funcinfo<<endl;
1996
1997 TQString name;
1998 if ( documentInfo() )
1999 {
2000 name = documentInfo()->title();
2001 }
2002 if ( name.isEmpty() )
2003 name = url().fileName();
2004
2005 if ( name.isEmpty() )
2006 name = i18n( "Untitled" );
2007
2008 int res = KMessageBox::warningYesNoCancel( 0L,
2009 i18n( "<p>The document <b>'%1'</b> has been modified.</p><p>Do you want to save it?</p>" ).arg(name));
2010
2011 switch(res)
2012 {
2013 case KMessageBox::Yes :
2014 setDoNotSaveExtDoc(); // Let save() only save myself and my internal docs
2015 save(); // NOTE: External files always in native format. ###TODO: Handle non-native format
2016 setModified( false ); // Now when queryClose() is called by closeEvent it won't do anything.
2017 break;
2018 case KMessageBox::No :
2020 setModified( false ); // Now when queryClose() is called by closeEvent it won't do anything.
2021 break;
2022 default : // case KMessageBox::Cancel :
2023 return res; // cancels the rest of the files
2024 }
2025 return res;
2026}
2027
2028int KoDocument::queryCloseExternalChildren()
2029{
2030 //kdDebug(30003)<<k_funcinfo<<" checking for children in: "<<url().url()<<endl;
2031 setDoNotSaveExtDoc(false);
2032 TQPtrListIterator<KoDocumentChild> it( children() );
2033 for (; it.current(); ++it )
2034 {
2035 if ( !it.current()->isDeleted() )
2036 {
2037 KoDocument *doc = it.current()->document();
2038 if ( doc )
2039 {
2040 bool foo = doc->isStoredExtern();
2041 kdDebug(36001) << "========== isStoredExtern() returned "
2042 << foo << " ==========" << endl;
2043
2044 if ( foo ) //###TODO: Handle non-native mimetype docs
2045 {
2046 {
2047 kdDebug(30003)<<k_funcinfo<<" found modified child: "<<doc->url().url()<<" extern="<<doc->isStoredExtern()<<endl;
2048 if ( doc->queryCloseDia() == KMessageBox::Cancel )
2049 return KMessageBox::Cancel;
2050 }
2051 }
2052 if ( doc->queryCloseExternalChildren() == KMessageBox::Cancel )
2053 return KMessageBox::Cancel;
2054 }
2055 }
2056 }
2057 return KMessageBox::Ok;
2058}
2059
2060void KoDocument::setTitleModified( const TQString caption, bool mod )
2061{
2062 //kdDebug(30003)<<k_funcinfo<<" url: "<<url().url()<<" caption: "<<caption<<" mod: "<<mod<<endl;
2063 KoDocument *doc = dynamic_cast<KoDocument *>( parent() );
2064 if ( doc )
2065 {
2066 doc->setTitleModified( caption, mod );
2067 return;
2068 }
2069 // we must be root doc so update caption in all related windows
2070 TQPtrListIterator<KoMainWindow> it( d->m_shells );
2071 for (; it.current(); ++it )
2072 {
2073 it.current()->updateCaption();
2074 it.current()->updateReloadFileAction(this);
2075 it.current()->updateVersionsFileAction(this);
2076 }
2077}
2078
2080{
2081 //kdDebug(30003)<<k_funcinfo<<" url: "<<url().url()<<" extern: "<<isStoredExtern()<<" current: "<<d->m_current<<endl;
2082 KoDocument *doc = dynamic_cast<KoDocument *>( parent() );
2083 TQString caption;
2084 if ( (url().isEmpty() || isStoredExtern()) && d->m_current )
2085 {
2086 // Get caption from document info (title(), in about page)
2087 if ( documentInfo() )
2088 {
2089 KoDocumentInfoPage * page = documentInfo()->page( TQString::fromLatin1("about") );
2090 if (page)
2091 caption = static_cast<KoDocumentInfoAbout *>(page)->title();
2092 }
2093 if ( caption.isEmpty() )
2094 caption = url().prettyURL( 0, KURL::StripFileProtocol ); // Fall back to document URL
2095
2096 //kdDebug(30003)<<k_funcinfo<<" url: "<<url().url()<<" caption: "<<caption<<endl;
2097 if ( doc )
2098 {
2099 doc->setTitleModified( caption, isModified() );
2100 return;
2101 }
2102 else
2103 {
2104 // we must be root doc so update caption in all related windows
2105 setTitleModified( caption, isModified() );
2106 return;
2107 }
2108 }
2109 if ( doc )
2110 {
2111 // internal doc or not current doc, so pass on the buck
2112 doc->setTitleModified();
2113 }
2114}
2115
2117{
2118 return true;
2119}
2120
2122{
2123 return true;
2124}
2125
2127{
2128 return true;
2129}
2130
2131TQDomDocument KoDocument::createDomDocument( const TQString& tagName, const TQString& version ) const
2132{
2133 return createDomDocument( instance()->instanceName(), tagName, version );
2134}
2135
2136//static
2137TQDomDocument KoDocument::createDomDocument( const TQString& appName, const TQString& tagName, const TQString& version )
2138{
2139 TQDomImplementation impl;
2140 TQString url = TQString("http://www.koffice.org/DTD/%1-%1.dtd").arg(appName).arg(version);
2141 TQDomDocumentType dtype = impl.createDocumentType( tagName,
2142 TQString("-//KDE//DTD %1 %1//EN").arg(appName).arg(version),
2143 url );
2144 // The namespace URN doesn't need to include the version number.
2145 TQString namespaceURN = TQString("http://www.koffice.org/DTD/%1").arg(appName);
2146 TQDomDocument doc = impl.createDocument( namespaceURN, tagName, dtype );
2147 doc.insertBefore( doc.createProcessingInstruction( "xml", "version=\"1.0\" encoding=\"UTF-8\"" ), doc.documentElement() );
2148 return doc;
2149}
2150
2151KoXmlWriter* KoDocument::createOasisXmlWriter( TQIODevice* dev, const char* rootElementName )
2152{
2153 KoXmlWriter* writer = new KoXmlWriter( dev );
2154 writer->startDocument( rootElementName );
2155 writer->startElement( rootElementName );
2156 writer->addAttribute( "xmlns:office", KoXmlNS::office );
2157 writer->addAttribute( "xmlns:meta", KoXmlNS::meta );
2158
2159 if ( qstrcmp( rootElementName, "office:document-meta" ) != 0 ) {
2160 writer->addAttribute( "xmlns:config", KoXmlNS::config );
2161 writer->addAttribute( "xmlns:text", KoXmlNS::text );
2162 writer->addAttribute( "xmlns:table", KoXmlNS::table );
2163 writer->addAttribute( "xmlns:draw", KoXmlNS::draw );
2164 writer->addAttribute( "xmlns:presentation", KoXmlNS::presentation );
2165 writer->addAttribute( "xmlns:dr3d", KoXmlNS::dr3d );
2166 writer->addAttribute( "xmlns:chart", KoXmlNS::chart );
2167 writer->addAttribute( "xmlns:form", KoXmlNS::form );
2168 writer->addAttribute( "xmlns:script", KoXmlNS::script );
2169 writer->addAttribute( "xmlns:style", KoXmlNS::style );
2170 writer->addAttribute( "xmlns:number", KoXmlNS::number );
2171 writer->addAttribute( "xmlns:math", KoXmlNS::math );
2172 writer->addAttribute( "xmlns:svg", KoXmlNS::svg );
2173 writer->addAttribute( "xmlns:fo", KoXmlNS::fo );
2174 writer->addAttribute( "xmlns:koffice", KoXmlNS::koffice );
2175 }
2176 // missing: office:version="1.0"
2177
2178 writer->addAttribute( "xmlns:dc", KoXmlNS::dc );
2179 writer->addAttribute( "xmlns:xlink", KoXmlNS::xlink );
2180 return writer;
2181}
2182
2183TQDomDocument KoDocument::saveXML()
2184{
2185 kdError(30003) << "KoDocument::saveXML not implemented" << endl;
2186 d->lastErrorMessage = i18n( "Internal error: saveXML not implemented" );
2187 return TQDomDocument();
2188}
2189
2190KService::Ptr KoDocument::nativeService()
2191{
2192 if ( !m_nativeService )
2193 m_nativeService = readNativeService( instance() );
2194
2195 return m_nativeService;
2196}
2197
2199{
2200 KService::Ptr service = const_cast<KoDocument *>(this)->nativeService();
2201 if ( !service )
2202 return TQCString();
2203 TQCString nativeMimeType = service->property( "X-TDE-NativeMimeType" ).toString().latin1();
2204 if ( nativeMimeType.isEmpty() ) {
2205 // shouldn't happen, let's find out why it happened
2206 if ( !service->serviceTypes().contains( "KOfficePart" ) )
2207 kdWarning(30003) << "Wrong desktop file, KOfficePart isn't mentionned" << endl;
2208 else if ( !KServiceType::serviceType( "KOfficePart" ) )
2209 kdWarning(30003) << "The KOfficePart service type isn't installed!" << endl;
2210 }
2211 return nativeMimeType;
2212}
2213
2215{
2216 KService::Ptr service = const_cast<KoDocument *>(this)->nativeService();
2217 if ( !service )
2218 return TQCString();
2219 return service->property( "X-TDE-NativeOasisMimeType" ).toString().latin1();
2220}
2221
2222
2223//static
2224KService::Ptr KoDocument::readNativeService( TDEInstance *instance )
2225{
2226 TQString instname = instance ? instance->instanceName() : kapp->instanceName();
2227
2228 // The new way is: we look for a foopart.desktop in the kde_services dir.
2229 TQString servicepartname = instname + "part.desktop";
2230 KService::Ptr service = KService::serviceByDesktopPath( servicepartname );
2231 if ( service )
2232 kdDebug(30003) << servicepartname << " found." << endl;
2233 if ( !service )
2234 {
2235 // The old way is kept as fallback for compatibility, but in theory this is really never used anymore.
2236
2237 // Try by path first, so that we find the global one (which has the native mimetype)
2238 // even if the user created a kword.desktop in ~/.trinity/share/applnk or any subdir of it.
2239 // If he created it under ~/.trinity/share/applnk/Office/ then no problem anyway.
2240 service = KService::serviceByDesktopPath( TQString::fromLatin1("Office/%1.desktop").arg(instname) );
2241 }
2242 if ( !service )
2243 service = KService::serviceByDesktopName( instname );
2244
2245 return service;
2246}
2247
2248TQCString KoDocument::readNativeFormatMimeType( TDEInstance *instance ) //static
2249{
2250 KService::Ptr service = readNativeService( instance );
2251 if ( !service )
2252 return TQCString();
2253
2254 if ( service->property( "X-TDE-NativeMimeType" ).toString().isEmpty() )
2255 {
2256 // It may be that the servicetype "KOfficePart" is missing, which leads to this property not being known
2257 if ( KServiceType::serviceType( "KOfficePart" ) == 0L )
2258 kdError(30003) << "The serviceType KOfficePart is missing. Check that you have a kofficepart.desktop file in the share/servicetypes directory." << endl;
2259 else {
2260 TQString instname = instance ? instance->instanceName() : kapp->instanceName();
2261 if ( instname != "koshell" ) // hack for koshell
2262 kdWarning(30003) << service->desktopEntryPath() << ": no X-TDE-NativeMimeType entry!" << endl;
2263 }
2264 }
2265
2266 return service->property( "X-TDE-NativeMimeType" ).toString().latin1();
2267}
2268
2269TQStringList KoDocument::readExtraNativeMimeTypes( TDEInstance *instance ) //static
2270{
2271 KService::Ptr service = readNativeService( instance );
2272 if ( !service )
2273 return TQStringList();
2274 return service->property( "X-TDE-ExtraNativeMimeTypes" ).toStringList();
2275}
2276
2277void KoDocument::setupXmlReader( TQXmlSimpleReader& reader, bool namespaceProcessing )
2278{
2279 if ( namespaceProcessing )
2280 {
2281 reader.setFeature( "http://xml.org/sax/features/namespaces", true );
2282 reader.setFeature( "http://xml.org/sax/features/namespace-prefixes", false );
2283 }
2284 else
2285 {
2286 reader.setFeature( "http://xml.org/sax/features/namespaces", false );
2287 reader.setFeature( "http://xml.org/sax/features/namespace-prefixes", true );
2288 }
2289 reader.setFeature( "http://trolltech.com/xml/features/report-whitespace-only-CharData", true );
2290}
2291
2292
2293bool KoDocument::isNativeFormat( const TQCString& mimetype ) const
2294{
2295 if ( mimetype == nativeFormatMimeType() )
2296 return true;
2297 return extraNativeMimeTypes().contains( mimetype );
2298}
2299
2301{
2302 TQStringList lst;
2303 // This implementation is temporary while we treat both koffice-1.3 and OASIS formats as native.
2304 // But it's good to have this virtual method, in case some app want to
2305 // support more than one native format.
2306 KService::Ptr service = const_cast<KoDocument *>(this)->nativeService();
2307 if ( !service ) // can't happen
2308 return lst;
2309 return service->property( "X-TDE-ExtraNativeMimeTypes" ).toStringList();
2310}
2311
2313{
2314 // Apps which support special output flags can add reimplement and add to this.
2315 // E.g. this is how did "saving in the 1.1 format".
2316 // SaveAsDirectoryStore is a given since it's implemented by KoDocument itself.
2317 return SaveAsDirectoryStore;
2318}
2319
2321{
2322 if ( d->m_shells.findRef( shell ) == -1 )
2323 {
2324 //kdDebug(30003) << "addShell: shell " << (void*)shell << " added to doc " << this << endl;
2325 d->m_shells.append( shell );
2326 }
2327}
2328
2330{
2331 //kdDebug(30003) << "removeShell: shell " << (void*)shell << " removed from doc " << this << endl;
2332 d->m_shells.removeRef( shell );
2333}
2334
2335const TQPtrList<KoMainWindow>& KoDocument::shells() const
2336{
2337 return d->m_shells;
2338}
2339
2341{
2342 return d->m_shells.count();
2343}
2344
2346{
2347 if ( !d->m_dcopObject )
2348 d->m_dcopObject = new KoDocumentIface( this );
2349 return d->m_dcopObject;
2350}
2351
2353{
2354 return const_cast<KoDocument *>(this)->dcopObject()->objId();
2355}
2356
2357void KoDocument::setErrorMessage( const TQString& errMsg )
2358{
2359 d->lastErrorMessage = errMsg;
2360}
2361
2363{
2364 return d->lastErrorMessage;
2365}
2366
2368{
2369 if ( d->lastErrorMessage.isEmpty() )
2370 {
2371 KMessageBox::error( 0L, i18n( "Could not save\n%1" ).arg( m_file ) );
2372 }
2373 else if ( d->lastErrorMessage != "USER_CANCELED" )
2374 {
2375 KMessageBox::error( 0L, i18n( "Could not save %1\nReason: %2" ).arg( m_file, d->lastErrorMessage ) );
2376 }
2377}
2378
2380{
2381 if ( d->lastErrorMessage.isEmpty() )
2382 {
2383 KMessageBox::error( 0L, i18n( "Could not open\n%1" ).arg( url().prettyURL( 0, KURL::StripFileProtocol ) ) );
2384 }
2385 else if ( d->lastErrorMessage != "USER_CANCELED" )
2386 {
2387 KMessageBox::error( 0L, i18n( "Could not open %1\nReason: %2" ).arg( url().prettyURL( 0, KURL::StripFileProtocol ), d->lastErrorMessage ) );
2388 }
2389}
2390
2392{
2393 return d->m_autosaving;
2394}
2395
2397{
2398 return d->m_bLoading;
2399}
2400
2402{
2403 // Eliminate any auto-save file
2404 TQString asf = autoSaveFile( m_file ); // the one in the current dir
2405 if ( TQFile::exists( asf ) )
2406 TQFile::remove( asf );
2407 asf = autoSaveFile( TQString() ); // and the one in $HOME
2408 if ( TQFile::exists( asf ) )
2409 TQFile::remove( asf );
2410}
2411
2412void KoDocument::setBackupFile( bool _b )
2413{
2414 d->m_backupFile = _b;
2415}
2416
2417bool KoDocument::backupFile()const
2418{
2419 return d->m_backupFile;
2420}
2421
2422
2423void KoDocument::setBackupPath( const TQString & _path)
2424{
2425 d->m_backupPath = _path;
2426}
2427
2429{
2430 return d->m_backupPath;
2431}
2432
2434{
2435 //kdDebug(30003)<<k_funcinfo<<" url: "<<url().url()<<" set to: "<<on<<endl;
2436 KoDocument *doc = dynamic_cast<KoDocument *>( parent() );
2437 if ( doc )
2438 {
2439 if ( !isStoredExtern() )
2440 {
2441 // internal doc so set next external to current (for safety)
2442 doc->setCurrent( true );
2443 return;
2444 }
2445 // only externally stored docs shall have file name in title
2446 d->m_current = on;
2447 if ( !on )
2448 {
2449 doc->setCurrent( true ); // let my next external parent take over
2450 return;
2451 }
2452 doc->forceCurrent( false ); // everybody else should keep off
2453 }
2454 else
2455 d->m_current = on;
2456
2458}
2459
2461{
2462 //kdDebug(30003)<<k_funcinfo<<" url: "<<url().url()<<" force to: "<<on<<endl;
2463 d->m_current = on;
2464 KoDocument *doc = dynamic_cast<KoDocument *>( parent() );
2465 if ( doc )
2466 {
2467 doc->forceCurrent( false );
2468 }
2469}
2470
2471bool KoDocument::isCurrent() const
2472{
2473 return d->m_current;
2474}
2475
2477{
2478 return d->m_storeInternal;
2479}
2480
2482{
2483 d->m_storeInternal = i;
2484 //kdDebug(30003)<<k_funcinfo<<"="<<d->m_storeInternal<<" doc: "<<url().url()<<endl;
2485}
2486
2487bool KoDocument::hasExternURL() const
2488{
2489 return !url().protocol().isEmpty() && url().protocol() != STORE_PROTOCOL && url().protocol() != INTERNAL_PROTOCOL;
2490}
2491
2492void KoDocument::slotStarted( TDEIO::Job* job )
2493{
2494 if ( job )
2495 {
2496 job->setWindow( d->m_shells.current() );
2497 }
2498}
2499
2500static const struct {
2501 const char* localName;
2502 const char* documentType;
2503} TN2DTArray[] = {
2504 { "text", I18N_NOOP( "a word processing" ) },
2505 { "spreadsheet", I18N_NOOP( "a spreadsheet" ) },
2506 { "presentation", I18N_NOOP( "a presentation" ) },
2507 { "chart", I18N_NOOP( "a chart" ) },
2508 { "drawing", I18N_NOOP( "a drawing" ) }
2509};
2510static const unsigned int numTN2DT = sizeof( TN2DTArray ) / sizeof( *TN2DTArray );
2511
2512TQString KoDocument::tagNameToDocumentType( const TQString& localName )
2513{
2514 for ( unsigned int i = 0 ; i < numTN2DT ; ++i )
2515 if ( localName == TN2DTArray[i].localName )
2516 return i18n( TN2DTArray[i].documentType );
2517 return localName;
2518}
2519
2520TQValueList<KoTextDocument *> KoDocument::allTextDocuments() const
2521{
2522 return TQValueList<KoTextDocument *>();
2523}
2524
2525KoPageLayout KoDocument::pageLayout(int /*pageNumber*/) const
2526{
2527 return m_pageLayout;
2528}
2529
2531{
2532 return d->m_unit;
2533}
2534
2536{
2537 if ( d->m_unit != unit )
2538 {
2539 d->m_unit = unit;
2540 emit unitChanged( unit );
2541 }
2542}
2543
2544TQString KoDocument::unitName() const
2545{
2546 return KoUnit::unitName( unit() );
2547}
2548
2549void KoDocument::showStartUpWidget( KoMainWindow* parent, bool alwaysShow )
2550{
2551 if(!alwaysShow) {
2552 TDEConfigGroup cfgGrp( instance()->config(), "TemplateChooserDialog" );
2553 TQString fullTemplateName = cfgGrp.readPathEntry( "AlwaysUseTemplate" );
2554
2555 if( !fullTemplateName.isEmpty() ) {
2556 openTemplate( fullTemplateName );
2557 shells().getFirst()->setRootDocument( this );
2558 return;
2559 }
2560 }
2561
2562 if(d->m_startUpWidget){
2563 d->m_startUpWidget->show();
2564 } else {
2565 d->m_startUpWidget = createOpenPane( parent->centralWidget(), instance(), templateType() );
2566 }
2567
2568 parent->setDocToOpen( this );
2569 parent->factory()->container("mainToolBar", parent)->hide();
2570}
2571
2572void KoDocument::openExistingFile( const TQString& file )
2573{
2574 KURL url( file );
2575 bool ok = openURL( url );
2576 setModified( false );
2577
2578 if( ok )
2579 TQTimer::singleShot( 0, this, TQ_SLOT( deleteOpenPane() ) );
2580}
2581
2582void KoDocument::openTemplate( const TQString& file )
2583{
2584 bool ok = loadNativeFormat( file );
2585 setModified( false );
2586
2587 if ( ok ) {
2588 deleteOpenPane();
2589 resetURL();
2590 setEmpty();
2591 } else {
2593 initEmpty();
2594 }
2595}
2596
2598{
2599 setEmpty();
2600 setModified(false);
2601}
2602
2603void KoDocument::startCustomDocument() {
2604 deleteOpenPane();
2605}
2606
2607KoOpenPane* KoDocument::createOpenPane( TQWidget* parent, TDEInstance* instance,
2608 const TQString& templateType )
2609{
2610 KoOpenPane* openPane = new KoOpenPane( parent, instance, templateType );
2611 TQWidget *customDoc = createCustomDocumentWidget(openPane);
2612 if(customDoc) {
2613 openPane->setCustomDocumentWidget( customDoc );
2614 connect( customDoc, TQ_SIGNAL( documentSelected() ), this, TQ_SLOT( startCustomDocument() ) );
2615 }
2616 openPane->show();
2617
2618 connect( openPane, TQ_SIGNAL( openExistingFile( const TQString& ) ),
2619 this, TQ_SLOT( openExistingFile( const TQString& ) ) );
2620 connect( openPane, TQ_SIGNAL( openTemplate( const TQString& ) ),
2621 this, TQ_SLOT( openTemplate( const TQString& ) ) );
2622
2623 return openPane;
2624}
2625
2626void KoDocument::setTemplateType( const TQString& _templateType )
2627{
2628 d->m_templateType = _templateType;
2629}
2630
2632{
2633 return d->m_templateType;
2634}
2635
2636void KoDocument::deleteOpenPane()
2637{
2638 if( d->m_startUpWidget ) {
2639 d->m_startUpWidget->hide();
2640 TQTimer::singleShot(1000, this, TQ_SLOT(deleteOpenPaneDelayed()));
2641
2642 shells().getFirst()->factory()->container("mainToolBar", shells().getFirst())->show();
2643 shells().getFirst()->setRootDocument( this );
2644 } else {
2645 emit closeEmbedInitDialog();
2646 }
2647}
2648
2649void KoDocument::deleteOpenPaneDelayed()
2650{
2651 delete d->m_startUpWidget;
2652 d->m_startUpWidget = 0;
2653}
2654
2655TQWidget* KoDocument::createCustomDocumentWidget(TQWidget */*parent*/) {
2656 return 0;
2657}
2658
2660{
2661 KDialogBase dlg(parent, "EmbedInitDialog", true, i18n("Embedding Object"), 0, KDialogBase::NoDefault);
2662 KoOpenPane* pane = createOpenPane(&dlg, instance(), templateType());
2663 pane->layout()->setMargin(0);
2664 dlg.setMainWidget(pane);
2665 dlg.setInitialSize(dlg.configDialogSize("EmbedInitDialog"));
2666 connect(this, TQ_SIGNAL(closeEmbedInitDialog()), &dlg, TQ_SLOT(slotOk()));
2667
2668 bool ok = dlg.exec() == TQDialog::Accepted;
2669
2670 dlg.saveDialogSize("EmbedInitDialog");
2671
2672 return ok;
2673}
2674
2675#include "KoDocument_p.moc"
2676#include "KoDocument.moc"
TQCString objId() const
void setMainWidget(TQWidget *widget)
TQSize configDialogSize(const TQString &groupName) const
void saveDialogSize(const TQString &groupName, bool global=false)
void setInitialSize(const TQSize &s, bool noResize=false)
static void error(TQWidget *parent, const TQString &text, const TQString &caption=TQString::null, int options=Notify)
static int warningYesNoCancel(TQWidget *parent, const TQString &text, const TQString &caption=TQString::null, const KGuiItem &buttonYes=KStdGuiItem::yes(), const KGuiItem &buttonNo=KStdGuiItem::no(), const TQString &dontAskAgainName=TQString::null, int options=Notify)
virtual Part * activePart() const
virtual TQWidget * selectedWidget() const
virtual TQWidget * activeWidget() const
virtual Part * selectedPart() const
virtual void addPart(Part *part, bool setActive=true)
virtual void setWidget(TQWidget *widget)
virtual TQWidget * widget()
PartManager * manager() const
virtual bool openURL(const KURL &url)
void started(TDEIO::Job *)
virtual void setReadWrite(bool readwrite=true)
virtual bool saveAs(const KURL &url)
virtual bool closeURL()
bool isModified() const
bool isReadWrite() const
virtual bool save()
virtual void setModified()
virtual TDEInstance * instance() const
KXMLGUIFactory * factory() const
TDEAction * action(const char *name) const
void removeClient(KXMLGUIClient *client)
void addClient(KXMLGUIClient *client)
TQWidget * container(const TQString &containerName, KXMLGUIClient *client, bool useTagName=false)
KoChild is an abstract base class that represents the geometry associated with an embedded document.
Definition KoChild.h:42
virtual bool isTransparent() const
It might be interesting for view updates and repainting in general whether a child is transparent or ...
Definition KoChild.cpp:334
virtual void transform(TQPainter &painter)
Transforms the painter (its worldmatrix and the clipping) in such a way that the painter can be passe...
Definition KoChild.cpp:217
virtual double xScaling() const
Definition KoChild.cpp:149
virtual TQRect contentRect() const
Definition KoChild.cpp:233
virtual double yScaling() const
Definition KoChild.cpp:154
Holds an embedded object.
KoDocument * document() const
bool isDeleted() const
This document (child) is deleted.
DCOP interface for any KOffice document Use KoApplicationIface to get hold of an existing document's ...
The KOffice document class.
Definition KoDocument.h:61
KoDocument(TQWidget *parentWidget, const char *widgetName, TQObject *parent, const char *name, bool singleViewMode=false)
Constructor.
bool isLoading() const
Returns true during loading (openURL can be asynchronous)
virtual void openTemplate(const TQString &file)
This slot loads a template and deletes the start up widget.
TQString templateType() const
Template type used.
static TQString tagNameToDocumentType(const TQString &localName)
The first thing to do in loadOasis is get hold of the office:body tag, then its child.
void resetURL()
Sets the document URL to empty URL KParts doesn't allow this, but KOffice apps have e....
Definition KoDocument.h:818
KoView * hitTestView()
Temporary API for accessing the view that calls hitTest.
virtual bool saveToStream(TQIODevice *dev)
Save the document.
virtual TQDomDocument saveXML()
Reimplement this to save the contents of the KOffice document into a TQDomDocument.
bool isAutoErrorHandlingEnabled() const
Checks whether error message boxes should be shown.
void removeAutoSaveFiles()
Performs a cleanup of unneeded backup files.
virtual int supportedSpecialFormats() const
Return the set of SupportedSpecialFormats that the application wants to offer in the "Save" file dial...
virtual bool showEmbedInitDialog(TQWidget *parent)
Shows the init dialog when embeding.
virtual TQWidget * createCustomDocumentWidget(TQWidget *parent)
Override this method in your derived class to show a widget in the startup 'dialog'.
virtual bool isStoredExtern() const
Return true if url() is a real filename, false if url() is an internal url in the store,...
bool isImporting() const
Returns whether or not the current openURL() or openFile() call is actually an import operation (like...
virtual bool loadOasis(const TQDomDocument &doc, KoOasisStyles &oasisStyles, const TQDomDocument &settings, KoStore *store)=0
Reimplement this method to load the contents of your KOffice document, from the XML document ("conten...
TQString backupPath() const
virtual TQValueList< KoTextDocument * > allTextDocuments() const
virtual bool loadNativeFormat(const TQString &file)
Loads a document in the native format from a given URL.
bool checkAutoSaveFile()
Called by koApplication to check for an autosave file in $HOME.
virtual KParts::Part * hitTest(TQWidget *widget, const TQPoint &globalPos)
Reimplemented from KParts::Part.
virtual TDEAction * action(const TQDomElement &element) const
Returns the action described action object.
TQString errorMessage() const
Return the last error message.
virtual bool completeLoading(KoStore *store)
Overload this function if you have to load additional files from a store.
virtual void paintChildren(TQPainter &painter, const TQRect &rect, KoView *view, double zoomX=1.0, double zoomY=1.0)
Paints all of the documents children into the given painter object.
KoDocumentChild * child(KoDocument *doc)
KoView * createView(TQWidget *parent=0, const char *name=0)
Create a new view for the document.
virtual bool saveToStore(KoStore *store, const TQString &path)
Saves a document to a store.
bool storeInternal() const
void setMimeType(const TQCString &mimeType)
Sets the mime type for the document.
static TQCString readNativeFormatMimeType(TDEInstance *instance=0)
Used by KoApplication, and by KoMainWindow, when no document exists yet.
void setAutoErrorHandlingEnabled(bool b)
Set whether the next openURL call should show error message boxes in case of errors.
virtual TQStringList extraNativeMimeTypes() const
Returns a list of the mimetypes considered "native", i.e.
virtual bool saveChildren(KoStore *store)
Saves all internal children (only!).
bool isNativeFormat(const TQCString &mimetype) const
Checks whether a given mimetype can be handled natively.
virtual bool loadChildren(KoStore *)
OLD XML method.
virtual void setReadWrite(bool readwrite=true)
Sets whether the document can be edited or is read only.
TQString & file()
Only use these functions to restore m_file (in KoMainWindow) after a failed save (remember to use set...
Definition KoDocument.h:846
virtual void removeShell(KoMainWindow *shell)
Removes the shell from the list.
virtual bool openFile()
Loads a document from KReadOnlyPart::m_file (KParts takes care of downloading remote documents).
static TQStringList readExtraNativeMimeTypes(TDEInstance *instance=0)
Used by KoMainWindow, when no document exists yet.
virtual bool saveOasis(KoStore *store, KoXmlWriter *manifestWriter)=0
Reimplement this method to save the contents of your KOffice document, using the OASIS format.
TQString unitName() const
Returns the name of the unit used to display all measures/distances.
const TQPtrList< KoMainWindow > & shells() const
virtual void setEmpty()
Sets the document to empty.
Definition KoDocument.h:499
void showSavingErrorDialog()
Show the last error message in a message box.
void sigStatusBarMessage(const TQString &text)
Emitted e.g.
void unitChanged(KoUnit::Unit)
This signal is emitted when the unit is changed by setUnit() It is common to connect views to it,...
TQCString mimeType() const
Returns the actual mimetype of the document.
virtual TQPixmap generatePreview(const TQSize &size)
Generates a preview picture of the document.
virtual bool saveFile()
Saves a document to KReadOnlyPart::m_file (KParts takes care of uploading remote documents) Applies a...
virtual DCOPObject * dcopObject()
Return a DCOP interface for this document.
static void setupXmlReader(TQXmlSimpleReader &reader, bool namespaceProcessing=false)
setup the XML reader, so that we don't have to duplicate the code.
void setDoNotSaveExtDoc(bool on=true)
Set when we do not want to save external children when saving our 'main' doc.
void sigClearStatusBarMessage()
Emitted e.g.
bool isEmbedded() const
Is the document embedded?
virtual bool saveExternalChildren()
Saves all externally stored children.
TQCString nativeOasisMimeType() const
Returns the OASIS OpenDocument mimetype of the document, if supported This comes from the X-TDE-Nativ...
void modified(bool)
Emitted when the document is modified.
virtual bool saveNativeFormat(const TQString &file)
Saves the document in native format, to a given file You should never have to reimplement.
virtual void addView(KoView *view)
Adds a view to the document.
void setCurrent(bool on=true)
Indicates that this document is currently viewed and thus should control the title caption.
void childChanged(KoDocumentChild *child)
This signal is emitted when a direct or indirect child document changes and needs to be updated in al...
bool import(const KURL &url)
Opens the document given by url, without storing the URL in the KoDocument.
bool isSingleViewMode() const
Tells whether this document is in singleview mode.
void setErrorMessage(const TQString &errMsg)
Sets the error message to be shown to the user (use i18n()!) when loading or saving fails.
const TQPtrList< KoDocumentChild > & children() const
virtual TQDomDocument domDocument() const
Returns the DOM document which describes the GUI of the first view.
TQDomDocument createDomDocument(const TQString &tagName, const TQString &version) const
Return a correctly created TQDomDocument for this KoDocument, including processing instruction,...
virtual void paintChild(KoDocumentChild *child, TQPainter &painter, KoView *view, double zoomX=1.0, double zoomY=1.0)
Paint a given child.
bool confirmNonNativeSave(const bool exporting) const
Returns true if this document was the result of opening a foreign file format and if the user hasn't ...
void sigProgress(int value)
Progress info while loading or saving.
void setUnit(KoUnit::Unit u)
Sets the unit used to display all measures/distances.
virtual void addShell(KoMainWindow *shell)
Appends the shell to the list of shells which show this document as their root document.
virtual ~KoDocument()
Destructor.
int shellCount() const
virtual void setModified(bool _mod)
Sets the modified flag on the document.
virtual void initEmpty()
Initialize an empty document using default values.
TQCString dcopObjectId() const
void setTemplateType(const TQString &_templateType)
Set the template type used.
virtual void paintContent(TQPainter &painter, const TQRect &rect, bool transparent=false, double zoomX=1.0, double zoomY=1.0)=0
Paints the data itself.
virtual bool completeSaving(KoStore *store)
If you want to write additional files to a store, then you must do it here.
int viewCount() const
virtual bool openURL(const KURL &url)
Reimplemented from KParts::ReadWritePart for internal reasons (for the autosave functionality)
void setCheckAutoSaveFile(bool b)
Set whether the next openURL call should check for an auto-saved file and offer to open it.
virtual bool loadFromStore(KoStore *store, const TQString &url)
Loads a document from a store.
void setStoreInternal(bool i)
Set when you want an external embedded document to be stored internally.
KoUnit::Unit unit() const
Returns the unit used to display all measures/distances.
KoDocumentInfo * documentInfo() const
virtual void removeView(KoView *view)
Removes a view of the document.
void forceCurrent(bool on)
Sets current flag for this document and all its parents.
virtual void insertChild(KoDocumentChild *child)
Inserts the new child in the list of children and emits the childChanged() signal.
KoOpenPane * createOpenPane(TQWidget *parent, TDEInstance *instance, const TQString &templateType=TQString())
Creates the open widget showed at application start up.
void setAutoSave(int delay)
Activate/deactivate/configure the autosave feature.
virtual TQCString nativeFormatMimeType() const
To be preferred when a document exists.
virtual bool loadXML(TQIODevice *, const TQDomDocument &doc)=0
Reimplement this method to load the contents of your KOffice document, from the XML document.
bool exp0rt(const KURL &url)
Saves the document as url without changing the state of the KoDocument (URL, modified flag etc....
bool isModified() const
Returns true if this document or any of its internal child documents are modified.
void setOutputMimeType(const TQCString &mimeType, int specialOutputFlag=0)
Set the format in which the document should be saved.
virtual void paintEverything(TQPainter &painter, const TQRect &rect, bool transparent=false, KoView *view=0L, double zoomX=1.0, double zoomY=1.0)
Paints the whole document into the given painter object.
virtual KoPageLayout pageLayout(int pageNumber=0) const
virtual bool loadOasisFromStore(KoStore *store)
Loads an OASIS document from a store.
bool isAutosaving() const
Checks whether the document is currently in the process of autosaving.
bool isExporting() const
Returns whether or not the current saveFile() call is actually an export operation (like File --> Exp...
const TQPtrList< KoView > & views() const
static KService::Ptr readNativeService(TDEInstance *instance=0)
With the help of instance or TDEApplication::instance() this method figures out which ....
virtual void showStartUpWidget(KoMainWindow *parent, bool alwaysShow=false)
Creates and shows the start up widget.
virtual bool isEmpty() const
Definition KoDocument.h:489
void setBackupPath(const TQString &_path)
Sets the backup path of the document.
virtual bool saveChildrenOasis(KoStore *store, KoXmlWriter *manifestWriter)
Saves all internal children (only!), to the store, using the OASIS format.
virtual void setTitleModified()
Tells the document that its title has been modified, either because the modified status changes (this...
static KoXmlWriter * createOasisXmlWriter(TQIODevice *dev, const char *rootElementName)
Return an XML writer for saving Oasis XML into the device dev, including the XML processing instructi...
void showLoadingErrorDialog()
Show the last error message in a message box.
virtual void openExistingFile(const TQString &file)
This slot loads an existing file and deletes the start up widget.
The class managing all the filters.
ConversionStatus
This enum is used to signal the return state of your filter.
Definition KoFilter.h:64
Main window for a KOffice application.
void setDocToOpen(KoDocument *doc)
This is used to handle the document used at start up before it actually added as root document.
Helper class around KoStore for writing out OASIS files.
bool closeManifestWriter()
Close the manifest writer, writing its contents to manifest.xml.
KoXmlWriter * manifestWriter(const char *mimeType)
Create and return a manifest writer. It will write to a memory buffer.
bool loadAndParse(const TQString &fileName, TQDomDocument &doc, TQString &errorMessage)
A completely unrelated method, for loading a file from an oasis store.
Repository of styles used during loading of OASIS/OOo file.
void createStyleMap(const TQDomDocument &doc, bool stylesDotXml)
Look into doc for styles and remember them.
This class implements a TQIODevice around KoStore, so that it can be used to create a TQDomDocument f...
Saves and loads KOffice documents using various backends.
Definition KoStore.h:40
bool close()
Close the file inside the store.
Definition KoStore.cpp:242
bool hasFile(const TQString &fileName) const
Definition KoStore.cpp:625
void pushDirectory()
Stacks the current directory.
Definition KoStore.cpp:417
void popDirectory()
Restores the previously pushed directory.
Definition KoStore.cpp:422
TQIODevice * device() const
Get a device for reading a file from the store directly (slightly faster than read() calls) You need ...
Definition KoStore.cpp:261
bool bad() const
Definition KoStore.h:158
bool open(const TQString &name)
Open a new file inside the store.
Definition KoStore.cpp:188
static KoStore * createStore(const TQString &fileName, Mode mode, const TQCString &appIdentification="", Backend backend=Auto)
Open a store (i.e.
Definition KoStore.cpp:58
void disallowNameExpansion(void)
Do not expand file and directory names Useful when using KoStore on non-KOffice files.
Definition KoStore.cpp:620
bool enterDirectory(const TQString &directory)
Enters one or multiple directories.
Definition KoStore.cpp:374
Unit
Length units supported by KOffice.
Definition KoUnit.h:63
static TQString unitName(Unit _unit)
Get the name of a unit.
Definition KoUnit.cpp:200
This class is used to display a KoDocument.
Definition KoView.h:58
virtual TQWidget * canvas() const
Overload this function if the content will be displayed on some child widget instead of the view dire...
Definition KoView.cpp:299
virtual int canvasYOffset() const
Overload this function if the content will be displayed with an offset relative to the upper left cor...
Definition KoView.cpp:311
virtual int canvasXOffset() const
Overload this function if the content will be displayed with an offset relative to the upper left cor...
Definition KoView.cpp:306
virtual void print(KPrinter &printer)
Overload this method with your own printing code.
Definition KoView.cpp:639
virtual KoDocument * hitTest(const TQPoint &pos)
Retrieves the document that is hit.
Definition KoView.cpp:233
virtual void setupPrinter(KPrinter &printer)
Overload this method to setup KPrinter before the actual printing.
Definition KoView.cpp:634
virtual void updateReadWrite(bool readwrite)=0
You have to implement this method and disable/enable certain functionality (actions for example) in y...
A class for writing out XML (to any TQIODevice), with a special attention on performance.
Definition KoXmlWriter.h:37
void startElement(const char *tagName, bool indentInside=true)
Start a new element, as a child of the current element.
void startDocument(const char *rootElemName, const char *publicId=0, const char *systemId=0)
Start the XML document.
void addManifestEntry(const TQString &fullPath, const TQString &mediaType)
Special helper for writing "manifest" files This is equivalent to startElement/2*addAttribute/endElem...
void addAttribute(const char *attrName, const TQString &value)
Overloaded version of addAttribute( const char*, const char* ), which is a bit slower because it need...
Definition KoXmlWriter.h:76
const char * name(StdAction id)
This structure defines the page layout, including its size in pt, its format (e.g.
double ptRight
Right margin in pt.
double ptHeight
Page height in pt.
double ptLeft
Left margin in pt.
double ptBottom
Bottom margin in pt.
double ptWidth
Page width in pt.
double ptTop
Top margin in pt.