DatabaseConnectionDialog/es

From Qt Wiki
Jump to navigation Jump to search


Dialog de Conexión a Base de Datos

Este fragmento de código muestra cómo implementar un Dialog de base de datos en general que le pedirá al usuario propiedades generales de conexión de la base de datos (nombre de usuario, contraseña, nombre de host, etc.), Así como un combo con todos los controladores de base de datos disponible. El Dialog proporciona también una señal que pasara la conexión de base de datos (si está establecida) para que los componentes de terceros puedan utilizar dicha conexión.

Uso

El uso del Dialog vendria siendo algo asi:

DatabaseConnectionDialog* dialog = new DatabaseConnectionDialog(this);

// opcional: preparando los datos que mostraremos al usuario en un formulario auto-completado
 dialog->setDatabaseName( "mydb" );
 dialog->setDatabasePortNumber( 1234 );
 dialog->setDatabaseHostName( "localhost" );
 dialog->setDatabaseUsername( "luca" );
 dialog->setDatabaseDriverName( "QPSQL" );
 dialog->setDatabasePassword( "pwd" );

// habilitando el botón de conectar si todos los datos son correctos
 dialog->checkFormData();
 // contactando la signal del dialog con el slot donde usaremos la conexion
 connect( dialog,
 SIGNAL (databaseConnect(QSqlDatabase&)),
 this,
 SLOT (slotHandleNewDatabaseConnection(QSqlDatabase&)));

// mostramos el dialog (sin auto-conexion)
 dialog->run( false );

El dialog nos permite pre-inicializar los campos del formulario, asi como el modo de auto-conectar que hace que la conexión sea automática si todos los datos están en su lugar. Notemos que este dialog puede ser perfeccionado de varias formas, y representa además un punto de partida para una conexión a base de datos más específica.

Modo Auto-Conectar

Cuando el método

run()

se invoca puede especificarse el modo de autoconectar con el valor booleano de true. En este modo si todos los campos estan llenos el dialog inmediatamente intenta conectarse a la base de datos, y en caso de lograrlo transparente al usuario emite el signal.

En caso de que los datos del formulario no estén completos o la conexión no se pueda establecer el dialog se muestra nuevamente. Si el modo de autoconectar esta apagado (parámetro = false) el dialog siempre se mostrará.

Código de fuente

El siguiente código es del fichero de encabezado (header):

/*!
 * databasedialog.h
 */
#ifndef DATABASEDIALOG_H
#define DATABASEDIALOG_H

#include <QDialog>
#include <QLabel>
#include <QLineEdit>
#include <QComboBox>
#include <QSpinBox>
#include <QDialogButtonBox>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QGridLayout>
#include <QSqlDatabase>
#include <QString>
#include <QMessageBox>
#include <QDebug>
#include <QSqlError>
#include <QPushButton>
#include <QGroupBox>

class DatabaseConnectionDialog : public QDialog
{
 Q_OBJECT

private:

 /*!
 * La etiqueta para el driver de la base de datos.
 */
 QLabel''' labelDatabaseDriverName;

/*!
 * La etiqueta para el puerto TCP/IP que la base de datos
 * utiliza para las conexiones entrantes.
 */
 QLabel''' labelDatabasePort;

/*!
 * La etiqueta para el nombre de la base de datos.
 */
 QLabel''' labelDatabaseName;

/*!
 * La etiqueta para el nombre de la máquina.
 */
 QLabel''' labelDatabaseHostName;

/*!
 * La etiqueta para el nombre de usuario.
 */
 QLabel''' labelDatabaseUsername;

/*!
 * La etiqueta para la contraseña.
 */
 QLabel''' labelDatabasePassword;

/*!
 * Una etiqueta para mostrar la URL de la conexión
 * a la base de datos.
 */
 QLabel''' labelDatabaseURL;

/*!
 * El nombre de la base de datos a la que el
 * usuario desea conectarse.
 */
 QLineEdit''' editDatabaseName;

/*!
 * El nombre del servidor donde se encuentra la base
 * de datos.
 */
 QLineEdit''' editDatabaseHostName;

/*!
 * El puerto de escucha del servidor de base de datos.
 */
 QSpinBox''' spinBoxDatabasePort;

/*!
 * El usuario para la conexión a la base de datos.
 */
 QLineEdit''' editDatabaseUsername;

/*!
 * Para poner la contraseña de la conexión a la base de datos.
 */
 QLineEdit''' editDatabasePassword;

/*!
 * El combo desde donde el usuario puede seleccionar el
 * driver y tipo de base de datos.
 */
 QComboBox''' comboDatabaseDriverName;

/*!
 * Un Dialog para mostrar los botones de conexión
 * conectar/cancelar.
 */
 QDialogButtonBox''' buttons;

/*!
 * Un método para crear todos los componentes del dialog
 * y alinearlos correctamente.
 */
 void setUpGUI();

 /*!
 * Para buscar y generar el combo con los controladores disponibles
 * para establecer la conexión con la base de datos.
 */
 void findAvailableDrivers();


 /*!
 * Para realizar la conexión con la base de datos
 * y emitir la señal para que pueda ser usada por otros.
 */
 void doDatabaseConnection();

public:
 explicit DatabaseConnectionDialog(QWidget '''parent = 0);

 /*!
 * Para asignar el nombre de la base de datos.
 * dbName
 */
 void setDatabaseName( const QString&amp;amp; dbName );

 /*!
 * Para asignar el puerto de escucha del servidor de base de datos.
 * portNumber
 */
 void setDatabasePortNumber( int&amp;amp; portNumber );

 /*!
 * Para asignar el nombre del servidor (nombre mnemónico).
 * hostname
 */
 void setDatabaseHostName( const QString&amp;amp; hostname );

 /*!
 * Para asignar el usuario de conexion.
 * username
 */
 void setDatabaseUsername( const QString&amp;amp; username );

 /*!
 * Para seleccionar el nombre del controlador.
 * drvName (ademas del tipo de base de datos)
 */
 void setDatabaseDriverName( const QString&amp;amp; drvName );

 /*!
 * Para asignar la contraseña.
 * pwd
 */
 void setDatabasePassword( const QString&amp;amp; pwd );


 /*!
 * Realizar un chequeo contra los datos introducidos para habilitar/deshabilitar
 * el boton de conectar dependiendo del completado o no del formulario.
 '''true Devuelve verdadero si es satisfactoria la conexion
*/
 bool checkFormData();

/*!
 * Realiza la conexion o muestra al usuario el Dialog en caso
 * de no haber completado el llenado o no haber podido realizar la
 * conexion automatica.
 * autoConnect si es ''true'' intenta conectarse automaticamente
 * si los datos estan completos, o avisa al usuario de los datos faltantes
 * Si es ''false'' simplemente muestra el Dialog y espera.
 */
 void run( bool autoConnect );


signals:

 /*!
 * Pasa la conexion en caso de que sea satisfactoria
 * databaseConnection Objeto
 */
 void databaseConnect( QSqlDatabase&amp;amp; databaseConnection );

public slots:

 /*!
 * Chequea si el usuario ha entrado los datos suficientes
 * para intentar conectarse a la base de datos
 */
 bool slotCheckFormData();


 /*!
 * Realiza la conexion.
 */
 void slotPerformConnection();

};

#endif // DATABASEDIALOG_H

A continuación la implementación de la clase:

#include "databasedialog.h"

DatabaseConnectionDialog::DatabaseConnectionDialog(QWidget parent) :

QDialog(parent)

{

// este dialog es modal
setModal( true );
// titulo del dialog
setWindowTitle( tr("Conexion a base de datos") );
// seteando cada componente GUI
setUpGUI();
// cargando los controladores
findAvailableDrivers();

}

void DatabaseConnectionDialog::setUpGUI() {


// creando todos los gui components
labelDatabaseDriverName = new QLabel( tr("Database Type (driver name)"), this );
labelDatabasePort = new QLabel( tr("TCP/IP Port Number"), this );
labelDatabaseName = new QLabel( tr("Database Name"), this );
labelDatabaseHostName = new QLabel( tr("Host Name"), this );
labelDatabaseUsername = new QLabel( tr("Username"), this );
labelDatabasePassword = new QLabel( tr("Password"), this );
labelDatabaseURL = new QLabel( this );
labelDatabaseURL->setAlignment( Qt::AlignCenter );
spinBoxDatabasePort = new QSpinBox( this );
spinBoxDatabasePort->setMaximum( 9999 );
spinBoxDatabasePort->setMinimum( 100 );
spinBoxDatabasePort->setSingleStep( 1 );
comboDatabaseDriverName = new QComboBox( this );
comboDatabaseDriverName->setEditable( false );


editDatabaseName = new QLineEdit( this );
editDatabaseHostName = new QLineEdit( this );
editDatabaseUsername = new QLineEdit( this );
editDatabasePassword = new QLineEdit( this );
editDatabasePassword->setEchoMode( QLineEdit::Password );
connect( editDatabaseName,
SIGNAL (editingFinished()),
this,
SLOT (slotCheckFormData()) );
connect( editDatabaseHostName,
SIGNAL (editingFinished()),
this,
SLOT (slotCheckFormData()) );
connect( editDatabaseUsername,
SIGNAL (editingFinished()),
this,
SLOT (slotCheckFormData()) );
connect( editDatabasePassword,
SIGNAL (editingFinished()),
this,
SLOT (slotCheckFormData()) );
connect( editDatabasePassword,
SIGNAL (returnPressed()),
this,
SLOT (slotCheckFormData()) );


// creando la caja de botones
buttons = new QDialogButtonBox( this );
buttons->addButton( QDialogButtonBox::Ok );
buttons->addButton( QDialogButtonBox::Cancel );
QPushButton okButton = buttons->button( QDialogButtonBox::Ok );
okButton->setText( tr( "Connect!" ) );
okButton->setEnabled( false );
connect( buttons,
SIGNAL (accepted()),
this,
SLOT (slotPerformConnection()));
connect( buttons,
SIGNAL (rejected()),
this,
SLOT (close()));

// configurando margen vertical para mostrar los componentes

QVBoxLayout* verticalLayout = new QVBoxLayout( this );

// create a grid layout to add all the components

QGridLayout* formGridLayout = new QGridLayout( this );
QGroupBox* gridGroupBox = new QGroupBox( this );
gridGroupBox->setTitle( tr("Database connection properties" ) );
formGridLayout->addWidget( labelDatabaseDriverName, 0, 0 );
formGridLayout->addWidget( comboDatabaseDriverName, 0, 1 );
labelDatabaseDriverName->setBuddy( comboDatabaseDriverName );
formGridLayout->addWidget( labelDatabaseHostName, 1, 0 );
formGridLayout->addWidget( editDatabaseHostName, 1, 1);
labelDatabaseHostName->setBuddy( editDatabaseHostName );
formGridLayout->addWidget( labelDatabasePort, 2, 0 );
formGridLayout->addWidget( spinBoxDatabasePort, 2, 1 );
labelDatabasePort->setBuddy( spinBoxDatabasePort );
formGridLayout->addWidget( labelDatabaseName, 3, 0 );
formGridLayout->addWidget( editDatabaseName , 3, 1 );
labelDatabaseName->setBuddy( editDatabaseName );
formGridLayout->addWidget( labelDatabaseUsername, 4, 0 );
formGridLayout->addWidget( editDatabaseUsername, 4, 1 );
labelDatabaseUsername->setBuddy( editDatabaseUsername );
formGridLayout->addWidget( labelDatabasePassword, 5, 0 );
formGridLayout->addWidget( editDatabasePassword, 5, 1 );
labelDatabasePassword->setBuddy( editDatabasePassword );
// agregar todos los elementos al groupbox
gridGroupBox->setLayout( formGridLayout );

// agregando un nuevo groupbox que contenga la URL de la conexion

QGroupBox* urlGroupBox = new QGroupBox( this );
urlGroupBox->setTitle( tr( "Database URL" ) );
QHBoxLayout* urlLayout = new QHBoxLayout( this );
urlLayout->addWidget( labelDatabaseURL );
urlGroupBox->setLayout( urlLayout );

// todos los margenes juntos

verticalLayout->addWidget( gridGroupBox );
verticalLayout->addStretch();
verticalLayout->addWidget( urlGroupBox );
verticalLayout->addWidget( buttons );

comboDatabaseDriverName->setFocus(); }

void DatabaseConnectionDialog::findAvailableDrivers() {

// eliminando todos los elementos
comboDatabaseDriverName->clear();

// rellenando el combo con los controladores disponibles

foreach( QString driverName, QSqlDatabase::drivers() )
comboDatabaseDriverName->addItem( driverName );

}

bool DatabaseConnectionDialog::slotCheckFormData() {

return checkFormData();

}

bool DatabaseConnectionDialog::checkFormData(){

if( editDatabaseName->text().isEmpty()
|| editDatabaseHostName->text().isEmpty()
|| editDatabaseUsername->text().isEmpty()
|| editDatabasePassword->text().isEmpty() )
buttons->button( QDialogButtonBox::Ok )->setEnabled( false );
else{
// enable the connect button and give focus
buttons->button( QDialogButtonBox::Ok )->setEnabled( true );
buttons->button( QDialogButtonBox::Ok )->setFocus();
}


// si la conexion se puede establecer (o al menos intentar)
// mostrar la URL
if( buttons->button( QDialogButtonBox::Ok )->isEnabled() )
labelDatabaseURL->setText( comboDatabaseDriverName->currentText()
+ "://"
+ editDatabaseUsername->text()
+ "@"
+ editDatabaseHostName->text()
+ "/"
+ editDatabaseName->text() );
else
labelDatabaseURL->setText( "" );

return buttons->button( QDialogButtonBox::Ok )->isEnabled(); }

void DatabaseConnectionDialog::doDatabaseConnection() {

// chequear que el controlador de la base de datos esta realmente disponible
// (no deberia suceder pero…)
if( ! QSqlDatabase::isDriverAvailable( comboDatabaseDriverName->currentText() ) ){
QMessageBox::critical( this,
tr("Database Connection Error"),
tr("Database driver not available!")
);

return;

}

qDebug() << "Realizando la configuracion del controlador..";

// configurar las propiedades del controlador

QSqlDatabase databaseConnection = QSqlDatabase::addDatabase( comboDatabaseDriverName->currentText() );
databaseConnection.setDatabaseName( editDatabaseName->text() );
databaseConnection.setUserName( editDatabaseUsername->text() );
databaseConnection.setHostName( editDatabaseHostName->text() );
databaseConnection.setPassword( editDatabasePassword->text() );
databaseConnection.setPort( spinBoxDatabasePort->text().toInt() );

if( ! databaseConnection.open() ){

QMessageBox::critical( this,
tr("Database Connection Error"),
databaseConnection.lastError().text()
);

// deshabilitando el boton de conectar y situando el cursor

// en el primer campo
buttons->button( QDialogButtonBox::Ok )->setEnabled( false );
editDatabaseHostName->setFocus();
}
else{
// ocultar el dialog
this->hide();

// emitir la señal

qDebug() << "Emitiendo la señal indicando la conexion satisfactoria con la base de datos!";
emit databaseConnect( databaseConnection );
}

}

void DatabaseConnectionDialog::slotPerformConnection() {

// realizando otro chequeo contra los datos del usuario
if( slotCheckFormData() )
doDatabaseConnection();

}

void DatabaseConnectionDialog::setDatabaseName(const QString &dbName) {

editDatabaseName->setText( dbName );

}

void DatabaseConnectionDialog::setDatabasePortNumber(int &portNumber) {

spinBoxDatabasePort->setValue( portNumber );

}

void DatabaseConnectionDialog::setDatabaseHostName(const QString &hostname) {

editDatabaseHostName->setText( hostname );

}

void DatabaseConnectionDialog::setDatabaseUsername(const QString &username) {

editDatabaseUsername->setText( username );

}

void DatabaseConnectionDialog::setDatabaseDriverName(const QString &drvName) {

int index = comboDatabaseDriverName->findText( drvName );
if( index >= 0 )
comboDatabaseDriverName->setCurrentIndex( index );

}

void DatabaseConnectionDialog::setDatabasePassword(const QString &pwd) {

editDatabasePassword->setText( pwd );

}

void DatabaseConnectionDialog::run(bool autoConnect) {

bool statusOk = checkFormData();
if( ! autoConnect || ! statusOk )
exec();
else
doDatabaseConnection();

}