def __init__(self):
GUIComponent.__init__(self)
self.l = eListboxServiceContent()
-
+
def getCurrent(self):
r = eServiceReference()
self.l.getCurrent(r)
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:
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:
<key id="m" mapto="mainMenu" flags="mr" />
<key id="c" mapto="switchChannel" flags="mr" />
</map>
- <map context="MainMenuActions">
- <key id=" " mapto="selected" flags="mr" />
- </map>
<map context="ChannelSelectActions">
- <key id=" " mapto="selectChannel" flags="mr" />
-
+ <key id="m" mapto="mark" flags="m" />
<!-- yes, this is flexible as hell. -->
- <key id="p" mapto="bouquet:PREMIERE" flags="m" />
- <key id="d" mapto="bouquet:Das Erste" flags="m" />
+ <key id="p" mapto="bouquet:(provider == PREMIERE)" flags="m" />
+ <key id="d" mapto="bouquet:(provider == ARD)" flags="m" />
+ </map>
+ <map context="OkCancelActions">
+ <key id="\x0a" mapto="ok" flags="mr" />
+ <key id="\x1b" mapto="cancel" flags="mr" />
</map>
<map context="WindowActions">
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]
return 1;
}
-RESULT eDVBChannelQuery::compile(ePtr<eDVBChannelQuery> &res, std::string query)
+/* (<name|provider|type|bouquet|satpos|chid> <==|...> <"string"|int>)[AND (..)] */
+
+ /* never, NEVER write a parser in C++! */
+RESULT parseExpression(ePtr<eDVBChannelQuery> &res, std::list<std::string>::const_iterator begin, std::list<std::string>::const_iterator end)
{
+ std::list<std::string>::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<eDVBChannelQuery> 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" <op> "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 <type> <op> <val>", 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<eDVBChannelQuery> &res, const eServiceReferenceDVB &source, std::string query)
+{
+ std::list<std::string> 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<std::string>::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);
class ServiceDescriptionTable;
+struct eDVBBouquet
+{
+ std::vector<eServiceReferenceDVB> m_services;
+ int lookupService(eServiceReferenceDVB &ref);
+};
+
class eDVBDB: public iDVBChannelList
{
DECLARE_REF(eDVBDB);
std::map<eDVBChannelID, channel> m_channels;
std::map<eServiceReferenceDVB, ePtr<eDVBService> > m_services;
+
+ std::map<eServiceReference, eDVBBouquet> m_bouquets;
public:
eDVBDB();
virtual ~eDVBDB();
RESULT addService(const eServiceReferenceDVB &service, eDVBService *service);
RESULT getService(const eServiceReferenceDVB &reference, ePtr<eDVBService> &service);
-
+
RESULT startQuery(ePtr<iDVBChannelListQuery> &query, eDVBChannelQuery *query);
};
std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator m_cursor;
ePtr<eDVBDB> m_db;
ePtr<eDVBChannelQuery> m_query;
+ eServiceReferenceDVB m_source;
public:
- eDVBDBQuery(eDVBDB *db, eDVBChannelQuery *query);
+ eDVBDBQuery(eDVBDB *db, const eServiceReferenceDVB &source, eDVBChannelQuery *query);
virtual RESULT getNextResult(eServiceReferenceDVB &ref);
};
m_top = 0;
m_selected = 0;
invalidate();
- eDebug("inval!");
}
painter.setForegroundColor(gColor(0x1C));
painter.setBackgroundColor(m_background_color);
break;
+ case styleListboxMarked:
+ painter.setForegroundColor(gColor(0x2F));
+ painter.setBackgroundColor(gColor(0x2A));
+ break;
}
}
enum {
styleLabel,
styleListboxSelected,
- styleListboxNormal
+ styleListboxNormal,
+ styleListboxMarked
};
virtual void drawFrame(gPainter &painter, const eRect &frame, int type) = 0;
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()
{
ePtr<gFont> 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())
#include <lib/gui/elistbox.h>
#include <lib/service/iservice.h>
+#include <set>
class eServiceCenter;
class eListboxServiceContent: public virtual iListboxContent
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();
ePtr<eServiceCenter> m_service_center;
eServiceReference m_root;
+
+ /* support for marked services */
+ std::set<eServiceReference> m_marked;
};
#endif
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 ]
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()
def __init__(self, session):
Screen.__init__(self, session)
- self["actions"] = ActionMap("InfobarActions",
+ self["actions"] = ActionMap( [ "InfobarActions" ],
{
"switchChannel": self.switchChannel,
"mainMenu": self.mainMenu