Skip to content

Commit 2280cca

Browse files
author
jmbowman
committed
CSV import enhancements, 1.6 release, etc.
1 parent baef52b commit 2280cca

20 files changed

+530
-112
lines changed

CHANGES

+18
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
2003-03-30 #################### PortaBase 1.6 ####################
2+
3+
2003-03-30 JMB CSV import enhancements, menu update bugfix
4+
5+
If an imported row doesn't have enough columns and the last few
6+
columns are strings or notes, PortaBase now treats those fields as
7+
empty strings. (There often aren't enough delimiters at the end of
8+
lines ending with blank fields when exporting from programs like Excel,
9+
this just corrects for that.)
10+
11+
CSV files can now be imported as either UTF-8 or Latin-1; this avoids
12+
the need for users importing files exported from other programs in
13+
Latin-1 to use another program to perform an encoding conversion.
14+
15+
In version 1.5, making changes in the format editor would clear the
16+
view, sorting, and filter lists from the menus without restoring them;
17+
they are now populated correctly again.
18+
119
2003-03-27 JMB Japanese UI translation, better CSV import error messages
220

321
The entire PortaBase interface has now been translated into Japanese.

README.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ The main features PortaBase currently has are:
2020
- View summary statistics for columns (total, average, min, max, etc.)
2121
- Import data from CSV, XML, and MobileDB files
2222
- Export data to CSV and XML files
23-
- Command-line format conversions (to and from XML, from MobileDB)
23+
- Command-line format conversions (to and from XML, to and from CSV,
24+
from MobileDB)
2425
- Data file encryption
2526
- Unicode support
2627
- Pick any available font to use throughout the application

commandline.cpp

+15-1
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,14 @@ int CommandLine::fromOtherFormat(int argc, char **argv)
6969
}
7070
numArgs += 2;
7171
}
72+
int encIndex = args.findIndex("-e");
73+
if (encIndex != -1) {
74+
if (argc < encIndex + 4) {
75+
printUsage();
76+
return 1;
77+
}
78+
numArgs += 2;
79+
}
7280
if (argc != numArgs) {
7381
printUsage();
7482
return 1;
@@ -116,7 +124,11 @@ int CommandLine::fromOtherFormat(int argc, char **argv)
116124
error = utils.importXML(sourceFile, db);
117125
}
118126
else if (fromcsv) {
119-
QStringList result = db->importFromCSV(sourceFile);
127+
QString encoding = "UTF-8";
128+
if (encIndex != -1) {
129+
encoding = args[encIndex + 1];
130+
}
131+
QStringList result = db->importFromCSV(sourceFile, encoding);
120132
int count = result.count();
121133
if (count > 0) {
122134
error = result[0];
@@ -266,6 +278,8 @@ void CommandLine::printUsage()
266278
printf(" -v viewname (apply this view before exporting)\n");
267279
printf(" -s sortname (apply this sorting before exporting)\n");
268280
printf(" -f filtername (apply this filter before exporting)\n");
281+
printf(" There is one option for fromcsv:\n");
282+
printf(" -e encoding (UTF-8 or Latin-1; default is UTF-8)\n");
269283
printf(" When using fromcsv, \"tofile\" must be an existing PortaBase file.\n");
270284
printf(" Specify -h or --help to receive this message\n");
271285
}

csvutils.cpp

+57-51
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,9 @@
1212
#include <qfile.h>
1313
#include <qobject.h>
1414
#include <qregexp.h>
15-
#include <qstringlist.h>
1615
#include <qtextstream.h>
1716
#include "csvutils.h"
1817
#include "database.h"
19-
#include "datatypes.h"
2018

2119
CSVUtils::CSVUtils() : m_textquote('"'), m_delimiter(',')
2220
{
@@ -28,27 +26,34 @@ CSVUtils::~CSVUtils()
2826

2927
}
3028

31-
QStringList CSVUtils::parseFile(QString filename, Database *db)
29+
QStringList CSVUtils::parseFile(const QString &filename,
30+
const QString &encoding, Database *db)
3231
{
32+
initializeCounts(db);
3333
QFile f(filename);
3434
QStringList returnVal;
3535
if (!f.open(IO_ReadOnly)) {
3636
returnVal.append(QObject::tr("Unable to open file"));
3737
return returnVal;
3838
}
3939
QTextStream input(&f);
40-
input.setEncoding(QTextStream::UnicodeUTF8);
41-
int rowNum = 1;
42-
QString message = "";
40+
if (encoding == "Latin-1") {
41+
input.setEncoding(QTextStream::Latin1);
42+
}
43+
else {
44+
input.setEncoding(QTextStream::UnicodeUTF8);
45+
}
46+
rowNum = 1;
47+
message = "";
4348
enum { S_START, S_QUOTED_FIELD, S_MAYBE_END_OF_QUOTED_FIELD,
4449
S_END_OF_QUOTED_FIELD, S_MAYBE_NORMAL_FIELD,
4550
S_NORMAL_FIELD } state = S_START;
4651
QChar x;
47-
QString rowString = "";
48-
QStringList row;
52+
rowString = "";
53+
row.clear();
4954
QString field = "";
5055
// store IDs of added rows; if there's an error, delete them
51-
IntList addedIds;
56+
addedIds.clear();
5257
while (!input.atEnd()) {
5358
input >> x; // read one char
5459

@@ -75,17 +80,9 @@ QStringList CSVUtils::parseFile(QString filename, Database *db)
7580
// row ended on a delimiter (empty cell)
7681
row.append("");
7782
field = "";
78-
int rowId = 0;
79-
message = db->addRow(row, &rowId);
80-
if (message != "") {
81-
message = QObject::tr("Error in row %1").arg(rowNum)
82-
+ "\n" + message;
83+
if (!addRow(db)) {
8384
break;
8485
}
85-
addedIds.append(rowId);
86-
row.clear();
87-
rowString = "";
88-
rowNum++;
8986
}
9087
}
9188
else {
@@ -110,17 +107,9 @@ QStringList CSVUtils::parseFile(QString filename, Database *db)
110107
row.append(field);
111108
field = "";
112109
if (x == '\n') {
113-
int rowId = 0;
114-
message = db->addRow(row, &rowId);
115-
if (message != "") {
116-
message = QObject::tr("Error in row %1").arg(rowNum)
117-
+ "\n" + message;
110+
if (!addRow(db)) {
118111
break;
119112
}
120-
addedIds.append(rowId);
121-
row.clear();
122-
rowString = "";
123-
rowNum++;
124113
}
125114
state = S_START;
126115
}
@@ -133,17 +122,9 @@ QStringList CSVUtils::parseFile(QString filename, Database *db)
133122
row.append(field);
134123
field = "";
135124
if (x == '\n') {
136-
int rowId = 0;
137-
message = db->addRow(row, &rowId);
138-
if (message != "") {
139-
message = QObject::tr("Error in row %1").arg(rowNum)
140-
+ "\n" + message;
125+
if (!addRow(db)) {
141126
break;
142127
}
143-
addedIds.append(rowId);
144-
row.clear();
145-
rowString = "";
146-
rowNum++;
147128
}
148129
state = S_START;
149130
}
@@ -166,17 +147,9 @@ QStringList CSVUtils::parseFile(QString filename, Database *db)
166147
else if (x == '\n') {
167148
row.append(field);
168149
field = "";
169-
int rowId = 0;
170-
message = db->addRow(row, &rowId);
171-
if (message != "") {
172-
message = QObject::tr("Error in row %1").arg(rowNum)
173-
+ "\n" + message;
150+
if (!addRow(db)) {
174151
break;
175152
}
176-
addedIds.append(rowId);
177-
row.clear();
178-
rowString = "";
179-
rowNum++;
180153
}
181154
else {
182155
field += x;
@@ -189,12 +162,7 @@ QStringList CSVUtils::parseFile(QString filename, Database *db)
189162
if (message == "" && row.count() > 0) {
190163
// last line doesn't end with '\n'
191164
row.append(field);
192-
int rowId = 0;
193-
message = db->addRow(row, &rowId);
194-
if (message != "") {
195-
message = QObject::tr("Error in row %1").arg(rowNum)
196-
+ "\n" + message;
197-
}
165+
addRow(db);
198166
}
199167
if (message != "") {
200168
// an error was encountered; delete any rows that were added
@@ -232,3 +200,41 @@ QString CSVUtils::encodeCell(QString content)
232200
result += content.replace(QRegExp("\""), "\"\"");
233201
return result + "\"";
234202
}
203+
204+
void CSVUtils::initializeCounts(Database *db)
205+
{
206+
QStringList colNames = db->listColumns();
207+
colCount = colNames.count();
208+
endStringCount = 0;
209+
int i;
210+
for (i = colCount - 1; i > -1; i--) {
211+
int type = db->getType(colNames[i]);
212+
if (type != STRING && type != NOTE) {
213+
break;
214+
}
215+
endStringCount++;
216+
}
217+
}
218+
219+
bool CSVUtils::addRow(Database *db)
220+
{
221+
int countDiff = colCount - row.count();
222+
if (countDiff > 0 && countDiff <= endStringCount) {
223+
// last columns may have been blank in Excel or whatever...
224+
int i;
225+
for (i = 0; i < countDiff; i++) {
226+
row.append("");
227+
}
228+
}
229+
int rowId = 0;
230+
message = db->addRow(row, &rowId);
231+
if (message != "") {
232+
message = QObject::tr("Error in row %1").arg(rowNum) + "\n" + message;
233+
return FALSE;
234+
}
235+
addedIds.append(rowId);
236+
row.clear();
237+
rowString = "";
238+
rowNum++;
239+
return TRUE;
240+
}

csvutils.h

+16-2
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,37 @@
1212
#ifndef CSVUTILS_H
1313
#define CSVUTILS_H
1414

15+
#include <qstringlist.h>
16+
#include "datatypes.h"
17+
1518
class Database;
1619
class QString;
17-
class QStringList;
1820

1921
class CSVUtils
2022
{
2123
public:
2224
CSVUtils();
2325
~CSVUtils();
2426

25-
QStringList parseFile(QString filename, Database *db);
27+
QStringList parseFile(const QString &filename, const QString &encoding,
28+
Database *db);
2629
QString encodeRow(QStringList row);
2730
QString encodeCell(QString content);
2831

32+
private:
33+
void initializeCounts(Database *db);
34+
bool addRow(Database *db);
35+
2936
private:
3037
QChar m_textquote;
3138
QChar m_delimiter;
39+
int colCount;
40+
int endStringCount;
41+
int rowNum;
42+
QString message;
43+
QString rowString;
44+
QStringList row;
45+
IntList addedIds;
3246
};
3347

3448
#endif

database.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -1423,10 +1423,11 @@ QPixmap Database::getCheckBoxPixmap(int checked)
14231423
}
14241424
}
14251425

1426-
QStringList Database::importFromCSV(QString filename)
1426+
QStringList Database::importFromCSV(const QString &filename,
1427+
const QString &encoding)
14271428
{
14281429
CSVUtils csv;
1429-
return csv.parseFile(filename, this);
1430+
return csv.parseFile(filename, encoding, this);
14301431
}
14311432

14321433
void Database::exportToXML(QString filename, c4_View &fullView,

database.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,8 @@ class Database
128128
QString timeToString(int time);
129129
QString parseTimeString(QString value, bool *ok);
130130
void setShowSeconds(bool show);
131-
QStringList importFromCSV(QString filename);
131+
QStringList importFromCSV(const QString &filename,
132+
const QString &encoding);
132133
void exportToXML(QString filename, c4_View &fullView,
133134
c4_View &filteredView, QStringList cols);
134135
void setGlobalInfo(const QString &view, const QString &sorting,

dbeditor.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <qlistview.h>
1818
#include <qmessagebox.h>
1919
#include <qpushbutton.h>
20+
#include <qregexp.h>
2021
#include <qvbox.h>
2122
#include "columneditor.h"
2223
#include "database.h"
@@ -311,6 +312,9 @@ void DBEditor::updateTable()
311312
int type = ceType (temp[i]);
312313
QString typeString = getTypeString(type);
313314
QString defaultVal = QString::fromUtf8(ceDefault (temp[i]));
315+
if (type == NOTE) {
316+
defaultVal = defaultVal.replace(QRegExp("\n"), " ");
317+
}
314318
if (i == 0) {
315319
last = new QListViewItem(table, name, typeString, defaultVal);
316320
}

debian/changelog

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
portabase (1.6-1) unstable; urgency=low
2+
3+
* New upstream version
4+
5+
-- Jeremy Bowman <[email protected]> Sun, 30 Mar 2003 15:56:53 -0500
6+
17
portabase (1.5-1) unstable; urgency=low
28

39
* Initial Release.

debian/portabase.1

+6
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ Apply the named sorting before exporting.
9999
.TP
100100
\fB\-f\fP \fI<filter>\fP
101101
Apply the named filter before exporting.
102+
.PP
103+
The fromcsv command supports one option:
104+
.TP
105+
\fB\-e\fP \fI<encoding>\fP
106+
Specifies the text encoding of the imported CSV file; options are UTF-8
107+
(the default) and Latin-1.
102108
.SH OPTIONS
103109
\fIPortaBase\fP accepts the following options:
104110
.TP

desktop/importdialog.cpp

+15-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include <qfiledialog.h>
1313
#include <qfileinfo.h>
14+
#include <qinputdialog.h>
1415
#include <qmessagebox.h>
1516
#include <qobject.h>
1617
#include <qstringlist.h>
@@ -54,10 +55,23 @@ bool ImportDialog::exec()
5455
QFileInfo info(file);
5556
QPEApplication::setDocumentDir(info.dirPath(TRUE));
5657
}
58+
59+
QStringList encodings;
60+
encodings.append("UTF-8");
61+
encodings.append("Latin-1");
62+
bool ok;
63+
QString encoding = QInputDialog::getItem(QObject::tr("Import"),
64+
QObject::tr("Text encoding") + ":",
65+
encodings, 0, FALSE, &ok,
66+
parentWidget);
67+
if (!ok) {
68+
return FALSE;
69+
}
70+
5771
QString error;
5872
QString data = "";
5973
if (source == CSV_FILE) {
60-
QStringList result = db->importFromCSV(file);
74+
QStringList result = db->importFromCSV(file, encoding);
6175
int count = result.count();
6276
if (count > 0) {
6377
error = result[0];

0 commit comments

Comments
 (0)