ruby_do 0.0.0 → 0.0.2

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.
data/Gemfile CHANGED
@@ -6,6 +6,7 @@ source "http://rubygems.org"
6
6
  gem "gtk2"
7
7
  gem "knjrbfw"
8
8
  gem "gettext"
9
+ gem "sqlite3"
9
10
 
10
11
  # Add dependencies to develop your gem here.
11
12
  # Include everything needed to run rake, tests, features, etc.
data/Gemfile.lock CHANGED
@@ -43,6 +43,7 @@ GEM
43
43
  rspec-expectations (2.8.0)
44
44
  diff-lcs (~> 1.1.2)
45
45
  rspec-mocks (2.8.0)
46
+ sqlite3 (1.3.6)
46
47
  tsafe (0.0.1)
47
48
  wref (0.0.4)
48
49
 
@@ -58,3 +59,4 @@ DEPENDENCIES
58
59
  rcov
59
60
  rdoc (~> 3.12)
60
61
  rspec (~> 2.8.0)
62
+ sqlite3
data/Rakefile CHANGED
@@ -17,8 +17,8 @@ Jeweler::Tasks.new do |gem|
17
17
  gem.name = "ruby_do"
18
18
  gem.homepage = "http://github.com/kaspernj/ruby_do"
19
19
  gem.license = "MIT"
20
- gem.summary = %Q{A clone of Gnome-Do and Kupfer written in Ruby. }
21
- gem.description = %Q{A clone of Gnome-Do and Kupfer written in Ruby. }
20
+ gem.summary = %Q{A clone of Gnome-Do and Kupfer written in Ruby.}
21
+ gem.description = %Q{A clone of Gnome-Do and Kupfer written in Ruby.}
22
22
  gem.email = "k@spernj.org"
23
23
  gem.authors = ["Kasper Johansen"]
24
24
  # dependencies defined in Gemfile
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.0
1
+ 0.0.2
data/bin/ruby_do.rb CHANGED
@@ -22,6 +22,10 @@ if args[:cmd]
22
22
  exit
23
23
  end
24
24
 
25
+ def _(str)
26
+ return GetText._(str)
27
+ end
28
+
25
29
  require "#{File.realpath(File.dirname(__FILE__))}/../lib/ruby_do.rb"
26
30
  rdo = Ruby_do.new
27
31
  rdo.join
data/gfx/search.png ADDED
Binary file
data/glade/win_main.glade CHANGED
@@ -4,10 +4,12 @@
4
4
  <!-- interface-naming-policy project-wide -->
5
5
  <object class="GtkWindow" id="window">
6
6
  <property name="can_focus">False</property>
7
+ <property name="border_width">10</property>
7
8
  <property name="title" translatable="yes">Ruby Do</property>
8
9
  <property name="window_position">center</property>
9
- <property name="default_width">640</property>
10
- <property name="default_height">480</property>
10
+ <property name="default_width">800</property>
11
+ <property name="default_height">300</property>
12
+ <signal name="focus-out-event" handler="on_window_focus_out_event" swapped="no"/>
11
13
  <child>
12
14
  <object class="GtkVBox" id="vbox1">
13
15
  <property name="visible">True</property>
@@ -31,6 +33,7 @@
31
33
  <packing>
32
34
  <property name="expand">False</property>
33
35
  <property name="fill">False</property>
36
+ <property name="padding">4</property>
34
37
  <property name="position">0</property>
35
38
  </packing>
36
39
  </child>
@@ -70,6 +73,8 @@
70
73
  <property name="primary_icon_sensitive">True</property>
71
74
  <property name="secondary_icon_sensitive">True</property>
72
75
  <signal name="changed" handler="on_txtSearch_changed" swapped="no"/>
76
+ <signal name="activate" handler="on_txtSearch_activate" swapped="no"/>
77
+ <signal name="key-press-event" handler="on_txtSearch_key_press_event" swapped="no"/>
73
78
  </object>
74
79
  <packing>
75
80
  <property name="left_attach">1</property>
@@ -84,60 +89,83 @@
84
89
  </packing>
85
90
  </child>
86
91
  <child>
87
- <object class="GtkHBox" id="hbox1">
92
+ <object class="GtkVBox" id="vbox2">
88
93
  <property name="visible">True</property>
89
94
  <property name="can_focus">False</property>
90
95
  <child>
91
- <object class="GtkViewport" id="viewport1">
92
- <property name="width_request">170</property>
93
- <property name="height_request">150</property>
96
+ <object class="GtkHBox" id="hbox1">
94
97
  <property name="visible">True</property>
95
98
  <property name="can_focus">False</property>
96
99
  <child>
97
- <object class="GtkImage" id="imgActionIcon">
100
+ <object class="GtkViewport" id="viewport1">
101
+ <property name="width_request">150</property>
102
+ <property name="height_request">150</property>
98
103
  <property name="visible">True</property>
99
104
  <property name="can_focus">False</property>
100
- <property name="stock">gtk-missing-image</property>
105
+ <property name="shadow_type">none</property>
106
+ <child>
107
+ <object class="GtkImage" id="imgActionIcon">
108
+ <property name="visible">True</property>
109
+ <property name="can_focus">False</property>
110
+ <property name="stock">gtk-missing-image</property>
111
+ </object>
112
+ </child>
101
113
  </object>
114
+ <packing>
115
+ <property name="expand">False</property>
116
+ <property name="fill">False</property>
117
+ <property name="padding">5</property>
118
+ <property name="position">0</property>
119
+ </packing>
102
120
  </child>
103
- </object>
104
- <packing>
105
- <property name="expand">False</property>
106
- <property name="fill">True</property>
107
- <property name="padding">30</property>
108
- <property name="position">0</property>
109
- </packing>
110
- </child>
111
- <child>
112
- <object class="GtkFrame" id="frame1">
113
- <property name="visible">True</property>
114
- <property name="can_focus">False</property>
115
- <property name="label_xalign">0</property>
116
- <property name="shadow_type">none</property>
117
121
  <child>
118
- <object class="GtkAlignment" id="alignment1">
122
+ <object class="GtkFrame" id="frame1">
119
123
  <property name="visible">True</property>
120
124
  <property name="can_focus">False</property>
121
- <property name="left_padding">12</property>
125
+ <property name="label_xalign">0</property>
126
+ <property name="shadow_type">none</property>
122
127
  <child>
123
- <object class="GtkLabel" id="labActionDescr">
128
+ <object class="GtkAlignment" id="alignment1">
124
129
  <property name="visible">True</property>
125
130
  <property name="can_focus">False</property>
126
- <property name="xalign">0</property>
127
- <property name="yalign">0</property>
128
- <property name="label" translatable="yes">Description</property>
131
+ <property name="left_padding">12</property>
132
+ <child>
133
+ <object class="GtkLabel" id="labActionDescr">
134
+ <property name="visible">True</property>
135
+ <property name="can_focus">False</property>
136
+ <property name="xalign">0</property>
137
+ <property name="yalign">0</property>
138
+ <property name="label" translatable="yes">Description</property>
139
+ </object>
140
+ </child>
141
+ </object>
142
+ </child>
143
+ <child type="label">
144
+ <object class="GtkLabel" id="labActionTitle">
145
+ <property name="visible">True</property>
146
+ <property name="can_focus">False</property>
147
+ <property name="label" translatable="yes">&lt;b&gt;Action&lt;/b&gt;</property>
148
+ <property name="use_markup">True</property>
129
149
  </object>
130
150
  </child>
131
151
  </object>
152
+ <packing>
153
+ <property name="expand">True</property>
154
+ <property name="fill">True</property>
155
+ <property name="position">1</property>
156
+ </packing>
132
157
  </child>
133
- <child type="label">
134
- <object class="GtkLabel" id="labActionTitle">
135
- <property name="visible">True</property>
136
- <property name="can_focus">False</property>
137
- <property name="label" translatable="yes">&lt;b&gt;Action&lt;/b&gt;</property>
138
- <property name="use_markup">True</property>
139
- </object>
140
- </child>
158
+ </object>
159
+ <packing>
160
+ <property name="expand">False</property>
161
+ <property name="fill">True</property>
162
+ <property name="position">0</property>
163
+ </packing>
164
+ </child>
165
+ <child>
166
+ <object class="GtkLabel" id="label2">
167
+ <property name="visible">True</property>
168
+ <property name="can_focus">False</property>
141
169
  </object>
142
170
  <packing>
143
171
  <property name="expand">True</property>
@@ -0,0 +1,231 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <interface>
3
+ <requires lib="gtk+" version="2.24"/>
4
+ <!-- interface-naming-policy project-wide -->
5
+ <object class="GtkWindow" id="window">
6
+ <property name="can_focus">False</property>
7
+ <property name="title" translatable="yes">Properties</property>
8
+ <property name="window_position">center</property>
9
+ <property name="default_width">640</property>
10
+ <property name="default_height">480</property>
11
+ <child>
12
+ <object class="GtkNotebook" id="notebook1">
13
+ <property name="visible">True</property>
14
+ <property name="can_focus">True</property>
15
+ <child>
16
+ <object class="GtkVBox" id="vbox3">
17
+ <property name="visible">True</property>
18
+ <property name="can_focus">False</property>
19
+ <child>
20
+ <object class="GtkTable" id="table2">
21
+ <property name="visible">True</property>
22
+ <property name="can_focus">False</property>
23
+ <property name="n_columns">2</property>
24
+ <child>
25
+ <object class="GtkCheckButton" id="cbShowWindowOnStartup">
26
+ <property name="label" translatable="yes">Show window on startup</property>
27
+ <property name="visible">True</property>
28
+ <property name="can_focus">True</property>
29
+ <property name="receives_default">False</property>
30
+ <property name="use_action_appearance">False</property>
31
+ <property name="draw_indicator">True</property>
32
+ <signal name="toggled" handler="on_cbShowWindowOnStartup_toggled" after="yes" swapped="no"/>
33
+ </object>
34
+ <packing>
35
+ <property name="right_attach">2</property>
36
+ <property name="x_options">GTK_FILL</property>
37
+ <property name="y_options">GTK_FILL</property>
38
+ </packing>
39
+ </child>
40
+ </object>
41
+ <packing>
42
+ <property name="expand">False</property>
43
+ <property name="fill">True</property>
44
+ <property name="position">0</property>
45
+ </packing>
46
+ </child>
47
+ <child>
48
+ <object class="GtkLabel" id="label4">
49
+ <property name="visible">True</property>
50
+ <property name="can_focus">False</property>
51
+ </object>
52
+ <packing>
53
+ <property name="expand">True</property>
54
+ <property name="fill">True</property>
55
+ <property name="position">1</property>
56
+ </packing>
57
+ </child>
58
+ </object>
59
+ </child>
60
+ <child type="tab">
61
+ <object class="GtkLabel" id="label1">
62
+ <property name="visible">True</property>
63
+ <property name="can_focus">False</property>
64
+ <property name="label" translatable="yes">Properties</property>
65
+ </object>
66
+ <packing>
67
+ <property name="tab_fill">False</property>
68
+ </packing>
69
+ </child>
70
+ <child>
71
+ <object class="GtkHPaned" id="hpaned1">
72
+ <property name="visible">True</property>
73
+ <property name="can_focus">True</property>
74
+ <property name="position">150</property>
75
+ <property name="position_set">True</property>
76
+ <child>
77
+ <object class="GtkFrame" id="frame1">
78
+ <property name="visible">True</property>
79
+ <property name="can_focus">False</property>
80
+ <property name="label_xalign">0</property>
81
+ <property name="shadow_type">none</property>
82
+ <child>
83
+ <object class="GtkAlignment" id="alignment1">
84
+ <property name="visible">True</property>
85
+ <property name="can_focus">False</property>
86
+ <property name="left_padding">12</property>
87
+ <child>
88
+ <object class="GtkViewport" id="viewport1">
89
+ <property name="visible">True</property>
90
+ <property name="can_focus">False</property>
91
+ <child>
92
+ <object class="GtkScrolledWindow" id="scrolledwindow1">
93
+ <property name="visible">True</property>
94
+ <property name="can_focus">True</property>
95
+ <property name="hscrollbar_policy">automatic</property>
96
+ <property name="vscrollbar_policy">automatic</property>
97
+ <child>
98
+ <object class="GtkTreeView" id="tvPlugins">
99
+ <property name="visible">True</property>
100
+ <property name="can_focus">True</property>
101
+ </object>
102
+ </child>
103
+ </object>
104
+ </child>
105
+ </object>
106
+ </child>
107
+ </object>
108
+ </child>
109
+ <child type="label">
110
+ <object class="GtkLabel" id="label6">
111
+ <property name="visible">True</property>
112
+ <property name="can_focus">False</property>
113
+ <property name="label" translatable="yes">&lt;b&gt;Plugins&lt;/b&gt;</property>
114
+ <property name="use_markup">True</property>
115
+ </object>
116
+ </child>
117
+ </object>
118
+ <packing>
119
+ <property name="resize">False</property>
120
+ <property name="shrink">True</property>
121
+ </packing>
122
+ </child>
123
+ <child>
124
+ <object class="GtkVBox" id="vbox1">
125
+ <property name="visible">True</property>
126
+ <property name="can_focus">False</property>
127
+ <child>
128
+ <object class="GtkFrame" id="frame2">
129
+ <property name="visible">True</property>
130
+ <property name="can_focus">False</property>
131
+ <property name="label_xalign">0</property>
132
+ <property name="shadow_type">none</property>
133
+ <child>
134
+ <object class="GtkAlignment" id="alignment2">
135
+ <property name="visible">True</property>
136
+ <property name="can_focus">False</property>
137
+ <property name="left_padding">12</property>
138
+ <child>
139
+ <object class="GtkVBox" id="vbox2">
140
+ <property name="visible">True</property>
141
+ <property name="can_focus">False</property>
142
+ <property name="spacing">4</property>
143
+ <child>
144
+ <object class="GtkTable" id="table1">
145
+ <property name="visible">True</property>
146
+ <property name="can_focus">False</property>
147
+ <property name="n_columns">2</property>
148
+ <property name="column_spacing">4</property>
149
+ <property name="row_spacing">4</property>
150
+ <child>
151
+ <object class="GtkCheckButton" id="cbPluginActivate">
152
+ <property name="label" translatable="yes">Activated</property>
153
+ <property name="visible">True</property>
154
+ <property name="can_focus">True</property>
155
+ <property name="receives_default">False</property>
156
+ <property name="use_action_appearance">False</property>
157
+ <property name="draw_indicator">True</property>
158
+ <signal name="toggled" handler="on_cbPluginActivate_toggled" after="yes" swapped="no"/>
159
+ </object>
160
+ <packing>
161
+ <property name="right_attach">2</property>
162
+ <property name="x_options">GTK_FILL</property>
163
+ <property name="y_options">GTK_FILL</property>
164
+ </packing>
165
+ </child>
166
+ </object>
167
+ <packing>
168
+ <property name="expand">False</property>
169
+ <property name="fill">True</property>
170
+ <property name="position">0</property>
171
+ </packing>
172
+ </child>
173
+ <child>
174
+ <object class="GtkVBox" id="boxPluginOptions">
175
+ <property name="visible">True</property>
176
+ <property name="can_focus">False</property>
177
+ <child>
178
+ <placeholder/>
179
+ </child>
180
+ </object>
181
+ <packing>
182
+ <property name="expand">True</property>
183
+ <property name="fill">True</property>
184
+ <property name="position">1</property>
185
+ </packing>
186
+ </child>
187
+ </object>
188
+ </child>
189
+ </object>
190
+ </child>
191
+ <child type="label">
192
+ <object class="GtkLabel" id="label8">
193
+ <property name="visible">True</property>
194
+ <property name="can_focus">False</property>
195
+ <property name="label" translatable="yes">&lt;b&gt;Plugin options&lt;/b&gt;</property>
196
+ <property name="use_markup">True</property>
197
+ </object>
198
+ </child>
199
+ </object>
200
+ <packing>
201
+ <property name="expand">True</property>
202
+ <property name="fill">True</property>
203
+ <property name="position">0</property>
204
+ </packing>
205
+ </child>
206
+ </object>
207
+ <packing>
208
+ <property name="resize">True</property>
209
+ <property name="shrink">True</property>
210
+ </packing>
211
+ </child>
212
+ </object>
213
+ <packing>
214
+ <property name="position">1</property>
215
+ </packing>
216
+ </child>
217
+ <child type="tab">
218
+ <object class="GtkLabel" id="label3">
219
+ <property name="visible">True</property>
220
+ <property name="can_focus">False</property>
221
+ <property name="label" translatable="yes">Plugins</property>
222
+ </object>
223
+ <packing>
224
+ <property name="position">1</property>
225
+ <property name="tab_fill">False</property>
226
+ </packing>
227
+ </child>
228
+ </object>
229
+ </child>
230
+ </object>
231
+ </interface>
data/gui/win_main.rb CHANGED
@@ -1,13 +1,121 @@
1
+ #This class controls the main window.
1
2
  class Ruby_do::Gui::Win_main
3
+ #Initializes various variables for the object.
2
4
  def initialize(args)
3
5
  @args = args
4
-
6
+ end
7
+
8
+ #Spawn the GUI-object.
9
+ def spawn_gui
5
10
  @gui = Gtk::Builder.new.add("#{File.dirname(__FILE__)}/../glade/win_main.glade")
11
+ @gui.connect_signals{|h| method(h)}
6
12
  Knj::Gtk2.translate(@gui)
7
13
  end
8
14
 
15
+ def reset
16
+ @gui["txtSearch"].text = ""
17
+ self.update_res
18
+ self.on_txtSearch_changed_wait
19
+ end
20
+
21
+ #Spawns the GUI (if not already spawned) and focusses the window.
9
22
  def show
23
+ self.spawn_gui if !@gui or @gui["window"].destroyed?
24
+ self.reset
25
+
10
26
  @gui["window"].show_all
27
+ @gui["window"].present
11
28
  @gui["txtSearch"].grab_focus
29
+
30
+ #Update icon and text.
31
+ self.update_res
32
+ end
33
+
34
+ def hide
35
+ @gui["window"].hide
36
+ end
37
+
38
+ #Updates the icon, title and description to match the current result (if any).
39
+ def update_res
40
+ if @cur_res
41
+ @gui["labActionTitle"].markup = @cur_res.title_html!
42
+ @gui["labActionDescr"].label = @cur_res.descr_html!
43
+ @gui["imgActionIcon"].pixbuf = @cur_res.icon_pixbuf!
44
+ else
45
+ @gui["labActionTitle"].markup = "<b>#{Knj::Web.html(_("Nothing found"))}</b>"
46
+ @gui["labActionDescr"].label = _("Please enter something in the search text-field to do something.")
47
+ @gui["imgActionIcon"].pixbuf = Ruby_do::Plugin::Result.search_icon
48
+ end
49
+ end
50
+
51
+ #Starts the timeout of half a second in order to not mass-call plugins and start lagging.
52
+ def on_txtSearch_changed
53
+ Gtk.timeout_remove(@timeout) if @timeout
54
+ @timeout = Gtk.timeout_add(500) do
55
+ self.on_txtSearch_changed_wait
56
+ false
57
+ end
58
+ end
59
+
60
+ #This happens when the timeout is over and the plugins should be called.
61
+ def on_txtSearch_changed_wait
62
+ return nil if @gui["window"].destroyed?
63
+
64
+ text = @gui["txtSearch"].text
65
+ words = text.split(/\s+/).map{|ele| ele.downcase}
66
+
67
+ if words.empty?
68
+ @cur_res = nil
69
+ else
70
+ @enum = @args[:rdo].plugin.send(:text => text, :words => words)
71
+
72
+ begin
73
+ @cur_res = @enum.next
74
+ rescue StopIteration
75
+ @cur_res = nil
76
+ end
77
+ end
78
+
79
+ self.update_res
80
+ end
81
+
82
+ #This happens when <ENTER> is pressed while the search-textfield has focus.
83
+ def on_txtSearch_activate
84
+ #If enter was pressed before search was executed, then be sure to execute a search first and disable the timeout, so search wont be done two times.
85
+ if @timeout
86
+ Gtk.timeout_remove(@timeout)
87
+ self.on_txtSearch_changed_wait
88
+ end
89
+
90
+ if !@cur_res
91
+ Knj::Gtk2.msgbox(_("Please search for something in order to activate."))
92
+ return nil
93
+ end
94
+
95
+ begin
96
+ res = @cur_res.args[:plugin].execute_result(:res => @cur_res)
97
+
98
+ if res == :close_win_main
99
+ @gui["window"].destroy
100
+ end
101
+ rescue => e
102
+ Knj::Gtk2.msgbox(_("An error occurred.") + "\n\n#{e.inspect}\n\n#{e.backtrace.join("\n")}")
103
+ end
104
+ end
105
+
106
+ #In order the register <ESCAPE>-presses.
107
+ def on_txtSearch_key_press_event(entry, eventkey)
108
+ if Gdk::Keyval.to_name(eventkey.keyval) == "Escape"
109
+ @gui["window"].destroy
110
+ end
111
+ end
112
+
113
+ def on_btnProperties_clicked
114
+ @args[:rdo].show_win_properties
115
+ @gui["window"].destroy
116
+ end
117
+
118
+ def on_window_focus_out_event
119
+ @gui["window"].destroy
12
120
  end
13
121
  end
@@ -0,0 +1,130 @@
1
+ #This class controls the properties window.
2
+ class Ruby_do::Gui::Win_properties
3
+ attr_reader :gui
4
+
5
+ def initialize(args)
6
+ @args = args
7
+
8
+ @gui = Gtk::Builder.new.add("#{File.dirname(__FILE__)}/../glade/win_properties.glade")
9
+ @gui.connect_signals{|h| method(h)}
10
+ Knj::Gtk2.translate(@gui)
11
+
12
+
13
+ #Initialize plugins-treeview.
14
+ Knj::Gtk2::Tv.init(@gui["tvPlugins"], [
15
+ _("Name"),
16
+ _("Title")
17
+ ])
18
+ @gui["tvPlugins"].columns[0].visible = false
19
+ @gui["tvPlugins"].selection.signal_connect_after("changed", &self.method(:on_tvPlugins_changed))
20
+ self.reload_plugins
21
+ @gui["tvPlugins"].selection.select_iter(@gui["tvPlugins"].model.iter_first)
22
+
23
+
24
+ #Show the properties window.
25
+ @gui["window"].show
26
+
27
+
28
+ #Hides checkbutton until a plugin is chosen.
29
+ self.load_widget
30
+
31
+
32
+ #Set the value of main-window-show checkbutton.
33
+ if Knj::Opts.get("skip_main_on_startup").to_i == 1
34
+ @gui["cbShowWindowOnStartup"].active = false
35
+ else
36
+ @gui["cbShowWindowOnStartup"].active = true
37
+ end
38
+ end
39
+
40
+ def reload_plugins
41
+ @gui["tvPlugins"].model.clear
42
+
43
+ @args[:rdo].plugin.plugins.each do |name, plugin_obj|
44
+ Knj::Gtk2::Tv.append(@gui["tvPlugins"], [
45
+ plugin_obj.classname,
46
+ plugin_obj.title
47
+ ])
48
+ end
49
+ end
50
+
51
+ def on_tvPlugins_changed(*args)
52
+ sel = Knj::Gtk2::Tv.sel(@gui["tvPlugins"])
53
+ model = @args[:rdo].ob.get_by(:Plugin, {"classname" => sel[0]}) if sel
54
+
55
+ if model and model[:active].to_i == 1
56
+ @gui["cbPluginActivate"].active = true
57
+ else
58
+ @gui["cbPluginActivate"].active = false
59
+ end
60
+
61
+ self.load_widget
62
+
63
+ @gui["boxPluginOptions"].show_all
64
+ end
65
+
66
+ def load_widget
67
+ #Remove plugin-widgets.
68
+ @gui["boxPluginOptions"].children.each do |child|
69
+ @gui["boxPluginOptions"].remove(child)
70
+ child.destroy
71
+ end
72
+
73
+ sel = Knj::Gtk2::Tv.sel(@gui["tvPlugins"])
74
+ model = @args[:rdo].ob.get_by(:Plugin, {"classname" => sel[0]}) if sel
75
+
76
+ #If a plugin is selected and that plugin has a option-widget, then show that widget. Else show a label describing what is going on.
77
+ if sel and model and plugin = @args[:rdo].plugin.plugins[sel[0]]
78
+ if model[:active].to_i == 1
79
+ @gui["cbPluginActivate"].active = true
80
+
81
+ opt_res = plugin.on_options and opt_res[:widget]
82
+ if opt_res and opt_res[:widget]
83
+ @gui["boxPluginOptions"].pack_start(opt_res[:widget])
84
+ opt_res[:widget].show
85
+ else
86
+ label = Gtk::Label.new(_("This plugin doesnt have any options."))
87
+ @gui["boxPluginOptions"].pack_start(label)
88
+ label.show
89
+ end
90
+ else
91
+ @gui["cbPluginActivate"].active = false
92
+ label = Gtk::Label.new(_("Activate the plugin to see available options."))
93
+ @gui["boxPluginOptions"].pack_start(label)
94
+ label.show
95
+ end
96
+
97
+ @gui["cbPluginActivate"].show
98
+ else
99
+ label = Gtk::Label.new(_("Please choose a plugin."))
100
+ @gui["boxPluginOptions"].pack_start(label)
101
+ label.show
102
+ @gui["cbPluginActivate"].hide
103
+ end
104
+ end
105
+
106
+ def on_cbPluginActivate_toggled
107
+ sel = Knj::Gtk2::Tv.sel(@gui["tvPlugins"])
108
+ model = @args[:rdo].ob.get_by(:Plugin, {"classname" => sel[0]}) if sel
109
+
110
+ if model
111
+ if @gui["cbPluginActivate"].active?
112
+ model[:active] = 1
113
+ else
114
+ model[:active] = 0
115
+ end
116
+ end
117
+
118
+ self.load_widget
119
+ end
120
+
121
+ def on_cbShowWindowOnStartup_toggled
122
+ val = @gui["cbShowWindowOnStartup"].active?
123
+
124
+ if val
125
+ Knj::Opts.set("skip_main_on_startup", 0)
126
+ else
127
+ Knj::Opts.set("skip_main_on_startup", 1)
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,28 @@
1
+ class Ruby_do::Database
2
+ SCHEMA = {
3
+ "tables" => {
4
+ "Option" => {
5
+ "columns" => [
6
+ {"name" => "id", "type" => "int", "autoincr" => true, "primarykey" => true},
7
+ {"name" => "title", "type" => "varchar"},
8
+ {"name" => "value", "type" => "text"}
9
+ ],
10
+ "indexes" => [
11
+ "title"
12
+ ]
13
+ },
14
+ "Plugin" => {
15
+ "columns" => [
16
+ {"name" => "id", "type" => "int", "autoincr" => true, "primarykey" => true},
17
+ {"name" => "name", "type" => "varchar"},
18
+ {"name" => "classname", "type" => "varchar"},
19
+ {"name" => "active", "type" => "enum", "maxlength" => "'0','1'", "default" => 0}
20
+ ],
21
+ "indexes" => [
22
+ "name",
23
+ "classname"
24
+ ]
25
+ }
26
+ }
27
+ }
28
+ end
data/include/gui.rb ADDED
@@ -0,0 +1,8 @@
1
+ #This class contains all the GUI-subclasses (windows, tray-icon and such).
2
+ class Ruby_do::Gui
3
+ #Autoloader for Gui-subclasses.
4
+ def self.const_missing(name)
5
+ require "#{File.dirname(__FILE__)}/../gui/#{name.to_s.downcase}.rb"
6
+ return self.const_get(name)
7
+ end
8
+ end
data/include/models.rb ADDED
@@ -0,0 +1,3 @@
1
+ class Ruby_do::Models
2
+
3
+ end
data/include/plugin.rb ADDED
@@ -0,0 +1,160 @@
1
+ class Ruby_do::Plugin
2
+ def self.const_missing(name)
3
+
4
+ end
5
+
6
+ attr_reader :plugins
7
+
8
+ def register_plugins
9
+ paths = [
10
+ File.realpath("#{File.dirname(__FILE__)}/../../") #To enable developing of plugins in parent directory without having to do Gem-installs all the time.
11
+ ]
12
+
13
+ Gem.path.each do |gem_path|
14
+ paths << "#{gem_path}/gems"
15
+ end
16
+
17
+ paths.each do |path|
18
+ Dir.foreach(path) do |gem_dir|
19
+ next if gem_dir == "." or gem_dir == ".." or gem_dir[0, 15] != "ruby_do_plugin_"
20
+
21
+ match = gem_dir.match(/^([A-z_\d]+)(|-([\d\.]*))$/)
22
+ next if !match
23
+ next if @plugins.key?(match[1])
24
+ classname = "#{match[1][0].upcase}#{match[1][1, match[1].length]}"
25
+
26
+ begin
27
+ require "#{path}/#{gem_dir}/lib/#{match[1]}"
28
+ plugin = Kernel.const_get(classname).new(:rdo => @args[:rdo], :classname => match[1])
29
+ @plugins[match[1]] = plugin
30
+
31
+ model = @args[:rdo].ob.get_by(:Plugin, {
32
+ "classname" => plugin.classname
33
+ })
34
+
35
+ if !model
36
+ model = @args[:rdo].ob.add(:Plugin, {
37
+ :classname => plugin.classname,
38
+ :name => plugin.name
39
+ })
40
+ end
41
+
42
+ plugin.model = model
43
+ model.plugin = plugin
44
+ rescue NameError => e
45
+ $stderr.puts "Cant loading plugin '#{match[1]}' because of the following."
46
+ $stderr.puts e.inspect
47
+ $stderr.puts e.backtrace
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ def initialize(args)
54
+ @args = args
55
+ @plugins = {}
56
+ end
57
+
58
+ def send(args)
59
+ return Enumerator.new do |yielder|
60
+ @plugins.each do |name, plugin_instance|
61
+ plugin_model = @args[:rdo].ob.get_by(:Plugin, "classname" => plugin_instance.classname)
62
+ next if !plugin_model or plugin_model[:active].to_i != 1
63
+
64
+ begin
65
+ enum = plugin_instance.on_search(args)
66
+ enum.each do |res|
67
+ yielder << res
68
+ end
69
+ rescue => e
70
+ $stderr.puts e.inspect
71
+ $stderr.puts e.backtrace
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ class Base
78
+ attr_accessor :model
79
+
80
+ attr_reader :rdo_plugin_args
81
+
82
+ def initialize(args)
83
+ @rdo_plugin_args = args
84
+ end
85
+
86
+ def classname
87
+ return @rdo_plugin_args[:classname]
88
+ end
89
+
90
+ def name
91
+ return @rdo_plugin_args[:name]
92
+ end
93
+
94
+ #Returns a default name based on the plugin-name. This method can be over-written on the plugin itself.
95
+ def title
96
+ name = Knj::Php.ucwords(self.class.name.to_s[15, 999].gsub("_", " "))
97
+ end
98
+ end
99
+
100
+ class Result
101
+ attr_reader :args
102
+
103
+ @@search_icon = Gdk::Pixbuf.new("#{File.dirname(__FILE__)}/../gfx/search.png")
104
+ def self.search_icon
105
+ return @@search_icon
106
+ end
107
+
108
+ def initialize(args)
109
+ @args = args
110
+ end
111
+
112
+ def icon_pixbuf!
113
+ if @args[:icon]
114
+ if File.exists?(@args[:icon])
115
+ return Gdk::Pixbuf.new(@args[:icon])
116
+ else
117
+ $stderr.puts "Icon does not exist: '#{@args[:icon]}'."
118
+ end
119
+ end
120
+
121
+ return @@search_icon
122
+ end
123
+
124
+ def title!
125
+ if !@args[:title].to_s.empty?
126
+ return @args[:title]
127
+ else
128
+ return "[#{_("no title")}]"
129
+ end
130
+ end
131
+
132
+ def title_html!
133
+ if !@args[:title_html].to_s.empty?
134
+ return @args[:title_html]
135
+ elsif !@args[:title].to_s.empty?
136
+ return "<b>#{Knj::Web.html(@args[:title])}</b>"
137
+ else
138
+ return "<b>[#{_("no title")}]</b>"
139
+ end
140
+ end
141
+
142
+ def descr!
143
+ if !@args[:descr].to_s.empty?
144
+ return @args[:descr]
145
+ else
146
+ return "[#{_("no description")}]"
147
+ end
148
+ end
149
+
150
+ def descr_html!
151
+ if !@args[:descr_html].to_s.empty?
152
+ return @args[:descr_html]
153
+ elsif !@args[:descr].to_s.empty?
154
+ return Knj::Web.html(@args[:descr])
155
+ else
156
+ return "[#{_("no description")}]"
157
+ end
158
+ end
159
+ end
160
+ end
@@ -21,8 +21,8 @@ class Ruby_do::Unix_socket
21
21
  client.each_line do |line|
22
22
  line = line.strip
23
23
 
24
- if line.strip == "open_main_window"
25
- @args[:oata].show_main
24
+ if line.strip == "show_win_main"
25
+ @args[:rdo].show_win_main
26
26
  else
27
27
  $stderr.puts "Unknown line: #{line}"
28
28
  end
data/lib/ruby_do.rb CHANGED
@@ -1,35 +1,102 @@
1
1
  class Ruby_do
2
- class Gui
3
- def self.const_missing(name)
4
- require "#{File.dirname(__FILE__)}/../gui/#{name.to_s.downcase}.rb"
5
- return self.const_get(name)
6
- end
7
- end
8
-
2
+ #Autoloader for subclasses.
9
3
  def self.const_missing(name)
10
4
  require "#{File.dirname(__FILE__)}/../include/#{name.to_s.downcase}.rb"
11
5
  return self.const_get(name)
12
6
  end
13
7
 
14
- attr_reader :args
8
+ attr_reader :args, :db, :ob, :plugin
15
9
 
16
10
  def initialize(args = {})
11
+ #Require various used libs.
17
12
  require "rubygems"
18
- require "gtk2"
19
13
  require "knjrbfw"
20
- require "gettext"
21
14
 
15
+
16
+ #Set arguments (config).
22
17
  homedir = Knj::Os.homedir
23
18
  path = "#{homedir}/.ruby_do"
24
19
  Dir.mkdir(path) if !File.exists?(path)
25
20
 
26
21
  @args = {
27
- :sock_path => "#{path}/sock"
22
+ :sock_path => "#{path}/sock",
23
+ :db_path => "#{path}/database.sqlite3",
24
+ :run_path => "#{path}/run"
28
25
  }.merge(args)
29
26
 
27
+
28
+ #Checks if the run-file exists and creates it if not.
29
+ if File.exists?(@args[:run_path])
30
+ pid = File.read(@args[:run_path]).to_i
31
+ procs = Knj::Unix_proc.list("pids" => [pid])
32
+ if !procs.empty?
33
+ puts "Ruby-Do is already running. Trying to show main window..."
34
+ require "socket"
35
+ UNIXSocket.open(@args[:sock_path]) do |sock|
36
+ sock.puts "show_win_main"
37
+ end
38
+
39
+ exit
40
+ #raise sprintf(_("Ruby-Do is already running with PID '%s'."), pid)
41
+ end
42
+ end
43
+
44
+ File.open(@args[:run_path], "w") do |fp|
45
+ fp.write(Process.pid)
46
+ end
47
+
48
+
49
+ #Require the rest of the heavy libs.
50
+ require "gtk2"
51
+ require "gettext"
52
+ require "sqlite3"
53
+
54
+
55
+ #Load database.
56
+ @db = Knj::Db.new(
57
+ :type => "sqlite3",
58
+ :path => @args[:db_path],
59
+ :return_keys => "symbols",
60
+ :index_append_table_name => true
61
+ )
62
+
63
+
64
+ #Update database structure.
65
+ Knj::Db::Revision.new.init_db("db" => @db, "schema" => Ruby_do::Database::SCHEMA)
66
+
67
+
68
+ #Object framework.
69
+ @ob = Knj::Objects.new(
70
+ :datarow => true,
71
+ :class_path => "#{File.dirname(__FILE__)}/../models",
72
+ :class_pre => "",
73
+ :db => @db,
74
+ :module => Ruby_do::Models
75
+ )
76
+
77
+
78
+
79
+ #Start options-module.
80
+ Knj::Opts.init("knjdb" => @db, "table" => "Option")
81
+
82
+
83
+ #Start unix-socket to enable custom shortcuts.
30
84
  @unix_socket = Ruby_do::Unix_socket.new(:rdo => self)
85
+
86
+
87
+ #Start plugins-engine.
88
+ @plugin = Ruby_do::Plugin.new(:rdo => self)
89
+ @plugin.register_plugins
90
+
91
+
92
+ #Show main window if it is not set to be skipped.
93
+ val = Knj::Opts.get("skip_main_on_startup").to_i
94
+ if val != 1
95
+ self.show_win_main
96
+ end
31
97
  end
32
98
 
99
+ #Shows the main window. If already shown then tries to give it focus.
33
100
  def show_win_main
34
101
  if !@win_main
35
102
  @win_main = Ruby_do::Gui::Win_main.new(:rdo => self)
@@ -38,6 +105,14 @@ class Ruby_do
38
105
  @win_main.show
39
106
  end
40
107
 
108
+ #Opens the properties-window or focuses it if it is already open.
109
+ def show_win_properties
110
+ Knj::Gtk2::Window.unique!("preferences") do
111
+ Ruby_do::Gui::Win_properties.new(:rdo => self)
112
+ end
113
+ end
114
+
115
+ #Joins the Gtk-main-loop.
41
116
  def join
42
117
  Gtk.main
43
118
  end
data/models/plugin.rb ADDED
@@ -0,0 +1,3 @@
1
+ class Ruby_do::Models::Plugin < Knj::Datarow
2
+ attr_accessor :plugin
3
+ end
data/ruby_do.gemspec CHANGED
@@ -5,13 +5,13 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ruby_do}
8
- s.version = "0.0.0"
8
+ s.version = "0.0.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Kasper Johansen"]
12
- s.date = %q{2012-07-08}
12
+ s.date = %q{2012-07-09}
13
13
  s.default_executable = %q{ruby_do.rb}
14
- s.description = %q{A clone of Gnome-Do and Kupfer written in Ruby. }
14
+ s.description = %q{A clone of Gnome-Do and Kupfer written in Ruby.}
15
15
  s.email = %q{k@spernj.org}
16
16
  s.executables = ["ruby_do.rb"]
17
17
  s.extra_rdoc_files = [
@@ -28,10 +28,18 @@ Gem::Specification.new do |s|
28
28
  "Rakefile",
29
29
  "VERSION",
30
30
  "bin/ruby_do.rb",
31
+ "gfx/search.png",
31
32
  "glade/win_main.glade",
33
+ "glade/win_properties.glade",
32
34
  "gui/win_main.rb",
35
+ "gui/win_properties.rb",
36
+ "include/database.rb",
37
+ "include/gui.rb",
38
+ "include/models.rb",
39
+ "include/plugin.rb",
33
40
  "include/unix_socket.rb",
34
41
  "lib/ruby_do.rb",
42
+ "models/plugin.rb",
35
43
  "ruby_do.gemspec",
36
44
  "spec/ruby_do_spec.rb",
37
45
  "spec/spec_helper.rb"
@@ -49,6 +57,7 @@ Gem::Specification.new do |s|
49
57
  s.add_runtime_dependency(%q<gtk2>, [">= 0"])
50
58
  s.add_runtime_dependency(%q<knjrbfw>, [">= 0"])
51
59
  s.add_runtime_dependency(%q<gettext>, [">= 0"])
60
+ s.add_runtime_dependency(%q<sqlite3>, [">= 0"])
52
61
  s.add_development_dependency(%q<rspec>, ["~> 2.8.0"])
53
62
  s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
54
63
  s.add_development_dependency(%q<bundler>, [">= 1.0.0"])
@@ -58,6 +67,7 @@ Gem::Specification.new do |s|
58
67
  s.add_dependency(%q<gtk2>, [">= 0"])
59
68
  s.add_dependency(%q<knjrbfw>, [">= 0"])
60
69
  s.add_dependency(%q<gettext>, [">= 0"])
70
+ s.add_dependency(%q<sqlite3>, [">= 0"])
61
71
  s.add_dependency(%q<rspec>, ["~> 2.8.0"])
62
72
  s.add_dependency(%q<rdoc>, ["~> 3.12"])
63
73
  s.add_dependency(%q<bundler>, [">= 1.0.0"])
@@ -68,6 +78,7 @@ Gem::Specification.new do |s|
68
78
  s.add_dependency(%q<gtk2>, [">= 0"])
69
79
  s.add_dependency(%q<knjrbfw>, [">= 0"])
70
80
  s.add_dependency(%q<gettext>, [">= 0"])
81
+ s.add_dependency(%q<sqlite3>, [">= 0"])
71
82
  s.add_dependency(%q<rspec>, ["~> 2.8.0"])
72
83
  s.add_dependency(%q<rdoc>, ["~> 3.12"])
73
84
  s.add_dependency(%q<bundler>, [">= 1.0.0"])
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: ruby_do
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.0
5
+ version: 0.0.2
6
6
  platform: ruby
7
7
  authors:
8
8
  - Kasper Johansen
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2012-07-08 00:00:00 +02:00
13
+ date: 2012-07-09 00:00:00 +02:00
14
14
  default_executable: ruby_do.rb
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -47,8 +47,19 @@ dependencies:
47
47
  prerelease: false
48
48
  version_requirements: *id003
49
49
  - !ruby/object:Gem::Dependency
50
- name: rspec
50
+ name: sqlite3
51
51
  requirement: &id004 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ type: :runtime
58
+ prerelease: false
59
+ version_requirements: *id004
60
+ - !ruby/object:Gem::Dependency
61
+ name: rspec
62
+ requirement: &id005 !ruby/object:Gem::Requirement
52
63
  none: false
53
64
  requirements:
54
65
  - - ~>
@@ -56,10 +67,10 @@ dependencies:
56
67
  version: 2.8.0
57
68
  type: :development
58
69
  prerelease: false
59
- version_requirements: *id004
70
+ version_requirements: *id005
60
71
  - !ruby/object:Gem::Dependency
61
72
  name: rdoc
62
- requirement: &id005 !ruby/object:Gem::Requirement
73
+ requirement: &id006 !ruby/object:Gem::Requirement
63
74
  none: false
64
75
  requirements:
65
76
  - - ~>
@@ -67,10 +78,10 @@ dependencies:
67
78
  version: "3.12"
68
79
  type: :development
69
80
  prerelease: false
70
- version_requirements: *id005
81
+ version_requirements: *id006
71
82
  - !ruby/object:Gem::Dependency
72
83
  name: bundler
73
- requirement: &id006 !ruby/object:Gem::Requirement
84
+ requirement: &id007 !ruby/object:Gem::Requirement
74
85
  none: false
75
86
  requirements:
76
87
  - - ">="
@@ -78,10 +89,10 @@ dependencies:
78
89
  version: 1.0.0
79
90
  type: :development
80
91
  prerelease: false
81
- version_requirements: *id006
92
+ version_requirements: *id007
82
93
  - !ruby/object:Gem::Dependency
83
94
  name: jeweler
84
- requirement: &id007 !ruby/object:Gem::Requirement
95
+ requirement: &id008 !ruby/object:Gem::Requirement
85
96
  none: false
86
97
  requirements:
87
98
  - - ~>
@@ -89,10 +100,10 @@ dependencies:
89
100
  version: 1.8.4
90
101
  type: :development
91
102
  prerelease: false
92
- version_requirements: *id007
103
+ version_requirements: *id008
93
104
  - !ruby/object:Gem::Dependency
94
105
  name: rcov
95
- requirement: &id008 !ruby/object:Gem::Requirement
106
+ requirement: &id009 !ruby/object:Gem::Requirement
96
107
  none: false
97
108
  requirements:
98
109
  - - ">="
@@ -100,8 +111,8 @@ dependencies:
100
111
  version: "0"
101
112
  type: :development
102
113
  prerelease: false
103
- version_requirements: *id008
104
- description: "A clone of Gnome-Do and Kupfer written in Ruby. "
114
+ version_requirements: *id009
115
+ description: A clone of Gnome-Do and Kupfer written in Ruby.
105
116
  email: k@spernj.org
106
117
  executables:
107
118
  - ruby_do.rb
@@ -120,10 +131,18 @@ files:
120
131
  - Rakefile
121
132
  - VERSION
122
133
  - bin/ruby_do.rb
134
+ - gfx/search.png
123
135
  - glade/win_main.glade
136
+ - glade/win_properties.glade
124
137
  - gui/win_main.rb
138
+ - gui/win_properties.rb
139
+ - include/database.rb
140
+ - include/gui.rb
141
+ - include/models.rb
142
+ - include/plugin.rb
125
143
  - include/unix_socket.rb
126
144
  - lib/ruby_do.rb
145
+ - models/plugin.rb
127
146
  - ruby_do.gemspec
128
147
  - spec/ruby_do_spec.rb
129
148
  - spec/spec_helper.rb
@@ -141,7 +160,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
141
160
  requirements:
142
161
  - - ">="
143
162
  - !ruby/object:Gem::Version
144
- hash: -3142706706586162189
163
+ hash: -2248539457086474609
145
164
  segments:
146
165
  - 0
147
166
  version: "0"