mirror of
https://github.com/sqlitebrowser/sqlitebrowser.git
synced 2026-05-06 20:09:54 -05:00
first working prototype
This commit is contained in:
+81
-75
@@ -21,6 +21,7 @@
|
||||
#include "FindDialog.h"
|
||||
#include "SQLiteSyntaxHighlighter.h"
|
||||
#include "sqltextedit.h"
|
||||
#include "sqlitetablemodel.h"
|
||||
|
||||
MainWindow::MainWindow(QWidget* parent)
|
||||
: QMainWindow(parent),
|
||||
@@ -51,6 +52,8 @@ void MainWindow::init()
|
||||
// Init the SQL log dock
|
||||
db.mainWindow = this;
|
||||
|
||||
m_browseTableModel = new SqliteTableModel(this, &db);
|
||||
|
||||
// Set up the db tree widget
|
||||
ui->dbTreeWidget->setColumnHidden(1, true);
|
||||
ui->dbTreeWidget->setColumnWidth(0, 300);
|
||||
@@ -63,7 +66,8 @@ void MainWindow::init()
|
||||
createSyntaxHighlighters();
|
||||
|
||||
// Set up DB models
|
||||
ui->dataTable->setModel(browseTableModel);
|
||||
//ui->dataTable->setModel(browseTableModel);
|
||||
ui->dataTable->setModel(m_browseTableModel);
|
||||
|
||||
queryResultListModel = new QStandardItemModel(this);
|
||||
ui->queryResultTableView->setModel(queryResultListModel);
|
||||
@@ -270,43 +274,45 @@ void MainWindow::populateStructure()
|
||||
|
||||
void MainWindow::populateTable( const QString & tablename, bool keepColumnWidths)
|
||||
{
|
||||
bool mustreset = false;
|
||||
QApplication::setOverrideCursor( Qt::WaitCursor );
|
||||
if (tablename.compare(db.curBrowseTableName)!=0)
|
||||
{
|
||||
mustreset = true;
|
||||
curBrowseOrderByIndex = 1;
|
||||
curBrowseOrderByMode = ORDERMODE_ASC;
|
||||
}
|
||||
if(!tablename.isEmpty())
|
||||
m_browseTableModel->setQuery(QString("SELECT * FROM `%1`").arg(tablename));
|
||||
// bool mustreset = false;
|
||||
// if (tablename.compare(db.curBrowseTableName)!=0)
|
||||
// {
|
||||
// mustreset = true;
|
||||
// curBrowseOrderByIndex = 1;
|
||||
// curBrowseOrderByMode = ORDERMODE_ASC;
|
||||
// }
|
||||
|
||||
QString orderby = QString::number(curBrowseOrderByIndex) + " " + (curBrowseOrderByMode == ORDERMODE_ASC ? "ASC" : "DESC");
|
||||
if(!db.browseTable(tablename, orderby))
|
||||
{
|
||||
browseTableModel->setRowCount(0);
|
||||
browseTableModel->setColumnCount(0);
|
||||
QApplication::restoreOverrideCursor();
|
||||
if(findWin)
|
||||
findWin->resetFields(db.getTableFields(""));
|
||||
return;
|
||||
}
|
||||
// QString orderby = QString::number(curBrowseOrderByIndex) + " " + (curBrowseOrderByMode == ORDERMODE_ASC ? "ASC" : "DESC");
|
||||
// if(!db.browseTable(tablename, orderby))
|
||||
// {
|
||||
// browseTableModel->setRowCount(0);
|
||||
// browseTableModel->setColumnCount(0);
|
||||
// QApplication::restoreOverrideCursor();
|
||||
// if(findWin)
|
||||
// findWin->resetFields(db.getTableFields(""));
|
||||
// return;
|
||||
// }
|
||||
|
||||
// Activate the add and delete record buttons and editing only if a table has been selected
|
||||
bool is_table = db.getObjectByName(tablename).gettype() == "table";
|
||||
ui->buttonNewRecord->setEnabled(is_table);
|
||||
ui->buttonDeleteRecord->setEnabled(is_table);
|
||||
ui->dataTable->setEditTriggers(is_table ? QAbstractItemView::DoubleClicked | QAbstractItemView::AnyKeyPressed | QAbstractItemView::EditKeyPressed : QAbstractItemView::NoEditTriggers);
|
||||
// // Activate the add and delete record buttons and editing only if a table has been selected
|
||||
// bool is_table = db.getObjectByName(tablename).gettype() == "table";
|
||||
// ui->buttonNewRecord->setEnabled(is_table);
|
||||
// ui->buttonDeleteRecord->setEnabled(is_table);
|
||||
// ui->dataTable->setEditTriggers(is_table ? QAbstractItemView::DoubleClicked | QAbstractItemView::AnyKeyPressed | QAbstractItemView::EditKeyPressed : QAbstractItemView::NoEditTriggers);
|
||||
|
||||
if (mustreset){
|
||||
updateTableView(0, keepColumnWidths);
|
||||
if (findWin) findWin->resetFields(db.getTableFields(db.curBrowseTableName));
|
||||
} else {
|
||||
updateTableView(-1, keepColumnWidths);
|
||||
}
|
||||
//got to keep findWin in synch
|
||||
if(findWin)
|
||||
findWin->resetFields();
|
||||
if(editWin)
|
||||
editWin->reset();
|
||||
// if (mustreset){
|
||||
// updateTableView(0, keepColumnWidths);
|
||||
// if (findWin) findWin->resetFields(db.getTableFields(db.curBrowseTableName));
|
||||
// } else {
|
||||
// updateTableView(-1, keepColumnWidths);
|
||||
// }
|
||||
// //got to keep findWin in synch
|
||||
// if(findWin)
|
||||
// findWin->resetFields();
|
||||
// if(editWin)
|
||||
// editWin->reset();
|
||||
QApplication::restoreOverrideCursor();
|
||||
}
|
||||
|
||||
@@ -423,52 +429,52 @@ void MainWindow::updateTableView(int lineToSelect, bool keepColumnWidths)
|
||||
{
|
||||
QApplication::setOverrideCursor( Qt::WaitCursor );
|
||||
|
||||
browseTableModel->setRowCount(db.getRecordCount());
|
||||
browseTableModel->setColumnCount(db.browseFields.count());
|
||||
browseTableModel->setHorizontalHeaderLabels(db.browseFields);
|
||||
// browseTableModel->setRowCount(db.getRecordCount());
|
||||
// browseTableModel->setColumnCount(db.browseFields.count());
|
||||
// browseTableModel->setHorizontalHeaderLabels(db.browseFields);
|
||||
|
||||
rowList tab = db.browseRecs;
|
||||
int maxRecs = db.getRecordCount();
|
||||
gotoValidator->setRange(0, maxRecs);
|
||||
// rowList tab = db.browseRecs;
|
||||
// int maxRecs = db.getRecordCount();
|
||||
// gotoValidator->setRange(0, maxRecs);
|
||||
|
||||
if ( maxRecs > 0 ) {
|
||||
// if ( maxRecs > 0 ) {
|
||||
|
||||
int rowNum = 0;
|
||||
int colNum = 0;
|
||||
QString rowLabel;
|
||||
for (int i = 0; i < tab.size(); ++i)
|
||||
{
|
||||
rowLabel.setNum(rowNum+1);
|
||||
browseTableModel->setVerticalHeaderItem(rowNum, new QStandardItem(rowLabel));
|
||||
colNum = 0;
|
||||
QList<QByteArray> rt = tab[i];
|
||||
for (int e = 1; e < rt.size(); ++e)
|
||||
{
|
||||
QString content = rt[e];
|
||||
// int rowNum = 0;
|
||||
// int colNum = 0;
|
||||
// QString rowLabel;
|
||||
// for (int i = 0; i < tab.size(); ++i)
|
||||
// {
|
||||
// rowLabel.setNum(rowNum+1);
|
||||
// browseTableModel->setVerticalHeaderItem(rowNum, new QStandardItem(rowLabel));
|
||||
// colNum = 0;
|
||||
// QList<QByteArray> rt = tab[i];
|
||||
// for (int e = 1; e < rt.size(); ++e)
|
||||
// {
|
||||
// QString content = rt[e];
|
||||
|
||||
QStandardItem* item = new QStandardItem(content);
|
||||
item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||||
item->setToolTip(wrapText(content));
|
||||
browseTableModel->setItem( rowNum, colNum, item);
|
||||
colNum++;
|
||||
}
|
||||
rowNum++;
|
||||
if (rowNum==maxRecs) break;
|
||||
}
|
||||
}
|
||||
// QStandardItem* item = new QStandardItem(content);
|
||||
// item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||||
// item->setToolTip(wrapText(content));
|
||||
// browseTableModel->setItem( rowNum, colNum, item);
|
||||
// colNum++;
|
||||
// }
|
||||
// rowNum++;
|
||||
// if (rowNum==maxRecs) break;
|
||||
// }
|
||||
// }
|
||||
|
||||
if(!keepColumnWidths) {
|
||||
for(int i=0;i<browseTableModel->columnCount();++i)
|
||||
{
|
||||
ui->dataTable->resizeColumnToContents(i);
|
||||
if( ui->dataTable->columnWidth(i) > 400 )
|
||||
ui->dataTable->setColumnWidth(i, 400);
|
||||
}
|
||||
}
|
||||
if (lineToSelect!=-1){
|
||||
selectTableLine(lineToSelect);
|
||||
}
|
||||
setRecordsetLabel();
|
||||
// if(!keepColumnWidths) {
|
||||
// for(int i=0;i<browseTableModel->columnCount();++i)
|
||||
// {
|
||||
// ui->dataTable->resizeColumnToContents(i);
|
||||
// if( ui->dataTable->columnWidth(i) > 400 )
|
||||
// ui->dataTable->setColumnWidth(i, 400);
|
||||
// }
|
||||
// }
|
||||
// if (lineToSelect!=-1){
|
||||
// selectTableLine(lineToSelect);
|
||||
// }
|
||||
// setRecordsetLabel();
|
||||
QApplication::restoreOverrideCursor();
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ class QStandardItemModel;
|
||||
class QIntValidator;
|
||||
class QLabel;
|
||||
class QModelIndex;
|
||||
class SqliteTableModel;
|
||||
|
||||
namespace Ui {
|
||||
class MainWindow;
|
||||
@@ -53,6 +54,7 @@ private:
|
||||
Ui::MainWindow* ui;
|
||||
|
||||
QStandardItemModel *browseTableModel;
|
||||
SqliteTableModel* m_browseTableModel;
|
||||
QStandardItemModel *queryResultListModel;
|
||||
QMenu *popupTableMenu;
|
||||
QMenu *recentFilesMenu;
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
#include "sqlitetablemodel.h"
|
||||
|
||||
#include "sqlitedb.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
SqliteTableModel::SqliteTableModel(QObject* parent, DBBrowserDB* db)
|
||||
: QAbstractTableModel(parent)
|
||||
, m_db(db)
|
||||
, m_rowCount(0)
|
||||
, m_columnCount(0)
|
||||
, m_chunkSize(1000)
|
||||
{
|
||||
}
|
||||
|
||||
void SqliteTableModel::setChunkSize(size_t chunksize)
|
||||
{
|
||||
m_chunkSize = chunksize;
|
||||
}
|
||||
|
||||
void SqliteTableModel::setQuery(const QString& sQuery)
|
||||
{
|
||||
if(!m_db->isOpen())
|
||||
return;
|
||||
|
||||
sqlite3_stmt *stmt;
|
||||
m_rowCount = 0;
|
||||
m_sQuery = sQuery;
|
||||
|
||||
// do a count query to get the full row count in a fast manner
|
||||
QString sCountQuery = QString("SELECT COUNT(*) FROM (%1);").arg(sQuery);
|
||||
QByteArray utf8Query = sCountQuery.toUtf8();
|
||||
int status = sqlite3_prepare_v2(m_db->_db, utf8Query, utf8Query.size(), &stmt, NULL);
|
||||
|
||||
if(SQLITE_OK == status)
|
||||
{
|
||||
status = sqlite3_step(stmt);
|
||||
if(SQLITE_ROW == status)
|
||||
{
|
||||
m_columnCount = sqlite3_data_count(stmt);
|
||||
QString sCount = QString::fromUtf8((const char *) sqlite3_column_text(stmt, 0));
|
||||
m_rowCount = sCount.toInt();
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
// now fetch the first 100 entries and get headers
|
||||
m_headers.clear();
|
||||
m_columnCount = 0;
|
||||
QString sLimitQuery = QString("%1 LIMIT 0, %2;").arg(sQuery).arg(m_chunkSize);
|
||||
utf8Query = sLimitQuery.toUtf8();
|
||||
status = sqlite3_prepare_v2(m_db->_db, utf8Query, utf8Query.size(), &stmt, NULL);
|
||||
|
||||
if(SQLITE_OK == status)
|
||||
{
|
||||
status = sqlite3_step(stmt);
|
||||
|
||||
if(SQLITE_ROW == status)
|
||||
{
|
||||
m_columnCount = sqlite3_data_count(stmt);
|
||||
for (int i = 0; i < m_columnCount; ++i)
|
||||
m_headers.append(QString::fromUtf8((const char *)sqlite3_column_name(stmt, i)));
|
||||
|
||||
int row = 0;
|
||||
// row data starts here
|
||||
do
|
||||
{
|
||||
QStringList rowdata;
|
||||
for (int i = 0; i < m_columnCount; ++i)
|
||||
rowdata.append(QString::fromUtf8((const char *)sqlite3_column_text(stmt, i)));
|
||||
m_data.insert(row++, rowdata);
|
||||
} while(sqlite3_step(stmt) == SQLITE_ROW);
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
emit layoutChanged();
|
||||
}
|
||||
|
||||
int SqliteTableModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
(void)parent;
|
||||
return m_data.size(); // current fetched row count
|
||||
}
|
||||
|
||||
int SqliteTableModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
(void)parent;
|
||||
return m_columnCount;
|
||||
}
|
||||
|
||||
QVariant SqliteTableModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (role != Qt::DisplayRole)
|
||||
return QVariant();
|
||||
|
||||
if (orientation == Qt::Horizontal)
|
||||
return m_headers.at(section);
|
||||
else
|
||||
return QString("Row %1").arg(section);
|
||||
}
|
||||
|
||||
QVariant SqliteTableModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
if (index.row() >= m_rowCount)
|
||||
return QVariant();
|
||||
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
return m_data[index.row()].at(index.column());
|
||||
}
|
||||
else
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool SqliteTableModel::canFetchMore(const QModelIndex &parent) const
|
||||
{
|
||||
return m_data.size() < m_rowCount;
|
||||
}
|
||||
|
||||
void SqliteTableModel::fetchMore(const QModelIndex& parent)
|
||||
{
|
||||
int currentsize = m_data.size();
|
||||
int row = m_data.size();
|
||||
QString sLimitQuery = QString("%1 LIMIT %2, %3;").arg(m_sQuery).arg(row).arg(row + m_chunkSize);
|
||||
QByteArray utf8Query = sLimitQuery.toUtf8();
|
||||
sqlite3_stmt *stmt;
|
||||
int status = sqlite3_prepare_v2(m_db->_db, utf8Query, utf8Query.size(), &stmt, NULL);
|
||||
|
||||
if(SQLITE_OK == status)
|
||||
{
|
||||
status = sqlite3_step(stmt);
|
||||
|
||||
if(SQLITE_ROW == status)
|
||||
{
|
||||
do
|
||||
{
|
||||
QStringList rowdata;
|
||||
for (int i = 0; i < m_columnCount; ++i)
|
||||
rowdata.append(QString::fromUtf8((const char *)sqlite3_column_text(stmt, i)));
|
||||
Q_ASSERT(m_headers.size() == rowdata.size());
|
||||
m_data.insert(row++, rowdata);
|
||||
} while(sqlite3_step(stmt) == SQLITE_ROW);
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
beginInsertRows(parent, currentsize, m_data.size());
|
||||
endInsertRows();
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#ifndef SQLITETABLEMODEL_H
|
||||
#define SQLITETABLEMODEL_H
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include <QStringList>
|
||||
|
||||
class DBBrowserDB;
|
||||
|
||||
class SqliteTableModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SqliteTableModel(QObject *parent = 0, DBBrowserDB* db = 0);
|
||||
|
||||
int rowCount(const QModelIndex &parent) const;
|
||||
int columnCount(const QModelIndex &parent) const;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
bool canFetchMore(const QModelIndex &parent) const;
|
||||
void fetchMore(const QModelIndex &parent);
|
||||
size_t queryMore(size_t offset);
|
||||
|
||||
void setQuery(const QString& sQuery);
|
||||
void setChunkSize(size_t chunksize);
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
|
||||
|
||||
private:
|
||||
DBBrowserDB* m_db;
|
||||
int m_rowCount;
|
||||
int m_columnCount;
|
||||
QStringList m_headers;
|
||||
QMap<int, QStringList> m_data;
|
||||
QString m_sQuery;
|
||||
|
||||
size_t m_chunkSize;
|
||||
};
|
||||
|
||||
#endif // SQLITETABLEMODEL_H
|
||||
+4
-2
@@ -25,7 +25,8 @@ HEADERS += \
|
||||
ExtendedTableWidget.h \
|
||||
grammar/Sqlite3Lexer.hpp \
|
||||
grammar/Sqlite3Parser.hpp \
|
||||
grammar/sqlite3TokenTypes.hpp
|
||||
grammar/sqlite3TokenTypes.hpp \
|
||||
sqlitetablemodel.h
|
||||
|
||||
SOURCES += \
|
||||
sqlitedb.cpp \
|
||||
@@ -43,7 +44,8 @@ SOURCES += \
|
||||
sqlitetypes.cpp \
|
||||
ExtendedTableWidget.cpp \
|
||||
grammar/Sqlite3Lexer.cpp \
|
||||
grammar/Sqlite3Parser.cpp
|
||||
grammar/Sqlite3Parser.cpp \
|
||||
sqlitetablemodel.cpp
|
||||
|
||||
# create a unittest option
|
||||
CONFIG(unittest) {
|
||||
|
||||
Reference in New Issue
Block a user