Warning, file /office/calligra/libs/text/KoInlineNote.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 Thomas Zander <zander@kde.org>
0003  * Copyright (C) 2010 KO Gmbh <boud@kogmbh.com>
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 #include "KoInlineNote.h"
0021 
0022 #include <KoXmlWriter.h>
0023 #include <KoXmlNS.h>
0024 #include <KoShapeSavingContext.h>
0025 #include <KoOdfNumberDefinition.h>
0026 #include <KoTextLoader.h>
0027 #include <KoTextWriter.h>
0028 #include <KoTextDocument.h>
0029 #include <KoText.h>
0030 #include <KoStyleManager.h>
0031 #include <KoParagraphStyle.h>
0032 #include "TextDebug.h"
0033 #include <writeodf/writeodftext.h>
0034 #include <writeodf/writeodfoffice.h>
0035 #include <writeodf/writeodfdc.h>
0036 
0037 #include <QTextDocument>
0038 #include <QTextFrame>
0039 #include <QTextCursor>
0040 #include <QTextInlineObject>
0041 #include <QFontMetricsF>
0042 #include <QTextOption>
0043 #include <QDateTime>
0044 
0045 using namespace writeodf;
0046 
0047 class Q_DECL_HIDDEN KoInlineNote::Private
0048 {
0049 public:
0050     Private(KoInlineNote::Type t)
0051         : textFrame(0)
0052         , autoNumbering(false)
0053         , type(t)
0054     {
0055     }
0056 
0057     QTextDocument *document;
0058     QTextFrame *textFrame;
0059     QString label;
0060     QString author;
0061     QDateTime date;
0062     bool autoNumbering;
0063     KoInlineNote::Type type;
0064     int posInDocument;
0065 };
0066 
0067 KoInlineNote::KoInlineNote(Type type)
0068     : KoInlineObject(true)
0069     , d(new Private(type))
0070 {
0071 }
0072 
0073 KoInlineNote::~KoInlineNote()
0074 {
0075     delete d;
0076 }
0077 
0078 void KoInlineNote::setMotherFrame(QTextFrame *motherFrame)
0079 {
0080     d->document = motherFrame->document();
0081 
0082     // We create our own subframe
0083 
0084     QTextCursor cursor(motherFrame->lastCursorPosition());
0085     QTextFrameFormat format;
0086     format.setProperty(KoText::SubFrameType, KoText::NoteFrameType);
0087     d->textFrame = cursor.insertFrame(format);
0088 
0089     // Now let's make sure it has the right paragraph
0090     KoOdfNotesConfiguration *notesConfig = 0;
0091     if (d->type == KoInlineNote::Footnote) {
0092         notesConfig = KoTextDocument(d->document).styleManager()->notesConfiguration(KoOdfNotesConfiguration::Footnote);
0093     } else if (d->type == KoInlineNote::Endnote) {
0094         notesConfig = KoTextDocument(d->document).styleManager()->notesConfiguration(KoOdfNotesConfiguration::Endnote);
0095     }
0096 
0097     KoParagraphStyle *style = static_cast<KoParagraphStyle *>(notesConfig->defaultNoteParagraphStyle());
0098     if (style) {
0099         QTextBlockFormat bf;
0100         QTextCharFormat cf;
0101         style->applyStyle(bf);
0102         style->KoCharacterStyle::applyStyle(cf);
0103         cursor.setBlockFormat(bf);
0104         cursor.setBlockCharFormat(cf);
0105     }
0106 }
0107 
0108 void KoInlineNote::setLabel(const QString &text)
0109 {
0110     d->label = text;
0111 }
0112 
0113 void KoInlineNote::setAutoNumber(int autoNumber)
0114 {
0115     if (d->autoNumbering) {
0116         KoOdfNotesConfiguration *notesConfig = 0;
0117         if (d->type == KoInlineNote::Footnote) {
0118             notesConfig = KoTextDocument(d->document).styleManager()->notesConfiguration(KoOdfNotesConfiguration::Footnote);
0119         } else if (d->type == KoInlineNote::Endnote) {
0120             notesConfig = KoTextDocument(d->document).styleManager()->notesConfiguration(KoOdfNotesConfiguration::Endnote);
0121         }
0122         d->label = notesConfig->numberFormat().formattedNumber(autoNumber + notesConfig->startValue());
0123     }
0124 }
0125 
0126 QTextFrame *KoInlineNote::textFrame() const
0127 {
0128     return d->textFrame;
0129 }
0130 
0131 void KoInlineNote::setTextFrame(QTextFrame *textFrame)
0132 {
0133     d->textFrame = textFrame;
0134 }
0135 
0136 QString KoInlineNote::label() const
0137 {
0138     return d->label;
0139 }
0140 
0141 bool KoInlineNote::autoNumbering() const
0142 {
0143     return d->autoNumbering;
0144 }
0145 
0146 void KoInlineNote::setAutoNumbering(bool on)
0147 {
0148     d->autoNumbering = on;
0149 }
0150 
0151 KoInlineNote::Type KoInlineNote::type() const
0152 {
0153     return d->type;
0154 }
0155 
0156 void KoInlineNote::updatePosition(const QTextDocument *document, int posInDocument, const QTextCharFormat &format)
0157 {
0158     Q_UNUSED(document);
0159     Q_UNUSED(format);
0160 
0161     d->posInDocument = posInDocument;
0162 }
0163 
0164 void KoInlineNote::resize(const QTextDocument *document, QTextInlineObject &object, int posInDocument, const QTextCharFormat &format, QPaintDevice *pd)
0165 {
0166     Q_UNUSED(document);
0167     Q_UNUSED(posInDocument);
0168     if (d->label.isEmpty()) {
0169         object.setWidth(0);
0170         object.setAscent(0);
0171         object.setDescent(0);
0172     } else {
0173         Q_ASSERT(format.isCharFormat());
0174         QFontMetricsF fm(format.font(), pd);
0175         object.setWidth(fm.width(d->label));
0176         object.setAscent(fm.ascent());
0177         object.setDescent(fm.descent());
0178     }
0179 }
0180 
0181 void KoInlineNote::paint(QPainter &painter, QPaintDevice *pd, const QTextDocument *document, const QRectF &rect, const QTextInlineObject &object, int posInDocument, const QTextCharFormat &originalFormat)
0182 {
0183     Q_UNUSED(document);
0184     Q_UNUSED(posInDocument);
0185 
0186     if (d->label.isEmpty())
0187         return;
0188 
0189     QTextCharFormat format = originalFormat;
0190     KoOdfNotesConfiguration *notesConfig = 0;
0191     if (d->type == KoInlineNote::Footnote) {
0192         notesConfig = KoTextDocument(d->document).styleManager()->notesConfiguration(KoOdfNotesConfiguration::Footnote);
0193     } else if (d->type == KoInlineNote::Endnote) {
0194         notesConfig = KoTextDocument(d->document).styleManager()->notesConfiguration(KoOdfNotesConfiguration::Endnote);
0195     }
0196     KoCharacterStyle *style = static_cast<KoCharacterStyle *>(notesConfig->citationBodyTextStyle());
0197     if (style) {
0198         style->applyStyle(format);
0199     }
0200 
0201     QFont font(format.font(), pd);
0202     QTextLayout layout(d->label, font, pd);
0203     layout.setCacheEnabled(true);
0204     QList<QTextLayout::FormatRange> layouts;
0205     QTextLayout::FormatRange range;
0206     range.start = 0;
0207     range.length = d->label.length();
0208     range.format = format;
0209     layouts.append(range);
0210     layout.setAdditionalFormats(layouts);
0211 
0212     QTextOption option(Qt::AlignLeft | Qt::AlignAbsolute);
0213     option.setTextDirection(object.textDirection());
0214     layout.setTextOption(option);
0215     layout.beginLayout();
0216     layout.createLine();
0217     layout.endLayout();
0218     layout.draw(&painter, rect.topLeft());
0219 }
0220 
0221 bool KoInlineNote::loadOdf(const KoXmlElement & element, KoShapeLoadingContext &context)
0222 {
0223     KoTextLoader loader(context);
0224     QTextCursor cursor(d->textFrame);
0225 
0226     if (element.namespaceURI() == KoXmlNS::text && element.localName() == "note") {
0227 
0228         QString className = element.attributeNS(KoXmlNS::text, "note-class");
0229         if (className == "footnote") {
0230             d->type = Footnote;
0231         }
0232         else if (className == "endnote") {
0233             d->type = Endnote;
0234         }
0235         else {
0236             return false;
0237         }
0238 
0239         for (KoXmlNode node = element.firstChild(); !node.isNull(); node = node.nextSibling()) {
0240             KoXmlElement ts = node.toElement();
0241             if (ts.namespaceURI() != KoXmlNS::text)
0242                 continue;
0243             if (ts.localName() == "note-body") {
0244                 loader.loadBody(ts, cursor);
0245             } else if (ts.localName() == "note-citation") {
0246                 d->label = ts.attributeNS(KoXmlNS::text, "label");
0247                 if (d->label.isEmpty()) {
0248                     setAutoNumbering(true);
0249                     d->label = ts.text();
0250                 }
0251             }
0252         }
0253     }
0254     else if (element.namespaceURI() == KoXmlNS::office && element.localName() == "annotation") {
0255         d->author = element.attributeNS(KoXmlNS::text, "dc-creator");
0256         d->date = QDateTime::fromString(element.attributeNS(KoXmlNS::text, "dc-date"), Qt::ISODate);
0257         loader.loadBody(element, cursor); // would skip author and date, and do just the <text-p> and <text-list> elements
0258     }
0259     else {
0260         return false;
0261     }
0262 
0263     return true;
0264 }
0265 
0266 void KoInlineNote::saveOdf(KoShapeSavingContext & context)
0267 {
0268     KoXmlWriter *writer = &context.xmlWriter();
0269 
0270     if (d->type == Footnote || d->type == Endnote) {
0271         text_note note(writer, (d->type == Footnote) ?"footnote" :"endnote");
0272         text_note_citation cite(note.add_text_note_citation());
0273         if (!autoNumbering()) {
0274             cite.set_text_label(d->label);
0275         }
0276         cite.addTextNode(d->label);
0277 
0278         text_note_body body(note.add_text_note_body());
0279         KoTextWriter textWriter(context);
0280         textWriter.write(d->document, d->textFrame->firstPosition(), d->textFrame->lastPosition());
0281     }
0282     else if (d->type == Annotation) {
0283         office_annotation annotation(writer);
0284         if (!d->author.isEmpty()) {
0285             dc_creator creator(annotation.add_dc_creator());
0286             creator.addTextNode(d->author);
0287         }
0288         if (d->date.isValid()) {
0289             dc_date date(annotation.add_dc_date());
0290             date.addTextNode(d->date.toString(Qt::ISODate));
0291         }
0292 
0293         KoTextWriter textWriter(context);
0294         textWriter.write(d->document, d->textFrame->firstPosition(),d->textFrame->lastPosition());
0295     }
0296 }
0297 
0298 int KoInlineNote::getPosInDocument() const
0299 {
0300     return d->posInDocument;
0301 }