QTableView和horizo​​ntalHeader()->restoreState()

发布于 2024-07-28 23:24:31 字数 306 浏览 6 评论 0原文

我无法缩小此错误的范围,但是我似乎遇到以下问题:

  • horizo​​ntalHeader() 的 saveState()
  • 重新启动应用程序
  • 修改模型,使其少一列
  • restoreState()
  • 现在,由于某种原因, headerview 的状态完全混乱了。 我无法显示或隐藏任何新列,也无法得到合理的状态,

我知道,这不是很有描述性,但我希望其他人以前也遇到过这个问题。

I can't narrow down this bug, however I seem to have the following problem:

  • saveState() of a horizontalHeader()
  • restart app
  • modify model so that it has one less column
  • restoreState()
  • Now, for some reason, the state of the headerview is totally messed up. I cannot show or hide any new columns, nor can I ever get a reasonable state back

I know, this is not very descriptive but I'm hoping others have had this problem before.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

锦欢 2024-08-04 23:24:31

对于 QMainWindow,save/restoreState 采用版本号。 QTableView的restoreState()没有,所以你需要管理这种情况你自己。

如果您想要在模型不匹配的情况下恢复状态,您可以选择以下选项:

  • 将状态与保存时模型中存在的列的列表一起存储,这样您就可以避免在列不匹配时从数据中恢复不匹配,并恢复为默认情况
  • 实现您自己的 save/restoreState 函数来处理这种情况(呃)
  • 添加一个代理模型,为正在恢复的状态提供虚假/虚拟列,然后立即删除这些列。

For QMainWindow, the save/restoreState takes a version number. QTableView's restoreState() does not, so you need to manage this case yourself.

If you want to restore state even if the model doesn't match, you have these options:

  • Store the state together with a list of the columns that existed in the model upon save, so you can avoid restoring from the data if the columns don't match, and revert to defualt case
  • Implement your own save/restoreState functions that handle that case (ugh)
  • Add a proxy model that has provides bogus/dummy columns for state that is being restored, then remove those columns just afterwards.
披肩女神 2024-08-04 23:24:31

我个人从来没有在任何 Qt 小部件中使用 saveState()/restoreState() ,因为它们只是返回一个二进制 blob。 我希望我的配置文件是人类可读的,具有简单的类型。 这也摆脱了此类问题。

此外,QHeaderView还有一个顽皮的问题,即restoreState()(或等效方法)仅在模型已经设置后才对我有用,然后一段时间。 我最终连接到 QHeaderView::sectionCountChanged() 信号并在从它调用的槽中设置状态。

I personally never use saveState()/restoreState() in any Qt widget, since they just return a binary blob anyway. I want my config files to be human-readable, with simple types. That also gets rid of these kind of problems.

In addition, QHeaderView has the naughty problem that restoreState() (or equivalents) only ever worked for me when the model has already been set, and then some time. I ended up connecting to the QHeaderView::sectionCountChanged() signal and setting the state in the slot called from it.

撩人痒 2024-08-04 23:24:31

这是我使用 Boost Serialization 制作的解决方案。

它或多或少地处理新的和删除的列。 适用于我的用例。

  // Because QHeaderView sucks
  struct QHeaderViewState
  {
    explicit QHeaderViewState(ssci::CustomTreeView const & view):
      m_headers(view.header()->count())
    {
      QHeaderView const & headers(*view.header());
      // Stored in *visual index* order
      for(int vi = 0; vi < headers.count();++vi)
      {
        int           li     = headers.logicalIndex(vi);
        HeaderState & header = m_headers[vi];

        header.hidden               = headers.isSectionHidden(li);
        header.size                 = headers.sectionSize(li);
        header.logical_index        = li;
        header.visual_index         = vi;
        header.name                 = view.model()->headerData(li,Qt::Horizontal).toString();
        header.view                 = &view;
      }
      m_sort_indicator_shown   = headers.isSortIndicatorShown();
      if(m_sort_indicator_shown)
      {
        m_sort_indicator_section = headers.sortIndicatorSection();
        m_sort_order             = headers.sortIndicatorOrder();
      }
    }

    QHeaderViewState(){}

    template<typename Archive>
    void serialize(Archive & ar, unsigned int)
    {
      ar & m_headers;
      ar & m_sort_indicator_shown;
      if(m_sort_indicator_shown)
      {
        ar & m_sort_indicator_section;
        ar & m_sort_order;
      }
    }

    void
    restoreState(ssci::CustomTreeView & view) const
    {
      QHeaderView & headers(*view.header());

      const int max_columns = std::min(headers.count(),
                                       static_cast<int>(m_headers.size()));      

      std::vector<HeaderState> header_state(m_headers);
      std::map<QString,HeaderState *> map;
      for(std::size_t ii = 0; ii < header_state.size(); ++ii)
        map[header_state[ii].name] = &header_state[ii];

      // First set all sections to be hidden and update logical
      // indexes
      for(int li = 0; li < headers.count(); ++li)
      {
        headers.setSectionHidden(li,true);
        std::map<QString,HeaderState *>::iterator it =
          map.find(view.model()->headerData(li,Qt::Horizontal).toString());
        if(it != map.end())
          it->second->logical_index = li;
      }

      // Now restore
      for(int vi = 0; vi < max_columns; ++vi)
      {
        HeaderState const & header = header_state[vi];
        const int li = header.logical_index;
        SSCI_ASSERT_BUG(vi == header.visual_index);
        headers.setSectionHidden(li,header.hidden);
        headers.resizeSection(li,header.size);
        headers.moveSection(headers.visualIndex(li),vi);
      }
      if(m_sort_indicator_shown)
        headers.setSortIndicator(m_sort_indicator_section,
                                 m_sort_order);
    }

    struct HeaderState
    {
      initialize<bool,false>  hidden;
      initialize<int,0>       size;
      initialize<int,0>       logical_index;
      initialize<int,0>       visual_index;
      QString                 name;
      CustomTreeView const  *view;

      HeaderState():view(0){}

      template<typename Archive>
      void serialize(Archive & ar, unsigned int)
      {
        ar & hidden & size & logical_index & visual_index & name;
      }
    };

    std::vector<HeaderState> m_headers;
    bool                     m_sort_indicator_shown;
    int                      m_sort_indicator_section;
    Qt::SortOrder            m_sort_order; // iff m_sort_indicator_shown
  };

Here is the solution I made using Boost Serialization.

It handles new and removed columns, more or less. Works for my use cases.

  // Because QHeaderView sucks
  struct QHeaderViewState
  {
    explicit QHeaderViewState(ssci::CustomTreeView const & view):
      m_headers(view.header()->count())
    {
      QHeaderView const & headers(*view.header());
      // Stored in *visual index* order
      for(int vi = 0; vi < headers.count();++vi)
      {
        int           li     = headers.logicalIndex(vi);
        HeaderState & header = m_headers[vi];

        header.hidden               = headers.isSectionHidden(li);
        header.size                 = headers.sectionSize(li);
        header.logical_index        = li;
        header.visual_index         = vi;
        header.name                 = view.model()->headerData(li,Qt::Horizontal).toString();
        header.view                 = &view;
      }
      m_sort_indicator_shown   = headers.isSortIndicatorShown();
      if(m_sort_indicator_shown)
      {
        m_sort_indicator_section = headers.sortIndicatorSection();
        m_sort_order             = headers.sortIndicatorOrder();
      }
    }

    QHeaderViewState(){}

    template<typename Archive>
    void serialize(Archive & ar, unsigned int)
    {
      ar & m_headers;
      ar & m_sort_indicator_shown;
      if(m_sort_indicator_shown)
      {
        ar & m_sort_indicator_section;
        ar & m_sort_order;
      }
    }

    void
    restoreState(ssci::CustomTreeView & view) const
    {
      QHeaderView & headers(*view.header());

      const int max_columns = std::min(headers.count(),
                                       static_cast<int>(m_headers.size()));      

      std::vector<HeaderState> header_state(m_headers);
      std::map<QString,HeaderState *> map;
      for(std::size_t ii = 0; ii < header_state.size(); ++ii)
        map[header_state[ii].name] = &header_state[ii];

      // First set all sections to be hidden and update logical
      // indexes
      for(int li = 0; li < headers.count(); ++li)
      {
        headers.setSectionHidden(li,true);
        std::map<QString,HeaderState *>::iterator it =
          map.find(view.model()->headerData(li,Qt::Horizontal).toString());
        if(it != map.end())
          it->second->logical_index = li;
      }

      // Now restore
      for(int vi = 0; vi < max_columns; ++vi)
      {
        HeaderState const & header = header_state[vi];
        const int li = header.logical_index;
        SSCI_ASSERT_BUG(vi == header.visual_index);
        headers.setSectionHidden(li,header.hidden);
        headers.resizeSection(li,header.size);
        headers.moveSection(headers.visualIndex(li),vi);
      }
      if(m_sort_indicator_shown)
        headers.setSortIndicator(m_sort_indicator_section,
                                 m_sort_order);
    }

    struct HeaderState
    {
      initialize<bool,false>  hidden;
      initialize<int,0>       size;
      initialize<int,0>       logical_index;
      initialize<int,0>       visual_index;
      QString                 name;
      CustomTreeView const  *view;

      HeaderState():view(0){}

      template<typename Archive>
      void serialize(Archive & ar, unsigned int)
      {
        ar & hidden & size & logical_index & visual_index & name;
      }
    };

    std::vector<HeaderState> m_headers;
    bool                     m_sort_indicator_shown;
    int                      m_sort_indicator_section;
    Qt::SortOrder            m_sort_order; // iff m_sort_indicator_shown
  };
各空 2024-08-04 23:24:31

如果你改变模型,我预计它会损坏! 这些函数直接保存和恢复私有类成员变量,无需任何健全性检查。 尝试恢复状态然后更改模型。

I would expect it to break if you change the model! Those functions save and restore private class member variables directly without any sanity checks. Try restoring the state and then changing the model.

晨曦慕雪 2024-08-04 23:24:31

在遇到同样的问题后,我正在尝试修复 Qt 5.6.2 的这个问题。 看
此链接为正在审核中的 Qt 补丁,这使得 RestoreState() 能够处理以下情况:保存状态下的节(例如列)与当前视图中的节数不匹配。

I'm attempting to fix this issue for Qt 5.6.2, after hitting the same issue. See
this link for a Qt patch under review, which makes restoreState() handle the case where the number of sections (e.g. columns) in the saved state does not match the number of sections in the current view.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文