1 /* This file is part of the KDE project
2
3 Copyright (C) 2010 Boudewijn Rempt
4 Copyright (C) 2011 Mojtaba Shahi Senobari <mojtaba.shahi3000@gmail.com>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License version 2 as published by the Free Software Foundation.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19 */
20 #include "KoOdfNumberDefinition.h"
21
22 #include "KoXmlNS.h"
23 #include "KoXmlWriter.h"
24 #include "KoXmlReader.h"
25
26 class Q_DECL_HIDDEN KoOdfNumberDefinition::Private
27 {
28 public:
29 QString prefix;
30 QString suffix;
31 KoOdfNumberDefinition::FormatSpecification formatSpecification;
32 bool letterSynchronization;
33 };
34
KoOdfNumberDefinition()35 KoOdfNumberDefinition::KoOdfNumberDefinition()
36 : d(new Private())
37 {
38 d->formatSpecification = Numeric;
39 d->letterSynchronization = false;
40 }
41
KoOdfNumberDefinition(const KoOdfNumberDefinition & other)42 KoOdfNumberDefinition::KoOdfNumberDefinition(const KoOdfNumberDefinition &other)
43 : d(new Private())
44 {
45 d->prefix = other.d->prefix;
46 d->suffix = other.d->suffix;
47 d->formatSpecification = other.d->formatSpecification;
48 d->letterSynchronization = other.d->letterSynchronization;
49 }
50
operator =(const KoOdfNumberDefinition & other)51 KoOdfNumberDefinition &KoOdfNumberDefinition::operator=(const KoOdfNumberDefinition &other)
52 {
53 d->prefix = other.d->prefix;
54 d->suffix = other.d->suffix;
55 d->formatSpecification = other.d->formatSpecification;
56 d->letterSynchronization = other.d->letterSynchronization;
57
58 return *this;
59 }
60
~KoOdfNumberDefinition()61 KoOdfNumberDefinition::~KoOdfNumberDefinition()
62 {
63 delete d;
64 }
65
loadOdf(const KoXmlElement & element)66 void KoOdfNumberDefinition::loadOdf(const KoXmlElement &element)
67 {
68 const QString format = element.attributeNS(KoXmlNS::style, "num-format", QString());
69 if (format.isEmpty()) {
70 //do nothing fall back to what we had.
71 }
72 else if (format[0] == '1') {
73 d->formatSpecification = Numeric;
74 }
75 else if (format[0] == 'a') {
76 d->formatSpecification = AlphabeticLowerCase;
77 }
78 else if (format[0] == 'A') {
79 d->formatSpecification = AlphabeticUpperCase;
80 }
81 else if (format[0] == 'i') {
82 d->formatSpecification = RomanLowerCase;
83 }
84 else if (format[0] == 'I') {
85 d->formatSpecification = RomanUpperCase;
86 }
87 else if (format == QString::fromUtf8("أ, ب, ت, ...")){
88 d->formatSpecification = ArabicAlphabet;
89 }
90 else if (format == QString::fromUtf8("ก, ข, ค, ...")){
91 d->formatSpecification = Thai;
92 }
93 else if (format == QString::fromUtf8("أ, ب, ج, ...")) {
94 d->formatSpecification = Abjad;
95 }
96 else if (format == QString::fromUtf8("ﺃ,ﺏ, ﺝ, ... ")) {
97 d->formatSpecification = AbjadMinor;
98 }
99 else if (format == QString::fromUtf8("౧, ౨, ౩, ...")) {
100 d->formatSpecification = Telugu;
101 }
102 else if (format == QString::fromUtf8("௧, ௨, ௪, ...")) {
103 d->formatSpecification = Tamil;
104 }
105 else if (format == QString::fromUtf8("୧, ୨, ୩, ...")) {
106 d->formatSpecification = Oriya;
107 }
108 else if (format == QString::fromUtf8("൧, ൨, ൩, ...")) {
109 d->formatSpecification = Malayalam;
110 }
111 else if (format == QString::fromUtf8("೧, ೨, ೩, ...")) {
112 d->formatSpecification = Kannada;
113 }
114 else if (format == QString::fromUtf8("੧, ੨, ੩, ...")) {
115 d->formatSpecification = Gurumukhi;
116 }
117 else if (format == QString::fromUtf8("૧, ૨, ૩, ...")) {
118 d->formatSpecification = Gujarati;
119 }
120 else if (format == QString::fromUtf8("১, ২, ৩, ...")) {
121 d->formatSpecification = Bengali;
122 }
123 else {
124 d->formatSpecification = Numeric;
125 }
126
127 //The style:num-prefix and style:num-suffix attributes specify what to display before and after the number.
128 d->prefix = element.attributeNS(KoXmlNS::style, "num-prefix", d->prefix);
129 d->suffix = element.attributeNS(KoXmlNS::style, "num-suffix", d->suffix);
130
131 d->letterSynchronization = (element.attributeNS(KoXmlNS::style, "num-letter-sync", d->letterSynchronization ? "true" : "false") == "true");
132 }
133
saveOdf(KoXmlWriter * writer) const134 void KoOdfNumberDefinition::saveOdf(KoXmlWriter *writer) const
135 {
136 if (!d->prefix.isNull()) {
137 writer->addAttribute("style:num-prefix", d->prefix);
138 }
139
140 if (!d->suffix.isNull()) {
141 writer->addAttribute("style:num-suffix", d->suffix);
142 }
143 QByteArray format;
144 switch(d->formatSpecification) {
145 case Numeric:
146 format = "1";
147 break;
148 case AlphabeticLowerCase:
149 format = "a";
150 break;
151 case AlphabeticUpperCase:
152 format = "A";
153 break;
154 case RomanLowerCase:
155 format = "i";
156 break;
157 case RomanUpperCase:
158 format = "I";
159 break;
160 case ArabicAlphabet:
161 format = "أ, ب, ت, ...";
162 break;
163 case Thai:
164 format = "ก, ข, ค, ...";
165 break;
166 case Telugu:
167 format = "౧, ౨, ౩, ...";
168 break;
169 case Tamil:
170 format = "௧, ௨, ௪, ...";
171 break;
172 case Oriya:
173 format = "୧, ୨, ୩, ...";
174 break;
175 case Malayalam:
176 format = "൧, ൨, ൩, ...";
177 break;
178 case Kannada:
179 format = "೧, ೨, ೩, ...";
180 break;
181 case Gurumukhi:
182 format = "੧, ੨, ੩, ...";
183 break;
184 case Gujarati:
185 format = "૧, ૨, ૩, ...";
186 break;
187 case Bengali:
188 format = "১, ২, ৩, ...";
189 break;
190 case Empty:
191 default:
192 ;
193 };
194 if (!format.isNull()) {
195 writer->addAttribute("style:num-format", format);
196 }
197
198 if (d->letterSynchronization) {
199 writer->addAttribute("style:num-letter-sync", "true");
200 }
201 }
202
formattedNumber(int number,KoOdfNumberDefinition * defaultDefinition) const203 QString KoOdfNumberDefinition::formattedNumber(int number, KoOdfNumberDefinition *defaultDefinition) const
204 {
205 switch(d->formatSpecification) {
206 case Numeric:
207 return QString::number(number);
208 break;
209
210 case AlphabeticLowerCase:
211 {
212 if (d->letterSynchronization) {
213 int loop = (number-1)/26;
214 int rem = (number-1)%26;
215 QChar letter = (char)(rem+97);
216 QString alpha;
217 for (int i=0; i<=loop; i++) {
218 alpha.append(letter);
219 }
220 return alpha;
221 } else {
222 int loop = (number-1)/26;
223 QChar letter;
224 QString alpha;
225 if (loop>0) {
226 letter = (char)(loop+96);
227 alpha.append(letter);
228 }
229 int rem = (number -1)%26;
230 letter = (char)(rem+97);
231 alpha.append(letter);
232 return alpha;
233 }
234 break;
235 }
236 case AlphabeticUpperCase:
237 {
238 if (d->letterSynchronization) {
239 int loop = (number-1)/26;
240 int rem = (number-1)%26;
241 QChar letter = (char)(rem+65);
242 QString alpha;
243 for (int i=0; i<=loop; i++) {
244 alpha.append(letter);
245 }
246 return alpha;
247 } else {
248 int loop = (number-1)/26;
249 QChar letter;
250 QString alpha;
251 if (loop>0) {
252 letter = (char)(loop+64);
253 alpha.append(letter);
254 }
255 int rem = (number -1)%26;
256 letter = (char)(rem+65);
257 alpha.append(letter);
258 return alpha;
259 }
260 break;
261 }
262 case RomanLowerCase:
263 {
264 QString roman;
265 int loop = number/1000;
266 for (int i=1; i<=loop && number/1000!=0; i++) {
267 roman.append("m");
268 }
269 number = number%1000;
270 loop = number/500;
271 if (loop > 0) {
272 roman.append("d");
273 }
274 number = number%500;
275 loop = number/100;
276 for (int i=1; i<=loop && number/100!=0; i++) {
277 roman.append("c");
278 }
279 number = number%100;
280 loop = number/50;
281 if (loop > 0) {
282 roman.append("l");
283 }
284 number = number%50;
285 loop = number/10;
286 for (int i=1; i<=loop && number/10!=0; i++) {
287 roman.append("x");
288 }
289 number = number%10;
290 if (number>=5 && number<=8) {
291 loop = number%5;
292 roman.append("v");
293 for (int i=1;i<=loop;i++)
294 roman.append("i");
295 }
296 else if (number==9) {
297 roman.append("ix");
298 }
299 else if (number>=1 && number<=3) {
300 for (int i=1; i<=number; i++)
301 roman.append("i");
302 }
303 else if (number==4)
304 roman.append("iv");
305
306 return roman;
307 break;
308 }
309 case RomanUpperCase:
310 {
311 QString roman;
312 int loop = number/1000;
313 for (int i=1; i<=loop && number/1000!=0; i++) {
314 roman.append("M");
315 }
316 number = number%1000;
317 loop = number/500;
318 if (loop > 0) {
319 roman.append("D");
320 }
321 number = number%500;
322 loop = number/100;
323 for (int i=1; i<=loop && number/100!=0; i++) {
324 roman.append("C");
325 }
326 number = number%100;
327 loop = number/50;
328 if (loop > 0) {
329 roman.append("L");
330 }
331 number = number%50;
332 loop = number/10;
333 for (int i=1; i<=loop && number/10!=0; i++) {
334 roman.append("X");
335 }
336 number = number%10;
337 if (number>=5 && number<=8) {
338 loop = number%5;
339 roman.append("V");
340 for (int i=1; i<=loop; i++)
341 roman.append("I");
342 }
343 else if (number==9) {
344 roman.append("IX");
345 }
346 else if (number>=1 && number<=3) {
347 for (int i=1; i<=number; i++)
348 roman.append("I");
349 }
350 else if (number==4)
351 roman.append("IV");
352
353 return roman;
354 }
355 case Empty:
356 if (defaultDefinition) {
357 return defaultDefinition->formattedNumber(number);
358 }
359
360 break;
361 default:
362 ;
363 };
364
365 return "";
366 }
367
368
prefix() const369 QString KoOdfNumberDefinition::prefix() const
370 {
371 return d->prefix;
372 }
373
setPrefix(const QString & prefix)374 void KoOdfNumberDefinition::setPrefix(const QString &prefix)
375 {
376 d->prefix = prefix;
377 }
378
suffix() const379 QString KoOdfNumberDefinition::suffix() const
380 {
381 return d->suffix;
382 }
383
setSuffix(const QString & suffix)384 void KoOdfNumberDefinition::setSuffix(const QString &suffix)
385 {
386 d->suffix = suffix;
387 }
388
formatSpecification() const389 KoOdfNumberDefinition::FormatSpecification KoOdfNumberDefinition::formatSpecification() const
390 {
391 return d->formatSpecification;
392 }
393
setFormatSpecification(FormatSpecification formatSpecification)394 void KoOdfNumberDefinition::setFormatSpecification(FormatSpecification formatSpecification)
395 {
396 d->formatSpecification = formatSpecification;
397 }
398
letterSynchronization() const399 bool KoOdfNumberDefinition::letterSynchronization() const
400 {
401 return d->letterSynchronization;
402 }
403
setLetterSynchronization(bool letterSynchronization)404 void KoOdfNumberDefinition::setLetterSynchronization(bool letterSynchronization)
405 {
406 d->letterSynchronization = letterSynchronization;
407 }
408