Warning, file /office/calligra/libs/rdf/KoRdfSemanticItem.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 
0004    This library is free software; you can redistribute it and/or
0005    modify it under the terms of the GNU Library General Public
0006    License as published by the Free Software Foundation; either
0007    version 2 of the License, or (at your option) any later version.
0008 
0009    This library is distributed in the hope that it will be useful,
0010    but WITHOUT ANY WARRANTY; without even the implied warranty of
0011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012    Library General Public License for more details.
0013 
0014    You should have received a copy of the GNU Library General Public License
0015    along with this library; see the file COPYING.LIB.  If not, write to
0016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017  * Boston, MA 02110-1301, USA.
0018 */
0019 
0020 #include "KoRdfSemanticItem.h"
0021 
0022 //Calligra
0023 #include <KoCanvasBase.h>
0024 #include <KoCanvasResourceManager.h>
0025 #include <KoChangeTrackerDisabledRAII.h>
0026 #include <KoDocumentRdf.h>
0027 #include <KoTextDocument.h>
0028 #include <KoTextEditor.h>
0029 #include <KoText.h>
0030 #include <KoTextInlineRdf.h>
0031 #include <KoTextMeta.h>
0032 #include <KoTextRdfCore.h>
0033 
0034 // KF5
0035 #include <KDebug>
0036 
0037 //QT
0038 #include <QUuid>
0039 #include <QWidget>
0040 
0041 using namespace Soprano;
0042 
0043 KoRdfSemanticItem::KoRdfSemanticItem(QObject *parent)
0044     : KoRdfBasicSemanticItem(parent)
0045 {
0046 }
0047 
0048 KoRdfSemanticItem::KoRdfSemanticItem(QObject *parent, const KoDocumentRdf *rdf)
0049     : KoRdfBasicSemanticItem(parent, rdf)
0050 {
0051 }
0052 
0053 KoRdfSemanticItem::KoRdfSemanticItem(QObject *parent, const KoDocumentRdf *rdf, Soprano::QueryResultIterator &it)
0054     : KoRdfBasicSemanticItem(parent, rdf, it)
0055 {
0056 }
0057 
0058 KoRdfSemanticItem::~KoRdfSemanticItem()
0059 {
0060 }
0061 
0062 KoRdfSemanticTreeWidgetItem *KoRdfSemanticItem::createQTreeWidgetItem(QTreeWidgetItem *parent)
0063 {
0064     Q_UNUSED(parent);
0065     return 0;
0066 }
0067 
0068 void KoRdfSemanticItem::importFromDataComplete(const QByteArray &ba, const KoDocumentRdf *rdf, KoCanvasBase *host)
0069 {
0070     Q_UNUSED(ba);
0071 
0072     // Create and populate and editor with the current data,
0073     // then update the Rdf from that editor.
0074     QWidget *parent = 0;
0075     QWidget *objectEditor = createEditor(parent);
0076     updateFromEditorData();
0077 
0078     if (host) {
0079         insert(host);
0080     }
0081     delete objectEditor;
0082 
0083     if (rdf) {
0084         rdf->emitSemanticObjectAdded(hKoRdfSemanticItem(this));
0085     }
0086 }
0087 
0088 void KoRdfSemanticItem::setupStylesheetReplacementMapping(QMap<QString, QString> &m)
0089 {
0090     Q_UNUSED(m);
0091 }
0092 
0093 void KoRdfSemanticItem::exportToMime(QMimeData *md) const
0094 {
0095     Q_UNUSED(md);
0096 }
0097 
0098 void KoRdfSemanticItem::insert(KoCanvasBase *host)
0099 {
0100     Q_UNUSED(host);
0101     kDebug(30015) << "insert...";
0102     KoTextEditor *editor = KoTextEditor::getTextEditorFromCanvas(host);
0103 
0104     Q_ASSERT(editor);
0105     Q_ASSERT(editor->document());
0106 
0107     KoTextDocument ktd(editor->document());
0108     KoChangeTrackerDisabledRAII disableChangeTracker(ktd.changeTracker());
0109     Q_UNUSED(disableChangeTracker);
0110 
0111 //    int originalpos = editor->position();
0112     KoTextMeta *startmark = new KoTextMeta(editor->document());
0113     editor->insertInlineObject(startmark);
0114     KoTextInlineRdf *inlineRdf(new KoTextInlineRdf((QTextDocument*)editor->document(), startmark));
0115 
0116     // generate an xml:id for inlineRdf
0117     // set it and also insert some Rdf into manifest.rdf to link
0118     // the new xml:id to the foaf Rdf data.
0119     QString newID = inlineRdf->createXmlId();
0120     inlineRdf->setXmlId(newID);
0121     startmark->setInlineRdf(inlineRdf);
0122 
0123     // we could do a paragraph relayout to update the position() values
0124     // of the start and end, but this is more efficient.
0125     startmark->updatePosition( (QTextDocument*)editor->document(),
0126                                startmark->position()-1,
0127                                QTextCharFormat() );
0128     if (documentRdf()) {
0129         Soprano::Statement st(
0130             linkingSubject(),
0131             Node::createResourceNode(QUrl("http://docs.oasis-open.org/ns/office/1.2/meta/pkg#idref")),
0132             Node::createLiteralNode(newID),
0133             documentRdf()->manifestRdfNode());
0134         documentRdf()->model()->addStatement(st);
0135         kDebug(30015) << "KoRdfSemanticItem::insert() HAVE documentRdf(), linking statement:" << st;
0136 
0137         QSharedPointer<Soprano::Model> model(Soprano::createModel());
0138         const_cast<KoDocumentRdf*>(documentRdf())->addStatements(model, newID);
0139         kDebug(30015) << "KoRdfSemanticItem::insert() returned model size:" << model->statementCount();
0140         const_cast<KoDocumentRdf*>(documentRdf())->rememberNewInlineRdfObject(inlineRdf);
0141     } else {
0142         kDebug(30015) << "KoRdfSemanticItem::insert() documentRdf() is not set!";
0143     }
0144 
0145     //
0146     // Use stylesheets to format the display of the newly inserted
0147     // semitem. To do this, there needs to be a start and end KoTextMeta
0148     // and they have to be properly linked. So first the name() is inserted
0149     // and the endmark inserted so that the stylesheet system has a valid
0150     // begin <-> end range. To make the docker happy, we move the cursor back
0151     // over the end marker so that the cursor is within the newly inserted
0152     // semitem.
0153     //
0154     editor->insertText(name());
0155 
0156     KoTextMeta *endmark = new KoTextMeta(editor->document());
0157     editor->insertInlineObject(endmark);
0158     startmark->setEndBookmark(endmark);
0159 
0160     editor->setPosition(editor->position() - 1, QTextCursor::MoveAnchor);
0161     // let the RDF docker know about this new object too.
0162     KoCanvasResourceManager *provider = host->resourceManager();
0163     provider->setResource(KoText::CurrentTextPosition, editor->position() - 1);
0164 
0165     hKoSemanticStylesheet ss = defaultStylesheet();
0166     KoRdfSemanticItemViewSite vs(hKoRdfSemanticItem(this), newID);
0167     vs.applyStylesheet(editor, ss);
0168 
0169 }
0170 
0171 QList<hKoSemanticStylesheet> KoRdfSemanticItem::userStylesheets() const
0172 {
0173     return documentRdf()->userStyleSheetList(className());
0174 }
0175 
0176 hKoSemanticStylesheet KoRdfSemanticItem::findStylesheetByUuid(const QString &id) const
0177 {
0178     hKoSemanticStylesheet ret = hKoSemanticStylesheet(0);
0179     if (id.isEmpty()) {
0180         return ret;
0181     }
0182     foreach (hKoSemanticStylesheet ss, stylesheets()) {
0183         if (ss->uuid() == id) {
0184             return ss;
0185         }
0186     }
0187     foreach (hKoSemanticStylesheet ss, userStylesheets()) {
0188         if (ss->uuid() == id) {
0189             return ss;
0190         }
0191     }
0192     return ret;
0193 }
0194 
0195 hKoSemanticStylesheet KoRdfSemanticItem::findStylesheetByName(const QList<hKoSemanticStylesheet> &ssheets,
0196         const QString &n) const
0197 {
0198     hKoSemanticStylesheet ret = hKoSemanticStylesheet(0);
0199     foreach (hKoSemanticStylesheet ss, ssheets) {
0200         if (ss->name() == n) {
0201             return ss;
0202         }
0203     }
0204     return ret;
0205 }
0206 
0207 hKoSemanticStylesheet KoRdfSemanticItem::findStylesheetByName(const QString &sheetType, const QString &n) const
0208 {
0209     if (sheetType == "System") {
0210         return findStylesheetByName(stylesheets(), n);
0211     }
0212     return findStylesheetByName(userStylesheets(), n);
0213 }
0214 
0215 hKoSemanticStylesheet KoRdfSemanticItem::defaultStylesheet() const
0216 {
0217     QString semanticClass = metaObject()->className();
0218     QSharedPointer<Soprano::Model> m = documentRdf()->model();
0219     QString name = KoTextRdfCore::getProperty(m,
0220                                               Node::createResourceNode(QUrl("http://calligra.org/rdf/document/" + semanticClass)),
0221                                               Node::createResourceNode(QUrl("http://calligra.org/rdf/stylesheet")),
0222                                               "name");
0223     QString type = KoTextRdfCore::getProperty(m,
0224                                               Node::createResourceNode(QUrl("http://calligra.org/rdf/document/" + semanticClass)),
0225                                               Node::createResourceNode(QUrl("http://calligra.org/rdf/stylesheet-type")),
0226                                               KoSemanticStylesheet::stylesheetTypeSystem());
0227     QString uuid = KoTextRdfCore::getProperty(m,
0228                                               Node::createResourceNode(QUrl("http://calligra.org/rdf/document/" + semanticClass)),
0229                                               Node::createResourceNode(QUrl("http://calligra.org/rdf/stylesheet-uuid")),
0230                                               QString());
0231     kDebug(30015) << "name:" << name << " type:" << type << "\n uuid:" << uuid;
0232     hKoSemanticStylesheet ret = findStylesheetByUuid(uuid);
0233     if (!ret) {
0234         ret = findStylesheetByName(type, name);
0235     }
0236     if (!ret) {
0237         // The "name" stylesheet should always exist
0238         ret = findStylesheetByName(KoSemanticStylesheet::stylesheetTypeSystem(), "name");
0239     }
0240     Q_ASSERT(ret);
0241     return ret;
0242 }
0243 
0244 void KoRdfSemanticItem::defaultStylesheet(hKoSemanticStylesheet ss)
0245 {
0246     const KoDocumentRdf *rdf = documentRdf();
0247     QSharedPointer<Soprano::Model> m = documentRdf()->model();
0248     QString uuid = ss->uuid();
0249     QString name = ss->name();
0250     QString semanticClass = metaObject()->className();
0251 
0252     m->removeAllStatements(
0253         Statement(Node::createResourceNode(QUrl("http://calligra.org/rdf/document/" + semanticClass)),
0254                   Node::createResourceNode(QUrl("http://calligra.org/rdf/stylesheet")),
0255                   Node()));
0256     m->addStatement(Node::createResourceNode(QUrl("http://calligra.org/rdf/document/" + semanticClass)),
0257                     Node::createResourceNode(QUrl("http://calligra.org/rdf/stylesheet")),
0258                     Node::createLiteralNode(name),
0259                     rdf->manifestRdfNode());
0260     m->removeAllStatements(
0261         Statement(Node::createResourceNode(QUrl("http://calligra.org/rdf/document/" + semanticClass)),
0262                   Node::createResourceNode(QUrl("http://calligra.org/rdf/stylesheet-type")),
0263                   Node()));
0264     m->addStatement(Node::createResourceNode(QUrl("http://calligra.org/rdf/document/" + semanticClass)),
0265                     Node::createResourceNode(QUrl("http://calligra.org/rdf/stylesheet-type")),
0266                     Node::createLiteralNode(name),
0267                     rdf->manifestRdfNode());
0268     m->removeAllStatements(
0269         Statement(Node::createResourceNode(QUrl("http://calligra.org/rdf/document/" + semanticClass)),
0270                   Node::createResourceNode(QUrl("http://calligra.org/rdf/stylesheet-uuid")),
0271                   Node()));
0272     m->addStatement(Node::createResourceNode(QUrl("http://calligra.org/rdf/document/" + semanticClass)),
0273                     Node::createResourceNode(QUrl("http://calligra.org/rdf/stylesheet-uuid")),
0274                     Node::createLiteralNode(uuid),
0275                     rdf->manifestRdfNode());
0276 }
0277 
0278 hKoSemanticStylesheet KoRdfSemanticItem::createUserStylesheet(const QString &name, const QString &templateString)
0279 {
0280     bool isMutable = true;
0281     hKoSemanticStylesheet ss =
0282         hKoSemanticStylesheet(
0283             new KoSemanticStylesheet(QUuid::createUuid().toString(),
0284                                      name, templateString,
0285                                      KoSemanticStylesheet::stylesheetTypeUser(),
0286                                      isMutable));
0287     QList<hKoSemanticStylesheet> userSheets = userStylesheets();
0288     userSheets << ss;
0289     const_cast<KoDocumentRdf*>(documentRdf())->setUserStyleSheetList(className(),userSheets);
0290     connect(ss.data(), SIGNAL(nameChanging(hKoSemanticStylesheet,QString,QString)),
0291             this, SLOT(onUserStylesheetRenamed(hKoSemanticStylesheet,QString,QString)));
0292     return ss;
0293 }
0294 
0295 hKoSemanticStylesheet KoRdfSemanticItem::createSystemStylesheet(const QString &uuid, const QString &name, const QString &templateString) const
0296 {
0297     const bool isNotMutable = false;
0298     hKoSemanticStylesheet ss =
0299         hKoSemanticStylesheet(new KoSemanticStylesheet(uuid, name, templateString, KoSemanticStylesheet::stylesheetTypeSystem(), isNotMutable));
0300     return ss;
0301 }
0302 
0303 void KoRdfSemanticItem::onUserStylesheetRenamed(hKoSemanticStylesheet ss, const QString &oldName, const QString &newName)
0304 {
0305     Q_UNUSED(ss);
0306     Q_UNUSED(oldName);
0307     Q_UNUSED(newName);
0308 }
0309 
0310 void KoRdfSemanticItem::destroyUserStylesheet(hKoSemanticStylesheet ss)
0311 {
0312     QList<hKoSemanticStylesheet> userSheets = userStylesheets();
0313     userSheets.removeAll(ss);
0314     const_cast<KoDocumentRdf*>(documentRdf())->setUserStyleSheetList(className(),userSheets);
0315 }
0316 
0317 void KoRdfSemanticItem::loadUserStylesheets(QSharedPointer<Soprano::Model> model)
0318 {
0319     QString semanticClass = metaObject()->className();
0320     QString nodePrefix = "http://calligra.org/rdf/user-stylesheets/" + semanticClass + "/";
0321     Node rdfNil = Node::createResourceNode(QUrl("http://www.w3.org/1999/02/22-rdf-syntax-ns#nil"));
0322     Node rdfFirst = Node::createResourceNode(QUrl("http://www.w3.org/1999/02/22-rdf-syntax-ns#first"));
0323     Node rdfRest = Node::createResourceNode(QUrl("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest"));
0324 
0325     Soprano::Node ListHeadSubject = Node::createResourceNode(QUrl(nodePrefix + "list"));
0326     QList<Statement> listNodes = KoTextRdfCore::loadList(model, ListHeadSubject);
0327     kDebug(30015) << "semanticClass:" << semanticClass << " listNodes.sz:" << listNodes.size();
0328     foreach (const Soprano::Statement &s, listNodes) {
0329         Soprano::Node dataBNode = s.object();
0330 
0331         QString uuid = KoTextRdfCore::getObject(model, dataBNode,
0332                                                 Node::createResourceNode(QUrl(nodePrefix + "uuid"))).toString();
0333         QString name = KoTextRdfCore::getObject(model, dataBNode,
0334                                                 Node::createResourceNode(QUrl(nodePrefix + "name"))).toString();
0335         QString templateString = KoTextRdfCore::getObject(model, dataBNode,
0336                                  Node::createResourceNode(QUrl(nodePrefix + "template"))).toString();
0337         kDebug(30015) << "dataBNode:" << dataBNode;
0338         kDebug(30015) << "loading name:" << name << " template:" << templateString;
0339 
0340         if (findStylesheetByName(userStylesheets(), name)) {
0341             continue;
0342         }
0343 
0344         bool isMutable = true;
0345         hKoSemanticStylesheet ss =
0346             hKoSemanticStylesheet(
0347                 new KoSemanticStylesheet(uuid, name, templateString,
0348                                          KoSemanticStylesheet::stylesheetTypeUser(),
0349                                          isMutable));
0350         QList<hKoSemanticStylesheet> userSheets = userStylesheets();
0351         userSheets << ss;
0352         const_cast<KoDocumentRdf*>(documentRdf())->setUserStyleSheetList(className(),userSheets);
0353         connect(ss.data(), SIGNAL(nameChanging(hKoSemanticStylesheet,QString,QString)),
0354                 this, SLOT(onUserStylesheetRenamed(KoSemanticStylesheetPtr,QString,QString)));
0355     }
0356 }
0357 
0358 void KoRdfSemanticItem::saveUserStylesheets(QSharedPointer<Soprano::Model> model, const Soprano::Node &context) const
0359 {
0360     QString semanticClass = metaObject()->className();
0361     QString nodePrefix = "http://calligra.org/rdf/user-stylesheets/" + semanticClass + "/";
0362     Node rdfNil = Node::createResourceNode(QUrl("http://www.w3.org/1999/02/22-rdf-syntax-ns#nil"));
0363     Node rdfFirst = Node::createResourceNode(QUrl("http://www.w3.org/1999/02/22-rdf-syntax-ns#first"));
0364     Node rdfRest = Node::createResourceNode(QUrl("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest"));
0365 
0366     Soprano::Node dataBNode = model->createBlankNode();
0367     QList< Soprano::Node > dataBNodeList;
0368 
0369     QList<hKoSemanticStylesheet> ssl = userStylesheets();
0370     foreach (hKoSemanticStylesheet ss, ssl) {
0371         kDebug(30015) << "saving sheet:" << ss->name();
0372 
0373         dataBNode = model->createBlankNode();
0374         model->addStatement(dataBNode, Node::createResourceNode(QUrl(nodePrefix + "uuid")),
0375             Node::createLiteralNode(ss->uuid()), context);
0376         model->addStatement(dataBNode, Node::createResourceNode(QUrl(nodePrefix + "name")),
0377             Node::createLiteralNode(ss->name()), context);
0378         model->addStatement(dataBNode, Node::createResourceNode(QUrl(nodePrefix + "template")),
0379             Node::createLiteralNode(ss->templateString()), context);
0380         dataBNodeList << dataBNode;
0381     }
0382 
0383     kDebug(30015) << "saving list, size:" << dataBNodeList.size();
0384     Soprano::Node ListHeadSubject = Node::createResourceNode(QUrl(nodePrefix + "list"));
0385     KoTextRdfCore::saveList(model, ListHeadSubject, dataBNodeList, context);
0386 }
0387 
0388 QList<hKoRdfSemanticItem> KoRdfSemanticItem::fromList(const QList< hKoRdfBasicSemanticItem > &lst)
0389 {
0390     QList<hKoRdfSemanticItem> res;
0391     foreach (const hKoRdfBasicSemanticItem &l, lst) {
0392         KoRdfSemanticItem *newl = dynamic_cast<KoRdfSemanticItem *>(l.data());
0393         if (newl) {
0394             res << hKoRdfSemanticItem(newl);
0395         }
0396     }
0397     return res;
0398 }