ruber 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. data/CHANGES +21 -0
  2. data/data/share/apps/ruber/ruberui.rc +3 -1
  3. data/lib/ruber/application/application.rb +22 -23
  4. data/lib/ruber/application/plugin.yaml +7 -2
  5. data/lib/ruber/{projects → application}/project_files_list.rb +0 -0
  6. data/lib/ruber/{projects → application}/project_files_widget.rb +0 -0
  7. data/lib/ruber/application/ui/project_files_rule_chooser_widget.rb +74 -0
  8. data/lib/ruber/{projects → application}/ui/project_files_rule_chooser_widget.ui +0 -0
  9. data/lib/ruber/application/ui/project_files_widget.rb +117 -0
  10. data/lib/ruber/{projects → application}/ui/project_files_widget.ui +0 -0
  11. data/lib/ruber/component_manager.rb +14 -9
  12. data/lib/ruber/editor/document.rb +35 -5
  13. data/lib/ruber/kde_sugar.rb +16 -0
  14. data/lib/ruber/main_window/choose_plugins_dlg.rb +7 -4
  15. data/lib/ruber/main_window/main_window.rb +131 -193
  16. data/lib/ruber/main_window/main_window_actions.rb +157 -58
  17. data/lib/ruber/main_window/main_window_internal.rb +145 -54
  18. data/lib/ruber/main_window/open_file_in_project_dlg.rb +4 -4
  19. data/lib/ruber/main_window/plugin.yaml +3 -6
  20. data/lib/ruber/main_window/ui/workspace_settings_widget.rb +2 -2
  21. data/lib/ruber/main_window/workspace.rb +62 -32
  22. data/lib/ruber/output_widget.rb +20 -16
  23. data/lib/ruber/pane.rb +11 -5
  24. data/lib/ruber/project.rb +27 -12
  25. data/lib/ruber/projects/ui/project_files_rule_chooser_widget.rb +2 -2
  26. data/lib/ruber/projects/ui/project_files_widget.rb +2 -2
  27. data/lib/ruber/utils.rb +37 -4
  28. data/lib/ruber/version.rb +1 -1
  29. data/lib/ruber/world/document_factory.rb +121 -0
  30. data/lib/ruber/world/document_list.rb +396 -0
  31. data/lib/ruber/world/environment.rb +470 -0
  32. data/lib/ruber/{main_window → world}/hint_solver.rb +1 -1
  33. data/lib/ruber/world/plugin.yaml +11 -0
  34. data/lib/ruber/world/project_factory.rb +131 -0
  35. data/lib/ruber/world/project_list.rb +265 -0
  36. data/lib/ruber/world/ui/workspace_settings_widget.rb +51 -0
  37. data/lib/ruber/{main_window → world}/ui/workspace_settings_widget.ui +0 -0
  38. data/lib/ruber/world/world.rb +307 -0
  39. data/plugins/auto_end/auto_end.rb +135 -9
  40. data/plugins/autosave/autosave.rb +4 -4
  41. data/plugins/find_in_files/find_in_files.rb +5 -5
  42. data/plugins/find_in_files/find_in_files_widgets.rb +1 -1
  43. data/plugins/project_browser/project_browser.rb +4 -4
  44. data/plugins/rake/rake.rb +4 -4
  45. data/plugins/rake/rake_extension.rb +1 -1
  46. data/plugins/rspec/rspec.rb +4 -4
  47. data/plugins/rspec/ruber_rspec_formatter.rb +2 -2
  48. data/plugins/ruby_development/ruby_development.rb +3 -3
  49. data/plugins/ruby_runner/ruby_runner.rb +2 -2
  50. data/plugins/state/plugin.yaml +6 -8
  51. data/plugins/state/state.rb +201 -391
  52. data/plugins/state/ui/config_widget.rb +5 -5
  53. data/plugins/state/ui/config_widget.ui +3 -3
  54. data/plugins/syntax_checker/syntax_checker.rb +4 -0
  55. data/spec/annotation_model_spec.rb +1 -1
  56. data/spec/auto_end_spec.rb +98 -47
  57. data/spec/component_manager_spec.rb +80 -21
  58. data/spec/document_factory_spec.rb +115 -0
  59. data/spec/document_list_spec.rb +560 -450
  60. data/spec/document_spec.rb +143 -55
  61. data/spec/editor_view_spec.rb +2 -2
  62. data/spec/environment_spec.rb +1900 -0
  63. data/spec/hint_solver_spec.rb +5 -5
  64. data/spec/kde_sugar_spec.rb +16 -0
  65. data/spec/output_widget_spec.rb +177 -51
  66. data/spec/pane_spec.rb +29 -5
  67. data/spec/plugin_spec.rb +1 -1
  68. data/spec/project_factory_spec.rb +104 -0
  69. data/spec/project_list_spec.rb +352 -447
  70. data/spec/project_spec.rb +34 -33
  71. data/spec/qt_sugar_spec.rb +2 -2
  72. data/spec/state_spec.rb +508 -811
  73. data/spec/utils_spec.rb +149 -98
  74. data/spec/workspace_spec.rb +120 -9
  75. data/spec/world_spec.rb +1219 -0
  76. metadata +23 -14
  77. data/lib/ruber/documents/document_list.rb +0 -412
  78. data/lib/ruber/documents/plugin.yaml +0 -4
  79. data/lib/ruber/main_window/view_manager.rb +0 -431
  80. data/lib/ruber/projects/plugin.yaml +0 -11
  81. data/lib/ruber/projects/project_list.rb +0 -314
@@ -1,511 +1,416 @@
1
- require 'spec/common'
1
+ require './spec/framework'
2
+ require './spec/common'
3
+ require 'ruber/world/project_list'
4
+ require 'ruber/project'
2
5
 
3
- require 'flexmock'
6
+ require 'tmpdir'
4
7
 
5
- require 'ruber/projects/project_list'
6
- require 'ruber/plugin_specification'
7
-
8
- class Ruber::ProjectList::FakeProject < Qt::Object
9
-
10
- signals 'closing(QObject*)'
11
- attr_reader :project_name, :project_file
12
- def initialize name = 'test', file = nil
13
- super()
14
- @project_file = file || Array.new(6){97 + rand(26)}.join
15
- @project_name = name
16
- end
17
-
18
- def deactivate;end
19
-
20
- def activate;end
21
-
22
- def close
23
- emit closing(self)
24
- end
25
- end
26
-
27
- describe Ruber::ProjectList do
8
+ describe Ruber::World::ProjectList do
28
9
 
29
- it 'should mix-in Enumerable' do
30
- Ruber::ProjectList.ancestors.include?(Enumerable).should be_true
10
+ def create_project file, name = nil
11
+ name ||= file.sub(/[_-]/, ' ').sub('.ruprj','').capitalize
12
+ file = File.join Dir.tmpdir, file unless file.start_with? '/'
13
+ file += '.ruprj' unless file.end_with?('ruprj')
14
+ Ruber::Project.new file, name
31
15
  end
32
-
33
- end
34
-
35
- describe 'Ruber::ProjectList#project_for_file' do
36
16
 
37
17
  before do
38
- manager = flexmock('components'){|m| m.should_ignore_missing}
39
- flexmock(Ruber).should_receive(:[]).with(:app).and_return(KDE::Application.instance).by_default
40
- flexmock(Ruber).should_receive(:[]).with(:config).and_return(nil).by_default
41
- flexmock(Ruber).should_receive(:[]).with(:components).and_return(manager).by_default
42
- pdf = Ruber::PluginSpecification.full({:name => :projects, :class => Ruber::ProjectList})
43
- @projects = Ruber::ProjectList.new manager, pdf
44
- end
45
-
46
- it 'returns nil if there\'s no current project' do
47
- flexmock(@projects).should_receive(:current).twice.and_return nil
48
- @projects.project_for_file(__FILE__, :active).should be_nil
49
- @projects.project_for_file(__FILE__, :all).should be_nil
18
+ @projects = 3.times.map{|i| create_project "project-#{i}"}
19
+ @list = Ruber::World::ProjectList.new @projects
50
20
  end
51
21
 
52
- it 'returns the current project if there\'s one and the file belongs to it' do
53
- prj = flexmock{|m| m.should_receive('project_files.file_in_project?').twice.with(__FILE__).and_return true}
54
- flexmock(@projects).should_receive(:current).twice.and_return prj
55
- @projects.project_for_file(__FILE__, :active).should == prj
56
- @projects.project_for_file(__FILE__, :all).should == prj
22
+ it 'includes the Enumerable module' do
23
+ Ruber::World::ProjectList.ancestors.should include(Enumerable)
57
24
  end
58
25
 
59
- it 'returns nil if the file doesn\'t belong to the current project and the second argument is :active, even if the file belongs to another project' do
60
- active_prj = flexmock{|m| m.should_receive('project_files.file_in_project?').once.with(__FILE__).and_return false}
61
- prj = flexmock{|m| m.should_receive('project_files.file_in_project?').with(__FILE__).and_return true}
62
- flexmock(@projects).should_receive(:current).once.and_return(active_prj)
63
- flexmock(@projects).should_receive(:each).and_yield(active_prj, prj)
64
- @projects.project_for_file(__FILE__, :active).should be_nil
65
- end
66
-
67
- it 'returns the first project to which the file belongs, if it doesn\'t belong to the current one and the second argument is :all' do
68
- active_prj = flexmock{|m| m.should_receive('project_files.file_in_project?').twice.with(__FILE__).and_return false}
69
- prjs = [
70
- flexmock{|m| m.should_receive('project_files.file_in_project?').with(__FILE__).once.and_return false},
71
- active_prj,
72
- flexmock{|m| m.should_receive('project_files.file_in_project?').with(__FILE__).once.and_return true},
73
- flexmock{|m| m.should_receive('project_files.file_in_project?').with(__FILE__).never}
74
- ]
75
- flexmock(@projects).should_receive(:current).once.and_return(active_prj)
76
- projects = {
77
- '0' => prjs[0],
78
- '1' => prjs[1],
79
- '2' => prjs[2],
80
- '3' => prjs[3]
81
- }
82
- @projects.instance_variable_set(:@projects, projects)
83
- @projects.project_for_file(__FILE__, :all).should equal(prjs[2])
84
- end
26
+ describe '.new' do
85
27
 
86
- it 'returns nil if the second argument is :all and the file doesn\'t belong to any project' do
87
- active_prj = flexmock{|m| m.should_receive('project_files.file_in_project?').twice.with(__FILE__).and_return false}
88
- prjs = [
89
- flexmock{|m| m.should_receive('project_files.file_in_project?').with(__FILE__).once.and_return false},
90
- active_prj,
91
- flexmock{|m| m.should_receive('project_files.file_in_project?').with(__FILE__).once.and_return false},
92
- flexmock{|m| m.should_receive('project_files.file_in_project?').with(__FILE__).once.and_return false}
93
- ]
94
- flexmock(@projects).should_receive(:current).once.and_return(active_prj)
95
- projects = {
96
- '0' => prjs[0],
97
- '1' => prjs[1],
98
- '2' => prjs[2],
99
- '3' => prjs[3]
100
- }
101
- @projects.instance_variable_set(:@projects, projects)
102
- @projects.project_for_file(__FILE__, :all).should be_nil
103
- end
104
-
105
- end
106
-
107
- describe 'Ruber::ProjectList#each_project' do
108
-
109
- before do
110
- app = Qt::Object.new
111
- manager = flexmock('components'){|m| m.should_ignore_missing}
112
- flexmock(Ruber).should_receive(:[]).with(:app).and_return(app)
113
- flexmock(Ruber).should_receive(:[]).with(:components).and_return(manager)
114
- flexmock(Ruber).should_receive(:[]).with(:config).and_return(nil)
115
- pdf = Ruber::PluginSpecification.full({:name => :projects, :class => Ruber::ProjectList})
116
- @keeper = Ruber::ProjectList.new manager, pdf
117
- end
118
-
119
-
120
- it 'should yield all the projects in the list if called with a block' do
121
- prjs = Array.new(3){|i| Ruber::ProjectList::FakeProject.new("test#{i}")}
122
- prjs.each{|pr| @keeper.add_project pr}
123
- res = []
124
- @keeper.each_project{|pr| res << pr}
125
- res.sort_by{|pr| pr.project_file}.should == prjs.sort_by{|pr| pr.project_file}
126
- end
127
-
128
- it 'should return an enumerable which yields all the projects in the list if called without a block' do
129
- prjs = Array.new(3){|i| Ruber::ProjectList::FakeProject.new("test#{i}")}
130
- prjs.each{|pr| @keeper.add_project pr}
131
- m = flexmock do |mk|
132
- prjs.each{|prj| mk.should_receive(:test).once.with prj}
28
+ it 'takes a hash or a DocumentList as argument' do
29
+ list = Ruber::World::ProjectList.new @projects
30
+ list.to_a.map(&:project_file).sort == @projects.map(&:project_file).sort
31
+ other_list = Ruber::World::ProjectList.new @projects
32
+ list = Ruber::World::ProjectList.new other_list
33
+ list.to_a.map(&:project_file).sort == @projects.map(&:project_file).sort
133
34
  end
134
- en = @keeper.each_project
135
- if RUBY_VERSION.match(/8/) then en.should be_an(Enumerable::Enumerator)
136
- else en.should be_an(Enumerator)
35
+
36
+ it 'creates a duplicate of the argument if it is a hash' do
37
+ list = Ruber::World::ProjectList.new @projects
38
+ new_project = create_project 'project-3'
39
+ @projects << new_project
40
+ list.count.should == 3
137
41
  end
138
- en.each{|prj| m.test prj}
139
- end
140
-
141
- end
142
-
143
- describe 'Ruber::ProjectList, when created' do
144
-
145
- before do
146
- app = Qt::Object.new
147
- manager = flexmock('components'){|m| m.should_ignore_missing}
148
- flexmock(Ruber).should_receive(:[]).with(:app).and_return(app)
149
- flexmock(Ruber).should_receive(:[]).with(:components).and_return(manager)
150
- flexmock(Ruber).should_receive(:[]).with(:config).and_return(nil)
151
- @pdf = Ruber::PluginSpecification.full({:name => :projects, :class => Ruber::ProjectList})
152
- @keeper = Ruber::ProjectList.new manager, @pdf
153
- end
154
-
155
- it 'should call its initialize_plugin method' do
156
- @keeper.plugin_description.should == @pdf
157
- end
158
-
159
- it 'should have no project' do
160
- @keeper.projects.should be_empty
161
- end
162
-
163
- it 'should have no current project' do
164
- @keeper.current_project.should be_nil
165
- end
166
-
167
- end
168
-
169
- describe 'Ruber::Project#current_project=, when called with a non-nil argument' do
170
-
171
- before do
172
- app = Qt::Object.new
173
- manager = flexmock('components'){|m| m.should_ignore_missing}
174
- flexmock(Ruber).should_receive(:[]).with(:app).and_return(app)
175
- flexmock(Ruber).should_receive(:[]).with(:components).and_return(manager)
176
- flexmock(Ruber).should_receive(:[]).with(:config).and_return(nil)
177
- pdf = Ruber::PluginSpecification.full({:name => :projects, :class => Ruber::ProjectList})
178
- @keeper = Ruber::ProjectList.new manager, pdf
179
- @prj = Ruber::ProjectList::FakeProject.new
180
- @keeper.instance_variable_get(:@projects)[@prj.project_file] = @prj
181
- @keeper.instance_variable_get(:@projects)['test'] = @prj
182
- end
183
-
184
- it 'should set the current project to its argument' do
185
- @keeper.current_project = @prj
186
- @keeper.current_project.should equal( @prj )
187
- end
188
-
189
- it 'should call the "deactivate" method of the old current project, if it\'s not nil' do
190
- @keeper.instance_variable_set(:@current_project, @prj)
191
- new_prj = Ruber::ProjectList::FakeProject.new 'Test1'
192
- @keeper.add_project new_prj
193
- flexmock(@prj).should_receive( :deactivate).once
194
- @keeper.current_project = new_prj
195
- @keeper.instance_variable_set :@current_project, nil
196
- lambda{@keeper.current_project = @prj}.should_not raise_error
197
- end
198
-
199
- it 'should emit the "current_project_changed(QObject*)" signal with the project as argument' do
200
- test = flexmock('test'){|m| m.should_receive(:current_project_changed).once.with(@prj)}
201
- @keeper.connect(SIGNAL('current_project_changed(QObject*)')){|o| test.current_project_changed(o)}
202
- @keeper.current_project = @prj
203
- end
204
-
205
- it 'should call the "activate" method of the new current project' do
206
- @keeper.instance_variable_set(:@current_project, @prj)
207
- new_prj = Ruber::ProjectList::FakeProject.new 'Test1'
208
- @keeper.add_project new_prj
209
- flexmock(new_prj).should_receive( :activate).once
210
- @keeper.current_project = new_prj
211
- end
212
-
213
- it 'should raise ArgumentError if the project is not in the project list' do
214
- @keeper.instance_variable_get(:@projects).clear
215
- lambda{@keeper.current_project = @prj}.should raise_error(ArgumentError, "Tried to set an unknown as current project")
216
- end
217
-
218
- end
219
-
220
- describe 'Ruber::Project#current_project=, when called with nil' do
221
-
222
- before do
223
- app = Qt::Object.new
224
- manager = flexmock('components'){|m| m.should_ignore_missing}
225
- flexmock(Ruber).should_receive(:[]).with(:app).and_return(app)
226
- flexmock(Ruber).should_receive(:[]).with(:components).and_return(manager)
227
- flexmock(Ruber).should_receive(:[]).with(:config).and_return(nil)
228
- pdf = Ruber::PluginSpecification.full({:name => :projects, :class => Ruber::ProjectList})
229
- @keeper = Ruber::ProjectList.new manager, pdf
230
- end
231
-
232
- it 'should set the current project to nil' do
233
- @keeper.current_project = nil
234
- @keeper.current_project.should be_nil
235
- end
236
-
237
- it 'should emit the "current_project_changed(QObject*)" signal with Qt::NilObject as argument' do
238
- test = flexmock('test'){|m| m.should_receive(:current_project_changed).once.with(nil)}
239
- @keeper.connect(SIGNAL('current_project_changed(QObject*)')){|o| test.current_project_changed(o)}
240
- @keeper.current_project = nil
241
- end
242
-
243
- end
244
-
245
- describe 'Ruber::ProjectList#add_project' do
246
-
247
- before do
248
- app = Qt::Object.new
249
- manager = flexmock('components'){|m| m.should_ignore_missing}
250
- flexmock(Ruber).should_receive(:[]).with(:app).and_return(app)
251
- flexmock(Ruber).should_receive(:[]).with(:components).and_return(manager)
252
- flexmock(Ruber).should_receive(:[]).with(:config).and_return(nil)
253
- pdf = Ruber::PluginSpecification.full({:name => :projects, :class => Ruber::ProjectList})
254
- @keeper = Ruber::ProjectList.new manager, pdf
255
- end
256
-
257
- it 'should add the project passed as argument to the list of projects' do
258
- prj = Ruber::ProjectList::FakeProject.new 'Test'
259
- @keeper.add_project prj
260
- @keeper.instance_variable_get(:@projects)[prj.project_file].should equal(prj)
42
+
43
+ it 'doesn\'t create a duplicate of the argument if it is a ProjectList' do
44
+ other_list = Ruber::World::ProjectList.new @projects
45
+ list = Ruber::World::ProjectList.new other_list
46
+ list.send(:project_hash).should equal(other_list.send(:project_hash))
47
+ end
48
+
49
+ it 'keeps a single copy of projects with the same project file' do
50
+ @projects << create_project('project-1')
51
+ @list = Ruber::World::ProjectList.new @projects
52
+ @list.to_a.select{|prj| prj.project_name == "Project 1"}.count.should == 1
53
+ end
54
+
261
55
  end
262
56
 
263
- it 'should return the project' do
264
- prj = Ruber::ProjectList::FakeProject.new 'Test'
265
- @keeper.add_project( prj).should equal(prj)
57
+ describe '#each' do
58
+
59
+ context 'when called with a block' do
60
+
61
+ it 'calls the block once for each project' do
62
+ res = []
63
+ @list.each{|prj| res << prj}
64
+ res.should == @projects
65
+ end
66
+
67
+ it 'returns self' do
68
+ @list.each{}.should equal(@list)
69
+ end
70
+
71
+ end
72
+
73
+ context 'when called without a block' do
74
+
75
+ it 'returns an Enumerator which iterates on the projects' do
76
+ res = []
77
+ enum = @list.each
78
+ enum.should be_an(Enumerator)
79
+ enum.each{|prj| res << prj}
80
+ res.should == @projects
81
+
82
+ end
83
+
84
+ end
85
+
266
86
  end
267
87
 
268
- it 'should emit the "project_added(QObject*)" signal passing the added project' do
269
- prj = Ruber::ProjectList::FakeProject.new 'Test'
270
- m = flexmock('test'){|mk| mk.should_receive(:project_added).once.with(prj)}
271
- @keeper.connect(SIGNAL('project_added(QObject*)')){|o| m.project_added(o)}
272
- @keeper.add_project prj
88
+ describe '#empty?' do
89
+
90
+ it 'returns true if the list doesn\'t contain any element' do
91
+ list = Ruber::World::ProjectList.new({})
92
+ list.should be_empty
93
+ end
94
+
95
+ it 'returns false if the list contains at least one element' do
96
+ @list.should_not be_empty
97
+ end
98
+
273
99
  end
274
100
 
275
- it 'should raise RuntimeError if the project is already in the list' do
276
- prj_file = File.expand_path('test.ruprj')
277
- prj1 = Ruber::ProjectList::FakeProject.new 'test1', prj_file
278
- prj2 = Ruber::ProjectList::FakeProject.new 'test2', prj_file
279
- @keeper.add_project prj1
280
- lambda{@keeper.add_project prj2}.should raise_error(RuntimeError, "A project with project file #{prj_file} is already open")
101
+ describe '#size' do
102
+
103
+ it 'returns the number of elements in the list' do
104
+ list = Ruber::World::ProjectList.new({})
105
+ list.size.should == 0
106
+ list = Ruber::World::ProjectList.new @projects
107
+ list.size.should == 3
108
+ end
109
+
281
110
  end
282
111
 
283
- end
284
-
285
- describe 'Ruber::ProjectList, when a project in the list is closed' do
286
-
287
- before do
288
- app = Qt::Object.new
289
- manager = flexmock('components'){|m| m.should_ignore_missing}
290
- flexmock(Ruber).should_receive(:[]).with(:app).and_return(app)
291
- flexmock(Ruber).should_receive(:[]).with(:components).and_return(manager)
292
- flexmock(Ruber).should_receive(:[]).with(:config).and_return(nil)
293
- pdf = Ruber::PluginSpecification.full({:name => :projects, :class => Ruber::ProjectList})
294
- @keeper = Ruber::ProjectList.new manager, pdf
112
+ describe '#==' do
113
+
114
+ context 'when the argument is a ProjectList' do
115
+
116
+ it 'returns true if the argument contains the same projects' do
117
+ other = Ruber::World::ProjectList.new @projects
118
+ @list.should == other
119
+ end
120
+
121
+ it 'returns false if the argument contains different projects' do
122
+ new_prj = create_project 'project-3'
123
+ @projects << new_prj
124
+ other = Ruber::World::ProjectList.new @projects
125
+ @list.should_not == other
126
+ end
127
+
128
+ end
129
+
130
+ context 'when the argument is an Array' do
131
+
132
+ it 'returns true if the argument contains the same projects' do
133
+ @list.should == @projects.reverse
134
+ end
135
+
136
+ it 'returns false if the argument contains different projects' do
137
+ @list.should_not == [@projects[0], 'x']
138
+ end
139
+
140
+ end
141
+
142
+ context 'when the argument is neither a ProjectList nor an array' do
143
+
144
+ it 'returns false' do
145
+ @list.should_not == {}
146
+ @list.should_not == 'x'
147
+ end
148
+
149
+ end
150
+
295
151
  end
296
152
 
297
- it 'should emit the "project_closing" signal, passing the project as argument' do
298
- prj = Ruber::ProjectList::FakeProject.new
299
- @keeper.add_project prj
300
- m = flexmock{|mk| mk.should_receive(:project_closing).once}
301
- @keeper.connect(SIGNAL('closing_project(QObject*)')){|o| m.project_closing(o)}
302
- prj.close
153
+ describe '#eql?' do
154
+
155
+ context 'when the argument is a ProjectList' do
156
+
157
+ it 'returns true if the argument contains the same projects' do
158
+ other = Ruber::World::ProjectList.new @projects
159
+ @list.should eql(other)
160
+ end
161
+
162
+ it 'returns false if the argument contains different projects' do
163
+ new_prj = create_project 'project-3'
164
+ @projects << new_prj
165
+ other = Ruber::World::ProjectList.new @projects
166
+ @list.should_not eql(other)
167
+ end
168
+
169
+ end
170
+
171
+ context 'when the argument is not a ProjectList' do
172
+
173
+ it 'returns false' do
174
+ @list.should_not eql({})
175
+ @list.should_not eql('x')
176
+ @list.should_not eql(@projects)
177
+ end
178
+
179
+ end
180
+
303
181
  end
304
182
 
305
- it 'should set the current project to nil if the closed project was the current one' do
306
- prj = Ruber::ProjectList::FakeProject.new
307
- @keeper.add_project prj
308
- @keeper.current_project = prj
309
- prj.close
310
- @keeper.current_project.should be_nil
183
+ describe '#hash' do
184
+
185
+ it 'returns the same value as an hash contining the same arguments' do
186
+ @list.hash.should == Hash[@projects.map{|prj| [prj.project_file, prj]}].hash
187
+ end
188
+
311
189
  end
312
-
313
- end
314
190
 
315
- describe 'Ruber::ProjectList#close_current_project' do
316
-
317
- include FlexMock::ArgumentTypes
318
-
319
- before do
320
- app = Qt::Object.new
321
- manager = flexmock('components'){|m| m.should_ignore_missing}
322
- flexmock(Ruber).should_receive(:[]).with(:app).and_return(app)
323
- flexmock(Ruber).should_receive(:[]).with(:components).and_return(manager)
324
- flexmock(Ruber).should_receive(:[]).with(:config).and_return(nil)
325
- pdf = Ruber::PluginSpecification.full({:name => :projects, :class => Ruber::ProjectList})
326
- @keeper = Ruber::ProjectList.new manager, pdf
327
- @prj = Ruber::ProjectList::FakeProject.new{self.object_name = 'project'}
328
- @keeper.add_project = @prj
329
- @keeper.current_project= @prj
330
- end
331
-
332
- it 'should set the current project to nil' do
333
- flexmock(@keeper).should_receive(:current_project=).with(nil).once
334
- @keeper.close_current_project
335
- end
336
-
337
- it 'should emit the "closing_project(QObject*)" signal after setting the current_project to nil, passing the project as argument' do
338
- test = flexmock("test"){|m| m.should_receive(:project_closed).once.with(on{|a| a == @prj and !a.disposed?})}
339
- flexmock(Ruber).should_receive(:[]).and_return(flexmock{|m| m.should_ignore_missing})
340
- @keeper.connect(SIGNAL('closing_project(QObject*)')){|o| test.project_closed(o)}
341
- @keeper.close_current_project
342
- end
343
-
344
- it 'should do nothing if the current project is nil' do
345
- @keeper.instance_variable_set(:@current_project, nil)
346
- lambda{@keeper.close_current_project}.should_not raise_error
191
+ describe "#[]" do
192
+
193
+ context 'if the argument starts with a slash' do
194
+
195
+ it 'retuns the project associated witt the given file' do
196
+ @list[@projects[0].project_file].should == @projects[0]
197
+ end
198
+
199
+ it 'returns nil if there\'s no project in the list associated with the given file' do
200
+ @list['/xyz.ruprj'].should be_nil
201
+ end
202
+
203
+ end
204
+
205
+ context 'if the argument doesn\'t start with a slash' do
206
+
207
+ it 'returns the project having the argument as project name' do
208
+ name = 'Project 1'
209
+ @list[name].project_name.should == 'Project 1'
210
+ end
211
+
212
+ it 'returns nil if there\'s no project with the given name in the list' do
213
+ @list['xyz'].should be_nil
214
+ end
215
+
216
+ end
217
+
347
218
  end
348
219
 
349
220
  end
350
221
 
351
- describe 'Ruber::ProjectList#new_project' do
352
-
353
- before do
354
- app = Qt::Object.new
355
- manager = flexmock('components'){|m| m.should_ignore_missing}
356
- flexmock(Ruber).should_receive(:[]).with(:app).and_return(app)
357
- flexmock(Ruber).should_receive(:[]).with(:components).and_return(manager)
358
- flexmock(Ruber).should_receive(:[]).with(:config).and_return(nil)
359
- pdf = Ruber::PluginSpecification.full({:name => :projects, :class => Ruber::ProjectList})
360
- @keeper = Ruber::ProjectList.new manager, pdf
361
- end
362
-
363
- it 'should create a new empty project and return it' do
364
- prj = Ruber::ProjectList::FakeProject.new 'test.ruprj', 'Test'
365
- flexmock(Ruber::Project).should_receive(:new).once.with('test.ruprj', 'Test').and_return prj
366
- res = @keeper.new_project 'test.ruprj', 'Test'
367
- res.should equal(prj)
368
- end
369
-
370
- it 'should add the new project to the project list' do
371
- prj = Ruber::ProjectList::FakeProject.new 'Test', 'test.ruprj'
372
- flexmock(Ruber::Project).should_receive(:new).once.with('test.ruprj', 'Test').and_return prj
373
- @keeper.new_project 'test.ruprj', 'Test'
374
- @keeper.instance_variable_get(:@projects)['test.ruprj'].should equal(prj)
375
- end
222
+ describe Ruber::World::MutableProjectList do
376
223
 
377
- it 'should emit the "project_added(QObject*)" signal with the new project as argument' do
378
- prj = Ruber::ProjectList::FakeProject.new 'Test', 'test.ruprj'
379
- flexmock(Ruber::Project).should_receive(:new).once.with('test.ruprj', 'Test').and_return prj
380
- m = flexmock('test'){|mk| mk.should_receive(:project_added).once.with(prj)}
381
- @keeper.connect(SIGNAL('project_added(QObject*)')){|o| m.project_added(o)}
382
- @keeper.new_project 'test.ruprj', 'Test'
224
+ def create_project file, name = nil
225
+ name ||= file.sub(/[_-]/, ' ').sub('.ruprj','').capitalize
226
+ file = File.join Dir.tmpdir, file unless file.start_with? '/'
227
+ file += '.ruprj' unless file.end_with?('ruprj')
228
+ Ruber::Project.new file, name
383
229
  end
384
230
 
385
- end
386
-
387
- describe 'Ruber::Project#project' do
388
-
389
231
  before do
390
- app = Qt::Object.new
391
- manager = flexmock('components'){|m| m.should_ignore_missing}
392
- flexmock(Ruber).should_receive(:[]).with(:app).and_return(app)
393
- flexmock(Ruber).should_receive(:[]).with(:components).and_return(manager)
394
- flexmock(Ruber).should_receive(:[]).with(:config).and_return(nil)
395
- pdf = Ruber::PluginSpecification.full({:name => :projects, :class => Ruber::ProjectList})
396
- @keeper = Ruber::ProjectList.new manager, pdf
232
+ @projects = 3.times.map{|i| create_project "project-#{i}"}
233
+ @list = Ruber::World::MutableProjectList.new
397
234
  end
398
235
 
399
- it 'should return the project corresponding to the file passed as argument, if it is in the list' do
400
- prj = Ruber::ProjectList::FakeProject.new 'Test', 'test.ruprj'
401
- @keeper.instance_variable_get(:@projects)[prj.project_file] = prj
402
- @keeper.project('test.ruprj').should equal(prj)
236
+ it 'inherits from Ruber::World::ProjectList' do
237
+ Ruber::World::MutableProjectList.ancestors.should include(Ruber::World::ProjectList)
403
238
  end
404
239
 
405
- it 'should load the project from the file passed as argument if it isn\'t in the list' do
406
- prj = Ruber::ProjectList::FakeProject.new 'Test', 'test.ruprj'
407
- flexmock(Ruber::Project).should_receive(:new).once.with('test.ruprj').and_return prj
408
- @keeper.project('test.ruprj').should equal(prj)
409
- end
410
-
411
- it 'should emit the "project_added(QObject*)" signal, passing the project as argument, if the project isn\'t in the list' do
412
- prj = Ruber::ProjectList::FakeProject.new 'Test', 'test.ruprj'
413
- flexmock(Ruber::Project).should_receive(:new).once.with('test.ruprj').and_return prj
414
- m = flexmock{|mk| mk.should_receive(:project_added).once.with(prj)}
415
- @keeper.connect(SIGNAL('project_added(QObject*)')){|o| m.project_added(o)}
416
- @keeper.project 'test.ruprj'
240
+ describe '#initialize' do
241
+
242
+ context 'when called with no arguments' do
243
+
244
+ it 'creates an empty list' do
245
+ @list.should be_empty
246
+ end
247
+
248
+ end
249
+
250
+ context 'when called with an array as argument' do
251
+
252
+ it 'creates a list containing the same projects as the argument' do
253
+ @list = Ruber::World::MutableProjectList.new @projects
254
+ @list.to_a.sort_by{|prj| prj.object_id}.should == @projects.sort_by{|prj| prj.object_id}
255
+ end
256
+
257
+ it 'creates a duplicate of the argument' do
258
+ @list = Ruber::World::MutableProjectList.new @projects
259
+ new_prj = create_project 'project-4'
260
+ @projects << new_prj
261
+ @list.size.should == 3
262
+ end
263
+
264
+ end
265
+
266
+ context 'when called with a ProjectList as argument' do
267
+
268
+ it 'creates a list containing the same documents as the argument' do
269
+ orig = Ruber::World::ProjectList.new @projects
270
+ @list = Ruber::World::MutableProjectList.new orig
271
+ @list.to_a.should == @projects
272
+ end
273
+
274
+ it 'creates a duplicate of the argument' do
275
+ orig = Ruber::World::ProjectList.new @projects
276
+ @list = Ruber::World::MutableProjectList.new orig
277
+ new_prj = create_project 'project-4'
278
+ orig.send(:project_hash)[new_prj.project_file] = new_prj
279
+ @list.size.should == 3
280
+ end
281
+
282
+ end
283
+
417
284
  end
418
285
 
419
- end
420
-
421
- describe 'Ruber::Project#[]' do
422
-
423
- before do
424
- app = Qt::Object.new
425
- manager = flexmock('components'){|m| m.should_ignore_missing}
426
- flexmock(Ruber).should_receive(:[]).with(:app).and_return(app)
427
- flexmock(Ruber).should_receive(:[]).with(:components).and_return(manager)
428
- flexmock(Ruber).should_receive(:[]).with(:config).and_return(nil)
429
- pdf = Ruber::PluginSpecification.full({:name => :projects, :class => Ruber::ProjectList})
430
- @keeper = Ruber::ProjectList.new manager, pdf
286
+ describe '#dup' do
287
+
288
+ it 'duplicates the document list' do
289
+ @list.add @projects
290
+ new_list = @list.dup
291
+ new_list.remove @projects[1]
292
+ @list.should == @projects
293
+ end
294
+
431
295
  end
432
296
 
433
- it 'should return the project corresponding to the given file, if the argument is a string starting with /, if such a project exists' do
434
- prj = Ruber::ProjectList::FakeProject.new 'Test', '/test.ruprj'
435
- @keeper.add_project prj
436
- @keeper['/test.ruprj'].should equal(prj)
297
+ describe '#clone' do
298
+
299
+ it 'duplicates the document list' do
300
+ @list.add @projects
301
+ new_list = @list.clone
302
+ new_list.remove @projects[1]
303
+ @list.should == @projects
304
+ end
305
+
306
+ it 'copies the frozen status of the project list' do
307
+ @list.freeze
308
+ new_list = @list.clone
309
+ new_list.should be_frozen
310
+ lambda{new_list.add create_project('project-4')}.should raise_error(RuntimeError)
311
+ end
312
+
437
313
  end
438
314
 
439
- it 'should return the project with the given name if the argument is a string not starting with /, if such a project exists' do
440
- prj = Ruber::ProjectList::FakeProject.new 'xyz', '/test.ruprj'
441
- @keeper.add_project prj
442
- @keeper['xyz'].should equal(prj)
315
+ describe '#add' do
316
+
317
+ it 'appends the given projects to the list' do
318
+ @list.add @projects[0]
319
+ @list.to_a.should == [@projects[0]]
320
+ @list.add *@projects[1..-1]
321
+ @list.to_a.should == @projects
322
+ end
323
+
324
+ it 'treats arrays of projects as if each project was an argument by itself' do
325
+ @list.add @projects
326
+ @list.to_a.should == @projects
327
+ end
328
+
329
+ it 'returns self' do
330
+ @list.add(@projects).should equal(@list)
331
+ end
332
+
443
333
  end
444
334
 
445
- it 'should return nil if the requested project doesn\'t exist' do
446
- prj = Ruber::ProjectList::FakeProject.new 'xyz', '/test.ruprj'
447
- @keeper.add_project prj
448
- @keeper['abc'].should be_nil
449
- @keeper['/xyz.ruprj'].should be_nil
335
+ describe '#merge!' do
336
+
337
+ before do
338
+ @projects = 5.times.map{|i| create_project "project-#{i}"}
339
+ @list.add @projects[3..4]
340
+ end
341
+
342
+ it 'adds the contents of the argument to self' do
343
+ other = Ruber::World::MutableProjectList.new @projects[0..2]
344
+ @list.merge!(other)
345
+ @list.should == @projects[3..4]+@projects[0..2]
346
+ end
347
+
348
+ it 'also works with an array argument' do
349
+ @list.merge!(@projects[0..2])
350
+ @list.should == @projects[3..4]+@projects[0..2]
351
+ end
352
+
353
+ it 'returns self' do
354
+ @list.merge!(@projects[0..2]).should equal(@list)
355
+ end
356
+
450
357
  end
451
358
 
452
- end
453
-
454
- describe 'Ruber::ProjectList#save_settings' do
455
-
456
- before do
457
- app = Qt::Object.new
458
- manager = flexmock('components'){|m| m.should_ignore_missing}
459
- flexmock(Ruber).should_receive(:[]).with(:app).and_return(app)
460
- flexmock(Ruber).should_receive(:[]).with(:components).and_return(manager)
461
- flexmock(Ruber).should_receive(:[]).with(:config).and_return(nil)
462
- pdf = Ruber::PluginSpecification.full({:name => :projects, :class => Ruber::ProjectList})
463
- @keeper = Ruber::ProjectList.new manager, pdf
359
+ describe '#remove' do
360
+
361
+ before do
362
+ @list.add @projects
363
+ end
364
+
365
+ it 'removes the project from the list' do
366
+ @list.remove @projects[1]
367
+ @list.to_a.should == [@projects[0], @projects[2]]
368
+ end
369
+
370
+ it 'does nothing if the project is not in the list' do
371
+ @list.remove create_project('project-4')
372
+ @list.to_a.should == @projects
373
+ end
374
+
375
+ it 'returns the removed document, if any' do
376
+ @list.remove(@projects[1]).should == @projects[1]
377
+ end
378
+
379
+ it 'returns nil if no document was removed' do
380
+ @list.remove(create_project('project-4')).should be_nil
381
+ end
382
+
464
383
  end
465
384
 
466
- it 'should call the save method of each open project' do
467
- projects = @keeper.instance_variable_get(:@projects)
468
- 5.times do |i|
469
- projects[i] = flexmock(i.to_s){|m| m.should_receive(:save).once}
385
+ describe '#clear' do
386
+
387
+ it 'removes all elements from the list' do
388
+ @list.add @projects
389
+ @list.clear
390
+ @list.should be_empty
391
+ end
392
+
393
+ it 'returns self' do
394
+ @list.clear.should equal(@list)
470
395
  end
471
- @keeper.save_settings
396
+
472
397
  end
473
398
 
474
- end
475
-
476
- describe Ruber::ProjectList do
477
-
478
- describe '#query_close' do
399
+ describe '#delete_if' do
479
400
 
480
401
  before do
481
- app = Qt::Object.new
482
- manager = flexmock('components'){|m| m.should_ignore_missing}
483
- flexmock(Ruber).should_receive(:[]).with(:app).and_return(app)
484
- flexmock(Ruber).should_receive(:[]).with(:components).and_return(manager)
485
- flexmock(Ruber).should_receive(:[]).with(:config).and_return(nil)
486
- pdf = Ruber::PluginSpecification.full({:name => :projects, :class => Ruber::ProjectList})
487
- @keeper = Ruber::ProjectList.new manager, pdf
488
- @values = 5.times.map{|i| flexmock(:project_name => i.to_s)}
489
- prjs = @keeper.instance_variable_get(:@projects)
490
- @values.each{|v| prjs[v.project_name] = v}
491
- def prjs.values
492
- super.sort_by{|p| p.project_name}
493
- end
402
+ @list.add @projects
494
403
  end
495
404
 
496
- it 'calls the query_close method of all the projects and returns true if they all return true' do
497
- @values.each{|pr| pr.should_receive(:query_close).once.and_return true}
498
- @keeper.query_close.should be_true
405
+ it 'removes all the elements for which the block returns true' do
406
+ @list.delete_if{|prj| prj.project_name == 'Project 1'}
407
+ @list.should == [@projects[0], @projects[2]]
499
408
  end
500
409
 
501
- it 'stops iterating through the projects and returns false if one of the project\'s query_close method returns false' do
502
- @values[0].should_receive(:query_close).once.and_return true
503
- @values[1].should_receive(:query_close).once.and_return true
504
- @values[2].should_receive(:query_close).once.and_return false
505
- @values[3].should_receive(:query_close).never
506
- @values[4].should_receive(:query_close).never
507
- @keeper.query_close.should be_false
410
+ it 'returns self' do
411
+ @list.delete_if{|prj| prj.project_name == 'Project 1'}.should equal(@list)
508
412
  end
509
413
 
510
414
  end
415
+
511
416
  end