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,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