Class: QDA::GUI::QueryWindow

Inherits:
InspectorWindow show all
Includes:
Subscriber
Defined in:
lib/weft/wxgui/inspectors/query.rb

Overview

a window that allows the entry of criteria (category intersections and unions, text search, document attributes), and interactively presents the text meeting the criteria, and to save the results as a permanent category (memo describing the rules used to produce the codes.

Constant Summary

Constants inherited from InspectorWindow

InspectorWindow::INSPECTOR_NB_STYLE

Constants inherited from WorkAreaWindow

WorkAreaWindow::W_WINDOW_DEF_SIZE

Instance Attribute Summary collapse

Attributes inherited from InspectorWindow

#client

Instance Method Summary collapse

Methods included from Subscriber

#notify, #subscribe

Methods inherited from InspectorWindow

#get_current_category, #on_activate, #on_code, #on_key_down, #on_uncode, #receive_text_font_changed

Methods inherited from WorkAreaWindow

#active?, #layout, #layout=, #on_focus

Constructor Details

#initialize(obj, client, workarea, layout) ⇒ QueryWindow

obj is a simple object with a dbid representing a project unique identifier for this query



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/weft/wxgui/inspectors/query.rb', line 14

def initialize(obj, client, workarea, layout)
  @client = client

  
  @rows, @funcs, @args, @exprs = [], [], [], []
  
  super(workarea, "Query #{obj.dbid}", layout) do | parent |
    @text_box = CompositeText.new(parent, '', 0, @client)
  end
  set_icon( @client.fetch_icon("query") )
  construct_query_panel
  # go to the query constructor panel, if query not defined, else show 
  # results pane
  self.query = obj
  if query.empty?
    @notebook.selection = 1
  else
    if results = get_results(query)
      populate(results)
    end
  end
end

Instance Attribute Details

#queryObject

Returns the value of attribute query.



9
10
11
# File 'lib/weft/wxgui/inspectors/query.rb', line 9

def query
  @query
end

Instance Method Details

#add_rowObject



250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
# File 'lib/weft/wxgui/inspectors/query.rb', line 250

def add_row()
  row_sizer = Wx::BoxSizer.new(Wx::HORIZONTAL)
  row_index = @rows.length
  
  func_sel = Wx::Choice.new( @crit_panel, -1)
  func_sel.append('IS CODED BY')
  func_sel.append('CONTAINS WORD')
  func_sel.selection = 0
  row_sizer.add( func_sel, 2, Wx::GROW|Wx::ALL, 2)
  @funcs.push( func_sel )

  cat_dd  = CategoryDropDown.new(@client, @crit_panel, nil, true)
  arg_sel = MultiTypedControl.new(cat_dd)
  arg_sel.add_control( Wx::TextCtrl.new(@crit_panel, -1, '') )
  # TODO - allow currently highlighted category dropdown to
  # receive global focus_category events
  # type_op2.evt_set_focus() { | e | on_focus_dropdown(e) }
  # type_op2.evt_kill_focus() { | e | on_blur_dropdown(e) }
  row_sizer.add( arg_sel, 2, Wx::GROW|Wx::ADJUST_MINSIZE|Wx::ALL, 2)
  @args.push( arg_sel )


  # switch inputs
  evt_choice(func_sel.get_id) { arg_sel.show( func_sel.selection() ) }

  expr_sel = Wx::Choice.new(@crit_panel, -1)
  expr_sel.append('')
  expr_sel.append('OR')
  expr_sel.append('AND')
  expr_sel.append('AND NOT')
  expr_sel.selection = 0
  # Previously passed the event, but see on_alter_expression
  # evt_choice(expr_sel.get_id) { | e | on_alter_expression(e, row_index) }
  evt_choice(expr_sel.get_id) { on_alter_expression(expr_sel, row_index) }
  
  row_sizer.add( expr_sel, 1, Wx::GROW|Wx::ALL, 2)
  @exprs.push( expr_sel )
  @crit_sizer.add( row_sizer, 0,  
                   Wx::GROW|Wx::ALL|Wx::ALIGN_TOP, 1 )
  
  @rows.push(row_sizer)
end

#associated_subscribersObject



76
77
78
# File 'lib/weft/wxgui/inspectors/query.rb', line 76

def associated_subscribers()
  super << @args.grep(CategoryDropDown)
end

#construct_query_panelObject



219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
# File 'lib/weft/wxgui/inspectors/query.rb', line 219

def construct_query_panel()
  panel2 = Wx::Panel.new(@notebook, -1)
  sizer2 = Wx::BoxSizer.new(Wx::VERTICAL)
  sizer2.add( Wx::StaticText.new(panel2, -1, 'Find text that:'),
              0, Wx::ALL|Wx::ADJUST_MINSIZE, 4 )

  @crit_panel = Wx::Panel.new(panel2, -1)
  @crit_sizer = Wx::BoxSizer.new(Wx::VERTICAL)

  add_row()
  @crit_panel.set_sizer(@crit_sizer)
  sizer2.add(@crit_panel, 1, Wx::GROW|Wx::ALL|Wx::ADJUST_MINSIZE, 4 )

  butt_panel = Wx::Panel.new(panel2, -1)
  bott_sizer = Wx::BoxSizer.new(Wx::HORIZONTAL)

  button = Wx::Button.new(butt_panel, -1, 'View')
  button.evt_button(button.get_id) { | e | on_view(e) }
  bott_sizer.add(button, 1, Wx::ALL, 4)

  button = Wx::Button.new(butt_panel, -1, 'Save Results')
  button.evt_button(button.get_id) { | e | on_save_results(e) }
  bott_sizer.add(button, 1, Wx::ALL, 4)

  butt_panel.set_sizer(bott_sizer)
  sizer2.add(butt_panel, 0,
              Wx::GROW|Wx::ADJUST_MINSIZE|Wx::ALIGN_BOTTOM) 
  @notebook.add_page(panel2, 'query')
  panel2.set_sizer_and_fit(sizer2)
end

#get_function(i) ⇒ Object



99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/weft/wxgui/inspectors/query.rb', line 99

def get_function(i)
  arg_ctrl = args[i].visible_item
  case funcs[i].string_selection
  when 'IS CODED BY'
    return QDA::Query::CodedByFunction.new(@client.app,
                                           arg_ctrl.current_category)
  when 'CONTAINS WORD'
      return QDA::Query::WordSearchFunction.new(@client.app, 
                                                arg_ctrl.get_value(),
                                                :wrap_both => 200 )
  end    
end

#get_queryObject



112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/weft/wxgui/inspectors/query.rb', line 112

def get_query()
  q = QDA::Query.new( get_function(0) )
  1.upto(rows.length - 1) do | i |
    expr = exprs[i - 1].string_selection
    break if expr.empty?
    q.add_expression(expr, get_function(i))
  end
  return q
rescue ArgumentError => err
  ErrorDialog.display("Error in query", err.to_s)
  return
end

#get_query_string(join_char = " ") ⇒ Object

returns a stringified representation of the query. The only reason this is here at the moment is because the underlying query code parser doesn’t accept string literal paths or names for categories- only database ids. This should be remedied, so the string passed to query and this are the same.



130
131
132
# File 'lib/weft/wxgui/inspectors/query.rb', line 130

def get_query_string(join_char = " ")
  get_query.to_s
end

#get_results(query) ⇒ Object

runs a query using the currently selected query options



81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/weft/wxgui/inspectors/query.rb', line 81

def get_results(query)
  # remember the last query we did
  @last_query = query
  set_cursor( Wx::BUSY_CURSOR )
  @last_results = @last_query.calculate()
  return @last_results
rescue QDA::CalculationError => err
  ErrorDialog.display("Error computing query", err.to_s)
  return @last_results = QDA::FragmentTable.new()
ensure
  set_cursor( Wx::NORMAL_CURSOR )
end

#get_target_argument(offset, as_string = false) ⇒ Object



94
95
96
97
# File 'lib/weft/wxgui/inspectors/query.rb', line 94

def get_target_argument(offset, as_string = false)
  return nil unless @objects[offset].is_shown

end

#hide_row(idx) ⇒ Object



197
198
199
200
201
202
# File 'lib/weft/wxgui/inspectors/query.rb', line 197

def hide_row(idx)
  return if rows[idx].nil?
  @crit_sizer.show( rows[idx], false )
  @crit_sizer.layout()
  hide_row(idx + 1)
end

#objObject



37
38
39
# File 'lib/weft/wxgui/inspectors/query.rb', line 37

def obj
  @query
end

#on_alter_expression(expr_sel, row_index) ⇒ Object

handle changing the /AND/OR/AND NOT/ selector at the end of each row, hiding or showing rows below as appropriate



206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/weft/wxgui/inspectors/query.rb', line 206

def on_alter_expression(expr_sel, row_index)
  # Previously used to receive parameters as (event, row_index)
  # .. but ..
  # This seems to cause regular segfaults - wxruby 0.6.0
  # expr_sel = event.event_object()
  expr = expr_sel.string_selection()
  if expr.empty?
    hide_row(row_index + 1)
  else
    show_row(row_index + 1)
  end
end

#on_blur_dropdown(e) ⇒ Object



176
177
178
179
180
# File 'lib/weft/wxgui/inspectors/query.rb', line 176

def on_blur_dropdown(e)
  # p "blurred #{e.event_object}"
  # p active?
  # e.skip()
end

#on_focus_dropdown(e) ⇒ Object



171
172
173
174
# File 'lib/weft/wxgui/inspectors/query.rb', line 171

def on_focus_dropdown(e)
  # p "focussed #{e.event_object}"
  # e.skip()
end

#on_save_results(e) ⇒ Object



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/weft/wxgui/inspectors/query.rb', line 150

def on_save_results(e)
  # check for saved results
  Wx::BusyCursor.busy do
    query   = get_query()
    return unless query
    results = get_results( query )
    return unless results
    @text_box.populate(results)
  end

  q_string = get_query_string
  title = "'Query #{obj.dbid} results'"
  search_parent = @client.app.get_root_category('SEARCHES')
  title = search_parent.unique_name(title)
  query_cat = QDA::Category.new( title, search_parent )
  query_cat.codetable = @last_results
  query_cat.memo = get_query_string("\n")

  @client.app.save_category(query_cat, true)
end

#on_view(e) ⇒ Object

run the query, display the results, view them



135
136
137
138
139
140
141
# File 'lib/weft/wxgui/inspectors/query.rb', line 135

def on_view(e)
  return unless query   = get_query()
  return unless results = get_results( query )

  populate(results)
  @notebook.selection = 0
end

#populate(results) ⇒ Object



143
144
145
146
147
148
# File 'lib/weft/wxgui/inspectors/query.rb', line 143

def populate(results)
  @text_box.populate( results )
  if curr_category = @drop_down.current_category()
    @text_box.highlight_codingtable(curr_category.codes)
  end    
end

#show_row(idx) ⇒ Object



183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/weft/wxgui/inspectors/query.rb', line 183

def show_row(idx)
  if rows[idx].nil?
    add_row()
  else
    @crit_sizer.show( rows[idx], true )
  end
  
  # show the next row below if this one ends with a valid expression
  if not exprs[idx].get_string_selection.empty?
    show_row(idx + 1)
  end
  @crit_sizer.layout()
end