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

KParts

Skip menu "KParts"
  • Main Page
  • Modules
  • 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
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
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