Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using QTableView with a model

Tags:

c++

qt

model-view

I have the QVector cars that I want to filter basing on the car's registration number. I want to create a new filtered vector. I don't think that this is ok because i'm iterating 2 vectors, copying from the first one to the second one. Am I doing this right?

void MainWindow::on_actionBy_registration_number_triggered()
{
    myDialog = new MyDialog(this);
    myDialog->exec();

    QString toSearchString = myDialog->getRegistrationNumber();
    QVector<Vehicle> founded;
    QVectorIterator<Vehicle> iterator(cars);
    while(iterator.hasNext()){
        Vehicle car = iterator.next();
        QString num = car.getRegistration().getRegistrationNumber();
        if(num.contains(toSearchString,Qt::CaseInsensitive)){
            founded.append(car);
        }
    }
    model = new QStandardItemModel(founded.size(),5,this);

    //create header
    createHeader(model);

    int j = 0; //row
    QVectorIterator<Vehicle> iter(founded);
    while(iter.hasNext()){
        Vehicle output = iter.next();
        //set car
        QString makeAndModel = output.getGeneralData().getMake() + output.getGeneralData().getModel();
        QStandardItem *mAndM = new QStandardItem(QString(makeAndModel));
        model->setItem(j,0,mAndM);

        //set type
        QStandardItem *type = new QStandardItem(QString(output.getGeneralData().getType()));
        model->setItem(j,1,type);

        //set mileage
        QString mileageString = QString::number(output.getGeneralData().getMileage());
        QStandardItem *mileage = new QStandardItem(QString(mileageString));
        model->setItem(j,2,mileage);

        //set year
        QString yearString = QString::number(output.getGeneralData().getYear());
        QStandardItem *year = new QStandardItem(QString(yearString));
        model->setItem(j,3,year);


        //set registration
        QString regString = VehicleHelper::convertBoolToString(output.getRegistration().isRegistered());
        QStandardItem *regDate = new QStandardItem(QString(regString));
        model->setItem(j,4,regDate);
        j++;
    }

    ui->tableView->setModel(model);
    ui->tableView->setEnabled(false);
}
like image 252
laura Avatar asked Sep 23 '13 16:09

laura


People also ask

What is the difference between QTableView and QTableWidget?

The major difference between the two is that QTableView requires you to use an external class derived from QAbstractItemModel with it. The rowCount(), columnCount(), and data() methods for the item model are used by the table view to tell it how to fill in and format the table cells.

What is QTableView?

A QTableView implements a table view that displays items from a model. This class is used to provide standard tables that were previously provided by the QTable class, but using the more flexible approach provided by Qt's model/view architecture.

What is a QT item model?

Two models included in QtQStandardItemModel is a multi-purpose model that can be used to represent various different data structures needed by list, table, and tree views. This model also holds the items of data. QFileSystemModel is a model that maintains information about the contents of a directory.

What is a delegate in Qt?

As each item in a model is visualized through a delegate, what is actually visible to the user are the delegates. Each delegate gets access to a number of attached properties, some from the data model, others from the view. From the model, the properties convey the data for each item to the delegate.


1 Answers

This can be done neatly using a proxy filter model. Below is a self-contained example that runs on both Qt 4 and 5.

screenshot

// https://github.com/KubaO/stackoverflown/tree/master/questions/filter-18964377
#include <QtGui>
#if QT_VERSION_MAJOR > 4
#include <QtWidgets>
#endif

class Vehicle {
   QString m_make, m_model, m_registrationNumber;
public:
   Vehicle(const QString & make, const QString & model, const QString & registrationNumber) :
      m_make{make}, m_model{model}, m_registrationNumber{registrationNumber} {}
   QString make() const { return m_make; }
   QString model() const { return m_model; }
   QString registrationNumber() const { return m_registrationNumber; }
   bool isRegistered() const { return !m_registrationNumber.isEmpty(); }
};

class VehicleModel : public QAbstractTableModel {
   QList<Vehicle> m_data;
public:
   VehicleModel(QObject * parent = {}) : QAbstractTableModel{parent} {}
   int rowCount(const QModelIndex &) const override { return m_data.count(); }
   int columnCount(const QModelIndex &) const override { return 3; }
   QVariant data(const QModelIndex &index, int role) const override {
      if (role != Qt::DisplayRole && role != Qt::EditRole) return {};
      const auto & vehicle = m_data[index.row()];
      switch (index.column()) {
      case 0: return vehicle.make();
      case 1: return vehicle.model();
      case 2: return vehicle.registrationNumber();
      default: return {};
      };
   }
   QVariant headerData(int section, Qt::Orientation orientation, int role) const override {
      if (orientation != Qt::Horizontal || role != Qt::DisplayRole) return {};
      switch (section) {
      case 0: return "Make";
      case 1: return "Model";
      case 2: return "Reg.#";
      default: return {};
      }
   }
   void append(const Vehicle & vehicle) {
      beginInsertRows({}, m_data.count(), m_data.count());
      m_data.append(vehicle);
      endInsertRows();
   }
};

class Widget : public QWidget {
   QGridLayout m_layout{this};
   QTableView m_view;
   QPushButton m_button{"Filter"};
   VehicleModel m_model;
   QSortFilterProxyModel m_proxy;
   QInputDialog m_dialog;
public:
   Widget() {
      m_layout.addWidget(&m_view, 0, 0, 1, 1);
      m_layout.addWidget(&m_button, 1, 0, 1, 1);
      connect(&m_button, SIGNAL(clicked()), &m_dialog, SLOT(open()));
      m_model.append({"Volvo", "240", "SQL8941"});
      m_model.append({"Volvo", "850", {}});
      m_model.append({"Volvo", "940", "QRZ1321"});
      m_model.append({"Volvo", "960", "QRZ1628"});
      m_proxy.setSourceModel(&m_model);
      m_proxy.setFilterKeyColumn(2);
      m_view.setModel(&m_proxy);
      m_dialog.setLabelText("Enter registration number fragment to filter on. Leave empty to clear filter.");
      m_dialog.setInputMode(QInputDialog::TextInput);
      connect(&m_dialog, SIGNAL(textValueSelected(QString)),
              &m_proxy, SLOT(setFilterFixedString(QString)));
   }
};

int main(int argc, char *argv[])
{
   QApplication a{argc, argv};
   Widget w;
   w.show();
   return a.exec();
}
like image 67
Kuba hasn't forgotten Monica Avatar answered Sep 28 '22 06:09

Kuba hasn't forgotten Monica