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.
- data/COPYING +339 -0
- data/INSTALL +137 -0
- data/LICENSE +8 -0
- data/bin/ruber +65 -0
- data/data/share/apps/ruber/core_components.yaml +31 -0
- data/data/share/apps/ruber/ruberui.rc +109 -0
- data/data/share/icons/ruber.png +0 -0
- data/data/share/pixmaps/ruby.png +0 -0
- data/icons/ruber-16.png +0 -0
- data/icons/ruber-32.png +0 -0
- data/icons/ruber-48.png +0 -0
- data/icons/ruber-8.png +0 -0
- data/lib/ruber/application/application.rb +288 -0
- data/lib/ruber/application/plugin.yaml +11 -0
- data/lib/ruber/component_manager.rb +899 -0
- data/lib/ruber/config/config.rb +82 -0
- data/lib/ruber/config/plugin.yaml +3 -0
- data/lib/ruber/document_project.rb +209 -0
- data/lib/ruber/documents/document_list.rb +416 -0
- data/lib/ruber/documents/plugin.yaml +4 -0
- data/lib/ruber/editor/document.rb +506 -0
- data/lib/ruber/editor/editor_view.rb +167 -0
- data/lib/ruber/editor/ktexteditor_wrapper.rb +202 -0
- data/lib/ruber/exception_widgets.rb +245 -0
- data/lib/ruber/external_program_plugin.rb +397 -0
- data/lib/ruber/filtered_output_widget.rb +342 -0
- data/lib/ruber/gui_states_handler.rb +231 -0
- data/lib/ruber/kde_config_option_backend.rb +167 -0
- data/lib/ruber/kde_sugar.rb +249 -0
- data/lib/ruber/main_window/choose_plugins_dlg.rb +353 -0
- data/lib/ruber/main_window/main_window.rb +524 -0
- data/lib/ruber/main_window/main_window_actions.rb +537 -0
- data/lib/ruber/main_window/main_window_internal.rb +239 -0
- data/lib/ruber/main_window/open_file_in_project_dlg.rb +212 -0
- data/lib/ruber/main_window/output_color_widget.rb +35 -0
- data/lib/ruber/main_window/plugin.yaml +58 -0
- data/lib/ruber/main_window/save_modified_files_dlg.rb +89 -0
- data/lib/ruber/main_window/status_bar.rb +156 -0
- data/lib/ruber/main_window/ui/choose_plugins_widget.rb +90 -0
- data/lib/ruber/main_window/ui/choose_plugins_widget.ui +77 -0
- data/lib/ruber/main_window/ui/main_window_settings_widget.rb +108 -0
- data/lib/ruber/main_window/ui/main_window_settings_widget.ui +89 -0
- data/lib/ruber/main_window/ui/new_project_widget.rb +119 -0
- data/lib/ruber/main_window/ui/new_project_widget.ui +178 -0
- data/lib/ruber/main_window/ui/open_file_in_project_dlg.rb +109 -0
- data/lib/ruber/main_window/ui/open_file_in_project_dlg.ui +168 -0
- data/lib/ruber/main_window/ui/output_color_widget.rb +241 -0
- data/lib/ruber/main_window/ui/output_color_widget.ui +204 -0
- data/lib/ruber/main_window/workspace.rb +442 -0
- data/lib/ruber/output_widget.rb +1093 -0
- data/lib/ruber/plugin.rb +264 -0
- data/lib/ruber/plugin_like.rb +589 -0
- data/lib/ruber/plugin_specification.rb +106 -0
- data/lib/ruber/plugin_specification_reader.rb +451 -0
- data/lib/ruber/project.rb +493 -0
- data/lib/ruber/project_backend.rb +105 -0
- data/lib/ruber/projects/plugin.yaml +11 -0
- data/lib/ruber/projects/project_files_list.rb +314 -0
- data/lib/ruber/projects/project_files_widget.rb +301 -0
- data/lib/ruber/projects/project_list.rb +314 -0
- data/lib/ruber/projects/ui/project_files_rule_chooser_widget.rb +74 -0
- data/lib/ruber/projects/ui/project_files_rule_chooser_widget.ui +61 -0
- data/lib/ruber/projects/ui/project_files_widget.rb +117 -0
- data/lib/ruber/projects/ui/project_files_widget.ui +123 -0
- data/lib/ruber/qt_sugar.rb +673 -0
- data/lib/ruber/settings_container.rb +515 -0
- data/lib/ruber/settings_dialog.rb +244 -0
- data/lib/ruber/settings_dialog_manager.rb +503 -0
- data/lib/ruber/utils.rb +414 -0
- data/lib/ruber/yaml_option_backend.rb +159 -0
- data/outsider_files +15 -0
- data/plugins/autosave/autosave.rb +404 -0
- data/plugins/autosave/plugin.yaml +16 -0
- data/plugins/autosave/ui/autosave_config_widget.rb +83 -0
- data/plugins/autosave/ui/autosave_config_widget.ui +68 -0
- data/plugins/command/command.png +0 -0
- data/plugins/command/command.rb +74 -0
- data/plugins/command/plugin.yaml +11 -0
- data/plugins/find_in_files/find_in_files.rb +337 -0
- data/plugins/find_in_files/find_in_files_dlg.rb +411 -0
- data/plugins/find_in_files/find_in_files_ui.rc +11 -0
- data/plugins/find_in_files/find_in_files_widgets.rb +485 -0
- data/plugins/find_in_files/plugin.yaml +23 -0
- data/plugins/find_in_files/ui/config_widget.rb +58 -0
- data/plugins/find_in_files/ui/config_widget.ui +41 -0
- data/plugins/find_in_files/ui/find_in_files_widget.rb +260 -0
- data/plugins/find_in_files/ui/find_in_files_widget.ui +324 -0
- data/plugins/project_browser/plugin.yaml +10 -0
- data/plugins/project_browser/project_browser.rb +245 -0
- data/plugins/rake/plugin.yaml +39 -0
- data/plugins/rake/rake.png +0 -0
- data/plugins/rake/rake.rb +567 -0
- data/plugins/rake/rake_extension.rb +153 -0
- data/plugins/rake/rake_widgets.rb +615 -0
- data/plugins/rake/rakeui.rc +27 -0
- data/plugins/rake/ui/add_quick_task_widget.rb +71 -0
- data/plugins/rake/ui/add_quick_task_widget.ui +59 -0
- data/plugins/rake/ui/choose_task_widget.rb +77 -0
- data/plugins/rake/ui/choose_task_widget.ui +72 -0
- data/plugins/rake/ui/config_widget.rb +127 -0
- data/plugins/rake/ui/config_widget.ui +123 -0
- data/plugins/rake/ui/project_widget.rb +217 -0
- data/plugins/rake/ui/project_widget.ui +246 -0
- data/plugins/rspec/plugin.yaml +30 -0
- data/plugins/rspec/rspec.png +0 -0
- data/plugins/rspec/rspec.rb +945 -0
- data/plugins/rspec/rspec.svg +90 -0
- data/plugins/rspec/rspecui.rc +20 -0
- data/plugins/rspec/ruber_rspec_formatter.rb +312 -0
- data/plugins/rspec/ui/rspec_project_widget.rb +170 -0
- data/plugins/rspec/ui/rspec_project_widget.ui +193 -0
- data/plugins/ruby_development/plugin.yaml +27 -0
- data/plugins/ruby_development/ruby_development.png +0 -0
- data/plugins/ruby_development/ruby_development.rb +453 -0
- data/plugins/ruby_development/ruby_developmentui.rc +19 -0
- data/plugins/ruby_development/ui/project_widget.rb +112 -0
- data/plugins/ruby_development/ui/project_widget.ui +108 -0
- data/plugins/ruby_runner/config_widget.rb +116 -0
- data/plugins/ruby_runner/plugin.yaml +26 -0
- data/plugins/ruby_runner/project_widget.rb +62 -0
- data/plugins/ruby_runner/ruby.png +0 -0
- data/plugins/ruby_runner/ruby_interpretersui.rc +26 -0
- data/plugins/ruby_runner/ruby_runner.rb +411 -0
- data/plugins/ruby_runner/ui/config_widget.rb +92 -0
- data/plugins/ruby_runner/ui/config_widget.ui +91 -0
- data/plugins/ruby_runner/ui/project_widget.rb +60 -0
- data/plugins/ruby_runner/ui/project_widget.ui +48 -0
- data/plugins/ruby_runner/ui/ruby_runnner_plugin_option_widget.rb +59 -0
- data/plugins/ruby_runner/ui/ruby_runnner_plugin_option_widget.ui +44 -0
- data/plugins/state/plugin.yaml +28 -0
- data/plugins/state/state.rb +520 -0
- data/plugins/state/ui/config_widget.rb +92 -0
- data/plugins/state/ui/config_widget.ui +89 -0
- data/plugins/syntax_checker/plugin.yaml +18 -0
- data/plugins/syntax_checker/syntax_checker.rb +662 -0
- data/ruber.desktop +10 -0
- data/spec/annotation_model_spec.rb +174 -0
- data/spec/common.rb +119 -0
- data/spec/component_manager_spec.rb +1259 -0
- data/spec/document_list_spec.rb +626 -0
- data/spec/document_project_spec.rb +373 -0
- data/spec/document_spec.rb +779 -0
- data/spec/editor_view_spec.rb +167 -0
- data/spec/external_program_plugin_spec.rb +676 -0
- data/spec/filtered_output_widget_spec.rb +642 -0
- data/spec/gui_states_handler_spec.rb +304 -0
- data/spec/kde_config_option_backend_spec.rb +214 -0
- data/spec/kde_sugar_spec.rb +101 -0
- data/spec/ktexteditor_wrapper_spec.rb +305 -0
- data/spec/output_widget_spec.rb +1703 -0
- data/spec/plugin_spec.rb +1393 -0
- data/spec/plugin_specification_reader_spec.rb +1765 -0
- data/spec/plugin_specification_spec.rb +401 -0
- data/spec/project_backend_spec.rb +172 -0
- data/spec/project_files_list_spec.rb +401 -0
- data/spec/project_list_spec.rb +511 -0
- data/spec/project_spec.rb +990 -0
- data/spec/qt_sugar_spec.rb +328 -0
- data/spec/settings_container_spec.rb +617 -0
- data/spec/settings_dialog_manager_spec.rb +773 -0
- data/spec/settings_dialog_spec.rb +419 -0
- data/spec/state_spec.rb +991 -0
- data/spec/utils_spec.rb +406 -0
- data/spec/workspace_spec.rb +869 -0
- data/spec/yaml_option_backend_spec.rb +246 -0
- metadata +284 -0
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
Copyright (C) 2010 by Stefano Crocco
|
|
3
|
+
stefano.crocco@alice.it
|
|
4
|
+
|
|
5
|
+
This program is free software; you can redistribute it andor modify
|
|
6
|
+
it under the terms of the GNU General Public License as published by
|
|
7
|
+
the Free Software Foundation; either version 2 of the License, or
|
|
8
|
+
(at your option) any later version.
|
|
9
|
+
|
|
10
|
+
This program is distributed in the hope that it will be useful,
|
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
GNU General Public License for more details.
|
|
14
|
+
|
|
15
|
+
You should have received a copy of the GNU General Public License
|
|
16
|
+
along with this program; if not, write to the
|
|
17
|
+
Free Software Foundation, Inc.,
|
|
18
|
+
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
19
|
+
=end
|
|
20
|
+
|
|
21
|
+
require 'facets/enumerable/sum'
|
|
22
|
+
|
|
23
|
+
module Ruber
|
|
24
|
+
|
|
25
|
+
class MainWindow < KParts::MainWindow
|
|
26
|
+
|
|
27
|
+
=begin rdoc
|
|
28
|
+
A list of strings to be used to create the filter for open file dialogs
|
|
29
|
+
=end
|
|
30
|
+
OPEN_DLG_FILTERS = [
|
|
31
|
+
'*.rb|Ruby source file (*.rb)',
|
|
32
|
+
'*.yaml *.yml|YAML files (*.yaml, *.yml)',
|
|
33
|
+
'*|All files'
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
slots 'remove_view(QWidget*)', 'document_modified_changed(bool)',
|
|
37
|
+
:document_url_changed, :next_document, :previous_document,
|
|
38
|
+
'store_splitter_sizes(QString)', 'update_document_icon(QObject*)',
|
|
39
|
+
'remove_plugin_ui_actions(QObject*)', 'close_project_files(QObject*)'
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
=begin rdoc
|
|
44
|
+
Checks whether an editor view for the given document exists and creates it if it
|
|
45
|
+
doesn't. In both cases, An editor view for the document is returned. _doc_ is the
|
|
46
|
+
Document for which the editor should be created.
|
|
47
|
+
|
|
48
|
+
<b>Note:</b> this also creates a new tab with the new view, if it needs to create
|
|
49
|
+
one
|
|
50
|
+
=end
|
|
51
|
+
def create_editor_if_needed doc
|
|
52
|
+
if doc.view then doc.view
|
|
53
|
+
else
|
|
54
|
+
view = doc.create_view
|
|
55
|
+
@editors_mapper.set_mapping view, view
|
|
56
|
+
connect view, SIGNAL(:closing), @editors_mapper, SLOT(:map)
|
|
57
|
+
connect view.document, SIGNAL('modified_changed(bool, QObject*)'), self, SLOT('document_modified_changed(bool)')
|
|
58
|
+
connect view.document, SIGNAL('modified_on_disk(QObject*, bool, KTextEditor::ModificationInterface::ModifiedOnDiskReason)'), self, SLOT('update_document_icon(QObject*)')
|
|
59
|
+
connect view.document, SIGNAL('document_url_changed(QObject*)'), self, SLOT(:document_url_changed)
|
|
60
|
+
@views.add_tab view, doc.icon, doc.document_name
|
|
61
|
+
view
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
=begin rdoc
|
|
66
|
+
Changes the icon in the tab corresponding to the Document _doc_ so that it reflects
|
|
67
|
+
its current status
|
|
68
|
+
=end
|
|
69
|
+
def update_document_icon doc
|
|
70
|
+
ed = editor_for doc
|
|
71
|
+
return unless ed
|
|
72
|
+
idx = @views.index_of ed
|
|
73
|
+
return unless idx
|
|
74
|
+
@views.set_tab_icon idx, doc.icon
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
=begin rdoc
|
|
78
|
+
Opens a file, creating a document and an editor for it, activates and gives focus
|
|
79
|
+
to the editor and adds the file to the list of recent files. _file_ is the absolute
|
|
80
|
+
path of the file to open
|
|
81
|
+
=end
|
|
82
|
+
def gui_open_file file
|
|
83
|
+
editor = editor_for! file
|
|
84
|
+
return unless editor
|
|
85
|
+
focus_on_editor editor
|
|
86
|
+
url = KDE::Url.from_path(file)
|
|
87
|
+
action_collection.action('file_open_recent').add_url url, url.file_name
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
=begin rdoc
|
|
91
|
+
If _ed_ is the active editor, it deactivates it and removes it from the gui. If
|
|
92
|
+
_ed_ is not the active editor (or if it's *nil*), nothing is done.
|
|
93
|
+
|
|
94
|
+
<b>Note:</b> this doesn't change the status bar associated with the view.
|
|
95
|
+
=end
|
|
96
|
+
def deactivate_editor ed
|
|
97
|
+
return unless ed and ed == @active_editor
|
|
98
|
+
@active_editor.document.deactivate
|
|
99
|
+
gui_factory.remove_client ed.send( :internal)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
=begin rdoc
|
|
103
|
+
Remove the editor _ed_ from the tab widget, deactivating it before (if needed).
|
|
104
|
+
If automatical activation of editors is on, it also activates another editor,
|
|
105
|
+
if any
|
|
106
|
+
=end
|
|
107
|
+
def remove_view ed
|
|
108
|
+
status_bar.view = nil if ed == @active_editor
|
|
109
|
+
deactivate_editor ed
|
|
110
|
+
idx = @views.index_of ed
|
|
111
|
+
@views.remove_tab idx
|
|
112
|
+
#This assumes that only one editor can exist for each document
|
|
113
|
+
ed.document.disconnect SIGNAL('modified_changed(bool, QObject*)'), self
|
|
114
|
+
ed.document.disconnect SIGNAL('document_url_changed(QObject*)'), self
|
|
115
|
+
if @views.current_widget and @auto_activate_editors
|
|
116
|
+
activate_editor @views.current_widget
|
|
117
|
+
@views.current_widget.set_focus
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
protected
|
|
122
|
+
|
|
123
|
+
=begin rdoc
|
|
124
|
+
Override of <tt>KParts::MainWindow#queryClose</tt> which calls the <tt>query_close</tt>
|
|
125
|
+
method of the component manager. This means that the latter method will be called
|
|
126
|
+
everytime the application is closed.
|
|
127
|
+
=end
|
|
128
|
+
def queryClose
|
|
129
|
+
Ruber[:components].query_close
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
=begin rdoc
|
|
133
|
+
Override of <tt>KParts::MainWindow#queryExit</tt> which calls the +shutdown+ method
|
|
134
|
+
of the component
|
|
135
|
+
=end
|
|
136
|
+
def queryExit
|
|
137
|
+
Ruber[:app].quit_ruber
|
|
138
|
+
true
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
=begin rdoc
|
|
142
|
+
Saves the properties for session management.
|
|
143
|
+
TODO: currently, session management doesn't work at all. So, either remove the
|
|
144
|
+
method or make it work
|
|
145
|
+
=end
|
|
146
|
+
def saveProperties conf
|
|
147
|
+
data = YAML.dump @session_data
|
|
148
|
+
conf.write_entry 'Ruber', data
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
=begin rdoc
|
|
152
|
+
Reads the properties from the config object for session management
|
|
153
|
+
=end
|
|
154
|
+
def readProperties conf
|
|
155
|
+
@last_session_data = YAML.load conf.read_entry('Ruber', '{}')
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
=begin rdoc
|
|
159
|
+
Creates a suitable title for the main window.
|
|
160
|
+
=end
|
|
161
|
+
def make_title
|
|
162
|
+
title = ''
|
|
163
|
+
prj = Ruber[:projects].current_project
|
|
164
|
+
if prj
|
|
165
|
+
title << (prj.project_name ? prj.project_name :
|
|
166
|
+
File.basename(prj.project_file, '.ruprj'))
|
|
167
|
+
end
|
|
168
|
+
if @active_editor and @active_editor.document.path.empty?
|
|
169
|
+
title << ' - ' << @active_editor.document.document_name
|
|
170
|
+
elsif @active_editor
|
|
171
|
+
title << ' - ' << @active_editor.document.path
|
|
172
|
+
end
|
|
173
|
+
title.sub!(/\A\s+-/, '')
|
|
174
|
+
mod = current_document.modified? rescue false
|
|
175
|
+
set_caption title, mod
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
=begin rdoc
|
|
179
|
+
:call-seq: document_modified_changed(mod) [SLOT]
|
|
180
|
+
|
|
181
|
+
Slot called whenever the modified status of a document changes. It updates the
|
|
182
|
+
icon on the tab of the document's editor and the window title (if the document
|
|
183
|
+
was the active one) accordingly.
|
|
184
|
+
=end
|
|
185
|
+
def document_modified_changed mod
|
|
186
|
+
doc = self.sender
|
|
187
|
+
make_title
|
|
188
|
+
#This assumes that only one editor exists for each document
|
|
189
|
+
update_document_icon doc
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
=begin rdoc
|
|
193
|
+
Slot called whenever the document url changes (usually because the document has
|
|
194
|
+
been saved). It changes the title and icon of the tab and changes the title of the
|
|
195
|
+
window is the document is active.
|
|
196
|
+
=end
|
|
197
|
+
def document_url_changed
|
|
198
|
+
doc = self.sender
|
|
199
|
+
make_title
|
|
200
|
+
idx = @views.index_of doc.view
|
|
201
|
+
@views.set_tab_text idx, doc.document_name
|
|
202
|
+
update_document_icon doc
|
|
203
|
+
|
|
204
|
+
unless doc.path.empty?
|
|
205
|
+
action_collection.action('file_open_recent').add_url KDE::Url.new(doc.path)
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
=begin rdoc
|
|
210
|
+
Removes the action handlers for all the actions belonging to the plugin _plug_
|
|
211
|
+
from the list of handlers
|
|
212
|
+
=end
|
|
213
|
+
def remove_plugin_ui_actions plug
|
|
214
|
+
@actions_state_handlers.delete_if do |state, hs|
|
|
215
|
+
hs.delete_if{|h| h.plugin == plug}
|
|
216
|
+
hs.empty?
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
=begin
|
|
221
|
+
Sets the UI states defined by the main window to their initial values.
|
|
222
|
+
=end
|
|
223
|
+
def setup_initial_states
|
|
224
|
+
change_state 'active_project_exists', false
|
|
225
|
+
change_state 'current_document', false
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def close_project_files prj
|
|
229
|
+
to_close = @views.select do |v|
|
|
230
|
+
prj.project_files.file_in_project? v.document.path
|
|
231
|
+
end
|
|
232
|
+
save_documents to_close.map &:document
|
|
233
|
+
to_close.each{|v| v.document.close}
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
end
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
Copyright (C) 2010 by Stefano Crocco
|
|
3
|
+
stefano.crocco@alice.it
|
|
4
|
+
|
|
5
|
+
This program is free software; you can redistribute it andor modify
|
|
6
|
+
it under the terms of the GNU General Public License as published by
|
|
7
|
+
the Free Software Foundation; either version 2 of the License, or
|
|
8
|
+
(at your option) any later version.
|
|
9
|
+
|
|
10
|
+
This program is distributed in the hope that it will be useful,
|
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
GNU General Public License for more details.
|
|
14
|
+
|
|
15
|
+
You should have received a copy of the GNU General Public License
|
|
16
|
+
along with this program; if not, write to the
|
|
17
|
+
Free Software Foundation, Inc.,
|
|
18
|
+
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
19
|
+
=end
|
|
20
|
+
|
|
21
|
+
require 'facets/boolean'
|
|
22
|
+
|
|
23
|
+
require 'pathname'
|
|
24
|
+
|
|
25
|
+
require_relative "ui/open_file_in_project_dlg"
|
|
26
|
+
|
|
27
|
+
module Ruber
|
|
28
|
+
|
|
29
|
+
=begin rdoc
|
|
30
|
+
This class is a dialog where the user can choose a file to open among the
|
|
31
|
+
files of the project.
|
|
32
|
+
|
|
33
|
+
The dialog is made by two widgets: a <tt>KDE::LineEdit</tt>, where the user
|
|
34
|
+
can enter a file pattern, and a <tt>Qt::ListView</tt>, where all files in
|
|
35
|
+
the project matching the
|
|
36
|
+
given regexp are shown. The user can choose the file either by pressing the
|
|
37
|
+
Return key or by activating an item in the list.
|
|
38
|
+
|
|
39
|
+
The pattern is interpreted as a regexp and is checked against the whole path
|
|
40
|
+
of the file if it contains a pattern separator character (the '/' character
|
|
41
|
+
on UNIX) and only
|
|
42
|
+
against the name of the file otherwise. When the user changes the pattern,
|
|
43
|
+
the file list is changed accordingly. This is achieved using a
|
|
44
|
+
filter model derived from <tt>Qt::SortFilterProxyModel</tt>.
|
|
45
|
+
=end
|
|
46
|
+
class OpenFileInProjectDlg < Qt::Dialog
|
|
47
|
+
|
|
48
|
+
=begin rdoc
|
|
49
|
+
Class implementing the filter for the +OpenFileInProjectDlg+ class.
|
|
50
|
+
=end
|
|
51
|
+
class FilterModel < Qt::SortFilterProxyModel
|
|
52
|
+
|
|
53
|
+
=begin rdoc
|
|
54
|
+
Returns a new +FilterModel+.
|
|
55
|
+
=====Arguments
|
|
56
|
+
_parent_:: the <tt>Qt::Object</tt> parent of the filter
|
|
57
|
+
=end
|
|
58
|
+
def initialize parent = nil
|
|
59
|
+
super
|
|
60
|
+
@filter = nil
|
|
61
|
+
@role = Qt::DisplayRole
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
=begin rdoc
|
|
65
|
+
Changes the regexp used to filter the files, then re-applies the filter
|
|
66
|
+
calling the +invalidate+ method.
|
|
67
|
+
=====Arguments
|
|
68
|
+
_value_:: the new regexp. It can be +nil+ or a regexp. In the first case,
|
|
69
|
+
the filter won't be applied.
|
|
70
|
+
=====TODO
|
|
71
|
+
On Windows, allow to also use the '\' character as pattern separator.
|
|
72
|
+
The problem is that that character is also the escape character in a regexp,
|
|
73
|
+
so things may become complicated.
|
|
74
|
+
=end
|
|
75
|
+
def filter= value
|
|
76
|
+
@filter = value
|
|
77
|
+
# TODO This doesn't work
|
|
78
|
+
#on windows, where one can also use \ as separator. The problem is that in regexp
|
|
79
|
+
#it's the escape character, so one must use something like
|
|
80
|
+
#value.include?(File::SEPARATOR) || (File::ALT_SEPARATOR and value.match(/\\{2}))
|
|
81
|
+
@role = if @filter and !value.source.include?(File::SEPARATOR) then Qt::UserRole + 1
|
|
82
|
+
else Qt::DisplayRole
|
|
83
|
+
end
|
|
84
|
+
invalidate
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
protected
|
|
88
|
+
|
|
89
|
+
=begin rdoc
|
|
90
|
+
Reimplementation of Qt::SortFilterProxyModel#filterAcceptsRow which returns
|
|
91
|
+
+true+ if the file matches the regexp and +false+ otherwise (if the regexp
|
|
92
|
+
is +nil+, this method always returns +true+).
|
|
93
|
+
|
|
94
|
+
If the source of the regexp contains the pattern separator, the whole
|
|
95
|
+
filename is tested, otherwise only the name of the file will be tested.
|
|
96
|
+
=end
|
|
97
|
+
def filterAcceptsRow r, parent
|
|
98
|
+
return true unless @filter
|
|
99
|
+
idx = source_model.index r, 0, parent
|
|
100
|
+
res = idx.data(@role).to_string.match @filter
|
|
101
|
+
res.to_bool #It seems that it's required to return true or false - other objects don't work
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
slots 'change_filter(const QString &)', 'item_activated(const QModelIndex &)'
|
|
107
|
+
|
|
108
|
+
=begin rdoc
|
|
109
|
+
Returns a new +OpenFileInProjectDlg+.
|
|
110
|
+
=====Arguments
|
|
111
|
+
_parent_:: the widget parent of the dialog
|
|
112
|
+
=end
|
|
113
|
+
def initialize parent = nil
|
|
114
|
+
super
|
|
115
|
+
files = Ruber.current_project.project_files.to_a
|
|
116
|
+
@base_dir = Ruber.current_project.project_directory
|
|
117
|
+
@ui = Ui::OpenFileInProjectDlg.new
|
|
118
|
+
@ui.setupUi self
|
|
119
|
+
@ui.regexp_error.hide
|
|
120
|
+
filter = FilterModel.new @ui.file_list
|
|
121
|
+
model = Qt::StandardItemModel.new filter
|
|
122
|
+
@ui.file_list.model = filter
|
|
123
|
+
filter.source_model = model
|
|
124
|
+
files.each do |f|
|
|
125
|
+
path = f.sub %r{\A#{Regexp.quote(@base_dir)}/}, ''
|
|
126
|
+
it = Qt::StandardItem.new path
|
|
127
|
+
it.set_data Qt::Variant.new(File.basename(path))
|
|
128
|
+
it.editable = false
|
|
129
|
+
model.append_row it
|
|
130
|
+
end
|
|
131
|
+
@ui.pattern.install_event_filter self
|
|
132
|
+
connect @ui.pattern, SIGNAL('textChanged(const QString &)'), self, SLOT('change_filter(const QString &)')
|
|
133
|
+
connect @ui.file_list, SIGNAL('activated(const QModelIndex &)'), self, SLOT('item_activated(const QModelIndex &)')
|
|
134
|
+
@ui.file_list.selection_model.select @ui.file_list.model.index(0,0),
|
|
135
|
+
Qt::ItemSelectionModel::ClearAndSelect|Qt::ItemSelectionModel::Rows
|
|
136
|
+
@ui.file_list.current_index = @ui.file_list.model.index(0,0)
|
|
137
|
+
# @ui.file_list.header.resize_sections Qt::HeaderView::ResizeToContents
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
=begin rdoc
|
|
141
|
+
Returns the file chosen by the user or +nil+ if no file has been chosen. The
|
|
142
|
+
chosen file is the file last selected in the file list.
|
|
143
|
+
=end
|
|
144
|
+
def chosen_file
|
|
145
|
+
selection = @ui.file_list.selection_model.selected_indexes
|
|
146
|
+
return nil if selection.empty?
|
|
147
|
+
idx = selection.first
|
|
148
|
+
File.join(@base_dir, idx.data.to_string.gsub(/\A\./,''))
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
=begin rdoc
|
|
152
|
+
Reimplements Qt::Object.eventFilter. It blocks the +KeyPress+ events for the
|
|
153
|
+
up and down keys (but only if there's no modifier) and redirects them to the
|
|
154
|
+
file list widget. All other events are allowed to pass. This allows to scroll
|
|
155
|
+
the list without taking the focus from the pattern widget.
|
|
156
|
+
=====Arguments
|
|
157
|
+
_obj_:: the object whose events should be filtered
|
|
158
|
+
_e_:: the event
|
|
159
|
+
=end
|
|
160
|
+
def eventFilter obj, e
|
|
161
|
+
if e.type != Qt::Event::KeyPress then return false
|
|
162
|
+
else
|
|
163
|
+
if (e.key == Qt::Key_Down || e.key == Qt::Key_Up) and e.modifiers == Qt::NoModifier
|
|
164
|
+
# TODO: reintroduce the last parameter when it stops giving errors
|
|
165
|
+
new_ev = Qt::KeyEvent.new e.type, e.key, e.modifiers, e.text,
|
|
166
|
+
e.is_auto_repeat, e.count
|
|
167
|
+
Ruber[:app].post_event @ui.file_list, new_ev
|
|
168
|
+
true
|
|
169
|
+
else false
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
private
|
|
175
|
+
|
|
176
|
+
=begin rdoc
|
|
177
|
+
Changes the pattern used by the filter model applied to the view so that it is
|
|
178
|
+
equal to the text currently in the pattern widget and selects the first item in
|
|
179
|
+
the view (if any). If the list is empty, it also disables the Ok button.
|
|
180
|
+
=====Arguments
|
|
181
|
+
_text_:: the new pattern
|
|
182
|
+
=end
|
|
183
|
+
def change_filter text
|
|
184
|
+
begin
|
|
185
|
+
reg = text.empty? ? nil : Regexp.new( text )
|
|
186
|
+
@ui.file_list.model.filter= reg
|
|
187
|
+
@ui.file_list.selection_model.select @ui.file_list.model.index(0,0),
|
|
188
|
+
Qt::ItemSelectionModel::ClearAndSelect|Qt::ItemSelectionModel::Rows
|
|
189
|
+
@ui.file_list.current_index = @ui.file_list.model.index(0,0)
|
|
190
|
+
@ui.buttons.button(Qt::DialogButtonBox::Ok).enabled = @ui.file_list.model.row_count > 0
|
|
191
|
+
@ui.regexp_error.hide
|
|
192
|
+
rescue RegexpError
|
|
193
|
+
@ui.regexp_error.show
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
=begin rdoc
|
|
198
|
+
Closes the dialog with the <tt>Qt::Dialog::Accepted</tt> status and selects the
|
|
199
|
+
index passed as argument.
|
|
200
|
+
=====Arguments
|
|
201
|
+
_idx_:: the index of the activated item.
|
|
202
|
+
=end
|
|
203
|
+
def item_activated idx
|
|
204
|
+
@ui.file_list.selection_model.select idx, Qt::ItemSelectionModel::ClearAndSelect|
|
|
205
|
+
Qt::ItemSelectionModel::Rows
|
|
206
|
+
@ui.file_list.current_index = idx
|
|
207
|
+
accept
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
end
|