QTreeView和QAbstractItemModel [英] QTreeView and QAbstractItemModel

查看:216
本文介绍了QTreeView和QAbstractItemModel的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Qt的新手,我正在尝试基于平面(或来自sqlite表)文件路径列表(而不是来自FS)制作一棵简单的树,如下所示:

I'm new to Qt and I'm trying to make a simple tree based on a flat (or from a sqlite table) file paths list (not from FS) like this:

C:\Parent1\Child1\Leaf1.jpg
C:\Parent1\Child1\Leaf2.jpg
C:\Parent1\Child1\Leaf3.jpg
C:\Parent1\Child2\Leaf1.jpg
C:\Parent1\Child2\Leaf2.jpg
C:\Parent2\Child1\Leaf1.jpg
C:\Parent2\Child1\Leaf2.jpg
...
D:\....
...

我想将其显示为树状视图(例如文件浏览器).

I'd like to display this as a tree view (e.g. a file explorer).

我研究了QAbstractItemModel,但是在构建树时遇到了一些困难. 我的想法是使用'\'拆分每个路径,并在添加分支之前检查分支是否已经存在.如果分支存在,我必须找到好父母来添加这个新孩子.

I looked into QAbstractItemModel but I have some difficulties to build the tree. My idea is to split each of the path using '\' and check if the branches already exist before adding them. If the branches exist, I have to find the good parent to add this new child.

我正在使用一个简单的树示例但是我在实施模型方面确实有困难.

I'm using a simple tree example but I have real difficulties to implement my model.

void MyTreeModel::setupModelData(TreeItem *parent)
{
    QList<TreeItem*> parents;
    parents << parent;

    int number = 0;

    QString path = "mydb_path";
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName(path);
    if(db.open())
    {
        QSqlQuery query("SELECT path FROM file");
        int idPath = query.record().indexOf("path");

        while (query.next())
        {
           QString name = query.value(idPath).toString();
           int id_file = query.value(idIdx).toInt();

           QStringList nodeString = name.split("\\", QString::SkipEmptyParts);


           for(int node = 0; node < nodeString.count(); ++node)
           {
            // I don't know what to do now... Should I build a lookup table with a parent id for each node before to populate my TreeItems ?

           }
        }
    }
    //...
}

有什么建议吗?

推荐答案

使用QAbstractModelItem并不直观.但是看来您最大的问题实际上是 建模 元素的路径的列表.有两个任务:

Using a QAbstractModelItem is not intuitive. But it looks like your biggest problem is actually modeling your list of paths into a tree of elements. There are two tasks :

  1. 处理您的输入数据以获得一个数据结构,以紧密地对数据进行概念性解释(您知道它们是路径).
  2. 在您的QAbstractItemModel实现下使用此数据结构.
  1. Process your input data to obtain a data structure close your conceptual interpretation of the data (you know they are path.)
  2. Use this data structure under your QAbstractItemModel implementation.

第1步:实际的树实现

您需要首先实现一棵树.像

Step 1: An actual tree implementation

You need to implement a tree first. Something like

struct mytree
{
    static std::shared_ptr<mytree> frompath(QString path);
    static std::shared_ptr<mytree> merge(std::shared_ptr<mytree> t1, std::shared_ptr<mytree> t2);

    //may need helpers : is leaf, etc, or just access to children
    QString value;
    std::list<std::shared_ptr<mytree> > childrens_;

    mytree(); //construct empty tree
};

值是文件名或文件夹名.

Where the value is a file name or folder name.

  • frompath从单个条目构建树.C:\Parent2\Child1\Leaf2.jpg变为

  • frompath builds the tree from a single entry.C:\Parent2\Child1\Leaf2.jpg becomes

C->Parent2->Child1->Leaf2.jpg

  • merge采取两棵现有树并构建一棵树

  • merge take two existing trees and construct a single one

    C->Parent2->Child1->Leaf1.jpg
    C->Parent2->Child2->Leaf1.jpg
    

    成为

    C->Parent2->{Child1->Leaf1.jpg, Child2->Leaf1.jpg}
    

  • 拥有该列表后,您至少需要实现以下方法:

    Once you have that list, you need to implement at least the following methods:

    QModelIndex parent(const QModelIndex & index) const;
    QModelIndex index(int row, int column, const QModelIndex & parent) const;
    
    int columnCount(const QModelIndex & parent) const;
    int rowCount(const QModelIndex & parent) const;
    QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
    

    一些提示:

    1. 无效的模型索引是QModelIndex().顶级项目具有QModelIndex
    2. 您必须将一个或多个QModelIndex分配给对象mytree
    3. 对于任何父项,您只有一列,因为只有一个数据(文件名).
    4. 行数是子项数.
    5. QModelIndex是使用 createIndex
    6. 创建的
    1. An invalid model index is QModelIndex(). A top level item has QModelIndex
    2. You have to assign one or more QModelIndex to an object mytree
    3. You have only one column for any parent, because there is only one data (the filename).
    4. The number of rows is the number of children.
    5. QModelIndex are created using createIndex

    现在要实现这些方法,您需要在树中添加3个字段:

    Now to be able to implement those method you need to add 3 fields to the tree :

    • 对父项的引用
    • 当前元素在父列表中的位置
    • 一个id字段,用于唯一地标识一个节点.您可以在路径上使用uint qHash(const QString & key).

    新树包含字段

    struct mytree
    {
        //removed methods;
        QString path;          eg C:\Parent1\Child1
        QString value;         eg Child1
        unsigned int id;       eg: qHash(path)
    
        int pos; //my position in the parent list. this is the row in the model
    
        std::shared_ptr<mytree> parent;      
        std::list<std::shared_ptr<mytree> > childrens;
    };
    

    您需要能够快速获得mytree的ID.这意味着您模型中的内部数据结构将是

    You need to be able to quickly get a mytree given its id. Which means your internal data structure in the model will be

    std::map<unsigned int, std::shared_pr<mytree> > items_by_id;
    std::shared_pr<mytree> root_item;
    

    现在,您拥有实现上述方法所需的全部条件.这只是用于演示,因此不要认为此代码是理所当然的

    Now you have all you need to implement the methods above. This is just for demo so don't take this code for granted

    std::shared_pr<mytree> find_elt_helper(const QModelIndex & index) const
    {   
       auto iter = items_by_id.find(index.internalId());
       if(iter == items_by_id.end())
           return std::shared_pr<mytree>();
    
       return iter->second;
    }
    
    
    QModelIndex parent(const QModelIndex & index) const
    {
       if(!index.isValid())
           return QModelIndex();
    
       std::shared_pr<mytree> index_item = find_elt_helper(index);
    
       return index_item ? create_index(index_item->parent->pos, 0, index_item->parent->id) : QModelIndex();
    }
    
    QModelIndex index(int row, int column, const QModelIndex & parent) const
    {
        std::shared_pr<mytree> parent_item = !parent.isValid() ? root_item : find_elt_helper(parent);
    
        std::shared_pr<mytree> item;
        if(row >= parent_item.children.size())
           return QModelIndex();
    
        item = parent_item.children[row];
    
        return create_index(row, 0, item->id);
    }
    

    这篇关于QTreeView和QAbstractItemModel的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆