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