QTreeView with sqlalchemy

I want to make a QTreeView that shows some data that I get with sqlalchemy. There are about 1000-10.000 rows to show. I thought that a using a model would be better to use here than the simpler QTreeWidget, because I thought it would be relatively easy to connect the model to sqlalchemy, because I assumed that this is something that is done quite often. Apparently it is not... I am unable to find good examples of this.

I looked at the documentation of QStandardItemModel, and as I understood it, I have to create a QStandardItem for every value. With thousands of rows times nine columns, I think that this is going to be terribly slow. I have worked with ObjectListView in wxpython before and hoped the treeview in Qt would work similar, so you can imagine my disappointment when I found how complex this was going to be :P.

So my questions:

  1. Is there a way to connect sqlalchemy to the QTreeView?
  2. How can I use the items that are returned by sqlaclhemy in my treeview? (like done by ObjectListView)

As you can see I am very new to models and views (and Qt), so any answer, explanation, link, usefull hint or whatsever that has something to say about this is very welcome!

Answers


Good news - you do not need to create any QStandardItems. The Qt view classes never call any methods on your data classes, so your data can be stored in any way you want. They only call methods on the model class (unlike in, say Ruby on Rails, where each data class is considered a model, in Qt, "model" refers to the entire collection of data classes).

I'd recommend subclassing QAbstractItemModel (see the "Subclassing" section) and working from there. If you just have a flat list, you can probably even set it up so that your custom model simply wraps the results returned from your database.

I did this in C++ - took me quite a while to wrap my head around it, but once I did it was pretty easy to work with. Here's my basic code for a read-only model - you'll have to translate it to python, but hopefully it spares you my pain!

Note: The code below assumes your data is a flat list (no parent-child relationships). If that's not the case, check out this tutorial for details on what tweaks you'll have to make.

template <typename T> class ListModel : public QAbstractItemModel
{
protected:
    //This is where I store my data - it's just a generic list!
    //Try using your SQL result instead?
    QList<T*> mData;

public:
    ListModel(): mData() {}

    int columnCount(const QModelIndex& index) const
    {
        //You'll probably want a different number here:
        return 1;
    }

    QVariant data(const QModelIndex& index, int role) const
    {
        if(index.isValid() && role == Qt::DisplayRole && index.column() == 0)
        {
            if(T* t = (T*) index.internalPointer())
            {
                //Something, based on column number:
                return t->data[index.column()];
            }
        }

        return QVariant();
    }

    QVariant headerData(int section, Qt::Orientation orientation, int role) const
    {
        if(orientation == Qt::Horizontal && role == Qt::DisplayRole && section == 0)
        {
            //Something, based on column number:
            return "header text";
        }

        return QVariant();
    }

    QModelIndex index(int row, int column, const QModelIndex& parent) const
    {
        //Tweak this if you have a hierarchical model:
        return (parent.isValid())? QModelIndex() : createIndex(row, column, (void*) mData[row]);
    }

    QModelIndex parent(const QModelIndex& child) const
    {
        //Tweak this if you have a hierarchical model:
        return QModelIndex();
    }

    int rowCount(const QModelIndex& index) const
    {
        //Tweak this if you have a hierarchical model:
        return (index.isValid())? 0 : mData.count();
    }
};

Need Your Help

how to change uinavigation controller back button action

iphone objective-c ios

I have a UINavigationController and I have to keep the the default back button "the back arrow style" I just want to ask if I can change the back button action without build new one and change its ...

How to optimize JS canvas drawing?

javascript html5 canvas

My impl of fillRect much (> 3 times) slower than context2d.fillRect. How I can optimize my code or why builtin fillRect faster (some app acceleration?)?