swat 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,83 @@
1
+ module Swat
2
+ class StatBox
3
+ attr_accessor :meta_data,:vbox_container
4
+ def initialize(meta_data)
5
+ @meta_data = meta_data
6
+ @vbox_container = Gtk::VBox.new
7
+ stat_label = Gtk::Label.new
8
+ stat_label.xalign = 0.02
9
+ stat_label.set_markup("<span underline='double' weight='bold' style='oblique'> Stats </span>\n")
10
+
11
+ @vbox_container.pack_start(stat_label,false,false)
12
+
13
+ set_today_label
14
+ @vbox_container.pack_start(@today_label,false,false)
15
+
16
+ set_yesterday_label
17
+ @vbox_container.pack_start(@yesterday_label,false,false)
18
+
19
+ set_lastweek_label
20
+ @vbox_container.pack_start(@lastweek_label,false,false)
21
+ end
22
+
23
+ def set_today_label(p_meta_data = nil)
24
+ @meta_data = p_meta_data if p_meta_data
25
+ today_heading = Gtk::Label.new
26
+ today_heading.xalign = 0.02
27
+ today_heading.set_markup("<span foreground='#6d0835' style='oblique' size='smaller'> Today </span>")
28
+ @vbox_container.pack_start(today_heading,false,false)
29
+
30
+ @today_label = Gtk::Label.new
31
+ @today_label.xalign = 0
32
+ today_str = <<-EOD
33
+ <small> Done : <span foreground='#206d08'>#{@meta_data.tasks_done_today}</span>, Added : <span foreground='red'>#{@meta_data.tasks_added_today}</span> </small>
34
+ EOD
35
+ @today_label.set_markup(today_str)
36
+ end
37
+
38
+ def update_today_label(p_meta_data = nil)
39
+ @meta_data = p_meta_data if p_meta_data
40
+ today_str = <<-EOD
41
+ <small> Done : <span foreground='#206d08'>#{@meta_data.tasks_done_today}</span>, Added : <span foreground='red'>#{@meta_data.tasks_added_today}</span> </small>
42
+ EOD
43
+ @today_label.set_markup(today_str)
44
+ end
45
+
46
+ def show_all
47
+ @vbox_container.show_all
48
+ end
49
+
50
+ def hide_all
51
+ @vbox_container.hide_all
52
+ end
53
+
54
+ def set_yesterday_label
55
+ yesterday_heading = Gtk::Label.new
56
+ yesterday_heading.xalign = 0.02
57
+ yesterday_heading.set_markup("<span foreground='#6d0835' style='oblique' size='smaller'> Yesterday </span>")
58
+ @vbox_container.pack_start(yesterday_heading,false,false)
59
+
60
+ @yesterday_label = Gtk::Label.new
61
+ @yesterday_label.xalign = 0
62
+ yesterday_str = <<-EOD
63
+ <small> Done : <span foreground='#206d08'>#{@meta_data.tasks_done_yesterday}</span>, Added : <span foreground='red'>#{@meta_data.tasks_added_yesterday}</span> </small>
64
+ EOD
65
+ @yesterday_label.set_markup(yesterday_str)
66
+ end
67
+
68
+ def set_lastweek_label
69
+ lastweek_heading = Gtk::Label.new
70
+ lastweek_heading.xalign = 0.02
71
+ lastweek_heading.set_markup("<span foreground='#6d0835' style='oblique' size='smaller'> Lastweek </span>")
72
+ @vbox_container.pack_start(lastweek_heading,false,false)
73
+
74
+ @lastweek_label = Gtk::Label.new
75
+ @lastweek_label.xalign = 0
76
+ lastweek_str = <<-EOD
77
+ <small> Done : <span foreground='#206d08'> #{@meta_data.tasks_done_lastweek} </span>, Added : <span foreground='red'> #{@meta_data.tasks_added_lastweek}</span> </small>
78
+ EOD
79
+ @lastweek_label.set_markup(lastweek_str)
80
+ end
81
+ end
82
+ end
83
+
@@ -0,0 +1,51 @@
1
+ module Swat
2
+ VERSION = "1.0.0"
3
+ class SwatMain
4
+ attr_accessor :todo_window
5
+ attr_accessor :status_icon
6
+ attr_accessor :key_binder
7
+
8
+ def initialize
9
+ @status_icon = Gtk::StatusIcon.new
10
+ icon_file = Gdk::Pixbuf.new("#{SWAT_APP}/resources/todo.png")
11
+ @status_icon.pixbuf = icon_file
12
+ TodoWindow.todo_file_location = File.join(ENV['HOME'], 'snippets/todo.org')
13
+ TodoWindow.wishlist = File.join(ENV['HOME'], 'snippets/wishlist.org')
14
+ TodoWindow.meta_data_file = File.join(ENV['HOME'], 'snippets/meta_data.yml')
15
+ @todo_window = TodoWindow.new("#{SWAT_APP}/resources/todo_window.glade")
16
+
17
+ @status_icon.set_tooltip("Your Task List")
18
+ @status_icon.visible = true
19
+ @status_icon.signal_connect('activate') { show_task_list }
20
+ @status_icon.signal_connect('popup-menu') { |*args| display_context_menu(*args) }
21
+
22
+ @key_binder = KeyBinder.new
23
+ bind_proc = lambda { show_task_list }
24
+ @key_binder.bindkey("<Alt>F11",bind_proc)
25
+ end
26
+
27
+ def show_task_list
28
+ @todo_window.show_window
29
+ end
30
+
31
+ def display_context_menu(*args)
32
+ w,button,activate_time = *args
33
+ menu = Gtk::Menu.new
34
+ menuitem = Gtk::MenuItem.new(" Quit ")
35
+ menuitem.signal_connect("activate") {
36
+ w.set_visible(false)
37
+ Gtk.main_quit
38
+ }
39
+ menu.append(menuitem)
40
+
41
+ hidemenuitem = Gtk::MenuItem.new(" Hide ")
42
+ hidemenuitem.signal_connect("activate") {
43
+ @todo_window.hide_window
44
+ }
45
+ menu.append(hidemenuitem)
46
+ menu.show_all
47
+ menu.popup(nil,nil,button,activate_time)
48
+ end
49
+ end
50
+ end
51
+
@@ -0,0 +1,61 @@
1
+ module Swat
2
+ class SwatMetaData
3
+ attr_accessor :meta_data
4
+ attr_accessor :meta_data_file_location,:todo_file
5
+
6
+ def initialize(config_file)
7
+ @meta_data_file_location = config_file
8
+ if File.exists?(@meta_data_file_location)
9
+ @meta_data = YAML.load(ERB.new(IO.read(config_file)).result) || { }
10
+ else
11
+ @meta_data = {}
12
+ end
13
+ end
14
+
15
+ def todo_added
16
+ @meta_data[current_time] ||= {:tasks_added => 0, :tasks_done => 0 }
17
+ @meta_data[current_time][:tasks_added] += 1
18
+ end
19
+
20
+ def todo_done
21
+ @meta_data[current_time] ||= {:tasks_added => 0, :tasks_done => 0 }
22
+ @meta_data[current_time][:tasks_done] += 1
23
+ end
24
+
25
+ def tasks_added_today;
26
+ @meta_data[current_time] ? @meta_data[current_time][:tasks_added] : 0
27
+ end
28
+
29
+ def tasks_done_today
30
+ @meta_data[current_time] ? @meta_data[current_time][:tasks_done] : 0
31
+ end
32
+
33
+ def tasks_added_yesterday
34
+ @meta_data[yesterday] ? @meta_data[yesterday][:tasks_added] : 0
35
+ end
36
+
37
+ def tasks_done_yesterday
38
+ @meta_data[yesterday] ? @meta_data[yesterday][:tasks_done] : 0
39
+ end
40
+
41
+ def tasks_added_lastweek
42
+ lastweek.inject(0) { |mem,obj| mem += (@meta_data[obj] ? @meta_data[obj][:tasks_added] : 0) }
43
+ end
44
+
45
+ def tasks_done_lastweek
46
+ lastweek.inject(0) { |mem,obj| mem += (@meta_data[obj] ? @meta_data[obj][:tasks_done] : 0) }
47
+ end
48
+
49
+ def current_time; Time.now.strftime("%Y-%m-%d"); end
50
+ def yesterday;
51
+ (Time.now - 24*3600).strftime("%Y-%m-%d")
52
+ end
53
+
54
+ def lastweek; (0..6).to_a.map { |i| (Time.now - i*24*3600).strftime("%Y-%m-%d")}; end
55
+
56
+ # method dumps data to file
57
+ def dump
58
+ File.open(@meta_data_file_location,'w') { |f| f.write(YAML.dump(@meta_data))}
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,22 @@
1
+ module Swat
2
+ class TodoContextMenu
3
+ attr_accessor :todo_menu
4
+ def initialize(title = nil)
5
+ @todo_menu = Gtk::Menu.new
6
+ empty_item = Gtk::MenuItem.new(" ")
7
+ @todo_menu.append(empty_item)
8
+ # @todo_menu.show_all
9
+ end
10
+
11
+ def append(title)
12
+ item = Gtk::MenuItem.new(title)
13
+ item.signal_connect("activate") { yield }
14
+ @todo_menu.append(item)
15
+ end
16
+
17
+ def show
18
+ @todo_menu.show_all
19
+ end
20
+ end
21
+
22
+ end
@@ -0,0 +1,106 @@
1
+ module Swat
2
+ class TodoData
3
+ attr_accessor :config_file,:todo_container
4
+ def initialize(config_file)
5
+ @config_file = config_file
6
+ @todo_container = {}
7
+ parse_file_data if File.exist?(@config_file)
8
+ end
9
+
10
+ def parse_file_data
11
+ current_category = nil
12
+ todo_lines = []
13
+ File.open(@config_file) {|fl| todo_lines = fl.readlines() }
14
+ line_count = 0
15
+ todo_lines.each do |todo_line|
16
+ todo_line.strip!.chomp!
17
+ next if todo_line.nil? or todo_line.empty?
18
+ case todo_line
19
+ when /^\*{1}\ (.+)?/
20
+ current_category = $1
21
+ line_count = 0
22
+ @todo_container[current_category] ||= []
23
+ when /^(\*{2,})\ TODO\ (.+)?/
24
+ priority = $1.size
25
+ item = OpenStruct.new(:priority => priority, :flag => true, :text => $2,:index => line_count )
26
+ line_count += 1
27
+ @todo_container[current_category] << item
28
+ when /^(\*{2,})\ DONE\ (.+)?/
29
+ priority = $1.size
30
+ item = OpenStruct.new(:priority => priority, :flag => false, :text => $2,:index => line_count )
31
+ line_count += 1
32
+ @todo_container[current_category] << item
33
+ end
34
+ end
35
+ end
36
+
37
+ def open_tasks
38
+ @todo_container.each do |category,todo_array|
39
+ next if todo_array.empty?
40
+ todo_array.sort! { |x,y| x.priority <=> y.priority }
41
+ todo_array.reject! { |x| !x.flag }
42
+ yield(category,todo_array)
43
+ end
44
+ end
45
+
46
+ def open_tasks_with_index
47
+ @todo_container.each_with_index do |category,todo_array,index|
48
+ todo_array.sort! { |x,y| x.priority <=> y.priority }
49
+ todo_array.reject! { |x| !x.flag }
50
+ yield(category,todo_array,index)
51
+ end
52
+ end
53
+
54
+ def dump
55
+ File.open(@config_file,'w') do |fl|
56
+ @todo_container.each do |category,todo_array|
57
+ fl << "* #{category}\n"
58
+ todo_array.each do |todo_item|
59
+ fl << "#{priority_star(todo_item.priority)} #{todo_item.flag ? 'TODO' : 'DONE'} #{todo_item.text}\n"
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ def priority_star(count)
66
+ foo = ''
67
+ count.times { foo << '*'}
68
+ return foo
69
+ end
70
+
71
+ def delete(category,task_index)
72
+ @todo_container[category].each do |task_item|
73
+ if task_item.index == task_index
74
+ task_item.flag = false
75
+ end
76
+ end
77
+ end
78
+
79
+ def remove(category,task_index)
80
+ @todo_container[category].delete_if { |x| x.index == task_index }
81
+ end
82
+
83
+ def categories
84
+ return @todo_container.keys
85
+ end
86
+
87
+ def insert(category,task,priority)
88
+ @todo_container[category] ||= []
89
+ last_task = @todo_container[category].last
90
+ next_index = last_task ? (last_task.index + 1): 0
91
+ @todo_container[category] << OpenStruct.new(:priority => priority, :text => task.gsub(/\n/,' '), :flag => true,:index => next_index)
92
+ end
93
+
94
+ def get_priority(category,task_index)
95
+ result = @todo_container[category].detect { |x| x.index == task_index }
96
+ result ? result.priority : 2
97
+ end
98
+
99
+ def get_task(category,task_index)
100
+ result = @todo_container[category].detect { |x| x.index == task_index }
101
+ return result.text
102
+ end
103
+
104
+ end
105
+ end
106
+
@@ -0,0 +1,169 @@
1
+ module Swat
2
+ class TodoWindow
3
+ include Swat::ListHelper
4
+ attr_accessor :todo_data,:glade,:todo_window
5
+
6
+ TreeItem = Struct.new('TreeItem',:description, :priority,:category)
7
+ @@todo_file_location = nil
8
+ @@meta_data_file = nil
9
+ @@wish_list = nil
10
+
11
+ def self.meta_data_file= (file); @@meta_data_file = file; end
12
+ def self.todo_file_location= (filename); @@todo_file_location = filename; end
13
+ def self.wishlist= (filename); @@wishlist = filename; end
14
+
15
+ def on_todo_window_delete_event
16
+ hide_window
17
+ return true
18
+ end
19
+
20
+ def on_todo_window_destroy_event; return true; end
21
+
22
+ def on_add_todo_button_clicked
23
+ AddTodoDialog.new(@todo_data.categories) do |priority,category,todo|
24
+ add_to_tasklist(category,todo,priority)
25
+ end
26
+ end
27
+
28
+ def add_to_tasklist(category,todo,priority)
29
+ @todo_data.insert(category,todo,priority.to_i)
30
+ @meta_data.todo_added
31
+ @meta_data.dump
32
+ @todo_data.dump
33
+ reload_view
34
+ @stat_vbox.update_today_label(@meta_data)
35
+ end
36
+
37
+ def on_toggle_stat_button_clicked
38
+ # stat box is hidden
39
+ unless @stat_box_status
40
+ button_icon_widget = Gtk::Image.new("#{SWAT_APP}/resources/control_end_blue.png")
41
+ @stat_vbox.show_all
42
+ # stat box is already shown
43
+ else
44
+ button_icon_widget = Gtk::Image.new("#{SWAT_APP}/resources/control_rewind_blue.png")
45
+ @stat_vbox.hide_all
46
+ end
47
+ @stat_box_status = !@stat_box_status
48
+ @stat_toggle_button.image = button_icon_widget
49
+ end
50
+
51
+ def on_todo_window_key_press_event(widget,key)
52
+ hide_window if Gdk::Keyval.to_name(key.keyval) =~ /Escape/i
53
+ end
54
+
55
+ def on_reload_button_clicked
56
+ @todo_data = TodoData.new(@@todo_file_location)
57
+ reload_view
58
+ end
59
+
60
+
61
+ def initialize path
62
+ @glade = GladeXML.new(path) { |handler| method(handler) }
63
+ @list_view = @glade.get_widget("todo_view")
64
+ @todo_window = @glade.get_widget("todo_window")
65
+ window_icon = Gdk::Pixbuf.new("#{SWAT_APP}/resources/todo.png")
66
+ @todo_window.icon_list = [window_icon]
67
+ @todo_window.title = "Your TaskList"
68
+ @todo_selection = @list_view.selection
69
+ @todo_selection.mode = Gtk::SELECTION_SINGLE
70
+
71
+ @meta_data = SwatMetaData.new(@@meta_data_file)
72
+ layout_statbar
73
+ @todo_data = TodoData.new(@@todo_file_location)
74
+ @model = create_model
75
+ load_available_lists
76
+ add_columns
77
+ connect_custom_signals
78
+ layout_wishlist
79
+ @list_view.expand_all
80
+ @todo_window.hide
81
+ end
82
+
83
+ # layout statistic bar
84
+ def layout_statbar
85
+ @stat_toggle_button = @glade.get_widget("toggle_stat_button")
86
+ @stat_hbox = @glade.get_widget("stat_box")
87
+ @stat_vbox = StatBox.new(@meta_data)
88
+
89
+ @stat_hbox.pack_end(@stat_vbox.vbox_container,true)
90
+ button_icon_widget = Gtk::Image.new("#{SWAT_APP}/resources/control_rewind_blue.png")
91
+ @stat_box_status = false
92
+ @stat_toggle_button.image = button_icon_widget
93
+ end
94
+
95
+ def layout_wishlist
96
+ wish_list_view = @glade.get_widget("wish_list_view")
97
+ @wish_list_tab = WishList.new(@@wishlist,wish_list_view,self)
98
+ end
99
+
100
+ def connect_custom_signals
101
+ @todo_context_menu = TodoContextMenu.new
102
+ @todo_context_menu.append(" Mark As Done ") { mark_as_done }
103
+ @todo_context_menu.append(" Mark As Wishlist ") { mark_as_wishlist }
104
+ @todo_context_menu.show
105
+
106
+ @list_view.signal_connect("button_press_event") do |widget,event|
107
+ if event.kind_of? Gdk::EventButton and event.button == 3
108
+ @todo_context_menu.todo_menu.popup(nil, nil, event.button, event.time)
109
+ end
110
+ end
111
+ @list_view.signal_connect("popup_menu") { @todo_context_menu.todo_menu.popup(nil, nil, 0, Gdk::Event::CURRENT_TIME) }
112
+
113
+ # FIXME: implement fold and unfold of blocks
114
+ @list_view.signal_connect("key-press-event") do |widget,event|
115
+ if event.kind_of? Gdk::EventKey
116
+ key_str = Gdk::Keyval.to_name(event.keyval)
117
+ if key_str =~ /Left/i
118
+ # fold the block
119
+ elsif key_str =~ /Right/i
120
+ # unfold the block
121
+ end
122
+ end
123
+ end
124
+ end
125
+
126
+ def mark_as_done
127
+ selection = @list_view.selection
128
+ if iter = selection.selected
129
+ selected_category = iter.parent[0]
130
+ task_index = iter[3]
131
+ @todo_data.delete(selected_category,task_index)
132
+ @list_view.model.remove(iter)
133
+ @todo_data.dump
134
+ @meta_data.todo_done
135
+ @meta_data.dump
136
+ @stat_vbox.update_today_label(@meta_data)
137
+ end
138
+ end
139
+
140
+ def mark_as_wishlist
141
+ selection = @list_view.selection
142
+ if iter = selection.selected
143
+ selected_category = iter.parent[0]
144
+ task_index = iter[3]
145
+ priority = todo_data.get_priority(selected_category,task_index)
146
+ task_text = todo_data.get_task(selected_category,task_index)
147
+ @wish_list_tab.add_to_wishlist(selected_category,task_text,priority)
148
+ @todo_data.remove(selected_category,task_index)
149
+ @todo_data.dump
150
+ @list_view.model.remove(iter)
151
+ end
152
+ end
153
+
154
+ def show_window
155
+ @todo_window = @glade.get_widget("todo_window")
156
+ @todo_window.show
157
+ end
158
+
159
+ def hide_window; @todo_window.hide; end
160
+
161
+ def on_sync_button_clicked
162
+ system("svn up #{@@todo_file_location}")
163
+ system("svn ci #{@@todo_file_location} -m 'foo'")
164
+ end
165
+
166
+ end
167
+ end
168
+
169
+