File indexing completed on 2024-05-12 16:40:14

0001 /* This file is part of the KDE project
0002    Copyright (C) 2009 Adam Pigg <adam@piggz.co.uk>
0003    Copyright (C) 2014-2016 Jarosław Staniek <staniek@kde.org>
0004 
0005    This library is free software; you can redistribute it and/or
0006    modify it under the terms of the GNU Library General Public
0007    License version 2 as published by the Free Software Foundation.
0008 
0009    This library is distributed in the hope that it will be useful,
0010    but WITHOUT ANY WARRANTY; without even the implied warranty of
0011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012    Library General Public License for more details.
0013 
0014    You should have received a copy of the GNU Library General Public License
0015    along with this library; see the file COPYING.LIB.  If not, write to
0016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017    Boston, MA 02110-1301, USA.
0018 */
0019 
0020 #include "importtablewizard.h"
0021 #include "importoptionsdlg.h"
0022 #include "migratemanager.h"
0023 #include "keximigrate.h"
0024 #include "keximigratedata.h"
0025 #include "AlterSchemaWidget.h"
0026 #include <KexiIcon.h>
0027 #include <core/kexidbconnectionset.h>
0028 #include <core/kexi.h>
0029 #include <core/kexipartmanager.h>
0030 #include <kexiutils/utils.h>
0031 #include <kexidbdrivercombobox.h>
0032 #include <kexitextmsghandler.h>
0033 #include <kexipart.h>
0034 #include <KexiMainWindowIface.h>
0035 #include <kexiproject.h>
0036 #include <widget/kexicharencodingcombobox.h>
0037 #include <widget/kexiprjtypeselector.h>
0038 #include <widget/KexiConnectionSelectorWidget.h>
0039 #include <widget/KexiProjectSelectorWidget.h>
0040 #include <widget/KexiDBCaptionPage.h>
0041 #include <widget/KexiNameWidget.h>
0042 
0043 #include <KDbConnectionData>
0044 #include <KDbDriver>
0045 #include <KDbDriverManager>
0046 #include <KDbSqlResult>
0047 #include <KDbTransactionGuard>
0048 #include <KDbUtils>
0049 
0050 #include <KMessageBox>
0051 
0052 #include <QSet>
0053 #include <QVBoxLayout>
0054 #include <QListWidget>
0055 #include <QStringList>
0056 #include <QProgressBar>
0057 #include <QCheckBox>
0058 #include <QMimeDatabase>
0059 #include <QMimeType>
0060 #include <QPushButton>
0061 #include <QDebug>
0062 
0063 using namespace KexiMigration;
0064 
0065 #define RECORDS_FOR_PREVIEW 3
0066 
0067 ImportTableWizard::ImportTableWizard ( KDbConnection* curDB, QWidget* parent, QMap<QString, QString>* args, Qt::WindowFlags flags)
0068     : KAssistantDialog ( parent, flags ),
0069       m_args(args)
0070 {
0071     m_connection = curDB;
0072     m_migrateDriver = 0;
0073     m_prjSet = 0;
0074     m_importComplete = false;
0075     m_importWasCanceled = false;
0076     m_sourceDbEncoding = QString::fromLatin1(KexiUtils::encoding()); //default
0077 
0078     KexiMainWindowIface::global()->setReasonableDialogSize(this);
0079 
0080     setupIntroPage();
0081     setupSrcConn();
0082     setupSrcDB();
0083     setupTableSelectPage();
0084     setupAlterTablePage();
0085     setupImportingPage();
0086     setupProgressPage();
0087     setupFinishPage();
0088 
0089     setValid(m_srcConnPageItem, false);
0090 
0091     connect(this, SIGNAL(currentPageChanged(KPageWidgetItem*,KPageWidgetItem*)), this, SLOT(slot_currentPageChanged(KPageWidgetItem*,KPageWidgetItem*)));
0092     //! @todo Change this to message prompt when we move to non-dialog wizard.
0093     connect(m_srcConnSel, SIGNAL(connectionSelected(bool)), this,
0094             SLOT(slotConnPageItemSelected(bool)));
0095     connect(m_srcConnSel, &KexiConnectionSelectorWidget::connectionItemHighlighted,
0096             [this]() { setValid(m_srcConnPageItem, true); });
0097     connect(m_srcConnSel, &KexiConnectionSelectorWidget::connectionItemExecuted, [this]() {
0098         setValid(m_srcConnPageItem, true);
0099         next();
0100     });
0101 }
0102 
0103 
0104 ImportTableWizard::~ImportTableWizard()
0105 {
0106     delete m_prjSet;
0107     delete m_srcConnSel;
0108 }
0109 
0110 void ImportTableWizard::back() {
0111     KAssistantDialog::back();
0112 }
0113 
0114 void ImportTableWizard::next() {
0115     if (currentPage() == m_srcConnPageItem) {
0116         if (fileBasedSrcSelected()) {
0117             setAppropriate(m_srcDBPageItem, false);
0118         } else {
0119             setAppropriate(m_srcDBPageItem, true);
0120         }
0121     } else if (currentPage() == m_alterTablePageItem) {
0122         if (m_alterSchemaWidget->nameExists(m_alterSchemaWidget->nameWidget()->nameText())) {
0123             KMessageBox::information(this,
0124                  xi18nc("@info",
0125                         "<resource>%1</resource> name is already used by an existing table. "
0126                         "Enter different table name to continue.",
0127                         m_alterSchemaWidget->nameWidget()->nameText()),
0128                  xi18n("Name Already Used"));
0129             return;
0130         }
0131     }
0132 
0133     KAssistantDialog::next();
0134 }
0135 
0136 void ImportTableWizard::accept() {
0137     if (m_args) {
0138         if (m_finishCheckBox->isChecked()) {
0139             m_args->insert("destinationTableName",m_alterSchemaWidget->nameWidget()->nameText());
0140         } else {
0141             m_args->remove("destinationTableName");
0142         }
0143     }
0144 
0145     QDialog::accept();
0146 }
0147 
0148 void ImportTableWizard::reject() {
0149     QDialog::reject();
0150 }
0151 
0152 //===========================================================
0153 //
0154 void ImportTableWizard::setupIntroPage()
0155 {
0156     m_introPageWidget = new QWidget(this);
0157     QVBoxLayout *vbox = new QVBoxLayout();
0158 
0159     m_introPageWidget->setLayout(vbox);
0160 
0161     KexiUtils::setStandardMarginsAndSpacing(vbox);
0162 
0163     QLabel *lblIntro = new QLabel(m_introPageWidget);
0164     lblIntro->setAlignment(Qt::AlignTop | Qt::AlignLeft);
0165     lblIntro->setWordWrap(true);
0166     lblIntro->setText(
0167         xi18nc("@info",
0168              "<para>Table Importing Assistant allows you to import a table from an existing "
0169              "database into the current Kexi project.</para>"
0170              "<para>Click <interface>Next</interface> button to continue or "
0171              "<interface>Cancel</interface> button to exit this assistant.</para>"));
0172     vbox->addWidget(lblIntro);
0173 
0174     m_introPageItem = new KPageWidgetItem(m_introPageWidget,
0175                                           xi18n("Welcome to the Table Importing Assistant"));
0176     addPage(m_introPageItem);
0177 }
0178 
0179 void ImportTableWizard::setupSrcConn()
0180 {
0181     m_srcConnPageWidget = new QWidget(this);
0182     QVBoxLayout *vbox = new QVBoxLayout(m_srcConnPageWidget);
0183 
0184     m_srcConnSel = new KexiConnectionSelectorWidget(&Kexi::connset(),
0185                             QUrl("kfiledialog:///ProjectMigrationSourceDir"),
0186                             KexiConnectionSelectorWidget::Opening, m_srcConnPageWidget);
0187 
0188     m_srcConnSel->hideConnectonIcon();
0189     m_srcConnSel->showSimpleConnection();
0190 
0191     //! @todo remove when support for kexi files as source prj is added in migration
0192     const QStringList excludedMimeTypes({
0193         KDb::defaultFileBasedDriverMimeType(),
0194         "application/x-kexiproject-shortcut",
0195         "application/x-kexi-connectiondata"});
0196     m_srcConnSel->setExcludedMimeTypes(excludedMimeTypes);
0197 
0198     vbox->addWidget(m_srcConnSel);
0199 
0200     m_srcConnPageItem = new KPageWidgetItem(m_srcConnPageWidget, xi18n("Select Location for Source Database"));
0201     addPage(m_srcConnPageItem);
0202 }
0203 
0204 void ImportTableWizard::setupSrcDB()
0205 {
0206     // arrivesrcdbPage creates widgets on that page
0207     m_srcDBPageWidget = new QWidget(this);
0208     m_srcDBName = NULL;
0209 
0210     m_srcDBPageItem = new KPageWidgetItem(m_srcDBPageWidget, xi18n("Select Source Database"));
0211     addPage(m_srcDBPageItem);
0212 }
0213 
0214 
0215 void ImportTableWizard::setupTableSelectPage() {
0216     m_tablesPageWidget = new QWidget(this);
0217     QVBoxLayout *vbox = new QVBoxLayout(m_tablesPageWidget);
0218     KexiUtils::setStandardMarginsAndSpacing(vbox);
0219 
0220     m_tableListWidget = new QListWidget(this);
0221     m_tableListWidget->setSelectionMode(QAbstractItemView::SingleSelection);
0222     connect(m_tableListWidget, SIGNAL(itemSelectionChanged()),
0223             this, SLOT(slotTableListWidgetSelectionChanged()));
0224 
0225     vbox->addWidget(m_tableListWidget);
0226 
0227     m_tablesPageItem = new KPageWidgetItem(m_tablesPageWidget, xi18n("Select the Table to Import"));
0228     addPage(m_tablesPageItem);
0229 }
0230 
0231 //===========================================================
0232 //
0233 void ImportTableWizard::setupImportingPage()
0234 {
0235     m_importingPageWidget = new QWidget(this);
0236     m_importingPageWidget->hide();
0237     QVBoxLayout *vbox = new QVBoxLayout(m_importingPageWidget);
0238     KexiUtils::setStandardMarginsAndSpacing(vbox);
0239     m_lblImportingTxt = new QLabel(m_importingPageWidget);
0240     m_lblImportingTxt->setAlignment(Qt::AlignTop | Qt::AlignLeft);
0241     m_lblImportingTxt->setWordWrap(true);
0242 
0243     m_lblImportingErrTxt = new QLabel(m_importingPageWidget);
0244     m_lblImportingErrTxt->setAlignment(Qt::AlignTop | Qt::AlignLeft);
0245     m_lblImportingErrTxt->setWordWrap(true);
0246 
0247     vbox->addWidget(m_lblImportingTxt);
0248     vbox->addWidget(m_lblImportingErrTxt);
0249     vbox->addStretch(1);
0250 
0251     QWidget *options_widget = new QWidget(m_importingPageWidget);
0252     vbox->addWidget(options_widget);
0253     QVBoxLayout *options_vbox = new QVBoxLayout(options_widget);
0254     options_vbox->setSpacing(KexiUtils::spacingHint());
0255     m_importOptionsButton = new QPushButton(koIcon("configure"), xi18n("Advanced Options"), options_widget);
0256     connect(m_importOptionsButton, SIGNAL(clicked()),this, SLOT(slotOptionsButtonClicked()));
0257     options_vbox->addWidget(m_importOptionsButton);
0258     options_vbox->addStretch(1);
0259 
0260     m_importingPageWidget->show();
0261 
0262     m_importingPageItem = new KPageWidgetItem(m_importingPageWidget, xi18n("Importing"));
0263     addPage(m_importingPageItem);
0264 }
0265 
0266 void ImportTableWizard::setupAlterTablePage()
0267 {
0268     m_alterTablePageWidget = new QWidget(this);
0269     m_alterTablePageWidget->hide();
0270 
0271     QVBoxLayout *vbox = new QVBoxLayout(m_alterTablePageWidget);
0272     KexiUtils::setStandardMarginsAndSpacing(vbox);
0273 
0274     m_alterSchemaWidget = new KexiMigration::AlterSchemaWidget(this);
0275     vbox->addWidget(m_alterSchemaWidget);
0276     m_alterTablePageWidget->show();
0277 
0278     m_alterTablePageItem = new KPageWidgetItem(m_alterTablePageWidget, xi18n("Alter the Detected Table Design"));
0279     addPage(m_alterTablePageItem);
0280 }
0281 
0282 void ImportTableWizard::setupProgressPage()
0283 {
0284     m_progressPageWidget = new QWidget(this);
0285     m_progressPageWidget->hide();
0286     QVBoxLayout *vbox = new QVBoxLayout(m_progressPageWidget);
0287     KexiUtils::setStandardMarginsAndSpacing(vbox);
0288     m_progressPageWidget->setLayout(vbox);
0289     m_progressLbl = new QLabel(m_progressPageWidget);
0290     m_progressLbl->setAlignment(Qt::AlignTop | Qt::AlignLeft);
0291     m_progressLbl->setWordWrap(true);
0292     m_rowsImportedLbl = new QLabel(m_progressPageWidget);
0293 
0294     m_importingProgressBar = new QProgressBar(m_progressPageWidget);
0295     m_importingProgressBar->setMinimum(0);
0296     m_importingProgressBar->setMaximum(0);
0297     m_importingProgressBar->setValue(0);
0298 
0299     vbox->addWidget(m_progressLbl);
0300     vbox->addWidget(m_rowsImportedLbl);
0301     vbox->addWidget(m_importingProgressBar);
0302     vbox->addStretch(1);
0303 
0304     m_progressPageItem = new KPageWidgetItem(m_progressPageWidget, xi18n("Processing Import"));
0305     addPage(m_progressPageItem);
0306 }
0307 
0308 void ImportTableWizard::setupFinishPage()
0309 {
0310     m_finishPageWidget = new QWidget(this);
0311     m_finishPageWidget->hide();
0312     QVBoxLayout *vbox = new QVBoxLayout(m_finishPageWidget);
0313     KexiUtils::setStandardMarginsAndSpacing(vbox);
0314     m_finishLbl = new QLabel(m_finishPageWidget);
0315     m_finishLbl->setAlignment(Qt::AlignTop | Qt::AlignLeft);
0316     m_finishLbl->setWordWrap(true);
0317 
0318     vbox->addWidget(m_finishLbl);
0319     m_finishCheckBox = new QCheckBox(xi18n("Open imported table"),
0320                                      m_finishPageWidget);
0321     m_finishCheckBox->setChecked(true);
0322     vbox->addSpacing(KexiUtils::spacingHint());
0323     vbox->addWidget(m_finishCheckBox);
0324     vbox->addStretch(1);
0325 
0326     m_finishPageItem = new KPageWidgetItem(m_finishPageWidget, xi18n("Success"));
0327     addPage(m_finishPageItem);
0328 }
0329 
0330 void ImportTableWizard::slot_currentPageChanged(KPageWidgetItem* curPage,KPageWidgetItem* prevPage)
0331 {
0332     Q_UNUSED(prevPage);
0333     if (curPage == m_introPageItem) {
0334     }
0335     else if (curPage == m_srcConnPageItem) {
0336         arriveSrcConnPage();
0337     } else if (curPage == m_srcDBPageItem) {
0338         arriveSrcDBPage();
0339     } else if (curPage == m_tablesPageItem) {
0340         arriveTableSelectPage(prevPage);
0341     } else if (curPage == m_alterTablePageItem) {
0342         if (prevPage == m_tablesPageItem) {
0343             arriveAlterTablePage();
0344         }
0345     } else if (curPage == m_importingPageItem) {
0346         arriveImportingPage();
0347     } else if (curPage == m_progressPageItem) {
0348         arriveProgressPage();
0349     } else if (curPage == m_finishPageItem) {
0350         arriveFinishPage();
0351     }
0352 }
0353 
0354 void ImportTableWizard::arriveSrcConnPage()
0355 {
0356 }
0357 
0358 void ImportTableWizard::arriveSrcDBPage()
0359 {
0360     if (fileBasedSrcSelected()) {
0361         //! @todo Back button doesn't work after selecting a file to import
0362     } else {
0363         delete m_prjSet;
0364         m_prjSet = 0;
0365         m_srcDBPageWidget->hide();
0366         qDebug() << "Looks like we need a project selector widget!";
0367 
0368         KDbConnectionData* conndata = m_srcConnSel->selectedConnectionData();
0369         if (conndata) {
0370             KexiGUIMessageHandler handler;
0371             m_prjSet = new KexiProjectSet(&handler);
0372             if (!m_prjSet->setConnectionData(conndata)) {
0373                 handler.showErrorMessage(m_prjSet->result());
0374                 delete m_prjSet;
0375                 m_prjSet = 0;
0376                 return;
0377             }
0378             if (!m_srcDBName) {
0379                 QVBoxLayout *vbox = new QVBoxLayout(m_srcDBPageWidget);
0380                 KexiUtils::setStandardMarginsAndSpacing(vbox);
0381                 m_srcDBName = new KexiProjectSelectorWidget(m_srcDBPageWidget);
0382                 vbox->addWidget(m_srcDBName);
0383                 m_srcDBName->label()->setText(xi18n("Select source database you wish to import:"));
0384             }
0385             m_srcDBName->setProjectSet(m_prjSet);
0386         }
0387         m_srcDBPageWidget->show();
0388     }
0389 }
0390 
0391 void ImportTableWizard::arriveTableSelectPage(KPageWidgetItem *prevPage)
0392 {
0393     if (prevPage == m_alterTablePageItem) {
0394         if (m_tableListWidget->count() == 1) { //we was skiping it before
0395             back();
0396         }
0397     } else {
0398         Kexi::ObjectStatus result;
0399         KexiUtils::WaitCursor wait;
0400         m_tableListWidget->clear();
0401         m_migrateDriver = prepareImport(&result);
0402 
0403         bool ok = m_migrateDriver;
0404         if (ok) {
0405             if (!m_sourceDbEncoding.isEmpty()) {
0406                 m_migrateDriver->setPropertyValue(
0407                     "source_database_nonunicode_encoding",
0408                     QVariant(m_sourceDbEncoding.toUpper().remove(' ')) // "CP1250", not "cp 1250"
0409                     );
0410             }
0411             ok = m_migrateDriver->connectSource(&result);
0412         }
0413         if (ok) {
0414             QStringList tableNames;
0415             if (m_migrateDriver->tableNames(&tableNames)) {
0416                 m_tableListWidget->addItems(tableNames);
0417             }
0418             if (m_tableListWidget->item(0)) {
0419                 m_tableListWidget->item(0)->setSelected(true);
0420                 if (m_tableListWidget->count() == 1) {
0421                     KexiUtils::removeWaitCursor();
0422                     next();
0423                 }
0424             }
0425         }
0426         KexiUtils::removeWaitCursor();
0427         if (!ok) {
0428             QString errMessage =result.message.isEmpty() ? xi18n("Unknown error") : result.message;
0429             QString errDescription = result.description.isEmpty() ? errMessage : result.description;
0430             KMessageBox::error(this, errMessage, errDescription);
0431             setValid(m_tablesPageItem, false);
0432         }
0433     }
0434 }
0435 
0436 void ImportTableWizard::arriveAlterTablePage()
0437 {
0438 //! @todo handle errors
0439     if (m_tableListWidget->selectedItems().isEmpty())
0440         return;
0441 //! @todo (js) support multiple tables?
0442 #if 0
0443     foreach(QListWidgetItem *table, m_tableListWidget->selectedItems()) {
0444         m_importTableName = table->text();
0445     }
0446 #else
0447     m_importTableName = m_tableListWidget->selectedItems().first()->text();
0448 #endif
0449 
0450     QScopedPointer<KDbTableSchema> ts(new KDbTableSchema);
0451     if (!m_migrateDriver->readTableSchema(m_importTableName, ts.data())) {
0452         return;
0453     }
0454 
0455     setValid(m_alterTablePageItem, ts->fieldCount() > 0);
0456     if (isValid(m_alterTablePageItem)) {
0457        connect(m_alterSchemaWidget->nameWidget(), SIGNAL(textChanged()), this, SLOT(slotNameChanged()), Qt::UniqueConnection);
0458     }
0459 
0460     m_alterSchemaWidget->setTableSchema(ts.take());
0461     if (!readFromTable()) {
0462         m_alterSchemaWidget->setTableSchema(nullptr);
0463         back();
0464         KMessageBox::information(this,
0465             xi18nc("@info", "Could not import table <resource>%1</resource>. "
0466                    "Select different table or cancel importing.", m_importTableName));
0467     }
0468 }
0469 
0470 bool ImportTableWizard::readFromTable()
0471 {
0472     QSharedPointer<KDbSqlResult> tableResult = m_migrateDriver->readFromTable(m_importTableName);
0473     KDbTableSchema *newSchema = m_alterSchemaWidget->newSchema();
0474     if (!tableResult || tableResult->lastResult().isError()
0475             || tableResult->fieldsCount() != newSchema->fieldCount())
0476     {
0477         back();
0478         KMessageBox::information(this,
0479             xi18nc("@info", "Could not import table <resource>%1</resource>. "
0480                    "Select different table or cancel importing.", m_importTableName));
0481         return false;
0482     }
0483     QScopedPointer<QList<KDbRecordData*>> data(new QList<KDbRecordData*>);
0484     for (int i = 0; i < RECORDS_FOR_PREVIEW; ++i) {
0485         QSharedPointer<KDbRecordData> record(tableResult->fetchRecordData());
0486         if (!record) {
0487             if (tableResult->lastResult().isError()) {
0488                 return false;
0489             }
0490             break;
0491         }
0492         data->append(record.data());
0493     }
0494     if (data->isEmpty()) {
0495         back();
0496         KMessageBox::information(this,
0497             xi18nc("@info", "No data has been found in table <resource>%1</resource>. "
0498                    "Select different table or cancel importing.", m_importTableName));
0499         return false;
0500     }
0501     m_alterSchemaWidget->model()->setRowCount(data->count());
0502     m_alterSchemaWidget->setData(data.take());
0503     return true;
0504 }
0505 
0506 void ImportTableWizard::arriveImportingPage()
0507 {
0508     m_importingPageWidget->hide();
0509 #if 0
0510     if (checkUserInput()) {
0511         //setNextEnabled(m_importingPageWidget, true);
0512         user2Button->setEnabled(true);
0513     } else {
0514         //setNextEnabled(m_importingPageWidget, false);
0515         user2Button->setEnabled(false);
0516     }
0517 #endif
0518 
0519     QString txt;
0520 
0521     txt = xi18nc("@info Table import wizard, final message", "<para>All required information has now been gathered. "
0522                  "Click <interface>Next</interface> button to start importing table <resource>%1</resource>.</para>"
0523                  "<para><note>Depending on size of the table this may take some time.</note></para>",
0524                  m_alterSchemaWidget->nameWidget()->nameText());
0525 
0526     m_lblImportingTxt->setText(txt);
0527 
0528     //temp. hack for MS Access driver only
0529     //! @todo for other databases we will need KexiMigration::Connection
0530     //! and KexiMigration::Driver classes
0531     bool showOptions = false;
0532     if (fileBasedSrcSelected()) {
0533         Kexi::ObjectStatus result;
0534         KexiMigrate* sourceDriver = prepareImport(&result);
0535         if (sourceDriver) {
0536             showOptions = !result.error()
0537             && sourceDriver->propertyValue("source_database_has_nonunicode_encoding").toBool();
0538             sourceDriver->setData(nullptr);
0539         }
0540     }
0541     if (showOptions)
0542         m_importOptionsButton->show();
0543     else
0544         m_importOptionsButton->hide();
0545 
0546     m_importingPageWidget->show();
0547     setAppropriate(m_progressPageItem, true);
0548 }
0549 
0550 void ImportTableWizard::arriveProgressPage()
0551 {
0552     m_progressLbl->setText(xi18nc("@info", "Please wait while the table is imported."));
0553 
0554     backButton()->setEnabled(false);
0555     nextButton()->setEnabled(false);
0556 
0557     connect(button(QDialogButtonBox::Cancel), &QPushButton::clicked,
0558             this, &ImportTableWizard::slotCancelClicked);
0559 
0560     QApplication::setOverrideCursor(Qt::BusyCursor);
0561     m_importComplete = doImport();
0562     QApplication::restoreOverrideCursor();
0563 
0564     disconnect(button(QDialogButtonBox::Cancel), &QPushButton::clicked,
0565                this, &ImportTableWizard::slotCancelClicked);
0566 
0567     next();
0568 }
0569 
0570 void ImportTableWizard::arriveFinishPage()
0571 {
0572     if (m_importComplete) {
0573         m_finishPageItem->setHeader(xi18n("Success"));
0574         m_finishLbl->setText(xi18nc("@info",
0575                                     "Table <resource>%1</resource> has been imported.",
0576                                     m_alterSchemaWidget->nameWidget()->nameText()));
0577     } else {
0578         m_finishPageItem->setHeader(xi18n("Failure"));
0579         m_finishLbl->setText(xi18n("An error occurred."));
0580     }
0581     m_migrateDriver->disconnectSource();
0582     button(QDialogButtonBox::Cancel)->setEnabled(!m_importComplete);
0583     m_finishCheckBox->setVisible(m_importComplete);
0584     finishButton()->setEnabled(m_importComplete);
0585     nextButton()->setEnabled(m_importComplete);
0586     setAppropriate(m_progressPageItem, false);
0587 }
0588 
0589 bool ImportTableWizard::fileBasedSrcSelected() const
0590 {
0591     return m_srcConnSel->selectedConnectionType() == KexiConnectionSelectorWidget::FileBased;
0592 }
0593 
0594 KexiMigrate* ImportTableWizard::prepareImport(Kexi::ObjectStatus *result)
0595 {
0596     Q_ASSERT(result);
0597     // Find a source (migration) driver name
0598     QString sourceDriverId = driverIdForSelectedSource();
0599     if (sourceDriverId.isEmpty()) {
0600         result->setStatus(xi18n("No appropriate migration driver found."),
0601                             m_migrateManager.possibleProblemsMessage());
0602     }
0603 
0604     // Get a source (migration) driver
0605     KexiMigrate* sourceDriver = 0;
0606     if (!result->error()) {
0607         sourceDriver = m_migrateManager.driver(sourceDriverId);
0608         if (!sourceDriver || m_migrateManager.result().isError()) {
0609             qDebug() << "Import migrate driver error...";
0610             result->setStatus(m_migrateManager.resultable());
0611         }
0612     }
0613 
0614     // Set up source (migration) data required for connection
0615     if (sourceDriver && !result->error()) {
0616         #if 0
0617         // Setup progress feedback for the GUI
0618         if (sourceDriver->progressSupported()) {
0619             m_progressBar->updateGeometry();
0620             disconnect(sourceDriver, SIGNAL(progressPercent(int)),
0621                        this, SLOT(progressUpdated(int)));
0622                        connect(sourceDriver, SIGNAL(progressPercent(int)),
0623                                this, SLOT(progressUpdated(int)));
0624                                progressUpdated(0);
0625         }
0626         #endif
0627 
0628         bool keepData = true;
0629 
0630         #if 0
0631         if (m_importTypeStructureAndDataCheckBox->isChecked()) {
0632             qDebug() << "Structure and data selected";
0633             keepData = true;
0634         } else if (m_importTypeStructureOnlyCheckBox->isChecked()) {
0635             qDebug() << "structure only selected";
0636             keepData = false;
0637         } else {
0638             qDebug() << "Neither radio button is selected (not possible?) presume keep data";
0639             keepData = true;
0640         }
0641         #endif
0642 
0643         KexiMigration::Data* md = new KexiMigration::Data();
0644 
0645         if (fileBasedSrcSelected()) {
0646             KDbConnectionData* conn_data = new KDbConnectionData();
0647             conn_data->setDatabaseName(m_srcConnSel->selectedFile());
0648             md->source = conn_data;
0649             md->sourceName.clear();
0650         } else {
0651             md->source = m_srcConnSel->selectedConnectionData();
0652             md->sourceName = m_srcDBName->selectedProjectData()->databaseName();
0653 
0654         }
0655 
0656         md->setShouldCopyData(keepData);
0657         sourceDriver->setData(md);
0658 
0659         return sourceDriver;
0660     }
0661     return 0;
0662 }
0663 
0664 //===========================================================
0665 //
0666 QString ImportTableWizard::driverIdForSelectedSource()
0667 {
0668     if (fileBasedSrcSelected()) {
0669         QMimeDatabase db;
0670         QMimeType mime = db.mimeTypeForFile(m_srcConnSel->selectedFile());
0671         if (!mime.isValid()
0672             || mime.name() == "application/octet-stream"
0673             || mime.name() == "text/plain"
0674             || mime.name() == "application/zip")
0675         {
0676             //try by URL:
0677             mime = db.mimeTypeForFile(m_srcConnSel->selectedFile());
0678         }
0679         if (!mime.isValid()) {
0680             return QString();
0681         }
0682         const QStringList ids(m_migrateManager.driverIdsForMimeType(mime.name()));
0683         //! @todo do we want to return first migrate driver for the mime type or allow to select it?
0684         return ids.isEmpty() ? QString() : ids.first();
0685     }
0686     return m_srcConnSel->selectedConnectionData()
0687            ? m_srcConnSel->selectedConnectionData()->databaseName() : QString();
0688 }
0689 
0690 bool ImportTableWizard::doImport()
0691 {
0692     KexiGUIMessageHandler msg;
0693 
0694     KexiProject* project = KexiMainWindowIface::global()->project();
0695     if (!project) {
0696         msg.showErrorMessage(KDbMessageHandler::Error, xi18n("No project available."));
0697         return false;
0698     }
0699 
0700     KexiPart::Part *part = Kexi::partManager().partForPluginId("org.kexi-project.table");
0701     if (!part) {
0702         msg.showErrorMessage(Kexi::partManager().result());
0703         return false;
0704     }
0705 
0706     KDbTableSchema* newSchema = m_alterSchemaWidget->newSchema();
0707     if (!newSchema) {
0708         msg.showErrorMessage(KDbMessageHandler::Error, xi18n("No table was selected to import."));
0709         return false;
0710     }
0711     newSchema->setName(m_alterSchemaWidget->nameWidget()->nameText());
0712     newSchema->setCaption(m_alterSchemaWidget->nameWidget()->captionText());
0713 
0714     KexiPart::Item* partItemForSavedTable = project->createPartItem(part->info(), newSchema->name());
0715     if (!partItemForSavedTable) {
0716         msg.showErrorMessage(project->result());
0717         return false;
0718     }
0719 
0720     //Create the table
0721     if (!m_connection->createTable(newSchema,
0722             KDbConnection::CreateTableOption::Default | KDbConnection::CreateTableOption::DropDestination))
0723     {
0724         msg.showErrorMessage(KDbMessageHandler::Error,
0725                              xi18nc("@info", "Unable to create table <resource>%1</resource>.",
0726                                     newSchema->name()));
0727         return false;
0728     }
0729     m_alterSchemaWidget->takeTableSchema(); //m_connection takes ownership of the KDbTableSchema object
0730 
0731     //Import the data
0732     QApplication::setOverrideCursor(Qt::BusyCursor);
0733     QList<QVariant> row;
0734     unsigned int fieldCount = newSchema->fieldCount();
0735     m_migrateDriver->moveFirst();
0736     KDbTransactionGuard tg(m_connection);
0737     if (m_connection->result().isError()) {
0738         QApplication::restoreOverrideCursor();
0739         return false;
0740     }
0741     do  {
0742         for (unsigned int i = 0; i < fieldCount; ++i) {
0743             if (m_importWasCanceled) {
0744                 return false;
0745             }
0746             if (i % 100 == 0) {
0747                 QApplication::processEvents();
0748             }
0749             row.append(m_migrateDriver->value(i));
0750         }
0751         m_connection->insertRecord(newSchema, row);
0752         row.clear();
0753     } while (m_migrateDriver->moveNext());
0754     if (!tg.commit()) {
0755         QApplication::restoreOverrideCursor();
0756         return false;
0757     }
0758     QApplication::restoreOverrideCursor();
0759 
0760     //Done so save part and update gui
0761     partItemForSavedTable->setIdentifier(newSchema->id());
0762     project->addStoredItem(part->info(), partItemForSavedTable);
0763 
0764     return true;
0765 }
0766 
0767 void ImportTableWizard::slotConnPageItemSelected(bool isSelected)
0768 {
0769     setValid(m_srcConnPageItem, isSelected);
0770     if (isSelected && fileBasedSrcSelected()) {
0771         next();
0772     }
0773 }
0774 
0775 void ImportTableWizard::slotTableListWidgetSelectionChanged()
0776 {
0777     setValid(m_tablesPageItem, !m_tableListWidget->selectedItems().isEmpty());
0778 }
0779 
0780 void ImportTableWizard::slotNameChanged()
0781 {
0782     setValid(m_alterTablePageItem, !m_alterSchemaWidget->nameWidget()->captionText().isEmpty());
0783 }
0784 
0785 void ImportTableWizard::slotCancelClicked()
0786 {
0787     m_importWasCanceled = true;
0788 }
0789 
0790 void ImportTableWizard::slotOptionsButtonClicked()
0791 {
0792     OptionsDialog dlg(m_srcConnSel->selectedFile(), m_sourceDbEncoding, this);
0793     if (QDialog::Accepted == dlg.exec()) {
0794         m_sourceDbEncoding = dlg.encodingComboBox()->selectedEncoding();
0795     }
0796 }