ruber 0.0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (166) hide show
  1. data/COPYING +339 -0
  2. data/INSTALL +137 -0
  3. data/LICENSE +8 -0
  4. data/bin/ruber +65 -0
  5. data/data/share/apps/ruber/core_components.yaml +31 -0
  6. data/data/share/apps/ruber/ruberui.rc +109 -0
  7. data/data/share/icons/ruber.png +0 -0
  8. data/data/share/pixmaps/ruby.png +0 -0
  9. data/icons/ruber-16.png +0 -0
  10. data/icons/ruber-32.png +0 -0
  11. data/icons/ruber-48.png +0 -0
  12. data/icons/ruber-8.png +0 -0
  13. data/lib/ruber/application/application.rb +288 -0
  14. data/lib/ruber/application/plugin.yaml +11 -0
  15. data/lib/ruber/component_manager.rb +899 -0
  16. data/lib/ruber/config/config.rb +82 -0
  17. data/lib/ruber/config/plugin.yaml +3 -0
  18. data/lib/ruber/document_project.rb +209 -0
  19. data/lib/ruber/documents/document_list.rb +416 -0
  20. data/lib/ruber/documents/plugin.yaml +4 -0
  21. data/lib/ruber/editor/document.rb +506 -0
  22. data/lib/ruber/editor/editor_view.rb +167 -0
  23. data/lib/ruber/editor/ktexteditor_wrapper.rb +202 -0
  24. data/lib/ruber/exception_widgets.rb +245 -0
  25. data/lib/ruber/external_program_plugin.rb +397 -0
  26. data/lib/ruber/filtered_output_widget.rb +342 -0
  27. data/lib/ruber/gui_states_handler.rb +231 -0
  28. data/lib/ruber/kde_config_option_backend.rb +167 -0
  29. data/lib/ruber/kde_sugar.rb +249 -0
  30. data/lib/ruber/main_window/choose_plugins_dlg.rb +353 -0
  31. data/lib/ruber/main_window/main_window.rb +524 -0
  32. data/lib/ruber/main_window/main_window_actions.rb +537 -0
  33. data/lib/ruber/main_window/main_window_internal.rb +239 -0
  34. data/lib/ruber/main_window/open_file_in_project_dlg.rb +212 -0
  35. data/lib/ruber/main_window/output_color_widget.rb +35 -0
  36. data/lib/ruber/main_window/plugin.yaml +58 -0
  37. data/lib/ruber/main_window/save_modified_files_dlg.rb +89 -0
  38. data/lib/ruber/main_window/status_bar.rb +156 -0
  39. data/lib/ruber/main_window/ui/choose_plugins_widget.rb +90 -0
  40. data/lib/ruber/main_window/ui/choose_plugins_widget.ui +77 -0
  41. data/lib/ruber/main_window/ui/main_window_settings_widget.rb +108 -0
  42. data/lib/ruber/main_window/ui/main_window_settings_widget.ui +89 -0
  43. data/lib/ruber/main_window/ui/new_project_widget.rb +119 -0
  44. data/lib/ruber/main_window/ui/new_project_widget.ui +178 -0
  45. data/lib/ruber/main_window/ui/open_file_in_project_dlg.rb +109 -0
  46. data/lib/ruber/main_window/ui/open_file_in_project_dlg.ui +168 -0
  47. data/lib/ruber/main_window/ui/output_color_widget.rb +241 -0
  48. data/lib/ruber/main_window/ui/output_color_widget.ui +204 -0
  49. data/lib/ruber/main_window/workspace.rb +442 -0
  50. data/lib/ruber/output_widget.rb +1093 -0
  51. data/lib/ruber/plugin.rb +264 -0
  52. data/lib/ruber/plugin_like.rb +589 -0
  53. data/lib/ruber/plugin_specification.rb +106 -0
  54. data/lib/ruber/plugin_specification_reader.rb +451 -0
  55. data/lib/ruber/project.rb +493 -0
  56. data/lib/ruber/project_backend.rb +105 -0
  57. data/lib/ruber/projects/plugin.yaml +11 -0
  58. data/lib/ruber/projects/project_files_list.rb +314 -0
  59. data/lib/ruber/projects/project_files_widget.rb +301 -0
  60. data/lib/ruber/projects/project_list.rb +314 -0
  61. data/lib/ruber/projects/ui/project_files_rule_chooser_widget.rb +74 -0
  62. data/lib/ruber/projects/ui/project_files_rule_chooser_widget.ui +61 -0
  63. data/lib/ruber/projects/ui/project_files_widget.rb +117 -0
  64. data/lib/ruber/projects/ui/project_files_widget.ui +123 -0
  65. data/lib/ruber/qt_sugar.rb +673 -0
  66. data/lib/ruber/settings_container.rb +515 -0
  67. data/lib/ruber/settings_dialog.rb +244 -0
  68. data/lib/ruber/settings_dialog_manager.rb +503 -0
  69. data/lib/ruber/utils.rb +414 -0
  70. data/lib/ruber/yaml_option_backend.rb +159 -0
  71. data/outsider_files +15 -0
  72. data/plugins/autosave/autosave.rb +404 -0
  73. data/plugins/autosave/plugin.yaml +16 -0
  74. data/plugins/autosave/ui/autosave_config_widget.rb +83 -0
  75. data/plugins/autosave/ui/autosave_config_widget.ui +68 -0
  76. data/plugins/command/command.png +0 -0
  77. data/plugins/command/command.rb +74 -0
  78. data/plugins/command/plugin.yaml +11 -0
  79. data/plugins/find_in_files/find_in_files.rb +337 -0
  80. data/plugins/find_in_files/find_in_files_dlg.rb +411 -0
  81. data/plugins/find_in_files/find_in_files_ui.rc +11 -0
  82. data/plugins/find_in_files/find_in_files_widgets.rb +485 -0
  83. data/plugins/find_in_files/plugin.yaml +23 -0
  84. data/plugins/find_in_files/ui/config_widget.rb +58 -0
  85. data/plugins/find_in_files/ui/config_widget.ui +41 -0
  86. data/plugins/find_in_files/ui/find_in_files_widget.rb +260 -0
  87. data/plugins/find_in_files/ui/find_in_files_widget.ui +324 -0
  88. data/plugins/project_browser/plugin.yaml +10 -0
  89. data/plugins/project_browser/project_browser.rb +245 -0
  90. data/plugins/rake/plugin.yaml +39 -0
  91. data/plugins/rake/rake.png +0 -0
  92. data/plugins/rake/rake.rb +567 -0
  93. data/plugins/rake/rake_extension.rb +153 -0
  94. data/plugins/rake/rake_widgets.rb +615 -0
  95. data/plugins/rake/rakeui.rc +27 -0
  96. data/plugins/rake/ui/add_quick_task_widget.rb +71 -0
  97. data/plugins/rake/ui/add_quick_task_widget.ui +59 -0
  98. data/plugins/rake/ui/choose_task_widget.rb +77 -0
  99. data/plugins/rake/ui/choose_task_widget.ui +72 -0
  100. data/plugins/rake/ui/config_widget.rb +127 -0
  101. data/plugins/rake/ui/config_widget.ui +123 -0
  102. data/plugins/rake/ui/project_widget.rb +217 -0
  103. data/plugins/rake/ui/project_widget.ui +246 -0
  104. data/plugins/rspec/plugin.yaml +30 -0
  105. data/plugins/rspec/rspec.png +0 -0
  106. data/plugins/rspec/rspec.rb +945 -0
  107. data/plugins/rspec/rspec.svg +90 -0
  108. data/plugins/rspec/rspecui.rc +20 -0
  109. data/plugins/rspec/ruber_rspec_formatter.rb +312 -0
  110. data/plugins/rspec/ui/rspec_project_widget.rb +170 -0
  111. data/plugins/rspec/ui/rspec_project_widget.ui +193 -0
  112. data/plugins/ruby_development/plugin.yaml +27 -0
  113. data/plugins/ruby_development/ruby_development.png +0 -0
  114. data/plugins/ruby_development/ruby_development.rb +453 -0
  115. data/plugins/ruby_development/ruby_developmentui.rc +19 -0
  116. data/plugins/ruby_development/ui/project_widget.rb +112 -0
  117. data/plugins/ruby_development/ui/project_widget.ui +108 -0
  118. data/plugins/ruby_runner/config_widget.rb +116 -0
  119. data/plugins/ruby_runner/plugin.yaml +26 -0
  120. data/plugins/ruby_runner/project_widget.rb +62 -0
  121. data/plugins/ruby_runner/ruby.png +0 -0
  122. data/plugins/ruby_runner/ruby_interpretersui.rc +26 -0
  123. data/plugins/ruby_runner/ruby_runner.rb +411 -0
  124. data/plugins/ruby_runner/ui/config_widget.rb +92 -0
  125. data/plugins/ruby_runner/ui/config_widget.ui +91 -0
  126. data/plugins/ruby_runner/ui/project_widget.rb +60 -0
  127. data/plugins/ruby_runner/ui/project_widget.ui +48 -0
  128. data/plugins/ruby_runner/ui/ruby_runnner_plugin_option_widget.rb +59 -0
  129. data/plugins/ruby_runner/ui/ruby_runnner_plugin_option_widget.ui +44 -0
  130. data/plugins/state/plugin.yaml +28 -0
  131. data/plugins/state/state.rb +520 -0
  132. data/plugins/state/ui/config_widget.rb +92 -0
  133. data/plugins/state/ui/config_widget.ui +89 -0
  134. data/plugins/syntax_checker/plugin.yaml +18 -0
  135. data/plugins/syntax_checker/syntax_checker.rb +662 -0
  136. data/ruber.desktop +10 -0
  137. data/spec/annotation_model_spec.rb +174 -0
  138. data/spec/common.rb +119 -0
  139. data/spec/component_manager_spec.rb +1259 -0
  140. data/spec/document_list_spec.rb +626 -0
  141. data/spec/document_project_spec.rb +373 -0
  142. data/spec/document_spec.rb +779 -0
  143. data/spec/editor_view_spec.rb +167 -0
  144. data/spec/external_program_plugin_spec.rb +676 -0
  145. data/spec/filtered_output_widget_spec.rb +642 -0
  146. data/spec/gui_states_handler_spec.rb +304 -0
  147. data/spec/kde_config_option_backend_spec.rb +214 -0
  148. data/spec/kde_sugar_spec.rb +101 -0
  149. data/spec/ktexteditor_wrapper_spec.rb +305 -0
  150. data/spec/output_widget_spec.rb +1703 -0
  151. data/spec/plugin_spec.rb +1393 -0
  152. data/spec/plugin_specification_reader_spec.rb +1765 -0
  153. data/spec/plugin_specification_spec.rb +401 -0
  154. data/spec/project_backend_spec.rb +172 -0
  155. data/spec/project_files_list_spec.rb +401 -0
  156. data/spec/project_list_spec.rb +511 -0
  157. data/spec/project_spec.rb +990 -0
  158. data/spec/qt_sugar_spec.rb +328 -0
  159. data/spec/settings_container_spec.rb +617 -0
  160. data/spec/settings_dialog_manager_spec.rb +773 -0
  161. data/spec/settings_dialog_spec.rb +419 -0
  162. data/spec/state_spec.rb +991 -0
  163. data/spec/utils_spec.rb +406 -0
  164. data/spec/workspace_spec.rb +869 -0
  165. data/spec/yaml_option_backend_spec.rb +246 -0
  166. 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
+