首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >通过布尔变量扩展QFileSystemModel

通过布尔变量扩展QFileSystemModel
EN

Stack Overflow用户
提问于 2018-05-02 18:20:59
回答 1查看 173关注 0票数 1

我想扩展QFileSystemModel。我想有一个自定义的角色IsSelectedRole,我可以存储是否一个布尔值,存储是否一个文件被选择在一个QML TreeView。更确切地说,我不知道如何设置我的QFileSystemModel派生类的setDatadata函数,比如在哪里存储数据。我想创建我自己的bool变量树应该是可行的,但我希望有一种更简单的方法。

EN

回答 1

Stack Overflow用户

发布于 2018-05-03 02:50:21

Qt已经有了一个存储条目选择的模型:QItemSelectionModel。小部件视图和QML视图都使用此模型。剩下的工作就是在视图模型中将来自该模型的数据覆盖在来自QFileSystemModel的数据之上。

你绝对不应该从QFileSystemModel派生。视图模型只维护单个视图的状态,并且应该是一个代理,它将您的角色覆盖在底层模型的顶部。

代理不需要假设任何关于底层模型的东西,并且可以在任何模型上工作,而不仅仅是QFileSystemModel

例如:

代码语言:javascript
复制
// https://github.com/KubaO/stackoverflown/tree/master/questions/filesystem-model-select-50132273
#include <QtWidgets>
#include <algorithm>

class SelectionProxy : public QIdentityProxyModel {
   Q_OBJECT
   Q_PROPERTY(QItemSelectionModel* selectionModel
              READ selectionModel WRITE setSelectionModel NOTIFY selectionModelChanged)
   Q_PROPERTY(QVector<int> roles READ roles WRITE setRoles)
   using self_t = SelectionProxy;
   using base_t = QIdentityProxyModel;
   using model_t = QItemSelectionModel;
   QPointer<QItemSelectionModel> m_model;
   QVector<QMetaObject::Connection> m_modelConnections;
   QVector<int> m_roles{IsSelectedRole};
   QModelIndex topLeft() const {
      return sourceModel()->index(0, 0);
   }
   QModelIndex bottomRight() const {
      return sourceModel()->index(sourceModel()->rowCount()-1, sourceModel()->columnCount()-1);
   }
   void onSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected) {
      auto sel = selected;
      sel.merge(deselected, QItemSelectionModel::Select);
      for (auto &range : qAsConst(sel)) {
         auto topLeft = mapFromSource(range.topLeft());
         auto bottomRight = mapFromSource(range.bottomRight());
         emit dataChanged(topLeft, bottomRight, m_roles);
      }
   }
   void onModelChanged(QAbstractItemModel *model) {
      setSourceModel(model);
   }
   bool check(const QModelIndex &index, int role) const {
      return index.isValid() && m_model && m_roles.contains(role);
   }
public:
   static constexpr int IsSelectedRole = Qt::UserRole + 44;
   SelectionProxy(QObject *parent = {}) : QIdentityProxyModel(parent) {}
   QItemSelectionModel *selectionModel() const { return m_model; }
   virtual void setSelectionModel(QItemSelectionModel *model) {
      if (model == m_model) return;
      for (auto &conn : m_modelConnections)
         disconnect(conn);
      m_model = model;
      m_modelConnections = {
         connect(m_model, &model_t::selectionChanged, this, &self_t::onSelectionChanged),
         connect(m_model, &model_t::modelChanged, this, &self_t::onModelChanged) };
      setSourceModel(model->model());
      emit selectionModelChanged(m_model);
   }
   Q_SIGNAL void selectionModelChanged(QItemSelectionModel *);
   QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override {
      if (!check(index, role))
         return base_t::data(index, role);
      return m_model->isSelected(mapToSource(index));
   }
   bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override {
      if (!check(index, role))
         return base_t::setData(index, value, role);
      using Sel = QItemSelectionModel;
      m_model->select(mapToSource(index), value.toBool() ? Sel::SelectCurrent : (Sel::Deselect | Sel::Current));
      return true;
   }
   QVector<int> roles() const { return m_roles; }
   void setRoles(QVector<int> roles) {
      std::sort(roles.begin(), roles.end());
      if (roles == m_roles)
         return;
      std::swap(roles, m_roles);
      if (!m_model)
         return;
      QVector<int> allRoles;
      std::merge(roles.begin(), roles.end(), m_roles.begin(), m_roles.end(), std::back_inserter(allRoles));
      emit dataChanged(topLeft(), bottomRight(), allRoles);
   }
   void setRole(int role) {
      setRoles({role});
   }
};

#include "main.moc"

一个简单的演示程序设置了文件系统模型的两个视图;底部视图显示true/false,表示第一个视图的选择状态。

代码语言:javascript
复制
int main(int argc, char **argv) {
   QApplication app{argc, argv};
   QWidget win;
   QVBoxLayout layout{&win};
   QTreeView left, right;
   layout.addWidget(&left);
   layout.addWidget(&right);

   QFileSystemModel model;
   SelectionProxy selProxy;
   model.setRootPath(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
   auto rootPathIndex = model.index(model.rootPath());
   left.setModel(&model);
   left.setSelectionMode(QAbstractItemView::MultiSelection);
   left.setRootIndex(rootPathIndex);
   selProxy.setRole(Qt::DisplayRole);
   selProxy.setSelectionModel(left.selectionModel());
   right.setModel(&selProxy);
   right.setRootIndex(selProxy.mapFromSource(rootPathIndex));
   for (int col : {1,2,3})
      right.hideColumn(col);

   win.show();
   return app.exec();
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50132273

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档