2016-12-06 11 views
0

Я создал прокси-модель, подобную mixin (Qt5), которая просто добавляет дополнительный первый столбец в другую прокси-модель для добавления QToolBar действий в каждую строку вид таблицы (например, кнопка «удалить»). Модель просто предоставляет способ заполнения QList<QVariant> для первого столбца. Делегат должен знать, что означает каждый из QVariant (обычно int s/enum s идентифицирующие действия), и заполняют QToolBar соответственно. В качестве последней функции, если нет действий, дополнительный столбец не добавляется (в этом случае он ведет себя как QIdentityProxyModel). После добавления действия не могут быть удалены. Это особенность еще на один день.Специализация QAbstractProxyModel для добавления столбца: ячейки таблицы становятся пустыми

Проблема сегодня в том, что когда я вставляю действия (которые я делаю перед установкой модели в представление), ячейки - все пробелы. Таким образом, я делаю что-то неправильно с сигналами или кто знает, с чем (я думаю, что ошибка в функции 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 в качестве имени столбца.

Что я делаю неправильно?

+0

Может быть недостающим 'mapToSource()' , Код в 'columnCount()' также не идеален, вы полагаетесь на 'true', равным 1, а не на любое другое ненулевое значение. –

+0

. Комментарий к« mapToSource »комментируется для сокращения вопроса, чуть ниже' mapFromSource' (потому что они практически идентичны). По той же причине «columnCount» сокращается. В моем коде я использую 'if' без этого преобразования. Во всяком случае, 'emtpy' возвращает' bool', а стандарт гарантирует, что логическое значение 'false' приводится к' 0' 'int' и' 1' для 'true'. Итак, я считаю, что код правильный, стандартно-совместимый и так далее. Во всяком случае, проблема должна быть где-то в другом месте. –

+0

Хм, конечно, мне просто хотелось добавить логическое целое число. –

ответ

0

Проблема в вашем методе data().

  1. Вы не сравнивайте role к Qt::DisplayRole присваиваемое роли
  2. Если у вас есть действия, вы либо вернуть запись действий или QVariant(), никогда никаких данных