2016-12-06 3 views
0

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?

+0

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 –

+0

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. –

+0

Hmm, sicher, ich dachte nur, dass es seltsam ist, einen Boolean zu einer Ganzzahl hinzuzufügen. –

Antwort

0

Das Problem ist in Ihrer data() Methode.

  1. Sie vergleichen nicht role zu Qt::DisplayRole Sie Rolle zuweisen
  2. Wenn Sie Aktionen, Sie entweder zurückgeben die Aktion Eintrag oder QVariant(), nie irgendwelche Daten
Verwandte Themen