153
204
view->setupPrinter( printer );
154
205
if ( printer.setup( view ) )
155
206
view->print( printer );
158
209
KoDocument::KoDocument( QWidget * parentWidget, const char *widgetName, QObject* parent, const char* name, bool singleViewMode )
159
210
: KParts::ReadWritePart( parent, name )
161
if(s_documentList==0L)
162
s_documentList=new QList<KoDocument>;
163
s_documentList->append(this);
165
d = new KoDocumentPrivate;
168
d->m_dcopObject = 0L;
169
connect( &d->m_autoSaveTimer, SIGNAL( timeout() ), this, SLOT( slotAutoSave() ) );
170
setAutoSave( s_defaultAutoSave );
171
d->m_bSingleViewMode = singleViewMode;
172
d->filterManager = 0L;
173
d->modifiedAfterAutosave=false;
175
// the parent setting *always* overrides! (Simon)
178
if ( parent->inherits( "KoDocument" ) )
179
d->m_bSingleViewMode = ((KoDocument *)parent)->isSingleViewMode();
180
else if ( parent->inherits( "KParts::Part" ) )
181
d->m_bSingleViewMode = true;
184
if ( singleViewMode )
186
d->m_wrapperWidget = new KoViewWrapperWidget( parentWidget, widgetName );
187
setWidget( d->m_wrapperWidget );
188
kdDebug(30003) << "creating KoBrowserExtension" << endl;
189
(void) new KoBrowserExtension( this ); // ## only if embedded into a browser?
192
d->m_docInfo = new KoDocumentInfo( this, "document info" );
212
if(s_documentList==0L)
213
s_documentList=new QPtrList<KoDocument>;
214
s_documentList->append(this);
218
connect( &d->m_autoSaveTimer, SIGNAL( timeout() ), this, SLOT( slotAutoSave() ) );
219
setAutoSave( s_defaultAutoSave );
220
d->m_bSingleViewMode = singleViewMode;
223
// the parent setting *always* overrides! (Simon)
226
if ( parent->inherits( "KoDocument" ) )
227
d->m_bSingleViewMode = ((KoDocument *)parent)->isSingleViewMode();
228
else if ( parent->inherits( "KParts::Part" ) )
229
d->m_bSingleViewMode = true;
232
if ( singleViewMode )
234
d->m_wrapperWidget = new KoViewWrapperWidget( parentWidget, widgetName );
235
setWidget( d->m_wrapperWidget );
236
kdDebug(30003) << "creating KoBrowserExtension" << endl;
237
(void) new KoBrowserExtension( this ); // ## only if embedded into a browser?
240
d->m_docInfo = new KoDocumentInfo( this, "document info" );
242
m_pageLayout.ptWidth = 0;
243
m_pageLayout.ptHeight = 0;
244
m_pageLayout.ptTop = 0;
245
m_pageLayout.ptBottom = 0;
246
m_pageLayout.ptLeft = 0;
247
m_pageLayout.ptRight = 0;
249
// A way to 'fix' the job's window, since we have no widget known to KParts
250
if ( !singleViewMode )
251
connect( this, SIGNAL( started( KIO::Job* ) ), SLOT( slotStarted( KIO::Job* ) ) );
195
254
KoDocument::~KoDocument()
197
QListIterator<KoDocumentChild> childIt( d->m_children );
198
for (; childIt.current(); ++childIt )
199
disconnect( childIt.current(), SIGNAL( destroyed() ),
200
this, SLOT( slotChildDestroyed() ) );
202
// Tell our views that the document is already destroyed and
203
// that they shouldn't try to access it.
204
QListIterator<KoView> vIt( d->m_views );
205
for (; vIt.current(); ++vIt )
206
vIt.current()->setDocumentDeleted();
208
d->m_children.setAutoDelete( true );
209
d->m_children.clear();
211
d->m_shells.setAutoDelete( true );
214
delete d->m_dcopObject;
216
s_documentList->removeRef(this);
218
if(s_documentList->count()==0) {
219
delete s_documentList;
256
d->m_autoSaveTimer.stop();
258
QPtrListIterator<KoDocumentChild> childIt( d->m_children );
259
for (; childIt.current(); ++childIt )
260
disconnect( childIt.current(), SIGNAL( destroyed() ),
261
this, SLOT( slotChildDestroyed() ) );
263
// Tell our views that the document is already destroyed and
264
// that they shouldn't try to access it.
265
QPtrListIterator<KoView> vIt( d->m_views );
266
for (; vIt.current(); ++vIt )
267
vIt.current()->setDocumentDeleted();
269
d->m_children.setAutoDelete( true );
270
d->m_children.clear();
272
d->m_shells.setAutoDelete( true );
275
delete d->m_dcopObject;
276
delete d->filterManager;
278
s_documentList->removeRef(this);
280
if(s_documentList->isEmpty()) {
281
delete s_documentList;
224
286
bool KoDocument::isSingleViewMode() const
226
return d->m_bSingleViewMode;
229
bool KoDocument::isEmbedded() const {
230
return dynamic_cast<KoDocument *>( parent() ) != 0;
233
KoView *KoDocument::createView( QWidget *parent, const char *name ) {
288
return d->m_bSingleViewMode;
291
bool KoDocument::isEmbedded() const
293
return dynamic_cast<KoDocument *>( parent() ) != 0;
296
KoView *KoDocument::createView( QWidget *parent, const char *name )
235
298
KoView *view=createViewInstance(parent, name);
303
bool KoDocument::exp0rt( const KURL & _url )
307
d->m_isExporting = true;
310
// Preserve a lot of state here because we need to restore it in order to
311
// be able to fake a File --> Export. Can't do this in saveFile() because,
312
// for a start, KParts has already set m_url and m_file and because we need
313
// to restore the modified flag etc. and don't want to put a load on anyone
314
// reimplementing saveFile() (Note: import() and export() will remain
318
QString oldFile = m_file;
320
bool wasModified = isModified ();
321
QCString oldMimeType = mimeType ();
325
ret = saveAs( _url );
329
// This is sooooo hacky :(
330
// Hopefully we will restore enough state.
332
kdDebug(30003) << "Restoring KoDocument state to before export" << endl;
334
// always restore m_url & m_file because KParts has changed them
335
// (regardless of failure or success)
339
// on successful export we need to restore modified etc. too
340
// on failed export, mimetype/modified hasn't changed anyway
343
setModified (wasModified);
344
d->mimeType = oldMimeType;
348
d->m_isExporting = false;
240
353
bool KoDocument::saveFile()
242
kdDebug(30003) << "KoDocument::saveFile()" << endl;
243
if ( !kapp->inherits( "KoApplication" ) )
246
QCString _native_format = nativeFormatMimeType();
247
// The output format is set by koMainWindow, and by openFile
248
QCString outputMimeType = d->outputMimeType;
249
ASSERT( !outputMimeType.isEmpty() );
250
if ( outputMimeType.isEmpty() )
251
outputMimeType = _native_format;
253
QApplication::setOverrideCursor( waitCursor );
255
if ( KIO::NetAccess::exists( m_url ) ) { // this file exists => backup
256
// TODO : make this configurable ?
257
KURL backup( m_url );
258
backup.setPath( backup.path() + QString::fromLatin1("~") );
259
(void) KIO::NetAccess::del( backup );
260
(void) KIO::NetAccess::copy( m_url, backup );
262
// This is noticeably faster, but not network transparent, and more importantly
263
// it fails with '(' and other special chars in the filename.
264
//QString cmd = QString( "rm -rf %1~" ).arg( url.path() );
265
//system( cmd.local8Bit() );
266
//cmd = QString("cp %1 %2~").arg( url.path() ).arg( url.path() );
267
//system( cmd.local8Bit() );
270
if ( outputMimeType != _native_format ) {
271
kdDebug(30003) << "Saving to format " << outputMimeType << " in " << m_file << endl;
272
// Not native format : save using export filter
274
if ( !d->filterManager )
275
d->filterManager = new KoFilterManager();
276
QString nativeFile = d->filterManager->prepareExport( m_file, _native_format, outputMimeType, this);
277
kdDebug(30003) << "Temp native file " << nativeFile << endl;
279
if(d->m_changed==false && nativeFile!=m_file) {
280
ret = saveNativeFormat( nativeFile );
282
kdError(30003) << "Couldn't save in native format!" << endl;
284
ret = d->filterManager->export_();
355
kdDebug(30003) << "KoDocument::saveFile() doc='" << url().url() <<"'"<< endl;
356
if ( !kapp->inherits( "KoApplication" ) )
358
d->lastErrorMessage = i18n( "Internal error: not a KOffice application, saving not allowed." );
362
QCString _native_format = nativeFormatMimeType();
363
// The output format is set by koMainWindow, and by openFile
364
QCString outputMimeType = d->outputMimeType;
365
Q_ASSERT( !outputMimeType.isEmpty() );
366
if ( outputMimeType.isEmpty() )
367
outputMimeType = _native_format;
369
QApplication::setOverrideCursor( waitCursor );
371
if ( backupFile() ) {
373
#if KDE_IS_VERSION(3,1,90)
374
if ( KIO::NetAccess::stat( url(), entry, shells().current() ) ) { // this file exists => backup
376
if ( KIO::NetAccess::stat( url(), entry ) ) { // this file exists => backup
378
emit sigStatusBarMessage( i18n("Making backup...") );
380
if ( d->m_backupPath.isEmpty())
383
backup = d->m_backupPath +"/"+url().fileName();
384
backup.setPath( backup.path() + QString::fromLatin1("~") );
385
#if KDE_IS_VERSION(3,1,90)
386
KIO::NetAccess::file_copy( url(), backup, -1, true /*overwrite*/, false /*resume*/, shells().current() );
388
KFileItem item( entry, url() );
389
Q_ASSERT( item.name() == url().fileName() );
390
KIO::NetAccess::del( backup ); // Copy does not remove existing destination file
391
KIO::NetAccess::copy( url(), backup );
392
// Not network transparent.
393
if ( backup.isLocalFile() )
394
::chmod( QFile::encodeName( backup.path() ), item.permissions() );
399
emit sigStatusBarMessage( i18n("Saving...") );
401
bool suppressErrorDialog = false;
402
if ( outputMimeType != _native_format ) {
403
kdDebug(30003) << "Saving to format " << outputMimeType << " in " << m_file << endl;
404
// Not native format : save using export filter
405
if ( !d->filterManager )
406
d->filterManager = new KoFilterManager( this );
408
KoFilter::ConversionStatus status = d->filterManager->exp0rt( m_file, outputMimeType );
409
ret = status == KoFilter::OK;
410
suppressErrorDialog = (status == KoFilter::UserCancelled || status == KoFilter::BadConversionGraph );
286
// How can this happen ? m_changed = true ?
287
// No -> nativeFile==m_file :) (Werner)
291
// Native format => normal save
292
ret = saveNativeFormat( m_file );
297
// Eliminate any auto-save file
298
QString asf = autoSaveFile( m_file );
299
if ( QFile::exists( asf ) )
300
unlink( QFile::encodeName( asf ) );
303
QApplication::restoreOverrideCursor();
306
KMessageBox::error( 0L, i18n( "Could not save\n%1" ).arg( m_file ) );
311
void KoDocument::setOutputMimeType( const QCString & mimeType )
412
// Native format => normal save
413
ret = saveNativeFormat( m_file );
417
removeAutoSaveFiles();
418
// Restart the autosave timer
419
// (we don't want to autosave again 2 seconds after a real save)
420
setAutoSave( d->m_autoSaveDelay );
423
QApplication::restoreOverrideCursor();
426
if ( !suppressErrorDialog )
428
if ( d->lastErrorMessage.isEmpty() )
429
KMessageBox::error( 0L, i18n( "Could not save\n%1" ).arg( m_file ) );
430
else if ( d->lastErrorMessage != "USER_CANCELED" )
432
KMessageBox::error( 0L, i18n( "Could not save %1\nReason: %2" ).arg( m_file, d->lastErrorMessage ) );
436
// couldn't save file so this new URL is invalid
437
// FIXME: we should restore the current document's true URL instead of
438
// setting it to nothing otherwise anything that depends on the URL
439
// being correct will not work (i.e. the document will be called
440
// "Untitled" which may not be true)
442
// Update: now the URL is restored in KoMainWindow but really, this
443
// should still be fixed in KoDocument/KParts (ditto for m_file).
444
// We still resetURL() here since we may or may not have been called
445
// by KoMainWindow - Clarence
451
d->mimeType = outputMimeType;
452
setConfirmNonNativeSave ( isExporting (), false );
454
emit sigClearStatusBarMessage();
459
QCString KoDocument::mimeType() const
464
void KoDocument::setMimeType( const QCString & mimeType )
466
d->mimeType = mimeType;
469
void KoDocument::setOutputMimeType( const QCString & mimeType, int specialOutputFlag )
313
471
d->outputMimeType = mimeType;
472
d->m_specialOutputFlag = specialOutputFlag;
316
475
QCString KoDocument::outputMimeType() const
449
667
d->m_children.removeRef( child );
452
const QList<KoDocumentChild>& KoDocument::children() const
670
const QPtrList<KoDocumentChild>& KoDocument::children() const
454
return d->m_children;
672
return d->m_children;
457
675
KParts::Part *KoDocument::hitTest( QWidget *widget, const QPoint &globalPos )
459
QListIterator<KoView> it( d->m_views );
460
for (; it.current(); ++it )
461
if ( (QWidget *)it.current() == widget )
463
QPoint canvasPos( it.current()->canvas()->mapFromGlobal( globalPos ) );
464
canvasPos.rx() += it.current()->canvasXOffset();
465
canvasPos.ry() += it.current()->canvasYOffset();
467
KParts::Part *part = it.current()->hitTest( canvasPos );
677
QPtrListIterator<KoView> it( d->m_views );
678
for (; it.current(); ++it )
679
if ( (QWidget *)it.current() == widget )
681
QPoint canvasPos( it.current()->canvas()->mapFromGlobal( globalPos ) );
682
canvasPos.rx() += it.current()->canvasXOffset();
683
canvasPos.ry() += it.current()->canvasYOffset();
685
KParts::Part *part = it.current()->hitTest( canvasPos );
475
693
KoDocument *KoDocument::hitTest( const QPoint &pos, const QWMatrix &matrix )
477
QListIterator<KoDocumentChild> it( d->m_children );
478
for (; it.current(); ++it )
480
KoDocument *doc = it.current()->hitTest( pos, matrix );
695
QPtrListIterator<KoDocumentChild> it( d->m_children );
696
for (; it.current(); ++it )
698
KoDocument *doc = it.current()->hitTest( pos, matrix );
488
706
KoDocumentChild *KoDocument::child( KoDocument *doc )
490
QListIterator<KoDocumentChild> it( d->m_children );
491
for (; it.current(); ++it )
492
if ( it.current()->document() == doc )
708
QPtrListIterator<KoDocumentChild> it( d->m_children );
709
for (; it.current(); ++it )
710
if ( it.current()->document() == doc )
498
716
KoDocumentInfo *KoDocument::documentInfo() const
503
721
void KoDocument::setViewBuildDocument( KoView *view, const QDomDocument &doc )
505
if ( d->m_views.find( view ) == -1 )
508
uint viewIdx = d->m_views.at();
510
if ( d->m_viewBuildDocuments.count() == viewIdx )
512
d->m_viewBuildDocuments.append( doc );
514
else if ( d->m_viewBuildDocuments.count() > viewIdx )
516
d->m_viewBuildDocuments[ viewIdx ] = doc;
723
if ( d->m_views.find( view ) == -1 )
726
uint viewIdx = d->m_views.at();
728
if ( d->m_viewBuildDocuments.count() == viewIdx )
729
d->m_viewBuildDocuments.append( doc );
730
else if ( d->m_viewBuildDocuments.count() > viewIdx )
731
d->m_viewBuildDocuments[ viewIdx ] = doc;
520
734
QDomDocument KoDocument::viewBuildDocument( KoView *view )
524
if ( d->m_views.find( view ) == -1 )
527
uint viewIdx = d->m_views.at();
529
if ( viewIdx >= d->m_viewBuildDocuments.count() )
532
res = d->m_viewBuildDocuments[ viewIdx ];
534
// make this entry empty. otherwise we get a segfault in QMap ;-(
535
d->m_viewBuildDocuments[ viewIdx ] = QDomDocument();
738
if ( d->m_views.find( view ) == -1 )
741
uint viewIdx = d->m_views.at();
743
if ( viewIdx >= d->m_viewBuildDocuments.count() )
746
res = d->m_viewBuildDocuments[ viewIdx ];
748
// make this entry empty. otherwise we get a segfault in QMap ;-(
749
d->m_viewBuildDocuments[ viewIdx ] = QDomDocument();
540
754
void KoDocument::paintEverything( QPainter &painter, const QRect &rect, bool transparent, KoView *view, double zoomX, double zoomY )
542
paintContent( painter, rect, transparent, zoomX, zoomY );
543
paintChildren( painter, rect, view, zoomX, zoomY );
756
paintContent( painter, rect, transparent, zoomX, zoomY );
757
paintChildren( painter, rect, view, zoomX, zoomY );
546
760
void KoDocument::paintChildren( QPainter &painter, const QRect &/*rect*/, KoView *view, double zoomX, double zoomY )
548
QListIterator<KoDocumentChild> it( d->m_children );
549
for (; it.current(); ++it )
551
// #### todo: paint only if child is visible inside rect
553
paintChild( it.current(), painter, view, zoomX, zoomY );
762
QPtrListIterator<KoDocumentChild> it( d->m_children );
763
for (; it.current(); ++it )
765
// #### todo: paint only if child is visible inside rect
767
paintChild( it.current(), painter, view, zoomX, zoomY );
558
772
void KoDocument::paintChild( KoDocumentChild *child, QPainter &painter, KoView *view, double zoomX, double zoomY )
774
if ( child->isDeleted() )
560
777
// QRegion rgn = painter.clipRegion();
562
child->transform( painter );
563
child->document()->paintEverything( painter, child->contentRect(), child->isTransparent(), view, zoomX, zoomY );
565
if ( view && view->partManager() )
567
// ### do we need to apply zoomX and zoomY here ?
568
KParts::PartManager *manager = view->partManager();
570
painter.scale( 1.0 / child->xScaling(), 1.0 / child->yScaling() );
572
int w = int( (double)child->contentRect().width() * child->xScaling() );
573
int h = int( (double)child->contentRect().height() * child->yScaling() );
574
if ( ( manager->selectedPart() == (KParts::Part *)child->document() &&
575
manager->selectedWidget() == (QWidget *)view ) ||
576
( manager->activePart() == (KParts::Part *)child->document() &&
577
manager->activeWidget() == (QWidget *)view ) )
779
child->transform( painter );
780
child->document()->paintEverything( painter, child->contentRect(), child->isTransparent(), view, zoomX, zoomY );
782
if ( view && view->partManager() )
784
// ### do we need to apply zoomX and zoomY here ?
785
KParts::PartManager *manager = view->partManager();
787
painter.scale( 1.0 / child->xScaling(), 1.0 / child->yScaling() );
789
int w = int( (double)child->contentRect().width() * child->xScaling() );
790
int h = int( (double)child->contentRect().height() * child->yScaling() );
791
if ( ( manager->selectedPart() == (KParts::Part *)child->document() &&
792
manager->selectedWidget() == (QWidget *)view ) ||
793
( manager->activePart() == (KParts::Part *)child->document() &&
794
manager->activeWidget() == (QWidget *)view ) )
579
796
// painter.setClipRegion( rgn );
580
painter.setClipping( FALSE );
582
painter.setPen( black );
583
painter.fillRect( -5, -5, w + 10, 5, white );
584
painter.fillRect( -5, h, w + 10, 5, white );
585
painter.fillRect( -5, -5, 5, h + 10, white );
586
painter.fillRect( w, -5, 5, h + 10, white );
587
painter.fillRect( -5, -5, w + 10, 5, BDiagPattern );
588
painter.fillRect( -5, h, w + 10, 5, BDiagPattern );
589
painter.fillRect( -5, -5, 5, h + 10, BDiagPattern );
590
painter.fillRect( w, -5, 5, h + 10, BDiagPattern );
592
if ( manager->selectedPart() == (KParts::Part *)child->document() &&
593
manager->selectedWidget() == (QWidget *)view )
596
if ( view->koDocument() == this )
600
painter.fillRect( -5, -5, 5, 5, color );
601
painter.fillRect( -5, h, 5, 5, color );
602
painter.fillRect( w, h, 5, 5, color );
603
painter.fillRect( w, -5, 5, 5, color );
604
painter.fillRect( w / 2 - 3, -5, 5, 5, color );
605
painter.fillRect( w / 2 - 3, h, 5, 5, color );
606
painter.fillRect( -5, h / 2 - 3, 5, 5, color );
607
painter.fillRect( w, h / 2 - 3, 5, 5, color );
610
painter.setClipping( TRUE );
615
bool KoDocument::saveChildren( KoStore* /*_store*/, const QString& /*_path*/ )
617
// Lets assume that we do not have children
618
kdWarning(30003) << "KoDocument::saveChildren( KoStore*, const QString & )" << endl;
619
kdWarning(30003) << "Not implemented ( not really an error )" << endl;
623
bool KoDocument::saveNativeFormat( const QString & file )
625
kdDebug(30003) << "Saving to store" << endl;
627
QCString appIdentification( "KOffice " ); // We are limited in the number of chars.
628
appIdentification += nativeFormatMimeType();
629
appIdentification += '\004'; // Two magic bytes to make the identification
630
appIdentification += '\006'; // more reliable (DF)
631
KoStore* store = new KoStore( file, KoStore::Write, appIdentification );
633
// Save childen first since they might get a new url
634
if ( store->bad() || !saveChildren( store, QString(STORE_PROTOCOL) + ':' ) )
636
kdDebug(30003) << "store->bad()=" << store->bad() << " aborting saving !" << endl;
641
kdDebug(30003) << "Saving root" << endl;
642
if ( store->open( "root" ) )
644
KoStoreDevice dev( store );
645
if ( !saveToStream( &dev ) )
657
if ( store->open( "documentinfo.xml" ) )
659
QDomDocument doc = d->m_docInfo->save();
660
KoStoreDevice dev( store );
662
QCString s = doc.toCString(); // this is already Utf8!
664
dev.writeBlock( s.data(), s.length() );
668
bool ret = completeSaving( store );
669
kdDebug(30003) << "Saving done" << endl;
797
painter.setClipping( FALSE );
799
painter.setPen( black );
800
painter.fillRect( -5, -5, w + 10, 5, white );
801
painter.fillRect( -5, h, w + 10, 5, white );
802
painter.fillRect( -5, -5, 5, h + 10, white );
803
painter.fillRect( w, -5, 5, h + 10, white );
804
painter.fillRect( -5, -5, w + 10, 5, BDiagPattern );
805
painter.fillRect( -5, h, w + 10, 5, BDiagPattern );
806
painter.fillRect( -5, -5, 5, h + 10, BDiagPattern );
807
painter.fillRect( w, -5, 5, h + 10, BDiagPattern );
809
if ( manager->selectedPart() == (KParts::Part *)child->document() &&
810
manager->selectedWidget() == (QWidget *)view )
813
if ( view->koDocument() == this )
817
painter.fillRect( -5, -5, 5, 5, color );
818
painter.fillRect( -5, h, 5, 5, color );
819
painter.fillRect( w, h, 5, 5, color );
820
painter.fillRect( w, -5, 5, 5, color );
821
painter.fillRect( w / 2 - 3, -5, 5, 5, color );
822
painter.fillRect( w / 2 - 3, h, 5, 5, color );
823
painter.fillRect( -5, h / 2 - 3, 5, 5, color );
824
painter.fillRect( w, h / 2 - 3, 5, 5, color );
827
painter.setClipping( TRUE );
832
bool KoDocument::isModified()
834
if ( KParts::ReadWritePart::isModified() )
836
//kdDebug(30003)<<k_funcinfo<<" Modified doc='"<<url().url()<<"' extern="<<isStoredExtern()<<endl;
839
// Then go through internally stored children (considdered to be part of this doc)
840
QPtrListIterator<KoDocumentChild> it = children();
841
for (; it.current(); ++it )
843
if ( !it.current()->isStoredExtern() && !it.current()->isDeleted() )
845
KoDocument *doc = it.current()->document();
846
if ( doc && doc->isModified() )
853
bool KoDocument::saveChildren( KoStore* _store )
855
//kdDebug(30003)<<k_funcinfo<<" checking children of doc='"<<url().url()<<"'"<<endl;
857
QPtrListIterator<KoDocumentChild> it( children() );
858
for( ; it.current(); ++it ) {
859
KoDocument* childDoc = it.current()->document();
860
if (childDoc && !it.current()->isDeleted())
862
if ( !childDoc->isStoredExtern() )
864
//kdDebug(30003) << "KoDocument::saveChildren internal url: /" << i << endl;
865
if ( !childDoc->saveToStore( _store, QString::number( i++ ) ) )
869
childDoc->setModified( false );
871
//else kdDebug(30003)<<k_funcinfo<<" external (don't save) url:" << childDoc->url().url()<<endl;
877
bool KoDocument::saveExternalChildren()
879
if ( d->m_doNotSaveExtDoc )
881
//kdDebug(30003)<<k_funcinfo<<" Don't save external docs in doc='"<<url().url()<<"'"<<endl;
882
d->m_doNotSaveExtDoc = false;
886
//kdDebug(30003)<<k_funcinfo<<" checking children of doc='"<<url().url()<<"'"<<endl;
889
QPtrListIterator<KoDocumentChild> it = children();
890
for (; (ch = it.current()); ++it )
892
if ( !ch->isDeleted() )
894
doc = ch->document();
895
if ( doc->isStoredExtern() && doc->isModified() )
897
kdDebug(30003)<<" save external doc='"<<url().url()<<"'"<<endl;
898
doc->setDoNotSaveExtDoc(); // Only save doc + it's internal children
900
return false; // error
902
//kdDebug(30003)<<k_funcinfo<<" not modified doc='"<<url().url()<<"'"<<endl;
903
// save possible external docs inside doc
904
if ( !doc->saveExternalChildren() )
911
bool KoDocument::saveNativeFormat( const QString & _file )
913
QString file( _file );
914
d->lastErrorMessage = QString::null;
915
//kdDebug(30003) << "Saving to store" << endl;
917
KoStore::Backend backend = KoStore::Auto;
918
if ( d->m_specialOutputFlag == SaveAsKOffice1dot1 )
920
kdDebug(30003) << "Saving as KOffice-1.1 format, using a tar.gz" << endl;
921
backend = KoStore::Tar; // KOffice-1.0/1.1 used tar.gz for the native mimetype
922
//// TODO more backwards compat stuff (embedded docs etc.)
924
else if ( d->m_specialOutputFlag == SaveAsDirectoryStore )
926
backend = KoStore::Directory;
927
kdDebug(30003) << "Saving as uncompressed XML, using directory store." << endl;
930
kdDebug(30003) << "KoDocument::saveNativeFormat nativeFormatMimeType=" << nativeFormatMimeType() << endl;
931
KoStore* store = KoStore::createStore( file, KoStore::Write, nativeFormatMimeType(), backend );
934
d->lastErrorMessage = i18n( "Couldn't open the file for saving" ); // more details needed?
939
// Save internal children first since they might get a new url
940
if ( !saveChildren( store ) )
942
if ( d->lastErrorMessage.isEmpty() )
943
d->lastErrorMessage = i18n( "Error while saving embedded documents" ); // more details needed
948
kdDebug(30003) << "Saving root" << endl;
949
if ( store->open( "root" ) )
951
KoStoreDevice dev( store );
952
if ( !saveToStream( &dev ) )
954
kdDebug(30003) << "saveToStream failed" << endl;
958
if ( !store->close() )
963
d->lastErrorMessage = i18n( "Not able to write 'maindoc.xml'." );
967
if ( store->open( "documentinfo.xml" ) )
969
QDomDocument doc = d->m_docInfo->save();
970
KoStoreDevice dev( store );
972
QCString s = doc.toCString(); // this is already Utf8!
973
(void)dev.writeBlock( s.data(), s.size()-1 );
974
(void)store->close();
976
if ( store->open( "preview.png" ) )
978
savePreview( store );
979
(void)store->close();
982
bool ret = completeSaving( store );
983
kdDebug(30003) << "Saving done of url: " << url().url() << endl;
986
if ( !saveExternalChildren() )
674
993
bool KoDocument::saveToStream( QIODevice * dev )
676
QDomDocument doc = saveXML();
678
QCString s = doc.toCString(); // utf8 already!!!
679
return dev->writeBlock( s.data(), s.length() ) == (int)s.length();
995
QDomDocument doc = saveXML();
997
QCString s = doc.toCString(); // utf8 already
998
// Important: don't use s.length() here. It's slow, and dangerous (in case of a '\0' somewhere)
999
// The -1 is because we don't want to write the final \0.
1000
int nwritten = dev->writeBlock( s.data(), s.size()-1 );
1001
if ( nwritten != (int)s.size()-1 )
1002
kdWarning(30003) << "KoDocument::saveToStream wrote " << nwritten << " - expected " << s.size()-1 << endl;
1003
return nwritten == (int)s.size()-1;
682
1006
bool KoDocument::saveToStore( KoStore* _store, const QString & _path )
684
kdDebug(30003) << "Saving document to store" << endl;
686
// Use the path as the internal url
689
// Save childen first since they might get a new url
690
if ( !saveChildren( _store, _path ) )
693
QString u = url().url();
694
if ( _store->open( u ) )
696
KoStoreDevice dev( _store );
697
if ( !saveToStream( &dev ) )
706
if ( !completeSaving( _store ) )
709
kdDebug(30003) << "Saved document to store" << endl;
1008
kdDebug(30003) << "Saving document to store " << _path << endl;
1010
// Use the path as the internal url
1011
if ( _path.startsWith( STORE_PROTOCOL ) )
1012
m_url = KURL( _path );
1013
else // ugly hack to pass a relative URI
1014
m_url = KURL( INTERNAL_PREFIX + _path );
1016
// To make the children happy cd to the correct directory
1017
_store->pushDirectory();
1018
_store->enterDirectory( _path );
1020
// Save childen first since they might get a new url
1021
if ( !saveChildren( _store ) )
1024
// In the current directory we're the king :-)
1025
if ( _store->open( "root" ) )
1027
KoStoreDevice dev( _store );
1028
if ( !saveToStream( &dev ) )
1033
if ( !_store->close() )
1037
if ( !completeSaving( _store ) )
1040
// Now that we're done leave the directory again
1041
_store->popDirectory();
1043
kdDebug(30003) << "Saved document to store" << endl;
1048
void KoDocument::savePreview( KoStore* store )
1050
QPixmap pix = generatePreview(QSize(256, 256));
1051
// Reducing to 8bpp reduces file sizes quite a lot.
1053
imageIO.setImage( pix.convertToImage().convertDepth(8, Qt::AvoidDither | Qt::DiffuseDither) );
1055
// NOTE: we cannot use QDataStream, as it is not 1:1
1056
QByteArray imageData;
1057
QBuffer buffer(imageData);
1058
buffer.open(IO_WriteOnly);
1059
imageIO.setIODevice(&buffer);
1060
imageIO.setFormat("PNG");
1064
store->write( imageData );
1067
QPixmap KoDocument::generatePreview( const QSize& size )
1069
double docWidth, docHeight;
1070
int pixmapSize = QMAX(size.width(), size.height());
1072
if (m_pageLayout.ptWidth > 1.0) {
1073
docWidth = m_pageLayout.ptWidth / 72 * QPaintDevice::x11AppDpiX();
1074
docHeight = m_pageLayout.ptHeight / 72 * QPaintDevice::x11AppDpiX();
1077
// If we don't have a page layout, just draw the top left hand corner
1082
double ratio = docWidth / docHeight;
1085
int previewWidth, previewHeight;
1088
previewWidth = (int) pixmapSize;
1089
previewHeight = (int) (pixmapSize / ratio);
1093
previewWidth = (int) (pixmapSize * ratio);
1094
previewHeight = (int) pixmapSize;
1097
pix.resize((int)docWidth, (int)docHeight);
1099
pix.fill( QColor( 245, 245, 245 ) );
1101
QRect rc(0, 0, pix.width(), pix.height());
1105
paintEverything(p, rc, false);
1108
pix.convertFromImage(pix.convertToImage().smoothScale(previewWidth, previewHeight));
714
1113
QString KoDocument::autoSaveFile( const QString & path ) const
717
ASSERT( url.isLocalFile() );
718
QString dir = url.directory(false);
719
QString filename = url.filename();
720
return dir + '.' + filename + ".autosave";
1115
// Using the extension allows to avoid relying on the mime magic when opening
1116
KMimeType::Ptr mime = KMimeType::mimeType( nativeFormatMimeType() );
1117
QString extension = mime->property( "X-KDE-NativeExtension" ).toString();
1118
if ( path.isEmpty() )
1120
// Never saved? Use a temp file in $HOME then
1121
// Yes, two open unnamed docs will overwrite each other's autosave file,
1122
// but hmm, we can only do something if that's in the same process anyway...
1123
QString ret = QDir::homeDirPath() + "/." + QString::fromLatin1(instance()->instanceName()) + ".autosave" + extension;
1129
Q_ASSERT( url.isLocalFile() );
1130
QString dir = url.directory(false);
1131
QString filename = url.fileName();
1132
return dir + "." + filename + ".autosave" + extension;
1136
bool KoDocument::checkAutoSaveFile()
1138
QString asf = autoSaveFile( QString::null ); // the one in $HOME
1139
//kdDebug(30003) << "asf=" << asf << endl;
1140
if ( QFile::exists( asf ) )
1142
QDateTime date = QFileInfo(asf).lastModified();
1143
QString dateStr = date.toString(Qt::LocalDate);
1144
int res = KMessageBox::warningYesNoCancel(
1145
0, i18n( "An autosaved file for an unnamed document exists in %1.\nThis file is dated %2\nDo you want to open it?" )
1146
.arg(asf, dateStr) );
1148
case KMessageBox::Yes : {
1151
bool ret = openURL( url );
1156
case KMessageBox::No :
1157
unlink( QFile::encodeName( asf ) );
1166
bool KoDocument::import( const KURL & _url )
1170
kdDebug (30003) << "KoDocument::import url=" << _url.url() << endl;
1171
d->m_isImporting = true;
1174
ret = openURL (_url);
1176
// reset m_url & m_file (kindly? set by KParts::openURL()) to simulate a
1180
kdDebug (30003) << "KoDocument::import success, resetting url" << endl;
1182
setTitleModified ();
1185
d->m_isImporting = false;
723
1190
bool KoDocument::openURL( const KURL & _url )
725
// Reimplemented, to add a check for autosave files
726
if ( _url.isMalformed() )
731
bool autosaveOpened = false;
732
if ( url.isLocalFile() )
734
QString file = url.path();
735
QString asf = autoSaveFile( file );
736
if ( QFile::exists( asf ) )
738
kdDebug() << "KoDocument::openURL asf=" << asf << endl;
739
// ## TODO compare timestamps ?
740
int res = KMessageBox::warningYesNoCancel( 0,
741
i18n( "An autosaved file exists for this document.\nDo you want to open it instead ?" ));
743
case KMessageBox::Yes :
745
autosaveOpened = true;
747
case KMessageBox::No :
748
unlink( QFile::encodeName( asf ) );
756
if ( url.isLocalFile() )
758
// ReadOnlyPart::openURL does something wrong for local files: it emits completed
759
// even if openFile returned false :(
762
m_file = m_url.path();
769
ret = KParts::ReadWritePart::openURL( url );
771
if ( autosaveOpened )
772
m_url = KURL(); // Force save to act like 'Save As'
775
if ( d->m_shells.isEmpty() )
776
kdWarning() << "KoDocument::openURL no shell yet !" << endl;
777
// Add to recent actions list in our shells
778
QListIterator<KoMainWindow> it( d->m_shells );
779
for (; it.current(); ++it )
780
it.current()->addRecentURL( _url );
1192
kdDebug(30003) << "KoDocument::openURL url=" << _url.url() << endl;
1193
d->lastErrorMessage = QString::null;
1195
// Reimplemented, to add a check for autosave files and to improve error reporting
1196
if ( !_url.isValid() )
1198
d->lastErrorMessage = i18n( "Malformed URL\n%1" ).arg( _url.url() ); // ## used anywhere ?
1204
bool autosaveOpened = false;
1205
if ( url.isLocalFile() && d->m_shouldCheckAutoSaveFile )
1207
QString file = url.path();
1208
QString asf = autoSaveFile( file );
1209
if ( QFile::exists( asf ) )
1211
//kdDebug(30003) << "KoDocument::openURL asf=" << asf << endl;
1212
// ## TODO compare timestamps ?
1213
int res = KMessageBox::warningYesNoCancel( 0,
1214
i18n( "An autosaved file exists for this document.\nDo you want to open it instead?" ));
1216
case KMessageBox::Yes :
1218
autosaveOpened = true;
1220
case KMessageBox::No :
1221
unlink( QFile::encodeName( asf ) );
1228
bool ret = KParts::ReadWritePart::openURL( url );
1230
if ( autosaveOpened )
1231
resetURL(); // Force save to act like 'Save As'
1234
// We have no koffice shell when we are being embedded as a readonly part.
1235
//if ( d->m_shells.isEmpty() )
1236
// kdWarning(30003) << "KoDocument::openURL no shell yet !" << endl;
1237
// Add to recent actions list in our shells
1238
QPtrListIterator<KoMainWindow> it( d->m_shells );
1239
for (; it.current(); ++it )
1240
it.current()->addRecentURL( _url );
785
1245
bool KoDocument::openFile()
787
kdDebug(30003) << "KoDocument::openFile for " << m_file << endl;
788
if ( ! QFile::exists(m_file) )
790
// Maybe offer to create a new document with that name ?
791
KMessageBox::error(0L, i18n("The file %1 doesn't exist.").arg(m_file) );
795
QApplication::setOverrideCursor( waitCursor );
797
if ( d->m_bSingleViewMode && !d->m_views.isEmpty() )
799
// We already had a view (this happens when doing reload in konqueror)
800
removeView( d->m_views.first() );
801
delete d->m_views.first();
802
ASSERT( d->m_views.isEmpty() );
806
QCString _native_format = nativeFormatMimeType();
808
// Launch a filter if we need one for this url ?
809
if ( !d->filterManager )
810
d->filterManager = new KoFilterManager();
811
QString importedFile = d->filterManager->import( m_file, _native_format, this );
813
kdDebug(30003) << "KoDocument::openFile - importedFile " << importedFile << endl;
815
QApplication::restoreOverrideCursor();
819
if (!importedFile.isEmpty()) // Something to load (tmp or native file) ?
821
// The filter, if any, has been applied. It's all native format now.
822
if ( !loadNativeFormat( importedFile ) )
825
KMessageBox::error( 0L, i18n( "Could not open\n%1" ).arg( url().prettyURL() ) );
829
// The filter did it all. Ok if it changed something...
833
if ( importedFile != m_file )
835
// We opened a temporary file (result of an import filter)
836
// Set document URL to empty - we don't want to save in /tmp !
837
// But only if in readwrite mode (no saving problem otherwise)
840
// and remove temp file - uncomment this to debug import filters
841
if(!importedFile.isEmpty())
842
unlink( QFile::encodeName(importedFile) );
845
if ( ok && d->m_bSingleViewMode )
847
KoView *view = createView( d->m_wrapperWidget );
848
d->m_wrapperWidget->setKoView( view );
852
// We decided not to save in the file's original format by default
853
// ( KWord isn't a text editor or a MSWord editor :)
854
// The risk of losing formatting information is too high currently.
855
d->outputMimeType = _native_format;
1247
//kdDebug(30003) << "KoDocument::openFile for " << m_file << endl;
1248
if ( ! QFile::exists(m_file) )
1250
QApplication::restoreOverrideCursor();
1251
if ( d->m_autoErrorHandlingEnabled )
1252
// Maybe offer to create a new document with that name ?
1253
KMessageBox::error(0L, i18n("The file %1 doesn't exist.").arg(m_file) );
1257
QApplication::setOverrideCursor( waitCursor );
1259
if ( d->m_bSingleViewMode && !d->m_views.isEmpty() )
1261
// We already had a view (this happens when doing reload in konqueror)
1262
KoView* v = d->m_views.first();
1265
Q_ASSERT( d->m_views.isEmpty() );
1268
d->m_specialOutputFlag = 0;
1269
QCString _native_format = nativeFormatMimeType();
1272
u.setPath( m_file );
1273
QString typeName = KMimeType::findByURL( u, 0, true )->name();
1275
// Allow to open backup files, don't keep the mimetype application/x-trash.
1276
if ( typeName == "application/x-trash" )
1278
QString path = u.path();
1279
QStringList patterns = KMimeType::mimeType( typeName )->patterns();
1280
// Find the extension that makes it a backup file, and remove it
1281
for( QStringList::Iterator it = patterns.begin(); it != patterns.end(); ++it ) {
1283
if ( !ext.isEmpty() && ext[0] == '*' )
1286
if ( path.endsWith( ext ) ) {
1287
path.truncate( path.length() - ext.length() );
1292
typeName = KMimeType::findByPath( path, 0, true )->name();
1295
// Special case for flat XML files (e.g. using directory store)
1296
if ( u.fileName() == "maindoc.xml" || typeName == "inode/directory" )
1298
typeName = _native_format; // Hmm, what if it's from another app? ### Check mimetype
1299
d->m_specialOutputFlag = SaveAsDirectoryStore;
1300
kdDebug(30003) << "KoDocument::openFile loading maindoc.xml, using directory store for " << m_file << endl;
1302
kdDebug(30003) << "KoDocument::openFile " << m_file << " type:" << typeName << endl;
1304
QString importedFile = m_file;
1306
if ( typeName == KMimeType::defaultMimeType() ) {
1307
kdError(30003) << "No mimetype found for " << m_file << endl;
1308
QApplication::restoreOverrideCursor();
1309
if ( d->m_autoErrorHandlingEnabled )
1310
KMessageBox::error( 0L, i18n( "Could not open\n%1" ).arg( url().prettyURL( 0, KURL::StripFileProtocol ) ) );
1314
if ( typeName.latin1() != _native_format ) {
1315
if ( !d->filterManager )
1316
d->filterManager = new KoFilterManager( this );
1317
KoFilter::ConversionStatus status;
1318
importedFile = d->filterManager->import( m_file, status );
1319
if ( status != KoFilter::OK )
1321
QApplication::restoreOverrideCursor();
1322
if ( status != KoFilter::UserCancelled &&
1323
status != KoFilter::BadConversionGraph &&
1324
d->m_autoErrorHandlingEnabled )
1325
// Any way of passing a better error message from the filter?
1326
KMessageBox::error( 0L, i18n( "Could not open\n%1" ).arg( url().prettyURL( 0, KURL::StripFileProtocol ) ) );
1330
kdDebug(30003) << "KoDocument::openFile - importedFile '" << importedFile
1331
<< "', status: " << static_cast<int>( status ) << endl;
1334
QApplication::restoreOverrideCursor();
1338
if (!importedFile.isEmpty()) // Something to load (tmp or native file) ?
1340
// The filter, if any, has been applied. It's all native format now.
1341
if ( !loadNativeFormat( importedFile ) )
1344
if ( d->m_autoErrorHandlingEnabled )
1346
if ( d->lastErrorMessage.isEmpty() )
1347
KMessageBox::error( 0L, i18n( "Could not open\n%1" ).arg( url().prettyURL( 0, KURL::StripFileProtocol ) ) );
1348
else if ( d->lastErrorMessage != "USER_CANCELED" )
1349
KMessageBox::error( 0L, i18n( "Could not open %1\nReason: %2" ).arg( url().prettyURL( 0, KURL::StripFileProtocol ), d->lastErrorMessage ) );
1354
if ( importedFile != m_file )
1356
// We opened a temporary file (result of an import filter)
1357
// Set document URL to empty - we don't want to save in /tmp !
1358
// But only if in readwrite mode (no saving problem otherwise)
1360
// But this isn't true at all. If this is the result of an
1361
// import, then importedFile=temporary_file.kwd and
1362
// m_file/m_url=foreignformat.ext so m_url is correct!
1363
// So don't resetURL() or else the caption won't be set when
1364
// foreign files are opened (an annoying bug).
1368
if ( isReadWrite() )
1372
// remove temp file - uncomment this to debug import filters
1373
if(!importedFile.isEmpty())
1374
unlink( QFile::encodeName(importedFile) );
1377
if ( ok && d->m_bSingleViewMode )
1379
// See addClient below
1380
KXMLGUIFactory* guiFactory = factory();
1381
if( guiFactory ) // 0L when splitting views in konq, for some reason
1382
guiFactory->removeClient( this );
1384
KoView *view = createView( d->m_wrapperWidget );
1385
d->m_wrapperWidget->setKoView( view );
1388
// Ok, now we have a view, so action() and domDocument() will work as expected
1391
guiFactory->addClient( this );
1396
d->mimeType = typeName.latin1 ();
1398
d->outputMimeType = d->mimeType;
1400
const bool needConfirm = (d->mimeType != _native_format);
1401
setConfirmNonNativeSave ( false, needConfirm );
1402
setConfirmNonNativeSave ( true, needConfirm );
860
1408
bool KoDocument::loadNativeFormat( const QString & file )
862
QApplication::setOverrideCursor( waitCursor );
864
kdDebug(30003) << "KoDocument::loadNativeFormat( " << file << " )" << endl;
867
if ( !in.open( IO_ReadOnly ) )
869
QApplication::restoreOverrideCursor();
873
// Try to find out whether it is a mime multi part file
875
if ( in.readBlock( buf, 4 ) < 4 )
877
QApplication::restoreOverrideCursor();
882
//kdDebug(30003) << "PATTERN=" << buf << endl;
885
if ( strncasecmp( buf, "<?xm", 4 ) == 0 )
889
doc.setContent( &in );
890
bool res = loadXML( &in, doc );
892
res = completeLoading( 0L );
894
QApplication::restoreOverrideCursor();
899
{ // It's a koffice store (tar.gz)
901
KoStore * store = new KoStore( file, KoStore::Read );
906
QApplication::restoreOverrideCursor();
910
if ( store->open( "root" ) )
912
KoStoreDevice dev( store );
914
doc.setContent( &dev );
915
if ( !loadXML( &dev, doc ) )
1410
if ( !QFileInfo( file).isFile () )
1412
d->lastErrorMessage = i18n( "%1 is not a file." ).arg(file);
1416
QApplication::setOverrideCursor( waitCursor );
1418
kdDebug(30003) << "KoDocument::loadNativeFormat( " << file << " )" << endl;
1421
bool isRawXML = false;
1422
if ( d->m_specialOutputFlag != SaveAsDirectoryStore ) // Don't try to open a directory ;)
1425
if ( !in.open( IO_ReadOnly ) )
1427
QApplication::restoreOverrideCursor();
1428
d->lastErrorMessage = i18n( "Couldn't open the file for reading (check read permissions)." );
1432
// Try to find out whether it is a mime multi part file
1434
if ( in.readBlock( buf, 4 ) < 4 )
1436
QApplication::restoreOverrideCursor();
1438
d->lastErrorMessage = i18n( "Couldn't read the beginning of the file." );
1441
isRawXML = (strncasecmp( buf, "<?xm", 4 ) == 0);
1442
//kdDebug(30003) << "PATTERN=" << buf << endl;
1453
if ( doc.setContent( &in , &errorMsg, &errorLine, &errorColumn ) )
1455
res = loadXML( &in, doc );
1457
res = completeLoading( 0L );
1461
kdError (30003) << "Parsing Error! Aborting! (in KoDocument::loadNativeFormat (QFile))" << endl
1462
<< " Line: " << errorLine << " Column: " << errorColumn << endl
1463
<< " Message: " << errorMsg << endl;
1464
d->lastErrorMessage = i18n( "parsing error in the main document at line %1, column %2\nError message: %3" )
1465
.arg( errorLine ).arg( errorColumn ).arg( i18n ( "QXml", errorMsg.utf8() ) );
918
1469
QApplication::restoreOverrideCursor();
924
kdError(30003) << "ERROR: No maindoc.xml" << endl;
926
QApplication::restoreOverrideCursor();
930
if ( !loadChildren( store ) )
932
kdError(30003) << "ERROR: Could not load children" << endl;
934
QApplication::restoreOverrideCursor();
937
if ( store->open( "documentinfo.xml" ) )
939
KoStoreDevice dev( store );
941
doc.setContent( &dev );
942
d->m_docInfo->load( doc );
947
kdDebug( 30003 ) << "cannot open document info" << endl;
949
d->m_docInfo = new KoDocumentInfo( this, "document info" );
952
bool res = completeLoading( store );
954
QApplication::restoreOverrideCursor();
960
bool KoDocument::loadFromStore( KoStore* _store, const KURL & url )
962
if ( _store->open( url.url() ) )
964
KoStoreDevice dev( _store );
966
doc.setContent( &dev );
967
if ( !loadXML( &dev, doc ) )
971
// Store as document URL
974
if ( !loadChildren( _store ) )
976
kdError(30003) << "ERROR: Could not load children" << endl;
980
return completeLoading( _store );
1474
{ // It's a koffice store (tar.gz, zip, directory, etc.)
1476
KoStore::Backend backend = (d->m_specialOutputFlag == SaveAsDirectoryStore) ? KoStore::Directory : KoStore::Auto;
1477
KoStore * store = KoStore::createStore( file, KoStore::Read, "", backend );
1481
d->lastErrorMessage = i18n( "Not a valid KOffice file." );
1483
QApplication::restoreOverrideCursor();
1487
if ( store->open( "root" ) )
1493
if ( !doc.setContent( store->device(), &errorMsg, &errorLine, &errorColumn ) )
1495
kdError (30003) << "Parsing Error! Aborting! (in KoDocument::loadNativeFormat (KoStore))" << endl
1496
<< " Line: " << errorLine << " Column: " << errorColumn << endl
1497
<< " Message: " << errorMsg << endl;
1498
d->lastErrorMessage = i18n( "parsing error in the main document at line %1, column %2\nError message: %3" )
1499
.arg( errorLine ).arg( errorColumn ).arg( i18n ( errorMsg.utf8() ) );
1501
QApplication::restoreOverrideCursor();
1504
if ( !loadXML( store->device(), doc ) )
1507
QApplication::restoreOverrideCursor();
1513
kdError(30003) << "ERROR: No maindoc.xml" << endl;
1514
d->lastErrorMessage = i18n( "Invalid document: no file 'maindoc.xml'." );
1516
QApplication::restoreOverrideCursor();
1520
if ( !loadChildren( store ) )
1522
kdError(30003) << "ERROR: Could not load children" << endl;
1523
// Proceed nonetheless
1525
if ( d->lastErrorMessage.isEmpty() )
1526
d->lastErrorMessage = i18n( "Couldn't load embedded objects." );
1528
QApplication::restoreOverrideCursor();
1532
if ( store->open( "documentinfo.xml" ) )
1535
doc.setContent( store->device() );
1536
d->m_docInfo->load( doc );
1541
//kdDebug( 30003 ) << "cannot open document info" << endl;
1542
delete d->m_docInfo;
1543
d->m_docInfo = new KoDocumentInfo( this, "document info" );
1546
bool res = completeLoading( store );
1548
QApplication::restoreOverrideCursor();
1554
bool KoDocument::loadFromStore( KoStore* _store, const QString& url )
1556
if ( _store->open( url ) )
1559
doc.setContent( _store->device() );
1560
if ( !loadXML( _store->device(), doc ) )
1568
_store->pushDirectory();
1569
// Store as document URL
1570
if ( url.startsWith( STORE_PROTOCOL ) )
1571
m_url = KURL( url );
1573
m_url = KURL( INTERNAL_PREFIX + url );
1574
_store->enterDirectory( url );
1577
if ( !loadChildren( _store ) )
1579
kdError(30003) << "ERROR: Could not load children" << endl;
1585
bool result = completeLoading( _store );
1587
// Restore the "old" path
1588
_store->popDirectory();
1593
bool KoDocument::isInOperation()
1595
return d->m_numOperations > 0;
1598
void KoDocument::emitBeginOperation()
1601
/* if we're already in an operation, don't send the signal again */
1602
if (!isInOperation())
1603
emit sigBeginOperation();
1604
d->m_numOperations++;
1607
void KoDocument::emitEndOperation()
1609
d->m_numOperations--;
1611
/* don't end the operation till we've cleared all the nested operations */
1612
if (d->m_numOperations == 0)
1613
emit sigEndOperation();
1614
else if (d->m_numOperations < 0)
1615
/* ignore 'end' calls with no matching 'begin' call */
1616
d->m_numOperations = 0;
983
1620
bool KoDocument::isStoredExtern()
985
return ( m_url.protocol() != STORE_PROTOCOL );
1622
return !storeInternal() && hasExternURL();
988
1625
void KoDocument::setModified( bool mod )
990
if ( mod == isModified() )
993
kdDebug(30003) << "KoDocument::setModified( " << (mod ? "true" : "false") << ")" << endl;
1627
//kdDebug(30003)<<k_funcinfo<<" url:" << m_url.path() << endl;
1628
//kdDebug(30003)<<k_funcinfo<<" mod="<<mod<<" MParts mod="<<KParts::ReadWritePart::isModified()<<" isModified="<<isModified()<<endl;
1630
d->modifiedAfterAutosave=mod;
1631
if ( isAutosaving() ) // ignore setModified calls due to autosaving
1633
if ( mod == KParts::ReadWritePart::isModified() )
994
1636
KParts::ReadWritePart::setModified( mod );