00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "koDocument.h"
00022
00023 #include "koDocument_p.h"
00024 #include "KoDocumentIface.h"
00025 #include "koDocumentChild.h"
00026 #include "koView.h"
00027 #include "koMainWindow.h"
00028 #include "koFilterManager.h"
00029 #include "koDocumentInfo.h"
00030 #include "koOasisStyles.h"
00031 #include "koOasisStore.h"
00032 #include "koxmlns.h"
00033
00034 #include <koStoreDevice.h>
00035 #include <koxmlwriter.h>
00036
00037 #include <kapplication.h>
00038 #include <kdebug.h>
00039 #include <kdeversion.h>
00040 #include <kfileitem.h>
00041 #include <kiconloader.h>
00042 #include <kio/job.h>
00043 #include <kio/netaccess.h>
00044 #include <klocale.h>
00045 #include <kmessagebox.h>
00046 #include <kmimetype.h>
00047 #include <kparts/partmanager.h>
00048 #include <kprinter.h>
00049 #include <ksavefile.h>
00050
00051 #include <qbuffer.h>
00052 #include <qcursor.h>
00053 #include <qdir.h>
00054 #include <qfile.h>
00055 #include <qfileinfo.h>
00056 #include <qimage.h>
00057 #include <qmap.h>
00058 #include <qpainter.h>
00059 #include <qtimer.h>
00060 #include <qxml.h>
00061
00062 #include <config.h>
00063 #include <assert.h>
00064
00065
00066
00067
00068
00069 #define STORE_PROTOCOL "tar"
00070
00071
00072 #define INTERNAL_PROTOCOL "intern"
00073 #define INTERNAL_PREFIX "intern:/"
00074
00075
00076 QPtrList<KoDocument> *KoDocument::s_documentList=0L;
00077
00078 using namespace std;
00079 class KoViewWrapperWidget;
00080
00081
00082
00083
00084
00085
00086
00087 const int KoDocument::s_defaultAutoSave = 300;
00088
00089 class KoDocument::Private
00090 {
00091 public:
00092 Private() :
00093 m_dcopObject( 0L ),
00094 filterManager( 0L ),
00095 m_specialOutputFlag( 0 ),
00096 m_isImporting( false ), m_isExporting( false ),
00097 m_numOperations( 0 ),
00098 modifiedAfterAutosave( false ),
00099 m_autosaving( false ),
00100 m_shouldCheckAutoSaveFile( true ),
00101 m_autoErrorHandlingEnabled( true ),
00102 m_backupFile( true ),
00103 m_backupPath( QString::null ),
00104 m_doNotSaveExtDoc( false ),
00105 m_current( false ),
00106 m_storeInternal( false ),
00107 m_bLoading( false )
00108 {
00109 m_confirmNonNativeSave[0] = true;
00110 m_confirmNonNativeSave[1] = true;
00111 }
00112
00113 QPtrList<KoView> m_views;
00114 QPtrList<KoDocumentChild> m_children;
00115 QPtrList<KoMainWindow> m_shells;
00116 QValueList<QDomDocument> m_viewBuildDocuments;
00117
00118 KoViewWrapperWidget *m_wrapperWidget;
00119 KoDocumentIface * m_dcopObject;
00120 KoDocumentInfo *m_docInfo;
00121
00122 KoFilterManager * filterManager;
00123
00124 QCString mimeType;
00125 QCString outputMimeType;
00126 bool m_confirmNonNativeSave [2];
00127
00128
00129 int m_specialOutputFlag;
00130 bool m_isImporting, m_isExporting;
00131
00132 QTimer m_autoSaveTimer;
00133 QString lastErrorMessage;
00134 int m_autoSaveDelay;
00135 int m_numOperations;
00136 bool modifiedAfterAutosave;
00137 bool m_bSingleViewMode;
00138 bool m_autosaving;
00139 bool m_shouldCheckAutoSaveFile;
00140 bool m_autoErrorHandlingEnabled;
00141 bool m_backupFile;
00142 QString m_backupPath;
00143 bool m_doNotSaveExtDoc;
00144 bool m_current;
00145 bool m_storeInternal;
00146 bool m_bLoading;
00147 };
00148
00149
00150 class KoViewWrapperWidget : public QWidget
00151 {
00152 public:
00153 KoViewWrapperWidget( QWidget *parent, const char *name )
00154 : QWidget( parent, name )
00155 {
00156 KGlobal::locale()->insertCatalogue("koffice");
00157
00158 KGlobal::iconLoader()->addAppDir("koffice");
00159 m_view = 0L;
00160
00161 setFocusPolicy( ClickFocus );
00162 }
00163
00164 virtual ~KoViewWrapperWidget() {
00165 setFocusProxy( 0 );
00166 }
00167
00168 virtual void resizeEvent( QResizeEvent * )
00169 {
00170 QObject *wid = child( 0, "QWidget" );
00171 if ( wid )
00172 static_cast<QWidget *>(wid)->setGeometry( 0, 0, width(), height() );
00173 }
00174
00175 virtual void childEvent( QChildEvent *ev )
00176 {
00177 if ( ev->type() == QEvent::ChildInserted )
00178 resizeEvent( 0L );
00179 }
00180
00181
00182 void setKoView( KoView * view ) {
00183 m_view = view;
00184 setFocusProxy( m_view );
00185 }
00186 KoView * koView() const { return m_view; }
00187 private:
00188 KoView* m_view;
00189 };
00190
00191 KoBrowserExtension::KoBrowserExtension( KoDocument * doc, const char * name )
00192 : KParts::BrowserExtension( doc, name )
00193 {
00194 emit enableAction( "print", true );
00195 }
00196
00197 void KoBrowserExtension::print()
00198 {
00199 KoDocument * doc = static_cast<KoDocument *>( parent() );
00200 KoViewWrapperWidget * wrapper = static_cast<KoViewWrapperWidget *>( doc->widget() );
00201 KoView * view = wrapper->koView();
00202
00203 KPrinter printer;
00204
00205 view->setupPrinter( printer );
00206 if ( printer.setup( view ) )
00207 view->print( printer );
00208 }
00209
00210 KoDocument::KoDocument( QWidget * parentWidget, const char *widgetName, QObject* parent, const char* name, bool singleViewMode )
00211 : KParts::ReadWritePart( parent, name )
00212 {
00213 if(s_documentList==0L)
00214 s_documentList=new QPtrList<KoDocument>;
00215 s_documentList->append(this);
00216
00217 d = new Private;
00218 m_bEmpty = TRUE;
00219 connect( &d->m_autoSaveTimer, SIGNAL( timeout() ), this, SLOT( slotAutoSave() ) );
00220 setAutoSave( s_defaultAutoSave );
00221 d->m_bSingleViewMode = singleViewMode;
00222
00223
00224
00225 if ( parent )
00226 {
00227 if ( parent->inherits( "KoDocument" ) )
00228 d->m_bSingleViewMode = ((KoDocument *)parent)->isSingleViewMode();
00229 else if ( parent->inherits( "KParts::Part" ) )
00230 d->m_bSingleViewMode = true;
00231 }
00232
00233 if ( singleViewMode )
00234 {
00235 d->m_wrapperWidget = new KoViewWrapperWidget( parentWidget, widgetName );
00236 setWidget( d->m_wrapperWidget );
00237 kdDebug(30003) << "creating KoBrowserExtension" << endl;
00238 (void) new KoBrowserExtension( this );
00239 }
00240
00241 d->m_docInfo = new KoDocumentInfo( this, "document info" );
00242
00243 m_pageLayout.ptWidth = 0;
00244 m_pageLayout.ptHeight = 0;
00245 m_pageLayout.ptTop = 0;
00246 m_pageLayout.ptBottom = 0;
00247 m_pageLayout.ptLeft = 0;
00248 m_pageLayout.ptRight = 0;
00249
00250
00251 if ( !singleViewMode )
00252 connect( this, SIGNAL( started( KIO::Job* ) ), SLOT( slotStarted( KIO::Job* ) ) );
00253 }
00254
00255 KoDocument::~KoDocument()
00256 {
00257 d->m_autoSaveTimer.stop();
00258
00259 QPtrListIterator<KoDocumentChild> childIt( d->m_children );
00260 for (; childIt.current(); ++childIt )
00261 disconnect( childIt.current(), SIGNAL( destroyed() ),
00262 this, SLOT( slotChildDestroyed() ) );
00263
00264
00265
00266 QPtrListIterator<KoView> vIt( d->m_views );
00267 for (; vIt.current(); ++vIt )
00268 vIt.current()->setDocumentDeleted();
00269
00270 d->m_children.setAutoDelete( true );
00271 d->m_children.clear();
00272
00273 d->m_shells.setAutoDelete( true );
00274 d->m_shells.clear();
00275
00276 delete d->m_dcopObject;
00277 delete d->filterManager;
00278 delete d;
00279 s_documentList->removeRef(this);
00280
00281 if(s_documentList->isEmpty()) {
00282 delete s_documentList;
00283 s_documentList=0;
00284 }
00285 }
00286
00287 bool KoDocument::isSingleViewMode() const
00288 {
00289 return d->m_bSingleViewMode;
00290 }
00291
00292 bool KoDocument::isEmbedded() const
00293 {
00294 return dynamic_cast<KoDocument *>( parent() ) != 0;
00295 }
00296
00297 KoView *KoDocument::createView( QWidget *parent, const char *name )
00298 {
00299 KoView *view=createViewInstance(parent, name);
00300 addView(view);
00301 return view;
00302 }
00303
00304 bool KoDocument::exp0rt( const KURL & _url )
00305 {
00306 bool ret;
00307
00308 d->m_isExporting = true;
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318 KURL oldURL = m_url;
00319 QString oldFile = m_file;
00320
00321 bool wasModified = isModified ();
00322 QCString oldMimeType = mimeType ();
00323
00324
00325
00326 ret = saveAs( _url );
00327
00328
00329
00330
00331
00332
00333 kdDebug(30003) << "Restoring KoDocument state to before export" << endl;
00334
00335
00336
00337 m_url = oldURL;
00338 m_file = oldFile;
00339
00340
00341
00342 if (ret)
00343 {
00344 setModified (wasModified);
00345 d->mimeType = oldMimeType;
00346 }
00347
00348
00349 d->m_isExporting = false;
00350
00351 return ret;
00352 }
00353
00354 bool KoDocument::saveFile()
00355 {
00356 kdDebug(30003) << "KoDocument::saveFile() doc='" << url().url() <<"'"<< endl;
00357
00358
00359 const bool wasModified = isModified ();
00360
00361
00362 QCString outputMimeType = d->outputMimeType;
00363
00364 if ( outputMimeType.isEmpty() )
00365 outputMimeType = d->outputMimeType = nativeFormatMimeType();
00366
00367 QApplication::setOverrideCursor( waitCursor );
00368
00369 if ( backupFile() ) {
00370 if ( url().isLocalFile() )
00371 KSaveFile::backupFile( url().path(), d->m_backupPath );
00372 else {
00373 KIO::UDSEntry entry;
00374 if ( KIO::NetAccess::stat( url(), entry, shells().current() ) ) {
00375 emit sigStatusBarMessage( i18n("Making backup...") );
00376 KURL backup;
00377 if ( d->m_backupPath.isEmpty())
00378 backup = url();
00379 else
00380 backup = d->m_backupPath +"/"+url().fileName();
00381 backup.setPath( backup.path() + QString::fromLatin1("~") );
00382 KFileItem item( entry, url() );
00383 Q_ASSERT( item.name() == url().fileName() );
00384 KIO::NetAccess::file_copy( url(), backup, item.permissions(), true , false , shells().current() );
00385 }
00386 }
00387 }
00388
00389 emit sigStatusBarMessage( i18n("Saving...") );
00390 bool ret = false;
00391 bool suppressErrorDialog = false;
00392 if ( !isNativeFormat( outputMimeType ) ) {
00393 kdDebug(30003) << "Saving to format " << outputMimeType << " in " << m_file << endl;
00394
00395 if ( !d->filterManager )
00396 d->filterManager = new KoFilterManager( this );
00397
00398 KoFilter::ConversionStatus status = d->filterManager->exp0rt( m_file, outputMimeType );
00399 ret = status == KoFilter::OK;
00400 suppressErrorDialog = (status == KoFilter::UserCancelled || status == KoFilter::BadConversionGraph );
00401 } else {
00402
00403 Q_ASSERT( !m_file.isEmpty() );
00404 ret = saveNativeFormat( m_file );
00405 }
00406
00407 if ( ret ) {
00408 removeAutoSaveFiles();
00409
00410
00411 setAutoSave( d->m_autoSaveDelay );
00412 }
00413
00414 QApplication::restoreOverrideCursor();
00415 if ( !ret )
00416 {
00417 if ( !suppressErrorDialog )
00418 {
00419 showSavingErrorDialog();
00420 }
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432 resetURL();
00433
00434
00435 setModified( wasModified );
00436 }
00437
00438 if ( ret )
00439 {
00440 d->mimeType = outputMimeType;
00441 setConfirmNonNativeSave ( isExporting (), false );
00442 }
00443 emit sigClearStatusBarMessage();
00444
00445 return ret;
00446 }
00447
00448 QCString KoDocument::mimeType() const
00449 {
00450 return d->mimeType;
00451 }
00452
00453 void KoDocument::setMimeType( const QCString & mimeType )
00454 {
00455 d->mimeType = mimeType;
00456 }
00457
00458 void KoDocument::setOutputMimeType( const QCString & mimeType, int specialOutputFlag )
00459 {
00460 d->outputMimeType = mimeType;
00461 d->m_specialOutputFlag = specialOutputFlag;
00462 }
00463
00464 QCString KoDocument::outputMimeType() const
00465 {
00466 return d->outputMimeType;
00467 }
00468
00469 int KoDocument::specialOutputFlag() const
00470 {
00471 return d->m_specialOutputFlag;
00472 }
00473
00474 bool KoDocument::confirmNonNativeSave( const bool exporting ) const
00475 {
00476
00477
00478 return d->m_confirmNonNativeSave [ exporting ? 1 : 0 ];
00479 }
00480
00481 void KoDocument::setConfirmNonNativeSave( const bool exporting, const bool on )
00482 {
00483 d->m_confirmNonNativeSave [ exporting ? 1 : 0] = on;
00484 }
00485
00486 bool KoDocument::isImporting() const
00487 {
00488 return d->m_isImporting;
00489 }
00490
00491 bool KoDocument::isExporting() const
00492 {
00493 return d->m_isExporting;
00494 }
00495
00496 void KoDocument::setCheckAutoSaveFile( bool b )
00497 {
00498 d->m_shouldCheckAutoSaveFile = b;
00499 }
00500
00501 void KoDocument::setAutoErrorHandlingEnabled( bool b )
00502 {
00503 d->m_autoErrorHandlingEnabled = b;
00504 }
00505
00506 bool KoDocument::isAutoErrorHandlingEnabled() const
00507 {
00508 return d->m_autoErrorHandlingEnabled;
00509 }
00510
00511 void KoDocument::slotAutoSave()
00512 {
00513 if ( isModified() && d->modifiedAfterAutosave )
00514 {
00515 connect( this, SIGNAL( sigProgress( int ) ), shells().current(), SLOT( slotProgress( int ) ) );
00516 emit sigStatusBarMessage( i18n("Autosaving...") );
00517 d->m_autosaving = true;
00518 bool ret = saveNativeFormat( autoSaveFile( m_file ) );
00519 setModified( true );
00520 if ( ret ) {
00521 d->modifiedAfterAutosave = false;
00522 d->m_autoSaveTimer.stop();
00523 }
00524 d->m_autosaving = false;
00525 emit sigClearStatusBarMessage();
00526 disconnect( this, SIGNAL( sigProgress( int ) ), shells().current(), SLOT( slotProgress( int ) ) );
00527 if ( !ret )
00528 emit sigStatusBarMessage( i18n("Error during autosave! Partition full?") );
00529 }
00530 }
00531
00532 KAction *KoDocument::action( const QDomElement &element ) const
00533 {
00534
00535 KAction* act = KParts::ReadWritePart::action( element );
00536 if ( act )
00537 return act;
00538
00539 Q_ASSERT( d->m_bSingleViewMode );
00540
00541 if ( !d->m_views.isEmpty() )
00542 return d->m_views.getFirst()->action( element );
00543 else
00544 return 0L;
00545 }
00546
00547 QDomDocument KoDocument::domDocument() const
00548 {
00549
00550
00551 Q_ASSERT( d->m_bSingleViewMode );
00552 if ( d->m_views.isEmpty() )
00553 return QDomDocument();
00554 else
00555 return d->m_views.getFirst()->domDocument();
00556 }
00557
00558 void KoDocument::setManager( KParts::PartManager *manager )
00559 {
00560 KParts::ReadWritePart::setManager( manager );
00561 if ( d->m_bSingleViewMode && d->m_views.count() == 1 )
00562 d->m_views.getFirst()->setPartManager( manager );
00563
00564 if ( manager )
00565 {
00566 QPtrListIterator<KoDocumentChild> it( d->m_children );
00567 for (; it.current(); ++it )
00568 if ( it.current()->document() )
00569 manager->addPart( it.current()->document(), false );
00570 }
00571 }
00572
00573 void KoDocument::setReadWrite( bool readwrite )
00574 {
00575 KParts::ReadWritePart::setReadWrite( readwrite );
00576
00577 QPtrListIterator<KoView> vIt( d->m_views );
00578 for (; vIt.current(); ++vIt )
00579 vIt.current()->updateReadWrite( readwrite );
00580
00581 QPtrListIterator<KoDocumentChild> dIt( d->m_children );
00582 for (; dIt.current(); ++dIt )
00583 if ( dIt.current()->document() )
00584 dIt.current()->document()->setReadWrite( readwrite );
00585
00586 setAutoSave( d->m_autoSaveDelay );
00587 }
00588
00589 void KoDocument::setAutoSave( int delay )
00590 {
00591 d->m_autoSaveDelay = delay;
00592 if ( isReadWrite() && !isEmbedded() && d->m_autoSaveDelay > 0 )
00593 d->m_autoSaveTimer.start( d->m_autoSaveDelay * 1000 );
00594 else
00595 d->m_autoSaveTimer.stop();
00596 }
00597
00598 void KoDocument::addView( KoView *view )
00599 {
00600 if ( !view )
00601 return;
00602
00603 d->m_views.append( view );
00604 view->updateReadWrite( isReadWrite() );
00605 }
00606
00607 void KoDocument::removeView( KoView *view )
00608 {
00609 d->m_views.removeRef( view );
00610 }
00611
00612 const QPtrList<KoView>& KoDocument::views() const
00613 {
00614 return d->m_views;
00615 }
00616
00617 int KoDocument::viewCount() const
00618 {
00619 return d->m_views.count();
00620 }
00621
00622 void KoDocument::insertChild( KoDocumentChild *child )
00623 {
00624 setModified( true );
00625
00626 d->m_children.append( child );
00627
00628 connect( child, SIGNAL( changed( KoChild * ) ),
00629 this, SLOT( slotChildChanged( KoChild * ) ) );
00630 connect( child, SIGNAL( destroyed() ),
00631 this, SLOT( slotChildDestroyed() ) );
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641 if ( manager() && !isSingleViewMode() && child->document() )
00642 manager()->addPart( child->document(), false );
00643 }
00644
00645 void KoDocument::slotChildChanged( KoChild *c )
00646 {
00647 assert( c->inherits( "KoDocumentChild" ) );
00648 emit childChanged( static_cast<KoDocumentChild *>( c ) );
00649 }
00650
00651 void KoDocument::slotChildDestroyed()
00652 {
00653 setModified( true );
00654
00655 const KoDocumentChild *child = static_cast<const KoDocumentChild *>( sender() );
00656 d->m_children.removeRef( child );
00657 }
00658
00659 const QPtrList<KoDocumentChild>& KoDocument::children() const
00660 {
00661 return d->m_children;
00662 }
00663
00664 KParts::Part *KoDocument::hitTest( QWidget *widget, const QPoint &globalPos )
00665 {
00666 QPtrListIterator<KoView> it( d->m_views );
00667 for (; it.current(); ++it )
00668 if ( (QWidget *)it.current() == widget )
00669 {
00670 QPoint canvasPos( it.current()->canvas()->mapFromGlobal( globalPos ) );
00671 canvasPos.rx() += it.current()->canvasXOffset();
00672 canvasPos.ry() += it.current()->canvasYOffset();
00673
00674 KParts::Part *part = it.current()->hitTest( canvasPos );
00675 if ( part )
00676 return part;
00677 }
00678
00679 return 0L;
00680 }
00681
00682 KoDocument *KoDocument::hitTest( const QPoint &pos, const QWMatrix &matrix )
00683 {
00684 QPtrListIterator<KoDocumentChild> it( d->m_children );
00685 for (; it.current(); ++it )
00686 {
00687 KoDocument *doc = it.current()->hitTest( pos, matrix );
00688 if ( doc )
00689 return doc;
00690 }
00691
00692 return this;
00693 }
00694
00695 KoDocumentChild *KoDocument::child( KoDocument *doc )
00696 {
00697 QPtrListIterator<KoDocumentChild> it( d->m_children );
00698 for (; it.current(); ++it )
00699 if ( it.current()->document() == doc )
00700 return it.current();
00701
00702 return 0L;
00703 }
00704
00705 KoDocumentInfo *KoDocument::documentInfo() const
00706 {
00707 return d->m_docInfo;
00708 }
00709
00710 void KoDocument::setViewBuildDocument( KoView *view, const QDomDocument &doc )
00711 {
00712 if ( d->m_views.find( view ) == -1 )
00713 return;
00714
00715 uint viewIdx = d->m_views.at();
00716
00717 if ( d->m_viewBuildDocuments.count() == viewIdx )
00718 d->m_viewBuildDocuments.append( doc );
00719 else if ( d->m_viewBuildDocuments.count() > viewIdx )
00720 d->m_viewBuildDocuments[ viewIdx ] = doc;
00721 }
00722
00723 QDomDocument KoDocument::viewBuildDocument( KoView *view )
00724 {
00725 QDomDocument res;
00726
00727 if ( d->m_views.find( view ) == -1 )
00728 return res;
00729
00730 uint viewIdx = d->m_views.at();
00731
00732 if ( viewIdx >= d->m_viewBuildDocuments.count() )
00733 return res;
00734
00735 res = d->m_viewBuildDocuments[ viewIdx ];
00736
00737
00738 d->m_viewBuildDocuments[ viewIdx ] = QDomDocument();
00739
00740 return res;
00741 }
00742
00743 void KoDocument::paintEverything( QPainter &painter, const QRect &rect, bool transparent, KoView *view, double zoomX, double zoomY )
00744 {
00745 paintContent( painter, rect, transparent, zoomX, zoomY );
00746 paintChildren( painter, rect, view, zoomX, zoomY );
00747 }
00748
00749 void KoDocument::paintChildren( QPainter &painter, const QRect &, KoView *view, double zoomX, double zoomY )
00750 {
00751 QPtrListIterator<KoDocumentChild> it( d->m_children );
00752 for (; it.current(); ++it )
00753 {
00754
00755 painter.save();
00756 paintChild( it.current(), painter, view, zoomX, zoomY );
00757 painter.restore();
00758 }
00759 }
00760
00761 void KoDocument::paintChild( KoDocumentChild *child, QPainter &painter, KoView *view, double zoomX, double zoomY )
00762 {
00763 if ( child->isDeleted() )
00764 return;
00765
00766
00767
00768 child->transform( painter );
00769 child->document()->paintEverything( painter, child->contentRect(), child->isTransparent(), view, zoomX, zoomY );
00770
00771 if ( view && view->partManager() )
00772 {
00773
00774 KParts::PartManager *manager = view->partManager();
00775
00776 painter.scale( 1.0 / child->xScaling(), 1.0 / child->yScaling() );
00777
00778 int w = int( (double)child->contentRect().width() * child->xScaling() );
00779 int h = int( (double)child->contentRect().height() * child->yScaling() );
00780 if ( ( manager->selectedPart() == (KParts::Part *)child->document() &&
00781 manager->selectedWidget() == (QWidget *)view ) ||
00782 ( manager->activePart() == (KParts::Part *)child->document() &&
00783 manager->activeWidget() == (QWidget *)view ) )
00784 {
00785
00786 painter.setClipping( FALSE );
00787
00788 painter.setPen( black );
00789 painter.fillRect( -5, -5, w + 10, 5, white );
00790 painter.fillRect( -5, h, w + 10, 5, white );
00791 painter.fillRect( -5, -5, 5, h + 10, white );
00792 painter.fillRect( w, -5, 5, h + 10, white );
00793 painter.fillRect( -5, -5, w + 10, 5, BDiagPattern );
00794 painter.fillRect( -5, h, w + 10, 5, BDiagPattern );
00795 painter.fillRect( -5, -5, 5, h + 10, BDiagPattern );
00796 painter.fillRect( w, -5, 5, h + 10, BDiagPattern );
00797
00798 if ( manager->selectedPart() == (KParts::Part *)child->document() &&
00799 manager->selectedWidget() == (QWidget *)view )
00800 {
00801 QColor color;
00802 if ( view->koDocument() == this )
00803 color = black;
00804 else
00805 color = gray;
00806 painter.fillRect( -5, -5, 5, 5, color );
00807 painter.fillRect( -5, h, 5, 5, color );
00808 painter.fillRect( w, h, 5, 5, color );
00809 painter.fillRect( w, -5, 5, 5, color );
00810 painter.fillRect( w / 2 - 3, -5, 5, 5, color );
00811 painter.fillRect( w / 2 - 3, h, 5, 5, color );
00812 painter.fillRect( -5, h / 2 - 3, 5, 5, color );
00813 painter.fillRect( w, h / 2 - 3, 5, 5, color );
00814 }
00815
00816 painter.setClipping( TRUE );
00817 }
00818 }
00819 }
00820
00821 bool KoDocument::isModified() const
00822 {
00823 if ( KParts::ReadWritePart::isModified() )
00824 {
00825
00826 return true;
00827 }
00828
00829 QPtrListIterator<KoDocumentChild> it = children();
00830 for (; it.current(); ++it )
00831 {
00832 KoDocument *doc = it.current()->document();
00833 if ( doc && !it.current()->isStoredExtern() && !it.current()->isDeleted() && doc->isModified() )
00834 return true;
00835 }
00836 return false;
00837 }
00838
00839 bool KoDocument::saveChildren( KoStore* _store )
00840 {
00841
00842 int i = 0;
00843 QPtrListIterator<KoDocumentChild> it( children() );
00844 for( ; it.current(); ++it ) {
00845 KoDocument* childDoc = it.current()->document();
00846 if (childDoc && !it.current()->isDeleted())
00847 {
00848 if ( !childDoc->isStoredExtern() )
00849 {
00850
00851 if ( !childDoc->saveToStore( _store, QString::number( i++ ) ) )
00852 return FALSE;
00853
00854 if (!isExporting ())
00855 childDoc->setModified( false );
00856 }
00857
00858 }
00859 }
00860 return true;
00861 }
00862
00863
00864
00865 bool KoDocument::saveChildrenOasis( KoStore* store, KoXmlWriter* manifestWriter )
00866 {
00867
00868 QPtrListIterator<KoDocumentChild> it( children() );
00869 for( ; it.current(); ++it ) {
00870 KoDocument* childDoc = it.current()->document();
00871 if (childDoc && !it.current()->isDeleted())
00872 {
00873 QString path;
00874 if ( !childDoc->isStoredExtern() )
00875 {
00876 if ( !it.current()->saveOasisToStore( store, manifestWriter ) )
00877 return false;
00878 if (!isExporting ())
00879 childDoc->setModified( false );
00880
00881
00882 assert( childDoc->url().protocol() == INTERNAL_PROTOCOL );
00883 path = store->currentDirectory();
00884 if ( !path.isEmpty() )
00885 path += '/';
00886 path += childDoc->url().path();
00887 if ( path.startsWith( "/" ) )
00888 path = path.mid( 1 );
00889 }
00890 else
00891 {
00892 kdDebug(30003)<<k_funcinfo<<" external (don't save) url:" << childDoc->url().url()<<endl;
00893 path = childDoc->url().url();
00894 }
00895
00896 if ( !path.endsWith( "/" ) )
00897 path += '/';
00898 QCString mimetype = childDoc->nativeOasisMimeType();
00899 if ( mimetype.isEmpty() )
00900 mimetype = childDoc->nativeFormatMimeType();
00901 manifestWriter->addManifestEntry( path, mimetype );
00902 }
00903 }
00904 return true;
00905 }
00906
00907 bool KoDocument::saveExternalChildren()
00908 {
00909 if ( d->m_doNotSaveExtDoc )
00910 {
00911
00912 d->m_doNotSaveExtDoc = false;
00913 return true;
00914 }
00915
00916
00917 KoDocument *doc;
00918 KoDocumentChild *ch;
00919 QPtrListIterator<KoDocumentChild> it = children();
00920 for (; (ch = it.current()); ++it )
00921 {
00922 if ( !ch->isDeleted() )
00923 {
00924 doc = ch->document();
00925 if ( doc && doc->isStoredExtern() && doc->isModified() )
00926 {
00927 kdDebug(30003)<<" save external doc='"<<url().url()<<"'"<<endl;
00928 doc->setDoNotSaveExtDoc();
00929 if ( !doc->save() )
00930 return false;
00931 }
00932
00933
00934 if ( !doc->saveExternalChildren() )
00935 return false;
00936 }
00937 }
00938 return true;
00939 }
00940
00941 bool KoDocument::saveNativeFormat( const QString & file )
00942 {
00943 d->lastErrorMessage = QString::null;
00944
00945
00946 KoStore::Backend backend = KoStore::Auto;
00947 if ( d->m_specialOutputFlag == SaveAsKOffice1dot1 )
00948 {
00949 kdDebug(30003) << "Saving as KOffice-1.1 format, using a tar.gz" << endl;
00950 backend = KoStore::Tar;
00952 }
00953 else if ( d->m_specialOutputFlag == SaveAsDirectoryStore )
00954 {
00955 backend = KoStore::Directory;
00956 kdDebug(30003) << "Saving as uncompressed XML, using directory store." << endl;
00957 }
00958
00959 kdDebug(30003) << "KoDocument::saveNativeFormat nativeFormatMimeType=" << nativeFormatMimeType() << endl;
00960
00961
00962 QCString mimeType = d->outputMimeType;
00963 QCString nativeOasisMime = nativeOasisMimeType();
00964 bool oasis = !mimeType.isEmpty() && ( mimeType == nativeOasisMime || mimeType == nativeOasisMime + "-template" );
00965
00966
00967 KoStore* store = KoStore::createStore( file, KoStore::Write, mimeType, backend );
00968 if ( store->bad() )
00969 {
00970 d->lastErrorMessage = i18n( "Could not create the file for saving" );
00971 delete store;
00972 return false;
00973 }
00974
00975 if ( oasis )
00976 {
00977 kdDebug(30003) << "Saving to OASIS format" << endl;
00978
00979 store->disallowNameExpansion();
00980 KoOasisStore oasisStore( store );
00981 KoXmlWriter* manifestWriter = oasisStore.manifestWriter( mimeType );
00982
00983 if ( !saveOasis( store, manifestWriter ) )
00984 {
00985 kdDebug(30003) << "saveOasis failed" << endl;
00986 delete store;
00987 return false;
00988 }
00989
00990
00991 if ( !saveChildrenOasis( store, manifestWriter ) )
00992 {
00993 kdDebug(30003) << "saveChildrenOasis failed" << endl;
00994 delete store;
00995 return false;
00996 }
00997
00998 if ( store->open( "meta.xml" ) )
00999 {
01000 if ( !d->m_docInfo->saveOasis( store ) || !store->close() ) {
01001 delete store;
01002 return false;
01003 }
01004 manifestWriter->addManifestEntry( "meta.xml", "text/xml" );
01005 }
01006 else
01007 {
01008 d->lastErrorMessage = i18n( "Not able to write '%1'. Partition full?" ).arg( "meta.xml" );
01009 delete store;
01010 return false;
01011 }
01012
01013 if ( store->open( "Thumbnails/thumbnail.png" ) )
01014 {
01015 if ( !saveOasisPreview( store, manifestWriter ) || !store->close() ) {
01016 d->lastErrorMessage = i18n( "Error while trying to write '%1'. Partition full?" ).arg( "Thumbnails/thumbnail.png" );
01017 delete store;
01018 return false;
01019 }
01020
01021 }
01022 else
01023 {
01024 d->lastErrorMessage = i18n( "Not able to write '%1'. Partition full?" ).arg( "Thumbnails/thumbnail.png" );
01025 delete store;
01026 return false;
01027 }
01028
01029
01030 if ( !oasisStore.closeManifestWriter() )
01031 {
01032 d->lastErrorMessage = i18n( "Error while trying to write '%1'. Partition full?" ).arg( "META-INF/manifest.xml" );
01033 delete store;
01034 return false;
01035 }
01036
01037 delete store;
01038 }
01039 else
01040 {
01041
01042 if ( !saveChildren( store ) && !oasis )
01043 {
01044 if ( d->lastErrorMessage.isEmpty() )
01045 d->lastErrorMessage = i18n( "Error while saving embedded documents" );
01046 delete store;
01047 return false;
01048 }
01049
01050 kdDebug(30003) << "Saving root" << endl;
01051 if ( store->open( "root" ) )
01052 {
01053 KoStoreDevice dev( store );
01054 if ( !saveToStream( &dev ) || !store->close() )
01055 {
01056 kdDebug(30003) << "saveToStream failed" << endl;
01057 delete store;
01058 return false;
01059 }
01060 }
01061 else
01062 {
01063 d->lastErrorMessage = i18n( "Not able to write '%1'. Partition full?" ).arg( "maindoc.xml" );
01064 delete store;
01065 return false;
01066 }
01067 if ( store->open( "documentinfo.xml" ) )
01068 {
01069 QDomDocument doc = d->m_docInfo->save();
01070 KoStoreDevice dev( store );
01071
01072 QCString s = doc.toCString();
01073 (void)dev.writeBlock( s.data(), s.size()-1 );
01074 (void)store->close();
01075 }
01076
01077 if ( store->open( "preview.png" ) )
01078 {
01079
01080 savePreview( store );
01081 (void)store->close();
01082 }
01083
01084 if ( !completeSaving( store ) )
01085 {
01086 delete store;
01087 return false;
01088 }
01089 kdDebug(30003) << "Saving done of url: " << url().url() << endl;
01090 delete store;
01091 }
01092 if ( !saveExternalChildren() )
01093 {
01094 return false;
01095 }
01096 return true;
01097 }
01098
01099 bool KoDocument::saveToStream( QIODevice * dev )
01100 {
01101 QDomDocument doc = saveXML();
01102
01103 QCString s = doc.toCString();
01104
01105
01106 int nwritten = dev->writeBlock( s.data(), s.size()-1 );
01107 if ( nwritten != (int)s.size()-1 )
01108 kdWarning(30003) << "KoDocument::saveToStream wrote " << nwritten << " - expected " << s.size()-1 << endl;
01109 return nwritten == (int)s.size()-1;
01110 }
01111
01112
01113 bool KoDocument::saveToStore( KoStore* _store, const QString & _path )
01114 {
01115 kdDebug(30003) << "Saving document to store " << _path << endl;
01116
01117
01118 if ( _path.startsWith( STORE_PROTOCOL ) )
01119 m_url = KURL( _path );
01120 else
01121 m_url = KURL( INTERNAL_PREFIX + _path );
01122
01123
01124 _store->pushDirectory();
01125 _store->enterDirectory( _path );
01126
01127
01128 if ( !saveChildren( _store ) )
01129 return false;
01130
01131
01132 if ( _store->open( "root" ) )
01133 {
01134 KoStoreDevice dev( _store );
01135 if ( !saveToStream( &dev ) )
01136 {
01137 _store->close();
01138 return false;
01139 }
01140 if ( !_store->close() )
01141 return false;
01142 }
01143
01144 if ( !completeSaving( _store ) )
01145 return false;
01146
01147
01148 _store->popDirectory();
01149
01150 kdDebug(30003) << "Saved document to store" << endl;
01151
01152 return true;
01153 }
01154
01155 bool KoDocument::saveOasisPreview( KoStore* store, KoXmlWriter* manifestWriter )
01156 {
01157 const QPixmap pix = generatePreview( QSize( 128, 128 ) );
01158 QImage preview ( pix.convertToImage().convertDepth( 32, Qt::ColorOnly ) );
01159 if ( !preview.hasAlphaBuffer() )
01160 {
01161 preview.setAlphaBuffer( true );
01162 }
01163
01164 KoStoreDevice io ( store );
01165 if ( !io.open( IO_WriteOnly ) )
01166 return false;
01167 if ( ! preview.save( &io, "PNG", 0 ) )
01168 return false;
01169 io.close();
01170 manifestWriter->addManifestEntry( "Thumbnails/", "" );
01171 manifestWriter->addManifestEntry( "Thumbnails/thumbnail.png", "" );
01172 return true;
01173 }
01174
01175 bool KoDocument::savePreview( KoStore* store )
01176 {
01177 QPixmap pix = generatePreview(QSize(256, 256));
01178
01179 const QImage preview ( pix.convertToImage().convertDepth( 8, Qt::AvoidDither | Qt::DiffuseDither) );
01180 KoStoreDevice io ( store );
01181 if ( !io.open( IO_WriteOnly ) )
01182 return false;
01183 if ( ! preview.save( &io, "PNG" ) )
01184 return false;
01185 io.close();
01186 return true;
01187 }
01188
01189 QPixmap KoDocument::generatePreview( const QSize& size )
01190 {
01191 double docWidth, docHeight;
01192 int pixmapSize = QMAX(size.width(), size.height());
01193
01194 if (m_pageLayout.ptWidth > 1.0) {
01195 docWidth = m_pageLayout.ptWidth / 72 * KoGlobal::dpiX();
01196 docHeight = m_pageLayout.ptHeight / 72 * KoGlobal::dpiY();
01197
01198 } else {
01199
01200 docWidth = 500.0;
01201 docHeight = 500.0;
01202 }
01203
01204 double ratio = docWidth / docHeight;
01205
01206 QPixmap pix;
01207 int previewWidth, previewHeight;
01208 if (ratio > 1.0)
01209 {
01210 previewWidth = (int) pixmapSize;
01211 previewHeight = (int) (pixmapSize / ratio);
01212 }
01213 else
01214 {
01215 previewWidth = (int) (pixmapSize * ratio);
01216 previewHeight = (int) pixmapSize;
01217 }
01218
01219 pix.resize((int)docWidth, (int)docHeight);
01220
01221 pix.fill( QColor( 245, 245, 245 ) );
01222
01223 QRect rc(0, 0, pix.width(), pix.height());
01224
01225 QPainter p;
01226 p.begin(&pix);
01227 paintEverything(p, rc, false);
01228 p.end();
01229
01230
01231 pix.convertFromImage(pix.convertToImage().smoothScale(previewWidth, previewHeight));
01232
01233 return pix;
01234 }
01235
01236 QString KoDocument::autoSaveFile( const QString & path ) const
01237 {
01238
01239 KMimeType::Ptr mime = KMimeType::mimeType( nativeFormatMimeType() );
01240 QString extension = mime->property( "X-KDE-NativeExtension" ).toString();
01241 if ( path.isEmpty() )
01242 {
01243
01244
01245
01246 QString ret = QDir::homeDirPath() + "/." + QString::fromLatin1(instance()->instanceName()) + ".autosave" + extension;
01247 return ret;
01248 }
01249 else
01250 {
01251 KURL url( path );
01252 Q_ASSERT( url.isLocalFile() );
01253 QString dir = url.directory(false);
01254 QString filename = url.fileName();
01255 return dir + "." + filename + ".autosave" + extension;
01256 }
01257 }
01258
01259 bool KoDocument::checkAutoSaveFile()
01260 {
01261 QString asf = autoSaveFile( QString::null );
01262
01263 if ( QFile::exists( asf ) )
01264 {
01265 QDateTime date = QFileInfo(asf).lastModified();
01266 QString dateStr = date.toString(Qt::LocalDate);
01267 int res = KMessageBox::warningYesNoCancel(
01268 0, i18n( "An autosaved file for an unnamed document exists in %1.\nThis file is dated %2\nDo you want to open it?" )
01269 .arg(asf, dateStr) );
01270 switch(res) {
01271 case KMessageBox::Yes : {
01272 KURL url;
01273 url.setPath( asf );
01274 bool ret = openURL( url );
01275 if ( ret )
01276 resetURL();
01277 return ret;
01278 }
01279 case KMessageBox::No :
01280 QFile::remove( asf );
01281 return false;
01282 default:
01283 return false;
01284 }
01285 }
01286 return false;
01287 }
01288
01289 bool KoDocument::import( const KURL & _url )
01290 {
01291 bool ret;
01292
01293 kdDebug (30003) << "KoDocument::import url=" << _url.url() << endl;
01294 d->m_isImporting = true;
01295
01296
01297 ret = openURL (_url);
01298
01299
01300
01301 if (ret)
01302 {
01303 kdDebug (30003) << "KoDocument::import success, resetting url" << endl;
01304 resetURL ();
01305 setTitleModified ();
01306 }
01307
01308 d->m_isImporting = false;
01309
01310 return ret;
01311 }
01312
01313 bool KoDocument::openURL( const KURL & _url )
01314 {
01315 kdDebug(30003) << "KoDocument::openURL url=" << _url.url() << endl;
01316 d->lastErrorMessage = QString::null;
01317
01318
01319 if ( !_url.isValid() )
01320 {
01321 d->lastErrorMessage = i18n( "Malformed URL\n%1" ).arg( _url.url() );
01322 return false;
01323 }
01324 if ( !closeURL() )
01325 return false;
01326
01327 KURL url( _url );
01328 bool autosaveOpened = false;
01329 d->m_bLoading = true;
01330 if ( url.isLocalFile() && d->m_shouldCheckAutoSaveFile )
01331 {
01332 QString file = url.path();
01333 QString asf = autoSaveFile( file );
01334 if ( QFile::exists( asf ) )
01335 {
01336
01337
01338 int res = KMessageBox::warningYesNoCancel( 0,
01339 i18n( "An autosaved file exists for this document.\nDo you want to open it instead?" ));
01340 switch(res) {
01341 case KMessageBox::Yes :
01342 url.setPath( asf );
01343 autosaveOpened = true;
01344 break;
01345 case KMessageBox::No :
01346 QFile::remove( asf );
01347 break;
01348 default:
01349 d->m_bLoading = false;
01350 return false;
01351 }
01352 }
01353 }
01354
01355 bool ret = KParts::ReadWritePart::openURL( url );
01356
01357 if ( autosaveOpened )
01358 resetURL();
01359 else
01360 {
01361
01362
01363
01364
01365 QPtrListIterator<KoMainWindow> it( d->m_shells );
01366 for (; it.current(); ++it )
01367 it.current()->addRecentURL( _url );
01368 }
01369 return ret;
01370 }
01371
01372 bool KoDocument::openFile()
01373 {
01374
01375 if ( !QFile::exists(m_file) )
01376 {
01377 QApplication::restoreOverrideCursor();
01378 if ( d->m_autoErrorHandlingEnabled )
01379
01380 KMessageBox::error(0L, i18n("The file %1 does not exist.").arg(m_file) );
01381 d->m_bLoading = false;
01382 return false;
01383 }
01384
01385 QApplication::setOverrideCursor( waitCursor );
01386
01387 if ( d->m_bSingleViewMode && !d->m_views.isEmpty() )
01388 {
01389
01390 KoView* v = d->m_views.first();
01391 removeView( v );
01392 delete v;
01393 Q_ASSERT( d->m_views.isEmpty() );
01394 }
01395
01396 d->m_specialOutputFlag = 0;
01397 QCString _native_format = nativeFormatMimeType();
01398
01399 KURL u;
01400 u.setPath( m_file );
01401 QString typeName = KMimeType::findByURL( u, 0, true )->name();
01402
01403
01404 if ( typeName == "application/x-trash" )
01405 {
01406 QString path = u.path();
01407 QStringList patterns = KMimeType::mimeType( typeName )->patterns();
01408
01409 for( QStringList::Iterator it = patterns.begin(); it != patterns.end(); ++it ) {
01410 QString ext = *it;
01411 if ( !ext.isEmpty() && ext[0] == '*' )
01412 {
01413 ext.remove(0, 1);
01414 if ( path.endsWith( ext ) ) {
01415 path.truncate( path.length() - ext.length() );
01416 break;
01417 }
01418 }
01419 }
01420 typeName = KMimeType::findByPath( path, 0, true )->name();
01421 }
01422
01423
01424 if ( u.fileName() == "maindoc.xml" || typeName == "inode/directory" )
01425 {
01426 typeName = _native_format;
01427 d->m_specialOutputFlag = SaveAsDirectoryStore;
01428 kdDebug(30003) << "KoDocument::openFile loading maindoc.xml, using directory store for " << m_file << endl;
01429 }
01430 kdDebug(30003) << "KoDocument::openFile " << m_file << " type:" << typeName << endl;
01431
01432 QString importedFile = m_file;
01433
01434 if ( typeName == KMimeType::defaultMimeType() ) {
01435 kdError(30003) << "No mimetype found for " << m_file << endl;
01436 QApplication::restoreOverrideCursor();
01437 if ( d->m_autoErrorHandlingEnabled )
01438 KMessageBox::error( 0L, i18n( "Could not open\n%1" ).arg( url().prettyURL( 0, KURL::StripFileProtocol ) ) );
01439 d->m_bLoading = false;
01440 return false;
01441 }
01442
01443 if ( !isNativeFormat( typeName.latin1() ) ) {
01444 if ( !d->filterManager )
01445 d->filterManager = new KoFilterManager( this );
01446 KoFilter::ConversionStatus status;
01447 importedFile = d->filterManager->import( m_file, status );
01448 if ( status != KoFilter::OK )
01449 {
01450 QApplication::restoreOverrideCursor();
01451 if ( status != KoFilter::UserCancelled &&
01452 status != KoFilter::BadConversionGraph &&
01453 d->m_autoErrorHandlingEnabled )
01454
01455 KMessageBox::error( 0L, i18n( "Could not open\n%1" ).arg( url().prettyURL( 0, KURL::StripFileProtocol ) ) );
01456
01457 d->m_bLoading = false;
01458 return false;
01459 }
01460 kdDebug(30003) << "KoDocument::openFile - importedFile '" << importedFile
01461 << "', status: " << static_cast<int>( status ) << endl;
01462 }
01463
01464 QApplication::restoreOverrideCursor();
01465
01466 bool ok = true;
01467
01468 if (!importedFile.isEmpty())
01469 {
01470
01471 if ( !loadNativeFormat( importedFile ) )
01472 {
01473 ok = false;
01474 if ( d->m_autoErrorHandlingEnabled )
01475 {
01476 showLoadingErrorDialog();
01477 }
01478 }
01479 }
01480
01481 if ( importedFile != m_file )
01482 {
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494 #if 0
01495 if ( isReadWrite() )
01496 resetURL();
01497 #endif
01498
01499
01500 if(!importedFile.isEmpty()) {
01501 QFile::remove( importedFile );
01502 }
01503 }
01504
01505 if ( ok && d->m_bSingleViewMode )
01506 {
01507
01508 KXMLGUIFactory* guiFactory = factory();
01509 if( guiFactory )
01510 guiFactory->removeClient( this );
01511
01512 KoView *view = createView( d->m_wrapperWidget );
01513 d->m_wrapperWidget->setKoView( view );
01514 view->show();
01515
01516
01517
01518 if ( guiFactory )
01519 guiFactory->addClient( this );
01520 }
01521
01522 if ( ok )
01523 {
01524 setMimeTypeAfterLoading( typeName );
01525 }
01526 d->m_bLoading = false;
01527 return ok;
01528 }
01529
01530
01531 void KoDocument::setMimeTypeAfterLoading( const QString& mimeType )
01532 {
01533 d->mimeType = mimeType.latin1();
01534
01535 d->outputMimeType = d->mimeType;
01536
01537 const bool needConfirm = !isNativeFormat( d->mimeType );
01538 setConfirmNonNativeSave( false, needConfirm );
01539 setConfirmNonNativeSave( true, needConfirm );
01540 }
01541
01542
01543 bool KoDocument::oldLoadAndParse(KoStore* store, const QString& filename, QDomDocument& doc)
01544 {
01545
01546
01547 if (!store->open(filename))
01548 {
01549 kdWarning(30003) << "Entry " << filename << " not found!" << endl;
01550 d->lastErrorMessage = i18n( "Could not find %1" ).arg( filename );
01551 return false;
01552 }
01553
01554 QString errorMsg;
01555 int errorLine, errorColumn;
01556 bool ok = doc.setContent( store->device(), &errorMsg, &errorLine, &errorColumn );
01557 if ( !ok )
01558 {
01559 kdError(30003) << "Parsing error in " << filename << "! Aborting!" << endl
01560 << " In line: " << errorLine << ", column: " << errorColumn << endl
01561 << " Error message: " << errorMsg << endl;
01562 d->lastErrorMessage = i18n( "Parsing error in %1 at line %2, column %3\nError message: %4" )
01563 .arg( filename ).arg( errorLine ).arg( errorColumn )
01564 .arg( i18n ( "QXml", errorMsg.utf8() ) );
01565 store->close();
01566 return false;
01567 }
01568 kdDebug(30003) << "File " << filename << " loaded and parsed" << endl;
01569 return true;
01570 }
01571
01572 bool KoDocument::loadNativeFormat( const QString & file )
01573 {
01574 QFileInfo fileInfo( file );
01575 if ( !fileInfo.exists() )
01576 {
01577 d->lastErrorMessage = i18n("The file %1 does not exist.").arg(file);
01578 return false;
01579 }
01580 if ( !fileInfo.isFile() )
01581 {
01582 d->lastErrorMessage = i18n( "%1 is not a file." ).arg(file);
01583 return false;
01584 }
01585
01586 QApplication::setOverrideCursor( waitCursor );
01587
01588 kdDebug(30003) << "KoDocument::loadNativeFormat( " << file << " )" << endl;
01589
01590 QFile in;
01591 bool isRawXML = false;
01592 if ( d->m_specialOutputFlag != SaveAsDirectoryStore )
01593 {
01594 in.setName(file);
01595 if ( !in.open( IO_ReadOnly ) )
01596 {
01597 QApplication::restoreOverrideCursor();
01598 d->lastErrorMessage = i18n( "Could not open the file for reading (check read permissions)." );
01599 return false;
01600 }
01601
01602
01603 char buf[5];
01604 if ( in.readBlock( buf, 4 ) < 4 )
01605 {
01606 QApplication::restoreOverrideCursor();
01607 in.close();
01608 d->lastErrorMessage = i18n( "Could not read the beginning of the file." );
01609 return false;
01610 }
01611
01612 isRawXML = (strncasecmp( buf, "<?xm", 4 ) == 0);
01613
01614 }
01615
01616 if ( isRawXML )
01617 {
01618 in.at(0);
01619 QString errorMsg;
01620 int errorLine;
01621 int errorColumn;
01622 QDomDocument doc;
01623 bool res;
01624 if ( doc.setContent( &in, &errorMsg, &errorLine, &errorColumn ) )
01625 {
01626 res = loadXML( &in, doc );
01627 if ( res )
01628 res = completeLoading( 0L );
01629 }
01630 else
01631 {
01632 kdError (30003) << "Parsing Error! Aborting! (in KoDocument::loadNativeFormat (QFile))" << endl
01633 << " Line: " << errorLine << " Column: " << errorColumn << endl
01634 << " Message: " << errorMsg << endl;
01635 d->lastErrorMessage = i18n( "parsing error in the main document at line %1, column %2\nError message: %3" )
01636 .arg( errorLine ).arg( errorColumn ).arg( i18n ( errorMsg.utf8() ) );
01637 res=false;
01638 }
01639
01640 QApplication::restoreOverrideCursor();
01641 in.close();
01642 m_bEmpty = false;
01643 return res;
01644 } else
01645 {
01646 in.close();
01647
01648 return loadNativeFormatFromStore( file );
01649 }
01650 }
01651
01652 bool KoDocument::loadNativeFormatFromStore( const QString& file )
01653 {
01654 KoStore::Backend backend = (d->m_specialOutputFlag == SaveAsDirectoryStore) ? KoStore::Directory : KoStore::Auto;
01655 KoStore * store = KoStore::createStore( file, KoStore::Read, "", backend );
01656
01657 if ( store->bad() )
01658 {
01659 d->lastErrorMessage = i18n( "Not a valid KOffice file: %1" ).arg( file );
01660 delete store;
01661 QApplication::restoreOverrideCursor();
01662 return false;
01663 }
01664
01665 bool oasis = true;
01666
01667 if ( store->hasFile( "content.xml" ) )
01668 {
01669 store->disallowNameExpansion();
01670
01671 KoOasisStore oasisStore( store );
01672
01673
01674 if ( !loadOasisFromStore( store ) ) {
01675 delete store;
01676 QApplication::restoreOverrideCursor();
01677 return false;
01678 }
01679
01680 } else if ( store->hasFile( "root" ) )
01681 {
01682 oasis = false;
01683
01684 QDomDocument doc;
01685 bool ok = oldLoadAndParse( store, "root", doc );
01686 if ( ok )
01687 ok = loadXML( store->device(), doc );
01688 if ( !ok )
01689 {
01690 delete store;
01691 QApplication::restoreOverrideCursor();
01692 return false;
01693 }
01694 store->close();
01695
01696 if ( !loadChildren( store ) )
01697 {
01698 kdError(30003) << "ERROR: Could not load children" << endl;
01699
01700 }
01701
01702 } else
01703 {
01704 kdError(30003) << "ERROR: No maindoc.xml" << endl;
01705 d->lastErrorMessage = i18n( "Invalid document: no file 'maindoc.xml'." );
01706 delete store;
01707 QApplication::restoreOverrideCursor();
01708 return false;
01709 }
01710
01711 if ( oasis && store->hasFile( "meta.xml" ) ) {
01712 QDomDocument metaDoc;
01713 KoOasisStore oasisStore( store );
01714 if ( oasisStore.loadAndParse( "meta.xml", metaDoc, d->lastErrorMessage ) ) {
01715 d->m_docInfo->loadOasis( metaDoc );
01716 }
01717 }
01718 else if ( !oasis && store->hasFile( "documentinfo.xml" ) )
01719 {
01720 QDomDocument doc;
01721 if ( oldLoadAndParse( store, "documentinfo.xml", doc ) ) {
01722 store->close();
01723 d->m_docInfo->load( doc );
01724 }
01725 }
01726 else
01727 {
01728
01729 delete d->m_docInfo;
01730 d->m_docInfo = new KoDocumentInfo( this, "document info" );
01731 }
01732
01733 bool res = completeLoading( store );
01734 delete store;
01735 QApplication::restoreOverrideCursor();
01736 m_bEmpty = false;
01737 return res;
01738 }
01739
01740
01741 bool KoDocument::loadFromStore( KoStore* _store, const QString& url )
01742 {
01743 if ( _store->open( url ) )
01744 {
01745 QDomDocument doc;
01746 doc.setContent( _store->device() );
01747 if ( !loadXML( _store->device(), doc ) )
01748 {
01749 _store->close();
01750 return false;
01751 }
01752 _store->close();
01753 } else {
01754 kdWarning() << "couldn't open " << url << endl;
01755 }
01756
01757 _store->pushDirectory();
01758
01759 if ( url.startsWith( STORE_PROTOCOL ) ) {
01760 m_url = KURL( url );
01761 } else {
01762 m_url = KURL( INTERNAL_PREFIX + url );
01763 _store->enterDirectory( url );
01764 }
01765
01766 if ( !loadChildren( _store ) )
01767 {
01768 kdError(30003) << "ERROR: Could not load children" << endl;
01769 #if 0
01770 return false;
01771 #endif
01772 }
01773
01774 bool result = completeLoading( _store );
01775
01776
01777 _store->popDirectory();
01778
01779 return result;
01780 }
01781
01782 bool KoDocument::loadOasisFromStore( KoStore* store )
01783 {
01784 KoOasisStyles oasisStyles;
01785 QDomDocument contentDoc;
01786 QDomDocument settingsDoc;
01787 KoOasisStore oasisStore( store );
01788 bool ok = oasisStore.loadAndParse( "content.xml", contentDoc, d->lastErrorMessage );
01789 if ( !ok )
01790 return false;
01791
01792 QDomDocument stylesDoc;
01793 (void)oasisStore.loadAndParse( "styles.xml", stylesDoc, d->lastErrorMessage );
01794
01795 oasisStyles.createStyleMap( stylesDoc );
01796
01797 oasisStyles.createStyleMap( contentDoc );
01798
01799
01800
01801
01802
01803
01804
01805
01806 if ( store->hasFile( "settings.xml" ) ) {
01807 (void)oasisStore.loadAndParse( "settings.xml", settingsDoc, d->lastErrorMessage );
01808 }
01809 if ( !loadOasis( contentDoc, oasisStyles, settingsDoc, store ) )
01810 return false;
01811
01812 return true;
01813 }
01814
01815 bool KoDocument::isInOperation() const
01816 {
01817 return d->m_numOperations > 0;
01818 }
01819
01820 void KoDocument::emitBeginOperation()
01821 {
01822
01823
01824 if (!isInOperation())
01825 emit sigBeginOperation();
01826 d->m_numOperations++;
01827 }
01828
01829 void KoDocument::emitEndOperation()
01830 {
01831 d->m_numOperations--;
01832
01833
01834 if (d->m_numOperations == 0)
01835 emit sigEndOperation();
01836 else if (d->m_numOperations < 0)
01837
01838 d->m_numOperations = 0;
01839 }
01840
01841
01842 bool KoDocument::isStoredExtern() const
01843 {
01844 return !storeInternal() && hasExternURL();
01845 }
01846
01847 void KoDocument::setModified( bool mod )
01848 {
01849 if ( isAutosaving() )
01850 return;
01851
01852
01853
01854
01855 if ( mod && !d->modifiedAfterAutosave ) {
01856
01857 setAutoSave( d->m_autoSaveDelay );
01858 }
01859 d->modifiedAfterAutosave = mod;
01860
01861 if ( mod == isModified() )
01862 return;
01863
01864 KParts::ReadWritePart::setModified( mod );
01865
01866 if ( mod ) {
01867 m_bEmpty = FALSE;
01868 } else {
01869
01870 QPtrListIterator<KoDocumentChild> it = children();
01871 for (; it.current(); ++it )
01872 {
01873 KoDocument *doc = it.current()->document();
01874 if ( doc && !it.current()->isStoredExtern() && !it.current()->isDeleted() && doc->isModified() )
01875 doc->setModified( false );
01876 }
01877 }
01878
01879
01880 setTitleModified();
01881 }
01882
01883 void KoDocument::setDoNotSaveExtDoc( bool on )
01884 {
01885 d->m_doNotSaveExtDoc = on;
01886 }
01887
01888 int KoDocument::queryCloseDia()
01889 {
01890
01891
01892 QString name;
01893 if ( documentInfo() )
01894 {
01895 name = documentInfo()->title();
01896 }
01897 if ( name.isEmpty() )
01898 name = url().fileName();
01899
01900 if ( name.isEmpty() )
01901 name = i18n( "Untitled" );
01902
01903 int res = KMessageBox::warningYesNoCancel( 0L,
01904 i18n( "<p>The document <b>'%1'</b> has been modified.</p><p>Do you want to save it?</p>" ).arg(name));
01905
01906 switch(res)
01907 {
01908 case KMessageBox::Yes :
01909 setDoNotSaveExtDoc();
01910 save();
01911 setModified( false );
01912 break;
01913 case KMessageBox::No :
01914 removeAutoSaveFiles();
01915 setModified( false );
01916 break;
01917 default :
01918 return res;
01919 }
01920 return res;
01921 }
01922
01923 int KoDocument::queryCloseExternalChildren()
01924 {
01925
01926 setDoNotSaveExtDoc(false);
01927 QPtrListIterator<KoDocumentChild> it( children() );
01928 for (; it.current(); ++it )
01929 {
01930 if ( !it.current()->isDeleted() )
01931 {
01932 KoDocument *doc = it.current()->document();
01933 if ( doc )
01934 {
01935 bool foo = doc->isStoredExtern();
01936 kdDebug(36001) << "========== isStoredExtern() returned "
01937 << foo << " ==========" << endl;
01938
01939 if ( foo )
01940 {
01941 {
01942 kdDebug(30003)<<k_funcinfo<<" found modified child: "<<doc->url().url()<<" extern="<<doc->isStoredExtern()<<endl;
01943 if ( doc->queryCloseDia() == KMessageBox::Cancel )
01944 return KMessageBox::Cancel;
01945 }
01946 }
01947 if ( doc->queryCloseExternalChildren() == KMessageBox::Cancel )
01948 return KMessageBox::Cancel;
01949 }
01950 }
01951 }
01952 return KMessageBox::Ok;
01953 }
01954
01955 void KoDocument::setTitleModified( const QString caption, bool mod )
01956 {
01957
01958 KoDocument *doc = dynamic_cast<KoDocument *>( parent() );
01959 if ( doc )
01960 {
01961 doc->setTitleModified( caption, mod );
01962 return;
01963 }
01964
01965 QPtrListIterator<KoMainWindow> it( d->m_shells );
01966 for (; it.current(); ++it )
01967 {
01968 it.current()->updateCaption();
01969 it.current()->updateReloadFileAction(this);
01970 it.current()->updateVersionsFileAction(this);
01971 }
01972 }
01973
01974 void KoDocument::setTitleModified()
01975 {
01976
01977 KoDocument *doc = dynamic_cast<KoDocument *>( parent() );
01978 QString caption;
01979 if ( (url().isEmpty() || isStoredExtern()) && d->m_current )
01980 {
01981
01982 if ( documentInfo() )
01983 {
01984 KoDocumentInfoPage * page = documentInfo()->page( QString::fromLatin1("about") );
01985 if (page)
01986 caption = static_cast<KoDocumentInfoAbout *>(page)->title();
01987 }
01988 if ( caption.isEmpty() )
01989 caption = url().prettyURL( 0, KURL::StripFileProtocol );
01990
01991
01992 if ( doc )
01993 {
01994 doc->setTitleModified( caption, isModified() );
01995 return;
01996 }
01997 else
01998 {
01999
02000 setTitleModified( caption, isModified() );
02001 return;
02002 }
02003 }
02004 if ( doc )
02005 {
02006
02007 doc->setTitleModified();
02008 }
02009 }
02010
02011 bool KoDocument::loadChildren( KoStore* )
02012 {
02013 return true;
02014 }
02015
02016 bool KoDocument::completeLoading( KoStore* )
02017 {
02018 return true;
02019 }
02020
02021 bool KoDocument::completeSaving( KoStore* )
02022 {
02023 return true;
02024 }
02025
02026 QDomDocument KoDocument::createDomDocument( const QString& tagName, const QString& version ) const
02027 {
02028 return createDomDocument( instance()->instanceName(), tagName, version );
02029 }
02030
02031
02032 QDomDocument KoDocument::createDomDocument( const QString& appName, const QString& tagName, const QString& version )
02033 {
02034 QDomImplementation impl;
02035 QString url = QString("http://www.koffice.org/DTD/%1-%1.dtd").arg(appName).arg(version);
02036 QDomDocumentType dtype = impl.createDocumentType( tagName,
02037 QString("-//KDE//DTD %1 %1//EN").arg(appName).arg(version),
02038 url );
02039
02040 QString namespaceURN = QString("http://www.koffice.org/DTD/%1").arg(appName);
02041 QDomDocument doc = impl.createDocument( namespaceURN, tagName, dtype );
02042 doc.insertBefore( doc.createProcessingInstruction( "xml", "version=\"1.0\" encoding=\"UTF-8\"" ), doc.documentElement() );
02043 return doc;
02044 }
02045
02046 KoXmlWriter* KoDocument::createOasisXmlWriter( QIODevice* dev, const char* rootElementName )
02047 {
02048 KoXmlWriter* writer = new KoXmlWriter( dev );
02049 writer->startDocument( rootElementName );
02050 writer->startElement( rootElementName );
02051 writer->addAttribute( "xmlns:office", KoXmlNS::office );
02052 writer->addAttribute( "xmlns:meta", KoXmlNS::meta );
02053
02054 if ( qstrcmp( rootElementName, "office:document-meta" ) != 0 ) {
02055 writer->addAttribute( "xmlns:config", KoXmlNS::config );
02056 writer->addAttribute( "xmlns:text", KoXmlNS::text );
02057 writer->addAttribute( "xmlns:table", KoXmlNS::table );
02058 writer->addAttribute( "xmlns:draw", KoXmlNS::draw );
02059 writer->addAttribute( "xmlns:presentation", KoXmlNS::presentation );
02060 writer->addAttribute( "xmlns:dr3d", KoXmlNS::dr3d );
02061 writer->addAttribute( "xmlns:chart", KoXmlNS::chart );
02062 writer->addAttribute( "xmlns:form", KoXmlNS::form );
02063 writer->addAttribute( "xmlns:script", KoXmlNS::script );
02064 writer->addAttribute( "xmlns:style", KoXmlNS::style );
02065 writer->addAttribute( "xmlns:number", KoXmlNS::number );
02066 writer->addAttribute( "xmlns:math", KoXmlNS::math );
02067 writer->addAttribute( "xmlns:svg", KoXmlNS::svg );
02068 writer->addAttribute( "xmlns:fo", KoXmlNS::fo );
02069 writer->addAttribute( "xmlns:koffice", KoXmlNS::koffice );
02070 }
02071
02072
02073 writer->addAttribute( "xmlns:dc", KoXmlNS::dc );
02074 writer->addAttribute( "xmlns:xlink", KoXmlNS::xlink );
02075 return writer;
02076 }
02077
02078 QDomDocument KoDocument::saveXML()
02079 {
02080 kdError(30003) << "KoDocument::saveXML not implemented" << endl;
02081 d->lastErrorMessage = i18n( "Internal error: saveXML not implemented" );
02082 return QDomDocument();
02083 }
02084
02085 KService::Ptr KoDocument::nativeService()
02086 {
02087 if ( !m_nativeService )
02088 m_nativeService = readNativeService( instance() );
02089
02090 return m_nativeService;
02091 }
02092
02093 QCString KoDocument::nativeFormatMimeType() const
02094 {
02095 KService::Ptr service = const_cast<KoDocument *>(this)->nativeService();
02096 if ( !service )
02097 return QCString();
02098 return service->property( "X-KDE-NativeMimeType" ).toString().latin1();
02099 }
02100
02101 QCString KoDocument::nativeOasisMimeType() const
02102 {
02103 KService::Ptr service = const_cast<KoDocument *>(this)->nativeService();
02104 if ( !service )
02105 return QCString();
02106 return service->property( "X-KDE-NativeOasisMimeType" ).toString().latin1();
02107 }
02108
02109
02110
02111 KService::Ptr KoDocument::readNativeService( KInstance *instance )
02112 {
02113 QString instname = instance ? instance->instanceName() : kapp->instanceName();
02114
02115
02116 QString servicepartname = instname + "part.desktop";
02117 KService::Ptr service = KService::serviceByDesktopPath( servicepartname );
02118 if ( service )
02119 kdDebug(30003) << servicepartname << " found." << endl;
02120 if ( !service )
02121 {
02122
02123
02124
02125
02126
02127 service = KService::serviceByDesktopPath( QString::fromLatin1("Office/%1.desktop").arg(instname) );
02128 }
02129 if ( !service )
02130 service = KService::serviceByDesktopName( instname );
02131
02132 return service;
02133 }
02134
02135 QCString KoDocument::readNativeFormatMimeType( KInstance *instance )
02136 {
02137 KService::Ptr service = readNativeService( instance );
02138 if ( !service )
02139 return QCString();
02140
02141 if ( service->property( "X-KDE-NativeMimeType" ).toString().isEmpty() )
02142 {
02143
02144 if ( KServiceType::serviceType( "KOfficePart" ) == 0L )
02145 kdError(30003) << "The serviceType KOfficePart is missing. Check that you have a kofficepart.desktop file in the share/servicetypes directory." << endl;
02146 else {
02147 QString instname = instance ? instance->instanceName() : kapp->instanceName();
02148 if ( instname != "koshell" )
02149 kdWarning(30003) << service->desktopEntryPath() << ": no X-KDE-NativeMimeType entry!" << endl;
02150 }
02151 }
02152
02153 return service->property( "X-KDE-NativeMimeType" ).toString().latin1();
02154 }
02155
02156 QStringList KoDocument::readExtraNativeMimeTypes( KInstance *instance )
02157 {
02158 KService::Ptr service = readNativeService( instance );
02159 if ( !service )
02160 return QStringList();
02161 return service->property( "X-KDE-ExtraNativeMimeTypes" ).toStringList();
02162 }
02163
02164 void KoDocument::setupXmlReader( QXmlSimpleReader& reader, bool namespaceProcessing )
02165 {
02166 if ( namespaceProcessing )
02167 {
02168 reader.setFeature( "http://xml.org/sax/features/namespaces", TRUE );
02169 reader.setFeature( "http://xml.org/sax/features/namespace-prefixes", FALSE );
02170 }
02171 else
02172 {
02173 reader.setFeature( "http://xml.org/sax/features/namespaces", FALSE );
02174 reader.setFeature( "http://xml.org/sax/features/namespace-prefixes", TRUE );
02175 }
02176 reader.setFeature( "http://trolltech.com/xml/features/report-whitespace-only-CharData", TRUE );
02177 }
02178
02179
02180 bool KoDocument::isNativeFormat( const QCString& mimetype ) const
02181 {
02182 if ( mimetype == nativeFormatMimeType() )
02183 return true;
02184 return extraNativeMimeTypes().contains( mimetype );
02185 }
02186
02187 QStringList KoDocument::extraNativeMimeTypes() const
02188 {
02189 QStringList lst;
02190
02191
02192
02193 KService::Ptr service = const_cast<KoDocument *>(this)->nativeService();
02194 if ( !service )
02195 return lst;
02196 return service->property( "X-KDE-ExtraNativeMimeTypes" ).toStringList();
02197 }
02198
02199 int KoDocument::supportedSpecialFormats() const
02200 {
02201
02202
02203 return SaveAsDirectoryStore;
02204 }
02205
02206 void KoDocument::addShell( KoMainWindow *shell )
02207 {
02208 if ( d->m_shells.findRef( shell ) == -1 )
02209 {
02210
02211 d->m_shells.append( shell );
02212 }
02213 }
02214
02215 void KoDocument::removeShell( KoMainWindow *shell )
02216 {
02217
02218 d->m_shells.removeRef( shell );
02219 }
02220
02221 const QPtrList<KoMainWindow>& KoDocument::shells() const
02222 {
02223 return d->m_shells;
02224 }
02225
02226 int KoDocument::shellCount() const
02227 {
02228 return d->m_shells.count();
02229 }
02230
02231 DCOPObject * KoDocument::dcopObject()
02232 {
02233 if ( !d->m_dcopObject )
02234 d->m_dcopObject = new KoDocumentIface( this );
02235 return d->m_dcopObject;
02236 }
02237
02238 QCString KoDocument::dcopObjectId() const
02239 {
02240 return const_cast<KoDocument *>(this)->dcopObject()->objId();
02241 }
02242
02243 void KoDocument::setErrorMessage( const QString& errMsg )
02244 {
02245 d->lastErrorMessage = errMsg;
02246 }
02247
02248 QString KoDocument::errorMessage() const
02249 {
02250 return d->lastErrorMessage;
02251 }
02252
02253 void KoDocument::showSavingErrorDialog()
02254 {
02255 if ( d->lastErrorMessage.isEmpty() )
02256 {
02257 KMessageBox::error( 0L, i18n( "Could not save\n%1" ).arg( m_file ) );
02258 }
02259 else if ( d->lastErrorMessage != "USER_CANCELED" )
02260 {
02261 KMessageBox::error( 0L, i18n( "Could not save %1\nReason: %2" ).arg( m_file, d->lastErrorMessage ) );
02262 }
02263 }
02264
02265 void KoDocument::showLoadingErrorDialog()
02266 {
02267 if ( d->lastErrorMessage.isEmpty() )
02268 {
02269 KMessageBox::error( 0L, i18n( "Could not open\n%1" ).arg( url().prettyURL( 0, KURL::StripFileProtocol ) ) );
02270 }
02271 else if ( d->lastErrorMessage != "USER_CANCELED" )
02272 {
02273 KMessageBox::error( 0L, i18n( "Could not open %1\nReason: %2" ).arg( url().prettyURL( 0, KURL::StripFileProtocol ), d->lastErrorMessage ) );
02274 }
02275 }
02276
02277 bool KoDocument::isAutosaving() const
02278 {
02279 return d->m_autosaving;
02280 }
02281
02282 bool KoDocument::isLoading() const
02283 {
02284 return d->m_bLoading;
02285 }
02286
02287 void KoDocument::removeAutoSaveFiles()
02288 {
02289
02290 QString asf = autoSaveFile( m_file );
02291 if ( QFile::exists( asf ) )
02292 QFile::remove( asf );
02293 asf = autoSaveFile( QString::null );
02294 if ( QFile::exists( asf ) )
02295 QFile::remove( asf );
02296 }
02297
02298 void KoDocument::setBackupFile( bool _b )
02299 {
02300 d->m_backupFile = _b;
02301 }
02302
02303 bool KoDocument::backupFile()const
02304 {
02305 return d->m_backupFile;
02306 }
02307
02308
02309 void KoDocument::setBackupPath( const QString & _path)
02310 {
02311 d->m_backupPath = _path;
02312 }
02313
02314 QString KoDocument::backupPath()const
02315 {
02316 return d->m_backupPath;
02317 }
02318
02319 void KoDocument::setCurrent( bool on )
02320 {
02321
02322 KoDocument *doc = dynamic_cast<KoDocument *>( parent() );
02323 if ( doc )
02324 {
02325 if ( !isStoredExtern() )
02326 {
02327
02328 doc->setCurrent( true );
02329 return;
02330 }
02331
02332 d->m_current = on;
02333 if ( !on )
02334 {
02335 doc->setCurrent( true );
02336 return;
02337 }
02338 doc->forceCurrent( false );
02339 }
02340 else
02341 d->m_current = on;
02342
02343 setTitleModified();
02344 }
02345
02346 void KoDocument::forceCurrent( bool on )
02347 {
02348
02349 d->m_current = on;
02350 KoDocument *doc = dynamic_cast<KoDocument *>( parent() );
02351 if ( doc )
02352 {
02353 doc->forceCurrent( false );
02354 }
02355 }
02356
02357 bool KoDocument::isCurrent() const
02358 {
02359 return d->m_current;
02360 }
02361
02362 bool KoDocument::storeInternal() const
02363 {
02364 return d->m_storeInternal;
02365 }
02366
02367 void KoDocument::setStoreInternal( bool i )
02368 {
02369 d->m_storeInternal = i;
02370
02371 }
02372
02373 bool KoDocument::hasExternURL() const
02374 {
02375 return !url().protocol().isEmpty() && url().protocol() != STORE_PROTOCOL && url().protocol() != INTERNAL_PROTOCOL;
02376 }
02377
02378 void KoDocument::slotStarted( KIO::Job* job )
02379 {
02380 if ( job )
02381 {
02382 job->setWindow( d->m_shells.current() );
02383 }
02384 }
02385
02386 #include "koDocument_p.moc"
02387 #include "koDocument.moc"