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