ruber 0.0.1.1
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/COPYING +339 -0
- data/INSTALL +137 -0
- data/LICENSE +8 -0
- data/bin/ruber +65 -0
- data/data/share/apps/ruber/core_components.yaml +31 -0
- data/data/share/apps/ruber/ruberui.rc +109 -0
- data/data/share/icons/ruber.png +0 -0
- data/data/share/pixmaps/ruby.png +0 -0
- data/icons/ruber-16.png +0 -0
- data/icons/ruber-32.png +0 -0
- data/icons/ruber-48.png +0 -0
- data/icons/ruber-8.png +0 -0
- data/lib/ruber/application/application.rb +288 -0
- data/lib/ruber/application/plugin.yaml +11 -0
- data/lib/ruber/component_manager.rb +899 -0
- data/lib/ruber/config/config.rb +82 -0
- data/lib/ruber/config/plugin.yaml +3 -0
- data/lib/ruber/document_project.rb +209 -0
- data/lib/ruber/documents/document_list.rb +416 -0
- data/lib/ruber/documents/plugin.yaml +4 -0
- data/lib/ruber/editor/document.rb +506 -0
- data/lib/ruber/editor/editor_view.rb +167 -0
- data/lib/ruber/editor/ktexteditor_wrapper.rb +202 -0
- data/lib/ruber/exception_widgets.rb +245 -0
- data/lib/ruber/external_program_plugin.rb +397 -0
- data/lib/ruber/filtered_output_widget.rb +342 -0
- data/lib/ruber/gui_states_handler.rb +231 -0
- data/lib/ruber/kde_config_option_backend.rb +167 -0
- data/lib/ruber/kde_sugar.rb +249 -0
- data/lib/ruber/main_window/choose_plugins_dlg.rb +353 -0
- data/lib/ruber/main_window/main_window.rb +524 -0
- data/lib/ruber/main_window/main_window_actions.rb +537 -0
- data/lib/ruber/main_window/main_window_internal.rb +239 -0
- data/lib/ruber/main_window/open_file_in_project_dlg.rb +212 -0
- data/lib/ruber/main_window/output_color_widget.rb +35 -0
- data/lib/ruber/main_window/plugin.yaml +58 -0
- data/lib/ruber/main_window/save_modified_files_dlg.rb +89 -0
- data/lib/ruber/main_window/status_bar.rb +156 -0
- data/lib/ruber/main_window/ui/choose_plugins_widget.rb +90 -0
- data/lib/ruber/main_window/ui/choose_plugins_widget.ui +77 -0
- data/lib/ruber/main_window/ui/main_window_settings_widget.rb +108 -0
- data/lib/ruber/main_window/ui/main_window_settings_widget.ui +89 -0
- data/lib/ruber/main_window/ui/new_project_widget.rb +119 -0
- data/lib/ruber/main_window/ui/new_project_widget.ui +178 -0
- data/lib/ruber/main_window/ui/open_file_in_project_dlg.rb +109 -0
- data/lib/ruber/main_window/ui/open_file_in_project_dlg.ui +168 -0
- data/lib/ruber/main_window/ui/output_color_widget.rb +241 -0
- data/lib/ruber/main_window/ui/output_color_widget.ui +204 -0
- data/lib/ruber/main_window/workspace.rb +442 -0
- data/lib/ruber/output_widget.rb +1093 -0
- data/lib/ruber/plugin.rb +264 -0
- data/lib/ruber/plugin_like.rb +589 -0
- data/lib/ruber/plugin_specification.rb +106 -0
- data/lib/ruber/plugin_specification_reader.rb +451 -0
- data/lib/ruber/project.rb +493 -0
- data/lib/ruber/project_backend.rb +105 -0
- data/lib/ruber/projects/plugin.yaml +11 -0
- data/lib/ruber/projects/project_files_list.rb +314 -0
- data/lib/ruber/projects/project_files_widget.rb +301 -0
- data/lib/ruber/projects/project_list.rb +314 -0
- data/lib/ruber/projects/ui/project_files_rule_chooser_widget.rb +74 -0
- data/lib/ruber/projects/ui/project_files_rule_chooser_widget.ui +61 -0
- data/lib/ruber/projects/ui/project_files_widget.rb +117 -0
- data/lib/ruber/projects/ui/project_files_widget.ui +123 -0
- data/lib/ruber/qt_sugar.rb +673 -0
- data/lib/ruber/settings_container.rb +515 -0
- data/lib/ruber/settings_dialog.rb +244 -0
- data/lib/ruber/settings_dialog_manager.rb +503 -0
- data/lib/ruber/utils.rb +414 -0
- data/lib/ruber/yaml_option_backend.rb +159 -0
- data/outsider_files +15 -0
- data/plugins/autosave/autosave.rb +404 -0
- data/plugins/autosave/plugin.yaml +16 -0
- data/plugins/autosave/ui/autosave_config_widget.rb +83 -0
- data/plugins/autosave/ui/autosave_config_widget.ui +68 -0
- data/plugins/command/command.png +0 -0
- data/plugins/command/command.rb +74 -0
- data/plugins/command/plugin.yaml +11 -0
- data/plugins/find_in_files/find_in_files.rb +337 -0
- data/plugins/find_in_files/find_in_files_dlg.rb +411 -0
- data/plugins/find_in_files/find_in_files_ui.rc +11 -0
- data/plugins/find_in_files/find_in_files_widgets.rb +485 -0
- data/plugins/find_in_files/plugin.yaml +23 -0
- data/plugins/find_in_files/ui/config_widget.rb +58 -0
- data/plugins/find_in_files/ui/config_widget.ui +41 -0
- data/plugins/find_in_files/ui/find_in_files_widget.rb +260 -0
- data/plugins/find_in_files/ui/find_in_files_widget.ui +324 -0
- data/plugins/project_browser/plugin.yaml +10 -0
- data/plugins/project_browser/project_browser.rb +245 -0
- data/plugins/rake/plugin.yaml +39 -0
- data/plugins/rake/rake.png +0 -0
- data/plugins/rake/rake.rb +567 -0
- data/plugins/rake/rake_extension.rb +153 -0
- data/plugins/rake/rake_widgets.rb +615 -0
- data/plugins/rake/rakeui.rc +27 -0
- data/plugins/rake/ui/add_quick_task_widget.rb +71 -0
- data/plugins/rake/ui/add_quick_task_widget.ui +59 -0
- data/plugins/rake/ui/choose_task_widget.rb +77 -0
- data/plugins/rake/ui/choose_task_widget.ui +72 -0
- data/plugins/rake/ui/config_widget.rb +127 -0
- data/plugins/rake/ui/config_widget.ui +123 -0
- data/plugins/rake/ui/project_widget.rb +217 -0
- data/plugins/rake/ui/project_widget.ui +246 -0
- data/plugins/rspec/plugin.yaml +30 -0
- data/plugins/rspec/rspec.png +0 -0
- data/plugins/rspec/rspec.rb +945 -0
- data/plugins/rspec/rspec.svg +90 -0
- data/plugins/rspec/rspecui.rc +20 -0
- data/plugins/rspec/ruber_rspec_formatter.rb +312 -0
- data/plugins/rspec/ui/rspec_project_widget.rb +170 -0
- data/plugins/rspec/ui/rspec_project_widget.ui +193 -0
- data/plugins/ruby_development/plugin.yaml +27 -0
- data/plugins/ruby_development/ruby_development.png +0 -0
- data/plugins/ruby_development/ruby_development.rb +453 -0
- data/plugins/ruby_development/ruby_developmentui.rc +19 -0
- data/plugins/ruby_development/ui/project_widget.rb +112 -0
- data/plugins/ruby_development/ui/project_widget.ui +108 -0
- data/plugins/ruby_runner/config_widget.rb +116 -0
- data/plugins/ruby_runner/plugin.yaml +26 -0
- data/plugins/ruby_runner/project_widget.rb +62 -0
- data/plugins/ruby_runner/ruby.png +0 -0
- data/plugins/ruby_runner/ruby_interpretersui.rc +26 -0
- data/plugins/ruby_runner/ruby_runner.rb +411 -0
- data/plugins/ruby_runner/ui/config_widget.rb +92 -0
- data/plugins/ruby_runner/ui/config_widget.ui +91 -0
- data/plugins/ruby_runner/ui/project_widget.rb +60 -0
- data/plugins/ruby_runner/ui/project_widget.ui +48 -0
- data/plugins/ruby_runner/ui/ruby_runnner_plugin_option_widget.rb +59 -0
- data/plugins/ruby_runner/ui/ruby_runnner_plugin_option_widget.ui +44 -0
- data/plugins/state/plugin.yaml +28 -0
- data/plugins/state/state.rb +520 -0
- data/plugins/state/ui/config_widget.rb +92 -0
- data/plugins/state/ui/config_widget.ui +89 -0
- data/plugins/syntax_checker/plugin.yaml +18 -0
- data/plugins/syntax_checker/syntax_checker.rb +662 -0
- data/ruber.desktop +10 -0
- data/spec/annotation_model_spec.rb +174 -0
- data/spec/common.rb +119 -0
- data/spec/component_manager_spec.rb +1259 -0
- data/spec/document_list_spec.rb +626 -0
- data/spec/document_project_spec.rb +373 -0
- data/spec/document_spec.rb +779 -0
- data/spec/editor_view_spec.rb +167 -0
- data/spec/external_program_plugin_spec.rb +676 -0
- data/spec/filtered_output_widget_spec.rb +642 -0
- data/spec/gui_states_handler_spec.rb +304 -0
- data/spec/kde_config_option_backend_spec.rb +214 -0
- data/spec/kde_sugar_spec.rb +101 -0
- data/spec/ktexteditor_wrapper_spec.rb +305 -0
- data/spec/output_widget_spec.rb +1703 -0
- data/spec/plugin_spec.rb +1393 -0
- data/spec/plugin_specification_reader_spec.rb +1765 -0
- data/spec/plugin_specification_spec.rb +401 -0
- data/spec/project_backend_spec.rb +172 -0
- data/spec/project_files_list_spec.rb +401 -0
- data/spec/project_list_spec.rb +511 -0
- data/spec/project_spec.rb +990 -0
- data/spec/qt_sugar_spec.rb +328 -0
- data/spec/settings_container_spec.rb +617 -0
- data/spec/settings_dialog_manager_spec.rb +773 -0
- data/spec/settings_dialog_spec.rb +419 -0
- data/spec/state_spec.rb +991 -0
- data/spec/utils_spec.rb +406 -0
- data/spec/workspace_spec.rb +869 -0
- data/spec/yaml_option_backend_spec.rb +246 -0
- metadata +284 -0
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
Copyright (C) 2010 by Stefano Crocco
|
|
3
|
+
stefano.crocco@alice.it
|
|
4
|
+
|
|
5
|
+
This program is free software; you can redistribute it andor modify
|
|
6
|
+
it under the terms of the GNU General Public License as published by
|
|
7
|
+
the Free Software Foundation; either version 2 of the License, or
|
|
8
|
+
(at your option) any later version.
|
|
9
|
+
|
|
10
|
+
This program is distributed in the hope that it will be useful,
|
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
GNU General Public License for more details.
|
|
14
|
+
|
|
15
|
+
You should have received a copy of the GNU General Public License
|
|
16
|
+
along with this program; if not, write to the
|
|
17
|
+
Free Software Foundation, Inc.,
|
|
18
|
+
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
19
|
+
=end
|
|
20
|
+
|
|
21
|
+
require 'facets/boolean'
|
|
22
|
+
|
|
23
|
+
module Ruber
|
|
24
|
+
|
|
25
|
+
=begin rdoc
|
|
26
|
+
Module which provides a mechanism to enable/disable actions basing on whether
|
|
27
|
+
some 'states' are *true* or *false*. This functionality is similar to that provided
|
|
28
|
+
by the KDE XML GUI framework, but much more flexible.
|
|
29
|
+
|
|
30
|
+
A state is simply a string to which a *true* or *false* value is associated. For
|
|
31
|
+
example, the value associated with a state called <tt>"current_document_modified"</tt>
|
|
32
|
+
should be set to *true* whenever the current document becomes modified and to
|
|
33
|
+
*false* when it's saved. Through the rest of this documentation, the expression
|
|
34
|
+
<i>the value of the state</i> will mean <i>the true or false value associated with
|
|
35
|
+
the state</i>.
|
|
36
|
+
|
|
37
|
+
The system works this way: an action
|
|
38
|
+
is registered using the <tt>register_action_handler</tt> method. To do
|
|
39
|
+
so, a block (called a _handler_) and a list of states the action depends on are
|
|
40
|
+
supplied.
|
|
41
|
+
|
|
42
|
+
The value of a state is modified using the <tt>change_state</tt> method. That method
|
|
43
|
+
will call the handlers of every action depending on the changed state, passing it
|
|
44
|
+
a list of all known states, and enables or disable them according to the value
|
|
45
|
+
returned by the block.
|
|
46
|
+
|
|
47
|
+
Whenever this module is included in a class derived from <tt>Qt::Object</tt>, it
|
|
48
|
+
will define a signal with the following signature <tt>ui_state_changed(QString, bool)</tt>,
|
|
49
|
+
which will be emitted from the <tt>state_changed</tt> method. The signal won't be
|
|
50
|
+
defined if the module _extends_ an object (even if it is <tt>Qt::Object</tt>).
|
|
51
|
+
|
|
52
|
+
<b>Note:</b> before using any of the functionality provided by this module, you
|
|
53
|
+
must call the <tt>initialize_states_handler</tt> method. This is usually done in
|
|
54
|
+
the +initialize+ method of the including class.
|
|
55
|
+
=end
|
|
56
|
+
module GuiStatesHandler
|
|
57
|
+
|
|
58
|
+
Data = Struct.new :action, :handler, :extra_id #:nodoc:
|
|
59
|
+
|
|
60
|
+
=begin rdoc
|
|
61
|
+
Override of +Module#included+ which is called whenever the module is included in
|
|
62
|
+
another module or class.
|
|
63
|
+
|
|
64
|
+
If _other_ is a class derived from <tt>Qt::Object</tt>, it defines the <tt>ui_state_changed(QString, bool)</tt>
|
|
65
|
+
signal.
|
|
66
|
+
=end
|
|
67
|
+
def self.included other
|
|
68
|
+
other.send :signals, 'ui_state_changed(QString, bool)' if other.ancestors.include?(Qt::Object)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
=begin rdoc
|
|
72
|
+
Makes an action known to the system, telling it on which states it depends and
|
|
73
|
+
which handler should be used to decide whether the action should be enabled or
|
|
74
|
+
not.
|
|
75
|
+
|
|
76
|
+
_action_ is a <tt>Qt::Action</tt> or derived object. _states_ is an array of strings
|
|
77
|
+
and/or symbols or a single string or symbol. Each string/symbol represents the
|
|
78
|
+
name of a state _action_ depends on (that is, a state whose value concurs in
|
|
79
|
+
deciding whether _action_ should be enabled or not).
|
|
80
|
+
|
|
81
|
+
_blk_ is the handler associated with _action_. It takes a single argument, which
|
|
82
|
+
will be a hash having the names of the states as keys and their values as values,
|
|
83
|
+
and returns a true value if, basing on the values of the states, _action_ should
|
|
84
|
+
be enabled and a false value if it shouldn't.
|
|
85
|
+
|
|
86
|
+
_option_ contains some options. One is <tt>:check</tt>: if *true*, the handler
|
|
87
|
+
will be called (and the action enabled or disabled) immediately after registering
|
|
88
|
+
it; if it's false, nothing will be done until one of the states in _states_
|
|
89
|
+
changes. The other option is <tt>:extra_id</tt>. If not *nil*, it is an extra value
|
|
90
|
+
used to identify the action (see <tt>remove_action_handler_for</tt> for more information).
|
|
91
|
+
|
|
92
|
+
If the block is not given and _states_ is a string, a symbol or an array with only
|
|
93
|
+
one element, then a default handler is generated (if _states_ is an array with
|
|
94
|
+
more than one element, +ArgumentError+ is raised). The default handler returns the
|
|
95
|
+
same value as the state value. If the only state starts with a <tt>!</tt>, instead,
|
|
96
|
+
the leading exclamation mark is removed from the name of the state and the generated
|
|
97
|
+
handler returns the opposite of the state value (that is, returns *true* if the
|
|
98
|
+
state is *false* and vice versa).
|
|
99
|
+
|
|
100
|
+
<b>Note:</b> even if states can be specified as symbols, they're actually always
|
|
101
|
+
converted to strings.
|
|
102
|
+
|
|
103
|
+
====Examples
|
|
104
|
+
|
|
105
|
+
In all the following examples, <tt>action_handler</tt> is an instance of a class
|
|
106
|
+
which includes this module.
|
|
107
|
+
|
|
108
|
+
This registers an handler for an action which depends on the two states 'a' and
|
|
109
|
+
'b'. The action should be enabled when 'a' is *true* and 'b' is *false* or when
|
|
110
|
+
'a' is *false*, regardless of 'b'.
|
|
111
|
+
|
|
112
|
+
action_handler.register_action_handler KDE::Action.new(nil), ['a', 'b'] do |states|
|
|
113
|
+
if states['a'] and !states['b'] then true
|
|
114
|
+
elsif !states['a'] then true
|
|
115
|
+
else false
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
This registers an action depending only on the state 'a' which should be enabled
|
|
120
|
+
when 'a' is *true* and disabled when 'a' is *false*.
|
|
121
|
+
|
|
122
|
+
action_handler.register_action_handler KDE::Action.new(nil), ['a'] do |states|
|
|
123
|
+
states['a']
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
Here we could also have passed simply the string 'a' as second argument. Even easier,
|
|
127
|
+
we could have omitted the block, relying on the default handler that would have
|
|
128
|
+
been generated:
|
|
129
|
+
action_handler.register_action_handler KDE::Action.new(nil), 'a'
|
|
130
|
+
|
|
131
|
+
Here, still using the default handler, register an handler for an action which
|
|
132
|
+
depends only on the state 'a' but needs to be enabled when 'a' is *false* and
|
|
133
|
+
disabled when it's *true*.
|
|
134
|
+
action_handler.register_action_handler KDE::Action.new(nil), '!a'
|
|
135
|
+
=end
|
|
136
|
+
def register_action_handler action, states, options = {:check => true}, &blk
|
|
137
|
+
states = Array(states)
|
|
138
|
+
states = states.map &:to_s
|
|
139
|
+
if !blk and states.size > 1
|
|
140
|
+
raise ArgumentError, "If more than one state is supplied, a block is needed"
|
|
141
|
+
elsif !blk
|
|
142
|
+
if states[0].start_with? '!'
|
|
143
|
+
states[0] = states[0][1..-1]
|
|
144
|
+
blk = Proc.new{|s| !s[states[0]]}
|
|
145
|
+
else blk = Proc.new{|s| s[states[0]]}
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
data = Data.new(action, blk, options[:extra_id])
|
|
149
|
+
states.each{|s| @gui_state_handler_handlers[s.to_s] << data}
|
|
150
|
+
if options[:check]
|
|
151
|
+
action.enabled = blk.call @gui_state_handler_states
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
=begin rdoc
|
|
156
|
+
Remove the existing handlers for actions matching _action_ and <i>extra_id</i>.
|
|
157
|
+
|
|
158
|
+
_action_ may be either a <tt>Qt::Action</tt> or a string. If it is a <tt>Qt::Action</tt>,
|
|
159
|
+
then only the handlers for that object will be removed (actually, there usually
|
|
160
|
+
is only one handler).
|
|
161
|
+
|
|
162
|
+
If _action_ is a string, all handlers for actions whose
|
|
163
|
+
<tt>object_name</tt> is _action_ will be removed. In this case, the <i>extra_id</i>
|
|
164
|
+
parameter can be used narrow the list of actions to remove (for example, if there
|
|
165
|
+
are more than one action with the same name but different <tt>extra_id</tt>s). If
|
|
166
|
+
<tt>extra_id</tt> isn't *nil*, then only actions whose <tt>object_name</tt> is
|
|
167
|
+
_action_ and which were given an <tt>extra_id</tt> equal to <i>extra_id</i> will
|
|
168
|
+
be removed.
|
|
169
|
+
=end
|
|
170
|
+
def remove_action_handler_for action, extra_id = nil
|
|
171
|
+
if action.is_a? KDE::Action
|
|
172
|
+
@gui_state_handler_handlers.each_value do |v|
|
|
173
|
+
v.delete_if{|d| d.action.same? action}
|
|
174
|
+
end
|
|
175
|
+
elsif extra_id
|
|
176
|
+
@gui_state_handler_handlers.each_value do |v|
|
|
177
|
+
v.delete_if{|d| d.action.object_name == action and d.extra_id == extra_id}
|
|
178
|
+
end
|
|
179
|
+
else
|
|
180
|
+
@gui_state_handler_handlers.each_value do |v|
|
|
181
|
+
v.delete_if{|d| d.action.object_name == action}
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
@gui_state_handler_handlers.delete_if{|k, v| v.empty?}
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
=begin rdoc
|
|
188
|
+
Sets the value associated with the state _state_ to _value_, then calls the
|
|
189
|
+
handlers of all actions depending on _state_ and enables or disables them according
|
|
190
|
+
to the returned value. If *self* is an instance of <tt>Qt::Object</tt>, it also
|
|
191
|
+
emits the <tt>ui_state_changed(QString, bool)</tt> signal, passing _state_ and
|
|
192
|
+
_value_ (converted to bool) as arguments.
|
|
193
|
+
|
|
194
|
+
_state_ can be either a string or symbol (in this case, it'll be converted to string).
|
|
195
|
+
_value_ can be any value. It will be converted to *true* or *false* according to
|
|
196
|
+
the usual ruby rules before being used.
|
|
197
|
+
=end
|
|
198
|
+
def change_state state, value
|
|
199
|
+
state = state.to_s
|
|
200
|
+
value = value.to_bool
|
|
201
|
+
@gui_state_handler_states[state] = value
|
|
202
|
+
@gui_state_handler_handlers[state].each do |d|
|
|
203
|
+
d.action.enabled = d.handler.call @gui_state_handler_states
|
|
204
|
+
end
|
|
205
|
+
emit ui_state_changed state, value if self.is_a?(Qt::Object)
|
|
206
|
+
end
|
|
207
|
+
alias_method :set_state, :change_state
|
|
208
|
+
|
|
209
|
+
=begin rdoc
|
|
210
|
+
Returns the value associated with the state _name_. If the value of the state
|
|
211
|
+
has never been set using <tt>change_state</tt>, *nil* will be returned.
|
|
212
|
+
=end
|
|
213
|
+
def state name
|
|
214
|
+
@gui_state_handler_states[name.to_s]
|
|
215
|
+
end
|
|
216
|
+
alias_method :gui_state, :state
|
|
217
|
+
|
|
218
|
+
private
|
|
219
|
+
|
|
220
|
+
=begin rdoc
|
|
221
|
+
Initializes the instance variables used by the module. It must be called before
|
|
222
|
+
any other method in the module is used.
|
|
223
|
+
=end
|
|
224
|
+
def initialize_states_handler
|
|
225
|
+
@gui_state_handler_states = {}
|
|
226
|
+
@gui_state_handler_handlers = Hash.new{|h, k| h[k] = []}
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
end
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
Copyright (C) 2010 by Stefano Crocco
|
|
3
|
+
stefano.crocco@alice.it
|
|
4
|
+
|
|
5
|
+
This program is free software; you can redistribute it andor modify
|
|
6
|
+
it under the terms of the GNU General Public License as published by
|
|
7
|
+
the Free Software Foundation; either version 2 of the License, or
|
|
8
|
+
(at your option) any later version.
|
|
9
|
+
|
|
10
|
+
This program is distributed in the hope that it will be useful,
|
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
GNU General Public License for more details.
|
|
14
|
+
|
|
15
|
+
You should have received a copy of the GNU General Public License
|
|
16
|
+
along with this program; if not, write to the
|
|
17
|
+
Free Software Foundation, Inc.,
|
|
18
|
+
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
19
|
+
=end
|
|
20
|
+
|
|
21
|
+
require 'facets/boolean'
|
|
22
|
+
require 'facets/kernel/deep_copy'
|
|
23
|
+
|
|
24
|
+
module Ruber
|
|
25
|
+
|
|
26
|
+
=begin rdoc
|
|
27
|
+
Backend for SettingsContainer which saves the options using the KDE configuration
|
|
28
|
+
system (namely, <tt>KDE::Config</tt>).
|
|
29
|
+
|
|
30
|
+
To allow to store values of types which the KDE configuration system can't handle
|
|
31
|
+
(for example, hashes or symbols), those values are converted to strings using YAML
|
|
32
|
+
on writing and converted back to their original values on reading. This also happens
|
|
33
|
+
when the value of the option and its default value are of different classes (the
|
|
34
|
+
reason for this is that otherwise the object would be converted to the class of
|
|
35
|
+
the default value when calling <tt>KDE::ConfigGroup#read_entry</tt>).
|
|
36
|
+
|
|
37
|
+
To know which options are stored as YAML strings and which aren't, an extra option
|
|
38
|
+
is written to file. It's store in the "Ruber Internal" group under the "Yaml options"
|
|
39
|
+
key and contains a list of the options which have been stored in YAML format. Each
|
|
40
|
+
entry of this option has the form "group_name/option_name".
|
|
41
|
+
|
|
42
|
+
Group names and option names are converted to a more human friendly form before
|
|
43
|
+
being written to the file: underscores are replaced by spaces and the first letters
|
|
44
|
+
of all the words are capitalized.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
TODO: it seems that writing and reading some kind of options doesn't work for the ruby bindings,
|
|
48
|
+
while it works in C++ (for example, fonts). To work around this, I've changed a
|
|
49
|
+
bit the code where the actual read and write was done. I've asked on the mailing
|
|
50
|
+
list about this. When I get an answer, I'll see how to better fix this.
|
|
51
|
+
=end
|
|
52
|
+
class KDEConfigSettingsBackend
|
|
53
|
+
|
|
54
|
+
=begin rdoc
|
|
55
|
+
An array containing the classes which can be handled directly by KDE::Config.
|
|
56
|
+
+Array+ isn't included because whether it can be handled or not depends on its
|
|
57
|
+
contents.
|
|
58
|
+
=end
|
|
59
|
+
RECOGNIZED_CLASSES = [Qt::Variant, String, Qt::Font, Qt::Point, Qt::Rect,
|
|
60
|
+
Qt::Size, Qt::Color, Fixnum, Bignum, TrueClass, FalseClass,
|
|
61
|
+
Float, Qt::DateTime, Qt::Time]
|
|
62
|
+
|
|
63
|
+
=begin rdoc
|
|
64
|
+
Creates a new KDEConfigSettingsBackend. _filename_ is the name of the file where
|
|
65
|
+
the options will be stored, while _mode_ is the open flag to pass to
|
|
66
|
+
<tt>KDE::SharedConfig#open_config</tt>. If _filename_ is not given, the global config
|
|
67
|
+
object is used.
|
|
68
|
+
|
|
69
|
+
<b>Note:</b> this class uses <tt>KDE::SharedConfig</tt>, rather than a regular
|
|
70
|
+
<tt>KDE::Config</tt>. This means that if another instance of this class is created
|
|
71
|
+
for the same file, they'll share the configuration object.
|
|
72
|
+
=end
|
|
73
|
+
def initialize filename = nil, mode = KDE::Config::FullConfig
|
|
74
|
+
@config = if filename then KDE::SharedConfig.open_config filename, mode
|
|
75
|
+
else KDE::Global.config
|
|
76
|
+
end
|
|
77
|
+
yaml_options = @config.group('Ruber Internal').read_entry('Yaml options', [])
|
|
78
|
+
@yaml_options = yaml_options.map{|o| o.split('/').map( &:to_sym)}
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
=begin rdoc
|
|
82
|
+
Returns the option corresponding to _opt_. _opt_ is an option object with
|
|
83
|
+
the characteristics specified in SettingsContainer#add_option. If an option with
|
|
84
|
+
the same name and value of _opt_ isn't stored in the file, the option
|
|
85
|
+
default value will be returned
|
|
86
|
+
=end
|
|
87
|
+
def [] opt
|
|
88
|
+
grp = KDE::ConfigGroup.new @config, humanize(opt.group)
|
|
89
|
+
return opt.default.deep_copy unless grp.has_key(humanize(opt.name))
|
|
90
|
+
if @yaml_options.include? [opt.group, opt.name] or !recognized_value?(opt.default)
|
|
91
|
+
YAML.load grp.read_entry humanize(opt.name), ''
|
|
92
|
+
# else res = grp.read_entry humanize(opt.name), opt.default
|
|
93
|
+
else (grp.read_entry humanize(opt.name), Qt::Variant.from_value(opt.default)).value
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
=begin rdoc
|
|
98
|
+
Writes the options back to the file. _options_ is a
|
|
99
|
+
hash with option objects as keys and the corresponding values as entries. There
|
|
100
|
+
are two issues to be aware of:
|
|
101
|
+
* if one of the options in _options_ has a value which is equal to its default
|
|
102
|
+
value, it won't be written to file
|
|
103
|
+
* _options_ is interpreted as only containing the options which might have changed:
|
|
104
|
+
any option already in the file but not contained in _options_ is left unchanged
|
|
105
|
+
|
|
106
|
+
This method also updates the list of options written in YAML format, both in memory
|
|
107
|
+
and on file.
|
|
108
|
+
=end
|
|
109
|
+
def write opts
|
|
110
|
+
opts.each_pair do |opt, value|
|
|
111
|
+
if opt.default == value
|
|
112
|
+
@config.group(humanize(opt.group)).delete_entry humanize(opt.name)
|
|
113
|
+
next
|
|
114
|
+
elsif need_yaml? opt, value
|
|
115
|
+
@config.group(humanize(opt.group)).write_entry(humanize(opt.name), YAML.dump(value))
|
|
116
|
+
@yaml_options << [opt.group, opt.name]
|
|
117
|
+
# else @config.group(humanize(opt.group)).write_entry(humanize(opt.name), value)
|
|
118
|
+
else @config.group(humanize(opt.group)).write_entry(humanize(opt.name), Qt::Variant.from_value(value))
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
@yaml_options.uniq!
|
|
122
|
+
@config.group('Ruber Internal').write_entry('Yaml options', @yaml_options.map{|i| i.join('/')})
|
|
123
|
+
@config.sync
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
private
|
|
127
|
+
|
|
128
|
+
=begin rdoc
|
|
129
|
+
Returns the human-friendly version of the _data_ (which must be a string or symbol).
|
|
130
|
+
This is obtained by replacing all underscores with spaces and capitalizing the
|
|
131
|
+
first letter of each word.
|
|
132
|
+
=end
|
|
133
|
+
def humanize data
|
|
134
|
+
data.to_s.split('_').map{|s| s.capitalize}.join ' '
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
=begin rdoc
|
|
138
|
+
Tells whether the object _value_ is recognized by <tt>KDE::ConfigGroup</tt>. It
|
|
139
|
+
returns *true* if the object's class is included in <tt>RECOGNIZED_CLASSES</tt>
|
|
140
|
+
or if it is an array and all its entries are of classes included in that array
|
|
141
|
+
and *false* otherwise.
|
|
142
|
+
=end
|
|
143
|
+
def recognized_value? value
|
|
144
|
+
if RECOGNIZED_CLASSES.include? value.class then true
|
|
145
|
+
elsif value.is_a? Array then value.all?{|v| RECOGNIZED_CLASSES.include? v.class}
|
|
146
|
+
else false
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
=begin rdoc
|
|
151
|
+
Tells whether the value _value_ for the option represented by the option object
|
|
152
|
+
_opt_ needs to be stored using YAML or not. In particular, this returns *true*
|
|
153
|
+
if the value can't be handled by <tt>KDE::ConfigGroup</tt> or if the class of _value_
|
|
154
|
+
and that of the default value of the option differ (except in the case when one
|
|
155
|
+
is *true* and the other is *false*) and *false* otherwise.
|
|
156
|
+
=end
|
|
157
|
+
def need_yaml? opt, value
|
|
158
|
+
if !recognized_value? value then return true
|
|
159
|
+
elsif value.class == opt.default.class then return false
|
|
160
|
+
elsif value.bool? and opt.default.bool? then return false
|
|
161
|
+
else return true
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
end
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
Copyright (C) 2010 by Stefano Crocco
|
|
3
|
+
stefano.crocco@alice.it
|
|
4
|
+
|
|
5
|
+
This program is free software; you can redistribute it andor modify
|
|
6
|
+
it under the terms of the GNU General Public License as published by
|
|
7
|
+
the Free Software Foundation; either version 2 of the License, or
|
|
8
|
+
(at your option) any later version.
|
|
9
|
+
|
|
10
|
+
This program is distributed in the hope that it will be useful,
|
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
GNU General Public License for more details.
|
|
14
|
+
|
|
15
|
+
You should have received a copy of the GNU General Public License
|
|
16
|
+
along with this program; if not, write to the
|
|
17
|
+
Free Software Foundation, Inc.,
|
|
18
|
+
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
19
|
+
=end
|
|
20
|
+
|
|
21
|
+
require 'yaml'
|
|
22
|
+
|
|
23
|
+
module KDE
|
|
24
|
+
|
|
25
|
+
class Url
|
|
26
|
+
|
|
27
|
+
yaml_as "tag:ruby.yaml.org,2002:KDE::Url"
|
|
28
|
+
|
|
29
|
+
def self.yaml_new cls, tag, val
|
|
30
|
+
KDE::Url.new val
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def to_yaml opts = {}
|
|
34
|
+
YAML.quick_emit(self, opts) do |out|
|
|
35
|
+
out.scalar taguri, to_encoded.to_s, :plain
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def _dump _
|
|
40
|
+
to_encoded.to_s
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def self._load str
|
|
44
|
+
self.new str
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def local_file?
|
|
48
|
+
is_local_file
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
class TabWidget
|
|
54
|
+
|
|
55
|
+
include QtEnumerable
|
|
56
|
+
|
|
57
|
+
def empty?
|
|
58
|
+
count == 0
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def each
|
|
62
|
+
count.times{|i| yield widget( i )}
|
|
63
|
+
end
|
|
64
|
+
alias_method :each_widget, :each
|
|
65
|
+
|
|
66
|
+
alias_method :tabs, :to_a
|
|
67
|
+
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
class ConfigGroup
|
|
71
|
+
|
|
72
|
+
include QtEnumerable
|
|
73
|
+
|
|
74
|
+
def each_key
|
|
75
|
+
key_list.each{|k| yield k}
|
|
76
|
+
end
|
|
77
|
+
alias_method :each, :each_key
|
|
78
|
+
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
class IconLoader
|
|
82
|
+
|
|
83
|
+
def self.load_pixmap name, hash = {}
|
|
84
|
+
args = {:null_icon => true, :group => Small, :size => 0, :state => DefaultState, :overlays => []}
|
|
85
|
+
args.merge! hash
|
|
86
|
+
pix = global.load_icon name, args[:group], args[:size], args[:state],
|
|
87
|
+
args[:overlays], nil, args[:null_icon]
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def self.load_mime_type_pixmap name, hash = {}
|
|
91
|
+
args = {:group => Small, :size => 0, :state => DefaultState, :overlays => []}
|
|
92
|
+
args.merge! hash
|
|
93
|
+
pix = global.load_mime_type_icon name, args[:group], args[:size], args[:state],
|
|
94
|
+
args[:overlays], nil
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def self.load_icon name, hash = {}
|
|
98
|
+
pix = load_pixmap name, hash
|
|
99
|
+
Qt::Icon.new pix
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def self.pixmap_path name, group = Small, allow_null = true
|
|
103
|
+
global.icon_path name, group, allow_null
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
class ListWidget
|
|
109
|
+
|
|
110
|
+
include QtEnumerable
|
|
111
|
+
|
|
112
|
+
def each
|
|
113
|
+
count.times{|i| yield item(i)}
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
class CmdLineArgs
|
|
119
|
+
|
|
120
|
+
def files
|
|
121
|
+
res = []
|
|
122
|
+
count.times{|i| res << ::File.expand_path(arg(i))}
|
|
123
|
+
res
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
class InputDialog
|
|
129
|
+
|
|
130
|
+
DEFAULT = {:value => '', :parent => nil, :validator => nil, :mask => '',
|
|
131
|
+
:whats_this => '', :completion_list => []}
|
|
132
|
+
|
|
133
|
+
def self.get_text caption = '', label = '', args = {}
|
|
134
|
+
args = DEFAULT.merge args
|
|
135
|
+
getText caption, label, args[:value], nil, args[:parent], args[:validator],
|
|
136
|
+
args[:mask], args[:whats_this], args[:completion_list]
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
class XMLGUIClient
|
|
142
|
+
|
|
143
|
+
=begin rdoc
|
|
144
|
+
Changes the GUI state _state_, by calling KDE::XMLGUIClient#stateChanged. If
|
|
145
|
+
_value_ is a true value, stateChanged will be called with KDE::XMLGUIClient::StateNoReverse,
|
|
146
|
+
if it is *false* or *nil*, it will be called with KDE::XMLGUIClient::StateReverse.
|
|
147
|
+
|
|
148
|
+
Returns KDE::XMLGUIClient::StateNoReverse or KDE::XMLGUIClient::StateReverse,
|
|
149
|
+
depending on which argument was passed to stateChanged
|
|
150
|
+
=end
|
|
151
|
+
def change_state state, value
|
|
152
|
+
value = value ? StateNoReverse : StateReverse
|
|
153
|
+
stateChanged(state, value)
|
|
154
|
+
value
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
=begin rdoc
|
|
158
|
+
Changes the GUI state _state_, by calling KDE::XMLGUIClient#stateChanged. If
|
|
159
|
+
_value_ is a true value, stateChanged will be called with KDE::XMLGUIClient::StateNoReverse,
|
|
160
|
+
if it is *false* or *nil*, it will be called with KDE::XMLGUIClient::StateReverse.
|
|
161
|
+
|
|
162
|
+
Unlike change_state, this method recursively changes the state of child clients,
|
|
163
|
+
calling their global_change_state method, if defined, or their stateChanged method
|
|
164
|
+
otherwise.
|
|
165
|
+
=end
|
|
166
|
+
def global_change_state state, value
|
|
167
|
+
res = change_state state, value
|
|
168
|
+
child_clients.each do |c|
|
|
169
|
+
if c.respond_to? :global_change_state then c.global_change_state state, value
|
|
170
|
+
else c.send :stateChanged, state, res
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
res
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
class MimeType
|
|
179
|
+
|
|
180
|
+
=begin rdoc
|
|
181
|
+
Compares *self* with the string _str_. The comparison works as follows:
|
|
182
|
+
* if _str_ doesn't start with <tt>!</tt> or <tt>=</tt>, it works as
|
|
183
|
+
<tt>KDE::MimeType#is</tt>
|
|
184
|
+
* if _str_ starts with <tt>!</tt>, returns the oppsite of <tt>KDE::MimeType#is</tt>
|
|
185
|
+
* if _str_ starts with <tt>=</tt>, makes an exact match between _str_ and <tt>self.name</tt>
|
|
186
|
+
* if _str_ starts with <tt>!=</tt> or <tt>=!</tt>, makes an exact match and inverts
|
|
187
|
+
it
|
|
188
|
+
=end
|
|
189
|
+
def =~ str
|
|
190
|
+
str = str.sub(/^([!=]{0,2})/, '')
|
|
191
|
+
case $1
|
|
192
|
+
when '!' then !(self.is str)
|
|
193
|
+
when '=' then self.name == str
|
|
194
|
+
when '!=', '=!' then !(self.name == str)
|
|
195
|
+
else self.is str
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
class Application
|
|
202
|
+
|
|
203
|
+
=begin rdoc
|
|
204
|
+
Executes the block between calls to <tt>set_override_cursor</tt> and
|
|
205
|
+
<tt>restore_override_cursor</tt>. The override cursor used is _cursor_.
|
|
206
|
+
|
|
207
|
+
This method returns the value returned by the block
|
|
208
|
+
=end
|
|
209
|
+
def self.with_override_cursor cursor = Qt::Cursor.new(Qt::WaitCursor)
|
|
210
|
+
begin
|
|
211
|
+
set_override_cursor cursor
|
|
212
|
+
res = yield
|
|
213
|
+
ensure restore_override_cursor
|
|
214
|
+
end
|
|
215
|
+
res
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
=begin rdoc
|
|
219
|
+
The same as KDE::Application.with_override_cursor
|
|
220
|
+
=end
|
|
221
|
+
def with_override_cursor cursor = Qt::Cursor.new(Qt::WaitCursor), &blk
|
|
222
|
+
KDE::Application.with_override_cursor cursor, &blk
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
class ComboBox
|
|
228
|
+
|
|
229
|
+
include QtEnumerable
|
|
230
|
+
|
|
231
|
+
=begin rdoc
|
|
232
|
+
Returns an array containing the text of all items in the combo box
|
|
233
|
+
=end
|
|
234
|
+
def items
|
|
235
|
+
count.times.map{|i| item_text(i)}
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
=begin rdoc
|
|
239
|
+
Calls the block for each item. If no block is given, returns an +Enumerator+ which
|
|
240
|
+
does the same
|
|
241
|
+
=end
|
|
242
|
+
def each &blk
|
|
243
|
+
blk ? items.each(&blk) : items.each
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
end
|
|
249
|
+
|