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 }