Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
Executable
+80
@@ -0,0 +1,80 @@
|
||||
#include "AddLine.h"
|
||||
|
||||
#include "ui_AddLinesUi.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
|
||||
AddLines::AddLines(QWidget* parent)
|
||||
: QDialog(parent)
|
||||
, m_ui(new Ui::AddLines)
|
||||
{
|
||||
qRegisterMetaType<AddModel*>("AddModel*");
|
||||
|
||||
m_ui->setupUi(this);
|
||||
|
||||
m_ui->dataView->setModel(&addModel);
|
||||
|
||||
connect(m_ui->pbDone, &QPushButton::clicked,
|
||||
this, &AddLines::slotAddLines);
|
||||
|
||||
connect(m_ui->pbAbort, &QPushButton::clicked,
|
||||
this, &AddLines::close);
|
||||
|
||||
connect(m_ui->pbDelete, &QPushButton::clicked,
|
||||
this, &AddLines::slotDeleteLines);
|
||||
|
||||
connect(m_ui->pbClear, &QPushButton::clicked,
|
||||
this, &AddLines::slotClear);
|
||||
}
|
||||
|
||||
|
||||
AddLines::~AddLines()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
|
||||
void AddLines::slotDeleteLines()
|
||||
{
|
||||
//qWarning() << "slotDeleteLines";
|
||||
|
||||
while (m_ui->dataView->selectionModel()->selectedRows().count())
|
||||
{
|
||||
const QModelIndexList selectedRows = m_ui->dataView->selectionModel()->selectedRows();
|
||||
|
||||
if (selectedRows.at(0).row() == addModel.rowCount()-1) // do not delete empty row!
|
||||
{
|
||||
return; // In hope that the selectedRows list is sorted.....
|
||||
}
|
||||
|
||||
addModel.removeRow(selectedRows.at(0).row());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AddLines::slotClear()
|
||||
{
|
||||
//qWarning() << "slotClear";
|
||||
addModel.clear();
|
||||
}
|
||||
|
||||
|
||||
void AddLines::reject()
|
||||
{
|
||||
emit signalAddLines(nullptr);
|
||||
}
|
||||
|
||||
|
||||
void AddLines::copyDataFromModel(DataModel* dataModel)
|
||||
{
|
||||
addModel.setHeaderList(dataModel->getHeaderList());
|
||||
addModel.setTablename(dataModel->getTableName());
|
||||
}
|
||||
|
||||
|
||||
void AddLines::slotAddLines()
|
||||
{
|
||||
this->hide(); // hide until in work..
|
||||
emit signalAddLines(&addModel);
|
||||
}
|
||||
Executable
+37
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include "AddModel.h"
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class AddLines;
|
||||
}
|
||||
|
||||
|
||||
class AddLines : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AddLines(QWidget *parent = nullptr);
|
||||
~AddLines();
|
||||
|
||||
void copyDataFromModel(DataModel* dataModel);
|
||||
|
||||
protected:
|
||||
void reject();
|
||||
|
||||
private:
|
||||
Ui::AddLines* m_ui;
|
||||
AddModel addModel;
|
||||
|
||||
private slots:
|
||||
void slotAddLines();
|
||||
void slotDeleteLines();
|
||||
void slotClear();
|
||||
|
||||
signals:
|
||||
void signalAddLines(AddModel*);
|
||||
};
|
||||
Executable
+152
@@ -0,0 +1,152 @@
|
||||
#include "AddModel.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
|
||||
void AddModel::setHeaderList(const HeaderList& headerList)
|
||||
{
|
||||
m_headerList = headerList;
|
||||
beginResetModel();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
|
||||
const HeaderList& AddModel::getHeaderList() const
|
||||
{
|
||||
return m_headerList;
|
||||
}
|
||||
|
||||
|
||||
bool AddModel::removeRow(int row, const QModelIndex &parent)
|
||||
{
|
||||
//qWarning() << "removeRow";
|
||||
|
||||
(void)parent;
|
||||
|
||||
if (row >= m_dataList.count())
|
||||
{
|
||||
//qWarning() << "removeRows false";
|
||||
return false;
|
||||
}
|
||||
|
||||
beginRemoveRows(parent, row, row);
|
||||
m_dataList.removeAt(row);
|
||||
endRemoveRows();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void AddModel::clear()
|
||||
{
|
||||
beginResetModel();
|
||||
m_dataList.clear();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
|
||||
QVariant AddModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
switch (role)
|
||||
{
|
||||
case Qt::EditRole:
|
||||
case Qt::DisplayRole:
|
||||
{
|
||||
if (index.row() >= m_dataList.count())
|
||||
{
|
||||
return QVariant(); // probably the new line was not added yet (use setData the first time to create it)
|
||||
}
|
||||
|
||||
return m_dataList.at(index.row()).at(index.column());
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
|
||||
bool AddModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
if (role != Qt::EditRole)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (index.row() >= m_dataList.count()) // no row in dataList?
|
||||
{
|
||||
Data newData; // create new row
|
||||
int headerListCount = m_headerList.count();
|
||||
newData.reserve(headerListCount);
|
||||
|
||||
for (int i = 0; i < headerListCount; i++) // preadd empty columns
|
||||
{
|
||||
newData.append(QString());
|
||||
}
|
||||
|
||||
m_dataList.append(newData); // finally add new line to dataList
|
||||
}
|
||||
|
||||
Data data = m_dataList.at(index.row()); // get old row
|
||||
data.replace(index.column(), value.toString()); // replace column in row
|
||||
m_dataList.replace(index.row(), data); // finally replace row in dataList
|
||||
|
||||
beginResetModel();
|
||||
endResetModel(); // tell the model to show the new empty line
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
QVariant::Type AddModel::getColumnType(const int column) const
|
||||
{
|
||||
if (column < 0 || column >= m_headerList.size())
|
||||
return QVariant::Invalid;
|
||||
return m_headerList.at(column).second;
|
||||
}
|
||||
|
||||
|
||||
QVariant AddModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation != Qt::Horizontal)
|
||||
return QVariant();
|
||||
|
||||
switch (role)
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
{
|
||||
return m_headerList.at(section).first;
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
|
||||
int AddModel::rowCount(const QModelIndex &) const
|
||||
{
|
||||
return m_dataList.count() + 1 /* empty row for new data */; // yes, if the user wants to add more than 1 line!
|
||||
}
|
||||
|
||||
|
||||
int AddModel::columnCount(const QModelIndex &) const
|
||||
{
|
||||
return m_headerList.count();
|
||||
}
|
||||
|
||||
|
||||
Qt::ItemFlags AddModel::flags(const QModelIndex &) const
|
||||
{
|
||||
return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable;
|
||||
}
|
||||
|
||||
|
||||
void AddModel::setTablename(const QString& tableName)
|
||||
{
|
||||
m_tableName = tableName;
|
||||
}
|
||||
|
||||
|
||||
const QString& AddModel::getTableName() const
|
||||
{
|
||||
return m_tableName;
|
||||
}
|
||||
Executable
+33
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include "DataModel.h"
|
||||
|
||||
class AddModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
using QAbstractTableModel::QAbstractTableModel;
|
||||
|
||||
void setHeaderList(const HeaderList& headerList);
|
||||
void setTablename(const QString& tableName);
|
||||
const QString& getTableName() const;
|
||||
QVariant::Type getColumnType(const int column) const;
|
||||
const HeaderList& getHeaderList() const;
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
bool removeRow(int row, const QModelIndex &parent = QModelIndex());
|
||||
void clear();
|
||||
|
||||
private:
|
||||
HeaderList m_headerList;
|
||||
DataList m_dataList;
|
||||
QString m_tableName;
|
||||
|
||||
};
|
||||
Executable
+251
@@ -0,0 +1,251 @@
|
||||
#include "ui_BrowserWndUi.h"
|
||||
#include "BrowserWnd.h"
|
||||
#include "LoginWnd.h"
|
||||
#include "Query.h"
|
||||
#include "DataModel.h"
|
||||
#include "QueryThread.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QGraphicsDropShadowEffect>
|
||||
#include <QListWidgetItem>
|
||||
#include <QMessageBox>
|
||||
#include <QRegExp>
|
||||
#include <QShortcut>
|
||||
#include <QThread>
|
||||
|
||||
|
||||
BrowserWnd::BrowserWnd()
|
||||
: QWidget(nullptr)
|
||||
, m_loginWnd(new LoginWnd(this))
|
||||
, m_waitWnd(new WaitWnd(this))
|
||||
, m_ui(new Ui::BrowserWnd)
|
||||
, m_queryWorker(new QueryWorker())
|
||||
, m_queryThread(new QThread())
|
||||
{
|
||||
//setVersionView();
|
||||
|
||||
qRegisterMetaType<LoginData>("LoginData");
|
||||
|
||||
if (!test())
|
||||
exit(1);
|
||||
|
||||
new QShortcut(QKeySequence(QStringLiteral("Ctrl+Q")), this, SLOT(close()));
|
||||
|
||||
connect(this, &BrowserWnd::signalConnect, m_queryWorker, &QueryWorker::slotConnectIt);
|
||||
connect(m_queryWorker, &QueryWorker::signalConnectResult, this, &BrowserWnd::slotConnectResult);
|
||||
|
||||
connect(this, &BrowserWnd::signalGetTableList, m_queryWorker, &QueryWorker::slotGetTableList);
|
||||
connect(m_queryWorker, &QueryWorker::signalNewTableList, this, &BrowserWnd::slotNewTableList);
|
||||
|
||||
m_queryWorker->moveToThread(m_queryThread);
|
||||
m_queryThread->start();
|
||||
}
|
||||
|
||||
BrowserWnd::~BrowserWnd()
|
||||
{
|
||||
endThread();
|
||||
delete m_ui;
|
||||
delete m_waitWnd;
|
||||
delete m_loginWnd;
|
||||
}
|
||||
|
||||
|
||||
void BrowserWnd::slotAddNewQuery()
|
||||
{
|
||||
addNewQuery();
|
||||
}
|
||||
|
||||
|
||||
void BrowserWnd::slotConnectResult(const QString &result)
|
||||
{
|
||||
if (result.isEmpty()) // connection success!
|
||||
{
|
||||
// everything okay, logged in, go!
|
||||
m_ui->setupUi(this);
|
||||
|
||||
// showing Host / DB name in window title
|
||||
this->setWindowTitle(QStringLiteral("RDE SQL Browser on Database: ") + m_loginWnd->getLoginData().database);
|
||||
|
||||
m_ui->splitter->setStretchFactor(0, 0); // not stretch for table list
|
||||
m_ui->splitter->setStretchFactor(1, 1); // stretch the query widget
|
||||
|
||||
this->show();
|
||||
|
||||
addNewQuery();
|
||||
|
||||
refreshTableList();
|
||||
|
||||
connect(m_ui->leFilter, &QLineEdit::textChanged, this, &BrowserWnd::slotFilterTableList);
|
||||
connect(m_ui->lwTables, &QListWidget::itemDoubleClicked, this, &BrowserWnd::slotFilterTableItemChanged);
|
||||
connect(m_ui->twQueries, &QTabWidget::tabCloseRequested, this, &BrowserWnd::slotTabCloseRequested);
|
||||
connect(m_ui->pbNewQuery, &QPushButton::clicked, this, &BrowserWnd::slotAddNewQuery);
|
||||
connect(m_ui->pushButton, &QPushButton::clicked, qApp, &QApplication::quit);
|
||||
connect(m_ui->pushButton_2, &QPushButton::clicked, this, &BrowserWnd::slotHeart);
|
||||
}
|
||||
else // failed with message
|
||||
{
|
||||
QMessageBox::critical(this,
|
||||
tr("Connection Error"),
|
||||
tr("Cannot connect to specified server."
|
||||
"\nError:"
|
||||
"\n'%1'").arg(result));
|
||||
}
|
||||
|
||||
m_waitWnd->hide();
|
||||
}
|
||||
|
||||
|
||||
void BrowserWnd::slotFilterTableList(const QString &)
|
||||
{
|
||||
refreshTableList();
|
||||
}
|
||||
|
||||
|
||||
void BrowserWnd::addNewQuery(const QString &tableName) // tableName only set when query from double clicking table list
|
||||
{
|
||||
Query *query = new Query(m_queryWorker);
|
||||
|
||||
connect(query, &Query::signalShowWait, this, &BrowserWnd::slotShowWait);
|
||||
connect(query, &Query::signalHideWait, this, &BrowserWnd::slotHideWait);
|
||||
|
||||
int tabIndex = -1;
|
||||
|
||||
if (tableName.length()) // there is a tablename
|
||||
{
|
||||
query->setTable(tableName);
|
||||
tabIndex = m_ui->twQueries->addTab(query, tableName);
|
||||
}
|
||||
else // no tablename
|
||||
tabIndex = m_ui->twQueries->addTab(query, QStringLiteral("Query %1").arg(m_newQueryCounter++));
|
||||
|
||||
m_ui->twQueries->setCurrentIndex(tabIndex);
|
||||
}
|
||||
|
||||
//#warning TODO: reimpl
|
||||
//void BrowserWnd::slotSelectQueryStatus(int percent)
|
||||
//{
|
||||
// m_waitWnd->setStatus(percent);
|
||||
//}
|
||||
|
||||
|
||||
void BrowserWnd::endThread()
|
||||
{
|
||||
if (!m_queryThread)
|
||||
return;
|
||||
|
||||
m_queryWorker->dy();
|
||||
m_queryThread->quit();
|
||||
m_queryThread->wait();
|
||||
|
||||
delete m_queryThread;
|
||||
m_queryThread = nullptr;
|
||||
delete m_queryWorker;
|
||||
m_queryWorker = nullptr;
|
||||
}
|
||||
|
||||
|
||||
void BrowserWnd::refreshTableList()
|
||||
{
|
||||
m_ui->lwTables->clear();
|
||||
|
||||
m_waitWnd->wait(QStringLiteral("Refreshing Table List .."));
|
||||
|
||||
emit signalGetTableList();
|
||||
}
|
||||
|
||||
|
||||
void BrowserWnd::slotNewTableList(QStringList tables)
|
||||
{
|
||||
if (!m_ui->leFilter->text().isEmpty()) // filter when there is a filter
|
||||
{
|
||||
QRegExp regExp(m_ui->leFilter->text(), Qt::CaseInsensitive, QRegExp::Wildcard);
|
||||
tables = tables.filter(regExp);
|
||||
}
|
||||
|
||||
m_ui->lwTables->addItems(tables);
|
||||
|
||||
m_waitWnd->hide();
|
||||
}
|
||||
|
||||
|
||||
void BrowserWnd::startConnect()
|
||||
{
|
||||
//m_loginWnd->setDefaultLoginData(presetManager. defaultLoginData);
|
||||
|
||||
if (!m_loginWnd->exec()) // false = user reject
|
||||
{
|
||||
QCoreApplication::quit();
|
||||
return;
|
||||
}
|
||||
|
||||
m_waitWnd->wait(tr("Connecting .."));
|
||||
|
||||
emit signalConnect(m_loginWnd->getLoginData());
|
||||
}
|
||||
|
||||
|
||||
bool BrowserWnd::test()
|
||||
{
|
||||
if (QSqlDatabase::drivers().isEmpty() ||
|
||||
QSqlDatabase::drivers().indexOf(QLatin1String("QSQLITE")) == -1)
|
||||
{
|
||||
QMessageBox::critical(this,
|
||||
tr("Missing Qt PostgreSQL driver"),
|
||||
tr("There is no QPSQL driver."
|
||||
"\nDid you install the package 'libQt5Sql5-postgresql'?"));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void BrowserWnd::slotFilterTableItemChanged(QListWidgetItem *item)
|
||||
{
|
||||
QString tableName = item->text();
|
||||
addNewQuery(tableName);
|
||||
}
|
||||
|
||||
|
||||
void BrowserWnd::slotTabCloseRequested(int index)
|
||||
{
|
||||
Query *q = qobject_cast<Query *>(m_ui->twQueries->widget(index));
|
||||
|
||||
m_ui->twQueries->removeTab(index);
|
||||
|
||||
if (!q)
|
||||
QMessageBox::critical(this, QStringLiteral("Query Failed"), QStringLiteral("Woops..?!!"));
|
||||
|
||||
delete q; // It´s safe to delete nullptr;
|
||||
}
|
||||
|
||||
|
||||
void BrowserWnd::slotShowWait(const QString &msg)
|
||||
{
|
||||
m_waitWnd->wait(msg);
|
||||
}
|
||||
|
||||
|
||||
void BrowserWnd::slotHideWait()
|
||||
{
|
||||
m_waitWnd->hide();
|
||||
}
|
||||
|
||||
|
||||
void BrowserWnd::slotHeart()
|
||||
{
|
||||
QWidget *w = new QWidget;
|
||||
w->setAttribute(Qt::WA_DeleteOnClose); // delete when closed
|
||||
QVBoxLayout *b = new QVBoxLayout;
|
||||
QLabel *l = new QLabel(QStringLiteral("<html><body>Geschmiedet mit %1 , ohne Kostenträger, für das Team.<br>Diese Software wurde in meiner Freizeit entwickelt, bitte habt Verständnis für Bugs und Geduld für Fixes. Danke! - Euer Mike Wille, SLSE 2016, 17</body></html>").arg(QChar(0x2764)));
|
||||
QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect;
|
||||
shadow->setOffset(0, 0);
|
||||
shadow->setBlurRadius(22);
|
||||
shadow->setColor(QColor("blue"));
|
||||
l->setGraphicsEffect(shadow);
|
||||
b->addWidget(l);
|
||||
w->setLayout(b);
|
||||
|
||||
w->show();
|
||||
}
|
||||
Executable
+68
@@ -0,0 +1,68 @@
|
||||
#pragma once
|
||||
|
||||
#include "LoginWnd.h"
|
||||
#include "WaitWnd.h"
|
||||
#include "QueryThread.h"
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
|
||||
class QListWidgetItem;
|
||||
class Query;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class BrowserWnd;
|
||||
}
|
||||
|
||||
|
||||
class BrowserWnd: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
BrowserWnd();
|
||||
~BrowserWnd();
|
||||
|
||||
/** Must be called *after* the event loop was started, i.e. use QTimer::singleShot(). */
|
||||
void startConnect();
|
||||
|
||||
private:
|
||||
bool test();
|
||||
void endThread();
|
||||
|
||||
void refreshTableList();
|
||||
void selectQuery(QString queryString, Query *query, QString tableName);
|
||||
void addNewQuery(const QString &tableName = QString());
|
||||
|
||||
LoginWnd *m_loginWnd{nullptr};
|
||||
WaitWnd *m_waitWnd{nullptr};
|
||||
Ui::BrowserWnd *m_ui{nullptr};
|
||||
QueryWorker *m_queryWorker{nullptr};
|
||||
QThread *m_queryThread{nullptr};
|
||||
Query *m_waitingQueryWidget{nullptr};
|
||||
int m_newQueryCounter{0};
|
||||
|
||||
private slots:
|
||||
void slotFilterTableList(const QString &filter);
|
||||
void slotFilterTableItemChanged(QListWidgetItem *item);
|
||||
void slotConnectResult(const QString &);
|
||||
void slotNewTableList(QStringList);
|
||||
void slotHeart();
|
||||
|
||||
/*void slotSelectQueryResult(QString errorMsg, DataModel* dataModel);
|
||||
void slotSelectQueryStatus(int percent);
|
||||
void slotQueryQuery(QString); // when the query widget starts a query....*/
|
||||
void slotTabCloseRequested(int);
|
||||
/*void slotExecute(QString, QVariant, QModelIndex);
|
||||
void slotExecuteQueryResult(bool success, QString msg, QVariant val, QModelIndex onThisPosition);*/
|
||||
void slotAddNewQuery();
|
||||
|
||||
|
||||
void slotShowWait(const QString &msg);
|
||||
void slotHideWait();
|
||||
|
||||
signals:
|
||||
void signalConnect(const LoginData &data);
|
||||
void signalGetTableList();
|
||||
};
|
||||
Executable
+50
@@ -0,0 +1,50 @@
|
||||
#
|
||||
# CMakeLists.txt for New SQL Browser
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
# Created by Mike Wille, SLSE, 2016-02-10
|
||||
#
|
||||
|
||||
SET(my_SRCS
|
||||
main.cpp
|
||||
LoginWnd.cpp
|
||||
LoginWnd.h
|
||||
BrowserWnd.cpp
|
||||
BrowserWnd.h
|
||||
WaitWnd.cpp
|
||||
WaitWnd.h
|
||||
Query.cpp
|
||||
Query.h
|
||||
QueryThread.cpp
|
||||
QueryThread.h
|
||||
DataModel.cpp
|
||||
DataModel.h
|
||||
PresetManager.cpp
|
||||
PresetManager.h
|
||||
AddModel.cpp
|
||||
AddModel.h
|
||||
AddLine.cpp
|
||||
AddLine.h
|
||||
)
|
||||
|
||||
SET(my_UICS
|
||||
ui/LoginUi.ui
|
||||
ui/BrowserWndUi.ui
|
||||
ui/WaitWndUi.ui
|
||||
ui/QueryUi.ui
|
||||
ui/AddLinesUi.ui
|
||||
)
|
||||
|
||||
NGL_ADD_TOOL_ICON(my_SRCS "sql")
|
||||
NGL_WRAP_UI(my_SRCS ${my_UICS})
|
||||
NGL_ADD_EXECUTABLE(AAR SV WS NO_TRANSLATION sqlbrowser ${my_SRCS} ${my_UICS})
|
||||
NGL_TARGET_LINK_LIBRARIES(sqlbrowser
|
||||
PUBLIC
|
||||
nglapplication
|
||||
Qt5::Core
|
||||
Qt5::Widgets
|
||||
Qt5::Sql
|
||||
)
|
||||
NGL_INSTALL_TARGET(sqlbrowser)
|
||||
Executable
+217
@@ -0,0 +1,217 @@
|
||||
#include "DataModel.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QColor>
|
||||
#include <QDateTime>
|
||||
#include <QMetaEnum>
|
||||
#include <QMetaObject>
|
||||
#include <QMetaType>
|
||||
|
||||
//#define WAIT_FOR_IDLE while (!m_idle) { QThread::msleep(50); } (void)m_idle
|
||||
|
||||
|
||||
DataModel::DataModel(QObject *parent) // [M]VC
|
||||
: QAbstractTableModel(parent)
|
||||
, m_idle(true)
|
||||
{
|
||||
resetFlags();
|
||||
}
|
||||
|
||||
|
||||
//void DataModel::fillModel(const HeaderList &headerList, const DataList &dataList)
|
||||
//{
|
||||
// beginResetModel();
|
||||
|
||||
// m_headerList = headerList;
|
||||
// m_dataList = dataList;
|
||||
|
||||
// endResetModel();
|
||||
//}
|
||||
|
||||
|
||||
void DataModel::dataListReserve(const int size)
|
||||
{
|
||||
m_newDataList.reserve(size);
|
||||
}
|
||||
|
||||
|
||||
void DataModel::addLine(const Data& data)
|
||||
{
|
||||
m_newDataList.append(data);
|
||||
}
|
||||
|
||||
|
||||
void DataModel::addColumn(const QString& columnName, QVariant::Type type)
|
||||
{
|
||||
// QPair<QString,QVariant::Type> pair;
|
||||
// pair.first = columnName;
|
||||
// pair.second = type;
|
||||
m_newHeaderList.append(QPair<QString,QVariant::Type>(columnName, type));
|
||||
}
|
||||
|
||||
|
||||
void DataModel::slotSwapLists() // for threading..
|
||||
{
|
||||
m_dataList = m_newDataList;
|
||||
m_headerList = m_newHeaderList;
|
||||
|
||||
m_newDataList.clear();
|
||||
m_newHeaderList.clear();
|
||||
|
||||
beginResetModel();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
|
||||
void DataModel::setTableName(const QString &tableName)
|
||||
{
|
||||
m_tableName = tableName;
|
||||
setEditable(!m_tableName.isEmpty()); // editable items depend on wether it's a custom query, or a table list query
|
||||
}
|
||||
|
||||
|
||||
QString DataModel::getTableName() const
|
||||
{
|
||||
return m_tableName;
|
||||
}
|
||||
|
||||
|
||||
int DataModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
return parent.isValid() ? 0 : m_dataList.count();
|
||||
}
|
||||
|
||||
|
||||
int DataModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
return parent.isValid() ? 0 : m_headerList.count();
|
||||
}
|
||||
|
||||
|
||||
QVariant DataModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (index.row() >= m_dataList.count())
|
||||
{
|
||||
//qWarning() << "threading problems.. #1";
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
const Data& row = m_dataList.at(index.row());
|
||||
if (index.column() >= row.count())
|
||||
{
|
||||
//qWarning() << "threading problems.. #2";
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
const QVariant& element = row.at(index.column());
|
||||
|
||||
switch (role)
|
||||
{
|
||||
case Qt::EditRole:
|
||||
case Qt::DisplayRole:
|
||||
return element;
|
||||
|
||||
case Qt::BackgroundRole:
|
||||
if (element.isNull())
|
||||
return QColor::fromRgb(255, 255, 215);
|
||||
return QVariant();
|
||||
|
||||
case Qt::ToolTipRole:
|
||||
if ((element.type() == QVariant::ULongLong || element.type() == QVariant::LongLong)
|
||||
&& element.toLongLong() > 1000000000)
|
||||
return QDateTime::fromMSecsSinceEpoch(element.toLongLong()).toString(QStringLiteral("dd.MM.yyyy hh:mm:ss.zzz"));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
|
||||
QVariant DataModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal && section >= 0 && section < m_headerList.size())
|
||||
{
|
||||
switch (role)
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
return m_headerList.at(section).first;
|
||||
case Qt::ToolTipRole:
|
||||
int type = m_headerList.at(section).second;
|
||||
return QString::fromUtf8(QMetaType::typeName(type));
|
||||
}
|
||||
}
|
||||
|
||||
return QAbstractTableModel::headerData(section, orientation, role);
|
||||
}
|
||||
|
||||
|
||||
void DataModel::setEditable(bool editable)
|
||||
{
|
||||
resetFlags();
|
||||
|
||||
if (editable)
|
||||
m_flags |= Qt::ItemIsEditable;
|
||||
}
|
||||
|
||||
|
||||
const HeaderList& DataModel::getHeaderList() const
|
||||
{
|
||||
return m_headerList;
|
||||
}
|
||||
|
||||
|
||||
void DataModel::resetFlags()
|
||||
{
|
||||
m_flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
|
||||
}
|
||||
|
||||
|
||||
Qt::ItemFlags DataModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
Q_UNUSED(index);
|
||||
|
||||
return m_flags;
|
||||
}
|
||||
|
||||
|
||||
void DataModel::slotSetData(const QModelIndex &index, const QVariant &value)
|
||||
{
|
||||
Data row = m_dataList.at(index.row()); // get row from data list
|
||||
row.replace(index.column(), value); // replace column in row
|
||||
m_dataList.replace(index.row(), row); // replace row in data list
|
||||
|
||||
emit dataChanged(index, index); // tell the view that data has changed and redraw/reget data
|
||||
}
|
||||
|
||||
bool DataModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
if (role != Qt::EditRole)
|
||||
return true;
|
||||
|
||||
// DataModel* => model to write value to on success
|
||||
// QModelIndex => row&col of value to write
|
||||
// QVariant => value to write
|
||||
emit signalSetData(this, index, value);
|
||||
|
||||
return false; // ALWAYS! as we need to wait for a result (which is async)
|
||||
}
|
||||
|
||||
|
||||
void DataModel::deleteLines(const QList<QModelIndex> &affectedRowsList)
|
||||
{
|
||||
if (affectedRowsList.isEmpty())
|
||||
{
|
||||
//qWarning() << "DataModel::deleteLines: !affectedRowsList->count()";
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < affectedRowsList.count(); i++)
|
||||
{
|
||||
const QModelIndex &idx = affectedRowsList.at(i);
|
||||
|
||||
beginRemoveRows(QModelIndex() /* FIXME: ??? */, idx.row(), idx.row());
|
||||
m_dataList.removeAt(idx.row() /* TODO: checks ?? */);
|
||||
endRemoveRows();
|
||||
}
|
||||
}
|
||||
Executable
+62
@@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
|
||||
using Data = QVector<QVariant>;
|
||||
using DataList = QVector<Data>;
|
||||
using HeaderList = QVector<QPair<QString, QVariant::Type>>;
|
||||
|
||||
class DataModel: public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DataModel(QObject* parent = nullptr);
|
||||
|
||||
|
||||
//void fillModel(const HeaderList &headerList, const DataList &dataList);
|
||||
void dataListReserve(const int size);
|
||||
void addLine(const Data& data);
|
||||
void addColumn(const QString& columnName, QVariant::Type type);
|
||||
const HeaderList& getHeaderList() const;
|
||||
|
||||
|
||||
|
||||
void setTableName(const QString& tableName);
|
||||
QString getTableName() const;
|
||||
void setEditable(bool editable);
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
|
||||
|
||||
|
||||
void deleteLines(const QList<QModelIndex> &affectedRowsList);
|
||||
|
||||
private:
|
||||
HeaderList m_headerList;
|
||||
DataList m_dataList;
|
||||
|
||||
// Threading...
|
||||
HeaderList m_newHeaderList;
|
||||
DataList m_newDataList;
|
||||
|
||||
|
||||
QString m_tableName;
|
||||
Qt::ItemFlags m_flags;
|
||||
|
||||
QAtomicInt m_idle;
|
||||
|
||||
void resetFlags();
|
||||
|
||||
|
||||
public slots:
|
||||
void slotSwapLists();
|
||||
void slotSetData(const QModelIndex &index, const QVariant &value);
|
||||
|
||||
signals:
|
||||
void signalSetData(DataModel*, const QModelIndex &, const QVariant &);
|
||||
};
|
||||
Executable
+161
@@ -0,0 +1,161 @@
|
||||
#include "LoginWnd.h"
|
||||
#include "ui_LoginUi.h"
|
||||
|
||||
#include <QGraphicsDropShadowEffect>
|
||||
#include <QFileDialog>
|
||||
#include <QDebug>
|
||||
#include <QSqlDatabase>
|
||||
|
||||
|
||||
LoginWnd::LoginWnd(QWidget *parent)
|
||||
: QDialog(parent)
|
||||
, m_ui(new Ui::LoginWnd)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
connect(m_ui->pbHeart, &QPushButton::clicked,
|
||||
this, &LoginWnd::slotHeart);
|
||||
|
||||
// SQLite:
|
||||
connect(m_ui->pbLoadFile, &QPushButton::clicked, this, &LoginWnd::slotLoadFile);
|
||||
connect(m_ui->tbChooseFile, &QToolButton::clicked, this, &LoginWnd::slotChooseFile);
|
||||
connect(m_ui->pbExit_2, &QPushButton::clicked, this, &LoginWnd::reject);
|
||||
|
||||
// DBMS:
|
||||
connect(m_ui->pbLogin, &QPushButton::clicked, this, &LoginWnd::accept);
|
||||
connect(m_ui->pbExit, &QPushButton::clicked, this, &LoginWnd::reject);
|
||||
|
||||
// Common:
|
||||
connect(m_ui->pbLoad, &QPushButton::clicked, this, &LoginWnd::slotLoadPreset);
|
||||
connect(m_ui->pbSave, &QPushButton::clicked, this, &LoginWnd::slotSavePreset);
|
||||
|
||||
fillPresetComboBox();
|
||||
|
||||
|
||||
// set typical values
|
||||
m_ui->leDatabase->setText(QStringLiteral("lts_ets_pro"));
|
||||
m_ui->leUsername->setText(QStringLiteral("ets_exm"));
|
||||
|
||||
m_ui->leHostname->setPlaceholderText(QStringLiteral("on-site: try 'EXCDBS01'"));
|
||||
|
||||
m_ui->cbDriver->addItems(QSqlDatabase::drivers());
|
||||
const int idx = m_ui->cbDriver->findText(QStringLiteral("QPSQL"));
|
||||
if (idx >= 0)
|
||||
m_ui->cbDriver->setCurrentIndex(idx);
|
||||
}
|
||||
|
||||
LoginWnd::~LoginWnd()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
|
||||
void LoginWnd::slotLoadFile()
|
||||
{
|
||||
if (m_ui->leFilename->text().isEmpty())
|
||||
return;
|
||||
|
||||
accept(); // just to make clear that the user cannot login to a database, so he has to click explicitly on "Load File"
|
||||
}
|
||||
|
||||
|
||||
void LoginWnd::slotChooseFile()
|
||||
{
|
||||
QString fileName = QFileDialog::getOpenFileName(this, tr("Select File-based Database"),
|
||||
QString(), // last wd
|
||||
tr("All Files (*.*)"));
|
||||
|
||||
if (fileName.isEmpty())
|
||||
return;
|
||||
|
||||
m_ui->leFilename->setText(fileName);
|
||||
}
|
||||
|
||||
|
||||
void LoginWnd::fillPresetComboBox()
|
||||
{
|
||||
m_ui->cbPresets->clear();
|
||||
|
||||
const PresetManager::PresetList &presetList = presetManager.getPresetList();
|
||||
|
||||
for (const Preset &preset : qAsConst(presetList))
|
||||
m_ui->cbPresets->addItem(preset.name);
|
||||
|
||||
if (!presetList.isEmpty())
|
||||
{
|
||||
setDefaultLoginData(presetList.first().loginData);
|
||||
m_ui->cbPresets->setCurrentIndex(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LoginWnd::slotLoadPreset()
|
||||
{
|
||||
setDefaultLoginData(presetManager.getPresetList().at(m_ui->cbPresets->currentIndex()).loginData);
|
||||
}
|
||||
|
||||
void LoginWnd::slotSavePreset()
|
||||
{
|
||||
presetManager.savePreset(getLoginData(), this);
|
||||
|
||||
fillPresetComboBox();
|
||||
setDefaultLoginData(presetManager.getPresetList().at(m_ui->cbPresets->count()-1).loginData); // set default to last (new) preset
|
||||
m_ui->cbPresets->setCurrentIndex(m_ui->cbPresets->count()-1); // set index to last (new) preset
|
||||
}
|
||||
|
||||
|
||||
void LoginWnd::setDefaultLoginData(const LoginData &defaultLoginData)
|
||||
{
|
||||
if (!defaultLoginData.filename.isEmpty()) // no username, etc needed if that's a file
|
||||
{
|
||||
m_ui->leFilename->setText(defaultLoginData.filename);
|
||||
m_ui->leDatabase->setText(QString());
|
||||
m_ui->leUsername->setText(QString());
|
||||
m_ui->lePassword->setText(QString());
|
||||
m_ui->leHostname->setText(QString());
|
||||
m_ui->sbPort->setValue(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ui->leFilename->setText(QString());
|
||||
m_ui->leDatabase->setText(defaultLoginData.database);
|
||||
m_ui->leUsername->setText(defaultLoginData.username);
|
||||
m_ui->lePassword->setText(defaultLoginData.password);
|
||||
m_ui->leHostname->setText(defaultLoginData.hostname);
|
||||
m_ui->cbDriver->setCurrentIndex(m_ui->cbDriver->findText(defaultLoginData.driver));
|
||||
m_ui->sbPort->setValue(defaultLoginData.port);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LoginData LoginWnd::getLoginData() const
|
||||
{
|
||||
LoginData ld;
|
||||
|
||||
ld.driver = m_ui->cbDriver->currentText();
|
||||
ld.database = m_ui->leDatabase->text();
|
||||
ld.username = m_ui->leUsername->text();
|
||||
ld.password = m_ui->lePassword->text();
|
||||
ld.hostname = m_ui->leHostname->text();
|
||||
ld.port = m_ui->sbPort->value();
|
||||
ld.filename = m_ui->leFilename->text();
|
||||
|
||||
return ld;
|
||||
}
|
||||
|
||||
void LoginWnd::slotHeart()
|
||||
{
|
||||
QWidget* w = new QWidget;
|
||||
w->setAttribute(Qt::WA_DeleteOnClose); // delete when closed
|
||||
QVBoxLayout* b = new QVBoxLayout;
|
||||
QLabel* l = new QLabel(QStringLiteral("<html><body>Geschmiedet mit %1 , ohne Kostenträger, für das Team.<br>Diese Software wurde in meiner Freizeit entwickelt, bitte habt Verständnis für Bugs und Geduld für Fixes. Danke! - Euer Mike Wille, SLSE 2016, 17</body></html>").arg(QChar(0x2764)));
|
||||
QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect;
|
||||
shadow->setOffset(0,0);
|
||||
shadow->setBlurRadius(22);
|
||||
shadow->setColor(QColor("blue"));
|
||||
l->setGraphicsEffect(shadow);
|
||||
b->addWidget(l);
|
||||
w->setLayout(b);
|
||||
|
||||
w->show();
|
||||
}
|
||||
Executable
+35
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include "PresetManager.h"
|
||||
#include <QDialog>
|
||||
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class LoginWnd;
|
||||
}
|
||||
|
||||
class LoginWnd : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LoginWnd(QWidget *parent);
|
||||
~LoginWnd();
|
||||
|
||||
LoginData getLoginData() const;
|
||||
void setDefaultLoginData(const LoginData &defaultLoginData);
|
||||
private:
|
||||
Ui::LoginWnd* m_ui;
|
||||
PresetManager presetManager;
|
||||
|
||||
void fillPresetComboBox();
|
||||
|
||||
private slots:
|
||||
void slotLoadFile();
|
||||
void slotChooseFile();
|
||||
void slotHeart();
|
||||
|
||||
void slotLoadPreset();
|
||||
void slotSavePreset();
|
||||
};
|
||||
Executable
+187
@@ -0,0 +1,187 @@
|
||||
#include "PresetManager.h"
|
||||
|
||||
#include <QInputDialog>
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
static QString newLine(QStringLiteral("\r\n"));
|
||||
#else
|
||||
static QString newLine(QStringLiteral("\n"));
|
||||
#endif
|
||||
|
||||
PresetManager::PresetManager()
|
||||
: QObject()
|
||||
{
|
||||
QString filename(QStringLiteral("%1.conf").arg(QApplication::arguments().at(0)));
|
||||
file.setFileName(filename);
|
||||
|
||||
bool goCreateFile = false;
|
||||
if (!file.exists())
|
||||
{
|
||||
goCreateFile = true;
|
||||
}
|
||||
|
||||
if (!file.open(QIODevice::ReadWrite))
|
||||
{
|
||||
//qWarning() << "cannot read/write conf file! ("<<filename<<")";
|
||||
return;
|
||||
}
|
||||
|
||||
if (goCreateFile)
|
||||
{
|
||||
addDefaultPreset();
|
||||
createFile();
|
||||
savePresets(); // add default preset to new file
|
||||
}
|
||||
|
||||
// read file...
|
||||
QString presetString(QString::fromUtf8(file.readLine(32000)));
|
||||
while (!presetString.isEmpty())
|
||||
{
|
||||
if (presetString.endsWith(newLine))
|
||||
{
|
||||
presetString.truncate(presetString.length() - newLine.length());
|
||||
}
|
||||
|
||||
if (presetString.at(0) == QLatin1Char('#')) // allow comments
|
||||
{
|
||||
//qWarning() << "line is comment line! next line..";
|
||||
presetString = QString::fromUtf8(file.readLine(32000));
|
||||
continue;
|
||||
}
|
||||
|
||||
QStringList presetStringList = presetString.split(QStringLiteral(":"));
|
||||
|
||||
if (presetStringList.count() != 2)
|
||||
{
|
||||
//qWarning() << "line ded! next line..";
|
||||
presetString = QString::fromUtf8(file.readLine(32000));
|
||||
continue;
|
||||
}
|
||||
|
||||
Preset preset;
|
||||
preset.name = presetStringList.at(0);
|
||||
|
||||
QStringList presetValueList = presetStringList.at(1).split(QStringLiteral(","));
|
||||
|
||||
if (presetValueList.count() < 5) // port is optional, as there is a default port !!
|
||||
{
|
||||
//qWarning() << "too few valz! next line..";
|
||||
presetString = QString::fromUtf8(file.readLine(32000));
|
||||
continue;
|
||||
}
|
||||
|
||||
preset.loginData.database = presetValueList.at(0);
|
||||
preset.loginData.username = presetValueList.at(1);
|
||||
preset.loginData.password = presetValueList.at(2);
|
||||
preset.loginData.hostname = presetValueList.at(3);
|
||||
preset.loginData.driver = presetValueList.at(4);
|
||||
|
||||
if (presetValueList.count() > 5) // is there a port?
|
||||
preset.loginData.port = presetValueList.at(5).toInt();
|
||||
|
||||
// keep compatibility
|
||||
if (presetValueList.count() > 6) // is there a filename?
|
||||
preset.loginData.filename = presetValueList.at(6);
|
||||
|
||||
presetList.append(preset);
|
||||
presetString = QString::fromUtf8(file.readLine(32000));
|
||||
}
|
||||
}
|
||||
|
||||
const PresetManager::PresetList &PresetManager::getPresetList() const
|
||||
{
|
||||
return presetList;
|
||||
}
|
||||
|
||||
|
||||
void PresetManager::savePreset(const LoginData &loginData, QWidget* parent)
|
||||
{
|
||||
bool ok;
|
||||
QString presetName = QInputDialog::getText(parent, tr("Save new Preset as.."),
|
||||
tr("Preset name:"), QLineEdit::Normal,
|
||||
QString(), &ok);
|
||||
|
||||
if (!ok || presetName.isEmpty())
|
||||
{
|
||||
//qWarning() << "doin nothin";
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < presetList.size(); ++i)
|
||||
{
|
||||
if (presetList.at(i).name == presetName)
|
||||
{
|
||||
presetList.removeAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Preset preset;
|
||||
preset.name = presetName;
|
||||
preset.loginData = loginData;
|
||||
presetList.append(preset);
|
||||
|
||||
savePresets();
|
||||
}
|
||||
|
||||
|
||||
void PresetManager::savePresets()
|
||||
{
|
||||
createFile(); // recreate file
|
||||
|
||||
// save all presets to file
|
||||
for (const Preset &preset : qAsConst(presetList))
|
||||
{
|
||||
QString presetString = QStringLiteral("%1:%2%3");
|
||||
|
||||
QStringList presetValueList;
|
||||
|
||||
presetValueList << preset.loginData.database;
|
||||
presetValueList << preset.loginData.username;
|
||||
presetValueList << preset.loginData.password;
|
||||
presetValueList << preset.loginData.hostname;
|
||||
presetValueList << preset.loginData.driver;
|
||||
|
||||
if (preset.loginData.port > -1)
|
||||
presetValueList << QString::number(preset.loginData.port);
|
||||
|
||||
if (!preset.loginData.filename.isEmpty())
|
||||
presetValueList << preset.loginData.filename;
|
||||
|
||||
presetString = presetString.arg(preset.name, presetValueList.join(QLatin1Char(',')), newLine);
|
||||
|
||||
file.write(presetString.toUtf8());
|
||||
}
|
||||
|
||||
file.flush();
|
||||
}
|
||||
|
||||
|
||||
void PresetManager::addDefaultPreset()
|
||||
{
|
||||
Preset defaultPreset;
|
||||
|
||||
//defaultPreset.loginData.database = Settings::databaseName();
|
||||
defaultPreset.loginData.driver = QStringLiteral("PQSQL");
|
||||
defaultPreset.name = defaultPreset.loginData.database;
|
||||
defaultPreset.loginData.username = QStringLiteral("ctc_ws");
|
||||
defaultPreset.loginData.password = QStringLiteral("ctc11de");
|
||||
//defaultPreset.loginData.hostname = Settings::databaseHostname();
|
||||
defaultPreset.loginData.port = -1;
|
||||
// no need to set filename
|
||||
|
||||
presetList.insert(0, defaultPreset); // first item!
|
||||
}
|
||||
|
||||
|
||||
void PresetManager::createFile()
|
||||
{
|
||||
file.resize(0); // clear file
|
||||
file.flush();
|
||||
|
||||
file.write("#<PresetName>:<database><,username><,password><,hostname><,port(optional)><,filename(optional)>");
|
||||
file.write(newLine.toUtf8());
|
||||
file.flush();
|
||||
}
|
||||
Executable
+43
@@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include <QFile>
|
||||
#include <QVector>
|
||||
|
||||
struct LoginData
|
||||
{
|
||||
QString database;
|
||||
QString username;
|
||||
QString password;
|
||||
QString hostname;
|
||||
QString filename;
|
||||
QString driver;
|
||||
|
||||
int port = - 1; // no unsigned short (must contain -1 as default port)
|
||||
};
|
||||
|
||||
struct Preset
|
||||
{
|
||||
QString name;
|
||||
LoginData loginData;
|
||||
};
|
||||
|
||||
|
||||
class PresetManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
using PresetList = QVector<Preset>;
|
||||
|
||||
PresetManager();
|
||||
const PresetList &getPresetList() const;
|
||||
void savePreset(const LoginData &loginData, QWidget *parent);
|
||||
|
||||
private:
|
||||
QFile file;
|
||||
PresetList presetList;
|
||||
|
||||
void createFile();
|
||||
void savePresets();
|
||||
void addDefaultPreset();
|
||||
|
||||
};
|
||||
Executable
+474
@@ -0,0 +1,474 @@
|
||||
#include "ui_QueryUi.h"
|
||||
|
||||
#include "Query.h"
|
||||
#include "QueryThread.h"
|
||||
#include "AddLine.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QFileDialog>
|
||||
#include <QCheckBox>
|
||||
#include <QRadioButton>
|
||||
#include <QDebug>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#define NEWLINE "\r\n"
|
||||
#else
|
||||
#define NEWLINE "\n"
|
||||
#endif
|
||||
|
||||
Query::Query(//const QString &queryString,
|
||||
QueryWorker *queryWorker,
|
||||
QWidget* parent) // MV[C]
|
||||
: QWidget(parent)
|
||||
, m_ui(new Ui::Query)
|
||||
, m_model(new DataModel())
|
||||
, m_queryWorker(queryWorker)
|
||||
, m_addLines(nullptr)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
setCustomQuery(); // for safety, disable table sensitive buttons, until table name is set
|
||||
|
||||
qRegisterMetaType<QList<QModelIndex>>("QList<QModelIndex>");
|
||||
|
||||
|
||||
connect(m_ui->pbQueryDelete, &QPushButton::clicked, this, &Query::onQueryDelete);
|
||||
connect(m_ui->pbQueryInsert, &QPushButton::clicked, this, &Query::onQueryInsert);
|
||||
connect(m_ui->pbQueryUpdate, &QPushButton::clicked, this, &Query::onQueryUpdate);
|
||||
|
||||
// NEW ARCH
|
||||
// Delete Lines
|
||||
connect(this, &Query::signalDeleteLines,
|
||||
queryWorker, &QueryWorker::slotDeleteLines); // request => QueryWorker
|
||||
|
||||
connect(queryWorker, &QueryWorker::signalDeleteLinesResult,
|
||||
this, &Query::slotDeleteLinesResult); // reply => this
|
||||
|
||||
|
||||
// Custom Query
|
||||
connect(this, &Query::signalCustomQuery,
|
||||
queryWorker, &QueryWorker::slotCustomQuery);
|
||||
|
||||
connect(queryWorker, &QueryWorker::signalCustomQueryResult,
|
||||
this, &Query::slotCustomQueryResult);
|
||||
|
||||
|
||||
// Table Query
|
||||
connect(this, &Query::signalTableQuery,
|
||||
queryWorker, &QueryWorker::slotTableQuery);
|
||||
|
||||
connect(queryWorker, &QueryWorker::signalTableQueryResult,
|
||||
this, &Query::slotTableQueryResult);
|
||||
|
||||
|
||||
// Add Lines
|
||||
connect(this, &Query::signalAddLines,
|
||||
queryWorker, &QueryWorker::slotAddLines);
|
||||
|
||||
connect(queryWorker, &QueryWorker::signalAddLinesResult,
|
||||
this, &Query::slotAddLinesResult);
|
||||
|
||||
|
||||
// Set Data
|
||||
connect(m_model, &DataModel::signalSetData, // comes from the model ..
|
||||
this, &Query::slotSetData);
|
||||
|
||||
connect(this, &Query::signalSetData,
|
||||
queryWorker, &QueryWorker::slotSetData);
|
||||
|
||||
connect(queryWorker, &QueryWorker::signalSetDataResult, // .. and comes back to THIS ! (query)
|
||||
this, &Query::slotSetDataResult);
|
||||
|
||||
|
||||
connect(m_ui->pbQuery, &QPushButton::clicked, this, &Query::slotCustomQuery);
|
||||
connect(m_ui->pbAddLine, &QPushButton::clicked, this, &Query::slotStartAddLines);
|
||||
connect(m_ui->pbDeleteLine, &QPushButton::clicked, this, &Query::slotDeleteLine);
|
||||
connect(m_ui->pbReload, &QPushButton::clicked, this, &Query::slotTableQuery);
|
||||
connect(m_ui->pbExport, &QPushButton::clicked, this, &Query::slotExportCSV);
|
||||
|
||||
m_ui->dataTable->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); // TODO: qt4
|
||||
|
||||
setModel();
|
||||
}
|
||||
|
||||
|
||||
Query::~Query()
|
||||
{
|
||||
delete m_ui;
|
||||
delete m_model;
|
||||
}
|
||||
|
||||
|
||||
void Query::slotExportCSV()
|
||||
{
|
||||
//qWarning() << "slotExportCSV";
|
||||
|
||||
QFileDialog dialog(this); // save dialog
|
||||
//dialog.setFileMode(QFileDialog::ExistingFile); // single file selection
|
||||
dialog.setNameFilter(tr("CSV File (*.csv)"));
|
||||
dialog.setAcceptMode(QFileDialog::AcceptSave);
|
||||
|
||||
QStringList fileNames;
|
||||
if (dialog.exec())
|
||||
fileNames = dialog.selectedFiles();
|
||||
|
||||
if (!fileNames.count())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QFile file;
|
||||
file.setFileName(fileNames.at(0));
|
||||
|
||||
if (!file.open(QFile::ReadWrite))
|
||||
{
|
||||
QMessageBox::critical(this, tr("CSV Export Error"), tr("File '%1' is not accessible!").arg(fileNames.at(0)));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// file is open, now save to csv file
|
||||
int colCount = m_model->columnCount();
|
||||
|
||||
// get column names
|
||||
QStringList columnNames;
|
||||
columnNames.reserve(colCount);
|
||||
|
||||
for (int i = 0; i < colCount; i++)
|
||||
{
|
||||
columnNames.append(m_model->headerData(i, Qt::Horizontal).toString());
|
||||
}
|
||||
|
||||
|
||||
// get rows & row values
|
||||
QStringList rows;
|
||||
int rowsCount = m_sortModel.rowCount();
|
||||
rows.reserve(rowsCount);
|
||||
|
||||
QStringList rowData;
|
||||
for (int row = 0; row < rowsCount; row++)
|
||||
{
|
||||
// get row's values
|
||||
rowData.clear();
|
||||
|
||||
for (int col = 0; col < colCount; col++)
|
||||
{
|
||||
rowData.append(m_sortModel.data(m_sortModel.index(row, col)).toString());
|
||||
}
|
||||
|
||||
rows.append(rowData.join(QLatin1Char(',')));
|
||||
}
|
||||
|
||||
|
||||
file.write(columnNames.join(QLatin1Char(',')).toUtf8()); // write header
|
||||
file.write(NEWLINE);
|
||||
|
||||
for (const QString &row : qAsConst(rows))
|
||||
{
|
||||
file.write(row.toUtf8());
|
||||
file.write(NEWLINE);
|
||||
}
|
||||
|
||||
file.close();
|
||||
|
||||
QMessageBox::information(this, tr("CSV Export Success"), tr("CSV Export was successful"));
|
||||
}
|
||||
|
||||
void Query::onQueryDelete()
|
||||
{
|
||||
m_ui->queryText->setText(tr("DELETE FROM %1 WHERE %2").arg(m_model->getTableName(), m_idInWhere ? QStringLiteral("id = ") : QString()));
|
||||
}
|
||||
|
||||
void Query::onQueryInsert()
|
||||
{
|
||||
m_ui->queryText->setText(tr("INSERT INTO %1 (%2) VALUES ()").arg(m_model->getTableName(), checkedColumnsNames().join(QStringLiteral(", "))));
|
||||
}
|
||||
|
||||
void Query::onQueryUpdate()
|
||||
{
|
||||
const QStringList sl = checkedColumnsNames();
|
||||
QStringList sl2;
|
||||
sl2.reserve(sl.size());
|
||||
for (const QString &s : sl)
|
||||
sl2.append(tr("%1 = ").arg(s));
|
||||
m_ui->queryText->setText(tr("UPDATE %1 SET %2 WHERE %3").arg(m_model->getTableName(), sl2.join(QStringLiteral(", ")), m_idInWhere ? QStringLiteral("id = ") : QString()));
|
||||
}
|
||||
|
||||
void Query::handleError(const QString &errorText)
|
||||
{
|
||||
emit signalHideWait();
|
||||
|
||||
if (errorText.isEmpty())
|
||||
return; // nothing to handle
|
||||
|
||||
QMessageBox::critical(this, tr("Error while executing query"),
|
||||
tr("There was an error executing the query:\n%1").arg(errorText));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Delete Lines
|
||||
void Query::slotDeleteLine() // called from UI
|
||||
{
|
||||
int result = QMessageBox::question(this, tr("SqlBrowser"),
|
||||
tr("Do you really want to delete selected data?"),
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
|
||||
if (result == QMessageBox::No)
|
||||
return;
|
||||
|
||||
emit signalShowWait(QStringLiteral("Deleting line(s).."));
|
||||
|
||||
const QModelIndexList unmapped = m_ui->dataTable->selectionModel()->selectedRows();
|
||||
QModelIndexList mapped;
|
||||
mapped.reserve(unmapped.size());
|
||||
|
||||
for (const auto &idx : unmapped)
|
||||
mapped.append(m_sortModel.mapToSource(idx));
|
||||
|
||||
emit signalDeleteLines(this, mapped, m_model); // => QueryWorker
|
||||
}
|
||||
|
||||
|
||||
void Query::slotDeleteLinesResult(Query* caller, int affectedRowsCount, QString errorText, const QList<QModelIndex> &affectedRowsList) // => from QueryWorker
|
||||
{
|
||||
if (caller != this)
|
||||
return;
|
||||
|
||||
if (errorText.isEmpty() && !affectedRowsCount) // no error but no rows affected?
|
||||
{
|
||||
errorText = tr("The row to be deleted could not be found - This is probably a type-conversion error! Please report that to Mike");
|
||||
}
|
||||
|
||||
handleError(errorText);
|
||||
|
||||
//qWarning() << "Query::slotDeleteLinesResult: errorText = " << errorText << "affectedRowsCount = " << affectedRowsCount;
|
||||
|
||||
if (affectedRowsCount == affectedRowsList.count())
|
||||
{
|
||||
m_model->deleteLines(affectedRowsList); // tell the model to delete that rows (and tell the view about it)
|
||||
}
|
||||
}
|
||||
|
||||
// Custom Query
|
||||
void Query::slotCustomQuery()
|
||||
{
|
||||
emit signalShowWait(QStringLiteral("Executing query.."));
|
||||
emit signalCustomQuery(this, m_ui->queryText->document()->toPlainText(), m_model);
|
||||
}
|
||||
|
||||
|
||||
void Query::slotCustomQueryResult(Query* caller, const QString &errorText)
|
||||
{
|
||||
if (caller != this)
|
||||
return;
|
||||
|
||||
setCustomQuery();
|
||||
|
||||
handleError(errorText);
|
||||
|
||||
//qWarning() << "Query::slotCustomQueryResult: errorText = " << errorText;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Table Query
|
||||
void Query::slotTableQuery()
|
||||
{
|
||||
emit signalShowWait(QStringLiteral("Getting table data .."));
|
||||
//qWarning() << "Query: model" << m_model;
|
||||
emit signalTableQuery(this, m_model);
|
||||
}
|
||||
|
||||
void Query::slotTableQueryResult(Query* caller, const QString &errorText)
|
||||
{
|
||||
if (caller != this)
|
||||
return;
|
||||
|
||||
handleError(errorText);
|
||||
|
||||
// Don't put it in twice
|
||||
if (!m_checkboxes.isEmpty())
|
||||
return;
|
||||
|
||||
for(const auto &item : m_model->getHeaderList())
|
||||
{
|
||||
QCheckBox *cb = new QCheckBox(item.first, this);
|
||||
m_ui->checkboxes->addWidget(cb);
|
||||
m_checkboxes << cb;
|
||||
|
||||
if (item.first.compare(QStringLiteral("id"), Qt::CaseInsensitive) != 0)
|
||||
continue;
|
||||
|
||||
// Only for ID:
|
||||
QRadioButton *rbwhere = new QRadioButton(tr("in WHERE"), this);
|
||||
m_ui->checkboxes->addWidget(rbwhere);
|
||||
QRadioButton *rbnormal = new QRadioButton(tr("normal"), this);
|
||||
m_ui->checkboxes->addWidget(rbnormal);
|
||||
|
||||
rbnormal->setEnabled(cb->isChecked());
|
||||
rbwhere->setEnabled(cb->isChecked());
|
||||
|
||||
connect(cb, &QCheckBox::toggled, rbwhere, &QRadioButton::setEnabled);
|
||||
connect(cb, &QCheckBox::toggled, rbnormal, &QRadioButton::setEnabled);
|
||||
connect(rbwhere, &QRadioButton::toggled, this, [this, rbwhere, cb] { m_idInWhere = rbwhere->isChecked() && cb->isChecked(); });
|
||||
connect(cb, &QRadioButton::toggled, this, [this, rbwhere, cb] { m_idInWhere = rbwhere->isChecked() && cb->isChecked(); });
|
||||
|
||||
rbwhere->setChecked(true);
|
||||
}
|
||||
m_ui->checkboxes->addItem(new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum));
|
||||
//qWarning() << "Query::slotTableQueryResult: errorText = " << errorText;
|
||||
}
|
||||
|
||||
QStringList Query::checkedColumnsNames() const
|
||||
{
|
||||
QStringList sl;
|
||||
for(const auto &cb : m_checkboxes)
|
||||
{
|
||||
if (cb->isChecked())
|
||||
{
|
||||
if ((cb->text().compare(QStringLiteral("id"), Qt::CaseInsensitive) == 0) && m_idInWhere)
|
||||
continue;
|
||||
sl << cb->text();
|
||||
}
|
||||
}
|
||||
return sl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Add Lines
|
||||
void Query::slotStartAddLines()
|
||||
{
|
||||
if (!m_addLines)
|
||||
{
|
||||
m_addLines = new AddLines(this);
|
||||
|
||||
connect(m_addLines, &AddLines::signalAddLines,
|
||||
this, &Query::slotAddLines);
|
||||
|
||||
m_addLines->copyDataFromModel(m_model);
|
||||
}
|
||||
|
||||
m_addLines->show();
|
||||
}
|
||||
|
||||
|
||||
void Query::slotAddLines(AddModel *model)
|
||||
{
|
||||
emit signalShowWait(QStringLiteral("Adding line(s).."));
|
||||
emit signalAddLines(this, model);
|
||||
}
|
||||
|
||||
|
||||
void Query::slotAddLinesResult(Query* caller, int , const QString &errorText)
|
||||
{
|
||||
if (caller != this)
|
||||
return;
|
||||
|
||||
handleError(errorText);
|
||||
|
||||
//qWarning() << "Query::slotAddLinesResult: affectedRows = " << affectedRows << "errorText = " << errorText;
|
||||
|
||||
if (errorText.isEmpty()) // no error
|
||||
{
|
||||
// if (affectedRows) // only get new data when something changed
|
||||
// {
|
||||
// emit signalTableQuery(m_model); // re-get table!
|
||||
// }
|
||||
|
||||
m_addLines->deleteLater(); // done, close add lines window and delete it..
|
||||
m_addLines = nullptr;
|
||||
|
||||
emit signalTableQuery(this, m_model); // get fresh data from db
|
||||
}
|
||||
else // error
|
||||
{
|
||||
if (!m_addLines) // FIXME: needed! but not logically needed ;) what's going on here?
|
||||
{
|
||||
//qWarning() << "Query::slotAddLinesResult: !m_addLines";
|
||||
}
|
||||
else
|
||||
m_addLines->show(); // show again, error!
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Set Data
|
||||
void Query::slotSetData(DataModel* model, const QModelIndex &index, const QVariant &val)
|
||||
{
|
||||
int result = QMessageBox::question(this, tr("SqlBrowser"),
|
||||
tr("Do you really want to change the data?"),
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
|
||||
if (result == QMessageBox::No)
|
||||
return;
|
||||
|
||||
emit signalShowWait(QStringLiteral("Setting data.."));
|
||||
emit signalSetData(this, model, index, val);
|
||||
}
|
||||
|
||||
|
||||
void Query::slotSetDataResult(Query* caller, const QString &errorText)
|
||||
{
|
||||
if (caller != this)
|
||||
return;
|
||||
|
||||
handleError(errorText);
|
||||
|
||||
//qWarning() << "Query::slotSetDataResult: errorText =" << errorText;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Query::setTable(const QString &tableName)
|
||||
{
|
||||
emit signalShowWait(QStringLiteral("Updating value.."));
|
||||
|
||||
if (tableName.isEmpty())
|
||||
{
|
||||
//qWarning() << "Query::setTable: tableName.isEmpty()";
|
||||
return;
|
||||
}
|
||||
|
||||
m_model->setTableName(tableName);
|
||||
|
||||
setTableQuery();
|
||||
|
||||
slotTableQuery();
|
||||
}
|
||||
|
||||
|
||||
void Query::setModel()
|
||||
{
|
||||
m_sortModel.setSourceModel(m_model);
|
||||
m_ui->dataTable->setModel(/*(QAbstractTableModel*)*/&m_sortModel);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Query::setCustomQuery() // cannot add/delete/reload
|
||||
{
|
||||
m_ui->pbAddLine->setEnabled(false);
|
||||
m_ui->pbDeleteLine->setEnabled(false);
|
||||
m_ui->pbReload->setEnabled(false);
|
||||
}
|
||||
|
||||
|
||||
void Query::setTableQuery() // cannot add/delete/reload
|
||||
{
|
||||
m_ui->pbAddLine->setEnabled(true);
|
||||
m_ui->pbDeleteLine->setEnabled(true);
|
||||
m_ui->pbReload->setEnabled(true);
|
||||
}
|
||||
|
||||
Executable
+105
@@ -0,0 +1,105 @@
|
||||
#pragma once
|
||||
|
||||
#include "DataModel.h"
|
||||
#include "AddModel.h"
|
||||
#include "AddLine.h"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QList>
|
||||
#include <QSet>
|
||||
#include <QModelIndex>
|
||||
|
||||
class QueryWorker;
|
||||
class QCheckBox;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class Query;
|
||||
}
|
||||
|
||||
|
||||
class Query: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Query(QueryWorker* queryWorker, QWidget *parent = nullptr);
|
||||
~Query();
|
||||
|
||||
void setTable(const QString& tableName); // get's data from specified table and shows it in the data view
|
||||
|
||||
void setModel();
|
||||
void refreshData(QVariant val, QModelIndex onThisPosition);
|
||||
void handleError(const QString &errorText);
|
||||
|
||||
private:
|
||||
Ui::Query* m_ui;
|
||||
DataModel* m_model;
|
||||
QSortFilterProxyModel m_sortModel;
|
||||
QueryWorker* m_queryWorker;
|
||||
AddLines* m_addLines; // need access to add lines for show/hide/close.....
|
||||
QSet<QCheckBox *> m_checkboxes;
|
||||
bool m_idInWhere;
|
||||
|
||||
void setCustomQuery(); // cannot add/delete/reload
|
||||
void setTableQuery(); // can add/delete/reload
|
||||
|
||||
QStringList checkedColumnsNames() const;
|
||||
signals:
|
||||
void signalShowWait(const QString &msg);
|
||||
void signalHideWait();
|
||||
|
||||
private slots:
|
||||
void slotExportCSV();
|
||||
void onQueryDelete();
|
||||
void onQueryInsert();
|
||||
void onQueryUpdate();
|
||||
|
||||
// new architecture
|
||||
|
||||
// Delete Line(s)
|
||||
signals:
|
||||
void signalDeleteLines(Query* caller, const QList<QModelIndex> &, DataModel*);
|
||||
|
||||
private slots:
|
||||
void slotDeleteLine();
|
||||
void slotDeleteLinesResult(Query* caller, int affectedRowsCount, QString errorText, const QList<QModelIndex> &affectedRowsList);
|
||||
|
||||
|
||||
// Custom Query
|
||||
signals:
|
||||
void signalCustomQuery(Query* caller, const QString &, DataModel*);
|
||||
|
||||
private slots:
|
||||
void slotCustomQuery();
|
||||
void slotCustomQueryResult(Query* caller, const QString &errorText);
|
||||
|
||||
|
||||
// Table Query
|
||||
signals:
|
||||
void signalTableQuery(Query* caller, DataModel*);
|
||||
|
||||
private slots:
|
||||
void slotTableQuery();
|
||||
void slotTableQueryResult(Query* caller, const QString &errorText);
|
||||
|
||||
|
||||
// Add Line
|
||||
signals:
|
||||
void signalAddLines(Query* caller, AddModel*);
|
||||
|
||||
private slots:
|
||||
void slotStartAddLines();
|
||||
void slotAddLines(AddModel*);
|
||||
void slotAddLinesResult(Query* caller, int affectedRows, const QString &errorText);
|
||||
|
||||
|
||||
// Set Data
|
||||
signals:
|
||||
void signalSetData(Query* caller, DataModel *model, const QModelIndex &index, const QVariant &val);
|
||||
|
||||
private slots:
|
||||
void slotSetData(DataModel* model, const QModelIndex &index, const QVariant &val);
|
||||
void slotSetDataResult(Query* caller, const QString &errorText);
|
||||
};
|
||||
Executable
+510
@@ -0,0 +1,510 @@
|
||||
#include "QueryThread.h"
|
||||
#include "DataModel.h"
|
||||
#include "AddModel.h"
|
||||
|
||||
#include <QSqlDatabase>
|
||||
#include <QSqlError>
|
||||
#include <QSqlField>
|
||||
#include <QSqlQuery>
|
||||
#include <QSqlRecord>
|
||||
#include <QDebug>
|
||||
|
||||
// uncomment next line to unarm the delete method - delete method does actually not delete content
|
||||
//#define UNARMED
|
||||
const char browserName[] = "SQLBrowser";
|
||||
const char driverName[] = "QSQLITE";
|
||||
|
||||
|
||||
|
||||
QueryWorker::QueryWorker()
|
||||
: m_dy(false)
|
||||
, m_idle(true)
|
||||
{
|
||||
//qWarning() << "QueryWorker";
|
||||
//test.dummy();
|
||||
}
|
||||
|
||||
|
||||
QueryWorker::~QueryWorker()
|
||||
{
|
||||
//qWarning() << "~QueryWorker";
|
||||
m_idle = true;
|
||||
m_sqlDB.close();
|
||||
//QSqlDatabase::removeDatabase(BROWSER_NAME);
|
||||
}
|
||||
|
||||
|
||||
void QueryWorker::slotGetTableList()
|
||||
{
|
||||
m_idle = false;
|
||||
|
||||
if (m_sqlDB.isOpen())
|
||||
{
|
||||
QStringList tables = m_sqlDB.tables();
|
||||
tables.append(m_sqlDB.tables(QSql::Views));
|
||||
tables.sort();
|
||||
|
||||
emit signalNewTableList(tables);
|
||||
}
|
||||
else
|
||||
{
|
||||
//qWarning() << "mep...";
|
||||
}
|
||||
|
||||
m_idle = true;
|
||||
}
|
||||
|
||||
|
||||
void QueryWorker::slotConnectIt(const LoginData &loginData)
|
||||
{
|
||||
m_idle = false;
|
||||
|
||||
// SQLite
|
||||
if (!loginData.filename.isEmpty())
|
||||
{
|
||||
m_sqlDB = QSqlDatabase::addDatabase(QLatin1String(driverName), QLatin1String(browserName));
|
||||
m_sqlDB.setDatabaseName(loginData.filename);
|
||||
}
|
||||
else // DBMS
|
||||
{
|
||||
// CONNECT & TEST
|
||||
m_sqlDB = QSqlDatabase::addDatabase(loginData.driver, QLatin1String(browserName));
|
||||
m_sqlDB.setDatabaseName(loginData.database);
|
||||
m_sqlDB.setHostName(loginData.hostname);
|
||||
m_sqlDB.setPort(loginData.port);
|
||||
m_sqlDB.setUserName(loginData.username);
|
||||
m_sqlDB.setPassword(loginData.password);
|
||||
}
|
||||
|
||||
if (!m_sqlDB.open())
|
||||
{
|
||||
emit signalConnectResult(m_sqlDB.lastError().text());
|
||||
}
|
||||
else
|
||||
{
|
||||
emit signalConnectResult(QString()); // connected!
|
||||
}
|
||||
|
||||
m_idle = true;
|
||||
}
|
||||
|
||||
|
||||
void QueryWorker::slotDeleteLines(Query* caller, const QList<QModelIndex> &selectedRows, DataModel* dataModel)
|
||||
{
|
||||
m_idle = false;
|
||||
|
||||
if (dataModel->getTableName().isEmpty())
|
||||
{
|
||||
emit signalDeleteLinesResult(caller, 0, QStringLiteral("This is a custom query"), QList<QModelIndex>());
|
||||
m_idle = true;
|
||||
return;
|
||||
}
|
||||
|
||||
QString deleteStatement(QStringLiteral("DELETE FROM %1 WHERE %2"));
|
||||
|
||||
if (!selectedRows.count())
|
||||
{
|
||||
emit signalDeleteLinesResult(caller, 0, QStringLiteral("No line(s) selected to delete"), QList<QModelIndex>());
|
||||
m_idle = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// DELETE FROM table_name WHERE (x1=1 AND x2=2) OR (x1=2 AND x=3)
|
||||
|
||||
QStringList rows; // (x1=1 AND x2=2) (x1=2 AND x2=3) - join with "AND" !
|
||||
|
||||
rows.reserve(selectedRows.size());
|
||||
for (int rowIterator = 0; rowIterator < selectedRows.count(); rowIterator++)
|
||||
{
|
||||
QStringList whereStatements;
|
||||
int columnCount = dataModel->columnCount();
|
||||
whereStatements.reserve(columnCount);
|
||||
int row = selectedRows.at(rowIterator).row();
|
||||
|
||||
//qWarning() << "row" << row;
|
||||
|
||||
for (int column = 0; column < columnCount; column++)
|
||||
{
|
||||
//qWarning() << "col" << column;
|
||||
|
||||
QVariant var = dataModel->data(dataModel->index(row, column), Qt::DisplayRole);
|
||||
QString value = valueToSqlString(var.toString(), dataModel->getHeaderList(), column);
|
||||
|
||||
QStringList whereStatement;
|
||||
whereStatement.reserve(2);
|
||||
|
||||
whereStatement.append(dataModel->headerData(column, Qt::Horizontal, Qt::DisplayRole).toString()); // column name
|
||||
whereStatement.append(value);
|
||||
|
||||
if (value == QStringLiteral("NULL"))
|
||||
whereStatements.append(whereStatement.join(QStringLiteral(" IS "))); // >>> column_name = %value% <<<
|
||||
else
|
||||
whereStatements.append(whereStatement.join(QStringLiteral("="))); // >>> column_name IS NULL <<<
|
||||
}
|
||||
|
||||
QString rowText(QStringLiteral("(%1)").arg(whereStatements.join(QStringLiteral(" AND "))));
|
||||
rows.append(rowText); // >>> column_name1 = 'value1' AND column_name2 = 'value2' <<<
|
||||
}
|
||||
|
||||
|
||||
deleteStatement = deleteStatement.arg(dataModel->getTableName(), rows.join(QStringLiteral(" OR ")));
|
||||
|
||||
qWarning() << "OKAY! my statement = >>>" << deleteStatement;
|
||||
|
||||
|
||||
|
||||
int rowsAffected = -1;
|
||||
emit signalDeleteLinesResult(caller, rowsAffected,
|
||||
#ifdef UNARMED
|
||||
QString(),
|
||||
#else
|
||||
executeQuery(&rowsAffected, deleteStatement),
|
||||
#endif
|
||||
selectedRows);
|
||||
|
||||
m_idle = true;
|
||||
}
|
||||
|
||||
|
||||
QString QueryWorker::selectQuery(const QString &queryString, DataModel* dataModel)
|
||||
{
|
||||
m_idle = false;
|
||||
|
||||
QString result;
|
||||
|
||||
QSqlQuery q(m_sqlDB);
|
||||
|
||||
if (q.exec(queryString) && !m_dy) // execute query first..
|
||||
{
|
||||
// header
|
||||
//HeaderList headerList;
|
||||
|
||||
const auto record = q.record();
|
||||
int querySize = q.size(); // aka rows
|
||||
int recordCount = record.count(); // aka columns
|
||||
|
||||
int statusStep = querySize / 100;
|
||||
int statusCurrent = 0; // NOT in percent! (maximum = querySize)
|
||||
int statusPercent = 0; // 0 - 100
|
||||
|
||||
// TODO: let's ignore the pk autoincrement first...
|
||||
//qWarning() << "primaryIndex" << m_sqlDB.primaryIndex(dataModel->getTableName());
|
||||
//q.record().field(i).setAutoValue(true);
|
||||
|
||||
|
||||
for (int i = 0; i < recordCount; i++)
|
||||
{
|
||||
dataModel->addColumn(record.fieldName(i), record.field(i).type());
|
||||
|
||||
if (m_dy) break;
|
||||
}
|
||||
|
||||
|
||||
// data
|
||||
//DataList dataList;
|
||||
dataModel->dataListReserve(querySize); // speedup
|
||||
|
||||
Data data;
|
||||
data.reserve(recordCount);
|
||||
while (q.next() && !m_dy)
|
||||
{
|
||||
if (statusCurrent >= statusStep)
|
||||
{
|
||||
statusPercent++;
|
||||
statusCurrent = 0;
|
||||
emit signalSelectQueryStatus(statusPercent);
|
||||
}
|
||||
statusCurrent++;
|
||||
|
||||
data.clear();
|
||||
|
||||
for (int i = 0; i < recordCount; i++)
|
||||
data.append(q.value(i));
|
||||
|
||||
dataModel->addLine(data);
|
||||
}
|
||||
|
||||
|
||||
// done reading, create model
|
||||
//DataModel* dataModel = 0;
|
||||
if (!m_dy)
|
||||
{
|
||||
// resultHeaderList = headerList;
|
||||
// resultDataList = dataList;
|
||||
|
||||
connect(this, &QueryWorker::signalSwapModelData,
|
||||
dataModel, &DataModel::slotSwapLists);
|
||||
|
||||
emit signalSwapModelData(); // single shot.... for threading
|
||||
|
||||
disconnect(this, &QueryWorker::signalSwapModelData,
|
||||
dataModel, &DataModel::slotSwapLists);
|
||||
|
||||
//qWarning() << "QueryThread: headerList.count()" << headerList->count();
|
||||
//qWarning() << "QueryThread: dataList.count()" << dataList->count();
|
||||
}
|
||||
}
|
||||
else // query failed
|
||||
{
|
||||
if (!m_dy) // only an error when not dying
|
||||
{
|
||||
result = /*
|
||||
emit signalSelectQueryResult(*/q.lastError().text()/*, 0)*/; // TODO: respect qt4 return invalid pointer
|
||||
}
|
||||
}
|
||||
|
||||
m_idle = true;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void QueryWorker::slotSetData(Query* caller, DataModel* model, const QModelIndex &index, const QVariant &value)
|
||||
{
|
||||
// TODO: use executeQuery here!
|
||||
|
||||
m_idle = false;
|
||||
|
||||
QString queryString(QStringLiteral("UPDATE %1 SET %2=%3 WHERE %4"));
|
||||
|
||||
int row = index.row();
|
||||
|
||||
/* %1 */ QString tableName = model->getTableName();
|
||||
|
||||
if (tableName.isEmpty())
|
||||
{
|
||||
emit signalSetDataResult(caller, QStringLiteral("This is a custom query"));
|
||||
m_idle = true;
|
||||
return;
|
||||
}
|
||||
|
||||
/* %2 */ QString columnToChange = model->headerData(index.column(), Qt::Horizontal).toString();
|
||||
|
||||
const HeaderList &headerList = model->getHeaderList();
|
||||
|
||||
/* %3 */ const QString &valueForColumn = valueToSqlString(value, headerList, index.column()); // cannot get from model, as setData retured FALSE, which resets the change
|
||||
|
||||
/* %4 */ QString allColumnValuesInRow;
|
||||
QStringList allColumnValuesInRowList;
|
||||
|
||||
allColumnValuesInRowList.reserve(model->columnCount());
|
||||
|
||||
QString condition;
|
||||
|
||||
for (int i = 0; i < model->columnCount(); i++)
|
||||
{
|
||||
QString columnName = model->headerData(i, Qt::Horizontal).toString();
|
||||
QString columnValue = valueToSqlString(model->data(model->index(row, i)).toString(), headerList, i);
|
||||
|
||||
// nur für Spalte mit Namen 'id'
|
||||
if (columnName.compare(QStringLiteral("id"), Qt::CaseInsensitive) == 0)
|
||||
condition = QStringLiteral("%1=%2").arg(columnName, columnValue);
|
||||
|
||||
QString statement(QStringLiteral("%1=%2").arg(columnName, columnValue));
|
||||
if (model->data(model->index(row, i)).isNull())
|
||||
statement = QStringLiteral("%1 IS NULL").arg(columnName);
|
||||
|
||||
allColumnValuesInRowList.append(statement);
|
||||
}
|
||||
allColumnValuesInRow = allColumnValuesInRowList.join(QStringLiteral(" AND "));
|
||||
if (condition.isEmpty())
|
||||
condition = allColumnValuesInRow;
|
||||
|
||||
queryString = queryString.arg(tableName, columnToChange, valueForColumn, condition);
|
||||
|
||||
// qCritical() << "queryString =" << queryString;
|
||||
|
||||
QSqlQuery q(m_sqlDB);
|
||||
if (q.exec(queryString) && !m_dy) // execute set data query
|
||||
{
|
||||
// worked? then change value in model
|
||||
|
||||
// signalSetDataResult(caller, QStringLiteral("Num affected rows: %1").arg(q.numRowsAffected()));
|
||||
|
||||
auto con = connect(this, &QueryWorker::signalSetDataInModel,
|
||||
model, &DataModel::slotSetData);
|
||||
|
||||
if (value.toString().isEmpty())
|
||||
emit signalSetDataInModel(index, QVariant()); // single shot.... for threading
|
||||
else
|
||||
emit signalSetDataInModel(index, value); // single shot.... for threading
|
||||
|
||||
disconnect(con);
|
||||
|
||||
emit signalSetDataResult(caller, QString()); // empty string = success
|
||||
}
|
||||
else
|
||||
{
|
||||
emit signalSetDataResult(caller, q.lastError().text()); // error
|
||||
}
|
||||
|
||||
m_idle = true;
|
||||
}
|
||||
|
||||
|
||||
void QueryWorker::slotTableQuery(Query* caller, DataModel *model)
|
||||
{
|
||||
// no need to unidle here, as selectQuery does it!
|
||||
|
||||
//qWarning() << "QueryWorker: model" << model;
|
||||
|
||||
if (model->getTableName().isEmpty())
|
||||
{
|
||||
emit signalTableQueryResult(caller, QStringLiteral("This is a custom query"));
|
||||
return;
|
||||
}
|
||||
|
||||
QString queryString(QStringLiteral("SELECT * FROM %1").arg(model->getTableName()));
|
||||
|
||||
emit signalTableQueryResult(caller, selectQuery(queryString, model));
|
||||
}
|
||||
|
||||
|
||||
void QueryWorker::slotCustomQuery(Query* caller, const QString &queryString, DataModel *model)
|
||||
{
|
||||
// no need to unidle here, as selectQuery does it!
|
||||
|
||||
model->setTableName(QString()); // set empty table name, as this is not a table query anymore!
|
||||
emit signalCustomQueryResult(caller, selectQuery(queryString, model));
|
||||
}
|
||||
|
||||
|
||||
void QueryWorker::slotAddLines(Query* caller, AddModel* addModel)
|
||||
{
|
||||
if (!addModel) // no lines to add
|
||||
{
|
||||
emit signalAddLinesResult(caller, 0, QString());
|
||||
return;
|
||||
}
|
||||
|
||||
// no need to unidle here, as executeQuery does it!
|
||||
|
||||
QString addQuery(QStringLiteral("INSERT INTO %1 VALUES %2"));
|
||||
|
||||
QStringList rows;
|
||||
rows.reserve(addModel->rowCount());
|
||||
|
||||
for (int row = 0; row < addModel->rowCount() - 1 /* ignore empty add-line */; row++)
|
||||
{
|
||||
QStringList columns;
|
||||
int columnCount = addModel->columnCount();
|
||||
columns.reserve(columnCount);
|
||||
|
||||
for (int col = 0; col < columnCount; col++)
|
||||
{
|
||||
//qWarning() << "col" << col << "type" << addModel->getColumnType(col);
|
||||
|
||||
columns << valueToSqlString(addModel->data(addModel->index(row,col)), addModel->getHeaderList(), col);
|
||||
|
||||
////#warning implement IS NULL !
|
||||
// if (addModel->getColumnType(col) == QVariant::Int) // get sql type
|
||||
// {
|
||||
// columns << addModel->data(addModel->index(row, col)).toString();
|
||||
// }
|
||||
// else // string
|
||||
// {
|
||||
// QString str = "'%1'";
|
||||
// str = str.arg(addModel->data(addModel->index(row, col)).toString());
|
||||
// columns << str;
|
||||
// }
|
||||
}
|
||||
|
||||
const QString rowString(QLatin1Char('(') + columns.join(QLatin1Char(',')) + QLatin1Char(')'));
|
||||
rows << rowString;
|
||||
}
|
||||
|
||||
|
||||
addQuery = addQuery.arg(addModel->getTableName(), rows.join(QLatin1Char(',')));
|
||||
|
||||
int affectedRows = -1;
|
||||
emit signalAddLinesResult(caller, affectedRows, executeQuery(&affectedRows, addQuery));
|
||||
|
||||
qWarning() << "OKAY! add query = " << addQuery;
|
||||
}
|
||||
|
||||
|
||||
//QString QueryWorker::valueFromSqlString(const QString& val, const HeaderList &headerList, const int col)
|
||||
//{
|
||||
// // value comes from sql database and must be made 'visual'
|
||||
|
||||
// QVariant::Type type = headerList.at(col).second; // get column type from model
|
||||
|
||||
// //qWarning() << "QueryWorker::variantToSqlString: type =" << type;
|
||||
|
||||
// if (val.isEmpty()) // if val is empty, return empty sql type "NULL"
|
||||
// {
|
||||
// return "NULL";
|
||||
// }
|
||||
|
||||
// if (type == QVariant::String) // col is string type
|
||||
// {
|
||||
// return "'" + val + "'";
|
||||
// }
|
||||
// else // col is ANY int type
|
||||
// {
|
||||
// return val;
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
QString QueryWorker::valueToSqlString(const QVariant& val, const HeaderList &headerList, const int col)
|
||||
{
|
||||
// value must be converted to sql value
|
||||
|
||||
QVariant::Type type = headerList.at(col).second; // get column type from model
|
||||
|
||||
//qWarning() << "QueryWorker::valueToSqlString: val" << val << "type" << type << "("<<type<<")";
|
||||
|
||||
if (val.isNull() || val.toString().isEmpty()) // if val is empty, return empty sql type "NULL"
|
||||
return QStringLiteral("NULL");
|
||||
|
||||
//if (type == QVariant::String) // col is string type
|
||||
switch (type)
|
||||
{
|
||||
case QVariant::Int:
|
||||
return QString::number(val.toInt());
|
||||
case QVariant::UInt:
|
||||
return QString::number(val.toUInt());
|
||||
case QVariant::LongLong:
|
||||
return QString::number(val.toLongLong());
|
||||
case QVariant::ULongLong:
|
||||
return QString::number(val.toULongLong());
|
||||
case QVariant::Double:
|
||||
return QString::number(val.toDouble());
|
||||
|
||||
default: // any other than numeric type
|
||||
break;
|
||||
}
|
||||
|
||||
return QStringLiteral("'%1'").arg(val.toString());
|
||||
}
|
||||
|
||||
|
||||
QString QueryWorker::executeQuery(int* affectedRows, const QString &queryString)
|
||||
{
|
||||
m_idle = false;
|
||||
|
||||
QString result;
|
||||
|
||||
QSqlQuery q(m_sqlDB);
|
||||
|
||||
if (q.exec(queryString))
|
||||
{
|
||||
qWarning() << "executeQuery: success: numRowsAffected" << q.numRowsAffected();
|
||||
*affectedRows= q.numRowsAffected();
|
||||
}
|
||||
else // error
|
||||
{
|
||||
*affectedRows = 0;
|
||||
result = q.lastError().text(); // error (no rows affected)
|
||||
|
||||
// if (result.isEmpty())
|
||||
// {
|
||||
// result = "UNKNOWN ERROR";
|
||||
// }
|
||||
}
|
||||
|
||||
m_idle = true;
|
||||
|
||||
return result;
|
||||
}
|
||||
Executable
+108
@@ -0,0 +1,108 @@
|
||||
#pragma once
|
||||
|
||||
#include "LoginWnd.h"
|
||||
#include "DataModel.h"
|
||||
#include "AddModel.h"
|
||||
|
||||
#include <QSqlDatabase>
|
||||
#include <QList>
|
||||
#include <QModelIndex>
|
||||
|
||||
class Query;
|
||||
|
||||
class QueryWorker: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit QueryWorker();
|
||||
~QueryWorker();
|
||||
|
||||
void dy()
|
||||
{
|
||||
m_dy = true;
|
||||
}
|
||||
|
||||
bool isIdle() const
|
||||
{
|
||||
return m_idle;
|
||||
}
|
||||
|
||||
QAtomicInt m_dy;
|
||||
QAtomicInt m_idle; // dunno how to solve this atm
|
||||
|
||||
private:
|
||||
QSqlDatabase m_sqlDB;
|
||||
|
||||
QString selectQuery(const QString &queryString, DataModel *dataModel); //DataModel* model, )
|
||||
QString executeQuery(int* affectedRows, const QString &queryString);
|
||||
QString valueToSqlString(const QVariant &val, const HeaderList &headerList, const int col);
|
||||
|
||||
|
||||
// NEW ARCH
|
||||
// Delete Lines
|
||||
public slots:
|
||||
void slotDeleteLines(Query* caller, const QList<QModelIndex> &selectedRows, DataModel* dataModel);
|
||||
|
||||
signals:
|
||||
void signalDeleteLinesResult(Query*,int, const QString &, const QList<QModelIndex> &);
|
||||
|
||||
|
||||
// Custom Query
|
||||
public slots:
|
||||
void slotCustomQuery(Query* caller, const QString &queryString, DataModel* model);
|
||||
|
||||
signals:
|
||||
void signalCustomQueryResult(Query*,const QString &);
|
||||
|
||||
|
||||
// Table Query
|
||||
public slots:
|
||||
void slotTableQuery(Query* caller, DataModel* model);
|
||||
|
||||
signals:
|
||||
void signalTableQueryResult(Query*,const QString &);
|
||||
void signalSwapModelData();
|
||||
|
||||
|
||||
|
||||
// Add Lines
|
||||
public slots:
|
||||
void slotAddLines(Query* caller, AddModel* addModel);
|
||||
|
||||
signals:
|
||||
void signalAddLinesResult(Query*,int, const QString &);
|
||||
|
||||
|
||||
|
||||
// Set Data
|
||||
public slots:
|
||||
void slotSetData(Query* caller, DataModel*, const QModelIndex &, const QVariant &);
|
||||
|
||||
signals:
|
||||
void signalSetDataResult(Query*,const QString &);
|
||||
void signalSetDataInModel(const QModelIndex &idx, const QVariant &data);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public slots:
|
||||
void slotConnectIt(const LoginData &loginData);
|
||||
void slotGetTableList();
|
||||
|
||||
|
||||
signals:
|
||||
void signalConnectResult(const QString &);
|
||||
void signalNewTableList(const QStringList &);
|
||||
|
||||
//unused?void signalSelectQueryResult(QString errorMsg, DataModel* dataModel);
|
||||
void signalSelectQueryStatus(int percent); // 0 - 100
|
||||
|
||||
//unsued?void signalExecuteQueryResult(bool success, QString errorMsg, QVariant actualValue, QModelIndex onThisPosition); // take actual value as the new value set!
|
||||
void signalExecuteQueryStatus(int percent);
|
||||
|
||||
};
|
||||
Executable
+33
@@ -0,0 +1,33 @@
|
||||
#include "WaitWnd.h"
|
||||
|
||||
#include "ui_WaitWndUi.h"
|
||||
|
||||
|
||||
WaitWnd::WaitWnd(QWidget* parent)
|
||||
: QDialog(parent)
|
||||
, m_ui(new Ui::WaitWnd)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
}
|
||||
|
||||
WaitWnd::~WaitWnd()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
void WaitWnd::wait(const QString &text)
|
||||
{
|
||||
m_ui->progressBar->setMinimum(0);
|
||||
m_ui->progressBar->setMaximum(0);
|
||||
m_ui->progressBar->setValue(-1);
|
||||
|
||||
m_ui->label->setText(text);
|
||||
show();
|
||||
}
|
||||
|
||||
void WaitWnd::setStatus(int status)
|
||||
{
|
||||
m_ui->progressBar->setMinimum(0);
|
||||
m_ui->progressBar->setMaximum(100);
|
||||
m_ui->progressBar->setValue(status);
|
||||
}
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class WaitWnd;
|
||||
}
|
||||
|
||||
|
||||
class WaitWnd: public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit WaitWnd(QWidget* parent = nullptr);
|
||||
~WaitWnd();
|
||||
void wait(const QString &text);
|
||||
void setStatus(int status);
|
||||
|
||||
private:
|
||||
Ui::WaitWnd* m_ui;
|
||||
};
|
||||
Executable
+56
@@ -0,0 +1,56 @@
|
||||
// needed: libQt5Sql5-postgresql
|
||||
|
||||
/* TODO:
|
||||
*
|
||||
* hint for custom queries and their 'editibility'
|
||||
* autocompletion of tablenames (& columns?)
|
||||
* csv export for iuliana
|
||||
* to insert something, DataModel must use QVariant as data storage !
|
||||
*
|
||||
*/
|
||||
|
||||
#include "BrowserWnd.h"
|
||||
|
||||
#include <nglapplication/nglapplication.h>
|
||||
#include <QDebug>
|
||||
#include <QTimer>
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
QStringList params;
|
||||
params << QStringLiteral("--darkStyle");
|
||||
|
||||
int setDarkStyle = false;
|
||||
|
||||
for (int i = 0; i < argc; i++)
|
||||
{
|
||||
switch (params.indexOf(QString::fromUtf8(argv[i])))
|
||||
{
|
||||
case 0: // darkStyle
|
||||
{
|
||||
setDarkStyle = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (setDarkStyle)
|
||||
{
|
||||
qunsetenv("TDS_DEVEL"); // no dark style
|
||||
}
|
||||
else
|
||||
{
|
||||
qputenv("TDS_DEVEL", "1");
|
||||
}
|
||||
|
||||
|
||||
|
||||
NGLApplication a(argc, argv);
|
||||
a.createLogger("SQLBrowser", "log4cxx_sqlbrowser.props");
|
||||
|
||||
BrowserWnd browserWnd;
|
||||
QTimer::singleShot(0, &browserWnd, &BrowserWnd::startConnect);
|
||||
|
||||
return a.exec();
|
||||
}
|
||||
Executable
+110
@@ -0,0 +1,110 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AddLines</class>
|
||||
<widget class="QWidget" name="AddLines">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>526</width>
|
||||
<height>399</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Login</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTableView" name="dataView">
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbDone">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Adds all lines to the database and hides this window.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add && Hide</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbDelete">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Deletes all selected lines (one or more line) from this temporary table.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Delete</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbClear">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Clears the temporary table by deleting all lines from this temporary table.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Clear</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbAbort">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Do not make any changes and hide this window.<br/>This window's data will be kept until the query is deleted.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Hide</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
Executable
+219
@@ -0,0 +1,219 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BrowserWnd</class>
|
||||
<widget class="QWidget" name="BrowserWnd">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>762</width>
|
||||
<height>564</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>RDE SQL Browser</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><3</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbNewQuery">
|
||||
<property name="text">
|
||||
<string>New Query</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<property name="text">
|
||||
<string>Exit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="handleWidth">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetMinimumSize</enum>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Filter: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="leFilter"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListWidget" name="lwTables">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetMinimumSize</enum>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbRefreshTableList">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Refresh List</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="widget_2" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="twQueries">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="tabPosition">
|
||||
<enum>QTabWidget::North</enum>
|
||||
</property>
|
||||
<property name="tabShape">
|
||||
<enum>QTabWidget::Rounded</enum>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
<property name="tabsClosable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="movable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="tabBarAutoHide">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
Executable
+299
@@ -0,0 +1,299 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>LoginWnd</class>
|
||||
<widget class="QWidget" name="LoginWnd">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>407</width>
|
||||
<height>448</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Login</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Preset:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cbPresets">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbLoad">
|
||||
<property name="text">
|
||||
<string>Load</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbSave">
|
||||
<property name="text">
|
||||
<string>Save</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Load Database file:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="leFilename"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="tbChooseFile">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbLoadFile">
|
||||
<property name="text">
|
||||
<string>Load File [F12]</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>F12</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbExit_2">
|
||||
<property name="text">
|
||||
<string>Exit [ESC]</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Connect to Database:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>7</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>7</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>7</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>7</number>
|
||||
</property>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Database</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="leDatabase"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Username</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="leUsername"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Password</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="lePassword">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Hostname</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLineEdit" name="leHostname"/>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Port</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QSpinBox" name="sbPort">
|
||||
<property name="specialValueText">
|
||||
<string>Default</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>65535</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Driver</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="cbDriver"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetMinimumSize</enum>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbHeart">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><3</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbLogin">
|
||||
<property name="text">
|
||||
<string>Login [ENTER]</string>
|
||||
</property>
|
||||
<property name="default">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbExit">
|
||||
<property name="text">
|
||||
<string>Exit [ESC]</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>cbPresets</tabstop>
|
||||
<tabstop>pbLoad</tabstop>
|
||||
<tabstop>pbSave</tabstop>
|
||||
<tabstop>leFilename</tabstop>
|
||||
<tabstop>tbChooseFile</tabstop>
|
||||
<tabstop>pbLoadFile</tabstop>
|
||||
<tabstop>pbExit_2</tabstop>
|
||||
<tabstop>cbDriver</tabstop>
|
||||
<tabstop>leDatabase</tabstop>
|
||||
<tabstop>leUsername</tabstop>
|
||||
<tabstop>lePassword</tabstop>
|
||||
<tabstop>leHostname</tabstop>
|
||||
<tabstop>sbPort</tabstop>
|
||||
<tabstop>pbHeart</tabstop>
|
||||
<tabstop>pbLogin</tabstop>
|
||||
<tabstop>pbExit</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
Executable
+321
@@ -0,0 +1,321 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Query</class>
|
||||
<widget class="QWidget" name="Query">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>643</width>
|
||||
<height>527</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Login</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTableView" name="dataTable">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monospace</family>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="verticalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderCascadingSectionResizes">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="widget_2" native="true">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item row="1" column="0">
|
||||
<widget class="QPushButton" name="pbQueryUpdate">
|
||||
<property name="text">
|
||||
<string>Update...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="pbQueryDelete">
|
||||
<property name="text">
|
||||
<string>Delete...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="4">
|
||||
<widget class="QTextEdit" name="queryText">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monospace</family>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="pbQueryInsert">
|
||||
<property name="text">
|
||||
<string>Insert...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="4">
|
||||
<widget class="QScrollArea" name="saCheckboxes">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="checkboxesContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>629</width>
|
||||
<height>68</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="checkboxes">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbAddLine">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Opens a new window, where one or more lines can be added to the database.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbDeleteLine">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Deletes all selected lines (one or more line) from the database.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Delete</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbReload">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Reloads the table data with current data from the database.</p><p><span style=" font-style:italic;">Shortcut: F5</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Reload</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>F5</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbQuery">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Execute a custom query from the text box below the table data.</p><p><span style=" font-weight:600;">WARNING</span>: You cannot use Add, Delete, Revert anymore, as a custom query revokes the query tab's functionality as table query.</p><p><span style=" font-style:italic;">Shortcut: Ctrl + Enter</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Query</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+Return</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbExport">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Saves the current data from the data table in a CSV file. </p><p><span style=" font-style:italic;">Shortcut: Ctrl + S</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>CSV Export</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+S</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
Executable
+51
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>WaitWnd</class>
|
||||
<widget class="QWidget" name="WaitWnd">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>119</width>
|
||||
<height>79</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>RDE SQL Browser - Wait ...</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QProgressBar" name="progressBar">
|
||||
<property name="maximum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
Reference in new issue
Block a user