Store settings in SqliteTableModel

Store the relevant settings in SqliteTableModel and only update them
when they have changed. This avoids a lot of querying and converting of
variables in the data() function which is called very often and
therefore is somewhat critical for the overall performance.
This commit is contained in:
Martin Kleusberg
2019-10-04 18:40:22 +02:00
parent be06bf2ac9
commit a43e6a93e4
5 changed files with 65 additions and 35 deletions

View File

@@ -150,7 +150,7 @@ QWidget* ExtendedTableWidgetEditorDelegate::createEditor(QWidget* parent, const
if (!currentTable->fields.at(static_cast<size_t>(index.column())-1).notnull())
query.append (" UNION SELECT NULL");
SqliteTableModel* fkModel = new SqliteTableModel(m->db(), parent, m->chunkSize(), m->encoding());
SqliteTableModel* fkModel = new SqliteTableModel(m->db(), parent, m->encoding());
fkModel->setQuery(query);
QComboBox* combo = new QComboBox(parent);

View File

@@ -22,7 +22,7 @@ SqlExecutionArea::SqlExecutionArea(DBBrowserDB& _db, QWidget* parent) :
ui->setupUi(this);
// Create model
model = new SqliteTableModel(db, this, static_cast<std::size_t>(Settings::getValue("db", "prefetchsize").toUInt()));
model = new SqliteTableModel(db, this);
ui->tableResult->setModel(model);
connect(model, &SqliteTableModel::finishedFetch, this, &SqlExecutionArea::fetchedData);
@@ -149,8 +149,8 @@ void SqlExecutionArea::reloadSettings()
ui->splitter->restoreState(Settings::getValue("editor", "splitter1_sizes").toByteArray());
ui->splitter_2->restoreState(Settings::getValue("editor", "splitter2_sizes").toByteArray());
// Set prefetch settings
model->setChunkSize(static_cast<std::size_t>(Settings::getValue("db", "prefetchsize").toUInt()));
// Reload model settings
model->reloadSettings();
// Check if error indicators are enabled for the not-ok background clue
showErrorIndicators = Settings::getValue("editor", "error_indicators").toBool();

View File

@@ -287,7 +287,7 @@ void TableBrowser::init(DBBrowserDB* _db)
if(m_model)
delete m_model;
m_model = new SqliteTableModel(*db, this, static_cast<std::size_t>(Settings::getValue("db", "prefetchsize").toUInt()));
m_model = new SqliteTableModel(*db, this);
connect(m_model, &SqliteTableModel::finishedFetch, this, &TableBrowser::updateRecordsetLabel);
}
@@ -537,7 +537,7 @@ void TableBrowser::reloadSettings()
ui->dataTable->reloadSettings();
ui->browseToolbar->setToolButtonStyle(static_cast<Qt::ToolButtonStyle>(Settings::getValue("General", "toolbarStyleBrowse").toInt()));
m_model->setChunkSize(static_cast<std::size_t>(Settings::getValue("db", "prefetchsize").toUInt()));
m_model->reloadSettings();
}
void TableBrowser::setCurrentTable(const sqlb::ObjectIdentifier& name)

View File

@@ -20,14 +20,16 @@
using json = nlohmann::json;
SqliteTableModel::SqliteTableModel(DBBrowserDB& db, QObject* parent, size_t chunkSize, const QString& encoding)
SqliteTableModel::SqliteTableModel(DBBrowserDB& db, QObject* parent, const QString& encoding)
: QAbstractTableModel(parent)
, m_db(db)
, m_lifeCounter(0)
, m_currentRowCount(0)
, m_chunkSize(chunkSize)
, m_encoding(encoding)
{
// Load initial settings first
reloadSettings();
worker = new RowLoader(
[this](){ return m_db.get(tr("reading rows")); },
[this](QString stmt){ return m_db.logSQL(stmt, kLogMsg_App); },
@@ -114,11 +116,6 @@ void SqliteTableModel::reset()
endResetModel();
}
void SqliteTableModel::setChunkSize(size_t chunksize)
{
m_chunkSize = chunksize;
}
void SqliteTableModel::setQuery(const sqlb::Query& query)
{
// Unset all previous settings. When setting a table all information on the previously browsed data set is removed first.
@@ -341,15 +338,14 @@ QVariant SqliteTableModel::data(const QModelIndex &index, int role) const
return tr("loading...");
if(role == Qt::DisplayRole && cached_row->at(column).isNull())
{
return Settings::getValue("databrowser", "null_text").toString();
return m_nullText;
} else if(role == Qt::DisplayRole && nosync_isBinary(index)) {
return Settings::getValue("databrowser", "blob_text").toString();
return m_blobText;
} else if(role == Qt::DisplayRole) {
int limit = Settings::getValue("databrowser", "symbol_limit").toInt();
QByteArray displayText = cached_row->at(column);
if (displayText.length() > limit) {
if (displayText.length() > m_symbolLimit) {
// Add "..." to the end of truncated strings
return decode(displayText.left(limit).append(" ..."));
return decode(displayText.left(m_symbolLimit).append(" ..."));
} else {
return decode(displayText);
}
@@ -373,9 +369,9 @@ QVariant SqliteTableModel::data(const QModelIndex &index, int role) const
if(!row_available)
return QColor(100, 100, 100);
if(cached_row->at(column).isNull())
return QColor(Settings::getValue("databrowser", "null_fg_colour").toString());
return m_nullFgColour;
else if (nosync_isBinary(index))
return QColor(Settings::getValue("databrowser", "bin_fg_colour").toString());
return m_binFgColour;
else if (m_mCondFormats.find(column) != m_mCondFormats.end()) {
QString value = cached_row->at(column);
// Unlock before querying from DB
@@ -385,14 +381,14 @@ QVariant SqliteTableModel::data(const QModelIndex &index, int role) const
return condFormatColor;
}
// Regular case (not null, not binary and no matching conditional format)
return QColor(Settings::getValue("databrowser", "reg_fg_colour").toString());
return m_regFgColour;
} else if (role == Qt::BackgroundRole) {
if(!row_available)
return QColor(255, 200, 200);
if(cached_row->at(column).isNull())
return QColor(Settings::getValue("databrowser", "null_bg_colour").toString());
return m_nullBgColour;
else if (nosync_isBinary(index))
return QColor(Settings::getValue("databrowser", "bin_bg_colour").toString());
return m_binBgColour;
else if (m_mCondFormats.find(column) != m_mCondFormats.end()) {
QString value = cached_row->at(column);
// Unlock before querying from DB
@@ -402,7 +398,7 @@ QVariant SqliteTableModel::data(const QModelIndex &index, int role) const
return condFormatColor;
}
// Regular case (not null, not binary and no matching conditional format)
return QColor(Settings::getValue("databrowser", "reg_bg_colour").toString());
return m_regBgColour;
} else if(role == Qt::ToolTipRole) {
sqlb::ForeignKeyClause fk = getForeignKeyClause(column-1);
if(fk.isSet())
@@ -427,7 +423,7 @@ QVariant SqliteTableModel::data(const QModelIndex &index, int role) const
if(!row_available)
return QVariant();
if(Settings::getValue("databrowser", "image_preview").toBool() && !isImageData(cached_row->at(column)).isNull())
if(m_imagePreviewEnabled && !isImageData(cached_row->at(column)).isNull())
{
QImage img;
img.loadFromData(cached_row->at(column));
@@ -1151,3 +1147,18 @@ QModelIndex SqliteTableModel::nextMatch(const QModelIndex& start, const std::vec
return pos;
}
}
void SqliteTableModel::reloadSettings()
{
m_nullText = Settings::getValue("databrowser", "null_text").toString();
m_blobText = Settings::getValue("databrowser", "blob_text").toString();
m_regFgColour = QColor(Settings::getValue("databrowser", "reg_fg_colour").toString());
m_regBgColour = QColor(Settings::getValue("databrowser", "reg_bg_colour").toString());
m_nullFgColour = QColor(Settings::getValue("databrowser", "null_fg_colour").toString());
m_nullBgColour = QColor(Settings::getValue("databrowser", "null_bg_colour").toString());
m_binFgColour = QColor(Settings::getValue("databrowser", "bin_fg_colour").toString());
m_binBgColour = QColor(Settings::getValue("databrowser", "bin_bg_colour").toString());
m_symbolLimit = Settings::getValue("databrowser", "symbol_limit").toInt();
m_imagePreviewEnabled = Settings::getValue("databrowser", "image_preview").toBool();
m_chunkSize = static_cast<std::size_t>(Settings::getValue("db", "prefetchsize").toUInt());
}

View File

@@ -2,6 +2,7 @@
#define SQLITETABLEMODEL_H
#include <QAbstractTableModel>
#include <QColor>
#include <QMutex>
#include <memory>
@@ -25,7 +26,7 @@ class SqliteTableModel : public QAbstractTableModel
#endif
public:
explicit SqliteTableModel(DBBrowserDB& db, QObject *parent = nullptr, size_t chunkSize = 50000, const QString& encoding = QString());
explicit SqliteTableModel(DBBrowserDB& db, QObject *parent = nullptr, const QString& encoding = QString());
~SqliteTableModel() override;
/// reset to state after construction
@@ -86,8 +87,6 @@ public:
/// configure for browsing specified table
void setQuery(const sqlb::Query& query);
void setChunkSize(size_t chunksize);
size_t chunkSize() { return m_chunkSize; }
void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override;
void sort(const std::vector<sqlb::SortedColumn>& columns);
sqlb::ObjectIdentifier currentTableName() const { return m_query.table(); }
@@ -132,6 +131,8 @@ public:
DBBrowserDB& db() { return m_db; }
void reloadSettings();
public slots:
void updateFilter(size_t column, const QString& value);
void updateGlobalFilter(const std::vector<QString>& values);
@@ -200,6 +201,31 @@ private:
std::map<size_t, std::vector<CondFormat>> m_mCondFormats;
sqlb::Query m_query;
QString m_encoding;
/**
* These are used for multi-threaded population of the table
*/
mutable QMutex m_mutexDataCache;
private:
/**
* Settings. These are stored here to avoid fetching and converting them every time we need them. Because this class
* uses a lot of settings and because some of its functions are called very often, this should speed things up noticeable.
* Call reloadSettings() to update these.
*/
QString m_nullText;
QString m_blobText;
QColor m_regFgColour;
QColor m_regBgColour;
QColor m_nullFgColour;
QColor m_nullBgColour;
QColor m_binFgColour;
QColor m_binBgColour;
int m_symbolLimit;
bool m_imagePreviewEnabled;
/**
* @brief m_chunkSize Size of the next chunk fetch more will try to fetch.
* This value should be rather high, because our query
@@ -209,13 +235,6 @@ private:
* to that row count.
*/
size_t m_chunkSize;
QString m_encoding;
/**
* These are used for multi-threaded population of the table
*/
mutable QMutex m_mutexDataCache;
};
#endif