mirror of
https://projects.vdr-developer.org/git/vdr-plugin-skindesigner.git
synced 2023-10-19 17:58:31 +02:00
added possibiliy to use submenus in the skin setup menus
This commit is contained in:
parent
304f592004
commit
1883ac1691
3
HISTORY
3
HISTORY
@ -193,3 +193,6 @@ Version 0.2.1
|
||||
- fixed bug that global tokens were not parsed correctly
|
||||
- added finnish translation
|
||||
- some more nopacity optimizations - thanx@utility
|
||||
- added possibiliy to use submenus in the skin setup menus
|
||||
- reloading active skin directly after closing setup menu so that
|
||||
changes of setup parameters are immediately in use
|
||||
|
14
config.c
14
config.c
@ -25,6 +25,7 @@ cDesignerConfig::cDesignerConfig() {
|
||||
SetOSDSize();
|
||||
SetOSDFonts();
|
||||
osdLanguage = "";
|
||||
setupCloseDoReload = false;
|
||||
}
|
||||
|
||||
cDesignerConfig::~cDesignerConfig() {
|
||||
@ -88,7 +89,7 @@ void cDesignerConfig::DebugSkinSetups(void) {
|
||||
dsyslog("skindesigner: skin setups:");
|
||||
InitSetupIterator();
|
||||
cSkinSetup *skinSetup = NULL;
|
||||
while (skinSetup = GetSkinSetup()) {
|
||||
while (skinSetup = GetNextSkinSetup()) {
|
||||
skinSetup->Debug();
|
||||
}
|
||||
}
|
||||
@ -125,7 +126,7 @@ cSkinSetup* cDesignerConfig::GetSkinSetup(string &skin) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cSkinSetup* cDesignerConfig::GetSkinSetup(void) {
|
||||
cSkinSetup* cDesignerConfig::GetNextSkinSetup(void) {
|
||||
if (setupIt == skinSetups.end()) {
|
||||
return NULL;
|
||||
}
|
||||
@ -134,6 +135,15 @@ cSkinSetup* cDesignerConfig::GetSkinSetup(void) {
|
||||
return skinSetup;
|
||||
}
|
||||
|
||||
cSkinSetupMenu* cDesignerConfig::GetSkinSetupMenu(string &skin, string &menu) {
|
||||
cSkinSetup *skinSetup = GetSkinSetup(skin);
|
||||
if (!skinSetup)
|
||||
return NULL;
|
||||
esyslog("skindesigner: skinsetup found");
|
||||
return skinSetup->GetMenu(menu);
|
||||
}
|
||||
|
||||
|
||||
void cDesignerConfig::TranslateSetup(void) {
|
||||
for (map< string, cSkinSetup* >::iterator it = skinSetups.begin(); it != skinSetups.end(); it++) {
|
||||
(it->second)->TranslateSetup();
|
||||
|
5
config.h
5
config.h
@ -49,7 +49,8 @@ public:
|
||||
void DebugSkinSetups(void);
|
||||
void DebugSkinSetupParameters(void);
|
||||
cSkinSetup* GetSkinSetup(string &skin);
|
||||
cSkinSetup* GetSkinSetup(void);
|
||||
cSkinSetup* GetNextSkinSetup(void);
|
||||
cSkinSetupMenu* GetSkinSetupMenu(string &skin, string &menu);
|
||||
void InitSetupIterator(void) { setupIt = skinSetups.begin(); };
|
||||
void TranslateSetup(void);
|
||||
void SetSkinSetupParameters(void);
|
||||
@ -85,6 +86,8 @@ public:
|
||||
int rerunDistance;
|
||||
int rerunMaxChannel;
|
||||
int blockFlush;
|
||||
//TemplateReload on Setup Close
|
||||
bool setupCloseDoReload;
|
||||
};
|
||||
|
||||
#ifdef DEFINE_CONFIG
|
||||
|
@ -163,8 +163,8 @@ void cSkinDesigner::ListCustomTokens(void) {
|
||||
* PRIVATE FUNCTIONS
|
||||
*********************************************************************************/
|
||||
void cSkinDesigner::Init(void) {
|
||||
if (init || config.OsdSizeChanged() || config.SkinChanged() || config.OsdLanguageChanged()) {
|
||||
|
||||
if (init || config.OsdSizeChanged() || config.SkinChanged() || config.OsdLanguageChanged() || config.setupCloseDoReload) {
|
||||
config.setupCloseDoReload = false;
|
||||
if (init) {
|
||||
config.SetSkin();
|
||||
config.SetOSDSize();
|
||||
|
@ -1,9 +1,15 @@
|
||||
<?xml encoding="UTF-8"?>
|
||||
|
||||
<!ELEMENT setup (parameters,translations)>
|
||||
<!ELEMENT parameters (parameter)*>
|
||||
<!ELEMENT setup (menu,translations)>
|
||||
<!ELEMENT menu (submenu | parameter)*>
|
||||
<!ELEMENT translations (token)*>
|
||||
|
||||
<!ELEMENT submenu (submenu | parameter)*>
|
||||
<!ATTLIST submenu
|
||||
name NMTOKEN #REQUIRED
|
||||
displaytext CDATA #REQUIRED
|
||||
>
|
||||
|
||||
<!ELEMENT parameter (#PCDATA)>
|
||||
<!ATTLIST parameter
|
||||
name NMTOKEN #REQUIRED
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "skinsetup.h"
|
||||
#include "../config.h"
|
||||
#include "../libtemplate/xmlparser.h"
|
||||
|
||||
// --- cSkinSetupParameter -----------------------------------------------------------
|
||||
@ -23,76 +24,192 @@ void cSkinSetupParameter::Debug(void) {
|
||||
dsyslog("skindesigner: min %d, max %d", min, max);
|
||||
}
|
||||
|
||||
// --- cSkinSetupMenu -----------------------------------------------------------
|
||||
cSkinSetupMenu::cSkinSetupMenu(void) {
|
||||
name = "";
|
||||
displayText = "";
|
||||
parent = NULL;
|
||||
}
|
||||
|
||||
cSkinSetupMenu::~cSkinSetupMenu(void) {
|
||||
for (map < string, cSkinSetupParameter* >::iterator p = parameters.begin(); p != parameters.end(); p++) {
|
||||
delete p->second;
|
||||
}
|
||||
for (vector < cSkinSetupMenu* >::iterator s = subMenus.begin(); s != subMenus.end(); s++) {
|
||||
delete (*s);
|
||||
}
|
||||
}
|
||||
|
||||
cSkinSetupParameter *cSkinSetupMenu::GetNextParameter(bool deep) {
|
||||
cSkinSetupParameter *param = NULL;
|
||||
if (paramIt != parameters.end()) {
|
||||
param = paramIt->second;
|
||||
paramIt++;
|
||||
return param;
|
||||
}
|
||||
if (!deep)
|
||||
return NULL;
|
||||
|
||||
if (subMenuIt != subMenus.end()) {
|
||||
param = (*subMenuIt)->GetNextParameter();
|
||||
if (!param) {
|
||||
subMenuIt++;
|
||||
if (subMenuIt != subMenus.end()) {
|
||||
(*subMenuIt)->InitIterators();
|
||||
param = (*subMenuIt)->GetNextParameter();
|
||||
}
|
||||
}
|
||||
}
|
||||
return param;
|
||||
}
|
||||
|
||||
cSkinSetupParameter *cSkinSetupMenu::GetParameter(string name) {
|
||||
map < string, cSkinSetupParameter* >::iterator hit = parameters.find(name);
|
||||
if (hit != parameters.end())
|
||||
return hit->second;
|
||||
|
||||
cSkinSetupParameter *paramHit = NULL;
|
||||
for (vector < cSkinSetupMenu* >::iterator subMenu = subMenus.begin(); subMenu != subMenus.end(); subMenu++) {
|
||||
paramHit = (*subMenu)->GetParameter(name);
|
||||
if (paramHit)
|
||||
return paramHit;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void cSkinSetupMenu::InitIterators(void) {
|
||||
paramIt = parameters.begin();
|
||||
subMenuIt = subMenus.begin();
|
||||
while (subMenuIt != subMenus.end()) {
|
||||
(*subMenuIt)->InitIterators();
|
||||
subMenuIt++;
|
||||
}
|
||||
subMenuIt = subMenus.begin();
|
||||
}
|
||||
|
||||
void cSkinSetupMenu::SetParameter(eSetupParameterType paramType, xmlChar *name, xmlChar* displayText, xmlChar *min, xmlChar *max, xmlChar *value) {
|
||||
cSkinSetupParameter *param = new cSkinSetupParameter();
|
||||
param->type = paramType;
|
||||
param->name = (const char*)name;
|
||||
param->displayText = (const char*)displayText;
|
||||
|
||||
if (min && paramType == sptInt) {
|
||||
param->min = atoi((const char*)min);
|
||||
}
|
||||
if (max && paramType == sptInt) {
|
||||
param->max = atoi((const char*)max);
|
||||
}
|
||||
param->value = atoi((const char*)value);
|
||||
|
||||
parameters.insert(pair< string, cSkinSetupParameter* >(param->name, param));
|
||||
}
|
||||
|
||||
cSkinSetupMenu *cSkinSetupMenu::GetMenu(string &name) {
|
||||
for (vector<cSkinSetupMenu*>::iterator m = subMenus.begin(); m != subMenus.end(); m++) {
|
||||
cSkinSetupMenu *menu = (*m);
|
||||
if (!name.compare(menu->GetName()))
|
||||
return menu;
|
||||
menu = menu->GetMenu(name);
|
||||
if (menu)
|
||||
return menu;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cSkinSetupMenu *cSkinSetupMenu::GetNextSubMenu(bool deep) {
|
||||
cSkinSetupMenu *menu = NULL;
|
||||
if (subMenuIt != subMenus.end()) {
|
||||
if (deep) {
|
||||
menu = (*subMenuIt)->GetNextSubMenu(deep);
|
||||
if (menu)
|
||||
return menu;
|
||||
}
|
||||
menu = *subMenuIt;
|
||||
subMenuIt++;
|
||||
return menu;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void cSkinSetupMenu::Debug(bool deep) {
|
||||
dsyslog("skindesigner: Menu %s Setup Parameters", name.c_str());
|
||||
for (map < string, cSkinSetupParameter* >::iterator p = parameters.begin(); p != parameters.end(); p++) {
|
||||
(p->second)->Debug();
|
||||
}
|
||||
if (subMenus.empty())
|
||||
return;
|
||||
for (vector < cSkinSetupMenu* >::iterator s = subMenus.begin(); s != subMenus.end(); s++) {
|
||||
dsyslog("skindesigner: SubMenu %s, Parent %s", ((*s)->GetName()).c_str(), ((*s)->GetParent()->GetName()).c_str());
|
||||
if (deep)
|
||||
(*s)->Debug();
|
||||
}
|
||||
}
|
||||
// --- cSkinSetup -----------------------------------------------------------
|
||||
|
||||
cSkinSetup::cSkinSetup(string skin) {
|
||||
this->skin = skin;
|
||||
rootMenu = new cSkinSetupMenu();
|
||||
rootMenu->SetName("root");
|
||||
currentMenu = rootMenu;
|
||||
}
|
||||
|
||||
cSkinSetup::~cSkinSetup() {
|
||||
for (map < string, cSkinSetupParameter* >::iterator p = parameters.begin(); p != parameters.end(); p++) {
|
||||
delete p->second;
|
||||
}
|
||||
delete rootMenu;
|
||||
}
|
||||
|
||||
bool cSkinSetup::ReadFromXML(void) {
|
||||
string xmlFile = "setup.xml";
|
||||
string xmlPath = *cString::sprintf("%s%s/setup.xml", *config.skinPath, skin.c_str());
|
||||
cXmlParser parser;
|
||||
if (!parser.ReadSkinSetup(this, skin, xmlFile)) {
|
||||
if (!parser.ReadSkinSetup(this, xmlPath)) {
|
||||
return false;
|
||||
}
|
||||
parser.ParseSkinSetup(skin);
|
||||
return true;
|
||||
}
|
||||
|
||||
void cSkinSetup::SetParameter(xmlChar *type, xmlChar *name, xmlChar* displayText, xmlChar *min, xmlChar *max, xmlChar *value) {
|
||||
if (!type || !name || !displayText || !value) {
|
||||
esyslog("skindesigner: invalid setup parameter for skin %s", skin.c_str());
|
||||
return;
|
||||
}
|
||||
eSetupParameterType paramType = sptUnknown;
|
||||
if (!xmlStrcmp(type, (const xmlChar *) "int")) {
|
||||
paramType = sptInt;
|
||||
} else if (!xmlStrcmp(type, (const xmlChar *) "bool")) {
|
||||
paramType = sptBool;
|
||||
}
|
||||
if (paramType == sptUnknown) {
|
||||
esyslog("skindesigner: invalid setup parameter for skin %s", skin.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
cSkinSetupParameter *param = new cSkinSetupParameter();
|
||||
param->type = paramType;
|
||||
param->name = (const char*)name;
|
||||
param->displayText = (const char*)displayText;
|
||||
|
||||
if (min && paramType == sptInt) {
|
||||
param->min = atoi((const char*)min);
|
||||
}
|
||||
if (max && paramType == sptInt) {
|
||||
param->max = atoi((const char*)max);
|
||||
}
|
||||
param->value = atoi((const char*)value);
|
||||
|
||||
parameters.insert(pair< string, cSkinSetupParameter* >(param->name, param));
|
||||
void cSkinSetup::SetSubMenu(xmlChar *name, xmlChar *displayText) {
|
||||
cSkinSetupMenu *subMenu = new cSkinSetupMenu();
|
||||
subMenu->SetName((const char*)name);
|
||||
subMenu->SetDisplayText((const char*)displayText);
|
||||
subMenu->SetParent(currentMenu);
|
||||
currentMenu->AddSubMenu(subMenu);
|
||||
currentMenu = subMenu;
|
||||
}
|
||||
|
||||
cSkinSetupParameter *cSkinSetup::GetParameter(void) {
|
||||
if (paramIt == parameters.end())
|
||||
return NULL;
|
||||
cSkinSetupParameter *param = paramIt->second;
|
||||
paramIt++;
|
||||
return param;
|
||||
void cSkinSetup::SubMenuDone(void) {
|
||||
cSkinSetupMenu *parent = currentMenu->GetParent();
|
||||
if (parent) {
|
||||
currentMenu = parent;
|
||||
}
|
||||
}
|
||||
|
||||
void cSkinSetup::SetParameter(xmlChar *type, xmlChar *name, xmlChar* displayText, xmlChar *min, xmlChar *max, xmlChar *value) {
|
||||
if (!type || !name || !displayText || !value) {
|
||||
esyslog("skindesigner: invalid setup parameter for skin %s", skin.c_str());
|
||||
return;
|
||||
}
|
||||
eSetupParameterType paramType = sptUnknown;
|
||||
if (!xmlStrcmp(type, (const xmlChar *) "int")) {
|
||||
paramType = sptInt;
|
||||
} else if (!xmlStrcmp(type, (const xmlChar *) "bool")) {
|
||||
paramType = sptBool;
|
||||
}
|
||||
if (paramType == sptUnknown) {
|
||||
esyslog("skindesigner: invalid setup parameter for skin %s", skin.c_str());
|
||||
return;
|
||||
}
|
||||
currentMenu->SetParameter(paramType, name, displayText, min, max, value);
|
||||
}
|
||||
|
||||
cSkinSetupParameter *cSkinSetup::GetNextParameter(void) {
|
||||
return rootMenu->GetNextParameter();
|
||||
}
|
||||
|
||||
cSkinSetupParameter *cSkinSetup::GetParameter(string name) {
|
||||
map < string, cSkinSetupParameter* >::iterator hit = parameters.find(name);
|
||||
if (hit != parameters.end())
|
||||
return hit->second;
|
||||
return NULL;
|
||||
return rootMenu->GetParameter(name);
|
||||
}
|
||||
|
||||
|
||||
void cSkinSetup::SetTranslation(string translationToken, map < string, string > transl) {
|
||||
translations.insert(pair<string, map < string, string > >(translationToken, transl));
|
||||
}
|
||||
@ -100,21 +217,37 @@ void cSkinSetup::SetTranslation(string translationToken, map < string, string >
|
||||
void cSkinSetup::AddToGlobals(cGlobals *globals) {
|
||||
if (!globals)
|
||||
return;
|
||||
for (map < string, cSkinSetupParameter* >::iterator p = parameters.begin(); p != parameters.end(); p++) {
|
||||
cSkinSetupParameter *param = p->second;
|
||||
rootMenu->InitIterators();
|
||||
cSkinSetupParameter *param = NULL;
|
||||
while (param = rootMenu->GetNextParameter()) {
|
||||
globals->AddInt(param->name, param->value);
|
||||
}
|
||||
}
|
||||
|
||||
void cSkinSetup::TranslateSetup(void) {
|
||||
InitParameterIterator();
|
||||
rootMenu->InitIterators();
|
||||
cSkinSetupParameter *param = NULL;
|
||||
while (param = GetParameter()) {
|
||||
while (param = rootMenu->GetNextParameter()) {
|
||||
string transl = "";
|
||||
if (Translate(param->displayText, transl)) {
|
||||
param->displayText = transl;
|
||||
}
|
||||
}
|
||||
|
||||
rootMenu->InitIterators();
|
||||
cSkinSetupMenu *subMenu = NULL;
|
||||
while (subMenu = rootMenu->GetNextSubMenu()) {
|
||||
string transl = "";
|
||||
if (Translate(subMenu->GetDisplayText(), transl)) {
|
||||
subMenu->SetDisplayText(transl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cSkinSetupMenu *cSkinSetup::GetMenu(string &name) {
|
||||
if (name.size() == 0)
|
||||
return rootMenu;
|
||||
return rootMenu->GetMenu(name);
|
||||
}
|
||||
|
||||
bool cSkinSetup::Translate(string text, string &translation) {
|
||||
@ -161,11 +294,8 @@ string cSkinSetup::DoTranslate(string token) {
|
||||
}
|
||||
|
||||
void cSkinSetup::Debug(void) {
|
||||
dsyslog("skindesigner: Skin \"%s\" Setup Parameters", skin.c_str());
|
||||
for (map < string, cSkinSetupParameter* >::iterator p = parameters.begin(); p != parameters.end(); p++) {
|
||||
(p->second)->Debug();
|
||||
}
|
||||
|
||||
rootMenu->Debug();
|
||||
return;
|
||||
dsyslog("skindesigner: Skin \"%s\" Setup Parameter Translations", skin.c_str());
|
||||
for (map<string, map<string,string> >::iterator trans = translations.begin(); trans != translations.end(); trans++) {
|
||||
dsyslog("skindesigner: translation token %s", (trans->first).c_str());
|
||||
|
@ -34,28 +34,63 @@ public:
|
||||
void Debug(void);
|
||||
};
|
||||
|
||||
// --- cSkinSetupMenu -----------------------------------------------------------
|
||||
|
||||
class cSkinSetupMenu {
|
||||
private:
|
||||
string name;
|
||||
string displayText;
|
||||
cSkinSetupMenu *parent;
|
||||
vector < cSkinSetupMenu* > subMenus;
|
||||
vector < cSkinSetupMenu* >::iterator subMenuIt;
|
||||
map < string, cSkinSetupParameter* > parameters;
|
||||
map < string, cSkinSetupParameter* >::iterator paramIt;
|
||||
public:
|
||||
cSkinSetupMenu(void);
|
||||
virtual ~cSkinSetupMenu(void);
|
||||
void SetName(string name) { this->name = name; };
|
||||
void SetDisplayText(string displayText) { this->displayText = displayText; };
|
||||
string GetName(void) { return name; };
|
||||
string GetDisplayText(void) { return displayText; };
|
||||
void SetParent(cSkinSetupMenu *p) { parent = p; };
|
||||
cSkinSetupMenu *GetParent(void) { return parent; };
|
||||
void AddSubMenu(cSkinSetupMenu *sub) { subMenus.push_back(sub); };
|
||||
void SetParameter(eSetupParameterType paramType, xmlChar *name, xmlChar* displayText, xmlChar *min, xmlChar *max, xmlChar *value);
|
||||
void InitIterators(void);
|
||||
void InitParameterIterator(void) { paramIt = parameters.begin(); };
|
||||
cSkinSetupParameter *GetNextParameter(bool deep = true);
|
||||
cSkinSetupParameter *GetParameter(string name);
|
||||
void InitSubmenuIterator(void) { subMenuIt = subMenus.begin(); };
|
||||
cSkinSetupMenu *GetNextSubMenu(bool deep = true);
|
||||
cSkinSetupMenu *GetMenu(string &name);
|
||||
void Debug(bool deep = true);
|
||||
};
|
||||
|
||||
// --- cSkinSetup -----------------------------------------------------------
|
||||
|
||||
class cSkinSetup {
|
||||
private:
|
||||
string skin;
|
||||
map < string, cSkinSetupParameter* > parameters;
|
||||
map < string, cSkinSetupParameter* >::iterator paramIt;
|
||||
map < string, map< string, string > > translations;
|
||||
string skin;
|
||||
cSkinSetupMenu *rootMenu;
|
||||
cSkinSetupMenu *currentMenu;
|
||||
map < string, map< string, string > > translations;
|
||||
string DoTranslate(string token);
|
||||
bool Translate(string text, string &translation);
|
||||
public:
|
||||
cSkinSetup(string skin);
|
||||
virtual ~cSkinSetup(void);
|
||||
bool ReadFromXML(void);
|
||||
void SetSubMenu(xmlChar *name, xmlChar *displayText);
|
||||
void SubMenuDone(void);
|
||||
void SetParameter(xmlChar *type, xmlChar *name, xmlChar* displayText, xmlChar *min, xmlChar *max, xmlChar *value);
|
||||
void InitParameterIterator(void) { rootMenu->InitIterators(); };
|
||||
cSkinSetupParameter *GetNextParameter(void);
|
||||
cSkinSetupParameter *GetParameter(string name);
|
||||
void SetTranslation(string translationToken, map < string, string > transl);
|
||||
void AddToGlobals(cGlobals *globals);
|
||||
void TranslateSetup(void);
|
||||
void InitParameterIterator(void) { paramIt = parameters.begin(); };
|
||||
cSkinSetupParameter *GetParameter(void);
|
||||
cSkinSetupParameter *GetParameter(string name);
|
||||
string GetSkin(void) { return skin; };
|
||||
cSkinSetupMenu *GetMenu(string &name);
|
||||
void Debug(void);
|
||||
};
|
||||
|
||||
|
@ -134,28 +134,27 @@ bool cXmlParser::ReadGlobals(cGlobals *globals, string xmlFile, bool mandatory)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cXmlParser::ReadSkinSetup(cSkinSetup *skinSetup, string skin, string xmlFile) {
|
||||
bool cXmlParser::ReadSkinSetup(cSkinSetup *skinSetup, string xmlFile) {
|
||||
this->skinSetup = skinSetup;
|
||||
string xmlPath = *cString::sprintf("%s%s/%s", *config.skinPath, skin.c_str(), xmlFile.c_str());
|
||||
|
||||
if (!FileExists(xmlPath))
|
||||
if (!FileExists(xmlFile))
|
||||
return false;
|
||||
if (ctxt == NULL) {
|
||||
esyslog("skindesigner: Failed to allocate parser context");
|
||||
return false;
|
||||
}
|
||||
|
||||
doc = xmlCtxtReadFile(ctxt, xmlPath.c_str(), NULL, XML_PARSE_NOENT | XML_PARSE_DTDVALID);
|
||||
doc = xmlCtxtReadFile(ctxt, xmlFile.c_str(), NULL, XML_PARSE_NOENT | XML_PARSE_DTDVALID);
|
||||
|
||||
if (doc == NULL ) {
|
||||
esyslog("skindesigner: ERROR: skin setup %s not parsed successfully.", xmlPath.c_str());
|
||||
esyslog("skindesigner: ERROR: skin setup %s not parsed successfully.", xmlFile.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
root = xmlDocGetRootElement(doc);
|
||||
|
||||
if (ctxt->valid == 0) {
|
||||
esyslog("skindesigner: Failed to validate %s", xmlPath.c_str());
|
||||
esyslog("skindesigner: Failed to validate %s", xmlFile.c_str());
|
||||
return false;
|
||||
}
|
||||
if (root == NULL) {
|
||||
@ -281,8 +280,8 @@ bool cXmlParser::ParseSkinSetup(string skin) {
|
||||
node = node->next;
|
||||
continue;
|
||||
}
|
||||
if (!xmlStrcmp(node->name, (const xmlChar *) "parameters")) {
|
||||
ParseSetupParameter(node->xmlChildrenNode);
|
||||
if (!xmlStrcmp(node->name, (const xmlChar *) "menu")) {
|
||||
ParseSetupMenu(node->xmlChildrenNode);
|
||||
node = node->next;
|
||||
continue;
|
||||
} else if (!xmlStrcmp(node->name, (const xmlChar *) "translations")) {
|
||||
@ -324,64 +323,88 @@ string cXmlParser::GetPath(string xmlFile) {
|
||||
return path;
|
||||
}
|
||||
|
||||
void cXmlParser::ParseSetupParameter(xmlNodePtr node) {
|
||||
void cXmlParser::ParseSetupMenu(xmlNodePtr node) {
|
||||
if (!node)
|
||||
return;
|
||||
if (!skinSetup)
|
||||
return;
|
||||
|
||||
while (node != NULL) {
|
||||
|
||||
if (node->type != XML_ELEMENT_NODE) {
|
||||
node = node->next;
|
||||
continue;
|
||||
}
|
||||
if (xmlStrcmp(node->name, (const xmlChar *) "parameter")) {
|
||||
node = node->next;
|
||||
continue;
|
||||
}
|
||||
xmlAttrPtr attr = node->properties;
|
||||
if (attr == NULL) {
|
||||
node = node->next;
|
||||
continue;
|
||||
}
|
||||
xmlChar *paramType = NULL;
|
||||
xmlChar *paramName = NULL;
|
||||
xmlChar *paramDisplayText = NULL;
|
||||
xmlChar *paramMin = NULL;
|
||||
xmlChar *paramMax = NULL;
|
||||
xmlChar *paramValue = NULL;
|
||||
while (NULL != attr) {
|
||||
if (!xmlStrcmp(attr->name, (const xmlChar *) "type")) {
|
||||
paramType = xmlGetProp(node, attr->name);
|
||||
} else if (!xmlStrcmp(attr->name, (const xmlChar *) "name")) {
|
||||
paramName = xmlGetProp(node, attr->name);
|
||||
} else if (!xmlStrcmp(attr->name, (const xmlChar *) "displaytext")) {
|
||||
paramDisplayText = xmlGetProp(node, attr->name);
|
||||
} else if (!xmlStrcmp(attr->name, (const xmlChar *) "min")) {
|
||||
paramMin = xmlGetProp(node, attr->name);
|
||||
} else if (!xmlStrcmp(attr->name, (const xmlChar *) "max")) {
|
||||
paramMax = xmlGetProp(node, attr->name);
|
||||
}
|
||||
attr = attr->next;
|
||||
}
|
||||
paramValue = xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||
skinSetup->SetParameter(paramType, paramName, paramDisplayText, paramMin, paramMax, paramValue);
|
||||
|
||||
if (paramType)
|
||||
xmlFree(paramType);
|
||||
if (paramName)
|
||||
xmlFree(paramName);
|
||||
if (paramDisplayText)
|
||||
xmlFree(paramDisplayText);
|
||||
if (paramMin)
|
||||
xmlFree(paramMin);
|
||||
if (paramMax)
|
||||
xmlFree(paramMax);
|
||||
if (paramValue)
|
||||
xmlFree(paramValue);
|
||||
if (!xmlStrcmp(node->name, (const xmlChar *) "parameter")) {
|
||||
ParseSetupParameter(node);
|
||||
} else if (!xmlStrcmp(node->name, (const xmlChar *) "submenu")) {
|
||||
xmlAttrPtr attr = node->properties;
|
||||
xmlChar *subMenuName = NULL;
|
||||
xmlChar *subDisplayText = NULL;
|
||||
while (NULL != attr) {
|
||||
if (!xmlStrcmp(attr->name, (const xmlChar *) "name")) {
|
||||
subMenuName = xmlGetProp(node, attr->name);
|
||||
} else if (!xmlStrcmp(attr->name, (const xmlChar *) "displaytext")) {
|
||||
subDisplayText = xmlGetProp(node, attr->name);
|
||||
}
|
||||
attr = attr->next;
|
||||
}
|
||||
skinSetup->SetSubMenu(subMenuName, subDisplayText);
|
||||
ParseSetupMenu(node->xmlChildrenNode);
|
||||
if (subMenuName)
|
||||
xmlFree(subMenuName);
|
||||
if (subDisplayText)
|
||||
xmlFree(subDisplayText);
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
skinSetup->SubMenuDone();
|
||||
}
|
||||
|
||||
void cXmlParser::ParseSetupParameter(xmlNodePtr node) {
|
||||
if (!node)
|
||||
return;
|
||||
if (!skinSetup)
|
||||
return;
|
||||
|
||||
xmlAttrPtr attr = node->properties;
|
||||
if (attr == NULL) {
|
||||
return;
|
||||
}
|
||||
xmlChar *paramType = NULL;
|
||||
xmlChar *paramName = NULL;
|
||||
xmlChar *paramDisplayText = NULL;
|
||||
xmlChar *paramMin = NULL;
|
||||
xmlChar *paramMax = NULL;
|
||||
xmlChar *paramValue = NULL;
|
||||
while (NULL != attr) {
|
||||
if (!xmlStrcmp(attr->name, (const xmlChar *) "type")) {
|
||||
paramType = xmlGetProp(node, attr->name);
|
||||
} else if (!xmlStrcmp(attr->name, (const xmlChar *) "name")) {
|
||||
paramName = xmlGetProp(node, attr->name);
|
||||
} else if (!xmlStrcmp(attr->name, (const xmlChar *) "displaytext")) {
|
||||
paramDisplayText = xmlGetProp(node, attr->name);
|
||||
} else if (!xmlStrcmp(attr->name, (const xmlChar *) "min")) {
|
||||
paramMin = xmlGetProp(node, attr->name);
|
||||
} else if (!xmlStrcmp(attr->name, (const xmlChar *) "max")) {
|
||||
paramMax = xmlGetProp(node, attr->name);
|
||||
}
|
||||
attr = attr->next;
|
||||
}
|
||||
paramValue = xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||
skinSetup->SetParameter(paramType, paramName, paramDisplayText, paramMin, paramMax, paramValue);
|
||||
if (paramType)
|
||||
xmlFree(paramType);
|
||||
if (paramName)
|
||||
xmlFree(paramName);
|
||||
if (paramDisplayText)
|
||||
xmlFree(paramDisplayText);
|
||||
if (paramMin)
|
||||
xmlFree(paramMin);
|
||||
if (paramMax)
|
||||
xmlFree(paramMax);
|
||||
if (paramValue)
|
||||
xmlFree(paramValue);
|
||||
}
|
||||
|
||||
void cXmlParser::ParseGlobalColors(xmlNodePtr node) {
|
||||
|
@ -31,6 +31,7 @@ private:
|
||||
xmlDocPtr doc;
|
||||
xmlNodePtr root;
|
||||
string GetPath(string xmlFile);
|
||||
void ParseSetupMenu(xmlNodePtr node);
|
||||
void ParseSetupParameter(xmlNodePtr node);
|
||||
void ParseGlobalColors(xmlNodePtr node);
|
||||
void InsertColor(string name, string value);
|
||||
@ -51,7 +52,7 @@ public:
|
||||
bool ReadView(cTemplateView *view, string xmlFile);
|
||||
bool ReadPluginView(string plugName, int templateNumber, string templateName);
|
||||
bool ReadGlobals(cGlobals *globals, string xmlFile, bool mandatory);
|
||||
bool ReadSkinSetup(cSkinSetup *skinSetup, string skin, string xmlFile);
|
||||
bool ReadSkinSetup(cSkinSetup *skinSetup, string xmlFile);
|
||||
bool ParseView(void);
|
||||
bool ParsePluginView(string plugName, int templateNumber);
|
||||
bool ParseGlobals(void);
|
||||
|
45
setup.c
45
setup.c
@ -15,6 +15,7 @@ cSkinDesignerSetup::cSkinDesignerSetup() {
|
||||
}
|
||||
|
||||
cSkinDesignerSetup::~cSkinDesignerSetup() {
|
||||
config.setupCloseDoReload = true;
|
||||
}
|
||||
|
||||
|
||||
@ -44,7 +45,7 @@ eOSState cSkinDesignerSetup::ProcessKey(eKeys Key) {
|
||||
size_t hit = itemText.find(tr("Skin"));
|
||||
if (hit == 0) {
|
||||
string skin = itemText.substr(strlen(tr("Skin"))+1);
|
||||
state = AddSubMenu(new cSkindesignerSkinSetup(skin));
|
||||
state = AddSubMenu(new cSkindesignerSkinSetup(skin, ""));
|
||||
}
|
||||
break;
|
||||
} default:
|
||||
@ -67,11 +68,11 @@ void cSkinDesignerSetup::Store(void) {
|
||||
|
||||
config.InitSetupIterator();
|
||||
cSkinSetup *skinSetup = NULL;
|
||||
while (skinSetup = config.GetSkinSetup()) {
|
||||
while (skinSetup = config.GetNextSkinSetup()) {
|
||||
string skin = skinSetup->GetSkin();
|
||||
skinSetup->InitParameterIterator();
|
||||
cSkinSetupParameter *param = NULL;
|
||||
while (param = skinSetup->GetParameter()) {
|
||||
while (param = skinSetup->GetNextParameter()) {
|
||||
cString paramName = cString::sprintf("%s.%s", skin.c_str(), param->name.c_str());
|
||||
SetupStore(*paramName, param->value);
|
||||
config.UpdateSkinSetupParameter(*paramName, param->value);
|
||||
@ -157,10 +158,18 @@ void cSkinDesignerSetup::ImageCacheStatistics(void) {
|
||||
cList<cOsdItem>::Last()->SetSelectable(false);
|
||||
}
|
||||
|
||||
// --- cSkinSetupSubMenu -----------------------------------------------------------
|
||||
|
||||
cSkinSetupSubMenu::cSkinSetupSubMenu(string name, string displayText) : cOsdItem(displayText.c_str()) {
|
||||
this->name = name;
|
||||
}
|
||||
|
||||
// --- cSkindesignerSkinSetup -----------------------------------------------------------
|
||||
|
||||
cSkindesignerSkinSetup::cSkindesignerSkinSetup(string skin) : cOsdMenu(*cString::sprintf("%s: %s \"%s\"", trVDR("Setup"), tr("Skin"), skin.c_str()), 30) {
|
||||
cSkindesignerSkinSetup::cSkindesignerSkinSetup(string skin, string name) :
|
||||
cOsdMenu(*cString::sprintf("%s: %s \"%s\" %s", trVDR("Setup"), tr("Skin"), skin.c_str(), name.c_str()), 30) {
|
||||
this->skin = skin;
|
||||
this->name = name;
|
||||
Set();
|
||||
}
|
||||
|
||||
@ -171,9 +180,16 @@ eOSState cSkindesignerSkinSetup::ProcessKey(eKeys Key) {
|
||||
eOSState state = cOsdMenu::ProcessKey(Key);
|
||||
if (state == osUnknown) {
|
||||
switch (Key) {
|
||||
case kOk:
|
||||
return osBack;
|
||||
default:
|
||||
case kOk: {
|
||||
cOsdItem *current = Get(Current());
|
||||
cSkinSetupSubMenu *subMenuItem = dynamic_cast<cSkinSetupSubMenu*>(current);
|
||||
if (subMenuItem) {
|
||||
state = AddSubMenu(new cSkindesignerSkinSetup(skin, subMenuItem->GetName()));
|
||||
break;
|
||||
} else {
|
||||
return osBack;
|
||||
}
|
||||
} default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -181,13 +197,13 @@ eOSState cSkindesignerSkinSetup::ProcessKey(eKeys Key) {
|
||||
}
|
||||
|
||||
void cSkindesignerSkinSetup::Set(void) {
|
||||
cSkinSetup *skinSetup = config.GetSkinSetup(skin);
|
||||
if (!skinSetup)
|
||||
cSkinSetupMenu *menu = config.GetSkinSetupMenu(skin, name);
|
||||
if (!menu) {
|
||||
return;
|
||||
|
||||
skinSetup->InitParameterIterator();
|
||||
}
|
||||
menu->InitParameterIterator();
|
||||
cSkinSetupParameter *param = NULL;
|
||||
while (param = skinSetup->GetParameter()) {
|
||||
while (param = menu->GetNextParameter(false)) {
|
||||
if (param->type == sptInt) {
|
||||
Add(new cMenuEditIntItem(param->displayText.c_str(), ¶m->value, param->min, param->max));
|
||||
} else if (param->type == sptBool) {
|
||||
@ -195,4 +211,9 @@ void cSkindesignerSkinSetup::Set(void) {
|
||||
}
|
||||
}
|
||||
|
||||
menu->InitSubmenuIterator();
|
||||
cSkinSetupMenu *subMenu = NULL;
|
||||
while (subMenu = menu->GetNextSubMenu(false)) {
|
||||
Add(new cSkinSetupSubMenu(subMenu->GetName(), subMenu->GetDisplayText()));
|
||||
}
|
||||
}
|
||||
|
14
setup.h
14
setup.h
@ -29,16 +29,28 @@ public:
|
||||
virtual ~cSkinDesignerSetup();
|
||||
};
|
||||
|
||||
// --- cSkinSetupSubMenu -----------------------------------------------------------
|
||||
|
||||
class cSkinSetupSubMenu : public cOsdItem {
|
||||
private:
|
||||
string name;
|
||||
public:
|
||||
cSkinSetupSubMenu(string name, string displayText);
|
||||
virtual ~cSkinSetupSubMenu() {};
|
||||
string GetName(void) { return name; };
|
||||
};
|
||||
|
||||
// --- cSkindesignerSkinSetup -----------------------------------------------------------
|
||||
|
||||
class cSkindesignerSkinSetup : public cOsdMenu {
|
||||
private:
|
||||
string skin;
|
||||
string name;
|
||||
protected:
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
void Set(void);
|
||||
public:
|
||||
cSkindesignerSkinSetup(string skin);
|
||||
cSkindesignerSkinSetup(string skin, string menu);
|
||||
virtual ~cSkindesignerSkinSetup();
|
||||
};
|
||||
|
||||
|
@ -2,17 +2,7 @@
|
||||
<!DOCTYPE setup SYSTEM "../../dtd/setup.dtd">
|
||||
|
||||
<setup>
|
||||
<!--
|
||||
define all your parameters here which should be configurable via
|
||||
OSD and the skindesigner setup menu.
|
||||
Parameters must have type "bool" or "integer". For "bool" Parameters
|
||||
a choice yes/no is shown in the setup menu, a "integer" parameter
|
||||
can be configured to a value between "min" and "max". If "min" is not
|
||||
set, "0" is the minimum, if "max" is not set, "1000" is maximum.
|
||||
"displayname" is used to display the option in the setup menu.
|
||||
The configured parameter value is the default value.
|
||||
-->
|
||||
<parameters>
|
||||
<menu>
|
||||
<parameter type="bool" name="showdevices" displaytext="{tr(showdevices)}">0</parameter>
|
||||
<parameter type="bool" name="showposter" displaytext="{tr(showpostertext)}">1</parameter>
|
||||
<parameter type="bool" name="showmainmenuicons" displaytext="{tr(showmainmenuicons)}">1</parameter>
|
||||
@ -21,11 +11,8 @@
|
||||
<parameter type="int" name="nummenuitems" min="6" max="30" displaytext="{tr(nummenuitems)}">10</parameter>
|
||||
<parameter type="int" name="nummenuitemsdefault" min="6" max="30" displaytext="{tr(nummenuitemsdefault)}">16</parameter>
|
||||
<parameter type="bool" name="showsubtitle" displaytext="{tr(showsubtitle)}">1</parameter>
|
||||
</parameters>
|
||||
</menu>
|
||||
|
||||
<!--
|
||||
translations of displaytexts
|
||||
-->
|
||||
<translations>
|
||||
<token name="tr(showdevices)">
|
||||
<trans lang="en_EN">Show DVB device info when switching channel</trans>
|
||||
@ -43,24 +30,24 @@
|
||||
<trans lang="fi_FI">Näytä ikonit päävalikossa</trans>
|
||||
</token>
|
||||
<token name="tr(fadetext)">
|
||||
<trans lang="en_EN">Fade time in ms (needs VDR restart)</trans>
|
||||
<trans lang="de_DE">Einblendzeit in ms (erfordert VDR Neustart)</trans>
|
||||
<trans lang="fi_FI">Häivytyksen kesto [ms] (uud.käynnistys)</trans>
|
||||
<trans lang="en_EN">Fade time in ms</trans>
|
||||
<trans lang="de_DE">Einblendzeit in ms</trans>
|
||||
<trans lang="fi_FI">Häivytyksen kesto [ms]</trans>
|
||||
</token>
|
||||
<token name="tr(nummenuitemsmain)">
|
||||
<trans lang="en_EN">Items in main menu (needs VDR restart)</trans>
|
||||
<trans lang="de_DE">Elemente im Hauptmenü (erfordert VDR Neustart)</trans>
|
||||
<trans lang="fi_FI">Valinnat päävalikossa (uud.käynnistys)</trans>
|
||||
<trans lang="en_EN">Items in main menu</trans>
|
||||
<trans lang="de_DE">Elemente im Hauptmenü</trans>
|
||||
<trans lang="fi_FI">Valinnat päävalikossa</trans>
|
||||
</token>
|
||||
<token name="tr(nummenuitems)">
|
||||
<trans lang="en_EN">Items in schedules, timers, ... menus (needs VDR restart)</trans>
|
||||
<trans lang="de_DE">Elemente in Programm, Timer, ... Menüs (erfordert VDR Neustart)</trans>
|
||||
<trans lang="fi_FI">Valinnat alivalikoissa (uud.käynnistys)</trans>
|
||||
<trans lang="en_EN">Items in schedules, timers, ... menus</trans>
|
||||
<trans lang="de_DE">Elemente in Programm, Timer, ... Menüs</trans>
|
||||
<trans lang="fi_FI">Valinnat alivalikoissa</trans>
|
||||
</token>
|
||||
<token name="tr(nummenuitemsdefault)">
|
||||
<trans lang="en_EN">Items in default list menu (needs VDR restart)</trans>
|
||||
<trans lang="de_DE">Elemente im Standard ListenMenü (erfordert VDR Neustart)</trans>
|
||||
<trans lang="fi_FI">Valinnat valikkolistoissa (uud.käynnistys)</trans>
|
||||
<trans lang="en_EN">Items in default list menu</trans>
|
||||
<trans lang="de_DE">Elemente im Standard ListenMenü</trans>
|
||||
<trans lang="fi_FI">Valinnat valikkolistoissa</trans>
|
||||
</token>
|
||||
<token name="tr(showsubtitle)">
|
||||
<trans lang="en_EN">Show shorttexts in schedules menus</trans>
|
||||
|
@ -2,29 +2,16 @@
|
||||
<!DOCTYPE setup SYSTEM "../../dtd/setup.dtd">
|
||||
|
||||
<setup>
|
||||
<!--
|
||||
define all your parameters here which should be configurable via
|
||||
OSD and the skindesigner setup menu.
|
||||
Parameters must have type "bool" or "integer". For "bool" Parameters
|
||||
a choice yes/no is shown in the setup menu, a "integer" parameter
|
||||
can be configured to a value between "min" and "max". If "min" is not
|
||||
set, "0" is the minimum, if "max" is not set, "1000" is maximum.
|
||||
"displayname" is used to display the option in the setup menu.
|
||||
The configured parameter value is the default value.
|
||||
-->
|
||||
<parameters>
|
||||
<menu>
|
||||
<parameter type="int" name="fadetime" min="0" max="1000" displaytext="{tr(fadetext)}">0</parameter>
|
||||
<parameter type="bool" name="showdevices" displaytext="{tr(showdevices)}">0</parameter>
|
||||
</parameters>
|
||||
</menu>
|
||||
|
||||
<!--
|
||||
translations of displaytexts
|
||||
-->
|
||||
<translations>
|
||||
<token name="tr(fadetext)">
|
||||
<trans lang="en_EN">Fade time in ms (needs VDR restart)</trans>
|
||||
<trans lang="de_DE">Einblendzeit in ms (erfordert VDR Neustart)</trans>
|
||||
<trans lang="fi_FI">Häivytyksen kesto [ms] (uud.käynnistys)</trans>
|
||||
<trans lang="en_EN">Fade time in ms</trans>
|
||||
<trans lang="de_DE">Einblendzeit in ms</trans>
|
||||
<trans lang="fi_FI">Häivytyksen kesto [ms]</trans>
|
||||
</token>
|
||||
<token name="tr(showdevices)">
|
||||
<trans lang="en_EN">Show DVB device info when switching channel</trans>
|
||||
|
@ -2,26 +2,13 @@
|
||||
<!DOCTYPE setup SYSTEM "../../dtd/setup.dtd">
|
||||
|
||||
<setup>
|
||||
<!--
|
||||
define all your parameters here which should be configurable via
|
||||
OSD and the skindesigner setup menu.
|
||||
Parameters must have type "bool" or "integer". For "bool" Parameters
|
||||
a choice yes/no is shown in the setup menu, a "integer" parameter
|
||||
can be configured to a value between "min" and "max". If "min" is not
|
||||
set, "0" is the minimum, if "max" is not set, "1000" is maximum.
|
||||
"displayname" is used to display the option in the setup menu.
|
||||
The configured parameter value is the default value.
|
||||
-->
|
||||
<parameters>
|
||||
<menu>
|
||||
<parameter type="bool" name="showposter" displaytext="{tr(showpostertext)}">1</parameter>
|
||||
<parameter type="bool" name="showweather" displaytext="{tr(showweather)}">1</parameter>
|
||||
<parameter type="int" name="fadeTime" min="0" max="1000" displaytext="{tr(fadeText)}">300</parameter>
|
||||
<parameter type="int" name="transparency" min="0" max="30" displaytext="{tr(transparency)}">20</parameter>
|
||||
</parameters>
|
||||
</menu>
|
||||
|
||||
<!--
|
||||
translations of displaytexts
|
||||
-->
|
||||
<translations>
|
||||
<token name="tr(showpostertext)">
|
||||
<trans lang="en_EN">Show Poster when switching channel</trans>
|
||||
@ -32,12 +19,12 @@
|
||||
<trans lang="de_DE">Wetter in Infobar anzeigen</trans>
|
||||
</token>
|
||||
<token name="tr(fadeText)">
|
||||
<trans lang="en_EN">Fade time in ms (needs VDR restart)</trans>
|
||||
<trans lang="de_DE">Einblendzeit in ms (erfordert VDR Neustart)</trans>
|
||||
<trans lang="en_EN">Fade time in ms</trans>
|
||||
<trans lang="de_DE">Einblendzeit in ms</trans>
|
||||
</token>
|
||||
<token name="tr(transparency)">
|
||||
<trans lang="en_EN">Transpareny channel, replay and volume (needs VDR restart)</trans>
|
||||
<trans lang="de_DE">Transparenz bei Kanal,Wiedergabe und Lautstärke (erfordert VDR Neustart)</trans>
|
||||
<trans lang="en_EN">Transpareny channel, replay and volume</trans>
|
||||
<trans lang="de_DE">Transparenz bei Kanal,Wiedergabe und Lautstärke</trans>
|
||||
</token>
|
||||
</translations>
|
||||
</setup>
|
||||
|
@ -5,15 +5,20 @@
|
||||
<!--
|
||||
define all your parameters here which should be configurable via
|
||||
OSD and the skindesigner setup menu.
|
||||
<submenu> and <parameter> tags are allowed, <submenu> can be nested
|
||||
with arbitrary depth.
|
||||
Submenus must carry the attributes "name" and "displaytext". "name"
|
||||
is for internal usage, "displaytext" is used for displaying the submenu
|
||||
in the menu and can be an translation token
|
||||
Parameters must have type "bool" or "integer". For "bool" Parameters
|
||||
a choice yes/no is shown in the setup menu, a "integer" parameter
|
||||
can be configured to a value between "min" and "max". If "min" is not
|
||||
set, "0" is the minimum, if "max" is not set, "1000" is maximum.
|
||||
"displayname" is used to display the option in the setup menu.
|
||||
"displaytext" is used to display the option in the setup menu.
|
||||
The configured parameter value is the default value.
|
||||
-->
|
||||
<parameters>
|
||||
</parameters>
|
||||
<menu>
|
||||
</menu>
|
||||
|
||||
<!--
|
||||
translations of displaytexts
|
||||
|
Loading…
Reference in New Issue
Block a user