mirror of
https://github.com/sqlitebrowser/sqlitebrowser.git
synced 2026-01-20 02:50:46 -06:00
Support text in different encoding in Browse Data tab
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.
This commit is contained in:
@@ -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());
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ public:
|
||||
QMap<int, QString> filterValues;
|
||||
QMap<int, QString> displayFormats;
|
||||
bool showRowid;
|
||||
QString encoding;
|
||||
|
||||
friend QDataStream& operator<<(QDataStream& stream, const MainWindow::BrowseDataTableSettings& object)
|
||||
{
|
||||
@@ -49,6 +50,7 @@ public:
|
||||
stream << object.filterValues;
|
||||
stream << object.displayFormats;
|
||||
stream << object.showRowid;
|
||||
stream << object.encoding;
|
||||
|
||||
return stream;
|
||||
}
|
||||
@@ -62,6 +64,7 @@ public:
|
||||
stream >> object.filterValues;
|
||||
stream >> object.displayFormats;
|
||||
stream >> object.showRowid;
|
||||
stream >> object.encoding;
|
||||
|
||||
return stream;
|
||||
}
|
||||
@@ -218,6 +221,7 @@ private slots:
|
||||
void showDataColumnPopupMenu(const QPoint& pos);
|
||||
void editDataColumnDisplayFormat();
|
||||
void showRowidColumn(bool show);
|
||||
void browseDataSetTableEncoding();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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">
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -2792,5 +2816,6 @@
|
||||
<slot>jumpToRow(QString,QString,QByteArray)</slot>
|
||||
<slot>editDataColumnDisplayFormat()</slot>
|
||||
<slot>showRowidColumn(bool)</slot>
|
||||
<slot>browseDataSetTableEncoding()</slot>
|
||||
</slots>
|
||||
</ui>
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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))
|
||||
@@ -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
|
||||
@@ -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();
|
||||
@@ -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,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;
|
||||
@@ -40,12 +40,13 @@ public:
|
||||
|
||||
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);
|
||||
|
||||
@@ -57,6 +58,9 @@ private:
|
||||
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;
|
||||
@@ -82,6 +86,8 @@ private:
|
||||
size_t m_chunkSize;
|
||||
|
||||
bool m_valid; //! tells if the current query is valid.
|
||||
|
||||
QString m_encoding;
|
||||
};
|
||||
|
||||
#endif // SQLITETABLEMODEL_H
|
||||
|
||||
Reference in New Issue
Block a user