File indexing completed on 2024-05-12 15:27:46

0001 /***************************************************************************
0002 File                 : DatabaseManagerWidget.cpp
0003 Project              : LabPlot
0004 Description          : widget for managing database connections
0005 --------------------------------------------------------------------
0006 Copyright            : (C) 2017-2018 Alexander Semke (alexander.semke@web.de)
0007 
0008 ***************************************************************************/
0009 
0010 /***************************************************************************
0011  *                                                                         *
0012  *  This program is free software; you can redistribute it and/or modify   *
0013  *  it under the terms of the GNU General Public License as published by   *
0014  *  the Free Software Foundation; either version 2 of the License, or      *
0015  *  (at your option) any later version.                                    *
0016  *                                                                         *
0017  *  This program is distributed in the hope that it will be useful,        *
0018  *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
0019  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
0020  *  GNU General Public License for more details.                           *
0021  *                                                                         *
0022  *   You should have received a copy of the GNU General Public License     *
0023  *   along with this program; if not, write to the Free Software           *
0024  *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
0025  *   Boston, MA  02110-1301  USA                                           *
0026  *                                                                         *
0027  ***************************************************************************/
0028 
0029 #include "DatabaseManagerWidget.h"
0030 #include "backend/lib/macros.h"
0031 #include "kdefrontend/GuiTools.h"
0032 
0033 #include <KConfig>
0034 #include <KConfigGroup>
0035 #include <KLocalizedString>
0036 #include <KMessageBox>
0037 #include <KSharedConfig>
0038 
0039 #include <QFileDialog>
0040 #include <QTimer>
0041 #include <QSqlDatabase>
0042 #include <QSqlError>
0043 
0044 #ifdef HAVE_KF5_SYNTAX_HIGHLIGHTING
0045 #include <KF5/KSyntaxHighlighting/SyntaxHighlighter>
0046 #include <KF5/KSyntaxHighlighting/Definition>
0047 #include <KF5/KSyntaxHighlighting/Theme>
0048 #endif
0049 
0050 /*!
0051    \class DatabaseManagerWidget
0052    \brief widget for managing database connections, embedded in \c DatabaseManagerDialog.
0053 
0054    \ingroup kdefrontend
0055 */
0056 DatabaseManagerWidget::DatabaseManagerWidget(QWidget* parent, QString conn) : QWidget(parent),
0057     m_initConnName(std::move(conn)) {
0058 
0059     m_configPath = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation).constFirst() +  "sql_connections";
0060 
0061     ui.setupUi(this);
0062 
0063     ui.tbAdd->setIcon(QIcon::fromTheme("list-add"));
0064     ui.tbDelete->setIcon(QIcon::fromTheme("list-remove"));
0065     ui.bOpen->setIcon(QIcon::fromTheme("document-open"));
0066     ui.bTestConnection->setIcon(QIcon::fromTheme("network-connect"));
0067 
0068     ui.tbAdd->setToolTip(i18n("Add new database connection"));
0069     ui.tbDelete->setToolTip(i18n("Delete selected database connection"));
0070     ui.bOpen->setToolTip(i18n("Open database file"));
0071     ui.bTestConnection->setToolTip(i18n("Test selected database connection"));
0072 
0073     //add the list of supported SQL drivers
0074     ui.cbDriver->addItems(QSqlDatabase::drivers());
0075 
0076     //SIGNALs/SLOTs
0077     connect(ui.lwConnections, &QListWidget::currentRowChanged, this, &DatabaseManagerWidget::connectionChanged);
0078     connect(ui.tbAdd, &QToolButton::clicked, this, &DatabaseManagerWidget::addConnection);
0079     connect(ui.tbDelete, &QToolButton::clicked, this, &DatabaseManagerWidget::deleteConnection);
0080     connect(ui.bTestConnection, &QPushButton::clicked, this, &DatabaseManagerWidget::testConnection);
0081     connect(ui.bOpen, &QPushButton::clicked, this, &DatabaseManagerWidget::selectFile);
0082     connect(ui.cbDriver, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &DatabaseManagerWidget::driverChanged);
0083 
0084     connect(ui.leName, &QLineEdit::textChanged, this, &DatabaseManagerWidget::nameChanged);
0085     connect(ui.leDatabase, &QLineEdit::textChanged, this, &DatabaseManagerWidget::databaseNameChanged);
0086     connect(ui.leHost, &QLineEdit::textChanged, this, &DatabaseManagerWidget::hostChanged);
0087     connect(ui.sbPort, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &DatabaseManagerWidget::portChanged);
0088     connect(ui.chkCustomConnection, &QCheckBox::stateChanged, this, &DatabaseManagerWidget::customConnectionEnabledChanged);
0089     connect(ui.teCustomConnection, &QPlainTextEdit::textChanged, this, &DatabaseManagerWidget::customConnectionChanged);
0090     connect(ui.leUserName, &QLineEdit::textChanged, this, &DatabaseManagerWidget::userNameChanged);
0091     connect(ui.lePassword, &QLineEdit::textChanged, this, &DatabaseManagerWidget::passwordChanged);
0092 
0093     QTimer::singleShot(100, this, &DatabaseManagerWidget::loadConnections);
0094 }
0095 
0096 QString DatabaseManagerWidget::connection() const {
0097     if (ui.lwConnections->currentItem())
0098         return ui.lwConnections->currentItem()->text();
0099     else
0100         return QString();
0101 }
0102 
0103 /*!
0104     shows the settings of the currently selected connection
0105  */
0106 void DatabaseManagerWidget::connectionChanged(int index) {
0107     if (m_initializing)
0108         return;
0109 
0110     if (index == -1) {
0111         m_current_connection = nullptr;
0112         return;
0113     }
0114 
0115     m_current_connection = &m_connections[index];
0116     //show the settings for the selected connection
0117     m_initializing = true;
0118     const QString& driver = m_current_connection->driver;
0119     ui.leName->setText(m_current_connection->name);
0120     ui.cbDriver->setCurrentIndex(ui.cbDriver->findText(driver));
0121     ui.leDatabase->setText(m_current_connection->dbName);
0122 
0123     //no host and port number required for file DB and ODBC connections
0124     if (!isFileDB(driver) || !isODBC(driver)) {
0125         ui.leHost->setText(m_current_connection->hostName);
0126         ui.sbPort->setValue(m_current_connection->port);
0127     }
0128 
0129     //no credentials required for file DB
0130     if (!isFileDB(driver)) {
0131         ui.leUserName->setText(m_current_connection->userName);
0132         ui.lePassword->setText(m_current_connection->password);
0133     }
0134 
0135     if (isODBC(driver)) {
0136         ui.chkCustomConnection->setChecked(m_current_connection->customConnectionEnabled);
0137         ui.teCustomConnection->setPlainText(m_current_connection->customConnectionString);
0138     }
0139     m_initializing = false;
0140 }
0141 
0142 void DatabaseManagerWidget::nameChanged(const QString& name) {
0143     //check uniqueness of the provided name
0144     bool unique = true;
0145     for (int i = 0; i < ui.lwConnections->count(); ++i) {
0146         if (ui.lwConnections->currentRow() == i)
0147             continue;
0148 
0149         if (name == ui.lwConnections->item(i)->text()) {
0150             unique = false;
0151             break;
0152         }
0153     }
0154 
0155     if (unique) {
0156         GuiTools::highlight(ui.leName, false);
0157         if (auto item = ui.lwConnections->currentItem()) {
0158             item->setText(name);
0159 
0160             if (!m_initializing) {
0161                 m_current_connection->name = name;
0162                 emit changed();
0163             }
0164         }
0165     } else
0166         GuiTools::highlight(ui.leName, true);
0167 }
0168 
0169 void DatabaseManagerWidget::driverChanged() {
0170     //hide non-relevant fields (like host name, etc.) for file DBs and ODBC
0171     const QString& driver = ui.cbDriver->currentText();
0172 
0173     if (isFileDB(driver)) {
0174         ui.lHost->hide();
0175         ui.leHost->hide();
0176         ui.lPort->hide();
0177         ui.sbPort->hide();
0178         ui.bOpen->show();
0179         ui.gbAuthentication->hide();
0180         ui.lDatabase->setText(i18n("Database:"));
0181         ui.leDatabase->setEnabled(true);
0182         ui.lCustomConnection->hide();
0183         ui.chkCustomConnection->hide();
0184         ui.teCustomConnection->hide();
0185     } else if (isODBC(driver)) {
0186         ui.lHost->hide();
0187         ui.leHost->hide();
0188         ui.lPort->hide();
0189         ui.sbPort->hide();
0190         ui.bOpen->hide();
0191         ui.gbAuthentication->show();
0192         ui.lDatabase->setText(i18n("Data Source Name:"));
0193         ui.lCustomConnection->show();
0194         ui.chkCustomConnection->show();
0195         const bool customConnection = ui.chkCustomConnection->isChecked();
0196         ui.leDatabase->setEnabled(!customConnection);
0197         ui.teCustomConnection->setVisible(customConnection);
0198 
0199 #ifdef HAVE_KF5_SYNTAX_HIGHLIGHTING
0200         //syntax highlighting for custom ODBC string
0201         if (!m_highlighter) {
0202             m_highlighter = new KSyntaxHighlighting::SyntaxHighlighter(ui.teCustomConnection->document());
0203             m_highlighter->setDefinition(m_repository.definitionForName("INI Files"));
0204             m_highlighter->setTheme(  (palette().color(QPalette::Base).lightness() < 128)
0205                                         ? m_repository.defaultTheme(KSyntaxHighlighting::Repository::DarkTheme)
0206                                         : m_repository.defaultTheme(KSyntaxHighlighting::Repository::LightTheme) );
0207         }
0208 #endif
0209     } else {
0210         ui.lHost->show();
0211         ui.leHost->show();
0212         ui.lPort->show();
0213         ui.sbPort->show();
0214         ui.sbPort->setValue(defaultPort(driver));
0215         ui.bOpen->hide();
0216         ui.gbAuthentication->show();
0217         ui.lDatabase->setText(i18n("Database:"));
0218         ui.leDatabase->setEnabled(true);
0219         ui.lCustomConnection->hide();
0220         ui.chkCustomConnection->hide();
0221         ui.teCustomConnection->hide();
0222     }
0223 
0224     if (m_initializing)
0225         return;
0226 
0227     if (m_current_connection)
0228         m_current_connection->driver = driver;
0229     emit changed();
0230 }
0231 
0232 void DatabaseManagerWidget::selectFile() {
0233     KConfigGroup conf(KSharedConfig::openConfig(), QLatin1String("DatabaseManagerWidget"));
0234     QString dir = conf.readEntry(QLatin1String("LastDir"), "");
0235     QString path = QFileDialog::getOpenFileName(this, i18n("Select the database file"), dir);
0236     if (path.isEmpty())
0237         return; //cancel was clicked in the file-dialog
0238 
0239     int pos = path.lastIndexOf(QLatin1String("/"));
0240     if (pos != -1) {
0241         QString newDir = path.left(pos);
0242         if (newDir != dir)
0243             conf.writeEntry(QLatin1String("LastDir"), newDir);
0244     }
0245 
0246     ui.leDatabase->setText(path);
0247 }
0248 
0249 void DatabaseManagerWidget::hostChanged() {
0250     if (m_initializing)
0251         return;
0252 
0253     if (m_current_connection)
0254         m_current_connection->hostName = ui.leHost->text();
0255 
0256     //don't allow to try to connect if no hostname provided
0257     ui.bTestConnection->setEnabled( !ui.leHost->text().simplified().isEmpty() );
0258 
0259     emit changed();
0260 }
0261 
0262 void DatabaseManagerWidget::portChanged() {
0263     if (m_initializing)
0264         return;
0265 
0266     if (m_current_connection)
0267         m_current_connection->port = ui.sbPort->value();
0268     emit changed();
0269 }
0270 
0271 void DatabaseManagerWidget::databaseNameChanged() {
0272     QString dbName{ui.leDatabase->text().simplified()};
0273     if (isFileDB(ui.cbDriver->currentText())) {
0274 #ifdef HAVE_WINDOWS
0275         if (!dbName.isEmpty() && dbName.at(1) != QLatin1String(":"))
0276 #else
0277         if (!dbName.isEmpty() && dbName.at(0) != QLatin1String("/"))
0278 #endif
0279             dbName = QDir::homePath() + QLatin1String("/") + dbName;
0280 
0281         if (!dbName.isEmpty()) {
0282             bool fileExists = QFile::exists(dbName);
0283             GuiTools::highlight(ui.leName, !fileExists);
0284         } else {
0285             ui.leDatabase->setStyleSheet(QString());
0286         }
0287     } else {
0288         ui.leDatabase->setStyleSheet(QString());
0289     }
0290 
0291     //don't allow to try to connect if no database name was provided
0292     ui.bTestConnection->setEnabled(!dbName.isEmpty());
0293 
0294     if (m_initializing)
0295         return;
0296 
0297     if (m_current_connection)
0298         m_current_connection->dbName = dbName;
0299     emit changed();
0300 }
0301 
0302 void DatabaseManagerWidget::customConnectionEnabledChanged(int state) {
0303     //in case custom connection string is provided:
0304     //disable the line edit for the database name
0305     //and hide the textedit for the connection string
0306     ui.leDatabase->setEnabled(state != Qt::Checked);
0307     ui.teCustomConnection->setVisible(state == Qt::Checked);
0308 
0309     if (state == Qt::Checked)
0310         ui.teCustomConnection->setFocus();
0311     else
0312         ui.leDatabase->setFocus();
0313 
0314     if (m_current_connection)
0315         m_current_connection->customConnectionEnabled = (state == Qt::Checked);
0316     emit changed();
0317 }
0318 
0319 void DatabaseManagerWidget::customConnectionChanged() {
0320     if (m_current_connection)
0321         m_current_connection->customConnectionString = ui.teCustomConnection->toPlainText();
0322     emit changed();
0323 }
0324 
0325 void DatabaseManagerWidget::userNameChanged() {
0326     if (m_initializing)
0327         return;
0328 
0329     if (m_current_connection)
0330         m_current_connection->userName = ui.leUserName->text();
0331     emit changed();
0332 }
0333 
0334 void DatabaseManagerWidget::passwordChanged() {
0335     if (m_initializing)
0336         return;
0337 
0338     if (m_current_connection)
0339         m_current_connection->password = ui.lePassword->text();
0340     emit changed();
0341 }
0342 
0343 void DatabaseManagerWidget::addConnection() {
0344     DEBUG("Adding new connection");
0345     SQLConnection conn;
0346     conn.name = uniqueName();
0347     conn.driver = ui.cbDriver->currentText();
0348     conn.hostName = QLatin1String("localhost");
0349 
0350     if (!isFileDB(conn.driver) && !isODBC(conn.driver))
0351         conn.port = defaultPort(conn.driver);
0352 
0353     m_connections.append(conn);
0354     ui.lwConnections->addItem(conn.name);
0355     ui.lwConnections->setCurrentRow(m_connections.size()-1);
0356 
0357     m_initializing = true;
0358     //call this to properly update the widgets for the very first added connection
0359     driverChanged();
0360     m_initializing = false;
0361 
0362     //we have now more then one connection, enable widgets
0363     ui.tbDelete->setEnabled(true);
0364     ui.leName->setEnabled(true);
0365     ui.leDatabase->setEnabled(true);
0366     ui.cbDriver->setEnabled(true);
0367     ui.leHost->setEnabled(true);
0368     ui.sbPort->setEnabled(true);
0369     ui.leUserName->setEnabled(true);
0370     ui.lePassword->setEnabled(true);
0371 }
0372 
0373 /*!
0374     removes the current selected connection.
0375  */
0376 void DatabaseManagerWidget::deleteConnection() {
0377     int ret = KMessageBox::questionYesNo(this,
0378                 i18n("Do you really want to delete the connection '%1'?", ui.lwConnections->currentItem()->text()),
0379                 i18n("Delete Connection"));
0380     if (ret != KMessageBox::Yes)
0381         return;
0382 
0383     //remove the current selected connection
0384     int row = ui.lwConnections->currentRow();
0385     if (row != -1) {
0386         m_connections.removeAt(row);
0387         m_initializing = true;
0388         delete ui.lwConnections->takeItem(row);
0389         m_initializing = false;
0390     }
0391 
0392     //show the connection for the item that was automatically selected afte the deletion
0393     connectionChanged(ui.lwConnections->currentRow());
0394 
0395     //disable widgets if there're no connections anymore
0396     if (m_connections.size() == 0) {
0397         m_initializing = true;
0398         ui.tbDelete->setEnabled(false);
0399         ui.bTestConnection->setEnabled(false);
0400         ui.leName->clear();
0401         ui.leName->setEnabled(false);
0402         ui.leDatabase->clear();
0403         ui.leDatabase->setEnabled(false);
0404         ui.cbDriver->setEnabled(false);
0405         ui.leHost->clear();
0406         ui.leHost->setEnabled(false);
0407         ui.sbPort->clear();
0408         ui.sbPort->setEnabled(false);
0409         ui.leUserName->clear();
0410         ui.leUserName->setEnabled(false);
0411         ui.lePassword->clear();
0412         ui.lePassword->setEnabled(false);
0413         ui.teCustomConnection->clear();
0414         m_initializing = false;
0415     }
0416 
0417     emit changed();
0418 }
0419 
0420 void DatabaseManagerWidget::loadConnections() {
0421     QDEBUG("Loading connections from " << m_configPath);
0422 
0423     m_initializing = true;
0424 
0425     KConfig config(m_configPath, KConfig::SimpleConfig);
0426     for (const auto& groupName : config.groupList()) {
0427         const KConfigGroup& group = config.group(groupName);
0428         SQLConnection conn;
0429         conn.name = groupName;
0430         conn.driver = group.readEntry("Driver","");
0431         conn.dbName = group.readEntry("DatabaseName", "");
0432         if (!isFileDB(conn.driver) && !isODBC(conn.driver)) {
0433             conn.hostName = group.readEntry("HostName", "localhost");
0434             conn.port = group.readEntry("Port", defaultPort(conn.driver));
0435         }
0436         if (!isFileDB(conn.driver)) {
0437             conn.userName = group.readEntry("UserName", "root");
0438             conn.password = group.readEntry("Password", "");
0439         }
0440 
0441         if (isODBC(conn.driver)) {
0442             conn.customConnectionEnabled = group.readEntry("CustomConnectionEnabled", false);
0443             conn.customConnectionString = group.readEntry("CustomConnectionString", "");
0444         }
0445         m_connections.append(conn);
0446         ui.lwConnections->addItem(conn.name);
0447     }
0448 
0449     //show the first connection if available, create a new connection otherwise
0450     if (m_connections.size()) {
0451         if (!m_initConnName.isEmpty()) {
0452             QListWidgetItem* item = ui.lwConnections->findItems(m_initConnName, Qt::MatchExactly).constFirst();
0453             if (item)
0454                 ui.lwConnections->setCurrentItem(item);
0455             else
0456                 ui.lwConnections->setCurrentRow(ui.lwConnections->count()-1);
0457         } else {
0458             ui.lwConnections->setCurrentRow(ui.lwConnections->count()-1);
0459         }
0460     } else
0461         addConnection();
0462 
0463     //show/hide the driver dependent options
0464     driverChanged();
0465 
0466     m_initializing = false;
0467 
0468     //show the settings of the current connection
0469     connectionChanged(ui.lwConnections->currentRow());
0470 }
0471 
0472 void DatabaseManagerWidget::saveConnections() {
0473     QDEBUG("Saving connections to " + m_configPath);
0474     //delete saved connections
0475     KConfig config(m_configPath, KConfig::SimpleConfig);
0476     for (const auto& group : config.groupList())
0477         config.deleteGroup(group);
0478 
0479     //save connections
0480     for (const auto& conn : m_connections) {
0481         KConfigGroup group = config.group(conn.name);
0482         group.writeEntry("Driver", conn.driver);
0483         group.writeEntry("DatabaseName", conn.dbName);
0484         if (!isFileDB(conn.driver) && !isODBC(conn.driver)) {
0485             group.writeEntry("HostName", conn.hostName);
0486             group.writeEntry("Port", conn.port);
0487         }
0488 
0489         if (!isFileDB(conn.driver)) {
0490             group.writeEntry("UserName", conn.userName);
0491             group.writeEntry("Password", conn.password);
0492         }
0493 
0494         if (isODBC(conn.driver)) {
0495             group.writeEntry("CustomConnectionEnabled", conn.customConnectionEnabled);
0496             group.writeEntry("CustomConnectionString", conn.customConnectionString);
0497         }
0498     }
0499 
0500     config.sync();
0501 }
0502 
0503 void DatabaseManagerWidget::testConnection() {
0504     if (!m_current_connection)
0505         return;
0506 
0507     //don't allow to test the connection for file DBs if the file doesn't exist
0508     if (isFileDB(ui.cbDriver->currentText())) {
0509         QString fileName{ui.leDatabase->text()};
0510 #ifdef HAVE_WINDOWS
0511         if ( !fileName.isEmpty() && fileName.at(1) != QLatin1String(":"))
0512 #else
0513         if ( !fileName.isEmpty() && fileName.at(0) != QLatin1String("/"))
0514 #endif
0515             fileName = QDir::homePath() + QLatin1String("/") + fileName;
0516 
0517         if (!QFile::exists(fileName)) {
0518             KMessageBox::error(this, i18n("Failed to connect to the database '%1'.", m_current_connection->dbName),
0519                                  i18n("Connection Failed"));
0520             return;
0521         }
0522     }
0523 
0524     WAIT_CURSOR;
0525     const QString& driver = m_current_connection->driver;
0526     QSqlDatabase db = QSqlDatabase::addDatabase(driver);
0527     db.close();
0528 
0529     //db name or custom connection string for ODBC, if available
0530     if (isODBC(driver) && m_current_connection->customConnectionEnabled)
0531         db.setDatabaseName(m_current_connection->customConnectionString);
0532     else
0533         db.setDatabaseName(m_current_connection->dbName);
0534 
0535     //host and port number, if required
0536     if (!isFileDB(driver) && !isODBC(driver)) {
0537         db.setHostName(m_current_connection->hostName);
0538         db.setPort(m_current_connection->port);
0539     }
0540 
0541     //authentication, if required
0542     if (!isFileDB(driver)) {
0543         db.setUserName(m_current_connection->userName);
0544         db.setPassword(m_current_connection->password);
0545     }
0546 
0547     if (db.isValid() && db.open() && db.isOpen()) {
0548         db.close();
0549         RESET_CURSOR;
0550         KMessageBox::information(this, i18n("Connection to the database '%1' was successful.", m_current_connection->dbName),
0551                                  i18n("Connection Successful"));
0552     } else {
0553         RESET_CURSOR;
0554         KMessageBox::error(this, i18n("Failed to connect to the database '%1'.", m_current_connection->dbName) +
0555                                  QLatin1String("\n\n") + db.lastError().databaseText(),
0556                                  i18n("Connection Failed"));
0557     }
0558 }
0559 
0560 /*!
0561  * returns \c true if \c driver is for file databases like Sqlite or for ODBC datasources.
0562  * returns \c false otherwise.
0563  * for file databases and for ODBC/ODBC3, only the name of the database/ODBC-datasource is required.
0564  * used to show/hide relevant connection settings widgets.
0565  */
0566 bool DatabaseManagerWidget::isFileDB(const QString& driver) {
0567     //QSQLITE, QSQLITE3
0568     return driver.startsWith(QLatin1String("QSQLITE"));
0569 }
0570 
0571 bool DatabaseManagerWidget::isODBC(const QString& driver) {
0572     //QODBC, QODBC3
0573     return driver.startsWith(QLatin1String("QODBC"));
0574 }
0575 
0576 QString DatabaseManagerWidget::uniqueName() {
0577     QString name = i18n("New connection");
0578 
0579     //TODO
0580     QStringList connection_names;
0581     for (int row = 0; row < ui.lwConnections->count(); row++)
0582         connection_names << ui.lwConnections->item(row)->text();
0583 
0584     if (!connection_names.contains(name))
0585         return name;
0586 
0587     QString base = name;
0588     int last_non_digit;
0589     for (last_non_digit = base.size()-1; last_non_digit>=0 &&
0590             base[last_non_digit].category() == QChar::Number_DecimalDigit; --last_non_digit)
0591         base.chop(1);
0592 
0593     if (last_non_digit >=0 && base[last_non_digit].category() != QChar::Separator_Space)
0594         base.append(" ");
0595 
0596     int new_nr = name.rightRef(name.size() - base.size()).toInt();
0597     QString new_name;
0598     do
0599         new_name = base + QString::number(++new_nr);
0600     while (connection_names.contains(new_name));
0601 
0602     return new_name;
0603 }
0604 
0605 int DatabaseManagerWidget::defaultPort(const QString& driver) const {
0606     // QDB2     IBM DB2 (version 7.1 and above)
0607     // QIBASE   Borland InterBase
0608     // QMYSQL   MySQL
0609     // QOCI     Oracle Call Interface Driver
0610     // QODBC    Open Database Connectivity (ODBC) - Microsoft SQL Server and other ODBC-compliant databases
0611     // QPSQL    PostgreSQL (versions 7.3 and above)
0612 
0613     if (driver == "QDB2")
0614         return 50000;
0615     else if (driver == "QIBASE")
0616         return 3050;
0617     else if (driver == "QMYSQL3" || driver == "QMYSQL")
0618         return 3306;
0619     else if (driver == "QOCI")
0620         return 1521;
0621     else if (driver == "QODBC")
0622         return 1433;
0623     else if (driver == "QPSQL")
0624         return 5432;
0625     else
0626         return 0;
0627 }