NCBI C++ ToolKit
query_parse_panel.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: query_parse_panel.cpp 47479 2023-05-02 13:24:02Z ucko $
2  * ===========================================================================
3  *
4  * PUBLIC DOMAIN NOTICE
5  * National Center for Biotechnology Information
6  *
7  * This software/database is a "United States Government Work" under the
8  * terms of the United States Copyright Act. It was written as part of
9  * the author's official duties as a United States Government employee and
10  * thus cannot be copyrighted. This software/database is freely available
11  * to the public for use. The National Library of Medicine and the U.S.
12  * Government have not placed any restriction on its use or reproduction.
13  *
14  * Although all reasonable efforts have been taken to ensure the accuracy
15  * and reliability of the software and m_Data, the NLM and the U.S.
16  * Government do not and cannot warrant the performance or results that
17  * may be obtained by using this software or data. The NLM and the U.S.
18  * Government disclaim all warranties, express or implied, including
19  * warranties of performance, merchantability or fitness for any particular
20  * purpose.
21  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Authors: Robert Falk
27  *
28  * File Description:
29  *
30  */
31 
32 #include <ncbi_pch.hpp>
33 
36 
41 
47 
49 
52 
53 #include <util/checksum.hpp>
54 
55 #include <wx/app.h>
56 #include <wx/sizer.h>
57 #include <wx/menu.h>
58 #include <wx/button.h>
59 #include <wx/animate.h>
60 #include <wx/statline.h>
61 #include <wx/stattext.h>
62 #include <wx/toolbar.h>
63 #include <wx/choice.h>
64 #include <wx/panel.h>
65 #include <wx/timer.h>
66 #include <wx/textctrl.h>
67 #include <wx/checkbox.h>
68 #include <wx/dataobj.h>
69 #include <wx/clipbrd.h>
70 #include <wx/choice.h>
71 #include <wx/settings.h>
72 
73 
74 #include <algorithm>
75 
78 
79 
80 #define ID_SEARCHCTRL 13001
81 #define ID_SELECT_ALL 13005
82 #define ID_QUERY_ANIMATIONCTRL 13007
83 #define ID_TOOLBAR 13010
84 #define ID_TOOLBAR2 13011
85 #define ID_CASE_SENSITIVE 13012
86 #define ID_STRING_SEARCH 13013
87 #define ID_MRU1 13014
88 #define ID_STRING_MATCH_TYPE1 14014
89 
90 static const char* kRecentQueries = "Recent Queries";
91 static const char* kQueryPanel = ".QueryPanelGrid";
92 
93 const int kStringMatchTypesCount = 4;
95  "Exact Match",
96  "Wildcards",
97  "Regular Expression",
98  "Phonetic"
99 };
100 
101 // Allow display within toolbar to vary from display in menu (may be shorter
102 // to save space)
104  "Exact Match",
105  "Wildcards",
106  "Reg Exp",
107  "Phonetic"
108 };
109 
110 // enummerated comparison type for each match type
116 };
117 
118 ///////////////////////////////////////////////////////////////////////////////
119 //
120 // Background job for executing query on data source
121 //
122 ///////////////////////////////////////////////////////////////////////////////
124 {
125  CStopWatch timer;
126  timer.Start();
127 
128  if (!m_QExec.IsNull()) {
129  m_QExec->EvalStart();
130 
131  while (!m_QExec->EvalComplete()) {
132  if (canceled.IsCanceled())
133  return;
134 
135  if (m_QueryTree != NULL) {
137  ++m_NumSelected;
138  }
139  else {
140  if (m_QExec->EvalNext(*m_Macro))
141  ++m_NumSelected;
142  }
143  }
145  }
146  else if (m_DS != NULL) {
147 
150  }
151 
152  m_QueryTime = timer.Elapsed();
153 }
154 
156 {
157  delete m_QueryTree;
158  delete m_Macro;
159 }
160 
162 {
163  return m_NumQueried;
164 }
165 
167 {
168  if (!m_QExec.IsNull())
169  return m_QExec->GetExceptionCount();
170  else
171  return 0;
172 }
173 
174 ///////////////////////////////////////////////////////////////////////////////
175 //
176 // CQueryParsePanel
177 //
178 ///////////////////////////////////////////////////////////////////////////////
179 
183 
184 BEGIN_EVENT_TABLE( CQueryParsePanel, wxPanel )
185  EVT_CONTEXT_MENU( CQueryParsePanel::OnContextMenu )
196 
206  EVT_IDLE(CQueryParsePanel::OnIdle)
208 
209 
211 : m_pSearch(NULL)
212 , m_Animation(NULL)
213 , m_ToolBar(NULL)
216 , m_QueryWidget(w)
219 , m_StringCompare(CStringMatching::ePlainSearch)
220 , m_PrevStringCompare(CStringMatching::ePlainSearch)
221 {
222  SetDataSource(ds);
223  Init();
224 }
225 
227 {
228  #ifndef __WXMAC__
229  PopEventHandler( true );
230  #endif
231 
232  if (m_Future.IsRunning()) {
233  m_Future.cancel();
234  GUI_AsyncJoinFuture(m_Future, "Canceling Search...");
235  }
236 }
237 
238 void CQueryParsePanel::Create( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size )
239 {
240 #ifdef __WXOSX_COCOA__ // GB-8581
241  SetBackgroundStyle(wxBG_STYLE_COLOUR);
242  SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_FRAMEBK));
243 #endif
244 
245  wxPanel::Create(parent, id, pos, size);
246  CreateControls();
247 
248  #ifndef __WXMAC__
249  PushEventHandler( new CCommandToFocusHandler( this ) );
250  #endif
251 }
252 
254 {
255  m_pSearch = NULL;
256  m_Animation = NULL;
257  m_ToolBar = NULL;
258  m_ToolBar = NULL;
259  m_pSelectAll = NULL;
260 
261 
262  if( !m_IconsInitialized ){
264 
265  provider->RegisterFileAlias(wxT("menu::dm_start"), wxT("playhs.png"));
266  provider->RegisterFileAlias(wxT("menu::dm_stop"), wxT("stophs.png"));
267  provider->RegisterFileAlias(wxT("menu::back"), wxT("back.png"));
268  provider->RegisterFileAlias(wxT("menu::forward"), wxT("forward.png"));
269  provider->RegisterFileAlias(wxT("menu::help"), wxT("help.png"));
270  provider->RegisterFileAlias(wxT("menu::query_sel"), wxT("dropdown_sel.png"));
271  provider->RegisterFileAlias(wxT("menu::dm_filter"), wxT("filter.png"));
272 
273  m_IconsInitialized = true;
274  }
275 }
276 
278 {
279  wxBoxSizer* panel_sizer = new wxBoxSizer(wxHORIZONTAL);
280 
281 #ifndef __WXMAC__
282  long styles = wxTB_FLAT | wxTB_HORIZONTAL | wxTB_TEXT | wxTB_HORZ_LAYOUT;
283 #else
284  // Mac toolbars put text under the icon which looks really bad here so just doen't display icon text
285  long styles = wxTB_FLAT | wxTB_HORIZONTAL;
286 #endif
287  m_ToolBar = new wxToolBar(this, ID_TOOLBAR,
288  wxDefaultPosition, wxSize(-1, -1), styles);
289 
290  // label
291  wxStaticText* tool_text = new wxStaticText(m_ToolBar, wxID_ANY,
292  wxT("Search:"));
293  m_ToolBar->AddControl(tool_text);
294 
295  // Must supply wxTE_RICH otherwise the context menu (cut, copy, past...) for the search box will not work.
296  // Without wxTE_RICH, context menus from the parent widgets (this one, and CDockPanel) will both
297  // take priority over the search controls context menu meaning it never shows up. This is probably a wx
298  // bug coming from the fact wx uses the built-in context menu when wxTE_RICH is not used, and a wx-created
299  // context menu when it is. (and search control is derived from text control, so wxTE_RICH is recognized)
300 
301  // Update - The other reason to use TE_RICH is so that colored text (for fieldnames ) will work.
302  // unfortunately TE_RICH on cocoa forces creation of a multi-line control which is unusuable :-(.
303  // So I've patched wxWidgets so that when you do not provide wxTE_MULTILINE with wxTE_RICH it will
304  // create a single-line rich text control. Updates are in src/osx/cocoa/textctrl.mm (wxNSTextViewControl ctor)
305  // and include/wx/osx/cocoa/private/textimpl.h (ctor declaration).
306 /* Actual wxWidgets patch. This is for version 3.0.1
307 diff -ur -x'*-*' -x.DS_Store ./wxWidgets-3.0.1_orig/include/wx/osx/cocoa/private/textimpl.h ./wxWidgets-3.0.1/include/wx/osx/cocoa/private/textimpl.h
308 --- ./wxWidgets-3.0.1_orig/include/wx/osx/cocoa/private/textimpl.h 2014-06-14 17:48:48.000000000 -0400
309 +++ ./wxWidgets-3.0.1/include/wx/osx/cocoa/private/textimpl.h 2014-08-14 14:16:53.000000000 -0400
310 @@ -62,7 +62,7 @@
311  class wxNSTextViewControl : public wxWidgetCocoaImpl, public wxTextWidgetImpl
312  {
313  public:
314 - wxNSTextViewControl( wxTextCtrl *wxPeer, WXWidget w );
315 + wxNSTextViewControl( wxTextCtrl *wxPeer, WXWidget w, long style );
316  virtual ~wxNSTextViewControl();
317 
318  virtual wxString GetStringValue() const ;
319 diff -ur -x'*-*' -x.DS_Store ./wxWidgets-3.0.1_orig/src/osx/cocoa/textctrl.mm ./wxWidgets-3.0.1/src/osx/cocoa/textctrl.mm
320 --- ./wxWidgets-3.0.1_orig/src/osx/cocoa/textctrl.mm 2014-06-14 17:48:48.000000000 -0400
321 +++ ./wxWidgets-3.0.1/src/osx/cocoa/textctrl.mm 2014-08-14 14:36:58.000000000 -0400
322 @@ -545,25 +545,50 @@
323 
324  // wxNSTextViewControl
325 
326 -wxNSTextViewControl::wxNSTextViewControl( wxTextCtrl *wxPeer, WXWidget w )
327 +wxNSTextViewControl::wxNSTextViewControl( wxTextCtrl *wxPeer, WXWidget w, long style )
328  : wxWidgetCocoaImpl(wxPeer, w),
329  wxTextWidgetImpl(wxPeer)
330  {
331  wxNSTextScrollView* sv = (wxNSTextScrollView*) w;
332  m_scrollView = sv;
333 
334 - [m_scrollView setHasVerticalScroller:YES];
335 + bool single_line = !(style & wxTE_MULTILINE);
336 + [m_scrollView setHasVerticalScroller:NO];
337 +
338  [m_scrollView setHasHorizontalScroller:NO];
339  // TODO Remove if no regression, this was causing automatic resizes of multi-line textfields when the tlw changed
340  // [m_scrollView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
341 + if (single_line) {
342 + // Removes vertical scroll bar from single-line text
343 + [m_scrollView setAutoresizingMask:NSViewNotSizable];
344 + }
345 + else {
346 + [m_scrollView setHasVerticalScroller:YES];
347 + [m_scrollView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
348 + }
349  NSSize contentSize = [m_scrollView contentSize];
350 
351  wxNSTextView* tv = [[wxNSTextView alloc] initWithFrame: NSMakeRect(0, 0,
352  contentSize.width, contentSize.height)];
353  m_textView = tv;
354 - [tv setVerticallyResizable:YES];
355 - [tv setHorizontallyResizable:NO];
356 - [tv setAutoresizingMask:NSViewWidthSizable];
357 +
358 + const CGFloat LargeNumberForText = 1.0e7;
359 +
360 + if (single_line) {
361 + NSTextContainer *textContainer = [tv textContainer];
362 + [textContainer setContainerSize:NSMakeSize(LargeNumberForText, LargeNumberForText)];
363 + [textContainer setWidthTracksTextView:NO];
364 + [textContainer setHeightTracksTextView:NO];
365 + [tv setMaxSize:NSMakeSize(LargeNumberForText, LargeNumberForText)];
366 + [tv setHorizontallyResizable:YES];
367 + [tv setVerticallyResizable:NO];
368 + [tv setAutoresizingMask:NSViewNotSizable];
369 + }
370 + else {
371 + [tv setHorizontallyResizable:NO];
372 + [tv setVerticallyResizable:YES];
373 + [tv setAutoresizingMask:NSViewWidthSizable];
374 + }
375 
376  [m_scrollView setDocumentView: tv];
377 */
378 
379 
380  int search_width = 180;
381 
382  // Search box on mac is a little too short (vertically) so set size here:
383 #ifdef __WXMAC__
384  int search_height = tool_text->GetFont().GetPointSize()+8;
385 #else
386  int search_height = -1;
387 #endif
388 
390  ID_SEARCHCTRL, wxEmptyString,
391  wxDefaultPosition, wxSize(search_width, search_height),
392  wxTE_PROCESS_ENTER | wxTE_RICH );
393 
394  m_pSearch->SetToolTip(wxT("Enter search text as:\n\
395 1. A string to match against all fields\n\
396 2. A query based on field names, e.g. :\n\
397  dist > 0.2 and seq-id = \"NP_110296\""));
398 
399  m_ToolBar->AddControl(m_pSearch);
400 
401  wxBitmap bmp_selquery = wxArtProvider::GetBitmap(wxT("menu::query_sel"));
402  m_ToolBar->AddTool(eCmdSelQuery, wxEmptyString, bmp_selquery, wxNullBitmap, wxITEM_NORMAL, wxT("Select Query"));
403  m_ToolBar->EnableTool(eCmdSelQuery, true);
404 
405  // add empty space before the next control (seems to need to be a separator
406  // to do that)
407  m_ToolBar->AddSeparator();
408 
409  m_SearchType = new wxStaticText(m_ToolBar, wxID_ANY,
410  wxT("Exact Match"));
411  m_ToolBar->AddControl(m_SearchType);
412  m_ToolBar->AddTool(eCmdStringMatchType, wxEmptyString, bmp_selquery, wxNullBitmap, wxITEM_NORMAL, wxT("Match Type"));
413  m_ToolBar->EnableTool(eCmdStringMatchType, true);
414 
415  m_ToolBar->AddSeparator();
416 
417  // buttons
418  wxBitmap bmp_start = wxArtProvider::GetBitmap(wxT("menu::dm_start"));
419  m_ToolBar->AddTool(eCmdStartQuery, wxT(""), bmp_start, wxNullBitmap, wxITEM_NORMAL, wxT("Start Search"));
420  m_ToolBar->EnableTool(eCmdStartQuery, false);
421 
422  m_Animation = new wxAnimationCtrl(m_ToolBar, ID_QUERY_ANIMATIONCTRL, wxAnimation(),
423  wxDefaultPosition, wxSize(22, 22));
424  m_Animation->SetToolTip(wxT("Light moves while query is running"));
425 
426  wxString path = CSysPath::ResolvePath(wxT("<res>\\status_anim.gif"));
427  m_Animation->LoadFile(path);
428  m_ToolBar->AddControl(m_Animation);
429 
430  wxBitmap bmp_stop = wxArtProvider::GetBitmap(wxT("menu::dm_stop"));
431  m_ToolBar->AddTool(eCmdStopQuery, wxT("Stop"), bmp_stop, wxNullBitmap, wxITEM_NORMAL, wxT("Stop Search"));
432  m_ToolBar->EnableTool(eCmdStopQuery, false);
433 
434  m_ToolBar->AddSeparator();
435 
436  wxBitmap bmp_filter = wxArtProvider::GetBitmap(wxT("menu::dm_filter"));
437  m_ToolBar->AddTool(eCmdFilter, wxT("Filter"), bmp_filter, wxNullBitmap, wxITEM_CHECK, wxT("Only show query results"));
438  m_ToolBar->AddSeparator();
439 
440  m_pSelectAll = new wxCheckBox(m_ToolBar, ID_SELECT_ALL, _("All"),
441  wxDefaultPosition, wxDefaultSize, wxNO_BORDER );
442  m_pSelectAll->SetValue(true);
443  m_pSelectAll->SetToolTip(wxT("Check to show all matching nodes as selected\n\
444 Uncheck to show one matching node at a time\n"));
445  m_ToolBar->AddControl(m_pSelectAll);
446 
447  wxBitmap bmp_prev = wxArtProvider::GetBitmap(wxT("menu::back"));
448  m_ToolBar->AddTool(eCmdPrevious, wxT(""), bmp_prev, wxT("Previous selection"));
449  // Initially disabled because 'All' is true. Can only use previous
450  // and next when 'All' is false (so you are only selecting one at a
451  // time)
452 
453  wxBitmap bmp_next = wxArtProvider::GetBitmap(wxT("menu::forward"));
454  m_ToolBar->AddTool(eCmdNext, wxT(""), bmp_next, wxT("Next selection"));
455 
456  if (m_QueryWidget != NULL &&
457  m_QueryWidget->GetSearchHelpAddr() != string("")) {
458  m_ToolBar->AddSeparator();
459  wxBitmap bmp_help = wxArtProvider::GetBitmap(wxT("menu::help"));
460  m_ToolBar->AddTool(eCmdHelp, wxT("Help"), bmp_help, wxT("Online query help"));
461  }
462 
463  m_ToolBar->Realize();
464  panel_sizer->Add(m_ToolBar, 1, wxALL|wxGROW|wxALIGN_LEFT, 0);
465 
466  SetSizerAndFit(panel_sizer);
467 
468  m_pSearch->Connect(ID_SEARCHCTRL, wxEVT_KILL_FOCUS, wxFocusEventHandler(CQueryParsePanel::OnCtrlKillFocus), NULL, this);
469  m_pSelectAll->Connect(ID_SELECT_ALL, wxEVT_KILL_FOCUS, wxFocusEventHandler(CQueryParsePanel::OnCtrlKillFocus), NULL, this);
470 }
471 
473 {
475 
476  string prev_section = m_RegSection;
477 
478  if (ds != NULL) {
480  size_t i;
481  for (i = 0; i < m_QueryDataSource->GetColsCount(); ++i) {
482  cs.AddLine(m_QueryDataSource->GetColumnLabel(i));
483  }
484 
486 
487  if (m_RegSection != prev_section)
488  LoadSettings();
489  }
490  else {
491  m_RegSection = "";
492  }
493 
494  // Update selection so that if data source changed, we are not pointing to
495  // selected elements from previous source. Don't do this during widget
496  // initialization (when m_pSelectAll is NULL still)
497  if (m_QueryWidget != NULL && m_pSelectAll != NULL)
499 
500  // pevious query results may no longer be valid, so make sure we re-run
501  // the query if the start button is pressed again.
502  m_PrevQuery = "";
503 }
504 
506 {
507  m_DefaultQueries = q;
508 
509  if (m_DefaultQueries.size() > (unsigned int)m_MaxDefaultQueries) {
511  m_DefaultQueries.end());
512  }
513 }
514 
516 {
517  if (m_RecentQueries.size() > 0)
518  return m_RecentQueries[0].second;
519  return "";
520 }
521 
522 
523 void CQueryParsePanel::SetRegistryPath(const string& reg_path)
524 {
525  m_RegPath = reg_path + kQueryPanel;
526 }
527 
529 {
530  if (!m_RegPath.empty()) {
532  CRegistryReadView view = gui_reg.GetReadView(m_RegPath + "." + m_RegSection);
533 
534  vector<string> queries;
535  view.GetStringVec(kRecentQueries, queries);
536 
537  for (size_t i=0; i<queries.size(); ++i) {
538  if (m_RecentQueries.size() < (unsigned int)m_MaxRecentQueries)
539  m_RecentQueries.push_back(pair<string,string>(string(), queries[i]));
540  }
541  }
542 }
543 
545 {
546  if (m_RegPath.empty())
547  return;
548 
550  CRegistryWriteView view = gui_reg.GetWriteView(m_RegPath + "." + m_RegSection);
551 
552  vector<string> queries;
553 
554  vector<pair<string,string> >::const_iterator iter;
555  for (iter = m_RecentQueries.begin(); iter != m_RecentQueries.end(); ++iter) {
556  if (queries.size() < (unsigned int)m_MaxRecentQueries)
557  queries.push_back((*iter).second);
558  }
559 
560  if (queries.size() > 0)
561  view.Set(kRecentQueries, queries);
562 }
563 
564 
565 void CQueryParsePanel::AddQueryText(const string& query_mod)
566 {
567  wxString str = ToWxString(query_mod);
568 
569  if (str != "") {
570  string new_query = m_pSearch->GetUtf8();
571  NStr::TruncateSpacesInPlace(new_query);
572 
573  if (new_query != "") {
574 
575  // If there is already query text, add an "AND" before
576  // the new subclause UNLESS the last term in the query is
577  // already AND, OR, NOT or XOR
578  vector<string> arr;
579  NStr::Split(new_query, " ", arr);
580 
581  if (arr.size() > 0) {
582  string last_token = arr[arr.size()-1];
583  if ((NStr::CompareNocase(last_token, "and") != 0) &&
584  (NStr::CompareNocase(last_token, "or") != 0) &&
585  (NStr::CompareNocase(last_token, "xor") != 0) &&
586  (NStr::CompareNocase(last_token, "not") != 0)) {
587  new_query += " AND ";
588  }
589 
590  else {
591  }
592  }
593  }
594 
595  // We trimmed the existing query above. Now add one space to keep things
596  // from running together.
597  new_query += " " + str;
598 
599  m_pSearch->SetValue(new_query);
600  // This should automatically call OnSearchctrlTextEnter.
601  }
602 }
603 
604 void CQueryParsePanel::OnContextMenu( wxContextMenuEvent& evt )
605 {
606 }
607 
608 void CQueryParsePanel::OnRecentQuery(wxCommandEvent& evt)
609 {
610  m_QueryWidget->DlgOverlayFix(this->GetParent());
611  unsigned int query_idx = evt.GetId() - ID_MRU1;
612  string query;
613 
614  if (query_idx < m_DefaultQueries.size())
615  query = m_DefaultQueries[query_idx].second;
616  else
617  query = m_RecentQueries[query_idx - m_DefaultQueries.size()].second;
618 
619  m_pSearch->SetValue(ToWxString(query));
620 
621  wxCommandEvent evt_dummy;
622  OnSearchctrlTextEnter(evt_dummy);
623  x_ExecuteQuery(0);
624 }
625 
627 {
628  m_QueryWidget->DlgOverlayFix(this->GetParent());
629  x_ExecuteQuery(0);
630 }
631 
632 void CQueryParsePanel::OnCtrlKillFocus(wxFocusEvent& evt)
633 {
634  m_QueryWidget->DlgOverlayFix(this->GetParent());
635  evt.Skip();
636 }
637 
638 void CQueryParsePanel::OnSearchctrlSearchStop( wxCommandEvent& evt )
639 {
640  m_QueryWidget->DlgOverlayFix(this->GetParent());
642 }
643 
644 void CQueryParsePanel::OnSearchHelp(wxCommandEvent& evt)
645 {
646  m_QueryWidget->DlgOverlayFix(this->GetParent());
647  string help_addr = m_QueryWidget->GetSearchHelpAddr();
648 
649  ::wxLaunchDefaultBrowser(ToWxString(help_addr));
650 }
651 
653 {
654  // Enter processing is not working on Mac in the current wxWidgets
655  // release, so after each update, strip the string of carriage
656  // returns and, if any were found, call the function to submit the query.
657 #ifdef __WXMAC__
658  wxString no_return;
659  bool found_return = false;
660  for (size_t i=0; i<evt.GetString().size(); ++i) {
661  if (evt.GetString()[i] != wxT('\n'))
662  no_return += evt.GetString()[i];
663  else
664  found_return = true;
665  }
666  if (found_return) {
667  long cursor = m_pSearch->GetInsertionPoint();
668  // cursor is 0-based index so we subtract 1. Should never be <=0 but just in case:
669  cursor = std::max(long(0), cursor-1);
670 
671  m_pSearch->SetValue(no_return);
672  m_pSearch->SetInsertionPoint(std::min(cursor, m_pSearch->GetLastPosition()));
673  wxCommandEvent dummy_evt;
675  return;
676  }
677 #endif
678 
679  // Check if query is currently valid and give user some feedback if
680  // it is (or isn't)
681  string str = m_pSearch->GetUtf8();
682  vector<std::pair<size_t, size_t> > fields;
683 
684  bool valid = x_IsValidQuery(str, m_CaseSensitive, fields);
685 
686  wxFont f = m_pSearch->GetFont();
687 
688  // Remove any formatting from previous calls to this function:
689  wxTextAttr attr(wxColour(wxString(wxT("black"))));
690  attr.SetFlags(wxTEXT_ATTR_TEXT_COLOUR|wxTEXT_ATTR_FONT_WEIGHT);
691  attr.SetFont(f);
692  m_pSearch->SetStyle(0, str.length(), attr);
693 
694  // Find out how many leading blanks there are. Since those are truncated
695  // before query parsing, we need to add them back in when we highlight
696  // data fields.
697  string truncated_str = NStr::TruncateSpaces(str, NStr::eTrunc_Begin);
698  size_t tdelta = str.length() - truncated_str.length();
699 
700  // If query is valid, enable the search button:
701  if (valid)
702  m_ToolBar->EnableTool(eCmdStartQuery, true);
703  else
704  m_ToolBar->EnableTool(eCmdStartQuery, false);
705 
706  // If query is valid, highlight any substrings that were found during query
707  // parsing to be fields from the data dictionary. An invalid query may
708  // also return valid fields so highlight found-fields for invalid
709  // queries too.
710  if (valid || fields.size() > 0) {
711  wxTextAttr attr(wxColour(wxString(wxT("blue"))));
712  attr.SetFlags(wxTEXT_ATTR_TEXT_COLOUR|wxTEXT_ATTR_FONT_WEIGHT);
713  attr.SetFont(f);
714 
715  for (size_t i=0; i<fields.size(); ++i) {
716  m_pSearch->SetStyle((long)(fields[i].first + tdelta),
717  (long)(fields[i].second + tdelta),
718  attr);
719  }
720 
721  // Remember 'good' string and fields so that we can continue
722  // to highlight fields in parts of the query that have not been
723  // modified when the query doesn't parse.
725  m_SearchStringFields = fields;
726  }
727  // If the query is not valid and no fields were returned, highlight only
728  // those fields which appear in the part of the query string prior to
729  // any part of the string that has not been altered (this highlights
730  // fields found from the most recent valid query).
731  else {
732  // Keep highlighted dictionary fields that are in the text
733  // prior to any changes (which presumably made the text invalid)
734  if (m_SearchStringFields.size() > 0) {
735  wxTextAttr attr(wxColour(wxString(wxT("blue"))));
736  attr.SetFlags(wxTEXT_ATTR_TEXT_COLOUR|wxTEXT_ATTR_FONT_WEIGHT);
737  attr.SetFont(f);
738 
739  string::size_type idx;
740  for (idx = 0; idx<str.length() && idx<m_SearchString.length(); ++idx) {
741  if (str[idx] != m_SearchString[idx])
742  break;
743  }
744 
745  for (size_t i=0; i<m_SearchStringFields.size(); ++i) {
746  if (m_SearchStringFields[i].second < idx) {
747  m_pSearch->SetStyle((long)(m_SearchStringFields[i].first + tdelta),
748  (long)(m_SearchStringFields[i].second + tdelta),
749  attr);
750  }
751  }
752  }
753  }
754 
755  m_pSearch->Refresh();
756 }
757 
758 void CQueryParsePanel::OnQuerySel( wxCommandEvent& evt )
759 {
760  m_QueryWidget->DlgOverlayFix(this->GetParent());
761  wxMenu* m = new wxMenu();
762  unsigned int i;
763  unsigned int max_id = ID_MRU1;
764 
765  if (m_DefaultQueries.size() > 0) {
766  wxMenu* default_menu = new wxMenu();
767 
768  for (i=0; i<m_DefaultQueries.size(); ++i) {
769  default_menu->Append(max_id++, ToWxString(m_DefaultQueries[i].first));
770  }
771 
772  m->AppendSubMenu(default_menu, wxT("Saved Queries"));
773  }
774 
775  for (i=0; i<m_RecentQueries.size(); ++i) {
776  m->Append(max_id++, ToWxString(m_RecentQueries[i].second));
777  }
778 
779  m_ToolBar->PopupMenu(m);
780 
781  delete m;
782 }
783 
784 void CQueryParsePanel::OnButtonNext( wxCommandEvent& evt )
785 {
787  // Fix here for some reason can mess up checkbox labels on windows, so don't use it.
788  //m_QueryWidget->DlgOverlayFix(this->GetParent());
789 }
790 
791 void CQueryParsePanel::OnButtonPrevious( wxCommandEvent& evt )
792 {
794  // Fix here for some reason can mess up checkbox labels on windows, so don't use it.
795  //m_QueryWidget->DlgOverlayFix(this->GetParent());
796 }
797 
799 {
800  return m_pSelectAll->IsChecked();
801 }
802 
804 {
805  m_pSelectAll->SetValue(false);
806  m_pSelectAll->Show(false);
807 }
808 
809 void CQueryParsePanel::OnToggleSelectAll(wxCommandEvent & evt)
810 {
811  // Enable or disable previous/next selected element based on whether
812  // select all is checked. In 'select all' mode, previous and next
813  // do not do anything.
814  bool select_all = m_pSelectAll->IsChecked();
815 
816  m_ToolBar->EnableTool(eCmdNext, true);
817  m_ToolBar->EnableTool(eCmdPrevious, true);
818 
819  m_QueryWidget->SetSelectAll(select_all);
820 }
821 
823 {
824  // Quick check to see if the query has already been run - if not,
825  // clicking 'filter' will run the query too.
826  string query = m_pSearch->GetUtf8();
827  bool casesensitive = m_CaseSensitive;
828 
829  // Re-run the query if options that can change query results have changed
830  if (query!=m_PrevQuery ||
831  casesensitive!=m_PrevCaseSensitive ||
833  x_ExecuteQuery(0);
834  }
835 
837 
838 }
839 
840 void CQueryParsePanel::OnStringMatchTypeBtn( wxCommandEvent& evt )
841 {
842  m_QueryWidget->DlgOverlayFix(this->GetParent());
843  wxMenu* m = new wxMenu();
844  unsigned int max_id = ID_STRING_MATCH_TYPE1;
845 
846  m->SetTitle(wxT("String Matching Options"));
847 
848  for (int i=0; i<kStringMatchTypesCount; ++i) {
849  m->Append(max_id++, ToWxString(kStringMatchTypes[i]));
850  }
851  m->AppendSeparator();
852  m->AppendCheckItem(max_id, ToWxString("Case Sensitive"));
853  m->Check(max_id, m_CaseSensitive);
854 
855  m_ToolBar->PopupMenu(m);
856 
857  delete m;
858 }
860 {
861  m_QueryWidget->DlgOverlayFix(this->GetParent());
862  unsigned int query_idx = evt.GetId() - ID_STRING_MATCH_TYPE1;
863  string match_type = kStringMatchTypes[0];
864 
865  // If selected menu item is one of the phonetic matching choices
866  if (query_idx < kStringMatchTypesCount) {
867  match_type = kStringMatchTypesToolbar[query_idx];
868  m_SearchType->SetLabel(ToWxString(match_type));
870  }
871  // If selected menu item is to turn case-sensitive on/off
872  else if (query_idx == kStringMatchTypesCount) {
873  m_CaseSensitive = evt.IsChecked();
874  }
875 
876  m_ToolBar->Realize();
877 }
878 
879 ///////////////////////////////////////////////////////////////////////////////
880 /// Class for extracting positions of data fields from the query. A data field
881 /// is a query string token that matches a name in the dictionary.
882 ///
884 {
885 public:
887 
888  std::vector<std::pair<size_t, size_t> >
889  GetFieldPositions() const { return m_FieldPositions; }
890 
893  {
894  if (delta < 0)
895  return eTreeTraverse;
896 
897  const CQueryParseNode& qnode = tr.GetValue();
898 
899  const IQueryParseUserObject* uo = qnode.GetUserObject();
900  const CQueryNodeValue* v = dynamic_cast<const CQueryNodeValue*>(uo);
901 
902  if (v != NULL && v->IsDataField()) {
903  std::pair<size_t, size_t> field_position;
904 
905  // The length in SSrcLoc is left as 0
906  field_position.first = qnode.GetLoc().pos;
907  field_position.second = qnode.GetLoc().pos + qnode.GetStrValue().length();
908 
909  m_FieldPositions.push_back(field_position);
910  }
911 
912  return eTreeTraverse;
913  }
914 
915 
916 protected:
917  std::vector<std::pair<size_t, size_t> > m_FieldPositions;
918 };
919 
920 
922  bool casesensitive,
923  vector<std::pair<size_t, size_t> >& fields)
924 {
925  bool valid = (query.length() > 0);
926 
927  if (valid) {
928  CQueryParseTree qtree;
929  if (query.length() > 5 &&
930  !NStr::CompareNocase(query.substr(0, 5), "MACRO")) {
931  macro::CMacroRep* macro_rep = NULL;
932 
933  try {
934  CRef<CMacroQueryExec> qexec(m_QueryDataSource->GetQueryExec(casesensitive, m_StringCompare));
935 
936  macro::CMacroParser p;
937  qexec->GetFunctionNames(p);
938  p.SetSource(query.c_str());
939  p.Parse(true, qexec);
940  macro_rep = p.DetachMacroRep();
941 
942  if (macro_rep->GetWhereClause() != NULL &&
943  macro_rep->GetDoTree() != NULL) {
944 
945  CRef<objects::CScope> sc = m_QueryDataSource->GetScope();
946 
947  CQueryExecPreProcessFunc pre_process_exec(sc.GetPointerOrNull(),
948  *qexec);
949  TreeDepthFirstTraverse(*macro_rep->GetWhereClause()->GetQueryTree(),
950  pre_process_exec);
951  TreeDepthFirstTraverse(*macro_rep->GetDoTree()->GetQueryTree(),
952  pre_process_exec);
953 
954  CQueryHighlightFunction field_finder;
955  field_finder = TreeDepthFirstTraverse(*macro_rep->GetWhereClause()->GetQueryTree(),
956  field_finder);
957 
958  fields = field_finder.GetFieldPositions();
959 
960  field_finder = TreeDepthFirstTraverse(*macro_rep->GetDoTree()->GetQueryTree(),
961  field_finder);
962 
963  fields = field_finder.GetFieldPositions();
964  }
965 
966  delete macro_rep;
967  }
968  catch (const CException& e) {
969  LOG_POST(Info << "Error pre-processing macro: " << e.GetMsg());
970  valid = false;
971  delete macro_rep;
972  }
973  }
974  else {
975  try {
976  // parse the query. This will throw exceptions for syntax errors
977  // like 'dist > 0.2 AND' but since it does not look at the tree's
978  // dictionary, strings/phrases that can't be promoted to a reasonable
979  // value still pass, becuase they *could* be data fields, e.g.:
980  // 'dist > 0.7 AND my dog likes to bark' will parse without error.
981  CRef<CMacroQueryExec> qexec(m_QueryDataSource->GetQueryExec(casesensitive, m_StringCompare));
982  macro::CMacroParser p;
983  qexec->GetFunctionNames(p);
984 
985  qtree.Parse(query.c_str(),
986  casesensitive ? CQueryParseTree::eCaseSensitiveUpper :
989  false,
990  p.GetWhereFunctions());
991 
992  // If parsed query only has one top-level token then it is
993  // a simple string which is always a valid query
994  bool simple_string = false;
995  if (qtree.GetQueryTree()->CountNodes() == 0 &&
996  qtree.GetQueryTree()->GetValue().IsValue() &&
997  qtree.GetQueryTree()->GetValue().GetStrValue() != "") {
998  simple_string = true;
999  }
1000 
1001  if (!simple_string) {
1002  CRef<CMacroQueryExec> qexec(m_QueryDataSource->GetQueryExec(casesensitive, m_StringCompare));
1003 
1004  // Pre-process the query. This step determines, to the extent
1005  // possible, the types to be used in comaparison and whether a valid
1006  // number of arguments are present. Where possible, static types
1007  // (as opposed to identifers for field-values) are converted into
1008  // their required types for comparisons.
1009  CRef<objects::CScope> sc = m_QueryDataSource->GetScope();
1010 
1011  CQueryExecPreProcessFunc pre_process_exec(sc.GetPointerOrNull(),
1012  *qexec);
1014  pre_process_exec);
1015 
1016  CQueryHighlightFunction field_finder;
1017  field_finder = TreeDepthFirstTraverse(*qtree.GetQueryTree(),
1018  field_finder);
1019 
1020  fields = field_finder.GetFieldPositions();
1021  }
1022  }
1023  catch (const CException& e) {
1024  LOG_POST(Info << "Query Parse Error: " << e.GetMsg());
1025  valid = false;
1026  }
1027  }
1028  }
1029 
1030  // A simple string query. Return true unless string is empty:
1031  return (valid);
1032 }
1033 
1034 void CQueryParsePanel::CompleteQuery(CMacroQueryExec* qexec, const string& status)
1035 {
1036  // Let widget make any needed changes with query completed,
1037  // e.g. enable widget interaction, update selection set, etc.
1038  m_QueryWidget->QueryEnd(qexec);
1039 
1040  // Stop animation in query tool bar
1041  m_Animation->Stop();
1042 
1043  // Re-enable all input to window (and disable cancel button)
1044  this->SetCursor(*wxSTANDARD_CURSOR);
1045  m_ToolBar->EnableTool(eCmdStopQuery, false);
1046  m_ToolBar->EnableTool(eCmdStartQuery, true);
1047  m_ToolBar->EnableTool(eCmdNext, true);
1048  m_ToolBar->EnableTool(eCmdPrevious, true);
1049  m_ToolBar->EnableTool(eCmdStringMatchType, true);
1050  m_pSearch->Enable();
1051  m_pSelectAll->Enable();
1052  m_ToolBar->EnableTool(eCmdFilter, true);
1053 
1054  // Because we disable windows during the query we lose focus in the text
1055  // box. This brings it back. Now since the user can use other windows
1056  // while search is running (if the search turns out to be long...), we
1057  // only put focus back if it hasn't been assigned somewhere else.
1058  wxWindow* fwin = wxWindow::FindFocus();
1059 
1060  if (fwin == NULL) {
1061  m_pSearch->SetFocus();
1062  }
1063 
1064  if (status != "") {
1065  CQueryPanelEvent evt(status);
1066  Send(&evt, ePool_Parent);
1067  }
1068 
1069  // On mac (osx Cocoa) formatting can be lost after enter (when the wxTextCtrl
1070  // m_pSearch was disabled then re-enabled). This re-computes the highlighting.
1071  // (note: formatting is not lost on other platforms when we do this, but no
1072  // harm in re-setting it here)
1073  wxCommandEvent evt_dummy;
1074  OnSearchctrlTextEnter(evt_dummy);
1075 }
1076 
1078  CQueryParseTree* qtree,
1079  macro::CMacroRep* macro_rep,
1080  bool casesensitive,
1081  const string& query)
1082 {
1083  string result_status;
1084 
1085  // Pre-process the query. This step determines, to the extent
1086  // possible, the types to be used in comparison and whether a valid
1087  // number of arguments are present. Where possible, static types
1088  // (as opposed to identifers for field-values) are converted into
1089  // their required types for comparisons.
1090  if (macro_rep) {
1091  try {
1092  CRef<CScope> scope = m_QueryDataSource->GetScope();
1093  CQueryExecPreProcessFunc pre_process_exec(scope.GetPointerOrNull(), *qexec);
1094 
1095  CQueryParseTree* where_tree = macro_rep->GetWhereClause();
1096  if (where_tree) {
1097  TreeDepthFirstTraverse(*(where_tree->GetQueryTree()), pre_process_exec);
1098  }
1099 
1100  CQueryParseTree* do_tree = macro_rep->GetDoTree();
1101  if (do_tree) {
1102  TreeDepthFirstTraverse(*(do_tree->GetQueryTree()), pre_process_exec);
1103  }
1104  }
1105  catch (const CQueryExecException &e) {
1106  LOG_POST(Info << "Error pre-processing query: " << e.GetMsg());
1107  }
1108  }
1109  else if (qtree) {
1110  try {
1111  CRef<CScope> scope = m_QueryDataSource->GetScope();
1112  CQueryExecPreProcessFunc pre_process_exec(scope.GetPointerOrNull(), *qexec);
1113  TreeDepthFirstTraverse(*(qtree->GetQueryTree()), pre_process_exec);
1114 
1115  }
1116  catch (CQueryExecException &e) {
1117  LOG_POST(Info << "Error pre-processing query: " << e.GetMsg());
1118  }
1119  }
1120 
1121  // Create a job to run in the background so that the user can still access
1122  // the cancel button or interact with other views while the job is
1123  // running
1124  try {
1125  if (m_Future.IsRunning()) {
1126  m_Future.cancel();
1127  GUI_AsyncJoinFuture(m_Future, "Canceling Search...");
1128  }
1129  m_Job.Reset();
1130 
1131  if (macro_rep) {
1132  m_Job.Reset(new CQueryJob(qexec, macro_rep, casesensitive, m_StringCompare));
1133  }
1134  else if (qtree) {
1135  m_Job.Reset(new CQueryJob(qexec, qtree, casesensitive, m_StringCompare));
1136  }
1137  else {
1138  m_Job.Reset(new CQueryJob(query, casesensitive, m_StringCompare, m_QueryDataSource));
1139  }
1140 
1141  m_Future = job_async([job = m_Job](ICanceled& canceled) mutable { job->Execute(canceled); }, "Querying Tree");
1142  }
1143  // Unable to start a job - try to do physics in foreground
1144  catch (CAppJobException&) {
1145  _TRACE("Query job start failed");
1146  }
1147 }
1148 
1150 {
1151  string status_msg;
1152 
1153  // Execute the query. If it is a simple string query, do it synchronously,
1154  // otherwise start a asynchronous job to complete the query. If the query
1155  // is unchanged from the lasttime this funcion was called, do not re-execute
1156  // the query.
1157  if (m_ToolBar->GetToolEnabled(eCmdStartQuery)) {
1158  m_Animation->Play();
1159 
1160  // Disable all input to window except the cancel button
1161  this->SetCursor(*wxHOURGLASS_CURSOR);
1162  this->Update();
1163  m_ToolBar->EnableTool(eCmdStopQuery, true);
1164  m_ToolBar->EnableTool(eCmdStartQuery, false);
1165  m_ToolBar->EnableTool(eCmdNext, false);
1166  m_ToolBar->EnableTool(eCmdPrevious, false);
1167 
1168  // Let host widget perform query-start actions (disable widget, set cursor...)
1170 
1171  m_pSearch->Disable();
1172  m_pSelectAll->Disable();
1173  m_ToolBar->EnableTool(eCmdFilter, false);
1174  m_ToolBar->EnableTool(eCmdStringMatchType, false);
1175 
1176  // Setting host widget cursor my also set it for toolbar but we don't want
1177  // that since the cancel button is still active.
1178  m_ToolBar->SetCursor(*wxSTANDARD_CURSOR);
1179  m_ToolBar->SetCursor(*wxSTANDARD_CURSOR);
1180 
1181  try {
1182  bool casesensitive = m_CaseSensitive;
1183 
1184  // use the macro parser to get a list of function names that
1185  // may be found in the query:
1186  CRef<CMacroQueryExec> qexec(m_QueryDataSource->GetQueryExec(casesensitive, m_StringCompare));
1187  macro::CMacroParser p;
1188  qexec->GetFunctionNames(p);
1189 
1190  string query = m_pSearch->GetUtf8();
1191 
1193  m_PrevCaseSensitive = casesensitive;
1195 
1196  m_QueryDataSource->ClearQueryResults();
1197 
1198  CQueryParseTree* qtree = NULL;
1199  macro::CMacroRep* macro_rep = NULL;
1200  bool is_macro = false;
1201 
1202  try {
1203  // User May enter a macro or a query and they require different processing.
1204  // macros all start with 'macro' so check that first:
1205  if (query.length() > 5 &&
1206  !NStr::CompareNocase(query.substr(0, 5), "MACRO")) {
1207  is_macro = true;
1208 
1209  try {
1210  p.SetSource(query.c_str());
1211  p.Parse(true, qexec);
1212 
1213  macro_rep = p.DetachMacroRep();
1214  }
1215  catch (const CException& e) {
1216  LOG_POST(Error << "macro exception: " << e.GetMsg());
1217 
1218  status_msg = "Macro parsing failed: " + e.GetMsg();
1219  CompleteQuery(qexec.GetPointer(), status_msg);
1220  delete macro_rep;
1221  return;
1222  }
1223  }
1224  else {
1225  // If query tree parsing is case-sensitive, keywords like
1226  // AND and LIKE have to be uppercase, so we set that to
1227  // parsing to be case insensitive. The casesensitive we use
1228  // from the gui refers to string comparisons during execution and
1229  // does not effect parsing.
1230 
1231  qtree = new CQueryParseTree();
1232  qtree->Parse(query.c_str(),
1235  false,
1236  p.GetWhereFunctions());
1237 
1238  Flatten_ParseTree(*(qtree->GetQueryTree()));
1239 
1240 
1241  CNcbiOstrstream strstrm;
1242  qtree->Print(strstrm);
1243 
1244  // Logging merges lines (even if i call
1245  // UnsetDiagPostFlag(eDPF_PreMergeLines/eDPF_MergeLines);
1246  LOG_POST(Info << "Parsed Query: " << query);
1247  vector<string> arr;
1248  string s = (string)CNcbiOstrstreamToString(strstrm);
1249  NStr::Split(s, "\n", arr);
1250  for (size_t i = 0; i < arr.size(); ++i)
1251  LOG_POST(Info << arr[i]);
1252  }
1253  }
1254  catch (CQueryParseException& e) {
1255  LOG_POST(Info << "Error parsing query: " << e.GetMsg());
1256  m_QueryDataSource->ClearQueryResults();
1257  delete qtree;
1258  qtree = NULL;
1259 
1260  // Return completion status to caller:
1261  status_msg = "Query parsing failed: " + e.GetMsg();
1262  CompleteQuery(qexec.GetPointer(), status_msg);
1263  return;
1264  }
1265 
1266  if (is_macro) {
1267  // Regular queries are handled asynchronously since they
1268  // may require network access, which could get tied up.
1269  x_StartQueryJob(qexec, nullptr, macro_rep, casesensitive, query);
1270  }
1271  else {
1272  // If parsed query only has one top-level token, set that as a simple
1273  // string query (when query tree is NULL, string query is run)
1274  if (qtree->GetQueryTree()->CountNodes() == 0 &&
1275  qtree->GetQueryTree()->GetValue().IsValue() &&
1276  qtree->GetQueryTree()->GetValue().GetStrValue() != "") {
1277  // parsed query will remove double-quotes
1278  query = qtree->GetQueryTree()->GetValue().GetStrValue();
1279  delete qtree;
1280  qtree = NULL;
1281  }
1282 
1283  // Regular queries are handled asynchronously since they
1284  // may require network access, which could get tied up.
1285  x_StartQueryJob(qexec, qtree, macro_rep, casesensitive, query);
1286  }
1287 
1289  }
1290  // If this widget has been marked for deletion and has an exception,
1291  // return For a normal (query execution) exception without deletion,
1292  // continue normal processing.
1293  catch (CException&) {
1294  }
1295  }
1296 }
1297 
1298 void CQueryParsePanel::OnIdle(wxIdleEvent& event)
1299 {
1300  if (m_Future.IsComplete()) {
1301  try {
1302  m_Future();
1303  } NCBI_CATCH("CQueryParsePanel search.");
1304 
1305  if (!m_Job)
1306  return;
1307 
1308  string result_status;
1309 
1310  // If the job is finished, collect results and send completion message
1311  // to widget
1312  if (!m_Future.IsCanceled()) {
1313  LOG_POST(Info << "Number evaluated: " <<
1314  m_Job->GetQueriedCount() <<
1315  " Number of query execution errors: " <<
1316  m_Job->GetExceptionCount() <<
1317  string(" Query Time: ") << m_Job->GetQueryTime());
1318 
1319  result_status = string("Number evaluated: ") +
1320  NStr::NumericToString(m_Job->GetQueriedCount()) +
1321  string(". Number Selected: ") +
1322  NStr::NumericToString(m_Job->GetNumSelected()) +
1323  string(". Query Time: ") + NStr::DoubleToString(m_Job->GetQueryTime());
1324  if (m_Job->GetExceptionCount() > 0) {
1325  result_status += string(" Number with query errors: ") +
1326  NStr::IntToString(m_Job->GetExceptionCount());
1327  }
1328 
1329  // Set the selection set to the returned entries
1330  if (m_Job->GetQueryExec() != NULL)
1331  m_QueryDataSource->SetQueryResults(m_Job->GetQueryExec());
1332  }
1333  // Done with job, but we don't want the results:
1334  else {
1335  LOG_POST(Info << "Number evaluated (for cancelled search): " <<
1336  m_Job->GetQueriedCount() <<
1337  " Number with query execution errors: " <<
1338  m_Job->GetExceptionCount());
1339 
1340  result_status = string("Number evaluated (for cancelled search): ") +
1341  NStr::NumericToString(m_Job->GetQueriedCount()) +
1342  string(". Number Selected: ") +
1343  NStr::NumericToString(m_Job->GetNumSelected()) + string(".");
1344  if (m_Job->GetExceptionCount() > 0) {
1345  result_status += string(" Number with query errors: ") +
1346  NStr::IntToString(m_Job->GetExceptionCount());
1347  }
1348  }
1349 
1350  CompleteQuery(m_Job->GetQueryExec(), result_status);
1351 
1352  // Delete the completed job object
1353  m_Job.Reset();
1354 
1355  m_Future.reset();
1356  }
1357  else
1358  event.Skip();
1359 }
1360 
1362 {
1363  if (m_Future.IsRunning()) {
1364  m_Future.cancel();
1365 
1366  // by default, we do not run the same query twice (since the results
1367  // are already there) but if the job is cancelled, this allows the
1368  // query to be re-executed.
1369  m_PrevQuery = "";
1370  }
1371 }
1372 
1374 {
1375  if (q == "")
1376  return;
1377 
1378  vector<pair<string,string> >::iterator iter;
1379  for (iter = m_RecentQueries.begin(); iter != m_RecentQueries.end(); ++iter) {
1380  if ((*iter).second == q) {
1381  m_RecentQueries.erase(iter);
1382  break;
1383  }
1384  }
1385 
1386  m_RecentQueries.insert(m_RecentQueries.begin(), pair<string,string>(string(), q));
1387 
1388  if (m_RecentQueries.size() > (unsigned int)m_MaxRecentQueries)
1389  m_RecentQueries.erase(m_RecentQueries.begin() + m_RecentQueries.size()-1);
1390 }
1391 
EVT_CHECKBOX(ID_CADJUSTFEATURES_CHECKBOX, CAdjustFeaturesForGaps::OnKnownUnknownSelected) EVT_CHECKBOX(ID_CADJUSTFEATURES_CHECKBOX1
void GUI_AsyncJoinFuture(const job_future_base &future, const string &msg)
Definition: async_call.cpp:58
Checksum and hash calculation classes.
IAppJobListener Interface for components that need to be notified about changes in Jobs.
CChecksum – Checksum calculator.
Definition: checksum.hpp:302
CRegistryWriteView GetWriteView(const string &section)
get a read-write view at a particular level.
Definition: registry.cpp:462
static CGuiRegistry & GetInstance()
access the application-wide singleton
Definition: registry.cpp:400
CRegistryReadView GetReadView(const string &section) const
get a read-only view at a particular level.
Definition: registry.cpp:428
class CMacroQueryExec
virtual bool EvalNext(macro::CMacroRep &)
virtual void GetFunctionNames(macro::CMacroParser &parser) const
CNcbiOstrstreamToString class helps convert CNcbiOstrstream to a string Sample usage:
Definition: ncbistre.hpp:802
class CQueryExecException
class CQueryExecPreProcessFunc
Class for extracting positions of data fields from the query.
std::vector< std::pair< size_t, size_t > > GetFieldPositions() const
ETreeTraverseCode operator()(const CTreeNode< CQueryParseNode > &tr, int delta)
std::vector< std::pair< size_t, size_t > > m_FieldPositions
class CQueryNodeValue
bool IsDataField() const
Query parser exceptions.
Query node class.
Definition: query_parse.hpp:79
Job class used to run query on separate thread.
CStringMatching::EStringMatching m_StringCompare
string m_QueryString
For simple string queries.
CQueryParseTree * m_QueryTree
Parsed query tree.
size_t GetQueriedCount() const
Get stats on how many elements were checked and how many were checked but failed for some reason (suc...
void Execute(ICanceled &canceled)
CRef< CMacroQueryExec > m_QExec
Query execution object.
CQueryParsePanel.
bool m_PrevCaseSensitive
Value of case-sensitive button last time query was executed.
string GetLastQuery() const
Get the text for the most recently executed query.
void OnButtonNext(wxCommandEvent &evt)
void OnToggleSelectAll(wxCommandEvent &evt)
virtual void SaveSettings() const
void OnSearchctrlSearchButtonClick(wxCommandEvent &evt)
void x_ExecuteQuery(int search_dir)
Parse query and determine how to execute.
CIRef< CQueryJob > m_Job
Current tree-query job.
bool x_IsValidQuery(string query, bool casesensitive, vector< std::pair< size_t, size_t > > &fields)
Return true if query parses correctly, putting field names in 'fields'.
static const int m_MaxRecentQueries
Max number of recent queries to include in list.
virtual void SetRegistryPath(const string &reg_path)
void OnIdle(wxIdleEvent &event)
void OnQuerySel(wxCommandEvent &evt)
void OnSearchctrlTextEnter(wxCommandEvent &evt)
static const int m_MaxDefaultQueries
wxCheckBox * m_pSelectAll
CStringMatching::EStringMatching m_StringCompare
How to compare strings in query - wildcards, exact match, etc.
void x_StartQueryJob(CRef< CMacroQueryExec > qexec, CQueryParseTree *qtree, macro::CMacroRep *macro_rep, bool casesensitive, const string &query)
Submit query job for asynch execution.
void OnStringMatchTypeSelected(wxCommandEvent &evt)
vector< pair< string, string > > m_RecentQueries
Set of recent queries.
void SetDefaultQueries(const TNamedQueries &q)
Set the set of default queries for the current data source.
void CompleteQuery(CMacroQueryExec *qexec, const string &status)
void HideSelectAll(void)
Hide the Select All checkbox.
bool IsSelectAll()
Return true if select all checkbox is checked.
void SetDataSource(IQueryDataSource *ds)
Set or update data source.
void OnButtonPrevious(wxCommandEvent &evt)
virtual void Create(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize)
Create window.
string m_PrevQuery
String of query last time query was executed.
void CreateControls()
Creates the controls and sizers.
void OnStringMatchTypeBtn(wxCommandEvent &evt)
CRichTextCtrl * m_pSearch
Widgets.
void x_CancelQueryInProgress()
If user presses cancel button, cancel running job.
void OnSearchHelp(wxCommandEvent &evt)
virtual void LoadSettings()
vector< pair< string, string > > TNamedQueries
string m_RegSection
Registry section for specific current data source (derived from columns)
IQueryWidget * m_QueryWidget
Interface to widget which will display query results.
std::string m_SearchString
current search string (as of previous update to m_pSearch)
string m_RegPath
Registry path for query panel.
void OnRecentQuery(wxCommandEvent &evt)
CStringMatching::EStringMatching m_PrevStringCompare
Value of string-matching selection last time query was executed.
wxAnimationCtrl * m_Animation
std::vector< std::pair< size_t, size_t > > m_SearchStringFields
positions of dictionary fields in current search string
CIRef< IQueryDataSource > m_QueryDataSource
Interface to data source that is being queried.
vector< pair< string, string > > m_DefaultQueries
Set of default queries.
void OnSearchctrlSearchStop(wxCommandEvent &evt)
void AddQueryText(const string &query_mod)
Add given string to currently displayed query text.
void OnCtrlKillFocus(wxFocusEvent &evt)
bool m_CaseSensitive
Current value for case-sensitive.
void Init()
Initialises member variables.
void OnToggleHideUnselected(wxCommandEvent &evt)
void x_AddRecentQuery(const std::string &q)
Add a query to the list of recently used queries, if it is unique.
void OnContextMenu(wxContextMenuEvent &)
wxStaticText * m_SearchType
static bool m_IconsInitialized
Only need to load icons into art provider once per run.
job_future< void > m_Future
Query tree and associated utility methods.
class CRegistryReadView provides a nested hierarchical view at a particular key.
Definition: reg_view.hpp:58
void GetStringVec(const string &key, vector< string > &val) const
Definition: reg_view.cpp:263
void Set(const string &key, int val)
access a named key at this level, with no recursion
Definition: reg_view.cpp:533
CRichTextCtrl - a wrapper for wxRichTextCtrl that handles additional keyboard events (such as Clipboa...
string GetUtf8() const
CStopWatch –.
Definition: ncbitime.hpp:1938
class CTextSearch
EStringMatching
String matching algorithms.
@ eWildcardMatch
Wildcard pattern matching.
@ eRegex
Regular expression matching.
@ ePlainSearch
Plain search.
@ eMetaphone
Metaphone mathcing.
static wxString ResolvePath(const wxString &path, const wxString &rel_name)
Utility function to hide the platform specifics of locating our standard directories and files.
Definition: sys_path.cpp:106
definition of a Culling tree
Definition: ncbi_tree.hpp:100
Interface for testing cancellation request in a long lasting operation.
Definition: icanceled.hpp:51
class IQueryDataSource
virtual void ExecuteStringQuery(const string &query, size_t &num_selected, size_t &num_queried, CStringMatching::EStringMatching string_matching=CStringMatching::ePlainSearch, NStr::ECase use_case=NStr::eCase)=0
Execute a string-matching query on the underlying data.
Base class for query node user defined object.
Definition: query_parse.hpp:60
IQueryWidget.
virtual void SetHideUnselected(bool)
set to true to hide/obscure elements not selected by most recent query
virtual void IterateSelection(int)
go to next(1), previous(-1) or first(0) element from most recent query
virtual void SetSelectAll(bool)
set to yes to show all queried elements as selected
virtual string GetSearchHelpAddr() const
Return web-address for the help page that disusses help for the specific widget.
virtual void QueryStart()
Disable any widgets and/or set cursor/scroll as needed when query starts.
virtual void DlgOverlayFix(wxWindow *win)
let widget send fake resize to fix windows opengl bug.
virtual void QueryEnd(CMacroQueryExec *exec)
Re-enable widgets and/or set cursor/scroll as needed when query ends.
bool IsComplete() const
Definition: job_future.hpp:205
bool IsRunning() const
Definition: job_future.hpp:204
bool IsCanceled() const
Definition: job_future.hpp:206
virtual void RegisterFileAlias(const wxArtID &anId, const wxArtClient &aClient, const wxSize &aSize, const wxString &aName, long aType=wxBITMAP_TYPE_ANY, int anIndex=-1)
static int simple_string(void)
#define _(proto)
Definition: ct_nlmzip_i.h:78
#define false
Definition: bool.h:36
static DLIST_TYPE *DLIST_NAME() first(DLIST_LIST_TYPE *list)
Definition: dlist.tmpl.h:46
static const char * str(char *buf, int n)
Definition: stats.c:84
string
Definition: cgiapp.hpp:687
#define NULL
Definition: ncbistd.hpp:225
void AddLine(const char *line, size_t len)
Definition: checksum.hpp:609
#define _TRACE(message)
Definition: ncbidbg.hpp:122
#define LOG_POST(message)
This macro is deprecated and it's strongly recomended to move in all projects (except tests) to macro...
Definition: ncbidiag.hpp:226
void Error(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1197
#define NCBI_CATCH(message)
Catch CExceptions as well This macro is deprecated - use *_X or *_XX variant instead of it.
Definition: ncbiexpt.hpp:580
const string & GetMsg(void) const
Get message string.
Definition: ncbiexpt.cpp:461
void Info(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1185
virtual bool Send(CEvent *evt, EDispatch disp_how=eDispatch_Default, int pool_name=ePool_Default)
Sends an event synchronously.
TObjectType * GetPointer(void) THROWS_NONE
Get pointer,.
Definition: ncbiobj.hpp:998
void Reset(void)
Reset reference object.
Definition: ncbiobj.hpp:773
bool IsNull(void) const THROWS_NONE
Check if pointer is null – same effect as Empty().
Definition: ncbiobj.hpp:735
TObjectType * GetPointerOrNull(void) THROWS_NONE
Get pointer value.
Definition: ncbiobj.hpp:986
const IQueryParseUserObject * GetUserObject() const
Get user object.
void Parse(const char *query_str, ECase case_sense=eCaseInsensitive, ESyntaxCheck syntax_check=eSyntaxCheck, bool verbose=false, const TFunctionNames &functions=TFunctionNames(0), unsigned line=0, unsigned linePos=0)
Query parser front-end function.
Definition: parser.cpp:368
int GetQueriedCount() const
Definition: query_exec.hpp:224
virtual void EvalStart()
Definition: query_exec.hpp:219
virtual bool EvalComplete()
Definition: query_exec.hpp:222
unsigned pos
Position in the src line.
const TNode * GetQueryTree() const
void Print(CNcbiOstream &os) const
Print the query tree (debugging)
const string & GetStrValue() const
void Flatten_ParseTree(CQueryParseTree::TNode &node)
Flatten the AND and the OR subtrees transforming them from binary subtrees to n-ary subtrees.
Definition: parse_utils.cpp:38
const SSrcLoc & GetLoc() const
@ eCaseSensitiveUpper
Operators must come in upper case (AND)
@ eCaseInsensitive
Case insensitive parsing (AnD)
@ eSyntaxCheck
Best possible check for errors.
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
virtual bool IsCanceled(void) const =0
static string DoubleToString(double value, int precision=-1, TNumToStringFlags flags=0)
Convert double to string.
Definition: ncbistr.hpp:5187
static int CompareNocase(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n, const char *s2)
Case-insensitive compare of a substring with another string.
Definition: ncbistr.cpp:219
static list< string > & Split(const CTempString str, const CTempString delim, list< string > &arr, TSplitFlags flags=0, vector< SIZE_TYPE > *token_pos=NULL)
Split a string using specified delimiters.
Definition: ncbistr.cpp:3461
static void TruncateSpacesInPlace(string &str, ETrunc where=eTrunc_Both)
Truncate spaces in a string (in-place)
Definition: ncbistr.cpp:3201
static string IntToString(int value, TNumToStringFlags flags=0, int base=10)
Convert int to string.
Definition: ncbistr.hpp:5084
static enable_if< is_arithmetic< TNumeric >::value||is_convertible< TNumeric, Int8 >::value, string >::type NumericToString(TNumeric value, TNumToStringFlags flags=0, int base=10)
Convert numeric value to string.
Definition: ncbistr.hpp:673
static string TruncateSpaces(const string &str, ETrunc where=eTrunc_Both)
Truncate spaces in a string.
Definition: ncbistr.cpp:3186
@ eTrunc_Begin
Truncate leading spaces only.
Definition: ncbistr.hpp:2240
@ eNocase
Case insensitive compare.
Definition: ncbistr.hpp:1206
@ eCase
Case sensitive compare.
Definition: ncbistr.hpp:1205
double Elapsed(void) const
Return time elapsed since first Start() or last Restart() call (in seconds).
Definition: ncbitime.hpp:2776
void Start(void)
Start the timer.
Definition: ncbitime.hpp:2765
Fun TreeDepthFirstTraverse(TTreeNode &tree_node, Fun func)
Depth-first tree traversal algorithm.
Definition: ncbi_tree.hpp:504
ETreeTraverseCode
Tree traverse code returned by the traverse predicate function.
Definition: ncbi_tree.hpp:51
unsigned int CountNodes(unsigned int depth=1, TCountNodes how=0) const
Count nodes of the tree of which this node is a root.
Definition: ncbi_tree.hpp:999
const TValue & GetValue(void) const
Return node's value.
Definition: ncbi_tree.hpp:184
@ eTreeTraverse
Keep traversal.
Definition: ncbi_tree.hpp:52
job_function_traits< _Fty >::future job_async(const _Fty &_Fnarg, const string &descr)
Definition: job_future.hpp:428
END_EVENT_TABLE()
int i
Macro exceptions.
Macro parser components.
#define wxT(x)
Definition: muParser.cpp:41
const struct ncbi::grid::netcache::search::fields::SIZE size
T max(T x_, T y_)
T min(T x_, T y_)
Int4 delta(size_t dimension_, const Int4 *score_)
double f(double x_, const double &y_)
Definition: njn_root.hpp:188
Query string parsing components.
USING_SCOPE(objects)
#define ID_STRING_MATCH_TYPE1
#define ID_SELECT_ALL
#define ID_SEARCHCTRL
static const char * kRecentQueries
const char * kStringMatchTypes[kStringMatchTypesCount]
#define ID_MRU1
const int kStringMatchTypesCount
#define ID_QUERY_ANIMATIONCTRL
EVT_COMMAND_RANGE(13014, 13014+CQueryParsePanel::m_MaxRecentQueries+CQueryParsePanel::m_MaxDefaultQueries - 1, wxEVT_COMMAND_MENU_SELECTED, CQueryParsePanel::OnRecentQuery) EVT_COMMAND_RANGE(14014
static const char * kQueryPanel
CStringMatching::EStringMatching kStringMatchEnumTypes[kStringMatchTypesCount]
wxEVT_COMMAND_MENU_SELECTED
#define ID_TOOLBAR
const char * kStringMatchTypesToolbar[kStringMatchTypesCount]
static static static wxID_ANY
static string query
wxFileArtProvider * GetDefaultFileArtProvider()
Definition: wx_utils.cpp:334
wxString ToWxString(const string &s)
Definition: wx_utils.hpp:173
string GetMD5Digest(const CChecksum &cs)
Definition: wx_utils.cpp:211
Modified on Sun Apr 14 05:27:01 2024 by modify_doxy.py rev. 669887