Я создал прокси-модель, подобную миксину (Qt5), которая просто добавляет дополнительный первый столбец в другую прокси-модель для добавления QToolBar
действий в каждую строку табличного представления (например, кнопку «удалить»). Модель просто обеспечивает способ заполнения QList<QVariant>
для первого столбца. Делегат должен знать, что означает каждое QVariant
(обычно int
s/enum
s идентифицирующих действия), и соответственно заполнить QToolBar
. В качестве последней функции, если нет действий, дополнительный столбец не добавляется (в этом случае он ведет себя как QIdentityProxyModel
). После добавления действия нельзя удалить. Это функция для другого дня.
Сегодняшняя проблема заключается в том, что когда я вставляю действия (что я делаю перед установкой модели в представление), все ячейки остаются пустыми. Итак, я что-то делаю не так с сигналами или черт знает с чем (думаю, ошибка в функции add_action
, в конце фрагмента):
template<class proxy_model>
class action_model : public proxy_model
{
QList<QVariant> l_actions;
public:
using base_t = proxy_model;
using base_t::base_t; // Inheriting constructors.
QModelIndex mapFromSource(const QModelIndex& source_idx) const override
{
if (!l_actions.empty() and source_idx.isValid())
return this->createIndex(source_idx.row(),
source_idx.column() + 1);
else // identity proxy case
return base_t::mapFromSource(source_idx);
} // same for mapToSource but with - 1 instead of + 1.
int columnCount(const QModelIndex& parent = QModelIndex()) const override
{ return this->base_t::columnCount() + !l_actions.empty(); }
QVariant headerData(int section, Qt::Orientation orientation, int role) const override
{
if (!l_actions.empty()) {
if (orientation == Qt::Horizontal and section == 0
and role == Qt::DisplayRole)
return "Actions"; // Testing.
else
return base_t::headerData(section - 1, orientation, role);
} else // identity proxy case
return base_t::headerData(section, orientation, role);
}
QVariant data(const QModelIndex& idx, int role) const override
{
if (!l_actions.empty()) {
if (idx.column() == 0 and role = Qt::DisplayRole)
return l_actions; // All the actions for drawing.
else
return QVariant();
} else // identity proxy case
return base_t::data(idx, role);
}
Qt::ItemFlags flags(QModelIndex const& idx) const
{
if (!l_actions.empty() and idx.column() == 0)
return Qt::NoItemFlags; // No editable or selectable
else
return base_t::flags(idx);
}
// And here, I think, is where the fun starts:
// The action could be added before or after the sourceModel
// is set or this model is connected to a view, but I don't
// how that cases are supposed to be managed.
void add_action(QVariant const& action)
{
bool was_empty = l_actions.empty();
l_actions << action;
if (was_empty and !this->insertColumns(0, 1))
throw std::logic_error("Something went wrong");
Q_EMIT this->dataChanged
(this->createIndex(0, 0),
this->createIndex(this->rowCount(), 0),
{ Qt::DisplayRole });
}
};
Без настройки действий модель работает нормально, как с QAbstractIdentityProxyModel
, так и с QSortFilterProxyModel
как proxy_model
. Но при настройке действий представление показывает каждую пустую ячейку, как с QSortFilterProxyModel
, так и с QAbstractIdentityProxyModel
.
Вот код пользователя:
enum sql_action { DELETE };
auto* table_model = /* My QSqlTableModel */;
auto* view_model = new action_model<QIdentityProxyModel>(my_parent);
auto* table_view = new QTableView;
view_model->add_action(static_cast<int>(sql_action::DELETE));
view_model->setSourceModel(table_model);
table_view->setModel(view_model);
table_view->setSortingEnabled(true);
table_view->setAlternatingRowColors(true);
// The last column is printed in white, not with alternate colors.
table_view->show();
table_model->select();
Делегаты не проблема, потому что я никого не назначал. Я ожидаю первый столбец с белыми ячейками, но получаю полностью белую таблицу. Имена столбцов отображаются нормально, за исключением последнего, который печатает только 0
в качестве имени столбца.
Что я делаю не так?
mapToSource()
. Код вcolumnCount()
также не идеален, вы полагаетесь на то, чтоtrue
равно 1, а не какое-либо другое ненулевое значение. - person Kevin Krammer   schedule 06.12.2016mapToSource
закомментирован для сокращения вопроса, чуть нижеmapFromSource
(поскольку они практически идентичны).columnCount
укорачивается по той же причине. В моем коде я используюif
без этого преобразования. В любом случае,emtpy
возвращаетbool
, а стандарт гарантирует, что логическое значениеfalse
приводится к0
int
, а1
кtrue
. Итак, я думаю, что код правильный, соответствует стандарту и так далее. В любом случае проблема должна быть где-то в другом. - person Peregring-lk   schedule 06.12.2016