diff --git a/admin/StupanAdmin.pro b/admin/StupanAdmin.pro
index c9c1edfa40468f6460ac19ddb2fcc773ead5ceff..ae828d73024dbd07f8c89b54ad909fe7fe8d54aa 100644
--- a/admin/StupanAdmin.pro
+++ b/admin/StupanAdmin.pro
@@ -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
 
diff --git a/admin/mainwindow.cpp b/admin/mainwindow.cpp
index 4259a2ba966d338a8646099d717fa5a13689c9f5..b74f8473e9d5abdad9e7a35c72534ff76e430897 100644
--- a/admin/mainwindow.cpp
+++ b/admin/mainwindow.cpp
@@ -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();
+}
diff --git a/admin/mainwindow.h b/admin/mainwindow.h
index 8201175aa8abb3fd80ce42d99620ddc4d18e871a..19ef0bd6e1f529d2786178315e23812b53739f07 100644
--- a/admin/mainwindow.h
+++ b/admin/mainwindow.h
@@ -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();
diff --git a/admin/mainwindow.ui b/admin/mainwindow.ui
index 88ed7bff83ce1184a595a5e95281d03513886c4e..c4ea8d5c9dcc06597047579b233860203f8f8153 100644
--- a/admin/mainwindow.ui
+++ b/admin/mainwindow.ui
@@ -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>
diff --git a/admin/tableprinter.cpp b/admin/tableprinter.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..f832b8b75f963b0c2e85a709e8f55febf1a6d8a0
--- /dev/null
+++ b/admin/tableprinter.cpp
@@ -0,0 +1,274 @@
+/****************************************************************************
+**
+** 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;
+}
+
+void TablePrinter::setPagePrepare(PagePrepare *prep) {
+    prepare = prep;
+}
+
+void TablePrinter::setPen(QPen p) {
+    pen = p;
+}
+
+void TablePrinter::setHeadersFont(QFont f) {
+    headersFont = f;
+}
+
+void TablePrinter::setContentFont(QFont f) {
+    contentFont = f;
+}
+
+void TablePrinter::setHeaderColor(QColor color) {
+    headerColor = color;
+}
+
+void TablePrinter::setContentColor(QColor color) {
+    contentColor = color;
+}
+
+void TablePrinter::setMaxRowHeight(int height) {
+    maxRowHeight = height;
+}
diff --git a/admin/tableprinter.h b/admin/tableprinter.h
new file mode 100755
index 0000000000000000000000000000000000000000..9d1d9ec2a89f85f9418c605362b64b415238ce97
--- /dev/null
+++ b/admin/tableprinter.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+#ifndef TABLEPRINTER_H
+#define TABLEPRINTER_H
+
+#include <QPen>
+#include <QFont>
+
+class QPrinter;
+class QPainter;
+class QAbstractItemModel;
+
+/**
+ * @brief The PagePrepare Abstract class - base class for
+ * classes that will print something like headers, borders...
+ * on each page with table
+ */
+class PagePrepare {
+public:
+    virtual void preparePage(QPainter *painter) = 0;
+    virtual ~PagePrepare() {}
+};
+
+class TablePrinter
+{
+public:
+  TablePrinter(QPainter *painter, QPrinter *printer);
+  bool printTable(const QAbstractItemModel* model, const QVector<int> columnStretch,
+                  const QVector<QString> headers = QVector<QString>());
+  QString lastError();
+  void setCellMargin(int left = 10, int right = 5, int top = 5, int bottom = 5);
+  void setPageMargin(int left = 50, int right = 20, int top = 20, int bottom = 20);
+  void setPagePrepare(PagePrepare *prepare);
+  void setPen(QPen pen); // for table borders
+  void setHeadersFont(QFont font);
+  void setContentFont(QFont font);
+  void setHeaderColor(QColor color);
+  void setContentColor(QColor color);
+  void setMaxRowHeight(int height);
+private:
+  QPainter *painter;
+  QPrinter *printer;
+  PagePrepare *prepare;
+  QPen pen; // for table borders
+  QFont headersFont;
+  QFont contentFont;
+  QColor headerColor;
+  QColor contentColor;
+  // cell margins
+  int topMargin;
+  int bottomMargin;
+  int leftMargin;
+  int rightMargin;
+
+  // margins for table
+  int headerHeight;
+  int bottomHeight;
+  int leftBlank;
+  int rightBlank;
+
+  int maxRowHeight;
+
+  QString error;
+};
+
+#endif // TABLEPRINTER_H
diff --git a/create-db.sql b/create-db.sql
index a95e1c3cb0b0806e828f59edffe1d8812f5bcf93..dd3184c5a0116a093b6cb7cbf2eddecf2dbdb75f 100644
--- a/create-db.sql
+++ b/create-db.sql
@@ -125,6 +125,12 @@ CREATE TABLE my_db_settings (
     value
 );
 
+CREATE TABLE sql_queries (
+    id INTEGER PRIMARY KEY NOT NULL,
+    name TEXT NOT NULL UNIQUE,
+    query TEXT DEFAULT "" NOT NULL
+);
+
 -- ============================== Views ==================================
 
 CREATE VIEW drainage_change AS -- how prices have changed due to the drainage, or null
diff --git a/diff.sql b/diff.sql
new file mode 100644
index 0000000000000000000000000000000000000000..7f4a0c06d47bde620e548f40d3134424c30fd937
--- /dev/null
+++ b/diff.sql
@@ -0,0 +1,5 @@
+CREATE TABLE sql_queries (
+    id INTEGER PRIMARY KEY NOT NULL,
+    name TEXT NOT NULL UNIQUE,
+    query TEXT DEFAULT "" NOT NULL
+);