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

List:       koffice-devel
Subject:    Re: RFD: loading/pasting/DnD in Flake?
From:       Thomas Zander <zander () kde ! org>
Date:       2006-08-24 8:21:39
Message-ID: 200608241021.39718.zander () kde ! org
[Download RAW message or body]

[Attachment #2 (multipart/signed)]


Morning :)
Long emails, but progress is being made! Thanks for taking this on.

On Thursday 24 August 2006 06:35, Benjamin K. Stuhl wrote:
> On Mon, 21 Aug 2006 19:26:05 +0200, Thomas Zander inscribed:

> > A shape that finds out it needs to create a child-shape then needs to
> > call that.
> > Effectively;
> > myTool::paste(QDomElement e) {
> > 	firstSelectedObject->paste(e,
> >           KoToolManager::instance()->shapeCreatorTool(m_canvas);
>
> How does this work when only a subset of a shape (e.g. a few words in a
> KoTextShape) is selected? I guess the tool needs some (perhaps private)
> way of informing the shape what the current selection is. (e.g. the
> KoTextTool could pass a QTextCursor or something to the KoTextShape?)

The selection inside the shape is always part of the Tool, In the case of 
the KoTextShape there is a QTextCursor member.
In the case of the KoPathTool there is a:
QList<KoPathPoint*> m_selectedPoints

> > }
> > KoShape::paste(e, createTool) {
> >    // foo
> > }
> > KoCreateShapesTool::createShape(QDomElement elem);
> >
> >  It would use the ShapeRegistry to find out which shapeFactory can be
> > used for the datatype.  This means some mime-type should be
> > registered on the KoShapeFactory.
>
> Fleshing this out a bit more, I think that appropriate method
> signatures would be something like
>
> void KoShape::loadAs(QIODevice *source, const QString& mimeType,
> KoCreateShapesTool *createTool) {
>   // we can create a KoStore from |source|, or read an image from it,
>   // or insert it as raw data, or whatever is appropriate
>   //
> }

I don't think the mimetype should be there Any instance of a KoShape has 
only the required knowledge for loading exactly one mimetype. No more.  A 
textShape can only load a whole text in ODT format. A PathShape can only 
load a path in ODG format.  [more on this below]

I'm not into XML loading very much in KOffice, but should that source not 
be a xml element ?  Since the loading will be cascaded and loading of a 
small part of the XML tree is just delegated. No need to recreate an xml.

> enum SaveWhat { SaveSelection, SaveEntireShape };
>
> void KoShape::saveAs(QIODevice *dest, const QString& mimeType,
> KoShape::SaveWhat what) {
>   // store either the selection or the entire shape into |dest|;
>   // the definition of the selection is privately negotiated between
>   // a shape and its tools
> }

Due to MVC separation, I think the selection will have to be passed here 
in some way. Since you can't have a member in KoShape to point either to 
the tool or to the selection.
I'd suggest to have a save() method like you describe and a second method 
saveSelection() which is only implemented on the shapes that actually 
need it.
Reason for this suggestion is that  a) many shapes don't do selection 
(that can be saved) anyway.  b) in the shape that needs it you can 
finetune the signature of the saveSelection method to pass the needed 
info. Like a:
  KoTextShape::saveSelection(dest, int from, int length).

Same comment about the mimetype as above.

> // returns list of supported mime types, perhaps from
> //  a KServiceTypeTrader query for import plugins?
> QList<QString> KoShape::canLoadAs() const;
>
> // returns list of supported mime types, perhaps from
> //  a KServiceTypeTrader query for export plugins?
> QList<QString> KoShape::canSaveAs() const;

This would have to be moved to somewhere else since a Shape instance is 
not present when you are searching for "Who can load this!".
And I guess you don't want to instantiate one shape of all plugins to find 
out if it can load the data you have :)

We have all instances of KoShapeFactorys, so I suggest having a getter 
there.

This indeed throws a big wrench into your plan to have shapes do the 
loading on dragNdrop. I would guess that the suggestion you made to have 
a dropTool which is activated on drag-enter or similar would be a good 
alternative idea. The advantage that that gives are non trivial.
For example we can highlight a shape which can take the drop with an 
outline, or just the whole page when there is no such shape selected.
With multithreading we can even parse the drop data while the user is 
still dragging it and show a preview of the data half-transparent on the 
canvas :)

So, in overview;
* KoTool inheriting classes handle selection-based pastes. Possibly using 
a loadSelection on the shape its working on.
* KoShape inheriting classes handle single loading of single-shape data 
(no subobjects) coming from the KoCreateShapesTool.
* KoShapeContainer inheriting classes handle loading of multi-shape-data 
coming from, and with callbacks to KoCreateShapesTool
* KoCreateShapesTool handles pastes that current tool delegates and DnD 
loading which is delegated by KoDropTool
* a new KoDropTool is created which decides where data will go. Inside a 
shape, shapeContainer or to the page.

Saving is only relevant for KoShape, KoShapeContainer and KoTool (for 
current selection of the active shape(s)).

> As you can see, I'm also trying to figure out where import and export
> plugins fit into this... I think that they should be discovered and
> used by the appropriate Shapes? So e.g. the KoTextShape could query for
> and find a KoHtmlTextImporter that knows how to take HTML and feed it
> into a KoTextShape?

We use KoFilter in KOffice 1.x for that. This is a service based framework 
where each filter has a  "X-KDE-Import=application/x-kword" 
and "X-KDE-Export=Foo" pair.
I think we should use and extend that for cases like a html drop on a 
shape that takes rich-text (KoTextShape) or an image (Krita-layer) by 
using a filterchain that convert from html to ODT (which the textshape 
can load) or png to .kra which the krita shape should be able to load.

> Perhaps just KoImporterPlugin::importAs() which 
> mirrors KoShape::loadAs(), except that it manipulates an external
> shape, and likewise for KoExporterPlugin::exportAs() and
> KoShape::saveAs()? The plugins wouldn't need can*As(), since that would
> be declared in their .desktop... For a constructor, maybe just
>
> KoImporterPlugin::KoImporterPlugin(KoShape *target);
>
> and the constructor does a static_cast<> to the appropriate shape
> (e.g. static_cast<KoTextShape> for the KoHtmlTextImporter)?

Since all shapes are plugins (including the KoTextShape) I don't see how 
that can work. The fact that KoTextShape is located in libs/kotext is 
just legacy and its likely it will move to /shapes/text before the 
release.

> What about error handling? Should the shape simply have a
>
> signals:
>   void loadFailed(const QString& reason);
>
> to report when something didn't work? Or do we want something a bit
> more complex so that we can let the user do partial imports up to the
> broken point?

AFAICS just returning a boolean would work fine.

> KoTools should probably be given some extensions to adequately deal
> with selections and such... perhaps
>
> signals:
> // emitted as true when something is selected, false when the selection
> // is cleared -- good for (e.g.) enabling the cut and copy actions
>   void KoTool::hasSelection(bool);

Sounds good.

> public:
> // asks the tool to paste as the given mimetype, or as the best
> // available if |mimeType| is empty -- lets applications implement
> // "Paste As..." logic, while letting shapes decide what the "best"
> // format is
>   void KoTool::paste(QMimeData *source, const QString& mimeType);
>
> Thinking further on the "Paste As..." menu, that is really IMHO a
> property of the current clipboard contents, and so _has_ to be managed
> by the application, perhaps with the help of the shape registry.
>
> That's probably enough for now, it's getting kind of late here. Let me
> know what you think.

As elaborated earlier in this email I think this should be moved to a 
KoDropTool in unison with KoCreateShapesTool.
Since the (currently not-implemented) KoToolManager can create and 
register actions the dropTool could create the action for pasteAs.
We load all plugins in the same process so the tool can just call;
  QClipboard *clipboard = QApplication::clipboard();
to get access to the clipboard.  No access to the application needed.

-- 
Thomas Zander

[Attachment #5 (application/pgp-signature)]

_______________________________________________
koffice-devel mailing list
koffice-devel@kde.org
https://mail.kde.org/mailman/listinfo/koffice-devel


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

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