Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QTreeView selection and row insert interaction
Forum Updated to NodeBB v4.3 + New Features

QTreeView selection and row insert interaction

Scheduled Pinned Locked Moved General and Desktop
8 Posts 3 Posters 2.9k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • H Offline
    H Offline
    hummingway
    wrote on last edited by
    #1

    Hi,
    I have a QTreeView with a subclassed QAbstractItemModel. When a row is inserted (or removed) from before the current selection the index of the current selection doesn't change so the wrong item is selected.

    I would expect this to be handled by the view so am wondering if it's possible I've missed a step?

    Thanks.

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi and welcome to devnet,

      Can you post the code of your custom model ?

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      0
      • H Offline
        H Offline
        hummingway
        wrote on last edited by
        #3

        Thanks for the welcome.
        @
        #include "procfsmodel.h"

        #include <QObject>
        #include <QModelIndex>
        #include <iostream>
        #include <QFileIconProvider>
        #include <QPixmap>
        #include <dirent.h>

        #include "procfsicons.h"

        ProcFsModel::ProcFsModel (QObject* parent) :
        QAbstractItemModel (parent) {
        m_proc_fs = new ProcFs;
        m_icons = new ProcFsIcons;

        }

        ProcFsModel::~ProcFsModel () {
        delete m_icons;
        delete m_proc_fs;
        }

        QVariant ProcFsModel::data (const QModelIndex& index, int role) const {

        if (!index.isValid ())
            return QVariant ();
        
        if (role == Qt::DecorationRole) {
            return fileIcon (index);
        }
        
        if (role != Qt::DisplayRole)
            return QVariant ();
        
        Direntry* entry = static_cast<Direntry*> (index.internalPointer ());
        
        return entry->name ();
        

        }

        Qt::ItemFlags ProcFsModel::flags (const QModelIndex& index) const {

        if (!index.isValid ()) {
            return 0;
        }
        
        return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
        

        }

        QVariant ProcFsModel::headerData (int section, Qt::Orientation orientation, int role) const {
        if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
        return QVariant ("Name");

        return QVariant ();
        

        }

        QModelIndex ProcFsModel::index (int row, int column, const QModelIndex& parent) const {

        if (row < 0 || column < 0 || row >= rowCount (parent) || column >= columnCount (parent))
            return QModelIndex ();
        
        Direntry* parent_entry;
        
        if (!parent.internalPointer ()) {
            parent_entry = m_proc_fs->entries ();
        } else {
            parent_entry = static_cast<Direntry*> (parent.internalPointer ());
        }
        
        Direntry* child_entry = parent_entry->at (row);
        
        if (child_entry) {
            return createIndex (row, column, child_entry);
        }
        
        return QModelIndex ();
        

        }

        QModelIndex ProcFsModel::index (QString& path) const {
        return QModelIndex ();
        }

        QModelIndex ProcFsModel::parent (const QModelIndex& index) const {

        if (!index.isValid ())
            return QModelIndex ();
        
        Direntry* index_entry = static_cast<Direntry*> (index.internalPointer ());
        Direntry* parent_entry = index_entry ? index_entry->parent () : 0;
        
        if (!parent_entry || parent_entry == m_proc_fs->entries ())
            return QModelIndex ();
        
        return createIndex (parent_entry->row (), 0, parent_entry);
        

        }

        int ProcFsModel::rowCount (const QModelIndex& parent) const {
        Direntry* parent_entry;
        if (parent.column () > 0) {
        return 0;
        }

        if (!parent.isValid ()) {
            parent_entry = m_proc_fs->entries ();
        } else {
            parent_entry = static_cast<Direntry*> (parent.internalPointer ());
        }
        
        return parent_entry->count ();
        

        }

        int ProcFsModel::columnCount (const QModelIndex& parent) const {
        return (parent.column () > 0) ? 0 : 1;
        }

        QFileInfo ProcFsModel::fileInfo (const QModelIndex& index) const {
        Direntry* index_entry = static_cast<Direntry*> (index.internalPointer ());
        return QFileInfo (index_entry->pathName ());
        }

        QIcon ProcFsModel::fileIcon (const QModelIndex& index) const {

        Direntry* index_entry = static_cast<Direntry*> (index.internalPointer ());
        
        QIcon* ico = m_icons->get (index_entry->type ());
        
        if (ico) {
            return *ico;
        }
        
        QFileIconProvider ip;
        if (index_entry->isDir ()) {
            return ip.icon (ip.Folder);
        }
        
        return ip.icon (ip.File);
        

        }

        QModelIndex ProcFsModel::rootIndex () {
        return createIndex (0, 0, m_proc_fs->entries ());
        }

        Direntry* ProcFsModel::at (const QModelIndex& index) {
        if (!index.isValid ())
        return 0;

        return static_cast<Direntry*> (index.internalPointer ());
        

        }

        bool ProcFsModel::addOrRemoveEntry (Direntry* entry) {
        Direntry* data_store = m_proc_fs->entries ();

        int i = 0;
        std::vector<Direntry*>::iterator data_store_iter = data_store->begin ();
        std::vector<Direntry*>::iterator entry_iter = entry->begin ();
        
        for (; entry_iter < entry->end (); ++entry_iter) {
        
            if (! (data_store_iter < data_store->end ())) {
        
                Direntry* copy = (*entry_iter)->copy ();
        
                beginInsertRows (rootIndex (), i, i);
        
                data_store->push_back (copy);
        
                endInsertRows ();
        
                return false;
            } else {
                std::string name_in_store = (*data_store_iter)->name ();
                std::string name_in_entry = (*entry_iter)->name ();
        
                if (name_in_store != name_in_entry) {
                    if (Direntry::compare_dirent ((*data_store_iter), (*entry_iter))) {
        
                        beginRemoveRows (rootIndex (), i, i);
        
                        delete (*data_store_iter);
                        data_store->erase (data_store_iter);
        
                        endRemoveRows ();
                    } else {
        
                        Direntry* copy = (*entry_iter)->copy ();
        
                        beginInsertRows (rootIndex (), i, i);
        
                        data_store->insert (copy, data_store_iter);
        
                        endInsertRows ();
        
                    }
        
                    return false;
                }
            }
            ++i;
            ++data_store_iter;
        }
        
        return true;
        

        }

        void ProcFsModel::update (Direntry* entry) {
        bool done;
        do {
        done = addOrRemoveEntry (entry);
        } while (!done);

        delete entry;
        

        }

        @

        1 Reply Last reply
        0
        • H Offline
          H Offline
          hummingway
          wrote on last edited by
          #4

          Update is triggered by a thread signalling the main application.

          The thread is monitoring a Linux /proc system.

          1 Reply Last reply
          0
          • SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on last edited by
            #5

            One thing I find strange is that you are returning an invalid QVariant for everything that is not DisplayRole or Decoration role. You should return the value of the base class implementation of data.

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            1 Reply Last reply
            0
            • H Offline
              H Offline
              hummingway
              wrote on last edited by
              #6

              From the docs for QAbstractItemModel:
              "Returns the data stored under the given role for the item referred to by the index.

              Note: If you do not have a value to return, return an invalid QVariant instead of returning 0."

              The only data of interest to the tree are the display and decoration.

              I don't see anything in the selection model?

              1 Reply Last reply
              0
              • A Offline
                A Offline
                andreyc
                wrote on last edited by
                #7

                Not sure if I understand your problem. But I shall answer :-)
                I think it is not correct to call begin...Rows, end...Rows for each item.
                It should be something like this

                @
                beginInsertRows(parenIndex, from, to);
                doInserts()
                endInsertRows ();
                @

                After you have inserted you records the selected index is not valid and you need to set it to whatever index you expect to be selected.
                @
                ...
                QModelIndex child = model->index(0, 0, parent);
                view->selectionModel()->setCurrentIndex(child, QItemSelectionModel::ClearAndSelect);
                @

                1 Reply Last reply
                0
                • H Offline
                  H Offline
                  hummingway
                  wrote on last edited by
                  #8

                  So, basically I have to track and update the selection model myself. I wondered if that was the case.

                  Thanks.

                  1 Reply Last reply
                  0

                  • Login

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • Users
                  • Groups
                  • Search
                  • Get Qt Extensions
                  • Unsolved