1/* This file is part of the KDE project
2 Copyright (C) 1999 Simon Hausmann <hausmann@kde.org>
3 (C) 1999 David Faure <faure@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20#ifndef _KPART_H
21#define _KPART_H
22
23#include <QtCore/QPointer>
24#include <QtCore/QEvent>
25#include <QtCore/QSharedDataPointer>
26#include <QtXml/QDomElement> // KDE5: remove
27
28#include <kurl.h>
29#include <kxmlguiclient.h>
30
31#include <kparts/kparts_export.h>
32
33#define KPARTS_DECLARE_PRIVATE(Class) \
34 inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(PartBase::d_ptr); } \
35 inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(PartBase::d_ptr); } \
36 friend class Class##Private;
37
38class KIconLoader;
39class KComponentData;
40class QWidget;
41class QEvent;
42class QPoint;
43struct QUnknownInterface;
44
45class KJob;
46namespace KIO {
47 class Job;
48}
49
50namespace KParts
51{
52
53class PartManager;
54class Plugin;
55class PartPrivate;
56class PartActivateEvent;
57class PartSelectEvent;
58class GUIActivateEvent;
59class PartBasePrivate;
60
61/**
62 * @short Base class for all parts.
63 */
64class KPARTS_EXPORT PartBase : virtual public KXMLGUIClient
65{
66 KPARTS_DECLARE_PRIVATE(PartBase)
67
68public:
69
70 /**
71 * Constructor.
72 */
73 PartBase();
74
75 /**
76 * Destructor.
77 */
78 virtual ~PartBase();
79
80 /**
81 * Internal method. Called by KParts::Part to specify the parent object for plugin objects.
82 *
83 * @internal
84 */
85 void setPartObject( QObject *object );
86 QObject *partObject() const;
87
88protected:
89 /**
90 * Set the componentData(KComponentData) for this part.
91 *
92 * Call this *first* in the inherited class constructor,
93 * because it loads the i18n catalogs.
94 */
95 virtual void setComponentData(const KComponentData &componentData);
96
97 /**
98 * Set the componentData(KComponentData) for this part.
99 *
100 * Call this *first* in the inherited class constructor,
101 * because it loads the i18n catalogs.
102 *
103 * It is recommended to call setComponentData with loadPlugins set to false,
104 * and to load plugins at the end of your part constructor (in the case of
105 * KParts::MainWindow, plugins are automatically loaded in createGUI anyway,
106 * so set loadPlugins to false for KParts::MainWindow as well).
107 */
108 virtual void setComponentData(const KComponentData &componentData, bool loadPlugins);
109 // TODO KDE5: merge the above two methods, using loadPlugins=true. Or better, remove loadPlugins
110 // altogether and change plugins to call loadPlugins() manually at the end of their ctor.
111 // In the case of KParts MainWindows, plugins are automatically loaded in createGUI anyway,
112 // so setComponentData() should really not load the plugins.
113
114 /**
115 * We have three different policies, whether to load new plugins or not. The
116 * value in the KConfig object of the KComponentData object always overrides
117 * LoadPlugins and LoadPluginsIfEnabled.
118 */
119 enum PluginLoadingMode {
120 /**
121 * Don't load any plugins at all.
122 */
123 DoNotLoadPlugins = 0,
124 /**
125 * Load new plugins automatically. Can be
126 * overridden by the plugin if it sets
127 * EnabledByDefault=false in the corresponding
128 * .desktop file.
129 */
130 LoadPlugins = 1,
131 /**
132 * New plugins are disabled by default. Can be
133 * overridden by the plugin if it sets
134 * EnabledByDefault=true in the corresponding
135 * .desktop file.
136 */
137 LoadPluginsIfEnabled = 2
138 };
139
140 /**
141 * Load the Plugins honoring the PluginLoadingMode.
142 *
143 * If you call this method in an already constructed GUI (like when the user
144 * has changed which plugins are enabled) you need to add the new plugins to
145 * the KXMLGUIFactory:
146 * \code
147 * if( factory() )
148 * {
149 * QList<KParts::Plugin *> plugins = KParts::Plugin::pluginObjects( this );
150 * for(int i = 0; i != plugins.size(); ++i) {
151 * factory()->addClient( plugins[i] );
152 * }
153 * }
154 * \endcode
155 */
156 void loadPlugins(QObject *parent, KXMLGUIClient *parentGUIClient, const KComponentData &componentData);
157
158 /**
159 * Set how plugins should be loaded
160 * @param loadingMode see PluginLoadingMode
161 *
162 * For a KParts::Part: call this before setComponentData.
163 * For a KParts::MainWindow: call this before createGUI.
164 */
165 void setPluginLoadingMode( PluginLoadingMode loadingMode );
166
167 /**
168 * If you change the binary interface offered by your part, you can avoid crashes
169 * from old plugins lying around by setting X-KDE-InterfaceVersion=2 in the
170 * .desktop files of the plugins, and calling setPluginInterfaceVersion( 2 ), so that
171 * the old plugins are not loaded. Increase both numbers every time a
172 * binary incompatible change in the application's plugin interface is made.
173 *
174 * @param version the interface version that plugins must have in order to be loaded.
175 *
176 * For a KParts::Part: call this before setComponentData.
177 * For a KParts::MainWindow: call this before createGUI.
178 */
179 void setPluginInterfaceVersion( int version );
180
181protected:
182 PartBase(PartBasePrivate &dd);
183
184 PartBasePrivate *d_ptr;
185
186private:
187 Q_DISABLE_COPY(PartBase)
188};
189
190/**
191 * Base class for parts.
192 *
193 * A "part" is a GUI component, featuring:
194 * @li A widget embeddedable in any application.
195 * @li GUI elements that will be merged in the "host" user interface
196 * (menubars, toolbars... ).
197 *
198 * <b>About the widget:</b>\n
199 *
200 * Note that KParts::Part does not inherit QWidget.
201 * This is due to the fact that the "visual representation"
202 * will probably not be a mere QWidget, but an elaborate one.
203 * That's why when implementing your KParts::Part (or derived)
204 * you should call KParts::Part::setWidget() in your constructor.
205 *
206 * <b>About the GUI elements:</b>\n
207 *
208 * Those elements trigger actions, defined by the part ( action()).
209 * The layout of the actions in the GUI is defined by an XML file ( setXMLFile()).
210 *
211 * See also ReadOnlyPart and ReadWritePart, which define the
212 * framework for a "viewer" part and for an "editor"-like part.
213 * Use Part directly only if your part doesn't fit into those.
214 */
215class KPARTS_EXPORT Part : public QObject, public PartBase
216{
217 Q_OBJECT
218
219 KPARTS_DECLARE_PRIVATE(Part)
220
221public:
222
223 /**
224 * Constructor.
225 *
226 * @param parent Parent object of the part.
227 */
228 explicit Part( QObject *parent = 0 );
229
230 /**
231 * Destructor.
232 */
233 virtual ~Part();
234
235 /**
236 * Embed this part into a host widget.
237 *
238 * You don't need to do this if you created the widget with the
239 * correct parent widget - this is just a QWidget::reparent().
240 * Note that the Part is still the holder
241 * of the QWidget, meaning that if you delete the Part,
242 * then the widget gets destroyed as well, and vice-versa.
243 * This method is not recommended since creating the widget with the correct
244 * parent is simpler anyway.
245 */
246 virtual void embed( QWidget * parentWidget );
247
248 /**
249 * @return The widget defined by this part, set by setWidget().
250 */
251 virtual QWidget *widget();
252
253 /**
254 * @internal
255 * Used by the part manager.
256 */
257 virtual void setManager( PartManager * manager );
258
259 /**
260 * Returns the part manager handling this part, if any (0L otherwise).
261 */
262 PartManager * manager() const;
263
264 /**
265 * By default, the widget is deleted by the part when the part is deleted.
266 * The hosting application can call setAutoDeleteWidget(false) to
267 * disable this behavior, given that the widget is usually deleted by
268 * its parent widget anyway.
269 * This is a method for the hosting application only, Part subclasses
270 * should never call this.
271 */
272 void setAutoDeleteWidget(bool autoDeleteWidget);
273
274 /**
275 * By default, the part deletes itself when its widget is deleted.
276 * The hosting application can call setAutoDeletePart(false) to
277 * disable this behavior, to be able to delete the widget and then the part,
278 * independently.
279 * This is a method for the hosting application only, Part subclasses
280 * should never call this.
281 */
282 void setAutoDeletePart(bool autoDeletePart);
283
284 /**
285 * Returns the part (this, or a child part) at the given global position.
286 * This is called by the part manager to ask whether a part should be activated
287 * when clicking somewhere. In most cases the default implementation is enough.
288 * Reimplement this if your part has child parts in some areas (like in khtml or koffice)
289 * @param widget the part widget being clicked - usually the same as widget(), except in koffice.
290 * @param globalPos the mouse coordinates in global coordinates
291 */
292 virtual Part *hitTest( QWidget *widget, const QPoint &globalPos );
293
294 /**
295 * @param selectable Indicates whether the part is selectable or not.
296 */
297 virtual void setSelectable( bool selectable );
298
299 /**
300 * Returns whether the part is selectable or not.
301 */
302 bool isSelectable() const;
303
304 /**
305 * Use this icon loader to load any icons that are specific to this part,
306 * i.e. icons installed into this part's own directories as opposed to standard
307 * kde icons. Use KIcon("myicon", iconLoader()).
308 *
309 * Make sure to call setComponentData before calling iconLoader.
310 */
311 KIconLoader* iconLoader();
312
313Q_SIGNALS:
314 /**
315 * Emitted by the part, to set the caption of the window(s)
316 * hosting this part
317 */
318 void setWindowCaption( const QString & caption );
319 /**
320 * Emitted by the part, to set a text in the statusbar of the window(s)
321 * hosting this part
322 */
323 void setStatusBarText( const QString & text );
324
325protected:
326 /**
327 * Set the main widget.
328 *
329 * Call this in the Part-inherited class constructor.
330 */
331 virtual void setWidget( QWidget * widget );
332
333 /**
334 * @internal
335 */
336 virtual void customEvent( QEvent *event );
337
338 /**
339 * Convenience method which is called when the Part received a PartActivateEvent .
340 * Reimplement this if you don't want to reimplement event and test for the event yourself
341 * or even install an event filter.
342 */
343 virtual void partActivateEvent( PartActivateEvent *event );
344
345 /**
346 * Convenience method which is called when the Part received a
347 * PartSelectEvent .
348 * Reimplement this if you don't want to reimplement event and
349 * test for the event yourself or even install an event filter.
350 */
351 virtual void partSelectEvent( PartSelectEvent *event );
352
353 /**
354 * Convenience method which is called when the Part received a
355 * GUIActivateEvent .
356 * Reimplement this if you don't want to reimplement event and
357 * test for the event yourself or even install an event filter.
358 */
359 virtual void guiActivateEvent( GUIActivateEvent *event );
360
361 /**
362 * Convenience method for KXMLGUIFactory::container.
363 * @return a container widget owned by the Part's GUI.
364 */
365 QWidget *hostContainer( const QString &containerName );
366
367 /**
368 * Load this part's plugins now.
369 * Normally you want to call this at the end of the part constructor,
370 * if you used setComponentData(componentData, false)
371 * @since 4.1
372 */
373 void loadPlugins();
374 using PartBase::loadPlugins;
375
376protected Q_SLOTS:
377 /**
378 * @internal
379 */
380 void slotWidgetDestroyed();
381
382protected:
383 Part(PartPrivate &dd, QObject *parent);
384
385private:
386 Q_DISABLE_COPY(Part)
387};
388
389class ReadWritePart;
390class ReadOnlyPartPrivate;
391class BrowserExtension;
392class OpenUrlArgumentsPrivate;
393
394/**
395 * OpenUrlArguments is the set of arguments that specify
396 * how a URL should be opened by KParts::ReadOnlyPart::openUrl().
397 *
398 * For instance reload() indicates that the url should be loaded
399 * from the network even if it matches the current url of the part.
400 *
401 * All setter methods in this class are for the class that calls openUrl
402 * (usually the hosting application), all the getter methods are for the part.
403 */
404class KPARTS_EXPORT OpenUrlArguments
405{
406public:
407 OpenUrlArguments();
408 OpenUrlArguments(const OpenUrlArguments &other);
409 OpenUrlArguments &operator=( const OpenUrlArguments &other);
410 ~OpenUrlArguments();
411
412 /**
413 * @return true to indicate that the part should reload the URL,
414 * i.e. the cache shouldn't be used (forced reload).
415 */
416 bool reload() const;
417 /**
418 * Indicates that the url should be loaded
419 * from the network even if it matches the current url of the part.
420 */
421 void setReload(bool b);
422
423 /**
424 * xOffset is the horizontal scrolling of the part's widget
425 * (in case it's a scrollview). This is saved into the history
426 * and restored when going back in the history.
427 */
428 int xOffset() const;
429 void setXOffset(int x);
430
431 /**
432 * yOffset is the vertical scrolling of the part's widget
433 * (in case it's a scrollview). This is saved into the history
434 * and restored when going back in the history.
435 */
436 int yOffset() const;
437 void setYOffset(int y);
438
439 /**
440 * The mimetype to use when opening the url, when known by the calling application.
441 */
442 QString mimeType() const;
443 void setMimeType(const QString& mime);
444
445 /**
446 * True if the user requested that the URL be opened.
447 * False if the URL should be opened due to an external event, like javascript popups
448 * or automatic redirections.
449 * This is true by default
450 * @since 4.1
451 */
452 bool actionRequestedByUser() const;
453 void setActionRequestedByUser(bool userRequested);
454
455 /**
456 * Meta-data to associate with the KIO operation that will be used to open the URL.
457 * This method can be used to add or retrieve metadata.
458 * @see KIO::TransferJob etc.
459 */
460 QMap<QString, QString> &metaData();
461 const QMap<QString, QString> &metaData() const;
462
463private:
464 QSharedDataPointer<OpenUrlArgumentsPrivate> d;
465};
466
467
468/**
469 * Base class for any "viewer" part.
470 *
471 * This class takes care of network transparency for you,
472 * in the simplest way (downloading to a temporary file, then letting the part
473 * load from the temporary file).
474 * To use the built-in network transparency, you only need to implement
475 * openFile(), not openUrl().
476 *
477 * To implement network transparency differently (e.g. for progressive loading,
478 * like a web browser does for instance), or to prevent network transparency
479 * (but why would you do that?), you can override openUrl().
480 *
481 * KParts Application can use the signals to show feedback while the URL is being loaded.
482 *
483 * ReadOnlyPart handles the window caption by setting it to the current URL
484 * (set in openUrl(), and each time the part is activated).
485 * If you want another caption, set it in openFile() and
486 * (if the part might ever be used with a part manager) in guiActivateEvent()
487 */
488class KPARTS_EXPORT ReadOnlyPart : public Part
489{
490 Q_OBJECT
491
492 Q_PROPERTY( KUrl url READ url )
493
494 KPARTS_DECLARE_PRIVATE(ReadOnlyPart)
495
496public:
497 /**
498 * Constructor
499 * See also Part for the setXXX methods to call.
500 */
501 explicit ReadOnlyPart( QObject *parent = 0 );
502
503 /**
504 * Destructor
505 */
506 virtual ~ReadOnlyPart();
507
508 /**
509 * Call this to turn off the progress info dialog used by
510 * the internal KIO job. Use this if you provide another way
511 * of displaying progress info (e.g. a statusbar), using the
512 * signals emitted by this class, and/or those emitted by
513 * the Job given by started.
514 */
515 void setProgressInfoEnabled( bool show );
516
517 /**
518 * Returns whether the part shows the progress info dialog used by internal
519 * KIO job.
520 */
521 bool isProgressInfoEnabled() const;
522
523#ifndef KDE_NO_COMPAT
524 void showProgressInfo( bool show );
525#endif
526
527public Q_SLOTS:
528 /**
529 * Only reimplement openUrl if you don't want the network transparency support
530 * to download from the url into a temporary file (when the url isn't local).
531 * Otherwise, reimplement openFile() only .
532 *
533 * If you reimplement it, don't forget to set the caption, usually with
534 * emit setWindowCaption( url.prettyUrl() );
535 */
536 virtual bool openUrl( const KUrl &url );
537
538public:
539 /**
540 * Returns the URL currently opened in this part.
541 *
542 * @return The current URL.
543 */
544 KUrl url() const;
545
546 /**
547 * Called when closing the current url (e.g. document), for instance
548 * when switching to another url (note that openUrl() calls it
549 * automatically in this case).
550 * If the current URL is not fully loaded yet, aborts loading.
551 * Deletes the temporary file used when the url is remote.
552 * @return always true, but the return value exists for reimplementations
553 */
554 virtual bool closeUrl();
555
556 /**
557 * This convenience method returns the browserExtension for this part,
558 * or 0 if there isn't any.
559 */
560 BrowserExtension* browserExtension() const;
561
562 /**
563 * Sets the arguments to use for the next openUrl call.
564 */
565 void setArguments(const OpenUrlArguments& arguments);
566 // TODO to avoid problems with the case where the loading fails, this could also be a openUrl() argument (heavy porting!).
567 // However we need to have setArguments in any case for updated made by the part, see e.g. KHTMLPart::openUrl.
568 // Well, maybe we should have setArguments (affects next openurl call) and updateArguments?
569
570
571 /**
572 * @return the arguments that were used to open this URL.
573 */
574 OpenUrlArguments arguments() const;
575
576public:
577 /**
578 * Initiate sending data to this part.
579 * This is an alternative to openUrl, which allows the user of the part
580 * to load the data itself, and send it progressively to the part.
581 *
582 * @param mimeType the type of data that is going to be sent to this part.
583 * @param url the URL representing this data. Although not directly used,
584 * every ReadOnlyPart has a URL (see url()), so this simply sets it.
585 * @return true if the part supports progressive loading and accepts data, false otherwise.
586 */
587 bool openStream( const QString& mimeType, const KUrl& url );
588
589 /**
590 * Send some data to the part. openStream must have been called previously,
591 * and must have returned true.
592 * @return true if the data was accepted by the part. If false is returned,
593 * the application should stop sending data, and doesn't have to call closeStream.
594 */
595 bool writeStream( const QByteArray& data );
596
597 /**
598 * Terminate the sending of data to the part.
599 * With some data types (text, html...) closeStream might never actually be called,
600 * in the case of continuous streams, for instance plain text or HTML data.
601 */
602 bool closeStream();
603
604private: // Makes no sense for inherited classes to call those. But make it protected there.
605
606 /**
607 * Called by openStream to initiate sending of data.
608 * Parts which implement progress loading should check the @p mimeType
609 * parameter, and return true if they can accept a data stream of that type.
610 */
611 virtual bool doOpenStream( const QString& /*mimeType*/ ) { return false; }
612 /**
613 * Receive some data from the hosting application.
614 * In this method the part should attempt to display the data progressively.
615 * With some data types (text, html...) closeStream might never actually be called,
616 * in the case of continuous streams. This can't happen with e.g. images.
617 */
618 virtual bool doWriteStream( const QByteArray& /*data*/ ) { return false; }
619 /**
620 * This is called by closeStream(), to indicate that all the data has been sent.
621 * Parts should ensure that all of the data is displayed at this point.
622 * @return whether the data could be displayed correctly.
623 */
624 virtual bool doCloseStream() { return false; }
625
626Q_SIGNALS:
627 /**
628 * The part emits this when starting data.
629 * If using a KIO::Job, it sets the job in the signal, so that
630 * progress information can be shown. Otherwise, job is 0.
631 **/
632 void started( KIO::Job * );
633
634 /**
635 * Emit this when you have completed loading data.
636 * Hosting apps will want to know when the process of loading the data
637 * is finished, so that they can access the data when everything is loaded.
638 **/
639 void completed();
640
641 /**
642 * Same as the above signal except it indicates whether there is
643 * a pending action to be executed on a delay timer. An example of
644 * this is the meta-refresh tags on web pages used to reload/redirect
645 * after a certain period of time. This signal is useful if you want
646 * to give the user the ability to cancel such pending actions.
647 *
648 * @p pendingAction true if a pending action exists, false otherwise.
649 */
650 void completed( bool pendingAction );
651
652 /**
653 * Emit this if loading is canceled by the user or by an error.
654 * @param errMsg the error message, empty if the user canceled the loading voluntarily.
655 */
656 void canceled( const QString &errMsg );
657
658 /**
659 * Emitted by the part when url() changes
660 * @since 4.10
661 */
662 void urlChanged( const KUrl & url );
663
664protected:
665 /**
666 * If the part uses the standard implementation of openUrl(),
667 * it must reimplement this, to open the local file.
668 * The default implementation is simply { return false; }
669 */
670 virtual bool openFile();
671
672 /**
673 * @internal
674 */
675 void abortLoad();
676
677 /**
678 * Reimplemented from Part, so that the window caption is set to
679 * the current url (decoded) when the part is activated
680 * This is the usual behavior in 99% of the apps
681 * Reimplement if you don't like it - test for event->activated() !
682 *
683 * Technical note : this is done with GUIActivateEvent and not with
684 * PartActivateEvent because it's handled by the mainwindow
685 * (which gets the even after the PartActivateEvent events have been sent)
686 */
687 virtual void guiActivateEvent( GUIActivateEvent *event );
688
689 /**
690 * @internal
691 */
692#ifndef KDE_NO_DEPRECATED
693 KDE_DEPRECATED bool isLocalFileTemporary() const;
694#endif
695
696 /**
697 * @internal
698 */
699#ifndef KDE_NO_DEPRECATED
700 KDE_DEPRECATED void setLocalFileTemporary( bool temp );
701#endif
702
703 /**
704 * Sets the url associated with this part.
705 */
706 void setUrl(const KUrl &url);
707
708 /**
709 * Returns the local file path associated with this part.
710 */
711 QString localFilePath() const;
712
713 /**
714 * Sets the local file path associated with this part.
715 */
716 void setLocalFilePath( const QString &localFilePath );
717
718protected:
719 ReadOnlyPart(ReadOnlyPartPrivate &dd, QObject *parent);
720
721private:
722 Q_PRIVATE_SLOT(d_func(), void _k_slotJobFinished( KJob * job ))
723 Q_PRIVATE_SLOT(d_func(), void _k_slotStatJobFinished(KJob*))
724 Q_PRIVATE_SLOT(d_func(), void _k_slotGotMimeType(KIO::Job *job, const QString &mime))
725
726 Q_DISABLE_COPY(ReadOnlyPart)
727};
728class ReadWritePartPrivate;
729
730/**
731 * Base class for an "editor" part.
732 *
733 * This class handles network transparency for you.
734 * Anything that can open a URL, allow modifications, and save
735 * (to the same URL or a different one).
736 *
737 * A read-write part can be set to read-only mode, using setReadWrite().
738 *
739 * Part writers :
740 * Any part inheriting ReadWritePart should check isReadWrite
741 * before allowing any action that modifies the part.
742 * The part probably wants to reimplement setReadWrite, disable those
743 * actions. Don't forget to call the parent setReadWrite.
744 */
745class KPARTS_EXPORT ReadWritePart : public ReadOnlyPart
746{
747 Q_OBJECT
748
749 KPARTS_DECLARE_PRIVATE(ReadWritePart)
750
751public:
752 /**
753 * Constructor
754 * See parent constructor for instructions.
755 */
756 explicit ReadWritePart( QObject *parent = 0 );
757 /**
758 * Destructor
759 * Applications using a ReadWritePart should make sure, before
760 * destroying it, to call closeUrl().
761 * In KMainWindow::queryClose(), for instance, they should allow
762 * closing only if the return value of closeUrl() was true.
763 * This allows to cancel.
764 */
765 virtual ~ReadWritePart();
766
767 /**
768 * @return true if the part is in read-write mode
769 */
770 bool isReadWrite() const;
771
772 /**
773 * Changes the behavior of this part to readonly or readwrite.
774 * @param readwrite set to true to enable readwrite mode
775 */
776 virtual void setReadWrite ( bool readwrite = true );
777
778 /**
779 * @return true if the document has been modified.
780 */
781 bool isModified() const;
782
783 /**
784 * If the document has been modified, ask the user to save changes.
785 * This method is meant to be called from KMainWindow::queryClose().
786 * It will also be called from closeUrl().
787 *
788 * @return true if closeUrl() can be called without the user losing
789 * important data, false if the user chooses to cancel.
790 */
791 virtual bool queryClose();
792
793 /**
794 * Called when closing the current url (e.g. document), for instance
795 * when switching to another url (note that openUrl() calls it
796 * automatically in this case).
797 *
798 * If the current URL is not fully loaded yet, aborts loading.
799 *
800 * If isModified(), queryClose() will be called.
801 *
802 * @return false on cancel
803 */
804 virtual bool closeUrl();
805
806 /**
807 * Call this method instead of the above if you need control if
808 * the save prompt is shown. For example, if you call queryClose()
809 * from KMainWindow::queryClose(), you would not want to prompt
810 * again when closing the url.
811 *
812 * Equivalent to promptToSave ? closeUrl() : ReadOnlyPart::closeUrl()
813 */
814 virtual bool closeUrl( bool promptToSave );
815
816 /**
817 * Save the file to a new location.
818 *
819 * Calls save(), no need to reimplement
820 */
821 virtual bool saveAs( const KUrl &url );
822
823 /**
824 * Sets the modified flag of the part.
825 */
826 virtual void setModified( bool modified );
827
828Q_SIGNALS:
829 /**
830 * set handled to true, if you don't want the default handling
831 * set abortClosing to true, if you handled the request,
832 * but for any reason don't want to allow closing the document
833 */
834 void sigQueryClose(bool *handled, bool* abortClosing);
835
836public Q_SLOTS:
837 /**
838 * Call setModified() whenever the contents get modified.
839 * This is a slot for convenience, since it simply calls setModified(true),
840 * so that you can connect it to a signal, like textChanged().
841 */
842 void setModified();
843
844 /**
845 * Save the file in the location from which it was opened.
846 * You can connect this to the "save" action.
847 * Calls saveFile() and saveToUrl(), no need to reimplement.
848 */
849 virtual bool save();
850
851 /**
852 * Waits for any pending upload job to finish and returns whether the
853 * last save() action was successful.
854 */
855 bool waitSaveComplete();
856
857protected:
858 /**
859 * Save to a local file.
860 * You need to implement it, to save to the local file.
861 * The framework takes care of re-uploading afterwards.
862 *
863 * @return true on success, false on failure.
864 * On failure the function should inform the user about the
865 * problem with an appropriate message box. Standard error
866 * messages can be constructed using KIO::buildErrorString()
867 * in combination with the error codes defined in kio/global.h
868 */
869 virtual bool saveFile() = 0;
870
871 /**
872 * Save the file.
873 *
874 * Uploads the file, if @p url is remote.
875 * This will emit started(), and either completed() or canceled(),
876 * in case you want to provide feedback.
877 * @return true on success, false on failure.
878 */
879 virtual bool saveToUrl();
880
881private:
882 Q_PRIVATE_SLOT(d_func(), void _k_slotUploadFinished( KJob * job ))
883
884 Q_DISABLE_COPY(ReadWritePart)
885};
886
887} // namespace
888
889
890#undef KPARTS_DECLARE_PRIVATE
891
892#endif
893