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

Go to the SVN repository for this file.

1 /* $Id: selection_manager.cpp 47496 2023-05-19 14:31:58Z evgeniev $
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 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: Liangshou Wu
27 *
28 * File Description:
29 */
30 
31 #include <ncbi_pch.hpp>
35 #include <gui/objutils/snp_gui.hpp>
36 #include <objmgr/util/sequence.hpp>
37 
40 
41 void CSelectionVisitor::SetScope(objects::CScope* scope)
42 {
43  m_Scope.Reset(scope);
44  Clear();
45 }
46 
47 objects::CScope* CSelectionVisitor::GetScope()
48 {
49  return m_Scope.GetPointer();
50 }
51 
53 {
54  switch (m_ActionMode) {
55  case eAct_Select:
56  return x_DoSelection(glyph);
57  case eAct_Deselect:
58  glyph->SetSelected(false);
59  return true;
60  case eAct_CollectSel:
61  if (glyph->IsSelected()) {
62  m_SelGlyphs.push_back( CConstRef<CSeqGlyph>(glyph) );
63  }
64  return true;
65  default:
66  _ASSERT(false);
67  return false;
68  }
69 }
70 
71 
72 void CSelectionVisitor::SetSelectedObjectSig(const string& obj_sig)
73 {
74  m_SelectedSignatures.clear();
76  NON_CONST_ITERATE (list<string>, iter, m_SelectedSignatures) {
78  }
79  // remove the empty ones
80  m_SelectedSignatures.remove("");
81 }
82 
84 {
88 
89  m_SelFeatures.clear();
90  m_SelCDSFeatures.clear();
92 }
93 
94 
96 {
97  if (obj) {
98  if (m_SelectedObjects.count(CConstRef<CObject>(obj)) > 0) {
99  return true;
100  }
101 
102  // The original object changes for these two cases:
103  // 1. For component segments (the original objec tis a seq_id)
104  // 2. For snp features
105  // For this two cases, we need to fall back to CObjectIndex
106  // to do the matching.
107  bool use_index = false;
108  if (typeid(*obj) == typeid(CSeq_id)) {
109  use_index = true;
110  } else if (typeid(*obj) == typeid(CSeq_feat)) {
111  const CSeq_feat* feat_obj = dynamic_cast<const CSeq_feat*>(obj);
112  if (feat_obj->GetData().GetSubtype() == CSeqFeatData::eSubtype_variation) {
113  use_index = true;
114  }
115  }
116  if (use_index && m_SelectedIndexes.HasMatches(*obj, *m_Scope)) {
117  return true;
118  }
119  // another special case is CVcfVariant:
120  // instead of pointer/index matching we want to match the actual contents of CVcfVariant
121  const CVcfVariant* vcf_variant = dynamic_cast<const CVcfVariant*>(obj);
122  if(vcf_variant) {
123  for(auto selected_object: m_SelectedObjects) {
124  const CVcfVariant* vcf_variant_select_candidate = dynamic_cast<const CVcfVariant*>(selected_object.GetPointer());
125  if(vcf_variant_select_candidate && vcf_variant_select_candidate->WeakMatch(*vcf_variant)) {
126  return true;
127  }
128  }
129  }
130  }
131  return false;
132 }
133 
134 
137 {
138  m_SelGlyphs.clear();
140  top_glyph->Accept(this);
141 
142  return m_SelGlyphs;
143 }
144 
145 
147 {
148  objs.reserve(m_SelectedObjects.size());
150  objs.push_back(CConstRef<CObject>(*it));
151  }
152 }
153 
154 
156 {
157  m_SelFeatures.clear();
158  m_SelCDSFeatures.clear();
159  if (x_NeedUpdate()) {
164  glyph->Accept(this);
165  }
166 }
167 
168 
170 {
171  if(obj && IsObjectSelected(obj)) {
172  if ( !m_SelectedIndexes.Empty() ) {
174  }
177  if (iter == m_SelectedObjects.end()) {
178  const CSeq_id* id = dynamic_cast<const CSeq_id*>(obj);
179  if (id) {
182  const CSeq_id* t_id = dynamic_cast<const CSeq_id*>(o_iter->GetPointer());
183  if (t_id && sih == *t_id) {
184  iter = o_iter;
185  break;
186  }
187  }
188  }
189  }
190  if (iter != m_SelectedObjects.end()) {
191  m_SelectedObjects.erase(iter);
192  }
193 
194  m_DeselectedObjs = 1;
198  }
199  }
200 }
201 
202 
203 void CSelectionVisitor::SelectObject(const CObject* obj, bool verified)
204 {
205  CConstRef<CObject> object(obj);
206  if (m_SelectedObjects.count(object) != 0) return;
207 
208  if (verified) {
209  m_SelectedObjects.insert(object);
210  m_SelectedIndexes.Add(NULL, *const_cast<CObject*>(obj));
211  } else if ( !m_UnknownSelectedIndexes.HasMatches(*obj, *m_Scope) ) {
212  // the object may be broadcasted from other view, and it is
213  // not verified by any means if it is a seq-id
214  m_UnknownSelectedIndexes.Add(NULL, *const_cast<CObject*>(obj));
215  }
216 }
217 
218 
220 {
221  ITERATE (CSeqGlyph::TConstObjects, iter, glyphs) {
222  const IObjectBasedGlyph* obj_glyph =
223  dynamic_cast<const IObjectBasedGlyph*>(iter->GetPointer());
224  if (obj_glyph) {
225  vector< CConstRef<CObject> > objs;
226  obj_glyph->GetObjects(objs);
227  NON_CONST_ITERATE (vector< CConstRef<CObject> >, obj_iter, objs) {
228  if ( m_SelectedObjects.count(*obj_iter) == 0) {
229  m_SelectedIndexes.Add(NULL, const_cast<CObject&>(**obj_iter));
230  m_SelectedObjects.insert(*obj_iter);
231  }
232  }
233  }
234  }
235 }
236 
237 
239 {
241  m_TraversedObjs = 0;
242  m_TraversedSigs = 0;
243  m_SelCDSFeatures.clear();
244  m_SelFeatures.clear();
246 
247  if (x_NeedUpdate()) {
248  glyph->Accept(this);
251  break;
252  }
254  }
257  CRef<CSeqGlyph> pGlyph(iSelFeatures->Lock());
258 
259  if(pGlyph.NotNull()) {
260  CFeatGlyph* pFeatGlyph(dynamic_cast<CFeatGlyph*>(pGlyph.GetPointerOrNull()));
261  if(pFeatGlyph){
263  pFeatGlyph->LayoutChanged();
264  }
265  }
266  }
267  }
268  }
269  }
270 }
271 
272 
274 {
275  bool cont = true;
276 
277  IObjectBasedGlyph* obj_glyph = dynamic_cast<IObjectBasedGlyph*>(glyph);
278  if ( !obj_glyph ) {
279  return cont;
280  }
281 
282  // the optimization may not make sense since there might be
283  // two or more objects share the same signature
284  if (m_SelectedSignatures.size() == m_TraversedSigs) {
285  cont = false;
286  }
287 
288  // signatures for features
289  if (cont && !m_SelectedSignatures.empty()) {
290  string f_sig = obj_glyph->GetSignature();
291  ITERATE(list<string>, it, m_SelectedSignatures) {
292  string sig = *it;
293  // Considering that some signatures may not contain data source
294  // information, we tolerate partial matching here.
295  if (sig.find(f_sig) != string::npos) {
296  if(glyph->SetSelected(true)) {
298  cont = false;
299  }
300  m_SelFeatures.push_back(CWeakRef<CSeqGlyph>(glyph));
301  CCdsGlyph* cds = dynamic_cast<CCdsGlyph*>(glyph);
302  if (cds) {
303  // keep CDS features for speciality grid rendering
304  m_SelCDSFeatures.push_back(CWeakRef<CSeqGlyph>(glyph));
305  }
306  ++m_TraversedSigs;
307  }
308  }
309  // we assume selection by m_SelectedSignatures is only used in cgi mode,
310  // and in cgi mode, m_SelectedIndexes will never be used.
311  return cont;
312  }
313 
314  // the optimization may not make sense since there might be
315  // two or more objects share the same original object
316  //if (m_SelectedObjects.size() == m_TraversedObjs &&
317  // m_DeselectedObjs <= 0) {// do nothing in no selected objects
318  // return cont;
319  //}
320 
321  bool selected = false;
322  vector< CConstRef<CObject> > objs;
323  obj_glyph->GetObjects(objs);
324 
325  ITERATE(vector<CConstRef<CObject> >, it, objs) {
326  const CObject& object = **it;
330  m_SelectedIndexes.Add(NULL, const_cast<CObject&>(object));
332  selected = true;
333  ++m_TraversedObjs;
334  break;
335  }
336 
337  if (IsObjectSelected(&object)) {
338  selected = true;
339  ++m_TraversedObjs;
340  }
341 
342  // special case for SeqGraphs might be needed
343  /*CConstRef<CObject> obj1 = *it;
344  ITERATE (TSelectedObjects, it2, *m_SelectedObjects) {
345  CConstRef<CObject> obj2 = *it2;
346  if (obj1.GetPointer() == obj2.GetPointer()) {
347  selected = true;
348  break;
349  }
350  }*/
351  }
352 
353  if (selected != glyph->IsSelected()) {
354  if (glyph->SetSelected(selected)) {
356  }
357  if (!selected && m_DeselectedObjs > 0) {
359  }
360  }
361 
362  // Save intervals for selected features and pairwise alignments
363  // we do matching later, to render hair-lines for intervals
364  if (selected && obj_glyph) {
365  m_SelFeatures.push_back(CWeakRef<CSeqGlyph>(glyph));
366 
367  CCdsGlyph* cds = dynamic_cast<CCdsGlyph*>(obj_glyph);
368  if (cds) {
369  // keep CDS features for speciality grid rendering
370  m_SelCDSFeatures.push_back(CWeakRef<CSeqGlyph>(glyph));
371  }
372  }
373  return true;
374 }
375 
376 
CConstRef –.
Definition: ncbiobj.hpp:1266
void LayoutChanged()
update the layout for everything encompassing this glyph
void Clear(objects::CScope *scope)
bool Remove(const CObject &obj)
bool HasMatches(const CObject &object, objects::CScope &scope) const
bool Empty() const
void Add(ISelObjectHandle *obj_handle, CObject &obj)
CObject –.
Definition: ncbiobj.hpp:180
objects::CScope * GetScope()
TSelectedGlyphs m_SelCDSFeatures
void UpdateSelection(CSeqGlyph *glyph)
void ResetObjectSelection(CSeqGlyph *glyph)
TSelectedGlyphs m_SelFeatures
void GetObjectSelection(TConstObjects &objs) const
CSeqGlyph::TConstObjects m_SelGlyphs
const CSeqGlyph::TConstObjects & GetSelectedLayoutObjects(CSeqGlyph *top_glyph)
list< CWeakRef< CSeqGlyph > > TSelectedGlyphs
bool x_DoSelection(CSeqGlyph *glyph)
void SelectObject(const CObject *obj, bool verified)
TSelectedObjects m_SelectedObjects
bool IsObjectSelected(const CObject *obj)
@ ePUA_CallLayoutChanged
call LayoutChanged for all glyphs that are CFeatGlyph
CObjectIndex m_UnknownSelectedIndexes
CObjectIndex m_SelectedIndexes
virtual bool Visit(CSeqGlyph *glyph)
CRef< objects::CScope > m_Scope
EPostUpdateAction m_PostUpdateAction
void DeSelectObject(const CObject *obj)
void SelectSelection(const CSeqGlyph::TConstObjects &glyphs)
list< string > m_SelectedSignatures
void SetSelectedObjectSig(const string &obj_sig)
void SetActionMode(TActionMode mode)
CSelectionVisitor inline methods.
void SetScope(objects::CScope *scope)
ESubtype GetSubtype(void) const
class CSeqGlyph defines an interface that wraps a rectilinear abstract object.
Definition: seq_glyph.hpp:82
bool IsSelected() const
Definition: seq_glyph.hpp:573
virtual bool Accept(IGlyphVisitor *visitor)
Interface for accepting an IGlyphVisitor.
Definition: seq_glyph.hpp:519
virtual bool SetSelected(bool flag)
Select or deselect this glyph.
Definition: seq_glyph.hpp:525
list< CConstRef< CSeqGlyph > > TConstObjects
Definition: seq_glyph.hpp:86
namespace ncbi::objects::
Definition: Seq_feat.hpp:58
File Description:
virtual string GetSignature() const =0
return signature for this glyph.
virtual void GetObjects(vector< CConstRef< CObject > > &objs) const =0
retrieve CObjects corresponding to this CSeqGlyph.
iterator_bool insert(const value_type &val)
Definition: set.hpp:149
void clear()
Definition: set.hpp:153
parent_type::iterator iterator
Definition: set.hpp:80
size_type size() const
Definition: set.hpp:132
bool empty() const
Definition: set.hpp:133
const_iterator find(const key_type &key) const
Definition: set.hpp:137
void erase(iterator pos)
Definition: set.hpp:151
const_iterator end() const
Definition: set.hpp:136
#define ITERATE(Type, Var, Cont)
ITERATE macro to sequence through container elements.
Definition: ncbimisc.hpp:815
#define NON_CONST_ITERATE(Type, Var, Cont)
Non constant version of ITERATE macro.
Definition: ncbimisc.hpp:822
#define NULL
Definition: ncbistd.hpp:225
bool WeakMatch(const CVcfVariant &right) const
Definition: snp_gui.hpp:315
vector< CConstRef< CObject > > TConstObjects
Definition: objects.hpp:64
const CSeq_id & GetId(const CSeq_loc &loc, CScope *scope)
If all CSeq_ids embedded in CSeq_loc refer to the same CBioseq, returns the first CSeq_id found,...
@ eGetId_Canonical
Definition: sequence.hpp:114
bool NotNull(void) const THROWS_NONE
Check if pointer is not null – same effect as NotEmpty().
Definition: ncbiobj.hpp:744
TObjectType * GetPointer(void) THROWS_NONE
Get pointer,.
Definition: ncbiobj.hpp:998
void Reset(void)
Reset reference object.
Definition: ncbiobj.hpp:773
TObjectType * GetPointerOrNull(void) THROWS_NONE
Get pointer value.
Definition: ncbiobj.hpp:986
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
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:3452
static void TruncateSpacesInPlace(string &str, ETrunc where=eTrunc_Both)
Truncate whitespace in a string (in-place)
Definition: ncbistr.cpp:3192
@ fSplit_Tokenize
All delimiters are merged and trimmed, to get non-empty tokens only.
Definition: ncbistr.hpp:2510
const TData & GetData(void) const
Get the Data member data.
Definition: Seq_feat_.hpp:925
static int * results[]
USING_SCOPE(objects)
#define _ASSERT
Modified on Fri Sep 20 14:57:22 2024 by modify_doxy.py rev. 669887