How do you hide file extensions on a QFileSystemModel

2.2k Views Asked by At

I have bound a QFileSystemModel to a QTreeView. The QFileSystemModel has readOnly set to false so the user can rename files... However I don't want the user to accidentally rename a file and forget its extension as that will result in its exclusion from the QTreeView since I am filtering the file types...

How can I hide the file extensions keeping the rename functional ?

Thanks

4

There are 4 best solutions below

0
On

try reimplement data() and setData() for role Qt::EditRole:

virtual QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ) const
{
if (role == Qt::EditRole)
   {
   return QVariant(fileName(index));
   }
else
   return QFileSystemModel::data(index, role);
}

virtual bool setData ( const QModelIndex & idx, const QVariant & value, int role = Qt::EditRole )
{
if (role == Qt::EditRole)
   {
   return QFileSystemModel::setData( idx, QVariant(value.toString() + fileInfo(idx).completeSuffix()), role);
   }
else
   return QFileSystemModel::setData(idx, value, role);
}
0
On

You must create an item delegate specific for your situation, and associate it with your view.

As stated in the documentation here

void QAbstractItemView::setItemDelegate(QAbstractItemDelegate * delegate)

Sets the item delegate for this view and its model to delegate. This is useful if you want complete control over the editing and display of items.

This delegate will be the responsible of displaying the name of the file without extension, and allow the editing of the file name.

0
On

If you're using the QFileSystemModel using a delegate as suggested above might be the easiest option. The following delegate lets you hide the file extensions. Note that you're not limited to removing the extension you could change the filename as well.

class MyItemDelegate : public QStyledItemDelegate
{
    Q_OBJECT
protected:
    void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
    {
        QStyleOptionViewItem opt = option;
        initStyleOption(&opt, index);
        QFileInfo fileinfo(opt.text);
        opt.text = fileinfo.completeBaseName();
        QStyle* style = opt.widget ? opt.widget->style() : QApplication::style();
        style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, opt.widget);
    }

    QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
    {
        QSize result = QStyledItemDelegate::sizeHint(option, index);
        return result;
    }
};

And then you can apply this delegate to a QTreeView or a QListView for example:

MyItemDelegate* itemDelegate = new MyItemDelegate;
myListView_->setItemDelegate(itemDelegate);
0
On

This solution works for me and hides the extension entirely from the user.

Override data and setData in QFileSystemModel class.

def data(self, index, role):
    if role == Qt.EditRole:
        return self.fileName(index)
    else:
        return super(ContentFileSystemModel, self).data(index, role)

def setData(self, index: QModelIndex, value, role: int=...) -> bool:
    print("setData")
    if role == Qt.EditRole:
        if self.isDir(index):
            d = ""
        else:
            d = "."
        return super(ContentFileSystemModel, self).setData(index, str(value) + d + self.fileInfo(index).completeSuffix(), role)
    return super(ContentFileSystemModel, self).setData(index, value, role)

Create a QStyledItemDelegate:

class NameDelegate(QStyledItemDelegate):

    def initStyleOption(self, option, index):
        super().initStyleOption(option, index)
        if isinstance(index.model(), QFileSystemModel):
            if not index.model().isDir(index):
                option.text = index.model().fileInfo(index).baseName()

    def setEditorData(self, editor, index):
        if isinstance(index.model(), QFileSystemModel):
            if not index.model().isDir(index):
                editor.setText(index.model().fileInfo(index).baseName())
            else:
                super().setEditorData(editor, index)

And set it in your view:

delegate = NameDelegate(self.lv_file_manager)
view.setItemDelegate(delegate)