ruby_do 0.0.0 → 0.0.2

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