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