QString XMLParseBase::parseText(QDomElement &element) { QString text = getFirstText(element); // Escape xml-escaped newline text.replace("\\n", QString("<newline>")); // Remove newline whitespace added by // xml formatting QStringList lines = text.split('\n'); QStringList::iterator lineIt; for (lineIt = lines.begin(); lineIt != lines.end(); ++lineIt) { (*lineIt) = (*lineIt).trimmed(); } text = lines.join(" "); text.replace(QString("<newline>"), QString("\n")); return text; }
bool MythUITextEdit::ParseElement( const QString &filename, QDomElement &element, bool showWarnings) { bool parsed = true; if (element.tagName() == "area") { SetArea(parseRect(element)); } else if (element.tagName() == "keyboardposition") { QString pos = getFirstText(element); if (pos == "aboveedit") m_keyboardPosition = VK_POSABOVEEDIT; else if (pos == "belowedit") m_keyboardPosition = VK_POSBELOWEDIT; else if (pos == "screentop") m_keyboardPosition = VK_POSTOPDIALOG; else if (pos == "screenbottom") m_keyboardPosition = VK_POSBOTTOMDIALOG; else if (pos == "screencenter") m_keyboardPosition = VK_POSCENTERDIALOG; else { VERBOSE_XML(VB_GENERAL, LOG_ERR, filename, element, QString("Unknown popup position '%1'").arg(pos)); m_keyboardPosition = VK_POSBELOWEDIT; } } else { return MythUIType::ParseElement(filename, element, showWarnings); } return parsed; }
bool XMLParseBase::parseBool(QDomElement &element) { return parseBool(getFirstText(element)); }
bool XMLParseBase::doLoad(const QString &windowname, MythUIType *parent, const QString &filename, bool onlywindows, bool showWarnings) { QDomDocument doc; QFile f(filename); if (!f.open(QIODevice::ReadOnly)) return false; QString errorMsg; int errorLine = 0; int errorColumn = 0; if (!doc.setContent(&f, false, &errorMsg, &errorLine, &errorColumn)) { VERBOSE(VB_IMPORTANT, LOC_ERR + QString("Location: '%1' @ %2 column: %3" "\n\t\t\tError: %4") .arg(qPrintable(filename)).arg(errorLine).arg(errorColumn) .arg(qPrintable(errorMsg))); f.close(); return false; } f.close(); QDomElement docElem = doc.documentElement(); QDomNode n = docElem.firstChild(); while (!n.isNull()) { QDomElement e = n.toElement(); if (!e.isNull()) { if (e.tagName() == "include") { QString include = getFirstText(e); if (!include.isEmpty()) LoadBaseTheme(include); } if (onlywindows && e.tagName() == "window") { QString name = e.attribute("name", ""); if (name.isEmpty()) { VERBOSE_XML(VB_IMPORTANT, filename, e, LOC_ERR + "Window needs a name"); return false; } if (name == windowname) { ParseChildren(filename, e, parent, showWarnings); return true; } } if (!onlywindows) { QString type = e.tagName(); if (type == "font" || type == "fontdef") { bool global = (GetGlobalObjectStore() == parent); MythFontProperties *font = MythFontProperties::ParseFromXml( filename, e, parent, global, showWarnings); if (!global && font) { QString name = e.attribute("name"); parent->AddFont(name, font); } delete font; } else if (type == "imagetype" || type == "textarea" || type == "group" || type == "textedit" || type == "button" || type == "buttonlist" || type == "buttonlist2" || type == "buttontree" || type == "spinbox" || type == "checkbox" || type == "statetype" || type == "window" || type == "clock" || type == "progressbar" || type == "webbrowser" || type == "guidegrid" || type == "shape" || type == "editbar" || type == "video") { ParseUIType(filename, e, type, parent, NULL, showWarnings); } else { VERBOSE_XML(VB_IMPORTANT, filename, e, LOC_ERR + "Unknown widget type"); } } } n = n.nextSibling(); } if (onlywindows) return false; return true; }
int XMLParseBase::parseAlignment(QDomElement &element) { return parseAlignment(getFirstText(element)); }
QSize XMLParseBase::parseSize(QDomElement &element, bool normalize) { return parseSize(getFirstText(element), normalize); }
ProgInfo *XMLTVParser::parseProgram( QDomElement &element, int localTimezoneOffset) { QString uniqueid, seriesid, season, episode; int dd_progid_done = 0; ProgInfo *pginfo = new ProgInfo; pginfo->previouslyshown = false; pginfo->subtitletype = pginfo->videoproperties = pginfo->audioproperties = 0; pginfo->subtitle = pginfo->title = pginfo->desc = pginfo->category = pginfo->content = pginfo->catType = pginfo->syndicatedepisodenumber = pginfo->partnumber = pginfo->parttotal = pginfo->showtype = pginfo->colorcode = pginfo->stars = ""; pginfo->originalairdate = "0000-00-00"; QString text = element.attribute("start", ""); fromXMLTVDate(text, pginfo->start, localTimezoneOffset); pginfo->startts = text; text = element.attribute("stop", ""); fromXMLTVDate(text, pginfo->end, localTimezoneOffset); pginfo->endts = text; text = element.attribute("channel", ""); QStringList split = QStringList::split(" ", text); pginfo->channel = split[0]; text = element.attribute("clumpidx", ""); if (!text.isEmpty()) { split = QStringList::split("/", text); pginfo->clumpidx = split[0]; pginfo->clumpmax = split[1]; } for (QDomNode child = element.firstChild(); !child.isNull(); child = child.nextSibling()) { QDomElement info = child.toElement(); if (!info.isNull()) { if (info.tagName() == "title") { if (isJapan) { if (info.attribute("lang") == "ja_JP") { pginfo->title = getFirstText(info); } else if (info.attribute("lang") == "ja_JP@kana") { pginfo->title_pronounce = getFirstText(info); } } else if (pginfo->title == "") { pginfo->title = getFirstText(info); } } else if (info.tagName() == "sub-title" && pginfo->subtitle == "") { pginfo->subtitle = getFirstText(info); } else if (info.tagName() == "content") { pginfo->content = getFirstText(info); } else if (info.tagName() == "desc" && pginfo->desc == "") { pginfo->desc = getFirstText(info); } else if (info.tagName() == "category") { const QString cat = getFirstText(info); const QString lcat = cat.lower(); if (lcat == "movie" || lcat == "series" || lcat == "sports" || lcat == "tvshow") { if (pginfo->catType.isEmpty()) pginfo->catType = lcat; } else if (pginfo->category.isEmpty()) { pginfo->category = cat; } if (lcat == "film") { // Hack for tv_grab_uk_rt pginfo->catType = "movie"; } } else if (info.tagName() == "date" && pginfo->airdate == "") { // Movie production year QString date = getFirstText(info); pginfo->airdate = date.left(4); } else if (info.tagName() == "star-rating") { QDomNodeList values = info.elementsByTagName("value"); QDomElement item; QString stars, num, den; float avg = 0.0; // not sure why the XML suggests multiple ratings, // but the following will average them anyway. for (unsigned int i = 0; i < values.length(); i++) { item = values.item(i).toElement(); if (item.isNull()) continue; stars = getFirstText(item); num = stars.section('/', 0, 0); den = stars.section('/', 1, 1); if (0.0 >= den.toFloat()) continue; avg *= i/(i+1); avg += (num.toFloat()/den.toFloat()) / (i+1); } pginfo->stars.setNum(avg); } else if (info.tagName() == "rating") { // again, the structure of ratings seems poorly represented // in the XML. no idea what we'd do with multiple values. QDomNodeList values = info.elementsByTagName("value"); QDomElement item = values.item(0).toElement(); if (item.isNull()) continue; ProgRating rating; rating.system = info.attribute("system", ""); rating.rating = getFirstText(item); if ("" != rating.system) pginfo->ratings.append(rating); } else if (info.tagName() == "previously-shown") { pginfo->previouslyshown = true; QString prevdate = info.attribute("start"); pginfo->originalairdate = prevdate; } else if (info.tagName() == "credits") { parseCredits(info, pginfo); } else if (info.tagName() == "subtitles" && info.attribute("type") == "teletext") { pginfo->subtitletype |= SUB_NORMAL; } else if (info.tagName() == "subtitles" && info.attribute("type") == "onscreen") { pginfo->subtitletype |= SUB_ONSCREEN; } else if (info.tagName() == "subtitles" && info.attribute("type") == "deaf-signed") { pginfo->subtitletype |= SUB_SIGNED; } else if (info.tagName() == "audio") { parseAudio(info, pginfo); } else if (info.tagName() == "video") { parseVideo(info, pginfo); } else if (info.tagName() == "episode-num" && info.attribute("system") == "dd_progid") { QString episodenum(getFirstText(info)); // if this field includes a dot, strip it out int idx = episodenum.find('.'); if (idx != -1) episodenum.remove(idx, 1); pginfo->programid = episodenum; dd_progid_done = 1; } else if (info.tagName() == "episode-num" && info.attribute("system") == "xmltv_ns") { int tmp; QString episodenum(getFirstText(info)); episode = episodenum.section('.',1,1); episode = episode.section('/',0,0).stripWhiteSpace(); season = episodenum.section('.',0,0).stripWhiteSpace(); QString part(episodenum.section('.',2,2)); QString partnumber(part.section('/',0,0).stripWhiteSpace()); QString parttotal(part.section('/',1,1).stripWhiteSpace()); pginfo->catType = "series"; if (!episode.isEmpty()) { tmp = episode.toInt() + 1; episode = QString::number(tmp); pginfo->syndicatedepisodenumber = QString("E" + episode); } if (!season.isEmpty()) { tmp = season.toInt() + 1; season = QString::number(tmp); pginfo->syndicatedepisodenumber.append(QString("S" + season)); } if (!partnumber.isEmpty()) { tmp = partnumber.toInt() + 1; partnumber = QString::number(tmp); } if (partnumber != 0 && parttotal >= partnumber && !parttotal.isEmpty()) { pginfo->parttotal = parttotal; pginfo->partnumber = partnumber; } } else if (info.tagName() == "episode-num" && info.attribute("system") == "onscreen" && pginfo->subtitle.isEmpty()) { pginfo->catType = "series"; pginfo->subtitle = getFirstText(info); } } } if (pginfo->category.isEmpty() && !pginfo->catType.isEmpty()) pginfo->category = pginfo->catType; /* Hack for teveblad grabber to do something with the content tag*/ if (pginfo->content != "") { if (pginfo->category == "film") { pginfo->subtitle = pginfo->desc; pginfo->desc = pginfo->content; } else if (pginfo->desc != "") { pginfo->desc = pginfo->desc + " - " + pginfo->content; } else if (pginfo->desc == "") { pginfo->desc = pginfo->content; } } if (pginfo->airdate.isEmpty()) pginfo->airdate = QDate::currentDate().toString("yyyy"); /* Let's build ourself a programid */ QString programid; if (pginfo->catType == "movie") programid = "MV"; else if (pginfo->catType == "series") programid = "EP"; else if (pginfo->catType == "sports") programid = "SP"; else programid = "SH"; if (!uniqueid.isEmpty()) // we already have a unique id ready for use programid.append(uniqueid); else { if (seriesid.isEmpty()) //need to hash ourself a seriesid from the title { seriesid = QString::number(ELFHash(pginfo->title)); } pginfo->seriesid = seriesid; programid.append(seriesid); if (!episode.isEmpty() && !season.isEmpty()) { programid.append(episode); programid.append(season); if (!pginfo->partnumber.isEmpty() && !pginfo->parttotal.isEmpty()) { programid.append(pginfo->partnumber); programid.append(pginfo->parttotal); } } else { /* No ep/season info? Well then remove the programid and rely on normal dupchecking methods instead. */ if (pginfo->catType != "movie") programid = ""; } } if (dd_progid_done == 0) pginfo->programid = programid; return pginfo; }
void ImportFile::getRecordingList(void) { while (!m_recordingList.isEmpty()) delete m_recordingList.takeFirst(); QString xmlFile = getTempDirectory() + "work/recordings.xml"; QFileInfo fi(xmlFile); if (!fi.exists() || QDateTime::currentDateTime() > fi.lastModified().addSecs(3600)) { // run the script to get list of recordings from the External Box QString command = gCoreContext->GetSetting("MythArchiveGetRecordingList"); command.replace("%XMLFILE%", xmlFile); QScopedPointer<MythSystem> cmd(MythSystem::Create(command)); cmd->Wait(0); if (cmd.data()->GetExitCode() != GENERIC_EXIT_OK) { LOG(VB_GENERAL, LOG_ERR, QString("ERROR - Failed to get recording list")); LOG(VB_GENERAL, LOG_ERR, QString("Command exited with result: %1").arg(cmd.data()->GetExitCode())); LOG(VB_GENERAL, LOG_ERR, QString("Command was: %1").arg(command)); //return; } } // load the xml file contains the recordings list details QDomDocument doc("recordings"); QFile file(xmlFile); if (!file.open(QIODevice::ReadOnly)) { LOG(VB_GENERAL, LOG_ERR, "Could not open recordings file: " + xmlFile); return; } if (!doc.setContent(&file)) { LOG(VB_GENERAL, LOG_ERR, "Could not load recordings file: " + xmlFile); file.close(); return; } file.close(); QDomNodeList recordingNodes = doc.elementsByTagName("recording"); for (int x = 0; x < recordingNodes.count(); x++) { ImportItem *importItem = new ImportItem; QDomNode recordingNode = recordingNodes.item(x); QDomElement recordingElement = recordingNode.toElement(); for (int y = 0; y < recordingElement.childNodes().count(); y++) { QDomNode node = recordingElement.childNodes().at(y); QDomElement e = node.toElement(); if (e.nodeName() == "no") importItem->id = getFirstText(e).toInt(); else if (e.nodeName() == "title") importItem->title = decodeXML(getFirstText(e)); else if (e.nodeName() == "season") importItem->season = decodeXML(getFirstText(e)).toUInt(); else if (e.nodeName() == "episode") importItem->episode = decodeXML(getFirstText(e)).toUInt(); else if (e.nodeName() == "channelno") importItem->chanNo = decodeXML(getFirstText(e)); else if (e.nodeName() == "channelsign") importItem->chanSign = decodeXML(getFirstText(e)); else if (e.nodeName() == "channelname") importItem->chanName = decodeXML(getFirstText(e)); else if (e.nodeName() == "starttime") importItem->startTime = MythDate::fromString(getFirstText(e)); else if (e.nodeName() == "duration") importItem->duration = decodeDuration(getFirstText(e)); else if (e.nodeName() == "actualduration") importItem->actualDuration = decodeDuration(getFirstText(e)); else if (e.nodeName() == "description") importItem->description = decodeXML(getFirstText(e)) + QString("\n\nRecorded from %1 on %2 at %3.") .arg(importItem->chanName).arg(importItem->startTime.toString("dddd dd MMMM yyyy")) .arg(importItem->startTime.toString("hh:mm ap")); else if (e.nodeName() == "filesize") importItem->size = getFirstText(e).toInt(); else if (e.nodeName() == "filename") importItem->filename = getFirstText(e); else if (e.nodeName() == "category") importItem->category = getFirstText(e); } if (importItem->chanSign.isEmpty()) importItem->chanSign = importItem->chanName; if (importItem->category.isEmpty()) importItem->category = importItem->title; if (m_categories.indexOf(importItem->category) == -1) m_categories.append(importItem->category); // default to using the IPEncoder importItem->type = "IPEncoder"; m_recordingList.append(importItem); } }
/** * \copydoc MythUIType::ParseElement() */ bool MythUIImage::ParseElement( const QString &filename, QDomElement &element, bool showWarnings) { QWriteLocker updateLocker(&d->m_UpdateLock); if (element.tagName() == "filename") { m_imageProperties.isThemeImage = true; // This is an image distributed with the them m_OrigFilename = m_imageProperties.filename = getFirstText(element); if (m_imageProperties.filename.endsWith('/')) { m_showingRandomImage = true; m_imageDirectory = m_imageProperties.filename; FindRandomImage(); } } else if (element.tagName() == "filepattern") { m_imageProperties.isThemeImage = true; // This is an image distributed with the theme m_OrigFilename = m_imageProperties.filename = getFirstText(element); QString tmp = element.attribute("low"); if (!tmp.isEmpty()) m_LowNum = tmp.toInt(); tmp = element.attribute("high"); if (!tmp.isEmpty()) m_HighNum = tmp.toInt(); tmp = element.attribute("cycle", "start"); if (tmp == "reverse") m_animationCycle = kCycleReverse; } else if (element.tagName() == "area") { SetArea(parseRect(element)); m_imageProperties.forceSize = m_Area.size(); } else if (element.tagName() == "preserveaspect") m_imageProperties.preserveAspect = parseBool(element); else if (element.tagName() == "crop") m_imageProperties.cropRect = parseRect(element); else if (element.tagName() == "delay") { QString value = getFirstText(element); if (value.contains(",")) { QVector<int> delays; QStringList tokens = value.split(","); QStringList::iterator it = tokens.begin(); for (; it != tokens.end(); ++it) { if ((*it).isEmpty()) { if (delays.size()) delays.append(delays[delays.size()-1]); else delays.append(0); // Default 0ms delay before first image } else { delays.append((*it).toInt()); } } if (delays.size()) { m_Delay = delays[0]; SetDelays(delays); } } else { m_Delay = value.toInt(); } } else if (element.tagName() == "reflection") { m_imageProperties.isReflected = true; QString tmp = element.attribute("axis"); if (!tmp.isEmpty()) { if (tmp.toLower() == "horizontal") m_imageProperties.reflectAxis = ReflectHorizontal; else m_imageProperties.reflectAxis = ReflectVertical; } tmp = element.attribute("shear"); if (!tmp.isEmpty()) m_imageProperties.reflectShear = tmp.toInt(); tmp = element.attribute("scale"); if (!tmp.isEmpty()) m_imageProperties.reflectScale = tmp.toInt(); tmp = element.attribute("length"); if (!tmp.isEmpty()) m_imageProperties.reflectLength = tmp.toInt(); tmp = element.attribute("spacing"); if (!tmp.isEmpty()) m_imageProperties.reflectSpacing = tmp.toInt(); } else if (element.tagName() == "mask") { QString maskfile = getFirstText(element); MythImage *newMaskImage = GetPainter()->GetFormatImage(); if (newMaskImage->Load(maskfile)) { float wmult; // Width multipler float hmult; // Height multipler GetMythUI()->GetScreenSettings(wmult, hmult); if (wmult != 1.0f || hmult != 1.0f) { int width = newMaskImage->size().width() * wmult; int height = newMaskImage->size().height() * hmult; newMaskImage->Resize(QSize(width, height)); } m_imageProperties.SetMaskImage(newMaskImage); } else m_imageProperties.SetMaskImage(NULL); newMaskImage->DecrRef(); } else if (element.tagName() == "grayscale" || element.tagName() == "greyscale") { m_imageProperties.isGreyscale = parseBool(element); } else { return MythUIType::ParseElement(filename, element, showWarnings); } m_NeedLoad = true; if (m_Parent && m_Parent->IsDeferredLoading(true)) m_NeedLoad = false; return true; }
MythFontProperties *MythFontProperties::ParseFromXml( const QString &filename, const QDomElement &element, MythUIType *parent, bool addToGlobal, bool showWarnings) { // Crappy, but cached. Move to GlobalFontMap? static bool show_available = true; bool fromBase = false; MythFontProperties *newFont = new MythFontProperties(); newFont->Freeze(); if (element.tagName() == "font") LOG(VB_GENERAL, LOG_WARNING, LOC + QString("File %1: Use of 'font' is deprecated in favour of " "'fontdef'") .arg(filename)); QString name = element.attribute("name", ""); if (name.isEmpty()) { VERBOSE_XML(VB_GENERAL, LOG_ERR, filename, element, "Font requires a name"); delete newFont; return NULL; } QString base = element.attribute("from", ""); if (!base.isEmpty()) { MythFontProperties *tmp = NULL; if (parent) tmp = parent->GetFont(base); if (!tmp) tmp = GetGlobalFontMap()->GetFont(base); if (!tmp) { VERBOSE_XML(VB_GENERAL, LOG_ERR, filename, element, QString("Specified base font '%1' does not exist.").arg(base)); delete newFont; return NULL; } *newFont = *tmp; fromBase = true; } int size, pixelsize; size = pixelsize = -1; QString face = element.attribute("face", ""); if (face.isEmpty()) { if (!fromBase) { VERBOSE_XML(VB_GENERAL, LOG_ERR, filename, element, "Font needs a face"); delete newFont; return NULL; } } else { newFont->m_face.setFamily(face); } if (addToGlobal && GetGlobalFontMap()->Contains(name)) { MythFontProperties *tmp = GetGlobalFontMap()->GetFont(name); if (showWarnings) { VERBOSE_XML(VB_GENERAL, LOG_WARNING, filename, element, QString("Attempting to define '%1'\n\t\t\t" "with face '%2', but it already " "exists with face '%3'") .arg(name).arg(QFontInfo(newFont->m_face).family()) .arg((tmp) ? QFontInfo(tmp->m_face).family() : "ERROR")); } delete newFont; return NULL; } QString hint = element.attribute("stylehint", ""); if (!hint.isEmpty()) { newFont->m_face.setStyleHint((QFont::StyleHint)hint.toInt()); } for (QDomNode child = element.firstChild(); !child.isNull(); child = child.nextSibling()) { QDomElement info = child.toElement(); if (!info.isNull()) { if (info.tagName() == "size") { size = getFirstText(info).toInt(); } else if (info.tagName() == "pixelsize") { pixelsize = getFirstText(info).toInt(); } else if (info.tagName() == "color") { newFont->m_brush = QBrush(QColor(getFirstText(info))); } else if (info.tagName() == "gradient") { newFont->m_brush = parseGradient(info); } else if (info.tagName() == "shadowcolor") { newFont->m_shadowColor = QColor(getFirstText(info)); } else if (info.tagName() == "shadowoffset") { newFont->m_hasShadow = true; newFont->m_shadowOffset = parsePoint(info, false); } else if (info.tagName() == "shadowalpha") { newFont->m_shadowAlpha = getFirstText(info).toInt(); } else if (info.tagName() == "outlinecolor") { newFont->m_outlineColor = QColor(getFirstText(info)); } else if (info.tagName() == "outlinesize") { newFont->m_hasOutline = true; newFont->m_outlineSize = getFirstText(info).toInt(); } else if (info.tagName() == "outlinealpha") { newFont->m_outlineAlpha = getFirstText(info).toInt(); } else if (info.tagName() == "italics") { newFont->m_face.setItalic(parseBool(info)); } else if (info.tagName() == "letterspacing") { newFont->m_face.setLetterSpacing(QFont::AbsoluteSpacing, getFirstText(info).toInt()); } else if (info.tagName() == "wordspacing") { newFont->m_face.setWordSpacing(getFirstText(info).toInt()); } else if (info.tagName() == "decoration") { QString dec = getFirstText(info).toLower(); QStringList values = dec.split(','); QStringList::Iterator it; for ( it = values.begin(); it != values.end(); ++it ) { if (*it == "underline") newFont->m_face.setUnderline(true); else if (*it == "overline") newFont->m_face.setOverline(true); else if (*it == "strikeout") newFont->m_face.setStrikeOut(true); } } else if (info.tagName() == "weight") { QString weight = getFirstText(info).toLower(); if (weight == "ultralight" || weight == "1") newFont->m_face.setWeight(1); else if (weight == "light" || weight == "2") newFont->m_face.setWeight(QFont::Light); else if (weight == "normal" || weight == "3") newFont->m_face.setWeight(QFont::Normal); else if (weight == "demibold" || weight == "4") newFont->m_face.setWeight(QFont::DemiBold); else if (weight == "bold" || weight == "5") newFont->m_face.setWeight(QFont::Bold); else if (weight == "black" || weight == "6") newFont->m_face.setWeight(QFont::Black); else if (weight == "ultrablack" || weight == "7") newFont->m_face.setWeight(99); else newFont->m_face.setWeight(QFont::Normal); } else if (info.tagName() == "stretch") { QString stretch = getFirstText(info).toLower(); if (stretch == "ultracondensed" || stretch == "1") newFont->m_stretch = QFont::UltraCondensed; else if (stretch == "extracondensed" || stretch == "2") newFont->m_stretch = QFont::ExtraCondensed; else if (stretch == "condensed" || stretch == "3") newFont->m_stretch = QFont::Condensed; else if (stretch == "semicondensed" || stretch == "4") newFont->m_stretch = QFont::SemiCondensed; else if (stretch == "unstretched" || stretch == "5") newFont->m_stretch = QFont::Unstretched; else if (stretch == "semiexpanded" || stretch == "6") newFont->m_stretch = QFont::SemiExpanded; else if (stretch == "expanded" || stretch == "7") newFont->m_stretch = QFont::Expanded; else if (stretch == "extraexpanded" || stretch == "8") newFont->m_stretch = QFont::ExtraExpanded; else if (stretch == "ultraexpanded" || stretch == "9") newFont->m_stretch = QFont::UltraExpanded; else newFont->m_stretch = QFont::Unstretched; newFont->m_face.setStretch(newFont->m_stretch); } else { VERBOSE_XML(VB_GENERAL, LOG_ERR, filename, info, QString("Unknown tag in font '%1'").arg(name)); delete newFont; return NULL; } } } if (size <= 0 && pixelsize <= 0 && !fromBase) { VERBOSE_XML(VB_GENERAL, LOG_ERR, filename, element, "Font size must be greater than 0."); delete newFont; return NULL; } else if (pixelsize > 0) { newFont->SetPixelSize(pixelsize); } else if (size > 0) { newFont->SetPointSize(size); } newFont->Unfreeze(); QFontInfo fi(newFont->m_face); if (newFont->m_face.family() != fi.family()) { VERBOSE_XML(VB_GENERAL, LOG_ERR, filename, element, QString("Failed to load '%1', got '%2' instead") .arg(newFont->m_face.family()).arg(fi.family())); if (show_available) { LOG(VB_GUI, LOG_DEBUG, "Available fonts:"); QFontDatabase database; foreach (const QString &family, database.families()) { QStringList family_styles; family_styles << family + "::"; foreach (const QString &style, database.styles(family)) { family_styles << style + ":"; QString sizes; bool tic = false; foreach (int points, database.smoothSizes(family, style)) { if (tic) sizes += ","; tic = true; sizes += QString::number(points); } sizes += "; "; family_styles << sizes.trimmed(); } LOG(VB_GUI, LOG_DEBUG, family_styles.join(" ")); } show_available = false; } }
bool ThemeInfo::parseThemeInfo() { QDomDocument doc; if ((m_themeurl.startsWith("http://")) || (m_themeurl.startsWith("https://")) || (m_themeurl.startsWith("ftp://"))) { QByteArray data; bool ok = GetMythDownloadManager()->download(m_themeurl + "/themeinfo.xml", &data); if (!ok) return false; if (!doc.setContent(data)) { VERBOSE(VB_IMPORTANT, LOC_ERR + QString("Unable to parse themeinfo.xml " "for %1").arg(m_themeurl)); return false; } } else { QFile f(m_themeurl + "/themeinfo.xml"); if (!f.open(QIODevice::ReadOnly)) { VERBOSE(VB_IMPORTANT, LOC_WARN + QString("Unable to open themeinfo.xml " "for %1").arg(f.fileName())); return false; } if (!doc.setContent(&f)) { VERBOSE(VB_IMPORTANT, LOC_ERR + QString("Unable to parse themeinfo.xml " "for %1").arg(f.fileName())); f.close(); return false; } f.close(); } QDomElement docElem = doc.documentElement(); for (QDomNode n = docElem.firstChild(); !n.isNull(); n = n.nextSibling()) { QDomElement e = n.toElement(); if (!e.isNull()) { if (e.tagName() == "name") { m_name = getFirstText(e); } else if (e.tagName() == "aspect") { m_aspect = getFirstText(e); } else if (e.tagName() == "baseres") { QString size = getFirstText(e); m_baseres = QSize(size.section('x', 0, 0).toInt(), size.section('x', 1, 1).toInt()); } else if (e.tagName() == "types") { for (QDomNode child = e.firstChild(); !child.isNull(); child = child.nextSibling()) { QDomElement ce = child.toElement(); if (!ce.isNull()) { if (ce.tagName() == "type") { QString type = getFirstText(ce); if (type == "UI") { m_type |= THEME_UI; } else if (type == "OSD") { m_type |= THEME_OSD; } else if (type == "Menu") { m_type |= THEME_MENU; } else { VERBOSE_XML(VB_IMPORTANT, m_theme.fileName(), ce, LOC_ERR + "Invalid theme type"); } } } } } else if (e.tagName() == "version") { for (QDomNode child = e.firstChild(); !child.isNull(); child = child.nextSibling()) { QDomElement ce = child.toElement(); if (!ce.isNull()) { if (ce.tagName() == "major") { m_majorver = getFirstText(ce).toInt(); } else if (ce.tagName() == "minor") { m_minorver = getFirstText(ce).toInt(); } } } } else if (e.tagName() == "author") { for (QDomNode child = e.firstChild(); !child.isNull(); child = child.nextSibling()) { QDomElement ce = child.toElement(); if (!ce.isNull()) { if (ce.tagName() == "name") { m_authorName = getFirstText(ce); } else if (ce.tagName() == "email") { m_authorEmail = getFirstText(ce); } } } } else if (e.tagName() == "detail") { for (QDomNode child = e.firstChild(); !child.isNull(); child = child.nextSibling()) { QDomElement ce = child.toElement(); if (!ce.isNull()) { if (ce.tagName() == "thumbnail") { if (ce.attribute("name") == "preview") { QString thumbnail = getFirstText(ce); m_previewpath = m_themeurl + '/' + thumbnail; } } else if (ce.tagName() == "description") { m_description = qApp->translate("ThemeUI", parseText(ce).toUtf8(), NULL, QCoreApplication::UnicodeUTF8); } else if (ce.tagName() == "errata") { m_errata = qApp->translate("ThemeUI", parseText(ce).toUtf8(), NULL, QCoreApplication::UnicodeUTF8); } else if (ce.tagName() == "downloadurl") { m_downloadurl = getFirstText(ce); } else if (ce.tagName() == "themesite") { m_themesite = getFirstText(ce); } } } } } } return true; }
bool MythUIText::ParseElement( const QString &filename, QDomElement &element, bool showWarnings) { if (element.tagName() == "area") { SetArea(parseRect(element)); m_OrigDisplayRect = m_Area; } // else if (element.tagName() == "altarea") // Unused, but maybe in future? // m_AltDisplayRect = parseRect(element); else if (element.tagName() == "font") { QString fontname = getFirstText(element); MythFontProperties *fp = GetFont(fontname); if (!fp) fp = GetGlobalFontMap()->GetFont(fontname); if (fp) { MythFontProperties font = *fp; int screenHeight = GetMythMainWindow()->GetUIScreenRect().height(); font.Rescale(screenHeight); int fontStretch = GetMythUI()->GetFontStretch(); font.AdjustStretch(fontStretch); QString state = element.attribute("state",""); if (!state.isEmpty()) { m_FontStates.insert(state, font); } else { m_FontStates.insert("default", font); *m_Font = m_FontStates["default"]; } } } else if (element.tagName() == "value") { if (element.attribute("lang","").isEmpty()) { m_Message = qApp->translate("ThemeUI", parseText(element).toUtf8(), NULL, QCoreApplication::UnicodeUTF8); } #if 0 else if (element.attribute("lang","").toLower() == gCoreContext->GetLanguageAndVariant()) #else else if (element.attribute("lang","").toLower() == "en_us") #endif { m_Message = parseText(element); } #if 0 else if (element.attribute("lang","").toLower() == gCoreContext->GetLanguage()) #else else if (element.attribute("lang","").toLower() == "en") #endif { m_Message = parseText(element); } m_DefaultMessage = m_Message; SetText(m_Message); } else if (element.tagName() == "template")
bool MythUIText::ParseElement( const QString &filename, QDomElement &element, bool showWarnings) { if (element.tagName() == "area") { SetArea(parseRect(element)); m_OrigDisplayRect = m_Area; } // else if (element.tagName() == "altarea") // Unused, but maybe in future? // m_AltDisplayRect = parseRect(element); else if (element.tagName() == "font") { QString fontname = getFirstText(element); MythFontProperties *fp = GetFont(fontname); if (!fp) fp = GetGlobalFontMap()->GetFont(fontname); if (fp) { MythFontProperties font = *fp; int screenHeight = GetMythMainWindow()->GetUIScreenRect().height(); font.Rescale(screenHeight); int fontStretch = GetMythUI()->GetFontStretch(); font.AdjustStretch(fontStretch); QString state = element.attribute("state",""); if (!state.isEmpty()) { m_FontStates.insert(state, font); } else { m_FontStates.insert("default", font); *m_Font = m_FontStates["default"]; } } } else if (element.tagName() == "value") { if (element.attribute("lang","").isEmpty()) { m_Message = qApp->translate("ThemeUI", parseText(element).toUtf8(), NULL, QCoreApplication::UnicodeUTF8); } else if (element.attribute("lang","").toLower() == gCoreContext->GetLanguageAndVariant()) { m_Message = parseText(element); } else if (element.attribute("lang","").toLower() == gCoreContext->GetLanguage()) { m_Message = parseText(element); } m_DefaultMessage = m_Message; SetText(m_Message); } else if (element.tagName() == "template") { m_TemplateText = parseText(element); } else if (element.tagName() == "cutdown") { SetCutDown(parseBool(element)); } else if (element.tagName() == "multiline") { SetMultiLine(parseBool(element)); } else if (element.tagName() == "align") { QString align = getFirstText(element).toLower(); SetJustification(parseAlignment(align)); } else if (element.tagName() == "colorcycle") { if (GetPainter()->SupportsAnimation()) { QString tmp = element.attribute("start"); if (!tmp.isEmpty()) m_startColor = QColor(tmp); tmp = element.attribute("end"); if (!tmp.isEmpty()) m_endColor = QColor(tmp); tmp = element.attribute("steps"); if (!tmp.isEmpty()) m_numSteps = tmp.toInt(); // initialize the rest of the stuff CycleColor(m_startColor, m_endColor, m_numSteps); } else m_colorCycling = false; m_colorCycling = parseBool(element.attribute("disable")); } else if (element.tagName() == "scroll") { if (GetPainter()->SupportsAnimation()) { QString tmp = element.attribute("direction"); if (!tmp.isEmpty()) { tmp = tmp.toLower(); if (tmp == "left") m_scrollDirection = ScrollLeft; else if (tmp == "right") m_scrollDirection = ScrollRight; else if (tmp == "up") m_scrollDirection = ScrollUp; else if (tmp == "down") m_scrollDirection = ScrollDown; } m_scrolling = true; } else m_scrolling = false; } else if (element.tagName() == "case") { QString stringCase = getFirstText(element).toLower(); if (stringCase == "lower") m_textCase = CaseLower; else if (stringCase == "upper") m_textCase = CaseUpper; else if (stringCase == "capitalisefirst") m_textCase = CaseCapitaliseFirst; else if (stringCase == "capitaliseall") m_textCase = CaseCapitaliseAll; else m_textCase = CaseNormal; FillCutMessage(); } else { return MythUIType::ParseElement(filename, element, showWarnings); } return true; }
MythPoint XMLParseBase::parsePoint(QDomElement &element, bool normalize) { return parsePoint(getFirstText(element), normalize); }
/** \brief Parses the element's tags and set the ThemeButton's type, * text, depends, and action, then adds the button. * * \param element DOM element describing features of the themeButton */ void MythThemedMenu::parseThemeButton(QDomElement &element) { QString type; QString text; QStringList action; QString alttext; QString description; QString password; bool addit = true; for (QDomNode child = element.firstChild(); !child.isNull(); child = child.nextSibling()) { QDomElement info = child.toElement(); if (!info.isNull()) { if (info.tagName() == "type") { type = getFirstText(info); } else if (info.tagName() == "text") { if (text.isEmpty() && info.attribute("lang","").isEmpty()) { text = qApp->translate("ThemeUI", parseText(info).toUtf8(), NULL, QCoreApplication::UnicodeUTF8); } else if (info.attribute("lang","").toLower() == gCoreContext->GetLanguageAndVariant()) { text = parseText(info); } else if (info.attribute("lang","").toLower() == gCoreContext->GetLanguage()) { text = parseText(info); } } else if (info.tagName() == "alttext") { if (alttext.isEmpty() && info.attribute("lang","").isEmpty()) { alttext = qApp->translate("ThemeUI", parseText(info).toUtf8(), NULL, QCoreApplication::UnicodeUTF8); } else if (info.attribute("lang","").toLower() == gCoreContext->GetLanguageAndVariant()) { alttext = parseText(info); } else if (info.attribute("lang","").toLower() == gCoreContext->GetLanguage()) { alttext = parseText(info); } } else if (info.tagName() == "action") { action += getFirstText(info); } else if (info.tagName() == "depends") { addit = findDepends(getFirstText(info)); } else if (info.tagName() == "dependssetting") { addit = GetMythDB()->GetNumSetting(getFirstText(info)); } else if (info.tagName() == "dependjumppoint") { addit = GetMythMainWindow()->DestinationExists( getFirstText(info)); } else if (info.tagName() == "dependswindow") { QString xmlFile = info.attribute("xmlfile", ""); QString windowName = getFirstText(info); if (xmlFile.isEmpty() || windowName.isEmpty()) addit = false; else addit = XMLParseBase::WindowExists(xmlFile, windowName); } else if (info.tagName() == "description") { if (description.isEmpty() && info.attribute("lang","").isEmpty()) { description = qApp->translate("ThemeUI", getFirstText(info).toUtf8(), NULL, QCoreApplication::UnicodeUTF8); } else if (info.attribute("lang","").toLower() == gCoreContext->GetLanguageAndVariant()) { description = getFirstText(info); } else if (info.attribute("lang","").toLower() == gCoreContext->GetLanguage()) { description = getFirstText(info); } } else if (info.tagName() == "password") { password = getFirstText(info); } else { LOG(VB_GENERAL, LOG_ERR, QString("MythThemedMenu: Unknown tag %1 in button") .arg(info.tagName())); } } } if (text.isEmpty()) { LOG(VB_GENERAL, LOG_ERR, "MythThemedMenu: Missing 'text' in button"); return; } if (action.empty()) { LOG(VB_GENERAL, LOG_ERR, "MythThemedMenu: Missing 'action' in button"); return; } if (addit) addButton(type, text, alttext, action, description, password); }
ProgInfo *XMLTVParser::parseProgram( QDomElement &element, int localTimezoneOffset) { QString uniqueid, season, episode; int dd_progid_done = 0; ProgInfo *pginfo = new ProgInfo(); QString text = element.attribute("start", ""); fromXMLTVDate(text, pginfo->starttime, localTimezoneOffset); pginfo->startts = text; text = element.attribute("stop", ""); fromXMLTVDate(text, pginfo->endtime, localTimezoneOffset); pginfo->endts = text; text = element.attribute("channel", ""); QStringList split = text.split(" "); pginfo->channel = split[0]; text = element.attribute("clumpidx", ""); if (!text.isEmpty()) { split = text.split('/'); pginfo->clumpidx = split[0]; pginfo->clumpmax = split[1]; } for (QDomNode child = element.firstChild(); !child.isNull(); child = child.nextSibling()) { QDomElement info = child.toElement(); if (!info.isNull()) { if (info.tagName() == "title") { if (isJapan) { if (info.attribute("lang") == "ja_JP") { pginfo->title = getFirstText(info); } else if (info.attribute("lang") == "ja_JP@kana") { pginfo->title_pronounce = getFirstText(info); } } else if (pginfo->title.isEmpty()) { pginfo->title = getFirstText(info); } } else if (info.tagName() == "sub-title" && pginfo->subtitle.isEmpty()) { pginfo->subtitle = getFirstText(info); } else if (info.tagName() == "desc" && pginfo->description.isEmpty()) { pginfo->description = getFirstText(info); } else if (info.tagName() == "category") { const QString cat = getFirstText(info).toLower(); if (kCategoryNone == pginfo->categoryType && string_to_myth_category_type(cat) != kCategoryNone) { pginfo->categoryType = string_to_myth_category_type(cat); } else if (pginfo->category.isEmpty()) { pginfo->category = cat; } if (cat == "film") { // Hack for tv_grab_uk_rt pginfo->categoryType = kCategoryMovie; } } else if (info.tagName() == "date" && !pginfo->airdate) { // Movie production year QString date = getFirstText(info); pginfo->airdate = date.left(4).toUInt(); } else if (info.tagName() == "star-rating" && pginfo->stars.isEmpty()) { QDomNodeList values = info.elementsByTagName("value"); QDomElement item; QString stars, num, den; float rating = 0.0; // Use the first rating to appear in the xml, this should be // the most important one. // // Averaging is not a good idea here, any subsequent ratings // are likely to represent that days recommended programmes // which on a bad night could given to an average programme. // In the case of uk_rt it's not unknown for a recommendation // to be given to programmes which are 'so bad, you have to // watch!' item = values.item(0).toElement(); if (!item.isNull()) { stars = getFirstText(item); num = stars.section('/', 0, 0); den = stars.section('/', 1, 1); if (0.0 < den.toFloat()) rating = num.toFloat()/den.toFloat(); } pginfo->stars.setNum(rating); } else if (info.tagName() == "rating") { // again, the structure of ratings seems poorly represented // in the XML. no idea what we'd do with multiple values. QDomNodeList values = info.elementsByTagName("value"); QDomElement item = values.item(0).toElement(); if (item.isNull()) continue; EventRating rating; rating.system = info.attribute("system", ""); rating.rating = getFirstText(item); pginfo->ratings.append(rating); } else if (info.tagName() == "previously-shown") { pginfo->previouslyshown = true; QString prevdate = info.attribute("start"); if (!prevdate.isEmpty()) { QDateTime date; fromXMLTVDate(prevdate, date, localTimezoneOffset); pginfo->originalairdate = date.date(); } } else if (info.tagName() == "credits") { parseCredits(info, pginfo); } else if (info.tagName() == "subtitles") { if (info.attribute("type") == "teletext") pginfo->subtitleType |= SUB_NORMAL; else if (info.attribute("type") == "onscreen") pginfo->subtitleType |= SUB_ONSCREEN; else if (info.attribute("type") == "deaf-signed") pginfo->subtitleType |= SUB_SIGNED; } else if (info.tagName() == "audio") { parseAudio(info, pginfo); } else if (info.tagName() == "video") { parseVideo(info, pginfo); } else if (info.tagName() == "episode-num") { if (info.attribute("system") == "dd_progid") { QString episodenum(getFirstText(info)); // if this field includes a dot, strip it out int idx = episodenum.indexOf('.'); if (idx != -1) episodenum.remove(idx, 1); pginfo->programId = episodenum; dd_progid_done = 1; } else if (info.attribute("system") == "xmltv_ns") { int tmp; QString episodenum(getFirstText(info)); episode = episodenum.section('.',1,1); episode = episode.section('/',0,0).trimmed(); season = episodenum.section('.',0,0).trimmed(); QString part(episodenum.section('.',2,2)); QString partnumber(part.section('/',0,0).trimmed()); QString parttotal(part.section('/',1,1).trimmed()); pginfo->categoryType = kCategorySeries; if (!episode.isEmpty()) { tmp = episode.toInt() + 1; episode = QString::number(tmp); pginfo->syndicatedepisodenumber = QString('E' + episode); } if (!season.isEmpty()) { tmp = season.toInt() + 1; season = QString::number(tmp); pginfo->syndicatedepisodenumber.append(QString('S' + season)); } uint partno = 0; if (!partnumber.isEmpty()) { bool ok; partno = partnumber.toUInt(&ok) + 1; partno = (ok) ? partno : 0; } if (!parttotal.isEmpty() && partno > 0) { bool ok; uint partto = parttotal.toUInt(&ok) + 1; if (ok && partnumber <= parttotal) { pginfo->parttotal = partto; pginfo->partnumber = partno; } } } else if (info.attribute("system") == "onscreen" && pginfo->subtitle.isEmpty()) { pginfo->categoryType = kCategorySeries; pginfo->subtitle = getFirstText(info); } } } } if (pginfo->category.isEmpty() && pginfo->categoryType != kCategoryNone) pginfo->category = myth_category_type_to_string(pginfo->categoryType); if (!pginfo->airdate) pginfo->airdate = current_year; /* Let's build ourself a programid */ QString programid; if (kCategoryMovie == pginfo->categoryType) programid = "MV"; else if (kCategorySeries == pginfo->categoryType) programid = "EP"; else if (kCategorySports == pginfo->categoryType) programid = "SP"; else programid = "SH"; if (!uniqueid.isEmpty()) // we already have a unique id ready for use programid.append(uniqueid); else { QString seriesid = QString::number(ELFHash(pginfo->title.toLocal8Bit() .constData())); pginfo->seriesId = seriesid; programid.append(seriesid); if (!episode.isEmpty() && !season.isEmpty()) { /* Append unpadded episode and season number to the seriesid (to maintain consistency with historical encoding), but limit the season number representation to a single base-36 character to ensure unique programid generation. */ int season_int = season.toInt(); if (season_int > 35) { // Cannot represent season as a single base-36 character, so // remove the programid and fall back to normal dup matching. if (kCategoryMovie != pginfo->categoryType) programid.clear(); } else { programid.append(episode); programid.append(QString::number(season_int, 36)); if (pginfo->partnumber && pginfo->parttotal) { programid += QString::number(pginfo->partnumber); programid += QString::number(pginfo->parttotal); } } } else { /* No ep/season info? Well then remove the programid and rely on normal dupchecking methods instead. */ if (kCategoryMovie != pginfo->categoryType) programid.clear(); } } if (dd_progid_done == 0) pginfo->programId = programid; return pginfo; }
/** * \copydoc MythUIType::ParseElement() */ bool MythUIImage::ParseElement( const QString &filename, QDomElement &element, bool showWarnings) { QWriteLocker updateLocker(&d->m_UpdateLock); if (element.tagName() == "filename") { m_OrigFilename = m_Filename = getFirstText(element); if (m_Filename.endsWith('/')) { QDir imageDir(m_Filename); if (!imageDir.exists()) { QString themeDir = GetMythUI()->GetThemeDir() + '/'; imageDir = themeDir + m_Filename; } QStringList imageTypes; QList< QByteArray > exts = QImageReader::supportedImageFormats(); QList< QByteArray >::Iterator it = exts.begin(); for (;it != exts.end();++it) { imageTypes.append( QString("*.").append(*it) ); } imageDir.setNameFilters(imageTypes); QStringList imageList = imageDir.entryList(); srand(time(NULL)); QString randFile; if (imageList.size()) randFile = QString("%1%2").arg(m_Filename) .arg(imageList.takeAt(rand() % imageList.size())); m_OrigFilename = m_Filename = randFile; } } else if (element.tagName() == "filepattern") { m_OrigFilename = m_Filename = getFirstText(element); QString tmp = element.attribute("low"); if (!tmp.isEmpty()) m_LowNum = tmp.toInt(); tmp = element.attribute("high"); if (!tmp.isEmpty()) m_HighNum = tmp.toInt(); tmp = element.attribute("cycle", "start"); if (tmp == "reverse") m_animationCycle = kCycleReverse; } else if (element.tagName() == "area") { SetArea(parseRect(element)); m_ForceSize = m_Area.size(); } else if (element.tagName() == "preserveaspect") m_preserveAspect = parseBool(element); else if (element.tagName() == "crop") m_cropRect = parseRect(element); else if (element.tagName() == "delay") { QString value = getFirstText(element); if (value.contains(",")) { QVector<int> delays; QStringList tokens = value.split(","); QStringList::iterator it = tokens.begin(); for (; it != tokens.end(); ++it) { if ((*it).isEmpty()) { if (delays.size()) delays.append(delays[delays.size()-1]); else delays.append(0); // Default 0ms delay before first image } else { delays.append((*it).toInt()); } } if (delays.size()) { m_Delay = delays[0]; SetDelays(delays); } } else { m_Delay = value.toInt(); } } else if (element.tagName() == "reflection") { m_isReflected = true; QString tmp = element.attribute("axis"); if (!tmp.isEmpty()) { if (tmp.toLower() == "horizontal") m_reflectAxis = ReflectHorizontal; else m_reflectAxis = ReflectVertical; } tmp = element.attribute("shear"); if (!tmp.isEmpty()) m_reflectShear = tmp.toInt(); tmp = element.attribute("scale"); if (!tmp.isEmpty()) m_reflectScale = tmp.toInt(); tmp = element.attribute("length"); if (!tmp.isEmpty()) m_reflectLength = tmp.toInt(); tmp = element.attribute("spacing"); if (!tmp.isEmpty()) m_reflectSpacing = tmp.toInt(); } else if (element.tagName() == "mask") { QString maskfile = getFirstText(element); if (m_maskImage) { m_maskImage->DownRef(); m_maskImage = NULL; } m_maskImage = GetPainter()->GetFormatImage(); m_maskImage->UpRef(); if (m_maskImage->Load(maskfile)) m_isMasked = true; else { m_maskImage->DownRef(); m_maskImage = NULL; m_isMasked = false; } } else if (element.tagName() == "grayscale" || element.tagName() == "greyscale") { m_isGreyscale = parseBool(element); } else { return MythUIType::ParseElement(filename, element, showWarnings); } m_NeedLoad = true; if (m_Parent && m_Parent->IsDeferredLoading(true)) m_NeedLoad = false; return true; }