Warning, file /office/calligra/libs/text/KoTextInlineRdf.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /* This file is part of the KDE project
0002    Copyright (C) 2010 KO GmbH <ben.martin@kogmbh.com>
0003    Copyright (C) 2012 C. Boemann <cbo@boemann.dk>
0004 
0005    This library is free software; you can redistribute it and/or
0006    modify it under the terms of the GNU Library General Public
0007    License as published by the Free Software Foundation; either
0008    version 2 of the License, or (at your option) any later version.
0009 
0010    This library is distributed in the hope that it will be useful,
0011    but WITHOUT ANY WARRANTY; without even the implied warranty of
0012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013    Library General Public License for more details.
0014 
0015    You should have received a copy of the GNU Library General Public License
0016    along with this library; see the file COPYING.LIB.  If not, write to
0017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0018    Boston, MA 02110-1301, USA.
0019 */
0020 
0021 #include "KoTextInlineRdf.h"
0022 // lib
0023 #include <opendocument/KoTextSharedSavingData.h>
0024 #include <styles/KoCharacterStyle.h>
0025 #include <KoBookmark.h>
0026 #include <KoAnnotation.h>
0027 #include <KoTextMeta.h>
0028 #include <KoTextEditor.h>
0029 #include <KoTextDocument.h>
0030 // komain
0031 #include <KoShapeSavingContext.h>
0032 #include <KoXmlWriter.h>
0033 #include <KoXmlNS.h>
0034 #include <KoElementReference.h>
0035 // TODO: the "errorText" define in TextDebug.h results in a build error, if used as second include here
0036 // find out why and perhaps change the rather generic "errorText" & Co defines to something less conflict-prone
0037 #include "TextDebug.h"
0038 // Qt
0039 #include <QTextCursor>
0040 #include <QTextDocument>
0041 #include <QTextTableCell>
0042 
0043 
0044 #ifdef SHOULD_BUILD_RDF
0045 #include <Soprano/Soprano>
0046 enum Type {
0047     EmptyNode = Soprano::Node::EmptyNode,
0048     ResourceNode = Soprano::Node::ResourceNode,
0049     LiteralNode = Soprano::Node::LiteralNode,
0050     BlankNode = Soprano::Node::BlankNode
0051 };
0052 #else
0053 enum Type {
0054     EmptyNode,
0055     ResourceNode,
0056     LiteralNode,
0057     BlankNode
0058 };
0059 #endif
0060 
0061 class Q_DECL_HIDDEN KoTextInlineRdf::Private
0062 {
0063 public:
0064     Private(const QTextDocument *doc, const QTextBlock &b)
0065         : block(b)
0066         , document(doc)
0067     {
0068         isObjectAttributeUsed = false;
0069         sopranoObjectType = LiteralNode;
0070     }
0071 
0072     Private(const QTextDocument *doc, KoBookmark *b)
0073         : document(doc)
0074         , bookmark(b)
0075     {
0076         isObjectAttributeUsed = false;
0077         sopranoObjectType = LiteralNode;
0078     }
0079 
0080     Private(const QTextDocument *doc, KoAnnotation *b)
0081         : document(doc)
0082         , annotation(b)
0083     {
0084         isObjectAttributeUsed = false;
0085         sopranoObjectType = LiteralNode;
0086     }
0087 
0088     Private(const QTextDocument *doc, KoTextMeta *b)
0089         : document(doc)
0090         , kotextmeta(b)
0091     {
0092         isObjectAttributeUsed = false;
0093         sopranoObjectType = LiteralNode;
0094     }
0095 
0096     Private(const QTextDocument *doc, const QTextTableCell &c)
0097         : document(doc)
0098         , cell(c)
0099     {
0100         isObjectAttributeUsed = false;
0101         sopranoObjectType = LiteralNode;
0102     }
0103 
0104     Private(const QTextDocument *doc, KoSection *s)
0105         : document(doc)
0106         , section(s)
0107     {
0108         isObjectAttributeUsed = false;
0109         sopranoObjectType = LiteralNode;
0110     }
0111 
0112 
0113     QString id; // original xml:id
0114 
0115     //FIXME: design like this seems inapropriate, maybe
0116     // making Interface from KoTextInlineRdf will be better.
0117     // Just my thoughts.
0118 
0119     // where we might get the object value from
0120     QTextBlock block;
0121 
0122     // or document and one of bookmark, annotation, kotextmeta, ...
0123     QPointer<const QTextDocument> document;
0124     QPointer<KoBookmark> bookmark;
0125     QPointer<KoAnnotation> annotation;
0126     QPointer<KoTextMeta> kotextmeta;
0127     KoSection *section;
0128     QTextTableCell cell;
0129 
0130     QString subject;
0131     QString predicate;
0132     int sopranoObjectType;
0133     QString dt;
0134 
0135     // if the content="" attribute was used,
0136     // then isObjectAttributeUsed=1 and object=content attribute value.
0137     QString object;
0138     bool isObjectAttributeUsed;
0139 };
0140 
0141 KoTextInlineRdf::KoTextInlineRdf(const QTextDocument *doc, const QTextBlock &b)
0142     : QObject(const_cast<QTextDocument*>(doc))
0143     , d(new Private(doc, b))
0144 {
0145 }
0146 
0147 KoTextInlineRdf::KoTextInlineRdf(const QTextDocument *doc, KoBookmark *b)
0148     : QObject(const_cast<QTextDocument*>(doc))
0149     , d(new Private(doc, b))
0150 {
0151 }
0152 
0153 KoTextInlineRdf::KoTextInlineRdf(const QTextDocument *doc, KoAnnotation *b)
0154     : QObject(const_cast<QTextDocument*>(doc))
0155     , d(new Private(doc, b))
0156 {
0157 }
0158 
0159 KoTextInlineRdf::KoTextInlineRdf(const QTextDocument *doc, KoTextMeta *b)
0160     : QObject(const_cast<QTextDocument*>(doc))
0161     , d(new Private(doc, b))
0162 {
0163 }
0164 
0165 KoTextInlineRdf::KoTextInlineRdf(const QTextDocument *doc, const QTextTableCell &b)
0166     : QObject(const_cast<QTextDocument*>(doc))
0167     , d(new Private(doc, b))
0168 {
0169 }
0170 
0171 KoTextInlineRdf::KoTextInlineRdf(const QTextDocument *doc, KoSection *s)
0172     : QObject(const_cast<QTextDocument*>(doc))
0173     , d(new Private(doc, s))
0174 {
0175 }
0176 
0177 KoTextInlineRdf::~KoTextInlineRdf()
0178 {
0179     debugText << " this:" << (void*)this;
0180     delete d;
0181 }
0182 
0183 bool KoTextInlineRdf::loadOdf(const KoXmlElement &e)
0184 {
0185     d->id = e.attribute("id", QString());
0186     d->subject = e.attributeNS(KoXmlNS::xhtml, "about");
0187     d->predicate = e.attributeNS(KoXmlNS::xhtml, "property");
0188     d->dt = e.attributeNS(KoXmlNS::xhtml, "datatype");
0189     QString content = e.attributeNS(KoXmlNS::xhtml, "content");
0190     //
0191     // Content / triple object explicitly set through an attribute
0192     //
0193     if (e.hasAttributeNS(KoXmlNS::xhtml, "content")) {
0194         d->isObjectAttributeUsed = true;
0195         d->object = content;
0196     }
0197     return true;
0198 }
0199 
0200 bool KoTextInlineRdf::saveOdf(KoShapeSavingContext &context, KoXmlWriter *writer, KoElementReference id) const
0201 {
0202     debugText << " this:" << (void*)this << " xmlid:" << d->id << "passed id" << id.toString();
0203     QString oldID = d->id;
0204 
0205     if (!id.isValid()) {
0206         id = KoElementReference();
0207     }
0208 
0209     QString newID = id.toString();
0210     if (KoTextSharedSavingData *sharedData =
0211             dynamic_cast<KoTextSharedSavingData *>(context.sharedData(KOTEXT_SHARED_SAVING_ID))) {
0212         sharedData->addRdfIdMapping(oldID, newID);
0213     }
0214     debugText << "oldID:" << oldID << " newID:" << newID;
0215     writer->addAttribute("xml:id", newID);
0216     if (!d->subject.isEmpty()) {
0217         writer->addAttribute("xhtml:about", d->subject);
0218     }
0219     if (!d->predicate.isEmpty()) {
0220         writer->addAttribute("xhtml:property", d->predicate);
0221     }
0222     if (!d->dt.isEmpty()) {
0223         writer->addAttribute("xhtml:datatype", d->dt);
0224     }
0225     if (d->isObjectAttributeUsed) {
0226         writer->addAttribute("xhtml:content", d->object);
0227     }
0228     debugText << "done..";
0229     return true;
0230 }
0231 
0232 QString KoTextInlineRdf::createXmlId()
0233 {
0234     KoElementReference ref;
0235     return ref.toString();
0236 }
0237 
0238 QString KoTextInlineRdf::subject() const
0239 {
0240     return d->subject;
0241 }
0242 
0243 QString KoTextInlineRdf::predicate() const
0244 {
0245     return d->predicate;
0246 }
0247 
0248 QPair<int, int>  KoTextInlineRdf::findExtent() const
0249 {
0250     if (d->bookmark && d->document) {
0251         return QPair<int, int>(d->bookmark.data()->rangeStart(), d->bookmark.data()->rangeEnd());
0252     }
0253     if (d->annotation && d->document) {
0254         return QPair<int, int>(d->annotation.data()->rangeStart(), d->annotation.data()->rangeEnd());
0255     }
0256     // FIXME: We probably have to do something with endAnnotation()
0257     //        too, but I don't know exactly what...
0258     if (d->kotextmeta && d->document) {
0259         KoTextMeta *e = d->kotextmeta.data()->endBookmark();
0260         if (!e) {
0261             return QPair<int, int>(0, 0);
0262         }
0263         // debugText << "(Semantic)meta... start:" << d->kotextmeta.data()->position() << " end:" << e->position();
0264         return QPair<int, int>(d->kotextmeta.data()->position(), e->position());
0265     }
0266     if (d->cell.isValid() && d->document) {
0267         QTextCursor b = d->cell.firstCursorPosition();
0268         QTextCursor e = d->cell.lastCursorPosition();
0269         return QPair<int, int>(b.position(), e.position());
0270     }
0271 
0272     if (d->section) {
0273         return d->section->bounds();
0274     }
0275 
0276     return QPair<int, int>(0, 0);
0277 }
0278 
0279 QString KoTextInlineRdf::object() const
0280 {
0281     if (d->isObjectAttributeUsed) {
0282         return d->object;
0283     }
0284 
0285     KoTextDocument textDocument(d->document.data());
0286 
0287     if (d->bookmark && d->document) {
0288         QString ret  = d->bookmark.data()->text();
0289         return ret.remove(QChar::ObjectReplacementCharacter);
0290     }
0291     else if (d->kotextmeta && d->document) {
0292         // FIXME: Need to do something with endAnnotation?
0293         KoTextMeta *e = d->kotextmeta.data()->endBookmark();
0294         if (!e) {
0295             debugText << "Broken KoTextMeta, no end tag found!";
0296             return QString();
0297         } else {
0298             KoTextEditor *editor = textDocument.textEditor();
0299             editor->setPosition(d->kotextmeta.data()->position(), QTextCursor::MoveAnchor);
0300             editor->setPosition(e->position(), QTextCursor::KeepAnchor);
0301             QString ret = editor->selectedText();
0302             return ret.remove(QChar::ObjectReplacementCharacter);
0303         }
0304     }
0305     else if (d->cell.isValid() && d->document) {
0306         QTextCursor b = d->cell.firstCursorPosition();
0307         b.setPosition(d->cell.lastCursorPosition().position(), QTextCursor::KeepAnchor);
0308         QString ret = b.selectedText();
0309         return ret.remove(QChar::ObjectReplacementCharacter);
0310     }
0311 
0312     return d->block.text();
0313 }
0314 
0315 int KoTextInlineRdf::sopranoObjectType() const
0316 {
0317     return d->sopranoObjectType;
0318 }
0319 
0320 QString KoTextInlineRdf::xmlId() const
0321 {
0322     return d->id;
0323 }
0324 
0325 void KoTextInlineRdf::setXmlId(const QString &id)
0326 {
0327     d->id = id;
0328 }
0329 
0330 KoTextInlineRdf *KoTextInlineRdf::tryToGetInlineRdf(const QTextFormat &tf)
0331 {
0332     if (!tf.hasProperty(KoCharacterStyle::InlineRdf)) {
0333         return 0;
0334     }
0335     QVariant v = tf.property(KoCharacterStyle::InlineRdf);
0336     return v.value<KoTextInlineRdf *>();
0337 }
0338 
0339 KoTextInlineRdf *KoTextInlineRdf::tryToGetInlineRdf(QTextCursor &cursor)
0340 {
0341     QTextCharFormat cf = cursor.charFormat();
0342     if (!cf.hasProperty(KoCharacterStyle::InlineRdf)) {
0343         return 0;
0344     }
0345     QVariant v = cf.property(KoCharacterStyle::InlineRdf);
0346     return v.value<KoTextInlineRdf *>();
0347 }
0348 
0349 KoTextInlineRdf *KoTextInlineRdf::tryToGetInlineRdf(KoTextEditor *handler)
0350 {
0351     QTextCharFormat cf = handler->charFormat();
0352     if (!cf.hasProperty(KoCharacterStyle::InlineRdf)) {
0353         return 0;
0354     }
0355     QVariant v = cf.property(KoCharacterStyle::InlineRdf);
0356     return v.value<KoTextInlineRdf *>();
0357 }
0358 
0359 void KoTextInlineRdf::attach(KoTextInlineRdf *inlineRdf, QTextCursor &cursor)
0360 {
0361     QTextCharFormat format = cursor.charFormat();
0362     QVariant v = QVariant::fromValue(inlineRdf);
0363     format.setProperty(KoCharacterStyle::InlineRdf, v);
0364     cursor.mergeCharFormat(format);
0365 }