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.
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
+