part.cpp Source File (kparts Library)

| # kparts Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Source Files

# part.cpp

    00001 /* This file is part of the KDE project
    00002    Copyright (C) 1999 Simon Hausmann <hausmann@kde.org>
    00003              (C) 1999 David Faure <faure@kde.org>
    00004
    00005    This library is free software; you can redistribute it and/or
    00006    modify it under the terms of the GNU Library General Public
    00007    License as published by the Free Software Foundation; either
    00008    version 2 of the License, or (at your option) any later version.
    00009
    00010    This library is distributed in the hope that it will be useful,
    00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
    00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00013    Library General Public License for more details.
    00014
    00015    You should have received a copy of the GNU Library General Public License
    00016    along with this library; see the file COPYING.LIB.  If not, write to
    00017    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00018    Boston, MA 02111-1307, USA.
    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   // install 'instancename'data resource type
    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     // We need to disconnect first, to avoid calling it !
    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 ); // otherwise we get two connects
    00195   m_widget = widget;
    00196   connect( m_widget, SIGNAL( destroyed() ),
    00197            this, SLOT( slotWidgetDestroyed() ) );
    00198
    00199   // Tell the actionCollection() which widget its
    00200   //  action shortcuts should be connected to.
    00201   actionCollection()->setWidget( widget );
    00202
    00203   // Since KParts objects are XML-based, shortcuts should
    00204   //  be connected to the widget when the XML settings
    00205   //  are processed, rather than on KAction construction.
    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     // Use same extension as remote file. This is important for mimetype-determination (e.g. koffice)
    00342     QString fileName = url.fileName();
    00343     QFileInfo fileInfo(fileName);
    00344     QString ext = fileInfo.extension();
    00345     QString extension;
    00346     if ( !ext.isEmpty() && url.query().isNull() ) // not if the URL has a query, e.g. cgi.pl?something
    00347         extension = "."+ext; // keep the '.'
    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     //kdDebug(1000) << "Aborting job " << d->m_job << endl;
    00365     d->m_job->kill();
    00366     d->m_job = 0;
    00367   }
    00368 }
    00369
    00370 bool ReadOnlyPart::closeURL()
    00371 {
    00372   abortLoad(); //just in case
    00373
    00374   if ( m_bTemp )
    00375   {
    00376     unlink( QFile::encodeName(m_file) );
    00377     m_bTemp = false;
    00378   }
    00379   // It always succeeds for a read-only part,
    00380   // but the return value exists for reimplementations
    00381   // (e.g. pressing cancel for a modified read-write part)
    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   // parent destructor will delete temp file
    00440   // we can't call our own closeURL() here, because
    00441   // "cancel" wouldn't cancel anything. We have to assume
    00442   // the app called closeURL() before destroying us.
    00443 }
    00444
    00445 void ReadWritePart::setReadWrite( bool readwrite )
    00446 {
    00447   // Perhaps we should check isModified here and issue a warning if true
    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 : // case KMessageBox::Cancel :
    00491       return false;
    00492     }
    00493 }
    00494
    00495 bool ReadWritePart::closeURL()
    00496 {
    00497   abortLoad(); //just in case
    00498   if ( isReadWrite() && isModified() )
    00499   {
    00500     if (!queryClose())
    00501        return false;
    00502   }
    00503   // Not modified => ok and delete temp file.
    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; // Store where to upload in saveToURL
    00527   // Local file
    00528   if ( m_url.isLocalFile() )
    00529   {
    00530     if ( m_bTemp ) // get rid of a possible temp file first
    00531     {              // (happens if previous url was remote)
    00532       unlink( QFile::encodeName(m_file) );
    00533       m_bTemp = false;
    00534     }
    00535     m_file = m_url.path();
    00536   }
    00537   else
    00538   { // Remote file
    00539     // We haven't saved yet, or we did but locally - provide a temp file
    00540     if ( m_file.isEmpty() || !m_bTemp )
    00541     {
    00542       KTempFile tempFile;
    00543       m_file = tempFile.name();
    00544       m_bTemp = true;
    00545     }
    00546     // otherwise, we already had a temp file
    00547   }
    00548   emit setWindowCaption( m_url.prettyURL() );
    00549   return save(); // Save local file and upload local file
    00550 }
    00551
    00552 bool ReadWritePart::saveToURL()
    00553 {
    00554   if ( m_url.isLocalFile() )
    00555   {
    00556     setModified( false );
    00557     emit completed();
    00558     // if m_url is a local file there won't be a temp file -> nothing to remove
    00559     assert( !m_bTemp );
    00560     return true; // Nothing to do
    00561   }
    00562   else
    00563   {
    00564     KTempFile tempFile;
    00565     QString uploadFile = tempFile.name();
    00566     tempFile.unlink();
    00567     // Create hardlink
    00568     if (::link(QFile::encodeName(m_file), QFile::encodeName(uploadFile)) != 0)
    00569     {
    00570        // Uh oh, some error happened.
    00571        return false;
    00572     }
    00573     KIO::Job * job = KIO::file_move( uploadFile, m_url, -1, true /*overwrite*/ );
    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 // vim:sw=2:ts=8:et

This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 13:26:50 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001