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

0001 /*
0002  *  Copyright (c) 2011 Boudewijn Rempt <boud@valdyas.org>
0003  *  Copyright (c) 2014-2015 Denis Kuplyakov <dener.kup@gmail.com>
0004  *
0005  * This library is free software; you can redistribute it and/or
0006  * modify it under the terms of the GNU Lesser General Public
0007  * License as published by the Free Software Foundation; either
0008  * version 2.1 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  * Lesser General Public License for more details.
0014  *
0015  * You should have received a copy of the GNU Lesser 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 "KoSection.h"
0022 
0023 #include <KoXmlNS.h>
0024 #include <KoXmlReader.h>
0025 #include <KoTextSharedLoadingData.h>
0026 #include <KoShapeSavingContext.h>
0027 #include <KoXmlWriter.h>
0028 #include <KoSectionStyle.h>
0029 #include <KoSectionModel.h>
0030 #include <KoSectionEnd.h>
0031 #include <KoTextDocument.h>
0032 #include <KoTextInlineRdf.h>
0033 
0034 #include <QTextBlock>
0035 
0036 #include "TextDebug.h"
0037 
0038 class KoSectionPrivate
0039 {
0040 public:
0041     explicit KoSectionPrivate(const QTextCursor &cursor, const QString &_name, KoSection *_parent)
0042         : document(cursor.block().document())
0043         , name(_name)
0044         , sectionStyle(0)
0045         , boundingCursorStart(cursor)
0046         , boundingCursorEnd(cursor)
0047         , parent(_parent)
0048         , inlineRdf(0)
0049     {
0050     }
0051 
0052     const QTextDocument *document;
0053 
0054     QString condition;
0055     QString display;
0056     QString name;
0057     QString text_protected;
0058     QString protection_key;
0059     QString protection_key_digest_algorithm;
0060     QString style_name;
0061     KoSectionStyle *sectionStyle;
0062 
0063     QScopedPointer<KoSectionEnd> sectionEnd; ///< pointer to the corresponding section end
0064     int level; ///< level of the section in document, root sections have 0 level
0065     QTextCursor boundingCursorStart; ///< This cursor points to the start of the section
0066     QTextCursor boundingCursorEnd; ///< This cursor points to the end of the section (excluding paragraph symbol)
0067 
0068     // Boundings explanation:
0069     //
0070     // |S|e|c|t|i|o|n|...|t|e|x|t|P|
0071     // ^                         ^
0072     // |--- Start                |-- End
0073 
0074     QVector<KoSection *> children; ///< List of the section's childrens
0075     KoSection *parent; ///< Parent of the section
0076 
0077     KoTextInlineRdf *inlineRdf; ///< Handling associated RDF
0078 };
0079 
0080 KoSection::KoSection(const QTextCursor &cursor, const QString &name, KoSection *parent)
0081     : d_ptr(new KoSectionPrivate(cursor, name, parent))
0082 {
0083     Q_D(KoSection);
0084 
0085     d->boundingCursorStart.setKeepPositionOnInsert(true); // Start cursor should stay on place
0086     d->boundingCursorEnd.setKeepPositionOnInsert(false); // and end one should move forward
0087 
0088     if (parent) {
0089         d->level = parent->level() + 1;
0090     } else {
0091         d->level = 0;
0092     }
0093 }
0094 
0095 KoSection::~KoSection()
0096 {
0097     // Here scoped pointer will delete sectionEnd
0098 }
0099 
0100 QString KoSection::name() const
0101 {
0102     Q_D(const KoSection);
0103     return d->name;
0104 }
0105 
0106 QPair<int, int> KoSection::bounds() const
0107 {
0108     Q_D(const KoSection);
0109     return QPair<int, int>(
0110         d->boundingCursorStart.position(),
0111         d->boundingCursorEnd.position()
0112     );
0113 }
0114 
0115 int KoSection::level() const
0116 {
0117     Q_D(const KoSection);
0118     return d->level;
0119 }
0120 
0121 bool KoSection::loadOdf(const KoXmlElement &element, KoTextSharedLoadingData *sharedData, bool stylesDotXml)
0122 {
0123     Q_D(KoSection);
0124     // check whether we really are a section
0125     if (element.namespaceURI() == KoXmlNS::text && element.localName() == "section") {
0126         // get all the attributes
0127         d->condition = element.attributeNS(KoXmlNS::text, "condition");
0128         d->display = element.attributeNS(KoXmlNS::text, "display");
0129 
0130         if (d->display == "condition" && d->condition.isEmpty()) {
0131             warnText << "Section display is set to \"condition\", but condition is empty.";
0132         }
0133 
0134         QString newName = element.attributeNS(KoXmlNS::text, "name");
0135         if (!KoTextDocument(d->document).sectionModel()->setName(this, newName)) {
0136             warnText << "Section name \"" << newName
0137                 << "\" must be unique or is invalid. Resetting it to " << name();
0138         }
0139 
0140         d->text_protected = element.attributeNS(KoXmlNS::text, "text-protected");
0141         d->protection_key = element.attributeNS(KoXmlNS::text, "protection-key");
0142         d->protection_key_digest_algorithm = element.attributeNS(KoXmlNS::text, "protection-key-algorithm");
0143         d->style_name = element.attributeNS(KoXmlNS::text, "style-name", "");
0144 
0145         if (!d->style_name.isEmpty()) {
0146             d->sectionStyle = sharedData->sectionStyle(d->style_name, stylesDotXml);
0147         }
0148 
0149         // lets handle associated xml:id
0150         if (element.hasAttribute("id")) {
0151             KoTextInlineRdf* inlineRdf = new KoTextInlineRdf(const_cast<QTextDocument *>(d->document), this);
0152             if (inlineRdf->loadOdf(element)) {
0153                 d->inlineRdf = inlineRdf;
0154             } else {
0155                 delete inlineRdf;
0156                 inlineRdf = 0;
0157             }
0158         }
0159 
0160         return true;
0161     }
0162     return false;
0163 }
0164 
0165 void KoSection::saveOdf(KoShapeSavingContext &context) const
0166 {
0167     Q_D(const KoSection);
0168     KoXmlWriter *writer = &context.xmlWriter();
0169     Q_ASSERT(writer);
0170     writer->startElement("text:section", false);
0171 
0172     if (!d->condition.isEmpty()) writer->addAttribute("text:condition", d->condition);
0173     if (!d->display.isEmpty()) writer->addAttribute("text:display", d->condition);
0174     if (!d->name.isEmpty()) writer->addAttribute("text:name", d->name);
0175     if (!d->text_protected.isEmpty()) writer->addAttribute("text:text-protected", d->text_protected);
0176     if (!d->protection_key.isEmpty()) writer->addAttribute("text:protection-key", d->protection_key);
0177     if (!d->protection_key_digest_algorithm.isEmpty()) {
0178         writer->addAttribute("text:protection-key-digest-algorithm", d->protection_key_digest_algorithm);
0179     }
0180     if (!d->style_name.isEmpty()) writer->addAttribute("text:style-name", d->style_name);
0181 
0182     if (d->inlineRdf) {
0183         d->inlineRdf->saveOdf(context, writer);
0184     }
0185 }
0186 
0187 void KoSection::setSectionEnd(KoSectionEnd* sectionEnd)
0188 {
0189     Q_D(KoSection);
0190     d->sectionEnd.reset(sectionEnd);
0191 }
0192 
0193 void KoSection::setName(const QString &name)
0194 {
0195     Q_D(KoSection);
0196     d->name = name;
0197 }
0198 
0199 void KoSection::setLevel(int level)
0200 {
0201     Q_D(KoSection);
0202     d->level = level;
0203 }
0204 
0205 void KoSection::setKeepEndBound(bool state)
0206 {
0207     Q_D(KoSection);
0208     d->boundingCursorEnd.setKeepPositionOnInsert(state);
0209 }
0210 
0211 KoSection *KoSection::parent() const
0212 {
0213     Q_D(const KoSection);
0214     return d->parent;
0215 }
0216 
0217 QVector<KoSection *> KoSection::children() const
0218 {
0219     Q_D(const KoSection);
0220     return d->children;
0221 }
0222 
0223 void KoSection::insertChild(int childIdx, KoSection *section)
0224 {
0225     Q_D(KoSection);
0226     d->children.insert(childIdx, section);
0227 }
0228 
0229 void KoSection::removeChild(int childIdx)
0230 {
0231     Q_D(KoSection);
0232     d->children.remove(childIdx);
0233 }
0234 
0235 KoTextInlineRdf *KoSection::inlineRdf() const
0236 {
0237     Q_D(const KoSection);
0238     return d->inlineRdf;
0239 }
0240 
0241 void KoSection::setInlineRdf(KoTextInlineRdf *inlineRdf)
0242 {
0243     Q_D(KoSection);
0244     d->inlineRdf = inlineRdf;
0245 }