Back to index

easystroke  0.5.5.1
actiondb.h
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2008-2009, Thomas Jaeger <ThJaeger@gmail.com>
00003  *
00004  * Permission to use, copy, modify, and/or distribute this software for any
00005  * purpose with or without fee is hereby granted, provided that the above
00006  * copyright notice and this permission notice appear in all copies.
00007  *
00008  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
00009  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00010  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
00011  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00012  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
00013  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
00014  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00015  */
00016 #ifndef __STROKEDB_H__
00017 #define __STROKEDB_H__
00018 #include <string>
00019 #include <map>
00020 #include <set>
00021 #include <boost/serialization/access.hpp>
00022 #include <boost/serialization/version.hpp>
00023 #include <boost/serialization/split_member.hpp>
00024 #include <iostream>
00025 
00026 #include "gesture.h"
00027 #include "prefdb.h"
00028 
00029 class Action;
00030 class Command;
00031 class SendKey;
00032 class SendText;
00033 class Scroll;
00034 class Ignore;
00035 class Button;
00036 class Misc;
00037 class Ranking;
00038 
00039 typedef boost::shared_ptr<Action> RAction;
00040 typedef boost::shared_ptr<Command> RCommand;
00041 typedef boost::shared_ptr<SendKey> RSendKey;
00042 typedef boost::shared_ptr<SendText> RSendText;
00043 typedef boost::shared_ptr<Scroll> RScroll;
00044 typedef boost::shared_ptr<Ignore> RIgnore;
00045 typedef boost::shared_ptr<Button> RButton;
00046 typedef boost::shared_ptr<Misc> RMisc;
00047 typedef boost::shared_ptr<Ranking> RRanking;
00048 
00049 class Unique;
00050 
00051 class Modifiers;
00052 typedef boost::shared_ptr<Modifiers> RModifiers;
00053 
00054 class Action {
00055        friend class boost::serialization::access;
00056        friend std::ostream& operator<<(std::ostream& output, const Action& c);
00057        template<class Archive> void serialize(Archive & ar, const unsigned int version);
00058 public:
00059        virtual void run() {}
00060        virtual RModifiers prepare() { return RModifiers(); }
00061        virtual const Glib::ustring get_label() const = 0;
00062 };
00063 
00064 class Command : public Action {
00065        friend class boost::serialization::access;
00066        template<class Archive> void serialize(Archive & ar, const unsigned int version);
00067        Command(const std::string &c) : cmd(c) {}
00068 public:
00069        std::string cmd;
00070        Command() {}
00071        static RCommand create(const std::string &c) { return RCommand(new Command(c)); }
00072        virtual void run();
00073        virtual const Glib::ustring get_label() const { return cmd; }
00074 };
00075 
00076 class ModAction : public Action {
00077        friend class boost::serialization::access;
00078        template<class Archive> void serialize(Archive & ar, const unsigned int version);
00079 protected:
00080        ModAction() {}
00081        Gdk::ModifierType mods;
00082        ModAction(Gdk::ModifierType mods_) : mods(mods_) {}
00083        virtual RModifiers prepare();
00084 public:
00085        virtual const Glib::ustring get_label() const;
00086 };
00087 
00088 class SendKey : public ModAction {
00089        friend class boost::serialization::access;
00090        guint key;
00091        BOOST_SERIALIZATION_SPLIT_MEMBER()
00092        template<class Archive> void load(Archive & ar, const unsigned int version);
00093        template<class Archive> void save(Archive & ar, const unsigned int version) const;
00094        SendKey(guint key_, Gdk::ModifierType mods) :
00095               ModAction(mods), key(key_) {}
00096 public:
00097        SendKey() {}
00098        static RSendKey create(guint key, Gdk::ModifierType mods) {
00099               return RSendKey(new SendKey(key, mods));
00100        }
00101 
00102        virtual void run();
00103        virtual RModifiers prepare();
00104        virtual const Glib::ustring get_label() const;
00105 };
00106 BOOST_CLASS_VERSION(SendKey, 1)
00107 #define IS_KEY(act) (act && dynamic_cast<SendKey *>(act.get()))
00108 
00109 class SendText : public Action {
00110        friend class boost::serialization::access;
00111        Glib::ustring text;
00112        BOOST_SERIALIZATION_SPLIT_MEMBER()
00113        template<class Archive> void load(Archive & ar, const unsigned int version);
00114        template<class Archive> void save(Archive & ar, const unsigned int version) const;
00115        SendText(Glib::ustring text_) : text(text_) {}
00116 public:
00117        SendText() {}
00118        static RSendText create(Glib::ustring text) { return RSendText(new SendText(text)); }
00119 
00120        virtual void run();
00121        virtual const Glib::ustring get_label() const { return text; }
00122 };
00123 
00124 class Scroll : public ModAction {
00125        friend class boost::serialization::access;
00126        template<class Archive> void serialize(Archive & ar, const unsigned int version);
00127        Scroll(Gdk::ModifierType mods) : ModAction(mods) {}
00128 public:
00129        Scroll() {}
00130        static RScroll create(Gdk::ModifierType mods) { return RScroll(new Scroll(mods)); }
00131        virtual const Glib::ustring get_label() const;
00132 };
00133 #define IS_SCROLL(act) (act && dynamic_cast<Scroll *>(act.get()))
00134 
00135 class Ignore : public ModAction {
00136        friend class boost::serialization::access;
00137        template<class Archive> void serialize(Archive & ar, const unsigned int version);
00138        Ignore(Gdk::ModifierType mods) : ModAction(mods) {}
00139 public:
00140        Ignore() {}
00141        static RIgnore create(Gdk::ModifierType mods) { return RIgnore(new Ignore(mods)); }
00142        virtual const Glib::ustring get_label() const;
00143 };
00144 #define IS_IGNORE(act) (act && dynamic_cast<Ignore *>(act.get()))
00145 
00146 class Button : public ModAction {
00147        friend class boost::serialization::access;
00148        template<class Archive> void serialize(Archive & ar, const unsigned int version);
00149        Button(Gdk::ModifierType mods, guint button_) : ModAction(mods), button(button_) {}
00150        guint button;
00151 public:
00152        Button() {}
00153        ButtonInfo get_button_info() const;
00154        static unsigned int get_button(RAction act) {
00155               if (!act)
00156                      return 0;
00157               Button *b = dynamic_cast<Button *>(act.get());
00158               if (!b)
00159                      return 0;
00160               return b->get_button_info().button;
00161        }
00162        static RButton create(Gdk::ModifierType mods, guint button_) { return RButton(new Button(mods, button_)); }
00163        virtual const Glib::ustring get_label() const;
00164        virtual void run();
00165 };
00166 #define IF_BUTTON(act, b) if (unsigned int b = Button::get_button(act))
00167 
00168 class Misc : public Action {
00169        friend class boost::serialization::access;
00170 public:
00171        enum Type { NONE, UNMINIMIZE, SHOWHIDE, DISABLE };
00172        Type type;
00173 private:
00174        template<class Archive> void serialize(Archive & ar, const unsigned int version);
00175        Misc(Type t) : type(t) {}
00176 public:
00177        static const char *types[5];
00178        Misc() {}
00179        virtual const Glib::ustring get_label() const;
00180        static RMisc create(Type t) { return RMisc(new Misc(t)); }
00181        virtual void run();
00182 };
00183 
00184 class StrokeSet : public std::set<RStroke> {
00185        friend class boost::serialization::access;
00186        template<class Archive> void serialize(Archive & ar, const unsigned int version);
00187 };
00188 
00189 // Internal use only
00190 class Click : public Action {
00191        virtual const Glib::ustring get_label() const { return "Click"; }
00192 };
00193 #define IS_CLICK(act) (act && dynamic_cast<Click *>(act.get()))
00194 
00195 class StrokeInfo {
00196        friend class boost::serialization::access;
00197        template<class Archive> void serialize(Archive & ar, const unsigned int version);
00198 public:
00199        StrokeInfo(RStroke s, RAction a) : action(a) { strokes.insert(s); }
00200        StrokeInfo() {}
00201        StrokeSet strokes;
00202        RAction action;
00203        std::string name;
00204 };
00205 typedef boost::shared_ptr<StrokeInfo> RStrokeInfo;
00206 BOOST_CLASS_VERSION(StrokeInfo, 1)
00207 
00208 class Ranking {
00209        static bool show(RRanking r);
00210        int x, y;
00211 public:
00212        RStroke stroke, best_stroke;
00213        RAction action;
00214        double score;
00215        std::string name;
00216        std::multimap<double, std::pair<std::string, RStroke> > r;
00217        static void queue_show(RRanking r, RTriple e);
00218 };
00219 
00220 class Unique {
00221        friend class boost::serialization::access;
00222        template<class Archive> void serialize(Archive & ar, const unsigned int version);
00223 public:
00224        int level;
00225        int i;
00226 };
00227 
00228 class ActionListDiff {
00229        friend class boost::serialization::access;
00230        friend class ActionDB;
00231        template<class Archive> void serialize(Archive & ar, const unsigned int version);
00232        ActionListDiff *parent;
00233        std::set<Unique *> deleted;
00234        std::map<Unique *, StrokeInfo> added;
00235        std::list<Unique *> order;
00236        std::list<ActionListDiff> children;
00237 
00238        void update_order() {
00239               int j = 0;
00240               for (std::list<Unique *>::iterator i = order.begin(); i != order.end(); i++, j++) {
00241                      (*i)->level = level;
00242                      (*i)->i = j;
00243               }
00244        }
00245 
00246        void fix_tree(bool rebuild_order) {
00247               if (rebuild_order)
00248                      for (std::map<Unique *, StrokeInfo>::iterator i = added.begin(); i != added.end(); i++)
00249                             if (!(parent && parent->contains(i->first)))
00250                                    order.push_back(i->first);
00251               update_order();
00252               for (std::list<ActionListDiff>::iterator i = children.begin(); i != children.end(); i++) {
00253                      i->parent = this;
00254                      i->level = level + 1;
00255                      i->fix_tree(rebuild_order);
00256               }
00257        }
00258 public:
00259        int level;
00260        bool app;
00261        std::string name;
00262 
00263        ActionListDiff() : parent(0), level(0), app(false) {}
00264 
00265        typedef std::list<ActionListDiff>::iterator iterator;
00266        iterator begin() { return children.begin(); }
00267        iterator end() { return children.end(); }
00268 
00269        RStrokeInfo get_info(Unique *id, bool *deleted = 0, bool *stroke = 0, bool *name = 0, bool *action = 0) const;
00270        int order_size() const { return order.size(); }
00271        int size_rec() const {
00272               int size = added.size();
00273               for (std::list<ActionListDiff>::const_iterator i = children.begin(); i != children.end(); i++)
00274                      size += i->size_rec();
00275               return size;
00276        }
00277        bool resettable(Unique *id) const {
00278               return parent && (added.count(id) || deleted.count(id)) && parent->contains(id);
00279        }
00280 
00281        Unique *add(StrokeInfo &si, Unique *before = 0) {
00282               Unique *id = new Unique;
00283               added.insert(std::pair<Unique *, StrokeInfo>(id, si));
00284               id->level = level;
00285               id->i = order.size();
00286               if (before)
00287                      order.insert(std::find(order.begin(), order.end(), before), id);
00288               else
00289                      order.push_back(id);
00290               update_order();
00291               return id;
00292        }
00293        void set_action(Unique *id, RAction action) { added[id].action = action; }
00294        void set_strokes(Unique *id, StrokeSet strokes) { added[id].strokes = strokes; }
00295        void set_name(Unique *id, std::string name) { added[id].name = name; }
00296        bool contains(Unique *id) const {
00297               if (deleted.count(id))
00298                      return false;
00299               if (added.count(id))
00300                      return true;
00301               return parent && parent->contains(id);
00302        }
00303        bool remove(Unique *id) {
00304               bool really = !(parent && parent->contains(id));
00305               if (really) {
00306                      added.erase(id);
00307                      order.remove(id);
00308                      update_order();
00309               } else
00310                      deleted.insert(id);
00311               for (std::list<ActionListDiff>::iterator i = children.begin(); i != children.end(); i++)
00312                      i->remove(id);
00313               return really;
00314        }
00315        void reset(Unique *id) {
00316               if (!parent)
00317                      return;
00318               added.erase(id);
00319               deleted.erase(id);
00320        }
00321        void add_apps(std::map<std::string, ActionListDiff *> &apps) {
00322               if (app)
00323                      apps[name] = this;
00324               for (std::list<ActionListDiff>::iterator i = children.begin(); i != children.end(); i++)
00325                      i->add_apps(apps);
00326        }
00327        ActionListDiff *add_child(std::string name, bool app) {
00328               children.push_back(ActionListDiff());
00329               ActionListDiff *child = &(children.back());
00330               child->name = name;
00331               child->app = app;
00332               child->parent = this;
00333               child->level = level + 1;
00334               return child;
00335        }
00336        bool remove() {
00337               if (!parent)
00338                      return false;
00339               for (std::list<ActionListDiff>::iterator i = parent->children.begin(); i != parent->children.end(); i++) {
00340                      if (&*i == this) {
00341                             parent->children.erase(i);
00342                             return true;
00343                      }
00344 
00345               }
00346               return false;
00347        }
00348        bool move(Unique *src, Unique *dest) {
00349               if (!src)
00350                      return false;
00351               if (src == dest)
00352                      return false;
00353               if (parent && parent->contains(src))
00354                      return false;
00355               if (dest && parent && parent->contains(dest))
00356                      return false;
00357               if (!added.count(src))
00358                      return false;
00359               if (dest && !added.count(dest))
00360                      return false;
00361               order.remove(src);
00362               order.insert(dest ? std::find(order.begin(), order.end(), dest) : order.end(), src);
00363               update_order();
00364               return true;
00365        }
00366 
00367        boost::shared_ptr<std::map<Unique *, StrokeSet> > get_strokes() const;
00368        boost::shared_ptr<std::set<Unique *> > get_ids(bool include_deleted) const;
00369        int count_actions() const {
00370               return (parent ? parent->count_actions() : 0) + order.size() - deleted.size();
00371        }
00372        void all_strokes(std::list<RStroke> &strokes) const;
00373        RAction handle(RStroke s, RRanking &r) const;
00374        // b1 is always reported as b2
00375        void handle_advanced(RStroke s, std::map<guint, RAction> &a, std::map<guint, RRanking> &r, int b1, int b2) const;
00376 
00377        ~ActionListDiff();
00378 };
00379 BOOST_CLASS_VERSION(ActionListDiff, 1)
00380 
00381 class ActionDB {
00382        friend class boost::serialization::access;
00383        friend class ActionDBWatcher;
00384        template<class Archive> void load(Archive & ar, const unsigned int version);
00385        template<class Archive> void save(Archive & ar, const unsigned int version) const;
00386        BOOST_SERIALIZATION_SPLIT_MEMBER()
00387 
00388 public:
00389        std::map<std::string, ActionListDiff *> apps;
00390 private:
00391        ActionListDiff root;
00392 public:
00393        typedef std::map<Unique *, StrokeInfo>::const_iterator const_iterator;
00394        const const_iterator begin() const { return root.added.begin(); }
00395        const const_iterator end() const { return root.added.end(); }
00396 
00397        ActionListDiff *get_root() { return &root; }
00398 
00399        const ActionListDiff *get_action_list(std::string wm_class) const {
00400               std::map<std::string, ActionListDiff *>::const_iterator i = apps.find(wm_class);
00401               return i == apps.end() ? &root : i->second;
00402        }
00403        ActionDB();
00404 };
00405 BOOST_CLASS_VERSION(ActionDB, 3)
00406 
00407 class ActionDBWatcher : public TimeoutWatcher {
00408        bool good_state;
00409 public:
00410        ActionDBWatcher() : TimeoutWatcher(5000), good_state(true) {}
00411        void init();
00412        virtual void timeout();
00413 };
00414 
00415 extern ActionDB actions;
00416 void update_actions();
00417 #endif