2014-09-26 2 views
1

У меня возникла проблема правильно транспонировать таблицу, которую я получаю из db. Я пошел по пути, найденному here, и оказался в подклассе QAbstractProxyModel - как описано here. к сожалению, она не в полной мере работать, вот где проблема:Переключение заголовков в QSqlQueryModel (таблица транспонирования)

Что у меня есть:

X | A | B 
---------- 
1 | A1 | B1 
2 | A2 | B2 

Что я хочу:

X | 1 | 2 
---------- 
A | A1 | A2 
B | B1 | B2 

Что я получаю:

X | 1 | 1 
---------- 
A | A1 | A2 
A | B1 | B2 

Итак, как вы можете видеть, данные правильно транспонированы, но заголовки плохие ... И мне действительно нужно эм :(

Я попытался вручную установить данные заголовка, но это также не удалось:

origModel = new QSqlQueryModel; // set query and so on 
transposedModel = new TransposeProxyModel; 
transposedModel->setSourceModel(origModel); 
for (int i = 0; i < origModel->columnCount(); i++) { 
    qDebug() << "origModel->Qt::Horizontal(" << i << ")" << origModel->headerData(i, Qt::Horizontal, Qt::DisplayRole); 
    //transposedModel->setHeaderData(i, Qt::Vertical, origModel->headerData(i, Qt::Horizontal, Qt::DisplayRole), Qt::DisplayRole); //#try1 
    transposedModel->setHeaderData(i, Qt::Vertical, QVariant("abc"), Qt::DisplayRole); // #try2 
} 

Независимо от того, если я пытаюсь # 1 или # 2 - звоните в setHeaderData оценивает в ложь ...

Любые идеи?

фиксируется как @ Vinícius Gobbo А. де Оливейра указал

+1

Это уже поздняя ночь здесь ... но если я правильно посмотрю, что вы хотите и что получаете, это то же самое. Может быть, вы хотите проверить это, D –

+0

Да - я ошибся, что я на самом деле достиг. проблема в том, что я получаю один и тот же заголовок во всех столбцах (из первого столбца) и одинаковый во всех строках (из первой строки). И я не могу его изменить - даже вручную ... – murison

+0

Эй, ссылка в вашем посте, к сожалению, мертва, можете ли вы опубликовать полный рабочий код для справок в будущем? –

ответ

4

Ну, если вы использовали пример кода вы связаны, вы должны переопределить определение по умолчанию для метода headerData класса TransposeProxyModel, так же, как это:

QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const { 
    return sourceModel()->headerData(section, (orientation == Qt::Horizontal ? Qt::Vertical : Qt::Horizontal), role); 
} 

Забудьте о методах setHeaderData и setData: вам нужна прокси-модель, которая полагается на исходную!

Что ж, не знаете точно, что не так, какой выпуск Qt вы используете? Попробуйте этот код, он отлично работает здесь:

#include <QtCore> 
#include <QtWidgets> 

class TransposeProxyModel: public QAbstractProxyModel { 
public: 
    TransposeProxyModel(QObject *p = 0): 
     QAbstractProxyModel(p) 
    { 
    } 
    QModelIndex mapFromSource (const QModelIndex & sourceIndex) const{ 
     return index(sourceIndex.column(), sourceIndex.row()); 
    } 
    QModelIndex mapToSource (const QModelIndex & proxyIndex) const{ 
     return sourceModel()->index(proxyIndex.column(), proxyIndex.row()); 
    } 
    QModelIndex index(int r, int c, const QModelIndex &ind=QModelIndex()) const{ 
     return createIndex(r,c); 
    } 
    QModelIndex parent(const QModelIndex&) const { 
     return QModelIndex(); 
    } 
    int rowCount(const QModelIndex &) const{ 
     return sourceModel()->columnCount(); 
    } 
    int columnCount(const QModelIndex &) const{ 
     return sourceModel()->rowCount(); 
    } 
    QVariant data(const QModelIndex &ind, int role) const { 
     return sourceModel()->data(mapToSource(ind), role); 
    } 
    QVariant headerData(int section, Qt::Orientation orientation, 
     int role = Qt::DisplayRole) const { 
     return sourceModel()->headerData(section, 
      (orientation == Qt::Horizontal ? Qt::Vertical : Qt::Horizontal), 
      role); 
    } 
}; 

int main(int argc, char *argv[]) 
{ 
    QApplication a(argc, argv); 
    QStandardItemModel model(3,3); 
    model.setData(model.index(0,0), "1"); 
    model.setData(model.index(0,1), "2"); 
    model.setData(model.index(0,2), "3"); 
    model.setData(model.index(1,0), "4"); 
    model.setData(model.index(1,1), "5"); 
    model.setData(model.index(1,2), "6"); 
    model.setData(model.index(2,0), "7"); 
    model.setData(model.index(2,1), "8"); 
    model.setData(model.index(2,2), "9"); 
    model.setHeaderData(0, Qt::Horizontal, "a"); 
    model.setHeaderData(1, Qt::Horizontal, "b"); 
    model.setHeaderData(2, Qt::Horizontal, "c"); 
    TransposeProxyModel trans; 
    trans.setSourceModel(&model); 
    QSplitter split; 
    QTableView *t1 = new QTableView(&split); 
    t1->setModel(&model); 
    QTableView *t2 = new QTableView(&split); 
    t2->setModel(&trans); 
    split.show(); 
    return a.exec(); 
} 

Большая часть кода пришли по ссылке вы предоставили, я просто написал метод headerData.

+0

Я пробовал это сделать (написал одинаковый код) - не помогло. Я положил brakepoint внутрь - он никогда не срабатывает. – murison

+0

Боже мой Я идиот ... Мой код был ПОЧТИ одинаковым ... Я пропустил 'const' в объявлении функции ... – murison

+0

Рад, что это сработало! ;) – Albert

0

Забавная вещь, хотя - doc утверждает, что это виртуальный метод:

виртуальный QVariant headerData (интермедиат раздел, Qt :: ориентирование ориентация, ИНТ роль) Const

(...)

QVariant QAbstractProxyModel :: headerData (Int раздел, Qt :: Ориентация ориентации, Int роль) Const [виртуальный]

Реализовано из QAbstractItemModel :: headerData().

, но в реальной headerthe virtual ключевое слово отсутствует:

C: \ Qt \ Qt5.2.1 \ 5.2.1 \ msvc2010 \ включать \ QtCore \ QAbstractProxyModel.ч

(...) 
QVariant data(const QModelIndex &proxyIndex, int role = Qt::DisplayRole) const; //line76 
QVariant headerData(int section, Qt::Orientation orientation, int role) const; //line77 

Я проверил в обычном Qt директории и также отсутствует:

C: \ Qt \ Qt5.2.1 \ 5.2.1 \ Src \ qtbase \ SRC \ corelib \ itemmodels \ qabstractproxymodel.h

(...) 
QVariant data(const QModelIndex &proxyIndex, int role = Qt::DisplayRole) const; 
QVariant headerData(int section, Qt::Orientation orientation, int role) const; 

Я сделал тест:

sim = new QStandardItemModel (3,3); 

for (int i = 0; i < 3; i++) { 
    for (int j = 0; j < 3; j++) { 
     sim->setData(sim->index(i,j), QString("%1%2").arg(QChar(j+65), QString().setNum(i+1))); 
     if (i==0) 
      sim->setHeaderData(j, Qt::Horizontal, QChar(j+65)); 
    } 
    sim->setHeaderData(i, Qt::Vertical, i+1); 
} 

transposedModel = new TransposeProxyModel; 
transposedModel->setSourceModel(sim); 

QAbstractItemModel * aim = transposedModel; 
QAbstractProxyModel *apm = transposedModel; 

for (int i = 0; i < apm->rowCount(); i++) { 
    qDebug() << "aim->Qt::Vertical(" << i << ")" << aim->headerData(i, Qt::Vertical, Qt::DisplayRole); 
    qDebug() << "apm->Qt::Vertical(" << i << ")" << apm->headerData(i, Qt::Vertical, Qt::DisplayRole); 
    qDebug() << "transposedModel->Qt::Vertical(" << i << ")" << transposedModel->headerData(i, Qt::Vertical, Qt::DisplayRole); 
} 

И отладочная:

aim->Qt::Vertical(0) QVariant(int, 1) 
apm->Qt::Vertical(0) QVariant(int, 1) 
[ TransposeProxyModel::headerData ] //qDebug in TransposeProxyModel::headerData 
transposedModel->Qt::Vertical(0) QVariant(QChar, 'A') 
aim->Qt::Vertical(1) QVariant(int, 1) 
apm->Qt::Vertical(1) QVariant(int, 1) 
[ TransposeProxyModel::headerData ] //qDebug in TransposeProxyModel::headerData 
transposedModel->Qt::Vertical(1) QVariant(QChar, 'B') 
aim->Qt::Vertical(2) QVariant(int, 1) 
apm->Qt::Vertical(2) QVariant(int, 1) 
[ TransposeProxyModel::headerData ] //qDebug in TransposeProxyModel::headerData 
transposedModel->Qt::Vertical(2) QVariant(QChar, 'C') 

Так что, я думаю, это проблема - метод не абстрактный, и поэтому он не вызывает мой переопределенный метод. Ошибка Qt? или это специально? Я также взял заглянуть в

C: \ Qt \ Qt5.2.1 \ 5.2.1 \ Src \ qtbase \ SRC \ corelib \ itemmodels \ qabstractproxymodel.cpp

/*! 
    \reimp 
*/ 
QVariant QAbstractProxyModel::headerData(int section, Qt::Orientation orientation, int role) const 
{ 
    Q_D(const QAbstractProxyModel); 
    int sourceSection; 
    if (orientation == Qt::Horizontal) { 
     const QModelIndex proxyIndex = index(0, section); 
     sourceSection = mapToSource(proxyIndex).column(); 
    } else { 
     const QModelIndex proxyIndex = index(section, 0); 
     sourceSection = mapToSource(proxyIndex).row(); 
    } 
    return d->model->headerData(sourceSection, orientation, role); 
} 

Я думаю, он должен получить надлежащий заголовок в любом случае - он называет mapToSource, который является чисто виртуальным, и это должно получить правильный индекс?

+1

В моей настройке виртуальный на месте, из C: \ Qt \ Qt5.2.1 \ 5.2.1 \ msvc2010_opengl \ include \ QtCore \ qabstractitemmodel.h, строки 188-189, это: виртуальный QVariant headerData (int section, Qt :: Ориентационная ориентация, int role = Qt :: DisplayRole) const ... Так прекрасно. – Albert

+0

Я ошибся с именем файла - не могли бы вы проверить qabstractproxymodel.h? – murison

+1

Привет, он не объявлен виртуальным в QAbstractProxyModel, но он находится в QAbstractItemModel, который является его базовым классом, поэтому все в порядке. Didi вы попробуете полный код из моего ответа, я только что проверил здесь с другой настройкой Qt, и все еще работает отлично. Я думаю, у вас есть правильное решение. – Albert