00001 #include "constants.h"
00002
00003 #include "stringProcessor.h"
00004 #include "editor.h"
00005 #include "labelSyntaxChecker.h"
00006
00007 #include <QMap>
00008 #include <QList>
00009 #include <QPair>
00010 #include <QString>
00011 #include <QFont>
00012 #include <QFontMetrics>
00013 #include <QRectF>
00014 #include <QPainter>
00015 #include <QRegExp>
00016 #include <QtDebug>
00017
00018 #ifdef TESTING_STRING_PROCESSOR
00019 # define DBGLOG_SP(x) DBGLOG_("STRINGPROCESSOR", x)
00020 #else
00021 # define DBGLOG_SP(x)
00022 #endif
00023
00024 #if 0
00025 # define DBGLOG_SP_DRAW(x) DBGLOG_("SP_DRAW", x)
00026 #else
00027 # define DBGLOG_SP_DRAW(x)
00028 #endif
00029
00030
00031
00032
00033 StringProcessor::TString2CharMap StringProcessor::string2CharMap;
00034
00035 StringProcessor::TString2KwTypeMap StringProcessor::string2KwTypeMap;
00036
00037 const QRegExp StringProcessor::keywordRegex("((\\\\\\w+)\\s*)");
00038 const QRegExp StringProcessor::specCharacterRegex("(\\\\|\\{|\\})");
00039 const QRegExp StringProcessor::whitespaceRegex("\\s");
00040 const QRegExp StringProcessor::escapedCharacterRegex
00041 (
00042 "(\\\\\\$|\\\\\\%|\\\\\\#|\\\\\\&|\\\\\\~|\\\\\\_|\\\\\\^|\\\\\\{|\\\\\\}|\\\\\\\\)"
00043 );
00044
00045 #ifdef USE_UNKNOWN_CONVENTION
00046 const QChar StringProcessor::unknownCharacter = UNKNOWN_CHARACTER;
00047 const QString StringProcessor::unknownString = UNKNOWN_STRING;
00048 #endif
00049
00050 const QStringList StringProcessor::fontFamilyList =
00051 QStringList() << "Arial" << "Symbol";
00052
00053 void StringProcessor::initialize()
00054 {
00055
00056 if (string2CharMap.contains("\\alpha"))
00057 return;
00058
00059
00060 addToMaps("\\alpha", TCharPair('a', eSymbolFont));
00061 addToMaps("\\beta", TCharPair('b', eSymbolFont));
00062 addToMaps("\\gamma", TCharPair('g', eSymbolFont));
00063 addToMaps("\\delta", TCharPair('d', eSymbolFont));
00064 addToMaps("\\varepsilon", TCharPair('e', eSymbolFont));
00065 addToMaps("\\epsilon", TCharPair(0xCE, eSymbolFont));
00066 addToMaps("\\zeta", TCharPair('z', eSymbolFont));
00067 addToMaps("\\eta", TCharPair('h', eSymbolFont));
00068 addToMaps("\\theta", TCharPair('q', eSymbolFont));
00069 addToMaps("\\vartheta", TCharPair(0x4A, eSymbolFont));
00070 addToMaps("\\iota", TCharPair('i', eSymbolFont));
00071 addToMaps("\\kappa", TCharPair('k', eSymbolFont));
00072 addToMaps("\\lambda", TCharPair('l', eSymbolFont));
00073 addToMaps("\\mu", TCharPair('m', eSymbolFont));
00074 addToMaps("\\nu", TCharPair('n', eSymbolFont));
00075 addToMaps("\\xi", TCharPair('x', eSymbolFont));
00076 addToMaps("\\omicron", TCharPair('o', eSymbolFont));
00077 addToMaps("\\pi", TCharPair('p', eSymbolFont));
00078 addToMaps("\\varpi", TCharPair(0x76, eSymbolFont));
00079 addToMaps("\\rho", TCharPair('r', eSymbolFont));
00080 addToMaps("\\varsigma", TCharPair(0x56, eSymbolFont));
00081 addToMaps("\\sigma", TCharPair('s', eSymbolFont));
00082 addToMaps("\\tau", TCharPair('t', eSymbolFont));
00083 addToMaps("\\upsilon", TCharPair('u', eSymbolFont));
00084 addToMaps("\\varphi", TCharPair('j', eSymbolFont));
00085 addToMaps("\\phi", TCharPair(0x66, eSymbolFont));
00086 addToMaps("\\chi", TCharPair('c', eSymbolFont));
00087 addToMaps("\\psi", TCharPair('y', eSymbolFont));
00088 addToMaps("\\omega", TCharPair('w', eSymbolFont));
00089
00090 addToMaps("\\Alpha", TCharPair('A', eSymbolFont));
00091 addToMaps("\\Beta", TCharPair('B', eSymbolFont));
00092 addToMaps("\\Gamma", TCharPair('G', eSymbolFont));
00093 addToMaps("\\Delta", TCharPair('D', eSymbolFont));
00094 addToMaps("\\Epsilon", TCharPair('E', eSymbolFont));
00095 addToMaps("\\Zeta", TCharPair('Z', eSymbolFont));
00096 addToMaps("\\Eta", TCharPair('H', eSymbolFont));
00097 addToMaps("\\Theta", TCharPair('Q', eSymbolFont));
00098 addToMaps("\\Iota", TCharPair('I', eSymbolFont));
00099 addToMaps("\\Kappa", TCharPair('K', eSymbolFont));
00100 addToMaps("\\Lambda", TCharPair('L', eSymbolFont));
00101 addToMaps("\\Mu", TCharPair('M', eSymbolFont));
00102 addToMaps("\\Nu", TCharPair('N', eSymbolFont));
00103 addToMaps("\\Xi", TCharPair('X', eSymbolFont));
00104 addToMaps("\\Omicron", TCharPair('O', eSymbolFont));
00105 addToMaps("\\Pi", TCharPair('P', eSymbolFont));
00106 addToMaps("\\Rho", TCharPair('R', eSymbolFont));
00107 addToMaps("\\Sigma", TCharPair('S', eSymbolFont));
00108 addToMaps("\\Tau", TCharPair('T', eSymbolFont));
00109 addToMaps("\\Upsilon", TCharPair(0xA1, eSymbolFont));
00110 addToMaps("\\Phi", TCharPair(0x46, eSymbolFont));
00111 addToMaps("\\Chi", TCharPair('C', eSymbolFont));
00112 addToMaps("\\Psi", TCharPair('Y', eSymbolFont));
00113 addToMaps("\\Omega", TCharPair('W', eSymbolFont));
00114
00115
00116 addToMaps("\\{", TCharPair('{', eNormalFont));
00117 addToMaps("\\}", TCharPair('}', eNormalFont));
00118 addToMaps("\\\\", TCharPair('\\', eNormalFont));
00119
00120 addToMaps("\\$", TCharPair('$', eNormalFont));
00121 addToMaps("\\%", TCharPair('%', eNormalFont));
00122 addToMaps("\\#", TCharPair('#', eNormalFont));
00123 addToMaps("\\&", TCharPair('&', eNormalFont));
00124 addToMaps("\\~", TCharPair('~', eNormalFont));
00125 addToMaps("\\_", TCharPair('_', eNormalFont));
00126 addToMaps("\\^", TCharPair('^', eNormalFont));
00127 addToMaps("\\\\", TCharPair('\\', eNormalFont));
00128
00129 addToMaps("\\vdash", TCharPair(0x0370, eNormalFont));
00130
00131
00132 string2KwTypeMap["\\scriptstyle"] = eFontSize;
00133 string2KwTypeMap["\\textstyle"] = eFontSize;
00134 string2KwTypeMap["\\scriptscriptstyle"] = eFontSize;
00135
00136
00137 string2KwTypeMap["\\bar"] = eModifier;
00138 string2KwTypeMap["\\underline"] = eModifier;
00139 string2KwTypeMap["\\overline"] = eModifier;
00140
00141 #if defined(TESTING_STRING_PROCESSOR) || defined(STRING_PROCESSOR_TEST)
00142 DBGLOG_SP(string2CharMap);
00143 #endif
00144 }
00145
00146 void StringProcessor::addToMaps(const QString &str, const TCharPair &charPair)
00147 {
00148 string2CharMap[str] = charPair;
00149 string2KwTypeMap[str] = eString2Char;
00150 }
00151
00152 StringProcessor::CharacterInfo::CharacterInfo(EChangeType type, int idx, const QString &ch,
00153 EFontSize size, EModifier mod)
00154 : changeType(type), textIdx(idx), character(ch), fontSize(size), modifier(mod)
00155 {
00156 DBGLOG_SP("creating" << (CharacterInfo) (*this));
00157 }
00158
00159 bool StringProcessor::isSpecialSymbol(const QString &symb)
00160 {
00161 if (keywordRegex.indexIn(symb) == 0)
00162 {
00163 DBGLOG_SP(DBGPAR(symb));
00164 return true;
00165 }
00166 return false;
00167 }
00168
00169 QString StringProcessor::getSymbolPrintInfo(const QString &symb, QString &fontFamily)
00170 {
00171 initialize();
00172
00173 if (string2CharMap.contains(symb))
00174 {
00175 const int fontIdx = string2CharMap[symb].second;
00176 Q_ASSERT(fontIdx < fontFamilyList.count());
00177 Q_UNUSED(fontIdx);
00178 fontFamily = fontFamilyList[fontIdx];
00179 return string2CharMap[symb].first;
00180 }
00181
00182 fontFamily = fontFamilyList[eNormalFont];
00183 return symb;
00184 }
00185
00186 bool StringProcessor::parseFontSize(const QString &symb, EFontSize &fontSize)
00187 {
00188 if (symb == "\\textstyle")
00189 {
00190 fontSize = eTextStyle;
00191 return true;
00192 }
00193 if (symb == "\\displaystyle")
00194 {
00195 fontSize = eDisplayStyle;
00196 return true;
00197 }
00198 if (symb == "\\scriptstyle")
00199 {
00200 fontSize = eScriptStyle;
00201 return true;
00202 }
00203 if (symb == "\\scriptscriptstyle")
00204 {
00205 fontSize = eScriptScriptStyle;
00206 return true;
00207 }
00208 return false;
00209 }
00210
00211 bool StringProcessor::parseModifier(const QString &symb, EModifier &modifier)
00212 {
00213 if (symb == "\\bar")
00214 {
00215 modifier = eBar;
00216 return true;
00217 }
00218 if (symb == "\\underline")
00219 {
00220 modifier = eUnderline;
00221 return true;
00222 }
00223 if (symb == "\\overline")
00224 {
00225 modifier = eOverline;
00226 return true;
00227 }
00228 return false;
00229 }
00230
00231 StringProcessor::TCharacterList StringProcessor::computeCharacterListInBlock
00232 (const QString &input, int &startIdx, EFontSize fs, EModifier m)
00233 {
00234 TCharacterList result;
00235
00236 QString::ConstIterator inputIt = input.begin();
00237 if (QString(*inputIt) == "{")
00238 {
00239 QString newInput;
00240 inputIt++;
00241 ++startIdx;
00242 int b_count = 1;
00243 while(b_count != 0)
00244 {
00245 if (inputIt == input.end())
00246 {
00247 throw StringProcessorBraceMatchException();
00248 break;
00249 }
00250
00251 if ((*inputIt) == '{') b_count++;
00252 else if ((*inputIt) == '}') b_count--;
00253
00254 newInput += *inputIt;
00255 ++inputIt;
00256 }
00257 newInput.resize(newInput.length()-1);
00258
00259 result = computeCharacterList(newInput, startIdx, fs, m);
00260 ++startIdx;
00261 }
00262 else
00263 {
00264 result << computeCharacterList(input, startIdx, fs, m, true);
00265 }
00266
00267 return result;
00268 }
00269
00270 StringProcessor::TCharacterList StringProcessor::computeCharacterList(const QString &input)
00271 {
00272 int idx = 0;
00273 DBGLOG_SP(DBGPAR(input));
00274 TCharacterList result = computeCharacterList(input, idx, eTextStyle, eNoModifier);
00275 return result;
00276 }
00277
00278 StringProcessor::TCharacterList StringProcessor::computeCharacterList
00279 (const QString &input, int &startIdx, EFontSize fs, EModifier m, bool readOneCharacter)
00280 {
00281 EFontSize fontSize = fs;
00282 EModifier modifier = m;
00283
00284 int absPos;
00285 TCharacterList result;
00286
00287 int idx = -1, pos = 0;
00288 while((idx = specCharacterRegex.indexIn(input, pos)) != -1)
00289 {
00290 for(; pos<idx; ++pos)
00291 {
00292 QChar ch = input[pos];
00293 if (!whitespaceRegex.exactMatch(ch))
00294 {
00295 result << CharacterInfo(eNoChange, startIdx+pos, QString(ch), fontSize, modifier);
00296 if (readOneCharacter) { startIdx += ++pos; return result; }
00297 }
00298 }
00299
00300 QString subInput = input.mid(pos);
00301
00302 QString specCharacter = specCharacterRegex.cap(1);
00303 if (specCharacter == "{")
00304 {
00305 Q_ASSERT(!readOneCharacter);
00306 absPos = startIdx + pos;
00307 result << computeCharacterListInBlock(subInput, absPos, fontSize, modifier);
00308 pos = absPos - startIdx;
00309 continue;
00310 }
00311 else if (specCharacter == "}")
00312 {
00313 throw StringProcessorBraceMatchException();
00314 continue;
00315 }
00316
00317
00318 if (keywordRegex.indexIn(subInput) == 0)
00319 {
00320 QString matchedString = keywordRegex.cap(1);
00321 QString keyword = keywordRegex.cap(2);
00322
00323 if (!string2KwTypeMap.contains(keyword))
00324 {
00325 #ifdef USE_UNKNOWN_CONVENTION
00326 RELLOG(keyword << "is unknown keyword, used " << unknownString <<
00327 " instead, please contact developer");
00328 result << CharacterInfo(eNoChange, startIdx+pos, unknownString, fontSize, eNoModifier);
00329 #else
00330 DBGLOG(DBGPAR(subInput.mid(keyword.length(),2)));
00331 if (subInput.mid(keyword.length(),2) == "{}")
00332 keyword += "{}";
00333 RELLOG(keyword << "is unknown keyword, used unmodified, please contact developer");
00334 result << CharacterInfo(eNoChange, startIdx+pos, keyword, fontSize, eNoModifier);
00335 #endif
00336 pos += matchedString.length();
00337 if (readOneCharacter){ startIdx += pos; return result; }
00338 continue;
00339 }
00340
00341 EModifier newMod = modifier;
00342 switch(string2KwTypeMap[keyword])
00343 {
00344 case eString2Char:
00345 result << CharacterInfo(eStringToChar, startIdx+pos,
00346 keyword,
00347 fontSize, modifier);
00348 pos += matchedString.length();
00349 if (readOneCharacter){ startIdx += pos; return result; }
00350 break;
00351 case eFontSize:
00352 if (!parseFontSize(keyword, fontSize))
00353 {
00354 Q_ASSERT(0);
00355 }
00356 pos += matchedString.length();
00357 if (readOneCharacter){ startIdx += pos; return result; }
00358 break;
00359 case eModifier:
00360 if (!parseModifier(keyword, newMod))
00361 {
00362 Q_ASSERT(0);
00363 }
00364 pos += matchedString.length();
00365
00366 absPos = startIdx + pos;
00367 subInput = input.mid(pos);
00368 result << computeCharacterListInBlock(subInput, absPos, fontSize, newMod);
00369 pos = absPos - startIdx;
00370 if (readOneCharacter) { startIdx += pos; return result; }
00371 break;
00372 default:
00373 Q_ASSERT(0); break;
00374 }
00375
00376 continue;
00377 }
00378
00379
00380 if (escapedCharacterRegex.indexIn(subInput) == 0)
00381 {
00382
00383 QString character = escapedCharacterRegex.cap(1);
00384
00385 if (string2KwTypeMap.contains(character))
00386 {
00387 Q_ASSERT(string2KwTypeMap[character] == eString2Char);
00388 result << CharacterInfo(eStringToChar, startIdx+pos,
00389 character,
00390 fontSize, modifier);
00391 pos += character.length();
00392 if (readOneCharacter) { startIdx += pos; return result; }
00393 continue;
00394 }
00395 }
00396
00397 #ifdef USE_UNKNOWN_CONVENTION
00398 RELLOG(subInput.mid(0,2) << "is unknown sequence, used " << unknownCharacter
00399 << " instead, please contact developer");
00400 result << CharacterInfo(eNoChange, startIdx+pos,
00401 unknownCharacter,
00402 eTextStyle, eNoModifier);
00403 #else
00404 RELLOG(subInput.mid(0,2) << "is unknown sequence, used unmodified, please contact developer");
00405 result << CharacterInfo(eNoChange, startIdx+pos, subInput.mid(0,2), eTextStyle, eNoModifier);
00406 #endif
00407
00408 pos += 2;
00409 continue;
00410 }
00411
00412 for (; pos<input.length(); ++pos)
00413 {
00414 QChar ch = input[pos];
00415 if (!whitespaceRegex.exactMatch(ch))
00416 {
00417 result << CharacterInfo(eNoChange, startIdx+pos, QString(ch), fontSize, modifier);
00418 if (readOneCharacter){ startIdx += ++pos; return result; }
00419 }
00420 }
00421
00422 startIdx += pos;
00423
00424 DBGLOG_SP(DBGPAR(result));
00425 return result;
00426 }
00427
00428 QStringList StringProcessor::parseSymbols(const TCharacterList &characterList)
00429 {
00430 initialize();
00431
00432 QStringList symbols;
00433 foreach(const CharacterInfo &c, characterList)
00434 {
00435 symbols << c.character;
00436 }
00437
00438 return symbols;
00439 }
00440
00441 QStringList StringProcessor::parseSymbols(const QString &input)
00442 {
00443 initialize();
00444
00445 TCharacterList characterList = computeCharacterList(input);
00446 return parseSymbols(characterList);
00447 }
00448
00449 QStringList StringProcessor::getCharacters() const
00450 {
00451 return parseSymbols(m_characterList);
00452 }
00453
00454 StringProcessor::TCharacterList StringProcessor::getCharacterList() const
00455 {
00456 return m_characterList;
00457 }
00458
00459 StringProcessor::StringProcessor(const QString &text, int fontSize)
00460 : m_text(text), m_fontSize(fontSize)
00461 {
00462 initialize();
00463
00464 fillFontLists();
00465 bool ok = true;
00466 try
00467 {
00468 m_characterList = computeCharacterList(m_text);
00469 }
00470 catch(const StringProcessorException &e)
00471 {
00472 Q_ASSERT(0);
00473 RELLOG("StringProcessorException: " << e.what());
00474 m_text = "";
00475 ok = false;
00476 }
00477
00478 if(!ok)
00479 {
00480 try
00481 {
00482 m_characterList = computeCharacterList(m_text);
00483 }
00484 catch(const StringProcessorException &e)
00485 {
00486 Q_ASSERT(0);
00487 RELLOG("StringProcessorException: " << e.what());
00488 qFatal("Unexpected exception!");
00489 }
00490 }
00491
00492 computeMetrics();
00493 }
00494
00495 void StringProcessor::fillFontLists()
00496 {
00497 m_fontList.clear();
00498 m_metricsList.clear();
00499
00500 Q_ASSERT(fontFamilyList.size() >= 2);
00501
00502
00503 m_fontList << QFont(fontFamilyList[0], m_fontSize, QFont::Normal, false)
00504 << QFont(fontFamilyList[1], m_fontSize, QFont::Normal, false);
00505
00506
00507 m_fontList[0].setPixelSize(QFontInfo(m_fontList[0]).pixelSize());
00508 m_fontList[1].setPixelSize(QFontInfo(m_fontList[1]).pixelSize());
00509
00510 m_metricsList << QFontMetrics(m_fontList[0])
00511 << QFontMetrics(m_fontList[1]);
00512 }
00513
00514 void StringProcessor::computeMetrics()
00515 {
00516 int width = 0;
00517 int height = 0;
00518 int ascent = 0;
00519 int descent = 0;
00520
00521 m_height = height;
00522 m_ascent = ascent;
00523 m_descent = descent;
00524
00525 TCharPair tmpPair;
00526 QFont font;
00527 QFontMetrics metrics(font);
00528
00529 for(TCharacterList::ConstIterator charIt = m_characterList.begin();
00530 charIt != m_characterList.end();
00531 ++charIt)
00532 {
00533 switch((*charIt).changeType)
00534 {
00535 case eNoChange:
00536 font = m_fontList[eNormalFont];
00537 updateFont(font, *charIt);
00538 metrics = QFontMetrics(font);
00539 width += metrics.width((*charIt).character);
00540 break;
00541 case eStringToChar:
00542 tmpPair = string2CharMap[(*charIt).character];
00543 font = m_fontList[tmpPair.second];
00544 updateFont(font, *charIt);
00545 metrics = QFontMetrics(font);
00546 width += metrics.width(tmpPair.first);
00547 break;
00548 default:
00549 Q_ASSERT(0 && "unexpected value");
00550 break;
00551 }
00552
00553 if ((height = metrics.height()) > m_height) m_height = height;
00554 if ((ascent = metrics.ascent()) > m_ascent) m_ascent = ascent;
00555 if ((descent = metrics.descent()) > m_descent) m_descent = descent;
00556 }
00557
00558 m_width = width;
00559 }
00560
00561 int StringProcessor::getHeight() const
00562 {
00563 return m_height;
00564 }
00565
00566 int StringProcessor::getDescent() const
00567 {
00568 return m_descent;
00569 }
00570
00571 int StringProcessor::getAscent() const
00572 {
00573 return m_ascent;
00574 }
00575
00576 bool StringProcessor::setText(const QString &text)
00577 {
00578 try
00579 {
00580 m_characterList = computeCharacterList(text);
00581 }
00582 catch(const StringProcessorException &e)
00583 {
00584 RELLOG("StringProcessorException: " << e.what());
00585 RELLOG("Change wasn't applied!");
00586 return false;
00587 }
00588
00589 m_text = text;
00590 computeMetrics();
00591 return true;
00592 }
00593
00594 void StringProcessor::setFontSize(int fontSize)
00595 {
00596 m_fontSize = fontSize;
00597 fillFontLists();
00598 computeMetrics();
00599 }
00600
00601 bool StringProcessor::updateFont(QFont &font, const CharacterInfo &c) const
00602 {
00603 bool chFS = true;
00604 switch(c.fontSize)
00605 {
00606 case eScriptStyle:
00607 font.setPixelSize(font.pixelSize()*SCRIPT_STYLE_MULT); break;
00608 case eScriptScriptStyle:
00609 font.setPixelSize(font.pixelSize()*SCRIPT_SCRIPT_STYLE_MULT); break;
00610 default:
00611 chFS = false;
00612 break;
00613 }
00614
00615 bool chM = true;
00616 switch(c.modifier)
00617 {
00618 case eBar:
00619 font.setOverline(true); break;
00620 case eUnderline:
00621 font.setUnderline(true); break;
00622 case eOverline:
00623 font.setOverline(true); break;
00624 default:
00625 chM = false;
00626 break;
00627 }
00628
00629 if (chM || chFS)
00630 return true;
00631
00632 return false;
00633 }
00634
00635 void StringProcessor::drawText(QPainter *painter, QPointF& point) const
00636 {
00637 TCharPair tmpPair;
00638 QFont font;
00639 QFontMetrics metrics(font);
00640
00641 for(TCharacterList::ConstIterator charIt = m_characterList.begin();
00642 charIt != m_characterList.end();
00643 ++charIt)
00644 {
00645 switch((*charIt).changeType)
00646 {
00647 case eNoChange:
00648 DBGLOG_SP_DRAW((*charIt).character);
00649
00650 font = m_fontList[eNormalFont];
00651 updateFont(font, (*charIt));
00652 metrics = QFontMetrics(font);
00653 painter->setFont(font);
00654
00655 painter->drawText(point, (*charIt).character);
00656 point.setX(point.x() + metrics.width((*charIt).character));
00657 break;
00658 case eStringToChar:
00659 Q_ASSERT(string2CharMap.contains((*charIt).character));
00660 DBGLOG_SP_DRAW("character:" << (*charIt).character);
00661 tmpPair = string2CharMap[(*charIt).character];
00662 DBGLOG_SP_DRAW(tmpPair.first);
00663
00664 font = m_fontList[tmpPair.second];
00665 updateFont(font, (*charIt));
00666 metrics = QFontMetrics(font);
00667 painter->setFont(font);
00668
00669 painter->drawText(point, tmpPair.first);
00670 point.setX(point.x() + metrics.width(tmpPair.first));
00671 break;
00672 default:
00673 Q_ASSERT(0 && "unexpected value");
00674 break;
00675 }
00676 }
00677 }
00678
00679 #ifdef TESTING_STRING_PROCESSOR
00680 QDebug operator<<(QDebug dbg, const StringProcessor::CharacterInfo &c)
00681 {
00682 QString tmp;
00683 switch(c.changeType)
00684 {
00685 case StringProcessor::eStringToChar: tmp = QString("eStringToChar(%1)").arg(c.changeType); break;
00686 default: tmp = QString("eNoChange(%1)").arg(c.changeType); break;
00687 }
00688 dbg.nospace() << endl << tmp << "," << c.textIdx << "," << c.character << ",";
00689 switch(c.fontSize)
00690 {
00691 case StringProcessor::eScriptStyle: tmp = QString("eScriptStyle(%1)").arg(c.fontSize); break;
00692 case StringProcessor::eScriptScriptStyle: tmp = QString("eScriptScriptStyle(%1)").arg(c.fontSize);break;
00693 default: tmp = QString("eTextStyle(%1)").arg(c.fontSize); break;
00694 }
00695 dbg.nospace() << tmp;
00696 switch(c.modifier)
00697 {
00698 case StringProcessor::eBar: tmp = QString("eBar(%1)").arg(c.modifier); break;
00699 default: tmp = QString("eNoModifier(%1)").arg(c.modifier); break;
00700 }
00701 dbg.nospace() << tmp;
00702
00703 return dbg.nospace();
00704 }
00705 #endif
00706
00707
00708
00709
00710
00711 #ifdef STRING_PROCESSOR_TEST
00712
00713 #include "label.h"
00714 #include "labelSyntaxChecker.h"
00715 #include "dialogs.h"
00716
00717 #include <QLineEdit>
00718 #include <QPushButton>
00719 #include <QBoxLayout>
00720 #include <QGraphicsView>
00721 #include <QTimer>
00722 #include <QCheckBox>
00723
00724 ITransition::TCharSet g_alphabet =
00725 QSet<QString>::fromList((QStringList()
00726 << "a" << "b" << "c" << "d" << "e"
00727 << "\\alpha" << "\\beta" << "\\gamma" << "\\delta"));
00728
00729 StringProcessorTestDialog::StringProcessorTestDialog(QWidget *parent)
00730 : QDialog(parent), m_idx(0), m_syntaxChecker(new LabelSyntaxChecker(g_alphabet, "A", "\\varepsilon"))
00731 {
00732 m_timer = new QTimer(this);
00733 m_timer->setInterval(1000);
00734 connect(m_timer, SIGNAL(timeout()), this, SLOT(timerEvent()));
00735
00736 m_edtText = new QLineEdit(tr("\\alpha"), this);
00737 QPushButton *btnApply = new QPushButton(tr("&Apply"), this);
00738 connect(btnApply, SIGNAL(clicked()), this, SLOT(changeText()));
00739 m_checkTimer = new QCheckBox("alpha", this);
00740 connect(m_checkTimer, SIGNAL(stateChanged(int)), this, SLOT(timerChange(int)));
00741
00742 m_checkSyntax = new QCheckBox("checkSyntax", this);
00743
00744 QWidget *editHBox = new QWidget(this);
00745 QHBoxLayout *editHBoxLayout = new QHBoxLayout;
00746 editHBoxLayout->addWidget(m_edtText);
00747 editHBoxLayout->addWidget(btnApply);
00748 editHBoxLayout->addWidget(m_checkSyntax);
00749 editHBoxLayout->addWidget(m_checkTimer);
00750 editHBox->setLayout(editHBoxLayout);
00751
00752 m_view = new QGraphicsView(this);
00753 m_view->setScene(new QGraphicsScene(m_view));
00754 m_label = new LabelX(0, "\\alpha", true, 20);
00755 m_label->setPos(QPointF(10, 10));
00756 m_view->scene()->addItem(m_label);
00757
00758 QPushButton *btnClose = new QPushButton(tr("&Close"), this);
00759 connect(btnClose, SIGNAL(clicked()), this, SLOT(close()));
00760
00761 QVBoxLayout *vBoxLayout = new QVBoxLayout;
00762 vBoxLayout->addWidget(editHBox);
00763 vBoxLayout->addWidget(m_view);
00764 vBoxLayout->addWidget(btnClose, Qt::AlignHCenter);
00765 vBoxLayout->setSpacing(10);
00766
00767 this->setLayout(vBoxLayout);
00768
00769 m_greekList << "alpha" << "beta" << "gamma" << "delta" << "varepsilon" << "epsilon" << "zeta" << "eta"
00770 << "vartheta" << "theta" << "iota" << "kappa" << "lambda" << "mu" << "nu" << "xi" << "omicron"
00771 << "varpi" << "pi" << "rho" << "varsigma" << "sigma" << "tau" << "upsilon"
00772 << "varphi" << "phi" << "chi" << "psi" << "omega";
00773
00774 m_greekList << "Alpha" << "Beta" << "Gamma" << "Delta" << "Epsilon" << "Zeta" << "Eta"
00775 << "Theta" << "Iota" << "Kappa" << "Lambda" << "Mu" << "Nu" << "Xi" << "Omicron"
00776 << "Pi" << "Rho" << "Sigma" << "Tau" << "Upsilon" << "Phi" << "Chi" << "Psi" << "Omega";
00777 }
00778
00779 StringProcessorTestDialog::~StringProcessorTestDialog()
00780 {
00781 delete m_syntaxChecker;
00782 }
00783
00784 void StringProcessorTestDialog::changeText()
00785 {
00786 bool change = true;
00787 if (m_checkSyntax->isChecked())
00788 {
00789 try
00790 {
00791 StringProcessor::TCharacterList charList = StringProcessor::computeCharacterList(m_edtText->text());
00792 change &= m_syntaxChecker->checkSyntax(charList);
00793 }
00794 catch(const StringProcessorException &e)
00795 {
00796 DBGLOG("StringProcessorException: " << e.what());
00797 return;
00798 }
00799
00800 DBGLOG_SP(DBGPAR(m_syntaxChecker->getCharacters()));
00801 DBGLOG_SP(DBGPAR(m_syntaxChecker->getPattern()));
00802
00803 if (!change)
00804 {
00805 ReportDialog rd(m_syntaxChecker->getReport(), this);
00806 rd.exec();
00807 return;
00808 }
00809 }
00810
00811 m_label->setText(m_edtText->text());
00812 m_view->scene()->update();
00813 }
00814
00815 void StringProcessorTestDialog::timerChange(int state)
00816 {
00817 if (state == Qt::Checked)
00818 m_timer->start();
00819 else
00820 m_timer->stop();
00821 }
00822
00823 void StringProcessorTestDialog::timerEvent()
00824 {
00825 if (m_idx == m_greekList.size()) m_idx = 0;
00826 m_label->setText("\\" + m_greekList[m_idx]);
00827 m_view->scene()->update();
00828 m_checkTimer->setText(m_greekList[m_idx]);
00829 ++m_idx;
00830 }
00831
00832 void StringProcessor::runTest()
00833 {
00834 StringProcessorTestDialog sptd;
00835 sptd.exec();
00836 }
00837
00838 #endif