[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-core-devel
Subject:    Improving ktexteditor interface (patch included)
From:       Philippe Fremy <phil () freehackers ! org>
Date:       2007-08-18 11:51:19
Message-ID: 46C6DD37.2060103 () freehackers ! org
[Download RAW message or body]

Hi,

I propose the following patch to improve the ktexteditor interface.

The current ktexteditor interface is based on a master -> slave
relationship. The kpart host decides what to do (open documents, open
views, close them, ...) and the kpart component obeys.

When working with Yzis (a vi engine for text editing, see
http://www.yzis.org ), this does not work very well because Yzis is not
a good slave. It wants to do stuff on his own:
- with :edit some_file.txt , the kpart wants to open a new document and
a new view
- with :bdelete, the kpart wants to remove a document and a view
- with :bnext, the kpart wants to change the active view

The patch allows the kpart host to set a class instance, which can be
used for kpart component to kpart host communication. The mechanism is
based on qobject_cast - like other extension mechanism in ktexteditor -
and allows for current and future extensions of the kpart host interface
in a BC way.

The patch has been discussed on ktexteditor (hence the seventh
iteration) and has the approval of the people there ( see
http://lists.kde.org/?l=ktexteditor-devel&m=118724435408905&w=2 ).

The first extension supported is the MdiContainer, that allows the part
to create views, delete views, create documents, delete documents,
change and fetch the current active view. The extension mechanism is by
definition completely optional for the kpart host.

The patch is BC. Eventhough we have an API freeze, I would like it to go
into KDE 4.0 .

	cheers,

	Philippe


["kte-container-ext-7.diff" (text/x-diff)]

Index: containerinterface.h
===================================================================
--- containerinterface.h	(revision 0)
+++ containerinterface.h	(revision 0)
@@ -0,0 +1,265 @@
+/* This file is part of the KDE libraries
+   Copyright (C) 2007 Philippe Fremy (phil at freehackers dot org)
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License version 2 as published by the Free Software Foundation.
+
+   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 KDELIBS_KTEXTEDITOR_CONTAINER_INTERFACE_H
+#define KDELIBS_KTEXTEDITOR_CONTAINER_INTERFACE_H
+
+#include <ktexteditor/ktexteditor_export.h>
+
+namespace KTextEditor
+{
+
+class Document;
+class View;
+
+
+/** 
+ * \brief Class that allows the kpart host to provide some extensions.
+ *
+ * \ingroup kte_group_editor_extensions 
+ *
+ * The KTextEditor framework allows the kpart host to provide additional
+ * services to the kpart. Those services are provided through the 
+ * ContainerInterface class.
+ *
+ * If the container supports those specific services, it should set an
+ * instance of the service class with ContainerInterface::setContainer(). That
+ * instance should inherit QObject, have the Q_OBJECT macro and declare a
+ * Q_INTERFACES(), in order for the qobject_cast mechanism to work.
+ *
+ * To obtain a ContainerInterface, in order to set a specific container
+ * extension, the kpart host should do:
+ * \code
+ * // inside the kpart host
+ * Editor * editor = KTextEditor::EditorChooser::editor();
+ * ContainerInterface * iface = qobject_cast<ConainterInterace *>( editor );
+ * if (iface != NULL) {
+ *   iface->setContainer( myContainerExtension );
+ * } else {
+ *   // the kpart does not support ContainerInterface.
+ * }
+ * \endcode
+ *
+ * It is then up to the kpart to use it.
+ *
+ */
+class KTEXTEDITOR_EXPORT ContainerInterface
+{
+  public:
+
+    /** Virtual Destructor */
+    ~ContainerInterface() {}
+
+    /** 
+     * Set the KTextEditor container.
+     *
+     * This method is used by the KTextEditor host to set an instance
+     * of a class providing optional container extensions. 
+     *
+     * \sa container
+     */
+    virtual void setContainer( QObject * container ) = 0;
+
+    /** 
+     * Fetch the container extension.
+     *
+     * This method is used by the KTextEditor component to know
+     * which extensions are supported by the KTextEditor host.
+     *
+     * The kpart will cast the result with qobject_cast() to the right
+     * container extension to see if that particular extension is supported:
+     *
+     * <b>Example:</b>
+     * \code
+     * // inside the kpart 
+     *
+     * Editor * editor = KTextEditor::EditorChooser::editor();
+     * ContainerInterface * iface = qobject_cast<ConainterInterace *>( editor );
+     * SomeContainerExtension * myExt = 
+     *     qobject_cast<SomeContainerExtension *>( iface->container() );
+     *
+     * if (myExt) {
+     *     // do some stuff with the specific container extension
+     *     // ...
+     * } else {
+     *     // too bad, that extesion is not supported.
+     * }
+     * \endcode
+     *
+     * \sa setContainer
+     */
+    virtual QObject * container() = 0;
+
+}; // class ContainerInterface
+
+
+/** 
+ * A container for MDI-capable kpart hosts.
+ *
+ * The kpart container for the KTextEditor interface may have different
+ * capabilities. For example, inside KDevelop or Kate, the container can
+ * manage multiple views and multiple documents. However, if the kpart text
+ * is used inside konqueror as a replacement of the text entry in html
+ * forms, the container will only support one view with one document.
+ *
+ * This class allows the kpart component to create and delete views, create
+ * and delete documents, fetch and set the current view. Note that the
+ * ktexteditor framework already supports multiple document and views and
+ * that the kpart host can create them and delete them as it wishes. What
+ * this class provides is the ability for the <i>kpart component</i> being
+ * hosted to do the same.
+ *
+ * An instance of this extension should be set with 
+ * ContainerInterface::setContainerExtension().Check ContainerInterface() to
+ * see how to obtain an instance of ContainerInterface. The instance should
+ * inherit QObject, inherit MdiContainer, declare the Q_OBJECT macro and
+ * declare a Q_INTERFACES(KTextEditor::MdiContainer) .
+ *
+ * Code example to support MdiContainer (in the kpart host):
+ * \code
+ * class MyMdiContainer : public QObject,
+ *                        public MdiContainer
+ * {
+ *   Q_OBJECT
+ *   Q_INTERFACES( KTextEditor::MdiContainer )
+ *
+ *   public:
+ *     // ...
+ * }
+ * \endcode
+ *
+ *
+ * To check if the kpart hosts supports the MDI container: 
+ * \code
+ * Editor * editor = KTextEditor::EditorChooser::editor();
+ * ContainerInterface * iface = qobject_cast<ContainerInterface *>( editor );
+ * if (iface) {
+ *   MdiContainer * mdiContainer = qobject_cast<MdiContainer *>( iface->container() );
+ *   if (MdiContainer != NULL ) {
+ *    // great, I can create addtional views
+ *    // ...
+ *   }
+ * }
+ * \endcode
+ */
+class KTEXTEDITOR_EXPORT MdiContainer
+{
+
+  public:
+    
+    /** Constructor */
+    MdiContainer();
+
+    /** Virtual destructor */
+    virtual ~MdiContainer();
+
+    /** 
+     * Set the \p view requested by the part as the active view.
+     *
+     * \sa activeView
+     */
+    virtual void setActiveView( View * view )=0;
+
+    /** 
+     * Get the current activew view.
+     *
+     * \return the active view.
+     *
+     * \sa setActiveView
+     */
+    virtual View * activeView()=0;
+
+    /** 
+     * Create a new Document and return it to the kpart. 
+     *
+     * Canonical implementation is:
+     * \code
+     * Document * createDocument() 
+     * {
+     *     Document * doc;
+     *     // set parentQObject to relevant value
+     *     doc = editor->createDocument( parentQObject );
+     *     // integrate the new document in the document list of the
+     *     // container, ...
+     *     return doc;
+     * }
+     * \endcode
+     *
+     * The signal documentCreated() will be emitted during the creation.
+     *
+     * \return a pointer to the new Document object.
+     */
+    virtual Document * createDocument()=0;
+
+    /** 
+     * Closes of document \p doc .
+     *
+     * The document is about to be closed but is still valid when this
+     * call is made. The Document does not contain any view when this
+     * call is made (closeView() has been called on all the views of the
+     * document previously).
+     *
+     * The signal aboutToClose() is emitted before this method is
+     * called.
+     *
+     * \return true if the removal is authorized and acted, or
+     *     false if removing documents by the kpart is not supported
+     *     by the container.
+     */
+    virtual bool closeDocument( Document * doc )=0;
+
+    /** 
+     * Creates a new View and return it to the kpart.
+     *
+     * Canonical implementation is:
+     * \code
+     * View * createView( Document * doc ) 
+     * {
+     *     // set parentWidget to relevant value
+     *     return doc->createView( parentWidget );
+     * }
+     * \endcode
+     *
+     * The signal viewCreated() will be emitted during the createView()
+     * call.
+     *
+     * \return a pointer to the new View created.
+     */
+    virtual View * createView( Document * doc )=0;
+
+    /** 
+     * Closes the View \p view .
+     *
+     * The view is still valid when this call is made but will be deleted
+     * shortly after.
+     *
+     * \return true if the removal is authorized and acted, or 
+     *     false if the container does not support view removing from
+     *     the kpart, or 
+     */
+    virtual bool closeView( View * view )=0;
+
+}; // class MdiContainer
+
+} // namespace KTextEditor
+
+Q_DECLARE_INTERFACE(KTextEditor::ContainerInterface, "org.kde.KTextEditor.ContainerInterface")
+
+#endif // KDELIBS_KTEXTEDITOR_CONTAINER_EXTENSION_H
+
+
Index: editorchooser.h
===================================================================
--- editorchooser.h	(revision 699245)
+++ editorchooser.h	(working copy)
@@ -123,6 +123,10 @@
     /**
      * Static accessor to get the Editor instance of the currently used
      * KTextEditor component.
+     *
+     * That Editor instance can be qobject-cast to specific extensions.
+     * If the result of the cast is not NULL, that extension is supported:
+     *
      * \param postfix config group postfix string
      * \param fallBackToKatePart if \e true, the returned Editor component
      *        will be a katepart if no other implementation can be found
Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt	(revision 699245)
+++ CMakeLists.txt	(working copy)
@@ -59,6 +59,7 @@
     codecompletioninterface.h
     codecompletionmodel.h
     configinterface.h
+    containerinterface.h
     DESTINATION  ${INCLUDE_INSTALL_DIR}/ktexteditor )
 
 install( FILES ktexteditor.desktop ktexteditorplugin.desktop  DESTINATION  ${SERVICETYPES_INSTALL_DIR} )
Index: document.h


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic