tax_tree.cpp
来自「ncbi源码」· C++ 代码 · 共 429 行
CPP
429 行
/* * =========================================================================== * PRODUCTION $Log: tax_tree.cpp,v $ * PRODUCTION Revision 1000.1 2004/06/01 21:13:24 gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.11 * PRODUCTION * =========================================================================== *//* $Id: tax_tree.cpp,v 1000.1 2004/06/01 21:13:24 gouriano Exp $ * =========================================================================== * * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information * * This software/database is a "United States Government Work" under the * terms of the United States Copyright Act. It was written as part of * the author's official duties as a United States Government employee and * thus cannot be copyrighted. This software/database is freely available * to the public for use. The National Library of Medicine and the U.S. * Government have not placed any restriction on its use or reproduction. * * Although all reasonable efforts have been taken to ensure the accuracy * and reliability of the software and data, the NLM and the U.S. * Government do not and cannot warrant the performance or results that * may be obtained by using this software or data. The NLM and the U.S. * Government disclaim all warranties, express or implied, including * warranties of performance, merchantability or fitness for any particular * purpose. * * Please cite the author in any work or product based on this material. * * =========================================================================== * * Authors: Mike DiCuccio * * File Description: * */#include <ncbi_pch.hpp>#include <gui/widgets/tax_tree/tax_tree.hpp>#include <gui/widgets/tax_tree/tax_tree_ds.hpp>#include <gui/utils/reporter.hpp>#include <gui/objutils/utils.hpp>#include <objects/taxon1/taxon1.hpp>#include <algorithm>#include <stack>BEGIN_NCBI_SCOPEUSING_SCOPE(objects);//// internal tree structure//class CTaxTree{public: typedef list<CTaxTree*> TChildren; CTaxTree(const CTaxTreeDataSource& ds, const ITaxon1Node* node, const CTaxTreeDataSource::TUidVec& uids) : m_TaxNode(node) , m_Uids(uids) , m_DS(&ds) { } ~CTaxTree() { Clear(); } void AddChild(CTaxTree* child) { m_Children.push_back(child); } void RemoveChild(CTaxTree* child) { m_Children.remove(child); } string GetName(void) const { string str; m_DS->GetTitle(*m_TaxNode, &str); str += " (" + NStr::IntToString(CountUids()) + " sequences)"; return str; } void Clear(void) { NON_CONST_ITERATE (TChildren, iter, m_Children) { delete *iter; } m_Children.clear(); } size_t CountUids(void) const { size_t sum = m_Uids.size(); ITERATE (TChildren, iter, m_Children) { sum += (*iter)->CountUids(); } return sum; } void CollectUids(CTaxTreeDataSource::TUidVec& uids) const { uids.insert(uids.end(), m_Uids.begin(), m_Uids.end()); ITERATE (TChildren, iter, m_Children) { (*iter)->CollectUids(uids); } } // information for this node CConstRef<CTaxTreeDataSource> m_DS; const ITaxon1Node* m_TaxNode; CTaxTreeDataSource::TUidVec m_Uids; TChildren m_Children;};//// internal class to fill our tree structure//class CTreeFiller : public ITreeIterator::I4Each{public: CTreeFiller(CTaxTreeDataSource& ds, const CTaxTreeBrowser::TTaxMap& tax_map) : m_TaxMap(tax_map) , m_Curr(NULL) , m_DS(&ds) { } ITreeIterator::EAction LevelBegin(const ITaxon1Node* tax_node) { if (m_Curr) { m_Nodes.push(m_Curr); } m_Curr = NULL; return ITreeIterator::eOk; } ITreeIterator::EAction Execute(const ITaxon1Node* tax_node) { CTaxTreeDataSource::TUidVec uids; int tax_id = tax_node->GetTaxId(); CTaxTreeBrowser::TTaxMap::const_iterator iter = m_TaxMap.find(tax_id); if (iter != m_TaxMap.end()) { uids = iter->second; } CTaxTree* node = new CTaxTree(*m_DS, tax_node, uids); if ( !m_Tree.get() ) { m_Tree.reset(node); } if (m_Nodes.size()) { CTaxTree* parent = m_Nodes.top(); parent->AddChild(node); } m_Curr = node; return ITreeIterator::eOk; } ITreeIterator::EAction LevelEnd(const ITaxon1Node* tax_node) { m_Curr = m_Nodes.top(); m_Nodes.pop(); return ITreeIterator::eOk; } const CTaxTreeBrowser::TTaxMap& m_TaxMap; auto_ptr<CTaxTree> m_Tree; CTaxTree* m_Curr; CConstRef<CTaxTreeDataSource> m_DS; stack<CTaxTree*> m_Nodes;};// callback - not a good way to go, but keeps FluTree unchanged// in case it will be updated externallyvoid OnTaxtreeNotify(Fl_Widget * widget, void * data){ CTaxTreeBrowser * pTaxTree = dynamic_cast<CTaxTreeBrowser*> (widget); if (pTaxTree) { CTaxTreeDataSource::TUidVec uids; uids.clear(); pTaxTree->GetSelectedUids(uids); switch (pTaxTree->callback_reason()) { case FLU_SELECTED: case FLU_UNSELECTED: { CObjectFor< vector<CConstRef<objects::CSeq_id> > > csid; csid = uids; pTaxTree->FireEvent(CViewEvent::CreateEvent(CViewEvent::eSelectionChanged, CViewEvent::eEventViews, CViewEvent::TEventObject(&csid), pTaxTree)); } } } }CTaxTreeBrowser::CTaxTreeBrowser(int x, int y, int w, int h, const char* label) : CTreeBrowser(x, y, w, h, label) , m_Reporter(NULL) , m_DispMode(CTaxTreeDataSource::eDisplay_Default){ callback(OnTaxtreeNotify); show_root(false); }CTaxTreeBrowser::~CTaxTreeBrowser(){}void CTaxTreeBrowser::SetReporter(IReporter* reporter){ m_Reporter = reporter;}void CTaxTreeBrowser::SetDataSource(CTaxTreeDataSource& ds){ m_DataSource.Reset(&ds); x_Refresh();}void CTaxTreeBrowser::x_Refresh(){ // clear the tree to start clear(); if (m_Reporter) { m_Reporter->SetMessage("Retrieving taxonomic IDs..."); } TTaxMap tax_map; m_DataSource->GetTaxMap(tax_map); ITreeIterator& iter = m_DataSource->GetIterator(m_DispMode); CTreeFiller filler(*m_DataSource, tax_map); iter.TraverseDownward(filler); m_TaxTree.reset(filler.m_Tree.release()); // next, populate the browser if (m_TaxTree.get()) { x_PopulateTree(get_root(), m_TaxTree.get()); } if (m_Reporter) { m_Reporter->SetMessage("Done."); m_Reporter->SetPctCompleted(0); } redraw();}void CTaxTreeBrowser::SetDisplayMode(CTaxTreeDataSource::EDisplayMode mode){ m_DispMode = mode; x_Refresh();}void CTaxTreeBrowser::GetSelectedUids(CTaxTreeDataSource::TUidVec& uids) const{ Node* node = NULL; while ( (node = GetSelected(node)) != NULL) { CTaxTree * tree = reinterpret_cast<CTaxTree *>(node->user_data()); if (tree){ if (!node->is_leaf()){ tree->CollectUids(uids); } else { int idx = node->id() - node->parent()->id() - 1; uids.push_back(tree->m_Uids[idx>=0?idx:0]); } } if ((node = node->next())==NULL) break; } std::sort(uids.begin(), uids.end()); uids.erase(std::unique(uids.begin(), uids.end()), uids.end());}void CTaxTreeBrowser::x_PopulateTree(Node* node, CTaxTree* tree){ // add a node for the current branch node = AddChild(tree->GetName(), node); node->user_data(tree); // recurse our tree if (tree->m_Children.size()) { if (tree->m_Children.size() == 1) { node->open(true); } ITERATE (CTaxTree::TChildren, iter, tree->m_Children) { x_PopulateTree(node, *iter); } } else { // add uids string str; ITERATE (CTaxTreeDataSource::TUidVec, iter, tree->m_Uids) { str.erase(); m_DataSource->GetTitle(**iter, &str); Node * leafNode = AddLeaf(str, node); leafNode->user_data(tree); } }}void CTaxTreeBrowser::SetSelectedUids(const CTaxTreeDataSource::TUidVec& uids, Node* node){ CTaxTree * tree = reinterpret_cast<CTaxTree *>(node->user_data()); if (node->is_leaf()){ int idx = node->id() - node->parent()->id() - 1; CTaxTreeDataSource::TUid uid = tree->m_Uids[idx>=0?idx:0]; for (CTaxTreeDataSource::TUidVec::const_iterator itt=uids.begin(); itt!=uids.end(); itt++){ if (CSeqUtils::Match(**itt, *uid, (CScope*) m_DataSource->GetScope().GetPointer())){ node->select(true); Node * parNode = node; while (!((parNode=parNode->parent())->is_root())) { parNode->open(true); Node * chNode = NULL; bool bsel = true; do { if (!chNode) chNode = parNode->first_leaf(); else chNode = chNode->next_leaf(); if (!(bsel=chNode->selected())) break; } while (chNode!=parNode->last_leaf()); parNode->select(bsel); } } } } if (node->next()) SetSelectedUids(uids, node->next()); }void CTaxTreeBrowser::OnSelChangedEvent(CViewEvent::TEventObject obj){ CObjectFor< vector<CConstRef<objects::CSeq_id> > > * csid = dynamic_cast< CObjectFor< vector<CConstRef<objects::CSeq_id> > > *>(obj.GetPointer()); if (csid){ unselect_all(); SetSelectedUids(*csid, get_root()); } }END_NCBI_SCOPE/* * =========================================================================== * $Log: tax_tree.cpp,v $ * Revision 1000.1 2004/06/01 21:13:24 gouriano * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.11 * * Revision 1.11 2004/05/21 22:27:55 gorelenk * Added PCH ncbi_pch.hpp * * Revision 1.10 2004/05/13 17:31:46 dicuccio * Renamed data source file * * Revision 1.9 2004/05/03 13:23:58 dicuccio * gui/utils --> gui/objutils where needed * * Revision 1.8 2004/04/09 20:02:28 tereshko * Extended tree selection logic * * Revision 1.7 2004/04/09 16:53:32 tereshko * Added functionality to send/accept selections * * Revision 1.6 2004/04/07 13:13:04 dicuccio * Changed storage of sequence info to use CConstRef<CSeq_id> * * Revision 1.5 2004/04/01 19:03:13 dicuccio * Added support for limiting the list of displayed nodes. Changed retrieval of * tax-id to favor sequence first * * Revision 1.4 2004/01/07 18:55:36 dicuccio * Code clean-up. Don't forget to initialize or CTaxon1 class * * Revision 1.3 2003/12/23 15:39:18 dicuccio * Altered the data source - expose an ITreeIterator; the widget no longer * directly creates a CTaxon1 class. Chaned storage notion from 'gi' to 'uid' * * Revision 1.2 2003/12/22 21:57:35 ucko * ITreeIterator::Execute: use a const_iterator because m_TaxMap is const. * * Revision 1.1 2003/12/22 19:42:59 dicuccio * Initial revision * * =========================================================================== */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?