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 }