Skip to content

Commit

Permalink
Support text in different encoding in Browse Data tab
Browse files Browse the repository at this point in the history
When browsing and editing a table in the Browse Data tab allow the user
to change the assumed encoding of the text in the table. We'll then try
to convert from this encoding to Unicode for display purposes and to
convert from Unicode to this encoding for editing purposes. This way the
UI and all tools will keep using Unicode while the database format is
still respected. I hope the amount conversions generated this way won't
affect the performance too much.

See issue #414.
  • Loading branch information
MKleusberg committed Sep 14, 2015
1 parent 1ebecbb commit eaf6ff1
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 9 deletions.
32 changes: 32 additions & 0 deletions src/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ void MainWindow::init()
popupBrowseDataHeaderMenu = new QMenu(this);
popupBrowseDataHeaderMenu->addAction(ui->actionShowRowidColumn);
popupBrowseDataHeaderMenu->addAction(ui->actionBrowseTableEditDisplayFormat);
popupBrowseDataHeaderMenu->addAction(ui->actionSetTableEncoding);

// Add menu item for log dock
ui->viewMenu->insertAction(ui->viewDBToolbarAction, ui->dockLog->toggleViewAction());
Expand Down Expand Up @@ -389,6 +390,9 @@ void MainWindow::populateTable(const QString& tablename)
FilterTableHeader* filterHeader = qobject_cast<FilterTableHeader*>(ui->dataTable->horizontalHeader());
for(QMap<int, QString>::ConstIterator filterIt=tableIt.value().filterValues.constBegin();filterIt!=tableIt.value().filterValues.constEnd();++filterIt)
filterHeader->setFilter(filterIt.key(), filterIt.value());

// Encoding
m_browseTableModel->setEncoding(tableIt.value().encoding);
} else {
// There aren't any information stored for this table yet, so use some default values

Expand All @@ -403,6 +407,9 @@ void MainWindow::populateTable(const QString& tablename)
m_browseTableModel->sort(0, Qt::AscendingOrder);
ui->dataTable->filterHeader()->setSortIndicator(0, Qt::AscendingOrder);

// Encoding
m_browseTableModel->setEncoding(QString());

// The filters can be left empty as they are
}

Expand Down Expand Up @@ -2312,3 +2319,28 @@ void MainWindow::showRowidColumn(bool show)
// Update the filter row
qobject_cast<FilterTableHeader*>(ui->dataTable->horizontalHeader())->generateFilters(m_browseTableModel->columnCount(), show);
}

void MainWindow::browseDataSetTableEncoding()
{
// Get the old encoding
QString encoding = m_browseTableModel->encoding();

// Ask the user for a new encoding
bool ok;
encoding = QInputDialog::getText(this,
tr("Set encoding"),
tr("Please choose a new encoding for this table. Leave the field empty for using the database encoding."),
QLineEdit::Normal,
encoding,
&ok);

// Only set the new encoding if the user clicked the OK button
if(ok)
{
// Set encoding
m_browseTableModel->setEncoding(encoding);

// Save encoding for this table
browseTableSettings[ui->comboBrowseTable->currentText()].encoding = encoding;
}
}
4 changes: 4 additions & 0 deletions src/MainWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class MainWindow : public QMainWindow
QMap<int, QString> filterValues;
QMap<int, QString> displayFormats;
bool showRowid;
QString encoding;

friend QDataStream& operator<<(QDataStream& stream, const MainWindow::BrowseDataTableSettings& object)
{
Expand All @@ -49,6 +50,7 @@ class MainWindow : public QMainWindow
stream << object.filterValues;
stream << object.displayFormats;
stream << object.showRowid;
stream << object.encoding;

return stream;
}
Expand All @@ -62,6 +64,7 @@ class MainWindow : public QMainWindow
stream >> object.filterValues;
stream >> object.displayFormats;
stream >> object.showRowid;
stream >> object.encoding;

return stream;
}
Expand Down Expand Up @@ -218,6 +221,7 @@ private slots:
void showDataColumnPopupMenu(const QPoint& pos);
void editDataColumnDisplayFormat();
void showRowidColumn(bool show);
void browseDataSetTableEncoding();
};

#endif
29 changes: 27 additions & 2 deletions src/MainWindow.ui
Original file line number Diff line number Diff line change
Expand Up @@ -324,8 +324,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>514</width>
<height>579</height>
<width>506</width>
<height>558</height>
</rect>
</property>
<layout class="QFormLayout" name="formLayout">
Expand Down Expand Up @@ -1779,6 +1779,14 @@
<string>Toggle the visibility of the rowid column</string>
</property>
</action>
<action name="actionSetTableEncoding">
<property name="text">
<string>Set encoding</string>
</property>
<property name="toolTip">
<string>Change the encoding of the text in the table cells</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
Expand Down Expand Up @@ -2734,6 +2742,22 @@
</hint>
</hints>
</connection>
<connection>
<sender>actionSetTableEncoding</sender>
<signal>triggered()</signal>
<receiver>MainWindow</receiver>
<slot>browseDataSetTableEncoding()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>518</x>
<y>314</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>fileOpen()</slot>
Expand Down Expand Up @@ -2792,5 +2816,6 @@
<slot>jumpToRow(QString,QString,QByteArray)</slot>
<slot>editDataColumnDisplayFormat()</slot>
<slot>showRowidColumn(bool)</slot>
<slot>browseDataSetTableEncoding()</slot>
</slots>
</ui>
26 changes: 22 additions & 4 deletions src/sqlitetablemodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@
#include <QDebug>
#include <QMessageBox>
#include <QApplication>
#include <QTextCodec>

SqliteTableModel::SqliteTableModel(QObject* parent, DBBrowserDB* db, size_t chunkSize)
SqliteTableModel::SqliteTableModel(QObject* parent, DBBrowserDB* db, size_t chunkSize, const QString& encoding)
: QAbstractTableModel(parent)
, m_db(db)
, m_rowCount(0)
, m_chunkSize(chunkSize)
, m_valid(false)
, m_encoding(encoding)
{
reset();
}
Expand Down Expand Up @@ -251,7 +253,7 @@ QVariant SqliteTableModel::data(const QModelIndex &index, int role) const
else if(role == Qt::DisplayRole && m_data.at(index.row()).at(index.column()).isNull())
return PreferencesDialog::getSettingsValue("databrowser", "null_text").toString();
else
return m_data.at(index.row()).at(index.column());
return decode(m_data.at(index.row()).at(index.column()));
} else if(role == Qt::FontRole) {
QFont font;
if(m_data.at(index.row()).at(index.column()).isNull() || isBinary(index))
Expand Down Expand Up @@ -293,7 +295,7 @@ bool SqliteTableModel::setData(const QModelIndex& index, const QVariant& value,
{
if(index.isValid() && role == Qt::EditRole)
{
QByteArray newValue = value.toByteArray();
QByteArray newValue = encode(value.toByteArray());
QByteArray oldValue = m_data.at(index.row()).at(index.column());

// Don't do anything if the data hasn't changed
Expand Down Expand Up @@ -570,7 +572,7 @@ void SqliteTableModel::updateFilter(int column, const QString& value)
if(val == "''")
m_mWhere.remove(column);
else
m_mWhere.insert(column, QString("%1 %2").arg(op).arg(val));
m_mWhere.insert(column, QString("%1 %2").arg(op).arg(QString(encode(val.toUtf8()))));

// Build the new query
buildQuery();
Expand All @@ -587,3 +589,19 @@ bool SqliteTableModel::isBinary(const QModelIndex& index) const
{
return m_vDataTypes.at(index.column()) == SQLITE_BLOB;
}

QByteArray SqliteTableModel::encode(const QByteArray& str) const
{
if(m_encoding.isEmpty())
return str;
else
return QTextCodec::codecForName(m_encoding.toUtf8())->fromUnicode(str);
}

QByteArray SqliteTableModel::decode(const QByteArray& str) const
{
if(m_encoding.isEmpty())
return str;
else
return QTextCodec::codecForName(m_encoding.toUtf8())->toUnicode(str).toUtf8();
}
12 changes: 9 additions & 3 deletions src/sqlitetablemodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class SqliteTableModel : public QAbstractTableModel
{
Q_OBJECT
public:
explicit SqliteTableModel(QObject *parent = 0, DBBrowserDB* db = 0, size_t chunkSize = 50000);
explicit SqliteTableModel(QObject *parent = 0, DBBrowserDB* db = 0, size_t chunkSize = 50000, const QString& encoding = QString());
void reset();

int rowCount(const QModelIndex &parent = QModelIndex()) const;
Expand Down Expand Up @@ -40,12 +40,13 @@ class SqliteTableModel : public QAbstractTableModel

bool isBinary(const QModelIndex& index) const;

void setEncoding(QString encoding) { m_encoding = encoding; }
QString encoding() const { return m_encoding; }

typedef QList<QByteArray> QByteArrayList;

sqlb::ForeignKeyClause getForeignKeyClause(int column) const;

signals:

public slots:
void updateFilter(int column, const QString& value);

Expand All @@ -57,6 +58,9 @@ public slots:
QStringList getColumns(const QString& sQuery, QVector<int>& fieldsTypes);
int getQueryRowCount();

QByteArray encode(const QByteArray& str) const;
QByteArray decode(const QByteArray& str) const;

DBBrowserDB* m_db;
int m_rowCount;
QStringList m_headers;
Expand All @@ -82,6 +86,8 @@ public slots:
size_t m_chunkSize;

bool m_valid; //! tells if the current query is valid.

QString m_encoding;
};

#endif // SQLITETABLEMODEL_H

0 comments on commit eaf6ff1

Please sign in to comment.