Skip to content

Commit 6c8712d

Browse files
committed
Change the internal data type for cell contents to a binary type
Store the data of a DB cell in a QByteArray, i.e. a binary data type, instead of putting it in a QString, thus converting it to a UTF8 string. Rewrite the reading and writing of DB cells to correctly handle binary data containing 0x00 bytes. Change the edit dialog to actually do all the data checks etc. on a currently invisible QHexEdit widget instead of a QTextEdit. All these changes combined make it possible to actually store binary data without it being corrupted. You can for example import pictures now, export them and actually open the exported file. So this is an improvement.
1 parent 0cf9ecd commit 6c8712d

File tree

7 files changed

+102
-84
lines changed

7 files changed

+102
-84
lines changed

src/EditDialog.cpp

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,17 @@
44
#include <QMessageBox>
55
#include <QFileDialog>
66
#include "sqlitedb.h"
7+
#include <src/qhexedit.h>
78

89
EditDialog::EditDialog(QWidget* parent)
910
: QDialog(parent),
1011
ui(new Ui::EditDialog)
1112
{
1213
ui->setupUi(this);
14+
15+
hexEdit = new QHexEdit(this);
16+
hexEdit->setVisible(false);
17+
1318
reset();
1419
}
1520

@@ -24,6 +29,7 @@ void EditDialog::reset()
2429
curCol = -1;
2530
ui->editData->setPlainText("");
2631
ui->editData->setFocus();
32+
hexEdit->setData(QByteArray());
2733
setDataType(kSQLiteMediaType_Void, 0);
2834
}
2935

@@ -57,14 +63,15 @@ void EditDialog::closeEvent(QCloseEvent*)
5763
emit goingAway();
5864
}
5965

60-
void EditDialog::loadText(const QString& text, int row, int col)
66+
void EditDialog::loadText(const QByteArray& data, int row, int col)
6167
{
62-
ui->editData->setPlainText(text);
68+
ui->editData->setPlainText(data);
6369
ui->editData->setFocus();
6470
ui->editData->selectAll();
71+
hexEdit->setData(data);
6572
curRow = row;
6673
curCol = col;
67-
if(ui->editData->toPlainText().length() > 0)
74+
if(hexEdit->data().length() > 0)
6875
setDataType(kSQLiteMediaType_String, 0);
6976
else
7077
setDataType(kSQLiteMediaType_Void, 0);
@@ -84,11 +91,12 @@ void EditDialog::importData()
8491
QFile file(fileName);
8592
if(file.open(QIODevice::ReadOnly))
8693
{
87-
QTextStream stream(&file);
88-
ui->editData->setPlainText(stream.readAll());
94+
QByteArray d = file.readAll();
95+
hexEdit->setData(d);
96+
ui->editData->setPlainText(d);
8997
file.close();
9098
}
91-
setDataType(type, ui->editData->toPlainText().length());
99+
setDataType(type, hexEdit->data().length());
92100
}
93101
}
94102

@@ -119,8 +127,7 @@ void EditDialog::exportData()
119127
QFile file(fileName);
120128
if(file.open(QIODevice::WriteOnly))
121129
{
122-
QTextStream stream(&file);
123-
stream << ui->editData->toPlainText();
130+
file.write(hexEdit->data());
124131
file.close();
125132
}
126133
}
@@ -134,13 +141,14 @@ void EditDialog::exportData()
134141
void EditDialog::clearData()
135142
{
136143
ui->editData->setPlainText("");
144+
hexEdit->setData(QByteArray());
137145
setDataType(kSQLiteMediaType_Void, 0);
138146
}
139147

140148
void EditDialog::accept()
141149
{
142150
if(dataType == kSQLiteMediaType_String)
143-
emit updateRecordText(curRow, curCol, ui->editData->toPlainText());
151+
emit updateRecordText(curRow, curCol, hexEdit->data());
144152

145153
if (dataType == kSQLiteMediaType_Void)
146154
emit updateRecordText(curRow, curCol, "");
@@ -150,8 +158,11 @@ void EditDialog::accept()
150158

151159
void EditDialog::editTextChanged()
152160
{
161+
if(ui->editData->hasFocus())
162+
hexEdit->setData(ui->editData->toPlainText().toUtf8());
163+
153164
int newtype = kSQLiteMediaType_String;
154-
if(ui->editData->toPlainText().length() == 0)
165+
if(hexEdit->data().length() == 0)
155166
newtype = kSQLiteMediaType_Void;
156-
setDataType(newtype, ui->editData->toPlainText().length());
167+
setDataType(newtype, hexEdit->data().length());
157168
}

src/EditDialog.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define __EDITDIALOG_H__
33

44
#include <QDialog>
5+
class QHexEdit;
56

67
namespace Ui {
78
class EditDialog;
@@ -23,7 +24,7 @@ class EditDialog : public QDialog
2324

2425
public slots:
2526
virtual void reset();
26-
virtual void loadText(const QString& text, int row, int col);
27+
virtual void loadText(const QByteArray& data, int row, int col);
2728

2829
private slots:
2930
virtual void enableExport(bool enabled);
@@ -37,10 +38,11 @@ private slots:
3738

3839
signals:
3940
void goingAway();
40-
void updateRecordText(int, int, const QString&);
41+
void updateRecordText(int, int, const QByteArray&);
4142

4243
private:
4344
Ui::EditDialog* ui;
45+
QHexEdit* hexEdit;
4446
int dataType;
4547
int dataSize;
4648
int curCol;

src/ExportCsvDialog.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ void ExportCsvDialog::accept()
7373
rowList data = pdb->browseRecs;
7474
for(int i=0;i<data.size();i++)
7575
{
76-
QStringList& row = data[i];
76+
QList<QByteArray> row = data[i];
7777
for(int j=1;j<row.size();j++)
7878
{
7979
QString content = row[j];

src/MainWindow.cpp

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ void MainWindow::init()
105105
connect(ui->dataTable->horizontalHeader(), SIGNAL(sectionClicked(int)), this, SLOT(browseTableHeaderClicked(int)));
106106
connect(ui->dataTable->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(setRecordsetLabel()));
107107
connect(editWin, SIGNAL(goingAway()), this, SLOT(editWinAway()));
108-
connect(editWin, SIGNAL(updateRecordText(int, int , QString)), this, SLOT(updateRecordText(int, int , QString)));
108+
connect(editWin, SIGNAL(updateRecordText(int, int, QByteArray)), this, SLOT(updateRecordText(int, int , QByteArray)));
109109

110110
// Load window settings
111111
QSettings settings(QApplication::organizationName(), QApplication::organizationName());
@@ -449,10 +449,10 @@ void MainWindow::updateTableView(int lineToSelect, bool keepColumnWidths)
449449
rowLabel.setNum(rowNum+1);
450450
browseTableModel->setVerticalHeaderItem(rowNum, new QStandardItem(rowLabel));
451451
colNum = 0;
452-
QStringList& rt = tab[i];
452+
QList<QByteArray> rt = tab[i];
453453
for (int e = 1; e < rt.size(); ++e)
454454
{
455-
QString& content = rt[e];
455+
QString content = rt[e];
456456

457457
QStandardItem* item = new QStandardItem(content);
458458
item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
@@ -704,20 +704,19 @@ void MainWindow::helpAbout()
704704
dialog.exec();
705705
}
706706

707-
void MainWindow::updateRecordText(int row, int col, const QString& newtext)
707+
void MainWindow::updateRecordText(int row, int col, const QByteArray& newtext)
708708
{
709709
if (!db.updateRecord(row, col, newtext)){
710710
QMessageBox::information( this, QApplication::applicationName(), tr("Data could not be updated"));
711711
}
712712

713713
rowList tab = db.browseRecs;
714-
QStringList& rt = tab[row];
715-
QString& cv = rt[col+1];//must account for rowid
714+
QList<QByteArray>& rt = tab[row];
715+
QByteArray& cv = rt[col+1];//must account for rowid
716716

717-
QStandardItem* item = new QStandardItem(cv);
717+
QStandardItem* item = new QStandardItem(QString(cv));
718718
item->setToolTip( wrapText(cv) );
719719
browseTableModel->setItem(row, col, item);
720-
721720
}
722721

723722
void MainWindow::editWinAway()
@@ -730,8 +729,8 @@ void MainWindow::editWinAway()
730729
void MainWindow::editText(int row, int col)
731730
{
732731
rowList tab = db.browseRecs;
733-
QStringList& rt = tab[row];
734-
QString cv = rt[col+1];//must account for rowid
732+
QList<QByteArray> rt = tab[row];
733+
QByteArray cv = rt[col+1];//must account for rowid
735734

736735
editWin->loadText(cv , row, col);
737736
editWin->show();

src/MainWindow.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ private slots:
127127
virtual void editTable();
128128
virtual void helpWhatsThis();
129129
virtual void helpAbout();
130-
virtual void updateRecordText( int row, int col, const QString& newtext );
130+
virtual void updateRecordText(int row, int col, const QByteArray& newtext);
131131
virtual void editWinAway();
132132
virtual void editText( int row, int col );
133133
virtual void doubleClickTable(const QModelIndex& index);

src/sqlitedb.cpp

Lines changed: 63 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -386,8 +386,8 @@ bool DBBrowserDB::deleteRecord( int wrow)
386386
if (!isOpen()) return false;
387387
bool ok = false;
388388
rowList tab = browseRecs;
389-
QStringList& rt = tab[wrow];
390-
QString& rowid = rt[0];
389+
QList<QByteArray> rt = tab[wrow];
390+
QString rowid = rt[0];
391391
lastErrorMessage = QString("no error");
392392

393393
QString statement = QString("DELETE FROM `%1` WHERE rowid=%2;").arg(curBrowseTableName).arg(rowid);
@@ -406,45 +406,52 @@ bool DBBrowserDB::deleteRecord( int wrow)
406406
return ok;
407407
}
408408

409-
bool DBBrowserDB::updateRecord(int wrow, int wcol, const QString & wtext)
409+
bool DBBrowserDB::updateRecord(int wrow, int wcol, const QByteArray& wtext)
410410
{
411-
char * errmsg;
412411
if (!hasValidBrowseSet) return false;
413412
if (!isOpen()) return false;
414-
bool ok = false;
415413

416414
lastErrorMessage = QString("no error");
417415

418-
QStringList& rt = browseRecs[wrow];
419-
QString& rowid = rt[0];
420-
QString& cv = rt[wcol+1];//must account for rowid
416+
QList<QByteArray>& rt = browseRecs[wrow];
417+
QString rowid = rt[0];
418+
QByteArray& cv = rt[wcol+1];//must account for rowid
421419
QString ct = browseFields.at(wcol);
422420

423-
QString statement = QString("UPDATE `%1` SET `%2`=").arg(curBrowseTableName).arg(ct);
421+
QString sql = QString("UPDATE `%1` SET `%2`=? WHERE rowid=%4;").arg(curBrowseTableName).arg(ct).arg(rowid);
424422

425-
char * formSQL = sqlite3_mprintf("%Q", wtext.toUtf8().constData());
426-
statement.append(formSQL);
427-
if (formSQL) sqlite3_free(formSQL);
428-
429-
statement.append(" WHERE rowid=");
430-
statement.append(rowid);
431-
statement.append(";");
423+
logSQL(sql, kLogMsg_App);
424+
setRestorePoint();
432425

433-
if (_db){
434-
logSQL(statement, kLogMsg_App);
435-
setRestorePoint();
436-
if (SQLITE_OK==sqlite3_exec(_db,statement.toUtf8(),
437-
NULL,NULL,&errmsg)){
438-
ok=true;
439-
/*update local copy*/
440-
cv = wtext;
441-
} else {
442-
lastErrorMessage = QString::fromUtf8(errmsg);
443-
qCritical() << "update Record: " << lastErrorMessage;
444-
}
426+
sqlite3_stmt* stmt;
427+
if(sqlite3_prepare(_db, sql.toUtf8(), -1, &stmt, 0) != SQLITE_OK)
428+
{
429+
lastErrorMessage = sqlite3_errmsg(_db);
430+
qCritical() << "updateRecord: " << lastErrorMessage;
431+
return false;
432+
}
433+
if(sqlite3_bind_blob(stmt, 1, wtext.constData(), wtext.length(), SQLITE_STATIC) != SQLITE_OK)
434+
{
435+
lastErrorMessage = sqlite3_errmsg(_db);
436+
qCritical() << "updateRecord: " << lastErrorMessage;
437+
return false;
438+
}
439+
if(sqlite3_step(stmt) != SQLITE_DONE)
440+
{
441+
lastErrorMessage = sqlite3_errmsg(_db);
442+
qCritical() << "updateRecord: " << lastErrorMessage;
443+
return false;
444+
}
445+
if(sqlite3_finalize(stmt) != SQLITE_OK)
446+
{
447+
lastErrorMessage = sqlite3_errmsg(_db);
448+
qCritical() << "updateRecord: " << lastErrorMessage;
449+
return false;
445450
}
446451

447-
return ok;
452+
cv = wtext;
453+
454+
return true;
448455
}
449456

450457
bool DBBrowserDB::browseTable( const QString & tablename, const QString& orderby )
@@ -664,44 +671,43 @@ bool DBBrowserDB::renameTable(const QString& from_table, const QString& to_table
664671

665672
void DBBrowserDB::getTableRecords( const QString & tablename, const QString& orderby )
666673
{
667-
sqlite3_stmt *vm;
668-
const char *tail;
674+
sqlite3_stmt* stmt;
669675

670676
int ncol;
671-
QStringList r;
672-
// char *errmsg;
673-
int err=0;
674-
// int tabnum = 0;
677+
QList<QByteArray> r;
675678
browseRecs.clear();
676679
idmap.clear();
677680
lastErrorMessage = QObject::tr("no error");
678681

679-
QString statement = QString("SELECT rowid, * FROM `%1` ORDER BY %2;").arg(tablename).arg(orderby);
680-
logSQL(statement, kLogMsg_App);
681-
QByteArray utf8Statement = statement.toUtf8();
682-
err=sqlite3_prepare(_db,utf8Statement,utf8Statement.length(),
683-
&vm, &tail);
684-
if (err == SQLITE_OK){
685-
int rownum = 0;
682+
QString sql = QString("SELECT rowid, * FROM `%1` ORDER BY %2;").arg(tablename).arg(orderby);
683+
logSQL(sql, kLogMsg_App);
684+
if(sqlite3_prepare(_db, sql.toUtf8(), -1, &stmt, 0) != SQLITE_OK)
685+
{
686+
lastErrorMessage = QObject::tr("could not get fields");
687+
return;
688+
}
686689

687-
while ( sqlite3_step(vm) == SQLITE_ROW ){
688-
r.clear();
689-
ncol = sqlite3_data_count(vm);
690-
for (int e=0; e<ncol; ++e){
691-
QString rv = QString::fromUtf8((const char*)sqlite3_column_text(vm,e));
692-
r << rv;
693-
if (e==0){
694-
idmap.insert(rv.toInt(),rownum);
695-
rownum++;
696-
}
690+
int rownum = 0;
691+
692+
while(sqlite3_step(stmt) == SQLITE_ROW)
693+
{
694+
r.clear();
695+
ncol = sqlite3_data_count(stmt);
696+
for(int e=0;e<ncol;++e)
697+
{
698+
QByteArray rv = QByteArray(static_cast<const char*>(sqlite3_column_blob(stmt, e)), sqlite3_column_bytes(stmt, e));
699+
r.append(rv);
700+
701+
if(e == 0)
702+
{
703+
idmap.insert(rv.toInt(), rownum);
704+
rownum++;
697705
}
698-
browseRecs.append(r);
699706
}
700-
701-
sqlite3_finalize(vm);
702-
}else{
703-
lastErrorMessage = QObject::tr("could not get fields");
707+
browseRecs.append(r);
704708
}
709+
710+
sqlite3_finalize(stmt);
705711
}
706712

707713
resultMap DBBrowserDB::getFindResults( const QString & wstatement)

src/sqlitedb.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ typedef QMap<int, class DBBrowserField> fieldMap;
2626
typedef QMultiMap<QString, class DBBrowserObject> objectMap;
2727
typedef QMap<int, int> rowIdMap;
2828

29-
typedef QList<QStringList> rowList;
29+
typedef QList<QList<QByteArray> > rowList;
3030
typedef QMap<int, QString> resultMap;
3131

3232
class DBBrowserField
@@ -97,7 +97,7 @@ class DBBrowserDB
9797
void updateSchema() ;
9898
bool addRecord();
9999
bool deleteRecord(int wrow);
100-
bool updateRecord(int wrow, int wcol, const QString & wtext);
100+
bool updateRecord(int wrow, int wcol, const QByteArray& wtext);
101101
bool browseTable( const QString & tablename, const QString& orderby = "rowid" );
102102

103103
bool createTable(const QString& name, const QList<DBBrowserField>& structure);

0 commit comments

Comments
 (0)