Commit 4d765f48 authored by Hugo Hörnquist's avatar Hugo Hörnquist

Merge branch 'sql'

This adds a new tab to the admin window, containing functions for
writing, storing and executing SQL queries. But also, and this is the
big part PRINTING THEM!

The database needs to be patched, see diff.sql.
parents 63975d2e 53f328bb
......@@ -4,7 +4,7 @@
#
#-------------------------------------------------
QT += core gui sql
QT += core gui sql printsupport
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
......@@ -20,7 +20,8 @@ SOURCES += main.cpp\
texteditdelegate.cpp \
disablingmodel.cpp \
qintornullvalidator.cpp \
maybevalidatordelegate.cpp
maybevalidatordelegate.cpp \
tableprinter.cpp
HEADERS += mainwindow.h \
comboboxitemdelegate.h \
......@@ -29,7 +30,8 @@ HEADERS += mainwindow.h \
texteditdelegate.h \
disablingmodel.h \
qintornullvalidator.h \
maybevalidatordelegate.h
maybevalidatordelegate.h \
tableprinter.h
FORMS += mainwindow.ui
......
......@@ -18,6 +18,12 @@
#include <QFileInfo>
#include <QPrinter>
#include <QPrintDialog>
#include <QPrintPreviewDialog>
#include <QPainter>
#include "tableprinter.h"
#include <cstring>
#include "comboboxitemdelegate.h"
......@@ -344,6 +350,22 @@ MainWindow::MainWindow(QWidget *parent) :
transHistoryModel->setEditStrategy(QSqlTableModel::OnManualSubmit);
ui->moneyTransferHistory->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
// ==================================================
QSqlQueryModel* sqlQueryModel = new QSqlQueryModel;
ui->sqlOutput->setModel(sqlQueryModel);
QSqlTableModel* sqlQueryListModel = new QSqlTableModel;
sqlQueryListModel->setTable("sql_queries");
sqlQueryListModel->select();
sqlQueryListModel->setHeaderData(0, Qt::Horizontal, "id");
sqlQueryListModel->setHeaderData(1, Qt::Horizontal, "Namn");
sqlQueryListModel->setHeaderData(2, Qt::Horizontal, "Query");
ui->sqlBufferList->setModel(sqlQueryListModel);
ui->sqlBufferList->hideColumn(0);
ui->sqlBufferList->hideColumn(2);
ui->sqlBufferList->sortByColumn(1);
}
MainWindow::~MainWindow()
......@@ -936,3 +958,130 @@ void MainWindow::on_accNewAccBtn_clicked()
setMoneyAccountValues();
setAccTransferCombo();
}
void MainWindow::setSqlQuery(qlonglong id)
{
QSqlQuery query;
query.prepare("SELECT name, query FROM sql_queries "
"WHERE id = :id");
query.bindValue(":id", id);
query.exec();
if (query.next()) {
ui->sqlBufferName->setText(query.value(0).toString());
ui->sqlEdit->setPlainText(query.value(1).toString());
}
}
void MainWindow::setSqlQuery(QString name)
{
QSqlQuery query;
query.prepare("SELECT name, query FROM sql_queries "
"WHERE name = :name");
query.bindValue(":name", name);
query.exec();
if (query.next()) {
ui->sqlBufferName->setText(query.value(0).toString());
ui->sqlEdit->setPlainText(query.value(1).toString());
}
}
void MainWindow::on_sqlBufferList_activated(const QModelIndex &index)
{
QAbstractItemModel* model = ui->sqlBufferList->model();
qlonglong id = model->data(model->index(index.row(), 0)).toLongLong();
setSqlQuery(id);
}
void MainWindow::on_sqlLoad_clicked()
{
setSqlQuery(ui->sqlBufferName->text());
}
void MainWindow::on_sqlSave_clicked()
{
// QSqlTableModel* model = (QSqlTableModel*) ui->sqlBufferList->model();
QSqlQuery query;
query.prepare("INSERT OR REPLACE "
"INTO sql_queries (name, query) "
"VALUES (:name, :query)");
query.bindValue(":name", ui->sqlBufferName->text());
query.bindValue(":query", ui->sqlEdit->toPlainText());
query.exec();
((QSqlTableModel*) ui->sqlBufferList->model())->select();
}
void MainWindow::on_sqlOutReload_clicked()
{
QSqlQueryModel* model = (QSqlQueryModel*) ui->sqlOutput->model();
model->setQuery(ui->sqlEdit->toPlainText());
if (model->lastError().isValid()) {
QMessageBox::warning(
this, "SQL Querry error",
"Error while executing query\n\n " + model->lastError().text());
return;
}
ui->tabWidget_2->setCurrentIndex(0);
}
void MainWindow::printTable(QPrinter* printer)
{
QPainter painter;
if (!painter.begin(printer)) {
qWarning() << "can't start printer";
return;
}
QSqlQueryModel* model = (QSqlQueryModel*) ui->sqlOutput->model();
TablePrinter tablePrinter(&painter, printer);
QVector<int> columnStretch = QVector<int>();
QVector<QString> headers = QVector<QString>();
for (int i = 0; i < model->columnCount(); i++) {
columnStretch << 1;
headers << model->headerData(i, Qt::Horizontal).toString();
}
QFont headerFont;
headerFont.setBold(true);
tablePrinter.setHeadersFont(headerFont);
if (!tablePrinter.printTable(ui->sqlOutput->model(), columnStretch, headers)) {
qDebug() << tablePrinter.lastError();
}
painter.end();
}
void MainWindow::on_sqlPrint_clicked()
{
QPrintPreviewDialog dialog;
connect(&dialog, SIGNAL(paintRequested(QPrinter*)), this, SLOT(printTable(QPrinter*)));
dialog.exec();
}
void MainWindow::on_sqlBufferDeleteButton_clicked()
{
QSqlTableModel* model = (QSqlTableModel*) ui->sqlBufferList->model();
QSqlQuery query;
query.prepare("DELETE FROM sql_queries WHERE id = ?");
QVariantList ids;
foreach (QModelIndex index, ui->sqlBufferList->selectionModel()->selectedRows())
{
ids << model->data(model->index(index.row(), 0));
}
query.addBindValue(ids);
if (!query.execBatch())
qDebug() << query.lastError();
model->select();
}
......@@ -5,6 +5,7 @@
#include <QSqlTableModel>
#include <QSqlRelationalTableModel>
#include <QTableView>
#include <QPrinter>
#include "disablingmodel.h"
......@@ -85,6 +86,20 @@ private slots:
void on_accNewAccBtn_clicked();
void on_sqlBufferList_activated(const QModelIndex &index);
void on_sqlLoad_clicked();
void on_sqlSave_clicked();
void on_sqlOutReload_clicked();
void on_sqlPrint_clicked();
void printTable(QPrinter* printer);
void on_sqlBufferDeleteButton_clicked();
private:
Ui::MainWindow *ui;
QSqlTableModel* model;
......@@ -106,6 +121,9 @@ private:
void setProductFilter();
void setMoneyAccountValues();
void setSqlQuery(qlonglong id);
void setSqlQuery(QString name);
QVariant get_projected_stock_value();
QVariant get_acquistion_stock_value();
void setStockValues();
......
......@@ -14,8 +14,8 @@
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QTabWidget" name="tabWidget">
<property name="tabShape">
<enum>QTabWidget::Rounded</enum>
......@@ -960,6 +960,153 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="sqlTab">
<attribute name="title">
<string>SQL</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_12">
<item>
<widget class="QSplitter" name="splitter_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QTabWidget" name="tabWidget_2">
<property name="currentIndex">
<number>1</number>
</property>
<widget class="QWidget" name="tab_6">
<attribute name="title">
<string>Output</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0" colspan="3">
<widget class="QTableView" name="sqlOutput">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
</widget>
</item>
<item row="1" column="0">
<spacer name="horizontalSpacer_7">
<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 row="1" column="2">
<widget class="QPushButton" name="sqlPrint">
<property name="text">
<string>Skriv ut</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_7">
<attribute name="title">
<string>Sparade</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTreeView" name="sqlBufferList">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<spacer name="horizontalSpacer_8">
<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="sqlBufferDeleteButton">
<property name="text">
<string>Ta bort</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<widget class="QWidget" name="gridLayoutWidget">
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0" colspan="4">
<widget class="QLineEdit" name="sqlBufferName"/>
</item>
<item row="2" column="0" colspan="4">
<widget class="QPlainTextEdit" name="sqlEdit">
<property name="font">
<font>
<family>Monospace</family>
</font>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QPushButton" name="sqlSave">
<property name="text">
<string>Spara</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="sqlLoad">
<property name="text">
<string>Ladda</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="sqlOutReload">
<property name="text">
<string>Kör</string>
</property>
</widget>
</item>
<item row="1" column="1">
<spacer name="horizontalSpacer_9">
<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>
</layout>
</widget>
<widget class="QWidget" name="tab_3">
<attribute name="title">
<string>Övrigt</string>
......
/****************************************************************************
**
** Copyright (c) 2016, Anton Onishchenko
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without modification,
** are permitted provided that the following conditions are met:
**
** 1. Redistributions of source code must retain the above copyright notice, this
** list of conditions and the following disclaimer.
**
** 2. Redistributions in binary form must reproduce the above copyright notice, this
** list of conditions and the following disclaimer in the documentation and/or other
** materials provided with the distribution.
**
** 3. Neither the name of the copyright holder nor the names of its contributors may
** be used to endorse or promote products derived from this software without
** specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
** ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
****************************************************************************/
#include "tableprinter.h"
#include <QAbstractItemModel>
#include <QPainter>
#include <QPrinter>
TablePrinter::TablePrinter(QPainter* painter, QPrinter* printer) :
painter(painter),
printer(printer) {
topMargin = 5;
bottomMargin = 5;
leftMargin = 10;
rightMargin = 5;
headerHeight = 0;
bottomHeight = 0;
leftBlank = 0;
rightBlank = 0;
maxRowHeight = 1000;
pen = painter->pen();
headersFont = painter->font();
contentFont = painter->font();
headerColor = painter->pen().color();
contentColor = painter->pen().color();
prepare = NULL;
error = "No error";
}
bool TablePrinter::printTable(const QAbstractItemModel* model, const QVector<int> columnStretch,
const QVector<QString> headers) {
//--------------------------------- error checking -------------------------------------
int columnCount = model->columnCount();
int count = columnStretch.count();
if(count != columnCount) {
error = "Different columns count in model and in columnStretch";
return false;
}
count = headers.count();
if(count != columnCount && count != 0) {
error = "Different columns count in model and in headers";
return false;
}
if(!printer->isValid()) {
error = "printer.isValid() == false";
return false;
}
if(!painter->isActive()) {
error = "painter.isActive() == false";
return false;
}
double tableWidth = painter->viewport().width() - leftBlank - rightBlank;
if(tableWidth <= 0) {
error = "wrong table width";
return false;
}
int totalStretch = 0;
for (int i = 0; i < columnStretch.count(); i++) {
if(columnStretch[i] < 0) {
error = QString("wrong column stretch, columnt: %1 stretch: %2").arg(i).arg(columnStretch[i]);
return false;
}
totalStretch += columnStretch[i];
}
if(totalStretch <= 0) {
error = QString("wrong stretch");
return false;
}
QVector<double> columnWidth;
for (int i = 0; i < columnStretch.count(); i++) {
columnWidth.append(tableWidth / totalStretch * columnStretch[i]);
}
int initValue;
headers.isEmpty() ? initValue = 0 : initValue = -1;
//----------------------------------------------------------------------------
painter->save(); // before table print
// to know row height before printing
// at first print to test image
QPainter testSize;
QImage* image = new QImage(10, 10, QImage::Format_RGB32);
image->setDotsPerMeterX(printer->logicalDpiX() * 100 / 2.54); // 2.54 cm = 1 inch
image->setDotsPerMeterY(printer->logicalDpiY() * 100 / 2.54);
testSize.begin(image);
if(prepare) {
painter->save();
painter->translate(-painter->transform().dx(), -painter->transform().dy());
prepare->preparePage(painter);
painter->restore();
}
painter->setPen(pen);
painter->setFont(contentFont);
testSize.setFont(contentFont);
painter->translate(-painter->transform().dx() + leftBlank, 0);
painter->save();
painter->setFont(headersFont);
testSize.setFont(headersFont);
painter->drawLine(0, 0, tableWidth, 0); // first horizontal line
float max_y;
for(int j = initValue; j < model->rowCount(); j++) { // for each row
if(j == 0) {
painter->setFont(contentFont);
testSize.setFont(contentFont);
}
// --------------------------- row height counting ----------------------------
int maxHeight = 0; // max row Height
for(int i = 0; i < columnCount; i++) { // for each column
QString str;
if(j >= 0) {
str = model->data(model->index(j,i), Qt::DisplayRole).toString();
} else {
str = headers.at(i);
}
QRect rect(0, 0, columnWidth[i] - rightMargin - leftMargin, maxRowHeight);
QRect realRect;
testSize.drawText(rect, Qt::AlignLeft | Qt::TextWordWrap, str, &realRect);
if (realRect.height() > maxHeight && columnStretch[i] != 0) {
realRect.height() > maxRowHeight ? maxHeight = maxRowHeight : maxHeight = realRect.height();
}
}
if(painter->transform().dy() + maxHeight + topMargin + bottomMargin > painter->viewport().height() -
bottomHeight) { // begin from new page
int y = painter->transform().dy();
painter->restore();
painter->save();
for(int i = 0; i < columnCount; i++) { // vertical lines
painter->drawLine(0, 0, 0,
- painter->transform().dy() + y);
painter->translate(columnWidth[i], 0);
}
painter->drawLine(0, 0, 0, - painter->transform().dy() + y); // last vertical line
painter->restore();
printer->newPage();
if(prepare) {
painter->save();
painter->translate(-painter->transform().dx(), -painter->transform().dy());
prepare->preparePage(painter);
painter->restore();
}
painter->translate(-painter->transform().dx() + leftBlank, -painter->transform().dy() + headerHeight);
painter->save();
painter->drawLine(0, 0, tableWidth,
0); // first horizontal line
}
//------------------------------ content printing -------------------------------------------
painter->save();
j >= 0 ? painter->setPen(QPen(contentColor)) : painter->setPen(QPen(headerColor));
for(int i = 0; i < columnCount; i++) { // for each column
QString str;
if(j >= 0) {
str = model->data(model->index(j,i), Qt::DisplayRole).toString();
} else {
str = headers.at(i);
}
QRect rec(leftMargin, topMargin, columnWidth[i] - rightMargin - leftMargin, maxHeight);
painter->drawText(rec, Qt::AlignLeft | Qt::TextWordWrap, str);
painter->translate(columnWidth[i], 0);
}
painter->restore();
painter->drawLine(0, maxHeight + topMargin + bottomMargin, tableWidth,
maxHeight + topMargin + bottomMargin); // last horizontal line
painter->translate(0, maxHeight + topMargin + bottomMargin);
max_y = painter->transform().dy();
}
int y = painter->transform().dy();
painter->restore();
painter->save();
for(int i = 0; i < columnCount; i++) { // vertical lines
painter->drawLine(0, 0, 0,
- painter->transform().dy() + y);
painter->translate(columnWidth[i], 0);
}
painter->drawLine(0, 0, 0, - painter->transform().dy() + y); // last vertical line
painter->restore();
testSize.end();
delete image;
painter->restore(); // before table print
painter->translate(0, max_y);
return true;
}
QString TablePrinter::lastError() {
return error;
}
void TablePrinter::setCellMargin(int left, int right, int top, int bottom) {
topMargin = top;
bottomMargin = bottom;
leftMargin = left;
rightMargin = right;
}
void TablePrinter::setPageMargin(int left, int right, int top, int bottom) {
headerHeight = top;
bottomHeight = bottom;
leftBlank = left;
rightBlank = right;
}