00001
00002
00003 #include "xmlparsebase.h"
00004
00005
00006 #include <typeinfo>
00007
00008
00009 #include <QFile>
00010 #include <QDomDocument>
00011 #include <QString>
00012 #include <QBrush>
00013 #include <QLinearGradient>
00014 #include <QRadialGradient>
00015
00016
00017 #include "mythlogging.h"
00018
00019
00020 #include "mythmainwindow.h"
00021 #include "mythuihelper.h"
00022
00023
00024 #include "mythscreentype.h"
00025 #include "mythuiimage.h"
00026 #include "mythuitext.h"
00027 #include "mythuitextedit.h"
00028 #include "mythuiclock.h"
00029 #include "mythuibuttonlist.h"
00030 #include "mythuibutton.h"
00031 #include "mythuispinbox.h"
00032 #include "mythuicheckbox.h"
00033 #include "mythuiprogressbar.h"
00034 #include "mythuiscrollbar.h"
00035 #include "mythuigroup.h"
00036 #include "mythuiwebbrowser.h"
00037 #include "mythuiguidegrid.h"
00038 #include "mythuishape.h"
00039 #include "mythuibuttontree.h"
00040 #include "mythuivideo.h"
00041 #include "mythuieditbar.h"
00042 #include "mythfontproperties.h"
00043
00044 #define LOC QString("XMLParseBase: ")
00045
00046 QString XMLParseBase::getFirstText(QDomElement &element)
00047 {
00048 for (QDomNode dname = element.firstChild(); !dname.isNull();
00049 dname = dname.nextSibling())
00050 {
00051 QDomText t = dname.toText();
00052 if (!t.isNull())
00053 return t.data();
00054 }
00055 return QString();
00056 }
00057
00058 bool XMLParseBase::parseBool(const QString &text)
00059 {
00060 QString s = text.toLower();
00061 return (s == "yes" || s == "true" || s.toInt());
00062 }
00063
00064 bool XMLParseBase::parseBool(QDomElement &element)
00065 {
00066 return parseBool(getFirstText(element));
00067 }
00068
00069 MythPoint XMLParseBase::parsePoint(const QString &text, bool normalize)
00070 {
00071 MythPoint retval;
00072 QStringList values = text.split(',', QString::SkipEmptyParts);
00073 if (values.size() == 2)
00074 retval = MythPoint(values[0], values[1]);
00075
00076 if (normalize)
00077 retval.NormPoint();
00078
00079 return retval;
00080 }
00081
00082 MythPoint XMLParseBase::parsePoint(QDomElement &element, bool normalize)
00083 {
00084 return parsePoint(getFirstText(element), normalize);
00085 }
00086
00087 QSize XMLParseBase::parseSize(const QString &text, bool normalize)
00088 {
00089 int x, y;
00090 QSize retval;
00091
00092 QStringList tmp = text.split(",");
00093 bool x_ok = false, y_ok = false;
00094 if (tmp.size() >= 2)
00095 {
00096 x = tmp[0].toInt(&x_ok);
00097 y = tmp[1].toInt(&y_ok);
00098 }
00099
00100 if (x_ok && y_ok)
00101 {
00102 if (x == -1 || y == -1)
00103 {
00104 QRect uiSize = GetMythMainWindow()->GetUIScreenRect();
00105 x = uiSize.width();
00106 y = uiSize.height();
00107 normalize = false;
00108 }
00109
00110 retval = QSize(x, y);
00111 }
00112
00113 if (normalize)
00114 retval = GetMythMainWindow()->NormSize(retval);
00115
00116 return retval;
00117 }
00118
00119 QSize XMLParseBase::parseSize(QDomElement &element, bool normalize)
00120 {
00121 return parseSize(getFirstText(element), normalize);
00122 }
00123
00124 MythRect XMLParseBase::parseRect(const QString &text, bool normalize)
00125 {
00126 MythRect retval;
00127 QStringList values = text.split(',', QString::SkipEmptyParts);
00128 if (values.size() == 4)
00129 retval = MythRect(values[0], values[1], values[2], values[3]);
00130
00131 if (normalize)
00132 retval.NormRect();
00133
00134 return retval;
00135 }
00136
00137 MythRect XMLParseBase::parseRect(QDomElement &element, bool normalize)
00138 {
00139 return parseRect(getFirstText(element), normalize);
00140 }
00141
00142 int XMLParseBase::parseAlignment(const QString &text)
00143 {
00144 int alignment = Qt::AlignLeft | Qt::AlignTop;
00145
00146 QStringList values = text.split(',');
00147
00148 QStringList::Iterator it;
00149 for ( it = values.begin(); it != values.end(); ++it )
00150 {
00151
00152 QString align = *it;
00153 align = align.trimmed();
00154 align = align.toLower();
00155
00156 if (align == "center" || align == "allcenter")
00157 {
00158 alignment &= ~(Qt::AlignHorizontal_Mask | Qt::AlignVertical_Mask);
00159 alignment |= Qt::AlignCenter;
00160 break;
00161 }
00162 else if (align == "justify")
00163 {
00164 alignment &= ~Qt::AlignHorizontal_Mask;
00165 alignment |= Qt::AlignJustify;
00166 }
00167 else if (align == "left")
00168 {
00169 alignment &= ~Qt::AlignHorizontal_Mask;
00170 alignment |= Qt::AlignLeft;
00171 }
00172 else if (align == "hcenter")
00173 {
00174 alignment &= ~Qt::AlignHorizontal_Mask;
00175 alignment |= Qt::AlignHCenter;
00176 }
00177 else if (align == "right")
00178 {
00179 alignment &= ~Qt::AlignHorizontal_Mask;
00180 alignment |= Qt::AlignRight;
00181 }
00182 else if (align == "top")
00183 {
00184 alignment &= ~Qt::AlignVertical_Mask;
00185 alignment |= Qt::AlignTop;
00186 }
00187 else if (align == "vcenter")
00188 {
00189 alignment &= ~Qt::AlignVertical_Mask;
00190 alignment |= Qt::AlignVCenter;
00191 }
00192 else if (align == "bottom")
00193 {
00194 alignment &= ~Qt::AlignVertical_Mask;
00195 alignment |= Qt::AlignBottom;
00196 }
00197 }
00198
00199 return alignment;
00200 }
00201
00202 int XMLParseBase::parseAlignment(QDomElement &element)
00203 {
00204 return parseAlignment(getFirstText(element));
00205 }
00206
00207 QBrush XMLParseBase::parseGradient(const QDomElement &element)
00208 {
00209 QBrush brush;
00210 QString gradientStart = element.attribute("start", "");
00211 QString gradientEnd = element.attribute("end", "");
00212 int gradientAlpha = element.attribute("alpha", "255").toInt();
00213 QString direction = element.attribute("direction", "vertical");
00214
00215 QGradientStops stops;
00216
00217 if (!gradientStart.isEmpty())
00218 {
00219 QColor startColor = QColor(gradientStart);
00220 startColor.setAlpha(gradientAlpha);
00221 QGradientStop stop(0.0, startColor);
00222 stops.append(stop);
00223 }
00224
00225 for (QDomNode child = element.firstChild(); !child.isNull();
00226 child = child.nextSibling())
00227 {
00228 QDomElement childElem = child.toElement();
00229 if (childElem.tagName() == "stop")
00230 {
00231 float position = childElem.attribute("position", "0").toFloat();
00232 QString color = childElem.attribute("color", "");
00233 int alpha = childElem.attribute("alpha", "-1").toInt();
00234 if (alpha < 0)
00235 alpha = gradientAlpha;
00236 QColor stopColor = QColor(color);
00237 stopColor.setAlpha(alpha);
00238 QGradientStop stop((position / 100), stopColor);
00239 stops.append(stop);
00240 }
00241 }
00242
00243 if (!gradientEnd.isEmpty())
00244 {
00245 QColor endColor = QColor(gradientEnd);
00246 endColor.setAlpha(gradientAlpha);
00247 QGradientStop stop(1.0, endColor);
00248 stops.append(stop);
00249 }
00250
00251 if (direction == "radial")
00252 {
00253 QRadialGradient gradient;
00254 gradient.setCoordinateMode(QGradient::ObjectBoundingMode);
00255 float x1 = 0.5, y1 = 0.5, radius = 0.5;
00256 gradient.setCenter(x1,y1);
00257 gradient.setFocalPoint(x1,y1);
00258 gradient.setRadius(radius);
00259 gradient.setStops(stops);
00260 brush = QBrush(gradient);
00261 }
00262 else
00263 {
00264 QLinearGradient gradient;
00265 gradient.setCoordinateMode(QGradient::ObjectBoundingMode);
00266 float x1 = 0.0, y1 = 0.0, x2 = 0.0, y2 = 0.0;
00267 if (direction == "vertical")
00268 {
00269 x1 = 0.5;
00270 x2 = 0.5;
00271 y1 = 0.0;
00272 y2 = 1.0;
00273 }
00274 else if (direction == "diagonal")
00275 {
00276 x1 = 0.0;
00277 x2 = 1.0;
00278 y1 = 0.0;
00279 y2 = 1.0;
00280 }
00281 else
00282 {
00283 x1 = 0.0;
00284 x2 = 1.0;
00285 y1 = 0.5;
00286 y2 = 0.5;
00287 }
00288
00289 gradient.setStart(x1, y1);
00290 gradient.setFinalStop(x2, y2);
00291 gradient.setStops(stops);
00292 brush = QBrush(gradient);
00293 }
00294
00295
00296 return brush;
00297 }
00298
00299 QString XMLParseBase::parseText(QDomElement &element)
00300 {
00301 QString text = getFirstText(element);
00302
00303
00304 text.replace("\\n", QString("<newline>"));
00305
00306
00307
00308 QStringList lines = text.split('\n');
00309 QStringList::iterator lineIt;
00310
00311 for (lineIt = lines.begin(); lineIt != lines.end(); ++lineIt)
00312 {
00313 (*lineIt) = (*lineIt).trimmed();
00314 }
00315
00316 text = lines.join(" ");
00317
00318 text.replace(QString("<newline>"), QString("\n"));
00319
00320 return text;
00321 }
00322
00323 static MythUIType *globalObjectStore = NULL;
00324 static QStringList loadedBaseFiles;
00325
00326 MythUIType *XMLParseBase::GetGlobalObjectStore(void)
00327 {
00328 if (!globalObjectStore)
00329 globalObjectStore = new MythUIType(NULL, "global store");
00330 return globalObjectStore;
00331 }
00332
00333 void XMLParseBase::ClearGlobalObjectStore(void)
00334 {
00335 delete globalObjectStore;
00336 globalObjectStore = NULL;
00337 GetGlobalObjectStore();
00338
00339
00340 loadedBaseFiles.clear();
00341 }
00342
00343 void XMLParseBase::ParseChildren(const QString &filename,
00344 QDomElement &element,
00345 MythUIType *parent,
00346 bool showWarnings)
00347 {
00348 if (!parent)
00349 {
00350 LOG(VB_GENERAL, LOG_ERR, LOC + "Parent is NULL");
00351 return;
00352 }
00353
00354 QMap<QString, QString> dependsMap;
00355 for (QDomNode child = element.firstChild(); !child.isNull();
00356 child = child.nextSibling())
00357 {
00358 QDomElement info = child.toElement();
00359 if (!info.isNull())
00360 {
00361 QString type = info.tagName();
00362 if (parent->ParseElement(filename, info, showWarnings))
00363 {
00364 }
00365 else if (type == "font" || type == "fontdef")
00366 {
00367 bool global = (GetGlobalObjectStore() == parent);
00368 MythFontProperties *font = MythFontProperties::ParseFromXml(
00369 filename, info, parent, global, showWarnings);
00370
00371 if (!global && font)
00372 {
00373 QString name = info.attribute("name");
00374 parent->AddFont(name, font);
00375 }
00376
00377 delete font;
00378 }
00379 else if (type == "imagetype" ||
00380 type == "textarea" ||
00381 type == "group" ||
00382 type == "textedit" ||
00383 type == "button" ||
00384 type == "buttonlist" ||
00385 type == "buttonlist2" ||
00386 type == "buttontree" ||
00387 type == "spinbox" ||
00388 type == "checkbox" ||
00389 type == "statetype" ||
00390 type == "clock" ||
00391 type == "progressbar" ||
00392 type == "scrollbar" ||
00393 type == "webbrowser" ||
00394 type == "guidegrid" ||
00395 type == "shape" ||
00396 type == "editbar" ||
00397 type == "video")
00398 {
00399 ParseUIType(filename, info, type, parent, NULL, showWarnings, dependsMap);
00400 }
00401 else
00402 {
00403 VERBOSE_XML(VB_GENERAL, LOG_ERR, filename, info,
00404 "Unknown widget type");
00405 }
00406 }
00407 }
00408 parent->SetDependsMap(dependsMap);
00409 parent->ConnectDependants(true);
00410 parent->Finalize();
00411 }
00412
00413 MythUIType *XMLParseBase::ParseUIType(
00414 const QString &filename,
00415 QDomElement &element, const QString &type,
00416 MythUIType *parent,
00417 MythScreenType *screen,
00418 bool showWarnings,
00419 QMap<QString, QString> &parentDependsMap)
00420 {
00421 QString name = element.attribute("name", "");
00422 if (name.isEmpty())
00423 {
00424 VERBOSE_XML(VB_GENERAL, LOG_ERR, filename, element,
00425 "This element requires a name");
00426 return NULL;
00427 }
00428
00429 MythUIType *olduitype = NULL;
00430
00431
00432 if (parent && parent->GetChild(name))
00433 {
00434
00435
00436 if (parent == GetGlobalObjectStore())
00437 return NULL;
00438
00439
00440 olduitype = parent->GetChild(name);
00441 }
00442
00443 MythUIType *uitype = NULL;
00444 MythUIType *base = NULL;
00445
00446 QString inherits = element.attribute("from", "");
00447 if (!inherits.isEmpty())
00448 {
00449 if (parent)
00450 base = parent->GetChild(inherits);
00451
00452
00453 if (screen && !base)
00454 base = screen->GetChild(inherits);
00455
00456 if (!base)
00457 base = GetGlobalObjectStore()->GetChild(inherits);
00458
00459 if (!base)
00460 {
00461 VERBOSE_XML(VB_GENERAL, LOG_ERR, filename, element,
00462 QString("Couldn't find object '%1' to inherit '%2' from")
00463 .arg(inherits).arg(name));
00464 return NULL;
00465 }
00466 }
00467
00468 if (type == "imagetype")
00469 uitype = new MythUIImage(parent, name);
00470 else if (type == "textarea")
00471 uitype = new MythUIText(parent, name);
00472 else if (type == "group")
00473 uitype = new MythUIGroup(parent, name);
00474 else if (type == "textedit")
00475 uitype = new MythUITextEdit(parent, name);
00476 else if (type == "button")
00477 uitype = new MythUIButton(parent, name);
00478 else if (type == "buttonlist2" || type == "buttonlist")
00479 uitype = new MythUIButtonList(parent, name);
00480 else if (type == "buttontree")
00481 uitype = new MythUIButtonTree(parent, name);
00482 else if (type == "spinbox")
00483 uitype = new MythUISpinBox(parent, name);
00484 else if (type == "checkbox")
00485 uitype = new MythUICheckBox(parent, name);
00486 else if (type == "statetype")
00487 uitype = new MythUIStateType(parent, name);
00488 else if (type == "clock")
00489 uitype = new MythUIClock(parent, name);
00490 else if (type == "progressbar")
00491 uitype = new MythUIProgressBar(parent, name);
00492 else if (type == "scrollbar")
00493 uitype = new MythUIScrollBar(parent, name);
00494 else if (type == "webbrowser")
00495 uitype = new MythUIWebBrowser(parent, name);
00496 else if (type == "guidegrid")
00497 uitype = new MythUIGuideGrid(parent, name);
00498 else if (type == "shape")
00499 uitype = new MythUIShape(parent, name);
00500 else if (type == "editbar")
00501 uitype = new MythUIEditBar(parent, name);
00502 else if (type == "video")
00503 uitype = new MythUIVideo(parent, name);
00504 else if (type == "window" && parent == GetGlobalObjectStore())
00505 uitype = new MythScreenType(parent, name);
00506 else
00507 {
00508 VERBOSE_XML(VB_GENERAL, LOG_ERR, filename, element,
00509 "Unknown widget type.");
00510 return NULL;
00511 }
00512
00513 if (!uitype)
00514 {
00515 VERBOSE_XML(VB_GENERAL, LOG_ERR, filename, element,
00516 "Failed to instantiate widget type.");
00517 return NULL;
00518 }
00519
00520 if (olduitype)
00521 {
00522 if (typeid(*olduitype) != typeid(*uitype))
00523 {
00524 VERBOSE_XML(VB_GENERAL, LOG_ERR, filename, element,
00525 QString("Duplicate name: '%1' in parent '%2'")
00526 .arg(name).arg(parent->objectName()));
00527 parent->DeleteChild(olduitype);
00528 }
00529 else
00530 {
00531 parent->DeleteChild(uitype);
00532 uitype = olduitype;
00533 }
00534 }
00535
00536 if (base)
00537 {
00538 if (typeid(*base) != typeid(*uitype))
00539 {
00540 VERBOSE_XML(VB_GENERAL, LOG_ERR, filename, element,
00541 QString("Type of new widget '%1' doesn't match old '%2'")
00542 .arg(name).arg(inherits));
00543 parent->DeleteChild(uitype);
00544 return NULL;
00545 }
00546 else
00547 uitype->CopyFrom(base);
00548
00549 }
00550
00551 QString dependee = element.attribute("depends", "");
00552 if (!dependee.isEmpty())
00553 parentDependsMap.insert(name, dependee);
00554
00555 QFileInfo fi(filename);
00556 uitype->SetXMLLocation(fi.fileName(), element.lineNumber());
00557
00558
00559
00560 QMap<QString, QString> dependsMap = uitype->GetDependsMap();
00561 for (QDomNode child = element.firstChild(); !child.isNull();
00562 child = child.nextSibling())
00563 {
00564 QDomElement info = child.toElement();
00565 if (!info.isNull())
00566 {
00567 if (uitype->ParseElement(filename, info, showWarnings))
00568 {
00569 }
00570 else if (info.tagName() == "font" || info.tagName() == "fontdef")
00571 {
00572 bool global = (GetGlobalObjectStore() == parent);
00573 MythFontProperties *font = MythFontProperties::ParseFromXml(
00574 filename, info, parent, global, showWarnings);
00575
00576 if (!global && font)
00577 {
00578 QString name = info.attribute("name");
00579 uitype->AddFont(name, font);
00580 }
00581
00582 delete font;
00583 }
00584 else if (info.tagName() == "imagetype" ||
00585 info.tagName() == "textarea" ||
00586 info.tagName() == "group" ||
00587 info.tagName() == "textedit" ||
00588 info.tagName() == "button" ||
00589 info.tagName() == "buttonlist" ||
00590 info.tagName() == "buttonlist2" ||
00591 info.tagName() == "buttontree" ||
00592 info.tagName() == "spinbox" ||
00593 info.tagName() == "checkbox" ||
00594 info.tagName() == "statetype" ||
00595 info.tagName() == "clock" ||
00596 info.tagName() == "progressbar" ||
00597 info.tagName() == "scrollbar" ||
00598 info.tagName() == "webbrowser" ||
00599 info.tagName() == "guidegrid" ||
00600 info.tagName() == "shape" ||
00601 info.tagName() == "editbar" ||
00602 info.tagName() == "video")
00603 {
00604 ParseUIType(filename, info, info.tagName(),
00605 uitype, screen, showWarnings, dependsMap);
00606 }
00607 else
00608 {
00609 VERBOSE_XML(VB_GENERAL, LOG_ERR, filename, info,
00610 "Unknown widget type.");
00611 }
00612 }
00613 }
00614 uitype->SetDependsMap(dependsMap);
00615
00616 uitype->Finalize();
00617 return uitype;
00618 }
00619
00620 bool XMLParseBase::WindowExists(const QString &xmlfile,
00621 const QString &windowname)
00622 {
00623 const QStringList searchpath = GetMythUI()->GetThemeSearchPath();
00624 QStringList::const_iterator it = searchpath.begin();
00625 for (; it != searchpath.end(); ++it)
00626 {
00627 QString themefile = *it + xmlfile;
00628 QFile f(themefile);
00629
00630 if (!f.open(QIODevice::ReadOnly))
00631 continue;
00632
00633 QDomDocument doc;
00634 QString errorMsg;
00635 int errorLine = 0;
00636 int errorColumn = 0;
00637
00638 if (!doc.setContent(&f, false, &errorMsg, &errorLine, &errorColumn))
00639 {
00640 LOG(VB_GENERAL, LOG_ERR, LOC +
00641 QString("Location: '%1' @ %2 column: %3"
00642 "\n\t\t\tError: %4")
00643 .arg(qPrintable(themefile)).arg(errorLine).arg(errorColumn)
00644 .arg(qPrintable(errorMsg)));
00645 f.close();
00646 continue;
00647 }
00648
00649 f.close();
00650
00651 QDomElement docElem = doc.documentElement();
00652 QDomNode n = docElem.firstChild();
00653 while (!n.isNull())
00654 {
00655 QDomElement e = n.toElement();
00656 if (!e.isNull())
00657 {
00658 if (e.tagName() == "window")
00659 {
00660 QString name = e.attribute("name", "");
00661 if (name == windowname)
00662 return true;
00663 }
00664 }
00665 n = n.nextSibling();
00666 }
00667 }
00668
00669 return false;
00670 }
00671
00672 bool XMLParseBase::LoadWindowFromXML(const QString &xmlfile,
00673 const QString &windowname,
00674 MythUIType *parent)
00675 {
00676 bool onlyLoadWindows = true;
00677 bool showWarnings = true;
00678
00679 const QStringList searchpath = GetMythUI()->GetThemeSearchPath();
00680 QStringList::const_iterator it = searchpath.begin();
00681 for (; it != searchpath.end(); ++it)
00682 {
00683 QString themefile = *it + xmlfile;
00684 LOG(VB_GUI, LOG_INFO, LOC + QString("Loading window %1 from %2").arg(windowname).arg(themefile));
00685 if (doLoad(windowname, parent, themefile,
00686 onlyLoadWindows, showWarnings))
00687 {
00688 return true;
00689 }
00690 else
00691 {
00692 LOG(VB_FILE, LOG_ERR, LOC + "No theme file " + themefile);
00693 }
00694 }
00695
00696 LOG(VB_GENERAL, LOG_ERR, LOC +
00697 QString("Unable to load window '%1' from '%2'")
00698 .arg(windowname).arg(xmlfile));
00699
00700 return false;
00701 }
00702
00703 bool XMLParseBase::doLoad(const QString &windowname,
00704 MythUIType *parent,
00705 const QString &filename,
00706 bool onlywindows,
00707 bool showWarnings)
00708 {
00709 QDomDocument doc;
00710 QFile f(filename);
00711
00712 if (!f.open(QIODevice::ReadOnly))
00713 return false;
00714
00715 QString errorMsg;
00716 int errorLine = 0;
00717 int errorColumn = 0;
00718
00719 if (!doc.setContent(&f, false, &errorMsg, &errorLine, &errorColumn))
00720 {
00721 LOG(VB_GENERAL, LOG_ERR, LOC +
00722 QString("Location: '%1' @ %2 column: %3"
00723 "\n\t\t\tError: %4")
00724 .arg(qPrintable(filename)).arg(errorLine).arg(errorColumn)
00725 .arg(qPrintable(errorMsg)));
00726 f.close();
00727 return false;
00728 }
00729
00730 f.close();
00731
00732 QDomElement docElem = doc.documentElement();
00733 QDomNode n = docElem.firstChild();
00734 while (!n.isNull())
00735 {
00736 QDomElement e = n.toElement();
00737 if (!e.isNull())
00738 {
00739 if (e.tagName() == "include")
00740 {
00741 QString include = getFirstText(e);
00742
00743 if (!include.isEmpty())
00744 LoadBaseTheme(include);
00745 }
00746
00747 if (onlywindows && e.tagName() == "window")
00748 {
00749 QString name = e.attribute("name", "");
00750 QString include = e.attribute("include", "");
00751 if (name.isEmpty())
00752 {
00753 VERBOSE_XML(VB_GENERAL, LOG_ERR, filename, e,
00754 "Window needs a name");
00755 return false;
00756 }
00757
00758 if (!include.isEmpty())
00759 LoadBaseTheme(include);
00760
00761 if (name == windowname)
00762 {
00763 ParseChildren(filename, e, parent, showWarnings);
00764 return true;
00765 }
00766 }
00767
00768 if (!onlywindows)
00769 {
00770 QString type = e.tagName();
00771 if (type == "font" || type == "fontdef")
00772 {
00773 bool global = (GetGlobalObjectStore() == parent);
00774 MythFontProperties *font = MythFontProperties::ParseFromXml(
00775 filename, e, parent, global, showWarnings);
00776
00777 if (!global && font)
00778 {
00779 QString name = e.attribute("name");
00780 parent->AddFont(name, font);
00781 }
00782 delete font;
00783 }
00784 else if (type == "imagetype" ||
00785 type == "textarea" ||
00786 type == "group" ||
00787 type == "textedit" ||
00788 type == "button" ||
00789 type == "buttonlist" ||
00790 type == "buttonlist2" ||
00791 type == "buttontree" ||
00792 type == "spinbox" ||
00793 type == "checkbox" ||
00794 type == "statetype" ||
00795 type == "window" ||
00796 type == "clock" ||
00797 type == "progressbar" ||
00798 type == "scrollbar" ||
00799 type == "webbrowser" ||
00800 type == "guidegrid" ||
00801 type == "shape" ||
00802 type == "editbar" ||
00803 type == "video")
00804 {
00805
00806
00807
00808 QMap<QString, QString> dependsMap;
00809 MythUIType *uitype = NULL;
00810 uitype = ParseUIType(filename, e, type, parent,
00811 NULL, showWarnings, dependsMap);
00812 if (uitype)
00813 uitype->ConnectDependants(true);
00814 }
00815 else
00816 {
00817 VERBOSE_XML(VB_GENERAL, LOG_ERR, filename, e,
00818 "Unknown widget type");
00819 }
00820 }
00821 }
00822 n = n.nextSibling();
00823 }
00824 if (onlywindows)
00825 return false;
00826 return true;
00827 }
00828
00829 bool XMLParseBase::LoadBaseTheme(void)
00830 {
00831 bool ok = false;
00832 bool loadOnlyWindows = false;
00833 bool showWarnings = true;
00834
00835 const QStringList searchpath = GetMythUI()->GetThemeSearchPath();
00836 QMap<QString, QString> dependsMap;
00837 QStringList::const_iterator it = searchpath.begin();
00838 for (; it != searchpath.end(); ++it)
00839 {
00840 QString themefile = *it + "base.xml";
00841 if (doLoad(QString(), GetGlobalObjectStore(), themefile,
00842 loadOnlyWindows, showWarnings))
00843 {
00844 LOG(VB_GUI, LOG_INFO, LOC +
00845 QString("Loaded base theme from '%1'").arg(themefile));
00846
00847
00848 showWarnings = false;
00849 ok = true;
00850 }
00851 else
00852 {
00853 LOG(VB_GUI | VB_FILE, LOG_WARNING, LOC +
00854 QString("No theme file '%1'").arg(themefile));
00855 }
00856 }
00857
00858 return ok;
00859 }
00860
00861 bool XMLParseBase::LoadBaseTheme(const QString &baseTheme)
00862 {
00863 LOG(VB_GUI, LOG_INFO, LOC +
00864 QString("Asked to load base file from '%1'").arg(baseTheme));
00865
00866 if (loadedBaseFiles.contains(baseTheme))
00867 {
00868 LOG(VB_GUI, LOG_INFO, LOC +
00869 QString("Base file already loaded '%1'").arg(baseTheme));
00870 return true;
00871 }
00872
00873 bool ok = false;
00874 bool loadOnlyWindows = false;
00875 bool showWarnings = true;
00876
00877 const QStringList searchpath = GetMythUI()->GetThemeSearchPath();
00878
00879 QStringList::const_iterator it = searchpath.begin();
00880 for (; it != searchpath.end(); ++it)
00881 {
00882 QString themefile = *it + baseTheme;
00883 if (doLoad(QString(), GetGlobalObjectStore(), themefile,
00884 loadOnlyWindows, showWarnings))
00885 {
00886 LOG(VB_GUI, LOG_INFO, LOC +
00887 QString("Loaded base theme from '%1'").arg(themefile));
00888
00889
00890 showWarnings = false;
00891 ok = true;
00892 }
00893 else
00894 {
00895 LOG(VB_GUI | VB_FILE, LOG_WARNING, LOC +
00896 QString("No theme file '%1'").arg(themefile));
00897 }
00898 }
00899
00900 if (ok)
00901 loadedBaseFiles.append(baseTheme);
00902
00903 return ok;
00904 }
00905
00906 bool XMLParseBase::CopyWindowFromBase(const QString &windowname,
00907 MythScreenType *win)
00908 {
00909 MythUIType *ui = GetGlobalObjectStore()->GetChild(windowname);
00910 if (!ui)
00911 {
00912 LOG(VB_GENERAL, LOG_ERR, LOC +
00913 QString("Unable to load window '%1' from base") .arg(windowname));
00914 return false;
00915 }
00916
00917 MythScreenType *st = dynamic_cast<MythScreenType *>(ui);
00918 if (!st)
00919 {
00920 LOG(VB_GENERAL, LOG_ERR, LOC +
00921 QString("UI Object '%1' is not a ScreenType") .arg(windowname));
00922 return false;
00923 }
00924
00925 win->CopyFrom(st);
00926 return true;
00927 }