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