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. beginResetModel/endResetModel problems
Qt 6.11 is out! See what's new in the release blog

beginResetModel/endResetModel problems

Scheduled Pinned Locked Moved Solved General and Desktop
15 Posts 3 Posters 3.7k Views
  • 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.
  • A Offline
    A Offline
    ailika
    wrote on last edited by
    #1

    I want to reset my data, but when I use beginResetModel/endResetModel, the program just cracks. I don't know why.
    I'm using Qt Quick's GridView to show the model.
    I subclassed QAbstractListModel, which accomplish a function reading the picture file information in the the file system.
    When I need to change the dir, I need to reset the model data dramatically, so I use beginResetModel/endResetModel, as following:
    beginResetModel();
    m_picfiles->clear(); //private data m_picfiles definition: QList<PhotoInfo> *m_picfiles;
    changePicPath_Internal(m_path); //change m_picfiles
    endResetModel();
    the program will crack when calling endResetModel(), the error warning is:
    ASSERT failure in QList<T>::at: "index out of range", file E:/QT/5.12.9/mingw73_64/include/QtCore/qlist.h, line 544

    Even I just use beginResetModel() and endResetModel(), the problem doesn't disappear.

    And likely, there is the the same problem with beginRemoveRows/endRemoveRows
    bool PhotoFiles::removeRows(int row, int count, const QModelIndex &/parent/)
    {
    if(row > rowCount())
    return true;
    beginRemoveRows(QModelIndex(), row, row+count-1);
    for (int i = 0; i < count; ++i) {
    m_picfiles->removeAt(row);
    }
    endRemoveRows();
    return true;
    }

    Although, I can use something like QFileSystemModel/FolderListModel, I really want to figure out the model subclass problem.

    jsulmJ 1 Reply Last reply
    0
    • A ailika

      @jsulm
      Thank you.

      #ifndef PHOTOFILES_H
      #define PHOTOFILES_H
      
      #include <QObject>
      #include <QAbstractListModel>
      #include <QFileInfo>
      #include <QUrl>
      #include <QDebug>
      
      class PhotoInfo{
      public:
          PhotoInfo() {}
          PhotoInfo(QUrl url,QString title,bool isdir,QString path){m_url = url;m_title = title;m_isDir = isdir;m_path = path;}
      
          void setData(QUrl url,QString title,bool isdir,QString path){m_url = url;m_title = title;m_isDir = isdir;m_path = path;}
          void setIsDir(bool isdir) {m_isDir = isdir;}
          void setTitle(QString title){m_title = title;}
          void setUrl(QUrl url){m_url = url;}
          void setPath(QString path){m_path = path;}
          bool getIsDir(){return m_isDir;}
          QUrl getUrl(){return m_url;}
          QString getTitle(){return m_title;}
          QString getPath(){return m_path;}
      private:
          QUrl m_url;
          QString m_title;
          bool m_isDir;
          QString m_path;
      };
      
      
      class PhotoFiles : public QAbstractListModel//QAbstractListModel
      {
          Q_OBJECT
          Q_ENUMS(FileRoles)
      
          Q_PROPERTY(QString folder READ folder WRITE setFolder NOTIFY folderChanged)
      
      public:
          enum FileRoles {
              FileNameRole = Qt::UserRole + 1,
              FileUrlRole,
              FileIsDirRole,
          };
      
          void setFolder(const QString &a) {
              if (a != m_path) {
                  m_path = a;
                  changePicPath(m_path);
                  emit folderChanged();   //emit the signal when the property value changes
              }
          }
      
          QString folder() const {
              return m_path;
          }
      
          PhotoFiles();
          ~PhotoFiles(){delete m_picfiles;}
      
          QHash<int, QByteArray> roleNames() const override;
          int rowCount(const QModelIndex &parent = QModelIndex()) const override;
          QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
          //QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
          Qt::ItemFlags flags(const QModelIndex &index) const override;
          bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
          bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
          bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
      
          //自定义函数
          void changePicPath_Internal(QString paths);
          void changePicPath(QString paths);
      
          Q_INVOKABLE bool isFolder(int index);
          Q_INVOKABLE QString getPath(int index);
          Q_INVOKABLE void changePathAct();
      signals:
          void folderChanged();
      
      
      private:
          QList<PhotoInfo> *m_picfiles;
          QString m_path;
      };
      
      #endif // PHOTOFILES_H
      
      #include "photos\photofiles.h"
      #include <QDir>
      #include <QDirIterator>
      #include <QDebug>
      
      
      PhotoFiles::PhotoFiles()
      {
          m_picfiles = new QList<PhotoInfo>;
      }
      
      QHash<int, QByteArray> PhotoFiles::roleNames() const
      {
          QHash<int, QByteArray> names;
          names[FileNameRole] = "fileName";
          names[FileUrlRole] = "fileURL";
          names[FileIsDirRole] = "fileIsDir";
          return names;
      }
      
      int PhotoFiles::rowCount(const QModelIndex &/*parent*/) const
      {
          return m_picfiles->count();
      }
      
      
      
      //QVariant PhotoFiles::headerData(int /*section*/, Qt::Orientation /*orientation*/, int /*role*/) const
      //{
      //    return  QVariant();
      //}
      
      QVariant PhotoFiles::data(const QModelIndex &index, int role) const
      {
      
          if (!index.isValid())
              return QVariant();
          if (index.row() >= m_picfiles->count())
              return QVariant();
      
          PhotoInfo photo = m_picfiles->at(index.row());
      
          if (role == FileNameRole)
              return photo.getTitle();
          else if(role == FileUrlRole)
              return photo.getUrl();
          else if(role == FileIsDirRole)
              return  photo.getIsDir();
          else
              return QVariant();
          return  QVariant();
      }
      
      
      
      Qt::ItemFlags PhotoFiles::flags(const QModelIndex &index) const
      {
          if (!index.isValid())
              return Qt::ItemIsEnabled;
          return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
      }
      
      bool PhotoFiles::setData(const QModelIndex &index, const QVariant &value, int role)
      {
          if (index.isValid()) {
              PhotoInfo photo = m_picfiles->at(index.row());
      
              if(role == FileNameRole)
              {
                  photo.setTitle(value.toString());
              }
              else if(role == FileUrlRole)
              {
                  photo.setUrl(value.toUrl());
              }
              else if(role == FileIsDirRole)
              {
                  photo.setIsDir(value.toBool());
              }
              else
                  return false;
      
              emit dataChanged(index, index, {role});
              return true;
          }
          return false;
      }
      
      bool PhotoFiles::insertRows(int row, int count, const QModelIndex &/*parent*/)
      {
          beginInsertRows(QModelIndex(), row, row+count-1);
          for (int i = 0; i < count; ++i) {
              m_picfiles->insert(row,PhotoInfo());
          }
          endInsertRows();
          return true;
      }
      
      bool PhotoFiles::removeRows(int row, int count, const QModelIndex &/*parent*/)
      {
          if(row > rowCount())
              return true;
          beginRemoveRows(QModelIndex(), row, row+count-1);
          for (int i = 0; i < count; ++i) {
              m_picfiles->removeAt(row);
          }
          endRemoveRows();
          return true;
      }
      
      //更换目录显示
      void PhotoFiles::changePicPath_Internal(QString paths)
      {
          /*加入paths中所有的文件,包括文件夹(文件夹在前,图片在后,但是QDirIterator又没有排序信息,自己手动? TobedoneSign)*/
          QStringList filter;
          filter << "*.jpg" << "*.png";
          QDirIterator it(paths,filter,QDir::AllDirs|QDir::Files|QDir::NoSymLinks);
          while (it.hasNext()) {
              it.next();
              if(it.fileName() != ".")    //加入到m_picfiles种
              {
                  PhotoInfo photo;
                  if(it.fileName() == "..")
                  {
                      photo.setIsDir(true);
                      photo.setTitle("上级目录");
                      photo.setPath(it.filePath()+"/");
                  }
                  else
                  {
                      QUrl url = QUrl::fromLocalFile(it.filePath());
                      photo.setData(url,it.fileName(),it.fileInfo().isDir(),it.filePath()+"/");
                  }
                  m_picfiles->append(photo);
              }
          }
      
      
          //debug
      //    QList<PhotoInfo>::iterator i;
      //    for (i = m_picfiles->begin(); i != m_picfiles->end(); ++i)
      //    {
      //        qDebug() << i->getIsDir() << " " << i->getTitle() << " " << i->getUrl() << " " << i->getPath();
      //    }
      
      }
      
      void PhotoFiles::changePicPath(QString paths)
      {
          /*判断路径有效性*/
          QDir directory(paths);
          if(!directory.exists())
          {
              qDebug() << "path not exist!";
              return;
          }
      
          m_path = paths;
      
          //delete m_picfiles;
          //m_picfiles = new QList<PhotoInfo>;
      
          beginResetModel();
          m_picfiles->clear();
          changePicPath_Internal(m_path);
          endResetModel();
      }
      
      void PhotoFiles::changePathAct()
      {
          beginResetModel();
          m_picfiles->clear();
          changePicPath_Internal(m_path);
          endResetModel();
      }
      
      bool PhotoFiles::isFolder(int index)
      {
          PhotoInfo photo = m_picfiles->at(index);
          return photo.getIsDir();
      }
      
      
      QString PhotoFiles::getPath(int index)
      {
          PhotoInfo photo = m_picfiles->at(index);
          return photo.getPath();
      }
      
      import QtQuick 2.12
      import QtQuick.Window 2.12
      import PhotoFiles 1.0
      import QtQuick.Controls 2.12
      import QtQuick.Layouts 1.12
      
      Item {
          id:root
          property string  pic_folder//:"E:/BaiduNetdiskDownload/qt_projects/ZjrDesktop/build-ZjrDesktop-Desktop_Qt_5_12_9_MinGW_64_bit-Debug/debug/images/"
                          //初始化时,这个是空,后来才赋值的;所以model里面没处理好的话,不会更新显示
      
          GridView {
              id:grid
              width: parent.width;
              height: parent.height
              cellWidth: 150; cellHeight: 150
              cacheBuffer:800   //没看出来有什么区别
      
              PhotoFiles {
                  id: folderModel
                  folder:pic_folder
              }
      
              model: folderModel
              delegate: fileDelegate
      
              ScrollBar.vertical: ScrollBar {}
      
          }
      
          Component {
              id: fileDelegate
      
              Item{
                  id:delegate_item
                  width:  grid.cellWidth
                  height: grid.cellHeight
      
      
                  Column{
                      anchors.fill: parent
      
                      Image
                      {
                          visible: true
                          height:delegate_item.GridView.view.model.isFolder(index)?delegate_item.height-folder_text.implicitHeight:delegate_item.height
                          width:delegate_item.width
                          source:delegate_item.GridView.view.model.isFolder(index)?"qrc:///photos/images/filefolder_pic.png":fileURL
                          mipmap:true   //但是没有系统缩略图效果好
                      }
      
                      Text {
                          anchors.horizontalCenter: parent.horizontalCenter
                          id:folder_text
                          text: fileName
                          visible: delegate_item.GridView.view.model.isFolder(index)
                          font.pixelSize: 16
                      }
                  }
      
                  MouseArea{
                      anchors.fill: parent
                      onClicked:{
                          if(delegate_item.GridView.view.model.isFolder(index))
                          {
                              root.pic_folder = delegate_item.GridView.view.model.getPath(index)
                          }
                          else
                          {
                              //stack.push(photo_disp,{"start_pic": index})
                          }
                      }
                  }
              }
          }
      }
      

      ed3a3615-496f-4b3b-855a-373d89d21969-image.png
      f7fe5863-8af9-4c17-9d69-640af18df2e8-image.png
      d998c575-dbca-4566-9c5d-0d2bca62d1df-image.png

      jsulmJ Offline
      jsulmJ Offline
      jsulm
      Lifetime Qt Champion
      wrote on last edited by
      #6

      @ailika said in beginResetModel/endResetModel problems:

      bool PhotoFiles::isFolder(int index)
      {
      PhotoInfo photo = m_picfiles->at(index);
      return photo.getIsDir();
      }

      You're not checking whether "index" is out of bounds or not. And according to the error message it is...

      https://forum.qt.io/topic/113070/qt-code-of-conduct

      A 1 Reply Last reply
      2
      • A ailika

        I want to reset my data, but when I use beginResetModel/endResetModel, the program just cracks. I don't know why.
        I'm using Qt Quick's GridView to show the model.
        I subclassed QAbstractListModel, which accomplish a function reading the picture file information in the the file system.
        When I need to change the dir, I need to reset the model data dramatically, so I use beginResetModel/endResetModel, as following:
        beginResetModel();
        m_picfiles->clear(); //private data m_picfiles definition: QList<PhotoInfo> *m_picfiles;
        changePicPath_Internal(m_path); //change m_picfiles
        endResetModel();
        the program will crack when calling endResetModel(), the error warning is:
        ASSERT failure in QList<T>::at: "index out of range", file E:/QT/5.12.9/mingw73_64/include/QtCore/qlist.h, line 544

        Even I just use beginResetModel() and endResetModel(), the problem doesn't disappear.

        And likely, there is the the same problem with beginRemoveRows/endRemoveRows
        bool PhotoFiles::removeRows(int row, int count, const QModelIndex &/parent/)
        {
        if(row > rowCount())
        return true;
        beginRemoveRows(QModelIndex(), row, row+count-1);
        for (int i = 0; i < count; ++i) {
        m_picfiles->removeAt(row);
        }
        endRemoveRows();
        return true;
        }

        Although, I can use something like QFileSystemModel/FolderListModel, I really want to figure out the model subclass problem.

        jsulmJ Offline
        jsulmJ Offline
        jsulm
        Lifetime Qt Champion
        wrote on last edited by
        #2

        @ailika Please provide stack trace after the crash.
        And please format your code properly - this helps others to read it.

        https://forum.qt.io/topic/113070/qt-code-of-conduct

        A 1 Reply Last reply
        0
        • jsulmJ jsulm

          @ailika Please provide stack trace after the crash.
          And please format your code properly - this helps others to read it.

          A Offline
          A Offline
          ailika
          wrote on last edited by
          #3
          This post is deleted!
          jsulmJ 1 Reply Last reply
          0
          • A ailika

            This post is deleted!

            jsulmJ Offline
            jsulmJ Offline
            jsulm
            Lifetime Qt Champion
            wrote on last edited by
            #4

            @ailika said in beginResetModel/endResetModel problems:

            I'm sorry I don't know how to paste beautifully

            Simply use the code tags.
            And you did not post the stack trace after the crash...

            https://forum.qt.io/topic/113070/qt-code-of-conduct

            A 1 Reply Last reply
            0
            • jsulmJ jsulm

              @ailika said in beginResetModel/endResetModel problems:

              I'm sorry I don't know how to paste beautifully

              Simply use the code tags.
              And you did not post the stack trace after the crash...

              A Offline
              A Offline
              ailika
              wrote on last edited by
              #5

              @jsulm
              Thank you.

              #ifndef PHOTOFILES_H
              #define PHOTOFILES_H
              
              #include <QObject>
              #include <QAbstractListModel>
              #include <QFileInfo>
              #include <QUrl>
              #include <QDebug>
              
              class PhotoInfo{
              public:
                  PhotoInfo() {}
                  PhotoInfo(QUrl url,QString title,bool isdir,QString path){m_url = url;m_title = title;m_isDir = isdir;m_path = path;}
              
                  void setData(QUrl url,QString title,bool isdir,QString path){m_url = url;m_title = title;m_isDir = isdir;m_path = path;}
                  void setIsDir(bool isdir) {m_isDir = isdir;}
                  void setTitle(QString title){m_title = title;}
                  void setUrl(QUrl url){m_url = url;}
                  void setPath(QString path){m_path = path;}
                  bool getIsDir(){return m_isDir;}
                  QUrl getUrl(){return m_url;}
                  QString getTitle(){return m_title;}
                  QString getPath(){return m_path;}
              private:
                  QUrl m_url;
                  QString m_title;
                  bool m_isDir;
                  QString m_path;
              };
              
              
              class PhotoFiles : public QAbstractListModel//QAbstractListModel
              {
                  Q_OBJECT
                  Q_ENUMS(FileRoles)
              
                  Q_PROPERTY(QString folder READ folder WRITE setFolder NOTIFY folderChanged)
              
              public:
                  enum FileRoles {
                      FileNameRole = Qt::UserRole + 1,
                      FileUrlRole,
                      FileIsDirRole,
                  };
              
                  void setFolder(const QString &a) {
                      if (a != m_path) {
                          m_path = a;
                          changePicPath(m_path);
                          emit folderChanged();   //emit the signal when the property value changes
                      }
                  }
              
                  QString folder() const {
                      return m_path;
                  }
              
                  PhotoFiles();
                  ~PhotoFiles(){delete m_picfiles;}
              
                  QHash<int, QByteArray> roleNames() const override;
                  int rowCount(const QModelIndex &parent = QModelIndex()) const override;
                  QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
                  //QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
                  Qt::ItemFlags flags(const QModelIndex &index) const override;
                  bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
                  bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
                  bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
              
                  //自定义函数
                  void changePicPath_Internal(QString paths);
                  void changePicPath(QString paths);
              
                  Q_INVOKABLE bool isFolder(int index);
                  Q_INVOKABLE QString getPath(int index);
                  Q_INVOKABLE void changePathAct();
              signals:
                  void folderChanged();
              
              
              private:
                  QList<PhotoInfo> *m_picfiles;
                  QString m_path;
              };
              
              #endif // PHOTOFILES_H
              
              #include "photos\photofiles.h"
              #include <QDir>
              #include <QDirIterator>
              #include <QDebug>
              
              
              PhotoFiles::PhotoFiles()
              {
                  m_picfiles = new QList<PhotoInfo>;
              }
              
              QHash<int, QByteArray> PhotoFiles::roleNames() const
              {
                  QHash<int, QByteArray> names;
                  names[FileNameRole] = "fileName";
                  names[FileUrlRole] = "fileURL";
                  names[FileIsDirRole] = "fileIsDir";
                  return names;
              }
              
              int PhotoFiles::rowCount(const QModelIndex &/*parent*/) const
              {
                  return m_picfiles->count();
              }
              
              
              
              //QVariant PhotoFiles::headerData(int /*section*/, Qt::Orientation /*orientation*/, int /*role*/) const
              //{
              //    return  QVariant();
              //}
              
              QVariant PhotoFiles::data(const QModelIndex &index, int role) const
              {
              
                  if (!index.isValid())
                      return QVariant();
                  if (index.row() >= m_picfiles->count())
                      return QVariant();
              
                  PhotoInfo photo = m_picfiles->at(index.row());
              
                  if (role == FileNameRole)
                      return photo.getTitle();
                  else if(role == FileUrlRole)
                      return photo.getUrl();
                  else if(role == FileIsDirRole)
                      return  photo.getIsDir();
                  else
                      return QVariant();
                  return  QVariant();
              }
              
              
              
              Qt::ItemFlags PhotoFiles::flags(const QModelIndex &index) const
              {
                  if (!index.isValid())
                      return Qt::ItemIsEnabled;
                  return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
              }
              
              bool PhotoFiles::setData(const QModelIndex &index, const QVariant &value, int role)
              {
                  if (index.isValid()) {
                      PhotoInfo photo = m_picfiles->at(index.row());
              
                      if(role == FileNameRole)
                      {
                          photo.setTitle(value.toString());
                      }
                      else if(role == FileUrlRole)
                      {
                          photo.setUrl(value.toUrl());
                      }
                      else if(role == FileIsDirRole)
                      {
                          photo.setIsDir(value.toBool());
                      }
                      else
                          return false;
              
                      emit dataChanged(index, index, {role});
                      return true;
                  }
                  return false;
              }
              
              bool PhotoFiles::insertRows(int row, int count, const QModelIndex &/*parent*/)
              {
                  beginInsertRows(QModelIndex(), row, row+count-1);
                  for (int i = 0; i < count; ++i) {
                      m_picfiles->insert(row,PhotoInfo());
                  }
                  endInsertRows();
                  return true;
              }
              
              bool PhotoFiles::removeRows(int row, int count, const QModelIndex &/*parent*/)
              {
                  if(row > rowCount())
                      return true;
                  beginRemoveRows(QModelIndex(), row, row+count-1);
                  for (int i = 0; i < count; ++i) {
                      m_picfiles->removeAt(row);
                  }
                  endRemoveRows();
                  return true;
              }
              
              //更换目录显示
              void PhotoFiles::changePicPath_Internal(QString paths)
              {
                  /*加入paths中所有的文件,包括文件夹(文件夹在前,图片在后,但是QDirIterator又没有排序信息,自己手动? TobedoneSign)*/
                  QStringList filter;
                  filter << "*.jpg" << "*.png";
                  QDirIterator it(paths,filter,QDir::AllDirs|QDir::Files|QDir::NoSymLinks);
                  while (it.hasNext()) {
                      it.next();
                      if(it.fileName() != ".")    //加入到m_picfiles种
                      {
                          PhotoInfo photo;
                          if(it.fileName() == "..")
                          {
                              photo.setIsDir(true);
                              photo.setTitle("上级目录");
                              photo.setPath(it.filePath()+"/");
                          }
                          else
                          {
                              QUrl url = QUrl::fromLocalFile(it.filePath());
                              photo.setData(url,it.fileName(),it.fileInfo().isDir(),it.filePath()+"/");
                          }
                          m_picfiles->append(photo);
                      }
                  }
              
              
                  //debug
              //    QList<PhotoInfo>::iterator i;
              //    for (i = m_picfiles->begin(); i != m_picfiles->end(); ++i)
              //    {
              //        qDebug() << i->getIsDir() << " " << i->getTitle() << " " << i->getUrl() << " " << i->getPath();
              //    }
              
              }
              
              void PhotoFiles::changePicPath(QString paths)
              {
                  /*判断路径有效性*/
                  QDir directory(paths);
                  if(!directory.exists())
                  {
                      qDebug() << "path not exist!";
                      return;
                  }
              
                  m_path = paths;
              
                  //delete m_picfiles;
                  //m_picfiles = new QList<PhotoInfo>;
              
                  beginResetModel();
                  m_picfiles->clear();
                  changePicPath_Internal(m_path);
                  endResetModel();
              }
              
              void PhotoFiles::changePathAct()
              {
                  beginResetModel();
                  m_picfiles->clear();
                  changePicPath_Internal(m_path);
                  endResetModel();
              }
              
              bool PhotoFiles::isFolder(int index)
              {
                  PhotoInfo photo = m_picfiles->at(index);
                  return photo.getIsDir();
              }
              
              
              QString PhotoFiles::getPath(int index)
              {
                  PhotoInfo photo = m_picfiles->at(index);
                  return photo.getPath();
              }
              
              import QtQuick 2.12
              import QtQuick.Window 2.12
              import PhotoFiles 1.0
              import QtQuick.Controls 2.12
              import QtQuick.Layouts 1.12
              
              Item {
                  id:root
                  property string  pic_folder//:"E:/BaiduNetdiskDownload/qt_projects/ZjrDesktop/build-ZjrDesktop-Desktop_Qt_5_12_9_MinGW_64_bit-Debug/debug/images/"
                                  //初始化时,这个是空,后来才赋值的;所以model里面没处理好的话,不会更新显示
              
                  GridView {
                      id:grid
                      width: parent.width;
                      height: parent.height
                      cellWidth: 150; cellHeight: 150
                      cacheBuffer:800   //没看出来有什么区别
              
                      PhotoFiles {
                          id: folderModel
                          folder:pic_folder
                      }
              
                      model: folderModel
                      delegate: fileDelegate
              
                      ScrollBar.vertical: ScrollBar {}
              
                  }
              
                  Component {
                      id: fileDelegate
              
                      Item{
                          id:delegate_item
                          width:  grid.cellWidth
                          height: grid.cellHeight
              
              
                          Column{
                              anchors.fill: parent
              
                              Image
                              {
                                  visible: true
                                  height:delegate_item.GridView.view.model.isFolder(index)?delegate_item.height-folder_text.implicitHeight:delegate_item.height
                                  width:delegate_item.width
                                  source:delegate_item.GridView.view.model.isFolder(index)?"qrc:///photos/images/filefolder_pic.png":fileURL
                                  mipmap:true   //但是没有系统缩略图效果好
                              }
              
                              Text {
                                  anchors.horizontalCenter: parent.horizontalCenter
                                  id:folder_text
                                  text: fileName
                                  visible: delegate_item.GridView.view.model.isFolder(index)
                                  font.pixelSize: 16
                              }
                          }
              
                          MouseArea{
                              anchors.fill: parent
                              onClicked:{
                                  if(delegate_item.GridView.view.model.isFolder(index))
                                  {
                                      root.pic_folder = delegate_item.GridView.view.model.getPath(index)
                                  }
                                  else
                                  {
                                      //stack.push(photo_disp,{"start_pic": index})
                                  }
                              }
                          }
                      }
                  }
              }
              

              ed3a3615-496f-4b3b-855a-373d89d21969-image.png
              f7fe5863-8af9-4c17-9d69-640af18df2e8-image.png
              d998c575-dbca-4566-9c5d-0d2bca62d1df-image.png

              jsulmJ 1 Reply Last reply
              0
              • A ailika

                @jsulm
                Thank you.

                #ifndef PHOTOFILES_H
                #define PHOTOFILES_H
                
                #include <QObject>
                #include <QAbstractListModel>
                #include <QFileInfo>
                #include <QUrl>
                #include <QDebug>
                
                class PhotoInfo{
                public:
                    PhotoInfo() {}
                    PhotoInfo(QUrl url,QString title,bool isdir,QString path){m_url = url;m_title = title;m_isDir = isdir;m_path = path;}
                
                    void setData(QUrl url,QString title,bool isdir,QString path){m_url = url;m_title = title;m_isDir = isdir;m_path = path;}
                    void setIsDir(bool isdir) {m_isDir = isdir;}
                    void setTitle(QString title){m_title = title;}
                    void setUrl(QUrl url){m_url = url;}
                    void setPath(QString path){m_path = path;}
                    bool getIsDir(){return m_isDir;}
                    QUrl getUrl(){return m_url;}
                    QString getTitle(){return m_title;}
                    QString getPath(){return m_path;}
                private:
                    QUrl m_url;
                    QString m_title;
                    bool m_isDir;
                    QString m_path;
                };
                
                
                class PhotoFiles : public QAbstractListModel//QAbstractListModel
                {
                    Q_OBJECT
                    Q_ENUMS(FileRoles)
                
                    Q_PROPERTY(QString folder READ folder WRITE setFolder NOTIFY folderChanged)
                
                public:
                    enum FileRoles {
                        FileNameRole = Qt::UserRole + 1,
                        FileUrlRole,
                        FileIsDirRole,
                    };
                
                    void setFolder(const QString &a) {
                        if (a != m_path) {
                            m_path = a;
                            changePicPath(m_path);
                            emit folderChanged();   //emit the signal when the property value changes
                        }
                    }
                
                    QString folder() const {
                        return m_path;
                    }
                
                    PhotoFiles();
                    ~PhotoFiles(){delete m_picfiles;}
                
                    QHash<int, QByteArray> roleNames() const override;
                    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
                    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
                    //QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
                    Qt::ItemFlags flags(const QModelIndex &index) const override;
                    bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
                    bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
                    bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
                
                    //自定义函数
                    void changePicPath_Internal(QString paths);
                    void changePicPath(QString paths);
                
                    Q_INVOKABLE bool isFolder(int index);
                    Q_INVOKABLE QString getPath(int index);
                    Q_INVOKABLE void changePathAct();
                signals:
                    void folderChanged();
                
                
                private:
                    QList<PhotoInfo> *m_picfiles;
                    QString m_path;
                };
                
                #endif // PHOTOFILES_H
                
                #include "photos\photofiles.h"
                #include <QDir>
                #include <QDirIterator>
                #include <QDebug>
                
                
                PhotoFiles::PhotoFiles()
                {
                    m_picfiles = new QList<PhotoInfo>;
                }
                
                QHash<int, QByteArray> PhotoFiles::roleNames() const
                {
                    QHash<int, QByteArray> names;
                    names[FileNameRole] = "fileName";
                    names[FileUrlRole] = "fileURL";
                    names[FileIsDirRole] = "fileIsDir";
                    return names;
                }
                
                int PhotoFiles::rowCount(const QModelIndex &/*parent*/) const
                {
                    return m_picfiles->count();
                }
                
                
                
                //QVariant PhotoFiles::headerData(int /*section*/, Qt::Orientation /*orientation*/, int /*role*/) const
                //{
                //    return  QVariant();
                //}
                
                QVariant PhotoFiles::data(const QModelIndex &index, int role) const
                {
                
                    if (!index.isValid())
                        return QVariant();
                    if (index.row() >= m_picfiles->count())
                        return QVariant();
                
                    PhotoInfo photo = m_picfiles->at(index.row());
                
                    if (role == FileNameRole)
                        return photo.getTitle();
                    else if(role == FileUrlRole)
                        return photo.getUrl();
                    else if(role == FileIsDirRole)
                        return  photo.getIsDir();
                    else
                        return QVariant();
                    return  QVariant();
                }
                
                
                
                Qt::ItemFlags PhotoFiles::flags(const QModelIndex &index) const
                {
                    if (!index.isValid())
                        return Qt::ItemIsEnabled;
                    return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
                }
                
                bool PhotoFiles::setData(const QModelIndex &index, const QVariant &value, int role)
                {
                    if (index.isValid()) {
                        PhotoInfo photo = m_picfiles->at(index.row());
                
                        if(role == FileNameRole)
                        {
                            photo.setTitle(value.toString());
                        }
                        else if(role == FileUrlRole)
                        {
                            photo.setUrl(value.toUrl());
                        }
                        else if(role == FileIsDirRole)
                        {
                            photo.setIsDir(value.toBool());
                        }
                        else
                            return false;
                
                        emit dataChanged(index, index, {role});
                        return true;
                    }
                    return false;
                }
                
                bool PhotoFiles::insertRows(int row, int count, const QModelIndex &/*parent*/)
                {
                    beginInsertRows(QModelIndex(), row, row+count-1);
                    for (int i = 0; i < count; ++i) {
                        m_picfiles->insert(row,PhotoInfo());
                    }
                    endInsertRows();
                    return true;
                }
                
                bool PhotoFiles::removeRows(int row, int count, const QModelIndex &/*parent*/)
                {
                    if(row > rowCount())
                        return true;
                    beginRemoveRows(QModelIndex(), row, row+count-1);
                    for (int i = 0; i < count; ++i) {
                        m_picfiles->removeAt(row);
                    }
                    endRemoveRows();
                    return true;
                }
                
                //更换目录显示
                void PhotoFiles::changePicPath_Internal(QString paths)
                {
                    /*加入paths中所有的文件,包括文件夹(文件夹在前,图片在后,但是QDirIterator又没有排序信息,自己手动? TobedoneSign)*/
                    QStringList filter;
                    filter << "*.jpg" << "*.png";
                    QDirIterator it(paths,filter,QDir::AllDirs|QDir::Files|QDir::NoSymLinks);
                    while (it.hasNext()) {
                        it.next();
                        if(it.fileName() != ".")    //加入到m_picfiles种
                        {
                            PhotoInfo photo;
                            if(it.fileName() == "..")
                            {
                                photo.setIsDir(true);
                                photo.setTitle("上级目录");
                                photo.setPath(it.filePath()+"/");
                            }
                            else
                            {
                                QUrl url = QUrl::fromLocalFile(it.filePath());
                                photo.setData(url,it.fileName(),it.fileInfo().isDir(),it.filePath()+"/");
                            }
                            m_picfiles->append(photo);
                        }
                    }
                
                
                    //debug
                //    QList<PhotoInfo>::iterator i;
                //    for (i = m_picfiles->begin(); i != m_picfiles->end(); ++i)
                //    {
                //        qDebug() << i->getIsDir() << " " << i->getTitle() << " " << i->getUrl() << " " << i->getPath();
                //    }
                
                }
                
                void PhotoFiles::changePicPath(QString paths)
                {
                    /*判断路径有效性*/
                    QDir directory(paths);
                    if(!directory.exists())
                    {
                        qDebug() << "path not exist!";
                        return;
                    }
                
                    m_path = paths;
                
                    //delete m_picfiles;
                    //m_picfiles = new QList<PhotoInfo>;
                
                    beginResetModel();
                    m_picfiles->clear();
                    changePicPath_Internal(m_path);
                    endResetModel();
                }
                
                void PhotoFiles::changePathAct()
                {
                    beginResetModel();
                    m_picfiles->clear();
                    changePicPath_Internal(m_path);
                    endResetModel();
                }
                
                bool PhotoFiles::isFolder(int index)
                {
                    PhotoInfo photo = m_picfiles->at(index);
                    return photo.getIsDir();
                }
                
                
                QString PhotoFiles::getPath(int index)
                {
                    PhotoInfo photo = m_picfiles->at(index);
                    return photo.getPath();
                }
                
                import QtQuick 2.12
                import QtQuick.Window 2.12
                import PhotoFiles 1.0
                import QtQuick.Controls 2.12
                import QtQuick.Layouts 1.12
                
                Item {
                    id:root
                    property string  pic_folder//:"E:/BaiduNetdiskDownload/qt_projects/ZjrDesktop/build-ZjrDesktop-Desktop_Qt_5_12_9_MinGW_64_bit-Debug/debug/images/"
                                    //初始化时,这个是空,后来才赋值的;所以model里面没处理好的话,不会更新显示
                
                    GridView {
                        id:grid
                        width: parent.width;
                        height: parent.height
                        cellWidth: 150; cellHeight: 150
                        cacheBuffer:800   //没看出来有什么区别
                
                        PhotoFiles {
                            id: folderModel
                            folder:pic_folder
                        }
                
                        model: folderModel
                        delegate: fileDelegate
                
                        ScrollBar.vertical: ScrollBar {}
                
                    }
                
                    Component {
                        id: fileDelegate
                
                        Item{
                            id:delegate_item
                            width:  grid.cellWidth
                            height: grid.cellHeight
                
                
                            Column{
                                anchors.fill: parent
                
                                Image
                                {
                                    visible: true
                                    height:delegate_item.GridView.view.model.isFolder(index)?delegate_item.height-folder_text.implicitHeight:delegate_item.height
                                    width:delegate_item.width
                                    source:delegate_item.GridView.view.model.isFolder(index)?"qrc:///photos/images/filefolder_pic.png":fileURL
                                    mipmap:true   //但是没有系统缩略图效果好
                                }
                
                                Text {
                                    anchors.horizontalCenter: parent.horizontalCenter
                                    id:folder_text
                                    text: fileName
                                    visible: delegate_item.GridView.view.model.isFolder(index)
                                    font.pixelSize: 16
                                }
                            }
                
                            MouseArea{
                                anchors.fill: parent
                                onClicked:{
                                    if(delegate_item.GridView.view.model.isFolder(index))
                                    {
                                        root.pic_folder = delegate_item.GridView.view.model.getPath(index)
                                    }
                                    else
                                    {
                                        //stack.push(photo_disp,{"start_pic": index})
                                    }
                                }
                            }
                        }
                    }
                }
                

                ed3a3615-496f-4b3b-855a-373d89d21969-image.png
                f7fe5863-8af9-4c17-9d69-640af18df2e8-image.png
                d998c575-dbca-4566-9c5d-0d2bca62d1df-image.png

                jsulmJ Offline
                jsulmJ Offline
                jsulm
                Lifetime Qt Champion
                wrote on last edited by
                #6

                @ailika said in beginResetModel/endResetModel problems:

                bool PhotoFiles::isFolder(int index)
                {
                PhotoInfo photo = m_picfiles->at(index);
                return photo.getIsDir();
                }

                You're not checking whether "index" is out of bounds or not. And according to the error message it is...

                https://forum.qt.io/topic/113070/qt-code-of-conduct

                A 1 Reply Last reply
                2
                • jsulmJ jsulm

                  @ailika said in beginResetModel/endResetModel problems:

                  bool PhotoFiles::isFolder(int index)
                  {
                  PhotoInfo photo = m_picfiles->at(index);
                  return photo.getIsDir();
                  }

                  You're not checking whether "index" is out of bounds or not. And according to the error message it is...

                  A Offline
                  A Offline
                  ailika
                  wrote on last edited by
                  #7

                  @jsulm Thank you very much. It solves the problem. I just saw someone has a similar problem, but I neglected these last two functions. I thought these were not the inhereted functions so that it does's not matter. What a misunderstanding.
                  By the way, Did you figure out the reason by code or by the stack? How to check the stack? Is it like that I can find in what function the problem takes place?

                  jsulmJ 1 Reply Last reply
                  0
                  • A ailika has marked this topic as solved on
                  • A ailika

                    @jsulm Thank you very much. It solves the problem. I just saw someone has a similar problem, but I neglected these last two functions. I thought these were not the inhereted functions so that it does's not matter. What a misunderstanding.
                    By the way, Did you figure out the reason by code or by the stack? How to check the stack? Is it like that I can find in what function the problem takes place?

                    jsulmJ Offline
                    jsulmJ Offline
                    jsulm
                    Lifetime Qt Champion
                    wrote on last edited by
                    #8

                    @ailika said in beginResetModel/endResetModel problems:

                    Did you figure out the reason by code or by the stack?

                    Both. In the stack trace you can see that the last method from your code which was called is PhotoFiles::isFolder (line 6 in stack trace). So I checked the implementation of that method and saw that you do not check the index which also matches the error you posted.

                    https://forum.qt.io/topic/113070/qt-code-of-conduct

                    A 2 Replies Last reply
                    0
                    • jsulmJ jsulm

                      @ailika said in beginResetModel/endResetModel problems:

                      Did you figure out the reason by code or by the stack?

                      Both. In the stack trace you can see that the last method from your code which was called is PhotoFiles::isFolder (line 6 in stack trace). So I checked the implementation of that method and saw that you do not check the index which also matches the error you posted.

                      A Offline
                      A Offline
                      ailika
                      wrote on last edited by
                      #9

                      @jsulm Oh, I see. I have never used the stack to check problems. It seems really helpful. I have thought some Qt inbuild functions somehow call my QList object because Qt has meta object functions....I thought I have wrongly used the model subclass process.
                      Thank you very much.

                      1 Reply Last reply
                      0
                      • jsulmJ jsulm

                        @ailika said in beginResetModel/endResetModel problems:

                        Did you figure out the reason by code or by the stack?

                        Both. In the stack trace you can see that the last method from your code which was called is PhotoFiles::isFolder (line 6 in stack trace). So I checked the implementation of that method and saw that you do not check the index which also matches the error you posted.

                        A Offline
                        A Offline
                        ailika
                        wrote on last edited by
                        #10

                        @jsulm I have another question.
                        I add delete function in the program. the model's function changes as follows:

                        bool PhotoFiles::removeRows(int row, int count, const QModelIndex &/*parent*/)
                        {
                            if(row > rowCount())
                                return true;
                        
                            beginRemoveRows(QModelIndex(), row, row+count-1);
                        
                        
                            PhotoInfo photo = m_picfiles->at(row);
                            QUrl url = photo.getUrl();
                            qDebug() << url;
                            QFile file(url.toLocalFile());
                        
                            for (int i = 0; i < count; ++i) {
                                m_picfiles->removeAt(row);
                            }
                        
                            if(file.exists())
                            {
                                //qDebug() << "file exist";
                                if(file.remove())
                                {
                                    //qDebug() << "file removed";
                                    return true;
                                }
                                else
                                    qDebug() << "file remove fail";
                            }
                        
                            endRemoveRows();
                            return true;
                        }
                        

                        And I use a button to delete the selected picture.
                        ```

                        Button {//删除文件
                                        id: btnDelete
                                        anchors.left: parent.left
                                        anchors.leftMargin: 10
                                        anchors.verticalCenter: parent.verticalCenter
                                        style: ButtonStyle {
                                            background: Image {
                                                sourceSize.width: 20
                                                sourceSize.height: 20
                                                anchors.fill: parent
                                                source: "qrc:/photos/images/delete.png"
                                            }
                                        }
                                        onClicked: {
                                            if(folderModel.isFolder(pathView.currentIndex) == true) //没有做目录删除处理
                                                return;
                                            var del_index = pathView.currentIndex
                                            if(pathView.currentIndex == folderModel.rowCount())
                                                pathView.currentIndex = pathView.currentIndex - 1
                                            else
                                                pathView.currentIndex = pathView.currentIndex + 1
                        
                                            folderModel.removeRow(del_index)
                                        }
                                    }
                        
                        Though after I delete a picture, it will show the next picture and the picture is deleted from the file system, when I slip back,the deleted  picture is still shown(like it has some cache). 
                        How to solve this question? I see some example code that only says the only thing to do is to delete it between beginRemoveRows/endRemoveRows, but as I use this, the view seems not be able to be informed of the deleting operation.
                        Christian EhrlicherC 1 Reply Last reply
                        0
                        • A ailika

                          @jsulm I have another question.
                          I add delete function in the program. the model's function changes as follows:

                          bool PhotoFiles::removeRows(int row, int count, const QModelIndex &/*parent*/)
                          {
                              if(row > rowCount())
                                  return true;
                          
                              beginRemoveRows(QModelIndex(), row, row+count-1);
                          
                          
                              PhotoInfo photo = m_picfiles->at(row);
                              QUrl url = photo.getUrl();
                              qDebug() << url;
                              QFile file(url.toLocalFile());
                          
                              for (int i = 0; i < count; ++i) {
                                  m_picfiles->removeAt(row);
                              }
                          
                              if(file.exists())
                              {
                                  //qDebug() << "file exist";
                                  if(file.remove())
                                  {
                                      //qDebug() << "file removed";
                                      return true;
                                  }
                                  else
                                      qDebug() << "file remove fail";
                              }
                          
                              endRemoveRows();
                              return true;
                          }
                          

                          And I use a button to delete the selected picture.
                          ```

                          Button {//删除文件
                                          id: btnDelete
                                          anchors.left: parent.left
                                          anchors.leftMargin: 10
                                          anchors.verticalCenter: parent.verticalCenter
                                          style: ButtonStyle {
                                              background: Image {
                                                  sourceSize.width: 20
                                                  sourceSize.height: 20
                                                  anchors.fill: parent
                                                  source: "qrc:/photos/images/delete.png"
                                              }
                                          }
                                          onClicked: {
                                              if(folderModel.isFolder(pathView.currentIndex) == true) //没有做目录删除处理
                                                  return;
                                              var del_index = pathView.currentIndex
                                              if(pathView.currentIndex == folderModel.rowCount())
                                                  pathView.currentIndex = pathView.currentIndex - 1
                                              else
                                                  pathView.currentIndex = pathView.currentIndex + 1
                          
                                              folderModel.removeRow(del_index)
                                          }
                                      }
                          
                          Though after I delete a picture, it will show the next picture and the picture is deleted from the file system, when I slip back,the deleted  picture is still shown(like it has some cache). 
                          How to solve this question? I see some example code that only says the only thing to do is to delete it between beginRemoveRows/endRemoveRows, but as I use this, the view seems not be able to be informed of the deleting operation.
                          Christian EhrlicherC Offline
                          Christian EhrlicherC Offline
                          Christian Ehrlicher
                          Lifetime Qt Champion
                          wrote on last edited by
                          #11

                          @ailika said in beginResetModel/endResetModel problems:

                          endRemoveRows()

                          This is never called. Fix your loop.

                          Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                          Visit the Qt Academy at https://academy.qt.io/catalog

                          A 2 Replies Last reply
                          0
                          • Christian EhrlicherC Christian Ehrlicher

                            @ailika said in beginResetModel/endResetModel problems:

                            endRemoveRows()

                            This is never called. Fix your loop.

                            A Offline
                            A Offline
                            ailika
                            wrote on last edited by
                            #12

                            @Christian-Ehrlicher What do you mean? I have called it at the end of the removeRows() function

                            The following is code segment from qt's help document[Model/View Programming], I think it is just like my code
                            32ec376b-510e-4568-b076-b82d0d8eeb7b-image.png

                            Christian EhrlicherC 1 Reply Last reply
                            0
                            • A ailika

                              @Christian-Ehrlicher What do you mean? I have called it at the end of the removeRows() function

                              The following is code segment from qt's help document[Model/View Programming], I think it is just like my code
                              32ec376b-510e-4568-b076-b82d0d8eeb7b-image.png

                              Christian EhrlicherC Offline
                              Christian EhrlicherC Offline
                              Christian Ehrlicher
                              Lifetime Qt Champion
                              wrote on last edited by
                              #13

                              @ailika said in beginResetModel/endResetModel problems:

                              , I think it is just like my code

                              But it is not. You return when you removed the first file (and forget to remove the rest btw, but that's just another error in your code)

                              Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                              Visit the Qt Academy at https://academy.qt.io/catalog

                              1 Reply Last reply
                              1
                              • Christian EhrlicherC Christian Ehrlicher

                                @ailika said in beginResetModel/endResetModel problems:

                                endRemoveRows()

                                This is never called. Fix your loop.

                                A Offline
                                A Offline
                                ailika
                                wrote on last edited by
                                #14
                                This post is deleted!
                                1 Reply Last reply
                                0
                                • A Offline
                                  A Offline
                                  ailika
                                  wrote on last edited by
                                  #15

                                  @Christian-Ehrlicher Oh, right. How careless of me. I copyed the file deleting operation code and forget to delete the return true.
                                  This is awkward.I thought there is some mechanisam that I don't know...
                                  Thank you very much.

                                  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