Hieratic data in TreeViews and TreeView update methods

I have a lot of (hierarchical) data that I display in a TreeView (maybe about 20 thousand units or more, including children). A specific problem with my data is that every object shown in a tree can exist in many treeview elements. I mean, I can have a hierarchy like this:

  • Item_A -> Item_B -> ItemC
  • Item_B -> Item_C
  • ItemC

Suppose that Item_Acontains Item_B, which contains Item_C, as shown above. This means that my list will also show the hierarchy Item_Band Item_C. Now consider that something is happening with the object shown asItem_B(e.g. change of name). Then, of course, both subjects need to be updated. Consider now thousands of elements in a tree structure with complex hierarchies. What strategy would you use to update the tree? Speed, of course, is the main problem here, but also the ease of use and maintenance. I currently hold internal mappings of list items with objects and vice versa to quickly find and update items. Is this the right strategy? After recreating the list after each update, I can throw a lot of code, but I don’t know which paths of the elements were expanded or collapsed. How can I solve this problem? Should I store extended paths in an internal container?

Thanks.

PS: The programming language is C ++, and the GUI lib is QT3.

+3
4

- , TreeView Windows.

CUSTOMDRAW, node node : 3 Item_C Item_C.

, Item_C, Invoke InvalidateRect() 3 Item_C, , () .

, .

+1

Qt4 model/view, Qt4 .

, , , / . / .

Qt/view ( // ), gUI

+1

widget->setUpdatesEnabled(false), , , widget->setUpdatesEnabled(true).

Qt.

+1

, wxWidgets. , , . .

class ReferenceCounter
{
public:
    // Singleton pattern. Implementation left up to you.
    static ReferenceCounter& get();

    void add(const TreeData& data) {
        mCounter[data.getId()].push_back(&data);
    }

    void remove(const TreeData& data) {
        const CounterType::const_iterator itr = mCounter.find(data.getId());
        if (itr != mCounter.end()) {
            ItemType& items = itr->second;
            items.erase(std::remove(items.begin(), items.end(), &data), items.end());
            if (items.empty()) {
                mCounter.erase(itr);
            }
        }
    }

    typedef std::vector<TreeData*> ItemType;
    ItemType::iterator begin(const TreeData& data) {
        const CounterType::const_iterator itr = mCounter.find(data.getId());
        if (itr != mCounter.end()) {
            return itr->second.begin();
        }
        // Else condition handling left up to you.
    }

    ItemType::iterator end(const TreeData& data) {
        const CounterType::const_iterator itr = mCounter.find(data.getId());
        if (itr != mCounter.end()) {
            return itr->second.end();
        }
        // Else condition handling left up to you.
    }

private:     
    typedef std::map<int, ItemType> CounterType;
    CounterType mCounter;
};

class TreeData
{
public:
    TreeData() { ReferenceCounter::get().add(*this); }
    ~TreeData() { ReferenceCounter::get().remove(*this); }

    // Get database rows or whatever your tree is tracking.
    int getId() const;
};

Therefore, given any TreeData, you can find all the other TreeData with the corresponding identifiers in the control counter. This allows you to easily and quickly save names and update them. Our tree processes over 1,000,000 nodes with no problems. In my implementation, I have simplified the transfer of iteration to the class boost::iterator_facade.

+1
source

Source: https://habr.com/ru/post/1714134/


All Articles