/*************************************************************************** cmddef.cpp - description ------------------- begin : Sun Mar 17 2002 copyright : (C) 2002 by Vladimir Shutoff email : vovan@shutoff.ru ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "cmddef.h" #include "event.h" #include "log.h" #include "misc.h" namespace SIM { using namespace std; Command::Command() { m_cmd.clear(); } CommandDef &Command::operator=(const CommandDef &cmd) { m_cmd = cmd; return m_cmd; } class CommandsDefPrivate : public EventReceiver { public: CommandsDefPrivate(unsigned id, bool bMenu); void setConfig(const QString &cfg); virtual bool processEvent(Event *e); bool addCommand(const CommandDef *cmd); bool changeCommand(const CommandDef *cmd); bool delCommand(unsigned id); void generateConfig(); list buttons; list cfg; QString config; unsigned m_id; bool m_bMenu; }; CommandsDefPrivate::CommandsDefPrivate(unsigned id, bool bMenu) { m_id = id; m_bMenu = bMenu; } bool CommandsDefPrivate::changeCommand(const CommandDef *cmd) { list::iterator it; for (it = buttons.begin(); it != buttons.end(); ++it){ if ((*it).id == cmd->id){ (*it) = *cmd; return true; } } return false; } bool CommandsDefPrivate::addCommand(const CommandDef *cmd) { if (changeCommand(cmd)) return false; unsigned item_grp = m_bMenu ? cmd->menu_grp : cmd->bar_grp; if (item_grp){ list::iterator it; for (it = buttons.begin(); it != buttons.end(); ++it){ unsigned grp = m_bMenu ? (*it).menu_grp : (*it).bar_grp; if (grp > item_grp){ buttons.insert(it, *cmd); return true; } } } buttons.push_back(*cmd); return true; } bool CommandsDefPrivate::delCommand(unsigned id) { for (list::iterator it = buttons.begin(); it != buttons.end(); ++it){ if ((*it).id == id){ buttons.erase(it); return true; } } return false; } bool CommandsDefPrivate::processEvent(Event *e) { list::iterator it; switch (e->type()){ case eEventCommandCreate: { EventCommandCreate *ecc = static_cast(e); CommandDef *def = ecc->cmd(); if (((m_bMenu ? def->menu_id : def->bar_id) == m_id) && (m_bMenu || def->icon)){ if (addCommand(def)) cfg.clear(); } break; } case eEventCommandChange: { EventCommandChange *ecc = static_cast(e); CommandDef *def = ecc->cmd(); if (def->param == NULL){ for (it = buttons.begin(); it != buttons.end(); ++it){ if ((*it).id == def->id){ *it = *def; break; } } } break; } case eEventCommandRemove: { EventCommandRemove *ecr = static_cast(e); if (delCommand(ecr->id())) cfg.clear(); break; } default: break; } return false; } void CommandsDefPrivate::setConfig(const QString &cfg_str) { if (cfg_str == config && cfg.size()) return; cfg.clear(); config = cfg_str; generateConfig(); } void CommandsDefPrivate::generateConfig() { if (cfg.size()) return; if (config.length()){ list processed; QString active = config; QString noactive; int n = config.find('/'); if (n >= 0){ active = config.left(n); noactive = config.mid(n + 1); } while (active.length()){ QString v = getToken(active, ','); unsigned id = v.toUInt(); cfg.push_back(id); if (id) processed.push_back(id); } while (noactive.length()){ QString v = getToken(noactive, ','); unsigned id = v.toUInt(); if (id) processed.push_back(id); } for (list::iterator it = buttons.begin(); it != buttons.end(); ++it){ CommandDef &c = (*it); unsigned grp = m_bMenu ? c.menu_grp : c.bar_grp; if (grp == 0) continue; list::iterator it_p; for (it_p = processed.begin(); it_p != processed.end(); ++it_p) if ((*it_p) == c.id) break; if (it_p != processed.end()) continue; unsigned cur_grp = 0; for (it_p = cfg.begin(); it_p != cfg.end(); ++it_p){ if ((*it_p) == 0){ if (cur_grp == grp) break; continue; } list::iterator itl; for (itl = buttons.begin(); itl != buttons.end(); ++itl) if ((*itl).id == (*it_p)) break; if (itl == buttons.end()) continue; unsigned itl_grp = m_bMenu ? (*itl).menu_grp : (*itl).bar_grp; if (itl_grp == 0) continue; cur_grp = itl_grp; if (grp > cur_grp) break; } cfg.insert(it_p, c.id); } }else{ unsigned cur_grp = 0; for (list::iterator it = buttons.begin(); it != buttons.end(); ++it){ CommandDef &c = (*it); unsigned grp = m_bMenu ? c.menu_grp : c.bar_grp; if (grp == 0) continue; if ((grp & ~0xFF) != (cur_grp & ~0xFF)){ if (cur_grp) cfg.push_back(0); } cur_grp = grp; cfg.push_back(c.id); } } } class CommandsListPrivate { public: CommandsListPrivate(CommandsDefPrivate *def); virtual ~CommandsListPrivate() {} virtual CommandDef *next() = 0; virtual void reset() = 0; CommandsDefPrivate *m_def; }; CommandsListPrivate::CommandsListPrivate(CommandsDefPrivate *def) { m_def = def; } class CommandsListPrivateFull : public CommandsListPrivate { public: CommandsListPrivateFull(CommandsDefPrivate *p); list::iterator it; virtual CommandDef *next(); virtual void reset(); }; CommandsListPrivateFull::CommandsListPrivateFull(CommandsDefPrivate *def) : CommandsListPrivate(def) { reset(); } void CommandsListPrivateFull::reset() { it = m_def->buttons.begin(); } CommandDef *CommandsListPrivateFull::next() { if (it == m_def->buttons.end()) return NULL; CommandDef *res = &(*it); ++it; return res; } class CommandsListPrivateShort : public CommandsListPrivate { public: CommandsListPrivateShort(CommandsDefPrivate *p); list::iterator it; virtual CommandDef *next(); virtual void reset(); }; CommandsListPrivateShort::CommandsListPrivateShort(CommandsDefPrivate *def) : CommandsListPrivate(def) { reset(); } void CommandsListPrivateShort::reset() { it = m_def->cfg.begin(); } static CommandDef SeparatorDef = CommandDef (); CommandDef *CommandsListPrivateShort::next() { for (;;++it){ if (it == m_def->cfg.end()) return NULL; unsigned id = (*it); if (id == 0){ ++it; return &SeparatorDef; } for (list::iterator itb = m_def->buttons.begin(); itb != m_def->buttons.end(); ++itb){ if ((*itb).id == id){ ++it; return &(*itb); } } } } CommandsList::CommandsList(CommandsDef &def, bool bFull) { def.p->generateConfig(); if (bFull){ p = new CommandsListPrivateFull(def.p); }else{ p = new CommandsListPrivateShort(def.p); } } CommandsList::~CommandsList() { delete p; } CommandDef *CommandsList::operator ++() { CommandDef *c = p->next(); return c; } void CommandsList::reset() { p->reset(); } CommandsDef::CommandsDef(unsigned id, bool bMenu) { p = new CommandsDefPrivate(id, bMenu); } CommandsDef::~CommandsDef() { delete p; } unsigned CommandsDef::id() { return p->m_id; } bool CommandsDef::isMenu() { return p->m_bMenu; } void CommandsDef::set(const CommandDef *cmd) { p->changeCommand(cmd); } void CommandsDef::set(const CommandDef &cmd) { p->changeCommand(&cmd); } void CommandsDef::setConfig(const QString &cfg_str) { p->setConfig(cfg_str); } class CommandsMapPrivate : public map { }; CommandsMap::CommandsMap() { p = new CommandsMapPrivate; } CommandsMap::~CommandsMap() { delete p; } CommandDef *CommandsMap::find(unsigned id) { CommandsMapPrivate::iterator it = p->find(id); if (it == p->end()) return NULL; return &(*it).second; } bool CommandsMap::add(CommandDef *def) { CommandsMapPrivate::iterator it = p->find(def->id); if (it == p->end()){ p->insert(CommandsMapPrivate::value_type(def->id, *def)); return true; } (*it).second = *def; return false; } bool CommandsMap::erase(unsigned id) { CommandsMapPrivate::iterator it = p->find(id); if (it == p->end()) return false; p->erase(it); return true; } void CommandsMap::clear() { log(L_DEBUG, "CommandsMap::clear %p", this); p->clear(); } class CommandsMapIteratorPrivate { COPY_RESTRICTED(CommandsMapIteratorPrivate) public: CommandsMapIteratorPrivate(CommandsMapPrivate &_map) : map(_map) { it = map.begin(); } CommandsMapPrivate::iterator it; CommandsMapPrivate ↦ }; CommandsMapIterator::CommandsMapIterator(CommandsMap &m) { log(L_DEBUG, "CommandsMapIterator for %p", &m); p = new CommandsMapIteratorPrivate(*m.p); } CommandsMapIterator::~CommandsMapIterator() { delete p; } CommandDef *CommandsMapIterator::operator++() { if (p->it == p->map.end()) return NULL; CommandDef *res = &(*p->it).second; ++(p->it); return res; } }