mirror of
https://github.com/sqlitebrowser/sqlitebrowser.git
synced 2026-01-21 03:21:43 -06:00
Rewrite the Import CSV Dialog using Qt Creator
Rewrite the dialog to import CSV files using a Qt Creator form file. Simplify the CSV import a little bit. A bit unrelated, but needed for this anyway: Create the restorepoint right after opening a database file instead of just doing so after the first change.
This commit is contained in:
@@ -1,245 +0,0 @@
|
||||
#include "ImportCSVForm.h"
|
||||
#include <QMessageBox>
|
||||
#include <QProgressDialog>
|
||||
#include "sqlitedb.h"
|
||||
|
||||
/*
|
||||
* Constructs a importCSVForm as a child of 'parent', with the
|
||||
* name 'name' and widget flags set to 'f'.
|
||||
*
|
||||
* The dialog will by default be modeless, unless you set 'modal' to
|
||||
* true to construct a modal dialog.
|
||||
*/
|
||||
importCSVForm::importCSVForm(QWidget* parent, Qt::WindowFlags fl)
|
||||
: QDialog(parent, fl)
|
||||
{
|
||||
setupUi(this);
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroys the object and frees any allocated resources
|
||||
*/
|
||||
importCSVForm::~importCSVForm()
|
||||
{
|
||||
// no need to delete child widgets, Qt does it all for us
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the strings of the subwidgets using the current
|
||||
* language.
|
||||
*/
|
||||
void importCSVForm::languageChange()
|
||||
{
|
||||
retranslateUi(this);
|
||||
}
|
||||
|
||||
void importCSVForm::init()
|
||||
{
|
||||
pdb = 0;
|
||||
sep=',';
|
||||
quote='"';
|
||||
}
|
||||
void importCSVForm::initialize(QString & csvfile, DBBrowserDB * db)
|
||||
{
|
||||
pdb = db;
|
||||
csvfilename = csvfile;
|
||||
preview();
|
||||
}
|
||||
|
||||
void importCSVForm::createButtonPressed()
|
||||
{
|
||||
QString tabname;
|
||||
QStringList fieldList;
|
||||
QString sql;
|
||||
|
||||
//minimun validation for tabname
|
||||
tabname = tableNameEdit->text();
|
||||
if (tabname.isEmpty()) {
|
||||
QMessageBox::information( this, QApplication::applicationName(), "Please choose a name for the new table that will hold the csv data" );
|
||||
return;
|
||||
}
|
||||
tabname.replace(" ", "");
|
||||
tabname.replace('"', "");
|
||||
tabname.replace("'","");
|
||||
tabname.replace(",","");
|
||||
tabname.replace(";","");
|
||||
|
||||
if (tabname.isEmpty()) {
|
||||
tabname = "tempTable";
|
||||
}
|
||||
|
||||
//parse all csv data
|
||||
curList = pdb->decodeCSV(csvfilename, sep, quote, -1, &numfields);
|
||||
|
||||
//can not operate on an empty result
|
||||
if (numfields==0) return;
|
||||
|
||||
if (extractFieldNamesCheckbox->isChecked())
|
||||
{
|
||||
int cfieldnum = 0;
|
||||
for ( QStringList::Iterator ct = curList.begin(); ct != curList.end(); ++ct ) {
|
||||
QString thisfield = *ct;
|
||||
//basic conforming
|
||||
thisfield.replace(" ", "");
|
||||
thisfield.replace('"', "");
|
||||
thisfield.replace("'","");
|
||||
thisfield.replace(",","");
|
||||
thisfield.replace(";","");
|
||||
|
||||
if (thisfield.isEmpty()) thisfield.append("field");
|
||||
|
||||
fieldList << thisfield;
|
||||
cfieldnum++;
|
||||
if (cfieldnum==numfields) break;
|
||||
}
|
||||
//pop the fieldnames
|
||||
for (int e=0; e<numfields; e++)
|
||||
{
|
||||
curList.pop_front();
|
||||
}
|
||||
} else {
|
||||
//generate temp fieldnames
|
||||
for (int e=0; e<numfields; e++)
|
||||
{
|
||||
fieldList << QString("field").append(QString::number(e+1,10));
|
||||
}
|
||||
}
|
||||
|
||||
QProgressDialog progress("Inserting data...", "Cancel", 0, curList.size());
|
||||
progress.setWindowModality(Qt::ApplicationModal);
|
||||
|
||||
sql = QString("CREATE TABLE `%1` (").arg(tabname);
|
||||
for (int r=0; r<numfields;r++){
|
||||
sql.append(QString("`%1`").arg(fieldList[r]));
|
||||
//createStatement.append(" text");
|
||||
if (r<(numfields - 1))
|
||||
sql.append(", ");
|
||||
}
|
||||
sql.append(");");
|
||||
|
||||
//declare local variables we will need before the rollback jump
|
||||
int colNum = 0;
|
||||
|
||||
//begin a savepoint, so we can rollback in case of any errors during importing
|
||||
//db needs to be saved or an error will occur
|
||||
if (!pdb->executeSQL(QString("SAVEPOINT CSVIMPORT;"), false, false)) goto rollback;
|
||||
|
||||
//execute the create table statement
|
||||
if (!pdb->executeSQL(sql, false, false)) goto rollback;
|
||||
|
||||
{//avoid error on MSVC due to rollback label
|
||||
//now lets import all data, one row at a time
|
||||
for ( int i=0; i < curList.size(); ++i ) {
|
||||
if (colNum==0)
|
||||
sql = QString("INSERT INTO `%1` VALUES(").arg(tabname);
|
||||
|
||||
//need to mprintf here
|
||||
//sql.append(*ct);
|
||||
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)) goto rollback;
|
||||
}
|
||||
progress.setValue(i);
|
||||
if (progress.wasCanceled()) goto rollback;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//everything ok, just return
|
||||
//Do not commit, it will be done automatically on save
|
||||
if (!pdb->executeSQL(QString("RELEASE CSVIMPORT;"))) goto rollback;
|
||||
pdb->setDirtyDirect(true);
|
||||
QApplication::restoreOverrideCursor(); // restore original cursor
|
||||
accept();
|
||||
return;
|
||||
|
||||
rollback:
|
||||
progress.cancel();
|
||||
QApplication::restoreOverrideCursor(); // restore original cursor
|
||||
QString error = "Error importing data. Message from database engine: ";
|
||||
error.append(pdb->lastErrorMessage);
|
||||
QMessageBox::warning( this, QApplication::applicationName(), error );
|
||||
//we will uncomment this when SQLite support nested transactions
|
||||
pdb->executeSQL(QString("ROLLBACK TO SAVEPOINT CSVIMPORT;"), false, false);
|
||||
}
|
||||
|
||||
void importCSVForm::preview()
|
||||
{
|
||||
//get only 20 lines, for preview
|
||||
int maxrecs = 20;
|
||||
curList = pdb->decodeCSV(csvfilename, sep, quote, maxrecs, &numfields);
|
||||
|
||||
previewTable->clear();
|
||||
previewTable->setColumnCount(numfields);
|
||||
|
||||
//can not operate on an empty result
|
||||
if (numfields==0) return;
|
||||
|
||||
if (extractFieldNamesCheckbox->isChecked())
|
||||
{
|
||||
previewTable->setHorizontalHeaderLabels(curList);
|
||||
//pop the fieldnames
|
||||
for (int e=0; e<numfields; e++)
|
||||
{
|
||||
curList.pop_front();
|
||||
}
|
||||
}
|
||||
previewTable->setRowCount(curList.count()/numfields);
|
||||
int rowNum = 0;
|
||||
int colNum = 0;
|
||||
for ( QStringList::Iterator ct = curList .begin(); ct != curList .end(); ++ct ) {
|
||||
if (colNum==0) previewTable->setVerticalHeaderItem( rowNum, new QTableWidgetItem( QString::number(rowNum+1) ) );
|
||||
previewTable->setItem(rowNum, colNum, new QTableWidgetItem( *ct ) );
|
||||
colNum++;
|
||||
if (colNum==numfields)
|
||||
{
|
||||
colNum = 0;
|
||||
rowNum ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void importCSVForm::fieldSeparatorChanged()
|
||||
{
|
||||
QString curText =fieldBox->currentText();
|
||||
if (curText.compare(QString("TAB"))==0)
|
||||
{
|
||||
sep = 9;
|
||||
} else {
|
||||
QChar qsep = curText.at(0);
|
||||
sep = (char) qsep.toAscii();
|
||||
}
|
||||
preview();
|
||||
}
|
||||
|
||||
|
||||
void importCSVForm::textQuoteChanged()
|
||||
{
|
||||
QString curText = quoteBox->currentText();
|
||||
if(curText.length() > 0)
|
||||
{
|
||||
QChar qquote = curText.at(0);
|
||||
quote = (char) qquote.toAscii();
|
||||
}
|
||||
preview();
|
||||
}
|
||||
|
||||
|
||||
void importCSVForm::extractFieldNamesChanged( bool enabled )
|
||||
{
|
||||
preview();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,224 +0,0 @@
|
||||
#ifndef IMPORTCSVFORM_H
|
||||
#define IMPORTCSVFORM_H
|
||||
|
||||
#include <QTableWidget>
|
||||
#include <QtGui/QApplication>
|
||||
#include <QtGui/QCheckBox>
|
||||
#include <QtGui/QComboBox>
|
||||
#include <QtGui/QDialog>
|
||||
#include <QtGui/QGridLayout>
|
||||
#include <QtGui/QHBoxLayout>
|
||||
#include <QtGui/QLabel>
|
||||
#include <QtGui/QLineEdit>
|
||||
#include <QtGui/QPushButton>
|
||||
#include <QtGui/QSpacerItem>
|
||||
#include <QtGui/QVBoxLayout>
|
||||
#include <QtCore/QStringList>
|
||||
|
||||
class DBBrowserDB;
|
||||
|
||||
class Ui_importCSVForm
|
||||
{
|
||||
public:
|
||||
QVBoxLayout *vboxLayout;
|
||||
QGridLayout *gridLayout;
|
||||
QLabel *textLabel3;
|
||||
QLineEdit *tableNameEdit;
|
||||
QCheckBox *extractFieldNamesCheckbox;
|
||||
QHBoxLayout *hboxLayout;
|
||||
QVBoxLayout *vboxLayout1;
|
||||
QLabel *textLabel1;
|
||||
QLabel *textLabel2;
|
||||
QSpacerItem *spacer15;
|
||||
QVBoxLayout *vboxLayout2;
|
||||
QComboBox *fieldBox;
|
||||
QComboBox *quoteBox;
|
||||
QSpacerItem *spacer14;
|
||||
QTableWidget *previewTable;
|
||||
QHBoxLayout *hboxLayout1;
|
||||
QSpacerItem *spacer13;
|
||||
QPushButton *cancelButton;
|
||||
QPushButton *createButton;
|
||||
|
||||
void setupUi(QDialog *importCSVForm)
|
||||
{
|
||||
if (importCSVForm->objectName().isEmpty())
|
||||
importCSVForm->setObjectName(QString::fromUtf8("importCSVForm"));
|
||||
importCSVForm->resize(372, 382);
|
||||
importCSVForm->setModal(true);
|
||||
vboxLayout = new QVBoxLayout(importCSVForm);
|
||||
vboxLayout->setSpacing(6);
|
||||
vboxLayout->setContentsMargins(11, 11, 11, 11);
|
||||
vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
|
||||
gridLayout = new QGridLayout();
|
||||
gridLayout->setSpacing(6);
|
||||
gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
|
||||
textLabel3 = new QLabel(importCSVForm);
|
||||
textLabel3->setObjectName(QString::fromUtf8("textLabel3"));
|
||||
textLabel3->setWordWrap(false);
|
||||
|
||||
gridLayout->addWidget(textLabel3, 0, 0, 1, 1);
|
||||
|
||||
tableNameEdit = new QLineEdit(importCSVForm);
|
||||
tableNameEdit->setObjectName(QString::fromUtf8("tableNameEdit"));
|
||||
|
||||
gridLayout->addWidget(tableNameEdit, 0, 1, 1, 1);
|
||||
|
||||
extractFieldNamesCheckbox = new QCheckBox(importCSVForm);
|
||||
extractFieldNamesCheckbox->setObjectName(QString::fromUtf8("extractFieldNamesCheckbox"));
|
||||
|
||||
gridLayout->addWidget(extractFieldNamesCheckbox, 2, 0, 1, 2);
|
||||
|
||||
hboxLayout = new QHBoxLayout();
|
||||
hboxLayout->setSpacing(6);
|
||||
hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
|
||||
vboxLayout1 = new QVBoxLayout();
|
||||
vboxLayout1->setSpacing(6);
|
||||
vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1"));
|
||||
textLabel1 = new QLabel(importCSVForm);
|
||||
textLabel1->setObjectName(QString::fromUtf8("textLabel1"));
|
||||
textLabel1->setWordWrap(false);
|
||||
|
||||
vboxLayout1->addWidget(textLabel1);
|
||||
|
||||
textLabel2 = new QLabel(importCSVForm);
|
||||
textLabel2->setObjectName(QString::fromUtf8("textLabel2"));
|
||||
textLabel2->setWordWrap(false);
|
||||
|
||||
vboxLayout1->addWidget(textLabel2);
|
||||
|
||||
|
||||
hboxLayout->addLayout(vboxLayout1);
|
||||
|
||||
spacer15 = new QSpacerItem(81, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||
|
||||
hboxLayout->addItem(spacer15);
|
||||
|
||||
vboxLayout2 = new QVBoxLayout();
|
||||
vboxLayout2->setSpacing(6);
|
||||
vboxLayout2->setObjectName(QString::fromUtf8("vboxLayout2"));
|
||||
fieldBox = new QComboBox(importCSVForm);
|
||||
fieldBox->setObjectName(QString::fromUtf8("fieldBox"));
|
||||
|
||||
vboxLayout2->addWidget(fieldBox);
|
||||
|
||||
quoteBox = new QComboBox(importCSVForm);
|
||||
quoteBox->setObjectName(QString::fromUtf8("quoteBox"));
|
||||
|
||||
vboxLayout2->addWidget(quoteBox);
|
||||
|
||||
|
||||
hboxLayout->addLayout(vboxLayout2);
|
||||
|
||||
|
||||
gridLayout->addLayout(hboxLayout, 1, 0, 1, 2);
|
||||
|
||||
|
||||
vboxLayout->addLayout(gridLayout);
|
||||
|
||||
spacer14 = new QSpacerItem(138, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||
|
||||
vboxLayout->addItem(spacer14);
|
||||
|
||||
previewTable = new QTableWidget(importCSVForm);
|
||||
previewTable->setObjectName(QString::fromUtf8("previewTable"));
|
||||
previewTable->setRowCount(0);
|
||||
previewTable->setColumnCount(0);
|
||||
previewTable->setSelectionMode(QTableWidget::NoSelection);
|
||||
|
||||
vboxLayout->addWidget(previewTable);
|
||||
|
||||
hboxLayout1 = new QHBoxLayout();
|
||||
hboxLayout1->setSpacing(6);
|
||||
hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
|
||||
spacer13 = new QSpacerItem(41, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||
|
||||
hboxLayout1->addItem(spacer13);
|
||||
|
||||
cancelButton = new QPushButton(importCSVForm);
|
||||
cancelButton->setObjectName(QString::fromUtf8("cancelButton"));
|
||||
|
||||
hboxLayout1->addWidget(cancelButton);
|
||||
|
||||
createButton = new QPushButton(importCSVForm);
|
||||
createButton->setObjectName(QString::fromUtf8("createButton"));
|
||||
|
||||
hboxLayout1->addWidget(createButton);
|
||||
|
||||
|
||||
vboxLayout->addLayout(hboxLayout1);
|
||||
|
||||
|
||||
retranslateUi(importCSVForm);
|
||||
QObject::connect(cancelButton, SIGNAL(clicked()), importCSVForm, SLOT(reject()));
|
||||
QObject::connect(createButton, SIGNAL(clicked()), importCSVForm, SLOT(createButtonPressed()));
|
||||
QObject::connect(fieldBox, SIGNAL(activated(int)), importCSVForm, SLOT(fieldSeparatorChanged()));
|
||||
QObject::connect(quoteBox, SIGNAL(activated(int)), importCSVForm, SLOT(textQuoteChanged()));
|
||||
QObject::connect(extractFieldNamesCheckbox, SIGNAL(toggled(bool)), importCSVForm, SLOT(extractFieldNamesChanged(bool)));
|
||||
|
||||
QMetaObject::connectSlotsByName(importCSVForm);
|
||||
} // setupUi
|
||||
|
||||
void retranslateUi(QDialog *importCSVForm)
|
||||
{
|
||||
importCSVForm->setWindowTitle(QApplication::translate("importCSVForm", "Create table from CSV file", 0, QApplication::UnicodeUTF8));
|
||||
textLabel3->setText(QApplication::translate("importCSVForm", "New table name:", 0, QApplication::UnicodeUTF8));
|
||||
extractFieldNamesCheckbox->setText(QApplication::translate("importCSVForm", "Extract field names from first line", 0, QApplication::UnicodeUTF8));
|
||||
textLabel1->setText(QApplication::translate("importCSVForm", "Field separator:", 0, QApplication::UnicodeUTF8));
|
||||
textLabel2->setText(QApplication::translate("importCSVForm", "Text quote character:", 0, QApplication::UnicodeUTF8));
|
||||
fieldBox->clear();
|
||||
fieldBox->insertItems(0, QStringList()
|
||||
<< QApplication::translate("importCSVForm", ",", 0, QApplication::UnicodeUTF8)
|
||||
<< QApplication::translate("importCSVForm", ";", 0, QApplication::UnicodeUTF8)
|
||||
<< QApplication::translate("importCSVForm", "TAB", 0, QApplication::UnicodeUTF8)
|
||||
);
|
||||
quoteBox->clear();
|
||||
quoteBox->insertItems(0, QStringList()
|
||||
<< QApplication::translate("importCSVForm", "\"", 0, QApplication::UnicodeUTF8)
|
||||
<< QApplication::translate("importCSVForm", "'", 0, QApplication::UnicodeUTF8)
|
||||
<< QApplication::translate("importCSVForm", "\\", 0, QApplication::UnicodeUTF8)
|
||||
<< QString()
|
||||
);
|
||||
cancelButton->setText(QApplication::translate("importCSVForm", "Cancel", 0, QApplication::UnicodeUTF8));
|
||||
createButton->setText(QApplication::translate("importCSVForm", "Create", 0, QApplication::UnicodeUTF8));
|
||||
} // retranslateUi
|
||||
|
||||
};
|
||||
|
||||
namespace Ui {
|
||||
class importCSVForm: public Ui_importCSVForm {};
|
||||
} // namespace Ui
|
||||
|
||||
class importCSVForm : public QDialog, public Ui::importCSVForm
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
importCSVForm(QWidget* parent = 0, Qt::WindowFlags fl = Qt::Window);
|
||||
~importCSVForm();
|
||||
|
||||
public slots:
|
||||
virtual void initialize( QString & csvfile, DBBrowserDB * db );
|
||||
virtual void createButtonPressed();
|
||||
virtual void preview();
|
||||
virtual void fieldSeparatorChanged();
|
||||
virtual void textQuoteChanged();
|
||||
virtual void extractFieldNamesChanged( bool enabled );
|
||||
|
||||
protected:
|
||||
QStringList curList;
|
||||
char quote;
|
||||
char sep;
|
||||
int numfields;
|
||||
QString csvfilename;
|
||||
DBBrowserDB * pdb;
|
||||
|
||||
protected slots:
|
||||
virtual void languageChange();
|
||||
|
||||
private:
|
||||
void init();
|
||||
|
||||
};
|
||||
|
||||
#endif // IMPORTCSVFORM_H
|
||||
191
src/ImportCsvDialog.cpp
Normal file
191
src/ImportCsvDialog.cpp
Normal file
@@ -0,0 +1,191 @@
|
||||
#include "ImportCsvDialog.h"
|
||||
#include "ui_ImportCsvDialog.h"
|
||||
#include <QMessageBox>
|
||||
#include <QProgressDialog>
|
||||
#include <QPushButton>
|
||||
#include "sqlitedb.h"
|
||||
|
||||
ImportCsvDialog::ImportCsvDialog(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;
|
||||
}
|
||||
|
||||
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
|
||||
QList<DBBrowserField> 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(DBBrowserField(thisfield, ""));
|
||||
cfieldnum++;
|
||||
curList.pop_front();
|
||||
}
|
||||
} else {
|
||||
for(int i=0;i<numfields;i++)
|
||||
fieldList.push_back(DBBrowserField(QString("field%1").arg(i+1), ""));
|
||||
}
|
||||
|
||||
// Show progress dialog
|
||||
QProgressDialog progress("Inserting data...", "Cancel", 0, curList.size());
|
||||
progress.setWindowModality(Qt::ApplicationModal);
|
||||
|
||||
// declare local variables we will need before the rollback jump
|
||||
int colNum = 0;
|
||||
|
||||
// Create a savepoint, so we can rollback in case of any errors during importing
|
||||
// db needs to be saved or an error will occur
|
||||
if(!pdb->executeSQL("SAVEPOINT CSVIMPORT;", false))
|
||||
goto rollback;
|
||||
|
||||
// Create table
|
||||
if(!pdb->createTable(ui->editName->text(), fieldList))
|
||||
goto rollback;
|
||||
|
||||
{ // avoid error on MSVC due to rollback label
|
||||
// now lets import all data, one row at a time
|
||||
for(int i=0;i<curList.size();++i)
|
||||
{
|
||||
if(colNum == 0)
|
||||
sql = QString("INSERT INTO `%1` VALUES(").arg(ui->editName->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))
|
||||
goto rollback;
|
||||
}
|
||||
progress.setValue(i);
|
||||
if(progress.wasCanceled())
|
||||
goto rollback;
|
||||
}
|
||||
}
|
||||
|
||||
// Everything ok, release the savepoint
|
||||
if(!pdb->executeSQL("RELEASE SAVEPOINT CSVIMPORT;"))
|
||||
goto rollback;
|
||||
pdb->setDirtyDirect(true);
|
||||
QApplication::restoreOverrideCursor(); // restore original cursor
|
||||
QDialog::accept();
|
||||
return;
|
||||
|
||||
rollback:
|
||||
progress.hide();
|
||||
QApplication::restoreOverrideCursor(); // restore original cursor
|
||||
QString error = QString("Error importing data. Message from database engine: %1").arg(pdb->lastErrorMessage);
|
||||
QMessageBox::warning(this, QApplication::applicationName(), error);
|
||||
pdb->executeSQL("ROLLBACK TO SAVEPOINT CSVIMPORT;", false);
|
||||
}
|
||||
|
||||
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;e<numfields;e++)
|
||||
curList.pop_front();
|
||||
}
|
||||
|
||||
// Fill data section
|
||||
ui->tablePreview->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() == "Tab" ? '\t' : ui->comboSeparator->currentText().at(0).toAscii();
|
||||
}
|
||||
33
src/ImportCsvDialog.h
Normal file
33
src/ImportCsvDialog.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef __IMPORTCSVDIALOG_H__
|
||||
#define __IMPORTCSVDIALOG_H__
|
||||
|
||||
#include <QDialog>
|
||||
class DBBrowserDB;
|
||||
|
||||
namespace Ui {
|
||||
class ImportCsvDialog;
|
||||
}
|
||||
|
||||
class ImportCsvDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ImportCsvDialog(QString filename, DBBrowserDB* db, QWidget* parent = 0);
|
||||
~ImportCsvDialog();
|
||||
|
||||
protected slots:
|
||||
virtual void accept();
|
||||
virtual void updatePreview();
|
||||
virtual void checkInput();
|
||||
|
||||
private:
|
||||
Ui::ImportCsvDialog* ui;
|
||||
QString csvFilename;
|
||||
DBBrowserDB* pdb;
|
||||
|
||||
char currentQuoteChar();
|
||||
char currentSeparatorChar();
|
||||
};
|
||||
|
||||
#endif
|
||||
235
src/ImportCsvDialog.ui
Normal file
235
src/ImportCsvDialog.ui
Normal file
@@ -0,0 +1,235 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ImportCsvDialog</class>
|
||||
<widget class="QDialog" name="ImportCsvDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>738</width>
|
||||
<height>490</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Import CSV file</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelName">
|
||||
<property name="text">
|
||||
<string>&Table name</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>editName</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="editName"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelHeader">
|
||||
<property name="text">
|
||||
<string>&Column names in first line</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>checkboxHeader</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="checkboxHeader">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelSeparator">
|
||||
<property name="text">
|
||||
<string>Field &separator</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>comboSeparator</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="comboSeparator">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>,</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>;</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Tab</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="labelQuote">
|
||||
<property name="text">
|
||||
<string>&Quote character</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>comboQuote</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="comboQuote">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>"</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>'</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableWidget" name="tablePreview"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>editName</tabstop>
|
||||
<tabstop>checkboxHeader</tabstop>
|
||||
<tabstop>comboSeparator</tabstop>
|
||||
<tabstop>comboQuote</tabstop>
|
||||
<tabstop>tablePreview</tabstop>
|
||||
<tabstop>buttonBox</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>ImportCsvDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>252</x>
|
||||
<y>485</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>ImportCsvDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>320</x>
|
||||
<y>485</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>checkboxHeader</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>ImportCsvDialog</receiver>
|
||||
<slot>updatePreview()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>187</x>
|
||||
<y>46</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>354</x>
|
||||
<y>45</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>comboSeparator</sender>
|
||||
<signal>currentIndexChanged(int)</signal>
|
||||
<receiver>ImportCsvDialog</receiver>
|
||||
<slot>updatePreview()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>216</x>
|
||||
<y>71</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>445</x>
|
||||
<y>64</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>comboQuote</sender>
|
||||
<signal>currentIndexChanged(int)</signal>
|
||||
<receiver>ImportCsvDialog</receiver>
|
||||
<slot>updatePreview()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>224</x>
|
||||
<y>100</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>350</x>
|
||||
<y>88</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>editName</sender>
|
||||
<signal>textChanged(QString)</signal>
|
||||
<receiver>ImportCsvDialog</receiver>
|
||||
<slot>checkInput()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>609</x>
|
||||
<y>13</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>631</x>
|
||||
<y>45</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
<slots>
|
||||
<slot>updatePreview()</slot>
|
||||
<slot>checkInput()</slot>
|
||||
</slots>
|
||||
</ui>
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "AboutDialog.h"
|
||||
#include "EditTableDialog.h"
|
||||
#include "EditFieldDialog.h"
|
||||
#include "ImportCSVForm.h"
|
||||
#include "ImportCsvDialog.h"
|
||||
#include "ExportCsvDialog.h"
|
||||
#include "PreferencesDialog.h"
|
||||
#include "EditDialog.h"
|
||||
@@ -827,8 +827,7 @@ void MainWindow::importTableFromCSV()
|
||||
|
||||
if (QFile::exists(wFile) )
|
||||
{
|
||||
importCSVForm dialog(this);
|
||||
dialog.initialize(wFile, &db);
|
||||
ImportCsvDialog dialog(wFile, &db, this);
|
||||
if(dialog.exec())
|
||||
{
|
||||
populateStructure();
|
||||
|
||||
@@ -19,10 +19,6 @@ bool DBBrowserDB::isOpen ( )
|
||||
|
||||
void DBBrowserDB::setDirty(bool dirtyval)
|
||||
{
|
||||
if ((dirty==false)&&(dirtyval==true))
|
||||
{
|
||||
setRestorePoint();
|
||||
}
|
||||
dirty = dirtyval;
|
||||
if (logWin)
|
||||
{
|
||||
@@ -120,8 +116,10 @@ bool DBBrowserDB::open ( const QString & db)
|
||||
setDirty(false);
|
||||
}
|
||||
curDBFilename = db;
|
||||
setRestorePoint();
|
||||
}
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
11
src/src.pro
11
src/src.pro
@@ -14,7 +14,6 @@ HEADERS += \
|
||||
sqlitedb.h \
|
||||
sqlbrowser_util.h \
|
||||
SQLLogDock.h \
|
||||
ImportCSVForm.h \
|
||||
MainWindow.h \
|
||||
SQLiteSyntaxHighlighter.h \
|
||||
CreateIndexDialog.h \
|
||||
@@ -24,14 +23,14 @@ HEADERS += \
|
||||
PreferencesDialog.h \
|
||||
FindDialog.h \
|
||||
EditDialog.h \
|
||||
ExportCsvDialog.h
|
||||
ExportCsvDialog.h \
|
||||
ImportCsvDialog.h
|
||||
|
||||
SOURCES += \
|
||||
sqlitedb.cpp \
|
||||
sqlbrowser_util.c \
|
||||
SQLLogDock.cpp \
|
||||
main.cpp \
|
||||
ImportCSVForm.cpp \
|
||||
MainWindow.cpp \
|
||||
SQLiteSyntaxHighlighter.cpp \
|
||||
CreateIndexDialog.cpp \
|
||||
@@ -41,7 +40,8 @@ SOURCES += \
|
||||
AboutDialog.cpp \
|
||||
FindDialog.cpp \
|
||||
EditDialog.cpp \
|
||||
ExportCsvDialog.cpp
|
||||
ExportCsvDialog.cpp \
|
||||
ImportCsvDialog.cpp
|
||||
|
||||
QMAKE_CXXFLAGS += -DAPP_VERSION=\\\"`cd $$PWD;git log -n1 --format=%h_git`\\\"
|
||||
|
||||
@@ -71,4 +71,5 @@ FORMS += \
|
||||
PreferencesDialog.ui \
|
||||
FindDialog.ui \
|
||||
EditDialog.ui \
|
||||
ExportCsvDialog.ui
|
||||
ExportCsvDialog.ui \
|
||||
ImportCsvDialog.ui
|
||||
|
||||
Reference in New Issue
Block a user