Skip to content

CopperSpice Journal

CopperSpice Journal

Source Code  (Gui Example 23)

Posted on May 23, 2022May 30, 2022 By Barbara Geller

The QTableView class is used to display multiple rows and columns of data. This view makes sense when the data resides in a multi-dimensional container or a database. Since our data is stored in an SQL table we will use the QSqlTableModel to populate the view.

#include <QtCore>
#include <QtGui>

#include <QSqlTableModel>
#include <QSqlQuery>

class MainWindow : public QWidget
{
 public:
   MainWindow();

 private:
   QTableView *m_view;
   QSqlTableModel *m_sqlModel;
   QSqlDatabase m_db;

   bool createConnection();
};

The declaration for MainWindow has three data members and one method. No signals or slots are declared in this example.

MainWindow::MainWindow()
{
   setMinimumSize(800, 500);

   QLabel *label = new QLabel();
   label->setText("Table View");
   label->setAlignment(Qt::AlignHCenter);

   QFont font = label->font();
   font.setPointSize(11);
   label->setFont(font);

   if (! createConnection()) {
      std::exit(EXIT_FAILURE);
   }

   m_sqlModel = new QSqlTableModel(this, m_db);
   m_sqlModel->setTable("famousPeople");

   m_sqlModel->setSort(2, Qt::AscendingOrder);
   m_sqlModel->select();

   m_sqlModel->setHeaderData(1, Qt::Horizontal, 
      QString("First Name"));
   m_sqlModel->setHeaderData(2, Qt::Horizontal, 
      QString("Last Name"));
   m_sqlModel->setHeaderData(3, Qt::Horizontal, 
      QString("Professional Biography"));

   //
   m_view = new QTableView();
   m_view->setModel(m_sqlModel);
   m_view->horizontalHeader()->setSectionsMovable(true);
   m_view->horizontalHeader()->setStretchLastSection(true);

   m_view->hideColumn(0);
   m_view->setColumnWidth(1, 100);
   m_view->setColumnWidth(2, 100);

   QPushButton *pb_close = new QPushButton();
   pb_close->setText("Close");

   QHBoxLayout *layout = new QHBoxLayout();
   layout->addStretch();
   layout->addWidget(pb_close);
   layout->addStretch();

   QVBoxLayout *layout_main = new QVBoxLayout(this);
   layout_main->setContentsMargins(20, 20, 20, 15);

   layout_main->addWidget(label);
   layout_main->addSpacing(10);
   layout_main->addWidget(m_view);
   layout_main->addSpacing(10);
   layout_main->addLayout(layout);

   connect(pb_close, &QPushButton::clicked, 
      this, &QWidget::close);
}

The createConnection() method is called on line 13 to create an SQL database and populate it with the data the QTableView will display. This method will assign a new database connection to the variable m_db.

On line 17 we instantiate a new QSqlTableModel which is responsible for storing the data displayed in the view. This model will work with any SQL database such as SQLite, PostgreSQL, MySQL, or MariaDB. On the next line the name of the table in our database is passed to the model. Line 20 configures the model to sort the data based on second column.

The purpose of this example was to show a read only view so you can not edit the data in this example. The user can rearrange the columns by dragging the column headings. This feature is off by default. The call to setSectionsMovable(true) on line 33 will enable column reordering.

The next line instructs the view to stretch the last column to fill up the full width of the display view. This is why we do not need to set the width for column 3.

Line 36 is used to hide the contents of the first column which contains the ID used as the primary key in the SQL table. Calling showColumn(0) at any time would restore the visibility of this column.

Creating the SQL Database

The first part of the source code for the createConnection() method is listed below. The code to store the data was omitted for simplicity. The full implementation is available in the source code located in the zip file.

The call to addDatabase() on line 3 sets the connection name and the data base name to peopleDB. On line 4 the database name is changed to a special name available in SQLite which will store the database in memory. Once the connection is closed the database will cease to exist. The database is never saved to disk.

On line 15 the call to exec() defines the fields which are stored in the table with we are calling famousPeople. The remaining code, which is not shown here, will insert several rows of data.

bool MainWindow::createConnection()
{
   m_db = QSqlDatabase::addDatabase("QSQLITE", "peopleDB");
   m_db.setDatabaseName(":memory:");

   if (! m_db.open()) {
      QMessageBox::critical(nullptr, "Error Opening Database",
         "Unable to establish a connection to the "
         "SQLite database.", QMessageBox::Cancel);

      return false;
   }
    
   QSqlQuery query(m_db);
   query.exec("create table famousPeople (id int primary key, "
      "firstname varchar(20), lastname varchar(20), "
      "bio varchar(200))");

   // populate data (download zip to view source file )
 }

Main Function

Since the source code for main() has not changed there is no need to show it again. Refer to example 3 or download the full source for this example.

Running the Example

To build and run this example use the same CMake build file and commands as we showed for the first example. Modify line 2 of the CMakeLists.txt file and change “example_1” to “example_23”.

There are two other required changes on lines 61 and 68 to link with CsSql.

target_link_libraries(${PROJECT_NAME}
   PRIVATE
   CopperSpice::CsCore
   CopperSpice::CsGui
   CopperSpice::CsSql
)

install(TARGETS ${PROJECT_NAME} DESTINATION .)

cs_copy_library(CsCore)
cs_copy_library(CsGui)
cs_copy_library(CsSql)
  

https://download.copperspice.com/journal/example_23.zip

Uncategorized

Post navigation

Previous Post: Source Code  (Gui Example 22)
Next Post: Source Code  (Gui Example 24)
  • CopperSpice Journal Homepage
    • Table of Contents
    • Example Source Code
    • Discussion Forum
  • CopperSpice Homepage
  • Github Repository
  • Videos About C++

Post comments or questions on our CopperSpice Forum

Copyright © 2021-2022 CopperSpice