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/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
|