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