MythTV  0.26-pre
xmlparsebase.cpp
Go to the documentation of this file.
00001 
00002 // Own header
00003 #include "xmlparsebase.h"
00004 
00005 // C++/C headers
00006 #include <typeinfo>
00007 
00008 // QT headers
00009 #include <QFile>
00010 #include <QDomDocument>
00011 #include <QString>
00012 #include <QBrush>
00013 #include <QLinearGradient>
00014 #include <QRadialGradient>
00015 
00016 // libmyth headers
00017 #include "mythlogging.h"
00018 
00019 // Mythui headers
00020 #include "mythmainwindow.h"
00021 #include "mythuihelper.h"
00022 
00023 /* ui type includes */
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 // Linear
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 // Horizontal
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     // Escape xml-escaped newline
00304     text.replace("\\n", QString("<newline>"));
00305 
00306     // Remove newline whitespace added by
00307     // xml formatting
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     // clear any loaded base xml files which will force a reload the next time they are used
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     // check for name in immediate parent as siblings cannot share names
00432     if (parent && parent->GetChild(name))
00433     {
00434         // if we're the global object store, assume it's just a theme overriding
00435         // the defaults..
00436         if (parent == GetGlobalObjectStore())
00437             return NULL;
00438 
00439         // Reuse the existing child and reparse
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         // might remove this
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     // If this was copied from another uitype then it already has a depends
00559     // map so we want to append to that one
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                     // We don't want widgets in base.xml
00807                     // depending on each other so ignore dependsMap
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             // Don't complain about duplicate definitions after first
00847             // successful load (set showWarnings to false).
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             // Don't complain about duplicate definitions after first
00889             // successful load (set showWarnings to false).
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends