Reputation:
I can't narrow down this bug, however I seem to have the following problem:
saveState()
of a horizontalHeader()
restoreState()
I know, this is not very descriptive but I'm hoping others have had this problem before.
Upvotes: 3
Views: 3537
Reputation:
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
};
Upvotes: 1
Reputation: 1997
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.
Upvotes: -1
Reputation: 25690
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:
Upvotes: 2
Reputation: 25313
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.
Upvotes: 1
Reputation: 27593
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.
Upvotes: 0