• Skip to content
  • Skip to link menu
KDE 4.3 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KParts

part.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE project
00002    Copyright (C) 1999 Simon Hausmann <hausmann@kde.org>
00003              (C) 1999-2005 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., 51 Franklin Street, Fifth Floor,
00018    Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include "part.h"
00022 #include "event.h"
00023 #include "plugin.h"
00024 #include "mainwindow.h"
00025 #include "partmanager.h"
00026 #include "browserextension.h"
00027 
00028 #include <QtGui/QApplication>
00029 #include <QtCore/QFile>
00030 #include <QtCore/QFileInfo>
00031 #include <QtGui/QPainter>
00032 #include <QtCore/QPoint>
00033 
00034 #include <kdirnotify.h>
00035 #include <kfiledialog.h>
00036 #include <kcomponentdata.h>
00037 #include <kio/job.h>
00038 #include <kio/jobuidelegate.h>
00039 #include <klocale.h>
00040 #include <kmessagebox.h>
00041 #include <kstandarddirs.h>
00042 #include <ktemporaryfile.h>
00043 #include <kxmlguifactory.h>
00044 
00045 #include <stdio.h>
00046 #include <unistd.h>
00047 #include <assert.h>
00048 #include <kdebug.h>
00049 #include <kiconloader.h>
00050 
00051 using namespace KParts;
00052 
00053 namespace KParts
00054 {
00055 
00056 class PartBasePrivate
00057 {
00058 public:
00059     Q_DECLARE_PUBLIC(PartBase)
00060 
00061     PartBasePrivate(PartBase *q): q_ptr(q)
00062     {
00063         m_pluginLoadingMode = PartBase::LoadPlugins;
00064         m_pluginInterfaceVersion = 0;
00065         m_obj = 0;
00066     }
00067 
00068     virtual ~PartBasePrivate()
00069     {
00070     }
00071 
00072     PartBase *q_ptr;
00073     PartBase::PluginLoadingMode m_pluginLoadingMode;
00074     int m_pluginInterfaceVersion;
00075     QObject *m_obj;
00076 };
00077 
00078 class PartPrivate: public PartBasePrivate
00079 {
00080 public:
00081     Q_DECLARE_PUBLIC(Part)
00082 
00083     PartPrivate(Part *q)
00084         : PartBasePrivate(q),
00085           m_iconLoader(0),
00086           m_bSelectable(true),
00087           m_autoDeleteWidget(true),
00088           m_autoDeletePart(true),
00089           m_manager(0)
00090     {
00091     }
00092 
00093     ~PartPrivate()
00094     {
00095     }
00096 
00097     KIconLoader* m_iconLoader;
00098     bool m_bSelectable;
00099     bool m_autoDeleteWidget;
00100     bool m_autoDeletePart;
00101     PartManager * m_manager;
00102     QPointer<QWidget> m_widget;
00103 };
00104 
00105 }
00106 
00107 PartBase::PartBase()
00108     : d_ptr(new PartBasePrivate(this))
00109 {
00110 }
00111 
00112 PartBase::PartBase(PartBasePrivate &dd)
00113     : d_ptr(&dd)
00114 {
00115 }
00116 
00117 PartBase::~PartBase()
00118 {
00119     delete d_ptr;
00120 }
00121 
00122 void PartBase::setPartObject( QObject *obj )
00123 {
00124     Q_D(PartBase);
00125 
00126     d->m_obj = obj;
00127 }
00128 
00129 QObject *PartBase::partObject() const
00130 {
00131     Q_D(const PartBase);
00132 
00133     return d->m_obj;
00134 }
00135 
00136 void PartBase::setComponentData(const KComponentData &componentData)
00137 {
00138     setComponentData(componentData, true);
00139 }
00140 
00141 void PartBase::setComponentData(const KComponentData &componentData, bool bLoadPlugins)
00142 {
00143     Q_D(PartBase);
00144 
00145     KXMLGUIClient::setComponentData(componentData);
00146     KGlobal::locale()->insertCatalog(componentData.catalogName());
00147     // install 'instancename'data resource type
00148     KGlobal::dirs()->addResourceType((componentData.componentName() + "data").toUtf8(),
00149                                      "data", componentData.componentName());
00150     if (bLoadPlugins) {
00151         loadPlugins(d->m_obj, this, componentData);
00152     }
00153 }
00154 
00155 void PartBase::loadPlugins(QObject *parent, KXMLGUIClient *parentGUIClient, const KComponentData &instance)
00156 {
00157     Q_D(PartBase);
00158 
00159     if( d->m_pluginLoadingMode != DoNotLoadPlugins )
00160         Plugin::loadPlugins( parent, parentGUIClient, instance, d->m_pluginLoadingMode == LoadPlugins, d->m_pluginInterfaceVersion );
00161 }
00162 
00163 void PartBase::setPluginLoadingMode( PluginLoadingMode loadingMode )
00164 {
00165     Q_D(PartBase);
00166 
00167     d->m_pluginLoadingMode = loadingMode;
00168 }
00169 
00170 void KParts::PartBase::setPluginInterfaceVersion( int version )
00171 {
00172     Q_D(PartBase);
00173 
00174     d->m_pluginInterfaceVersion = version;
00175 }
00176 
00177 Part::Part( QObject *parent )
00178     : QObject( parent ), PartBase( *new PartPrivate(this) )
00179 {
00180     PartBase::setPartObject( this );
00181 }
00182 
00183 Part::Part(PartPrivate &dd, QObject *parent)
00184     : QObject( parent ), PartBase( dd )
00185 {
00186     PartBase::setPartObject( this );
00187 }
00188 
00189 Part::~Part()
00190 {
00191     Q_D(Part);
00192 
00193     //kDebug(1000) << this;
00194 
00195     if ( d->m_widget )
00196     {
00197         // We need to disconnect first, to avoid calling it !
00198         disconnect( d->m_widget, SIGNAL( destroyed() ),
00199                     this, SLOT( slotWidgetDestroyed() ) );
00200     }
00201 
00202     if ( d->m_manager )
00203         d->m_manager->removePart(this);
00204 
00205     if ( d->m_widget && d->m_autoDeleteWidget )
00206     {
00207         kDebug(1000) << "deleting widget" << d->m_widget << d->m_widget->objectName();
00208         delete static_cast<QWidget*>(d->m_widget);
00209     }
00210 
00211     delete d->m_iconLoader;
00212 }
00213 
00214 void Part::embed( QWidget * parentWidget )
00215 {
00216     if ( widget() )
00217     {
00218         widget()->setParent( parentWidget, 0 );
00219         widget()->setGeometry( 0, 0, widget()->width(), widget()->height() );
00220         widget()->show();
00221     }
00222 }
00223 
00224 QWidget *Part::widget()
00225 {
00226     Q_D(Part);
00227 
00228     return d->m_widget;
00229 }
00230 
00231 void Part::setAutoDeleteWidget(bool autoDeleteWidget)
00232 {
00233     Q_D(Part);
00234     d->m_autoDeleteWidget = autoDeleteWidget;
00235 }
00236 
00237 void Part::setAutoDeletePart(bool autoDeletePart)
00238 {
00239     Q_D(Part);
00240     d->m_autoDeletePart = autoDeletePart;
00241 }
00242 
00243 
00244 
00245 KIconLoader* Part::iconLoader()
00246 {
00247     Q_D(Part);
00248 
00249     if (!d->m_iconLoader) {
00250         Q_ASSERT(componentData().isValid());
00251         d->m_iconLoader = new KIconLoader( componentData() );
00252     }
00253     return d->m_iconLoader;
00254 }
00255 
00256 void Part::setManager( PartManager *manager )
00257 {
00258     Q_D(Part);
00259 
00260     d->m_manager = manager;
00261 }
00262 
00263 PartManager *Part::manager() const
00264 {
00265     Q_D(const Part);
00266 
00267     return d->m_manager;
00268 }
00269 
00270 Part *Part::hitTest( QWidget *widget, const QPoint & )
00271 {
00272     Q_D(Part);
00273 
00274     if ( (QWidget *)d->m_widget != widget )
00275         return 0;
00276 
00277     return this;
00278 }
00279 
00280 void Part::setWidget( QWidget *widget )
00281 {
00282     Q_D(Part);
00283 
00284     assert ( !d->m_widget ); // otherwise we get two connects
00285     d->m_widget = widget;
00286     connect( d->m_widget, SIGNAL( destroyed() ),
00287              this, SLOT( slotWidgetDestroyed() ) );
00288 }
00289 
00290 void Part::setSelectable( bool selectable )
00291 {
00292     Q_D(Part);
00293 
00294     d->m_bSelectable = selectable;
00295 }
00296 
00297 bool Part::isSelectable() const
00298 {
00299     Q_D(const Part);
00300 
00301     return d->m_bSelectable;
00302 }
00303 
00304 void Part::customEvent( QEvent *ev )
00305 {
00306     if ( PartActivateEvent::test( ev ) )
00307     {
00308         partActivateEvent( static_cast<PartActivateEvent *>(ev) );
00309         return;
00310     }
00311 
00312     if ( PartSelectEvent::test( ev ) )
00313     {
00314         partSelectEvent( static_cast<PartSelectEvent *>(ev) );
00315         return;
00316     }
00317 
00318     if ( GUIActivateEvent::test( ev ) )
00319     {
00320         guiActivateEvent( static_cast<GUIActivateEvent *>(ev) );
00321         return;
00322     }
00323 
00324     QObject::customEvent( ev );
00325 }
00326 
00327 void Part::partActivateEvent( PartActivateEvent * )
00328 {
00329 }
00330 
00331 void Part::partSelectEvent( PartSelectEvent * )
00332 {
00333 }
00334 
00335 void Part::guiActivateEvent( GUIActivateEvent * )
00336 {
00337 }
00338 
00339 QWidget *Part::hostContainer( const QString &containerName )
00340 {
00341     if ( !factory() )
00342         return 0;
00343 
00344     return factory()->container( containerName, this );
00345 }
00346 
00347 void Part::slotWidgetDestroyed()
00348 {
00349     Q_D(Part);
00350 
00351     d->m_widget = 0;
00352     if (d->m_autoDeletePart) {
00353         kDebug(1000) << "deleting part" << objectName();
00354         delete this; // ouch, this should probably be deleteLater()
00355     }
00356 }
00357 
00358 void Part::loadPlugins()
00359 {
00360     PartBase::loadPlugins(this, this, componentData());
00361 }
00362 
00364 
00365 namespace KParts
00366 {
00367 
00368 class ReadOnlyPartPrivate: public PartPrivate
00369 {
00370 public:
00371     Q_DECLARE_PUBLIC(ReadOnlyPart)
00372 
00373     ReadOnlyPartPrivate(ReadOnlyPart *q): PartPrivate(q)
00374     {
00375         m_job = 0;
00376         m_uploadJob = 0;
00377         m_showProgressInfo = true;
00378         m_saveOk = false;
00379         m_waitForSave = false;
00380         m_duringSaveAs = false;
00381         m_bTemp = false;
00382         m_bAutoDetectedMime = false;
00383     }
00384 
00385     ~ReadOnlyPartPrivate()
00386     {
00387     }
00388 
00389     void _k_slotJobFinished( KJob * job );
00390     void _k_slotGotMimeType(KIO::Job *job, const QString &mime);
00391 
00392     KIO::FileCopyJob * m_job;
00393     KIO::FileCopyJob * m_uploadJob;
00394     KUrl m_originalURL; // for saveAs
00395     QString m_originalFilePath; // for saveAs
00396     bool m_showProgressInfo : 1;
00397     bool m_saveOk : 1;
00398     bool m_waitForSave : 1;
00399     bool m_duringSaveAs : 1;
00400 
00404     bool m_bTemp: 1;
00405 
00406     // whether the mimetype in the arguments was detected by the part itself
00407     bool m_bAutoDetectedMime : 1;
00408 
00412     KUrl m_url;
00413 
00417     QString m_file;
00418 
00419     OpenUrlArguments m_arguments;
00420 };
00421 
00422 class ReadWritePartPrivate: public ReadOnlyPartPrivate
00423 {
00424 public:
00425     Q_DECLARE_PUBLIC(ReadWritePart)
00426 
00427     ReadWritePartPrivate(ReadWritePart *q): ReadOnlyPartPrivate(q)
00428     {
00429         m_bModified = false;
00430         m_bReadWrite = true;
00431         m_bClosing = false;
00432     }
00433 
00434     void _k_slotUploadFinished( KJob * job );
00435 
00436     void prepareSaving();
00437 
00438     bool m_bModified;
00439     bool m_bReadWrite;
00440     bool m_bClosing;
00441     QEventLoop m_eventLoop;
00442 };
00443 
00444 }
00445 
00446 ReadOnlyPart::ReadOnlyPart( QObject *parent )
00447     : Part( *new ReadOnlyPartPrivate(this), parent )
00448 {
00449 }
00450 
00451 ReadOnlyPart::ReadOnlyPart( ReadOnlyPartPrivate &dd, QObject *parent )
00452     : Part( dd, parent )
00453 {
00454 }
00455 
00456 ReadOnlyPart::~ReadOnlyPart()
00457 {
00458     ReadOnlyPart::closeUrl();
00459 }
00460 
00461 KUrl ReadOnlyPart::url() const
00462 {
00463     Q_D(const ReadOnlyPart);
00464 
00465     return d->m_url;
00466 }
00467 
00468 void ReadOnlyPart::setUrl(const KUrl &url)
00469 {
00470     Q_D(ReadOnlyPart);
00471 
00472     d->m_url = url;
00473 }
00474 
00475 QString ReadOnlyPart::localFilePath() const
00476 {
00477     Q_D(const ReadOnlyPart);
00478 
00479     return d->m_file;
00480 }
00481 
00482 void ReadOnlyPart::setLocalFilePath( const QString &localFilePath )
00483 {
00484     Q_D(ReadOnlyPart);
00485 
00486     d->m_file = localFilePath;
00487 }
00488 
00489 bool ReadOnlyPart::isLocalFileTemporary() const
00490 {
00491     Q_D(const ReadOnlyPart);
00492 
00493     return d->m_bTemp;
00494 }
00495 
00496 void ReadOnlyPart::setLocalFileTemporary( bool temp )
00497 {
00498     Q_D(ReadOnlyPart);
00499 
00500     d->m_bTemp = temp;
00501 }
00502 
00503 void ReadOnlyPart::setProgressInfoEnabled( bool show )
00504 {
00505     Q_D(ReadOnlyPart);
00506 
00507     d->m_showProgressInfo = show;
00508 }
00509 
00510 bool ReadOnlyPart::isProgressInfoEnabled() const
00511 {
00512     Q_D(const ReadOnlyPart);
00513 
00514     return d->m_showProgressInfo;
00515 }
00516 
00517 #ifndef KDE_NO_COMPAT
00518 void ReadOnlyPart::showProgressInfo( bool show )
00519 {
00520     Q_D(ReadOnlyPart);
00521 
00522     d->m_showProgressInfo = show;
00523 }
00524 #endif
00525 
00526 bool ReadOnlyPart::openUrl( const KUrl &url )
00527 {
00528     Q_D(ReadOnlyPart);
00529 
00530     if ( !url.isValid() )
00531         return false;
00532     if (d->m_bAutoDetectedMime) {
00533         d->m_arguments.setMimeType(QString());
00534         d->m_bAutoDetectedMime = false;
00535     }
00536     OpenUrlArguments args = d->m_arguments;
00537     if ( !closeUrl() )
00538         return false;
00539     d->m_arguments = args;
00540     d->m_url = url;
00541     if ( d->m_url.isLocalFile() )
00542     {
00543         emit started( 0 );
00544         d->m_file = d->m_url.toLocalFile();
00545         d->m_bTemp = false;
00546         // set the mimetype only if it was not already set (for example, by the host application)
00547         if (d->m_arguments.mimeType().isEmpty())
00548         {
00549             // get the mimetype of the file
00550             // using findByUrl() to avoid another string -> url conversion
00551             KMimeType::Ptr mime = KMimeType::findByUrl(d->m_url, 0, true /* local file*/);
00552             if (mime) {
00553                 d->m_arguments.setMimeType(mime->name());
00554                 d->m_bAutoDetectedMime = true;
00555             }
00556         }
00557         bool ret = openFile();
00558         if (ret) {
00559             emit setWindowCaption( d->m_url.prettyUrl() );
00560             emit completed();
00561         } else emit canceled(QString());
00562         return ret;
00563     }
00564     else
00565     {
00566         d->m_bTemp = true;
00567         // Use same extension as remote file. This is important for mimetype-determination (e.g. koffice)
00568         QString fileName = url.fileName();
00569         QFileInfo fileInfo(fileName);
00570         QString ext = fileInfo.completeSuffix();
00571         QString extension;
00572         if ( !ext.isEmpty() && url.query().isNull() ) // not if the URL has a query, e.g. cgi.pl?something
00573             extension = '.'+ext; // keep the '.'
00574         KTemporaryFile tempFile;
00575         tempFile.setSuffix(extension);
00576         tempFile.setAutoRemove(false);
00577         tempFile.open();
00578         d->m_file = tempFile.fileName();
00579 
00580         KUrl destURL;
00581         destURL.setPath( d->m_file );
00582         KIO::JobFlags flags = d->m_showProgressInfo ? KIO::DefaultFlags : KIO::HideProgressInfo;
00583         flags |= KIO::Overwrite;
00584         d->m_job = KIO::file_copy( d->m_url, destURL, 0600, flags );
00585         d->m_job->ui()->setWindow( widget() ? widget()->topLevelWidget() : 0 );
00586         emit started( d->m_job );
00587         connect( d->m_job, SIGNAL( result( KJob * ) ), this, SLOT( _k_slotJobFinished ( KJob * ) ) );
00588         connect(d->m_job, SIGNAL(mimetype(KIO::Job *, const QString &)),
00589                 this, SLOT(_k_slotGotMimeType(KIO::Job *, const QString&)));
00590         return true;
00591     }
00592 }
00593 
00594 void ReadOnlyPart::abortLoad()
00595 {
00596     Q_D(ReadOnlyPart);
00597 
00598     if ( d->m_job )
00599     {
00600         //kDebug(1000) << "Aborting job" << d->m_job;
00601         d->m_job->kill();
00602         d->m_job = 0;
00603     }
00604 }
00605 
00606 bool ReadOnlyPart::closeUrl()
00607 {
00608     Q_D(ReadOnlyPart);
00609 
00610     abortLoad(); //just in case
00611 
00612     d->m_arguments = KParts::OpenUrlArguments();
00613 
00614     if ( d->m_bTemp )
00615     {
00616         QFile::remove( d->m_file );
00617         d->m_bTemp = false;
00618     }
00619     // It always succeeds for a read-only part,
00620     // but the return value exists for reimplementations
00621     // (e.g. pressing cancel for a modified read-write part)
00622     return true;
00623 }
00624 
00625 void ReadOnlyPartPrivate::_k_slotJobFinished( KJob * job )
00626 {
00627     Q_Q(ReadOnlyPart);
00628 
00629     assert( job == m_job );
00630     m_job = 0;
00631     if (job->error())
00632         emit q->canceled( job->errorString() );
00633     else
00634     {
00635         if ( q->openFile() ) {
00636             emit q->setWindowCaption( m_url.prettyUrl() );
00637             emit q->completed();
00638         } else emit q->canceled(QString());
00639     }
00640 }
00641 
00642 void ReadOnlyPartPrivate::_k_slotGotMimeType(KIO::Job *job, const QString &mime)
00643 {
00644     kDebug(1000) << mime;
00645     Q_ASSERT(job == m_job);
00646     // set the mimetype only if it was not already set (for example, by the host application)
00647     if (m_arguments.mimeType().isEmpty()) {
00648         m_arguments.setMimeType(mime);
00649         m_bAutoDetectedMime = true;
00650     }
00651 }
00652 
00653 void ReadOnlyPart::guiActivateEvent( GUIActivateEvent * event )
00654 {
00655     Q_D(ReadOnlyPart);
00656 
00657     if (event->activated())
00658     {
00659         if (!d->m_url.isEmpty())
00660         {
00661             kDebug(1000) << d->m_url;
00662             emit setWindowCaption( d->m_url.prettyUrl() );
00663         } else emit setWindowCaption( "" );
00664     }
00665 }
00666 
00667 bool ReadOnlyPart::openStream( const QString& mimeType, const KUrl& url )
00668 {
00669     Q_D(ReadOnlyPart);
00670 
00671     OpenUrlArguments args = d->m_arguments;
00672     if ( !closeUrl() )
00673         return false;
00674     d->m_arguments = args;
00675     d->m_url = url;
00676     return doOpenStream( mimeType );
00677 }
00678 
00679 bool ReadOnlyPart::writeStream( const QByteArray& data )
00680 {
00681     return doWriteStream( data );
00682 }
00683 
00684 bool ReadOnlyPart::closeStream()
00685 {
00686     return doCloseStream();
00687 }
00688 
00689 BrowserExtension* ReadOnlyPart::browserExtension() const
00690 {
00691     return findChild<KParts::BrowserExtension *>();
00692 }
00693 
00694 void KParts::ReadOnlyPart::setArguments(const OpenUrlArguments& arguments)
00695 {
00696     Q_D(ReadOnlyPart);
00697     d->m_arguments = arguments;
00698     d->m_bAutoDetectedMime = arguments.mimeType().isEmpty();
00699 }
00700 
00701 OpenUrlArguments KParts::ReadOnlyPart::arguments() const
00702 {
00703     Q_D(const ReadOnlyPart);
00704     return d->m_arguments;
00705 }
00706 
00708 
00709 
00710 ReadWritePart::ReadWritePart( QObject *parent )
00711     : ReadOnlyPart( *new ReadWritePartPrivate(this), parent )
00712 {
00713 }
00714 
00715 ReadWritePart::~ReadWritePart()
00716 {
00717     // parent destructor will delete temp file
00718     // we can't call our own closeUrl() here, because
00719     // "cancel" wouldn't cancel anything. We have to assume
00720     // the app called closeUrl() before destroying us.
00721 }
00722 
00723 void ReadWritePart::setReadWrite( bool readwrite )
00724 {
00725     Q_D(ReadWritePart);
00726 
00727     // Perhaps we should check isModified here and issue a warning if true
00728     d->m_bReadWrite = readwrite;
00729 }
00730 
00731 void ReadWritePart::setModified( bool modified )
00732 {
00733     Q_D(ReadWritePart);
00734 
00735     kDebug(1000) << "setModified(" << (modified ? "true" : "false") << ")";
00736     if ( !d->m_bReadWrite && modified )
00737     {
00738         kError(1000) << "Can't set a read-only document to 'modified' !" << endl;
00739         return;
00740     }
00741     d->m_bModified = modified;
00742 }
00743 
00744 void ReadWritePart::setModified()
00745 {
00746     setModified( true );
00747 }
00748 
00749 bool ReadWritePart::queryClose()
00750 {
00751     Q_D(ReadWritePart);
00752 
00753     if ( !isReadWrite() || !isModified() )
00754         return true;
00755 
00756     QString docName = url().fileName();
00757     if (docName.isEmpty()) docName = i18n( "Untitled" );
00758 
00759     QWidget *parentWidget=widget();
00760     if(!parentWidget) parentWidget=QApplication::activeWindow();
00761 
00762     int res = KMessageBox::warningYesNoCancel( parentWidget,
00763                                                i18n( "The document \"%1\" has been modified.\n"
00764                                                      "Do you want to save your changes or discard them?" ,  docName ),
00765                                                i18n( "Close Document" ), KStandardGuiItem::save(), KStandardGuiItem::discard() );
00766 
00767     bool abortClose=false;
00768     bool handled=false;
00769 
00770     switch(res) {
00771     case KMessageBox::Yes :
00772         sigQueryClose(&handled,&abortClose);
00773         if (!handled)
00774         {
00775             if (d->m_url.isEmpty())
00776             {
00777                 KUrl url = KFileDialog::getSaveUrl(KUrl(), QString(), parentWidget);
00778                 if (url.isEmpty())
00779                     return false;
00780 
00781                 saveAs( url );
00782             }
00783             else
00784             {
00785                 save();
00786             }
00787         } else if (abortClose) return false;
00788         return waitSaveComplete();
00789     case KMessageBox::No :
00790         return true;
00791     default : // case KMessageBox::Cancel :
00792         return false;
00793     }
00794 }
00795 
00796 bool ReadWritePart::closeUrl()
00797 {
00798     abortLoad(); //just in case
00799     if ( isReadWrite() && isModified() )
00800     {
00801         if (!queryClose())
00802             return false;
00803     }
00804     // Not modified => ok and delete temp file.
00805     return ReadOnlyPart::closeUrl();
00806 }
00807 
00808 bool ReadWritePart::closeUrl( bool promptToSave )
00809 {
00810     return promptToSave ? closeUrl() : ReadOnlyPart::closeUrl();
00811 }
00812 
00813 bool ReadWritePart::save()
00814 {
00815     Q_D(ReadWritePart);
00816 
00817     d->m_saveOk = false;
00818     if ( d->m_file.isEmpty() ) // document was created empty
00819         d->prepareSaving();
00820     if( saveFile() )
00821         return saveToUrl();
00822     else
00823         emit canceled(QString());
00824     return false;
00825 }
00826 
00827 bool ReadWritePart::saveAs( const KUrl & kurl )
00828 {
00829     Q_D(ReadWritePart);
00830 
00831     if (!kurl.isValid())
00832     {
00833         kError(1000) << "saveAs: Malformed URL " << kurl.url() << endl;
00834         return false;
00835     }
00836     d->m_duringSaveAs = true;
00837     d->m_originalURL = d->m_url;
00838     d->m_originalFilePath = d->m_file;
00839     d->m_url = kurl; // Store where to upload in saveToURL
00840     d->prepareSaving();
00841     bool result = save(); // Save local file and upload local file
00842     if (result) {
00843         emit setWindowCaption( d->m_url.prettyUrl() );
00844     } else {
00845         d->m_url = d->m_originalURL;
00846         d->m_file = d->m_originalFilePath;
00847         d->m_duringSaveAs = false;
00848         d->m_originalURL = KUrl();
00849         d->m_originalFilePath.clear();
00850     }
00851 
00852     return result;
00853 }
00854 
00855 // Set m_file correctly for m_url
00856 void ReadWritePartPrivate::prepareSaving()
00857 {
00858     // Local file
00859     if ( m_url.isLocalFile() )
00860     {
00861         if ( m_bTemp ) // get rid of a possible temp file first
00862         {              // (happens if previous url was remote)
00863             QFile::remove( m_file );
00864             m_bTemp = false;
00865         }
00866         m_file = m_url.toLocalFile();
00867     }
00868     else
00869     { // Remote file
00870         // We haven't saved yet, or we did but locally - provide a temp file
00871         if ( m_file.isEmpty() || !m_bTemp )
00872         {
00873             KTemporaryFile tempFile;
00874             tempFile.setAutoRemove(false);
00875             tempFile.open();
00876             m_file = tempFile.fileName();
00877             m_bTemp = true;
00878         }
00879         // otherwise, we already had a temp file
00880     }
00881 }
00882 
00883 bool ReadWritePart::saveToUrl()
00884 {
00885     Q_D(ReadWritePart);
00886 
00887     if ( d->m_url.isLocalFile() )
00888     {
00889         setModified( false );
00890         emit completed();
00891         // if m_url is a local file there won't be a temp file -> nothing to remove
00892         assert( !d->m_bTemp );
00893         d->m_saveOk = true;
00894         d->m_duringSaveAs = false;
00895         d->m_originalURL = KUrl();
00896         d->m_originalFilePath.clear();
00897         return true; // Nothing to do
00898     }
00899     else
00900     {
00901         if (d->m_uploadJob)
00902         {
00903             QFile::remove(d->m_uploadJob->srcUrl().toLocalFile());
00904             d->m_uploadJob->kill();
00905             d->m_uploadJob = 0;
00906         }
00907         KTemporaryFile *tempFile = new KTemporaryFile();
00908         tempFile->open();
00909         QString uploadFile = tempFile->fileName();
00910         delete tempFile;
00911         KUrl uploadUrl;
00912         uploadUrl.setPath( uploadFile );
00913         // Create hardlink
00914         if (::link(QFile::encodeName(d->m_file), QFile::encodeName(uploadFile)) != 0)
00915         {
00916             // Uh oh, some error happened.
00917             return false;
00918         }
00919         d->m_uploadJob = KIO::file_move( uploadUrl, d->m_url, -1, KIO::Overwrite );
00920         d->m_uploadJob->ui()->setWindow( widget() ? widget()->topLevelWidget() : 0 );
00921         connect( d->m_uploadJob, SIGNAL( result( KJob * ) ), this, SLOT( _k_slotUploadFinished (KJob *) ) );
00922         return true;
00923     }
00924 }
00925 
00926 void ReadWritePartPrivate::_k_slotUploadFinished( KJob * )
00927 {
00928     Q_Q(ReadWritePart);
00929 
00930     if (m_uploadJob->error())
00931     {
00932         QFile::remove(m_uploadJob->srcUrl().toLocalFile());
00933         QString error = m_uploadJob->errorString();
00934         m_uploadJob = 0;
00935         if (m_duringSaveAs) {
00936             m_url = m_originalURL;
00937             m_file = m_originalFilePath;
00938         }
00939         emit q->canceled( error );
00940     }
00941     else
00942     {
00943         KUrl dirUrl( m_url );
00944         dirUrl.setPath( dirUrl.directory() );
00945         ::org::kde::KDirNotify::emitFilesAdded( dirUrl.url() );
00946 
00947         m_uploadJob = 0;
00948         q->setModified( false );
00949         emit q->completed();
00950         m_saveOk = true;
00951     }
00952     m_duringSaveAs = false;
00953     m_originalURL = KUrl();
00954     m_originalFilePath.clear();
00955     if (m_waitForSave) {
00956         m_eventLoop.quit();
00957     }
00958 }
00959 
00960 bool ReadWritePart::isReadWrite() const
00961 {
00962     Q_D(const ReadWritePart);
00963 
00964     return d->m_bReadWrite;
00965 }
00966 
00967 bool ReadWritePart::isModified() const
00968 {
00969     Q_D(const ReadWritePart);
00970 
00971     return d->m_bModified;
00972 }
00973 
00974 bool ReadWritePart::waitSaveComplete()
00975 {
00976     Q_D(ReadWritePart);
00977 
00978     if (!d->m_uploadJob)
00979         return d->m_saveOk;
00980 
00981     d->m_waitForSave = true;
00982 
00983     d->m_eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
00984 
00985     d->m_waitForSave = false;
00986 
00987     return d->m_saveOk;
00988 }
00989 
00991 
00992 class KParts::OpenUrlArgumentsPrivate : public QSharedData
00993 {
00994 public:
00995     OpenUrlArgumentsPrivate()
00996         : reload(false),
00997           actionRequestedByUser(true),
00998           xOffset(0),
00999           yOffset(0),
01000           mimeType(),
01001           metaData()
01002     {}
01003     bool reload;
01004     bool actionRequestedByUser;
01005     int xOffset;
01006     int yOffset;
01007     QString mimeType;
01008     QMap<QString, QString> metaData;
01009 };
01010 
01011 KParts::OpenUrlArguments::OpenUrlArguments()
01012     : d(new OpenUrlArgumentsPrivate)
01013 {
01014 }
01015 
01016 KParts::OpenUrlArguments::OpenUrlArguments(const OpenUrlArguments &other)
01017     : d(other.d)
01018 {
01019 }
01020 
01021 KParts::OpenUrlArguments & KParts::OpenUrlArguments::operator=( const OpenUrlArguments &other)
01022 {
01023     d = other.d;
01024     return *this;
01025 }
01026 
01027 KParts::OpenUrlArguments::~OpenUrlArguments()
01028 {
01029 }
01030 
01031 bool KParts::OpenUrlArguments::reload() const
01032 {
01033     return d->reload;
01034 }
01035 
01036 void KParts::OpenUrlArguments::setReload(bool b)
01037 {
01038     d->reload = b;
01039 }
01040 
01041 int KParts::OpenUrlArguments::xOffset() const
01042 {
01043     return d->xOffset;
01044 }
01045 
01046 void KParts::OpenUrlArguments::setXOffset(int x)
01047 {
01048     d->xOffset = x;
01049 }
01050 
01051 int KParts::OpenUrlArguments::yOffset() const
01052 {
01053     return d->yOffset;
01054 }
01055 
01056 void KParts::OpenUrlArguments::setYOffset(int y)
01057 {
01058     d->yOffset = y;
01059 }
01060 
01061 QString KParts::OpenUrlArguments::mimeType() const
01062 {
01063     return d->mimeType;
01064 }
01065 
01066 void KParts::OpenUrlArguments::setMimeType(const QString& mime)
01067 {
01068     d->mimeType = mime;
01069 }
01070 
01071 QMap<QString, QString> & KParts::OpenUrlArguments::metaData()
01072 {
01073     return d->metaData;
01074 }
01075 
01076 const QMap<QString, QString> & KParts::OpenUrlArguments::metaData() const
01077 {
01078     return d->metaData;
01079 }
01080 
01081 bool KParts::OpenUrlArguments::actionRequestedByUser() const
01082 {
01083     return d->actionRequestedByUser;
01084 }
01085 
01086 void KParts::OpenUrlArguments::setActionRequestedByUser(bool userRequested)
01087 {
01088     d->actionRequestedByUser = userRequested;
01089 }
01090 
01091 #include "part.moc"

KParts

Skip menu "KParts"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal