diff --git a/src/ImportCSVForm.cpp b/src/ImportCSVForm.cpp deleted file mode 100644 index e9adb585..00000000 --- a/src/ImportCSVForm.cpp +++ /dev/null @@ -1,245 +0,0 @@ -#include "ImportCSVForm.h" -#include -#include -#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; eexecuteSQL(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 (colNumexecuteSQL(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; esetRowCount(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(); -} - - diff --git a/src/ImportCSVForm.h b/src/ImportCSVForm.h deleted file mode 100644 index a2eaccc3..00000000 --- a/src/ImportCSVForm.h +++ /dev/null @@ -1,224 +0,0 @@ -#ifndef IMPORTCSVFORM_H -#define IMPORTCSVFORM_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -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 diff --git a/src/ImportCsvDialog.cpp b/src/ImportCsvDialog.cpp new file mode 100644 index 00000000..6df5f633 --- /dev/null +++ b/src/ImportCsvDialog.cpp @@ -0,0 +1,191 @@ +#include "ImportCsvDialog.h" +#include "ui_ImportCsvDialog.h" +#include +#include +#include +#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 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;iexecuteSQL("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;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)) + 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;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() == "Tab" ? '\t' : ui->comboSeparator->currentText().at(0).toAscii(); +} diff --git a/src/ImportCsvDialog.h b/src/ImportCsvDialog.h new file mode 100644 index 00000000..331f51ce --- /dev/null +++ b/src/ImportCsvDialog.h @@ -0,0 +1,33 @@ +#ifndef __IMPORTCSVDIALOG_H__ +#define __IMPORTCSVDIALOG_H__ + +#include +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 diff --git a/src/ImportCsvDialog.ui b/src/ImportCsvDialog.ui new file mode 100644 index 00000000..80994f49 --- /dev/null +++ b/src/ImportCsvDialog.ui @@ -0,0 +1,235 @@ + + + ImportCsvDialog + + + + 0 + 0 + 738 + 490 + + + + Import CSV file + + + + + + + + &Table name + + + editName + + + + + + + + + + &Column names in first line + + + checkboxHeader + + + + + + + + + + + + + + Field &separator + + + comboSeparator + + + + + + + + , + + + + + ; + + + + + Tab + + + + + + + + &Quote character + + + comboQuote + + + + + + + + " + + + + + ' + + + + + + + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + editName + checkboxHeader + comboSeparator + comboQuote + tablePreview + buttonBox + + + + + buttonBox + accepted() + ImportCsvDialog + accept() + + + 252 + 485 + + + 157 + 274 + + + + + buttonBox + rejected() + ImportCsvDialog + reject() + + + 320 + 485 + + + 286 + 274 + + + + + checkboxHeader + toggled(bool) + ImportCsvDialog + updatePreview() + + + 187 + 46 + + + 354 + 45 + + + + + comboSeparator + currentIndexChanged(int) + ImportCsvDialog + updatePreview() + + + 216 + 71 + + + 445 + 64 + + + + + comboQuote + currentIndexChanged(int) + ImportCsvDialog + updatePreview() + + + 224 + 100 + + + 350 + 88 + + + + + editName + textChanged(QString) + ImportCsvDialog + checkInput() + + + 609 + 13 + + + 631 + 45 + + + + + + updatePreview() + checkInput() + + diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 971aed12..78d54fc2 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -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(); diff --git a/src/sqlitedb.cpp b/src/sqlitedb.cpp index c5cd8231..38f17153 100644 --- a/src/sqlitedb.cpp +++ b/src/sqlitedb.cpp @@ -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; } diff --git a/src/src.pro b/src/src.pro index 0f920a78..6f1efdfe 100644 --- a/src/src.pro +++ b/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