Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Using different Views with one model and different data
Forum Updated to NodeBB v4.3 + New Features

Using different Views with one model and different data

Scheduled Pinned Locked Moved Unsolved General and Desktop
22 Posts 3 Posters 4.5k Views 1 Watching
  • 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.
  • W Offline
    W Offline
    Wuzi
    wrote on last edited by Wuzi
    #1

    Hello,

    I'm trying to write an application, which plots data to a diagram. In a class, which was derived from QAbstractTableModel, I imported the *.mf4 file which includes data I store in a 2d array and the names of the data I store in a 1d array.

    Now I would like to list the names in a listview and 2 rows of the data array in a plot.

    I thought I can use for every View a QSortFilterProxyModel and reimplement rowCount, columnCount, data, but this does not work.

    How do I handle something like this with only one model or is it better to use multiple models?

    JonBJ 1 Reply Last reply
    0
    • W Wuzi

      Hello,

      I'm trying to write an application, which plots data to a diagram. In a class, which was derived from QAbstractTableModel, I imported the *.mf4 file which includes data I store in a 2d array and the names of the data I store in a 1d array.

      Now I would like to list the names in a listview and 2 rows of the data array in a plot.

      I thought I can use for every View a QSortFilterProxyModel and reimplement rowCount, columnCount, data, but this does not work.

      How do I handle something like this with only one model or is it better to use multiple models?

      JonBJ Online
      JonBJ Online
      JonB
      wrote on last edited by
      #2

      @Wuzi said in Using different Views with one model and different data:

      I thought I can use for every View a QSortFilterProxyModel and reimplement rowCount, columnCount, data, but this does not work.

      That would have been my first thought. So what does "this does not work" mean?

      1 Reply Last reply
      0
      • W Offline
        W Offline
        Wuzi
        wrote on last edited by
        #3

        @JonB said in Using different Views with one model and different data:

        So what does "this does not work" mean?

        The functions will never called. Everytime the modelfunction will be called, not the proxy function

        JonBJ 1 Reply Last reply
        0
        • W Wuzi

          @JonB said in Using different Views with one model and different data:

          So what does "this does not work" mean?

          The functions will never called. Everytime the modelfunction will be called, not the proxy function

          JonBJ Online
          JonBJ Online
          JonB
          wrote on last edited by
          #4

          @Wuzi
          Then do you think you should show the code for that which you wrote?

          1 Reply Last reply
          0
          • W Offline
            W Offline
            Wuzi
            wrote on last edited by
            #5

            ok I set the wrong prefix, but my idea will not work
            Main.cpp:

                SignalNamesProxyModel* proxy_signal_names = new SignalNamesProxyModel(this);
                proxy_signal_names->setSourceModel(m_data.getSignalNames());
                m_listview_signal->setModel(proxy_signal_names);es());
            

            My plan was to set the row to a negative number, so I know in the model, that this will get different data:

            Proxymodel.cpp:

            QVariant SignalNamesProxyModel::data(const QModelIndex &index, int role) const {
            
                const QAbstractItemModel * model = index.model();
                QString value = sourceModel()->data(model->index(-1,index.row()),role).toString();
                return value;
            }
            

            Model.cpp:

            QVariant SignalData::data(const QModelIndex &index, int role) const {
            
                int row = index.row();
                int column = index.column();
            
            
                if (role == Qt::DisplayRole){
                    if(row >= 0){
                        return m_data[row][column];
                    }else if(row == -1){
                        return m_column_names[column];
                    }else if(row == -2){
                        return m_column_units[column];
                    }
                }
            
                return QVariant();
            }
            

            But this does not work, because when I set the row to a negative number, the column becomes -1 too.

            Is there another way to get different data?

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #6

              Hi,

              Wouldn't the KConcatenateRowsProxyModel do what you want ?

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              W 1 Reply Last reply
              0
              • SGaistS SGaist

                Hi,

                Wouldn't the KConcatenateRowsProxyModel do what you want ?

                W Offline
                W Offline
                Wuzi
                wrote on last edited by Wuzi
                #7

                @SGaist said in Using different Views with one model and different data:

                Wouldn't the KConcatenateRowsProxyModel do what you want ?

                Thank you SGaist, but in the documentation there is written, that it is assumed that all rows have the same number ("All models are assumed to have the same number of columns")

                This is my dataclass:

                class SignalData : public QAbstractTableModel
                {
                    Q_OBJECT
                public:
                    SignalData(Data *parent);
                    int rowCount(const QModelIndex &parent = QModelIndex()) const override ;
                    int columnCount(const QModelIndex &parent = QModelIndex()) const override ;
                    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
                    bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()); // wieso darf hier kein override stehen?
                    bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
                    int readMDFFile(QString path);
                private:
                    Data* m_parent;
                
                    std::vector<std::vector<double> > m_data;
                    std::vector<QString> m_column_names;
                    std::vector<QString> m_column_units;
                };
                

                m_data are the datas, column_names are the names of the data columns and olumn_units are the units of the data columns.
                For example: size(m_column_names) = size(m_column_units) = 8
                and size(m_data) = 8x1000 or so

                1 Reply Last reply
                0
                • SGaistS Offline
                  SGaistS Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  Right, I was thinking about KExtraColumnsProxyModel.

                  But I realise I might have misunderstood your final goal.

                  Can you show an image of what you would like to show in your view ?

                  Interested in AI ? www.idiap.ch
                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                  1 Reply Last reply
                  0
                  • W Offline
                    W Offline
                    Wuzi
                    wrote on last edited by
                    #9

                    Sorry for my bad explanation.

                    Here is the main view.

                    0_1540573885327_MDFViewer.png

                    This application should load Data files *.mf4 and store this data. The signals which are in this file are listen in the Listview "Signals". If you click on one of this signals, you will see a preview of this signal in the "Preview" Listview. The central Widget contains a tabwidget, where you can add charts. At the end you should be able to drag a Signal name in one of this charts, and the signal will be showed in this chart.

                    So I need the Signal name in the "Signals" Listview and the Signal data in the "Preview" and in the central widget charts.

                    1 Reply Last reply
                    0
                    • SGaistS Offline
                      SGaistS Offline
                      SGaist
                      Lifetime Qt Champion
                      wrote on last edited by
                      #10

                      Ok, then isn't it rather a tree style model that you should have ?

                      Or if still a table style, you should maybe consider creating an object that encapsulates your signals data and build your model on top of that.

                      Interested in AI ? www.idiap.ch
                      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                      1 Reply Last reply
                      1
                      • W Offline
                        W Offline
                        Wuzi
                        wrote on last edited by
                        #11

                        @SGaist said in Using different Views with one model and different data:

                        Ok, then isn't it rather a tree style model that you should have ?

                        You mean something like this:
                        0_1540627115290_TreeView.png
                        Sounds good for me, thanks

                        @SGaist said in Using different Views with one model and different data:

                        Or if still a table style, you should maybe consider creating an object that encapsulates your signals data and build your model on top of that

                        You mean. creating for every signal a own model? Putting The signal names in a seperate model than the data?

                        1 Reply Last reply
                        0
                        • W Offline
                          W Offline
                          Wuzi
                          wrote on last edited by
                          #12

                          No I created a tree model like in this example.

                          This is the code which add the data as SignalDataTreeItems to the m_root_item

                              beginInsertRows(QModelIndex(), 0, channel_list.size()-1);
                          
                              for (int channel_index : channel_list) {
                                  const mdf::channel& ch = channels[channel_index];
                          
                                  QList<QVariant> signalname = {QVariant::fromValue<QString>(QString::fromStdString(ch.get_name()))};
                                  SignalDataTreeItem *signal = new SignalDataTreeItem(signalname);
                          
                                  QList<QVariant> unit_string = {QVariant::fromValue<QString>(QString::fromStdString(ch.get_metadata_unit()))};
                                  SignalDataTreeItem *unit = new SignalDataTreeItem(unit_string,signal);
                                  signal->appendChild(unit);
                          
                          
                                  // TODO: optimize this step!
                                  std::vector<double> column;
                                  ch.get_data_real(column);
                                  QList<QVariant> datas;
                                  foreach(double d, column){
                                      datas.append(QVariant(d));
                                  }
                                  SignalDataTreeItem *data = new SignalDataTreeItem(datas,signal);
                                  signal->appendChild(data);
                          
                                  m_rootItem->appendChild(signal);
                              }
                          
                              endInsertRows();
                          

                          The problem is, that in the proxy the function data will never called.

                          SignalNamesProxyModel::SignalNamesProxyModel(QObject *parent): QSortFilterProxyModel (parent){
                          }
                          
                          int SignalNamesProxyModel::rowCount(const QModelIndex &parent) const {
                              int rowcount = sourceModel()->rowCount(QModelIndex()); // of root item (number of signals)
                              return rowcount;
                          }
                          
                          int SignalNamesProxyModel::columnCount(const QModelIndex &parent) const{
                              return 1;
                          }
                          
                          QVariant SignalNamesProxyModel::data(const QModelIndex &index, int role) const {
                          
                              QString value = sourceModel()->data(index).toString();
                          
                              return value;
                          }
                          
                          QModelIndex SignalNamesProxyModel::index(int row, int column, const QModelIndex &parent)const {
                          
                              return sourceModel()->index(row,0,QModelIndex()); // child "row" of m_root_item of sourceModel (signal)
                          }
                          

                          The problem is, that I don't understand how do I have to use beginInsertRows and endInsertRows, when I have to different datas, because the row count matches only for one view not for both at the same time.

                          1 Reply Last reply
                          0
                          • SGaistS Offline
                            SGaistS Offline
                            SGaist
                            Lifetime Qt Champion
                            wrote on last edited by
                            #13

                            I just re-read your first post. In the end, can't it be simplified to a two column table ?

                            First column: name
                            Second column: data

                            Interested in AI ? www.idiap.ch
                            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                            1 Reply Last reply
                            0
                            • W Offline
                              W Offline
                              Wuzi
                              wrote on last edited by
                              #14

                              @SGaist said in Using different Views with one model and different data:

                              I just re-read your first post. In the end, can't it be simplified to a two column table ?
                              First column: name
                              Second column: data

                              The problem is, that in the data variable are multiple signals:

                              row0, column0: signal0, first value
                              row0, column1: signal0, second value
                              row1, column0: signal1, first value
                              row1, colimn1: signal1, second value
                              ....

                              So this is the second concept I tested while the weekend, it has nothing to do with the tree model.
                              I moved the signal name in a seperate listmodel (So it is easy to list all signal names in a list view).
                              The data I store in a table model.

                              The problem is, how can I set, which row of this table should be shown?
                              For example:
                              I have a chart where I would like to plot some of this data (but only few signals, not every row). I would like to select which signal should be used for the x axis and which should be used on the y axis. To do that I created a QSortFilterProxyModel and reimplemented the rowCount, columnCount and the mapToSource function as follows:

                              int SignalPreviewProxyModel::rowCount(const QModelIndex &parent) const {
                                  return 2*m_mapToSourceIndex.lenght();
                              }
                              
                              int SignalPreviewProxyModel::columnCount(const QModelIndex &parent) const{
                              
                                  int column = sourceModel()->columnCount(parent);
                                  return column;
                              }
                              
                              QModelIndex SignalPreviewProxyModel::mapToSource(const QModelIndex & proxyIndex) const {
                              
                                  if(!proxyIndex.isValid()){
                                      return QModelIndex();
                                  }
                              
                                  int row = proxyIndex.row();
                                  int column = proxyIndex.column();
                              
                                  int axis = row % 2; // modulo 2, because x and y axis
                                  int value = row /2; // graph
                              
                                  if(axis == 0){
                                      row = m_mapToSourceIndex.at(value).first;
                                  }else{
                                      row = m_mapToSourceIndex.at(value).second;
                                  }
                                  QModelIndex index2 = sourceModel()->index(row,column,QModelIndex()); // get from already existing item the index
                                  return index2;
                              }
                              

                              In this concept, the problem is, that mapToSource transformation is not invertable ( when there should be the possibility to display mutiple signals in the graph, this is why m_mapToSourceIndex is a vector of mappings), so I'm not able create the mapFromSource function and I get a segmentation fault.

                              I really don't know how I can solve this problem (which is the most common way?).
                              Thanks for helping me! :)

                              0_1540820607321_MDFViewer.png

                              1 Reply Last reply
                              0
                              • SGaistS Offline
                                SGaistS Offline
                                SGaist
                                Lifetime Qt Champion
                                wrote on last edited by
                                #15

                                I'm still wondering if there's not a bit of model over-engineering.

                                Wouldn't it be simpler to have a class that encapsulates a "signal". Store of all your signals in a QVector of that class.

                                Then build a simple table module that would return the data from the correct signal object.

                                struct Signal
                                {
                                    QString name;
                                    QString unit;
                                    QVector<QVariant> data;
                                };
                                
                                class SignalTableModel
                                {
                                
                                QVariant data(const QModelIndex &index, int role) const
                                {
                                    // Add index validity checks
                                    Signal signal(_signalVector.at(index.row()));
                                    if (index.column() == 1) {
                                        return signal.name();
                                    }
                                   // etc.
                                }
                                
                                };
                                

                                Interested in AI ? www.idiap.ch
                                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                                1 Reply Last reply
                                0
                                • W Offline
                                  W Offline
                                  Wuzi
                                  wrote on last edited by
                                  #16

                                  So you mean, when column ==1 then return name, when column == 2 then return unit and when the column is greater than 2 return the respective value?

                                  So then I have to use a proxy between this model and the signal name list view and set the columcount to 1?

                                  And for the chartview(derived from tableview) I have to use a proxy, which maps the index to +2 because the first two rows are name and unit?

                                  Do I understand you correct?

                                  1 Reply Last reply
                                  0
                                  • SGaistS Offline
                                    SGaistS Offline
                                    SGaist
                                    Lifetime Qt Champion
                                    wrote on last edited by
                                    #17

                                    What do you mean by respective value ?

                                    You can use a QListView so no need for fiddling with a proxy model.

                                    And for the table view, you can simply hide the columns you don't want to show.

                                    Interested in AI ? www.idiap.ch
                                    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                                    1 Reply Last reply
                                    1
                                    • W Offline
                                      W Offline
                                      Wuzi
                                      wrote on last edited by
                                      #18

                                      @SGaist said in Using different Views with one model and different data:

                                      What do you mean by respective value ?
                                      One signal consists of multiple data (due to a time range on which the signal was logged). The different signals are stored in a 2d array:

                                      std::vector<std::vector<double> > m_data;
                                      

                                      @SGaist said in Using different Views with one model and different data:

                                      You can use a QListView so no need for fiddling with a proxy model.

                                      Yes for the signal names I have a QListView. The signal names are stored in a list model. This works fine.

                                      Or did I missunderstand your question?

                                      1 Reply Last reply
                                      0
                                      • SGaistS Offline
                                        SGaistS Offline
                                        SGaist
                                        Lifetime Qt Champion
                                        wrote on last edited by
                                        #19

                                        You wrote that you wanted to use a proxy and setting the columns count to 1 so I thought you were trying to "re-invent" QListView.

                                        Interested in AI ? www.idiap.ch
                                        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                                        1 Reply Last reply
                                        0
                                        • W Offline
                                          W Offline
                                          Wuzi
                                          wrote on last edited by
                                          #20

                                          @SGaist said in Using different Views with one model and different data:

                                          You wrote that you wanted to use a proxy and setting the columns count to 1 so I thought you were trying to "re-invent" QListView.

                                          Oh sorry. this was in the concept with the tree model, but in the actual concept I have the data stored in a tablemodel.

                                          1 Reply Last reply
                                          0

                                          • Login

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • Users
                                          • Groups
                                          • Search
                                          • Get Qt Extensions
                                          • Unsolved