/* This file is part of the KDE project
   Copyright (C) 1999 Simon Hausmann <hausmann@kde.org>
             (C) 1999 David Faure <faure@kde.org>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/
#ifndef _KPART_H
#define _KPART_H

#include <QtCore/QPointer>
#include <QtCore/QEvent>
#include <QtCore/QSharedDataPointer>
#include <QtXml/QDomElement> // KDE5: remove

#include <kurl.h>
#include <kxmlguiclient.h>

#include <kparts/kparts_export.h>

#define KPARTS_DECLARE_PRIVATE(Class) \
    inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(PartBase::d_ptr); } \
    inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(PartBase::d_ptr); } \
    friend class Class##Private;

class KIconLoader;
class KComponentData;
class QWidget;
class QEvent;
class QPoint;
struct QUnknownInterface;

class KJob;
namespace KIO {
  class Job;
}

namespace KParts
{

class PartManager;
class Plugin;
class PartPrivate;
class PartActivateEvent;
class PartSelectEvent;
class GUIActivateEvent;
class PartBasePrivate;

/**
 *  @short Base class for all parts.
 */
class KPARTS_EXPORT PartBase : virtual public KXMLGUIClient
{
    KPARTS_DECLARE_PRIVATE(PartBase)

public:

  /**
   *  Constructor.
   */
  PartBase();

  /**
   *  Destructor.
   */
  virtual ~PartBase();

  /**
   *  Internal method. Called by KParts::Part to specify the parent object for plugin objects.
   *
   * @internal
   */
  void setPartObject( QObject *object );
  QObject *partObject() const;

protected:
  /**
   * Set the componentData(KComponentData) for this part.
   *
   * Call this *first* in the inherited class constructor,
   * because it loads the i18n catalogs.
   */
  virtual void setComponentData(const KComponentData &componentData);

  /**
   * Set the componentData(KComponentData) for this part.
   *
   * Call this *first* in the inherited class constructor,
   * because it loads the i18n catalogs.
   *
   * It is recommended to call setComponentData with loadPlugins set to false,
   * and to load plugins at the end of your part constructor (in the case of
   * KParts::MainWindow, plugins are automatically loaded in createGUI anyway,
   * so set loadPlugins to false for KParts::MainWindow as well).
   */
  virtual void setComponentData(const KComponentData &componentData, bool loadPlugins);
  // TODO KDE5: merge the above two methods, using loadPlugins=true. Or better, remove loadPlugins
  // altogether and change plugins to call loadPlugins() manually at the end of their ctor.
    // In the case of KParts MainWindows, plugins are automatically loaded in createGUI anyway,
    // so setComponentData() should really not load the plugins.

  /**
   * We have three different policies, whether to load new plugins or not. The
   * value in the KConfig object of the KComponentData object always overrides
   * LoadPlugins and LoadPluginsIfEnabled.
   */
  enum PluginLoadingMode {
    /**
     * Don't load any plugins at all.
     */
    DoNotLoadPlugins = 0,
    /**
     * Load new plugins automatically. Can be
     * overridden by the plugin if it sets
     * EnabledByDefault=false in the corresponding
     * .desktop file.
     */
    LoadPlugins = 1,
    /**
     * New plugins are disabled by default. Can be
     * overridden by the plugin if it sets
     * EnabledByDefault=true in the corresponding
     * .desktop file.
     */
    LoadPluginsIfEnabled = 2
  };

  /**
   * Load the Plugins honoring the PluginLoadingMode.
   *
   * If you call this method in an already constructed GUI (like when the user
   * has changed which plugins are enabled) you need to add the new plugins to
   * the KXMLGUIFactory:
   * \code
   * if( factory() )
   * {
   *   QList<KParts::Plugin *> plugins = KParts::Plugin::pluginObjects( this );
   *   for(int i = 0; i != plugins.size(); ++i) {
   *      factory()->addClient( plugins[i] );
   *   }
   * }
   * \endcode
   */
  void loadPlugins(QObject *parent, KXMLGUIClient *parentGUIClient, const KComponentData &componentData);

  /**
   * Set how plugins should be loaded
   * @param loadingMode see PluginLoadingMode
   *
   * For a KParts::Part: call this before setComponentData.
   * For a KParts::MainWindow: call this before createGUI.
   */
  void setPluginLoadingMode( PluginLoadingMode loadingMode );

  /**
   * If you change the binary interface offered by your part, you can avoid crashes
   * from old plugins lying around by setting X-KDE-InterfaceVersion=2 in the
   * .desktop files of the plugins, and calling setPluginInterfaceVersion( 2 ), so that
   * the old plugins are not loaded. Increase both numbers every time a
   * binary incompatible change in the application's plugin interface is made.
   *
   * @param version the interface version that plugins must have in order to be loaded.
   *
   * For a KParts::Part: call this before setComponentData.
   * For a KParts::MainWindow: call this before createGUI.
   */
  void setPluginInterfaceVersion( int version );

protected:
  PartBase(PartBasePrivate &dd);

  PartBasePrivate *d_ptr;

private:
  Q_DISABLE_COPY(PartBase)
};

/**
 * Base class for parts.
 *
 * A "part" is a GUI component, featuring:
 * @li A widget embeddedable in any application.
 * @li GUI elements that will be merged in the "host" user interface
 * (menubars, toolbars... ).
 *
 * <b>About the widget:</b>\n
 *
 * Note that KParts::Part does not inherit QWidget.
 * This is due to the fact that the "visual representation"
 * will probably not be a mere QWidget, but an elaborate one.
 * That's why when implementing your KParts::Part (or derived)
 * you should call KParts::Part::setWidget() in your constructor.
 *
 * <b>About the GUI elements:</b>\n
 *
 * Those elements trigger actions, defined by the part ( action()).
 * The layout of the actions in the GUI is defined by an XML file ( setXMLFile()).
 *
 * See also ReadOnlyPart and ReadWritePart, which define the
 * framework for a "viewer" part and for an "editor"-like part.
 * Use Part directly only if your part doesn't fit into those.
 */
class KPARTS_EXPORT Part : public QObject, public PartBase
{
    Q_OBJECT

    KPARTS_DECLARE_PRIVATE(Part)

public:

    /**
     *  Constructor.
     *
     *  @param parent Parent object of the part.
     */
    explicit Part( QObject *parent = 0 );

    /**
     *  Destructor.
     */
    virtual ~Part();

    /**
     * Embed this part into a host widget.
     *
     * You don't need to do this if you created the widget with the
     * correct parent widget - this is just a QWidget::reparent().
     * Note that the Part is still the holder
     * of the QWidget, meaning that if you delete the Part,
     * then the widget gets destroyed as well, and vice-versa.
     * This method is not recommended since creating the widget with the correct
     * parent is simpler anyway.
     */
    virtual void embed( QWidget * parentWidget );

    /**
     * @return The widget defined by this part, set by setWidget().
     */
    virtual QWidget *widget();

    /**
     * @internal
     * Used by the part manager.
     */
    virtual void setManager( PartManager * manager );

    /**
     * Returns the part manager handling this part, if any (0L otherwise).
     */
    PartManager * manager() const;

    /**
     * By default, the widget is deleted by the part when the part is deleted.
     * The hosting application can call setAutoDeleteWidget(false) to
     * disable this behavior, given that the widget is usually deleted by
     * its parent widget anyway.
     * This is a method for the hosting application only, Part subclasses
     * should never call this.
     */
    void setAutoDeleteWidget(bool autoDeleteWidget);

    /**
     * By default, the part deletes itself when its widget is deleted.
     * The hosting application can call setAutoDeletePart(false) to
     * disable this behavior, to be able to delete the widget and then the part,
     * independently.
     * This is a method for the hosting application only, Part subclasses
     * should never call this.
     */
    void setAutoDeletePart(bool autoDeletePart);

    /**
     * Returns the part (this, or a child part) at the given global position.
     * This is called by the part manager to ask whether a part should be activated
     * when clicking somewhere. In most cases the default implementation is enough.
     * Reimplement this if your part has child parts in some areas (like in khtml or koffice)
     * @param widget the part widget being clicked - usually the same as widget(), except in koffice.
     * @param globalPos the mouse coordinates in global coordinates
     */
    virtual Part *hitTest( QWidget *widget, const QPoint &globalPos );

    /**
     *  @param selectable Indicates whether the part is selectable or not.
     */
    virtual void setSelectable( bool selectable );

    /**
     *  Returns whether the part is selectable or not.
     */
    bool isSelectable() const;

    /**
     * Use this icon loader to load any icons that are specific to this part,
     * i.e. icons installed into this part's own directories as opposed to standard
     * kde icons. Use KIcon("myicon", iconLoader()).
     *
     * Make sure to call setComponentData before calling iconLoader.
     */
    KIconLoader* iconLoader();

Q_SIGNALS:
    /**
     * Emitted by the part, to set the caption of the window(s)
     * hosting this part
     */
    void setWindowCaption( const QString & caption );
    /**
     * Emitted by the part, to set a text in the statusbar of the window(s)
     * hosting this part
     */
    void setStatusBarText( const QString & text );

protected:
    /**
     * Set the main widget.
     *
     * Call this in the Part-inherited class constructor.
     */
    virtual void setWidget( QWidget * widget );

    /**
     * @internal
     */
    virtual void customEvent( QEvent *event );

    /**
     * Convenience method which is called when the Part received a PartActivateEvent .
     * Reimplement this if you don't want to reimplement event and test for the event yourself
     * or even install an event filter.
     */
    virtual void partActivateEvent( PartActivateEvent *event );

    /**
     * Convenience method which is called when the Part received a
     * PartSelectEvent .
     * Reimplement this if you don't want to reimplement event and
     * test for the event yourself or even install an event filter.
     */
    virtual void partSelectEvent( PartSelectEvent *event );

    /**
     * Convenience method which is called when the Part received a
     * GUIActivateEvent .
     * Reimplement this if you don't want to reimplement event and
     * test for the event yourself or even install an event filter.
     */
    virtual void guiActivateEvent( GUIActivateEvent *event );

    /**
     * Convenience method for KXMLGUIFactory::container.
     * @return a container widget owned by the Part's GUI.
     */
    QWidget *hostContainer( const QString &containerName );

    /**
     * Load this part's plugins now.
     * Normally you want to call this at the end of the part constructor,
     * if you used setComponentData(componentData, false)
     * @since 4.1
     */
    void loadPlugins();
    using PartBase::loadPlugins;

protected Q_SLOTS:
    /**
     * @internal
     */
    void slotWidgetDestroyed();

protected:
    Part(PartPrivate &dd, QObject *parent);

private:
    Q_DISABLE_COPY(Part)
};

class ReadWritePart;
class ReadOnlyPartPrivate;
class BrowserExtension;
class OpenUrlArgumentsPrivate;

/**
 * OpenUrlArguments is the set of arguments that specify
 * how a URL should be opened by KParts::ReadOnlyPart::openUrl().
 *
 * For instance reload() indicates that the url should be loaded
 * from the network even if it matches the current url of the part.
 *
 * All setter methods in this class are for the class that calls openUrl
 * (usually the hosting application), all the getter methods are for the part.
 */
class KPARTS_EXPORT OpenUrlArguments
{
public:
    OpenUrlArguments();
    OpenUrlArguments(const OpenUrlArguments &other);
    OpenUrlArguments &operator=( const OpenUrlArguments &other);
    ~OpenUrlArguments();

    /**
     * @return true to indicate that the part should reload the URL,
     * i.e. the cache shouldn't be used (forced reload).
     */
    bool reload() const;
    /**
     * Indicates that the url should be loaded
     * from the network even if it matches the current url of the part.
     */
    void setReload(bool b);

    /**
     * xOffset is the horizontal scrolling of the part's widget
     * (in case it's a scrollview). This is saved into the history
     * and restored when going back in the history.
     */
    int xOffset() const;
    void setXOffset(int x);

    /**
     * yOffset is the horizontal scrolling of the part's widget
     * (in case it's a scrollview). This is saved into the history
     * and restored when going back in the history.
     */
    int yOffset() const;
    void setYOffset(int y);

    /**
     * The mimetype to use when opening the url, when known by the calling application.
     */
    QString mimeType() const;
    void setMimeType(const QString& mime);

    /**
     * True if the user requested that the URL be opened.
     * False if the URL should be opened due to an external event, like javascript popups
     * or automatic redirections.
     * This is true by default
     * @since 4.1
     */
    bool actionRequestedByUser() const;
    void setActionRequestedByUser(bool userRequested);

    /**
     * Meta-data to associate with the KIO operation that will be used to open the URL.
     * This method can be used to add or retrieve metadata.
     * @see KIO::TransferJob etc.
     */
    QMap<QString, QString> &metaData();
    const QMap<QString, QString> &metaData() const;

private:
    QSharedDataPointer<OpenUrlArgumentsPrivate> d;
};


/**
 * Base class for any "viewer" part.
 *
 * This class takes care of network transparency for you,
 * in the simplest way (downloading to a temporary file, then letting the part
 * load from the temporary file).
 * To use the built-in network transparency, you only need to implement
 * openFile(), not openUrl().
 *
 * To implement network transparency differently (e.g. for progressive loading,
 * like a web browser does for instance), or to prevent network transparency
 * (but why would you do that?), you can override openUrl().
 *
 * KParts Application can use the signals to show feedback while the URL is being loaded.
 *
 * ReadOnlyPart handles the window caption by setting it to the current URL
 * (set in openUrl(), and each time the part is activated).
 * If you want another caption, set it in openFile() and
 * (if the part might ever be used with a part manager) in guiActivateEvent()
 */
class KPARTS_EXPORT ReadOnlyPart : public Part
{
    Q_OBJECT

    Q_PROPERTY( KUrl url READ url )

    KPARTS_DECLARE_PRIVATE(ReadOnlyPart)

public:
    /**
     * Constructor
     * See also Part for the setXXX methods to call.
     */
    explicit ReadOnlyPart( QObject *parent = 0 );

    /**
     * Destructor
     */
    virtual ~ReadOnlyPart();

    /**
     * Call this to turn off the progress info dialog used by
     * the internal KIO job. Use this if you provide another way
     * of displaying progress info (e.g. a statusbar), using the
     * signals emitted by this class, and/or those emitted by
     * the Job given by started.
     */
    void setProgressInfoEnabled( bool show );

    /**
     * Returns whether the part shows the progress info dialog used by internal
     * KIO job.
     */
    bool isProgressInfoEnabled() const;

#ifndef KDE_NO_COMPAT
    void showProgressInfo( bool show );
#endif

public Q_SLOTS:
    /**
     * Only reimplement openUrl if you don't want the network transparency support
     * to download from the url into a temporary file (when the url isn't local).
     * Otherwise, reimplement openFile() only .
     *
     * If you reimplement it, don't forget to set the caption, usually with
     * emit setWindowCaption( url.prettyUrl() );
     */
    virtual bool openUrl( const KUrl &url );

public:
    /**
     *  Returns the URL currently opened in this part.
     *
     *  @return The current URL.
     */
    KUrl url() const;

    /**
     * Called when closing the current url (e.g. document), for instance
     * when switching to another url (note that openUrl() calls it
     * automatically in this case).
     * If the current URL is not fully loaded yet, aborts loading.
     * Deletes the temporary file used when the url is remote.
     * @return always true, but the return value exists for reimplementations
     */
    virtual bool closeUrl();

    /**
     * This convenience method returns the browserExtension for this part,
     * or 0 if there isn't any.
     */
    BrowserExtension* browserExtension() const;

    /**
     * Sets the arguments to use for the next openUrl call.
     */
    void setArguments(const OpenUrlArguments& arguments);
    // TODO to avoid problems with the case where the loading fails, this could also be a openUrl() argument (heavy porting!).
    // However we need to have setArguments in any case for updated made by the part, see e.g. KHTMLPart::openUrl.
    // Well, maybe we should have setArguments (affects next openurl call) and updateArguments?


    /**
     * @return the arguments that were used to open this URL.
     */
    OpenUrlArguments arguments() const;

public:
    /**
     * Initiate sending data to this part.
     * This is an alternative to openUrl, which allows the user of the part
     * to load the data itself, and send it progressively to the part.
     *
     * @param mimeType the type of data that is going to be sent to this part.
     * @param url the URL representing this data. Although not directly used,
     * every ReadOnlyPart has a URL (see url()), so this simply sets it.
     * @return true if the part supports progressive loading and accepts data, false otherwise.
     */
    bool openStream( const QString& mimeType, const KUrl& url );

    /**
     * Send some data to the part. openStream must have been called previously,
     * and must have returned true.
     * @return true if the data was accepted by the part. If false is returned,
     * the application should stop sending data, and doesn't have to call closeStream.
     */
    bool writeStream( const QByteArray& data );

    /**
     * Terminate the sending of data to the part.
     * With some data types (text, html...) closeStream might never actually be called,
     * in the case of continuous streams, for instance plain text or HTML data.
     */
    bool closeStream();

private: // Makes no sense for inherited classes to call those. But make it protected there.

    /**
     * Called by openStream to initiate sending of data.
     * Parts which implement progress loading should check the @p mimeType
     * parameter, and return true if they can accept a data stream of that type.
     */
    virtual bool doOpenStream( const QString& /*mimeType*/ ) { return false; }
    /**
     * Receive some data from the hosting application.
     * In this method the part should attempt to display the data progressively.
     * With some data types (text, html...) closeStream might never actually be called,
     * in the case of continuous streams. This can't happen with e.g. images.
     */
    virtual bool doWriteStream( const QByteArray& /*data*/ ) { return false; }
    /**
     * This is called by closeStream(), to indicate that all the data has been sent.
     * Parts should ensure that all of the data is displayed at this point.
     * @return whether the data could be displayed correctly.
     */
    virtual bool doCloseStream() { return false; }

Q_SIGNALS:
    /**
     * The part emits this when starting data.
     * If using a KIO::Job, it sets the job in the signal, so that
     * progress information can be shown. Otherwise, job is 0.
     **/
    void started( KIO::Job * );

    /**
     * Emit this when you have completed loading data.
     * Hosting apps will want to know when the process of loading the data
     * is finished, so that they can access the data when everything is loaded.
     **/
    void completed();

    /**
     * Same as the above signal except it indicates whether there is
     * a pending action to be executed on a delay timer. An example of
     * this is the meta-refresh tags on web pages used to reload/redirect
     * after a certain period of time. This signal is useful if you want
     * to give the user the ability to cancel such pending actions.
     *
     * @p pendingAction true if a pending action exists, false otherwise.
     */
    void completed( bool pendingAction );

    /**
     * Emit this if loading is canceled by the user or by an error.
     * @param errMsg the error message, empty if the user canceled the loading voluntarily.
     */
    void canceled( const QString &errMsg );

protected:
    /**
     * If the part uses the standard implementation of openUrl(),
     * it must reimplement this, to open the local file.
     * The default implementation is simply { return false; }
     */
    virtual bool openFile();

    /**
     * @internal
     */
    void abortLoad();

    /**
     * Reimplemented from Part, so that the window caption is set to
     * the current url (decoded) when the part is activated
     * This is the usual behavior in 99% of the apps
     * Reimplement if you don't like it - test for event->activated() !
     *
     * Technical note : this is done with GUIActivateEvent and not with
     * PartActivateEvent because it's handled by the mainwindow
     * (which gets the even after the PartActivateEvent events have been sent)
     */
    virtual void guiActivateEvent( GUIActivateEvent *event );

    /**
     * @internal
     */
#ifndef KDE_NO_DEPRECATED
    KDE_DEPRECATED bool isLocalFileTemporary() const;
#endif

    /**
     * @internal
     */
#ifndef KDE_NO_DEPRECATED
    KDE_DEPRECATED void setLocalFileTemporary( bool temp );
#endif

    /**
     * Sets the url associated with this part.
     */
    void setUrl(const KUrl &url);

    /**
     * Returns the local file path associated with this part.
     */
    QString localFilePath() const;

    /**
     * Sets the local file path associated with this part.
     */
    void setLocalFilePath( const QString &localFilePath );

protected:
    ReadOnlyPart(ReadOnlyPartPrivate &dd, QObject *parent);

private:
    Q_PRIVATE_SLOT(d_func(), void _k_slotJobFinished( KJob * job ))
    Q_PRIVATE_SLOT(d_func(), void _k_slotStatJobFinished(KJob*))
    Q_PRIVATE_SLOT(d_func(), void _k_slotGotMimeType(KIO::Job *job, const QString &mime))

    Q_DISABLE_COPY(ReadOnlyPart)
};
class ReadWritePartPrivate;

/**
 * Base class for an "editor" part.
 *
 * This class handles network transparency for you.
 * Anything that can open a URL, allow modifications, and save
 * (to the same URL or a different one).
 *
 * A read-write part can be set to read-only mode, using setReadWrite().
 *
 * Part writers :
 * Any part inheriting ReadWritePart should check isReadWrite
 * before allowing any action that modifies the part.
 * The part probably wants to reimplement setReadWrite, disable those
 * actions. Don't forget to call the parent setReadWrite.
 */
class KPARTS_EXPORT ReadWritePart : public ReadOnlyPart
{
    Q_OBJECT

    KPARTS_DECLARE_PRIVATE(ReadWritePart)

public:
    /**
     * Constructor
     * See parent constructor for instructions.
     */
    explicit ReadWritePart( QObject *parent = 0 );
    /**
     * Destructor
     * Applications using a ReadWritePart should make sure, before
     * destroying it, to call closeUrl().
     * In KMainWindow::queryClose(), for instance, they should allow
     * closing only if the return value of closeUrl() was true.
     * This allows to cancel.
     */
    virtual ~ReadWritePart();

    /**
     * @return true if the part is in read-write mode
     */
    bool isReadWrite() const;

    /**
     * Changes the behavior of this part to readonly or readwrite.
     * @param readwrite set to true to enable readwrite mode
     */
    virtual void setReadWrite ( bool readwrite = true );

    /**
     * @return true if the document has been modified.
     */
    bool isModified() const;

    /**
     * If the document has been modified, ask the user to save changes.
     * This method is meant to be called from KMainWindow::queryClose().
     * It will also be called from closeUrl().
     *
     * @return true if closeUrl() can be called without the user losing
     * important data, false if the user chooses to cancel.
     */
    virtual bool queryClose();

    /**
     * Called when closing the current url (e.g. document), for instance
     * when switching to another url (note that openUrl() calls it
     * automatically in this case).
     *
     * If the current URL is not fully loaded yet, aborts loading.
     *
     * If isModified(), queryClose() will be called.
     *
     * @return false on cancel
     */
    virtual bool closeUrl();

    /**
     * Call this method instead of the above if you need control if
     * the save prompt is shown. For example, if you call queryClose()
     * from KMainWindow::queryClose(), you would not want to prompt
     * again when closing the url.
     *
     * Equivalent to promptToSave ? closeUrl() : ReadOnlyPart::closeUrl()
     */
    virtual bool closeUrl( bool promptToSave );

    /**
     * Save the file to a new location.
     *
     * Calls save(), no need to reimplement
     */
    virtual bool saveAs( const KUrl &url );

    /**
     *  Sets the modified flag of the part.
     */
    virtual void setModified( bool modified );

Q_SIGNALS:
    /**
     * set handled to true, if you don't want the default handling
     * set abortClosing to true, if you handled the request,
     * but for any reason don't  want to allow closing the document
     */
    void sigQueryClose(bool *handled, bool* abortClosing);

public Q_SLOTS:
    /**
     * Call setModified() whenever the contents get modified.
     * This is a slot for convenience, since it simply calls setModified(true),
     * so that you can connect it to a signal, like textChanged().
     */
    void setModified();

    /**
     * Save the file in the location from which it was opened.
     * You can connect this to the "save" action.
     * Calls saveFile() and saveToUrl(), no need to reimplement.
     */
    virtual bool save();

    /**
     * Waits for any pending upload job to finish and returns whether the
     * last save() action was successful.
     */
    bool waitSaveComplete();

protected:
    /**
     * Save to a local file.
     * You need to implement it, to save to the local file.
     * The framework takes care of re-uploading afterwards.
     *
     * @return true on success, false on failure.
     * On failure the function should inform the user about the
     * problem with an appropriate message box. Standard error
     * messages can be constructed using KIO::buildErrorString()
     * in combination with the error codes defined in kio/global.h
     */
    virtual bool saveFile() = 0;

    /**
     * Save the file.
     *
     * Uploads the file, if @p url is remote.
     * This will emit started(), and either completed() or canceled(),
     * in case you want to provide feedback.
     * @return true on success, false on failure.
     */
    virtual bool saveToUrl();

private:
    Q_PRIVATE_SLOT(d_func(), void _k_slotUploadFinished( KJob * job ))

    Q_DISABLE_COPY(ReadWritePart)
};

} // namespace


#undef KPARTS_DECLARE_PRIVATE

#endif
