From: Felix Domke Date: Sun, 20 Mar 2005 22:55:46 +0000 (+0000) Subject: - improved parser X-Git-Tag: 2.6.0~5922 X-Git-Url: https://git.cweiske.de/enigma2.git/commitdiff_plain/3af66122574386a2856e83ba9c5d73d27a6f3710 - improved parser - improved keymaps --- diff --git a/components.py b/components.py index a5df8ffe..abf25f20 100644 --- a/components.py +++ b/components.py @@ -277,7 +277,7 @@ class ServiceList(HTMLComponent, GUIComponent): def __init__(self): GUIComponent.__init__(self) self.l = eListboxServiceContent() - + def getCurrent(self): r = eServiceReference() self.l.getCurrent(r) @@ -292,6 +292,19 @@ class ServiceList(HTMLComponent, GUIComponent): def setRoot(self, root): self.l.setRoot(root) + + # mark stuff + def clearMarked(self): + self.l.clearMarked() + + def isMarked(self, ref): + return self.l.isMarked(ref) + + def addMarked(self, ref): + self.l.addMarked(ref) + + def removeMarked(self, ref): + self.l.removeMarked(ref) class ServiceScan: @@ -338,20 +351,23 @@ class ServiceScan: return self.state == self.Done class ActionMap: - def __init__(self, context, actions = { }, prio=0): + def __init__(self, contexts = [ ], actions = { }, prio=0): self.actions = actions - self.context = context + self.contexts = contexts self.prio = prio self.p = eActionMapPtr() eActionMap.getInstance(self.p) def execBegin(self): - self.p.bindAction(self.context, self.prio, self.action) + for ctx in self.contexts: + self.p.bindAction(ctx, self.prio, self.action) def execEnd(self): - self.p.unbindAction(self.context, self.action) + for ctx in self.contexts: + self.p.unbindAction(ctx, self.action) def action(self, context, action): + print " ".join(("action -> ", context, action)) try: self.actions[action]() except KeyError: diff --git a/keymap.xml b/keymap.xml index 82b8a507..e940ba74 100644 --- a/keymap.xml +++ b/keymap.xml @@ -13,16 +13,16 @@ - - - - - + - - + + + + + + diff --git a/keymapparser.py b/keymapparser.py index 510a47a9..032805b3 100644 --- a/keymapparser.py +++ b/keymapparser.py @@ -52,6 +52,13 @@ def readKeymap(): if len(id) == 1: keyid = ord(id) | 0x8000 + elif id[0] == '\\': + if id[1] == 'x': + keyid = int(id[2:], 0x10) | 0x8000 + elif id[1] == 'd': + keyid = int(id[2:]) | 0x8000 + else: + raise "key id '" + str(id) + "' is neither hex nor dec" else: try: keyid = KEYIDS[id] diff --git a/lib/dvb/db.cpp b/lib/dvb/db.cpp index fe4bcc76..4e0332ba 100644 --- a/lib/dvb/db.cpp +++ b/lib/dvb/db.cpp @@ -357,13 +357,192 @@ RESULT eDVBDBQuery::getNextResult(eServiceReferenceDVB &ref) return 1; } -RESULT eDVBChannelQuery::compile(ePtr &res, std::string query) +/* ( <==|...> <"string"|int>)[AND (..)] */ + + /* never, NEVER write a parser in C++! */ +RESULT parseExpression(ePtr &res, std::list::const_iterator begin, std::list::const_iterator end) { + std::list::const_iterator end_of_exp; + if (*begin == "(") + { + end_of_exp = begin; + while (end_of_exp != end) + if (*end_of_exp == ")") + break; + else + ++end_of_exp; + + if (end_of_exp == end) + { + eDebug("expression parse: end of expression while searching for closing brace"); + return -1; + } + + ++begin; + // begin..end_of_exp + int r = parseExpression(res, begin, end_of_exp); + if (r) + return r; + ++end_of_exp; + + /* we had only one sub expression */ + if (end_of_exp == end) + return 1; + + /* otherwise we have an operator here.. */ + + ePtr r2 = res; + res = new eDVBChannelQuery(); + res->m_p1 = r2; + res->m_inverse = 0; + r2 = 0; + + if (*end_of_exp == "||") + res->m_type = eDVBChannelQuery::tOR; + else if (*end_of_exp == "&&") + res->m_type = eDVBChannelQuery::tAND; + else + { + eDebug("found operator %s, but only && and || are allowed!", end_of_exp->c_str()); + res = 0; + return 1; + } + + ++end_of_exp; + + return parseExpression(res->m_p2, end_of_exp, end); + } + + // "begin" "end" + std::string type, op, val; + + res = new eDVBChannelQuery(); + + int cnt = 0; + while (begin != end) + { + switch (cnt) + { + case 0: + type = *begin; + break; + case 1: + op = *begin; + break; + case 2: + val = *begin; + break; + case 3: + eDebug("malformed query: got '%s', but expected only ", begin->c_str()); + return 1; + } + ++begin; + ++cnt; + } + + if (cnt != 3) + { + eDebug("malformed query: missing stuff"); + res = 0; + return 1; + } + + if (type == "name") + res->m_type = eDVBChannelQuery::tName; + else if (type == "provider") + res->m_type = eDVBChannelQuery::tProvider; + else if (type == "type") + res->m_type = eDVBChannelQuery::tType; + else if (type == "bouquet") + res->m_type = eDVBChannelQuery::tBouquet; + else if (type == "satellitePosition") + res->m_type = eDVBChannelQuery::tSatellitePosition; + else if (type == "channelID") + res->m_type = eDVBChannelQuery::tChannelID; + else + { + eDebug("malformed query: invalid type %s", type.c_str()); + res = 0; + return 1; + } + + eDebug("type is %d, nice!", res->m_type); + + if (op == "==") + res->m_inverse = 0; + else if (op == "!=") + res->m_inverse = 1; + else + { + eDebug("invalid operator %s", op.c_str()); + res = 0; + return 1; + } + + res->m_string = val; + res->m_int = atoi(val.c_str()); +// res->m_channelid = eDVBChannelID(val); + + return 0; +} + +RESULT eDVBChannelQuery::compile(ePtr &res, const eServiceReferenceDVB &source, std::string query) +{ + std::list tokens; + + m_source = source; + + std::string current_token; + +// eDebug("splitting %s....", query.c_str()); + unsigned int i = 0; + const char *splitchars="()"; + int quotemode = 0, lastsplit = 0, lastalnum = 0; + while (i <= query.size()) + { + int c = (i < query.size()) ? query[i] : ' '; + ++i; + + int issplit = !!strchr(splitchars, c); + int isaln = isalnum(c); + int iswhite = c == ' '; + int isquot = c == '\"'; + + if (quotemode) + { + iswhite = issplit = 0; + isaln = lastalnum; + } + + if (issplit || iswhite || isquot || lastsplit || (lastalnum != isaln)) + { + if (current_token.size()) + tokens.push_back(current_token); + current_token.clear(); + } + + if (!(iswhite || isquot)) + current_token += c; + + if (isquot) + quotemode = !quotemode; + lastsplit = issplit; + lastalnum = isaln; + } + +// for (std::list::const_iterator a(tokens.begin()); a != tokens.end(); ++a) +// { +// printf("%s\n", a->c_str()); +// } + + /* now we recursivly parse that. */ + return parseExpression(res, tokens.begin(), tokens.end()); +/* res = new eDVBChannelQuery(); res->m_type = eDVBChannelQuery::tName; res->m_inverse = 0; res->m_string = query; - return 0; + return 0; */ } DEFINE_REF(eDVBChannelQuery); diff --git a/lib/dvb/db.h b/lib/dvb/db.h index 22eb0b74..7e31a22d 100644 --- a/lib/dvb/db.h +++ b/lib/dvb/db.h @@ -6,6 +6,12 @@ class ServiceDescriptionTable; +struct eDVBBouquet +{ + std::vector m_services; + int lookupService(eServiceReferenceDVB &ref); +}; + class eDVBDB: public iDVBChannelList { DECLARE_REF(eDVBDB); @@ -19,6 +25,8 @@ private: std::map m_channels; std::map > m_services; + + std::map m_bouquets; public: eDVBDB(); virtual ~eDVBDB(); @@ -30,7 +38,7 @@ public: RESULT addService(const eServiceReferenceDVB &service, eDVBService *service); RESULT getService(const eServiceReferenceDVB &reference, ePtr &service); - + RESULT startQuery(ePtr &query, eDVBChannelQuery *query); }; @@ -42,8 +50,9 @@ private: std::map >::iterator m_cursor; ePtr m_db; ePtr m_query; + eServiceReferenceDVB m_source; public: - eDVBDBQuery(eDVBDB *db, eDVBChannelQuery *query); + eDVBDBQuery(eDVBDB *db, const eServiceReferenceDVB &source, eDVBChannelQuery *query); virtual RESULT getNextResult(eServiceReferenceDVB &ref); }; diff --git a/lib/gui/elistbox.cpp b/lib/gui/elistbox.cpp index a3fae34c..a6fe45f1 100644 --- a/lib/gui/elistbox.cpp +++ b/lib/gui/elistbox.cpp @@ -196,5 +196,4 @@ void eListbox::entryReset() m_top = 0; m_selected = 0; invalidate(); - eDebug("inval!"); } diff --git a/lib/gui/ewindowstyle.cpp b/lib/gui/ewindowstyle.cpp index 3b8271f6..25b89460 100644 --- a/lib/gui/ewindowstyle.cpp +++ b/lib/gui/ewindowstyle.cpp @@ -80,6 +80,10 @@ void eWindowStyleSimple::setStyle(gPainter &painter, int what) painter.setForegroundColor(gColor(0x1C)); painter.setBackgroundColor(m_background_color); break; + case styleListboxMarked: + painter.setForegroundColor(gColor(0x2F)); + painter.setBackgroundColor(gColor(0x2A)); + break; } } diff --git a/lib/gui/ewindowstyle.h b/lib/gui/ewindowstyle.h index 6431c242..0014bfa4 100644 --- a/lib/gui/ewindowstyle.h +++ b/lib/gui/ewindowstyle.h @@ -17,7 +17,8 @@ public: enum { styleLabel, styleListboxSelected, - styleListboxNormal + styleListboxNormal, + styleListboxMarked }; virtual void drawFrame(gPainter &painter, const eRect &frame, int type) = 0; diff --git a/lib/service/listboxservice.cpp b/lib/service/listboxservice.cpp index 647dbdb9..db4f6b86 100644 --- a/lib/service/listboxservice.cpp +++ b/lib/service/listboxservice.cpp @@ -30,6 +30,43 @@ void eListboxServiceContent::getCurrent(eServiceReference &ref) ref = eServiceReference(); } +void eListboxServiceContent::initMarked() +{ + m_marked.clear(); +} + +void eListboxServiceContent::addMarked(const eServiceReference &ref) +{ + m_marked.insert(ref); + if (m_listbox) + m_listbox->entryChanged(lookupService(ref)); +} + +void eListboxServiceContent::removeMarked(const eServiceReference &ref) +{ + m_marked.erase(ref); + if (m_listbox) + m_listbox->entryChanged(lookupService(ref)); +} + +int eListboxServiceContent::isMarked(const eServiceReference &ref) +{ + return m_marked.find(ref) != m_marked.end(); +} + +int eListboxServiceContent::lookupService(const eServiceReference &ref) +{ + /* shortcut for cursor */ + if (ref == *m_cursor) + return m_cursor_number; + /* otherwise, search in the list.. */ + int index = 0; + for (list::const_iterator i(m_list.begin()); i != m_list.end(); ++i, ++index); + + /* this is ok even when the index was not found. */ + return index; +} + DEFINE_REF(eListboxServiceContent); eListboxServiceContent::eListboxServiceContent() @@ -118,7 +155,10 @@ void eListboxServiceContent::paint(gPainter &painter, eWindowStyle &style, const { ePtr fnt = new gFont("Arial", 14); painter.clip(eRect(offset, m_itemsize)); - style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal); + if (cursorValid() && isMarked(*m_cursor)) + style.setStyle(painter, eWindowStyle::styleListboxMarked); + else + style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal); painter.clear(); if (cursorValid()) diff --git a/lib/service/listboxservice.h b/lib/service/listboxservice.h index 231bab16..d5241933 100644 --- a/lib/service/listboxservice.h +++ b/lib/service/listboxservice.h @@ -4,6 +4,7 @@ #include #include +#include class eServiceCenter; class eListboxServiceContent: public virtual iListboxContent @@ -13,6 +14,14 @@ public: eListboxServiceContent(); void setRoot(const eServiceReference &ref); void getCurrent(eServiceReference &ref); + + /* support for marked services */ + void initMarked(); + void addMarked(const eServiceReference &ref); + void removeMarked(const eServiceReference &ref); + int isMarked(const eServiceReference &ref); + int lookupService(const eServiceReference &ref); + protected: void cursorHome(); @@ -44,6 +53,9 @@ private: ePtr m_service_center; eServiceReference m_root; + + /* support for marked services */ + std::set m_marked; }; #endif diff --git a/screens.py b/screens.py index dd13c550..82646282 100644 --- a/screens.py +++ b/screens.py @@ -58,9 +58,10 @@ class mainMenu(Screen): Screen.__init__(self, session) b = Button("ok") - self["actions"] = ActionMap("MainMenuActions", + self["actions"] = ActionMap(["OkCancelActions"], { - "selected": self.okbuttonClick + "ok": self.okbuttonClick, + "cancel": self.close }) b.onClick = [ self.okbuttonClick ] @@ -90,24 +91,33 @@ class channelSelection(Screen): Screen.__init__(self, session) self["list"] = ServiceList() - self["list"].setRoot(eServiceReference("1:0:1:0:0:0:0:0:0:0:PREMIERE")) + self["list"].setRoot(eServiceReference("""1:0:1:0:0:0:0:0:0:0:(provider=="ARD") && (type == 1)""")) self["okbutton"] = Button("ok", [self.channelSelected]) class ChannelActionMap(ActionMap): - def action(self, context, action): + def action(self, contexts, action): if action[:7] == "bouquet": print "setting root to " + action[8:] self.csel["list"].setRoot(eServiceReference("1:0:1:0:0:0:0:0:0:0:" + action[8:])) else: - ActionMap.action(self, context, action) + ActionMap.action(self, contexts, action) - self["actions"] = ChannelActionMap("ChannelSelectActions", + self["actions"] = ChannelActionMap(["ChannelSelectActions", "OkCancelActions"], { - "selectChannel": self.channelSelected, + "cancel": self.close, + "ok": self.channelSelected, + "mark": self.doMark }) self["actions"].csel = self + def doMark(self): + ref = self["list"].getCurrent() + if self["list"].isMarked(ref): + self["list"].removeMarked(ref) + else: + self["list"].addMarked(ref) + def channelSelected(self): self.session.nav.playService(self["list"].getCurrent()) self.close() @@ -117,7 +127,7 @@ class infoBar(Screen): def __init__(self, session): Screen.__init__(self, session) - self["actions"] = ActionMap("InfobarActions", + self["actions"] = ActionMap( [ "InfobarActions" ], { "switchChannel": self.switchChannel, "mainMenu": self.mainMenu