kexi

identifier.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 2003-2005 Jaroslaw Staniek <js@iidea.pl>
00003    Copyright (C) 2005 Martin Ellis <martin.ellis@kdemail.net>
00004 
00005    This program is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this program; see the file COPYING.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include "identifier.h"
00022 #include <kstaticdeleter.h>
00023 #include <qdict.h>
00024 
00025 using namespace KexiUtils;
00026 
00027 bool KexiUtils::isIdentifier(const QString& s)
00028 {
00029     uint i;
00030     for (i=0; i<s.length(); i++) {
00031         QChar c = s.at(i).lower();
00032         if (!(c=='_' || c>='a' && c<='z' || i>0 && c>='0' && c<='9'))
00033             break;
00034     }
00035     return i>0 && i==s.length();
00036 }
00037 
00038 QString KexiUtils::string2FileName(const QString &s)
00039 {
00040     QString fn = s.simplifyWhiteSpace();
00041     fn.replace(' ',"_"); fn.replace('$',"_");
00042     fn.replace('\\',"-"); fn.replace('/',"-"); 
00043     fn.replace(':',"-"); fn.replace('*',"-"); 
00044     return fn;
00045 }
00046 
00047 // These are in pairs - first the non-latin character in UTF-8,
00048 // the second is the latin character(s) to appear in identifiers.
00049 static const char* string2Identifier_table[] = {
00050 /* 1. Polish characters */
00051 "Ą", "A",  "Ć", "C",  "Ę", "E",
00052 "Ł", "L",  "Ń", "N",  "Ó", "O",
00053 "Ś", "S",  "Ź", "Z",  "Ż", "Z",
00054 "ą", "a",  "ć", "c",  "ę", "e",
00055 "ł", "l",  "ń", "n",  "ó", "o",
00056 "ś", "s",  "ź", "z",  "ż", "z",
00057 
00058 /* 2. The mappings of the german "umlauts" to their 2-letter equivalents:
00059   (Michael Drüing <michael at drueing.de>)
00060 
00061  Note that ß->ss is AFAIK not always correct transliteration, for example
00062  "Maße" and "Masse" is different, the first meaning "measurements" (as
00063  plural of "Maß" meaning "measurement"), the second meaning "(physical)
00064  mass". They're also pronounced dirrefently, the first one is longer, the
00065  second one short. */
00069 "Ä", "Ae",
00070 "Ö", "Oe",
00071 "Ü", "Ue",
00072 "ä", "ae",
00073 "ö", "oe",
00074 "ü", "ue",
00075 "ß", "ss",
00076  
00077 /* 3. The part of Serbian Cyrillic which is shared with other Cyrillics but 
00078  that doesn't mean I am sure that eg. Russians or Bulgarians would do the 
00079  same. (Chusslove Illich <caslav.ilic at gmx.net>) */
00080 "а", "a",
00081 "б", "b",
00082 "в", "v",
00083 "г", "g",
00084 "д", "d",
00085 "е", "e",
00086 "ж", "z",
00087 "з", "z",
00088 "и", "i",
00089 "к", "k",
00090 "л", "l",
00091 "м", "m",
00092 "н", "n",
00093 "о", "o",
00094 "п", "p",
00095 "р", "r",
00096 "с", "s",
00097 "т", "t",
00098 "у", "u",
00099 "ф", "f",
00100 "х", "h",
00101 "ц", "c",
00102 "ч", "c",
00103 "ш", "s",
00104 "А", "A",
00105 "Б", "B",
00106 "В", "V",
00107 "Г", "G",
00108 "Д", "D",
00109 "Е", "E",
00110 "Ж", "Z",
00111 "З", "Z",
00112 "И", "I",
00113 "К", "K",
00114 "Л", "L",
00115 "М", "M",
00116 "Н", "N",
00117 "О", "O",
00118 "П", "P",
00119 "Р", "R",
00120 "С", "S",
00121 "Т", "T",
00122 "У", "U",
00123 "Ф", "F",
00124 "Х", "H",
00125 "Ц", "C",
00126 "Ч", "C",
00127 "Ш", "S",
00128 // 3.1. The Serbian-specific Cyrillic characters:
00129 "ђ", "dj",
00130 "ј", "j",
00131 "љ", "lj",
00132 "њ", "nj",
00133 "ћ", "c",
00134 "џ", "dz",
00135 "Ђ", "Dj",
00136 "Ј", "J",
00137 "Љ", "Lj",
00138 "Њ", "Nj",
00139 "Ћ", "C",
00140 "Џ", "Dz",
00141 // 3.2. The non-ASCII Serbian Latin characters:
00142 "đ", "dj",
00143 "ž", "z",
00144 "ć", "c",
00145 "č", "c",
00146 "š", "s",
00147 "Đ", "Dj",
00148 "Ž", "Z",
00149 "Ć", "C",
00150 "Č", "C",
00151 "Š", "S",
00152 // END.
00153 0
00154 };
00155 
00157 static KStaticDeleter< QDict<QCString> > string2Identifier_deleter;
00158 static QDict<QCString>* string2Identifier_dict = 0;
00159 
00160 inline QString char2Identifier(const QChar& c)
00161 {
00162     if ((c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || c=='_')
00163         return QString(c);
00164     else {
00165         if (!string2Identifier_dict) {
00166             //build dictionary for later use
00167             string2Identifier_deleter.setObject( string2Identifier_dict, new QDict<QCString>(1009) );
00168             string2Identifier_dict->setAutoDelete(true);
00169             for (const char **p = string2Identifier_table; *p; p+=2) {
00170                 string2Identifier_dict->replace( /* replace, not insert because there may be duplicates */
00171                     QString::fromUtf8(*p), new QCString(*(p+1)) );
00172             }
00173         }
00174         const QCString *fixedChar = string2Identifier_dict->find(c);
00175         if (fixedChar)
00176             return *fixedChar;
00177     }
00178     return QString(QChar('_'));
00179 }
00180 
00181 QString KexiUtils::string2Identifier(const QString &s)
00182 {
00183     QString r, id = s.simplifyWhiteSpace();
00184     if (id.isEmpty())
00185         return id;
00186     r.reserve(id.length());
00187 //      return "_";
00188     id.replace(' ',"_");
00189     QChar c = id[0];
00190 
00191     if (c>='0' && c<='9') {
00192         r+='_';
00193         r+=c;
00194     } else
00195         r+=char2Identifier(c);
00196 
00197     for (uint i=1; i<id.length(); i++)
00198         r+=char2Identifier(id.at(i));
00199     return r;
00200 }
00201 
00202 //--------------------------------------------------------------------------------
00203 
00204 QString KexiUtils::identifierExpectedMessage(const QString &valueName, const QVariant& v)
00205 {
00206     return "<p>"+i18n("Value of \"%1\" column must be an identifier.").arg(valueName)
00207         +"</p><p>"+i18n("\"%1\" is not a valid identifier.").arg(v.toString())+"</p>";
00208 }
00209 
00210 //--------------------------------------------------------------------------------
00211 
00212 IdentifierValidator::IdentifierValidator(QObject * parent, const char * name)
00213 : Validator(parent,name)
00214 {
00215 }
00216 
00217 IdentifierValidator::~IdentifierValidator()
00218 {
00219 }
00220 
00221 QValidator::State IdentifierValidator::validate( QString& input, int& pos ) const
00222 {
00223     uint i;
00224     for (i=0; i<input.length() && input.at(i)==' '; i++)
00225         ;
00226     pos -= i; //i chars will be removed from beginning
00227     if (i<input.length() && input.at(i)>='0' && input.at(i)<='9')
00228         pos++; //_ will be added at the beginning
00229     bool addspace = (input.right(1)==" ");
00230     input = string2Identifier(input);
00231     if (addspace)
00232         input += "_";
00233     if((uint)pos>input.length())
00234         pos=input.length();
00235     return input.isEmpty() ? Valid : Acceptable;
00236 }
00237 
00238 Validator::Result IdentifierValidator::internalCheck(
00239     const QString &valueName, const QVariant& v, 
00240     QString &message, QString & /*details*/)
00241 {
00242     if (isIdentifier(v.toString()))
00243         return Validator::Ok;
00244     message = identifierExpectedMessage(valueName, v);
00245     return Validator::Error;
00246 }
00247 
KDE Home | KDE Accessibility Home | Description of Access Keys