ruber 0.0.5 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. data/CHANGES +25 -0
  2. data/bin/ruber +0 -0
  3. data/data/share/apps/ruber/ruberui.rc +15 -1
  4. data/data/share/icons/{ruber.png → ruber-old.pgn} +0 -0
  5. data/lib/ruber/application/application.rb +216 -73
  6. data/lib/ruber/application/plugin.yaml +2 -2
  7. data/lib/ruber/document_project.rb +25 -5
  8. data/lib/ruber/documents/document_list.rb +11 -15
  9. data/lib/ruber/editor/document.rb +106 -50
  10. data/lib/ruber/editor/editor_view.rb +4 -2
  11. data/lib/ruber/external_program_plugin.rb +8 -0
  12. data/lib/ruber/kde_config_option_backend.rb +12 -4
  13. data/lib/ruber/kde_sugar.rb +35 -1
  14. data/lib/ruber/main_window/choose_plugins_dlg.rb +10 -10
  15. data/lib/ruber/main_window/hint_solver.rb +263 -0
  16. data/lib/ruber/main_window/main_window.rb +462 -206
  17. data/lib/ruber/main_window/main_window_actions.rb +228 -62
  18. data/lib/ruber/main_window/main_window_internal.rb +169 -115
  19. data/lib/ruber/main_window/plugin.yaml +13 -3
  20. data/lib/ruber/main_window/save_modified_files_dlg.rb +1 -1
  21. data/lib/ruber/main_window/ui/choose_plugins_widget.rb +1 -1
  22. data/lib/ruber/main_window/ui/main_window_settings_widget.rb +1 -1
  23. data/lib/ruber/main_window/ui/new_project_widget.rb +1 -1
  24. data/lib/ruber/main_window/ui/open_file_in_project_dlg.rb +1 -1
  25. data/lib/ruber/main_window/ui/output_color_widget.rb +1 -1
  26. data/lib/ruber/main_window/ui/workspace_settings_widget.rb +51 -0
  27. data/lib/ruber/main_window/ui/workspace_settings_widget.ui +28 -0
  28. data/lib/ruber/main_window/view_manager.rb +418 -0
  29. data/lib/ruber/main_window/workspace.png +0 -0
  30. data/lib/ruber/output_widget.rb +43 -37
  31. data/lib/ruber/pane.rb +621 -0
  32. data/lib/ruber/plugin_specification_reader.rb +8 -1
  33. data/lib/ruber/projects/project_files_list.rb +6 -0
  34. data/lib/ruber/projects/ui/project_files_rule_chooser_widget.rb +1 -1
  35. data/lib/ruber/projects/ui/project_files_widget.rb +1 -1
  36. data/lib/ruber/qt_sugar.rb +94 -4
  37. data/lib/ruber/utils.rb +16 -7
  38. data/lib/ruber/version.rb +2 -2
  39. data/plugins/autosave/autosave.rb +62 -1
  40. data/plugins/autosave/plugin.yaml +1 -0
  41. data/plugins/autosave/ui/autosave_config_widget.rb +37 -14
  42. data/plugins/autosave/ui/autosave_config_widget.ui +62 -12
  43. data/plugins/find_in_files/find_in_files_widgets.rb +1 -3
  44. data/plugins/find_in_files/ui/config_widget.rb +1 -1
  45. data/plugins/find_in_files/ui/find_in_files_widget.rb +1 -1
  46. data/plugins/rake/plugin.yaml +1 -1
  47. data/plugins/rake/ui/add_quick_task_widget.rb +1 -1
  48. data/plugins/rake/ui/choose_task_widget.rb +1 -1
  49. data/plugins/rake/ui/config_widget.rb +1 -1
  50. data/plugins/rake/ui/project_widget.rb +1 -1
  51. data/plugins/rspec/rspec.rb +14 -22
  52. data/plugins/rspec/ruber_rspec_formatter.rb +4 -1
  53. data/plugins/rspec/ui/rspec_project_widget.rb +1 -1
  54. data/plugins/ruby_development/plugin.yaml +7 -2
  55. data/plugins/ruby_development/ruby_development.rb +134 -13
  56. data/plugins/ruby_development/ui/config_widget.rb +66 -0
  57. data/plugins/ruby_development/ui/config_widget.ui +58 -0
  58. data/plugins/ruby_development/ui/project_widget.rb +1 -1
  59. data/plugins/ruby_runner/plugin.yaml +2 -2
  60. data/plugins/ruby_runner/ruby_runner.rb +15 -3
  61. data/plugins/ruby_runner/ui/config_widget.rb +1 -1
  62. data/plugins/ruby_runner/ui/project_widget.rb +1 -1
  63. data/plugins/ruby_runner/ui/ruby_runnner_plugin_option_widget.rb +1 -1
  64. data/plugins/state/plugin.yaml +6 -2
  65. data/plugins/state/state.rb +305 -81
  66. data/plugins/state/ui/config_widget.rb +1 -1
  67. data/spec/common.rb +11 -3
  68. data/spec/document_list_spec.rb +8 -8
  69. data/spec/document_project_spec.rb +98 -25
  70. data/spec/document_spec.rb +178 -152
  71. data/spec/editor_view_spec.rb +26 -5
  72. data/spec/framework.rb +5 -0
  73. data/spec/hint_solver_spec.rb +450 -0
  74. data/spec/kde_sugar_spec.rb +73 -6
  75. data/spec/output_widget_spec.rb +172 -156
  76. data/spec/pane_spec.rb +1165 -0
  77. data/spec/plugin_specification_reader_spec.rb +37 -1
  78. data/spec/project_files_list_spec.rb +30 -20
  79. data/spec/qt_sugar_spec.rb +269 -0
  80. data/spec/state_spec.rb +566 -353
  81. data/spec/utils_spec.rb +1 -1
  82. data/spec/view_manager_spec.rb +71 -0
  83. metadata +16 -4
@@ -53,7 +53,7 @@ module Ruber
53
53
  @reader.process_pdf({}).should eql(@info)
54
54
  end
55
55
 
56
- it 'should require all files obtained by joining the PluginSpecification\'s directory with the files returned by the read_required method, before calling the read_required method' do
56
+ it 'requires all files obtained by joining the PluginSpecification\'s directory with the files returned by the read_required method, before calling the read_required method' do
57
57
  @info.directory = '/xyz'
58
58
  flexmock(@reader).should_receive(:read_required).and_return %w[a b]
59
59
  flexmock(@reader).should_receive(:require).globally.ordered.once.with '/xyz/a'
@@ -61,6 +61,15 @@ module Ruber
61
61
  flexmock(@reader).should_receive(:read_ui_file).globally.ordered.once.and_return 'testui.rc'
62
62
  @reader.process_pdf({})
63
63
  end
64
+
65
+ it 'loads files returned by the read_required method rather than require them if they end in .rb' do
66
+ @info.directory = '/xyz'
67
+ flexmock(@reader).should_receive(:read_required).and_return %w[a b.rb]
68
+ flexmock(@reader).should_receive(:require).globally.ordered.once.with '/xyz/a'
69
+ flexmock(@reader).should_receive(:load).globally.ordered.once.with '/xyz/b.rb'
70
+ flexmock(@reader).should_receive(:read_ui_file).globally.ordered.once.and_return 'testui.rc'
71
+ @reader.process_pdf({})
72
+ end
64
73
 
65
74
  end
66
75
 
@@ -1651,6 +1660,33 @@ describe Ruber::PluginSpecificationReader do
1651
1660
 
1652
1661
  end
1653
1662
 
1663
+ context ', when reading the place' do
1664
+
1665
+ it 'puts the contents of the place entry of the argument in the :place entry of the returned hash' do
1666
+ @reader.send(:read_rules, {:place => [:local]})[:place].should == [:local]
1667
+ @reader.send(:read_rules, {'place' => [:remote]})[:place].should == [:remote]
1668
+ end
1669
+
1670
+ it 'converts the values :all and all to [:local, :remote]' do
1671
+ @reader.send(:read_rules, {:place => ['all']})[:place].should == [:local, :remote]
1672
+ @reader.send(:read_rules, {'place' => [:all]})[:place].should == [:local, :remote]
1673
+ end
1674
+
1675
+ it 'encloses the place entry of the argument in a array, unless it\'s already an array' do
1676
+ @reader.send(:read_rules, {:place => :local})[:place].should == [:local]
1677
+ end
1678
+
1679
+ it 'converts each entry of the place array to a symbol' do
1680
+ @reader.send(:read_rules, {:place => %w[local remote]})[:place].should == [:local, :remote]
1681
+ end
1682
+
1683
+ it 'uses [:local] as default value' do
1684
+ @reader.send(:read_rules, {})[:place].should == [:local]
1685
+ end
1686
+
1687
+ end
1688
+
1689
+
1654
1690
  describe ', when reading the mimetype' do
1655
1691
 
1656
1692
  it 'stores the contents of the mimetype entry of the argument in the returned value' do
@@ -131,49 +131,49 @@ describe 'Ruber::ProjectFilesList' do
131
131
  FileUtils.rm_f @dir
132
132
  end
133
133
 
134
- it 'should update the cache if it\'s not up to date' do
134
+ it 'updates the cache if it\'s not up to date' do
135
135
  @list.instance_variable_set :@up_to_date, false
136
136
  flexmock(@list).should_receive(:refresh).once
137
137
  @list.project_files
138
138
  end
139
139
 
140
- it 'should not update the cache if it\'s already up to date' do
140
+ it 'doesn\'t update the cache if it\'s already up to date' do
141
141
  @list.instance_variable_set :@up_to_date, true
142
142
  flexmock(@list).should_receive(:refresh).never
143
143
  @list.project_files
144
144
  end
145
145
 
146
- it 'should return an array containing all the files corresponding to include rules of type path unless they also correspond to an exclude rule of type path' do
146
+ it 'returns an array containing all the files corresponding to include rules of type path unless they also correspond to an exclude rule of type path' do
147
147
  @prj[:general, :project_files] = {:include => ['README', 'COPYING', 'f1.rb', 'd2/CHANGELOG', 'd2/f21.rb'], :exclude => ['COPYING', 'd2/f21.rb'], :extensions => []}
148
148
  @list.project_files(false).should =~ %w[README f1.rb d2/CHANGELOG]
149
149
  end
150
150
 
151
- it 'should not include in the returned array files which don\'t exist' do
151
+ it 'doesn\'t include in the returned array files which don\'t exist' do
152
152
  @prj[:general, :project_files] = {:include => ['README1', 'COPYING', 'f1.rb', 'd2/CHANGELOG', 'd2/f211.rb'], :exclude => ['COPYING'], :extensions => []}
153
153
  @list.project_files(false).should =~ %w[f1.rb d2/CHANGELOG]
154
154
  end
155
155
 
156
- it 'should skip include rules of type path corresponding to directories' do
156
+ it 'skips include rules of type path corresponding to directories' do
157
157
  @prj[:general, :project_files] = {:include => ['README', 'COPYING', 'f1.rb', 'd2/CHANGELOG', 'd2/f21.rb', 'd3'], :exclude => ['COPYING', 'd2/f21.rb'], :extensions => []}
158
158
  @list.project_files(false).should =~ %w[README f1.rb d2/CHANGELOG]
159
159
  end
160
160
 
161
- it 'should include all the files in the project directory which correspond to one of the extensions in the returned array, unless they match one of the exclude rule' do
161
+ it 'includes all the files in the project directory which correspond to one of the extensions in the returned array, unless they match one of the exclude rule' do
162
162
  @prj[:general, :project_files] = {:include => [], :exclude => ['COPYING', 'd2/f21.rb'], :extensions => %w[*.rb]}
163
163
  @list.project_files(false).should =~ %w[f1.rb d2/f22.rb d3/f31.rb d3/f32.rb]
164
164
  end
165
165
 
166
- it 'should include all the files in the project directory which match one of the include rules of type regexp and don\'t match any exclude rule' do
166
+ it 'includes all the files in the project directory which match one of the include rules of type regexp and don\'t match any exclude rule' do
167
167
  @prj[:general, :project_files] = {:include => [%r{d3/.*}, %r{.*\.yaml}], :exclude => [%r{d3/.*2.*}, %r{.*1.*\.rb}], :extensions => []}
168
168
  @list.project_files(false).should =~ %w[d2/f22.yaml f1.yaml d2/f21.yaml]
169
169
  end
170
170
 
171
- it 'should not include duplicate elements' do
171
+ it 'doesn\'t include duplicate elements' do
172
172
  @prj[:general, :project_files] = {:include => [%r{d2/.*}, 'f1.rb'], :exclude => [], :extensions => ['*.rb']}
173
173
  @list.project_files(false).should =~ %w[f1.rb d2/f21.rb d2/f22.rb d2/f21.yaml d2/f22.yaml d2/CHANGELOG d3/f31.rb d3/f32.rb]
174
174
  end
175
175
 
176
- it 'should return a deep copy of the cache object' do
176
+ it 'returns a deep copy of the cache object' do
177
177
  @prj[:general, :project_files] = {:include => [%r{d2/.*}, 'f1.rb'], :exclude => [], :extensions => ['*.rb']}
178
178
  old_cache = @list.instance_variable_get(:@project_files).deep_copy
179
179
  res = @list.project_files(false)
@@ -182,12 +182,12 @@ describe 'Ruber::ProjectFilesList' do
182
182
  @list.instance_variable_get(:@project_files).should == old_cache
183
183
  end
184
184
 
185
- it 'should return full paths if the argument is true' do
185
+ it 'returns full paths if the argument is true' do
186
186
  @prj[:general, :project_files] = {:include => [%r{d2/.*}, 'f1.rb'], :exclude => [], :extensions => ['*.rb']}
187
187
  @list.project_files(true).should =~ %w[f1.rb d2/f21.rb d2/f22.rb d2/f21.yaml d2/f22.yaml d2/CHANGELOG d3/f31.rb d3/f32.rb].map{|i| File.join @dir, i}
188
188
  end
189
189
 
190
- it 'should return the correct list if a file or directory is added or deleted after the file watcher has been created' do
190
+ it 'returns the correct list if a file or directory is added or deleted after the file watcher has been created' do
191
191
  @prj[:general, :project_files] = {:include => [], :exclude => [], :extensions => ['*.rb']}
192
192
  # Experiments show that KDE::DirWatch needs an event loop to work. Since we don't have one running, we'll have to make it emit the 'dirty' signal manually
193
193
  watcher = @list.instance_variable_get(:@watcher)
@@ -213,7 +213,7 @@ describe 'Ruber::ProjectFilesList' do
213
213
  watcher.instance_eval{emit dirty( @dir)}
214
214
  @list.project_files(false).should_not include("f1.rb")
215
215
  end
216
-
216
+
217
217
  end
218
218
 
219
219
  describe 'Ruber::ProjectFilesList#each' do
@@ -344,41 +344,41 @@ describe 'Ruber::ProjectFilesList' do
344
344
  @prj.add_extension :file_lister, @list
345
345
  end
346
346
 
347
- it 'should return true if the argument matches one of the exact include rules' do
347
+ it 'returns true if the argument matches one of the exact include rules' do
348
348
  @prj[:general, :project_files] = {:include => %w[./xyz ./abc ./123], :exclude => [], :extensions => ['*.rb']}
349
349
  @list.file_in_project?(File.join(@prj.project_dir, 'abc')).should be_true
350
350
  end
351
351
 
352
- it 'should return true if the argument matches one of the regexp include rules' do
352
+ it 'returns true if the argument matches one of the regexp include rules' do
353
353
  @prj[:general, :project_files] = {:include => [/a/, /x/], :exclude => [], :extensions => ['*.rb']}
354
354
  @list.file_in_project?(File.join(@prj.project_dir, 'xyz')).should be_true
355
355
  end
356
356
 
357
- it 'should return true if the argument matches one of the include extensions' do
357
+ it 'returns true if the argument matches one of the include extensions' do
358
358
  @prj[:general, :project_files] = {:include => [], :exclude => [], :extensions => ['*.rb', '*.yaml']}
359
359
  @list.file_in_project?(File.join(@prj.project_dir, 'abc.rb')).should be_true
360
360
  end
361
361
 
362
- it 'should return false if the file isn\'t in the project directory' do
362
+ it 'returns false if the file isn\'t in the project directory' do
363
363
  @prj[:general, :project_files] = {:include => %w[xyz abc 123], :exclude => [], :extensions => ['*.rb']}
364
364
  @list.file_in_project?('/usr/abc').should be_false
365
365
  end
366
366
 
367
- it 'should treat the argument as a path relative to the project directory if it isn\'t an absolute path' do
367
+ it 'treats the argument as a path relative to the project directory if it isn\'t an absolute path' do
368
368
  @prj[:general, :project_files] = {:include => %w[xyz abc 123], :exclude => [], :extensions => ['*.rb']}
369
369
  @list.file_in_project?('abc').should be_true
370
370
  end
371
371
 
372
- it 'should return false if the file doesn\'t match any include rule' do
372
+ it 'returns false if the file doesn\'t match any include rule' do
373
373
  @list.file_in_project?(File.join(@prj.project_dir, 'abc.rb')).should be_false
374
374
  end
375
375
 
376
- it 'should return false if the file matches one of the file exclude rules' do
376
+ it 'returns false if the file matches one of the file exclude rules' do
377
377
  @prj[:general, :project_files] = {:include => %w[xyz abc 123], :exclude => ['abc'], :extensions => ['*.rb']}
378
378
  @list.file_in_project?(File.join(@prj.project_dir, 'abc')).should be_false
379
379
  end
380
380
 
381
- it 'should return false if the file matches one of the exclude regexps' do
381
+ it 'returns false if the file matches one of the exclude regexps' do
382
382
  @prj[:general, :project_files] = {:include => [/a/], :exclude => [/a/], :extensions => []}
383
383
  @list.file_in_project?(File.join(@prj.project_dir, 'abc')).should be_false
384
384
  end
@@ -394,6 +394,16 @@ describe 'Ruber::ProjectFilesList' do
394
394
  @list.file_in_project?('xyz/').should be_nil
395
395
  end
396
396
 
397
+ it 'returns false if the path represents a remote URL' do
398
+ @prj[:general, :project_files] = {:include => [], :exclude => [], :extensions => ['*.rb']}
399
+ @list.file_in_project?("http://#{@dir}/abc.xyz.rb").should be_false
400
+ end
401
+
402
+ it 'works normally if the path represents a local url' do
403
+ @prj[:general, :project_files] = {:include => [], :exclude => [], :extensions => ['*.rb']}
404
+ @list.file_in_project?("file://#{@dir}/abc.xyz.rb").should be_true
405
+ end
406
+
397
407
  end
398
408
 
399
409
  end
@@ -326,3 +326,272 @@ describe Qt::Variant, '#to_bool' do
326
326
  end
327
327
 
328
328
  end
329
+
330
+ describe Qt::Layout do
331
+
332
+ it 'includes QtEnumerable' do
333
+ Qt::Layout.ancestors.should include(QtEnumerable)
334
+ end
335
+
336
+ describe '#each' do
337
+
338
+ it 'passes to the block each widget in turn if called with a block' do
339
+ #Since Qt::Layout is an abstract class, we fake calls to count and item_at,
340
+ #which are pure virtual, with mocks
341
+ w = Qt::Widget.new
342
+ layout = Qt::Layout.new w
343
+ w.layout = layout
344
+ widgets = [Qt::PushButton, Qt::VBoxLayout, Qt::CheckBox].map{|c| c.new}
345
+ res = []
346
+ flexmock(layout).should_receive(:count).once.and_return(3)
347
+ flexmock(layout).should_receive(:item_at).with(0).once.and_return(Qt::WidgetItem.new(widgets[0]))
348
+ flexmock(layout).should_receive(:item_at).with(1).once.and_return(widgets[1])
349
+ flexmock(layout).should_receive(:item_at).with(2).once.and_return(Qt::WidgetItem.new(widgets[2]))
350
+ layout.each{|w| res << w}
351
+ res.should == widgets
352
+ end
353
+
354
+ it 'returns an enumerator if no block is given' do
355
+ w = Qt::Widget.new
356
+ layout = Qt::Layout.new w
357
+ w.layout = layout
358
+ widgets = [Qt::PushButton, Qt::VBoxLayout, Qt::CheckBox].map{|c| c.new}
359
+ res = []
360
+ flexmock(layout).should_receive(:count).once.and_return(3)
361
+ flexmock(layout).should_receive(:item_at).with(0).once.and_return(Qt::WidgetItem.new(widgets[0]))
362
+ flexmock(layout).should_receive(:item_at).with(1).once.and_return(widgets[1])
363
+ flexmock(layout).should_receive(:item_at).with(2).once.and_return(Qt::WidgetItem.new(widgets[2]))
364
+ e = layout.each
365
+ e.each{|w| res << w}
366
+ res.should == widgets
367
+ end
368
+
369
+ end
370
+
371
+ end
372
+
373
+ shared_examples_for 'any box layout' do
374
+
375
+ it 'includes QtEnumerable' do
376
+ @layout.class.ancestors.should include(QtEnumerable)
377
+ end
378
+
379
+ it 'has an each method which passes to the block each widget in turn if called with a block' do
380
+ w = Qt::Widget.new
381
+ w.layout = @layout
382
+ widgets = [Qt::PushButton, Qt::VBoxLayout, Qt::CheckBox].map{|c| c.new}
383
+ widgets.each{|w| @layout.send w.is_a?(Qt::Widget) ? :add_widget : :add_layout, w}
384
+ res = []
385
+ @layout.each{|w| res << w}
386
+ res.should == widgets
387
+ end
388
+
389
+ it 'has an each method which returns an enumerator if no block is given' do
390
+ w = Qt::Widget.new
391
+ w.layout = @layout
392
+ widgets = [Qt::PushButton, Qt::VBoxLayout, Qt::CheckBox].map{|c| c.new}
393
+ res = []
394
+ widgets.each{|w| @layout.send w.is_a?(Qt::Widget) ? :add_widget : :add_layout, w}
395
+ e = @layout.each
396
+ e.each{|w| res << w}
397
+ res.should == widgets
398
+ end
399
+
400
+ end
401
+
402
+ describe Qt::BoxLayout do
403
+
404
+ before do
405
+ @layout = Qt::BoxLayout.new(Qt::Horizontal)
406
+ end
407
+
408
+ it_behaves_like 'any box layout'
409
+
410
+ end
411
+
412
+ describe Qt::VBoxLayout do
413
+
414
+ before do
415
+ @layout = Qt::VBoxLayout.new
416
+ end
417
+
418
+ it_behaves_like 'any box layout'
419
+
420
+ end
421
+
422
+ describe Qt::HBoxLayout do
423
+
424
+ before do
425
+ @layout = Qt::HBoxLayout.new
426
+ end
427
+
428
+ it_behaves_like 'any box layout'
429
+
430
+ end
431
+
432
+ describe Qt::StackedLayout do
433
+
434
+ before do
435
+ @layout = Qt::StackedLayout.new
436
+ end
437
+
438
+ it 'includes QtEnumerable' do
439
+ @layout.class.ancestors.should include(QtEnumerable)
440
+ end
441
+
442
+ it 'has an each method which passes to the block each widget in turn if called with a block' do
443
+ w = Qt::Widget.new
444
+ w.layout = @layout
445
+ widgets = [Qt::PushButton, Qt::LineEdit, Qt::CheckBox].map{|c| c.new}
446
+ widgets.each{|w| @layout.add_widget w}
447
+ res = []
448
+ @layout.each{|w| res << w}
449
+ res.should == widgets
450
+ end
451
+
452
+ it 'has an each method which returns an enumerator if no block is given' do
453
+ w = Qt::Widget.new
454
+ w.layout = @layout
455
+ widgets = [Qt::PushButton, Qt::LineEdit, Qt::CheckBox].map{|c| c.new}
456
+ res = []
457
+ widgets.each{|w| @layout.add_widget w}
458
+ e = @layout.each
459
+ e.each{|w| res << w}
460
+ res.should == widgets
461
+ end
462
+
463
+ end
464
+
465
+ describe Qt::FormLayout do
466
+
467
+ before do
468
+ @layout = Qt::FormLayout.new
469
+ end
470
+
471
+ it 'includes QtEnumerable' do
472
+ @layout.class.ancestors.should include(QtEnumerable)
473
+ end
474
+
475
+ it 'has an each method which passes to the block each widget in turn if called with a block' do
476
+ w = Qt::Widget.new
477
+ w.layout = @layout
478
+ widgets = [['l1', Qt::PushButton], ['l2', Qt::LineEdit], ['l3', Qt::CheckBox]].map{|c| [Qt::Label.new(c[0]), c[1].new]}
479
+ widgets.each{|w| @layout.add_row w[0], w[1]}
480
+ res = []
481
+ @layout.each{|w| res << w}
482
+ res.should == widgets.flatten
483
+ end
484
+
485
+ it 'has an each method which returns an enumerator if no block is given' do
486
+ w = Qt::Widget.new
487
+ w.layout = @layout
488
+ widgets = [['l1', Qt::PushButton], ['l2', Qt::LineEdit], ['l3', Qt::CheckBox]].map{|c| [Qt::Label.new(c[0]), c[1].new]}
489
+ widgets.each{|w| @layout.add_row w[0], w[1]}
490
+ res = []
491
+ e = @layout.each
492
+ e.each{|w| res << w}
493
+ res.should == widgets.flatten
494
+ end
495
+
496
+ end
497
+
498
+ describe Qt::GridLayout do
499
+
500
+ before do
501
+ @layout = Qt::GridLayout.new
502
+ end
503
+
504
+ it 'includes QtEnumerable' do
505
+ @layout.class.ancestors.should include(QtEnumerable)
506
+ end
507
+
508
+ it 'has an each method which passes to the block each widget in turn if called with a block' do
509
+ w = Qt::Widget.new
510
+ w.layout = @layout
511
+ widgets = [[Qt::TextEdit, Qt::HBoxLayout], [Qt::Label, Qt::LineEdit], [Qt::VBoxLayout, Qt::CheckBox]].map{|c1, c2| [c1.new, c2.new]}
512
+ add = lambda{|w, r, c|w.is_a?(Qt::Widget) ? @layout.add_widget(w, r, c) : @layout.add_layout(w, r, c) }
513
+ widgets.each_with_index do |w, r|
514
+ add.call w[0], r, 0
515
+ add.call w[1], r, 1
516
+ end
517
+ res = []
518
+ @layout.each{|w| res << w}
519
+ res.should == widgets.flatten
520
+ end
521
+
522
+ it 'has an each method which returns an enumerator if no block is given' do
523
+ w = Qt::Widget.new
524
+ w.layout = @layout
525
+ widgets = [[Qt::TextEdit, Qt::HBoxLayout], [Qt::Label, Qt::LineEdit], [Qt::VBoxLayout, Qt::CheckBox]].map{|c1, c2| [c1.new, c2.new]}
526
+ add = lambda{|w, r, c|w.is_a?(Qt::Widget) ? @layout.add_widget(w, r, c) : @layout.add_layout(w, r, c) }
527
+ widgets.each_with_index do |w, r|
528
+ add.call w[0], r, 0
529
+ add.call w[1], r, 1
530
+ end
531
+ res = []
532
+ e = @layout.each
533
+ e.each{|w| res << w}
534
+ res.should == widgets.flatten
535
+ end
536
+
537
+ it 'passes widgets spanning more than one row or column only once' do
538
+ w = Qt::Widget.new
539
+ w.layout = @layout
540
+ widgets = [[Qt::TextEdit, Qt::HBoxLayout], [Qt::LineEdit], [Qt::VBoxLayout, Qt::CheckBox]].map do |c1, c2|
541
+ c2 ? [c1.new, c2.new] : [c1.new]
542
+ end
543
+ add = lambda{|w, r, c, r1, c1|w.is_a?(Qt::Widget) ? @layout.add_widget(w, r, c, r1, c1) : @layout.add_layout(w, r, c, r1, c1) }
544
+ widgets.each_with_index do |w, r|
545
+ if w.size == 1
546
+ add.call w[0], r, 0, r, 1
547
+ else
548
+ add.call w[0], r, 0, r, 0
549
+ add.call w[1], r, 1, r, 1
550
+ end
551
+ end
552
+ res = []
553
+ @layout.each{|w| res << w}
554
+ res.should == widgets.flatten
555
+ end
556
+
557
+ end
558
+
559
+ describe Qt::Splitter do
560
+
561
+ it 'includes the QtEnumerable module' do
562
+ Qt::Splitter.ancestors.should include(QtEnumerable)
563
+ end
564
+
565
+ describe '#each' do
566
+
567
+ before do
568
+ @splitter = Qt::Splitter.new Qt::Vertical
569
+ end
570
+
571
+ it 'calls the block each widget in the splitter' do
572
+ widgets = [Qt::LineEdit, Qt::PushButton, Qt::Label].map{|cls| cls.new}
573
+ widgets.reverse_each{|w| @splitter.add_widget w}
574
+ res = []
575
+ @splitter.each{|w| res << w}
576
+ res.should == widgets.reverse
577
+ end
578
+
579
+ it 'returns an enumerator if no block is given' do
580
+ widgets = [Qt::LineEdit, Qt::PushButton, Qt::Label].map{|cls| cls.new}
581
+ widgets.reverse_each{|w| @splitter.add_widget w}
582
+ res = []
583
+ enum = @splitter.each
584
+ enum.should be_an(Enumerator)
585
+ enum.each{|w| res << w}
586
+ res.should == widgets.reverse
587
+ end
588
+
589
+ it 'returns self if a block has been given' do
590
+ widgets = [Qt::LineEdit, Qt::PushButton, Qt::Label].map{|cls| cls.new}
591
+ widgets.reverse_each{|w| @splitter.add_widget w}
592
+ @splitter.each{}.should == @splitter
593
+ end
594
+
595
+ end
596
+
597
+ end