• Skip to content
  • Skip to link menu
KDE 4.2 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 #include <QtCore/QTextStream>
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((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) << "Part::~Part " << 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) << "KPart::slotWidgetDestroyed(), 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_uploadJob = 0;
00378         m_showProgressInfo = true;
00379         m_saveOk = false;
00380         m_waitForSave = false;
00381         m_duringSaveAs = false;
00382         m_bTemp = false;
00383         m_bAutoDetectedMime = false;
00384     }
00385 
00386     ~ReadOnlyPartPrivate()
00387     {
00388     }
00389 
00390     void _k_slotJobFinished( KJob * job );
00391     void _k_slotGotMimeType(KIO::Job *job, const QString &mime);
00392 
00393     KIO::FileCopyJob * m_job;
00394     KIO::FileCopyJob * m_uploadJob;
00395     KUrl m_originalURL; // for saveAs
00396     QString m_originalFilePath; // for saveAs
00397     bool m_showProgressInfo : 1;
00398     bool m_saveOk : 1;
00399     bool m_waitForSave : 1;
00400     bool m_duringSaveAs : 1;
00401 
00405     bool m_bTemp: 1;
00406 
00407     // whether the mimetype in the arguments was detected by the part itself
00408     bool m_bAutoDetectedMime : 1;
00409 
00413     KUrl m_url;
00414 
00418     QString m_file;
00419 
00420     OpenUrlArguments m_arguments;
00421 };
00422 
00423 class ReadWritePartPrivate: public ReadOnlyPartPrivate
00424 {
00425 public:
00426     Q_DECLARE_PUBLIC(ReadWritePart)
00427 
00428     ReadWritePartPrivate(ReadWritePart *q): ReadOnlyPartPrivate(q)
00429     {
00430         m_bModified = false;
00431         m_bReadWrite = true;
00432         m_bClosing = false;
00433     }
00434 
00435     void _k_slotUploadFinished( KJob * job );
00436 
00437     void prepareSaving();
00438 
00439     bool m_bModified;
00440     bool m_bReadWrite;
00441     bool m_bClosing;
00442     QEventLoop m_eventLoop;
00443 };
00444 
00445 }
00446 
00447 ReadOnlyPart::ReadOnlyPart( QObject *parent )
00448     : Part( *new ReadOnlyPartPrivate(this), parent )
00449 {
00450 }
00451 
00452 ReadOnlyPart::ReadOnlyPart( ReadOnlyPartPrivate &dd, QObject *parent )
00453     : Part( dd, parent )
00454 {
00455 }
00456 
00457 ReadOnlyPart::~ReadOnlyPart()
00458 {
00459     ReadOnlyPart::closeUrl();
00460 }
00461 
00462 KUrl ReadOnlyPart::url() const
00463 {
00464     Q_D(const ReadOnlyPart);
00465 
00466     return d->m_url;
00467 }
00468 
00469 void ReadOnlyPart::setUrl(const KUrl &url)
00470 {
00471     Q_D(ReadOnlyPart);
00472 
00473     d->m_url = url;
00474 }
00475 
00476 QString ReadOnlyPart::localFilePath() const
00477 {
00478     Q_D(const ReadOnlyPart);
00479 
00480     return d->m_file;
00481 }
00482 
00483 void ReadOnlyPart::setLocalFilePath( const QString &localFilePath )
00484 {
00485     Q_D(ReadOnlyPart);
00486 
00487     d->m_file = localFilePath;
00488 }
00489 
00490 bool ReadOnlyPart::isLocalFileTemporary() const
00491 {
00492     Q_D(const ReadOnlyPart);
00493 
00494     return d->m_bTemp;
00495 }
00496 
00497 void ReadOnlyPart::setLocalFileTemporary( bool temp )
00498 {
00499     Q_D(ReadOnlyPart);
00500 
00501     d->m_bTemp = temp;
00502 }
00503 
00504 void ReadOnlyPart::setProgressInfoEnabled( bool show )
00505 {
00506     Q_D(ReadOnlyPart);
00507 
00508     d->m_showProgressInfo = show;
00509 }
00510 
00511 bool ReadOnlyPart::isProgressInfoEnabled() const
00512 {
00513     Q_D(const ReadOnlyPart);
00514 
00515     return d->m_showProgressInfo;
00516 }
00517 
00518 #ifndef KDE_NO_COMPAT
00519 void ReadOnlyPart::showProgressInfo( bool show )
00520 {
00521     Q_D(ReadOnlyPart);
00522 
00523     d->m_showProgressInfo = show;
00524 }
00525 #endif
00526 
00527 bool ReadOnlyPart::openUrl( const KUrl &url )
00528 {
00529     Q_D(ReadOnlyPart);
00530 
00531     if ( !url.isValid() )
00532         return false;
00533     if (d->m_bAutoDetectedMime) {
00534         d->m_arguments.setMimeType(QString());
00535         d->m_bAutoDetectedMime = false;
00536     }
00537     OpenUrlArguments args = d->m_arguments;
00538     if ( !closeUrl() )
00539         return false;
00540     d->m_arguments = args;
00541     d->m_url = url;
00542     if ( d->m_url.isLocalFile() )
00543     {
00544         emit started( 0 );
00545         d->m_file = d->m_url.toLocalFile();
00546         d->m_bTemp = false;
00547         // set the mimetype only if it was not already set (for example, by the host application)
00548         if (d->m_arguments.mimeType().isEmpty())
00549         {
00550             // get the mimetype of the file
00551             // using findByUrl() to avoid another string -> url conversion
00552             KMimeType::Ptr mime = KMimeType::findByUrl(d->m_url, 0, true /* local file*/);
00553             if (mime) {
00554                 d->m_arguments.setMimeType(mime->name());
00555                 d->m_bAutoDetectedMime = true;
00556             }
00557         }
00558         bool ret = openFile();
00559         if (ret) {
00560             emit setWindowCaption( d->m_url.prettyUrl() );
00561             emit completed();
00562         } else emit canceled(QString());
00563         return ret;
00564     }
00565     else
00566     {
00567         d->m_bTemp = true;
00568         // Use same extension as remote file. This is important for mimetype-determination (e.g. koffice)
00569         QString fileName = url.fileName();
00570         QFileInfo fileInfo(fileName);
00571         QString ext = fileInfo.completeSuffix();
00572         QString extension;
00573         if ( !ext.isEmpty() && url.query().isNull() ) // not if the URL has a query, e.g. cgi.pl?something
00574             extension = '.'+ext; // keep the '.'
00575         KTemporaryFile tempFile;
00576         tempFile.setSuffix(extension);
00577         tempFile.setAutoRemove(false);
00578         tempFile.open();
00579         d->m_file = tempFile.fileName();
00580 
00581         KUrl destURL;
00582         destURL.setPath( d->m_file );
00583         KIO::JobFlags flags = d->m_showProgressInfo ? KIO::DefaultFlags : KIO::HideProgressInfo;
00584         flags |= KIO::Overwrite;
00585         d->m_job = KIO::file_copy( d->m_url, destURL, 0600, flags );
00586         d->m_job->ui()->setWindow( widget() ? widget()->topLevelWidget() : 0 );
00587         emit started( d->m_job );
00588         connect( d->m_job, SIGNAL( result( KJob * ) ), this, SLOT( _k_slotJobFinished ( KJob * ) ) );
00589         connect(d->m_job, SIGNAL(mimetype(KIO::Job *, const QString &)),
00590                 this, SLOT(_k_slotGotMimeType(KIO::Job *, const QString&)));
00591         return true;
00592     }
00593 }
00594 
00595 void ReadOnlyPart::abortLoad()
00596 {
00597     Q_D(ReadOnlyPart);
00598 
00599     if ( d->m_job )
00600     {
00601         //kDebug(1000) << "Aborting job " << d->m_job;
00602         d->m_job->kill();
00603         d->m_job = 0;
00604     }
00605 }
00606 
00607 bool ReadOnlyPart::closeUrl()
00608 {
00609     Q_D(ReadOnlyPart);
00610 
00611     abortLoad(); //just in case
00612 
00613     d->m_arguments = KParts::OpenUrlArguments();
00614 
00615     if ( d->m_bTemp )
00616     {
00617         unlink( QFile::encodeName(d->m_file) );
00618         d->m_bTemp = false;
00619     }
00620     // It always succeeds for a read-only part,
00621     // but the return value exists for reimplementations
00622     // (e.g. pressing cancel for a modified read-write part)
00623     return true;
00624 }
00625 
00626 void ReadOnlyPartPrivate::_k_slotJobFinished( KJob * job )
00627 {
00628     Q_Q(ReadOnlyPart);
00629 
00630     kDebug(1000) << "ReadOnlyPart::slotJobFinished";
00631     assert( job == m_job );
00632     m_job = 0;
00633     if (job->error())
00634         emit q->canceled( job->errorString() );
00635     else
00636     {
00637         if ( q->openFile() ) {
00638             emit q->setWindowCaption( m_url.prettyUrl() );
00639             emit q->completed();
00640         } else emit q->canceled(QString());
00641     }
00642 }
00643 
00644 void ReadOnlyPartPrivate::_k_slotGotMimeType(KIO::Job *job, const QString &mime)
00645 {
00646     kDebug(1000) << "ReadOnlyPart::slotJobFinished:" << mime;
00647     Q_ASSERT(job == m_job);
00648     // set the mimetype only if it was not already set (for example, by the host application)
00649     if (m_arguments.mimeType().isEmpty()) {
00650         m_arguments.setMimeType(mime);
00651         m_bAutoDetectedMime = true;
00652     }
00653 }
00654 
00655 void ReadOnlyPart::guiActivateEvent( GUIActivateEvent * event )
00656 {
00657     Q_D(ReadOnlyPart);
00658 
00659     if (event->activated())
00660     {
00661         if (!d->m_url.isEmpty())
00662         {
00663             kDebug(1000) << "ReadOnlyPart::guiActivateEvent -> " << d->m_url.prettyUrl();
00664             emit setWindowCaption( d->m_url.prettyUrl() );
00665         } else emit setWindowCaption( "" );
00666     }
00667 }
00668 
00669 bool ReadOnlyPart::openStream( const QString& mimeType, const KUrl& url )
00670 {
00671     Q_D(ReadOnlyPart);
00672 
00673     OpenUrlArguments args = d->m_arguments;
00674     if ( !closeUrl() )
00675         return false;
00676     d->m_arguments = args;
00677     d->m_url = url;
00678     return doOpenStream( mimeType );
00679 }
00680 
00681 bool ReadOnlyPart::writeStream( const QByteArray& data )
00682 {
00683     return doWriteStream( data );
00684 }
00685 
00686 bool ReadOnlyPart::closeStream()
00687 {
00688     return doCloseStream();
00689 }
00690 
00691 BrowserExtension* ReadOnlyPart::browserExtension() const
00692 {
00693     return findChild<KParts::BrowserExtension *>();
00694 }
00695 
00696 void KParts::ReadOnlyPart::setArguments(const OpenUrlArguments& arguments)
00697 {
00698     Q_D(ReadOnlyPart);
00699     d->m_arguments = arguments;
00700     d->m_bAutoDetectedMime = arguments.mimeType().isEmpty();
00701 }
00702 
00703 OpenUrlArguments KParts::ReadOnlyPart::arguments() const
00704 {
00705     Q_D(const ReadOnlyPart);
00706     return d->m_arguments;
00707 }
00708 
00710 
00711 
00712 ReadWritePart::ReadWritePart( QObject *parent )
00713     : ReadOnlyPart( *new ReadWritePartPrivate(this), parent )
00714 {
00715 }
00716 
00717 ReadWritePart::~ReadWritePart()
00718 {
00719     // parent destructor will delete temp file
00720     // we can't call our own closeUrl() here, because
00721     // "cancel" wouldn't cancel anything. We have to assume
00722     // the app called closeUrl() before destroying us.
00723 }
00724 
00725 void ReadWritePart::setReadWrite( bool readwrite )
00726 {
00727     Q_D(ReadWritePart);
00728 
00729     // Perhaps we should check isModified here and issue a warning if true
00730     d->m_bReadWrite = readwrite;
00731 }
00732 
00733 void ReadWritePart::setModified( bool modified )
00734 {
00735     Q_D(ReadWritePart);
00736 
00737     kDebug(1000) << "ReadWritePart::setModified( " << (modified ? "true" : "false") << ")";
00738     if ( !d->m_bReadWrite && modified )
00739     {
00740         kError(1000) << "Can't set a read-only document to 'modified' !" << endl;
00741         return;
00742     }
00743     d->m_bModified = modified;
00744 }
00745 
00746 void ReadWritePart::setModified()
00747 {
00748     setModified( true );
00749 }
00750 
00751 bool ReadWritePart::queryClose()
00752 {
00753     Q_D(ReadWritePart);
00754 
00755     if ( !isReadWrite() || !isModified() )
00756         return true;
00757 
00758     QString docName = url().fileName();
00759     if (docName.isEmpty()) docName = i18n( "Untitled" );
00760 
00761     QWidget *parentWidget=widget();
00762     if(!parentWidget) parentWidget=QApplication::activeWindow();
00763 
00764     int res = KMessageBox::warningYesNoCancel( parentWidget,
00765                                                i18n( "The document \"%1\" has been modified.\n"
00766                                                      "Do you want to save your changes or discard them?" ,  docName ),
00767                                                i18n( "Close Document" ), KStandardGuiItem::save(), KStandardGuiItem::discard() );
00768 
00769     bool abortClose=false;
00770     bool handled=false;
00771 
00772     switch(res) {
00773     case KMessageBox::Yes :
00774         sigQueryClose(&handled,&abortClose);
00775         if (!handled)
00776         {
00777             if (d->m_url.isEmpty())
00778             {
00779                 KUrl url = KFileDialog::getSaveUrl(KUrl(), QString(), parentWidget);
00780                 if (url.isEmpty())
00781                     return false;
00782 
00783                 saveAs( url );
00784             }
00785             else
00786             {
00787                 save();
00788             }
00789         } else if (abortClose) return false;
00790         return waitSaveComplete();
00791     case KMessageBox::No :
00792         return true;
00793     default : // case KMessageBox::Cancel :
00794         return false;
00795     }
00796 }
00797 
00798 bool ReadWritePart::closeUrl()
00799 {
00800     abortLoad(); //just in case
00801     if ( isReadWrite() && isModified() )
00802     {
00803         if (!queryClose())
00804             return false;
00805     }
00806     // Not modified => ok and delete temp file.
00807     return ReadOnlyPart::closeUrl();
00808 }
00809 
00810 bool ReadWritePart::closeUrl( bool promptToSave )
00811 {
00812     return promptToSave ? closeUrl() : ReadOnlyPart::closeUrl();
00813 }
00814 
00815 bool ReadWritePart::save()
00816 {
00817     Q_D(ReadWritePart);
00818 
00819     d->m_saveOk = false;
00820     if ( d->m_file.isEmpty() ) // document was created empty
00821         d->prepareSaving();
00822     if( saveFile() )
00823         return saveToUrl();
00824     else
00825         emit canceled(QString());
00826     return false;
00827 }
00828 
00829 bool ReadWritePart::saveAs( const KUrl & kurl )
00830 {
00831     Q_D(ReadWritePart);
00832 
00833     if (!kurl.isValid())
00834     {
00835         kError(1000) << "saveAs: Malformed URL " << kurl.url() << endl;
00836         return false;
00837     }
00838     d->m_duringSaveAs = true;
00839     d->m_originalURL = d->m_url;
00840     d->m_originalFilePath = d->m_file;
00841     d->m_url = kurl; // Store where to upload in saveToURL
00842     d->prepareSaving();
00843     bool result = save(); // Save local file and upload local file
00844     if (result) {
00845         emit setWindowCaption( d->m_url.prettyUrl() );
00846     } else {
00847         d->m_url = d->m_originalURL;
00848         d->m_file = d->m_originalFilePath;
00849         d->m_duringSaveAs = false;
00850         d->m_originalURL = KUrl();
00851         d->m_originalFilePath.clear();
00852     }
00853 
00854     return result;
00855 }
00856 
00857 // Set m_file correctly for m_url
00858 void ReadWritePartPrivate::prepareSaving()
00859 {
00860     // Local file
00861     if ( m_url.isLocalFile() )
00862     {
00863         if ( m_bTemp ) // get rid of a possible temp file first
00864         {              // (happens if previous url was remote)
00865             unlink( QFile::encodeName(m_file) );
00866             m_bTemp = false;
00867         }
00868         m_file = m_url.path();
00869     }
00870     else
00871     { // Remote file
00872         // We haven't saved yet, or we did but locally - provide a temp file
00873         if ( m_file.isEmpty() || !m_bTemp )
00874         {
00875             KTemporaryFile tempFile;
00876             tempFile.setAutoRemove(false);
00877             tempFile.open();
00878             m_file = tempFile.fileName();
00879             m_bTemp = true;
00880         }
00881         // otherwise, we already had a temp file
00882     }
00883 }
00884 
00885 bool ReadWritePart::saveToUrl()
00886 {
00887     Q_D(ReadWritePart);
00888 
00889     if ( d->m_url.isLocalFile() )
00890     {
00891         setModified( false );
00892         emit completed();
00893         // if m_url is a local file there won't be a temp file -> nothing to remove
00894         assert( !d->m_bTemp );
00895         d->m_saveOk = true;
00896         d->m_duringSaveAs = false;
00897         d->m_originalURL = KUrl();
00898         d->m_originalFilePath.clear();
00899         return true; // Nothing to do
00900     }
00901     else
00902     {
00903         if (d->m_uploadJob)
00904         {
00905             unlink(QFile::encodeName(d->m_uploadJob->srcUrl().path()));
00906             d->m_uploadJob->kill();
00907             d->m_uploadJob = 0;
00908         }
00909         KTemporaryFile *tempFile = new KTemporaryFile();
00910         tempFile->open();
00911         QString uploadFile = tempFile->fileName();
00912         delete tempFile;
00913         KUrl uploadUrl;
00914         uploadUrl.setPath( uploadFile );
00915         // Create hardlink
00916         if (::link(QFile::encodeName(d->m_file), QFile::encodeName(uploadFile)) != 0)
00917         {
00918             // Uh oh, some error happened.
00919             return false;
00920         }
00921         d->m_uploadJob = KIO::file_move( uploadUrl, d->m_url, -1, KIO::Overwrite );
00922         d->m_uploadJob->ui()->setWindow( widget() ? widget()->topLevelWidget() : 0 );
00923         connect( d->m_uploadJob, SIGNAL( result( KJob * ) ), this, SLOT( _k_slotUploadFinished (KJob *) ) );
00924         return true;
00925     }
00926 }
00927 
00928 void ReadWritePartPrivate::_k_slotUploadFinished( KJob * )
00929 {
00930     Q_Q(ReadWritePart);
00931 
00932     if (m_uploadJob->error())
00933     {
00934         unlink(QFile::encodeName(m_uploadJob->srcUrl().path()));
00935         QString error = m_uploadJob->errorString();
00936         m_uploadJob = 0;
00937         if (m_duringSaveAs) {
00938             m_url = m_originalURL;
00939             m_file = m_originalFilePath;
00940         }
00941         emit q->canceled( error );
00942     }
00943     else
00944     {
00945         KUrl dirUrl( m_url );
00946         dirUrl.setPath( dirUrl.directory() );
00947         ::org::kde::KDirNotify::emitFilesAdded( dirUrl.url() );
00948 
00949         m_uploadJob = 0;
00950         q->setModified( false );
00951         emit q->completed();
00952         m_saveOk = true;
00953     }
00954     m_duringSaveAs = false;
00955     m_originalURL = KUrl();
00956     m_originalFilePath.clear();
00957     if (m_waitForSave) {
00958         m_eventLoop.quit();
00959     }
00960 }
00961 
00962 bool ReadWritePart::isReadWrite() const
00963 {
00964     Q_D(const ReadWritePart);
00965 
00966     return d->m_bReadWrite;
00967 }
00968 
00969 bool ReadWritePart::isModified() const
00970 {
00971     Q_D(const ReadWritePart);
00972 
00973     return d->m_bModified;
00974 }
00975 
00976 bool ReadWritePart::waitSaveComplete()
00977 {
00978     Q_D(ReadWritePart);
00979 
00980     if (!d->m_uploadJob)
00981         return d->m_saveOk;
00982 
00983     d->m_waitForSave = true;
00984 
00985     d->m_eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
00986 
00987     d->m_waitForSave = false;
00988 
00989     return d->m_saveOk;
00990 }
00991 
00993 
00994 class KParts::OpenUrlArgumentsPrivate : public QSharedData
00995 {
00996 public:
00997     OpenUrlArgumentsPrivate()
00998         : reload(false),
00999           actionRequestedByUser(true),
01000           xOffset(0),
01001           yOffset(0),
01002           mimeType(),
01003           metaData()
01004     {}
01005     bool reload;
01006     bool actionRequestedByUser;
01007     int xOffset;
01008     int yOffset;
01009     QString mimeType;
01010     QMap<QString, QString> metaData;
01011 };
01012 
01013 KParts::OpenUrlArguments::OpenUrlArguments()
01014     : d(new OpenUrlArgumentsPrivate)
01015 {
01016 }
01017 
01018 KParts::OpenUrlArguments::OpenUrlArguments(const OpenUrlArguments &other)
01019     : d(other.d)
01020 {
01021 }
01022 
01023 KParts::OpenUrlArguments & KParts::OpenUrlArguments::operator=( const OpenUrlArguments &other)
01024 {
01025     d = other.d;
01026     return *this;
01027 }
01028 
01029 KParts::OpenUrlArguments::~OpenUrlArguments()
01030 {
01031 }
01032 
01033 bool KParts::OpenUrlArguments::reload() const
01034 {
01035     return d->reload;
01036 }
01037 
01038 void KParts::OpenUrlArguments::setReload(bool b)
01039 {
01040     d->reload = b;
01041 }
01042 
01043 int KParts::OpenUrlArguments::xOffset() const
01044 {
01045     return d->xOffset;
01046 }
01047 
01048 void KParts::OpenUrlArguments::setXOffset(int x)
01049 {
01050     d->xOffset = x;
01051 }
01052 
01053 int KParts::OpenUrlArguments::yOffset() const
01054 {
01055     return d->yOffset;
01056 }
01057 
01058 void KParts::OpenUrlArguments::setYOffset(int y)
01059 {
01060     d->yOffset = y;
01061 }
01062 
01063 QString KParts::OpenUrlArguments::mimeType() const
01064 {
01065     return d->mimeType;
01066 }
01067 
01068 void KParts::OpenUrlArguments::setMimeType(const QString& mime)
01069 {
01070     d->mimeType = mime;
01071 }
01072 
01073 QMap<QString, QString> & KParts::OpenUrlArguments::metaData()
01074 {
01075     return d->metaData;
01076 }
01077 
01078 const QMap<QString, QString> & KParts::OpenUrlArguments::metaData() const
01079 {
01080     return d->metaData;
01081 }
01082 
01083 bool KParts::OpenUrlArguments::actionRequestedByUser() const
01084 {
01085     return d->actionRequestedByUser;
01086 }
01087 
01088 void KParts::OpenUrlArguments::setActionRequestedByUser(bool userRequested)
01089 {
01090     d->actionRequestedByUser = userRequested;
01091 }
01092 
01093 #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
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
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