[solved] QFileSystemModel - add new column before another column



  • I have been able to add a new column in my class derived from QFileSystemModel. I haven't been able to figure out how to add it in the column position that I want. The code below shows what I have done. As it is, it displays the files in "C:\tmp", showing the regular Name, Size, Type, and Date Modified columns, and showing a new column at the right called File Owner. For the task I'm working on, the file owner is written to the header of the file when it is first generated. I need to have the order of columns as Name, File Owner, Size. The Type and Date Modified columns will eventually be hidden.

    As you can see from the code, I have tried in in the TestFileSystemModel ctor to call insertColumn(1), which should insert a new column before column 1. Interestingly enough, the Qt 5 documentation for QAbstractItemModel doesn't say whether this is 0-based or not. I assume that it is. I'm not passing an index, and the documentation also doesn't state what taking the default on that parameter would do. The column count just before and just after that insert call both show as 4, and the call itself returns false. In the ctor, I then tried connecting to the model's directoryLoaded() signal, thinking that doing this in the ctor was too early, but in the onDirectoryLoaded() slot I get the same results.

    The way that I ended up doing it was just by returning 5 for columnCount(), returning the File Owner header in headerData(), and returning a simple generated string in the data() call for role == Qt::DisplayRole when index.column() == 4 gives me the header. I can't see a way with this method to move the column. I know there is a moveColumn() available, but I am not sure where that should be used.

    Does anyone have an idea how to add a column at a position other than at the end? What am I doing incorrectly with my call to insertColumn? Everything else seems to work well. I have posted the full code (all cpp/h files plus the ui file) on PasteBin at http://pastebin.com/fzZ7ASB7 just in case anyone wanted to run it themselves.

    testfilesystemmodeldialog.cpp:

    @
    #include "testfilesystemmodeldialog.h"

    #include <QDebug>
    #include <QTimer>
    #include <QPushButton>

    TestItemFileDelegate::TestItemFileDelegate(){}

    static int num = 0;

    QSize TestItemFileDelegate::sizeHint ( const QStyleOptionViewItem & /option/, const QModelIndex & index ) const
    {
    const QFileSystemModel *model = reinterpret_cast<const QFileSystemModel *>(index.model());
    QFileInfo info = model->fileInfo(index);
    if(info.isDir())
    {
    return QSize(40,40);
    }
    else
    {
    return QSize(64,64);
    }
    }

    TestFileSystemModel::TestFileSystemModel(QObject * parent) :
    QFileSystemModel(parent)
    {
    int i = QFileSystemModel::columnCount();
    bool b = insertColumn(4);
    int j = QFileSystemModel::columnCount();
    bool b1 = connect(this,SIGNAL(directoryLoaded(QString)),this,SLOT(onDirectoryLoaded(QString)));
    }

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

    QVariant TestFileSystemModel::headerData(int section, Qt::Orientation orientation, int role) const
    {
    if (section == 4 && orientation == Qt::Horizontal && role == Qt::DisplayRole)
    return tr("File Owner");
    return QFileSystemModel::headerData(section, orientation, role);
    }

    QVariant TestFileSystemModel::data(const QModelIndex & index, int role) const
    {
    if( !index.isValid() )
    return QVariant();
    switch(role)
    {
    case Qt::DisplayRole:
    if (index.column() == 4)
    return QString("Owner %1").arg(num++);
    else
    return QFileSystemModel::data(index, role);
    break;
    case Qt::TextAlignmentRole:
    return Qt::AlignHCenter | Qt::AlignVCenter;
    break;
    default:
    return QFileSystemModel::data(index, role);
    break;
    }
    return QFileSystemModel::data(index, role);
    }

    void TestFileSystemModel::onDirectoryLoaded(const QString & path)
    {
    int i = QFileSystemModel::columnCount();
    bool b = insertColumn(4);
    int j = QFileSystemModel::columnCount();
    }

    TestFileSystemModelDialog::TestFileSystemModelDialog(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::TestFileSystemModelWidget)
    {
    ui->setupUi(this);

    QString sPath("C:\\tmp");
    file = new TestFileSystemModel();
    QDir fcsDir(sPath);
    file->setFilter(QDir::NoDotAndDotDot | QDir::Files);
    QStringList filters;
    filters << "*.*";
    file->setNameFilters(filters);
    file->setNameFilterDisables(false);
    QModelIndex index = file->setRootPath(fcsDir.absolutePath());
    
    TestItemFileDelegate *iconItemFileDelegate = new TestItemFileDelegate();
    
    ui->fileTreeView->setModel(file);
    ui->fileTreeView->setVerticalScrollMode(QAbstractItemView::ScrollPerItem);
    ui->fileTreeView->setItemDelegate(iconItemFileDelegate);
    ui->fileTreeView->setRootIndex(index);
    

    }
    @


  • Lifetime Qt Champion

    Hi,

    Rather than modifying QFileSystemModel (which may have some expectation about it's column order), I'd e.g subclass QAbstractProxyModel were you can manipulate the mapping of your QFileSystemModel more easily and add your column where you want it.

    Hope it helps



  • I'd not bother with changing the order of the items in the model itself at all. Just solve that at the view level instead.

    QTreeView::header() gives you a QHeaderView, and QHeaderView supplies moveSection(int, int) to reorder your columns as you see fit.



  • Thanks SGaist. I have seen where others were pointing at doing this in the proxy model, but I was trying to avoid adding another layer of complexity. Turns out that Andre gave me exactly what I needed. Since I'm not creating the new column until I start loading the model, I connected to the model's directoryLoaded() signal, and in my slot I added the following code. Works perfectly. Thanks for the pointer.

    @
    void TestFileSystemModelDialog::onDirectoryLoaded()
    {
    QHeaderView *headerView = ui->fileTreeView->header();
    headerView->moveSection(4,1);
    }
    @


  • Lifetime Qt Champion

    Indeed, that's a way simpler solution I had forgot about


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.