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 + -
显示快捷键?