|
MythTV
0.26-pre
|
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 }
1.7.6.1