weft-qda 0.9.6

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 (55) hide show
  1. data/lib/weft.rb +21 -0
  2. data/lib/weft/WEFT-VERSION-STRING.rb +1 -0
  3. data/lib/weft/application.rb +130 -0
  4. data/lib/weft/backend.rb +39 -0
  5. data/lib/weft/backend/marshal.rb +26 -0
  6. data/lib/weft/backend/mysql.rb +267 -0
  7. data/lib/weft/backend/n6.rb +366 -0
  8. data/lib/weft/backend/sqlite.rb +633 -0
  9. data/lib/weft/backend/sqlite/category_tree.rb +104 -0
  10. data/lib/weft/backend/sqlite/schema.rb +152 -0
  11. data/lib/weft/backend/sqlite/upgradeable.rb +55 -0
  12. data/lib/weft/category.rb +157 -0
  13. data/lib/weft/coding.rb +355 -0
  14. data/lib/weft/document.rb +118 -0
  15. data/lib/weft/filters.rb +243 -0
  16. data/lib/weft/wxgui.rb +687 -0
  17. data/lib/weft/wxgui/category.xpm +26 -0
  18. data/lib/weft/wxgui/dialogs.rb +128 -0
  19. data/lib/weft/wxgui/document.xpm +25 -0
  20. data/lib/weft/wxgui/error_handler.rb +52 -0
  21. data/lib/weft/wxgui/inspectors.rb +361 -0
  22. data/lib/weft/wxgui/inspectors/category.rb +165 -0
  23. data/lib/weft/wxgui/inspectors/codereview.rb +275 -0
  24. data/lib/weft/wxgui/inspectors/document.rb +139 -0
  25. data/lib/weft/wxgui/inspectors/imagedocument.rb +56 -0
  26. data/lib/weft/wxgui/inspectors/script.rb +35 -0
  27. data/lib/weft/wxgui/inspectors/search.rb +265 -0
  28. data/lib/weft/wxgui/inspectors/textcontrols.rb +304 -0
  29. data/lib/weft/wxgui/lang.rb +17 -0
  30. data/lib/weft/wxgui/lang/en.rb +45 -0
  31. data/lib/weft/wxgui/mondrian.xpm +44 -0
  32. data/lib/weft/wxgui/search.xpm +25 -0
  33. data/lib/weft/wxgui/sidebar.rb +498 -0
  34. data/lib/weft/wxgui/utilities.rb +148 -0
  35. data/lib/weft/wxgui/weft16.xpm +31 -0
  36. data/lib/weft/wxgui/workarea.rb +249 -0
  37. data/test/001-document.rb +196 -0
  38. data/test/002-category.rb +138 -0
  39. data/test/003-code.rb +370 -0
  40. data/test/004-application.rb +52 -0
  41. data/test/006-filters.rb +139 -0
  42. data/test/009a-backend_sqlite_basic.rb +280 -0
  43. data/test/009b-backend_sqlite_complex.rb +175 -0
  44. data/test/009c_backend_sqlite_bench.rb +81 -0
  45. data/test/010-backend_nudist.rb +5 -0
  46. data/test/all-tests.rb +1 -0
  47. data/test/manual-gui-script.txt +24 -0
  48. data/test/testdata/autocoding-test.txt +15 -0
  49. data/test/testdata/iso-8859-1.txt +5 -0
  50. data/test/testdata/sample_doc.txt +19 -0
  51. data/test/testdata/search_results.txt +1254 -0
  52. data/test/testdata/text1-dos-ascii.txt +2 -0
  53. data/test/testdata/text1-unix-utf8.txt +2 -0
  54. data/weft-qda.rb +28 -0
  55. metadata +96 -0
@@ -0,0 +1,52 @@
1
+ $:.push('../lib/')
2
+
3
+ require 'weft/application'
4
+ require 'test/unit'
5
+
6
+ class DummyClient
7
+ attr_reader :state_display
8
+
9
+ def initialize(app = nil)
10
+ app.add_observer(self) if app
11
+ @state_display = "CLEAN"
12
+ end
13
+
14
+ def update(state)
15
+ @state_display = state ? "DIRTY" : "CLEAN"
16
+ end
17
+ end
18
+
19
+ class TestApplication < Test::Unit::TestCase
20
+ def setup
21
+
22
+ end
23
+
24
+ def test_basic
25
+ app = QDA::Application.new()
26
+ client = DummyClient.new(app)
27
+ assert_equal("CLEAN", client.state_display,
28
+ "Observer initially set to show clean")
29
+ app.dirty!
30
+ assert_equal("DIRTY", client.state_display,
31
+ "Observer picks up dirtying")
32
+ app.undirty!
33
+ assert_equal("CLEAN", client.state_display,
34
+ "Observer picks up saving")
35
+
36
+ end
37
+
38
+ def test_basic_w_initializer
39
+ client = DummyClient.new()
40
+ app = QDA::Application.new(client)
41
+
42
+ assert_equal("CLEAN", client.state_display,
43
+ "Observer initially set to show clean")
44
+ app.dirty!
45
+ assert_equal("DIRTY", client.state_display,
46
+ "Observer picks up dirtying")
47
+ app.undirty!
48
+ assert_equal("CLEAN", client.state_display,
49
+ "Observer picks up saving")
50
+
51
+ end
52
+ end
@@ -0,0 +1,139 @@
1
+ require 'english'
2
+
3
+ $:.push('../lib/')
4
+
5
+ require 'weft/application'
6
+ require 'weft/backend'
7
+ require 'weft/document'
8
+ require 'weft/filters'
9
+
10
+ require 'test/unit'
11
+
12
+ class TestFilter < Test::Unit::TestCase
13
+ def sample_file(filename)
14
+ File.join( File.dirname( __FILE__), 'testdata', filename)
15
+ end
16
+
17
+ def test_unix_utf8()
18
+ filter = QDA::TextFilter.new()
19
+ doc = filter.read(sample_file('text1-unix-utf8.txt'), 'test-unix-utf8')
20
+
21
+ str = "This is a text document\nin unix unicode.\n"
22
+ assert_equal(str, doc.text, "Document text read in")
23
+ end
24
+
25
+ def test_indexer
26
+ idx = QDA::Indexer.new()
27
+ idx.index('foo')
28
+
29
+ widx = QDA::WordIndexer.new()
30
+ my_word = 'SOMETHING'
31
+ widx.index(my_word)
32
+ assert_equal(1, widx.words.keys.length)
33
+ assert_equal(1, widx.words[my_word].length)
34
+ end
35
+
36
+ def test_dos_ascii()
37
+ filter = QDA::TextFilter.new()
38
+ doc = filter.read(sample_file('text1-dos-ascii.txt'), 'test-ascii')
39
+
40
+ str = "This is a text document\nin dos ascii.\n"
41
+ assert_equal(str, doc.text, "Document text read in")
42
+ end
43
+
44
+ def test_pdf
45
+ filter = QDA::PDFFilter.new()
46
+ windxr = QDA::WordIndexer.new()
47
+ filter.add_indexer(windxr)
48
+ doc = filter.read('testdata/emacs-refcard-a4.pdf', 'i')
49
+
50
+ doc.title = 'Acknowledgments'
51
+ word = 'moving'
52
+ windxr.words.each do | word, offsets |
53
+ offsets.each do | offset |
54
+ assert_equal( word, doc[offset, word.length] )
55
+ end
56
+ end
57
+ end
58
+
59
+ def test_word_indexing()
60
+ filter = QDA::TextFilter.new()
61
+ windxr = QDA::WordIndexer.new()
62
+ filter.add_indexer(windxr)
63
+ doc = filter.read(sample_file('autocoding-test.txt'),
64
+ 'word_indexing')
65
+ # ordinary, capitalised, short, apostrophe, longer
66
+ test_words = [ 'the', 'Before', 'I', 'It\'s', 'opinions' ]
67
+ test_words.each do | test_word |
68
+ windxr.words[test_word].each do | loc |
69
+ assert_equal(test_word, doc.text[loc, test_word.length].to_s)
70
+ end
71
+ end
72
+ end
73
+
74
+ def test_indexing_iso_8859_1
75
+ filter = QDA::TextFilter.new()
76
+ windxr = QDA::WordIndexer.new()
77
+ filter.add_indexer(windxr)
78
+ doc = filter.read(sample_file('iso-8859-1.txt'), 'iso-8859-1')
79
+ word_rx = /[\w\xC0-\xD6\xD8-\xF6\xF8-\xFF][\w\xC0-\xD6\xD8-\xF6\xF8-\xFF\']+/
80
+ windxr.words.each_key do | word |
81
+ assert_match(word_rx, word)
82
+ end
83
+ end
84
+
85
+ def test_autocoding
86
+ filter = QDA::TextFilter.new()
87
+ autocoder = QDA::AutoCoder.new(/^\*\*(.*)\*\*\s*$/ => 'Heading',
88
+ /^(.*)\:\s*$/ => 'Speaker')
89
+ filter.add_indexer(autocoder)
90
+
91
+ doc = filter.read(sample_file('autocoding-test.txt'),
92
+ 'autocoding')
93
+
94
+ str = "Before any autocoding\n\nSpeakerA:\nI am the first speaker.\nThis is what I say.\n\n**A TEXT HEADER**\n\nSpeakerB:\nI am the second speaker.\n\nThis is what I say. It's my opinions.\n\nSpeakerA:\nMe again.\n"
95
+ assert_equal(str, doc.text)
96
+ autocodes = autocoder.codes
97
+ assert_equal(2, autocodes.keys.length,
98
+ "Number of autocode types created")
99
+
100
+ speaker_a = autocodes['Speaker']['SpeakerA']
101
+ assert_instance_of(QDA::CodeSet, speaker_a,
102
+ "Autocode speaker A category created")
103
+ assert_equal(2, speaker_a.length, "Multiple passages coded")
104
+ # assert_equal(1, speaker_a.num_of_docs, "Single document coded")
105
+ content_a_1 =
106
+ "SpeakerA:
107
+ I am the first speaker.
108
+ This is what I say.
109
+
110
+ **A TEXT HEADER**
111
+
112
+ "
113
+ assert_equal(content_a_1,
114
+ doc.text[speaker_a[0].offset, speaker_a[0].length],
115
+ "Document text retrievable by code" )
116
+
117
+ speaker_b = autocodes['Speaker']['SpeakerB']
118
+ assert_instance_of(QDA::CodeSet, speaker_b,
119
+ "Autocode speaker B category created")
120
+
121
+ heading_1 = autocodes['Heading']['A TEXT HEADER']
122
+ assert_instance_of(QDA::CodeSet, heading_1,
123
+ "Autocode heading category created")
124
+
125
+ header_extract = "**A TEXT HEADER**
126
+
127
+ SpeakerB:
128
+ I am the second speaker.
129
+
130
+ This is what I say. It's my opinions.
131
+
132
+ SpeakerA:
133
+ Me again.
134
+ "
135
+ assert_equal(header_extract,
136
+ doc.text[heading_1[0].offset, heading_1[0].length],
137
+ "Document text retrievable by code" )
138
+ end
139
+ end
@@ -0,0 +1,280 @@
1
+ require 'english'
2
+ $:.push('../lib/')
3
+
4
+ require 'weft'
5
+ require 'test/unit'
6
+
7
+ class TestSQLiteBasic < Test::Unit::TestCase
8
+ def sample_file(filename)
9
+ File.join( File.dirname( __FILE__), 'testdata', filename)
10
+ end
11
+
12
+ def setup
13
+ @dbfile = nil
14
+ @app = QDA::Application.new()
15
+ @app.extend(QDA::Backend::SQLite)
16
+ end
17
+
18
+ # delete any files hanging around
19
+ def teardown()
20
+ if @app.started?
21
+ # p @app
22
+ # @app.end()
23
+ if @app.dbfile and File.exist?(@app.dbfile)
24
+ File.delete(@app.dbfile)
25
+ end
26
+ end
27
+ end
28
+
29
+ # test save & revert
30
+ def test_statefulness
31
+ @app.start(:dbfile => @dbfile)
32
+ @app.install_clean()
33
+ doc = QDA::Document.new('Doc-1')
34
+ @app.save_document(doc)
35
+
36
+ assert_raises(RuntimeError, "Cannot save without a filename") do
37
+ doc = @app.save()
38
+ end
39
+
40
+ @dbfile = 'foo.db'
41
+
42
+ @app.save(@dbfile)
43
+ assert(File.exist?(@dbfile), "File created after save")
44
+ assert(@app.get_doc('Doc-1'), "Still has saved content - new filename")
45
+
46
+ doc = QDA::Document.new('Doc-2')
47
+ @app.save_document(doc)
48
+ @app.save
49
+ assert(@app.get_doc('Doc-2'), "Still has saved content - re-use filename")
50
+
51
+ doc = QDA::Document.new('Doc-3')
52
+ @app.save_document(doc)
53
+ @app.revert
54
+ assert(File.exist?(@dbfile), "File exists after revert")
55
+
56
+ assert(@app.get_doc('Doc-1'), "Still has last-saved content")
57
+ assert(@app.get_doc('Doc-2'), "Still has last-saved content")
58
+ assert_raises(RuntimeError, "Lost unsaved content") do
59
+ doc = @app.get_doc('Doc-3')
60
+ end
61
+ end
62
+
63
+ def test_open_file
64
+ @app.start(:dbfile => @dbfile)
65
+ @app.install_clean()
66
+ @app.set_up()
67
+
68
+ # this will save in current working directory
69
+ @app.save('foo.db')
70
+ @app.end
71
+
72
+ @app.start(:dbfile => File::join(Dir.pwd, 'foo.db') )
73
+ File.unlink(File::join(Dir.pwd, 'foo.db'))
74
+ end
75
+
76
+ def test_basic_save_and_get_document()
77
+ @app.start(:dbfile => @dbfile)
78
+ @app.install_clean()
79
+ doc = QDA::Document.new('About Something')
80
+ assert_nil(doc.dbid, "No DBID set")
81
+ @app.save_document(doc)
82
+ assert(doc.dbid, 'Got a DBID set')
83
+
84
+ fetch_doc = @app.get_doc(doc.dbid)
85
+ assert(fetch_doc, "Got something back")
86
+
87
+ assert_equal(doc.dbid, fetch_doc.dbid,
88
+ "Fetched back thing has the same dbid")
89
+ assert_equal(doc.title, fetch_doc.title,
90
+ "Fetched back thing has the same dbid")
91
+
92
+ fetch_doc = @app.get_doc(doc.title)
93
+ assert(fetch_doc, "Got something back")
94
+
95
+ assert_equal(doc.dbid, fetch_doc.dbid,
96
+ "Fetched back thing has the same dbid")
97
+ assert_equal(doc.title, fetch_doc.title,
98
+ "Fetched back thing has the same dbid")
99
+ end
100
+
101
+ def test_save_and_get_document_content()
102
+ @app.start(:dbfile => @dbfile)
103
+ @app.install_clean()
104
+ doc = QDA::Document.new('About Something')
105
+ str1 = 'fo"o'
106
+ doc.append(str1)
107
+ str2 = "fo'o"
108
+ doc.append(str2)
109
+
110
+ @app.save_document(doc)
111
+ assert(doc.dbid, 'Got a DBID set')
112
+
113
+ fetch_doc = @app.get_doc(doc.dbid)
114
+ assert(fetch_doc, "Got something back")
115
+ assert_equal("fo\"o", fetch_doc[0,4],
116
+ "Got some fragments back")
117
+ assert_equal("fo'o\n", fetch_doc[5,5],
118
+ "Got some fragments back")
119
+
120
+ #assert_equal(2, fetch_doc.fragments.length,
121
+ #"Got some fragments back")
122
+ #assert_equal(str1, fetch_doc.fragments[0].text,
123
+ #"Got single-quote fragment back")
124
+ #assert_equal(str2, fetch_doc.fragments[1].text,
125
+ #"Got double-quote fragment back")
126
+ @app.save_document(doc)
127
+ end
128
+
129
+ def test_save_category_with_code()
130
+ @app.start(:dbfile => @dbfile)
131
+ @app.install_clean()
132
+ cat1 = QDA::Category.new("About 'Something'", nil, 'A memo')
133
+
134
+ doc = QDA::Document.new('Hello')
135
+ doc.append('this')
136
+ doc.append('that')
137
+ @app.save_document(doc)
138
+
139
+ # code 6 characters starting at index 1
140
+ cat1.code(doc.dbid, 1, 6)
141
+
142
+ @app.save_category(cat1)
143
+
144
+ f_cat1 = @app.get_category(cat1.dbid)
145
+ assert_equal(1, f_cat1.num_of_docs,
146
+ 'Have coded 1 doc')
147
+ assert_equal(1, f_cat1.num_of_codes,
148
+ 'Have applied one vector')
149
+ assert_equal(6, f_cat1.num_of_chars,
150
+ 'Have coded 6 characters')
151
+
152
+ texts = @app.get_text_at_category(cat1)
153
+
154
+ assert_equal(1, texts.keys.length,
155
+ 'Have stored one vector')
156
+ assert_equal("his\nth", texts[doc.title][0],
157
+ 'Have retrieved text')
158
+ assert_equal(1, texts[doc.title][0].offset,
159
+ 'Have retrieved text offset')
160
+ assert_equal(6, texts[doc.title][0].length,
161
+ 'Have retrieved text length')
162
+ assert(texts[doc.title][0].docid,
163
+ 'Have retrieved docid')
164
+
165
+
166
+ end
167
+
168
+ def test_basic_save_category
169
+ @app.start(:dbfile => @dbfile)
170
+ @app.install_clean()
171
+ cat1 = QDA::Category.new("About 'Something'", nil, 'the "memo"')
172
+
173
+ @app.save_category(cat1)
174
+ assert(cat1.dbid, 'Category was assigned a database id')
175
+
176
+ f_cat1 = @app.get_category(cat1.dbid)
177
+ assert_equal(cat1.name, f_cat1.name,
178
+ "Name retrieved successfully")
179
+ assert_equal(cat1.memo, f_cat1.memo,
180
+ "Memo retrieved successfully")
181
+
182
+ # test some parent-child stuff
183
+ cat2 = QDA::Category.new('Something "Specific"', cat1)
184
+ @app.save_category(cat2)
185
+ assert(cat2.dbid, 'Category was assigned a database id')
186
+
187
+ cat2a = QDA::Category.new('Something "Specific" & Detailed', cat2)
188
+ @app.save_category(cat2a)
189
+
190
+ cat3 = QDA::Category.new('Something "Else"', cat1)
191
+ @app.save_category(cat3)
192
+
193
+ # @app.dbh.execute("SELECT * FROM category") { | r | p r }
194
+ f_cat2 = @app.get_category(cat2.dbid)
195
+ assert_equal(cat2.name, f_cat2.name,
196
+ "Name retrieved successfully")
197
+
198
+ assert_equal(cat2.dbid, f_cat2.dbid,
199
+ "DBID retrieved successfully")
200
+
201
+ p_cat = @app.get_category(cat2.parent.dbid)
202
+ assert_equal(p_cat.dbid, cat1.dbid,
203
+ "Parent retrieved successfully")
204
+
205
+ assert_nil(@app.get_category_parent(p_cat.dbid),
206
+ "Nil retrieved for root node's parent")
207
+
208
+ roots = @app.get_all_categories()
209
+
210
+ assert_equal(1, roots.length,
211
+ "Root elements retrieved successfully")
212
+ assert_equal("About 'Something'", roots[0].name,
213
+ "Root element retrieved successfully")
214
+ assert_equal(2, roots[0].children.length,
215
+ "Root element children retrieved successfully")
216
+
217
+ cat3 = QDA::Category.new("NEw root node", nil)
218
+ @app.save_category(cat3)
219
+
220
+ roots = @app.get_all_categories()
221
+ assert_equal(2, roots.length,
222
+ "Multiple Root elements retrieved successfully")
223
+
224
+ new_root = @app.get_root_category("NEw root node")
225
+ assert_equal(QDA::Category, new_root.class)
226
+ assert_equal("NEw root node", new_root.name)
227
+ assert_equal(nil, new_root.parent)
228
+ assert_raises(RuntimeError) { @app.get_root_category("Doesn't exist") }
229
+
230
+
231
+ finds = @app.get_categories_by_path('Something')
232
+ assert_equal(3, finds.length, 'Normal name/path search')
233
+
234
+ finds = @app.get_categories_by_path('something')
235
+ assert_equal(3, finds.length, 'Case insensitive name/path search')
236
+
237
+ finds = @app.get_categories_by_path('Something/Something')
238
+ assert_equal(1, finds.length)
239
+
240
+ finds = @app.get_categories_by_path('Fake/Bad')
241
+ assert_equal(0, finds.length)
242
+ end
243
+
244
+ def test_cut_paste_category
245
+ @app.start(:dbfile => @dbfile)
246
+ @app.install_clean()
247
+ cat1 = QDA::Category.new("About 'Something'", nil)
248
+ @app.save_category(cat1)
249
+
250
+ cat2 = QDA::Category.new('Something "Specific"', cat1)
251
+ @app.save_category(cat2)
252
+ cat2a = QDA::Category.new('Something "Specific" & Detailed', cat2)
253
+ @app.save_category(cat2a)
254
+ cat3 = QDA::Category.new('Something "Else"', cat1)
255
+ @app.save_category(cat3)
256
+ cat4 = QDA::Category.new('Something "Again"', cat1)
257
+ @app.save_category(cat4)
258
+
259
+
260
+ cat2.parent = cat3
261
+ @app.save_category(cat2)
262
+
263
+
264
+ cat4.parent = cat3
265
+ @app.save_category(cat4)
266
+
267
+ cat2.parent = cat1
268
+ @app.save_category(cat2)
269
+
270
+ deletions = @app.delete_category(cat3)
271
+ assert_kind_of(Array, deletions)
272
+ assert_equal(2, deletions.length)
273
+ end
274
+
275
+ def test_install()
276
+ @app.start(:dbfile => @dbfile)
277
+ @app.install_clean()
278
+ assert_raises(RuntimeError) { doc = @app.get_doc('foo') }
279
+ end
280
+ end