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,167 @@
|
|
|
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 'ktexteditor'
|
|
22
|
+
require 'facets/boolean'
|
|
23
|
+
|
|
24
|
+
require 'ruber/editor/ktexteditor_wrapper'
|
|
25
|
+
|
|
26
|
+
module Ruber
|
|
27
|
+
|
|
28
|
+
class EditorView < Qt::Widget
|
|
29
|
+
|
|
30
|
+
include KTextEditorWrapper
|
|
31
|
+
|
|
32
|
+
signal_data = {
|
|
33
|
+
'information_message' => ['KTextEditor::View*, QString', [1, nil]],
|
|
34
|
+
'context_menu_about_to_show' => ['KTextEditor::View*, QMenu*', [1, nil]],
|
|
35
|
+
'focus_in' => ['KTextEditor::View*', [nil]],
|
|
36
|
+
'focus_out' => ['KTextEditor::View*', [nil]],
|
|
37
|
+
# 'selection_changed' => ['KTextEditor::View*', [nil]],
|
|
38
|
+
'vertical_scroll_position_changed' => ['KTextEditor::View*, KTextEditor::Cursor', [1, nil]],
|
|
39
|
+
'horizontal_scroll_position_changed' => ['KTextEditor::View*', [nil]],
|
|
40
|
+
'text_inserted' => ['KTextEditor::View*, KTextEditor::Cursor, QString', [1, 2, nil]],
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@signal_table = KTextEditorWrapper.prepare_wrapper_connections self, signal_data
|
|
44
|
+
|
|
45
|
+
signals 'closing()', 'cursor_position_changed(KTextEditor::Cursor, QWidget*)',
|
|
46
|
+
'view_mode_changed(QString, QWidget*)', 'edit_mode_changed(KTextEditor::View::EditMode, QWidget*)',
|
|
47
|
+
'selection_mode_changed(bool, QWidget*)', 'mouse_position_changed(KTextEditor::Cursor, QWidget*)',
|
|
48
|
+
'selection_changed(QWidget*)'
|
|
49
|
+
|
|
50
|
+
slots 'slot_selection_changed(KTextEditor::View*)'
|
|
51
|
+
|
|
52
|
+
# @view.connect(SIGNAL('selectionChanged(KTextEditor::View*)')) do |v|
|
|
53
|
+
# changed = @view.block_selection ^ @block_selection
|
|
54
|
+
# if changed
|
|
55
|
+
# @block_selection = @view.block_selection
|
|
56
|
+
# emit selection_mode_changed @block_selection, self
|
|
57
|
+
# end
|
|
58
|
+
# end
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
# signals 'closing()', 'information_message(QString, QObject*)',
|
|
63
|
+
# 'cursor_position_changed(KTextEditor::Cursor, QObject*)',
|
|
64
|
+
# 'view_mode_changed(QString, QObject*)', 'edit_mode_changed(KTextEditor::View::EditMode, QObject*)',
|
|
65
|
+
# 'selection_mode_changed(bool, QObject*)', 'context_menu_about_to_show(QMenu*, QObject*)',
|
|
66
|
+
# 'focus_in(QObject*)', 'focus_out(QObject*)', 'horizontal_scroll_position_changed(QObject*)',
|
|
67
|
+
# 'mouse_position_changed(KTextEditor::Cursor, QObject*)', 'selection_changed(QObject*)',
|
|
68
|
+
# 'text_inserted(KTextEditor::Cursor, QString, QObject*)', 'vertical_scroll_position_changed(KTextEditor::Cursor, QObject*)'
|
|
69
|
+
|
|
70
|
+
attr_reader :doc
|
|
71
|
+
alias_method :document, :doc
|
|
72
|
+
def initialize doc, internal, parent = nil
|
|
73
|
+
super parent
|
|
74
|
+
@block_selection = false
|
|
75
|
+
@doc = doc
|
|
76
|
+
@view = internal
|
|
77
|
+
@view.parent = self
|
|
78
|
+
initialize_wrapper @view, self.class.instance_variable_get(:@signal_table)
|
|
79
|
+
self.focus_proxy = @view
|
|
80
|
+
self.layout = Qt::VBoxLayout.new self
|
|
81
|
+
layout.set_contents_margins 0,0,0,0
|
|
82
|
+
layout.spacing = 0
|
|
83
|
+
layout.add_widget @view
|
|
84
|
+
|
|
85
|
+
connect @view, SIGNAL('selectionChanged(KTextEditor::View*)'), self, SLOT('slot_selection_changed(KTextEditor::View*)')
|
|
86
|
+
|
|
87
|
+
@view.connect(SIGNAL('cursorPositionChanged(KTextEditor::View*, KTextEditor::Cursor)'))do |v, c|
|
|
88
|
+
emit cursor_position_changed( @view.cursor_position_virtual, self)
|
|
89
|
+
end
|
|
90
|
+
@view.connect(SIGNAL('mousePositionChanged(KTextEditor::View*, KTextEditor::Cursor)')) do |v, c|
|
|
91
|
+
emit mouse_position_changed( @view.cursor_position_virtual, self)
|
|
92
|
+
end
|
|
93
|
+
@view.connect(SIGNAL('viewModeChanged(KTextEditor::View*)')) do |v|
|
|
94
|
+
emit view_mode_changed( view_mode, self)
|
|
95
|
+
end
|
|
96
|
+
@view.connect(SIGNAL('viewEditModeChanged(KTextEditor::View*, KTextEditor::View::EditMode)')) do |v, m|
|
|
97
|
+
emit edit_mode_changed( m, self)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
am = @doc.interface('annotation_interface').annotation_model
|
|
101
|
+
am.connect(SIGNAL('annotations_changed()')) do
|
|
102
|
+
show = Ruber[:config][:general, :auto_annotations] && am.has_annotations?
|
|
103
|
+
set_annotation_border_visible(show) rescue NoMethodError
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
@view.context_menu = @view.default_context_menu(Qt::Menu.new(@view))
|
|
107
|
+
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def go_to row, col
|
|
111
|
+
@view.cursor_position = KTextEditor::Cursor.new(row, col)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def show_annotation_border
|
|
115
|
+
set_annotation_border_visible true
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def hide_annotation_border
|
|
119
|
+
set_annotation_border_visible false
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def block_selection?
|
|
123
|
+
@view.block_selection.to_bool
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def close
|
|
127
|
+
emit closing
|
|
128
|
+
super
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def set_annotation_border_visible vis
|
|
132
|
+
@view.qobject_cast(KTextEditor::AnnotationViewInterface).set_annotation_border_visible vis
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
=begin rdoc
|
|
136
|
+
Executes the action with name the view's action
|
|
137
|
+
collection. This is made by having the action emit the <tt>triggered()</tt> or
|
|
138
|
+
<tt>toggled(bool)</tt> signal (depending on whether it's a standard action or a
|
|
139
|
+
<tt>KDE::ToggleAction</tt>). In the second case, _arg_ is the argument passed to
|
|
140
|
+
the signal.
|
|
141
|
+
|
|
142
|
+
Returns *true* if an action with name _name_ was found and *false* otherwise.
|
|
143
|
+
=end
|
|
144
|
+
def execute_action name, arg = nil
|
|
145
|
+
a = action_collection.action(name)
|
|
146
|
+
case a
|
|
147
|
+
when KDE::ToggleAction then a.instance_eval{emit toggled(arg)}
|
|
148
|
+
when nil then return false
|
|
149
|
+
else a.instance_eval{emit triggered}
|
|
150
|
+
end
|
|
151
|
+
true
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
private
|
|
155
|
+
|
|
156
|
+
def slot_selection_changed v
|
|
157
|
+
emit selection_changed(self)
|
|
158
|
+
changed = @view.block_selection ^ @block_selection
|
|
159
|
+
if changed
|
|
160
|
+
@block_selection = @view.block_selection
|
|
161
|
+
emit selection_mode_changed(@block_selection, self)
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
end
|
|
@@ -0,0 +1,202 @@
|
|
|
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/string/camelcase'
|
|
22
|
+
|
|
23
|
+
module Ruber
|
|
24
|
+
|
|
25
|
+
=begin rdoc
|
|
26
|
+
Module which abstracts some common functionality of Document and EditorView due
|
|
27
|
+
to the fact that both are mostly simply wrappers around two +KTextEditor+ classes.
|
|
28
|
+
|
|
29
|
+
Throught this documentation, the KTextEditor::Document or KTextEditor::View corresponding
|
|
30
|
+
to the object will be referred to as the <i>wrapped object</i>.
|
|
31
|
+
|
|
32
|
+
In particular, this class:
|
|
33
|
+
* provide a way to access methods provided by the different interfaces implemented
|
|
34
|
+
by the wrapped object without directly accessing it (using InterfaceProxy)
|
|
35
|
+
* redirect to the wrapped object any method call the object itself doesn't respond
|
|
36
|
+
to
|
|
37
|
+
* provide a (private) method to access the wrapped object
|
|
38
|
+
* provide some automatization in the process having the object emit an appropriate
|
|
39
|
+
signal when the wrapped object emits a signal.
|
|
40
|
+
=end
|
|
41
|
+
module KTextEditorWrapper
|
|
42
|
+
|
|
43
|
+
=begin rdoc
|
|
44
|
+
Helper class which, given a Qt::Object implementing different interfaces, allows
|
|
45
|
+
to access method provided by one interface without exposing the object itself.
|
|
46
|
+
=end
|
|
47
|
+
class InterfaceProxy
|
|
48
|
+
|
|
49
|
+
=begin rdoc
|
|
50
|
+
Creates a new InterfaceProxy. _obj_ is the <tt>Qt::Object</tt> to cast to the
|
|
51
|
+
appropriate interface
|
|
52
|
+
=end
|
|
53
|
+
def initialize obj
|
|
54
|
+
@obj = obj
|
|
55
|
+
@interface = nil
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
=begin rdoc
|
|
59
|
+
Sets the interface to which the object is going to be cast. _iface_ can be either
|
|
60
|
+
the name of an interface, as symbol or string, both in camelcase or snakecase
|
|
61
|
+
(withouth the +KTextEditor+ namespace) or the class itself. After a call to this
|
|
62
|
+
method (and until the next one) <tt>method_missing</tt> will redirect all unknown
|
|
63
|
+
method calls to this interface.
|
|
64
|
+
=end
|
|
65
|
+
def interface= iface
|
|
66
|
+
cls = if iface.is_a? Class then iface
|
|
67
|
+
else
|
|
68
|
+
name = iface.to_s.split('_').map(&:capitalize).join ''
|
|
69
|
+
KTextEditor.const_get(name)
|
|
70
|
+
end
|
|
71
|
+
@interface = @obj.qobject_cast cls
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
=begin rdoc
|
|
75
|
+
Passes the method call to the object cast to the current interface. If the argument
|
|
76
|
+
list contains instances of classes which mix-in KTextEditorWrapper, they're replaced
|
|
77
|
+
with the object they wrap before being passed to the interface.
|
|
78
|
+
=end
|
|
79
|
+
def method_missing name, *args, &blk
|
|
80
|
+
args.map!{|a| a.is_a?(KTextEditorWrapper) ? a.send(:internal) : a}
|
|
81
|
+
@interface.send name, *args, &blk
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
=begin rdoc
|
|
87
|
+
Makes easier having the object emit a signal in corrispondence with
|
|
88
|
+
signals emitted by the wrapped object. In particular, this method does the following
|
|
89
|
+
(for each signal given in the arguments):
|
|
90
|
+
* creates a signal for the object based on the name of the signal in the wrapped
|
|
91
|
+
object
|
|
92
|
+
* creates a slot for the object with a name obtained from the name of the signal, which takes
|
|
93
|
+
the same arguments as the signal in the wrapped object and emits the associated
|
|
94
|
+
signal of the object. The arguments of the emitted signal are taken from those
|
|
95
|
+
passed to the slot, but they can be reordered. Also, *self* can be specified
|
|
96
|
+
* returns a hash suitable to be passed as second argument to <tt>initialize_wrapper</tt>.
|
|
97
|
+
Usually, this method is called when the class is created and the returned hash
|
|
98
|
+
is stored in a class instance variable. The class's +initialize+ method then passes
|
|
99
|
+
it as second argument to <tt>initialize_wrapper</tt>.
|
|
100
|
+
|
|
101
|
+
_cls_ is the class for which signals and slots will be defined. _data_ is a hash
|
|
102
|
+
containing the information for the signal and slot to create.
|
|
103
|
+
* its keys are the names of the signals converted to snakecase. This name will be
|
|
104
|
+
converted to camelcase to obtain the name of the signal of the wrapped object,
|
|
105
|
+
while will be used as is for the signal of the object.
|
|
106
|
+
* its values are arrays. The first element is the signature of the signal of the
|
|
107
|
+
wrapped object. The second element is an array of integers and *nil*s. An integer
|
|
108
|
+
_i_ in the position _n_ of the array means that the _n_th argument of the new
|
|
109
|
+
signal will be the _i_th argument of the signal of the wrapped object (both
|
|
110
|
+
indexes start from 0). If the array contains *nil* in position _n_, the _n_th
|
|
111
|
+
argument of the new signal will be *self* (in the signature of the new signal,
|
|
112
|
+
this will mean <tt>QWidget*</tt> if _cls_ derives from <tt>Qt::Widget</tt> and
|
|
113
|
+
<tt>QObject*</tt> otherwise).
|
|
114
|
+
=end
|
|
115
|
+
def self.prepare_wrapper_connections cls, data
|
|
116
|
+
res = {}
|
|
117
|
+
data.each_pair do |name, d|
|
|
118
|
+
old_args = d[0].split(/,\s*/)
|
|
119
|
+
new_args = d[1].map do |i|
|
|
120
|
+
if i then old_args[i]
|
|
121
|
+
elsif cls.ancestors.include?(Qt::Widget) then 'QWidget*'
|
|
122
|
+
else 'QObject*'
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
new_args = new_args.join ', '
|
|
126
|
+
new_signal = "#{name}(#{new_args})"
|
|
127
|
+
old_signal = "#{name.camelcase :lower}(#{d[0]})"
|
|
128
|
+
slot_name = "__emit_#{name}_signal(#{d[0]})"
|
|
129
|
+
cls.send :signals, new_signal
|
|
130
|
+
cls.send :slots, slot_name
|
|
131
|
+
res[old_signal] = slot_name
|
|
132
|
+
method_def = <<-EOS
|
|
133
|
+
def __emit_#{name}_signal(#{old_args.size.times.map{|i| "a#{i}"}.join ', '})
|
|
134
|
+
emit #{name}(#{d[1].map{|i| i ? "a#{i}" : 'self'}.join ', '})
|
|
135
|
+
end
|
|
136
|
+
EOS
|
|
137
|
+
cls.class_eval method_def
|
|
138
|
+
end
|
|
139
|
+
res
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
=begin rdoc
|
|
143
|
+
Returns an InterfaceProxy set to the interface _name_. See <tt>InterfaceProxy#interface=</tt>
|
|
144
|
+
for the possible values for _name_. It is meant to be used this way (supposing
|
|
145
|
+
_doc_ is an object which wraps <tt>KTextEditor::Document</tt>)
|
|
146
|
+
doc.interface(:modification_interface).modified_on_disk_warning = true
|
|
147
|
+
=end
|
|
148
|
+
def interface name
|
|
149
|
+
@_interface.interface = name
|
|
150
|
+
@_interface
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
=begin rdoc
|
|
154
|
+
Forwards the method call to the wrapped object
|
|
155
|
+
=end
|
|
156
|
+
def method_missing name, *args, &blk
|
|
157
|
+
begin super
|
|
158
|
+
rescue NoMethodError, NameError, NotImplementedError
|
|
159
|
+
@_wrapped.send name, *args, &blk
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
private
|
|
164
|
+
|
|
165
|
+
=begin rdoc
|
|
166
|
+
Method which needs to be called before using any of the functionality provided by
|
|
167
|
+
the module (usually, it's called from +initialize+). _obj_ is the wrapped object,
|
|
168
|
+
while _signals_ is a hash as described in <tt>connect_wrapped_signals</tt>.
|
|
169
|
+
|
|
170
|
+
It creates an InterfaceProxy for the wrapped object and calls <tt>connect_wrapped_signals</tt>
|
|
171
|
+
passing _signals_ as argument.
|
|
172
|
+
=end
|
|
173
|
+
def initialize_wrapper obj, signals
|
|
174
|
+
@_interface = InterfaceProxy.new obj
|
|
175
|
+
@_wrapped = obj
|
|
176
|
+
connect_wrapped_signals signals
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
=begin rdoc
|
|
180
|
+
Returns the wrapped object (this method is mainly for internal use)
|
|
181
|
+
=end
|
|
182
|
+
def internal
|
|
183
|
+
@_wrapped
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
=begin rdoc
|
|
187
|
+
Makes a connections between a series of signals and of slots. _signals_ is a hash
|
|
188
|
+
whose keys are the names of the signals and whose entries are the slots each signal
|
|
189
|
+
should be connected to (only one slot can be connected to each signal). You can't
|
|
190
|
+
connect a signal to another signal with this method.
|
|
191
|
+
|
|
192
|
+
This method is mainly meant to be used in conjunction with <tt>prepare_wrapper_connections</tt>.
|
|
193
|
+
=end
|
|
194
|
+
def connect_wrapped_signals signals
|
|
195
|
+
signals.each_pair do |k, v|
|
|
196
|
+
connect @_wrapped, SIGNAL(k), self, SLOT(v)
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
end
|
|
@@ -0,0 +1,245 @@
|
|
|
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
|
+
module Ruber
|
|
22
|
+
|
|
23
|
+
=begin rdoc
|
|
24
|
+
Dialog which displays the content of an exception (that is, the message and the
|
|
25
|
+
backtrace) to the user.
|
|
26
|
+
|
|
27
|
+
The backtrace is shown as an extension widget, only if the user clicks the 'Backtrace'
|
|
28
|
+
button.
|
|
29
|
+
=end
|
|
30
|
+
class ExceptionDialog < KDE::Dialog
|
|
31
|
+
|
|
32
|
+
=begin rdoc
|
|
33
|
+
Subclass of @KDE::TextEdit@ specialized in displaying the backtrace of an
|
|
34
|
+
exception.
|
|
35
|
+
|
|
36
|
+
The differences with a standard @KDE::TextEdit@ are:
|
|
37
|
+
* automatically uses a fixed width font
|
|
38
|
+
* doesn't use word wrapping
|
|
39
|
+
* is always read-only
|
|
40
|
+
* its {#size_hint} method computes (or at least tries to compute) width
|
|
41
|
+
and height so that each line of the backtrace fits on a single line.
|
|
42
|
+
* automatically extracts the message and the backtrace from the exception
|
|
43
|
+
=end
|
|
44
|
+
class ExceptionBacktraceWidget < KDE::TextEdit
|
|
45
|
+
|
|
46
|
+
=begin rdoc
|
|
47
|
+
@param [Exception] ex the exception whose backtrace should be displayed
|
|
48
|
+
@param [Qt::Widget, nil] parent the parent widget
|
|
49
|
+
=end
|
|
50
|
+
def initialize ex, parent = nil
|
|
51
|
+
super parent
|
|
52
|
+
self.line_wrap_mode = NoWrap
|
|
53
|
+
self.read_only = true
|
|
54
|
+
#Replace < and > with the corresponding HTML entities in the message
|
|
55
|
+
msg = ex.message.gsub(/[<>]/){|s| s == '<' ? '<' : '>'}
|
|
56
|
+
#Replace < and > with the corresponding HTML entities in the backtrace
|
|
57
|
+
backtrace = ex.backtrace.map{|l| l.gsub(/[<>]/){|s| s == '<' ? '<' : '>'}}
|
|
58
|
+
text = "<tt>#{msg}<br/>#{backtrace.join '<br/>'}</tt>"
|
|
59
|
+
self.html = text
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
=begin rdoc
|
|
63
|
+
Override of @KDE::TextEdit#sizeHint@
|
|
64
|
+
|
|
65
|
+
The width is computed as the size (using the fixed width font) of the longest line,
|
|
66
|
+
while the height is computed as the height of a single line multiplied by the
|
|
67
|
+
number of lines.
|
|
68
|
+
|
|
69
|
+
Both width and height are computed using @Qt::FontMetrics@
|
|
70
|
+
|
|
71
|
+
@return [Qt::Size] the suggested size of the widget
|
|
72
|
+
=end
|
|
73
|
+
def sizeHint
|
|
74
|
+
font = Qt::TextCursor.new(document).char_format.font
|
|
75
|
+
fm = Qt::FontMetrics.new font
|
|
76
|
+
lines = to_plain_text.split_lines
|
|
77
|
+
longest = lines.sort_by{|l| l.size}[-1]
|
|
78
|
+
Qt::Size.new fm.width(longest), fm.height * lines.size
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
=begin rdoc
|
|
84
|
+
@param [Exception] ex the exception the dialog is for
|
|
85
|
+
@param [Qt::Widget,nil] the parent widget
|
|
86
|
+
@param [Boolean] out whether to display the exception to standard error when the
|
|
87
|
+
dialog is executed
|
|
88
|
+
@param [String] msg the text to display in the dialog before the exception message.
|
|
89
|
+
Note that this will always be treated as rich text. Unless empty,
|
|
90
|
+
a line break will always be inserted after it
|
|
91
|
+
=end
|
|
92
|
+
def initialize ex, parent = nil, out = true, msg = 'Ruber raised the following exception:'
|
|
93
|
+
super parent
|
|
94
|
+
self.caption = KDE::Dialog.make_standard_caption "Exception"
|
|
95
|
+
self.buttons = Ok | Details
|
|
96
|
+
set_button_text Ok, 'Quit Ruber'
|
|
97
|
+
set_button_text Details, 'Backtrace'
|
|
98
|
+
error = ex.message.gsub(/\n/, '<br/>')
|
|
99
|
+
error.gsub!(/[<>]/){|s| s == '<' ? '<' : '>'}
|
|
100
|
+
text = (!msg.empty? ? msg + '<br/>' : '') + '<tt>' + error + '</tt>'
|
|
101
|
+
self.main_widget = Qt::Label.new text, self
|
|
102
|
+
@backtrace_widget = ExceptionBacktraceWidget.new ex, self
|
|
103
|
+
self.details_widget = @backtrace_widget
|
|
104
|
+
@out = out
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
=begin rdoc
|
|
108
|
+
Override of @KDE::Dialog#sizeHint@
|
|
109
|
+
|
|
110
|
+
It takes into account the size of the details widget, if shown.
|
|
111
|
+
|
|
112
|
+
@return [Qt::Size] the suggested size for the dialog
|
|
113
|
+
=end
|
|
114
|
+
def sizeHint
|
|
115
|
+
orig = super
|
|
116
|
+
if defined?(@backtrace_widget) and @backtrace_widget.visible?
|
|
117
|
+
main_width = main_widget.sizeHint.width
|
|
118
|
+
diff = orig.width - main_width
|
|
119
|
+
det_width = @backtrace_widget.sizeHint.width
|
|
120
|
+
w = [det_width, main_width].max + diff
|
|
121
|
+
Qt::Size.new(w, orig.height)
|
|
122
|
+
else orig
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
=begin rdoc
|
|
127
|
+
Override of @KDE::Dialog#exec@
|
|
128
|
+
|
|
129
|
+
If the _out_ parameter passed to the constructor was *true*, displays the exception
|
|
130
|
+
message and backtrace on standard error before displaying the dialog
|
|
131
|
+
@return [Integer] the exit code of the dialog
|
|
132
|
+
=end
|
|
133
|
+
def exec
|
|
134
|
+
if @out
|
|
135
|
+
$stderr.puts @backtrace_widget.to_plain_text
|
|
136
|
+
end
|
|
137
|
+
super
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
=begin rdoc
|
|
141
|
+
Override of @KDE::Dialog#show@
|
|
142
|
+
|
|
143
|
+
If the _out_ parameter passed to the constructor was *true*, displays the exception
|
|
144
|
+
message and backtrace on standard error before displaying the dialog
|
|
145
|
+
@return [nil]
|
|
146
|
+
=end
|
|
147
|
+
def show
|
|
148
|
+
if @out
|
|
149
|
+
$stderr.puts @backtrace_widget.to_plain_text
|
|
150
|
+
end
|
|
151
|
+
super
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
=begin rdoc
|
|
157
|
+
ExceptionDialog specialized to display failures when loading plugins and components.
|
|
158
|
+
|
|
159
|
+
It differs from {ExceptionDialog} in the following aspects:
|
|
160
|
+
* it provides different buttons
|
|
161
|
+
* it provides a check box to decide whether or not to warn of subsequent errors while
|
|
162
|
+
loading plugins
|
|
163
|
+
* its #{exec} method provides values suitable to be returned from a block passed to
|
|
164
|
+
{ComponentManager#load_plugins}
|
|
165
|
+
* it provides an appropriate text
|
|
166
|
+
|
|
167
|
+
The buttons on the dialog are:
|
|
168
|
+
|
|
169
|
+
- Go on::= ignore the failure and attempt to load the remaining plugins, hoping
|
|
170
|
+
everything goes well
|
|
171
|
+
- Quit::= immediately quit Ruber
|
|
172
|
+
- Skip remaining::= ignore the failure, but don't attempt to load any other plugin
|
|
173
|
+
|
|
174
|
+
If the exception was raised while loading a core component, the dialog will behave
|
|
175
|
+
exactly as an {ExceptionDialog} (since you can't start Ruber without one of the core
|
|
176
|
+
components, the other buttons and the checkbox would be useless).
|
|
177
|
+
=end
|
|
178
|
+
class ComponentLoadingErrorDialog < ExceptionDialog
|
|
179
|
+
|
|
180
|
+
=begin rdoc
|
|
181
|
+
|
|
182
|
+
@param [Symbol,String] plugin the name of the component which caused the exception
|
|
183
|
+
@param [Exception] ex the exception which was raised
|
|
184
|
+
@param [Qt::Widget,nil] the parent widget
|
|
185
|
+
@param [Boolean] core whether the component which caused the failure is a core
|
|
186
|
+
component or a plugin
|
|
187
|
+
=end
|
|
188
|
+
def initialize plugin, ex, parent = nil, core = false
|
|
189
|
+
msg = "An error occurred while loading the #{core ? 'component' : 'plugin' } #{plugin}. The error was:"
|
|
190
|
+
super ex, parent, true, msg
|
|
191
|
+
unless core
|
|
192
|
+
label = main_widget
|
|
193
|
+
w = Qt::Widget.new self
|
|
194
|
+
self.main_widget = w
|
|
195
|
+
w.layout = Qt::VBoxLayout.new w
|
|
196
|
+
label.parent = w
|
|
197
|
+
w.layout.add_widget label
|
|
198
|
+
@silent = Qt::CheckBox.new "&Don't report other errors", w
|
|
199
|
+
w.layout.add_widget @silent
|
|
200
|
+
self.buttons = Yes|No|Cancel|Details
|
|
201
|
+
self.set_button_text KDE::Dialog::Yes, "&Go on"
|
|
202
|
+
self.set_button_text KDE::Dialog::No, "&Quit Ruber"
|
|
203
|
+
self.set_button_text KDE::Dialog::Cancel, "&Skip remaining plugins"
|
|
204
|
+
self.escape_button = KDE::Dialog::No
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
=begin rdoc
|
|
209
|
+
Whether or not the user checked to ignore subsequent errors
|
|
210
|
+
|
|
211
|
+
@return [Boolean,nil] *true* if the user checked the "Don't report other errors" check
|
|
212
|
+
box and *false* otherwise. If the dialog is shown for a core
|
|
213
|
+
component, this method always returns *nil*
|
|
214
|
+
=end
|
|
215
|
+
def silently?
|
|
216
|
+
@silent.checked? rescue nil
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
=begin rdoc
|
|
220
|
+
Override of {ExceptionDialog#exec}
|
|
221
|
+
|
|
222
|
+
It returns a different value according to the button pressed by the user and to
|
|
223
|
+
whether he checked the "Don't report other errors" checkbox. The returned values
|
|
224
|
+
are suitable for use by a block passed to {ComponentManager#load_plugins}.
|
|
225
|
+
|
|
226
|
+
@return [Boolean,Symbol]
|
|
227
|
+
|
|
228
|
+
- *true*:= if the user pressed the "Go on" button without checking the checkbox
|
|
229
|
+
- @:silent@:= if the user pressed the "Go on" button and checked the checkbox
|
|
230
|
+
- *false*:= if the user pressed the "Quit" button
|
|
231
|
+
- @:skip@:= if the user pressed the "Skip" button
|
|
232
|
+
=end
|
|
233
|
+
def exec
|
|
234
|
+
res = super
|
|
235
|
+
case res
|
|
236
|
+
when KDE::Dialog::Yes then dlg.silently? ? :silent : true
|
|
237
|
+
when KDE::Dialog::No then false
|
|
238
|
+
when KDE::Dialog::Cancel then :skip
|
|
239
|
+
else res
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
end
|