Подкласс c ++ qt qabstracttablemodel сбоит при обновлении базового qmap - PullRequest
0 голосов
/ 15 января 2012

У меня большие проблемы с обновлением пользовательской модели qabstracttablemodel.Я хочу иметь табличное представление, которое показывает цены нескольких акций.я получаю цены с локального сервера, которым я управляю.эта настройка предназначена для тестирования.информация о ценах получена в рабочем потоке.

Я подклассифицировал qabstracttablemodel следующим образом:

PriceModel.h:

class PriceModel : public QAbstractTableModel {
    Q_OBJECT
public:
    PriceModel( QObject* parent = 0 );

    void setPriceMap( const QMap<QString, ITick*> &curTickMap );
    int rowCount( const QModelIndex &parent ) const;
    int columnCount( const QModelIndex &parent ) const;
    QVariant data( const QModelIndex &index, int role ) const;
    QVariant headerData( int section, Qt::Orientation orientation, int role ) const;
private:
    QMap<QString, ITick*> currentTicks;
    QString stockAt( int offset ) const;
};

PriceModel.cpp

#include "PriceModel.h"

PriceModel::PriceModel( QObject* parent ) : QAbstractTableModel( parent ) {
}

int PriceModel::rowCount( const QModelIndex& parent ) const {
    return this->currentTicks.count();
}

int PriceModel::columnCount( const QModelIndex& parent ) const {
    return 4;
}

QString PriceModel::stockAt( int offset ) const {
    return ( currentTicks.begin() + offset ).key();
}

QVariant PriceModel::data( const QModelIndex& index, int role ) const {
    if ( !index.isValid() ) {
        return QVariant();
    }
    if ( role == Qt::TextAlignmentRole ) {
        return int( Qt::AlignRight | Qt::AlignVCenter );
    } else if ( role == Qt::DisplayRole ) {
        QString stock = stockAt( index.row() );
        int i = index.column();
        switch ( i ) {
            case 0 : return currentTicks.value( instrument )->getTime().toString( "hh:mm:ss:zzz" );
            case 1 : return currentTicks.value( instrument )->getBid();
            case 2 : return currentTicks.value( instrument )->getAsk();
            case 3 : return currentTicks.value( instrument )->getBidVolume();
            case 4 : return currentTicks.value( instrument )->getAskVolume();
        }
    }
    return QVariant();
}

QVariant PriceModel::headerData( int section, Qt::Orientation orientation, int role )  const {
    if ( role != Qt::DisplayRole ) {
        return QVariant();
    }
    if ( orientation == Qt::Horizontal ) {
        switch ( section ) {
            case 0 : return QString( "Time" );
            case 1 : return QString( "Bid" );
            case 2 : return QString( "Ask" );
            case 3 : return QString( "Bid Volume" );
            case 4 : return QString( "Ask Volume" );
        }
    } else {
        return instrumentAt( section )->getCurrencyPairWithDelimiter();
    }
    return QVariant();
}

void PriceModel::setTickMap( const QMap<QString,ITick*>& curTickMap ) {
    beginResetModel();
    this->currentTicks = curTickMap;
    endResetModel();
}

модель заполняет табличное представление, когда я вызываю метод setTickMap (qmap <...>), и все различные акции отображаются так, как и ожидалось.(инициализация данных в моей модели работает нормально)

проблема возникает, когда я хочу снова вызвать метод setTickMap (qmap <...>).происходит сбой приложения, и я не понимаю, почему я не получаю значительного сообщения об ошибке, а именно - segvault.

при сбое в конфигурации отладки netbeans открывает вкладку «Disassemlby» со следующим содержимым:

QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+50: add    %ebx,%r15d
QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+85: testb $0x4,0x20(%rax)
QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+89: jne 0x7ffff63f4df8 <QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+536>
QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+102: add    0x6c(%rsp),%ebx
QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+118: mov    %ebx,0x2c(%rsp)
QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+106: movq   $0x0,0x40(%rsp)
QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+95: mov    0x31c19a(%rip),%rdx        # 0x7ffff6710de0
QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+115: mov    (%rdx),%rax
QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+122: test   %rax,%rax
QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+125: je     0x7ffff63f4c72 <QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+146>
QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+127: lea    0x40(%rsp),%rdx
QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+132: test   %r13,%r13
QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+135: mov    %ebx,%esi
QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+137: mov    %r12,%rdi
QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+140: cmovne %r13,%rdx
QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+144: callq  *%rax

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

эта модель не должна редактироваться пользователем через графический интерфейс, и я в курсечто я мог бы использовать tablewidget, чтобы просто отобразить данные, но я не уверен, будет ли другое представление, которое поделится информацией об этой модели.карта с текущими ценами не будет очень большой (25 предметов), поэтому мне не неудобно сбрасывать модель при каждой новой цене.

заранее спасибо, и я надеюсь, что кто-то может мне помочьс этим микропором

Ответы [ 2 ]

0 голосов
/ 16 января 2012

Ух ты, моя глупость не знает границ ...

Я исправил проблему, и она не имела ничего общего с самой тикмоделью. Приведенные примеры кодов работают просто отлично. Я был явно слишком глуп, чтобы убедиться, что используется правильный указатель модели.

Этого достаточно:

void PriceModel::setTickMap( const QMap<QString,ITick*>& curTickMap ) {
    this->currentTicks = curTickMap;
    reset();
}
0 голосов
/ 16 января 2012

Учитывая, что вы отображаете тикданные в реальном времени, я бы порекомендовал приблизиться к хранилищу данных. Поскольку вы отображаете только 5 элементов из этого тика, возможно, вы захотите рассмотреть что-то другое, тогда QMap может быть массивом, поскольку ваша вселенная может быть достаточно стандартизирована в течение торгового дня.

Также я должен был бы предположить, что код является многопоточным, и curTickMap может измениться во время setTickMap, так как вполне вероятно, что вы не выполняете сброс модели на каждом тике.

И как указал webclectic, код, который вы разместили, вряд ли скомпилируется.

...