Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Help! New entries to model not sorted when sorting on a column in QTableView

    General and Desktop
    2
    6
    1535
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • O
      Olangu last edited by

      How do I make new rows automatically sorted when added to my model?

      By default this example program sorts on column 0, descending.
      Inserting new rows (by pressing button or by ctrl+n), will always add these in the bottom, not sorted.
      Why?

      main.cpp:
      @
      #include <QApplication>

      #include "window.h"

      int main(int argc, char *argv[])
      {
      QApplication app(argc, argv);
      Window mainWin;
      mainWin.show();
      return app.exec();
      }
      @

      window.h:
      @
      #ifndef WINDOW_H
      #define WINDOW_H

      #include <QMainWindow>

      QT_BEGIN_NAMESPACE
      class QTableView;
      class QSortFilterProxyModel;
      QT_END_NAMESPACE

      class Model;

      class Window : public QMainWindow
      {
      Q_OBJECT

      public:
      Window();

      private:
      void createToolBars();

      QTableView *_tableView;
      QSortFilterProxyModel *_sortFilterProxy;
      Model *_model;
      };

      #endif
      @

      window.cpp:
      @
      #include <QTableView>
      #include <QSortFilterProxyModel>
      #include <QAction>
      #include <QToolBar>

      #include "window.h"

      #include "model.h"

      Window::Window()
      {
      _tableView = new QTableView(this);
      _sortFilterProxy = new QSortFilterProxyModel();
      _model = new Model();

      _sortFilterProxy->setSourceModel(_model);
      _tableView->setModel(_sortFilterProxy);
      

      _tableView->setSortingEnabled(true);

      setCentralWidget(_tableView);

      QAction *insertAct = new QAction("Insert row", this);
      insertAct->setShortcuts(QKeySequence::New);
      connect(insertAct, SIGNAL(triggered()), _model, SLOT(insertRow()));
      QToolBar *toolBar = addToolBar(tr("Toolbar"));
      toolBar->addAction(insertAct);
      

      }
      @

      model.h:
      @
      #ifndef MODEL_H
      #define MODEL_H

      #include <QAbstractTableModel>

      class Model : public QAbstractTableModel
      {
      Q_OBJECT

      public:
      Model(QObject *parent = 0);

      QVariant data(const QModelIndex &index = QModelIndex(), int role = Qt::DisplayRole) const;
      int rowCount(const QModelIndex &parent = QModelIndex()) const;
      int columnCount(const QModelIndex &parent = QModelIndex()) const;

      public slots:
      void insertRow();

      private:
      int _columns;
      int _rows;
      };

      #endif
      @

      model.cpp:
      @
      #include <QAbstractTableModel>

      #include "model.h"

      Model::Model(QObject *parent)
      : _rows(3), _columns(6), QAbstractTableModel(parent)
      { }

      QVariant Model::data(const QModelIndex &index, int role) const
      {
      if(!index.isValid())
      {
      return QVariant();
      }

      switch( role )
      {
      case Qt::DisplayRole:
          return (index.row()+1)*(index.column()+1);
      default:
          return QVariant();
      }
      

      }

      int Model::rowCount(const QModelIndex &parent) const
      {
      return _rows;
      }

      int Model::columnCount(const QModelIndex &parent) const
      {
      return _columns;
      }

      void Model::insertRow()
      {
      QAbstractItemModel::beginInsertRows(QModelIndex(), _rows, _rows);
      _rows++;
      QAbstractItemModel::endInsertRows();
      }
      @

      CMakeLists.txt:
      @
      cmake_minimum_required (VERSION 2.6)

      set(PROJECT_NAME "SortTest")
      project (${PROJECT_NAME})

      set(CMAKE_AUTOMOC ON)
      set(CMAKE_BUILD_TYPE Debug)
      set (CMAKE_C_FLAGS "-std=c99")

      #source files
      set(${PROJECT_NAME}_SOURCES
      main.cpp
      window.cpp
      model.cpp)

      #qt
      find_package(Qt4 REQUIRED)

      #project includes
      include_directories(${PROJECT_BINARY_DIR})

      #qt includes
      include(${QT_USE_FILE})
      include_directories(${QT_INCLUDE_DIR}
      ${QT_QTCORE_INCLUDE_DIR}
      ${QT_QTGUI_INCLUDE_DIR})

      #qt libraries
      set(${PROJECT_NAME}_QT_LIBRARIES
      ${QT_QTGUI_LIBRARY}
      ${QT_QTCORE_LIBRARY})

      #our program
      add_executable(${PROJECT_NAME}
      ${${PROJECT_NAME}_SOURCES})

      #linking
      target_link_libraries(${PROJECT_NAME}
      ${${PROJECT_NAME}_QT_LIBRARIES})

      @

      1 Reply Last reply Reply Quote 0
      • Jeroentjehome
        Jeroentjehome last edited by

        Hi,
        You might want to add a reset or update of the view in your model (insertRow function). The insert/end rows is just there to 'protect' the view from reading data when you're updating you model data causing corrupt data or non existing data.

        Greetz, Jeroen

        1 Reply Last reply Reply Quote 0
        • O
          Olangu last edited by

          [quote author="Jeroentje@home" date="1411736618"]Hi,
          You might want to add a reset or update of the view in your model (insertRow function). The insert/end rows is just there to 'protect' the view from reading data when you're updating you model data causing corrupt data or non existing data.
          [/quote]

          But this would remove any selections and such in the view, it also will give a huge impact on preformance.

          Am I really needed to reset my complete model (think 100 000+ elements) because I want to inset a row or two? The framework can't really be this inflexible, can it?

          1 Reply Last reply Reply Quote 0
          • Jeroentjehome
            Jeroentjehome last edited by

            Maybe the update (QModelIndex) will do the same (then only the inserted items are updated).
            No idea how the selection will respond to that though.
            Did you read the Model/View docs for that?

            Greetz, Jeroen

            1 Reply Last reply Reply Quote 0
            • O
              Olangu last edited by

              [quote author="Jeroentje@home" date="1411739082"]Maybe the update (QModelIndex) will do the same (then only the inserted items are updated).
              No idea how the selection will respond to that though.
              Did you read the Model/View docs for that?[/quote]

              If im not mistaken, we don't have a QModelIndex for these rows before they are inserted. I could ofcourse catch the rowsinserted signal, but that can hardly be the way this is supposed to work.

              I've read the docs but can't find my mistake, thats why I'm asking here.

              1 Reply Last reply Reply Quote 0
              • O
                Olangu last edited by

                emitting layoutChanged() when the row has been inserted gives me the expected behaviour. But my guess is that it is also a very heavy operation. If anyone finds another way to do it ill be very happy.

                1 Reply Last reply Reply Quote 0
                • First post
                  Last post