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

List:       koffice-devel
Subject:    Re: RFD: loading/pasting/DnD in Flake?
From:       "Benjamin K. Stuhl" <benjamin.stuhl () colorado ! edu>
Date:       2006-08-24 15:16:13
Message-ID: 20060824091613.14d5a2d4 () localhost
[Download RAW message or body]

[Attachment #2 (multipart/signed)]


On Thu, 24 Aug 2006 10:21:39 +0200, Thomas Zander inscribed:
> Morning :)
> Long emails, but progress is being made! Thanks for taking this on.

Indeed. And it's a complex problem, so I, at least, don't mind the
verbiage. ^_^
 
> 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

Ok.
 
> > > }
> > > 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.

The vague motivation for a mime-type was to let the shape declare
support for all the mime types that can somehow be filtered into what
it can handle, but the filter-chain hunts can just as easily be done
outside the shape )in the KoDropTool or the like... perhaps there
should be a KoSaveTool and a KoLoadTool to encapsulate that logic?
or, thinking a bit more, I suppose the KoCreateShapesTool is the one
that needs to be able to figure out "I have a chunk of text/html, I
can use a filter chain to get it to ODT, so I need to create a
KoTextTool"... but that still leaves perhaps a KoSaveTool to take the
XML from the KoTextTool and convert it to, say, LaTeX.)

Does every application in koffice do its loading from XML in a KoStore?
Then instead of the QIODevice*, we could pass (KoStore *store,
QDomElement elem), just like we do to the createShape(). We do still
need the 

> > 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.

So then there would need to be KoTool::cut(), KoTool::copy(), and
KoTool::paste() methods to connect the application to the shape? (And,
presumably, the shape manipulation tool would need to be able to cut,
copy, and paste one or more entire shapes? But that's ok, since that
can just use the public KoShape::save() and KoShape::load() methods.)

> > // 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.

Ok.

> 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

And _anything_ that can have some other format embedded in it is a
KoShapeContainer? Ok.

> * KoCreateShapesTool handles pastes that current tool delegates and
> DnD loading which is delegated by KoDropTool

Yup; the KoDropTool itself delgates the actual data transfer back to
the shape's default tool or to the KoCreateShapesTool, as appropriate.

> * 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.

I know _of_ the filter framework, but I'll need to take a deeper look
at it... my only concern is, do the filters all produce ODF, or do they
still produce legacy .k*?

That also brings up a side question: is the plan to use the krita shape
for _all_ embedded images? It seems to me that that might be a bit of
overkill? (Not to mention slow, since it has to convert PNG and JPEG
images to .kra on loading and then back again on saving, since .kra is
not one of the image formats ODF supports... :-/) Perhaps it might be
work making just a KoPictureShape that supports anything QImage does
and just has trivial resize and "Open in Krita" actions? (Even MSOffice
pops open a Paint window to edit raster images.)

Also, I would suggest that KoTool::activate() should get a QPoint(F?)
(I'm not really sure when to use which version...) argument so that you
can, say, simply click a text shape twice (or double-click) to get the
cursor where you clicked? It's really rather irritating to always have
to mouse over to the toolbox to be able to enter text in a word
processor... ^_^

> > 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.

True. Linking plugins against other plugins is unportable, IIRC?
(MaxOSX?)

> > 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.

I just thought it might be nice to be able to say "your document did not
load, because the ZIP file was corrupted" or "your document did not
load because no manifest could be found" rather than just "unable to
open document"... but that is a nicety that could probably be added
later.

> > 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.

How should shapes declare that they do not accept drops or pastes of
their mimetype? Just a

bool KoShape::acceptsDrops() const;

?

> > 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.

Yeah, if we go the KoDropTool route (which I think we should, it's
sounding better and better) the dropTool can be responsible for
managing the clipboard. OTOH, I think that would mean that a dropTool
would need to always be active, at least in the background? _Someone_
needs to listen for QClipboard::changed() signals to enable/disable
pasting into the current shape...

Thanks,
-- BKS

["signature.asc" (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