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 }
00286 ~ReadOnlyPartPrivate()
00287 {
00288 }
00289
00290 KIO::FileCopyJob * m_job;
00291 KIO::FileCopyJob * m_uploadJob;
00292 bool m_showProgressInfo : 1;
00293 bool m_saveOk : 1;
00294 bool m_waitForSave : 1;
00295 };
00296
00297 }
00298
00299 ReadOnlyPart::ReadOnlyPart( QObject *parent, const char *name )
00300 : Part( parent, name ), m_bTemp( false )
00301 {
00302 d = new ReadOnlyPartPrivate;
00303 }
00304
00305 ReadOnlyPart::~ReadOnlyPart()
00306 {
00307 ReadOnlyPart::closeURL();
00308 delete d;
00309 }
00310
00311 void ReadOnlyPart::setProgressInfoEnabled( bool show )
00312 {
00313 d->m_showProgressInfo = show;
00314 }
00315
00316 bool ReadOnlyPart::isProgressInfoEnabled() const
00317 {
00318 return d->m_showProgressInfo;
00319 }
00320
00321 #ifndef KDE_NO_COMPAT
00322 void ReadOnlyPart::showProgressInfo( bool show )
00323 {
00324 d->m_showProgressInfo = show;
00325 }
00326 #endif
00327
00328 bool ReadOnlyPart::openURL( const KURL &url )
00329 {
00330 if ( !url.isValid() )
00331 return false;
00332 if ( !closeURL() )
00333 return false;
00334 m_url = url;
00335 if ( m_url.isLocalFile() )
00336 {
00337 emit started( 0 );
00338 m_file = m_url.path();
00339 bool ret = openFile();
00340 if (ret)
00341 {
00342 emit completed();
00343 emit setWindowCaption( m_url.prettyURL() );
00344 };
00345 return ret;
00346 }
00347 else
00348 {
00349 m_bTemp = true;
00350
00351 QString fileName = url.fileName();
00352 QFileInfo fileInfo(fileName);
00353 QString ext = fileInfo.extension();
00354 QString extension;
00355 if ( !ext.isEmpty() && url.query().isNull() )
00356 extension = "."+ext;
00357 KTempFile tempFile( QString::null, extension );
00358 m_file = tempFile.name();
00359
00360 KURL destURL;
00361 destURL.setPath( m_file );
00362 d->m_job = KIO::file_copy( m_url, destURL, 0600, true, false, d->m_showProgressInfo );
00363 d->m_job->setWindow( widget() ? widget()->topLevelWidget() : 0 );
00364 emit started( d->m_job );
00365 connect( d->m_job, SIGNAL( result( KIO::Job * ) ), this, SLOT( slotJobFinished ( KIO::Job * ) ) );
00366 return true;
00367 }
00368 }
00369
00370 void ReadOnlyPart::abortLoad()
00371 {
00372 if ( d->m_job )
00373 {
00374
00375 d->m_job->kill();
00376 d->m_job = 0;
00377 }
00378 }
00379
00380 bool ReadOnlyPart::closeURL()
00381 {
00382 abortLoad();
00383
00384 if ( m_bTemp )
00385 {
00386 unlink( QFile::encodeName(m_file) );
00387 m_bTemp = false;
00388 }
00389
00390
00391
00392 return true;
00393 }
00394
00395 void ReadOnlyPart::slotJobFinished( KIO::Job * job )
00396 {
00397 kdDebug(1000) << "ReadOnlyPart::slotJobFinished" << endl;
00398 assert( job == d->m_job );
00399 d->m_job = 0;
00400 if (job->error())
00401 emit canceled( job->errorString() );
00402 else
00403 {
00404 if ( openFile() )
00405 emit setWindowCaption( m_url.prettyURL() );
00406 emit completed();
00407 }
00408 }
00409
00410 void ReadOnlyPart::guiActivateEvent( GUIActivateEvent * event )
00411 {
00412 if (event->activated())
00413 {
00414 if (!m_url.isEmpty())
00415 {
00416 kdDebug(1000) << "ReadOnlyPart::guiActivateEvent -> " << m_url.prettyURL() << endl;
00417 emit setWindowCaption( m_url.prettyURL() );
00418 } else emit setWindowCaption( "" );
00419 }
00420 }
00421
00422 bool ReadOnlyPart::openStream( const QString& mimeType, const KURL& url )
00423 {
00424 if ( !closeURL() )
00425 return false;
00426 m_url = url;
00427 return doOpenStream( mimeType );
00428 }
00429
00430 bool ReadOnlyPart::writeStream( const QByteArray& data )
00431 {
00432 return doWriteStream( data );
00433 }
00434
00435 bool ReadOnlyPart::closeStream()
00436 {
00437 return doCloseStream();
00438 }
00439
00441
00442 ReadWritePart::ReadWritePart( QObject *parent, const char *name )
00443 : ReadOnlyPart( parent, name ), m_bModified( false ), m_bClosing( false )
00444 {
00445 m_bReadWrite = true;
00446 }
00447
00448 ReadWritePart::~ReadWritePart()
00449 {
00450
00451
00452
00453
00454 }
00455
00456 void ReadWritePart::setReadWrite( bool readwrite )
00457 {
00458
00459 m_bReadWrite = readwrite;
00460 }
00461
00462 void ReadWritePart::setModified( bool modified )
00463 {
00464 kdDebug(1000) << "ReadWritePart::setModified( " << (modified ? "true" : "false") << ")" << endl;
00465 if ( !m_bReadWrite && modified )
00466 {
00467 kdError(1000) << "Can't set a read-only document to 'modified' !" << endl;
00468 return;
00469 }
00470 m_bModified = modified;
00471 }
00472
00473 void ReadWritePart::setModified()
00474 {
00475 setModified( true );
00476 }
00477
00478 bool ReadWritePart::queryClose()
00479 {
00480 if ( !isReadWrite() || !isModified() )
00481 return true;
00482
00483 QString docName = url().fileName();
00484 if (docName.isEmpty()) docName = i18n( "Untitled" );
00485
00486 int res = KMessageBox::warningYesNoCancel( widget(),
00487 i18n( "The document \"%1\" has been modified.\n"
00488 "Do you want to save it?" ).arg( docName ),
00489 i18n( "Save Document?" ), KStdGuiItem::save(), KStdGuiItem::discard() );
00490
00491 bool abortClose=false;
00492 bool handled=false;
00493
00494 switch(res) {
00495 case KMessageBox::Yes :
00496 sigQueryClose(&handled,&abortClose);
00497 if (!handled)
00498 {
00499 if (m_url.isEmpty())
00500 {
00501 KURL url = KFileDialog::getSaveURL();
00502 if (url.isEmpty())
00503 return false;
00504
00505 saveAs( url );
00506 }
00507 else
00508 {
00509 save();
00510 }
00511 } else if (abortClose) return false;
00512 return waitSaveComplete();
00513 case KMessageBox::No :
00514 return true;
00515 default :
00516 return false;
00517 }
00518 }
00519
00520 bool ReadWritePart::closeURL()
00521 {
00522 abortLoad();
00523 if ( isReadWrite() && isModified() )
00524 {
00525 if (!queryClose())
00526 return false;
00527 }
00528
00529 return ReadOnlyPart::closeURL();
00530 }
00531
00532 bool ReadWritePart::closeURL( bool promptToSave )
00533 {
00534 return promptToSave ? closeURL() : ReadOnlyPart::closeURL();
00535 }
00536
00537 bool ReadWritePart::save()
00538 {
00539 d->m_saveOk = false;
00540 if( saveFile() )
00541 return saveToURL();
00542 return false;
00543 }
00544
00545 bool ReadWritePart::saveAs( const KURL & kurl )
00546 {
00547 if (!kurl.isValid())
00548 {
00549 kdError(1000) << "saveAs: Malformed URL" << kurl.url() << endl;
00550 return false;
00551 }
00552 m_url = kurl;
00553
00554 if ( m_url.isLocalFile() )
00555 {
00556 if ( m_bTemp )
00557 {
00558 unlink( QFile::encodeName(m_file) );
00559 m_bTemp = false;
00560 }
00561 m_file = m_url.path();
00562 }
00563 else
00564 {
00565
00566 if ( m_file.isEmpty() || !m_bTemp )
00567 {
00568 KTempFile tempFile;
00569 m_file = tempFile.name();
00570 m_bTemp = true;
00571 }
00572
00573 }
00574 emit setWindowCaption( m_url.prettyURL() );
00575 return save();
00576 }
00577
00578 bool ReadWritePart::saveToURL()
00579 {
00580 if ( m_url.isLocalFile() )
00581 {
00582 setModified( false );
00583 emit completed();
00584
00585 assert( !m_bTemp );
00586 d->m_saveOk = true;
00587 return true;
00588 }
00589 else
00590 {
00591 if (d->m_uploadJob)
00592 {
00593 unlink(QFile::encodeName(d->m_uploadJob->srcURL().path()));
00594 d->m_uploadJob->kill();
00595 d->m_uploadJob = 0;
00596 }
00597 KTempFile tempFile;
00598 QString uploadFile = tempFile.name();
00599 tempFile.unlink();
00600
00601 if (::link(QFile::encodeName(m_file), QFile::encodeName(uploadFile)) != 0)
00602 {
00603
00604 return false;
00605 }
00606 d->m_uploadJob = KIO::file_move( uploadFile, m_url, -1, true );
00607 d->m_uploadJob->setWindow( widget() ? widget()->topLevelWidget() : 0 );
00608 connect( d->m_uploadJob, SIGNAL( result( KIO::Job * ) ), this, SLOT( slotUploadFinished (KIO::Job *) ) );
00609 return true;
00610 }
00611 }
00612
00613 void ReadWritePart::slotUploadFinished( KIO::Job * )
00614 {
00615 if (d->m_uploadJob->error())
00616 {
00617 unlink(QFile::encodeName(d->m_uploadJob->srcURL().path()));
00618 QString error = d->m_uploadJob->errorString();
00619 d->m_uploadJob = 0;
00620 emit canceled( error );
00621 }
00622 else
00623 {
00624 d->m_uploadJob = 0;
00625 setModified( false );
00626 emit completed();
00627 d->m_saveOk = true;
00628 }
00629 if (d->m_waitForSave)
00630 {
00631 qApp->exit_loop();
00632 }
00633 }
00634
00635
00636 void qt_enter_modal( QWidget *widget );
00637 void qt_leave_modal( QWidget *widget );
00638
00639 bool ReadWritePart::waitSaveComplete()
00640 {
00641 if (!d->m_uploadJob)
00642 return d->m_saveOk;
00643
00644 d->m_waitForSave = true;
00645
00646 QWidget dummy(0,0,WType_Dialog | WShowModal);
00647 dummy.setFocusPolicy( QWidget::NoFocus );
00648 qt_enter_modal(&dummy);
00649 qApp->enter_loop();
00650 qt_leave_modal(&dummy);
00651
00652 d->m_waitForSave = false;
00653
00654 return d->m_saveOk;
00655 }
00656
00657 #include "part.moc"
00658
00659