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.
Files changed (86) hide show
  1. data/lib/weft.rb +16 -1
  2. data/lib/weft/WEFT-VERSION-STRING.rb +1 -1
  3. data/lib/weft/application.rb +17 -74
  4. data/lib/weft/backend.rb +6 -32
  5. data/lib/weft/backend/sqlite.rb +222 -164
  6. data/lib/weft/backend/sqlite/category_tree.rb +52 -48
  7. data/lib/weft/backend/sqlite/database.rb +57 -0
  8. data/lib/weft/backend/sqlite/upgradeable.rb +7 -0
  9. data/lib/weft/broadcaster.rb +90 -0
  10. data/lib/weft/category.rb +139 -47
  11. data/lib/weft/codereview.rb +160 -0
  12. data/lib/weft/coding.rb +74 -23
  13. data/lib/weft/document.rb +23 -10
  14. data/lib/weft/exceptions.rb +10 -0
  15. data/lib/weft/filters.rb +47 -224
  16. data/lib/weft/filters/indexers.rb +137 -0
  17. data/lib/weft/filters/input.rb +118 -0
  18. data/lib/weft/filters/output.rb +101 -0
  19. data/lib/weft/filters/templates.rb +80 -0
  20. data/lib/weft/filters/win32backtick.rb +246 -0
  21. data/lib/weft/query.rb +169 -0
  22. data/lib/weft/wxgui.rb +349 -294
  23. data/lib/weft/wxgui/constants.rb +43 -0
  24. data/lib/weft/wxgui/controls.rb +6 -0
  25. data/lib/weft/wxgui/controls/category_dropdown.rb +192 -0
  26. data/lib/weft/wxgui/controls/category_tree.rb +314 -0
  27. data/lib/weft/wxgui/controls/document_list.rb +97 -0
  28. data/lib/weft/wxgui/controls/multitype_control.rb +37 -0
  29. data/lib/weft/wxgui/{inspectors → controls}/textcontrols.rb +235 -64
  30. data/lib/weft/wxgui/dialogs.rb +144 -41
  31. data/lib/weft/wxgui/error_handler.rb +116 -36
  32. data/lib/weft/wxgui/exceptions.rb +7 -0
  33. data/lib/weft/wxgui/inspectors.rb +61 -208
  34. data/lib/weft/wxgui/inspectors/category.rb +19 -16
  35. data/lib/weft/wxgui/inspectors/codereview.rb +90 -132
  36. data/lib/weft/wxgui/inspectors/document.rb +12 -8
  37. data/lib/weft/wxgui/inspectors/imagedocument.rb +56 -56
  38. data/lib/weft/wxgui/inspectors/query.rb +284 -0
  39. data/lib/weft/wxgui/inspectors/script.rb +147 -23
  40. data/lib/weft/wxgui/lang/en.rb +69 -0
  41. data/lib/weft/wxgui/sidebar.rb +90 -432
  42. data/lib/weft/wxgui/utilities.rb +70 -91
  43. data/lib/weft/wxgui/workarea.rb +150 -43
  44. data/share/icons/category.ico +0 -0
  45. data/share/icons/category.xpm +109 -0
  46. data/share/icons/codereview.ico +0 -0
  47. data/share/icons/codereview.xpm +54 -0
  48. data/share/icons/d_and_c.xpm +126 -0
  49. data/share/icons/document.ico +0 -0
  50. data/share/icons/document.xpm +70 -0
  51. data/share/icons/project.ico +0 -0
  52. data/share/icons/query.ico +0 -0
  53. data/share/icons/query.xpm +56 -0
  54. data/{lib/weft/wxgui → share/icons}/search.xpm +0 -0
  55. data/share/icons/weft.ico +0 -0
  56. data/share/icons/weft.xpm +62 -0
  57. data/share/icons/weft16.ico +0 -0
  58. data/share/icons/weft32.ico +0 -0
  59. data/share/templates/category_plain.html +18 -0
  60. data/share/templates/codereview_plain.html +18 -0
  61. data/share/templates/document_plain.html +13 -0
  62. data/share/templates/document_plain.txt +7 -0
  63. data/test/001-document.rb +55 -36
  64. data/test/002-category.rb +81 -6
  65. data/test/003-code.rb +8 -4
  66. data/test/004-application.rb +13 -34
  67. data/test/005-query_review.rb +139 -0
  68. data/test/006-filters.rb +54 -42
  69. data/test/007-output_filters.rb +113 -0
  70. data/test/009a-backend_sqlite_basic.rb +95 -24
  71. data/test/009b-backend_sqlite_complex.rb +43 -62
  72. data/test/009c_backend_sqlite_bench.rb +5 -10
  73. data/test/053-doc_inspector.rb +46 -0
  74. data/test/055-query_window.rb +50 -0
  75. data/test/all-tests.rb +1 -0
  76. data/test/test-common.rb +19 -0
  77. data/test/testdata/empty.qdp +0 -0
  78. data/test/testdata/simple with space.pdf +0 -0
  79. data/test/testdata/simple.pdf +0 -0
  80. data/weft-qda.rb +40 -7
  81. metadata +74 -14
  82. data/lib/weft/wxgui/category.xpm +0 -26
  83. data/lib/weft/wxgui/document.xpm +0 -25
  84. data/lib/weft/wxgui/inspectors/search.rb +0 -265
  85. data/lib/weft/wxgui/mondrian.xpm +0 -44
  86. data/lib/weft/wxgui/weft16.xpm +0 -31
@@ -1,26 +0,0 @@
1
- /* XPM */
2
- static char *category[] = {
3
- /* columns rows colors chars-per-pixel */
4
- "16 16 4 1",
5
- " c black",
6
- ". c gray60",
7
- "X c gray100",
8
- "o c None",
9
- /* pixels */
10
- "oooooooooooooooo",
11
- "oo ooooooooo",
12
- "o XXXXX oooooooo",
13
- "o XXXXX oooooooo",
14
- "o XXXXX oooooooo",
15
- "oo ooooooooo",
16
- "oooo.ooooooooooo",
17
- "oooo.ooooooooooo",
18
- "oooo.ooo oo",
19
- "oooo.ooo XXXX oo",
20
- "oooo.... oo",
21
- "oooo.ooooooooooo",
22
- "oooo.ooo oo",
23
- "oooo.ooo XXXX oo",
24
- "oooo.... oo",
25
- "oooooooooooooooo"
26
- };
@@ -1,25 +0,0 @@
1
- /* XPM */
2
- static char *document[] = {
3
- /* columns rows colors chars-per-pixel */
4
- "16 16 3 1",
5
- " c black",
6
- ". c gray100",
7
- "X c None",
8
- /* pixels */
9
- "XXXXXXXXXXXXXXXX",
10
- "XX XXXXX",
11
- "XX ........ XXXX",
12
- "XX ......... XXX",
13
- "XX . ... XX",
14
- "XX .......... XX",
15
- "XX . . XX",
16
- "XX .......... XX",
17
- "XX . . XX",
18
- "XX .......... XX",
19
- "XX . . XX",
20
- "XX .......... XX",
21
- "XX . . XX",
22
- "XX .......... XX",
23
- "XX XX",
24
- "XXXXXXXXXXXXXXXX"
25
- };
@@ -1,265 +0,0 @@
1
- module QDA::GUI
2
- # a window that allows the entry of criteria (category
3
- # intersections and unions, text search, document attributes), and
4
- # interactively presents the text meeting the criteria, and to save
5
- # the results as a permanent category (memo describing the rules
6
- # used to produce the codes.
7
- class QueryWindow < InspectorWindow
8
- include Subscriber
9
-
10
- # obj is a simple object with a +dbid+ representing a project
11
- # unique identifier for this query
12
- def initialize(obj, app, workarea, layout)
13
- @app = app
14
- @query = obj # currently a pretty much empty object
15
-
16
- super(workarea, "Query #{@query.dbid}", layout) do | parent |
17
- @text_box = CompositeText.new(parent, '', 0, @app)
18
- end
19
- set_icon( app.fetch_icon("search.xpm") )
20
- construct_query_panel
21
- @notebook.selection = 1
22
- subscribe()
23
- # evt_set_focus() { | e | p "focussed #{e.event_object}"; e.skip() }
24
- end
25
-
26
- def associated_subscribers()
27
- super << @objects.grep(CategoryDropDown)
28
- end
29
-
30
- # runs a query using the currently selected query options
31
- def get_results()
32
- begin
33
- # remember the last query we did
34
- @last_query = get_query_string
35
- @last_results = @app.app.do_query( *get_query_arguments )
36
- rescue Exception => err
37
- Wx::MessageDialog.new(nil, err.to_s,
38
- "Error running query",
39
- Wx::OK|Wx::ICON_EXCLAMATION).show_modal()
40
- return
41
- end
42
- return @last_results
43
- end
44
-
45
- def get_target_argument(offset, as_string = false)
46
- return nil unless @objects[offset].is_shown
47
- if @rules[offset].value == 'IS CODED BY'
48
- if @objects[offset].current_category
49
- category = @objects[offset].current_category
50
- return as_string ? category.name : category.dbid
51
- else
52
- # use fail rather than raise as it gets interp as a method...
53
- fail RuntimeError.new("No category value set for CODED BY")
54
- end
55
- elsif @rules[offset].value == 'CONTAINS WORD'
56
- str = @objects[offset].get_value
57
- if str.empty?
58
- fail RuntimeError.new("No text search set for CONTAINS WORD")
59
- else
60
- return str
61
- end
62
- end
63
- end
64
-
65
- def get_query_arguments()
66
- return @rules[0].value, get_target_argument(0),
67
- @ops[0].value,
68
- @rules[1].value, get_target_argument(1)
69
- end
70
-
71
- # TODO
72
- # returns a stringified representation of the query. The only
73
- # reason this is here at the moment is because the underlying
74
- # query code parser doesn't accept string literal paths or names
75
- # for categories- only database ids. This should be remedied, so
76
- # the string passed to query and this are the same.
77
- def get_query_string(join_char = " ")
78
- begin
79
- query_parts = [ @rules[0].value, get_target_argument(0, true) ]
80
- # add on the second bit if used
81
- # TODO - this is barbaric - this whole thing needs tidying
82
- # and being made more extensible n = many
83
- if @ops[0].value != ''
84
- query_parts += [ @ops[0].value,
85
- @rules[1].value, get_target_argument(1, true) ]
86
- end
87
- return query_parts.join(join_char)
88
- rescue Exception => err
89
- return ''
90
- end
91
- end
92
-
93
- # run the query, display the results, view them
94
- def on_view(e)
95
- Wx::BusyCursor.busy do
96
- results = get_results()
97
- return unless results
98
- @text_box.populate( results )
99
- if curr_category = @drop_down.current_category()
100
- @text_box.highlight_codingtable(curr_category.codes)
101
- end
102
- end
103
- @notebook.selection = 0
104
- end
105
-
106
- def on_save_results(e)
107
- # check for saved results
108
- unless @last_results and ! @last_query.empty? and
109
- @last_query == get_query_string()
110
- Wx::BusyCursor.busy do
111
- results = get_results()
112
- return unless results
113
- @text_box.populate(results)
114
- end
115
- end
116
-
117
- q_string = get_query_string
118
- title = "'#{q_string[0, 30]}...' (query results)"
119
- search_parent = @app.app.get_root_category('SEARCHES')
120
- query_cat = Category.new( title, search_parent )
121
- query_cat.codetable = @last_results
122
- query_cat.memo = get_query_string("\n")
123
- $wxapp.app.save_category(query_cat)
124
- $wxapp.broadcast(:category_added, query_cat)
125
- end
126
-
127
- def on_focus_dropdown(e)
128
- # p "focussed #{e.event_object}"
129
- # e.skip()
130
- end
131
-
132
- def on_blur_dropdown(e)
133
- # p "blurred #{e.event_object}"
134
- # p active?
135
- # e.skip()
136
- end
137
-
138
- def construct_query_panel()
139
- panel2 = Wx::Panel.new(@notebook, -1)
140
- sizer2 = Wx::BoxSizer.new(Wx::VERTICAL)
141
- sizer2.add( Wx::StaticText.new(panel2, -1, 'Find text that:'),
142
- 0, Wx::ALL|Wx::ADJUST_MINSIZE, 4 )
143
-
144
- # criteria consist of rules ('is coded by', 'text matches'),
145
- # targets ('category "Foo"', 'text "Bar"') and may be joined by
146
- # ops ('AND', 'OR')
147
-
148
- @rules = []
149
- @objects = []
150
- @ops = []
151
-
152
- @crit_panel = Wx::Panel.new(panel2, -1)
153
- @crit_sizer = Wx::BoxSizer.new(Wx::VERTICAL)
154
-
155
- add_criterion(true)
156
- add_criterion(false)
157
-
158
-
159
- @ops[0].evt_combobox(@ops[0].get_id) do | e |
160
- operator = @ops[0].get_string_selection
161
- if operator != ""
162
- @rules[1].show(true)
163
- @objects[1].show(true)
164
- else
165
- @rules[1].hide()
166
- @objects[1].hide()
167
- end
168
- end
169
- @rules[1].hide()
170
- @objects[1].hide()
171
-
172
- @crit_panel.set_sizer(@crit_sizer)
173
- sizer2.add(@crit_panel, 1, Wx::GROW|Wx::ALL|Wx::ADJUST_MINSIZE, 4 )
174
-
175
- butt_panel = Wx::Panel.new(panel2, -1)
176
- bott_sizer = Wx::BoxSizer.new(Wx::HORIZONTAL)
177
-
178
- button = Wx::Button.new(butt_panel, -1, 'View')
179
- button.evt_button(button.get_id) { | e | on_view(e) }
180
- bott_sizer.add(button, 1, Wx::ALL, 4)
181
-
182
- button = Wx::Button.new(butt_panel, -1, 'Save Results')
183
- button.evt_button(button.get_id) { | e | on_save_results(e) }
184
- bott_sizer.add(button, 1, Wx::ALL, 4)
185
-
186
- butt_panel.set_sizer(bott_sizer)
187
- sizer2.add(butt_panel, 0,
188
- Wx::GROW|Wx::ADJUST_MINSIZE|Wx::ALIGN_BOTTOM)
189
- @notebook.add_page(panel2, 'query')
190
- panel2.set_sizer_and_fit(sizer2)
191
- # sizer2.set_size_hints(panel2)
192
- end
193
-
194
- def add_criterion(with_bool = false)
195
- row_sizer = Wx::BoxSizer.new(Wx::HORIZONTAL)
196
- row_n = @rules.length
197
-
198
- type_op1 = Wx::ComboBox.new(@crit_panel, -1, '', Wx::DEFAULT_POSITION,
199
- Wx::DEFAULT_SIZE, [],
200
- Wx::CB_READONLY|Wx::CB_DROPDOWN)
201
- type_op1.append('IS CODED BY')
202
- type_op1.append('CONTAINS WORD')
203
-
204
- type_op1.selection = 0
205
- row_sizer.add( type_op1, 1, Wx::GROW|Wx::ALL)
206
- @rules.push( type_op1 )
207
-
208
- op2_placeholder = Wx::BoxSizer.new(Wx::VERTICAL)
209
- type_op2 = CategoryDropDown.new(@app, @crit_panel, nil, true)
210
- # TODO - allow currently highlighted category dropdown to
211
- # receive global focus_category events
212
- # type_op2.evt_set_focus() { | e | on_focus_dropdown(e) }
213
- # type_op2.evt_kill_focus() { | e | on_blur_dropdown(e) }
214
-
215
- op2_placeholder.add(type_op2, 1,
216
- Wx:: GROW|Wx::ALL)
217
-
218
- type_op2_a = Wx::TextCtrl.new(@crit_panel, -1, '')
219
- type_op2_a.hide()
220
- row_sizer.add( op2_placeholder, 1, Wx::ADJUST_MINSIZE)
221
-
222
- @objects.push( type_op2 )
223
-
224
-
225
- # switch inputs
226
- evt_combobox(type_op1.get_id) do | e |
227
- function = type_op1.get_string_selection()
228
- if function == "IS CODED BY" and not type_op2.shown?
229
- type_op2_a.hide()
230
- op2_placeholder.remove(type_op2_a)
231
-
232
- op2_placeholder.add(type_op2, 1,
233
- Wx::GROW|Wx::ADJUST_MINSIZE|Wx::ALL)
234
- type_op2.show()
235
- op2_placeholder.layout()
236
- @objects[row_n] = type_op2
237
- elsif function == "CONTAINS WORD" and not type_op2_a.shown?
238
- type_op2.hide()
239
- op2_placeholder.remove(type_op2)
240
- op2_placeholder.add(type_op2_a, 1,
241
- Wx:: GROW|Wx::ADJUST_MINSIZE|Wx::ALL)
242
- type_op2_a.show()
243
- op2_placeholder.layout()
244
- @objects[row_n] = type_op2_a
245
- end
246
- end
247
-
248
- type_op3 = Wx::ComboBox.new(@crit_panel, -1, '', Wx::DEFAULT_POSITION,
249
- Wx::DEFAULT_SIZE, [],
250
- Wx::CB_READONLY|Wx::CB_DROPDOWN)
251
- type_op3.append('')
252
- type_op3.append('AND')
253
- type_op3.append('AND NOT')
254
- type_op3.append('OR')
255
- type_op3.selection = 0
256
-
257
- row_sizer.add( type_op3, 1, Wx::GROW|Wx::ALL, 2)
258
- @ops.push( type_op3 )
259
- unless with_bool
260
- type_op3.hide()
261
- end
262
- @crit_sizer.add( row_sizer, 0, Wx::GROW|Wx::ALL|Wx::ALIGN_TOP )
263
- end
264
- end
265
- end
@@ -1,44 +0,0 @@
1
- /* XPM */
2
- static char *mondrian_xpm[] = {
3
- /* columns rows colors chars-per-pixel */
4
- "32 32 6 1",
5
- " c Black",
6
- ". c Blue",
7
- "X c #00bf00",
8
- "o c Red",
9
- "O c Yellow",
10
- "+ c Gray100",
11
- /* pixels */
12
- " ",
13
- " oooooo +++++++++++++++++++++++ ",
14
- " oooooo +++++++++++++++++++++++ ",
15
- " oooooo +++++++++++++++++++++++ ",
16
- " oooooo +++++++++++++++++++++++ ",
17
- " oooooo +++++++++++++++++++++++ ",
18
- " oooooo +++++++++++++++++++++++ ",
19
- " oooooo +++++++++++++++++++++++ ",
20
- " ",
21
- " ++++++ ++++++++++++++++++ .... ",
22
- " ++++++ ++++++++++++++++++ .... ",
23
- " ++++++ ++++++++++++++++++ .... ",
24
- " ++++++ ++++++++++++++++++ .... ",
25
- " ++++++ ++++++++++++++++++ .... ",
26
- " ++++++ ++++++++++++++++++ ",
27
- " ++++++ ++++++++++++++++++ ++++ ",
28
- " ++++++ ++++++++++++++++++ ++++ ",
29
- " ++++++ ++++++++++++++++++ ++++ ",
30
- " ++++++ ++++++++++++++++++ ++++ ",
31
- " ++++++ ++++++++++++++++++ ++++ ",
32
- " ++++++ ++++++++++++++++++ ++++ ",
33
- " ++++++ ++++++++++++++++++ ++++ ",
34
- " ++++++ ++++++++++++++++++ ++++ ",
35
- " ++++++ ++++++++++++++++++ ++++ ",
36
- " ++++++ ++++ ",
37
- " ++++++ OOOOOOOOOOOO XXXXX ++++ ",
38
- " ++++++ OOOOOOOOOOOO XXXXX ++++ ",
39
- " ++++++ OOOOOOOOOOOO XXXXX ++++ ",
40
- " ++++++ OOOOOOOOOOOO XXXXX ++++ ",
41
- " ++++++ OOOOOOOOOOOO XXXXX ++++ ",
42
- " ++++++ OOOOOOOOOOOO XXXXX ++++ ",
43
- " "
44
- };
@@ -1,31 +0,0 @@
1
- /* XPM */
2
- static char *weft16[] = {
3
- /* columns rows colors chars-per-pixel */
4
- "16 16 9 1",
5
- " c #400000",
6
- ". c #CCCC00",
7
- "X c #E9E991",
8
- "o c #999900",
9
- "O c gray100",
10
- "+ c black",
11
- "@ c black",
12
- "# c black",
13
- "$ c None",
14
- /* pixels */
15
- "$$$$$ $$$ $$$$",
16
- "$$$$ XX $ XX $$$",
17
- "$$$$ .XX XX. $$$",
18
- "$$ $ .XX o $ $$",
19
- "$ XX $ .XX $ X $",
20
- "$ XX. o .X. XX. ",
21
- "$$ . XXo . XX. $",
22
- "$$$ XX. $ XX. $$",
23
- "$$ XX. o XX. o $",
24
- "$ XX. o.X . o.X ",
25
- " XX. $ XXX $ X $",
26
- " X. $ o XXX $ $$",
27
- "$ $ XXo XXX $$$",
28
- "$$$ XX. $ XX $$$",
29
- "$$$ X. $$$ $$$$",
30
- "$$$$ $$$$$$$$$$"
31
- };