General Database Connection Dialog

This code snippet shows how to implement a general database dialog that will prompt the user for general database connection properties (username, password, hostname, ecc.) as well as a combo with all available database drivers. The dialog provides also a signal that will pass the database connection (if established) so that third party components can use such connection.

Usage

Usage of the presented dialog is like the following:

  1. DatabaseConnectionDialog* dialog = new DatabaseConnectionDialog(this);
  2.  
  3.     // optional: set the data that will be presented to the user as auto-filled form
  4.     dialog->setDatabaseName( "mydb" );
  5.     dialog->setDatabasePortNumber( 1234 );
  6.     dialog->setDatabaseHostName( "localhost" );
  7.     dialog->setDatabaseUsername( "luca" );
  8.     dialog->setDatabaseDriverName( "QPSQL" );
  9.     dialog->setDatabasePassword( "pwd" );
  10.  
  11.     // enable the connect button if all the data is correct
  12.     dialog->checkFormData();
  13.     // connect the dialog signal to a slot where I will use the connection
  14.     connect( dialog,
  15.              SIGNAL(databaseConnect(QSqlDatabase&)),
  16.              this,
  17.              SLOT(slotHandleNewDatabaseConnection(QSqlDatabase&)));
  18.  
  19.      // show the dialog (without auto-connection)
  20.     dialog->run( false );

The dialog allows for pre-initialization of form fields, as well as an auto-connect mode that make the connection to happen automatically if all the data is in place.
Please note that this dialog can be improved in several ways, and represents therefore a starting point for a more specific database connection dialog.

Auto-Connect mode

When the run() method is invoked an autoconnect mode can be specified as boolean value true. In such mode, if all the form data is filled, the dialog immediately attempts to connect to the database, and in the case it succeed the dialog is not shown to the user and the signal is emitted. In the case the form data is not complete or the connection cannot be established, the dialog is shown to the user. If the autoconnect mode is off (parameter = false) the dialog is always shown.

Source code

The following is the header file:

  1. /*!
  2.   * \file databasedialog.h
  3.   */
  4. #ifndef DATABASEDIALOG_H
  5. #define DATABASEDIALOG_H
  6.  
  7. #include <QDialog>
  8. #include <QLabel>
  9. #include <QLineEdit>
  10. #include <QComboBox>
  11. #include <QSpinBox>
  12. #include <QDialogButtonBox>
  13. #include <QHBoxLayout>
  14. #include <QVBoxLayout>
  15. #include <QGridLayout>
  16. #include <QSqlDatabase>
  17. #include <QString>
  18. #include <QMessageBox>
  19. #include <QDebug>
  20. #include <QSqlError>
  21. #include <QPushButton>
  22. #include <QGroupBox>
  23.  
  24. class DatabaseConnectionDialog : public QDialog
  25. {
  26.     Q_OBJECT
  27.  
  28. private:
  29.  
  30.     /*!
  31.       * The display label for the database driver name.
  32.       */
  33.     QLabel* labelDatabaseDriverName;
  34.  
  35.     /*!
  36.       * The display label for the TCP/IP port the database
  37.       * is listening for connections.
  38.       */
  39.     QLabel* labelDatabasePort;
  40.  
  41.     /*!
  42.       * The label for the database name.
  43.       */
  44.     QLabel* labelDatabaseName;
  45.  
  46.     /*!
  47.       * The label for the database host name.
  48.       */
  49.     QLabel* labelDatabaseHostName;
  50.  
  51.     /*!
  52.       * The label for the database username.
  53.       */
  54.     QLabel* labelDatabaseUsername;
  55.  
  56.     /*!
  57.       * The label for the database password.
  58.       */
  59.     QLabel* labelDatabasePassword;
  60.  
  61.     /*!
  62.       * A label to display the summary database URL
  63.       * connection string.
  64.       */
  65.     QLabel* labelDatabaseURL;
  66.  
  67.  
  68.     /*!
  69.       * The editable name of the database to which the user
  70.       * wants to connect to.
  71.       */
  72.     QLineEdit* editDatabaseName;
  73.  
  74.     /*!
  75.       * The editable name of the database name to which connect.
  76.       */
  77.     QLineEdit* editDatabaseHostName;
  78.  
  79.     /*!
  80.       * The database listening port.
  81.       */
  82.     QSpinBox* spinBoxDatabasePort;
  83.  
  84.     /*!
  85.       * The editable username to use for the connection.
  86.       */
  87.     QLineEdit* editDatabaseUsername;
  88.  
  89.     /*!
  90.       * The editable password to use for the connection.
  91.       */
  92.     QLineEdit* editDatabasePassword;
  93.  
  94.     /*!
  95.       * The combo from which the user can select the database
  96.       * driver name and type
  97.       */
  98.     QComboBox* comboDatabaseDriverName;
  99.  
  100.  
  101.     /*!
  102.       * A Dialog button box for displaying the
  103.       * connect/cancel buttons.
  104.       */
  105.     QDialogButtonBox* buttons;
  106.  
  107.     /*!
  108.       * A method to create all the components of this dialog window
  109.       * and lay out them correctly.
  110.       */
  111.     void setUpGUI();
  112.  
  113.     /*!
  114.       * Searches for and populates the combo box with the
  115.       * available database drivers.
  116.       */
  117.     void findAvailableDrivers();
  118.  
  119.  
  120.     /*!
  121.       * Performs the connection to the database
  122.       * and emits the signal to pass the connection.
  123.       */
  124.     void doDatabaseConnection();
  125.  
  126. public:
  127.     explicit DatabaseConnectionDialog(QWidget *parent = 0);
  128.  
  129.     /*!
  130.       * Sets the database name in the dialog.
  131.       * \param dbName the name of the database
  132.       */
  133.     void setDatabaseName( const QString& dbName );
  134.  
  135.     /*!
  136.       * Sets the port number for the database connection.
  137.       * \param portNumber the port number the database is listening for
  138.       * connections
  139.       */
  140.     void setDatabasePortNumber( int& portNumber );
  141.  
  142.     /*!
  143.       * Sets the remote host name mnemonic name.
  144.       * \param hostname the name of the host the database is running on
  145.       */
  146.     void setDatabaseHostName( const QString& hostname );
  147.  
  148.     /*!
  149.       * Sets the username to use for the connection.
  150.       * \param username the username to use for the connection
  151.       */
  152.     void setDatabaseUsername( const QString& username );
  153.  
  154.     /*!
  155.       * Selects the driver name.
  156.       * \param the driver name (therefore the database type) to
  157.       * select in the combo box.
  158.       */
  159.     void setDatabaseDriverName( const QString& drvName );
  160.  
  161.     /*!
  162.       * Sets the user password.
  163.       * \param the password to use for the connection
  164.       */
  165.     void setDatabasePassword( const QString& pwd );
  166.  
  167.  
  168.     /*!
  169.       * Performs a check against the user data and enables/disables
  170.       * the connect button depending on the form fill status.
  171.       *\return true if the data allows a database connection
  172.       */
  173.     bool checkFormData();
  174.  
  175.     /*!
  176.       * Performs the database connection or prompt the user
  177.       * showing this dialog in the case data is not completed
  178.       * or should not perform the autoconnection.
  179.       * \param autoConnect if set to true tries to perform an automatic
  180.       * connection to the database, if the data is complete, or prompt the user
  181.       * for missing data. If set to false, simply shows the dialog and waits.
  182.       */
  183.     void run( bool autoConnect );
  184.  
  185.  
  186. signals:
  187.  
  188.     /*!
  189.       * Passes the database connection in the case the connection
  190.       * is succesful.
  191.       * \param databaseConnection the connection object
  192.       */
  193.     void databaseConnect( QSqlDatabase& databaseConnection );
  194.  
  195. public slots:
  196.  
  197.     /*!
  198.       * Checks if the user has entered enough data to
  199.       * try a database connection.
  200.       */
  201.     bool slotCheckFormData();
  202.  
  203.  
  204.     /*!
  205.       * Performs the database connection.
  206.       */
  207.     void slotPerformConnection();
  208.  
  209. };
  210.  
  211. #endif // DATABASEDIALOG_H

And the following is the class implementation:

  1. #include "databasedialog.h"
  2.  
  3. DatabaseConnectionDialog::DatabaseConnectionDialog(QWidget *parent) :
  4.     QDialog(parent)
  5. {
  6.     // this dialog is modal
  7.     setModal( true );
  8.     // the title of this dialog
  9.     setWindowTitle( tr("Database connection") );
  10.     // place each GUI component
  11.     setUpGUI();
  12.     // load available drivers
  13.     findAvailableDrivers();
  14. }
  15.  
  16. void DatabaseConnectionDialog::setUpGUI()
  17. {
  18.  
  19.  
  20.     // create all gui components
  21.     labelDatabaseDriverName = new QLabel( tr("Database Type (driver name)"), this );
  22.     labelDatabasePort       = new QLabel( tr("TCP/IP Port Number"), this );
  23.     labelDatabaseName       = new QLabel( tr("Database Name"), this );
  24.     labelDatabaseHostName   = new QLabel( tr("Host Name"), this );
  25.     labelDatabaseUsername   = new QLabel( tr("Username"), this );
  26.     labelDatabasePassword   = new QLabel( tr("Password"), this );
  27.     labelDatabaseURL        = new QLabel( this );
  28.     labelDatabaseURL->setAlignment( Qt::AlignCenter );
  29.  
  30.     spinBoxDatabasePort     = new QSpinBox( this );
  31.     spinBoxDatabasePort->setMaximum( 9999 );
  32.     spinBoxDatabasePort->setMinimum( 100 );
  33.     spinBoxDatabasePort->setSingleStep( 1 );
  34.  
  35.     comboDatabaseDriverName = new QComboBox( this );
  36.     comboDatabaseDriverName->setEditable( false );
  37.  
  38.  
  39.     editDatabaseName = new QLineEdit( this );
  40.     editDatabaseHostName = new QLineEdit( this );
  41.     editDatabaseUsername = new QLineEdit( this );
  42.     editDatabasePassword = new QLineEdit( this );
  43.     editDatabasePassword->setEchoMode( QLineEdit::Password );
  44.     connect( editDatabaseName,
  45.              SIGNAL(editingFinished()),
  46.              this,
  47.              SLOT(slotCheckFormData()) );
  48.     connect( editDatabaseHostName,
  49.              SIGNAL(editingFinished()),
  50.              this,
  51.              SLOT(slotCheckFormData()) );
  52.     connect( editDatabaseUsername,
  53.              SIGNAL(editingFinished()),
  54.              this,
  55.              SLOT(slotCheckFormData()) );
  56.     connect( editDatabasePassword,
  57.              SIGNAL(editingFinished()),
  58.              this,
  59.              SLOT(slotCheckFormData()) );
  60.     connect( editDatabasePassword,
  61.              SIGNAL(returnPressed()),
  62.              this,
  63.              SLOT(slotCheckFormData()) );
  64.  
  65.  
  66.     // create the button box
  67.     buttons = new QDialogButtonBox( this );
  68.     buttons->addButton( QDialogButtonBox::Ok );
  69.     buttons->addButton( QDialogButtonBox::Cancel );
  70.     QPushButton* okButton = buttons->button( QDialogButtonBox::Ok );
  71.     okButton->setText( tr( "Connect!" ) );
  72.     okButton->setEnabled( false );
  73.     connect( buttons,
  74.              SIGNAL(accepted()),
  75.              this,
  76.              SLOT(slotPerformConnection()));
  77.     connect( buttons,
  78.              SIGNAL(rejected()),
  79.              this,
  80.              SLOT(close()));
  81.  
  82.  
  83.  
  84.  
  85.  
  86.     // create a vertical layout to display components
  87.     QVBoxLayout* verticalLayout = new QVBoxLayout( this );
  88.  
  89.  
  90.     // create a grid layout to add all the components
  91.     QGridLayout* formGridLayout = new QGridLayout( this );
  92.     QGroupBox* gridGroupBox = new QGroupBox( this );
  93.     gridGroupBox->setTitle( tr("Database connection properties" ) );
  94.     formGridLayout->addWidget( labelDatabaseDriverName, 0, 0 );
  95.     formGridLayout->addWidget( comboDatabaseDriverName, 0, 1 );
  96.     labelDatabaseDriverName->setBuddy( comboDatabaseDriverName );
  97.     formGridLayout->addWidget( labelDatabaseHostName, 1, 0 );
  98.     formGridLayout->addWidget( editDatabaseHostName, 1, 1);
  99.     labelDatabaseHostName->setBuddy( editDatabaseHostName );
  100.     formGridLayout->addWidget( labelDatabasePort, 2, 0 );
  101.     formGridLayout->addWidget( spinBoxDatabasePort, 2, 1 );
  102.     labelDatabasePort->setBuddy( spinBoxDatabasePort );
  103.     formGridLayout->addWidget( labelDatabaseName, 3, 0 );
  104.     formGridLayout->addWidget( editDatabaseName , 3, 1 );
  105.     labelDatabaseName->setBuddy( editDatabaseName );
  106.     formGridLayout->addWidget( labelDatabaseUsername, 4, 0 );
  107.     formGridLayout->addWidget( editDatabaseUsername, 4, 1 );
  108.     labelDatabaseUsername->setBuddy( editDatabaseUsername );
  109.     formGridLayout->addWidget( labelDatabasePassword, 5, 0 );
  110.     formGridLayout->addWidget( editDatabasePassword, 5, 1 );
  111.     labelDatabasePassword->setBuddy( editDatabasePassword );
  112.     // add all the elements to groupbox
  113.     gridGroupBox->setLayout( formGridLayout );
  114.  
  115.     // place a new groupbox to contain the database connection URL
  116.     QGroupBox* urlGroupBox = new QGroupBox( this );
  117.     urlGroupBox->setTitle( tr( "Database URL" ) );
  118.     QHBoxLayout* urlLayout = new QHBoxLayout( this );
  119.     urlLayout->addWidget( labelDatabaseURL );
  120.     urlGroupBox->setLayout( urlLayout );
  121.  
  122.  
  123.  
  124.     // nest all layouts together
  125.     verticalLayout->addWidget( gridGroupBox );
  126.     verticalLayout->addStretch();
  127.     verticalLayout->addWidget( urlGroupBox );
  128.     verticalLayout->addWidget( buttons );
  129.  
  130.  
  131.     comboDatabaseDriverName->setFocus();
  132. }
  133.  
  134. void DatabaseConnectionDialog::findAvailableDrivers()
  135. {
  136.     // remove all items
  137.     comboDatabaseDriverName->clear();
  138.  
  139.     // populate the combo box with all available drivers
  140.     foreach( QString driverName, QSqlDatabase::drivers() )
  141.         comboDatabaseDriverName->addItem( driverName );
  142. }
  143.  
  144. bool DatabaseConnectionDialog::slotCheckFormData()
  145. {
  146.     return checkFormData();
  147. }
  148.  
  149.  
  150. bool DatabaseConnectionDialog::checkFormData(){
  151.     if( editDatabaseName->text().isEmpty()
  152.        || editDatabaseHostName->text().isEmpty()
  153.        || editDatabaseUsername->text().isEmpty()
  154.        || editDatabasePassword->text().isEmpty() )
  155.         buttons->button( QDialogButtonBox::Ok )->setEnabled( false );
  156.     else{
  157.         // enable the connect button and give focus
  158.         buttons->button( QDialogButtonBox::Ok )->setEnabled( true );
  159.         buttons->button( QDialogButtonBox::Ok )->setFocus();
  160.     }
  161.  
  162.  
  163.     // if the connection can be established (or at least tried)
  164.     // display the URL
  165.     if( buttons->button( QDialogButtonBox::Ok )->isEnabled() )
  166.         labelDatabaseURL->setText( comboDatabaseDriverName->currentText()
  167.                                    + "://"
  168.                                    + editDatabaseUsername->text()
  169.                                    + "@"
  170.                                    + editDatabaseHostName->text()
  171.                                    + "/"
  172.                                    + editDatabaseName->text() );
  173.     else
  174.         labelDatabaseURL->setText( "" );
  175.  
  176.  
  177.     return buttons->button( QDialogButtonBox::Ok )->isEnabled();
  178. }
  179.  
  180. void DatabaseConnectionDialog::doDatabaseConnection()
  181. {
  182.     // check the database driver is really available
  183.     // (should never happen)
  184.     if( ! QSqlDatabase::isDriverAvailable( comboDatabaseDriverName->currentText() ) ){
  185.         QMessageBox::critical( this,
  186.                                tr("Database Connection Error"),
  187.                                tr("Database driver not available!")
  188.                                );
  189.  
  190.  
  191.         return;
  192.     }
  193.  
  194.     qDebug() << "Performing the database driver setup..";
  195.  
  196.     // set database driver properties
  197.     QSqlDatabase databaseConnection = QSqlDatabase::addDatabase( comboDatabaseDriverName->currentText() );
  198.     databaseConnection.setDatabaseName( editDatabaseName->text() );
  199.     databaseConnection.setUserName( editDatabaseUsername->text() );
  200.     databaseConnection.setHostName( editDatabaseHostName->text() );
  201.     databaseConnection.setPassword( editDatabasePassword->text() );
  202.     databaseConnection.setPort( spinBoxDatabasePort->text().toInt() );
  203.  
  204.     if( ! databaseConnection.open() ){
  205.         QMessageBox::critical( this,
  206.                                tr("Database Connection Error"),
  207.                                databaseConnection.lastError().text()
  208.                                );
  209.  
  210.         // disable the connect button and set the focus again
  211.         // on the first field
  212.         buttons->button( QDialogButtonBox::Ok )->setEnabled( false );
  213.         editDatabaseHostName->setFocus();
  214.     }
  215.     else{
  216.         // hide the dialog
  217.         this->hide();
  218.  
  219.         // emit the signal
  220.         qDebug() << "Emitting signal since the database is connected!";
  221.         emit databaseConnect( databaseConnection );
  222.     }
  223. }
  224.  
  225. void DatabaseConnectionDialog::slotPerformConnection()
  226. {
  227.     // perform another check against the user data
  228.     if( slotCheckFormData() )
  229.         doDatabaseConnection();
  230.  
  231. }
  232.  
  233. void DatabaseConnectionDialog::setDatabaseName(const QString &dbName)
  234. {
  235.     editDatabaseName->setText( dbName );
  236. }
  237.  
  238. void DatabaseConnectionDialog::setDatabasePortNumber(int &portNumber)
  239. {
  240.     spinBoxDatabasePort->setValue( portNumber );
  241. }
  242.  
  243. void DatabaseConnectionDialog::setDatabaseHostName(const QString &hostname)
  244. {
  245.     editDatabaseHostName->setText( hostname );
  246. }
  247.  
  248. void DatabaseConnectionDialog::setDatabaseUsername(const QString &username)
  249. {
  250.     editDatabaseUsername->setText( username );
  251. }
  252.  
  253. void DatabaseConnectionDialog::setDatabaseDriverName(const QString &drvName)
  254. {
  255.     int index = comboDatabaseDriverName->findText( drvName );
  256.     if( index >= 0 )
  257.         comboDatabaseDriverName->setCurrentIndex( index );
  258. }
  259.  
  260. void DatabaseConnectionDialog::setDatabasePassword(const QString &pwd)
  261. {
  262.     editDatabasePassword->setText( pwd );
  263. }
  264.  
  265. void DatabaseConnectionDialog::run(bool autoConnect)
  266. {
  267.     bool statusOk = checkFormData();
  268.     if( ! autoConnect || ! statusOk )
  269.         exec();
  270.     else
  271.         doDatabaseConnection();
  272. }

Categories: