-rw-r--r-- | src/sleep_history.cc | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/src/sleep_history.cc b/src/sleep_history.cc new file mode 100644 index 0000000..1b5ce27 --- a/dev/null +++ b/src/sleep_history.cc | |||
@@ -0,0 +1,158 @@ | |||
1 | #include <gtkmm/main.h> | ||
2 | #include <napkin/util.h> | ||
3 | |||
4 | #include "sleep_timeline.h" | ||
5 | #include "sleep_history.h" | ||
6 | |||
7 | namespace napkin { | ||
8 | namespace gtk { | ||
9 | |||
10 | sleep_history_t::basic_textrenderer::basic_textrenderer() { | ||
11 | property_family().set_value("monospace"); | ||
12 | property_single_paragraph_mode().set_value(true); | ||
13 | } | ||
14 | void sleep_history_t::basic_textrenderer::render_vfunc( | ||
15 | const Glib::RefPtr<Gdk::Drawable>& window, Gtk::Widget& widget, | ||
16 | const Gdk::Rectangle& background_area, const Gdk::Rectangle& cell_area, | ||
17 | const Gdk::Rectangle& expose_area, Gtk::CellRendererState flags) { | ||
18 | hypnodata_t *hd = (hypnodata_t*)property_user_data().get_value(); | ||
19 | property_text().set_value(hd?get_text(*hd).c_str():""); | ||
20 | Gtk::CellRendererText::render_vfunc(window,widget, | ||
21 | background_area,cell_area,expose_area, | ||
22 | flags); | ||
23 | } | ||
24 | |||
25 | const string sleep_history_t::date_render_t::get_text(const hypnodata_t& hd) const { | ||
26 | return hd.str_date(); } | ||
27 | const string sleep_history_t::tobed_render_t::get_text(const hypnodata_t& hd) const { | ||
28 | return hd.str_to_bed(); } | ||
29 | const string sleep_history_t::alarm_render_t::get_text(const hypnodata_t& hd) const { | ||
30 | return hd.str_alarm(); } | ||
31 | sleep_history_t::window_render_t::window_render_t() { | ||
32 | property_xalign().set_value(1); } | ||
33 | const string sleep_history_t::window_render_t::get_text( | ||
34 | const hypnodata_t& hd) const { | ||
35 | char tmp[16]; | ||
36 | snprintf(tmp,sizeof(tmp),"%2d",hd.window); | ||
37 | return tmp; | ||
38 | } | ||
39 | sleep_history_t::nawakes_render_t::nawakes_render_t() { | ||
40 | property_xalign().set_value(1); } | ||
41 | const string sleep_history_t::nawakes_render_t::get_text( | ||
42 | const hypnodata_t& hd) const { | ||
43 | char tmp[16]; | ||
44 | snprintf(tmp,sizeof(tmp),"%2d",(int)hd.almost_awakes.size()); | ||
45 | return tmp; | ||
46 | } | ||
47 | const string sleep_history_t::data_a_render_t::get_text(const hypnodata_t& hd) const { | ||
48 | return hd.str_data_a(); } | ||
49 | |||
50 | sleep_history_t::sleep_timeline_render_t::sleep_timeline_render_t( | ||
51 | const sleep_history_t& sh) : sleep_history(sh) | ||
52 | { | ||
53 | property_xpad().set_value(2); property_ypad().set_value(2); | ||
54 | } | ||
55 | void sleep_history_t::sleep_timeline_render_t::render_vfunc( | ||
56 | const Glib::RefPtr<Gdk::Drawable>& window, Gtk::Widget&/*widget*/, | ||
57 | const Gdk::Rectangle&/*background_area*/, const Gdk::Rectangle& cell_area, | ||
58 | const Gdk::Rectangle&/*expose_area*/, Gtk::CellRendererState/*flags*/) { | ||
59 | hypnodata_t *hd = (hypnodata_t*)property_user_data().get_value(); | ||
60 | if(!hd) return; | ||
61 | int xpad = property_xpad(), ypad = property_ypad(); | ||
62 | int x0 = cell_area.get_x()+xpad, y0 = cell_area.get_y()+ypad, | ||
63 | dx = cell_area.get_width()-2*xpad, dy = cell_area.get_height()-2*ypad; | ||
64 | time_t a = hd->aligned_start(); | ||
65 | gtk::render_sleep_timeline( | ||
66 | *hd, | ||
67 | window, | ||
68 | x0,y0, dx,dy, | ||
69 | a+sleep_history.min_tobed, | ||
70 | a+sleep_history.max_alarm ); | ||
71 | } | ||
72 | |||
73 | sleep_history_t::sleep_history_t(db_t& d) | ||
74 | : store( Gtk::ListStore::create(cols) ), | ||
75 | r_sleep_timeline(*this), | ||
76 | min_tobed(24*60*60*2), max_alarm(0), | ||
77 | db(d) | ||
78 | { | ||
79 | w_tree.set_model(store); | ||
80 | add(w_tree); | ||
81 | append_c("Date",r_date); | ||
82 | append_c("To bed",r_to_bed); | ||
83 | (c_timeline=append_c("Sleep timeline",r_sleep_timeline))->set_expand(true); | ||
84 | append_c("Alarm",r_alarm); | ||
85 | append_c("Window",r_window); | ||
86 | append_c(" N",r_nawakes); | ||
87 | append_c("Data A",r_data_a); | ||
88 | |||
89 | w_tree.signal_query_tooltip().connect( | ||
90 | sigc::mem_fun(*this,&sleep_history_t::on_query_tooltip)); | ||
91 | w_tree.set_has_tooltip(true); | ||
92 | w_tree.signal_button_press_event().connect( | ||
93 | sigc::mem_fun(*this,&sleep_history_t::on_button_press),false); | ||
94 | } | ||
95 | |||
96 | Gtk::TreeView::Column *sleep_history_t::append_c(const string& title,Gtk::CellRenderer& renderer) { | ||
97 | Gtk::TreeView::Column *rv = w_tree.get_column(w_tree.append_column(title,renderer)-1); | ||
98 | rv->add_attribute(renderer.property_user_data(),cols.c_hypnodata_ptr); | ||
99 | rv->set_resizable(true); | ||
100 | return rv; | ||
101 | } | ||
102 | |||
103 | bool sleep_history_t::on_button_press(GdkEventButton* geb) { | ||
104 | if(geb->type!=GDK_2BUTTON_PRESS) return false; | ||
105 | double_click_signal(); | ||
106 | return true; | ||
107 | } | ||
108 | |||
109 | bool sleep_history_t::on_query_tooltip( | ||
110 | int x,int y,bool keyboard_tooltip, | ||
111 | const Glib::RefPtr<Gtk::Tooltip>& tooltip) { | ||
112 | if(keyboard_tooltip) return false; | ||
113 | int tx,ty; | ||
114 | w_tree.convert_widget_to_tree_coords(x,y,tx,ty); | ||
115 | Gtk::TreeModel::Path p; | ||
116 | Gtk::TreeViewColumn *c; | ||
117 | int cx, cy; | ||
118 | if(!w_tree.get_path_at_pos(tx,ty,p,c,cx,cy)) return false; | ||
119 | if(c != c_timeline) return false; | ||
120 | hypnodata_ptr_t hd = store->get_iter(p)->get_value(cols.c_hypnodata); | ||
121 | string mup = "Almost awake moments are:\n\n<tt>"; | ||
122 | for(vector<time_t>::const_iterator i=hd->almost_awakes.begin();i!=hd->almost_awakes.end();++i) | ||
123 | mup += strftime(" %H:%M:%S\n",*i); | ||
124 | mup += "</tt>"; | ||
125 | tooltip->set_markup( mup ); | ||
126 | return true; | ||
127 | } | ||
128 | |||
129 | void sleep_history_t::set_data(list<napkin::hypnodata_ptr_t> data) { | ||
130 | store->clear(); | ||
131 | min_tobed = 24*60*60*2; max_alarm = 0; | ||
132 | for(std::list<napkin::hypnodata_ptr_t>::const_iterator | ||
133 | i=data.begin(); i!=data.end(); ++i) { | ||
134 | Gtk::TreeModel::Row r = *(store->append()); | ||
135 | r[cols.c_hypnodata] = *i; | ||
136 | r[cols.c_hypnodata_ptr] = i->get(); | ||
137 | time_t a = (*i)->aligned_start(); | ||
138 | time_t soff = (*i)->to_bed-a; | ||
139 | if(soff < min_tobed) min_tobed = soff; | ||
140 | time_t eoff = (*i)->alarm-a; | ||
141 | if(eoff > max_alarm) max_alarm = eoff; | ||
142 | } | ||
143 | while(Gtk::Main::events_pending()) Gtk::Main::iteration() ; | ||
144 | w_tree.columns_autosize(); | ||
145 | } | ||
146 | |||
147 | const hypnodata_ptr_t sleep_history_t::get_current() { | ||
148 | Gtk::TreeModel::Path p; | ||
149 | Gtk::TreeViewColumn *c; | ||
150 | w_tree.get_cursor(p,c); | ||
151 | if( (!p.gobj()) || p.empty()) | ||
152 | return hypnodata_ptr_t(); /* XXX: or throw? */ | ||
153 | Gtk::ListStore::iterator i = store->get_iter(p); | ||
154 | return i->get_value(cols.c_hypnodata); | ||
155 | } | ||
156 | |||
157 | } | ||
158 | } | ||