weft-qda 0.9.6 → 0.9.8
Sign up to get free protection for your applications and to get access to all the features.
- 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/query.rb
ADDED
@@ -0,0 +1,169 @@
|
|
1
|
+
# A stub class modelling a boolean query expression
|
2
|
+
module QDA
|
3
|
+
class Query
|
4
|
+
attr_accessor :dbid, :root
|
5
|
+
|
6
|
+
def initialize( func = nil )
|
7
|
+
@root = func
|
8
|
+
end
|
9
|
+
|
10
|
+
def add_expression(expr, arg_2 = nil)
|
11
|
+
begin
|
12
|
+
expr_class = self.class.const_get( expr.upcase.gsub(/\s+/, '_') )
|
13
|
+
rescue NameError
|
14
|
+
raise ArgumentError.new("Unknown expression '#{expr}'")
|
15
|
+
end
|
16
|
+
@root = expr_class.new(@root, arg_2)
|
17
|
+
end
|
18
|
+
|
19
|
+
def empty?()
|
20
|
+
@root.nil?
|
21
|
+
end
|
22
|
+
|
23
|
+
def items(entry = @root)
|
24
|
+
entry.to_a.flatten
|
25
|
+
end
|
26
|
+
|
27
|
+
def traverse(entry = @root)
|
28
|
+
items(entry).each { | expr | yield(expr) }
|
29
|
+
end
|
30
|
+
|
31
|
+
# Yields a series of pairs of functions and expressions, in the evaluating
|
32
|
+
# left-to-right order of the query. Note that in the last iteration, the
|
33
|
+
# +expr+ will be nil.
|
34
|
+
#
|
35
|
+
# query.unroll { | func, expr | ... }
|
36
|
+
#
|
37
|
+
def unroll(entry = @root)
|
38
|
+
things = items(entry)
|
39
|
+
while func = things.shift
|
40
|
+
yield func, things.shift
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def num_functions()
|
45
|
+
items.grep(Function).length
|
46
|
+
end
|
47
|
+
|
48
|
+
def num_expressions()
|
49
|
+
items.grep(LogicalExpression).length
|
50
|
+
end
|
51
|
+
|
52
|
+
def calculate()
|
53
|
+
@root.calculate()
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_s()
|
57
|
+
@root.to_s()
|
58
|
+
end
|
59
|
+
class Function
|
60
|
+
def initialize(app = nil)
|
61
|
+
@app = app
|
62
|
+
end
|
63
|
+
|
64
|
+
def to_a
|
65
|
+
[ self ]
|
66
|
+
end
|
67
|
+
|
68
|
+
def calculated?()
|
69
|
+
true
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class CodedByFunction < Function
|
74
|
+
attr_reader :identifier
|
75
|
+
def initialize(app, identifier)
|
76
|
+
super(app)
|
77
|
+
case identifier
|
78
|
+
when Category # a category specified directly
|
79
|
+
@identifier = identifier.path
|
80
|
+
when String # a path to a category
|
81
|
+
@identifier = identifier
|
82
|
+
when Fixnum # a category id
|
83
|
+
@identifier = @app.get_category(identifier, false).path
|
84
|
+
when NilClass
|
85
|
+
raise ArgumentError.new("Unspecified category for CODED BY expression")
|
86
|
+
else
|
87
|
+
raise ArgumentError.new("Invalid value '#{identifier}' for CODED BY function")
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def to_s()
|
92
|
+
"( CODED BY(#{@identifier.inspect}) )"
|
93
|
+
end
|
94
|
+
|
95
|
+
def calculate()
|
96
|
+
cat = @app.get_category(@identifier, false)
|
97
|
+
@app.get_text_at_category( cat )
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
class WordSearchFunction < Function
|
102
|
+
attr_reader :word
|
103
|
+
def initialize(app, word, options = {})
|
104
|
+
super(app)
|
105
|
+
if word.empty?
|
106
|
+
raise ArgumentError.new('No word supplied for CONTAINS WORD function')
|
107
|
+
end
|
108
|
+
@word = word
|
109
|
+
@options = options
|
110
|
+
end
|
111
|
+
|
112
|
+
def to_s()
|
113
|
+
"( SEARCH(#{@word.inspect}) )"
|
114
|
+
end
|
115
|
+
|
116
|
+
def calculate()
|
117
|
+
@app.get_search_fragments(@word, @options)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
class LogicalExpression
|
122
|
+
attr_reader :arg_1, :arg_2
|
123
|
+
private :arg_1, :arg_2
|
124
|
+
def initialize(arg_1, arg_2)
|
125
|
+
@arg_1, @arg_2 = arg_1, arg_2
|
126
|
+
end
|
127
|
+
|
128
|
+
def to_a()
|
129
|
+
[ @arg_1.to_a, self, @arg_2.to_a ]
|
130
|
+
end
|
131
|
+
|
132
|
+
def val_1()
|
133
|
+
@arg_1.respond_to?(:calculate) ? @arg_1.calculate : @arg_1
|
134
|
+
end
|
135
|
+
|
136
|
+
def val_2()
|
137
|
+
@arg_2.respond_to?(:calculate) ? @arg_2.calculate : @arg_2
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
class OR < LogicalExpression
|
142
|
+
def calculate()
|
143
|
+
val_1.dup.merge(val_2)
|
144
|
+
end
|
145
|
+
|
146
|
+
def to_s
|
147
|
+
"( #{arg_1} OR #{@arg_2} )"
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
class AND < LogicalExpression
|
152
|
+
def calculate()
|
153
|
+
val_1.dup.join(val_2)
|
154
|
+
end
|
155
|
+
def to_s
|
156
|
+
"( #{arg_1} AND #{arg_2} )"
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
class AND_NOT < LogicalExpression
|
161
|
+
def calculate()
|
162
|
+
val_1.dup.remove(val_2)
|
163
|
+
end
|
164
|
+
def to_s
|
165
|
+
"( #{arg_1} AND NOT #{arg_2} )"
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
data/lib/weft/wxgui.rb
CHANGED
@@ -1,30 +1,11 @@
|
|
1
1
|
require 'wxruby'
|
2
|
-
require 'stringio'
|
3
|
-
|
4
|
-
# temporary hack to turn c++ style set_foo(), get_foo() and is_foo()
|
5
|
-
# accessors into ruby style foo=() foo() and foo?()
|
6
|
-
wx_classes = Wx::constants.collect { | c | Wx::const_get(c) }.grep(Class)
|
7
|
-
wx_classes.each do | klass |
|
8
|
-
klass.instance_methods.grep(/^([gs]et|evt|is)_/).each do | meth |
|
9
|
-
case meth
|
10
|
-
when /^get_(\w+)$/
|
11
|
-
klass.class_eval("alias :#{$1} :#{meth}")
|
12
|
-
when /^set_(\w+)$/
|
13
|
-
klass.class_eval("alias :#{$1}= :#{meth}")
|
14
|
-
when /^is_(\w+)$/
|
15
|
-
klass.class_eval("alias :#{$1}? :#{meth}")
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
# one global variable holds a reference to the single instance of the
|
21
|
-
# Wx::App class. This allows widgets deep within the GUI to receive
|
22
|
-
# notifications from the top level of the GUI.
|
23
|
-
$wxapp = nil
|
24
2
|
|
3
|
+
require 'weft/wxgui/constants'
|
25
4
|
require 'weft/wxgui/utilities'
|
5
|
+
require 'weft/wxgui/exceptions'
|
26
6
|
require 'weft/wxgui/lang'
|
27
7
|
|
8
|
+
require 'weft/wxgui/controls'
|
28
9
|
require 'weft/wxgui/dialogs'
|
29
10
|
require 'weft/wxgui/inspectors'
|
30
11
|
require 'weft/wxgui/sidebar'
|
@@ -34,42 +15,62 @@ require 'weft/wxgui/error_handler.rb'
|
|
34
15
|
|
35
16
|
module QDA
|
36
17
|
module GUI
|
37
|
-
# save some typing
|
38
|
-
DEF_POS = Wx::DEFAULT_POSITION
|
39
|
-
DEF_SIZE = Wx::DEFAULT_SIZE
|
40
|
-
|
41
18
|
# the default display font for text
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
19
|
+
DEFAULT_FONT = Wx::Font.new(10, Wx::DEFAULT, Wx::NORMAL, Wx::NORMAL)
|
20
|
+
class WeftClient < Wx::App
|
21
|
+
attr_reader :display_font, :workarea, :sidebar, :app
|
22
|
+
attr_reader :current_category, :current_document
|
23
|
+
|
48
24
|
include Wx
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
25
|
+
include Broadcaster
|
26
|
+
include Subscriber
|
27
|
+
SUBSCRIBABLE_EVENTS = QDA::Application::SUBSCRIBABLE_EVENTS +
|
28
|
+
[ :focus_category, :focus_document, :text_font_changed ]
|
53
29
|
|
54
30
|
def on_init()
|
55
|
-
|
31
|
+
self.app_name = 'WeftQDA'
|
32
|
+
# retrieve font
|
33
|
+
conf = Wx::ConfigBase.get()
|
34
|
+
conf.path = '/DisplayFont'
|
35
|
+
@display_font = Wx::Font.new( conf.read_int('size', 12),
|
36
|
+
conf.read_int('family', Wx::DEFAULT),
|
37
|
+
conf.read_int('style', Wx::NORMAL),
|
38
|
+
conf.read_int('weight', Wx::NORMAL),
|
39
|
+
false,
|
40
|
+
conf.read('face', '') )
|
56
41
|
# see wxgui/lang.rb
|
57
42
|
Lang::set_language('En')
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
# check if running under rubyscript2exe?
|
63
|
-
@icon_dirs = $:.dup << File.join( File.dirname( __FILE__ ), 'wxgui')
|
43
|
+
@icon_dirs = []
|
44
|
+
add_icon_dir( File.join( WEFT_SHAREDIR, 'icons') )
|
45
|
+
add_icon_dir( File.join( File.dirname( __FILE__ ), 'wxgui') )
|
64
46
|
create_workarea()
|
65
47
|
create_menus()
|
66
48
|
@workarea.show()
|
67
49
|
end
|
68
|
-
|
50
|
+
|
51
|
+
|
52
|
+
def main_loop()
|
53
|
+
super()
|
54
|
+
rescue Exception => err
|
55
|
+
if REPORT_CRASHES and not err.kind_of? SystemExit
|
56
|
+
workarea.hide_all()
|
57
|
+
CrashReportDialog.display(self, err)
|
58
|
+
end
|
59
|
+
Kernel.raise(err)
|
60
|
+
end
|
61
|
+
|
62
|
+
def app=(the_app)
|
63
|
+
if the_app
|
64
|
+
subscribe(the_app, :all)
|
65
|
+
else
|
66
|
+
@app.end()
|
67
|
+
end
|
68
|
+
@app = the_app
|
69
|
+
end
|
70
|
+
|
69
71
|
# forcibly closes all the windows - does not check for project
|
70
72
|
# saved state - just ends everything
|
71
73
|
def finish()
|
72
|
-
@sidebar.close() if @sidebar
|
73
74
|
@workarea.close()
|
74
75
|
end
|
75
76
|
|
@@ -78,8 +79,8 @@ module QDA
|
|
78
79
|
def create_workarea()
|
79
80
|
@workarea = WorkArea.new(self)
|
80
81
|
# TODO - nice windows icon
|
81
|
-
@workarea.set_icon( fetch_icon("
|
82
|
-
@workarea.evt_close() { | e |
|
82
|
+
@workarea.set_icon( fetch_icon("weft") )
|
83
|
+
@workarea.evt_close() { | e | on_quit(e) }
|
83
84
|
end
|
84
85
|
|
85
86
|
# create menus - also only created once, then manipulated as
|
@@ -102,21 +103,44 @@ module QDA
|
|
102
103
|
@menu_file.add_item("Save Project &As", "Ctrl-Shift-S") do | e |
|
103
104
|
on_saveas_project(e)
|
104
105
|
end
|
105
|
-
@menu_file.add_item("&
|
106
|
-
|
106
|
+
@menu_file.add_item("&Revert", "Ctrl-Shift-R") do | e |
|
107
|
+
on_revert_project(e)
|
107
108
|
end
|
108
109
|
@menu_file.append_separator()
|
109
110
|
@menu_file.add_item("&Exit", "Alt-F4") do | e |
|
110
|
-
@workarea.close()
|
111
|
+
@workarea.close() # this will trigger on_quit
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
@menu_view = EasyMenu.new(@workarea)
|
116
|
+
if WINDOW_MODE == :MDI
|
117
|
+
@menu_view.add_item("&Documents and Categories", "",
|
118
|
+
Wx::ITEM_CHECK) { | e | on_toggle_dandc(e) }
|
111
119
|
end
|
112
120
|
|
121
|
+
@menu_view.add_item("&Set Display Font") do | e |
|
122
|
+
on_set_display_font(e)
|
123
|
+
end
|
124
|
+
|
113
125
|
@menu_project = EasyMenu.new(@workarea)
|
114
126
|
@menu_project.add_item("&Import Document") do | e |
|
115
127
|
on_import_document(e)
|
116
128
|
end
|
117
|
-
|
118
|
-
|
129
|
+
@menu_project.add_item("Delete Document") do | e |
|
130
|
+
on_delete_document(e)
|
119
131
|
end
|
132
|
+
@menu_project.append_separator()
|
133
|
+
@menu_project.add_item("&Add Category") do | e |
|
134
|
+
on_add_category()
|
135
|
+
end
|
136
|
+
@menu_project.add_item("Delete Category") do | e |
|
137
|
+
on_delete_category(e)
|
138
|
+
end
|
139
|
+
@menu_project.append_separator()
|
140
|
+
@menu_project.add_item("&Export") do | e |
|
141
|
+
on_export(e)
|
142
|
+
end
|
143
|
+
|
120
144
|
# menu_project.append(MENU_IMPORT_DOCUMENT_CLIPBOARD ,
|
121
145
|
# "&Import Document...\t", 'Import')
|
122
146
|
# @workarea.evt_menu(MENU_IMPORT_DOCUMENT_CLIPBOARD) do | e |
|
@@ -139,9 +163,6 @@ module QDA
|
|
139
163
|
@menu_script.add_item("&New") { | e | on_start_script(e) }
|
140
164
|
end
|
141
165
|
|
142
|
-
@menu_view = EasyMenu.new(@workarea)
|
143
|
-
@menu_view.add_item("&Documents and Categories", "",
|
144
|
-
Wx::ITEM_CHECK) { | e | on_toggle_dandc(e) }
|
145
166
|
|
146
167
|
@menu_help = EasyMenu.new(@workarea)
|
147
168
|
@menu_help.add_item("&Help") { | e | on_help(e) }
|
@@ -150,21 +171,14 @@ module QDA
|
|
150
171
|
|
151
172
|
menu_bar = Wx::MenuBar.new()
|
152
173
|
menu_bar.append(@menu_file, "&File")
|
174
|
+
menu_bar.append(@menu_view, "&View")
|
153
175
|
menu_bar.append(@menu_project, "&Project")
|
154
176
|
menu_bar.append(@menu_search, "&Search")
|
155
177
|
menu_bar.append(@menu_script, "&Script") if ::WEFT_TESTING
|
156
|
-
menu_bar.append(@menu_view, "&View")
|
157
178
|
menu_bar.append(@menu_help, "&Help")
|
158
179
|
|
159
180
|
@workarea.menu_bar = menu_bar
|
160
181
|
end
|
161
|
-
|
162
|
-
def current_category
|
163
|
-
if @sidebar.tree_list.get_current_category()
|
164
|
-
return @app.get_category( @sidebar.tree_list.get_current_category().dbid )
|
165
|
-
end
|
166
|
-
return nil
|
167
|
-
end
|
168
182
|
|
169
183
|
# opens the document identified by +doc_id+, and, if +offset+ is
|
170
184
|
# supplied, jumps to that point in the document
|
@@ -175,95 +189,75 @@ module QDA
|
|
175
189
|
win.jump_to(offset)
|
176
190
|
end
|
177
191
|
|
192
|
+
|
193
|
+
def display_font=(font)
|
194
|
+
broadcast(:text_font_changed, font)
|
195
|
+
@display_font = font
|
196
|
+
# font.get_native_font_info_desc would be nicer, but
|
197
|
+
# set_native_font_info doesn't appear to work in WxRuby 0.6.0
|
198
|
+
conf = Wx::ConfigBase.get()
|
199
|
+
conf.path = '/DisplayFont'
|
200
|
+
conf.write("size", font.point_size)
|
201
|
+
conf.write("family", font.family)
|
202
|
+
conf.write("style", font.style)
|
203
|
+
conf.write("weight", font.weight)
|
204
|
+
conf.write("face", font.face_name)
|
205
|
+
end
|
206
|
+
|
178
207
|
def on_set_display_font(e)
|
179
208
|
font_data = Wx::FontData.new()
|
180
|
-
font_data.initial_font =
|
209
|
+
font_data.initial_font = display_font
|
181
210
|
dialog = Wx::FontDialog.new(@workarea, font_data)
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
# font.get_native_font_info_desc would be nicer, but
|
187
|
-
# set_native_font_info doesn't appear to work in WxRuby 0.5.0
|
188
|
-
@app.save_preference('DisplayFont',
|
189
|
-
:size => font.point_size,
|
190
|
-
:family => font.family,
|
191
|
-
:style => font.style,
|
192
|
-
:weight => font.weight,
|
193
|
-
:face => font.face_name )
|
194
|
-
when Wx::ID_CANCEL
|
195
|
-
return
|
196
|
-
end
|
211
|
+
return unless dialog.show_modal() == Wx::ID_OK
|
212
|
+
|
213
|
+
# actually find the newly selected font and communicate new choice
|
214
|
+
self.display_font = dialog.font_data.chosen_font()
|
197
215
|
end
|
198
216
|
|
199
217
|
def on_search_reindex(e)
|
200
|
-
confirm =
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
begin
|
220
|
-
new_doc = filter.read(doc, doc.doctitle)
|
221
|
-
rescue Exception => err
|
222
|
-
MessageDialog.new(nil, err.to_s + caller.to_s,
|
223
|
-
"Cannot reindex document",
|
224
|
-
OK|ICON_ERROR).show_modal()
|
225
|
-
return()
|
226
|
-
end
|
227
|
-
|
228
|
-
begin
|
229
|
-
wordcount = indexer.words.keys.length
|
230
|
-
prog = WordIndexSaveProgressTracker.new( wordcount, @workarea,
|
231
|
-
doc.doctitle )
|
232
|
-
@app.save_reverse_index(doc.dbid, indexer.words, prog)
|
233
|
-
rescue Exception => err
|
234
|
-
MessageDialog.new(nil, err.to_s,
|
235
|
-
"Cannot reindex document",
|
236
|
-
OK|ICON_ERROR).show_modal()
|
237
|
-
ensure
|
238
|
-
prog.progbar.close()
|
218
|
+
confirm = WarningDialog.display( Lang::REINDEX_DOCS_WARNING_TITLE,
|
219
|
+
Lang::REINDEX_DOCS_WARNING )
|
220
|
+
return true unless confirm == Wx::ID_YES
|
221
|
+
|
222
|
+
Wx::BusyCursor.busy do
|
223
|
+
begin
|
224
|
+
docs = @app.get_all_docs()
|
225
|
+
prog = StageProgressDialog.new(@workarea,
|
226
|
+
"Reindexing documents", '')
|
227
|
+
|
228
|
+
prog.retarget(docs.length + 2)
|
229
|
+
docs.each do | doc |
|
230
|
+
prog.step("Indexing document #{doc.title}")
|
231
|
+
doc = @app.get_doc(doc.dbid)
|
232
|
+
@app.drop_reverse_indexes(doc.dbid)
|
233
|
+
indexer = QDA::WordIndexer.new()
|
234
|
+
indexer.feed(doc)
|
235
|
+
@app.save_reverse_index(doc.dbid, indexer.words)
|
239
236
|
end
|
240
|
-
|
237
|
+
prog.finish()
|
238
|
+
rescue UserAbortedException => err
|
239
|
+
prog.finish() if prog
|
240
|
+
ErrorDialog.display("Reindex halted", err.to_s())
|
241
|
+
@workarea.cursor = Wx::NORMAL_CURSOR
|
242
|
+
end
|
241
243
|
end
|
242
244
|
end
|
243
245
|
|
244
|
-
def change_display_font(font)
|
245
|
-
@workarea.set_display_font(@display_font = font)
|
246
|
-
end
|
247
|
-
|
248
246
|
def on_help(e)
|
249
|
-
|
250
|
-
OK|ICON_INFORMATION).show_modal()
|
251
|
-
|
247
|
+
InformationDialog.display('Help', Lang::HELP_HELP_MESSAGE)
|
252
248
|
end
|
253
249
|
|
254
250
|
def on_help_about(e)
|
255
|
-
|
256
|
-
OK|ICON_INFORMATION).show_modal()
|
251
|
+
InformationDialog.display('About', Lang::HELP_ABOUT_MESSAGE)
|
257
252
|
end
|
258
253
|
|
259
254
|
def on_category_open(cat)
|
255
|
+
if not cat.codes
|
256
|
+
cat = @app.get_category(cat.dbid)
|
257
|
+
end
|
260
258
|
@workarea.launch_window(CategoryWindow, cat)
|
261
259
|
end
|
262
260
|
|
263
|
-
class Script
|
264
|
-
attr_accessor :dbid
|
265
|
-
end
|
266
|
-
|
267
261
|
# run a new query
|
268
262
|
def on_start_script(e)
|
269
263
|
s_id = @app.get_preference('NextScript') || 1
|
@@ -279,99 +273,133 @@ module QDA
|
|
279
273
|
|
280
274
|
# import a document
|
281
275
|
def import_document()
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
ext = fpath[-3, 3].downcase
|
292
|
-
if ext == 'txt'
|
293
|
-
filter = QDA::TextFilter.new()
|
294
|
-
elsif ext == 'pdf'
|
295
|
-
filter = QDA::PDFFilter.new()
|
296
|
-
else
|
297
|
-
# as a last shot, try importing the file as plaing text
|
298
|
-
filter = QDA::TextFilter.new()
|
299
|
-
end
|
300
|
-
|
301
|
-
Wx::BusyCursor.busy do
|
302
|
-
doc_title = file_dialog.get_filenames[i].gsub(/\.\w+$/, '')
|
303
|
-
indexer = QDA::WordIndexer.new()
|
304
|
-
filter.add_indexer(indexer)
|
305
|
-
tracker = DocumentImportProgressTracker.new( @workarea,
|
306
|
-
doc_title )
|
307
|
-
filter.add_indexer(tracker)
|
308
|
-
|
309
|
-
# try and import it
|
310
|
-
begin
|
311
|
-
doc = filter.read(fpath, doc_title)
|
312
|
-
rescue Exception => err
|
313
|
-
p err
|
314
|
-
tracker.terminate()
|
315
|
-
MessageDialog.new(nil, err.to_s,
|
316
|
-
"Cannot import document",
|
317
|
-
OK|ICON_ERROR).show_modal()
|
318
|
-
@workarea.cursor = Wx::Cursor.new(Wx::CURSOR_ARROW)
|
319
|
-
ensure
|
276
|
+
file_dialog = ImportFileDialog.new(@workarea, QDA::Document)
|
277
|
+
return unless file_dialog.show_modal() == Wx::ID_OK
|
278
|
+
file_dialog.each_with_path do | fpath, fname |
|
279
|
+
Wx::BusyCursor.busy do
|
280
|
+
prog = StageProgressDialog.new(@workarea, "Importing document",
|
281
|
+
"Reading file #{fname}")
|
282
|
+
begin
|
283
|
+
doc = Filters.import_file(Document, fpath) do | doc, filter |
|
284
|
+
doc.title = fname.gsub(/\.\w+$/, '')
|
320
285
|
end
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
@app.save_reverse_index(doc.dbid, indexer.words, prog)
|
332
|
-
end
|
333
|
-
rescue Exception => err
|
334
|
-
prog.terminate() if prog
|
335
|
-
@app.delete_document(doc.dbid) if doc.dbid
|
336
|
-
MessageDialog.new(nil, err.to_s,
|
337
|
-
"Cannot import document",
|
338
|
-
OK|ICON_ERROR).show_modal()
|
339
|
-
@workarea.cursor = Wx::Cursor.new(Wx::CURSOR_ARROW)
|
340
|
-
return
|
341
|
-
ensure
|
342
|
-
|
286
|
+
prog.step('Saving document')
|
287
|
+
@app.save_document(doc, true)
|
288
|
+
prog.step('Indexing document')
|
289
|
+
indexer = QDA::WordIndexer.new()
|
290
|
+
indexer.feed(doc)
|
291
|
+
prog.step('Saving indexes')
|
292
|
+
wordcount = indexer.words.keys.length
|
293
|
+
if wordcount > 0
|
294
|
+
prog.retarget(wordcount)
|
295
|
+
@app.save_reverse_index(doc.dbid, indexer.words, prog)
|
343
296
|
end
|
344
|
-
|
297
|
+
prog.finish()
|
298
|
+
rescue UserAbortedException, IOError => err
|
299
|
+
prog.finish() if prog
|
300
|
+
app.delete_document(doc) if doc && doc.dbid
|
301
|
+
MessageDialog.new(nil, err.to_s(),
|
302
|
+
"Document not imported",
|
303
|
+
OK|ICON_ERROR).show_modal()
|
304
|
+
@workarea.cursor = Wx::Cursor.new(Wx::CURSOR_ARROW)
|
345
305
|
end
|
346
306
|
end
|
347
307
|
end
|
348
308
|
end
|
349
309
|
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
310
|
+
def on_delete_document(e = nil)
|
311
|
+
return unless current_document
|
312
|
+
msg = Lang::DELETE_DOCUMENT_WARNING % current_document.title
|
313
|
+
confirm = SuppressibleConfirmDialog.display('DeleteDocument',
|
314
|
+
Lang::DELETE_DOCUMENT_TITLE,
|
315
|
+
msg )
|
316
|
+
return unless confirm == Wx::ID_YES
|
317
|
+
Wx::BusyCursor.busy do
|
318
|
+
@app.delete_document( current_document )
|
319
|
+
end
|
354
320
|
end
|
321
|
+
|
322
|
+
def on_add_category()
|
323
|
+
dialog = Wx::TextEntryDialog.new(@workarea.d_and_c, "Add Category\n",
|
324
|
+
"Enter the new category name",
|
325
|
+
"", Wx::OK | Wx::CANCEL)
|
326
|
+
return unless dialog.show_modal() == Wx::ID_OK
|
327
|
+
|
328
|
+
# go ahead and make the new category
|
329
|
+
parent = self.current_category || @app.get_root_category('CATEGORIES')
|
330
|
+
name = dialog.get_value()
|
331
|
+
begin
|
332
|
+
cat = QDA::Category.new(name, parent )
|
333
|
+
@app.save_category(cat)
|
334
|
+
rescue QDA::BadNameError
|
335
|
+
ErrorDialog.display( Lang::BAD_CATEGORY_NAME_TITLE,
|
336
|
+
Lang::BAD_CATEGORY_NAME_WARNING )
|
337
|
+
return false
|
338
|
+
rescue QDA::NotUniqueNameError
|
339
|
+
ErrorDialog.display( Lang::DUPLICATE_CATEGORY_NAME_TITLE,
|
340
|
+
Lang::DUPLICATE_CATEGORY_NAME_WARNING )
|
341
|
+
return false
|
342
|
+
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
# deletes the currently active category
|
347
|
+
def on_delete_category(e = nil)
|
348
|
+
return false unless current_category
|
349
|
+
msg = Lang::DELETE_CATEGORY_WARNING % current_category.name
|
350
|
+
confirm = SuppressibleConfirmDialog.display( 'DeleteCategory',
|
351
|
+
Lang::DELETE_CATEGORY_TITLE,
|
352
|
+
msg )
|
353
|
+
|
354
|
+
return false unless confirm == Wx::ID_YES
|
355
|
+
Wx::BusyCursor.busy() do
|
356
|
+
@app.delete_category(current_category)
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
355
360
|
|
361
|
+
def on_export(e)
|
362
|
+
a_win = @workarea.active_child
|
363
|
+
return unless a_win.respond_to?(:object)
|
364
|
+
obj = a_win.object
|
365
|
+
file_dialog = ExportFileDialog.new(@workarea, obj)
|
366
|
+
return unless file_dialog.show_modal() == Wx::ID_OK
|
367
|
+
Wx::BusyCursor.busy do
|
368
|
+
filter = file_dialog.filter.new(app)
|
369
|
+
File.open(file_dialog.get_path, 'w') do | outfile |
|
370
|
+
filter.write(obj, outfile)
|
371
|
+
end
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
def on_print(e)
|
376
|
+
a_win = @workarea.active_child
|
377
|
+
return unless a_win.respond_to?(:object)
|
378
|
+
obj = a_win.object
|
379
|
+
htmlprint = Wx::HtmlEasyPrinting.new('Weft print', @workarea)
|
380
|
+
htmlprint.page_setup()
|
381
|
+
file_dialog = ExportFileDialog.new(@workarea, obj)
|
382
|
+
return unless file_dialog.show_modal() == Wx::ID_OK
|
383
|
+
Wx::BusyCursor.busy do
|
384
|
+
filter = file_dialog.filter.new(app)
|
385
|
+
File.open(file_dialog.get_path, 'w') do | outfile |
|
386
|
+
filter.write(obj, outfile)
|
387
|
+
end
|
388
|
+
end
|
389
|
+
end
|
356
390
|
# run a new query
|
357
391
|
def on_query(e)
|
358
|
-
q_id =
|
359
|
-
|
392
|
+
q_id = app.get_preference('NextQuery') || 1
|
393
|
+
app.save_preference('NextQuery', q_id + 1)
|
360
394
|
q = Query.new()
|
361
395
|
q.dbid = q_id
|
362
396
|
@workarea.launch_window(QueryWindow, q)
|
363
397
|
end
|
364
398
|
|
365
|
-
|
366
|
-
# could potentially be saved in database
|
367
|
-
class CodeReview
|
368
|
-
attr_accessor :dbid
|
369
|
-
end
|
370
|
-
|
371
399
|
# run a new query
|
372
400
|
def on_review_coding(e)
|
373
401
|
q_id = @app.get_preference('NextReview') || 1
|
374
|
-
|
402
|
+
app.save_preference('NextReview', q_id + 1)
|
375
403
|
q = CodeReview.new()
|
376
404
|
q.dbid = q_id
|
377
405
|
@workarea.launch_window(CodeReviewWindow, q)
|
@@ -385,79 +413,94 @@ module QDA
|
|
385
413
|
:case_sensitive => search.case_sensitive,
|
386
414
|
:whole_word => search.whole_word }
|
387
415
|
|
388
|
-
text_results =
|
416
|
+
text_results = app.get_search_fragments(search.term, options)
|
389
417
|
title = "'#{search.term}' (#{Lang::SEARCH_RESULTS}) "
|
390
418
|
|
391
419
|
# create a category from the returned fragments
|
392
420
|
search_parent = @app.get_root_category('SEARCHES')
|
393
421
|
search_cat = Category.new( title, search_parent )
|
422
|
+
search_cat.codetable_init() # urgh
|
394
423
|
text_results.each do | docid, fragments |
|
395
424
|
fragments.each do | f |
|
396
425
|
search_cat.code( f.docid, f.offset, f.length )
|
397
426
|
end
|
398
427
|
end
|
399
|
-
|
400
|
-
broadcast(:category_added, search_cat)
|
428
|
+
app.save_category(search_cat, true)
|
401
429
|
@workarea.launch_window(CategoryWindow, search_cat)
|
402
430
|
end
|
403
431
|
end
|
404
432
|
end
|
405
433
|
|
406
|
-
def
|
434
|
+
def on_quit(event)
|
407
435
|
if on_close_project(event)
|
408
436
|
# remember window position and size
|
409
437
|
@workarea.remember_size()
|
410
438
|
event.skip()
|
439
|
+
exit() # required to exit reliably on Linux
|
411
440
|
else
|
412
441
|
event.veto()
|
413
442
|
end
|
414
443
|
end
|
415
|
-
|
444
|
+
|
445
|
+
def on_revert_project(e)
|
446
|
+
result = WarningDialog.display( Lang::REVERT_WARNING_TITLE,
|
447
|
+
Lang::REVERT_WARNING_MESSAGE )
|
448
|
+
return unless result == Wx::ID_OK
|
449
|
+
|
450
|
+
the_file = @app.dbfile
|
451
|
+
unpopulate()
|
452
|
+
open_project(the_file)
|
453
|
+
end
|
454
|
+
|
416
455
|
# returns true if a new project was started, false if not
|
417
456
|
def on_open_project(e)
|
418
457
|
return false unless on_close_project(e)
|
419
458
|
file_dialog = FileDialog.new(@workarea, "Open Project",
|
420
459
|
"", "", "Project Files (*.qdp)|*.qdp" )
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
@app = QDA::Application.new(self)
|
425
|
-
@app.extend( QDA::Backend::SQLite )
|
426
|
-
@app.start(:dbfile => file_dialog.get_path())
|
427
|
-
end
|
428
|
-
rescue Exception => err
|
429
|
-
MessageDialog.new(nil, err.to_s,
|
430
|
-
"Cannot open project",
|
431
|
-
OK|ICON_ERROR).show_modal()
|
432
|
-
@app = nil
|
433
|
-
return()
|
434
|
-
end
|
435
|
-
populate()
|
436
|
-
end
|
460
|
+
return false unless file_dialog.show_modal() == Wx::ID_OK
|
461
|
+
|
462
|
+
open_project( file_dialog.get_path() )
|
437
463
|
end
|
464
|
+
|
465
|
+
def open_project(pfile)
|
466
|
+
@workarea.set_cursor( Wx::BUSY_CURSOR )
|
467
|
+
self.app = QDA::Application.new()
|
468
|
+
app.extend( QDA::Backend::SQLite )
|
469
|
+
app.start(:dbfile => pfile)
|
470
|
+
populate()
|
471
|
+
rescue ArgumentError, NotImplementedError => err
|
472
|
+
ErrorDialog.display(Lang::OPEN_PROJECT_ERROR_TITLE, err.to_s)
|
473
|
+
self.app = nil
|
474
|
+
return false
|
475
|
+
ensure
|
476
|
+
@workarea.set_cursor( Wx::NORMAL_CURSOR )
|
477
|
+
end
|
438
478
|
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
479
|
+
def add_subscriber(subscriber, *events)
|
480
|
+
super
|
481
|
+
subscriber.evt_close do | e |
|
482
|
+
delete_subscriber(subscriber)
|
483
|
+
e.skip()
|
484
|
+
end
|
485
|
+
end
|
486
|
+
|
487
|
+
def notify(ev, content = nil)
|
488
|
+
if ev == :saved or ev == :started
|
489
|
+
@menu_file.disable_items(:save_project, :revert)
|
443
490
|
else
|
444
|
-
@menu_file.
|
491
|
+
@menu_file.enable_items(:save_project)
|
492
|
+
@menu_file.enable_items(:revert) if app.dbfile
|
445
493
|
end
|
446
|
-
broadcast(
|
494
|
+
broadcast(ev, content)
|
447
495
|
end
|
448
|
-
|
449
|
-
# Loads up metadata - eg from CSV file
|
450
|
-
def on_load_metadata(e)
|
451
|
-
|
452
|
-
end
|
453
496
|
|
454
497
|
def on_toggle_dandc(e)
|
455
|
-
if @
|
456
|
-
@
|
457
|
-
@
|
498
|
+
if @workarea.d_and_c_visible?
|
499
|
+
@workarea.hide_d_and_c()
|
500
|
+
@menu_view.uncheck_items(:documents_and_categories)
|
458
501
|
else
|
459
|
-
@
|
460
|
-
@
|
502
|
+
@workarea.show_d_and_c()
|
503
|
+
@menu_view.check_items(:documents_and_categories)
|
461
504
|
end
|
462
505
|
end
|
463
506
|
|
@@ -474,15 +517,14 @@ module QDA
|
|
474
517
|
# is open, prompt the user to supply a filename if this is a new
|
475
518
|
# project, otherwise just save the project.
|
476
519
|
def on_save_project(e)
|
477
|
-
return unless
|
478
|
-
return on_saveas_project(e) unless
|
520
|
+
return unless app
|
521
|
+
return on_saveas_project(e) unless app.dbfile
|
479
522
|
save_project()
|
480
523
|
end
|
481
524
|
|
482
525
|
def save_project()
|
483
526
|
@workarea.remember_layouts()
|
484
|
-
Wx::BusyCursor.busy() {
|
485
|
-
broadcast(:savestate_changed, @app)
|
527
|
+
Wx::BusyCursor.busy() { app.save }
|
486
528
|
end
|
487
529
|
|
488
530
|
def on_saveas_project(e)
|
@@ -506,17 +548,19 @@ module QDA
|
|
506
548
|
raise "Bad Status"
|
507
549
|
end
|
508
550
|
end
|
509
|
-
Wx::BusyCursor.busy() {
|
510
|
-
broadcast(:savestate_changed, @app)
|
551
|
+
Wx::BusyCursor.busy() { app.save(new_file) }
|
511
552
|
end
|
512
553
|
end
|
513
554
|
|
555
|
+
|
514
556
|
# Starts a new project
|
515
557
|
def on_new_project(e)
|
516
558
|
return unless on_close_project(e)
|
517
|
-
|
518
|
-
|
519
|
-
|
559
|
+
# TODO - this process is too protracted
|
560
|
+
self.app = QDA::Application.new(QDA::Backend::SQLite)
|
561
|
+
app.start(:dbfile => nil)
|
562
|
+
app.install_clean()
|
563
|
+
app.set_up()
|
520
564
|
populate()
|
521
565
|
end
|
522
566
|
|
@@ -554,53 +598,74 @@ module QDA
|
|
554
598
|
end
|
555
599
|
end
|
556
600
|
|
601
|
+
|
602
|
+
|
557
603
|
# refetch here - this is when it is transmitted to the child
|
558
604
|
# windows, and may then be used for coding, so it should contain
|
559
605
|
# a list of all the codes that apply to the vector
|
560
606
|
def current_category=(category)
|
561
|
-
|
562
|
-
|
607
|
+
if category
|
608
|
+
category = @app.get_category( category.dbid )
|
609
|
+
broadcast(:focus_category, category)
|
610
|
+
end
|
611
|
+
@current_category = category
|
612
|
+
end
|
613
|
+
|
614
|
+
def current_document=(document)
|
615
|
+
if document
|
616
|
+
document = @app.get_document( document.dbid )
|
617
|
+
broadcast(:focus_document, document)
|
618
|
+
end
|
619
|
+
@current_document = document
|
563
620
|
end
|
564
621
|
|
565
622
|
# unloads the currently loaded Weft instance and tidies up the GUI
|
566
623
|
def unpopulate()
|
567
|
-
return unless
|
568
|
-
|
624
|
+
return unless app
|
625
|
+
|
569
626
|
@workarea.close_all()
|
570
|
-
|
571
|
-
@sidebar.close()
|
572
|
-
@sidebar = nil
|
627
|
+
|
573
628
|
menu_state_no_project()
|
574
|
-
|
575
|
-
@app = nil
|
576
|
-
broadcast(:savestate_changed, nil)
|
629
|
+
self.app = nil
|
577
630
|
reset_subscriptions()
|
578
|
-
|
631
|
+
@workarea.subscribe(self, :all)
|
579
632
|
end
|
580
633
|
|
581
634
|
# updates the state of the menu above the main workarea to its
|
582
635
|
# initial state with no active project
|
583
636
|
def menu_state_no_project()
|
584
637
|
@menu_file.disable_items(:close_project, :save_project,
|
585
|
-
:save_project_as)
|
586
|
-
@menu_project.disable_items(:import_document, :
|
638
|
+
:save_project_as, :revert)
|
639
|
+
@menu_project.disable_items(:import_document, :delete_document,
|
640
|
+
:add_category, :delete_category,
|
641
|
+
:export)
|
587
642
|
@menu_search.disable_items( :search, :query, :review_coding,
|
588
643
|
:reindex_documents)
|
589
644
|
@menu_script.disable_items(:new) if ::WEFT_TESTING
|
590
|
-
|
645
|
+
if WINDOW_MODE == :MDI
|
646
|
+
@menu_view.disable_item(:documents_and_categories, :set_display_font)
|
647
|
+
else
|
648
|
+
@menu_view.disable_item(:set_display_font)
|
649
|
+
end
|
591
650
|
end
|
592
651
|
|
593
652
|
# updates the state of the menu above the main workarea to
|
594
653
|
# reflect the fact that a project has been opened.
|
595
654
|
def menu_state_open_project()
|
596
|
-
|
597
|
-
|
598
|
-
@menu_project.enable_items(:import_document, :
|
655
|
+
# :revert and :save_project are enabled when a change has been made
|
656
|
+
@menu_file.enable_items(:close_project, :save_project_as)
|
657
|
+
@menu_project.enable_items( :import_document, :delete_document,
|
658
|
+
:add_category, :delete_category,
|
659
|
+
:export)
|
599
660
|
@menu_search.enable_items( :search, :query, :review_coding,
|
600
661
|
:reindex_documents)
|
601
662
|
@menu_script.enable_items(:new) if ::WEFT_TESTING
|
602
|
-
|
603
|
-
|
663
|
+
if WINDOW_MODE == :MDI
|
664
|
+
@menu_view.enable_item(:documents_and_categories, :set_display_font)
|
665
|
+
@menu_view.check_item(:documents_and_categories)
|
666
|
+
else
|
667
|
+
@menu_view.enable_item(:set_display_font)
|
668
|
+
end
|
604
669
|
end
|
605
670
|
|
606
671
|
# Tries to close the current project, checking for unsaved
|
@@ -639,15 +704,22 @@ module QDA
|
|
639
704
|
end
|
640
705
|
end
|
641
706
|
|
707
|
+
|
642
708
|
# hunt through icon directories to find an icon +icon+ - returns
|
643
709
|
# a Wx::Icon constructed from that file, or raise an exception.
|
710
|
+
# +icon+ should be the name of an icon file *without* the extension.
|
711
|
+
# This method will search only for icons appropriate to the current
|
712
|
+
# platform. Raises a RuntimeError if no icon is found.
|
644
713
|
def fetch_icon(icon)
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
714
|
+
ICON_EXTS.each do | type |
|
715
|
+
maybe_icon_file = "%s.%s" % [ icon, type.extension ]
|
716
|
+
@icon_dirs.each do | dir |
|
717
|
+
if File.exist?( f = File.join(dir, maybe_icon_file) )
|
718
|
+
return Wx::Icon.new( f, type.constant )
|
719
|
+
end
|
649
720
|
end
|
650
721
|
end
|
722
|
+
|
651
723
|
raise RuntimeError, "Could not find icon #{icon}"
|
652
724
|
end
|
653
725
|
|
@@ -656,31 +728,14 @@ module QDA
|
|
656
728
|
end
|
657
729
|
|
658
730
|
def populate()
|
659
|
-
|
731
|
+
unless app
|
660
732
|
raise "Populate called without an @app set"
|
661
733
|
end
|
662
|
-
|
663
|
-
# @display_font.set_native_font_info(font_pref) - not impl
|
664
|
-
change_display_font(Wx::Font.new( font_pref[:size],
|
665
|
-
font_pref[:family],
|
666
|
-
font_pref[:style],
|
667
|
-
font_pref[:weight],
|
668
|
-
false,
|
669
|
-
font_pref[:face] ) )
|
670
|
-
end
|
671
|
-
|
672
|
-
frame = @workarea
|
673
|
-
@workarea.app = @app
|
674
|
-
# see sidebar.rb
|
675
|
-
@sidebar = SideBar.new( @workarea, self )
|
676
|
-
@sidebar.set_icon( fetch_icon("weft16.xpm") )
|
677
|
-
@sidebar.show()
|
678
|
-
|
734
|
+
@workarea.show_d_and_c()
|
679
735
|
# restore windows
|
680
736
|
@workarea.restore_layouts
|
681
737
|
|
682
738
|
menu_state_open_project()
|
683
|
-
broadcast(:savestate_changed, @app)
|
684
739
|
end
|
685
740
|
end
|
686
741
|
end
|