Warning, file /office/calligra/libs/text/KoAnnotation.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) 2007-2008 Fredy Yanardi <fyanardi@gmail.com>
0003  * Copyright (C) 2011 Boudewijn Rempt <boud@kogmbh.com>
0004  * Copyright (C) 2012 Inge Wallin <inge@lysator.liu.se>
0005  *
0006  * This library is free software; you can redistribute it and/or
0007  * modify it under the terms of the GNU Library General Public
0008  * License as published by the Free Software Foundation; either
0009  * version 2 of the License, or (at your option) any later version.
0010  *
0011  * This library is distributed in the hope that it will be useful,
0012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014  * Library General Public License for more details.
0015  *
0016  * You should have received a copy of the GNU Library General Public License
0017  * along with this library; see the file COPYING.LIB.  If not, write to
0018  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0019  * Boston, MA 02110-1301, USA.
0020  */
0021 
0022 #include "KoAnnotation.h"
0023 
0024 #include <KoShapeSavingContext.h>
0025 #include <KoXmlWriter.h>
0026 #include <KoXmlReader.h>
0027 #include <KoTextInlineRdf.h>
0028 #include <KoTextRangeManager.h>
0029 #include <KoXmlNS.h>
0030 #include <KoShape.h>
0031 
0032 #include <QTextDocument>
0033 #include <QTextBlock>
0034 #include <QTextCursor>
0035 #include "TextDebug.h"
0036 
0037 // Include Q_UNSUSED classes, for building on Windows
0038 #include <KoShapeLoadingContext.h>
0039 
0040 class Q_DECL_HIDDEN KoAnnotation::Private
0041 {
0042 public:
0043     Private(const QTextDocument *doc):
0044         document(doc),
0045         posInDocument(0) { }
0046     const QTextDocument *document;
0047     int posInDocument;
0048 
0049     // Name of this annotation. It is used to tie together the annotation and annotation-end tags
0050     QString name;
0051 
0052     KoShape *shape;
0053 };
0054 
0055 KoAnnotation::KoAnnotation(const QTextCursor &cursor)
0056     : KoTextRange(cursor),
0057       d(new Private(cursor.block().document()))
0058 {
0059 }
0060 
0061 KoAnnotation::~KoAnnotation()
0062 {
0063     delete d;
0064 }
0065 
0066 
0067 void KoAnnotation::setName(const QString &name)
0068 {
0069     d->name = name;
0070 }
0071 
0072 QString KoAnnotation::name() const
0073 {
0074     return d->name;
0075 }
0076 
0077 void KoAnnotation::setAnnotationShape(KoShape *shape)
0078 {
0079     d->shape = shape;
0080 }
0081 
0082 KoShape *KoAnnotation::annotationShape() const
0083 {
0084     return d->shape;
0085 }
0086 
0087 bool KoAnnotation::loadOdf(const KoXmlElement &element, KoShapeLoadingContext &context)
0088 {
0089     Q_UNUSED(context);
0090 
0091     if (element.localName() != "annotation") {
0092         return false;
0093     }
0094 
0095     //debugText << "****** Start Load odf ******";
0096     QString annotationName = element.attribute("name");
0097 
0098     if (manager()) {
0099         // For cut and paste, make sure that the name is unique.
0100         d->name = createUniqueAnnotationName(manager()->annotationManager(), annotationName, false);
0101 
0102         // When loading an annotation we must assume that it is for a point rather than
0103         // a range. If we encounter an <annotation-end> tag later, we will change that.
0104         setPositionOnlyMode(true);
0105 
0106         // Add inline Rdf to the annotation.
0107         if (element.hasAttributeNS(KoXmlNS::xhtml, "property") || element.hasAttribute("id")) {
0108             KoTextInlineRdf* inlineRdf = new KoTextInlineRdf(const_cast<QTextDocument*>(d->document), this);
0109             if (inlineRdf->loadOdf(element)) {
0110                 setInlineRdf(inlineRdf);
0111             }
0112             else {
0113                 delete inlineRdf;
0114                 inlineRdf = 0;
0115             }
0116         }
0117         //debugText << "****** End Load ******";
0118 
0119         return true;
0120     }
0121 
0122     return false;
0123 }
0124 
0125 void KoAnnotation::saveOdf(KoShapeSavingContext &context, int position, TagType tagType) const
0126 {
0127     KoXmlWriter *writer = &context.xmlWriter();
0128 
0129     if (!hasRange()) {
0130 
0131         if (tagType == StartTag) {
0132             writer->startElement("office:annotation", false);
0133             writer->addAttribute("text:name", d->name.toUtf8());
0134             if (inlineRdf()) {
0135                 inlineRdf()->saveOdf(context, writer);
0136             }
0137 
0138             d->shape->saveOdf(context);
0139 
0140             writer->endElement(); //office:annotation
0141         }
0142 
0143     } else if ((tagType == StartTag) && (position == rangeStart())) {
0144         writer->startElement("office:annotation", false);
0145         writer->addAttribute("text:name", d->name.toUtf8());
0146         if (inlineRdf()) {
0147             inlineRdf()->saveOdf(context, writer);
0148         }
0149 
0150         d->shape->saveOdf(context);
0151 
0152         writer->endElement(); //office:annotation
0153     } else if ((tagType == EndTag) && (position == rangeEnd())) {
0154         writer->startElement("office:annotation-end", false);
0155         writer->addAttribute("text:name", d->name.toUtf8());
0156         writer->endElement();
0157     }
0158         // else nothing
0159 
0160 }
0161 
0162 QString KoAnnotation::createUniqueAnnotationName(const KoAnnotationManager* kam,
0163                                                  const QString &annotationName, bool isEndMarker)
0164 {
0165     QString ret = annotationName;
0166     int uniqID = 0;
0167 
0168     while (true) {
0169         if (kam->annotation(ret)) {
0170             ret = QString("%1_%2").arg(annotationName).arg(++uniqID);
0171         } else {
0172             if (isEndMarker) {
0173                 --uniqID;
0174                 if (!uniqID)
0175                     ret = annotationName;
0176                 else
0177                     ret = QString("%1_%2").arg(annotationName).arg(uniqID);
0178             }
0179             break;
0180         }
0181     }
0182     return ret;
0183 }