lib

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