00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <kparts/part.h>
00022 #include <kparts/event.h>
00023 #include <kparts/plugin.h>
00024 #include <kparts/mainwindow.h>
00025 #include <kparts/partmanager.h>
00026
00027 #include <qapplication.h>
00028 #include <qfile.h>
00029 #include <qpoint.h>
00030 #include <qpointarray.h>
00031 #include <qpainter.h>
00032 #include <qtextstream.h>
00033 #include <qfileinfo.h>
00034
00035 #include <kinstance.h>
00036 #include <klocale.h>
00037 #include <ktempfile.h>
00038 #include <kmessagebox.h>
00039 #include <kio/job.h>
00040 #include <kstandarddirs.h>
00041 #include <kfiledialog.h>
00042
00043 #include <stdio.h>
00044 #include <unistd.h>
00045 #include <assert.h>
00046 #include <kdebug.h>
00047
00048 template class QPtrList<KXMLGUIClient>;
00049
00050 using namespace KParts;
00051
00052 namespace KParts
00053 {
00054
00055 class PartBasePrivate
00056 {
00057 public:
00058 PartBasePrivate()
00059 {
00060 m_pluginLoadingMode = PartBase::LoadPlugins;
00061 }
00062 ~PartBasePrivate()
00063 {
00064 }
00065 PartBase::PluginLoadingMode m_pluginLoadingMode;
00066 };
00067
00068 class PartPrivate
00069 {
00070 public:
00071 PartPrivate()
00072 {
00073 m_bSelectable = true;
00074 }
00075 ~PartPrivate()
00076 {
00077 }
00078
00079 bool m_bSelectable;
00080 };
00081 }
00082
00083 PartBase::PartBase()
00084 {
00085 d = new PartBasePrivate;
00086 m_obj = 0L;
00087 }
00088
00089 PartBase::~PartBase()
00090 {
00091 delete d;
00092 }
00093
00094 void PartBase::setPartObject( QObject *obj )
00095 {
00096 m_obj = obj;
00097 }
00098
00099 QObject *PartBase::partObject() const
00100 {
00101 return m_obj;
00102 }
00103
00104 void PartBase::setInstance( KInstance *inst )
00105 {
00106 setInstance( inst, true );
00107 }
00108
00109 void PartBase::setInstance( KInstance *inst, bool bLoadPlugins )
00110 {
00111 KXMLGUIClient::setInstance( inst );
00112 KGlobal::locale()->insertCatalogue( inst->instanceName() );
00113
00114 KGlobal::dirs()->addResourceType( inst->instanceName() + "data",
00115 KStandardDirs::kde_default( "data" )
00116 + QString::fromLatin1( inst->instanceName() ) + '/' );
00117 if ( bLoadPlugins )
00118 loadPlugins( m_obj, this, instance() );
00119 }
00120
00121 void PartBase::loadPlugins( QObject *parent, KXMLGUIClient *parentGUIClient, KInstance *instance )
00122 {
00123 if( d->m_pluginLoadingMode != DoNotLoadPlugins )
00124 Plugin::loadPlugins( parent, parentGUIClient, instance, d->m_pluginLoadingMode == LoadPlugins );
00125 }
00126
00127 void PartBase::setPluginLoadingMode( PluginLoadingMode loadingMode )
00128 {
00129 d->m_pluginLoadingMode = loadingMode;
00130 }
00131
00132 Part::Part( QObject *parent, const char* name )
00133 : QObject( parent, name )
00134 {
00135 d = new PartPrivate;
00136 m_widget = 0L;
00137 m_manager = 0L;
00138 PartBase::setPartObject( this );
00139 }
00140
00141 Part::~Part()
00142 {
00143 kdDebug(1000) << "Part::~Part " << this << endl;
00144
00145 if ( m_widget )
00146 {
00147
00148 disconnect( m_widget, SIGNAL( destroyed() ),
00149 this, SLOT( slotWidgetDestroyed() ) );
00150 }
00151
00152 if ( m_manager )
00153 m_manager->removePart(this);
00154
00155 if ( m_widget )
00156 {
00157 kdDebug(1000) << "deleting widget " << m_widget << " " << m_widget->name() << endl;
00158 delete (QWidget*) m_widget;
00159 }
00160
00161 delete d;
00162 }
00163
00164 void Part::embed( QWidget * parentWidget )
00165 {
00166 if ( widget() )
00167 widget()->reparent( parentWidget, 0, QPoint( 0, 0 ), true );
00168 }
00169
00170 QWidget *Part::widget()
00171 {
00172 return m_widget;
00173 }
00174
00175 void Part::setManager( PartManager *manager )
00176 {
00177 m_manager = manager;
00178 }
00179
00180 PartManager *Part::manager() const
00181 {
00182 return m_manager;
00183 }
00184
00185 Part *Part::hitTest( QWidget *widget, const QPoint & )
00186 {
00187 if ( (QWidget *)m_widget != widget )
00188 return 0L;
00189
00190 return this;
00191 }
00192
00193 void Part::setWidget( QWidget *widget )
00194 {
00195 assert ( !m_widget );
00196 m_widget = widget;
00197 connect( m_widget, SIGNAL( destroyed() ),
00198 this, SLOT( slotWidgetDestroyed() ) );
00199
00200
00201
00202 actionCollection()->setWidget( widget );
00203
00204
00205
00206
00207 actionCollection()->setAutoConnectShortcuts( false );
00208 }
00209
00210 void Part::setSelectable( bool selectable )
00211 {
00212 d->m_bSelectable = selectable;
00213 }
00214
00215 bool Part::isSelectable() const
00216 {
00217 return d->m_bSelectable;
00218 }
00219
00220 void Part::customEvent( QCustomEvent *event )
00221 {
00222 if ( PartActivateEvent::test( event ) )
00223 {
00224 partActivateEvent( (PartActivateEvent *)event );
00225 return;
00226 }
00227
00228 if ( PartSelectEvent::test( event ) )
00229 {
00230 partSelectEvent( (PartSelectEvent *)event );
00231 return;
00232 }
00233
00234 if ( GUIActivateEvent::test( event ) )
00235 {
00236 guiActivateEvent( (GUIActivateEvent *)event );
00237 return;
00238 }
00239
00240 QObject::customEvent( event );
00241 }
00242
00243 void Part::partActivateEvent( PartActivateEvent * )
00244 {
00245 }
00246
00247 void Part::partSelectEvent( PartSelectEvent * )
00248 {
00249 }
00250
00251 void Part::guiActivateEvent( GUIActivateEvent * )
00252 {
00253 }
00254
00255 QWidget *Part::hostContainer( const QString &containerName )
00256 {
00257 if ( !factory() )
00258 return 0L;
00259
00260 return factory()->container( containerName, this );
00261 }
00262
00263 void Part::slotWidgetDestroyed()
00264 {
00265 kdDebug(1000) << "KPart::slotWidgetDestroyed(), deleting part " << name() << endl;
00266 m_widget = 0;
00267 delete this;
00268 }
00269
00271
00272 namespace KParts
00273 {
00274
00275 class ReadOnlyPartPrivate
00276 {
00277 public:
00278 ReadOnlyPartPrivate()
00279 {
00280 m_job = 0L;
00281 m_uploadJob = 0L;
00282 m_showProgressInfo = true;
00283 m_saveOk = false;
00284 m_waitForSave = false;
00285 m_duringSaveAs = false;
00286 }
00287 ~ReadOnlyPartPrivate()
00288 {
00289 }
00290
00291 KIO::FileCopyJob * m_job;
00292 KIO::FileCopyJob * m_uploadJob;
00293 KURL m_originalURL;
00294 bool m_showProgressInfo : 1;
00295 bool m_saveOk : 1;
00296 bool m_waitForSave : 1;
00297 bool m_duringSaveAs : 1;
00298 };
00299
00300 }
00301
00302 ReadOnlyPart::ReadOnlyPart( QObject *parent, const char *name )
00303 : Part( parent, name ), m_bTemp( false )
00304 {
00305 d = new ReadOnlyPartPrivate;
00306 }
00307
00308 ReadOnlyPart::~ReadOnlyPart()
00309 {
00310 ReadOnlyPart::closeURL();
00311 delete d;
00312 }
00313
00314 void ReadOnlyPart::setProgressInfoEnabled( bool show )
00315 {
00316 d->m_showProgressInfo = show;
00317 }
00318
00319 bool ReadOnlyPart::isProgressInfoEnabled() const
00320 {
00321 return d->m_showProgressInfo;
00322 }
00323
00324 #ifndef KDE_NO_COMPAT
00325 void ReadOnlyPart::showProgressInfo( bool show )
00326 {
00327 d->m_showProgressInfo = show;
00328 }
00329 #endif
00330
00331 bool ReadOnlyPart::openURL( const KURL &url )
00332 {
00333 if ( !url.isValid() )
00334 return false;
00335 if ( !closeURL() )
00336 return false;
00337 m_url = url;
00338 if ( m_url.isLocalFile() )
00339 {
00340 emit started( 0 );
00341 m_file = m_url.path();
00342 bool ret = openFile();
00343 if (ret)
00344 {
00345 emit completed();
00346 emit setWindowCaption( m_url.prettyURL() );
00347 };
00348 return ret;
00349 }
00350 else
00351 {
00352 m_bTemp = true;
00353
00354 QString fileName = url.fileName();
00355 QFileInfo fileInfo(fileName);
00356 QString ext = fileInfo.extension();
00357 QString extension;
00358 if ( !ext.isEmpty() && url.query().isNull() )
00359 extension = "."+ext;
00360 KTempFile tempFile( QString::null, extension );
00361 m_file = tempFile.name();
00362
00363 KURL destURL;
00364 destURL.setPath( m_file );
00365 d->m_job = KIO::file_copy( m_url, destURL, 0600, true, false, d->m_showProgressInfo );
00366 d->m_job->setWindow( widget() ? widget()->topLevelWidget() : 0 );
00367 emit started( d->m_job );
00368 connect( d->m_job, SIGNAL( result( KIO::Job * ) ), this, SLOT( slotJobFinished ( KIO::Job * ) ) );
00369 return true;
00370 }
00371 }
00372
00373 void ReadOnlyPart::abortLoad()
00374 {
00375 if ( d->m_job )
00376 {
00377
00378 d->m_job->kill();
00379 d->m_job = 0;
00380 }
00381 }
00382
00383 bool ReadOnlyPart::closeURL()
00384 {
00385 abortLoad();
00386
00387 if ( m_bTemp )
00388 {
00389 unlink( QFile::encodeName(m_file) );
00390 m_bTemp = false;
00391 }
00392
00393
00394
00395 return true;
00396 }
00397
00398 void ReadOnlyPart::slotJobFinished( KIO::Job * job )
00399 {
00400 kdDebug(1000) << "ReadOnlyPart::slotJobFinished" << endl;
00401 assert( job == d->m_job );
00402 d->m_job = 0;
00403 if (job->error())
00404 emit canceled( job->errorString() );
00405 else
00406 {
00407 if ( openFile() )
00408 emit setWindowCaption( m_url.prettyURL() );
00409 emit completed();
00410 }
00411 }
00412
00413 void ReadOnlyPart::guiActivateEvent( GUIActivateEvent * event )
00414 {
00415 if (event->activated())
00416 {
00417 if (!m_url.isEmpty())
00418 {
00419 kdDebug(1000) << "ReadOnlyPart::guiActivateEvent -> " << m_url.prettyURL() << endl;
00420 emit setWindowCaption( m_url.prettyURL() );
00421 } else emit setWindowCaption( "" );
00422 }
00423 }
00424
00425 bool ReadOnlyPart::openStream( const QString& mimeType, const KURL& url )
00426 {
00427 if ( !closeURL() )
00428 return false;
00429 m_url = url;
00430 return doOpenStream( mimeType );
00431 }
00432
00433 bool ReadOnlyPart::writeStream( const QByteArray& data )
00434 {
00435 return doWriteStream( data );
00436 }
00437
00438 bool ReadOnlyPart::closeStream()
00439 {
00440 return doCloseStream();
00441 }
00442
00444
00445 ReadWritePart::ReadWritePart( QObject *parent, const char *name )
00446 : ReadOnlyPart( parent, name ), m_bModified( false ), m_bClosing( false )
00447 {
00448 m_bReadWrite = true;
00449 }
00450
00451 ReadWritePart::~ReadWritePart()
00452 {
00453
00454
00455
00456
00457 }
00458
00459 void ReadWritePart::setReadWrite( bool readwrite )
00460 {
00461
00462 m_bReadWrite = readwrite;
00463 }
00464
00465 void ReadWritePart::setModified( bool modified )
00466 {
00467 kdDebug(1000) << "ReadWritePart::setModified( " << (modified ? "true" : "false") << ")" << endl;
00468 if ( !m_bReadWrite && modified )
00469 {
00470 kdError(1000) << "Can't set a read-only document to 'modified' !" << endl;
00471 return;
00472 }
00473 m_bModified = modified;
00474 }
00475
00476 void ReadWritePart::setModified()
00477 {
00478 setModified( true );
00479 }
00480
00481 bool ReadWritePart::queryClose()
00482 {
00483 if ( !isReadWrite() || !isModified() )
00484 return true;
00485
00486 QString docName = url().fileName();
00487 if (docName.isEmpty()) docName = i18n( "Untitled" );
00488
00489 int res = KMessageBox::warningYesNoCancel( widget(),
00490 i18n( "The document \"%1\" has been modified.\n"
00491 "Do you want to save it?" ).arg( docName ),
00492 i18n( "Save Document?" ), KStdGuiItem::save(), KStdGuiItem::discard() );
00493
00494 bool abortClose=false;
00495 bool handled=false;
00496
00497 switch(res) {
00498 case KMessageBox::Yes :
00499 sigQueryClose(&handled,&abortClose);
00500 if (!handled)
00501 {
00502 if (m_url.isEmpty())
00503 {
00504 KURL url = KFileDialog::getSaveURL();
00505 if (url.isEmpty())
00506 return false;
00507
00508 saveAs( url );
00509 }
00510 else
00511 {
00512 save();
00513 }
00514 } else if (abortClose) return false;
00515 return waitSaveComplete();
00516 case KMessageBox::No :
00517 return true;
00518 default :
00519 return false;
00520 }
00521 }
00522
00523 bool ReadWritePart::closeURL()
00524 {
00525 abortLoad();
00526 if ( isReadWrite() && isModified() )
00527 {
00528 if (!queryClose())
00529 return false;
00530 }
00531
00532 return ReadOnlyPart::closeURL();
00533 }
00534
00535 bool ReadWritePart::closeURL( bool promptToSave )
00536 {
00537 return promptToSave ? closeURL() : ReadOnlyPart::closeURL();
00538 }
00539
00540 bool ReadWritePart::save()
00541 {
00542 d->m_saveOk = false;
00543 if( saveFile() )
00544 return saveToURL();
00545 return false;
00546 }
00547
00548 bool ReadWritePart::saveAs( const KURL & kurl )
00549 {
00550 if (!kurl.isValid())
00551 {
00552 kdError(1000) << "saveAs: Malformed URL" << kurl.url() << endl;
00553 return false;
00554 }
00555 d->m_duringSaveAs = true;
00556 d->m_originalURL = m_url;
00557 m_url = kurl;
00558
00559 if ( m_url.isLocalFile() )
00560 {
00561 if ( m_bTemp )
00562 {
00563 unlink( QFile::encodeName(m_file) );
00564 m_bTemp = false;
00565 }
00566 m_file = m_url.path();
00567 }
00568 else
00569 {
00570
00571 if ( m_file.isEmpty() || !m_bTemp )
00572 {
00573 KTempFile tempFile;
00574 m_file = tempFile.name();
00575 m_bTemp = true;
00576 }
00577
00578 }
00579 bool result = save();
00580 if (result)
00581 emit setWindowCaption( m_url.prettyURL() );
00582 else
00583 {
00584 m_url = d->m_originalURL;
00585 d->m_duringSaveAs = false;
00586 d->m_originalURL = KURL();
00587 }
00588
00589 return result;
00590 }
00591
00592 bool ReadWritePart::saveToURL()
00593 {
00594 if ( m_url.isLocalFile() )
00595 {
00596 setModified( false );
00597 emit completed();
00598
00599 assert( !m_bTemp );
00600 d->m_saveOk = true;
00601 d->m_duringSaveAs = false;
00602 d->m_originalURL = KURL();
00603 return true;
00604 }
00605 else
00606 {
00607 if (d->m_uploadJob)
00608 {
00609 unlink(QFile::encodeName(d->m_uploadJob->srcURL().path()));
00610 d->m_uploadJob->kill();
00611 d->m_uploadJob = 0;
00612 }
00613 KTempFile tempFile;
00614 QString uploadFile = tempFile.name();
00615 tempFile.unlink();
00616
00617 if (::link(QFile::encodeName(m_file), QFile::encodeName(uploadFile)) != 0)
00618 {
00619
00620 return false;
00621 }
00622 d->m_uploadJob = KIO::file_move( uploadFile, m_url, -1, true );
00623 d->m_uploadJob->setWindow( widget() ? widget()->topLevelWidget() : 0 );
00624 connect( d->m_uploadJob, SIGNAL( result( KIO::Job * ) ), this, SLOT( slotUploadFinished (KIO::Job *) ) );
00625 return true;
00626 }
00627 }
00628
00629 void ReadWritePart::slotUploadFinished( KIO::Job * )
00630 {
00631 if (d->m_uploadJob->error())
00632 {
00633 unlink(QFile::encodeName(d->m_uploadJob->srcURL().path()));
00634 QString error = d->m_uploadJob->errorString();
00635 d->m_uploadJob = 0;
00636 if (d->m_duringSaveAs)
00637 m_url = d->m_originalURL;
00638 emit canceled( error );
00639 }
00640 else
00641 {
00642 d->m_uploadJob = 0;
00643 setModified( false );
00644 emit completed();
00645 d->m_saveOk = true;
00646 }
00647 d->m_duringSaveAs = false;
00648 d->m_originalURL = KURL();
00649 if (d->m_waitForSave)
00650 {
00651 qApp->exit_loop();
00652 }
00653 }
00654
00655
00656 void qt_enter_modal( QWidget *widget );
00657 void qt_leave_modal( QWidget *widget );
00658
00659 bool ReadWritePart::waitSaveComplete()
00660 {
00661 if (!d->m_uploadJob)
00662 return d->m_saveOk;
00663
00664 d->m_waitForSave = true;
00665
00666 QWidget dummy(0,0,WType_Dialog | WShowModal);
00667 dummy.setFocusPolicy( QWidget::NoFocus );
00668 qt_enter_modal(&dummy);
00669 qApp->enter_loop();
00670 qt_leave_modal(&dummy);
00671
00672 d->m_waitForSave = false;
00673
00674 return d->m_saveOk;
00675 }
00676
00677 #include "part.moc"
00678
00679