File indexing completed on 2024-05-12 16:40:15
0001 /* This file is part of the KDE project 0002 Copyright (C) 2004-2009 Adam Pigg <adam@piggz.co.uk> 0003 Copyright (C) 2004-2016 Jarosław Staniek <staniek@kde.org> 0004 Copyright (C) 2005 Martin Ellis <martin.ellis@kdemail.net> 0005 0006 This library is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU Library General Public 0008 License as published by the Free Software Foundation; either 0009 version 2 of the License, or (at your option) any later version. 0010 0011 This library is distributed in the hope that it will be useful, 0012 but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 Library General Public License for more details. 0015 0016 You should have received a copy of the GNU Library General Public License 0017 along with this library; see the file COPYING.LIB. If not, write to 0018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 * Boston, MA 02110-1301, USA. 0020 */ 0021 0022 #include "importwizard.h" 0023 #include "keximigrate.h" 0024 #include "importoptionsdlg.h" 0025 #include <core/KexiMainWindowIface.h> 0026 #include <core/kexidbconnectionset.h> 0027 #include <core/kexi.h> 0028 #include <kexiutils/utils.h> 0029 #include <kexidbdrivercombobox.h> 0030 #include <kexitextmsghandler.h> 0031 #include <widget/kexicharencodingcombobox.h> 0032 #include <widget/kexiprjtypeselector.h> 0033 #include <widget/KexiConnectionSelectorWidget.h> 0034 #include <widget/KexiProjectSelectorWidget.h> 0035 #include <widget/KexiDBCaptionPage.h> 0036 #include <widget/KexiDBPasswordDialog.h> 0037 #include <widget/KexiStartupFileHandler.h> 0038 #include <KexiIcon.h> 0039 0040 #include <KDbDriverManager> 0041 #include <KDbDriver> 0042 #include <KDbConnectionData> 0043 #include <KDbUtils> 0044 #include <KDb> 0045 #include <KDbIdentifierValidator> 0046 0047 #include <KMessageBox> 0048 0049 #include <QGroupBox> 0050 #include <QLabel> 0051 #include <QLayout> 0052 #include <QRadioButton> 0053 #include <QCheckBox> 0054 #include <QVBoxLayout> 0055 #include <QHBoxLayout> 0056 #include <QDir> 0057 #include <QApplication> 0058 #include <QLineEdit> 0059 #include <QMimeDatabase> 0060 #include <QMimeType> 0061 #include <QPushButton> 0062 #include <QDebug> 0063 #include <QProgressBar> 0064 0065 using namespace KexiMigration; 0066 0067 class Q_DECL_HIDDEN ImportWizard::Private 0068 { 0069 public: 0070 0071 Private(QMap<QString, QString>* args_) 0072 : srcProjectSelector(0) 0073 , fileBasedDstWasPresented(false) 0074 , setupFileBasedSrcNeeded(true) 0075 , importExecuted(false) 0076 , prjSet(0) 0077 , args(args_) 0078 { 0079 } 0080 0081 ~Private() 0082 { 0083 delete prjSet; 0084 } 0085 0086 QWidget *introPageWidget, *srcConnPageWidget, *srcDBPageWidget, 0087 *dstTypePageWidget, *dstPageWidget, *importTypePageWidget, 0088 *importingPageWidget, *finishPageWidget; 0089 0090 KPageWidgetItem *introPageItem, *srcConnPageItem, *srcDBPageItem, 0091 *dstTypePageItem, *dstPageItem, *importTypePageItem, 0092 *importingPageItem, *finishPageItem; 0093 0094 0095 QGroupBox *importTypeGroupBox; 0096 QRadioButton *importTypeStructureAndDataCheckBox; 0097 QRadioButton *importTypeStructureOnlyCheckBox; 0098 KexiDBCaptionPage* dstCaptionPageWidget; 0099 KPageWidgetItem *dstCaptionPageItem; 0100 0101 KexiPrjTypeSelector *dstPrjTypeSelector; 0102 0103 KexiConnectionSelectorWidget *srcConn, *dstConn; 0104 QString driverIdForSelectedSource; 0105 0106 QLineEdit *dstNewDBCaptionLineEdit; 0107 QLabel *dstNewDBNameLabel; 0108 QLineEdit *dstNewDBNameLineEdit; 0109 0110 QLabel *dstNewDBNameUrlLabel; 0111 KUrlRequester *dstNewDBNameUrl; 0112 KexiStartupFileHandler *dstNewDBFileHandler; 0113 KexiProjectSelectorWidget *srcProjectSelector; 0114 0115 QLabel *lblImportingTxt, *lblImportingErrTxt, *finishLbl; 0116 QCheckBox *openImportedProjectCheckBox; 0117 bool fileBasedDstWasPresented; 0118 bool setupFileBasedSrcNeeded; 0119 bool importExecuted; //!< used in import() 0120 KexiProjectSet* prjSet; 0121 QProgressBar *progressBar; 0122 QPushButton* importOptionsButton; 0123 QMap<QString, QString> *args; 0124 QString predefinedDatabaseName, predefinedMimeType; 0125 KDbConnectionData *predefinedConnectionData; 0126 MigrateManager migrateManager; //!< object lives here, so status messages can be globally preserved 0127 0128 //! Encoding for source db. Currently only used for MDB driver. 0129 //! @todo Hardcoded. Move to KexiMigrate driver's impl. 0130 QString sourceDBEncoding; 0131 0132 }; 0133 0134 //=========================================================== 0135 // 0136 ImportWizard::ImportWizard(QWidget *parent, QMap<QString, QString>* args) 0137 : KAssistantDialog(parent) 0138 , d(new Private(args)) 0139 { 0140 setModal(true); 0141 setWindowTitle(xi18nc("@title:window", "Import Database")); 0142 setWindowIcon(KexiIcon("database-import")); 0143 0144 KexiMainWindowIface::global()->setReasonableDialogSize(this); 0145 0146 parseArguments(); 0147 0148 setupIntro(); 0149 setupSrcConn(); 0150 setupSrcDB(); 0151 setupDstType(); 0152 setupDstCaption(); 0153 setupDst(); 0154 setupImportType(); 0155 setupImporting(); 0156 setupFinish(); 0157 0158 connect(this, SIGNAL(currentPageChanged(KPageWidgetItem*,KPageWidgetItem*)), this, SLOT(slot_currentPageChanged(KPageWidgetItem*,KPageWidgetItem*))); 0159 connect(button(QDialogButtonBox::Help), &QPushButton::clicked, this, &ImportWizard::helpClicked); 0160 0161 if (d->predefinedConnectionData) { 0162 // setup wizard for predefined server source 0163 d->srcConn->showAdvancedConnection(); 0164 setAppropriate(d->srcConnPageItem, false); 0165 setAppropriate(d->srcDBPageItem, false); 0166 } else if (!d->predefinedDatabaseName.isEmpty()) { 0167 // setup wizard for predefined source 0168 // (used when external project type was opened in Kexi, e.g. mdb file) 0169 setAppropriate(d->srcConnPageItem, false); 0170 setAppropriate(d->srcDBPageItem, false); 0171 d->srcConn->showSimpleConnection(); 0172 d->srcConn->setSelectedFile(d->predefinedDatabaseName); 0173 0174 #if 0 0175 //disable all prev pages except "welcome" page 0176 for (int i = 0; i < indexOf(d->dstTypePage); i++) { 0177 if (page(i) != d->introPage) 0178 setAppropriate(page(i), false); 0179 } 0180 #endif 0181 } 0182 0183 d->sourceDBEncoding = QString::fromLatin1(KexiUtils::encoding()); //default 0184 } 0185 0186 //=========================================================== 0187 // 0188 ImportWizard::~ImportWizard() 0189 { 0190 delete d; 0191 } 0192 0193 //=========================================================== 0194 // 0195 void ImportWizard::parseArguments() 0196 { 0197 d->predefinedConnectionData = 0; 0198 if (!d->args) 0199 return; 0200 if (!(*d->args)["databaseName"].isEmpty() && !(*d->args)["mimeType"].isEmpty()) { 0201 d->predefinedDatabaseName = (*d->args)["databaseName"]; 0202 d->predefinedMimeType = (*d->args)["mimeType"]; 0203 if (d->args->contains("connectionData")) { 0204 bool ok; 0205 d->predefinedConnectionData = new KDbConnectionData( 0206 KDbUtils::deserializeMap((*d->args)["connectionData"]), &ok); 0207 if (!ok) { 0208 delete d->predefinedConnectionData; 0209 d->predefinedConnectionData = 0; 0210 } 0211 } 0212 } 0213 d->args->clear(); 0214 } 0215 0216 QString ImportWizard::selectedSourceFileName() const 0217 { 0218 if (d->predefinedDatabaseName.isEmpty()) 0219 return d->srcConn->selectedFile(); 0220 0221 return d->predefinedDatabaseName; 0222 } 0223 0224 //=========================================================== 0225 // 0226 void ImportWizard::setupIntro() 0227 { 0228 d->introPageWidget = new QWidget(this); 0229 QVBoxLayout *vbox = new QVBoxLayout(); 0230 0231 d->introPageWidget->setLayout(vbox); 0232 0233 KexiUtils::setStandardMarginsAndSpacing(vbox); 0234 0235 QLabel *lblIntro = new QLabel(d->introPageWidget); 0236 lblIntro->setAlignment(Qt::AlignTop | Qt::AlignLeft); 0237 lblIntro->setWordWrap(true); 0238 lblIntro->setTextFormat(Qt::RichText); 0239 KLocalizedString msg; 0240 if (d->predefinedConnectionData) { // predefined import: server source 0241 msg = kxi18nc("@info", 0242 "Database Importing Assistant is about to import <resource>%1</resource> " 0243 "database " 0244 "(connection <resource>%2</resource>) into a KEXI project.") 0245 .subs(d->predefinedDatabaseName) 0246 .subs(d->predefinedConnectionData->toUserVisibleString()); 0247 } else if (!d->predefinedDatabaseName.isEmpty()) { // predefined import: file source 0248 //! @todo this message is currently ok for files only 0249 QMimeDatabase db; 0250 QMimeType mime = db.mimeTypeForName(d->predefinedMimeType); 0251 if (!mime.isValid()) { 0252 qWarning() << QString("'%1' mimetype not installed!").arg(d->predefinedMimeType); 0253 } 0254 d->driverIdForSelectedSource = driverIdForMimeType(mime); 0255 msg = kxi18nc( 0256 "@info", 0257 "Database Importing Assistant is about to import <filename>%1</filename> file " 0258 "of type <resource>%2</resource> into a KEXI project.") 0259 .subs(QDir::toNativeSeparators(d->predefinedDatabaseName)) 0260 .subs(mime.isValid() ? mime.comment() : "???"); 0261 } else { 0262 msg = kxi18nc("@info", 0263 "Database Importing Assistant allows you to import an existing database " 0264 "into a KEXI project."); 0265 } 0266 const QString finalMessage = KexiUtils::localizedSentencesToHtml( 0267 msg, 0268 kxi18nc("@info", 0269 "<para>Click <interface>Next</interface> button to continue or " 0270 "<interface>Cancel</interface> button to exit this assistant.</para>")); 0271 lblIntro->setText(finalMessage); 0272 vbox->addWidget(lblIntro); 0273 0274 d->introPageItem = new KPageWidgetItem(d->introPageWidget, 0275 xi18n("Welcome to the Database Importing Assistant")); 0276 addPage(d->introPageItem); 0277 } 0278 0279 //=========================================================== 0280 // 0281 void ImportWizard::setupSrcConn() 0282 { 0283 d->srcConnPageWidget = new QWidget(this); 0284 QVBoxLayout *vbox = new QVBoxLayout(d->srcConnPageWidget); 0285 KexiUtils::setStandardMarginsAndSpacing(vbox); 0286 0287 d->srcConn = new KexiConnectionSelectorWidget(&Kexi::connset(), 0288 QUrl("kfiledialog:///ProjectMigrationSourceDir"), 0289 KexiConnectionSelectorWidget::Opening, d->srcConnPageWidget); 0290 0291 d->srcConn->hideConnectonIcon(); 0292 d->srcConn->showSimpleConnection(); 0293 connect(d->srcConn, &KexiConnectionSelectorWidget::connectionSelected, 0294 this, &ImportWizard::sourceConnectionSelected); 0295 0296 const QStringList excludedMimeTypes({ 0297 //! @todo remove when support for kexi files as source prj is added in migration 0298 KDb::defaultFileBasedDriverMimeType(), 0299 "application/x-kexiproject-shortcut", 0300 "application/x-kexi-connectiondata"}); 0301 d->srcConn->setExcludedMimeTypes(excludedMimeTypes); 0302 vbox->addWidget(d->srcConn); 0303 0304 d->srcConnPageItem = new KPageWidgetItem(d->srcConnPageWidget, xi18n("Select Location for Source Database")); 0305 addPage(d->srcConnPageItem); 0306 } 0307 0308 //=========================================================== 0309 // 0310 void ImportWizard::setupSrcDB() 0311 { 0312 // arrivesrcdbPage creates widgets on that page 0313 d->srcDBPageWidget = new QWidget(this); 0314 0315 d->srcDBPageItem = new KPageWidgetItem(d->srcDBPageWidget, xi18n("Select Source Database")); 0316 addPage(d->srcDBPageItem); 0317 } 0318 0319 //=========================================================== 0320 // 0321 void ImportWizard::setupDstType() 0322 { 0323 d->dstTypePageWidget = new QWidget(this); 0324 QVBoxLayout *vbox = new QVBoxLayout(d->dstTypePageWidget); 0325 KexiUtils::setStandardMarginsAndSpacing(vbox); 0326 0327 QHBoxLayout *hbox = new QHBoxLayout; 0328 vbox->addLayout(hbox); 0329 KexiUtils::setStandardMarginsAndSpacing(hbox); 0330 QLabel *lbl = new QLabel(xi18n("Destination database type:") /*+ ' '*/, d->dstTypePageWidget); 0331 lbl->setAlignment(Qt::AlignLeft | Qt::AlignTop); 0332 lbl->setTextFormat(Qt::RichText); 0333 hbox->addWidget(lbl); 0334 0335 d->dstPrjTypeSelector = new KexiPrjTypeSelector(d->dstTypePageWidget); 0336 hbox->addWidget(d->dstPrjTypeSelector); 0337 d->dstPrjTypeSelector->option_file->setText(xi18n("Database project stored in a file")); 0338 d->dstPrjTypeSelector->option_server->setText(xi18n("Database project stored on a server")); 0339 hbox->addStretch(1); 0340 vbox->addStretch(1); 0341 0342 d->dstTypePageItem = new KPageWidgetItem(d->dstTypePageWidget, xi18n("Select Destination Database Type")); 0343 addPage(d->dstTypePageItem); 0344 } 0345 0346 //=========================================================== 0347 // 0348 void ImportWizard::setupDstCaption() 0349 { 0350 d->dstCaptionPageWidget = new KexiDBCaptionPage(xi18n("Destination project's caption:"), this); 0351 d->dstCaptionPageWidget->layout()->setMargin(KexiUtils::marginHint()); 0352 d->dstCaptionPageWidget->updateGeometry(); 0353 d->dstNewDBCaptionLineEdit = d->dstCaptionPageWidget->le_caption; 0354 connect(d->dstNewDBCaptionLineEdit, &QLineEdit::textChanged, this, 0355 &ImportWizard::destinationCaptionTextChanged); 0356 d->dstNewDBNameUrlLabel = d->dstCaptionPageWidget->label_requester; 0357 d->dstNewDBNameUrl = d->dstCaptionPageWidget->file_requester; 0358 d->dstNewDBFileHandler = new KexiStartupFileHandler( 0359 QUrl("kfiledialog:///ProjectMigrationDestinationDir"), 0360 KexiFileFilters::SavingFileBasedDB, 0361 d->dstCaptionPageWidget->file_requester); 0362 d->dstNewDBNameLabel = new QLabel(xi18n("Destination project's name:"), d->dstCaptionPageWidget); 0363 d->dstCaptionPageWidget->formLayout->setWidget(2, QFormLayout::LabelRole, d->dstNewDBNameLabel); 0364 d->dstNewDBNameLineEdit = new QLineEdit(d->dstCaptionPageWidget); 0365 d->dstNewDBNameLineEdit->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed)); 0366 KDbIdentifierValidator *idValidator = new KDbIdentifierValidator(this); 0367 idValidator->setLowerCaseForced(true); 0368 d->dstNewDBNameLineEdit->setValidator(idValidator); 0369 d->dstCaptionPageWidget->formLayout->setWidget(2, QFormLayout::FieldRole, d->dstNewDBNameLineEdit); 0370 0371 d->dstCaptionPageItem = new KPageWidgetItem(d->dstCaptionPageWidget, xi18n("Enter Destination Database Project's Caption")); 0372 addPage(d->dstCaptionPageItem); 0373 } 0374 0375 void ImportWizard::destinationCaptionTextChanged(const QString &text) 0376 { 0377 Q_UNUSED(text); 0378 updateDestinationDBFileName(); 0379 } 0380 0381 void ImportWizard::updateDestinationDBFileName() 0382 { 0383 d->dstNewDBFileHandler->updateUrl(d->dstNewDBCaptionLineEdit->text()); 0384 d->dstNewDBNameLineEdit->setText(d->dstNewDBCaptionLineEdit->text()); 0385 } 0386 0387 //=========================================================== 0388 // 0389 void ImportWizard::setupDst() 0390 { 0391 d->dstPageWidget = new QWidget(this); 0392 QVBoxLayout *vbox = new QVBoxLayout(d->dstPageWidget); 0393 KexiUtils::setStandardMarginsAndSpacing(vbox); 0394 0395 d->dstConn = new KexiConnectionSelectorWidget(&Kexi::connset(), 0396 QUrl("kfiledialog:///ProjectMigrationDestinationDir"), 0397 KexiConnectionSelectorWidget::Saving, d->dstPageWidget); 0398 d->dstConn->hideHelpers(); 0399 0400 vbox->addWidget(d->dstConn); 0401 connect(d->dstConn, SIGNAL(connectionItemExecuted(ConnectionDataLVItem*)), 0402 this, SLOT(next())); 0403 0404 d->dstConn->showSimpleConnection(); 0405 //anyway, db files will be _saved_ 0406 d->dstConn->setFileMode(KexiFileFilters::SavingFileBasedDB); 0407 d->dstPageItem = new KPageWidgetItem(d->dstPageWidget, xi18n("Select Location for Destination Database Project")); 0408 addPage(d->dstPageItem); 0409 } 0410 0411 //=========================================================== 0412 // 0413 void ImportWizard::setupImportType() 0414 { 0415 d->importTypePageWidget = new QWidget(this); 0416 QVBoxLayout *vbox = new QVBoxLayout(d->importTypePageWidget); 0417 KexiUtils::setStandardMarginsAndSpacing(vbox); 0418 d->importTypeGroupBox = new QGroupBox(d->importTypePageWidget); 0419 0420 vbox->addWidget(d->importTypeGroupBox); 0421 QVBoxLayout *importTypeGroupBoxLyr = new QVBoxLayout; 0422 0423 importTypeGroupBoxLyr->addWidget( 0424 d->importTypeStructureAndDataCheckBox = new QRadioButton( 0425 xi18nc("Scope of import", "Structure and data"), d->importTypeGroupBox)); 0426 d->importTypeStructureAndDataCheckBox->setChecked(true); 0427 0428 importTypeGroupBoxLyr->addWidget( 0429 d->importTypeStructureOnlyCheckBox = new QRadioButton( 0430 xi18nc("Scope of import", "Structure only"), d->importTypeGroupBox)); 0431 0432 importTypeGroupBoxLyr->addStretch(1); 0433 d->importTypeGroupBox->setLayout(importTypeGroupBoxLyr); 0434 0435 d->importTypePageItem = new KPageWidgetItem(d->importTypePageWidget, 0436 xi18n("Select Scope of Import")); 0437 addPage(d->importTypePageItem); 0438 } 0439 0440 //=========================================================== 0441 // 0442 void ImportWizard::setupImporting() 0443 { 0444 d->importingPageWidget = new QWidget(this); 0445 d->importingPageWidget->hide(); 0446 QVBoxLayout *vbox = new QVBoxLayout(d->importingPageWidget); 0447 KexiUtils::setStandardMarginsAndSpacing(vbox); 0448 d->lblImportingTxt = new QLabel(d->importingPageWidget); 0449 d->lblImportingTxt->setAlignment(Qt::AlignTop | Qt::AlignLeft); 0450 d->lblImportingTxt->setWordWrap(true); 0451 d->lblImportingTxt->setTextFormat(Qt::RichText); 0452 0453 d->lblImportingErrTxt = new QLabel(d->importingPageWidget); 0454 d->lblImportingErrTxt->setAlignment(Qt::AlignTop | Qt::AlignLeft); 0455 d->lblImportingErrTxt->setWordWrap(true); 0456 d->lblImportingErrTxt->setTextFormat(Qt::RichText); 0457 0458 d->progressBar = new QProgressBar(d->importingPageWidget); 0459 d->progressBar->setRange(0, 100); 0460 d->progressBar->hide(); 0461 0462 vbox->addWidget(d->lblImportingTxt); 0463 vbox->addWidget(d->lblImportingErrTxt); 0464 vbox->addStretch(1); 0465 0466 QWidget *options_widget = new QWidget(d->importingPageWidget); 0467 vbox->addWidget(options_widget); 0468 QVBoxLayout *options_vbox = new QVBoxLayout(options_widget); 0469 options_vbox->setSpacing(KexiUtils::spacingHint()); 0470 QHBoxLayout *importOptionsButtonLyr = new QHBoxLayout; 0471 options_vbox->addLayout(importOptionsButtonLyr); 0472 d->importOptionsButton = new QPushButton(koIcon("configure"), 0473 xi18n("Advanced Options"), options_widget); 0474 connect(d->importOptionsButton, SIGNAL(clicked()), 0475 this, SLOT(slotOptionsButtonClicked())); 0476 importOptionsButtonLyr->addStretch(1); 0477 importOptionsButtonLyr->addWidget(d->importOptionsButton); 0478 importOptionsButtonLyr->addStretch(1); 0479 options_vbox->addStretch(1); 0480 0481 vbox->addWidget(d->progressBar); 0482 vbox->addStretch(2); 0483 d->importingPageWidget->show(); 0484 0485 d->importingPageItem = new KPageWidgetItem(d->importingPageWidget, xi18n("Importing")); 0486 addPage(d->importingPageItem); 0487 } 0488 0489 //=========================================================== 0490 // 0491 void ImportWizard::setupFinish() 0492 { 0493 d->finishPageWidget = new QWidget(this); 0494 d->finishPageWidget->hide(); 0495 QVBoxLayout *vbox = new QVBoxLayout(d->finishPageWidget); 0496 KexiUtils::setStandardMarginsAndSpacing(vbox); 0497 d->finishLbl = new QLabel(d->finishPageWidget); 0498 d->finishLbl->setAlignment(Qt::AlignTop | Qt::AlignLeft); 0499 d->finishLbl->setWordWrap(true); 0500 d->finishLbl->setTextFormat(Qt::RichText); 0501 0502 vbox->addWidget(d->finishLbl); 0503 d->openImportedProjectCheckBox = new QCheckBox(xi18n("Open imported project"), 0504 d->finishPageWidget); 0505 d->openImportedProjectCheckBox->setChecked(true); 0506 vbox->addSpacing(KexiUtils::spacingHint()); 0507 vbox->addWidget(d->openImportedProjectCheckBox); 0508 vbox->addStretch(1); 0509 0510 d->finishPageItem = new KPageWidgetItem(d->finishPageWidget, xi18n("Success")); 0511 addPage(d->finishPageItem); 0512 } 0513 0514 //=========================================================== 0515 // 0516 bool ImportWizard::checkUserInput() 0517 { 0518 KLocalizedString issues; 0519 0520 if (d->dstNewDBCaptionLineEdit->text().isEmpty()) { 0521 issues = kxi18nc("@info", "<para>No new database name was entered.</para>"); 0522 } 0523 0524 Kexi::ObjectStatus result; 0525 KexiMigrate* sourceDriver = prepareImport(result); 0526 if (sourceDriver && sourceDriver->isSourceAndDestinationDataSourceTheSame()) { 0527 KLocalizedString sameDbIssue = kxi18nc("@info", "%1<para>Source database is the same as destination.</para>"); 0528 issues = issues.isEmpty() ? sameDbIssue.subs("") : sameDbIssue.subs(issues); 0529 } 0530 0531 if (!issues.isEmpty()) { 0532 d->lblImportingErrTxt->setText( 0533 xi18nc("@info", "<para>Following issues were found with the data you entered:</para>" 0534 "%1" 0535 "<para>Please click <interface>Back</interface> button and correct these issues.</para>", 0536 issues)); 0537 return false; 0538 } 0539 return true; 0540 } 0541 0542 void ImportWizard::arriveSrcConnPage() 0543 { 0544 d->srcConnPageWidget->hide(); 0545 0546 /*! @todo KexiFileWidget needs "open file" and "open server" modes 0547 in addition to just "open" */ 0548 if (d->setupFileBasedSrcNeeded) { 0549 d->setupFileBasedSrcNeeded = false; 0550 d->srcConn->setFileMode(KexiFileFilters::Opening); 0551 d->srcConn->setAdditionalMimeTypes(QStringList()); 0552 } 0553 0554 /*! @todo Support different file extensions based on MigrationDriver */ 0555 d->srcConnPageWidget->show(); 0556 } 0557 0558 void ImportWizard::arriveSrcDBPage() 0559 { 0560 if (fileBasedSrcSelected()) { 0561 //! @todo Back button doesn't work after selecting a file to import 0562 } 0563 else { 0564 if (!d->srcProjectSelector) { 0565 QVBoxLayout *vbox = new QVBoxLayout(d->srcDBPageWidget); 0566 d->srcProjectSelector = new KexiProjectSelectorWidget(d->srcDBPageWidget); 0567 vbox->addWidget(d->srcProjectSelector); 0568 KexiUtils::setStandardMarginsAndSpacing(vbox); 0569 d->srcProjectSelector->label()->setText(xi18n("Select source database you wish to import:")); 0570 } 0571 d->srcDBPageWidget->hide(); 0572 KDbConnectionData* condata = d->srcConn->selectedConnectionData(); 0573 Q_ASSERT(condata); 0574 Q_ASSERT(d->prjSet); 0575 d->srcProjectSelector->setProjectSet(d->prjSet); 0576 d->srcDBPageWidget->show(); 0577 } 0578 } 0579 0580 void ImportWizard::arriveDstCaptionPage() 0581 { 0582 d->dstNewDBNameUrlLabel->setVisible(fileBasedDstSelected()); 0583 d->dstNewDBNameUrl->setVisible(fileBasedDstSelected()); 0584 d->dstNewDBNameLabel->setVisible(!fileBasedDstSelected()); 0585 d->dstNewDBNameLineEdit->setVisible(!fileBasedDstSelected()); 0586 if (fileBasedSrcSelected()) { 0587 const QString fname(selectedSourceFileName()); 0588 QString suggestedDBName(QFileInfo(fname).fileName()); 0589 const QFileInfo fi(suggestedDBName); 0590 suggestedDBName = suggestedDBName.left(suggestedDBName.length() 0591 - (fi.completeSuffix().isEmpty() ? 0 : (fi.completeSuffix().length() + 1))); 0592 d->dstNewDBCaptionLineEdit->setText(suggestedDBName); 0593 } 0594 else { 0595 if (d->predefinedConnectionData) { 0596 // server source db is predefined 0597 d->dstNewDBCaptionLineEdit->setText(d->predefinedDatabaseName); 0598 } else { 0599 if (!d->srcProjectSelector || !d->srcProjectSelector->selectedProjectData()) { 0600 back(); //!< @todo 0601 return; 0602 } 0603 d->dstNewDBCaptionLineEdit->setText(d->srcProjectSelector->selectedProjectData()->databaseName()); 0604 } 0605 } 0606 d->dstNewDBCaptionLineEdit->selectAll(); 0607 d->dstNewDBCaptionLineEdit->setFocus(); 0608 updateDestinationDBFileName(); 0609 } 0610 0611 void ImportWizard::arriveDstPage() 0612 { 0613 if (fileBasedDstSelected()) { 0614 d->dstPageWidget->hide(); 0615 KAssistantDialog::next(); 0616 return; 0617 } 0618 else { 0619 d->dstConn->showAdvancedConnection(); 0620 } 0621 d->dstPageWidget->show(); 0622 } 0623 0624 void ImportWizard::arriveImportingPage() 0625 { 0626 d->importingPageWidget->hide(); 0627 nextButton()->setEnabled(checkUserInput()); 0628 d->lblImportingTxt->setText(xi18nc("@info", 0629 "<para>All required information has now " 0630 "been gathered. Click <interface>Next</interface> button to start importing.</para>" 0631 "<para><note>Depending on size of the database this may take some time.</note></para>" 0632 /*"Note: You may be asked for extra " 0633 "information such as field types if " 0634 "the wizard could not automatically " 0635 "determine this for you."*/)); 0636 0637 //temp. hack for MS Access driver only 0638 //! @todo for other databases we will need KexiMigration::Connection 0639 //! and KexiMigration::Driver classes 0640 bool showOptions = false; 0641 if (fileBasedSrcSelected()) { 0642 Kexi::ObjectStatus result; 0643 KexiMigrate* sourceDriver = prepareImport(result); 0644 if (sourceDriver) { 0645 showOptions = !result.error() 0646 && sourceDriver->propertyValue("source_database_has_nonunicode_encoding").toBool(); 0647 sourceDriver->setData(nullptr); 0648 } 0649 } 0650 if (showOptions) 0651 d->importOptionsButton->show(); 0652 else 0653 d->importOptionsButton->hide(); 0654 0655 d->importingPageWidget->show(); 0656 } 0657 0658 void ImportWizard::arriveFinishPage() 0659 { 0660 } 0661 0662 bool ImportWizard::fileBasedSrcSelected() const 0663 { 0664 if (d->predefinedConnectionData) 0665 return false; 0666 0667 // qDebug() << (d->srcConn->selectedConnectionType()==KexiConnectionSelectorWidget::FileBased); 0668 return d->srcConn->selectedConnectionType() == KexiConnectionSelectorWidget::FileBased; 0669 } 0670 0671 bool ImportWizard::fileBasedDstSelected() const 0672 { 0673 return d->dstPrjTypeSelector->option_file->isChecked(); 0674 } 0675 0676 void ImportWizard::progressUpdated(int percent) 0677 { 0678 d->progressBar->setValue(percent); 0679 qApp->processEvents(); 0680 } 0681 0682 QString ImportWizard::driverIdForMimeType(const QMimeType &mime) const 0683 { 0684 if (!mime.isValid()) { 0685 return QString(); 0686 } 0687 const QStringList ids(d->migrateManager.driverIdsForMimeType(mime.name())); 0688 //! @todo do we want to return first migrate driver for the mime type or allow to select it? 0689 return ids.isEmpty() ? QString() : ids.first(); 0690 } 0691 0692 QString ImportWizard::findDriverIdForSelectedSource() 0693 { 0694 if (fileBasedSrcSelected()) { 0695 QMimeDatabase db; 0696 QMimeType mime = db.mimeTypeForFile(selectedSourceFileName()); 0697 if (!mime.isValid() 0698 || mime.name() == "application/octet-stream" 0699 || mime.name() == "text/plain" 0700 || mime.name() == "application/zip") 0701 { 0702 //try by URL: 0703 mime = db.mimeTypeForFile(selectedSourceFileName()); 0704 } 0705 return driverIdForMimeType(mime); 0706 } 0707 0708 //server-based 0709 QString sourceDriverId; 0710 if (d->predefinedConnectionData) { 0711 sourceDriverId = d->predefinedConnectionData->driverId(); 0712 } else if (d->srcConn->selectedConnectionData()) { 0713 sourceDriverId = d->srcConn->selectedConnectionData()->driverId(); 0714 } 0715 const QStringList migrationDriverIds(d->migrateManager.driverIdsForSourceDriver(sourceDriverId)); 0716 0717 //! @todo First found driver ID is picked. It's OK as long as there is one migration 0718 //! driver per source database type. How about allowing users to pick migration driver? 0719 return migrationDriverIds.isEmpty() ? QString() : migrationDriverIds.first(); 0720 } 0721 0722 //=========================================================== 0723 // 0724 void ImportWizard::accept() 0725 { 0726 if (d->args) { 0727 if ((!fileBasedDstSelected() && !d->args->contains("destinationConnectionShortcut")) 0728 || !d->openImportedProjectCheckBox->isChecked()) { 0729 //do not open dest db if used didn't want it 0730 //for server connections, destinationConnectionShortcut must be defined 0731 d->args->remove("destinationDatabaseName"); 0732 } 0733 } 0734 KAssistantDialog::accept(); 0735 } 0736 0737 KexiMigrate* ImportWizard::prepareImport(Kexi::ObjectStatus& result) 0738 { 0739 KexiUtils::WaitCursor wait; 0740 0741 // Start with a driver manager 0742 KDbDriverManager manager; 0743 0744 //qDebug() << "Creating destination driver..."; 0745 0746 // Get a driver to the destination database 0747 KDbDriver *destDriver = manager.driver( 0748 d->dstConn->selectedConnectionData() 0749 ? d->dstConn->selectedConnectionData()->driverId() 0750 : KDb::defaultFileBasedDriverId()); 0751 if (!destDriver || manager.result().isError()) { 0752 result.setStatus(manager.resultable()); 0753 qWarning() << "Manager error:" << manager.result(); 0754 } 0755 0756 // Set up destination connection data 0757 KDbConnectionData *cdata = 0; 0758 QScopedPointer<KDbConnectionData> cdataDeleter; 0759 QString dbname; 0760 if (!result.error()) { 0761 if (d->dstConn->selectedConnectionData()) { 0762 //server-based project 0763 qDebug() << "Server destination..."; 0764 cdata = d->dstConn->selectedConnectionData(); 0765 dbname = d->dstNewDBNameLineEdit->text(); 0766 } 0767 else { 0768 //file-based project 0769 qDebug() << "File Destination..."; 0770 cdata = new KDbConnectionData(); 0771 cdataDeleter.reset(cdata); // ownership won't be transferred 0772 cdata->setCaption(d->dstNewDBCaptionLineEdit->text()); 0773 cdata->setDriverId(KDb::defaultFileBasedDriverId()); 0774 dbname = d->dstCaptionPageWidget->file_requester->url().toLocalFile(); 0775 cdata->setDatabaseName(dbname); 0776 qDebug() << "Current file name:" << dbname; 0777 } 0778 } 0779 0780 // Find a source (migration) driver name 0781 if (!result.error()) { 0782 if (d->driverIdForSelectedSource.isEmpty()) 0783 result.setStatus(xi18n("No appropriate migration driver found."), 0784 d->migrateManager.possibleProblemsMessage()); 0785 } 0786 0787 // Get a source (migration) driver 0788 KexiMigrate* sourceDriver = 0; 0789 if (!result.error()) { 0790 sourceDriver = d->migrateManager.driver(d->driverIdForSelectedSource); 0791 if (!sourceDriver || d->migrateManager.result().isError()) { 0792 qDebug() << "Import migrate driver error..."; 0793 result.setStatus(d->migrateManager.resultable()); 0794 } 0795 } 0796 0797 KexiUtils::removeWaitCursor(); 0798 0799 // Set up source (migration) data required for connection 0800 if (sourceDriver && !result.error() && cdata) { 0801 // Setup progress feedback for the GUI 0802 if (sourceDriver->progressSupported()) { 0803 d->progressBar->updateGeometry(); 0804 disconnect(sourceDriver, SIGNAL(progressPercent(int)), 0805 this, SLOT(progressUpdated(int))); 0806 connect(sourceDriver, SIGNAL(progressPercent(int)), 0807 this, SLOT(progressUpdated(int))); 0808 progressUpdated(0); 0809 } 0810 0811 bool keepData; 0812 if (d->importTypeStructureAndDataCheckBox->isChecked()) { 0813 qDebug() << "Structure and data selected"; 0814 keepData = true; 0815 } else if (d->importTypeStructureOnlyCheckBox->isChecked()) { 0816 qDebug() << "structure only selected"; 0817 keepData = false; 0818 } else { 0819 qDebug() << "Neither radio button is selected (not possible?) presume keep data"; 0820 keepData = true; 0821 } 0822 0823 KexiMigration::Data* md = new KexiMigration::Data(); 0824 md->setDestinationProjectData(new KexiProjectData(*cdata, dbname)); 0825 if (fileBasedSrcSelected()) { 0826 KDbConnectionData* conn_data = new KDbConnectionData(); 0827 conn_data->setDatabaseName(selectedSourceFileName()); 0828 md->source = conn_data; 0829 md->sourceName.clear(); 0830 } else { 0831 if (d->predefinedConnectionData) 0832 md->source = d->predefinedConnectionData; 0833 else 0834 md->source = d->srcConn->selectedConnectionData(); 0835 0836 if (!d->predefinedDatabaseName.isEmpty()) 0837 md->sourceName = d->predefinedDatabaseName; 0838 else 0839 md->sourceName = d->srcProjectSelector->selectedProjectData()->databaseName(); 0840 //! @todo Aah, this is so C-like. Move to performImport(). 0841 } 0842 md->setShouldCopyData(keepData); 0843 sourceDriver->setData(md); 0844 return sourceDriver; 0845 } 0846 return 0; 0847 } 0848 0849 tristate ImportWizard::import() 0850 { 0851 d->importExecuted = true; 0852 Kexi::ObjectStatus result; 0853 KexiMigrate* sourceDriver = prepareImport(result); 0854 bool acceptingNeeded = false; 0855 0856 // Perform import 0857 if (sourceDriver && !result.error()) { 0858 if (!d->sourceDBEncoding.isEmpty()) { 0859 sourceDriver->setPropertyValue("source_database_nonunicode_encoding", 0860 QVariant(d->sourceDBEncoding.toUpper().remove(' ')) // "CP1250", not "cp 1250" 0861 ); 0862 } 0863 if (!sourceDriver->checkIfDestinationDatabaseOverwritingNeedsAccepting(&result, &acceptingNeeded)) { 0864 qDebug() << "Abort import cause checkIfDestinationDatabaseOverwritingNeedsAccepting " 0865 "returned false."; 0866 return false; 0867 } 0868 0869 qDebug() << sourceDriver->data()->destinationProjectData()->databaseName(); 0870 qDebug() << "Performing import..."; 0871 } 0872 0873 if (sourceDriver && !result.error() && acceptingNeeded) { 0874 // ok, the destination-db already exists... 0875 if (KMessageBox::Yes != KMessageBox::warningYesNo(this, 0876 xi18nc("@info (don't add tags around %1, it's done already)", 0877 "<para>Database %1 already exists.</para>" 0878 "<para>Do you want to replace it with a new one?</para>", 0879 KexiUtils::localizedStringToHtmlSubstring( 0880 sourceDriver->data()->destinationProjectData()->infoString())), 0881 0, KGuiItem(xi18nc("@action:button Replace Database", "&Replace")), KStandardGuiItem::no())) 0882 { 0883 return cancelled; 0884 } 0885 } 0886 0887 if (sourceDriver && !result.error() && sourceDriver->progressSupported()) { 0888 d->progressBar->show(); 0889 } 0890 0891 if (sourceDriver && !result.error() && sourceDriver->performImport(&result)) { 0892 if (d->args) { 0893 d->args->insert("destinationDatabaseName", 0894 fileBasedDstSelected() 0895 ? sourceDriver->data()->destinationProjectData()->connectionData()->databaseName() 0896 : sourceDriver->data()->destinationProjectData()->databaseName()); 0897 QString destinationConnectionShortcut; 0898 if (d->dstConn->selectedConnectionData()) { 0899 destinationConnectionShortcut 0900 = Kexi::connset().fileNameForConnectionData(*d->dstConn->selectedConnectionData()); 0901 } 0902 if (!destinationConnectionShortcut.isEmpty()) { 0903 d->args->insert("destinationConnectionShortcut", destinationConnectionShortcut); 0904 } 0905 } 0906 d->finishPageItem->setHeader(xi18n("Success")); 0907 return true; 0908 } 0909 0910 if (!sourceDriver || result.error()) { 0911 d->progressBar->setValue(0); 0912 d->progressBar->hide(); 0913 0914 QString msg, details; 0915 KexiTextMessageHandler handler(&msg, &details); 0916 handler.showErrorMessage(&result); 0917 0918 qDebug() << msg << "\n" << details; 0919 0920 d->finishPageItem->setHeader(xi18n("Failure")); 0921 // note: we're using QString.arg() here because the msg and details 0922 // arguments are already in rich-text format, but leaving out the 0923 // arguments from xi18nc writes (I18N_ARGUMENT_MISSING). Thus, first 0924 // replace %n with themselves to avoid ki18n warning and then call 0925 // QString.arg() to replace them with HTML text. 0926 d->finishLbl->setText( 0927 xi18nc("@info", 0928 "<para>Import failed.</para>" 0929 "<para>%1</para>" 0930 "<para>%2</para>" 0931 "<para>You can click <interface>Back</interface> button and try again.</para>", 0932 "%1", "%2").arg(msg).arg(details)); 0933 return false; 0934 } 0935 return true; 0936 } 0937 0938 void ImportWizard::reject() 0939 { 0940 KAssistantDialog::reject(); 0941 } 0942 0943 //=========================================================== 0944 // 0945 void ImportWizard::next() 0946 { 0947 if (currentPage() == d->srcConnPageItem) { 0948 if (fileBasedSrcSelected() 0949 && /*! @todo use QUrl? */!QFileInfo(selectedSourceFileName()).isFile()) { 0950 0951 KMessageBox::sorry(this, xi18n("Select source database filename.")); 0952 return; 0953 } 0954 0955 KDbConnectionData* conndata = d->srcConn->selectedConnectionData(); 0956 if (!fileBasedSrcSelected() && !conndata) { 0957 KMessageBox::sorry(this, xi18n("Select source database.")); 0958 return; 0959 } 0960 0961 d->driverIdForSelectedSource = findDriverIdForSelectedSource(); // cache 0962 KexiMigrate* import = d->migrateManager.driver(d->driverIdForSelectedSource); 0963 if (!import || d->migrateManager.result().isError()) { 0964 QString dbname; 0965 if (fileBasedSrcSelected()) 0966 dbname = QDir::toNativeSeparators(selectedSourceFileName()); 0967 else 0968 dbname = conndata ? conndata->toUserVisibleString() : QString(); 0969 KMessageBox::error(this, 0970 dbname.isEmpty() ? 0971 xi18n("Could not import database. This type is not supported.") 0972 : xi18nc("@info", 0973 "Could not import database <resource>%1</resource>. " 0974 "This type is not supported.", dbname)); 0975 return; 0976 } 0977 0978 if (!fileBasedSrcSelected()) { 0979 // make sure we have password if needed 0980 tristate passwordNeeded = false; 0981 if (conndata->password().isEmpty()) { 0982 passwordNeeded = KexiDBPasswordDialog::getPasswordIfNeeded(conndata, this); 0983 } 0984 bool ok = passwordNeeded != cancelled; 0985 if (ok) { 0986 KexiGUIMessageHandler handler; 0987 d->prjSet = new KexiProjectSet(&handler); 0988 if (!d->prjSet->setConnectionData(conndata)) { 0989 handler.showErrorMessage(d->prjSet->result()); 0990 ok = false; 0991 } 0992 } 0993 if (!ok) { 0994 if (passwordNeeded == true) { 0995 conndata->setPassword(QString()); // not clear(), we have to remove password 0996 } 0997 delete d->prjSet; 0998 d->prjSet = 0; 0999 return; 1000 } 1001 } 1002 } else if (currentPage() == d->dstCaptionPageItem) { 1003 if (fileBasedDstSelected()) { 1004 if (QFileInfo::exists(d->dstNewDBNameUrl->url().toLocalFile())) { 1005 if (!KexiUtils::askForFileOverwriting(d->dstNewDBNameUrl->url().toLocalFile(), this)) { 1006 return; 1007 } 1008 } 1009 } 1010 } else if (currentPage() == d->importTypePageItem) { 1011 if (!fileBasedDstSelected()) { 1012 // make sure we have password if needed 1013 tristate passwordNeeded = false; 1014 KDbConnectionData* condata = d->dstConn->selectedConnectionData(); 1015 if (condata->password().isEmpty()) { 1016 passwordNeeded = KexiDBPasswordDialog::getPasswordIfNeeded(condata, this); 1017 } 1018 bool ok = passwordNeeded != cancelled; 1019 if (!ok) { 1020 if (passwordNeeded == true) { 1021 condata->setPassword(QString()); // not clear(), we have to remove password 1022 } 1023 return; 1024 } 1025 } 1026 } else if (currentPage() == d->importingPageItem) { 1027 if (!d->importExecuted) { 1028 d->importOptionsButton->hide(); 1029 backButton()->setEnabled(false); 1030 nextButton()->setEnabled(false); 1031 finishButton()->setEnabled(false); 1032 d->lblImportingTxt->setText(xi18n("Importing in progress...")); 1033 tristate res = import(); 1034 if (true == res) { 1035 d->finishLbl->setText( 1036 xi18nc("@info", 1037 "Database has been imported into Kexi project <resource>%1</resource>.", 1038 d->dstNewDBNameLineEdit->text())); 1039 button(QDialogButtonBox::Cancel)->setEnabled(false); 1040 backButton()->setEnabled(false); 1041 nextButton()->setEnabled(true); 1042 finishButton()->setEnabled(false); 1043 d->openImportedProjectCheckBox->show(); 1044 next(); 1045 return; 1046 } 1047 1048 d->progressBar->hide(); 1049 1050 button(QDialogButtonBox::Cancel)->setEnabled(true); 1051 backButton()->setEnabled(true); 1052 nextButton()->setEnabled(false); 1053 finishButton()->setEnabled(false); 1054 1055 d->openImportedProjectCheckBox->hide(); 1056 if (!res) 1057 next(); 1058 else if (~res) { 1059 arriveImportingPage(); 1060 } 1061 d->importExecuted = false; 1062 return; 1063 } 1064 } 1065 1066 setAppropriate(d->srcDBPageItem, !fileBasedSrcSelected() && !d->predefinedConnectionData); 1067 setAppropriate(d->dstPageItem, !fileBasedDstSelected()); 1068 KAssistantDialog::next(); 1069 } 1070 1071 void ImportWizard::back() 1072 { 1073 setAppropriate(d->srcDBPageItem, !fileBasedSrcSelected() && !d->predefinedConnectionData); 1074 KAssistantDialog::back(); 1075 } 1076 1077 void ImportWizard::slot_currentPageChanged(KPageWidgetItem* curPage,KPageWidgetItem* prevPage) 1078 { 1079 Q_UNUSED(prevPage); 1080 if (curPage == d->introPageItem) { 1081 } 1082 else if (curPage == d->srcConnPageItem) { 1083 arriveSrcConnPage(); 1084 } else if (curPage == d->srcDBPageItem) { 1085 arriveSrcDBPage(); 1086 } else if (curPage == d->dstTypePageItem) { 1087 } else if (curPage == d->dstCaptionPageItem) { 1088 arriveDstCaptionPage(); 1089 } else if (curPage == d->dstPageItem) { 1090 if (fileBasedDstSelected()) { 1091 if (prevPage == d->importTypePageItem) { 1092 KAssistantDialog::back(); 1093 } 1094 else { 1095 KAssistantDialog::next(); 1096 } 1097 } 1098 else { 1099 arriveDstPage(); 1100 } 1101 } else if (curPage == d->importingPageItem) { 1102 arriveImportingPage(); 1103 } else if (curPage == d->finishPageItem) { 1104 arriveFinishPage(); 1105 } 1106 } 1107 1108 void ImportWizard::helpClicked() 1109 { 1110 if (currentPage() == d->introPageItem) { 1111 KMessageBox::information(this, xi18n("No help is available for this page."), xi18n("Help")); 1112 } 1113 else if (currentPage() == d->srcConnPageItem) { 1114 KMessageBox::information(this, xi18n("Here you can choose the location to import data from."), xi18n("Help")); 1115 } else if (currentPage() == d->srcDBPageItem) { 1116 KMessageBox::information(this, xi18n("Here you can choose the actual database to import data from."), xi18n("Help")); 1117 } else if (currentPage() == d->dstTypePageItem) { 1118 KMessageBox::information(this, xi18n("Here you can choose the location to save the data."), xi18n("Help")); 1119 } else if (currentPage() == d->dstPageItem) { 1120 KMessageBox::information(this, xi18n("Here you can choose the location to save the data in and the new database name."), xi18n("Help")); 1121 } else if (currentPage() == d->finishPageItem || currentPage() == d->importingPageItem) { 1122 KMessageBox::information(this, xi18n("No help is available for this page."), xi18n("Help")); 1123 } 1124 } 1125 1126 void ImportWizard::slotOptionsButtonClicked() 1127 { 1128 OptionsDialog dlg(selectedSourceFileName(), d->sourceDBEncoding, this); 1129 if (QDialog::Accepted == dlg.exec()) { 1130 d->sourceDBEncoding = dlg.encodingComboBox()->selectedEncoding(); 1131 } 1132 } 1133 1134 void ImportWizard::sourceConnectionSelected(bool selected) 1135 { 1136 if (selected) { 1137 next(); 1138 } 1139 }