32 #include <QLibraryInfo>
34 #include <QMessageBox>
41 #include <QPushButton>
42 #include <QApplication>
43 #include <QDesktopWidget>
44 #include <QDomDocument>
45 #include <QTextFormat>
54 if ( !
QDir(dir).exists() ) {
57 qWarning(
"Can't create local directory %s!", qPrintable(dir));
62 QFile::ReadUser|QFile::WriteUser|QFile::ExeUser);
64 qWarning(
"Can't set permissions to local config directory `%s' !", qPrintable(dir));
79 for (k = 0; k < qitems.
size(); ++k) {
81 if (interestQueryItems.isEmpty() || interestQueryItems.
contains(p.
first))
93 klfDbg(
": 1="<<url1<<
"; 2="<<url2<<
"; interestflags="<<interestFlags<<
"; int.q.i="
94 <<interestQueryItems ) ;
95 uint compareflags = 0x00;
97 Qt::CaseSensitivity queryItemValsCS = Qt::CaseSensitive;
99 queryItemValsCS = Qt::CaseInsensitive;
109 klfDbg(
" after q-i-stripping: u1="<<u1<<
"; u2="<<u2 ) ;
120 if (u1 == u2 && qitems_map1 == qitems_map2)
146 klfDbg(
"... and the result is compareflags="<<compareflags ) ;
157 Qt::MatchFlags flags,
const QString& queryStringCache )
165 uint matchType = flags & 0x0F;
166 Qt::CaseSensitivity cs = (flags & Qt::MatchCaseSensitive)
168 : Qt::CaseInsensitive;
170 const QVariant& v = testForHitCandidateValue;
173 if (matchType == Qt::MatchExactly)
174 return (queryValue == v);
180 case Qt::MatchRegExp:
181 return (
QRegExp(text, cs).exactMatch(t));
182 case Qt::MatchWildcard:
183 return (
QRegExp(text, cs, QRegExp::Wildcard).exactMatch(t));
184 case Qt::MatchStartsWith:
186 case Qt::MatchEndsWith:
188 case Qt::MatchFixedString:
190 case Qt::MatchContains:
203 return (
'0' <= c && c <=
'9') || (
'a' <= c && c <=
'f') || (
'A' <= c && c <=
'F');
208 #define KLF_BRUSH_STYLE(sty) \
209 { Qt::sty##Pattern, #sty }
212 { Qt::NoBrush,
"NoBrush" },
213 { Qt::SolidPattern,
"" },
214 { Qt::SolidPattern,
"Solid" },
233 #define KLF_TEXT_FORMAT_FORMAT(fmt) \
234 { QTextFormat::fmt##Format, #fmt "Format" }
248 #define KLF_TEXT_FORMAT_PROP(p, type) \
249 { QTextFormat::p, #p, #type }
260 { QTextFormat::ForegroundBrush,
"FG",
"QBrush" },
261 { QTextFormat::BackgroundBrush,
"BG",
"QBrush" },
267 {
"NORMALWEIGHT", QTextFormat::FontWeight,
QVariant(QFont::Normal) },
268 {
"BOLD", QTextFormat::FontWeight,
QVariant(QFont::Bold) },
269 {
"NORMALSTYLE", QTextFormat::FontItalic,
QVariant(
false) },
270 {
"ITALIC", QTextFormat::FontItalic,
QVariant(
true) },
280 qDebug(
"klfDataToEscaped: len=%d, data=`%s'", value_ba.
size(), value_ba.
constData());
283 for (k = 0; k < value_ba.
size(); ++k) {
285 if (value_ba[k] >= 32 && value_ba[k] <= 126 && value_ba[k] !=
'\\') {
288 }
else if (value_ba[k] ==
'\\') {
291 data +=
QString(
"\\x%1").
arg((uint)(uchar)value_ba[k], 2, 16,
QChar(
'0')).toAscii();
303 while (k < data.
size()) {
304 if (data[k] !=
'\\') {
309 if (data[k] ==
'\\' && k+1 >= data.
size()) {
315 if (data[k+1] !=
'x') {
317 value_ba += data[k+1];
329 uchar cval = data.
mid(k+2, 2).toUInt(&convertOk, 16);
330 value_ba += (char)cval;
340 for (
int k = 0; k < list.
size(); ++k) {
347 if (k < list.
size()-1)
359 bool first_item =
true;
361 for (k = 0; k < sections.size(); ++k) {
374 if (val.
isEmpty() && ignore_empty_values)
377 data += key +
"=" + val;
386 klfDbg(
"decaps_list, data="<<ba_data);
396 while (k < data.
size()) {
397 if (data[k] ==
';') {
404 if (data[k] ==
'\\') {
405 if (k+1 < data.
size()) {
414 if (data[k] ==
']') {
431 klfDbg(
"sections="<<sections);
451 while (k < data.
size()) {
452 if (data[k] ==
';') {
454 if (!allow_empty_values && curChunk == &chunkkey)
455 qWarning()<<
KLF_FUNC_NAME<<
": no '=' in pair at pos "<<k<<
" in string: "<<data<<
"";
456 sections << QPair<QByteArray,QByteArray>(chunkkey, chunkvalue);
460 curChunk = &chunkkey;
463 if (data[k] ==
'\\') {
464 if (k+1 < data.
size()) {
465 *curChunk += data[k+1];
468 *curChunk += data[k];
473 if (curChunk == &chunkkey && data[k] ==
'=') {
475 curChunk = &chunkvalue;
479 if (data[k] ==
'}') {
482 if (!allow_empty_values && curChunk == &chunkkey)
483 qWarning()<<
"klfLoadVariantFromText: no '=' in pair at pos "<<k<<
" in string: "<<data<<
"";
484 sections << QPair<QByteArray,QByteArray>(chunkkey, chunkvalue);
488 *curChunk += data[k];
501 xmldoc.appendChild(root);
514 "Wrong XML root node in wrapper for klfLoadVariantFromText(): "
515 <<el.nodeName() , ) ;
531 switch ((
int)value.
type()) {
532 case QMetaType::Bool:
533 data = value.
toBool() ?
"true" :
"false";
536 case QMetaType::UInt:
537 case QMetaType::Short:
538 case QMetaType::UShort:
539 case QMetaType::Long:
540 case QMetaType::ULong:
541 case QMetaType::LongLong:
542 case QMetaType::ULongLong:
543 case QMetaType::Double:
544 data = value.
toString().toLocal8Bit();
546 case QMetaType::Char:
548 char c = value.
value<
char>();
549 if (c >= 32 && c <= 126 && c !=
'\\')
556 case QMetaType::QChar:
567 case QMetaType::QString:
576 for (k = 0; k < s.
length(); ++k) {
580 data +=
QString(
"\\x%1").
arg((uint)s[k].unicode(), 4, 16,
QChar(
'0')).toAscii();
585 case QMetaType::QStringList:
590 for (k = 0; k < list.size(); ++k) {
596 case QMetaType::QUrl:
597 data = value.
toUrl().toEncoded();
break;
598 case QMetaType::QByteArray:
603 case QMetaType::QDate:
604 data = value.
value<
QDate>().toString(Qt::SystemLocaleShortDate).toLocal8Bit();
break;
605 case QMetaType::QTime:
606 data = value.
value<
QTime>().toString(Qt::SystemLocaleShortDate).toLocal8Bit();
break;
607 case QMetaType::QDateTime:
608 data = value.
value<
QDateTime>().toString(Qt::SystemLocaleShortDate).toLocal8Bit();
break;
609 case QMetaType::QSize:
614 case QMetaType::QPoint:
616 data =
QString(
"(%1 %2)").
arg(pt.
x()).arg(pt.
y()).toAscii();
619 case QMetaType::QRect:
624 case QMetaType::QColor:
626 klfDbg(
"Saving color "<<c<<
": alpha="<<c.
alpha()) ;
627 if (c.
alpha() == 255)
633 case QMetaType::QFont:
635 data =
"'" + f.
family().toLocal8Bit() +
"'";
637 case QFont::Light: data +=
" Light";
break;
638 case QFont::Normal:
break;
639 case QFont::DemiBold: data +=
" DemiBold";
break;
640 case QFont::Bold: data +=
" Bold";
break;
641 case QFont::Black: data +=
" Black";
break;
645 case QFont::StyleNormal:
break;
646 case QFont::StyleItalic: data +=
" Italic";
break;
647 case QFont::StyleOblique: data +=
" Oblique";
break;
654 case QMetaType::QBrush:
656 if (!b.
matrix().isIdentity())
658 int bstyle = b.style();
661 bool found_style =
false;
682 case QMetaType::QTextFormat:
704 for (it = props.begin(); it != props.end(); ++it) {
718 sections << QPair<QByteArray,QByteArray>(kw,
QByteArray());
732 sections << QPair<QByteArray,QByteArray>(
key, value);
736 <<
" 's type is `"<<propValue.
typeName()<<
"' which is not the known type: "
749 case QMetaType::QVariantList:
752 if (saveListAndMapsAsXML) {
755 data = el.ownerDocument().toByteArray(0);
758 for (k = 0; k < list.
size(); ++k) {
765 case QMetaType::QVariantMap:
768 if (saveListAndMapsAsXML) {
771 data = el.ownerDocument().toByteArray(0);
777 sections << QPair<QByteArray,QByteArray>(k, v);
791 if (typeName ==
"KLFStyle") {
820 qDebug(
"\tVariant value is %s, len=%d", vdata.
constData(), vdata.
size());
825 klfDbg(
"klfSaveVariantToText("<<value<<
"): saved data (len="<<data.
size()<<
") : "<<data ) ;
833 const char *listOrMapDataTypeName)
839 #define RX_INT "-?\\d+"
840 #define RX_COORD_SEP "\\s*(?:[,;]|\\s)\\s*" // note: non-capturing parenthesis
841 #define RX_SIZE_SEP "\\s*(?:[,;x]|\\s)\\s*" // note: non-capturing parenthesis
845 static const int V2RX_X = 1, V2RX_Y = 2;
849 static const int SZRX_W = 1, SZRX_H = 2;
856 "(" RX_INT
")(?:"RX_COORD_SEP"|\\s*([x])\\s*)(" RX_INT
")\\s*\\)?");
857 static const int RECTRX_X1 = 1, RECTRX_Y1 = 2, RECTRX_MIDDLESEP_PLUS = 3,
858 RECTRX_X2orW = 4, RECTRX_LASTSEP_X = 5, RECTRX_Y2orH = 6;
863 "(" RX_COORD_SEP "(\\d+))?\\s*\\)?", Qt::CaseInsensitive);
864 static const int COLRX_R = 1, COLRX_G = 2, COLRX_B = 3, COLRX_MAYBE_ALPHA = 4, COLRX_A = 5;
867 QRegExp brushrx(
"^(?:q?brush)?\\(?\\s*(?:([A-Za-z_]\\w*)" RX_COORD_SEP
")?(\\d+)" RX_COORD_SEP
"(\\d+)"
869 RX_COORD_SEP
"(\\d+)" "("RX_COORD_SEP
"(\\d+))?" "\\s*\\)?", Qt::CaseInsensitive);
870 static const int BRUSHRX_STYLE = 1, BRUSHRX_R = 2, BRUSHRX_G = 3, BRUSHRX_B = 4, BRUSHRX_A = 6;
873 QRegExp fontrx(
"^([\"']?)\\s*(.+)\\s*\\1"
875 "(\\s+(Light|Normal|DemiBold|Bold|Black|Wgt\\s*=\\s*(\\d+)))?"
877 "(\\s+(Normal|Italic|Oblique))?(\\s+(\\d+))?$");
879 static const int FONTRX_FAMILY = 2, FONTRX_WEIGHT_TEXT = 4, FONTRX_WEIGHT_VALUE = 5,
880 FONTRX_STYLE_TEXT = 7, FONTRX_POINTSIZE = 9;
891 klfDbg(
"\tAbout to read raw variant from datastr="<<vdata_esc<<
", ie. from data len="<<vdata.
size() ) ;
899 klfDbg(
"Will start loading a `"<<dataTypeName<<
"' from data (len="<<data.
size()<<
") : "<<data ) ;
903 bool convertOk =
false;
906 case QMetaType::Bool:
911 return QVariant::fromValue<bool>(c ==
't' || c ==
'y' || c ==
'1' || lowerdata ==
"on");
915 int i = data.
toInt(&convertOk);
917 return QVariant::fromValue<int>(i);
920 case QMetaType::UInt:
922 uint i = data.
toUInt(&convertOk);
924 return QVariant::fromValue<uint>(i);
927 case QMetaType::Short:
929 short i = data.
toShort(&convertOk);
931 return QVariant::fromValue<short>(i);
934 case QMetaType::UShort:
936 ushort i = data.
toUShort(&convertOk);
938 return QVariant::fromValue<ushort>(i);
941 case QMetaType::Long:
943 long i = data.
toLong(&convertOk);
945 return QVariant::fromValue<long>(i);
948 case QMetaType::ULong:
950 ulong i = data.
toULong(&convertOk);
952 return QVariant::fromValue<ulong>(i);
955 case QMetaType::LongLong:
959 return QVariant::fromValue<qlonglong>(i);
962 case QMetaType::ULongLong:
966 return QVariant::fromValue<qulonglong>(i);
969 case QMetaType::Double:
971 double val = data.
toDouble(&convertOk);
973 return QVariant::fromValue<double>(val);
976 case QMetaType::Char:
978 if (data[0] ==
'\\') {
982 return QVariant::fromValue<char>(
'\\');
985 uint c = data.
mid(1).toUInt(&convertOk, 16);
991 return QVariant::fromValue<char>( (char)c );
993 return QVariant::fromValue<char>( (char)data[0] );
995 case QMetaType::QChar:
997 if (data[0] ==
'\\') {
1000 if (data[1] ==
'\\')
1001 return QVariant::fromValue<QChar>(
QChar(
'\\'));
1002 if (data.
size() < 3)
1004 uint c = data.
mid(1).toUInt(&convertOk, 16);
1010 return QVariant::fromValue<QChar>(
QChar(c) );
1012 return QVariant::fromValue<QChar>(
QChar(data[0]) );
1014 case QMetaType::QString:
1019 while (k < data.
size()) {
1020 if (data[k] !=
'\\') {
1025 if (data[k] ==
'\\' && k+1 >= data.
size()) {
1031 if (data[k+1] !=
'x') {
1051 ushort cval = data.
mid(k+2, nlen).toUShort(&convertOk, 16);
1063 return QVariant::fromValue<QString>(s);
1065 case QMetaType::QStringList:
1071 for (k = 0; k < sections.
size(); ++k) {
1075 return QVariant::fromValue<QStringList>(list);
1077 case QMetaType::QUrl:
1079 case QMetaType::QByteArray:
1082 return QVariant::fromValue<QByteArray>(value_ba);
1084 case QMetaType::QDate:
1101 return QVariant::fromValue<QDate>(date);
1103 case QMetaType::QTime:
1121 return QVariant::fromValue<QTime>(time);
1123 case QMetaType::QDateTime:
1144 return QVariant::fromValue<QDateTime>(dt);
1146 case QMetaType::QSize:
1152 return QVariant::fromValue<QSize>(
QSize(vals[SZRX_W].toInt(), vals[SZRX_H].toInt()));
1154 case QMetaType::QPoint:
1160 return QVariant::fromValue<QPoint>(
QPoint(vals[V2RX_X].toInt(), vals[V2RX_Y].toInt()));
1162 case QMetaType::QRect:
1168 if (vals[RECTRX_MIDDLESEP_PLUS] ==
"+" || vals[RECTRX_LASTSEP_X] ==
"x") {
1169 return QVariant::fromValue<QRect>(
QRect(
QPoint(vals[RECTRX_X1].toInt(), vals[RECTRX_Y1].toInt()),
1170 QSize(vals[RECTRX_X2orW].toInt(), vals[RECTRX_Y2orH].toInt()) ));
1172 return QVariant::fromValue<QRect>(
QRect(
QPoint(vals[RECTRX_X1].toInt(), vals[RECTRX_Y1].toInt()),
1173 QPoint(vals[RECTRX_X2orW].toInt(), vals[RECTRX_Y2orH].toInt()) ));
1175 case QMetaType::QColor:
1179 if (colrx.
indexIn(colstr) < 0) {
1180 klfDbg(
"color "<<colstr<<
" does not match regexp="<<colrx.
pattern()<<
", trying named...") ;
1184 if (color.isValid())
1190 QColor color =
QColor(vals[COLRX_R].toInt(), vals[COLRX_G].toInt(), vals[COLRX_B].toInt(), 255);
1191 if (!vals[COLRX_MAYBE_ALPHA].isEmpty())
1192 color.
setAlpha(vals[COLRX_A].toInt());
1193 return QVariant::fromValue<QColor>(color);
1195 case QMetaType::QFont:
1198 klfDbg(
"malformed font: "<<data);
1202 klfDbg(
"parsing font: data="<<data<<
"; captured texts are: "<<vals );
1204 QString family = vals[FONTRX_FAMILY].trimmed();
1205 QString weighttxt = vals[FONTRX_WEIGHT_TEXT];
1206 QString weightval = vals[FONTRX_WEIGHT_VALUE];
1207 QString styletxt = vals[FONTRX_STYLE_TEXT];
1208 QString ptsval = vals[FONTRX_POINTSIZE];
1210 int weight = QFont::Normal;
1211 if (weighttxt ==
"Light") weight = QFont::Light;
1212 else if (weighttxt ==
"Normal") weight = QFont::Normal;
1213 else if (weighttxt ==
"DemiBold") weight = QFont::DemiBold;
1214 else if (weighttxt ==
"Bold") weight = QFont::Bold;
1215 else if (weighttxt ==
"Black") weight = QFont::Black;
1219 QFont::Style
style = QFont::StyleNormal;
1220 if (styletxt ==
"Normal") style = QFont::StyleNormal;
1221 else if (styletxt ==
"Italic") style = QFont::StyleItalic;
1222 else if (styletxt ==
"Oblique") style = QFont::StyleOblique;
1226 pt = ptsval.
toInt();
1228 QFont font(family, pt, weight);
1230 return QVariant::fromValue<QFont>(font);
1232 case QMetaType::QBrush:
1235 klfDbg(
"malformed brush text: "<<data) ;
1242 bool style_found =
false;
1250 klfDbg(
"Can't find style"<<style<<
" in brush style list!");
1255 QColor c =
QColor(vals[BRUSHRX_R].toInt(), vals[BRUSHRX_G].toInt(),
1256 vals[BRUSHRX_B].toInt());
1257 if (!vals[BRUSHRX_A].isEmpty())
1258 c.
setAlpha(vals[BRUSHRX_A].toInt());
1259 return QBrush(c, static_cast<Qt::BrushStyle>(qbrush_style));
1261 case QMetaType::QTextFormat:
1266 klfDbg(
"Invalid QTextFormat data.") ;
1274 Qt::CaseInsensitive) == 0)
1277 klfDbg(
"QTextFormat: Invalid format type: "<<fmttype) ;
1285 for (it = sections.
begin(); it != sections.
end(); ++it) {
1288 klfDbg(
"QTextFormat: considering property pair key="<<key<<
"; value="<<value) ;
1292 key, Qt::CaseInsensitive) == 0)
1305 key, Qt::CaseInsensitive) == 0)
1316 bool tointok =
true;
1317 int propid = key.toInt(&tointok);
1319 qWarning()<<
KLF_FUNC_NAME<<
": QTextFormat bad format for general property key=value pair; "
1320 <<
"key is not a numerical property ID, nor is it a known property name.";
1323 klfDbg(
"QTextFormat: property is not a known one. propid="<<propid) ;
1330 qWarning().nospace()<<
KLF_FUNC_NAME<<
": QTextFormat bad format for general property, value does "
1331 <<
"not begin with \"[type-name]\".";
1337 klfDbg(
"setting generalized property "<<propid<<
" to value "<<vval) ;
1342 case QMetaType::QVariantList:
1352 for (k = 0; k < sections.
size(); ++k) {
1357 return QVariant::fromValue<QVariantList>(list);
1360 case QMetaType::QVariantMap:
1369 for (it = sections.
begin(); it != sections.
end(); ++it) {
1374 return QVariant::fromValue<QVariantMap>(vmap);
1382 if (tname ==
"KLFStyle") {
1393 return QVariant::fromValue<KLFStyle>(
style);
1396 qWarning(
"klfLoadVariantFromText: Can't load a %s from %s !", dataTypeName, stringdata.
constData());
1414 for (QVariantMap::const_iterator it = vmap.begin(); it != vmap.end(); ++it) {
1422 keyNode.appendChild(keyText);
1423 pairNode.appendChild(keyNode);
1428 if (vtype ==
"QVariantMap") {
1430 }
else if (vtype ==
"QVariantList") {
1434 vdataNode.appendChild(vdataText);
1436 pairNode.appendChild(vdataNode);
1438 baseNode.appendChild(pairNode);
1452 if ( e.isNull() || n.
nodeType() != QDomNode::ElementNode )
1454 if ( e.nodeName() !=
"pair" ) {
1455 qWarning(
"%s: ignoring unexpected tag `%s'!\n",
KLF_FUNC_NAME, qPrintable(e.nodeName()));
1467 if ( ee.isNull() || nn.
nodeType() != QDomNode::ElementNode )
1469 if ( ee.nodeName() ==
"key" ) {
1473 if ( ee.nodeName() ==
"value" ) {
1476 valuedata = ee.text().toLocal8Bit();
1477 valuetype = ee.attribute(
"type").toLatin1();
1480 qWarning(
"%s: ignoring unexpected tag `%s' in <pair>!\n",
KLF_FUNC_NAME,
1481 qPrintable(ee.nodeName()));
1484 if (valuetype ==
"QVariantMap") {
1486 }
else if (valuetype ==
"QVariantList") {
1502 for (QVariantList::const_iterator it = vlist.begin(); it != vlist.end(); ++it) {
1509 if (vtype ==
"QVariantMap") {
1511 }
else if (vtype ==
"QVariantList") {
1515 elNode.appendChild(vdataText);
1519 baseNode.appendChild(elNode);
1534 if ( e.isNull() || n.
nodeType() != QDomNode::ElementNode )
1537 qWarning(
"%s: ignoring unexpected tag `%s'!\n",
KLF_FUNC_NAME, qPrintable(e.nodeName()));
1563 klfDbg(
"path="<<path<<
"; reference="<<reference) ;
1571 klfDbg(
"reference is "<<ref) ;