Ich habe ein Mixin-ähnliches Proxy-Modell (Qt5) erstellt, das nur eine zusätzliche erste Spalte zu einem anderen Proxy-Modell hinzufügt, um eine QToolBar
von Aktionen zu jeder Zeile hinzuzufügen die Tabellenansicht (z. B. eine Schaltfläche "Löschen"). Das Modell bietet nur eine Möglichkeit, einen QList<QVariant>
für die erste Spalte zu füllen. Der Delegierte muss wissen, was die Bedeutung der einzelnen QVariant
(in der Regel int
s/enum
s identifiziert Aktionen), und füllen Sie die QToolBar
entsprechend. Wenn keine Aktionen vorhanden sind, wird als letzte Funktion keine zusätzliche Spalte hinzugefügt (sie verhält sich in diesem Fall wie eine QIdentityProxyModel
). Einmal hinzugefügt, können Aktionen nicht entfernt werden. Das ist ein Feature für einen anderen Tag.Spezialisiert ein QAbstractProxyModel zum Hinzufügen einer Spalte: Die Tabellenzellen werden leer
Das Problem von heute ist, dass, wenn ich Aktionen einfügen (was ich tun, bevor Sie das Modell auf die Ansicht einstellen), die Zellen sind alle Leerzeichen. Also, ich bin etwas falsch mit den Signalen zu tun oder wer weiß, was (ich glaube, der Fehler in der add_action
Funktion ist, am Ende des Snippets):
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 });
}
};
Ohne Einstellung Aktionen arbeitet das Modell fein sowohl mit QAbstractIdentityProxyModel
als auch QSortFilterProxyModel
als proxy_model
. Beim Einstellen von Aktionen werden in der Ansicht jedoch alle Zellen leer angezeigt, und zwar sowohl mit QSortFilterProxyModel
als auch mit QAbstractIdentityProxyModel
.
Hier ist ein benutzer Land Code:
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();
Die Delegierten sind kein Problem, weil ich niemand gesetzt haben. Ich erwarte eine erste Spalte mit weißen Zellen, aber ich bekomme einen ganz weißen Tisch. Die Spaltennamen werden gut angezeigt, mit Ausnahme des letzten, der nur 0
als Spaltenname ausgibt.
Was mache ich falsch?
Vielleicht 'das fehlende' mapToSource() . Der Code in 'columnCount()' ist auch nicht ideal, man verlässt sich darauf, dass 'true' 1 ist und kein anderer Wert ungleich null –
Die' mapToSource' ist kommentiert, um die Frage zu verkürzen, direkt unter 'mapFromSource' (weil sie sind praktisch identisch). Der 'columnCount' ist aus dem gleichen Grund verkürzt. In meinem Code verwende ich ein 'if' ohne diese Konvertierung. Wie auch immer, 'emtpy' gibt einen' bool' zurück, und der Standard stellt sicher, dass ein 'false' boolescher Wert in' 0' 'int' umgewandelt wird, und' 1' für 'true'. Also, ich denke, dass der Code korrekt ist, standardkonform und so weiter. Das Problem muss irgendwo anders sein. –
Hmm, sicher, ich dachte nur, dass es seltsam ist, einen Boolean zu einer Ganzzahl hinzuzufügen. –