From: Konrad Rosenbaum Date: Sat, 24 Mar 2012 19:28:57 +0000 (+0100) Subject: better money formatting for client X-Git-Url: http://git.silmor.de/gitweb/?a=commitdiff_plain;h=3729eb0594295ef4384dd1d3d40be754608eafb6;p=web%2Fkonrad%2Fsmoke.git better money formatting for client --- diff --git a/src/misc/misc.cpp b/src/misc/misc.cpp index bbe8039..df3aba2 100644 --- a/src/misc/misc.cpp +++ b/src/misc/misc.cpp @@ -64,7 +64,7 @@ QByteArray xmlize(QByteArray str,QString newline) if(c=='>')out+=">";else if(c=='&')out+="&";else if(c=='\n')out+=newline;else - if(QChar(c).isSpace()||(c>=32&&c<=0x7f))out+=c; + if(QChar(c).isSpace()||(c>=32 && static_cast(c)<=0x7f))out+=c; else out+="&#"+QString::number((unsigned char)c)+";"; } return out; @@ -112,14 +112,31 @@ QString unix2dateTime(qint64 tm,bool localize) return mf.formatDateTime(tm); } +// ///////////////////////////////////// +// local formatting class +#include +class MLocalFormat::Private:public SharedDPtr +{ + public: + QStringList m_day,m_sday,m_month,m_smonth; + QString m_am,m_pm,m_timezone,m_dateformat,m_timeformat,m_datetimeformat; + QChar m_decimal,m_thousand; + + QString m_currency,m_moneyneg,m_moneypos; + int m_moneydecimals,m_thousanddigits; + bool m_moneysymbehind; + MOServerFormat::MoneyPos m_moneynegpos,m_moneypospos; +}; +DEFINE_SHARED_DPTR(MLocalFormat); + //static MLocalFormat MLocalFormat::defaultformat((int)1); MLocalFormat::MLocalFormat(int) { - m_moneydecimals=2; - m_thousanddigits=3; - m_timezone="UTC"; + d->m_moneydecimals=2; + d->m_thousanddigits=3; + d->m_timezone="UTC"; //set defaults setWeekDays();setShortWeekDays(); setMonths();setShortMonths(); @@ -137,19 +154,42 @@ MLocalFormat::MLocalFormat(const MOServerFormat& s) sl=s.shortweekdays();if(sl.size())setShortWeekDays(sl); sl=s.months();if(sl.size())setMonths(sl); sl=s.shortmonths();if(sl.size())setShortMonths(sl); - setMoneyFormat(s.currencysymbol(),s.moneydecimals(),s.moneynegative()); - setNumberFormat(s.decimaldot().value().at(0),s.thousandseparator().value().at(0),s.thousanddigits().value()); + setMoneyFormat(s.currencysymbol(),s.moneydecimals(),s.currencysymbolpos()); + setMoneySign(s.moneynegative(),s.moneypositive(),s.moneynegativepos(),s.moneypositivepos()); + setNumberFormat(s.decimaldot().value().at(0), s.thousandseparator().value().at(0), s.thousanddigits().value()); setAP(s.amtext(),s.pmtext()); setTimeZone(s.timezone()); setDateTimeFormat(s.dateformat(),s.timeformat(),s.datetimeformat()); } +QStringList MLocalFormat::weekDayNames()const{return d->m_day;} +QStringList MLocalFormat::shortWeekDayNames()const{return d->m_sday;} +QStringList MLocalFormat:: monthNames()const{return d->m_month;} +QStringList MLocalFormat::shortMonthNames()const{return d->m_smonth;} +QString MLocalFormat::currency()const{return d->m_currency;} +QChar MLocalFormat::decimalDot()const{return d->m_decimal;} +QString MLocalFormat::thousandSeparator()const +{ + if(d->m_thousanddigits>0) + return d->m_thousand; + else return ""; +} +int MLocalFormat::thousandDigits()const{return d->m_thousanddigits;} +int MLocalFormat::moneyDecimals()const{return d->m_moneydecimals;} +QString MLocalFormat::amText()const{return d->m_am;} +QString MLocalFormat::pmText()const{return d->m_pm;} +QString MLocalFormat::moneyNegativeSign()const{return d->m_moneyneg;} +QString MLocalFormat::moneyPositiveSign()const{return d->m_moneypos;} +QString MLocalFormat::dateFormat()const{return d->m_dateformat;} +QString MLocalFormat::timeFormat()const{return d->m_timeformat;} +QString MLocalFormat::dateTimeFormat()const{return d->m_datetimeformat;} +QString MLocalFormat::timeZone()const{return d->m_timezone;} //static void MLocalFormat::setDefaultFormat(const MLocalFormat& f) { defaultformat=f; - TimeStamp::setDefaultZone(f.m_timezone); + TimeStamp::setDefaultZone(f.d->m_timezone); } @@ -159,38 +199,11 @@ MLocalFormat::MLocalFormat() } -MLocalFormat::MLocalFormat(const MLocalFormat&f) -{ - operator=(f); -} - -MLocalFormat& MLocalFormat::operator=(const MLocalFormat&f) -{ - m_day=f.m_day; - m_sday=f.m_sday; - m_month=f.m_month; - m_smonth=f.m_smonth; - m_currency=f.m_currency; - m_decimal=f.m_decimal; - m_thousand=f.m_thousand; - m_moneydecimals=f.m_moneydecimals; - m_thousanddigits=f.m_thousanddigits; - m_am=f.m_am; - m_pm=f.m_pm; - m_moneyneg=f.m_moneyneg; - m_timezone=f.m_timezone; - m_dateformat=f.m_dateformat; - m_timeformat=f.m_timeformat; - m_datetimeformat=f.m_datetimeformat; - return *this; -} - -MLocalFormat::~MLocalFormat(){} - void MLocalFormat::setWeekDays(const QStringList&w) { + d.decouple(); if(w.size()==0){ - m_day=QStringList() + d->m_day=QStringList() <m_day=w; } void MLocalFormat::setShortWeekDays(const QStringList&w) { + d.decouple(); if(w.size()==0){ - m_sday=QStringList() + d->m_sday=QStringList() <m_sday=w; } void MLocalFormat::setMonths(const QStringList&m) { + d.decouple(); if(m.size()==0){ - m_month=QStringList() + d->m_month=QStringList() <m_month=m; } void MLocalFormat::setShortMonths(const QStringList&m) { + d.decouple(); if(m.size()==0){ - m_smonth=QStringList() + d->m_smonth=QStringList() <m_smonth=m; } void MLocalFormat::setDateTimeFormat(QString dateformat, QString timeformat, QString datetimeformat) { - if(dateformat=="")m_dateformat=QCoreApplication::translate("MLocalFormat","%Y-%M-%D","date format"); - else m_dateformat=dateformat; - if(timeformat=="")m_timeformat=QCoreApplication::translate("MLocalFormat","%h:%I","time format"); - else m_timeformat=timeformat; - if(datetimeformat=="")m_datetimeformat=QCoreApplication::translate("MLocalFormat","%Y-%M-%D %h:%I","date and time format"); - else m_datetimeformat=datetimeformat; + d.decouple(); + if(dateformat=="")d->m_dateformat=QCoreApplication::translate("MLocalFormat","%Y-%M-%D","date format"); + else d->m_dateformat=dateformat; + if(timeformat=="")d->m_timeformat=QCoreApplication::translate("MLocalFormat","%h:%I","time format"); + else d->m_timeformat=timeformat; + if(datetimeformat=="")d->m_datetimeformat=QCoreApplication::translate("MLocalFormat","%Y-%M-%D %h:%I","date and time format"); + else d->m_datetimeformat=datetimeformat; } -void MLocalFormat::setMoneyFormat(QString c,int n,QString g) +void MLocalFormat::setMoneyFormat(QString c,int n,bool s) { - m_currency=c; - m_moneydecimals=n; - if(g.size()>0)m_moneyneg=g.left(2); - else m_moneyneg=QCoreApplication::translate("MLocalFormat","-","negative sign for money values, the first char is put in front, the optional second one behind the number, use a newline to omit the first char"); + d.decouple(); + d->m_currency=c; + d->m_moneydecimals=n; + d->m_moneysymbehind=s; +} + +void MLocalFormat::setMoneySign(QString n,QString p, MOServerFormat::MoneyPos np, MOServerFormat::MoneyPos pp) +{ + d.decouple(); + d->m_moneyneg=n;d->m_moneypos=p; + d->m_moneynegpos=np;d->m_moneypospos=pp; } void MLocalFormat::setAP(QString am,QString pm) { - if(am=="--")m_am=QCoreApplication::translate("MLocalFormat","am","AM/PM time component"); - else m_am=am; - if(pm=="--")m_pm=QCoreApplication::translate("MLocalFormat","pm","AM/PM time component"); - else m_pm=pm; + d.decouple(); + + if(am=="--")d->m_am=QCoreApplication::translate("MLocalFormat","am","AM/PM time component"); + else d->m_am=am; + if(pm=="--")d->m_pm=QCoreApplication::translate("MLocalFormat","pm","AM/PM time component"); + else d->m_pm=pm; } void MLocalFormat::setNumberFormat(QChar dec,QChar thou,int dig) { - if(dec.isNull())m_decimal=QCoreApplication::translate("MLocalFormat",".","decimal dot")[0]; - else m_decimal=dec; + d.decouple(); + + if(dec.isNull())d->m_decimal=QCoreApplication::translate("MLocalFormat",".","decimal dot")[0]; + else d->m_decimal=dec; - if(thou.isNull())m_thousand=QCoreApplication::translate("MLocalFormat",",","thousand division character")[0]; - else m_thousand=thou; + if(thou.isNull())d->m_thousand=QCoreApplication::translate("MLocalFormat",",","thousand division character")[0]; + else d->m_thousand=thou; - if(dig<0)m_thousanddigits=QCoreApplication::translate("MLocalFormat","0","digits between thousand division chars, <=0 means none").toInt(); - else m_thousanddigits=dig; + if(dig<0)d->m_thousanddigits=QCoreApplication::translate("MLocalFormat","0","digits between thousand division chars, <=0 means none").toInt(); + else d->m_thousanddigits=dig; } void MLocalFormat::setNonLocalized() { + d.decouple(); //reset number format - m_decimal='.';m_thousanddigits=0; + d->m_decimal='.';d->m_thousanddigits=0; //reset money signs - m_moneyneg="-"; - m_currency=""; + setMoneyFormat();setMoneySign(); } QString MLocalFormat::formatDate(const QDate&date,QString format)const { - return formatDate(TimeStamp(date,m_timezone),format); + return formatDate(TimeStamp(date,d->m_timezone),format); } QString MLocalFormat::formatDate(const TimeStamp& date, QString format) const { - if(format=="")format=m_dateformat; + if(format=="")format=d->m_dateformat; return formatDateTime(date,format); } QString MLocalFormat::formatDate(qint64 date,QString format)const { - return formatDate(TimeStamp(date,m_timezone),format); + return formatDate(TimeStamp(date,d->m_timezone),format); } QString MLocalFormat::formatTime(const TimeStamp& time, QString format) const { - if(format=="")format=m_timeformat; + if(format=="")format=d->m_timeformat; return formatDateTime(time,format); } QString MLocalFormat::formatTime(const QTime&time,QString format)const { - return formatTime(TimeStamp(time,m_timezone),format); + return formatTime(TimeStamp(time,d->m_timezone),format); } QString MLocalFormat::formatTime(qint64 time,QString format)const { - return formatTime(TimeStamp(time,m_timezone),format); + return formatTime(TimeStamp(time,d->m_timezone),format); } QString MLocalFormat::formatDateTime(const QDateTime&time,QString format)const { - return formatDateTime(TimeStamp(time,m_timezone),format); + return formatDateTime(TimeStamp(time,d->m_timezone),format); } QString MLocalFormat::formatDateTime(const TimeStamp& ts, QString format) const { - if(format=="")format=m_datetimeformat; + if(format=="")format=d->m_datetimeformat; //parse - TimeStamp time=ts.toZone(m_timezone); + TimeStamp time=ts.toZone(d->m_timezone); QString out; bool inp=false; for(int i=0;im_smonth[time.month()-1];break; + case 'N':out+=d->m_month[time.month()-1];break; case 'd':out+=QString::number(time.day());break; case 'D':{ QString m=QString::number(time.day()); @@ -371,8 +399,8 @@ QString MLocalFormat::formatDateTime(const TimeStamp& ts, QString format) const out+=m; break; } - case 'w':out+=m_sday[time.weekDay()];break; - case 'W':out+=m_day[time.weekDay()];break; + case 'w':out+=d->m_sday[time.weekDay()];break; + case 'W':out+=d->m_day[time.weekDay()];break; //time formats case 'h':out+=QString::number(time.hour());break; case 'H':{ @@ -416,14 +444,14 @@ QString MLocalFormat::formatDateTime(const TimeStamp& ts, QString format) const } case 'p':{ int t=time.hour(); - if(t>=1 && t<=12)out+=m_am.toLower(); - else out+=m_pm.toLower(); + if(t>=1 && t<=12)out+=d->m_am.toLower(); + else out+=d->m_pm.toLower(); break; } case 'P':{ int t=time.hour(); - if(t>=1 && t<=12)out+=m_am; - else out+=m_pm; + if(t>=1 && t<=12)out+=d->m_am; + else out+=d->m_pm; break; } case 't': @@ -448,7 +476,7 @@ QString MLocalFormat::formatDateTime(const TimeStamp& ts, QString format) const break; } case 'o':out+=time.zoneAbbreviation();break; - case 'O':out+=m_timezone;break; + case 'O':out+=d->m_timezone;break; // % sign case '%':out+="%";break; //mistakes @@ -468,13 +496,13 @@ QString MLocalFormat::formatDateTime(const TimeStamp& ts, QString format) const QString MLocalFormat::formatDateTime(qint64 time,QString format)const { - return formatDateTime(TimeStamp(time,m_timezone),format); + return formatDateTime(TimeStamp(time,d->m_timezone),format); } QString MLocalFormat::formatNumber(qint64 n)const { //shortcut if we use standard format anyway - if(m_thousanddigits<=0)return QString::number(n); + if(d->m_thousanddigits<=0)return QString::number(n); //convert number to decimals bool neg=false; if(n<0){n*=-1;neg=true;} @@ -483,7 +511,7 @@ QString MLocalFormat::formatNumber(qint64 n)const QString r; int l=s.size(); for(int i=0;i0 && ((l-i)%m_thousanddigits)==0)r+=m_thousand; + if(i>0 && ((l-i)%d->m_thousanddigits)==0)r+=d->m_thousand; r+=s[i]; } if(neg)r="-"+r; @@ -500,7 +528,7 @@ QString MLocalFormat::formatNumber(double num,uint decimals)const QString r=formatNumber(be); //fractions if(decimals>0){ - r+=m_decimal; + r+=d->m_decimal; num-=be; for(int i=0;i<(int)decimals;i++){ num*=10.; @@ -517,35 +545,50 @@ QString MLocalFormat::formatNumber(double num,uint decimals)const QString MLocalFormat::formatMoney(qint64 num,bool usethousand)const { + return formatMoney(num,(usethousand?UseThousand:0)|ShowCurrencySymbol); +} + + +QString MLocalFormat::formatMoney(qint64 num, MLocalFormat::MoneyFlags flags) const +{ //check value bool neg=false; if(num<0){num*=-1;neg=true;} //split main and fraction - qint64 mod=1;for(int i=0;im_moneydecimals;i++)mod*=10; qint64 frac=num%mod; num/=mod; //create main unit QString ms; - if(usethousand)ms=formatNumber(num); + if(flags&UseThousand)ms=formatNumber(num); else ms=QString::number(num); //create fractional unit QString fs=QString::number(frac); - for(int i=fs.size();i=2){ - if(m_moneyneg[0]!='\n')r+=m_moneyneg[0]; - }else{ - if(m_moneyneg.size()>=1)r+=m_moneyneg[0]; - else r+='-';//emergency fallback - } + for(int i=fs.size();im_moneydecimals;i++)fs="0"+fs; + //combine and get currency symbol + QString r=ms+d->m_decimal+fs; + QString curr; + if(flags&ShowCurrencySymbol)curr=d->m_currency; + //add sign + QString sign; + if(neg)sign=d->m_moneyneg; + else sign=d->m_moneypos; + switch(neg?d->m_moneynegpos:d->m_moneypospos){ + case MOServerFormat::NoSign:break; + case MOServerFormat::SignParen:r="("+r+")";break; + case MOServerFormat::SignAfterSym:curr+=sign;break; + case MOServerFormat::SignBeforeSym:curr=sign+curr;break; + case MOServerFormat::SignAfterNum:r+=sign;break; + case MOServerFormat::SignBeforeNum: + default: + r=sign+r; + break; } - r+=ms+m_decimal+fs; - if(neg && m_moneyneg.size()>=2) - r+=m_moneyneg[1]; //add currency - r+=m_currency; + if(!curr.isEmpty()){ + if(d->m_moneysymbehind)r+=" "+curr; + else r=curr+" "+r; + } //return result return r; } @@ -565,7 +608,7 @@ qint64 MLocalFormat::scanInt(QString num)const r+=c.digitValue(); }else //ignore thousand divider - if(c==m_thousand)continue; + if(c==d->m_thousand)continue; //non-numericals break else break; } @@ -576,35 +619,35 @@ qint64 MLocalFormat::scanMoney(QString num)const { //init num=num.trimmed(); - qint64 r=0,d=0,nd=0; + qint64 r=0,dd=0,nd=0; bool neg=false,frc=false; //scan string; r=main unit; d=fractions for(int i=0;im_moneyneg.contains(c) || c=='-')neg=true;else //decimal dot - if(c==m_decimal)frc=true;else + if(c==d->m_decimal)frc=true;else //digits if(c.isDigit()){ if(frc){ - if(nd>=m_moneydecimals)break; - d*=10;d+=c.digitValue(); + if(nd>=d->m_moneydecimals)break; + dd*=10;dd+=c.digitValue(); nd++; }else{ r*=10;r+=c.digitValue(); } }else //ignore thousand divider - if(c==m_thousand)continue; + if(c==d->m_thousand)continue; //non-numericals break else break; } //move main to left - for(int i=0;im_moneydecimals;i++)r*=10; //add fractions - for(;ndm_moneydecimals;nd++)dd*=10; + r+=dd; //negative? if(neg)r*=-1; //result @@ -624,7 +667,7 @@ double MLocalFormat::scanFloat(QString num)const //negative sign if(c=='-')neg=true;else //decimal dot - if(c==m_decimal)frc=true;else + if(c==d->m_decimal)frc=true;else //digits if(c.isDigit()){ if(frc){ @@ -636,7 +679,7 @@ double MLocalFormat::scanFloat(QString num)const } }else //ignore thousand divider - if(c==m_thousand)continue; + if(c==d->m_thousand)continue; //non-numericals break else break; } @@ -648,36 +691,37 @@ double MLocalFormat::scanFloat(QString num)const QRegExp MLocalFormat::moneyRegExp(bool allownegative,bool allowcurrency)const { //main unit - QString r="[\\d"+QRegExp::escape(m_thousand)+"]+"; + QString r="[\\d"+QRegExp::escape(d->m_thousand)+"]+"; //fractions - if(m_moneydecimals>0){ - r+=QRegExp::escape(m_decimal); - r+="\\d{"+QString::number(m_moneydecimals)+"}"; + if(d->m_moneydecimals>0){ + r+=QRegExp::escape(d->m_decimal); + r+="\\d{"+QString::number(d->m_moneydecimals)+"}"; } //negative if(allownegative){ //front QString f="[-"; - if(m_moneyneg.size()>0) - if(m_moneyneg[0]!='\n' && m_moneyneg[0]!='-') - f+=QRegExp::escape(m_moneyneg[0]); + if(d->m_moneyneg.size()>0) + if(d->m_moneyneg[0]!='\n' && d->m_moneyneg[0]!='-') + f+=QRegExp::escape(d->m_moneyneg[0]); f+="]?"; r=f+r; //back - if(m_moneyneg.size()>1) - r+=QRegExp::escape(m_moneyneg[1])+"?"; + if(d->m_moneyneg.size()>1) + r+=QRegExp::escape(d->m_moneyneg[1])+"?"; } //currency - if(allowcurrency && m_currency!="") - r+="("+QRegExp::escape(m_currency)+")?"; + if(allowcurrency && d->m_currency!="") + r+="("+QRegExp::escape(d->m_currency)+")?"; //return return QRegExp(r); } void MLocalFormat::setTimeZone(QString olsonname) { + d.decouple(); if(TimeStamp::loadZone(olsonname)) - m_timezone=olsonname; + d->m_timezone=olsonname; } QString currentDir() diff --git a/src/misc/misc.h b/src/misc/misc.h index 009e915..2d4c496 100644 --- a/src/misc/misc.h +++ b/src/misc/misc.h @@ -19,7 +19,8 @@ #include class TimeStamp; -class MOServerFormat; +#include +#include /**converts special HTML characters into harmless &-codes, so the text can be included*/ QString htmlize(QString str); @@ -96,21 +97,22 @@ For example "%w the %d'th of %N in the year of the lord %Y at %a:%I %P" will be */ class MLocalFormat { + DECLARE_SHARED_DPTR(d); public: /**constructs a formatter object that corresponds to the default*/ MLocalFormat(); /**copies a formatter object inheriting its overrides*/ - MLocalFormat(const MLocalFormat&); + MLocalFormat(const MLocalFormat&)=default; /**initializes the formatter object from a server format object*/ MLocalFormat(const MOServerFormat&); /**deletes the formatter object*/ - virtual ~MLocalFormat(); + virtual ~MLocalFormat(){} /**sets a new default format*/ static void setDefaultFormat(const MLocalFormat&); /**copies a formatter object*/ - virtual MLocalFormat& operator=(const MLocalFormat&); + virtual MLocalFormat& operator=(const MLocalFormat&)=default; /**overrides the full names of week days, an empty list resets to the local translation, otherwise the list must be exactly seven entries long and starts with Sunday*/ virtual void setWeekDays(const QStringList&l=QStringList()); @@ -125,8 +127,16 @@ class MLocalFormat /**overrides the formatting of money - the settings of numbers are re-used \param digitsCents defines how many digits are used for sub-amounts (cents), if zero no cents are used, normal are the values 0, 2 and 3; the default is 2 \param currency defines the symbol of the currency used, the default is an empty string - \param negative defines how negative values are formatted, the first character is placed in front of the number, the optional second one behind the number and in front of the currency symbol; if you want no first character use a \n newline instead; the default falls back onto the translation, the default translation uses "-"*/ - virtual void setMoneyFormat(QString currency=QString(),int digitsCents=2,QString negative=QString()); + \param symbolBehind defines whether the currency symbol is shown before (false) or behind (true) the numeric value + */ + virtual void setMoneyFormat(QString currency=QString(),int digitsCents=2, bool symbolBehind=true); + /**overrides the formatting of money - the settings of numbers are re-used + \param negative defines the sign for negative values, the default is "-" + \param positive defines the sign for positive values, the default is an empty string + \param negativePos defines where the negative sign is printed + \param positivePos defines where the positive sign is printed + */ + virtual void setMoneySign(QString negative="-",QString positive=QString(), MOServerFormat::MoneyPos negativePos=MOServerFormat::SignBeforeNum, MOServerFormat::MoneyPos positivePos=MOServerFormat::NoSign); /**overrides the formatting of numbers and money; \param decimal defines the character used to separate decimals from the main body, if QChar() is used it returns to the translation default (a dot "." in default localization) @@ -145,7 +155,7 @@ class MLocalFormat virtual void setDateTimeFormat(QString dateformat=QString(),QString timeformat=QString(),QString datetimeformat=QString()); /**returns the currently set time zone of this formatter*/ - virtual QString timeZone()const{return m_timezone;} + virtual QString timeZone()const; /**overrides the formatting to be non-localized, numbers use decimal dot and no thousand separator, no currency symbol and "-" as negative sign; otherwise things stay the same; this is a helper for the shortcut methods like cent2str*/ virtual void setNonLocalized(); @@ -202,10 +212,23 @@ class MLocalFormat \param decimals the maximum number of digits after the decimal dot*/ virtual QString formatNumber(double num,uint decimals=4)const; + enum MoneyFlag { + PlainMoneyFormat=0, + UseThousand=1, + ShowCurrencySymbol=2, + + DefaultFormat=UseThousand|ShowCurrencySymbol + }; + Q_DECLARE_FLAGS(MoneyFlags,MoneyFlag); + + /**formats a money value + \param num the amount in cents + \param flags determines how the string will be formatted */ + virtual QString formatMoney(qint64 num,MoneyFlags flags=DefaultFormat)const; /**formats a money value \param num the amount in cents \param usethousand if true the thousand block division is inserted */ - virtual QString formatMoney(qint64 num,bool usethousand=true)const; + virtual QString formatMoney(qint64 num,bool usethousand)const; /**scans an integer number and returns the value, non-numerical chars are ignored*/ virtual qint64 scanInt(QString)const; @@ -217,37 +240,39 @@ class MLocalFormat virtual double scanFloat(QString)const; /**returns the names used for week days*/ - QStringList weekDayNames()const{return m_day;} + QStringList weekDayNames()const; /**returns the abbreviations used for week days*/ - QStringList shortWeekDayNames()const{return m_sday;} + QStringList shortWeekDayNames()const; /**returns the names used for months*/ - QStringList monthNames()const{return m_month;} + QStringList monthNames()const; /**returns the names used for months*/ - QStringList shortMonthNames()const{return m_smonth;} + QStringList shortMonthNames()const; /**returns the currency symbol*/ - QString currency()const{return m_currency;} + QString currency()const; /**returns the decimal dot symbol*/ - QChar decimalDot()const{return m_decimal;} + QChar decimalDot()const; /**returns the thousand separator if used, otherwise an empty string*/ - QString thousandSeparator()const{if(m_thousanddigits>0)return m_thousand;else return "";} + QString thousandSeparator()const; /**returns the amount of digits between thousand separators*/ - int thousandDigits()const{return m_thousanddigits;} + int thousandDigits()const; /**returns the amount of decimals in a money value*/ - int moneyDecimals()const{return m_moneydecimals;} + int moneyDecimals()const; /**returns the text for AM in 12-hour clock format*/ - QString amText()const{return m_am;} + QString amText()const; /**returns the text for PM in 12-hour clock format*/ - QString pmText()const{return m_pm;} + QString pmText()const; - /**returns the negative sign chars for money values*/ - QString moneyNegativeSigns()const{return m_moneyneg;} + /**returns the negative sign for money values*/ + QString moneyNegativeSign()const; + /**returns the positive sign for money values*/ + QString moneyPositiveSign()const; /**returns a regular expression matching money values \param allownegative if given the resulting RegExp allows to use negative values @@ -255,23 +280,19 @@ class MLocalFormat QRegExp moneyRegExp(bool allownegative=false,bool allowcurrency=false)const; /**returns the default format for dates*/ - QString dateFormat()const{return m_dateformat;} + QString dateFormat()const; /**returns the default format for times*/ - QString timeFormat()const{return m_timeformat;} + QString timeFormat()const; /**returns the default format for date/time*/ - QString dateTimeFormat()const{return m_datetimeformat;} + QString dateTimeFormat()const; protected: - QStringList m_day,m_sday,m_month,m_smonth; - QString m_currency,m_am,m_pm,m_moneyneg,m_timezone,m_dateformat,m_timeformat,m_datetimeformat; - QChar m_decimal,m_thousand; - int m_moneydecimals,m_thousanddigits; - /** \internal constructs the default object from the translation*/ MLocalFormat(int); /** \internal default format*/ static MLocalFormat defaultformat; }; +Q_DECLARE_OPERATORS_FOR_FLAGS(MLocalFormat::MoneyFlags); #endif diff --git a/src/misc/sclock.cpp b/src/misc/sclock.cpp index 5afd6ab..3284d12 100644 --- a/src/misc/sclock.cpp +++ b/src/misc/sclock.cpp @@ -119,7 +119,8 @@ void MServerClock::showInfo() fl->addRow(new QLabel(tr("Currency Settings:"))); fl->addRow(tr("Currency Symbol:"),new QLabel(lf.currency())); fl->addRow(tr("Division Digits:"),new QLabel(QString::number(lf.moneyDecimals()))); - fl->addRow(tr("Negative Sign:"),new QLabel(lf.moneyNegativeSigns())); + fl->addRow(tr("Negative Sign:"),new QLabel(lf.moneyNegativeSign())); + fl->addRow(tr("Positive Sign:"),new QLabel(lf.moneyPositiveSign())); fl->addRow(tr("Example:"),new QLabel(lf.formatMoney(-1234567890))); fl->addRow(new QLabel); diff --git a/wob/classes/basics.wolf b/wob/classes/basics.wolf index 5fbc4bd..ef5e9c2 100644 --- a/wob/classes/basics.wolf +++ b/wob/classes/basics.wolf @@ -39,7 +39,22 @@ The amount of digits between thousand separators, 0 for no thousand separator The amount of decimals for money values - this must be the same for all languages on a server, the default is 2 The currency used - One or two characters: for negative money values the first one is placed in front of the money value and the second one behind the money value + The currency used in HTML notation + The currency used in ASCII notation + Where the currency symbol is found: false: before the number, true: behind the number + Zero to three characters: for negative money values the first one is placed in front of the money value and the second one behind the money value + Zero to three characters: for positive money values the first one is placed in front of the money value and the second one behind the money value + + Position of the money sign in relation to number and currency symbol + no sign is shown, regardless of what symbol is set + the sign is shown before the numeric value + the sign is shown after the numeric value + the sign is shown before the currency symbol + the sign is shown after the currency symbol + parentheses are drawn around the numeric value + + position of the positive money sign + position of the negative money sign Olsen database time zone name diff --git a/www/inc/wext/format.php b/www/inc/wext/format.php index 375bf8e..2a58fb2 100644 --- a/www/inc/wext/format.php +++ b/www/inc/wext/format.php @@ -59,12 +59,35 @@ class WOServerFormat extends WOServerFormatAbstract case "thousanddigits":$this->setthousanddigits($val);break; case "moneydecimals":$this->setmoneydecimals($val);break; case "currencysymbol":$this->setcurrencysymbol($val);break; + case "currencysymbolplain":$this->setcurrencysymbolplain($val);break; + case "currencysymbolhtml":$this->setcurrencysymbolhtml($val);break; + case "currencysymbolpos":$this->setcurrencysymbolpos($val);break; case "moneynegative":$this->setmoneynegative($val);break; + case "moneypositive":$this->setmoneypositive($val);break; + case "moneynegativepos": + $this->setmoneynegativepos($this->mps2e($val));break; + case "moneypositivepos": + $this->setmoneypositivepos($this->mps2e($val));break; case "timezone":$this->settimezone($val);break; default: die("Unknown keyword in format config $file line ".($num+1));break; } } } + + ///helper function to convert string money sign position to enum + protected function mps2e($v) + { + switch(strtolower(trim($v))){ + case "none":return self::NoSign; + case "beforenum":return self::SignBeforeNum; + case "afternum":return self::SignAfterNum; + case "beforesym":return self::SignBeforeSym; + case "aftersym":return self::SignAfterSym; + case "paren":return self::SignParen; + //fallback + default:return self::SignBeforeNum; + } + } } diff --git a/www/template/format.cfg b/www/template/format.cfg index 98dff3f..f8009ca 100644 --- a/www/template/format.cfg +++ b/www/template/format.cfg @@ -80,16 +80,34 @@ thousanddigits "0" # changes the actual monetary value expressed by a stored int value changes! moneydecimals "2" -# currencysymbol: the currency used by this server +# currencysymbol: the currency used by this server as ASCII/Unicode string (used by the clients) +# currencysymbolplain: the currency symbol in plain ASCII formatting (e.g. used in eMails) +# currencysymbolhtml: the exact same symbol in HTML notation (used by the web pages, may be identical) # If you change this value in a translation, make sure it still reflects the # same currency, otherwise your customers might be surprised if the Web UI shows # amounts in US$, but they are billed in Euro. -currencysymbol "Euro" +currencysymbol "€" +currencysymbolplain "Euro" +currencysymbolhtml "€" -# the negative notation of money, it has one or two characters: -# character 1: the character placed in front of the number, or \n for none -# character 2: the character placed between number and currency symbol +# position of the currency symbol: +# value "0": before the number (e.g. "$ 123.00") +# value "1": behind the number (e.g. "123.00 $") +currencysymbolpos "1" + +# the negative/positive notation of money moneynegative "-" +moneypositive "" + +# the position of the negative and positive signs, possible values are: +# none - do not print the sign ("123.00 $") +# beforenum - before the number ("-123.00 $") +# afternum - after the number ("123.00- $") +# beforesym - before the symbol ("123.00 -$") +# aftersym - after the symbol ("123.00 $-") +# paren - use parentheses ("(123.00) $") +moneynegativepos "beforenum" +moneypositivepos "none" #Time Zone in Olson DB notation # THIS VALUE SHOULD NOT BE CHANGED IN LANGUAGE FOLDERS