File indexing completed on 2024-05-12 16:40:53
0001 /* This file is part of the KDE project 0002 Copyright (C) 2005-2014 Jarosław Staniek <staniek@kde.org> 0003 Copyright (C) 2014 Roman Shtemberko <shtemberko@gmail.com> 0004 0005 This program is free software; you can redistribute it and/or 0006 modify it under the terms of the GNU Library General Public 0007 License as published by the Free Software Foundation; either 0008 version 2 of the License, or (at your option) any later version. 0009 0010 This program is distributed in the hope that it will be useful, 0011 but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 Library General Public License for more details. 0014 0015 You should have received a copy of the GNU Library General Public License 0016 along with this program; see the file COPYING. If not, write to 0017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 * Boston, MA 02110-1301, USA. 0019 */ 0020 0021 #include "kexidbconnectionwidget.h" 0022 #include <kexi.h> 0023 #include <kexiguimsghandler.h> 0024 #include <widget/KexiDBPasswordDialog.h> 0025 #include "kexidbdrivercombobox.h" 0026 #include <KexiIcon.h> 0027 #include <kexiutils/utils.h> 0028 0029 #include <KDbConnection> 0030 0031 #include <KStandardAction> 0032 0033 #include <QCheckBox> 0034 #include <QVBoxLayout> 0035 #include <QHBoxLayout> 0036 #include <QWhatsThis> 0037 #include <QDialogButtonBox> 0038 #include <QPushButton> 0039 0040 //! Templorary hides db list 0041 //! @todo reenable this when implemented 0042 #define NO_LOAD_DB_LIST 0043 0044 // @internal 0045 class Q_DECL_HIDDEN KexiDBConnectionWidget::Private 0046 { 0047 public: 0048 Private() 0049 : connectionOnly(false) { 0050 } 0051 0052 QPushButton *btnSaveChanges, *btnTestConnection; 0053 bool connectionOnly; 0054 KexiProjectData data; 0055 KexiDBDriverComboBox *driversCombo; 0056 QAction *savePasswordHelpAction; 0057 }; 0058 0059 class Q_DECL_HIDDEN KexiDBConnectionDialog::Private 0060 { 0061 public: 0062 Private() { } 0063 0064 KexiDBConnectionTabWidget *tabWidget; 0065 QDialogButtonBox *buttonBox; 0066 }; 0067 0068 //--------- 0069 0070 KexiDBConnectionWidget::KexiDBConnectionWidget(QWidget* parent) 0071 : QWidget(parent) 0072 , d(new Private) 0073 { 0074 setupUi(this); 0075 setObjectName("KexiConnectionSelectorWidget"); 0076 iconLabel->setPixmap(koDesktopIconCStr(Kexi::serverIconName())); 0077 0078 QVBoxLayout *driversComboLyr = new QVBoxLayout(frmEngine); 0079 driversComboLyr->setMargin(0); 0080 d->driversCombo = new KexiDBDriverComboBox(frmEngine, KexiDBDriverComboBox::ShowServerDrivers); 0081 driversComboLyr->addWidget(d->driversCombo); 0082 frmEngine->setFocusProxy(d->driversCombo); 0083 lblEngine->setBuddy(d->driversCombo); 0084 QWidget::setTabOrder(lblEngine, d->driversCombo); 0085 0086 #ifdef NO_LOAD_DB_LIST 0087 btnLoadDBList->hide(); 0088 #endif 0089 btnLoadDBList->setIcon(koIcon("view-refresh")); 0090 btnLoadDBList->setToolTip(xi18n("Load database list from the server")); 0091 btnLoadDBList->setWhatsThis( 0092 xi18n("Loads database list from the server, so you can select one using the <interface>Name</interface> combo box.")); 0093 0094 btnSavePasswordHelp->setIcon(koIcon("help-about")); 0095 btnSavePasswordHelp->setToolTip(KStandardAction::whatsThis(0, 0, btnSavePasswordHelp)->text().remove('&')); 0096 d->savePasswordHelpAction = QWhatsThis::createAction(chkSavePassword); 0097 connect(btnSavePasswordHelp, SIGNAL(clicked()), this, SLOT(slotShowSavePasswordHelp())); 0098 0099 QHBoxLayout *hbox = new QHBoxLayout(frmBottom); 0100 hbox->addStretch(2); 0101 d->btnSaveChanges = new QPushButton(frmBottom); 0102 KGuiItem::assign(d->btnSaveChanges, 0103 KGuiItem(xi18nc("@action:button", "Save Changes"), "document-save", 0104 xi18n("Save all changes made to this connection information"), 0105 xi18n("Save all changes made to this connection information. " 0106 "You can later reuse this information."))); 0107 d->btnSaveChanges->setObjectName("savechanges"); 0108 hbox->addWidget(d->btnSaveChanges); 0109 hbox->addSpacing(KexiUtils::spacingHint()); 0110 QWidget::setTabOrder(titleEdit, d->btnSaveChanges); 0111 d->btnSaveChanges->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); 0112 0113 d->btnTestConnection = new QPushButton(frmBottom); 0114 //! @todo add Test Connection icon 0115 KGuiItem::assign(d->btnTestConnection, 0116 KGuiItem(xi18nc("@action:button", "&Test Connection"), QString(), 0117 xi18n("Test database connection"), 0118 xi18n("Tests database connection. " 0119 "You can check validity of connection information."))); 0120 d->btnTestConnection->setObjectName("testConnection"); 0121 hbox->addWidget(d->btnTestConnection); 0122 setTabOrder(d->btnSaveChanges, d->btnTestConnection); 0123 d->btnTestConnection->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); 0124 0125 connect(localhostRBtn, SIGNAL(clicked()), this, SLOT(slotLocationRadioClicked())); 0126 connect(remotehostRBtn, SIGNAL(clicked()), this, SLOT(slotLocationRadioClicked())); 0127 connect(chkPortDefault, SIGNAL(toggled(bool)), this , SLOT(slotCBToggled(bool))); 0128 connect(btnLoadDBList, SIGNAL(clicked()), this, SIGNAL(loadDBList())); 0129 connect(d->btnSaveChanges, SIGNAL(clicked()), this, SIGNAL(saveChanges())); 0130 } 0131 0132 KexiDBConnectionWidget::~KexiDBConnectionWidget() 0133 { 0134 delete d; 0135 } 0136 0137 bool KexiDBConnectionWidget::connectionOnly() const 0138 { 0139 return d->connectionOnly; 0140 } 0141 0142 void KexiDBConnectionWidget::setDataInternal(const KexiProjectData& data, bool connectionOnly, 0143 const QString& shortcutFileName) 0144 { 0145 d->data = data; 0146 d->connectionOnly = connectionOnly; 0147 0148 if (d->connectionOnly) { 0149 nameLabel->hide(); 0150 nameCombo->hide(); 0151 btnLoadDBList->hide(); 0152 dbGroupBox->setTitle(xi18n("Database Connection")); 0153 } else { 0154 nameLabel->show(); 0155 nameCombo->show(); 0156 #ifndef NO_LOAD_DB_LIST 0157 btnLoadDBList->show(); 0158 #endif 0159 nameCombo->setEditText(d->data.databaseName()); 0160 dbGroupBox->setTitle(xi18n("Database")); 0161 } 0162 //! @todo what if there's no such driver name? 0163 d->driversCombo->setCurrentDriverId(d->data.connectionData()->driverId()); 0164 hostEdit->setText(d->data.connectionData()->hostName()); 0165 if (d->data.connectionData()->hostName().isEmpty()) { 0166 localhostRBtn->setChecked(true); 0167 } 0168 else { 0169 remotehostRBtn->setChecked(true); 0170 } 0171 slotLocationRadioClicked(); 0172 if (d->data.connectionData()->port() != 0) { 0173 chkPortDefault->setChecked(false); 0174 customPortEdit->setValue(d->data.connectionData()->port()); 0175 } else { 0176 chkPortDefault->setChecked(true); 0177 /* @todo default port # instead of 0 */ 0178 customPortEdit->setValue(0); 0179 } 0180 userEdit->setText(d->data.connectionData()->userName()); 0181 passwordEdit->setText(d->data.connectionData()->password()); 0182 if (d->connectionOnly) 0183 titleEdit->setText(d->data.connectionData()->caption()); 0184 else 0185 titleEdit->setText(d->data.caption()); 0186 0187 if (shortcutFileName.isEmpty()) { 0188 d->btnSaveChanges->hide(); 0189 } else { 0190 if (!QFileInfo(shortcutFileName).isWritable()) { 0191 d->btnSaveChanges->setEnabled(false); 0192 } 0193 } 0194 chkSavePassword->setChecked(d->data.connectionData()->savePassword()); 0195 adjustSize(); 0196 } 0197 0198 void KexiDBConnectionWidget::setData(const KexiProjectData& data, const QString& shortcutFileName) 0199 { 0200 setDataInternal(data, false /*!connectionOnly*/, shortcutFileName); 0201 } 0202 0203 void KexiDBConnectionWidget::setData(const KDbConnectionData& data, const QString& shortcutFileName) 0204 { 0205 KexiProjectData pdata(data); 0206 setDataInternal(pdata, true /*connectionOnly*/, shortcutFileName); 0207 } 0208 0209 QPushButton* KexiDBConnectionWidget::saveChangesButton() const 0210 { 0211 return d->btnSaveChanges; 0212 } 0213 0214 QPushButton* KexiDBConnectionWidget::testConnectionButton() const 0215 { 0216 return d->btnTestConnection; 0217 } 0218 0219 KexiDBDriverComboBox* KexiDBConnectionWidget::driversCombo() const 0220 { 0221 return d->driversCombo; 0222 } 0223 0224 0225 KexiProjectData KexiDBConnectionWidget::data() 0226 { 0227 return d->data; 0228 } 0229 0230 void KexiDBConnectionWidget::slotLocationRadioClicked() 0231 { 0232 hostLbl->setEnabled(remotehostRBtn->isChecked()); 0233 hostEdit->setEnabled(remotehostRBtn->isChecked()); 0234 } 0235 0236 void KexiDBConnectionWidget::slotCBToggled(bool on) 0237 { 0238 if (sender() == chkPortDefault) { 0239 customPortEdit->setEnabled(!on); 0240 portLbl->setEnabled(!on); 0241 if (on) { 0242 portLbl->setBuddy(customPortEdit); 0243 } 0244 } 0245 } 0246 0247 void KexiDBConnectionWidget::slotShowSavePasswordHelp() 0248 { 0249 QWhatsThis::showText(chkSavePassword->mapToGlobal(QPoint(0, chkSavePassword->height())), 0250 chkSavePassword->whatsThis()); 0251 } 0252 0253 //----------- 0254 0255 KexiDBConnectionWidgetDetails::KexiDBConnectionWidgetDetails(QWidget* parent) 0256 : QWidget(parent) 0257 { 0258 setupUi(this); 0259 customSocketEdit->setMode(KFile::File | KFile::ExistingOnly | KFile::LocalOnly); 0260 } 0261 0262 KexiDBConnectionWidgetDetails::~KexiDBConnectionWidgetDetails() 0263 { 0264 } 0265 0266 //----------- 0267 0268 KexiDBConnectionTabWidget::KexiDBConnectionTabWidget(QWidget* parent) 0269 : QTabWidget(parent) 0270 { 0271 mainWidget = new KexiDBConnectionWidget(this); 0272 mainWidget->setObjectName("mainWidget"); 0273 mainWidget->layout()->setMargin(KexiUtils::marginHint()); 0274 addTab(mainWidget, xi18n("Parameters")); 0275 0276 detailsWidget = new KexiDBConnectionWidgetDetails(this); 0277 detailsWidget->setObjectName("detailsWidget"); 0278 addTab(detailsWidget, xi18n("Details")); 0279 connect(detailsWidget->chkSocketDefault, SIGNAL(toggled(bool)), 0280 this, SLOT(slotSocketComboboxToggled(bool))); 0281 connect(detailsWidget->chkUseSocket, SIGNAL(toggled(bool)), 0282 this, SLOT(slotSocketComboboxToggled(bool))); 0283 0284 connect(mainWidget->testConnectionButton(), SIGNAL(clicked()), 0285 this, SLOT(slotTestConnection())); 0286 } 0287 0288 KexiDBConnectionTabWidget::~KexiDBConnectionTabWidget() 0289 { 0290 } 0291 0292 void KexiDBConnectionTabWidget::setData(const KexiProjectData& data, const QString& shortcutFileName) 0293 { 0294 setData(*data.connectionData(), shortcutFileName); 0295 } 0296 0297 void KexiDBConnectionTabWidget::setData(const KDbConnectionData& data, 0298 const QString& shortcutFileName) 0299 { 0300 mainWidget->setData(data, shortcutFileName); 0301 detailsWidget->chkUseSocket->setChecked(data.useLocalSocketFile()); 0302 detailsWidget->customSocketEdit->setUrl(QUrl::fromLocalFile(data.localSocketFileName())); 0303 detailsWidget->customSocketEdit->setEnabled(detailsWidget->chkUseSocket->isChecked()); 0304 detailsWidget->chkSocketDefault->setChecked(data.localSocketFileName().isEmpty()); 0305 detailsWidget->chkSocketDefault->setEnabled(detailsWidget->chkUseSocket->isChecked()); 0306 detailsWidget->descriptionEdit->setText(data.description()); 0307 } 0308 0309 KexiProjectData KexiDBConnectionTabWidget::currentProjectData() 0310 { 0311 KexiProjectData data; 0312 0313 //! @todo check if that's database of connection shortcut. Now we're assuming db shortcut only! 0314 0315 // collect data from the form's fields 0316 if (mainWidget->connectionOnly()) { 0317 data.connectionData()->setCaption(mainWidget->titleEdit->text()); 0318 data.setCaption(QString()); 0319 data.connectionData()->setDescription(detailsWidget->descriptionEdit->toPlainText()); 0320 data.setDatabaseName(QString()); 0321 } else { 0322 data.connectionData()->caption().clear(); /* connection name is not specified... */ 0323 data.setCaption(mainWidget->titleEdit->text()); 0324 data.setDescription(detailsWidget->descriptionEdit->toPlainText()); 0325 data.setDatabaseName(mainWidget->nameCombo->currentText()); 0326 } 0327 data.connectionData()->setDriverId(mainWidget->driversCombo()->currentDriverId()); 0328 data.connectionData()->setHostName( 0329 (mainWidget->remotehostRBtn->isChecked()/*remote*/) 0330 ? mainWidget->hostEdit->text() : QString()); 0331 data.connectionData()->setPort(mainWidget->chkPortDefault->isChecked() 0332 ? 0 : mainWidget->customPortEdit->value()); 0333 data.connectionData()->setLocalSocketFileName(detailsWidget->chkSocketDefault->isChecked() 0334 ? QString() : detailsWidget->customSocketEdit->url().toLocalFile()); 0335 data.connectionData()->setUseLocalSocketFile(detailsWidget->chkUseSocket->isChecked()); 0336 //UNSAFE!!!! 0337 data.connectionData()->setUserName(mainWidget->userEdit->text()); 0338 if (mainWidget->chkSavePassword->isChecked()) { 0339 // avoid keeping potentially wrong password that then will be re-used 0340 data.connectionData()->setPassword(mainWidget->passwordEdit->text()); 0341 } 0342 data.connectionData()->setSavePassword(mainWidget->chkSavePassword->isChecked()); 0343 /*! @todo add "options=", eg. as string list? */ 0344 return data; 0345 } 0346 0347 bool KexiDBConnectionTabWidget::savePasswordOptionSelected() const 0348 { 0349 return mainWidget->chkSavePassword->isChecked(); 0350 } 0351 0352 void KexiDBConnectionTabWidget::slotTestConnection() 0353 { 0354 KDbConnectionData connectionData = *currentProjectData().connectionData(); 0355 bool savePasswordChecked = connectionData.savePassword(); 0356 if (!savePasswordChecked) { 0357 connectionData.setPassword(mainWidget->passwordEdit->text()); //not saved otherwise 0358 } 0359 if (mainWidget->passwordEdit->text().isEmpty()) { 0360 connectionData.setPassword(QString()); 0361 if (savePasswordChecked) { 0362 connectionData.setSavePassword(false); //for getPasswordIfNeeded() 0363 } 0364 if (~KexiDBPasswordDialog::getPasswordIfNeeded(&connectionData,this)) { 0365 return; 0366 } 0367 } 0368 KexiGUIMessageHandler msgHandler; 0369 KDb::showConnectionTestDialog(this, connectionData, &msgHandler); 0370 } 0371 0372 void KexiDBConnectionTabWidget::slotSocketComboboxToggled(bool on) 0373 { 0374 if (sender() == detailsWidget->chkSocketDefault) { 0375 detailsWidget->customSocketEdit->setEnabled(!on); 0376 } else if (sender() == detailsWidget->chkUseSocket) { 0377 detailsWidget->customSocketEdit->setEnabled( 0378 on && !detailsWidget->chkSocketDefault->isChecked()); 0379 detailsWidget->chkSocketDefault->setEnabled(on); 0380 } 0381 } 0382 0383 //-------- 0384 0385 //! @todo set proper help ctxt ID 0386 0387 KexiDBConnectionDialog::KexiDBConnectionDialog(QWidget* parent, const KexiProjectData& data, 0388 const QString& shortcutFileName, const KGuiItem& acceptButtonGuiItem) 0389 : QDialog(parent) 0390 , d(new Private) 0391 { 0392 setWindowTitle(xi18nc("@title:window", "Open Database")); 0393 d->tabWidget = new KexiDBConnectionTabWidget(this); 0394 d->tabWidget->setData(data, shortcutFileName); 0395 init(acceptButtonGuiItem); 0396 } 0397 0398 KexiDBConnectionDialog::KexiDBConnectionDialog(QWidget* parent, 0399 const KDbConnectionData& data, 0400 const QString& shortcutFileName, const KGuiItem& acceptButtonGuiItem) 0401 : QDialog(parent) 0402 , d(new Private) 0403 { 0404 setWindowTitle(xi18nc("@title:window", "Connect to a Database Server")); 0405 d->tabWidget = new KexiDBConnectionTabWidget(this); 0406 d->tabWidget->setData(data, shortcutFileName); 0407 init(acceptButtonGuiItem); 0408 } 0409 0410 KexiDBConnectionDialog::~KexiDBConnectionDialog() 0411 { 0412 delete d; 0413 } 0414 0415 void KexiDBConnectionDialog::init(const KGuiItem& acceptButtonGuiItem) 0416 { 0417 setObjectName("KexiDBConnectionDialog"); 0418 setModal(true); 0419 0420 QVBoxLayout *mainLayout = new QVBoxLayout; 0421 setLayout(mainLayout); 0422 0423 mainLayout->addWidget(d->tabWidget); 0424 connect(d->tabWidget->mainWidget, SIGNAL(saveChanges()), this, SIGNAL(saveChanges())); 0425 connect(d->tabWidget, SIGNAL(testConnection()), this, SIGNAL(testConnection())); 0426 0427 if (d->tabWidget->mainWidget->connectionOnly()) 0428 d->tabWidget->mainWidget->driversCombo()->setFocus(); 0429 else if (d->tabWidget->mainWidget->nameCombo->currentText().isEmpty()) 0430 d->tabWidget->mainWidget->nameCombo->setFocus(); 0431 else if (d->tabWidget->mainWidget->userEdit->text().isEmpty()) 0432 d->tabWidget->mainWidget->userEdit->setFocus(); 0433 else if (d->tabWidget->mainWidget->passwordEdit->text().isEmpty()) 0434 d->tabWidget->mainWidget->passwordEdit->setFocus(); 0435 else //back 0436 d->tabWidget->mainWidget->nameCombo->setFocus(); 0437 0438 // buttons 0439 d->buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel|QDialogButtonBox::Help); 0440 connect(d->buttonBox, SIGNAL(accepted()), this, SLOT(accept())); 0441 connect(d->buttonBox, SIGNAL(rejected()), this, SLOT(reject())); 0442 KGuiItem::assign(d->buttonBox->button(QDialogButtonBox::Ok), 0443 acceptButtonGuiItem.text().isEmpty() 0444 ? KGuiItem(xi18nc("@action:button", "&Open"), koIconName("document-open"), xi18n("Open Database Connection")) 0445 : acceptButtonGuiItem 0446 ); 0447 mainLayout->addWidget(d->buttonBox); 0448 0449 adjustSize(); 0450 resize(width(), d->tabWidget->height()); 0451 } 0452 0453 KexiProjectData KexiDBConnectionDialog::currentProjectData() 0454 { 0455 return d->tabWidget->currentProjectData(); 0456 } 0457 0458 bool KexiDBConnectionDialog::savePasswordOptionSelected() const 0459 { 0460 return d->tabWidget->savePasswordOptionSelected(); 0461 } 0462 0463 KexiDBConnectionWidget* KexiDBConnectionDialog::mainWidget() const 0464 { 0465 return d->tabWidget->mainWidget; 0466 } 0467 0468 KexiDBConnectionWidgetDetails* KexiDBConnectionDialog::detailsWidget() const 0469 { 0470 return d->tabWidget->detailsWidget; 0471 } 0472