File indexing completed on 2024-05-12 16:35:03

0001 /* This file is part of the KDE project
0002  * Copyright (C) 2007 Pierre Ducroquet <pinaraf@gmail.com>
0003  * Copyright (C) 2008 Thorsten Zachmann <zachmann@kde.org>
0004  * Copyright (C) 2008 Sebastian Sauer <mail@dipe.org>
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 "PageVariable.h"
0023 
0024 #include "VariablesDebug.h"
0025 
0026 #include <KoXmlReader.h>
0027 #include <KoXmlWriter.h>
0028 #include <KoProperties.h>
0029 #include <KoShape.h>
0030 #include <KoShapeSavingContext.h>
0031 #include <KoShapeLoadingContext.h>
0032 #include <KoXmlNS.h>
0033 #include <KoTextLayoutRootArea.h>
0034 #include <KoTextDocumentLayout.h>
0035 #include <KoTextDocument.h>
0036 
0037 #include <QFontMetricsF>
0038 #include <QTextDocument>
0039 #include <QAbstractTextDocumentLayout>
0040 #include <QTextInlineObject>
0041 
0042 PageVariable::PageVariable()
0043         : KoVariable(true),
0044         m_type(PageNumber),
0045         m_pageselect(KoTextPage::CurrentPage),
0046         m_pageadjust(0),
0047         m_fixed(false)
0048 {
0049 }
0050 
0051 void PageVariable::readProperties(const KoProperties *props)
0052 {
0053     switch (props->intProperty("vartype")) {
0054     case 1:
0055         m_type = PageCount;
0056         break;
0057     case 2:
0058         m_type = PageNumber;
0059         break;
0060     case 3:
0061         m_type = PageContinuation;
0062         break;
0063     default:
0064         Q_ASSERT(false);
0065         break;
0066     }
0067 }
0068 
0069 void PageVariable::propertyChanged(Property property, const QVariant &value)
0070 {
0071     switch (m_type) {
0072     case PageCount:
0073         if (property == KoInlineObject::PageCount) {
0074             KoOdfNumberDefinition defaultDefinition; // FIXME Should fetch from pagestyle
0075             QString newValue = value.toInt() >= 0 ? m_numberFormat.formattedNumber(value.toInt(), &defaultDefinition) : QString();
0076             setValue(newValue);
0077         }
0078         break;
0079     case PageNumber:
0080         break;
0081     case PageContinuation:
0082         break;
0083     }
0084 }
0085 
0086 void PageVariable::resize(const QTextDocument *document, QTextInlineObject &object, int posInDocument, const QTextCharFormat &format, QPaintDevice *pd)
0087 {
0088     KoTextPage *page = 0;
0089     if (m_type != PageCount) {
0090 #if 0 // the code is left here to do some testing
0091         KoTextDocumentLayout *lay = qobject_cast<KoTextDocumentLayout*>(document->documentLayout());
0092         KoTextLayoutRootArea *rootArea = 0;
0093         KoTextPage *page2 = 0;
0094         if (lay) {
0095             rootArea = lay->rootAreaForPosition(posInDocument);
0096             if (rootArea) {
0097                 page2 = rootArea->page();
0098             }
0099         }
0100 #endif
0101         page = document->resource(KoTextDocument::LayoutTextPage, KoTextDocument::LayoutTextPageUrl).value<KoTextPage*>();
0102     }
0103     int pagenumber = 0;
0104 
0105     switch (m_type) {
0106     case PageCount:
0107         break;
0108     case PageNumber:
0109         if (page) {
0110             // the text is not yet layouted therefore we don't get the rootArea
0111             // if we don't do that we get an endless change of the variable.
0112             QString currentValue = value();
0113             if (currentValue.isEmpty() || ! m_fixed) {
0114                 pagenumber = page->visiblePageNumber(m_pageselect, m_pageadjust);
0115                 KoOdfNumberDefinition defaultDefinition; // FIXME Should fetch from pagestyle
0116                 QString newValue = pagenumber >= 0 ? m_numberFormat.formattedNumber(pagenumber, &defaultDefinition) : QString();
0117                 // only update value when changed
0118                 if (currentValue != newValue) {
0119                      setValue(newValue);
0120                 }
0121             }
0122         }
0123         break;
0124     case PageContinuation:
0125         if (page) {
0126             // the text is not yet layouted therefore we don't get the rootArea
0127             // if we don't do that we get an endless change of the variable.
0128             pagenumber = page->visiblePageNumber(m_pageselect);
0129             setValue(pagenumber >= 0 ? m_continuation : QString());
0130         }
0131         break;
0132     }
0133     KoVariable::resize(document, object, posInDocument, format, pd);
0134 }
0135 
0136 void PageVariable::saveOdf(KoShapeSavingContext & context)
0137 {
0138     KoXmlWriter *writer = &context.xmlWriter();
0139     switch (m_type) {
0140     case PageCount:
0141         // <text:page-count>3</text:page-count>
0142         writer->startElement("text:page-count", false);
0143         writer->addTextNode(value());
0144         writer->endElement();
0145         break;
0146     case PageNumber:
0147         // <text:page-number text:select-page="current" text:page-adjust="2" text:fixed="true">3</text:page-number>
0148         writer->startElement("text:page-number", false);
0149 
0150         if (m_pageselect == KoTextPage::CurrentPage)
0151             writer->addAttribute("text:select-page", "current");
0152         else if (m_pageselect == KoTextPage::PreviousPage)
0153             writer->addAttribute("text:select-page", "previous");
0154         else if (m_pageselect == KoTextPage::NextPage)
0155             writer->addAttribute("text:select-page", "next");
0156 
0157         if (m_pageadjust != 0)
0158             writer->addAttribute("text:page-adjust", QString::number(m_pageadjust));
0159 
0160         m_numberFormat.saveOdf(writer);
0161 
0162         if (m_fixed)
0163             writer->addAttribute("text:fixed", "true");
0164 
0165         writer->addTextNode(value());
0166         writer->endElement();
0167         break;
0168     case PageContinuation:
0169         // <text:page-continuation-string text:select-page="previous">The Text</text:page-continuation-string>
0170         writer->startElement("page-continuation-string", false);
0171 
0172         if (m_pageselect == KoTextPage::PreviousPage)
0173             writer->addAttribute("text:select-page", "previous");
0174         else if (m_pageselect == KoTextPage::NextPage)
0175             writer->addAttribute("text:select-page", "next");
0176 
0177         writer->addTextNode(m_continuation);
0178         writer->endElement();
0179         break;
0180     }
0181 }
0182 
0183 bool PageVariable::loadOdf(const KoXmlElement & element, KoShapeLoadingContext & context)
0184 {
0185     Q_UNUSED(context);
0186     const QString localName(element.localName());
0187     if (localName == "page-count") {
0188         m_type = PageCount;
0189 
0190         m_numberFormat.loadOdf(element);
0191     } else if (localName == "page-number") {
0192         m_type = PageNumber;
0193 
0194         // The text:select-page attribute is used to display the number of the previous or the following
0195         // page rather than the number of the current page.
0196         QString pageselect = element.attributeNS(KoXmlNS::text, "select-page", QString());
0197         if (pageselect == "previous")
0198             m_pageselect = KoTextPage::PreviousPage;
0199         else if (pageselect == "next")
0200             m_pageselect = KoTextPage::NextPage;
0201         else // "current"
0202             m_pageselect = KoTextPage::CurrentPage;
0203 
0204         // The value of a page number field can be adjusted by a specified number, allowing the display
0205         // of page numbers of following or preceding pages. The adjustment amount is specified using
0206         // the text:page-adjust attribute.
0207         m_pageadjust = element.attributeNS(KoXmlNS::text, "page-adjust", QString()).toInt();
0208 
0209         m_numberFormat.loadOdf(element);
0210 
0211         // The text:fixed attribute specifies whether or not the value of a field element is fixed. If
0212         // the value of a field is fixed, the value of the field element to which this attribute is
0213         // attached is preserved in all future edits of the document. If the value of the field is not
0214         // fixed, the value of the field may be replaced by a new value when the document is edited.
0215         m_fixed = element.attributeNS(KoXmlNS::text, "fixed", QString()) == "true";
0216     } else if (localName == "page-continuation-string") {
0217         m_type = PageContinuation;
0218 
0219         // This attribute specifies whether to check for a previous or next page and if the page exists, the
0220         // continuation text is printed.
0221         QString pageselect = element.attributeNS(KoXmlNS::text, "select-page", QString());
0222         if (pageselect == "previous")
0223             m_pageselect = KoTextPage::PreviousPage;
0224         else if (pageselect == "next")
0225             m_pageselect = KoTextPage::NextPage;
0226         else
0227             m_pageselect = KoTextPage::CurrentPage;
0228 
0229         // The text to display
0230         m_continuation = element.text();
0231     }
0232     return true;
0233 }