Warning, file /office/calligra/libs/odf/KoOdfNumberDefinition.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 
0003    Copyright (C) 2010 Boudewijn Rempt
0004    Copyright (C) 2011 Mojtaba Shahi Senobari <mojtaba.shahi3000@gmail.com>
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 version 2 as published by the Free Software Foundation.
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 "KoOdfNumberDefinition.h"
0021 
0022 #include "KoXmlNS.h"
0023 #include "KoXmlWriter.h"
0024 
0025 class Q_DECL_HIDDEN KoOdfNumberDefinition::Private
0026 {
0027 public:
0028     QString prefix;
0029     QString suffix;
0030     KoOdfNumberDefinition::FormatSpecification formatSpecification;
0031     bool letterSynchronization;
0032 };
0033 
0034 KoOdfNumberDefinition::KoOdfNumberDefinition()
0035     : d(new Private())
0036 {
0037     d->formatSpecification = Numeric;
0038     d->letterSynchronization = false;
0039 }
0040 
0041 KoOdfNumberDefinition::KoOdfNumberDefinition(const KoOdfNumberDefinition &other)
0042     : d(new Private())
0043 {
0044     d->prefix = other.d->prefix;
0045     d->suffix = other.d->suffix;
0046     d->formatSpecification = other.d->formatSpecification;
0047     d->letterSynchronization = other.d->letterSynchronization;
0048 }
0049 
0050 KoOdfNumberDefinition &KoOdfNumberDefinition::operator=(const KoOdfNumberDefinition &other)
0051 {
0052     d->prefix = other.d->prefix;
0053     d->suffix = other.d->suffix;
0054     d->formatSpecification = other.d->formatSpecification;
0055     d->letterSynchronization = other.d->letterSynchronization;
0056 
0057     return *this;
0058 }
0059 
0060 KoOdfNumberDefinition::~KoOdfNumberDefinition()
0061 {
0062     delete d;
0063 }
0064 
0065 QStringList KoOdfNumberDefinition::userFormatDescriptions()
0066 {
0067     QStringList list;
0068     list << "1, 2, 3, ..."
0069     << "a, b, c, ..."
0070     << "A, B, C, ..."
0071     << "i, ii, iii, ..."
0072     << "I, II, III, ..." << "أ, ب, ت, ..."
0073     << "ก, ข, ค, ..."
0074     << "౧, ౨, ౩, ..."
0075     << "௧, ௨, ௪, ..."
0076     << "୧, ୨, ୩, ..."
0077     << "൧, ൨, ൩, ..."
0078     << "೧, ೨, ೩, ..."
0079     << "੧, ੨, ੩, ..."
0080     << "૧, ૨, ૩, ..."
0081     << "১, ২, ৩, ...";
0082 
0083     return list;
0084 }
0085 
0086 void KoOdfNumberDefinition::loadOdf(const KoXmlElement &element)
0087 {
0088     const QString format = element.attributeNS(KoXmlNS::style, "num-format", QString());
0089     if (format.isEmpty()) {
0090         //do nothing fall back to what we had.
0091     }
0092     else if (format[0] == '1') {
0093         d->formatSpecification = Numeric;
0094     }
0095     else if (format[0] == 'a') {
0096         d->formatSpecification = AlphabeticLowerCase;
0097     }
0098     else if (format[0] == 'A') {
0099         d->formatSpecification = AlphabeticUpperCase;
0100     }
0101     else if (format[0] == 'i') {
0102         d->formatSpecification = RomanLowerCase;
0103     }
0104     else if (format[0] == 'I') {
0105         d->formatSpecification = RomanUpperCase;
0106     }
0107     else if (format == QString::fromUtf8("أ, ب, ت, ...")){
0108         d->formatSpecification = ArabicAlphabet;
0109     }
0110     else if (format == QString::fromUtf8("ก, ข, ค, ...")){
0111         d->formatSpecification = Thai;
0112     }
0113     else if (format == QString::fromUtf8("أ, ب, ج, ...")) {
0114         d->formatSpecification = Abjad;
0115     }
0116     else if (format == QString::fromUtf8("ﺃ,ﺏ, ﺝ, ... ")) {
0117         d->formatSpecification = AbjadMinor;
0118     }
0119     else if (format == QString::fromUtf8("౧, ౨, ౩, ...")) {
0120         d->formatSpecification = Telugu;
0121     }
0122     else if (format == QString::fromUtf8("௧, ௨, ௪, ...")) {
0123         d->formatSpecification = Tamil;
0124     }
0125     else if (format == QString::fromUtf8("୧, ୨, ୩, ...")) {
0126         d->formatSpecification = Oriya;
0127     }
0128     else if (format == QString::fromUtf8("൧, ൨, ൩, ...")) {
0129         d->formatSpecification = Malayalam;
0130     }
0131     else if (format == QString::fromUtf8("೧, ೨, ೩, ...")) {
0132         d->formatSpecification = Kannada;
0133     }
0134     else if (format == QString::fromUtf8("੧, ੨, ੩, ...")) {
0135         d->formatSpecification = Gurumukhi;
0136     }
0137     else if (format == QString::fromUtf8("૧, ૨, ૩, ...")) {
0138         d->formatSpecification = Gujarati;
0139     }
0140     else if (format == QString::fromUtf8("১, ২, ৩, ...")) {
0141         d->formatSpecification = Bengali;
0142     }
0143     else {
0144         d->formatSpecification = Numeric;
0145     }
0146 
0147     //The style:num-prefix and style:num-suffix attributes specify what to display before and after the number.
0148     d->prefix = element.attributeNS(KoXmlNS::style, "num-prefix", d->prefix);
0149     d->suffix = element.attributeNS(KoXmlNS::style, "num-suffix", d->suffix);
0150 
0151     d->letterSynchronization = (element.attributeNS(KoXmlNS::style, "num-letter-sync", d->letterSynchronization ? "true" : "false") == "true");
0152 }
0153 
0154 void KoOdfNumberDefinition::saveOdf(KoXmlWriter *writer) const
0155 {
0156     if (!d->prefix.isNull()) {
0157         writer->addAttribute("style:num-prefix", d->prefix);
0158     }
0159 
0160     if (!d->suffix.isNull()) {
0161         writer->addAttribute("style:num-suffix", d->suffix);
0162     }
0163     QByteArray format;
0164     switch(d->formatSpecification) {
0165     case Numeric:
0166         format = "1";
0167         break;
0168     case AlphabeticLowerCase:
0169         format = "a";
0170         break;
0171     case AlphabeticUpperCase:
0172         format = "A";
0173         break;
0174     case RomanLowerCase:
0175         format = "i";
0176         break;
0177     case RomanUpperCase:
0178         format = "I";
0179         break;
0180     case ArabicAlphabet:
0181         format = "أ, ب, ت, ...";
0182         break;
0183     case Thai:
0184         format = "ก, ข, ค, ...";
0185         break;
0186     case Telugu:
0187         format = "౧, ౨, ౩, ...";
0188         break;
0189     case Tamil:
0190         format = "௧, ௨, ௪, ...";
0191         break;
0192     case Oriya:
0193         format = "୧, ୨, ୩, ...";
0194         break;
0195     case Malayalam:
0196         format = "൧, ൨, ൩, ...";
0197         break;
0198     case Kannada:
0199         format = "೧, ೨, ೩, ...";
0200         break;
0201     case Gurumukhi:
0202         format = "੧, ੨, ੩, ...";
0203         break;
0204     case Gujarati:
0205         format = "૧, ૨, ૩, ...";
0206         break;
0207     case Bengali:
0208         format = "১, ২, ৩, ...";
0209         break;
0210     case Empty:
0211     default:
0212         ;
0213     };
0214     if (!format.isNull()) {
0215         writer->addAttribute("style:num-format", format);
0216     }
0217 
0218     if (d->letterSynchronization) {
0219         writer->addAttribute("style:num-letter-sync", "true");
0220     }
0221 }
0222 
0223 static QString intToRoman(int n)
0224 {
0225     static const QString RNUnits[] = {"", "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix"};
0226     static const QString RNTens[] = {"", "x", "xx", "xxx", "xl", "l", "lx", "lxx", "lxxx", "xc"};
0227     static const QString RNHundreds[] = {"", "c", "cc", "ccc", "cd", "d", "dc", "dcc", "dccc", "cm"};
0228     static const QString RNThousands[] = {"", "m", "mm", "mmm", "mmmm", "mmmmm", "mmmmmm", "mmmmmmm", "mmmmmmmm", "mmmmmmmmm"};
0229 
0230     if (n <= 0) {
0231         return QString::number(n);
0232     }
0233 
0234     return RNThousands[(n / 1000)] +
0235            RNHundreds[(n / 100) % 10 ] +
0236            RNTens[(n / 10) % 10 ] +
0237            RNUnits[(n) % 10 ];
0238 }
0239 
0240 static QString intToAlpha(int n, bool letterSynchronization)
0241 {
0242     QString answer;
0243     if (letterSynchronization) {
0244         int digits = 1;
0245         for (; n > 26; n -= 26)
0246             digits += 1;
0247         for (int i = 0; i < digits; i++)
0248             answer.prepend(QChar('a' + n - 1));
0249         return answer;
0250     } else {
0251         char bottomDigit;
0252         while (n > 26) {
0253             bottomDigit = (n - 1) % 26;
0254             n = (n - 1) / 26;
0255             answer.prepend(QChar('a' + bottomDigit));
0256         }
0257     }
0258     answer.prepend(QChar('a' + n - 1));
0259     return answer;
0260 }
0261 
0262 static QString intToScript(int n, int offset)
0263 {
0264     // 10-base
0265     QString answer;
0266     while (n > 0) {
0267         answer.prepend(QChar(offset + n % 10));
0268         n = n / 10;
0269     }
0270     return answer;
0271 }
0272 
0273 static QString intToScriptList(int n, KoOdfNumberDefinition::FormatSpecification formatSpecification)
0274 {
0275     // 1 time Sequences
0276     // note; the leading X is to make these 1 based.
0277     static const char* const Abjad[] = { "أ", "ب", "ج", "د", "ﻫ", "و", "ز", "ح", "ط", "ي", "ك", "ل", "م",
0278                                    "ن", "س", "ع", "ف", "ص", "ق", "ر", "ش", "ت", "ث", "خ", "ذ", "ض", "ظ", "غ"
0279                                  };
0280     static const char* const Abjad2[] = { "ﺃ", "ﺏ", "ﺝ", "ﺩ", "ﻫ", "ﻭ", "ﺯ", "ﺡ", "ﻁ", "ﻱ", "ﻙ", "ﻝ", "ﻡ",
0281                                     "ﻥ", "ﺹ", "ﻉ", "ﻑ", "ﺽ", "ﻕ", "ﺭ", "ﺱ", "ﺕ", "ﺙ", "ﺥ", "ﺫ", "ﻅ", "ﻍ", "ﺵ"
0282                                   };
0283     static const char* const ArabicAlphabet[] = {"ا", "ب", "ت", "ث", "ج", "ح", "خ", "د", "ذ", "ر", "ز",
0284                                            "س", "ش", "ص", "ض", "ط", "ظ", "ع", "غ", "ف", "ق", "ك", "ل", "م", "ن", "ه", "و", "ي"
0285                                           };
0286 
0287     /*
0288     // see this page for the 10, 100, 1000 etc http://en.wikipedia.org/wiki/Chinese_numerals
0289     static const char* const chinese1[] = { '零','壹','貳','叄','肆','伍','陸','柒','捌','玖' };
0290     static const char* const chinese2[] = { '〇','一','二','三','四','五','六','七','八','九' };
0291 
0292     TODO: http://en.wikipedia.org/wiki/Korean_numerals
0293     http://en.wikipedia.org/wiki/Japanese_numerals
0294     'http://en.wikipedia.org/wiki/Hebrew_numerals'
0295     'http://en.wikipedia.org/wiki/Armenian_numerals'
0296     'http://en.wikipedia.org/wiki/Greek_numerals'
0297     'http://en.wikipedia.org/wiki/Cyrillic_numerals'
0298     'http://en.wikipedia.org/wiki/Sanskrit_numerals'
0299     'http://en.wikipedia.org/wiki/Ge%27ez_alphabet#Numerals'
0300     'http://en.wikipedia.org/wiki/Abjad_numerals'
0301     */
0302 
0303     switch (formatSpecification) {
0304     case KoOdfNumberDefinition::Abjad:
0305         if (n > 22) return "*";
0306         return QString::fromUtf8(Abjad[n-1]);
0307     case KoOdfNumberDefinition::AbjadMinor:
0308         if (n > 22) return "*";
0309         return QString::fromUtf8(Abjad2[n-1]);
0310     case KoOdfNumberDefinition::ArabicAlphabet:
0311         if (n > 28) return "*";
0312         return QString::fromUtf8(ArabicAlphabet[n-1]);
0313     default:
0314         return QString::number(n);
0315     }
0316 }
0317 
0318 QString KoOdfNumberDefinition::formattedNumber(int number, KoOdfNumberDefinition *defaultDefinition) const
0319 {
0320    switch(d->formatSpecification) {
0321     case Numeric:
0322         return QString::number(number);
0323         break;
0324 
0325     case AlphabeticLowerCase:
0326         return intToAlpha(number, d->letterSynchronization);
0327     case AlphabeticUpperCase:
0328         return intToAlpha(number, d->letterSynchronization).toUpper();
0329 
0330     case RomanLowerCase:
0331         return intToRoman(number);
0332     case RomanUpperCase:
0333         return intToRoman(number).toUpper();
0334 
0335     case Thai:
0336         return intToScript(number, 0xe50);
0337     case Tibetan:
0338         return intToScript(number, 0xf20);
0339     case Telugu:
0340         return intToScript(number, 0xc66);
0341     case Tamil:
0342         return intToScript(number, 0x0be6);
0343     case Oriya:
0344         return intToScript(number, 0xb66);
0345     case Malayalam:
0346         return intToScript(number, 0xd66);
0347     case Kannada:
0348         return intToScript(number, 0xce6);
0349     case Gurumukhi:
0350         return intToScript(number, 0xa66);
0351     case Gujarati:
0352         return intToScript(number, 0xae6);
0353     case Bengali:
0354         return intToScript(number, 0x9e6);
0355 
0356     case Abjad:
0357     case AbjadMinor:
0358     case ArabicAlphabet:
0359         return intToScriptList(number, d->formatSpecification);
0360 
0361     case Empty:
0362         if (defaultDefinition) {
0363             return defaultDefinition->formattedNumber(number);
0364         }
0365 
0366         break;
0367     default:
0368         ;
0369     };
0370 
0371     return "";
0372 }
0373 
0374 
0375 QString KoOdfNumberDefinition::prefix() const
0376 {
0377     return d->prefix;
0378 }
0379 
0380 void KoOdfNumberDefinition::setPrefix(const QString &prefix)
0381 {
0382     d->prefix = prefix;
0383 }
0384 
0385 QString KoOdfNumberDefinition::suffix() const
0386 {
0387     return d->suffix;
0388 }
0389 
0390 void KoOdfNumberDefinition::setSuffix(const QString &suffix)
0391 {
0392     d->suffix = suffix;
0393 }
0394 
0395 KoOdfNumberDefinition::FormatSpecification KoOdfNumberDefinition::formatSpecification() const
0396 {
0397     return d->formatSpecification;
0398 }
0399 
0400 void KoOdfNumberDefinition::setFormatSpecification(FormatSpecification formatSpecification)
0401 {
0402     d->formatSpecification = formatSpecification;
0403 }
0404 
0405 bool KoOdfNumberDefinition::letterSynchronization() const
0406 {
0407     return d->letterSynchronization;
0408 }
0409 
0410 void KoOdfNumberDefinition::setLetterSynchronization(bool letterSynchronization)
0411 {
0412     d->letterSynchronization = letterSynchronization;
0413 }