Warning, file /office/calligra/libs/rdf/KoDocumentRdf.h 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 #ifndef KO_DOCUMENT_Rdf_H 0021 #define KO_DOCUMENT_Rdf_H 0022 0023 #include "kordf_export.h" 0024 #include "RdfForward.h" 0025 #include "KoSemanticStylesheet.h" 0026 #include "KoRdfSemanticItem.h" 0027 #include "KoRdfSemanticItemViewSite.h" 0028 #include "RdfSemanticTreeWidgetAction.h" 0029 #include "KoRdfSemanticTree.h" 0030 // Calligra 0031 #include <KoDocumentRdfBase.h> 0032 #include <KoXmlReaderForward.h> 0033 #include <KoDataCenterBase.h> 0034 // Soprano 0035 #include <Soprano/Soprano> 0036 // Qt 0037 #include <QObject> 0038 #include <QMap> 0039 #include <QString> 0040 #include <QStringList> 0041 #include <QTextBlockUserData> 0042 #include <QTreeWidgetItem> 0043 0044 class QDomDocument; 0045 0046 class KoStore; 0047 class KoXmlWriter; 0048 class KoDocument; 0049 class KoCanvasBase; 0050 class KoTextEditor; 0051 0052 class KoDocumentRdfPrivate; 0053 0054 class QAction; 0055 0056 /** 0057 * @short The central access point for the Rdf metadata of an ODF document. 0058 * 0059 * @author Ben Martin <ben.martin@kogmbh.com> 0060 * @see KoDocument 0061 * @see KoDocumentInfo 0062 * 0063 * The KoDocumentRdf object is possibly associated with a KoDocument. 0064 * There does not need to be a KoDocumentRdf for each KoDocument, but 0065 * if one exists it is a one-to-one relationship. The KoDocumentRdf 0066 * is also associated with the KoDocumentResourceManager of a canvas. 0067 * 0068 * Once again, the canvas to KoDocumentRdf is either a 1-1 or 1 to 0069 * zero relationship. 0070 * 0071 * ACCESS TO Rdf: 0072 * 0073 * You can get at the Rdf information in two main ways: either using 0074 * Soprano/SPARQL or through KoRdfSemanticItem objects. 0075 * 0076 * Subclasses of KoRdfSemanticItem exist for locations (foaf,vcard), 0077 * events (ical), and locations (two Rdf geolocation formats). To get 0078 * a list of these objects use the foaf(), calendarEvents(), and 0079 * locations() methods of this class. Each of these methods optionally 0080 * takes a Soprano::Model and returns a list of SemanticItems of a 0081 * particular subclass. If you do not pass an Soprano::Model to the 0082 * methods the default model() of the KoDocumentRdf is used. By 0083 * allowing you to pass a model explicitly, you can find contacts that 0084 * exist in a subset of the full Rdf graph for a document. This is 0085 * useful if you want to find the contacts in the users current 0086 * "selection" in the document. 0087 * 0088 * For example, to find the foaf entries related to the current KoTextEditor 0089 * 0090 * Soprano::Model* model = rdf->findStatements( editor ); 0091 * QList<hKoRdfSemanticItem> foaflist = rdf->semanticItems( "Contact", model ); 0092 * 0093 * Using the Soprano::Model directly is covered in a latter section of 0094 * this comment. 0095 * 0096 * STORAGE OF Rdf: 0097 * 0098 * Broadly there are two ways Rdf metadata is stored in an ODF 0099 * document. 0100 * 0101 * 1) inline in the content.xml file in an Rdfa style, though not 0102 * using the full Rdfa spec 0103 * 0104 * 2) externally in manifest.rdf or other Rdf/XML files linked to by 0105 * manifest.rdf 0106 * 0107 * The Rdf that is stored using these methods is collected and made 0108 * available by the KoDocumentRdf class. The inline Rdf using option 0109 * (1) is stored along with the Calligra C++ objects that are created 0110 * during document loading. This class also knows how to find the 0111 * scattered Rdf that option (1) loads. Leaving the Rdf from option 0112 * (1) scattered in the document allows it to be preserved in the 0113 * normal course of document editing such as copy and paste, undo and 0114 * redo operations. 0115 * 0116 * The scattered Rdf from option (1) is stored using the 0117 * KoTextInlineRdf class. You can convert a KoTextInlineRdf to 0118 * a Soprano::Statement with the toStatement() method of this class. 0119 * 0120 * LOW LEVEL Rdf ACCESS: 0121 * 0122 * The model() method will give you a Soprano::model with all the Rdf 0123 * for the document, be them from option (1) or (2) above. 0124 * 0125 * The findStatements() methods will give you a Soprano::model 0126 * containing the statements relevant to a cursor or xml:id in the 0127 * document. The xml:id is the same identifier that is used in the 0128 * content.xml file that was loaded. 0129 * 0130 * Note that the findStatements() returns a submodel containing only 0131 * the statements relevant to the xml:id or cursor position you 0132 * selected. This will be a subset of all the Rdf for the document. 0133 * The various expand() methods can be used to add more Rdf statements 0134 * from the document to the submodel returned by findStatements(). For 0135 * example, the expandStatementsReferencingSubject() method will 0136 * expand the soprano::model to add Rdf statements which refer to any 0137 * subject in the Rdf submodel you pass in. 0138 */ 0139 class KORDF_EXPORT KoDocumentRdf : public KoDocumentRdfBase 0140 { 0141 Q_OBJECT 0142 public: 0143 /** 0144 * For Rdf stored in manifest.rdf or another rdf file referenced 0145 * by the manifest, this prefix is used as the start of the graph 0146 * context. The filename.rdf is appended so that the Rdf can be 0147 * put back into the right file again during save. 0148 */ 0149 const static QString RDF_PATH_CONTEXT_PREFIX; 0150 0151 /** 0152 * The constructor 0153 * @param parent a pointer to the parent object 0154 */ 0155 explicit KoDocumentRdf(QObject *parent = 0); 0156 0157 /** The destructor */ 0158 ~KoDocumentRdf(); 0159 0160 /** 0161 * Load from an OASIS document 0162 * @param store the store with the metaInformation 0163 * @return true if success 0164 */ 0165 bool loadOasis(KoStore *store); 0166 0167 /** 0168 * Save to an OASIS document 0169 * @param store a pointer to a KoStore to save in 0170 * @param manifestWriter the document writer 0171 * @return true if success 0172 */ 0173 bool saveOasis(KoStore *store, KoXmlWriter *manifestWriter); 0174 0175 /** 0176 * Used by KoRdfSemanticItem when creating new semantic items so that the 0177 * KoDocumentRdf class can find them. 0178 */ 0179 void rememberNewInlineRdfObject(KoTextInlineRdf *inlineRdf); 0180 0181 /** 0182 * Find all the KoTextInlineRdf objects that exist in the 0183 * document and update the statements in the Soprano::(model) to 0184 * reflect the current state of the inline Rdf. 0185 */ 0186 void updateInlineRdfStatements(const QTextDocument *qdoc); 0187 0188 /** 0189 * During a save(), various Rdf objects in the document will 0190 * create new xmlid values which are used in the saved document. 0191 * As part of the save state a QMap from the old xmlid to the new 0192 * xmlid is built up. This method is then used to update the Rdf 0193 * triples to use the new xmlid values before that Rdf itself is 0194 * saved. This way the Rdf -> xmlid references will remain valid 0195 * in the saved ODF file. 0196 * 0197 * Since the Rdf is updated to use the new xmlid values, this method 0198 * also updates the C++ objects to use the new xmlid values so that 0199 * the instance of the document in memory is correctly linked. 0200 * 0201 * This way, Calligra is free to change the xml:id during save() and 0202 * the Rdf is still linked correctly. 0203 */ 0204 void updateXmlIdReferences(const QMap<QString, QString> &m); 0205 0206 /** 0207 * Get the namespace to URI prefix mapping object. 0208 */ 0209 KoRdfPrefixMapping* prefixMapping() const; 0210 0211 /** 0212 * Get the Soprano::Model that contains all the Rdf 0213 * You do not own the model, do not delete it. 0214 */ 0215 virtual QSharedPointer<Soprano::Model> model() const; 0216 0217 /** 0218 * Convert an inlineRdf object into a Soprano::Statement 0219 */ 0220 Soprano::Statement toStatement(KoTextInlineRdf *inlineRdf) const; 0221 0222 /** 0223 * Look for the semitem with the given xmlid and return the 0224 * start and end position for that semitem. If there is no semitem 0225 * with the \p xmlId then 0,0 is returned. 0226 */ 0227 QPair<int, int> findExtent(const QString &xmlId) const; 0228 0229 /** 0230 * Look for the semitem that is at or surrounding the cursor given. Note that if there 0231 * are nested semitems, the extend for the most nested semitem is returned. 0232 * for example, in the below scenario the return value will be QPair< start-b, end-b >. 0233 * 0234 * <start-a> ... <start-b> ... cursor ... <end-b> ... <end-a> 0235 */ 0236 QPair<int, int> findExtent(KoTextEditor *handler) const; 0237 0238 /** 0239 * find the xmlid of the semitem that is at or surrounding the cursor given. As with 0240 * findExtent() this will be only the most nested semitem. 0241 * @see findExtent() 0242 */ 0243 QString findXmlId(KoTextEditor *cursor) const; 0244 0245 0246 /** 0247 * Find all of the statements which are 0248 * in context for a given cursor position. 0249 * 0250 * Rdf is also added to the returned model from external manifest.rdf 0251 * and other files which attach to the xml:id 0252 * 0253 * The depth parameter allows triple expansion, ie, 0254 * depth=1 adds only triples which reference ?s ?p xml:id 0255 * depth=2 adds references to statements in depth=1, 0256 * ie, ?s1 ?p2 ?s2 and ?s2 ?p xml:id 0257 * Because of the complexity, depth should be <=2 or you should use 0258 * a custom query. 0259 * 0260 * FIXME: The logical thing here would be to chain up. 0261 * given a cursor in a table:cell, the Rdf for the containing 0262 * text:p and text:meta elements should be returned too. 0263 * 0264 * Note that the returned model is owned by the caller, you must delete it. 0265 */ 0266 QSharedPointer<Soprano::Model> findStatements(const QString &xmlid, int depth = 1); 0267 QSharedPointer<Soprano::Model> findStatements(KoTextEditor *handler, int depth = 1); 0268 0269 /** 0270 * Add all the Rdf that is associated with the given xml:id 0271 */ 0272 void addStatements(QSharedPointer<Soprano::Model> model, const QString &xmlid); 0273 0274 /** 0275 * Find an inline Rdf object from the xml:id which 0276 * it has in the content.xml file 0277 */ 0278 KoTextInlineRdf* findInlineRdfByID(const QString &xmlid) const; 0279 0280 /** 0281 * Obtain a list of semantic objects of the given class, if any, for the Rdf 0282 * in the default model() or the one you optionally pass in. 0283 */ 0284 QList< hKoRdfBasicSemanticItem > semanticItems(const QString &className, QSharedPointer< Soprano::Model > m = QSharedPointer<Soprano::Model>(0)); 0285 0286 /** 0287 * Create a SemanticItem subclass using its name from 0288 * classNames(). Useful for menus and other places that want to 0289 * allow the user to create new SemanticItem Objects. 0290 */ 0291 hKoRdfBasicSemanticItem createSemanticItem(const QString &semanticClass, QObject *parent = 0) const; 0292 0293 /** 0294 * This is used for triples that do not specify their xhtml:about 0295 * ie, the subject URI. 0296 */ 0297 QString rdfInternalMetadataWithoutSubjectURI() const; 0298 0299 /** 0300 * Soprano::Node that can be used as the model context for 0301 * statements which should be stored in the manifest.rdf file. 0302 */ 0303 Soprano::Node manifestRdfNode() const; 0304 0305 /** 0306 * Soprano::Node that can be used as the model context for 0307 * statements which were stored in the context.xml file. 0308 */ 0309 Soprano::Node inlineRdfContext() const; 0310 0311 /** 0312 * If model contains ?s ?p ?o 0313 * look for and add 0314 * ?s2 ?p2 ?s 0315 */ 0316 void expandStatementsReferencingSubject(QSharedPointer<Soprano::Model> model) const; 0317 0318 /** 0319 * If model contains ?s ?p ?o 0320 * look for and add 0321 * ?o ?p2 ?o2 0322 */ 0323 void expandStatementsSubjectPointsTo(QSharedPointer<Soprano::Model> model) const; 0324 0325 /** 0326 * Add n ?p ?o from m_model to model 0327 */ 0328 void expandStatementsSubjectPointsTo(QSharedPointer<Soprano::Model> model, const Soprano::Node &n) const; 0329 0330 /** 0331 * Rdf allows for linked lists to be serialized as a graph. This method will 0332 * ensure that all data from m_model for any lists that are started in 'model' 0333 * is copied into 'model'. 0334 * 0335 * Lists have the format 0336 * prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> 0337 * ?id rdf:first ?value 0338 * ?id rdf:rest ?next1 0339 * ?next1 rdf:first ?value2 0340 * ?next1 rdf:rest ?nextN 0341 * ?nextN rdf:first ?valueN 0342 * ?nextN rdf:rest rdf:nil 0343 */ 0344 void expandStatementsToIncludeRdfLists(QSharedPointer<Soprano::Model> model) const; 0345 0346 /** 0347 * If model contains ?s ?p ?o 0348 * look for and add 0349 * ?s ?p3 ?o3 0350 */ 0351 void expandStatementsToIncludeOtherPredicates(QSharedPointer<Soprano::Model> model) const; 0352 0353 /** 0354 * One round of all expandStatements methods 0355 */ 0356 void expandStatements(QSharedPointer<Soprano::Model> model) const; 0357 0358 /** 0359 * FIXME? What does this do? 0360 */ 0361 QAction * createInsertSemanticObjectReferenceAction(KoCanvasBase *host); 0362 0363 /** 0364 * FIXME? What does this do? 0365 */ 0366 QList<QAction *> createInsertSemanticObjectNewActions(KoCanvasBase *host); 0367 0368 /** 0369 * Collect together the semantic item, stylehseet, xmlid of the 0370 * site to apply it at and the extent in the document (start,end) 0371 * of the semantic item. Used when applying stylesheets in bulk so 0372 * that all the sites can be collected and the QMap<int,reflowItem> map 0373 * will sort them in the order of start to end document position. 0374 * 0375 * @see insertReflow() 0376 * @see applyReflow() 0377 */ 0378 struct reflowItem 0379 { 0380 hKoRdfSemanticItem m_si; 0381 hKoSemanticStylesheet m_ss; 0382 QString m_xmlid; 0383 QPair<int, int> m_extent; 0384 0385 reflowItem(hKoRdfSemanticItem si, const QString &xmlid, hKoSemanticStylesheet ss, const QPair<int, int> &extent); 0386 }; 0387 0388 /** 0389 * Because applying a stylesheet to a semantic item could change 0390 * the length of the text showing the item in the document, it is 0391 * best to apply these stylesheets to semitems starting from the 0392 * end of the document. This is because any change in the length 0393 * of a semitem has no effect on all the other semitems that are 0394 * before it in the document. After we have applied all the 0395 * changes, the kwdoc will update the positions of all the 0396 * kotextmeta etc objects and they will once again be correct. 0397 * Doing things explicitly backwards is a huge efficiency gain 0398 * because no layout is needed on the document during our updates 0399 * because each update does not invalidate the positions of any 0400 * objects before the update in the document text. 0401 * 0402 * Call insertReflow() for all the items you want to apply a 0403 * stylesheet on and then applyReflow() with the built up 0404 * collection 'col' argument to will actually apply the 0405 * stylesheets starting from the semitem lowest in the document 0406 * and working backwards. 0407 * 0408 * @see applyReflow() 0409 */ 0410 void insertReflow(QMap<int, reflowItem> &col, hKoRdfSemanticItem obj, hKoSemanticStylesheet ss); 0411 void insertReflow(QMap<int, reflowItem> &col, hKoRdfSemanticItem obj, const QString &sheetType, const QString &stylesheetName); 0412 void insertReflow(QMap<int, reflowItem> &col, hKoRdfSemanticItem obj); 0413 /** 0414 * @short Apply the stylesheets built up with insertReflow(). 0415 * 0416 * @see insertReflow() 0417 */ 0418 void applyReflow(const QMap<int, reflowItem> &col); 0419 0420 //FIXME: this method also seems to be STATIC and why it has such second default param?? 0421 /** 0422 * For debugging, output the model and a header string for identification 0423 */ 0424 void dumpModel(const QString &msg, QSharedPointer<Soprano::Model> m = QSharedPointer<Soprano::Model>(0)) const; 0425 0426 Q_SIGNALS: 0427 /** 0428 * Emitted when a new semanticItem is created so that dockers can 0429 * update themselves accordingly. It is expected that when 0430 * semanticObjectViewSiteUpdated is emitted the view will take care 0431 * of reflowing the semantic item using it's stylesheet. 0432 */ 0433 void semanticObjectAdded(hKoRdfBasicSemanticItem item) const; 0434 void semanticObjectUpdated(hKoRdfBasicSemanticItem item) const; 0435 void semanticObjectViewSiteUpdated(hKoRdfBasicSemanticItem item, const QString &xmlid) const; 0436 0437 public: 0438 void emitSemanticObjectAdded(hKoRdfBasicSemanticItem item) const; 0439 void emitSemanticObjectUpdated(hKoRdfBasicSemanticItem item); 0440 void emitSemanticObjectViewSiteUpdated(hKoRdfBasicSemanticItem item, const QString &xmlid); 0441 void emitSemanticObjectAddedConst(hKoRdfBasicSemanticItem const item) const; 0442 0443 /** 0444 * You should use the KoRdfSemanticItem::userStylesheets() method instead of this one. 0445 * This is mainly an internal method to allow user stylesheets to be managed per document. 0446 */ 0447 QList<hKoSemanticStylesheet> userStyleSheetList(const QString& className) const; 0448 void setUserStyleSheetList(const QString& className,const QList<hKoSemanticStylesheet>& l); 0449 0450 0451 private: 0452 0453 /** 0454 * @see expandStatementsToIncludeRdfLists() 0455 */ 0456 void expandStatementsToIncludeRdfListsRecurse(QSharedPointer<Soprano::Model> model, 0457 QList<Soprano::Statement> &addList, 0458 const Soprano::Node &n) const; 0459 0460 0461 /** 0462 * Soprano can give undesirable behaviour when loading two files 0463 * into the same model. When parsing the second Rdf file, the sane 0464 * genid1 numbers can be reused, leading to semantic errors on 0465 * bnodes. This method updates all the bnodes in 'm' to be new 0466 * ones created using m_model->createBlankNode(). bnode identity 0467 * is preserved for the model m. ie. genid2 and another genid2 in 0468 * m will be replaced with the same m_model->createBlankNode() 0469 * value. After calling this method, you can add all the 0470 * statements to 'm' and be assured that no bnodes in 'm' are 0471 * going to accidentially be the same as a bnode in m_model. 0472 */ 0473 void freshenBNodes(QSharedPointer<Soprano::Model> m); 0474 0475 /** 0476 * Used by loadOasis() to load Rdf from a particular external 0477 * Rdf/XML file. 0478 */ 0479 bool loadRdf(KoStore *store, const Soprano::Parser *parser, const QString &fileName); 0480 0481 /** 0482 * Used by saveOasis() to save Rdf to a the Rdf file nominated 0483 * with context. Note that this method can not be used to save to 0484 * content.xml, those Rdf statements must be saved as the 0485 * content.xml file is generated. 0486 */ 0487 bool saveRdf(KoStore *store, KoXmlWriter *manifestWriter, const Soprano::Node &context) const; 0488 0489 0490 /** 0491 * idrefList queries soprano after loading and creates a list of all rdfid's that 0492 * where found in the manifest.rdf document. This list is used to make sure we do not 0493 * create more inline rdf objects than necessary 0494 * @return a list of xml-id's 0495 */ 0496 QStringList idrefList() const; 0497 0498 private: 0499 0500 /** 0501 * Test whether a model is present that supports: 0502 * - context / graphs 0503 * - querying on graphs 0504 * - storage in memory. 0505 */ 0506 bool backendIsSane(); 0507 0508 /// reimplemented 0509 virtual bool completeLoading(KoStore *store); 0510 0511 /// reimplemented 0512 virtual bool completeSaving(KoStore *store, KoXmlWriter *manifestWriter, KoShapeSavingContext *context); 0513 0514 KoDocumentRdfPrivate * const d; 0515 }; 0516 0517 #endif