swat 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+