The program will easily break down if I use QSortFilterProxyModel to help sort



  • I have a class ProSIModel inherited form QAbstractTableModel and use QTableView to display. In order to sort the table contents by column, I use QsortFilterProxyModel like this,

        ProSIModel *proModel = new ProSIModel(0);
        QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(this);
        proxyModel->setSourceModel(proModel);
        ui->tableView->setModel(proxyModel);
    

    I actually can sort by column now, but the program will crash after some seconds, and just show this

    **The program has unexpectedly finished.**
    

    I guess it's because I don't write the ProSIModel Method correctly, but I don't know where is wrong, my code like this

    ProSIModel:: ProSIModel(QObject *parent):
        QAbstractTableModel(parent)
    {
        timer = new QTimer(this);
        connect(timer,SIGNAL(timeout()),this,SLOT(timerUpDate()));
        timer->start(3000);
    }
    
    int ProSIModel:: rowCount(const QModelIndex &parent) const
    {
        return proShowInfoList.length();
    }
    
    int ProSIModel:: columnCount(const QModelIndex &parent) const
    {
        return 7;
    }
    
    QVariant ProSIModel:: data(const QModelIndex &index, int role) const
    {
        static int i;
        i++;
    
    
        int row = index.row();
        int col = index.column();
        qDebug() << role;
        switch(role)
        {
        case Qt::DisplayRole:
            switch(col)
            {
            qDebug() << QString("%1").arg(proShowInfoList[row].owner);
            case 0:
                return QString("%1").arg(proShowInfoList[row].pid);
                break;
            case 1:
                return QString("%1").arg(proShowInfoList[row].owner);
                break;
            case 2:
                return QString("%1").arg(proShowInfoList[row].pr);
                break;
            case 3:
                return QString("%1").arg(proShowInfoList[row].ni);
                break;
            case 4:
                return QString("%1").arg(QString::number(proShowInfoList[row].cpuUsage, 'f', 2));
                break;
            case 5:
                return QString("%1").arg(QString::number(proShowInfoList[row].memUsage, 'f', 2));
                break;
            case 6:
                return QString("%1").arg(proShowInfoList[row].cmdName);
                break;
            }
        }
        return QVariant();
    }
    
    QVariant ProSIModel::headerData(int section, Qt::Orientation orientation, int role) const
    {
        if (role == Qt::DisplayRole)
        {
            if (orientation == Qt::Horizontal)
            {
                switch(section)
                {
                case 0:
                    return "PID";
                    break;
                case 1:
                    return "USER";
                    break;
                case 2:
                    return "PR";
                    break;
                case 3:
                    return "NI";
                    break;
                case 4:
                    return "%CPU";
                    break;
                case 5:
                    return "%MEM";
                    break;
                case 6:
                    return "COMMAND";
                    break;
                }
            }
        }
        return QVariant();
    }
    

    Can anyone give me some suggestions. Thanks.



  • what's timerUpDate?

    P.S.

     static int i; //uninitialised!
        i++;
    
    case 0:
                return QString("%1").arg(proShowInfoList[row].pid); // Forcing to QString can only cause damage, just return the value in the native type
                break; // unnecessary after return
    


  • I use slot function timerUpdate to change the the global List proShowInfoList every 3 seconds, ProSIModel::data use the content of proShowInfoList, it's structure like this

    void ProSIModel::timerUpDate()
    {
        proShowInfoList.clear();
        ......
        proShowInfoList.append(...);
        ......
        emit layoutChanged();
    }
    


  • @VRonin Thanks for your advice, I really don't konw I can just return the native type. I know "break" unnecessary in there, I use this just to warn me not forget use "break" if I have no return. And can you give me some advice for what cause my problem easily crahsed.


  • Moderators

    @uuutty You didn't answer @VRonin question: "what's timerUpDate?"



  • @jsulm I give the description in the above, I think full code is unneccessary because I only the proShowInfoList is used in data function.



  • @jsulm I just forget to add @VRonin in my reply


  • Moderators

    @uuutty You wrote: "the program will crash after some seconds". You have a timer with 3 seconds time-out which calls timerUpDate(). Don't you think it could be something there?



  • @jsulm Maybe I didn't describe my question clearly. If I didn't use QSortFilterProxyModel to help sort and just use my own ProSIModel with same timerUpDate function. , the program will be fine.


  • Moderators

    @uuutty Run your program in a debugger. When it crashes, show us your stack trace.


  • Moderators

    @uuutty In timerUpDate you're modifying proShowInfoList and in data() you're accessing proShowInfoList using [] - most probably that's the problem (row does not exist in the list: proShowInfoList[row]). You need to check whether row < proShowInfoList.size().



  • @jsulm I add

    if (row >= proShowInfoList.length())
        {
            return QVariant();
        }
    

    into my my function but the problem still exists. Even thoughI do nothing, directly return from my data function.

    @JKSH 0_1487831980283_upload-d41fb452-2221-4354-abf8-2ba82902318e

    Is this what you want?


  • Moderators

    @uuutty said in The program will easily break down if I use QSortFilterProxyModel to help sort:

    @JKSH ...
    Is this what you want?

    Yep, that's the stack trace. Unfortunately, we cannot see the full names in the "Function" column.

    Generate that stack trace again, and then Right-Click -> "Copy Contents to Clipboard", and then paste the text here (you don't need to post a picture)



  • @JKSH

    0	QSortFilterProxyModel::parent(QModelIndex const&) const			0xb6e67fe6	
    1	QPersistentModelIndex::parent() const			0xb6e3c298	
    2	??			0xb6e55970	
    3	QItemSelection::merge(QItemSelection const&, QFlags<QItemSelectionModel::SelectionFlag>)			0xb6e4fb76	
    4	QItemSelectionModel::columnIntersectsSelection(int, QModelIndex const&) const			0xb6e505c4	
    5	??			0xb7ba26be	
    6	QHeaderView::paintSection(QPainter *, QRect const&, int) const			0xb7ba144e	
    7	QHeaderView::paintEvent(QPaintEvent *)			0xb7b9a86b	
    8	QWidget::event(QEvent *)			0xb7953e7a	
    9	QFrame::event(QEvent *)			0xb7a5ebda	
    10	QAbstractScrollArea::viewportEvent(QEvent *)			0xb7aec252	
    11	QAbstractItemView::viewportEvent(QEvent *)			0xb7b928f0	
    12	QHeaderView::viewportEvent(QEvent *)			0xb7ba0b3a	
    13	??			0xb7aecd43	
    14	QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject *, QEvent *)			0xb6e9a55f	
    15	QApplicationPrivate::notify_helper(QObject *, QEvent *)			0xb790def8	
    16	QApplication::notify(QObject *, QEvent *)			0xb7913464	
    17	QCoreApplication::notifyInternal(QObject *, QEvent *)			0xb6e9a787	
    18	QWidgetPrivate::sendPaintEvent(QRegion const&)			0xb794c5e6	
    19	QWidgetPrivate::drawWidget(QPaintDevice *, QRegion const&, QPoint const&, int, QPainter *, QWidgetBackingStore *)			0xb794cc3d	
    20	??			0xb791ba9d	
    21	??			0xb791bee6	
    22	QWidgetPrivate::syncBackingStore()			0xb793d9c1	
    23	QWidget::event(QEvent *)			0xb7953ebc	
    24	QMainWindow::event(QEvent *)			0xb7a7689f	
    25	QApplicationPrivate::notify_helper(QObject *, QEvent *)			0xb790df1a	
    26	QApplication::notify(QObject *, QEvent *)			0xb7913464	
    27	QCoreApplication::notifyInternal(QObject *, QEvent *)			0xb6e9a787	
    28	QCoreApplicationPrivate::sendPostedEvents(QObject *, int, QThreadData *)			0xb6e9cc1d	
    29	QCoreApplication::sendPostedEvents(QObject *, int)			0xb6e9d2f7	
    30	??			0xb6ef19b3	
    31	g_main_context_dispatch			0xb668fe29	
    32	??			0xb66900c9	
    33	g_main_context_iteration			0xb6690194	
    34	QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>)			0xb6ef1da4	
    35	??			0xb446ce21	
    36	QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>)			0xb6e97d13	
    37	QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>)			0xb6e9818a	
    38	QCoreApplication::exec()			0xb6ea028a	
    39	QGuiApplication::exec()			0xb722ba81	
    40	QApplication::exec()			0xb7909ab4	
    41	main	main.cpp	20	0x8052880	
    
    


  • since you reset the model inside timerUpDate you need to signal the operation with beginResetModel() and endResetModel() http://doc.qt.io/qt-5/qabstractitemmodel.html#beginResetModel



  • @VRonin Thanks a lot! Does this like a semaphore in something need mutual exclusion?



  • @uuutty I don't think I get your question... are you multi threading at the model level?



  • @VRonin I probably use the incorrect word. I mean do the beginResetModel() and endResetModel() help to prevent QSortFilterProxyModel or view read from proShowInfoList when I change it.



  • @VRonin By the way, how can I mark you answer as a correct answer, I find I can just mark my post as a correct answer.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.