weft-qda 0.9.6 → 0.9.8
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/lib/weft.rb +16 -1
- data/lib/weft/WEFT-VERSION-STRING.rb +1 -1
- data/lib/weft/application.rb +17 -74
- data/lib/weft/backend.rb +6 -32
- data/lib/weft/backend/sqlite.rb +222 -164
- data/lib/weft/backend/sqlite/category_tree.rb +52 -48
- data/lib/weft/backend/sqlite/database.rb +57 -0
- data/lib/weft/backend/sqlite/upgradeable.rb +7 -0
- data/lib/weft/broadcaster.rb +90 -0
- data/lib/weft/category.rb +139 -47
- data/lib/weft/codereview.rb +160 -0
- data/lib/weft/coding.rb +74 -23
- data/lib/weft/document.rb +23 -10
- data/lib/weft/exceptions.rb +10 -0
- data/lib/weft/filters.rb +47 -224
- data/lib/weft/filters/indexers.rb +137 -0
- data/lib/weft/filters/input.rb +118 -0
- data/lib/weft/filters/output.rb +101 -0
- data/lib/weft/filters/templates.rb +80 -0
- data/lib/weft/filters/win32backtick.rb +246 -0
- data/lib/weft/query.rb +169 -0
- data/lib/weft/wxgui.rb +349 -294
- data/lib/weft/wxgui/constants.rb +43 -0
- data/lib/weft/wxgui/controls.rb +6 -0
- data/lib/weft/wxgui/controls/category_dropdown.rb +192 -0
- data/lib/weft/wxgui/controls/category_tree.rb +314 -0
- data/lib/weft/wxgui/controls/document_list.rb +97 -0
- data/lib/weft/wxgui/controls/multitype_control.rb +37 -0
- data/lib/weft/wxgui/{inspectors → controls}/textcontrols.rb +235 -64
- data/lib/weft/wxgui/dialogs.rb +144 -41
- data/lib/weft/wxgui/error_handler.rb +116 -36
- data/lib/weft/wxgui/exceptions.rb +7 -0
- data/lib/weft/wxgui/inspectors.rb +61 -208
- data/lib/weft/wxgui/inspectors/category.rb +19 -16
- data/lib/weft/wxgui/inspectors/codereview.rb +90 -132
- data/lib/weft/wxgui/inspectors/document.rb +12 -8
- data/lib/weft/wxgui/inspectors/imagedocument.rb +56 -56
- data/lib/weft/wxgui/inspectors/query.rb +284 -0
- data/lib/weft/wxgui/inspectors/script.rb +147 -23
- data/lib/weft/wxgui/lang/en.rb +69 -0
- data/lib/weft/wxgui/sidebar.rb +90 -432
- data/lib/weft/wxgui/utilities.rb +70 -91
- data/lib/weft/wxgui/workarea.rb +150 -43
- data/share/icons/category.ico +0 -0
- data/share/icons/category.xpm +109 -0
- data/share/icons/codereview.ico +0 -0
- data/share/icons/codereview.xpm +54 -0
- data/share/icons/d_and_c.xpm +126 -0
- data/share/icons/document.ico +0 -0
- data/share/icons/document.xpm +70 -0
- data/share/icons/project.ico +0 -0
- data/share/icons/query.ico +0 -0
- data/share/icons/query.xpm +56 -0
- data/{lib/weft/wxgui → share/icons}/search.xpm +0 -0
- data/share/icons/weft.ico +0 -0
- data/share/icons/weft.xpm +62 -0
- data/share/icons/weft16.ico +0 -0
- data/share/icons/weft32.ico +0 -0
- data/share/templates/category_plain.html +18 -0
- data/share/templates/codereview_plain.html +18 -0
- data/share/templates/document_plain.html +13 -0
- data/share/templates/document_plain.txt +7 -0
- data/test/001-document.rb +55 -36
- data/test/002-category.rb +81 -6
- data/test/003-code.rb +8 -4
- data/test/004-application.rb +13 -34
- data/test/005-query_review.rb +139 -0
- data/test/006-filters.rb +54 -42
- data/test/007-output_filters.rb +113 -0
- data/test/009a-backend_sqlite_basic.rb +95 -24
- data/test/009b-backend_sqlite_complex.rb +43 -62
- data/test/009c_backend_sqlite_bench.rb +5 -10
- data/test/053-doc_inspector.rb +46 -0
- data/test/055-query_window.rb +50 -0
- data/test/all-tests.rb +1 -0
- data/test/test-common.rb +19 -0
- data/test/testdata/empty.qdp +0 -0
- data/test/testdata/simple with space.pdf +0 -0
- data/test/testdata/simple.pdf +0 -0
- data/weft-qda.rb +40 -7
- metadata +74 -14
- data/lib/weft/wxgui/category.xpm +0 -26
- data/lib/weft/wxgui/document.xpm +0 -25
- data/lib/weft/wxgui/inspectors/search.rb +0 -265
- data/lib/weft/wxgui/mondrian.xpm +0 -44
- data/lib/weft/wxgui/weft16.xpm +0 -31
data/lib/weft/wxgui/dialogs.rb
CHANGED
@@ -1,54 +1,91 @@
|
|
1
1
|
module QDA::GUI
|
2
|
-
class
|
3
|
-
PT_STYLE = Wx::PD_APP_MODAL|Wx::PD_AUTO_HIDE
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
def prepare(content)
|
11
|
-
@progbar = Wx::ProgressDialog.new('Importing document',
|
12
|
-
"Reading document #{@doctitle}",
|
13
|
-
content.count($/),
|
14
|
-
@parent, PT_STYLE)
|
15
|
-
@progress = 0
|
2
|
+
class StageProgressDialog < Wx::ProgressDialog
|
3
|
+
PT_STYLE = Wx::PD_APP_MODAL|Wx::PD_AUTO_HIDE|Wx::PD_CAN_ABORT
|
4
|
+
|
5
|
+
FIXED_PROGRESS = 200
|
6
|
+
def initialize(parent, title, msg)
|
7
|
+
super(title, msg, FIXED_PROGRESS, parent, PT_STYLE)
|
8
|
+
@progress = 0.0
|
9
|
+
@step = FIXED_PROGRESS.to_f / 10.0
|
16
10
|
end
|
17
11
|
|
18
|
-
def
|
19
|
-
|
20
|
-
|
12
|
+
def step(msg = nil)
|
13
|
+
@progress = @progress + @step
|
14
|
+
result = msg ? update(@progress.to_i, msg) :
|
15
|
+
update(@progress.to_i)
|
16
|
+
if not result
|
17
|
+
Kernel.raise UserAbortedException.new('Document import cancelled')
|
21
18
|
end
|
22
|
-
super
|
23
19
|
end
|
24
|
-
|
25
|
-
def
|
26
|
-
@
|
20
|
+
|
21
|
+
def retarget(new_target)
|
22
|
+
remaining = FIXED_PROGRESS - @progress
|
23
|
+
@step = remaining / new_target.to_f
|
24
|
+
end
|
25
|
+
|
26
|
+
def finish()
|
27
|
+
update(@progress = FIXED_PROGRESS)
|
27
28
|
end
|
28
29
|
end
|
29
|
-
|
30
|
-
class
|
31
|
-
|
32
|
-
|
33
|
-
def
|
34
|
-
|
35
|
-
@progbar = Wx::ProgressDialog.new( 'Importing document',
|
36
|
-
"Saving indexes for #{title}",
|
37
|
-
count, parent, PT_STYLE)
|
38
|
-
@progress = 0
|
30
|
+
|
31
|
+
# A simple class for displaying helpful info.
|
32
|
+
class InformationDialog < Wx::MessageDialog
|
33
|
+
INFO_DIALOG_FLAGS = Wx::OK|Wx::ICON_INFORMATION
|
34
|
+
def self.display(title, message)
|
35
|
+
new(nil, message, title, INFO_DIALOG_FLAGS).show_modal()
|
39
36
|
end
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
37
|
+
end
|
38
|
+
|
39
|
+
class ErrorDialog < Wx::MessageDialog
|
40
|
+
ERR_DIALOG_FLAGS = Wx::OK|Wx::ICON_ERROR
|
41
|
+
def self.display(title, message)
|
42
|
+
new(nil, message, title, ERR_DIALOG_FLAGS).show_modal()
|
45
43
|
end
|
46
|
-
|
47
|
-
|
48
|
-
|
44
|
+
end
|
45
|
+
|
46
|
+
# A simple class for seeking warnings of risky requests.
|
47
|
+
class WarningDialog < Wx::MessageDialog
|
48
|
+
WARN_DIALOG_FLAGS = Wx::NO_DEFAULT|Wx::OK|Wx::CANCEL|Wx::ICON_EXCLAMATION
|
49
|
+
def self.display(title, message)
|
50
|
+
new(nil, message, title, WARN_DIALOG_FLAGS).show_modal()
|
49
51
|
end
|
50
52
|
end
|
51
|
-
|
53
|
+
|
54
|
+
class ConfirmDialog < Wx::MessageDialog
|
55
|
+
CONFIRM_DIALOG_FLAGS = Wx::NO_DEFAULT|Wx::YES|Wx::NO|Wx::ICON_EXCLAMATION
|
56
|
+
def self.display(title, message)
|
57
|
+
new(nil, message, title, CONFIRM_DIALOG_FLAGS).show_modal()
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class SuppressibleConfirmDialog < ConfirmDialog
|
62
|
+
def self.suppress_conf()
|
63
|
+
conf = Wx::ConfigBase.get()
|
64
|
+
conf.path = '/SuppressWarnings'
|
65
|
+
conf
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.suppressed?(key)
|
69
|
+
suppress_conf.read_bool(key, false)
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.suppress(key)
|
73
|
+
suppress_conf.write(key, true)
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.release(key)
|
77
|
+
suppress_conf.write(key, false)
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.display(key, title, message)
|
81
|
+
if suppressed?(key)
|
82
|
+
return Wx::ID_YES
|
83
|
+
else
|
84
|
+
return super(title, message)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
52
89
|
class SearchDialog < Wx::Dialog
|
53
90
|
def initialize(parent)
|
54
91
|
super( parent, -1, 'Search', DEF_POS, Wx::Size.new(500,175) )
|
@@ -70,7 +107,7 @@ module QDA::GUI
|
|
70
107
|
|
71
108
|
@expand = Wx::SpinCtrl.new( self, -1, "")
|
72
109
|
@expand.set_range(0, 1000)
|
73
|
-
@expand.set_value(
|
110
|
+
@expand.set_value(200)
|
74
111
|
mini_sizer.add(@expand, 0, Wx::ALL, 4)
|
75
112
|
mini_sizer.add(Wx::StaticText.new(self, -1, 'characters'),
|
76
113
|
0, Wx::ALL, 6)
|
@@ -125,4 +162,70 @@ module QDA::GUI
|
|
125
162
|
@expand.get_value().to_i
|
126
163
|
end
|
127
164
|
end
|
165
|
+
|
166
|
+
class ImportFileDialog < Wx::FileDialog
|
167
|
+
def initialize(parent, import_class)
|
168
|
+
@import_class = import_class
|
169
|
+
imports = QDA::Filters::import_filters[import_class]
|
170
|
+
wildcard = imports.map { | filt | '%s (*.%s)|*.%s' %
|
171
|
+
[ filt::DESCRIPTION,
|
172
|
+
filt::EXTENSIONS,
|
173
|
+
filt::EXTENSIONS ] }.join('|')
|
174
|
+
super(parent, Lang::IMPORT_DOC_DIALOGUE_TITLE,
|
175
|
+
"", "", wildcard, Wx::MULTIPLE)
|
176
|
+
end
|
177
|
+
|
178
|
+
# return each selected file in turn into a block, passing in +path+ and
|
179
|
+
# +filename+
|
180
|
+
def each_with_path
|
181
|
+
get_paths.each_with_index do | fpath, i |
|
182
|
+
yield fpath, get_filenames[i]
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def filter()
|
187
|
+
QDA::Filters::import_filters[@import_class][filter_index]
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
|
192
|
+
class ExportFileDialog < Wx::FileDialog
|
193
|
+
def initialize(parent, export_obj)
|
194
|
+
@obj = export_obj
|
195
|
+
exports = QDA::Filters::export_filters[@obj.class]
|
196
|
+
wildcard = exports.map { | filt | '%s (*.%s)|*.%s' %
|
197
|
+
[ filt::DESCRIPTION,
|
198
|
+
filt::EXTENSION,
|
199
|
+
filt::EXTENSION ] }.join('|')
|
200
|
+
super(parent, Lang::EXPORT_DOC_DIALOGUE_TITLE,
|
201
|
+
"", "", wildcard, Wx::SAVE|Wx::OVERWRITE_PROMPT)
|
202
|
+
set_filename( exports[0].def_name(export_obj) )
|
203
|
+
end
|
204
|
+
|
205
|
+
def filter()
|
206
|
+
QDA::Filters::export_filters[@obj.class][filter_index]
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
|
211
|
+
class ScriptFileDialog < Wx::FileDialog
|
212
|
+
def initialize(parent, saving = false)
|
213
|
+
if saving
|
214
|
+
style = Wx::SAVE|Wx::OVERWRITE_PROMPT
|
215
|
+
title = 'Save a Script to a Ruby File'
|
216
|
+
else
|
217
|
+
style = Wx::OPEN
|
218
|
+
title = 'Import a Script from a Ruby File'
|
219
|
+
end
|
220
|
+
super(parent, title, "", "", 'Ruby files (*.rb)|*.rb', style)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
class ScriptOutputFileDialog < Wx::FileDialog
|
225
|
+
def initialize(parent)
|
226
|
+
style = Wx::SAVE|Wx::OVERWRITE_PROMPT
|
227
|
+
super(parent, 'Save Script Output to a File',
|
228
|
+
"", "", 'Output files (*.txt)|*.txt', style)
|
229
|
+
end
|
230
|
+
end
|
128
231
|
end
|
@@ -1,52 +1,132 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'rbconfig'
|
3
|
+
require 'uri'
|
4
|
+
|
1
5
|
module QDA::GUI
|
2
|
-
|
6
|
+
# A dialog that shows if Weft QDA encounters an unhandled exception.
|
7
|
+
# Gathers information about the error, and offers to send it over HTTP
|
8
|
+
# to a crash report CGI.
|
9
|
+
class CrashReportDialog < Wx::Dialog
|
3
10
|
attr_accessor :err
|
11
|
+
attr_reader :panel
|
12
|
+
private :panel
|
13
|
+
|
14
|
+
def initialize(parent, exception)
|
15
|
+
super(nil, -1, Lang::CRASH_REPORT_TITLE)
|
16
|
+
@err = exception
|
4
17
|
|
5
|
-
|
6
|
-
frame = Wx::Frame.new(nil, -1, 'Text')
|
7
|
-
|
8
|
-
panel = Wx::Panel.new(frame)
|
18
|
+
@panel = Wx::Panel.new(self)
|
9
19
|
sizer = Wx::BoxSizer.new(Wx::VERTICAL)
|
20
|
+
text = Wx::StaticText.new(panel, -1, Lang::CRASH_REPORT_MESSAGE)
|
21
|
+
sizer.add(text, 0, Wx::ALL, 8)
|
22
|
+
sizer.add( construct_crash_report_form , 1, Wx::GROW|Wx::ALL, 5)
|
23
|
+
sizer.add( construct_send_buttons, 0,
|
24
|
+
Wx::GROW|Wx::ADJUST_MINSIZE|Wx::ALIGN_BOTTOM, 8)
|
25
|
+
|
26
|
+
panel.set_sizer(sizer)
|
27
|
+
self.client_size = Wx::Size.new(400, 500)
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.display(*args)
|
31
|
+
new(*args).show_modal()
|
32
|
+
end
|
33
|
+
|
34
|
+
def rs2exe
|
35
|
+
if defined? ::RUBYSCRIPT2EXE_EEEEXE
|
36
|
+
return ::RUBYSCRIPT2EXE_EEEEXE
|
37
|
+
else
|
38
|
+
return ''
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def crash_details()
|
43
|
+
@crash ||= { 'when' => Time.now.to_s(),
|
44
|
+
'os' => Config::CONFIG['target_os'],
|
45
|
+
'config' => Config::CONFIG['build'],
|
46
|
+
'ruby_version' => [ Config::CONFIG['MAJOR'],
|
47
|
+
Config::CONFIG['MINOR'],
|
48
|
+
Config::CONFIG['TEENY'] ].join('.'),
|
49
|
+
'rs2exe' => rs2exe,
|
50
|
+
'backtrace' => ( [ err.inspect ] +
|
51
|
+
err.backtrace ).join("\n") }
|
52
|
+
end
|
53
|
+
|
54
|
+
def crash_details_string
|
55
|
+
%w[when os config ruby_version rs2exe backtrace].inject('') do | str, key |
|
56
|
+
str << "#{key}: #{crash_details[key]}\n"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
def encoded_crash_details()
|
62
|
+
str = crash_details.keys.inject('') do | str, key |
|
63
|
+
str << URI.encode(key) << '=' << URI.encode(crash_details[key]) << '&'
|
64
|
+
end
|
65
|
+
str << URI.encode('email') << '=' << URI.encode(@email_box.value) << '&'
|
66
|
+
str << URI.encode('info') << '=' << URI.encode(@info_box.value)
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
def on_dont_send()
|
71
|
+
end_modal(Wx::ID_CANCEL)
|
72
|
+
end
|
73
|
+
|
74
|
+
#
|
75
|
+
def on_send()
|
76
|
+
disable()
|
77
|
+
Wx::BusyCursor.busy do
|
78
|
+
# see weft/wxgui/constants.rb for CRASH_REPORT_URL
|
79
|
+
Net::HTTP.start(CRASH_REPORT_URL.host, 80) do | http |
|
80
|
+
response = http.post(CRASH_REPORT_URL.path, encoded_crash_details)
|
81
|
+
if response.code != '204'
|
82
|
+
ErrorDialog.display( Lang::FAILED_CRASH_SEND_TITLE,
|
83
|
+
Lang::FAILED_CRASH_SEND_MESSAGE %
|
84
|
+
response.inspect )
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end_modal(Wx::ID_OK)
|
89
|
+
end
|
90
|
+
|
91
|
+
def construct_crash_report_form()
|
92
|
+
report_box = Wx::StaticBox.new(panel, -1, Lang::CRASH_REPORT)
|
93
|
+
report_box_sizer = Wx::StaticBoxSizer.new(report_box, Wx::VERTICAL)
|
94
|
+
|
95
|
+
email_label = Wx::StaticText.new(panel, -1, Lang::CRASH_REPORT_EMAIL)
|
96
|
+
report_box_sizer.add(email_label, 0, Wx::ALL, 3)
|
97
|
+
@email_box = Wx::TextCtrl.new(panel, -1, '')
|
98
|
+
report_box_sizer.add(@email_box, 0, Wx::ALL|Wx::GROW, 3)
|
99
|
+
|
100
|
+
info_label = Wx::StaticText.new(panel, -1, Lang::CRASH_REPORT_INFO)
|
101
|
+
report_box_sizer.add(info_label, 0, Wx::ALL, 3)
|
102
|
+
@info_box = Wx::TextCtrl.new(panel, -1, '')
|
103
|
+
report_box_sizer.add(@info_box, 0, Wx::ALL|Wx::GROW, 3)
|
10
104
|
|
11
|
-
|
12
|
-
|
13
|
-
|
105
|
+
data_label = Wx::StaticText.new(panel, -1, Lang::CRASH_REPORT_DATA)
|
106
|
+
report_box_sizer.add(data_label, 0, Wx::ALL, 2)
|
107
|
+
|
108
|
+
@text_box = Wx::TextCtrl.new(panel, -1, crash_details_string(),
|
109
|
+
DEF_POS, DEF_SIZE,
|
110
|
+
Wx::TE_MULTILINE|Wx::TE_RICH|
|
111
|
+
Wx::TE_NOHIDESEL|Wx::TE_READONLY )
|
112
|
+
report_box_sizer.add(@text_box, 1, Wx::ALL|Wx::GROW, 3)
|
113
|
+
return report_box_sizer
|
114
|
+
end
|
115
|
+
|
116
|
+
|
117
|
+
def construct_send_buttons()
|
14
118
|
butt_panel = Wx::Panel.new(panel)
|
15
119
|
bott_sizer = Wx::BoxSizer.new(Wx::HORIZONTAL)
|
16
120
|
|
17
|
-
button = Wx::Button.new(butt_panel, -1, '
|
18
|
-
button.evt_button(button.get_id) { | e |
|
121
|
+
button = Wx::Button.new(butt_panel, -1, "Don't Send")
|
122
|
+
button.evt_button(button.get_id) { | e | on_dont_send() }
|
19
123
|
bott_sizer.add(button, 1, Wx::ALL, 4)
|
20
124
|
|
21
125
|
button = Wx::Button.new(butt_panel, -1, 'Send')
|
22
|
-
button.evt_button(button.get_id) {
|
23
|
-
bott_sizer.add(button, 1, Wx::ALL, 4)
|
24
|
-
|
25
|
-
button = Wx::Button.new(butt_panel, -1, 'Close')
|
26
|
-
button.evt_button(button.get_id) { | e | on_colour(e) }
|
126
|
+
button.evt_button(button.get_id) { on_send }
|
27
127
|
bott_sizer.add(button, 1, Wx::ALL, 4)
|
28
|
-
|
29
128
|
butt_panel.set_sizer(bott_sizer)
|
30
|
-
|
31
|
-
sizer.add(@text_box, 1, Wx::GROW)
|
32
|
-
sizer.add(butt_panel, 0, Wx::GROW|Wx::ADJUST_MINSIZE|Wx::ALIGN_BOTTOM)
|
33
|
-
panel.set_sizer(sizer)
|
34
|
-
|
35
|
-
|
36
|
-
frame.set_client_size( Wx::Size.new(200,200) )
|
37
|
-
frame.show()
|
38
|
-
end
|
39
|
-
|
40
|
-
def on_font(e)
|
41
|
-
dialog = Wx::FontDialog.new()
|
42
|
-
case dialog.show_modal()
|
43
|
-
when Wx::ID_OK
|
44
|
-
font = dialog.get_font_data.get_chosen_font()
|
45
|
-
@text_box.set_font(font)
|
46
|
-
when Wx::ID_CANCEL
|
47
|
-
return
|
48
|
-
end
|
129
|
+
return butt_panel
|
49
130
|
end
|
50
131
|
end
|
51
|
-
|
52
132
|
end
|
@@ -1,208 +1,36 @@
|
|
1
|
-
require 'weft/wxgui/inspectors/textcontrols'
|
2
|
-
|
3
1
|
module QDA::GUI
|
4
|
-
class
|
5
|
-
|
6
|
-
|
7
|
-
MAXIMUM_DROPDOWN_LENGTH = 7
|
8
|
-
attr_accessor :sticky
|
9
|
-
|
10
|
-
# +locked+ if true will prevent the dropdown from responding to
|
11
|
-
# global category focus events.
|
12
|
-
def initialize(app, parent, text_box = nil, locked = false)
|
13
|
-
super(parent, -1, '', Wx::DEFAULT_POSITION,
|
14
|
-
Wx::DEFAULT_SIZE, [])
|
15
|
-
@locked = locked
|
16
|
-
@client_data = {}
|
17
|
-
@text_box = text_box
|
18
|
-
@sticky = false
|
19
|
-
|
20
|
-
@app = app
|
21
|
-
|
22
|
-
evt_kill_focus() do | e |
|
23
|
-
find_and_add_categories()
|
24
|
-
e.skip()
|
25
|
-
end
|
26
|
-
|
27
|
-
evt_text_enter(self.get_id) do | e |
|
28
|
-
find_and_add_categories()
|
29
|
-
end
|
30
|
-
|
31
|
-
evt_combobox(self.get_id) do | e |
|
32
|
-
e.skip()
|
33
|
-
on_item_selected(e)
|
34
|
-
end
|
35
|
-
|
36
|
-
subscribe(:focus_category, :category_deleted, :category_changed)
|
37
|
-
if $wxapp.current_category
|
38
|
-
set_active_category($wxapp.current_category)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
# is this dropdown responding to global :focus_category events?
|
43
|
-
def locked?
|
44
|
-
@locked ? true : false
|
45
|
-
end
|
46
|
-
|
47
|
-
# make this dropdown receive global :focus_category events
|
48
|
-
def lock
|
49
|
-
@locked = true
|
2
|
+
class MDIWorkAreaWindow < Wx::MDIChildFrame
|
3
|
+
def initialize(workarea, *args)
|
4
|
+
super(workarea, -1, *args)
|
50
5
|
end
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
# highlight text coded by the category on the way.
|
58
|
-
def set_selection(idx)
|
59
|
-
super(idx)
|
60
|
-
if @text_box && category = current_category
|
61
|
-
@text_box.highlight_codingtable(category.codes)
|
62
|
-
end
|
6
|
+
end
|
7
|
+
|
8
|
+
class StandaloneWorkAreaWindow < Wx::Frame
|
9
|
+
def initialize(workarea, *args)
|
10
|
+
super(nil, -1, *args)
|
63
11
|
end
|
64
12
|
|
65
|
-
#
|
66
|
-
def
|
67
|
-
|
68
|
-
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
# add the newly-focused category to this dropdown and highlight
|
73
|
-
# its text.
|
74
|
-
def receive_focus_category(cat)
|
75
|
-
set_active_category(cat) unless locked?
|
13
|
+
#
|
14
|
+
def activate()
|
15
|
+
# TODO - raise() doesn't seem to work on GTK
|
16
|
+
shown? ? raise() : show()
|
76
17
|
end
|
18
|
+
end
|
77
19
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
def receive_category_changed(cat)
|
86
|
-
(0 .. count - 1).each do | i |
|
87
|
-
if get_client_data(i).dbid == cat.dbid
|
88
|
-
# TODO set_string not implemented (wxr 0.6.0)
|
89
|
-
# set_string(i, cat.name)
|
90
|
-
# set_client_data(cat.name, cat)
|
91
|
-
prepend(cat) # will automatically delete old
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
def set_active_category(category)
|
97
|
-
# clear the first node unless it is sticky because it has been used
|
98
|
-
unless @sticky
|
99
|
-
delete(0)
|
100
|
-
end
|
101
|
-
# clear any remaining excess items
|
102
|
-
while count > MAXIMUM_DROPDOWN_LENGTH
|
103
|
-
delete(count - 1)
|
104
|
-
end
|
105
|
-
|
106
|
-
prepend(category)
|
107
|
-
@sticky = false
|
108
|
-
set_selection(0)
|
109
|
-
# currently disabled until 0.9.6
|
110
|
-
|
111
|
-
end
|
112
|
-
|
113
|
-
def prepend(category)
|
114
|
-
copy = [ category.name, category ]
|
115
|
-
while count > 0
|
116
|
-
this_text = get_string(0)
|
117
|
-
this_cat = @client_data[this_text]
|
118
|
-
unless this_cat.dbid == category.dbid
|
119
|
-
copy.push( this_text, @client_data[this_text] )
|
120
|
-
end
|
121
|
-
delete(0)
|
122
|
-
end
|
123
|
-
|
124
|
-
until copy.empty?
|
125
|
-
new_text, new_data = copy.shift, copy.shift
|
126
|
-
append(new_text, nil)
|
127
|
-
set_client_data(new_text, new_data)
|
128
|
-
end
|
129
|
-
set_selection(0)
|
130
|
-
end
|
131
|
-
|
132
|
-
# added for compatibility with set_client_data - temporarily
|
133
|
-
# removed in WxRuby 0.4.0, should remove when this is fixed
|
134
|
-
def append(text, category, *args )
|
135
|
-
super(text, nil, *args)
|
136
|
-
set_client_data(text, category )
|
137
|
-
end
|
138
|
-
|
139
|
-
# mimicking WxWidgets method, temp disabled in WxRuby
|
140
|
-
def set_client_data(text, client_data)
|
141
|
-
@client_data[text] = client_data
|
142
|
-
end
|
143
|
-
|
144
|
-
# mimicking ...
|
145
|
-
def get_client_data(index)
|
146
|
-
text = get_string(index)
|
147
|
-
@client_data[text]
|
148
|
-
end
|
149
|
-
|
150
|
-
def find_and_add_categories()
|
151
|
-
typed_text = get_value()
|
152
|
-
unless find_string( typed_text ) || typed_text.empty?
|
153
|
-
matches = @app.app.get_categories_by_path(typed_text)
|
154
|
-
if matches.empty?
|
155
|
-
|
156
|
-
elsif matches.length > 1
|
157
|
-
|
158
|
-
end
|
159
|
-
matches.each { | cat | prepend(cat) unless cat.parent.nil? }
|
160
|
-
set_selection( 0 )
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
def on_blur(e)
|
165
|
-
find_and_add_categories()
|
166
|
-
e.skip()
|
167
|
-
end
|
168
|
-
|
169
|
-
# missing in wxruby, but part of WxWidgets
|
170
|
-
# this version differs by returning nil rather than -1 on failure
|
171
|
-
def find_string(str)
|
172
|
-
( 0 ... count ).each do | i |
|
173
|
-
return i if str == get_string(i)
|
174
|
-
end
|
175
|
-
return nil
|
176
|
-
end
|
177
|
-
|
178
|
-
|
179
|
-
# TODO - some visual cue to indicate that no category matched find-first
|
180
|
-
def set_broken(bool)
|
181
|
-
|
182
|
-
end
|
183
|
-
|
184
|
-
def set_warning(bool)
|
185
|
-
|
186
|
-
end
|
187
|
-
# returns the Category object associated with the currently
|
188
|
-
# selected item in the drop down.
|
189
|
-
def current_category
|
190
|
-
if curr_sel = get_selection()
|
191
|
-
if curr_sel.nil? || curr_sel == -1
|
192
|
-
return nil
|
193
|
-
end
|
194
|
-
return get_client_data( curr_sel )
|
195
|
-
end
|
196
|
-
end
|
20
|
+
if WINDOW_MODE == :MDI
|
21
|
+
WorkAreaWindowBaseClass = MDIWorkAreaWindow
|
22
|
+
else
|
23
|
+
WorkAreaWindowBaseClass = StandaloneWorkAreaWindow
|
197
24
|
end
|
198
25
|
|
199
|
-
class WorkAreaWindow <
|
26
|
+
class WorkAreaWindow < WorkAreaWindowBaseClass
|
200
27
|
# the default size for new windows of this type and
|
201
28
|
# subclasses. Expressed as a proportion of MDI client area width
|
202
29
|
# and MDI client area height.
|
203
30
|
W_WINDOW_DEF_SIZE = [ 0.6, 0.8 ]
|
204
31
|
|
205
32
|
def initialize(workarea, title, last_layout)
|
33
|
+
@workarea = workarea
|
206
34
|
size = pos = nil
|
207
35
|
if last_layout
|
208
36
|
size = Wx::Size.new( last_layout[:w], last_layout[:h] )
|
@@ -212,9 +40,15 @@ module QDA::GUI
|
|
212
40
|
size = workarea.proportional_size(*proportions)
|
213
41
|
pos = Wx::DEFAULT_POSITION
|
214
42
|
end
|
215
|
-
super(workarea,
|
43
|
+
super(workarea, title, pos, size)
|
44
|
+
evt_set_focus() { | e | on_focus() }
|
216
45
|
end
|
217
46
|
|
47
|
+
#
|
48
|
+
def on_focus()
|
49
|
+
@workarea.active_child = self
|
50
|
+
end
|
51
|
+
|
218
52
|
# returns a hash serialising the current shape and location of
|
219
53
|
# this window, so it can later be unthawed
|
220
54
|
def layout()
|
@@ -239,17 +73,19 @@ module QDA::GUI
|
|
239
73
|
|
240
74
|
# a WorkArea Window with a notebook layout with a coding panel
|
241
75
|
# including a text display in the first pane. Documents, Categories
|
242
|
-
# and Queries are all displayed using this model
|
76
|
+
# and Queries are all displayed using this model.
|
243
77
|
class InspectorWindow < WorkAreaWindow
|
244
|
-
if Wx::RUBY_PLATFORM == 'WXGTK'
|
78
|
+
if Wx::RUBY_PLATFORM == 'WXGTK' and WINDOW_MODE == :MDI
|
245
79
|
# GTK uses a notebook to fake MDI windows, so if running under
|
246
|
-
# WXGTK, place the real notebook tabs on the
|
80
|
+
# WXGTK and using MDI mode, place the real notebook tabs on the
|
81
|
+
# right instead. Note that this combo (GTK+MDI) is not recommended
|
247
82
|
INSPECTOR_NB_STYLE = [ Wx::DEFAULT_POSITION, Wx::DEFAULT_SIZE,
|
248
83
|
Wx::NB_RIGHT ]
|
249
84
|
else
|
250
85
|
INSPECTOR_NB_STYLE = []
|
251
86
|
end
|
252
|
-
|
87
|
+
attr_reader :client
|
88
|
+
|
253
89
|
def initialize(workarea, title, last_layout, &text_constructor)
|
254
90
|
super(workarea, title, last_layout)
|
255
91
|
|
@@ -258,22 +94,29 @@ module QDA::GUI
|
|
258
94
|
sizer_1 = Wx::BoxSizer.new(Wx::VERTICAL)
|
259
95
|
|
260
96
|
@text_box = text_constructor.call(panel_1)
|
97
|
+
@text_box.evt_key_down { | e | on_key_down(e) }
|
261
98
|
sizer_1.add(@text_box, 10, Wx::GROW|Wx::ALL, 4)
|
262
99
|
|
263
100
|
butt_panel = Wx::Panel.new(panel_1, -1)
|
264
101
|
bott_sizer = Wx::BoxSizer.new(Wx::HORIZONTAL)
|
265
102
|
|
266
|
-
@drop_down = CategoryDropDown.new(
|
103
|
+
@drop_down = CategoryDropDown.new(client, butt_panel, @text_box)
|
267
104
|
bott_sizer.add(@drop_down, 3, Wx::ALL, 4)
|
268
105
|
|
269
|
-
button = Wx::Button.new(butt_panel, -1, '
|
106
|
+
button = Wx::Button.new(butt_panel, -1, 'Mark')
|
270
107
|
button.evt_button(button.get_id) { | e | on_code(e) }
|
271
108
|
bott_sizer.add(button, 1, Wx::ALL, 4)
|
272
109
|
|
273
|
-
button = Wx::Button.new(butt_panel, -1, '
|
110
|
+
button = Wx::Button.new(butt_panel, -1, 'Unmark')
|
274
111
|
button.evt_button(button.get_id) { | e | on_uncode(e) }
|
275
112
|
bott_sizer.add(button, 1, Wx::ALL, 4)
|
276
|
-
|
113
|
+
|
114
|
+
if @text_box.respond_to?(:start_find)
|
115
|
+
button = Wx::Button.new(butt_panel, -1, 'Find')
|
116
|
+
button.evt_button(button.get_id) { @text_box.start_find(self) }
|
117
|
+
bott_sizer.add(button, 1, Wx::ALL, 4)
|
118
|
+
end
|
119
|
+
|
277
120
|
# button = Wx::Button.new(butt_panel, -1, 'Note')
|
278
121
|
# button.evt_button(button.get_id) { | e | on_code(e) }
|
279
122
|
# bott_sizer.add(button, 1, Wx::ALL, 4, Wx::ALIGN_RIGHT)
|
@@ -286,6 +129,7 @@ module QDA::GUI
|
|
286
129
|
panel_1.set_sizer( sizer_1 )
|
287
130
|
@notebook.add_page(panel_1, 'text')
|
288
131
|
evt_activate() { | e | on_activate(e) }
|
132
|
+
subscribe(client, :text_font_changed)
|
289
133
|
end
|
290
134
|
|
291
135
|
# (hopefully temporary) method -- when this window is closed,
|
@@ -315,9 +159,8 @@ module QDA::GUI
|
|
315
159
|
codes = @text_box.selection_to_fragments()
|
316
160
|
codes.each { | c | category.code(c.docid, c.offset, c.length) }
|
317
161
|
|
318
|
-
|
162
|
+
@client.app.save_category( category )
|
319
163
|
@drop_down.sticky = true
|
320
|
-
$wxapp.broadcast(:category_changed, category )
|
321
164
|
end
|
322
165
|
end
|
323
166
|
|
@@ -327,14 +170,24 @@ module QDA::GUI
|
|
327
170
|
Wx::BusyCursor.busy do
|
328
171
|
codes = @text_box.selection_to_fragments()
|
329
172
|
codes.each { | c | category.uncode(c.docid, c.offset, c.length) }
|
330
|
-
|
173
|
+
@client.app.save_category( category )
|
331
174
|
@drop_down.sticky = true
|
332
|
-
$wxapp.broadcast(:category_changed, category )
|
333
175
|
end
|
334
176
|
end
|
335
177
|
|
336
|
-
|
337
|
-
|
178
|
+
# implements keyboard shortcuts for this window - these are activated by
|
179
|
+
# interaction with the text-box.
|
180
|
+
# currently, CTRL-k is mapped to "Code" and CTRL-l is mapped to "Uncode"
|
181
|
+
def on_key_down(evt)
|
182
|
+
return unless evt.control_down()
|
183
|
+
case evt.key_code()
|
184
|
+
when 70 # "f"
|
185
|
+
@text_box.start_find(self) if @text_box.respond_to?(:start_find)
|
186
|
+
when 77 # "m"
|
187
|
+
on_code(evt)
|
188
|
+
when 44 # ","
|
189
|
+
on_uncode(evt)
|
190
|
+
end
|
338
191
|
end
|
339
192
|
|
340
193
|
# the current category active in this window
|
@@ -347,7 +200,7 @@ module QDA::GUI
|
|
347
200
|
end
|
348
201
|
|
349
202
|
# set the display font for use in this inspector
|
350
|
-
def
|
203
|
+
def receive_text_font_changed(font)
|
351
204
|
@text_box.set_font(font)
|
352
205
|
end
|
353
206
|
end
|
@@ -355,7 +208,7 @@ module QDA::GUI
|
|
355
208
|
require 'weft/wxgui/inspectors/document.rb'
|
356
209
|
require 'weft/wxgui/inspectors/category.rb'
|
357
210
|
# require 'weft/wxgui/inspectors/imagedocument.rb'
|
358
|
-
require 'weft/wxgui/inspectors/
|
211
|
+
require 'weft/wxgui/inspectors/query.rb'
|
359
212
|
require 'weft/wxgui/inspectors/script.rb'
|
360
213
|
require 'weft/wxgui/inspectors/codereview.rb'
|
361
214
|
end
|