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.6k 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
    #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
                          • SGaistS Offline
                            SGaistS Offline
                            SGaist
                            Lifetime Qt Champion
                            wrote on last edited by
                            #21

                            Ok, good.

                            So at what point are you now ?

                            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
                              #22

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

                              Ok, good.
                              So at what point are you now ?

                              After reading you question I had a new idea (before I thought it is not possible to use KDChart to plot) :D :

                              1. a data class which stores all the data
                              2. a table model which stores a pointer to the data which I would like to display.
                                In this model I reimplement the data, rowcount and columncount function as following:
                              class Data
                              {
                              public:
                                 QVector<double>* getDataPointer(int index){return &m_data.at(index);}
                              private:
                               QVector<QVector<double>> m_data;
                              };
                              
                              // Every Diagram uses an object of this class
                              class SignalModel: public QAbstractTableModel
                              {
                              public:
                              - override rowcount
                              - override columncount
                              - override data
                              void addData(QVector<double>* xaxis, QVector<double>* yaxis);
                              private:
                                  QVector<QVector<double>*> m_data;
                              };
                              
                              void SignalModel::addData(QVector<double>* xaxis, QVector<double>* yaxis){
                              // KDChart expects, that the axis keys and values are stored in different rows
                              m_data.append(xaxis);
                              m_data.append(yaxis);
                              }
                              
                              int SignalModel::rowCount(const QModelIndex &parent) const {
                                return m_data.lenght();
                              }
                              
                              int SignalModel::columnCount(const QModelIndex &parent) const{
                              
                                int column = m_data.at(0)->length()
                                return column;
                              }
                              
                              QVariant SignalModel::data(const QModelIndex &index) const{
                              
                                return m_data.at(index.row)->at(index.column);
                              }
                              
                              

                              removeRow and insertRow must be reimplemented too, to add dynamically new data.

                              For showing the signal names I would reimplement a listmodel.

                              I think it is the simplest method to do my task. (If there are errors in my code, it is because I didn't tested it, it's just a sketch).
                              I found kst-plot which does exactly what I want. So I think it is easier to extend this program and help to contribute to this one, than rewriting a new one.

                              Thank you SGaist for your help and the inspiration. If this last concept is unclear, just write and I will extend it.

                              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