Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

segv when getting QFileInfo from subclassed QFileSystemModel



  • Context:

    I am creating a directory browser using a QTableView & a subclassed QFileSystemModel due to its already existing file browser functionality.

    I am using 5 columns, first column [0] is 128px wide, the rest spaced out in widths respectively are 6, 9, 3, 2 all which I set in the class containing both the QTableWidget and QFileSystemModel.

     [0] Icon (default icon for folder or file, except in the case of an image where the image icon is loaded from cache)
     [1] File name
     [2] File location (relative to a specific directory)
     [3] Last date modified of the file
     [4] File size (formatted to human readable
    

    Problem:

    On implementing the QAbstractItemView::doubleClick (QTableView) to enter a directory and set the new root model index(i.e. browse into a set directory).

    When double-clicking on a cell:

     // Connect on list widget cell click to browse into directory or open file
     connect(ui->customTableView, &QTableView::doubleClicked, this, [this](const QModelIndex & index) {
          QFileInfo fi = model->getFileInfo(index);
          QString newPath = fi.filePath();
          changeDirectory(newPath);
     });
    
    • I query the model for the fileInfo entry (created a get method due for testing due to fileInfo(const QModexIndex&) wasn't working).

       QFileInfo FileSystemModel::getFileInfo(const QModelIndex& index)
       {
           QFileInfo mfileInfo = QFileInfo(fileInfo(index));
           return mfileInfo;
       }
      
    • Inside of the model, I ask for the QFileInfo object using fileInfo(index) which then results in a segv on a sharedpointer.

    See details below.

    Debugger output

    Locals		
    	index	@0x32d3dfd0	QModelIndex &
    		c	1	int
    		i	853000288	quintptr
    		m	@0x32d7a548	FileSystemModel
    			[QFileSystemModel]	@0x32d7a548	QFileSystemModel
    			[d]	@0x32d79b58	QFileSystemModelPrivate
    			[parent]	0x0	QObject *
    			[children]	<0 items>	
    			[properties]	<at least 0 items>	
    			[methods]	<0 items>	
    			[extra]		
    			COLUMN_DATE_MODIFIED	3	int
    			COLUMN_FILENAME	1	int
    			COLUMN_ICON	0	int
    			COLUMN_LOCATION	2	int
    			COLUMN_SIZE	4	int
    			dataPath	"H:/debug/Root"	QString
    			locale	@0x32d7a558	QLocale
    			mimeDb	@0x32d7a550	QMimeDatabase
    			staticMetaObject	@0x53a4c0	QMetaObject
    		r	0	int
    	mfileInfo	<not accessible>	QFileInfo
    	this	0xbaadf00d	FileSystemModel*
    Inspector		
    Expressions		
    Return Value		
    Tooltip		
    

    Stack Trace Output

    1   QScopedPointer<QObjectData, QScopedPointerDeleter<QObjectData>>::operator->                                                                                                                                                   qscopedpointer.h          118  0x207175ea 
    2   qGetPtrHelper<QScopedPointer<QObjectData, QScopedPointerDeleter<QObjectData>>>                                                                                                                                                qglobal.h                 1055 0x207175ea 
    3   QFileSystemModel::d_func                                                                                                                                                                                                      qfilesystemmodel.h        152  0x207175ea 
    4   QFileSystemModel::fileInfo                                                                                                                                                                                                    qfilesystemmodel.cpp      169  0x207175ea 
    5   FileSystemModel::getFileInfo                                                                                                                                                                                                  filesystemmodel.cpp       85   0x48ca6a   
    6   ExplorerDialog::<lambda(const QModelIndex&)>::operator()(const QModelIndex &) const                                                                                                                                           ExplorerView.cpp          418  0x44e3e6   
    7   QtPrivate::FunctorCall<QtPrivate::IndexesList<0>, QtPrivate::List<const QModelIndex&>, void, ExplorerDialog::setupListWidget()::<lambda(const QModelIndex&)>>::call(ExplorerDialog::<lambda(const QModelIndex&)> &, void * *) qobjectdefs_impl.h        146  0x45b0e9   
    8   QtPrivate::Functor<ExplorerDialog::setupListWidget()::<lambda(const QModelIndex&)>, 1>::call<QtPrivate::List<QModelIndex const&>, void>(ExplorerDialog::<lambda(const QModelIndex&)> &, void *, void * *)                     qobjectdefs_impl.h        256  0x45aca1   
    9   QtPrivate::QFunctorSlotObject<ExplorerDialog::setupListWidget()::<lambda(const QModelIndex&)>, 1, QtPrivate::List<const QModelIndex&>, void>::impl(int, QtPrivate::QSlotObjectBase *, QObject *, void * *, bool *)            qobjectdefs_impl.h        439  0x459f5b   
    10  QtPrivate::QSlotObjectBase::call                                                                                                                                                                                              qobjectdefs_impl.h        394  0x65c8161  
    11  QMetaObject::activate                                                                                                                                                                                                         qobject.cpp               3789 0x65c8161  
    12  QMetaObject::activate                                                                                                                                                                                                         qobject.cpp               3660 0x65c851b  
    13  QAbstractItemView::doubleClicked                                                                                                                                                                                              moc_qabstractitemview.cpp 661  0x207519a6 
    14  QAbstractItemView::mouseDoubleClickEvent                                                                                                                                                                                      qabstractitemview.cpp     1964 0x2075dd0a 
    //...
    

    Image of crash

    enter image description here

    Full Code Example (mostly adapted from ::data() found here) :

    Header file

    #ifndef FILESYSTEMMODEL_H
    #define FILESYSTEMMODEL_H
    
    #include <QFileSystemModel>
    #include <QMimeDatabase>
    #include "libs/global.h"
    #include "libs/imagecachehelper.h"
    
    class FileSystemModel : public QFileSystemModel {
         Q_OBJECT
      public:
         FileSystemModel(QString dataPath);
    
         // QAbstractItemModel interface
      public:
         QMimeDatabase mimeDb;
         QVariant data(const QModelIndex& index, int role) const;
         QFileInfo getFileInfo(const QModelIndex& index);
    
      private:
         static const int COLUMN_ICON = 0;
         static const int COLUMN_FILENAME = 1;
         static const int COLUMN_LOCATION = 2;
         static const int COLUMN_DATE_MODIFIED = 3;
         static const int COLUMN_SIZE = 4;
    
         QString dataPath;
         QLocale locale;
    
         // QAbstractItemModel interface
      public:
         QVariant headerData(int section, Qt::Orientation orientation, int role) const;
    
         // QAbstractItemModel interface
      public:
         int columnCount(const QModelIndex& parent) const;
    };
    
    #endif // FILESYSTEMMODEL_H
    

    and implementation

    #include "filesystemmodel.h"
    
    FileSystemModel::FileSystemModel(QString path): dataPath(path)
    {
         dataPath = QString(path);
         setRootPath(dataPath);
         setFilter(QDir::Files | QDir::Filter::Dirs | QDir::Filter::NoDotAndDotDot);
         sort(COLUMN_FILENAME, Qt::SortOrder::AscendingOrder);
    }
    
    QVariant FileSystemModel::data(const QModelIndex& index, int role) const
    {
    
    //    Q_D(const QFileSystemModel);
         if (!index.isValid() || index.model() != this)
              return QVariant();
    
         switch (role) {
              case Qt::EditRole:
                   break;
              case Qt::DisplayRole:
                   switch (index.column()) {
                        case COLUMN_FILENAME:
                             return fileInfo(index).fileName();
                        case COLUMN_LOCATION: {
                             QFileInfo fi = fileInfo(index);
                             QString s = fi.filePath();
                             QString localReplace = s.replace(dataPath, "/Root");
                             return localReplace;
                        }
                        case COLUMN_DATE_MODIFIED:
                             return Global::dateToQString(fileInfo(index).lastModified());;
                        case COLUMN_SIZE: {
                             QFileInfo fi = fileInfo(index);
                             if (fi.isDir()) {
                                  return QString("--");
                             }
                             else {
                                  return locale.formattedDataSize(fi.size());
                             }
                        };
                        default:
                             return QVariant();
                   }
                   break;
              case FilePathRole:
                   return filePath(index);
              case FileNameRole:
                   return fileName(index);
              case Qt::DecorationRole:
                   if (index.column() == COLUMN_ICON) {
                        QFileInfo fi = fileInfo(index);
                        if (fi.isFile()) {
                             QPixmap p = QPixmap(fi.filePath());
                             if (p.isNull()) {
                                  return QFileSystemModel::iconProvider()->icon(fi);
                             }
                             p.scaled(ImageHelper::getCacheImageSize());
                             return QIcon(p);
                        }
                        else {
                             return QFileSystemModel::iconProvider()->icon(fi);
                        }
                   }
                   break;
              case Qt::TextAlignmentRole:
                   switch (index.column()) {
                        case COLUMN_FILENAME:
                        case COLUMN_LOCATION:
                             return QVariant(Qt::AlignLeft | Qt::AlignVCenter);
                        case COLUMN_DATE_MODIFIED:
                             return QVariant(Qt::AlignCenter);
                        case COLUMN_SIZE:
                             return QVariant(Qt::AlignRight | Qt::AlignVCenter);
                        case COLUMN_ICON:
                        default:
                             return QVariant(Qt::AlignCenter);
                   }
         }
         return QFileSystemModel::data(index, role);
    }
    
    QFileInfo FileSystemModel::getFileInfo(const QModelIndex& index)
    {
         QFileInfo mfileInfo = QFileInfo(fileInfo(index));
         return mfileInfo;
    }
    
    QVariant FileSystemModel::headerData(int section, Qt::Orientation orientation, int role) const
    {
         switch (role) {
              case Qt::DisplayRole:  {
                   switch (section) {
                        case COLUMN_ICON: return tr("Preview");
                        case COLUMN_FILENAME: return tr("Name");
                        case COLUMN_LOCATION: return tr("Location");
                        case COLUMN_DATE_MODIFIED: return tr("Last Date Modified");
                        case COLUMN_SIZE: return tr("Size");
                   }
                   return QVariant();
              }
              case Qt::SizeHintRole:  {
                   return 128;
              }
              case Qt::TextAlignmentRole:  {
                   return QVariant(Qt::AlignLeft);
              }
         }
    
         return QVariant();
    }
    
    int FileSystemModel::columnCount(const QModelIndex& parent) const
    {
         Q_UNUSED(parent)
         return 5;
    }
    

  • Qt Champions 2019

    What's the benefit of FileSystemModel::getFileInfo()? I would guess your this pointer is a nullptr