Class: Ruber::AbstractProject
- Inherits:
-
Qt::Object
- Object
- Qt::Object
- Ruber::AbstractProject
- Includes:
- SettingsContainer
- Defined in:
- lib/ruber/project.rb,
lib/ruber/project.rb
Overview
Base class for all projects. It must be sublcassed to be used.
It has two main functionalities
- store configuration options specific to each project (called project options), and read/write them to file, allow access to them and provide a way to configure them
- store the projects extensions relative to this projects and allow access to them.
Project option management is almost all done by the included SettingsContainer module. The backend may be choose by subclasses, with the only restriction that it should provide a file method returning the name of the file associated with it.
Subclasses must reimplement the :scope method, which should return :global if the project is a global one (that is a project managed by the ProjectList) component or :document if the project is associated with a single document.
A project can be in two states: active and inactive, depending on whether the user chose it as active project or not. Signals are emitted when the state changes. Note: there can be at most one active project at any given time.
=Signals ===option_changed(QString, QString) Signal emitted when the value of an option changes. The two parameters are the group and the name of the option, converted to strings. You’ll have to convert them back to symbols if you want to use them to access the option’s value
=closing(QObject*) Signal emitted when the project is about to close The argument is the project itself. This is mostly used by project extensions which need to do some cleanup. They shouldn’t use it to store settings or similar, as there’s the save_settings method for that.
=saving() Signal emitted just before the project is saved to file. This can be used by extensions to write their options to the project.
Direct Known Subclasses
Defined Under Namespace
Classes: InvalidProjectFile
Instance Attribute Summary (collapse)
-
- (Object) project_file
readonly
The absolute path of the project file.
-
- (Object) project_name
readonly
A string containing the name of the project.
Attributes included from SettingsContainer
Instance Method Summary (collapse)
-
- (Object) []=(group, name, value)
Override of SettingsContainer#[]= which after changing the value of the option, emits the option_changed(QString, QString) message if the value of the option changed (according to eql?).
-
- (Object) add_extension(name, ext)
Adds the project extension ext to the project, under the name name.
-
- (Boolean) close(save = true)
Closes the project.
-
- (Object) each_extension
If called with a block, calls it for each extension passing the extension name and the extension object itself as argument.
-
- (Object) extension(name)
(also: #project_extension)
Returns the project extension with name name.
-
- (Object) extensions
(also: #project_extensions)
Returns a hash having the extension names as keys and the extension objects as values.
-
- (Object) files
Returns an array containing the name of the files belonging to the project.
-
- (nil) finalize
Registers each component with the project.
-
- (Boolean) has_extension?(name)
Returns true if the project contains an extension corresponding to the name :name and false otherwise.
-
- (AbstractProject) initialize(parent, backend, name = nil)
constructor
Creates a new Project.
-
- (Boolean) match_rule?(obj)
Tells whether the project matches the rule specified in the object obj.
-
- (Object) method_missing(name, *args, &blk)
Returns the project extension with name name.
-
- (Object) project_directory
(also: #project_dir)
Returns the absolute path of project directory, that is the directory where the project file lies.
- - (Object) query_close
-
- (Object) remove_extension(name)
Removes the project extension with name name.
- - (Object) save
-
- (Object) scope
Returns the scope of the project (currently it must be either :global or document).
-
- (Object) write
Override of SettingsContainer#write which emits the settings_changed signal after writing the settings to file.
Methods included from SettingsContainer
#[], #add_setting, #add_widget, #collect_options, #default, #delete_dialog, #dialog, #has_setting?, #relative_path?, #remove_setting, #remove_widget, #setup_container
Signal Summary
Constructor Details
- (AbstractProject) initialize(parent, backend, name = nil)
Creates a new Project. parent is the projects parent object (derived from Qt::Object); file is the name of the project file, which may already exist or not, while name is the name of the project. name can only be specified if the project file doesn’t exist, otherwise ArgumentError will be raised.
The project file, if existing, must follow the format described in the documentation for YamlSettingsBackend and must contain a :project_name entry under the :general group, otherwise it will be considered invalid. In this case, InvalidProjectFile will be raised.
The new project asks each component to register itself with it, so that project options, project widgets (widgets to be shown in the project’s configuration dialog) and project extensions are added. It also connects to the component_loaded and unloading_component signals of the component manager. The first allow each newly loaded plugin to register itself with the project, while the second allows any unloading plugin to unregister itself.
When the project is created, it’s not active.
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/ruber/project.rb', line 111 def initialize parent, backend, name = nil super(parent) @active = false @project_file = backend.file setup_container backend, project_dir @dialog_class = ProjectDialog self.dialog_title = 'Configure Project' add_option OpenStruct.new(:group => :general, :name => :project_name, :default => nil) @project_name = self[:general, :project_name] if @project_name and name raise ArgumentError, "You can't specify a file name for an already existing project" elsif name self[:general, :project_name] = name @project_name = name elsif !@project_name and File.exist? @project_file raise InvalidProjectFile, "The project file #{@project_file} isn't invalid because it doesn't contain a project name entry" elsif !name and !File.exist? @project_file raise InvalidProjectFile, "You need to specify a project name for a new project" end @project_extensions = {} Ruber[:components].named_connect(SIGNAL('component_loaded(QObject*)'), "register_component_with_project #{object_id}"){|c| c.register_with_project self} Ruber[:components].named_connect(SIGNAL('unloading_component(QObject*)'), "remove_component_from_project #{object_id}"){|c| c.remove_from_project self} end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
- (Object) method_missing(name, *args, &blk)
Returns the project extension with name name. If a project extension with that name doesn’t exist, or if args is not empty, ArgumentError is raised.
256 257 258 259 260 261 262 263 264 265 266 267 268 |
# File 'lib/ruber/project.rb', line 256 def method_missing name, *args, &blk begin super rescue NoMethodError, NameError, TypeError, ArgumentError => e if e.is_a? ArgumentError puts e. puts e.backtrace.join("\n") puts "Method name: #{name}" puts "Arguments: #{args.empty? ? '[]' : args.join( ', ')}" end raise ArgumentError, "wrong number of arguments (#{args.size} for 0)" unless args.empty? @project_extensions[name] || super end end |
Instance Attribute Details
- (Object) project_file (readonly)
The absolute path of the project file
89 90 91 |
# File 'lib/ruber/project.rb', line 89 def project_file @project_file end |
- (Object) project_name (readonly)
A string containing the name of the project
84 85 86 |
# File 'lib/ruber/project.rb', line 84 def project_name @project_name end |
Instance Method Details
- (Object) []=(group, name, value)
Override of SettingsContainer#[]= which after changing the value of the option, emits the option_changed(QString, QString) message if the value of the option changed (according to eql?).
188 189 190 191 192 |
# File 'lib/ruber/project.rb', line 188 def []= group, name, value old = @options[[group, name]] super emit option_changed group.to_s, name.to_s unless old.eql? value end |
- (Object) add_extension(name, ext)
Adds the project extension ext to the project, under the name name. If an extension is already stored under that name, ArgumentError is raised.
166 167 168 169 170 171 |
# File 'lib/ruber/project.rb', line 166 def add_extension name, ext if @project_extensions[name] raise ArgumentError, "An extension called '#{name}' already exists" end @project_extensions[name] = ext end |
- (Boolean) close(save = true)
Closes the project
According to the save parameter, the project may save itself and its extensions\’
settings or not. In the first case, extensions may stop the project from closing
by having their query_close
method return false. If save is false, nothing
will be saved and the closing can’t be interrupted.
Before closing the project, the #closing signal is emitted. After that, all extensions
will be removed (calling their remove_from_project
method if they have one).
310 311 312 313 314 315 316 317 318 319 320 |
# File 'lib/ruber/project.rb', line 310 def close save = true if save return false unless query_close return false unless self.save end emit closing(self) @project_extensions.each_key{|k| remove_extension k} Ruber[:components].named_disconnect "remove_component_from_project #{object_id}" Ruber[:components].named_disconnect "register_component_with_project #{object_id}" true end |
- (Object) each_extension
If called with a block, calls it for each extension passing the extension name and the extension object itself as argument. If called without a block, returns an Enumerator whose each method works as explained above
207 208 209 210 211 212 |
# File 'lib/ruber/project.rb', line 207 def each_extension if block_given? @project_extensions.each_pair{|name, ext| yield name, ext} else self.to_enum(:each_extension) end end |
- (Object) extension(name) Also known as: project_extension
Returns the project extension with name name.
197 198 199 |
# File 'lib/ruber/project.rb', line 197 def extension name @project_extensions[name] end |
- (Object) extensions Also known as: project_extensions
Returns a hash having the extension names as keys and the extension objects as values.
Note: modifiying the hash doesn’t change the internal list of extensions
220 221 222 |
# File 'lib/ruber/project.rb', line 220 def extensions @project_extensions.dup end |
- (Object) files
Returns an array containing the name of the files belonging to the project.
This method should be reimplemented in derived classes to return the actual list of files. The base class’s version always returns an empty array.
248 249 250 |
# File 'lib/ruber/project.rb', line 248 def files [] end |
- (nil) finalize
This method has nothing to do with finalizers
Registers each component with the project
This is done in #initialize because, at least for DocumentProject, the extensions may try to access the project (directly or not) before it has fully been created.
This method should only be called from the object calling new
337 338 339 340 |
# File 'lib/ruber/project.rb', line 337 def finalize Ruber[:components].each_component{|c| c.register_with_project self} nil end |
- (Boolean) has_extension?(name)
Returns true if the project contains an extension corresponding to the name :name and false otherwise
229 230 231 |
# File 'lib/ruber/project.rb', line 229 def has_extension? name @project_extensions.has_key? name end |
- (Boolean) match_rule?(obj)
Tells whether the project matches the rule specified in the object obj. obj is an object with at least the following methods:
- scope
- mimetype
- file_extension
This implementation returns true if obj.scope includes the value returned by self.scope (using this method requires subclassing AbstractProject, since AbstractProject#scope raises an exception). Subclasses may override this method to introduce other conditions. However, they’ll most likely always want to call the base class implementation.
158 159 160 |
# File 'lib/ruber/project.rb', line 158 def match_rule? obj obj.scope.include? self.scope end |
- (Object) project_directory Also known as: project_dir
Returns the absolute path of project directory, that is the directory where the project file lies.
237 238 239 |
# File 'lib/ruber/project.rb', line 237 def project_directory File.dirname(@project_file) end |
- (Object) query_close
322 323 324 325 |
# File 'lib/ruber/project.rb', line 322 def query_close @project_extensions.each_value{|v| return false unless v.query_close} true end |
- (Object) remove_extension(name)
Removes the project extension with name name. If an extension with that name doesn’t exist, nothing is done.
177 178 179 180 181 |
# File 'lib/ruber/project.rb', line 177 def remove_extension name ext = @project_extensions[name] ext.remove_from_project if ext.respond_to? :remove_from_project @project_extensions.delete name end |
- (Object) save
271 272 273 274 275 276 277 278 279 280 |
# File 'lib/ruber/project.rb', line 271 def save emit saving @project_extensions.each_value{|v| v.save_settings} begin write true rescue Exception false end end |
- (Object) scope
Returns the scope of the project (currently it must be either :global or document).
This method must be overridden in derived classes, as it only raises NoMethodError
141 142 143 |
# File 'lib/ruber/project.rb', line 141 def scope raise NoMethodError, "Undefined method `scope' for #{self}:#{self.class}" end |
- (Object) write
Override of SettingsContainer#write which emits the settings_changed signal after writing the settings to file
286 287 288 289 |
# File 'lib/ruber/project.rb', line 286 def write super emit settings_changed end |
Signal Details
- option_changed(QString arg1, QString arg2)
- closing(QObject* arg1)
- settings_changed
- saving