File indexing completed on 2025-07-13 03:32:33

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