ruber 0.0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. data/COPYING +339 -0
  2. data/INSTALL +137 -0
  3. data/LICENSE +8 -0
  4. data/bin/ruber +65 -0
  5. data/data/share/apps/ruber/core_components.yaml +31 -0
  6. data/data/share/apps/ruber/ruberui.rc +109 -0
  7. data/data/share/icons/ruber.png +0 -0
  8. data/data/share/pixmaps/ruby.png +0 -0
  9. data/icons/ruber-16.png +0 -0
  10. data/icons/ruber-32.png +0 -0
  11. data/icons/ruber-48.png +0 -0
  12. data/icons/ruber-8.png +0 -0
  13. data/lib/ruber/application/application.rb +288 -0
  14. data/lib/ruber/application/plugin.yaml +11 -0
  15. data/lib/ruber/component_manager.rb +899 -0
  16. data/lib/ruber/config/config.rb +82 -0
  17. data/lib/ruber/config/plugin.yaml +3 -0
  18. data/lib/ruber/document_project.rb +209 -0
  19. data/lib/ruber/documents/document_list.rb +416 -0
  20. data/lib/ruber/documents/plugin.yaml +4 -0
  21. data/lib/ruber/editor/document.rb +506 -0
  22. data/lib/ruber/editor/editor_view.rb +167 -0
  23. data/lib/ruber/editor/ktexteditor_wrapper.rb +202 -0
  24. data/lib/ruber/exception_widgets.rb +245 -0
  25. data/lib/ruber/external_program_plugin.rb +397 -0
  26. data/lib/ruber/filtered_output_widget.rb +342 -0
  27. data/lib/ruber/gui_states_handler.rb +231 -0
  28. data/lib/ruber/kde_config_option_backend.rb +167 -0
  29. data/lib/ruber/kde_sugar.rb +249 -0
  30. data/lib/ruber/main_window/choose_plugins_dlg.rb +353 -0
  31. data/lib/ruber/main_window/main_window.rb +524 -0
  32. data/lib/ruber/main_window/main_window_actions.rb +537 -0
  33. data/lib/ruber/main_window/main_window_internal.rb +239 -0
  34. data/lib/ruber/main_window/open_file_in_project_dlg.rb +212 -0
  35. data/lib/ruber/main_window/output_color_widget.rb +35 -0
  36. data/lib/ruber/main_window/plugin.yaml +58 -0
  37. data/lib/ruber/main_window/save_modified_files_dlg.rb +89 -0
  38. data/lib/ruber/main_window/status_bar.rb +156 -0
  39. data/lib/ruber/main_window/ui/choose_plugins_widget.rb +90 -0
  40. data/lib/ruber/main_window/ui/choose_plugins_widget.ui +77 -0
  41. data/lib/ruber/main_window/ui/main_window_settings_widget.rb +108 -0
  42. data/lib/ruber/main_window/ui/main_window_settings_widget.ui +89 -0
  43. data/lib/ruber/main_window/ui/new_project_widget.rb +119 -0
  44. data/lib/ruber/main_window/ui/new_project_widget.ui +178 -0
  45. data/lib/ruber/main_window/ui/open_file_in_project_dlg.rb +109 -0
  46. data/lib/ruber/main_window/ui/open_file_in_project_dlg.ui +168 -0
  47. data/lib/ruber/main_window/ui/output_color_widget.rb +241 -0
  48. data/lib/ruber/main_window/ui/output_color_widget.ui +204 -0
  49. data/lib/ruber/main_window/workspace.rb +442 -0
  50. data/lib/ruber/output_widget.rb +1093 -0
  51. data/lib/ruber/plugin.rb +264 -0
  52. data/lib/ruber/plugin_like.rb +589 -0
  53. data/lib/ruber/plugin_specification.rb +106 -0
  54. data/lib/ruber/plugin_specification_reader.rb +451 -0
  55. data/lib/ruber/project.rb +493 -0
  56. data/lib/ruber/project_backend.rb +105 -0
  57. data/lib/ruber/projects/plugin.yaml +11 -0
  58. data/lib/ruber/projects/project_files_list.rb +314 -0
  59. data/lib/ruber/projects/project_files_widget.rb +301 -0
  60. data/lib/ruber/projects/project_list.rb +314 -0
  61. data/lib/ruber/projects/ui/project_files_rule_chooser_widget.rb +74 -0
  62. data/lib/ruber/projects/ui/project_files_rule_chooser_widget.ui +61 -0
  63. data/lib/ruber/projects/ui/project_files_widget.rb +117 -0
  64. data/lib/ruber/projects/ui/project_files_widget.ui +123 -0
  65. data/lib/ruber/qt_sugar.rb +673 -0
  66. data/lib/ruber/settings_container.rb +515 -0
  67. data/lib/ruber/settings_dialog.rb +244 -0
  68. data/lib/ruber/settings_dialog_manager.rb +503 -0
  69. data/lib/ruber/utils.rb +414 -0
  70. data/lib/ruber/yaml_option_backend.rb +159 -0
  71. data/outsider_files +15 -0
  72. data/plugins/autosave/autosave.rb +404 -0
  73. data/plugins/autosave/plugin.yaml +16 -0
  74. data/plugins/autosave/ui/autosave_config_widget.rb +83 -0
  75. data/plugins/autosave/ui/autosave_config_widget.ui +68 -0
  76. data/plugins/command/command.png +0 -0
  77. data/plugins/command/command.rb +74 -0
  78. data/plugins/command/plugin.yaml +11 -0
  79. data/plugins/find_in_files/find_in_files.rb +337 -0
  80. data/plugins/find_in_files/find_in_files_dlg.rb +411 -0
  81. data/plugins/find_in_files/find_in_files_ui.rc +11 -0
  82. data/plugins/find_in_files/find_in_files_widgets.rb +485 -0
  83. data/plugins/find_in_files/plugin.yaml +23 -0
  84. data/plugins/find_in_files/ui/config_widget.rb +58 -0
  85. data/plugins/find_in_files/ui/config_widget.ui +41 -0
  86. data/plugins/find_in_files/ui/find_in_files_widget.rb +260 -0
  87. data/plugins/find_in_files/ui/find_in_files_widget.ui +324 -0
  88. data/plugins/project_browser/plugin.yaml +10 -0
  89. data/plugins/project_browser/project_browser.rb +245 -0
  90. data/plugins/rake/plugin.yaml +39 -0
  91. data/plugins/rake/rake.png +0 -0
  92. data/plugins/rake/rake.rb +567 -0
  93. data/plugins/rake/rake_extension.rb +153 -0
  94. data/plugins/rake/rake_widgets.rb +615 -0
  95. data/plugins/rake/rakeui.rc +27 -0
  96. data/plugins/rake/ui/add_quick_task_widget.rb +71 -0
  97. data/plugins/rake/ui/add_quick_task_widget.ui +59 -0
  98. data/plugins/rake/ui/choose_task_widget.rb +77 -0
  99. data/plugins/rake/ui/choose_task_widget.ui +72 -0
  100. data/plugins/rake/ui/config_widget.rb +127 -0
  101. data/plugins/rake/ui/config_widget.ui +123 -0
  102. data/plugins/rake/ui/project_widget.rb +217 -0
  103. data/plugins/rake/ui/project_widget.ui +246 -0
  104. data/plugins/rspec/plugin.yaml +30 -0
  105. data/plugins/rspec/rspec.png +0 -0
  106. data/plugins/rspec/rspec.rb +945 -0
  107. data/plugins/rspec/rspec.svg +90 -0
  108. data/plugins/rspec/rspecui.rc +20 -0
  109. data/plugins/rspec/ruber_rspec_formatter.rb +312 -0
  110. data/plugins/rspec/ui/rspec_project_widget.rb +170 -0
  111. data/plugins/rspec/ui/rspec_project_widget.ui +193 -0
  112. data/plugins/ruby_development/plugin.yaml +27 -0
  113. data/plugins/ruby_development/ruby_development.png +0 -0
  114. data/plugins/ruby_development/ruby_development.rb +453 -0
  115. data/plugins/ruby_development/ruby_developmentui.rc +19 -0
  116. data/plugins/ruby_development/ui/project_widget.rb +112 -0
  117. data/plugins/ruby_development/ui/project_widget.ui +108 -0
  118. data/plugins/ruby_runner/config_widget.rb +116 -0
  119. data/plugins/ruby_runner/plugin.yaml +26 -0
  120. data/plugins/ruby_runner/project_widget.rb +62 -0
  121. data/plugins/ruby_runner/ruby.png +0 -0
  122. data/plugins/ruby_runner/ruby_interpretersui.rc +26 -0
  123. data/plugins/ruby_runner/ruby_runner.rb +411 -0
  124. data/plugins/ruby_runner/ui/config_widget.rb +92 -0
  125. data/plugins/ruby_runner/ui/config_widget.ui +91 -0
  126. data/plugins/ruby_runner/ui/project_widget.rb +60 -0
  127. data/plugins/ruby_runner/ui/project_widget.ui +48 -0
  128. data/plugins/ruby_runner/ui/ruby_runnner_plugin_option_widget.rb +59 -0
  129. data/plugins/ruby_runner/ui/ruby_runnner_plugin_option_widget.ui +44 -0
  130. data/plugins/state/plugin.yaml +28 -0
  131. data/plugins/state/state.rb +520 -0
  132. data/plugins/state/ui/config_widget.rb +92 -0
  133. data/plugins/state/ui/config_widget.ui +89 -0
  134. data/plugins/syntax_checker/plugin.yaml +18 -0
  135. data/plugins/syntax_checker/syntax_checker.rb +662 -0
  136. data/ruber.desktop +10 -0
  137. data/spec/annotation_model_spec.rb +174 -0
  138. data/spec/common.rb +119 -0
  139. data/spec/component_manager_spec.rb +1259 -0
  140. data/spec/document_list_spec.rb +626 -0
  141. data/spec/document_project_spec.rb +373 -0
  142. data/spec/document_spec.rb +779 -0
  143. data/spec/editor_view_spec.rb +167 -0
  144. data/spec/external_program_plugin_spec.rb +676 -0
  145. data/spec/filtered_output_widget_spec.rb +642 -0
  146. data/spec/gui_states_handler_spec.rb +304 -0
  147. data/spec/kde_config_option_backend_spec.rb +214 -0
  148. data/spec/kde_sugar_spec.rb +101 -0
  149. data/spec/ktexteditor_wrapper_spec.rb +305 -0
  150. data/spec/output_widget_spec.rb +1703 -0
  151. data/spec/plugin_spec.rb +1393 -0
  152. data/spec/plugin_specification_reader_spec.rb +1765 -0
  153. data/spec/plugin_specification_spec.rb +401 -0
  154. data/spec/project_backend_spec.rb +172 -0
  155. data/spec/project_files_list_spec.rb +401 -0
  156. data/spec/project_list_spec.rb +511 -0
  157. data/spec/project_spec.rb +990 -0
  158. data/spec/qt_sugar_spec.rb +328 -0
  159. data/spec/settings_container_spec.rb +617 -0
  160. data/spec/settings_dialog_manager_spec.rb +773 -0
  161. data/spec/settings_dialog_spec.rb +419 -0
  162. data/spec/state_spec.rb +991 -0
  163. data/spec/utils_spec.rb +406 -0
  164. data/spec/workspace_spec.rb +869 -0
  165. data/spec/yaml_option_backend_spec.rb +246 -0
  166. metadata +284 -0
@@ -0,0 +1,642 @@
1
+ require 'spec/common'
2
+
3
+ require 'ruber/filtered_output_widget'
4
+
5
+ describe Ruber::FilteredOutputWidget do
6
+
7
+ it 'inherits from Ruber::OutputWidget' do
8
+ Ruber::FilteredOutputWidget.ancestors.should include(Ruber::OutputWidget)
9
+ end
10
+
11
+ describe ', when created' do
12
+
13
+ it 'can take up to two arguments' do
14
+ lambda{Ruber::FilteredOutputWidget.new}.should_not raise_error
15
+ lambda{Ruber::FilteredOutputWidget.new Qt::Widget.new}.should_not raise_error
16
+ lambda{Ruber::FilteredOutputWidget.new Qt::Widget.new, {}}.should_not raise_error
17
+ end
18
+
19
+ it 'stores the contnet of the :filter optional entry in the @filter_model instance variable, if the :filter entry is given' do
20
+ mod = Qt::SortFilterProxyModel.new
21
+ ow = Ruber::FilteredOutputWidget.new nil, :filter => mod
22
+ ow.instance_variable_get(:@filter_model).should be_the_same_as(mod)
23
+ end
24
+
25
+ it 'takes ownership of the filter model, if the :filter entry is given' do
26
+ mod = Qt::SortFilterProxyModel.new
27
+ ow = Ruber::FilteredOutputWidget.new nil, :filter => mod
28
+ ow.filter_model.parent.should be_the_same_as(ow)
29
+ end
30
+
31
+ it 'creates a new instance of Ruber::FilteredOutputWidget::FilterModel and uses it as model, if the :filter entry isn\'t given' do
32
+ ow = Ruber::FilteredOutputWidget.new
33
+ ow.filter.should be_a(Ruber::FilteredOutputWidget::FilterModel)
34
+ ow.filter.parent.should be_the_same_as(ow)
35
+ end
36
+
37
+ it 'sets the dynamic_sort_filter property of the filter model to true' do
38
+ ow = Ruber::FilteredOutputWidget.new
39
+ ow.filter.dynamic_sort_filter.should be_true
40
+ end
41
+
42
+ it 'associates the model with the filter model' do
43
+ ow = Ruber::FilteredOutputWidget.new
44
+ ow.filter.source_model.should be_the_same_as(ow.model)
45
+ end
46
+
47
+ it 'associates the view with the filter model' do
48
+ ow = Ruber::FilteredOutputWidget.new
49
+ ow.view.model.should be_a(Ruber::FilteredOutputWidget::FilterModel)
50
+ end
51
+
52
+ it 'connects the view\'s selection model\'s selectionChanged signal with its own selection_changed slot' do
53
+ ow = Ruber::FilteredOutputWidget.new
54
+ flexmock(ow).should_receive(:selection_changed).once.with(Qt::ItemSelection, Qt::ItemSelection)
55
+ ow.view.selection_model.instance_eval{emit selectionChanged(Qt::ItemSelection.new, Qt::ItemSelection.new)}
56
+ end
57
+
58
+ it 'creates a KDE::LineEdit below the view and hides it' do
59
+ editor = KDE::LineEdit.new
60
+ flexmock(editor).should_receive(:hide).once
61
+ flexmock(KDE::LineEdit).should_receive(:new).once.with(Ruber::FilteredOutputWidget).and_return editor
62
+ ow = Ruber::FilteredOutputWidget.new
63
+ ow.layout.item_at_position(1,0).widget.should be_the_same_as(editor)
64
+ end
65
+
66
+ it 'overrides the editor\'s keyReleasedEvent method so that it hides the editor itself if the ESC key (without modifiers) is pressed' do
67
+ ow = Ruber::FilteredOutputWidget.new
68
+ ed = ow.instance_variable_get(:@editor)
69
+ flexmock(ed).should_receive(:hide).once
70
+ ev = Qt::KeyEvent.new Qt::KeyEvent::KeyRelease, Qt::Key_Escape, 0
71
+ ed.send :keyReleaseEvent, ev
72
+ ev = Qt::KeyEvent.new Qt::KeyEvent::KeyRelease, Qt::Key_A, 0, 'A'
73
+ ed.send :keyReleaseEvent, ev
74
+ mods = [
75
+ Qt::ControlModifier,
76
+ Qt::ShiftModifier,
77
+ Qt::AltModifier,
78
+ Qt::MetaModifier,
79
+ Qt::ControlModifier | Qt::ShiftModifier
80
+ ]
81
+ mods.each do |m|
82
+ ev = Qt::KeyEvent.new Qt::KeyEvent::KeyRelease, Qt::Key_Escape, m.to_i
83
+ ed.send :keyReleaseEvent, ev
84
+ end
85
+ end
86
+
87
+ it 'gives a completion object to the editor' do
88
+ ow = Ruber::FilteredOutputWidget.new
89
+ ow.instance_variable_get(:@editor).completion_object.should be_a(KDE::Completion)
90
+ end
91
+
92
+ it 'connects the editor\'s returnPressed(QString) signal with its own "create_filter_from_editor()" slot' do
93
+ ow = Ruber::FilteredOutputWidget.new
94
+ flexmock(ow).should_receive(:create_filter_from_editor).once
95
+ ow.instance_variable_get(:@editor).instance_eval{emit returnPressed('xyz')}
96
+ end
97
+
98
+ it 'adds the "Create Filter", "Ignore Filter" and "Clear Filter" entries to the action list, before the last separator' do
99
+ ow = Ruber::FilteredOutputWidget.new
100
+ ow.instance_variable_get(:@action_list).should == ['copy', 'copy_selected', nil, 'create_filter', 'ignore_filter', 'clear_filter', nil, 'clear']
101
+ end
102
+
103
+ it 'adds the "copy" and "clear_filter" actions to the actions hash' do
104
+ ow = Ruber::FilteredOutputWidget.new
105
+ hash = ow.instance_variable_get :@actions
106
+ hash['create_filter'].should be_a(KDE::Action)
107
+ hash['clear_filter'].should be_a(KDE::Action)
108
+ end
109
+
110
+ it 'adds a toggle "ignore_filter" action to the actions hash' do
111
+ ow = Ruber::FilteredOutputWidget.new
112
+ hash = ow.instance_variable_get :@actions
113
+ hash['ignore_filter'].should be_a(KDE::ToggleAction)
114
+ end
115
+
116
+ it 'connects the "create_filter" action with the show_editor slot' do
117
+ ow = Ruber::FilteredOutputWidget.new
118
+ flexmock(ow).should_receive(:show_editor).once
119
+ ow.instance_variable_get(:@actions)['create_filter'].instance_eval{emit triggered}
120
+ end
121
+
122
+ it 'connects the "clear_filter" action with the clear_filter slot' do
123
+ ow = Ruber::FilteredOutputWidget.new
124
+ flexmock(ow).should_receive(:clear_filter).once
125
+ ow.instance_variable_get(:@actions)['clear_filter'].instance_eval{emit triggered}
126
+ end
127
+
128
+ it 'connects the "ignore_filter" action\'s toggled(bool) signal with the ignore_filter(bool) slot' do
129
+ ow = Ruber::FilteredOutputWidget.new
130
+ flexmock(ow).should_receive(:ignore_filter).once.with(false)
131
+ ow.instance_variable_get(:@actions)['ignore_filter'].instance_eval{emit toggled(false)}
132
+ end
133
+
134
+ it 'creates a gui state handler for the clear_filter action which returns true if the no_filter state is false and false if the no_filter state is true' do
135
+ ow = Ruber::FilteredOutputWidget.new
136
+ handlers = ow.instance_variable_get(:@gui_state_handler_handlers)
137
+ handlers['no_filter'].find{|h| h.action.object_name == 'clear_filter'}.handler.call('no_filter' => true).should be_false
138
+ handlers['no_filter'].find{|h| h.action.object_name == 'clear_filter'}.handler.call('no_filter' => false).should be_true
139
+ end
140
+
141
+ it 'creates a gui state handler for the ignore_filter action which returns true if the no_filter state is false and false if the no_filter state is true' do
142
+ ow = Ruber::FilteredOutputWidget.new
143
+ handlers = ow.instance_variable_get(:@gui_state_handler_handlers)
144
+ handlers['no_filter'].find{|h| h.action.object_name == 'ignore_filter'}.handler.call('no_filter' => true).should be_false
145
+ handlers['no_filter'].find{|h| h.action.object_name == 'ignore_filter'}.handler.call('no_filter' => false).should be_true
146
+ end
147
+
148
+ it 'sets the "no_filter" gui state to true' do
149
+ ow = Ruber::FilteredOutputWidget.new
150
+ ow.gui_state('no_filter').should be_true
151
+ end
152
+
153
+ it 'disconnects the do_auto_scroll signal from the model and connects it to the filter model' do
154
+ ow = Ruber::FilteredOutputWidget.new
155
+ flexmock(ow).should_receive(:do_auto_scroll).once
156
+ ow.model.append_row Qt::StandardItem.new('x')
157
+ ow.filter.source_model = nil
158
+ ow.model.append_row Qt::StandardItem.new('y')
159
+ end
160
+
161
+ end
162
+
163
+ describe '#show_editor' do
164
+
165
+ before do
166
+ @ow = Ruber::FilteredOutputWidget.new
167
+ @ed = @ow.instance_variable_get(:@editor)
168
+ end
169
+
170
+ it 'shows the editor' do
171
+ flexmock(@ed).should_receive(:show).once
172
+ @ow.send :show_editor
173
+ end
174
+
175
+ it 'gives focus to the editor' do
176
+ flexmock(@ed).should_receive(:set_focus).once
177
+ @ow.send :show_editor
178
+ end
179
+
180
+ end
181
+
182
+ describe '#create_filter_from_editor' do
183
+
184
+ before do
185
+ @ow = Ruber::FilteredOutputWidget.new
186
+ @ed = @ow.instance_variable_get(:@editor)
187
+ @ed.text = 'xyz'
188
+ end
189
+
190
+ describe ', when the editor is not empty' do
191
+
192
+ it 'adds the text in the editor widget to the completion object' do
193
+ @ow.send :create_filter_from_editor
194
+ @ed.completion_object.items[0].should == 'xyz'
195
+ @ed.text = 'abc'
196
+ @ow.send :create_filter_from_editor
197
+ @ed.completion_object.items.should == %w[xyz abc]
198
+ end
199
+
200
+ it 'doesn\'t add an existing item' do
201
+ @ow.send :create_filter_from_editor
202
+ @ow.send :create_filter_from_editor
203
+ @ed.completion_object.items.size.should == 1
204
+ end
205
+
206
+ it 'passes the text in the editor to the filter_reg_exp= method of the filter model' do
207
+ flexmock(@ow.filter).should_receive(:filter_reg_exp=).once.with('xyz')
208
+ @ow.send :create_filter_from_editor
209
+ end
210
+
211
+ it 'sets the "no_filter" gui state to false' do
212
+ @ow.send :create_filter_from_editor
213
+ @ow.gui_state('no_filter').should be_false
214
+ end
215
+
216
+ it 'doesn\'t call the "clear_filter" method' do
217
+ flexmock(@ow).should_receive(:clear_filter).never
218
+ @ow.send :create_filter_from_editor
219
+ end
220
+
221
+ end
222
+
223
+ describe ', when the editor is empty' do
224
+
225
+ before do
226
+ @ed.clear
227
+ end
228
+
229
+ it 'doesn\'t add entries to the editor\'s completion object' do
230
+ @ed.text = 'xyz'
231
+ @ow.send :create_filter_from_editor
232
+ @ed.clear
233
+ @ow.send :create_filter_from_editor
234
+ @ed.completion_object.items.should == ['xyz']
235
+ end
236
+
237
+ it 'calls the "clear_filter" method' do
238
+ flexmock(@ow).should_receive(:clear_filter).once
239
+ @ow.send :create_filter_from_editor
240
+ end
241
+
242
+ it 'doesn\'t call the filter model\'s filter_reg_exp= method' do
243
+ flexmock(@ow).should_receive(:clear_filter)
244
+ flexmock(@ow.filter).should_receive(:filter_reg_exp=).never
245
+ @ow.send :create_filter_from_editor
246
+ end
247
+
248
+ end
249
+
250
+ it 'hides the editor' do
251
+ flexmock(@ed).should_receive(:hide).twice
252
+ @ow.send :create_filter_from_editor
253
+ @ed.clear
254
+ @ow.send :create_filter_from_editor
255
+ end
256
+
257
+ end
258
+
259
+ describe '#clear_filter' do
260
+
261
+ before do
262
+ @ow = Ruber::FilteredOutputWidget.new
263
+ end
264
+
265
+ it 'calls the filter model\'s filter_reg_exp= method passing it an empty string' do
266
+ flexmock(@ow.filter).should_receive(:filter_reg_exp=).once.with('')
267
+ @ow.send :clear_filter
268
+ end
269
+
270
+ it 'sets the "no_filter" gui state to true' do
271
+ @ow.set_state 'no_filter', false
272
+ @ow.send :clear_filter
273
+ @ow.gui_state('no_filter').should be_true
274
+ end
275
+
276
+ end
277
+
278
+ describe '#toggle_ignore_filter' do
279
+
280
+ it 'calls the ignore_filter= method of the filter model passing the argument' do
281
+ ow = Ruber::FilteredOutputWidget.new
282
+ flexmock(ow.filter).should_receive(:ignore_filter=).once.with true
283
+ flexmock(ow.filter).should_receive(:ignore_filter=).once.with false
284
+ ow.send :ignore_filter, true
285
+ ow.send :ignore_filter, false
286
+ end
287
+
288
+ end
289
+
290
+ describe '#copy' do
291
+
292
+ before do
293
+ @ow = Ruber::FilteredOutputWidget.new
294
+ @mod = @ow.model
295
+ @filter = @ow.filter
296
+ def @filter.filterAcceptsRow r, parent
297
+ return true if parent.valid?
298
+ idx = source_model.index(r, 0)
299
+ idx.data.to_int < 4
300
+ end
301
+ 5.times{|i| @mod.append_row Qt::StandardItem.new(i.to_s)}
302
+ @filter.invalidate
303
+ end
304
+
305
+ it 'calls the text_for_clipboard method passing it an array containing all the indexes in the filter model, but referred to the source model' do
306
+ c1 = Qt::StandardItem.new 'c1'
307
+ c2 = Qt::StandardItem.new 'c2'
308
+ c3 = Qt::StandardItem.new 'c3'
309
+ it = @mod.item(3,0)
310
+ # Somehow, autoscrolling messes up the indexes
311
+ @ow.with_auto_scrolling(false) do
312
+ c1.append_row c3
313
+ it.append_row c1
314
+ it.append_row c2
315
+ end
316
+ exp = [@mod.index(0,0), @mod.index(1,0), @mod.index(2,0), it.index, c1.index, c3.index, c2.index]
317
+ flexmock(@ow).should_receive(:text_for_clipboard).once.with(exp)
318
+ @ow.send :copy
319
+ end
320
+
321
+ it 'inserts the value returned by text_for_clipboard in the clipboard' do
322
+ text = random_string
323
+ flexmock(@ow).should_receive(:text_for_clipboard).once.with(4.times.map{|i| @mod.index(i,0)}).and_return text
324
+ @ow.send :copy
325
+ KDE::Application.clipboard.text.should == text
326
+ end
327
+
328
+ end
329
+
330
+ describe '#copy_selected' do
331
+
332
+ before do
333
+ @ow = Ruber::FilteredOutputWidget.new
334
+ @mod = @ow.model
335
+ @filter = @ow.filter
336
+ 5.times{|i| @mod.append_row Qt::StandardItem.new(i.to_s)}
337
+ @mod.append_column 5.times.map{|i| Qt::StandardItem.new (i+5).to_s}
338
+ def @filter.filterAcceptsRow r, parent
339
+ return true if parent.valid?
340
+ idx = source_model.index(r, 0)
341
+ idx.data.to_int < 4
342
+ end
343
+ @filter.invalidate
344
+ sm = @ow.view.selection_model
345
+ @exp = [[1,0], [2,1], [3,1]].map{|i, j| @mod.index i, j}
346
+ @exp.each{|i| sm.select @filter.map_from_source(i), Qt::ItemSelectionModel::Select}
347
+ end
348
+
349
+ it 'calls the text_for_clipboard method passing the list of selected items in the source model as argument' do
350
+ flexmock(@ow).should_receive(:text_for_clipboard).once.with @exp
351
+ @ow.send :copy_selected
352
+ end
353
+
354
+ it 'inserts the value returned by text_for_clipboard in the clipboard' do
355
+ text = random_string
356
+ flexmock(@ow).should_receive(:text_for_clipboard).once.with(@exp).and_return text
357
+ @ow.send :copy_selected
358
+ KDE::Application.clipboard.text.should == text
359
+ end
360
+
361
+ end
362
+
363
+ describe '#scroll_to' do
364
+
365
+ before do
366
+ @ow = Ruber::FilteredOutputWidget.new
367
+ @mod = @ow.model
368
+ @filter = @ow.filter
369
+ def @filter.filterAcceptsRow row, parent
370
+ idx = source_model.index(row, 0)
371
+ idx.data.to_int % 2 != 0
372
+ end
373
+ 10.times{|i| @mod.append_row Qt::StandardItem.new(i.to_s)}
374
+ @filter.invalidate
375
+ end
376
+
377
+ describe ', when called with a positive integer' do
378
+
379
+ it 'it scrolls the view so that the row with the argument as index (in the filter model) is visible' do
380
+ idx = @filter.index(3, 0)
381
+ flexmock(@ow.view).should_receive(:scroll_to).with(idx).once
382
+ @ow.scroll_to 3
383
+ end
384
+
385
+ it 'scrolls to the last item if the argument is greater than the index of the last row of the filter model' do
386
+ idx = @filter.index(@filter.row_count - 1, 0)
387
+ flexmock(@ow.view).should_receive(:scroll_to).with(idx).once
388
+ @ow.scroll_to @filter.row_count + 3
389
+ end
390
+
391
+ end
392
+
393
+ describe ', when called with a negative integer' do
394
+
395
+ it 'scrolls the view so that the row with index the argument (in the filter model), counting from below, is visible' do
396
+ idx = @filter.index(3, 0)
397
+ flexmock(@ow.view).should_receive(:scroll_to).with(idx).once
398
+ @ow.scroll_to -2
399
+ end
400
+
401
+ it 'scrolls to the first item if the absolute value of the argument is greater than the index of the last row - 1 (in the filter model)' do
402
+ idx = @filter.index(0, 0)
403
+ flexmock(@ow.view).should_receive(:scroll_to).with(idx).once
404
+ @ow.scroll_to -8
405
+ end
406
+
407
+ end
408
+
409
+ describe ', when called with a Qt::ModelIndex' do
410
+
411
+ it 'converts the index to the filter model, if it refers to the source model' do
412
+ src_idx = @mod.index(1,0)
413
+ idx = @filter.map_from_source src_idx
414
+ flexmock(@filter).should_receive(:map_from_source).once.with(src_idx).and_return idx
415
+ flexmock(@ow.view).should_receive(:scroll_to).with(idx).once
416
+ @ow.scroll_to src_idx
417
+ end
418
+
419
+ it 'doesn\'t attempt to convert the index if it already refers to the filter model' do
420
+ idx = @filter.index(2,0)
421
+ flexmock(@filter).should_receive(:map_from_source).never
422
+ @ow.scroll_to idx
423
+ end
424
+
425
+ it 'scrolls the view so that the item corresponding to the index is visible' do
426
+ @mod.append_column(5.times.map{|i| Qt::StandardItem.new (2*i).to_s})
427
+ @filter.invalidate
428
+ idx = @filter.map_from_source @mod.index(3,1)
429
+ flexmock(@ow.view).should_receive(:scroll_to).with(idx).once
430
+ @ow.scroll_to idx
431
+ end
432
+
433
+ it 'scrolls to the last element of the filter model if the index is invalid' do
434
+ idx = @filter.index(@filter.row_count - 1,0)
435
+ flexmock(@ow.view).should_receive(:scroll_to).with(idx).once
436
+ @ow.scroll_to Qt::ModelIndex.new
437
+ end
438
+
439
+ end
440
+
441
+ describe ', when called with nil' do
442
+
443
+ it 'scrolls to the last element of the filter model' do
444
+ idx = @filter.index(@filter.row_count - 1,0)
445
+ flexmock(@ow.view).should_receive(:scroll_to).with(idx).once
446
+ @ow.scroll_to nil
447
+ end
448
+
449
+ end
450
+
451
+ end
452
+
453
+ describe '#maybe_open_file' do
454
+
455
+ before do
456
+ unless Ruber.constants.include? :Application
457
+ Ruber::Application = flexmock(:keyboard_modifiers => 0)
458
+ end
459
+ @ow = Ruber::FilteredOutputWidget.new
460
+ @mod = @ow.model
461
+ @filter = @ow.filter
462
+ @mod.append_row Qt::StandardItem.new('x')
463
+ end
464
+
465
+ it 'converts the index from the filter model to the source model before calling super' do
466
+ flexmock(@ow).should_receive(:find_filename_in_index).with(FlexMock.on{|i| i.model.equal?(@mod) and i.data.to_string == 'x'}).once
467
+ @ow.send :maybe_open_file, @filter.index(0,0)
468
+ end
469
+
470
+ it 'doesn\'t attempt to convert the index if it already refers to the source model' do
471
+ flexmock(@filter).should_receive(:map_to_source).never
472
+ flexmock(@ow).should_receive(:find_filename_in_index).with(FlexMock.on{|i| i.model.equal?(@mod) and i.data.to_string == 'x'}).once
473
+ @ow.send :maybe_open_file, @mod.index(0,0)
474
+ end
475
+
476
+ after do
477
+ Ruber.send :remove_const, :Application unless Ruber::Application.is_a?(KDE::Application)
478
+ end
479
+
480
+ end
481
+
482
+
483
+ end
484
+
485
+ describe Ruber::FilteredOutputWidget::FilterModel do
486
+
487
+ it 'inherits Qt::SortFilterProxyModel' do
488
+ Ruber::FilteredOutputWidget::FilterModel.ancestors.should include(Qt::SortFilterProxyModel)
489
+ end
490
+
491
+ describe ', when created' do
492
+
493
+ it 'takes up to two arguments' do
494
+ lambda{Ruber::FilteredOutputWidget::FilterModel.new}.should_not raise_error
495
+ lambda{Ruber::FilteredOutputWidget::FilterModel.new Qt::Widget.new}.should_not raise_error
496
+ lambda{Ruber::FilteredOutputWidget::FilterModel.new nil, :top_level}.should_not raise_error
497
+ end
498
+
499
+ it 'stores the second argument passed to the constructor in the @exclude instance variable' do
500
+ mod = Ruber::FilteredOutputWidget::FilterModel.new nil, :top_level
501
+ mod.exclude.should == :top_level
502
+ end
503
+
504
+ it 'doesn\'t ignore the filter' do
505
+ mod = Ruber::FilteredOutputWidget::FilterModel.new nil, :top_level
506
+ mod.filter_ignored?.should be_false
507
+ end
508
+
509
+ end
510
+
511
+ describe '#ignore_filter=' do
512
+
513
+ before do
514
+ @mod = Ruber::FilteredOutputWidget::FilterModel.new
515
+ end
516
+
517
+ it 'sets the @ignore_filter instance variable to the argument' do
518
+ @mod.ignore_filter = true
519
+ @mod.filter_ignored?.should be_true
520
+ end
521
+
522
+ it 'invalidates the model' do
523
+ flexmock(@mod).should_receive(:invalidate).once
524
+ @mod.ignore_filter = true
525
+ end
526
+
527
+ end
528
+
529
+ describe '#filter_reg_exp=' do
530
+
531
+ before do
532
+ @mod = Ruber::FilteredOutputWidget::FilterModel.new
533
+ end
534
+
535
+ it 'sets the filter reg exp to the argument' do
536
+ @mod.filter_reg_exp = 'a.*'
537
+ @mod.filter_reg_exp.should == Qt::RegExp.new('a.*')
538
+ end
539
+
540
+ it 'emits the filter_changed(QString) signal' do
541
+ m = flexmock{|mk| mk.should_receive(:test).once.with('a.*')}
542
+ @mod.connect(SIGNAL('filter_changed(QString)')){|s| m.test s}
543
+ @mod.filter_reg_exp = 'a.*'
544
+ end
545
+
546
+ end
547
+
548
+ describe '#filterAcceptsRow' do
549
+
550
+ before do
551
+ @source = Qt::StandardItemModel.new
552
+ 5.times{|i| @source.append_row Qt::StandardItem.new(i.to_s)}
553
+ @mod = Ruber::FilteredOutputWidget::FilterModel.new
554
+ @mod.source_model = @source
555
+ end
556
+
557
+ it 'always returns true if the filter is ignored' do
558
+ @mod.ignore_filter = true
559
+ @mod.filter_reg_exp = '[12]'
560
+ 5.times do |i|
561
+ @mod.send(:filterAcceptsRow, i, Qt::ModelIndex.new).should be_true
562
+ end
563
+ end
564
+
565
+ it 'always returns true if calling the exclude_from_filtering? method with the given row and parent returns true' do
566
+ 5.times{|i| flexmock(@mod).should_receive(:exclude_from_filtering?).once.with(i, Qt::ModelIndex).and_return(true)}
567
+ @mod.filter_reg_exp = '[12]'
568
+ 5.times do |i|
569
+ @mod.send(:filterAcceptsRow, i, Qt::ModelIndex.new).should be_true
570
+ end
571
+ end
572
+
573
+ it 'filters any row for which exclude_from_filtering? returns false according to the regexp' do
574
+ @mod.filter_reg_exp = '[12]'
575
+ flexmock(@mod).should_receive(:exclude_from_filtering?).once.with(0, Qt::ModelIndex).and_return(true)
576
+ flexmock(@mod).should_receive(:exclude_from_filtering?).and_return(false)
577
+ @mod.send(:filterAcceptsRow, 0, Qt::ModelIndex.new).should be_true
578
+ @mod.send(:filterAcceptsRow, 1, Qt::ModelIndex.new).should be_true
579
+ @mod.send(:filterAcceptsRow, 2, Qt::ModelIndex.new).should be_true
580
+ @mod.send(:filterAcceptsRow, 3, Qt::ModelIndex.new).should be_false
581
+ @mod.send(:filterAcceptsRow, 4, Qt::ModelIndex.new).should be_false
582
+ end
583
+
584
+ end
585
+
586
+ describe '#exclude=' do
587
+
588
+ before do
589
+ @source = Qt::StandardItemModel.new
590
+ 5.times{|i| @source.append_row Qt::StandardItem.new(i.to_s)}
591
+ @source.item(0,0).append_row Qt::StandardItem.new('c')
592
+ @mod = Ruber::FilteredOutputWidget::FilterModel.new
593
+ @mod.source_model = @source
594
+ end
595
+
596
+ it 'replaces the @exclude instance variable with the argument' do
597
+ @mod.instance_variable_set :@exclude, :children
598
+ @mod.exclude = :toplevel
599
+ @mod.instance_variable_get(:@exclude).should == :toplevel
600
+ end
601
+
602
+ it 'invalidates the filter' do
603
+ flexmock(@mod).should_receive(:invalidate_filter).once
604
+ @mod.exclude = :toplevel
605
+ end
606
+
607
+ end
608
+
609
+ describe '#exclude_from_filtering?' do
610
+
611
+ before do
612
+ @source = Qt::StandardItemModel.new
613
+ 5.times{|i| @source.append_row Qt::StandardItem.new(i.to_s)}
614
+ @source.item(0,0).append_row Qt::StandardItem.new('c')
615
+ @mod = Ruber::FilteredOutputWidget::FilterModel.new
616
+ @mod.source_model = @source
617
+ end
618
+
619
+ it 'returns false for child items and true for toplevel items if the @exclude instance variable is :toplevel' do
620
+ @mod.exclude = :toplevel
621
+ @mod.send(:exclude_from_filtering?, 0, Qt::ModelIndex.new).should be_true
622
+ @mod.send(:exclude_from_filtering?, 0, @source.index(0,0)).should be_false
623
+ end
624
+
625
+ it 'returns true for child items and false for toplevel items if the @exclude instance variable is :children' do
626
+ @mod.exclude = :children
627
+ @mod.send(:exclude_from_filtering?, 0, Qt::ModelIndex.new).should be_false
628
+ @mod.send(:exclude_from_filtering?, 0, @source.index(0,0)).should be_true
629
+ end
630
+
631
+ it 'always returns false for other values of the @exclude instance variable' do
632
+ @mod.exclude = :nil
633
+ @mod.send(:exclude_from_filtering?, 0, Qt::ModelIndex.new).should be_false
634
+ @mod.send(:exclude_from_filtering?, 0, @source.index(0,0)).should be_false
635
+ @mod.exclude = :x
636
+ @mod.send(:exclude_from_filtering?, 0, Qt::ModelIndex.new).should be_false
637
+ @mod.send(:exclude_from_filtering?, 0, @source.index(0,0)).should be_false
638
+ end
639
+
640
+ end
641
+
642
+ end