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,493 @@
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 'pathname'
22
+ require 'yaml'
23
+
24
+ require 'ruber/plugin'
25
+ require 'ruber/settings_container'
26
+ require 'ruber/project_backend'
27
+
28
+ module Ruber
29
+
30
+ =begin rdoc
31
+
32
+ Base class for all projects. It must be sublcassed to be used.
33
+
34
+ It has two main functionalities
35
+ * store configuration options specific to each project (called <i>project options</i>),
36
+ and read/write them to file, allow access to them and provide a way to configure
37
+ them
38
+ * store the projects extensions relative to this projects and allow access to them.
39
+
40
+ Project option management is almost all done by the included SettingsContainer module. The
41
+ backend may be choose by subclasses, with the only restriction that it should provide
42
+ a +file+ method returning the name of the file associated with it.
43
+
44
+ Subclasses must reimplement the +:scope+ method, which should return <tt>:global</tt>
45
+ if the project is a global one (that is a project managed by the +ProjectList+)
46
+ component or <tt>:document</tt> if the project is associated with a single document.
47
+
48
+ A project can be in two states: _active_ and _inactive_, depending on whether the
49
+ user chose it as active project or not. Signals are emitted when the state changes.
50
+ <b>Note:</b> there can be at most one active project at any given time.
51
+
52
+ ===Signals
53
+ =====<tt>option_changed(QString, QString)</tt>
54
+ Signal emitted when the value of an option changes. The two parameters are the
55
+ group and the name of the option, converted to strings. You'll have to convert
56
+ them back to symbols if you want to use them to access the option's value
57
+
58
+ =====<tt>closing(QObject*)</tt>
59
+ Signal emitted when the project is about to close The argument is the project itself.
60
+ This is mostly used by project
61
+ extensions which need to do some cleanup. They shouldn't use it to store settings
62
+ or similar, as there's the <tt>save_settings</tt> method for that.
63
+
64
+ =====<tt>saving()</tt>
65
+ Signal emitted just before the project is saved to file. This can be used by
66
+ extensions to write their options to the project.
67
+ =end
68
+ class AbstractProject < Qt::Object
69
+
70
+ =begin rdoc
71
+ Exception raised when a project file contains some errors
72
+ =end
73
+ class InvalidProjectFile < StandardError
74
+ end
75
+
76
+ include SettingsContainer
77
+
78
+ signals 'option_changed(QString, QString)', 'closing(QObject*)', :settings_changed,
79
+ :saving
80
+
81
+ =begin rdoc
82
+ A string containing the name of the project
83
+ =end
84
+ attr_reader :project_name
85
+
86
+ =begin rdoc
87
+ The absolute path of the project file
88
+ =end
89
+ attr_reader :project_file
90
+
91
+ =begin rdoc
92
+ Creates a new Project. _parent_ is the projects parent object (derived from <tt>Qt::Object</tt>);
93
+ _file_ is the name of the project file, which may already
94
+ exist or not, while _name_ is the name of the project. _name_ can only be specified
95
+ if the project file doesn't exist, otherwise +ArgumentError+ will be raised.
96
+
97
+ The project file, if existing, must follow the format described in the documentation for YamlSettingsBackend
98
+ and must contain a <tt>:project_name</tt> entry under the <tt>:general</tt> group,
99
+ otherwise it will be considered invalid. In this case, InvalidProjectFile will be
100
+ raised.
101
+
102
+ The new project asks each component to register itself with it, so that project
103
+ options, project widgets (widgets to be shown in the project's configuration dialog)
104
+ and project extensions are added. It also connects to the <tt>component_loaded</tt>
105
+ and <tt>unloading_component</tt> signals of the component manager. The first allow
106
+ each newly loaded plugin to register itself with the project, while the second allows
107
+ any unloading plugin to unregister itself.
108
+
109
+ When the project is created, it's not active.
110
+ =end
111
+ def initialize parent, backend, name = nil
112
+ super(parent)
113
+ @active = false
114
+ Ruber[:components].named_connect(SIGNAL('component_loaded(QObject*)'), "register_component_with_project #{object_id}"){|c| c.register_with_project self}
115
+ Ruber[:components].named_connect(SIGNAL('unloading_component(QObject*)'), "remove_component_from_project #{object_id}"){|c| c.remove_from_project self}
116
+ @project_file = backend.file
117
+ setup_container backend, project_dir
118
+ @dialog_class = ProjectDialog
119
+ self.dialog_title = 'Configure Project'
120
+ add_option OpenStruct.new(:group => :general, :name => :project_name, :default => nil)
121
+ @project_name = self[:general, :project_name]
122
+ if @project_name and name
123
+ raise ArgumentError, "You can't specify a file name for an already existing project"
124
+ elsif name
125
+ self[:general, :project_name] = name
126
+ @project_name = name
127
+ elsif !@project_name and File.exist? @project_file
128
+ raise InvalidProjectFile, "The project file #{@project_file} isn't invalid because it doesn't contain a project name entry"
129
+ elsif !name and !File.exist? @project_file
130
+ raise InvalidProjectFile, "You need to specify a project name for a new project"
131
+ end
132
+ @project_extensions = {}
133
+ Ruber[:components].each_component{|c| c.register_with_project self}
134
+ end
135
+
136
+ =begin rdoc
137
+ Returns the scope of the project (currently it must be either +:global+ or +document+).
138
+
139
+ This method must be overridden in derived classes, as it only raises +NoMethodError+
140
+ =end
141
+ def scope
142
+ raise NoMethodError, "Undefined method `scope' for #{self}:#{self.class}"
143
+ end
144
+
145
+ =begin rdoc
146
+ Tells whether the project matches the rule specified in the object _obj_. _obj_
147
+ is an object with at least the following methods:
148
+ * +scope+
149
+ * +mimetype+
150
+ * +file_extension+
151
+
152
+ This implementation returns *true* if <tt>obj.scope</tt> includes the value returned
153
+ by <tt>self.scope</tt> (using this method requires subclassing AbstractProject,
154
+ since <tt>AbstractProject#scope</tt> raises an exception). Subclasses may override
155
+ this method to introduce other conditions. However, they'll most likely always
156
+ want to call the base class implementation.
157
+ =end
158
+ def match_rule? obj
159
+ obj.scope.include? self.scope
160
+ end
161
+
162
+ =begin rdoc
163
+ Adds the project extension _ext_ to the project, under the name _name_. If an
164
+ extension is already stored under that name, +ArgumentError+ is raised.
165
+ =end
166
+ def add_extension name, ext
167
+ if @project_extensions[name]
168
+ raise ArgumentError, "An extension called '#{name}' already exists"
169
+ end
170
+ @project_extensions[name] = ext
171
+ end
172
+
173
+ =begin rdoc
174
+ Removes the project extension with name _name_. If an extension with that name
175
+ doesn't exist, nothing is done.
176
+ =end
177
+ def remove_extension name
178
+ ext = @project_extensions[name]
179
+ ext.remove_from_project if ext.respond_to? :remove_from_project
180
+ @project_extensions.delete name
181
+ end
182
+
183
+ =begin rdoc
184
+ Override of SettingsContainer#[]= which after changing the value of the option,
185
+ emits the <tt>option_changed(QString, QString)</tt> message if the value of
186
+ the option changed (according to eql?).
187
+ =end
188
+ def []= group, name, value
189
+ old = @options[[group, name]]
190
+ super
191
+ emit option_changed group.to_s, name.to_s unless old.eql? value
192
+ end
193
+
194
+ =begin rdoc
195
+ Returns the project extension with name _name_.
196
+ =end
197
+ def extension name
198
+ @project_extensions[name]
199
+ end
200
+ alias_method :project_extension, :extension
201
+
202
+ =begin rdoc
203
+ If called with a block, calls it for each extension passing the extension name
204
+ and the extension object itself as argument. If called without a block, returns
205
+ an +Enumerator+ whose +each+ method works as explained above
206
+ =end
207
+ def each_extension
208
+ if block_given?
209
+ @project_extensions.each_pair{|name, ext| yield name, ext}
210
+ else self.to_enum(:each_extension)
211
+ end
212
+ end
213
+
214
+ =begin rdoc
215
+ Returns a hash having the extension names as keys and the extension objects as
216
+ values.
217
+
218
+ <b>Note:</b> modifiying the hash doesn't change the internal list of extensions
219
+ =end
220
+ def extensions
221
+ @project_extensions.dup
222
+ end
223
+ alias_method :project_extensions, :extensions
224
+
225
+ =begin rdoc
226
+ Returns true if the project contains an extension corresponding to the name +:name+
227
+ and false otherwise
228
+ =end
229
+ def has_extension? name
230
+ @project_extensions.has_key? name
231
+ end
232
+
233
+ =begin rdoc
234
+ Returns the absolute path of project directory, that is the directory where the
235
+ project file lies.
236
+ =end
237
+ def project_directory
238
+ File.dirname(@project_file)
239
+ end
240
+ alias_method :project_dir, :project_directory
241
+
242
+ =begin rdoc
243
+ Returns an array containing the name of the files belonging to the project.
244
+
245
+ This method should be reimplemented in derived classes to return the actual list
246
+ of files. The base class's version always returns an empty array.
247
+ =end
248
+ def files
249
+ []
250
+ end
251
+
252
+ =begin rdoc
253
+ Returns the project extension with name _name_. If a project extension with that
254
+ name doesn't exist, or if _args_ is not empty, +ArgumentError+ is raised.
255
+ =end
256
+ def method_missing name, *args, &blk
257
+ begin super
258
+ rescue NoMethodError, NameError, TypeError, ArgumentError => e
259
+ if e.is_a? ArgumentError
260
+ puts e.message
261
+ puts e.backtrace.join("\n")
262
+ puts "Method name: #{name}"
263
+ puts "Arguments: #{args.empty? ? '[]' : args.join( ', ')}"
264
+ end
265
+ raise ArgumentError, "wrong number of arguments (#{args.size} for 0)" unless args.empty?
266
+ @project_extensions.fetch(name){|k| raise ArgumentError, "No project extension with name #{k}"}
267
+ end
268
+ end
269
+
270
+
271
+ def save
272
+ emit saving
273
+ @project_extensions.each_value{|v| v.save_settings}
274
+ begin
275
+ write
276
+ true
277
+ rescue Exception
278
+ false
279
+ end
280
+ end
281
+
282
+ =begin rdoc
283
+ Override of <tt>SettingsContainer#write</tt> which emits the +settings_changed+ signal after
284
+ writing the settings to file
285
+ =end
286
+ def write
287
+ super
288
+ emit settings_changed
289
+ end
290
+
291
+ =begin rdoc
292
+ Closes the project. This means:
293
+ * calling the +save+ method if _save_ is *true*
294
+ * removing all the project extensions
295
+ * emitting the <tt>closing(QObject*)</tt> signal
296
+
297
+ If _save_ is *true*, returns *false* if an error occurred while saving
298
+ and *true* if no error occurred. If _save_ is *false*, it always
299
+ returns *true*
300
+ =end
301
+ def close save = true
302
+ if save
303
+ return false unless self.save
304
+ end
305
+ emit closing(self)
306
+ @project_extensions.each_key{|k| remove_extension k}
307
+ Ruber[:components].named_disconnect "remove_component_from_project #{object_id}"
308
+ Ruber[:components].named_disconnect "register_component_with_project #{object_id}"
309
+ true
310
+ end
311
+
312
+ def query_close
313
+ @project_extensions.each_value{|v| return false unless v.query_close}
314
+ true
315
+ end
316
+
317
+ end
318
+
319
+ =begin rdoc
320
+ Class representing a global project (one which should be managed by ProjectList).
321
+
322
+ It uses ProjectBackend as backend and includes the Activable module.
323
+
324
+ ===Signals
325
+ =====<tt>activated()</tt>
326
+ Signal emitted when the project is activated
327
+
328
+ =====<tt>deactivated()</tt>
329
+ Signal emitted when the project is deactivated
330
+
331
+ ===Slots
332
+ * <tt>activate()</tt>
333
+ * <tt>deactivate()</tt>
334
+ =end
335
+ class Project < AbstractProject
336
+
337
+ class InvalidProjectFileName < StandardError
338
+ end
339
+
340
+ include Activable
341
+
342
+ signals :activated, :deactivated
343
+
344
+ slots :activate, :deactivate
345
+
346
+ =begin rdoc
347
+ Creates a new Project. _file_ is the name of the project file, while _name_ is
348
+ the project name. You must specify both arguments if the file _file_ doesn't exist,
349
+ while you must not pass the _name_ parameter if the file _file_ already exists (in
350
+ this case, the project name is written in the project file and there's no need
351
+ to specify it). Note that this method takes care of creating the backend, so you
352
+ don't need to do that yourself (unlike with AbstractProject).
353
+
354
+ If _file_ is a relative path, it's considered relative to the current directory.
355
+
356
+ If the project file _file_ already exists but it's not a valid project file,
357
+ AbstractProject::InvalidProjectFile will be raised.
358
+ =end
359
+ def initialize file, name = nil
360
+ file = File.join(Dir.pwd, file) unless file.start_with? '/'
361
+ back = begin ProjectBackend.new file
362
+ rescue YamlSettingsBackend::InvalidSettingsFile => e
363
+ raise Ruber::AbstractProject::InvalidProjectFile, e.message
364
+ end
365
+ super Ruber[:projects], back, name
366
+ end
367
+
368
+ =begin rdoc
369
+ Override of <tt>AbstractProject#close</tt> which deactivates the project before closing it
370
+ and disposes of it after closing. Aside from this, it works as the base class version.
371
+ =end
372
+ def close save = true
373
+ deactivate
374
+ res = super
375
+ dispose
376
+ res
377
+ end
378
+
379
+ =begin rdoc
380
+ Reimplementation of <tt>AbstractProject#scope</tt> which returns +:global+
381
+ =end
382
+ def scope
383
+ :global
384
+ end
385
+
386
+ =begin rdoc
387
+ Override of <tt>SettingsContainer#add_option</tt> which sets the type of _opt_
388
+ to +:global+ if <tt>opt.type</tt> returns *nil*.
389
+
390
+ This is necessary because +AbstractProject.new+ adds the +:project_name+ option
391
+ without specifying its type.
392
+ =end
393
+ def add_option opt
394
+ opt.type ||= :global
395
+ super
396
+ end
397
+
398
+ =begin rdoc
399
+ Override of AbstractProject#files which actually returns the list of files belonging
400
+ to the project.
401
+
402
+ <b>Note:</b> this method uses the <tt>project_files</tt> extension
403
+ =end
404
+ def files
405
+ @project_extensions[:project_files].project_files
406
+ end
407
+
408
+ end
409
+
410
+ =begin rdoc
411
+ Subclass of SettingsDialog which differs from it only in that it overrides the
412
+ <tt>widget_from_class</tt> method.
413
+
414
+ <bb>Note:</bb> since the overridden <tt>widget_from_class</tt> method passes
415
+ the project as argument to the widget's class <tt>#new</tt> method, the widget's
416
+ constructor must explicitly pass *nil* to the superclass method as parent. To
417
+ avoid any issues, you can derive your widget from ProjectConfigWidget
418
+ rather than from <tt>Qt::Widget</tt>. If, for some reason, you can't do that (for
419
+ example because you need to derive from another specialized widget), your widget
420
+ constructor must do something like this (assuming that the base class's construcor
421
+ take the same argument as Qt::Widget's):
422
+
423
+ class MyWidget < SomeWidget
424
+
425
+ def initialize prj
426
+ super()
427
+ # do (if you want) something with prj
428
+ end
429
+
430
+ end
431
+ =end
432
+ class ProjectDialog < SettingsDialog
433
+
434
+ private
435
+
436
+ =begin rdoc
437
+ Override of SettingsDialog#widget_from_class which passes the project as argument
438
+ to the class's +#new+ method.
439
+ =end
440
+ def widget_from_class cls
441
+ cls.new @container
442
+ end
443
+
444
+ end
445
+
446
+ =begin rdoc
447
+ Small class which can be used instead of <tt>Qt::Widget</tt> for widgets to be
448
+ used in the configuration dialog.
449
+
450
+ The only difference between this class and <tt>Qt::Widget</tt> is in the arguments
451
+ taken by the constructor: instead of taking the parent (which is instead set to
452
+ *nil*), this class accepts the project the dialog refers to and stores it in
453
+ its +project+ attribute.
454
+ =end
455
+ class ProjectConfigWidget < Qt::Widget
456
+
457
+ =begin rdoc
458
+ The project associated with the dialog containing the widget
459
+ =end
460
+ attr_reader :project
461
+
462
+ =begin rdoc
463
+ Creates a new instance. _project_ is the Project associated with the dialog the
464
+ widget will be put into.
465
+ =end
466
+ def initialize project
467
+ super()
468
+ @project = project
469
+ end
470
+
471
+ end
472
+
473
+
474
+ module Extension
475
+
476
+ attr_accessor :plugin
477
+
478
+ def save_settings
479
+ end
480
+
481
+ def shutdown
482
+ end
483
+
484
+ def remove_from_project
485
+ end
486
+
487
+ def query_close
488
+ true
489
+ end
490
+
491
+ end
492
+
493
+ end