00001 #include "Util.h"
00002
00003 const QString Util::languageCodeList[] = {
00004 QObject::tr( "en" ), QObject::tr( "fr" ), QObject::tr( "es" ), QObject::tr( "ja" ), QObject::tr( "de" ),
00005 QObject::tr( "ar" ), QObject::tr( "bg" ), QObject::tr( "el" ), QObject::tr( "it" ), QObject::tr( "ko" ), QObject::tr( "nl" ),
00006 QObject::tr( "pt" ), QObject::tr( "ru" ), QObject::tr( "sw" ), QObject::tr( "th" ), QObject::tr( "vi" ), QObject::tr( "zh" )
00007 };
00008
00009 QMap<QString,QString>* Util::digraphMap = 0;
00010
00011 const QString& Util::getLanguageCode( const QString& language ) {
00012 int languageCodeListLength = sizeof( languageCodeList ) / sizeof( QString );
00013 for( int i = 0; i < languageCodeListLength; i++ ) {
00014 if( QObject::tr( languageCodeList[ i ] ) == language )
00015 return( languageCodeList[ i ] );
00016 }
00017 return( QString::null );
00018 }
00019
00020 QString Util::getDefaultLabelsFontFamily() {
00021 return( getDefaultFontFamily() );
00022 }
00023
00024 int Util::getDefaultLabelsFontSizeModifier() {
00025 return( 0 );
00026 }
00027
00028 QString Util::getDefaultFontFamily() {
00029 QFontDatabase fontDatabase;
00030 QStringList families = fontDatabase.families( false );
00031 int unifontCount = families.contains( QString( "unifont" ) );
00032 int lcfontCount = families.contains( QString( "lcfont" ) );
00033 if( unifontCount > 0 )
00034 return( QString( "unifont" ) );
00035 else if( lcfontCount > 0 )
00036 return( QString( "lcfontCount" ) );
00037 else
00038 return( QFont::defaultFont().family() );
00039 }
00040
00041 int Util::getDefaultFontSizeModifier() {
00042 return( 0 );
00043 }
00044
00045 int Util::getDefaultQuizLength() {
00046 return( 1 );
00047 }
00048
00049 QString Util::escapeXml( QString xml ) {
00050 QString escapedStr;
00051 for( uint i = 0; i < xml.length(); i++ ) {
00052 if( xml[ i ] == QChar( '&' ) )
00053 escapedStr.append( "&" );
00054 else if( xml[ i ] == QChar( '<' ) )
00055 escapedStr.append( "<" );
00056 else if( xml[ i ] == QChar( '>' ) )
00057 escapedStr.append( ">" );
00058 else
00059 escapedStr.append( xml[ i ] );
00060 }
00061 return( escapedStr );
00062 }
00063
00064 QString Util::term2Xml( const Term& term, QStringList* languages, uint indentLevel = 0 ) {
00065 QString indent;
00066 for( uint i = 0; i < indentLevel; i++ )
00067 indent += QString( "\t" );
00068
00069 QString xml;
00070 QTextStream ts( &xml, IO_WriteOnly );
00071 ts << indent << QString( "<term id=\"" ) << QString::number( term.getId() ) << QString( "\"" );
00072 if( term.getImagePath() != QString::null ) {
00073 QString fileExtension = term.getImagePath().right( 4 );
00074 QString imageFilename = QString::number( term.getId() ) + fileExtension;
00075 ts << QString( " imagePath=\"" ) << imageFilename << QString( "\"" );
00076 }
00077 ts << QString( ">" ) << endl;
00078 for( Term::TranslationMap::ConstIterator it = term.translationsBegin(); it != term.translationsEnd(); it++ ) {
00079 const Translation& translation = it.data();
00080 if( !languages || languages->contains( translation.getLanguage() ) ) {
00081 ts << indent << QString( "\t<trans lang=\"" ) << translation.getLanguage() << QString( "\">" ) << endl;
00082 if( !translation.getWord().isEmpty() )
00083 ts << indent << QString( "\t\t<word>" ) << Util::escapeXml( translation.getWord() ) << QString( "</word>" ) << endl;
00084 if( !translation.getAlt().isEmpty() )
00085 ts << indent << QString( "\t\t<alt>" ) << Util::escapeXml( translation.getAlt() ) << QString( "</alt>" ) << endl;
00086 ts << indent << QString( "\t</trans>" ) << endl;
00087 }
00088 }
00089 for( Term::CommentMap::ConstIterator it = term.commentsBegin(); it != term.commentsEnd(); it++ ) {
00090 const BilingualKey& key = it.key();
00091 const QString& comment = it.data();
00092 if( !comment.isEmpty() ) {
00093 if( !languages || ( languages->contains( key.getFirstLanguage() ) && languages->contains( key.getSecondLanguage() ) ) )
00094 ts << indent << "\t<comment languages=\"" << key.toString() << "\">" << Util::escapeXml( comment ) << "</comment>" << endl;
00095 }
00096 }
00097 ts << indent << QString( "</term>" ) << endl;
00098 return( xml );
00099 }
00100
00101 bool Util::makeDirectory( const QString& dir ) {
00102 QDir d( dir );
00103 QDir absDir( d.absPath() );
00104 if( absDir.exists() )
00105 return( true );
00106
00107 QStringList subDirs = QStringList::split( QString( "/" ), d.absPath() );
00108 for( uint i = 0; i < subDirs.count(); i++ ) {
00109 QString tempDirStr( "" );
00110 for( uint j = 0; j <= i; j++ )
00111 tempDirStr = tempDirStr + QString( "/" ) + subDirs[ j ];
00112 QDir tempDir( tempDirStr );
00113 if( !tempDir.exists() ) {
00114 if( !tempDir.mkdir( tempDir.path() ) )
00115 return( false );
00116 }
00117 }
00118 return( true );
00119 }
00120
00121 bool Util::copy( const QString& fromFile, const QString& toFile ) {
00122
00123 QFileInfo srcInfo( fromFile );
00124 QFileInfo destInfo( toFile );
00125
00126
00127 if( srcInfo.absFilePath() == destInfo.absFilePath() )
00128 return( true );
00129
00130 QFile src( fromFile );
00131 if( !src.open( IO_ReadOnly ) ) {
00132 cerr << "Cannot open src file " << fromFile << " when performing copy." << endl;
00133 return( false );
00134 }
00135 QFile dest( toFile );
00136 if( !dest.open( IO_WriteOnly ) ) {
00137 src.close();
00138 cerr << "Cannot open dest file " << fromFile << " when performing copy." << endl;
00139 return( false );
00140 }
00141 bool isOk = false;
00142
00143 uInt bufferSize = 8192;
00144 char* buffer = (char*)malloc( bufferSize );
00145 int bytesRead;
00146 while( ( bytesRead = src.readBlock( buffer, bufferSize ) ) > 0 ) {
00147 int bytesWritten = dest.writeBlock( buffer, bytesRead );
00148 if( bytesRead != bytesWritten ) {
00149 cerr << "Read and written bytes count differs (" << bytesRead << " vs " << bytesWritten << ") when performing copy." << endl;
00150 break;
00151 }
00152 }
00153 if( bytesRead == 0 )
00154 isOk = true;
00155 delete( buffer );
00156 src.close();
00157 dest.close();
00158 return( isOk );
00159 }
00160
00161 bool Util::deleteDirectory( const QString& dir ) {
00162 QDir d( dir );
00163 QDir absDir( d.absPath() );
00164 if( !absDir.exists() )
00165 return( false );
00166
00167 QStringList entries = absDir.entryList();
00168 for( QStringList::Iterator it = entries.begin(); it != entries.end(); it++ ) {
00169 QString entry = *it;
00170 QString entryPath = absDir.path() + "/" + entry;
00171 QFileInfo info( entryPath );
00172 if( info.isDir() ) {
00173 if( entry != "." && entry != ".." ) {
00174 if( !deleteDirectory( entryPath ) )
00175 return( false );
00176 }
00177 }
00178 else if( info.isFile() ) {
00179 QFile f( entryPath );
00180 if( !f.remove() )
00181 return( false );
00182 }
00183 }
00184
00185 return( absDir.rmdir( d.absPath() ) );
00186 }
00187
00188 QString Util::getDigraph( const QString& buffer ) {
00189 if( !digraphMap )
00190 initDigraphs();
00191 return( digraphMap->contains( buffer ) ? (*digraphMap)[ buffer ] : QString::null );
00192 }
00193
00194 void Util::initDigraphs() {
00195 digraphMap = new QMap<QString, QString>();
00196
00197 QString digraphFilename( "/opt/Qtopia/lib/toMOTko/digraphs.conf" );
00198 QFile digraphFile( digraphFilename );
00199
00200 if( !digraphFile.open( IO_ReadOnly ) ) {
00201 cerr << "Could not open /opt/Qtopia/lib/toMOTko/digraphs.conf" << endl;
00202 return;
00203 }
00204
00205 QTextStream ts( &digraphFile );
00206 while ( !ts.eof() ) {
00207 QString line = ts.readLine();
00208 if( line.startsWith( "#" ) || line.length() == 0 )
00209 continue;
00210 QString digraph = line.left( 2 );
00211 QString strValue = line.mid( 5, 2 );
00212 if( !digraph.isNull() && !strValue.isNull() ) {
00213 bool isOk;
00214 uint value = strValue.toUInt( &isOk, 16 );
00215 if( isOk )
00216 (*digraphMap)[ digraph ] = QString( QChar( value ) );
00217 }
00218 }
00219
00220 digraphFile.close();
00221 }
00222
00223 QAction* Util::createAction( const QString& name, const char** icon, QObject* receiver, const char* slot, int defaultKey = -1, bool toggle = false ) {
00224 QAction *a;
00225 if( icon == NULL )
00226 a = new QAction( name, name, 0, receiver, 0, toggle );
00227 else
00228 a = new QAction( name, QIconSet( ZPIXMAP( icon ) ), name, 0, receiver, 0, toggle );
00229 if( toggle )
00230 QObject::connect( a, SIGNAL( toggled( bool ) ), receiver, slot );
00231 else
00232 QObject::connect( a, SIGNAL( activated() ), receiver, slot );
00233 if( defaultKey != -1 )
00234 a->setAccel( defaultKey );
00235 return a;
00236 }
00237
00238 QString Util::describeKey( int key ) {
00239 QString ks;
00240 if( (key & Qt::CTRL) != 0 )
00241 ks += "Ctrl+";
00242 if( (key & Qt::ALT) != 0 )
00243 ks += "Alt+";
00244 if( (key & Qt::SHIFT) != 0)
00245 ks += "Shift+";
00246
00247 key = key & ~Qt::MODIFIER_MASK;
00248
00249 if (key == 0x20)
00250 ks += "Space";
00251 else if (0x21 <= key && key <= 0xff) {
00252 char st[2];
00253 st[0] = key;
00254 st[1] = 0;
00255 ks += st;
00256 }
00257 else if (0x1030 <= key && key <= 0x1052)
00258 ks += QString("f") + QChar(key - 0x1030 + 1);
00259 else {
00260 switch (key) {
00261 case Qt::Key_Escape:
00262 ks += "Esc";
00263 break;
00264 case Qt::Key_Tab:
00265 ks += "Tab";
00266 break;
00267 case Qt::Key_Backtab:
00268 ks += "Backtab";
00269 break;
00270 case Qt::Key_Backspace:
00271 ks += "Backspace";
00272 break;
00273 case Qt::Key_Return:
00274 ks += "Return";
00275 break;
00276 case Qt::Key_Enter:
00277 ks += "Enter";
00278 break;
00279 case Qt::Key_Insert:
00280 ks += "Insert";
00281 break;
00282 case Qt::Key_Delete:
00283 ks += "Delete";
00284 break;
00285 case Qt::Key_Pause:
00286 ks += "Pause";
00287 break;
00288 case Qt::Key_Print:
00289 ks += "Print";
00290 break;
00291 case Qt::Key_SysReq:
00292 ks += "SysReq";
00293 break;
00294 case Qt::Key_Home:
00295 ks += "Home";
00296 break;
00297 case Qt::Key_End:
00298 ks += "End";
00299 break;
00300 case Qt::Key_Left:
00301 ks += "Left";
00302 break;
00303 case Qt::Key_Up:
00304 ks += "Up";
00305 break;
00306 case Qt::Key_Right:
00307 ks += "Right";
00308 break;
00309 case Qt::Key_Down:
00310 ks += "Down";
00311 break;
00312 case Qt::Key_PageUp:
00313 ks += "PageUp";
00314 break;
00315 case Qt::Key_PageDown:
00316 ks += "PageDown";
00317 break;
00318 case Qt::Key_Super_L:
00319 ks += "Super_L";
00320 break;
00321 case Qt::Key_Super_R:
00322 ks += "Super_R";
00323 break;
00324 case Qt::Key_Menu:
00325 ks += "Menu";
00326 break;
00327 case Qt::Key_Hyper_L:
00328 ks += "Hyper_L";
00329 break;
00330 case Qt::Key_Hyper_R:
00331 ks += "Hyper_R";
00332 break;
00333 case Qt::Key_Help:
00334 ks += "Help";
00335 break;
00336 default:
00337 ks += "<" + QString::number( key, 16 ) + ">";
00338 break;
00339 }
00340 }
00341 return ks;
00342 }
00343
00344 QByteArray Util::qCompress( const QByteArray& byteArray, int compressionLevel ) {
00345 const uchar* data = (const uchar*)(byteArray.data());
00346 int nbytes = byteArray.size();
00347
00348 if (nbytes == 0) {
00349 QByteArray a( 4 );
00350 a.fill( '\0' );
00351 return( a );
00352 }
00353 if (!data) {
00354 qWarning("qCompress: Data is null");
00355 return QByteArray();
00356 }
00357 if (compressionLevel < -1 || compressionLevel > 9)
00358 compressionLevel = -1;
00359
00360 ulong len = nbytes + nbytes / 100 + 13;
00361 QByteArray bazip;
00362 int res;
00363 do {
00364 bazip.resize(len + 4);
00365 res = ::compress2((uchar*)bazip.data()+4, &len, (uchar*)data, nbytes, compressionLevel);
00366
00367 switch (res) {
00368 case Z_OK:
00369 bazip.resize(len + 4);
00370 bazip[0] = (nbytes & 0xff000000) >> 24;
00371 bazip[1] = (nbytes & 0x00ff0000) >> 16;
00372 bazip[2] = (nbytes & 0x0000ff00) >> 8;
00373 bazip[3] = (nbytes & 0x000000ff);
00374 break;
00375 case Z_MEM_ERROR:
00376 qWarning("qCompress: Z_MEM_ERROR: Not enough memory");
00377 bazip.resize(0);
00378 break;
00379 case Z_BUF_ERROR:
00380 len *= 2;
00381 break;
00382 }
00383 } while (res == Z_BUF_ERROR);
00384
00385 return bazip;
00386 }
00387
00388 QByteArray Util::qUncompress( const QByteArray& byteArray ) {
00389 const uchar* data = (const uchar*)(byteArray.data());
00390 int nbytes = byteArray.size();
00391
00392 if (!data) {
00393 qWarning("qUncompress: Data is null");
00394 return QByteArray();
00395 }
00396 if (nbytes <= 4) {
00397 if (nbytes < 4 || (data[0]!=0 || data[1]!=0 || data[2]!=0 || data[3]!=0))
00398 qWarning("qUncompress: Input data is corrupted");
00399 return QByteArray();
00400 }
00401 ulong expectedSize = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | (data[3] );
00402
00403 ulong len = ( expectedSize > 1ul ? expectedSize : 1ul );
00404 QByteArray baunzip;
00405 int res;
00406 do {
00407 baunzip.resize(len);
00408 res = ::uncompress((uchar*)baunzip.data(), &len, (uchar*)data+4, nbytes-4);
00409
00410 switch (res) {
00411 case Z_OK:
00412 if ((uint)len != baunzip.size())
00413 baunzip.resize(len);
00414 break;
00415 case Z_MEM_ERROR:
00416 qWarning("qUncompress: Z_MEM_ERROR: Not enough memory");
00417 break;
00418 case Z_BUF_ERROR:
00419 len *= 2;
00420 break;
00421 case Z_DATA_ERROR:
00422 qWarning("qUncompress: Z_DATA_ERROR: Input data is corrupted");
00423 break;
00424 }
00425 } while (res == Z_BUF_ERROR);
00426
00427 if (res != Z_OK)
00428 baunzip = QByteArray();
00429
00430 return baunzip;
00431 }