#include "ImportCsvDialog.h" #include "ui_ImportCsvDialog.h" #include #include #include #include #include "sqlitedb.h" ImportCsvDialog::ImportCsvDialog(const QString& filename, DBBrowserDB* db, QWidget* parent) : QDialog(parent), ui(new Ui::ImportCsvDialog), csvFilename(filename), pdb(db) { ui->setupUi(this); checkInput(); updatePreview(); } ImportCsvDialog::~ImportCsvDialog() { delete ui; } namespace { void rollback(ImportCsvDialog* dialog, DBBrowserDB* pdb, QProgressDialog& progress, const QString& savepointName) { progress.hide(); QApplication::restoreOverrideCursor(); // restore original cursor QString error = QObject::tr("Error importing data. Message from database engine: %1").arg(pdb->lastErrorMessage); QMessageBox::warning(dialog, QApplication::applicationName(), error); pdb->revert(savepointName); } } void ImportCsvDialog::accept() { QString sql; // Parse all csv data int numfields; QStringList curList = pdb->decodeCSV(csvFilename, currentSeparatorChar(), currentQuoteChar(), -1, &numfields); // Can not operate on an empty result if(numfields == 0) return; // Generate field names. These are either taken from the first CSV row or are generated in the format of "fieldXY" depending on the user input QStringList fieldList; if(ui->checkboxHeader->isChecked()) { int cfieldnum = 0; while(!curList.empty() && cfieldnum != numfields) { // Remove invalid characters QString thisfield = curList.front(); thisfield.replace(" ", ""); thisfield.replace('"', ""); thisfield.replace("'",""); thisfield.replace(",",""); thisfield.replace(";",""); // Avoid empty field names if(thisfield.isEmpty()) thisfield = QString("field%1").arg(cfieldnum+1); fieldList.push_back(thisfield); cfieldnum++; curList.pop_front(); } } else { for(int i=0;igetBrowsableObjects(); for(objectMap::ConstIterator i=objects.begin();i!=objects.end();++i) { if(i.value().gettype() == "table" && i.value().getname() == ui->editName->text()) { if(i.value().fldmap.size() != numfields) { QMessageBox::warning(this, QApplication::applicationName(), tr("There is already a table of that name and an import into an existing table is only possible if the number of columns match.")); return; } else { if(QMessageBox::question(this, QApplication::applicationName(), tr("There is already a table of that name. Do you want to import the data into it?"), QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) { importToExistingTable = true; break; } else { return; } } } } // Create a savepoint, so we can rollback in case of any errors during importing // db needs to be saved or an error will occur QString restorepointName = QString("CSVIMPORT_%1").arg(QDateTime::currentMSecsSinceEpoch()); if(!pdb->setRestorePoint(restorepointName)) return rollback(this, pdb, progress, restorepointName); // Create table if(!importToExistingTable) { if(!pdb->createTable(ui->editName->text(), fieldList)) return rollback(this, pdb, progress, restorepointName); } // now lets import all data, one row at a time for(int i=0;ieditName->text()); // need to mprintf here char* formSQL = sqlite3_mprintf("%Q", (const char*)curList[i].toUtf8()); sql.append(formSQL); if(formSQL) sqlite3_free(formSQL); colNum++; if(colNum < numfields) { sql.append(","); } else { colNum = 0; sql.append(");"); if(!pdb->executeSQL(sql, false, false)) return rollback(this, pdb, progress, restorepointName); } progress.setValue(i); if(progress.wasCanceled()) return rollback(this, pdb, progress, restorepointName); } QApplication::restoreOverrideCursor(); // restore original cursor QDialog::accept(); } void ImportCsvDialog::updatePreview() { // Get preview data int numfields; int maxrecs = 20; QStringList curList = pdb->decodeCSV(csvFilename, currentSeparatorChar(), currentQuoteChar(), maxrecs, &numfields); // Reset preview widget ui->tablePreview->clear(); ui->tablePreview->setColumnCount(numfields); // Exit if there are no lines to preview at all if(numfields == 0) return; // Use first row as header if necessary if(ui->checkboxHeader->isChecked()) { ui->tablePreview->setHorizontalHeaderLabels(curList); // Remove this row to not show it in the data section for(int e=0;etablePreview->setRowCount(curList.count() / numfields); int rowNum = 0; int colNum = 0; for(QStringList::Iterator ct=curList.begin();ct!=curList.end();++ct) { if(colNum == 0) ui->tablePreview->setVerticalHeaderItem(rowNum, new QTableWidgetItem(QString::number(rowNum + 1))); ui->tablePreview->setItem(rowNum, colNum, new QTableWidgetItem(*ct)); colNum++; if(colNum == numfields) { colNum = 0; rowNum++; } } } void ImportCsvDialog::checkInput() { ui->editName->setText(ui->editName->text().trimmed()); bool valid = true; if(ui->editName->text().isEmpty() || ui->editName->text().contains(" ")) valid = false; ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(valid); } char ImportCsvDialog::currentQuoteChar() { if(ui->comboQuote->currentText().length()) return ui->comboQuote->currentText().at(0).toAscii(); else return 0; } char ImportCsvDialog::currentSeparatorChar() { return ui->comboSeparator->currentText() == tr("Tab") ? '\t' : ui->comboSeparator->currentText().at(0).toAscii(); }