Printing support #1525: print tables in Browse Data and Execute SQL tabs

Added contextual menu entry and keyboard shortcut for printing the browsed
table with headers. If a region is selected, print those cells data.
Otherwise, print the entire table.

The HTML conversion used for clipboard is reused. Borders are added for
better visual output.
This commit is contained in:
mgr
2018-09-23 18:26:57 +02:00
parent 99c53a436e
commit 4b34eb76b5
2 changed files with 60 additions and 4 deletions

View File

@@ -16,6 +16,10 @@
#include <QMenu>
#include <QDateTime>
#include <QLineEdit>
#include <QPrinter>
#include <QPrintDialog>
#include <QTextDocument>
#include <limits>
#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0)
@@ -169,6 +173,7 @@ ExtendedTableWidget::ExtendedTableWidget(QWidget* parent) :
QAction* copyWithHeadersAction = new QAction(QIcon(":/icons/special_copy"), tr("Copy with Headers"), m_contextMenu);
QAction* copyAsSQLAction = new QAction(QIcon(":/icons/sql_copy"), tr("Copy as SQL"), m_contextMenu);
QAction* pasteAction = new QAction(QIcon(":/icons/paste"), tr("Paste"), m_contextMenu);
QAction* printAction = new QAction(QIcon(":/icons/print"), tr("Print..."), m_contextMenu);
m_contextMenu->addAction(filterAction);
QMenu* filterMenu = m_contextMenu->addMenu(tr("Use in Filter Expression"));
@@ -187,6 +192,8 @@ ExtendedTableWidget::ExtendedTableWidget(QWidget* parent) :
m_contextMenu->addAction(copyWithHeadersAction);
m_contextMenu->addAction(copyAsSQLAction);
m_contextMenu->addAction(pasteAction);
m_contextMenu->addSeparator();
m_contextMenu->addAction(printAction);
setContextMenuPolicy(Qt::CustomContextMenu);
// Create and set up delegate
@@ -200,6 +207,7 @@ ExtendedTableWidget::ExtendedTableWidget(QWidget* parent) :
copyWithHeadersAction->setShortcut(QKeySequence(tr("Ctrl+Shift+C")));
copyAsSQLAction->setShortcut(QKeySequence(tr("Ctrl+Alt+C")));
pasteAction->setShortcut(QKeySequence::Paste);
printAction->setShortcut(QKeySequence::Print);
// Set up context menu actions
connect(this, &QTableView::customContextMenuRequested,
@@ -212,6 +220,7 @@ ExtendedTableWidget::ExtendedTableWidget(QWidget* parent) :
copyAction->setEnabled(enabled);
copyWithHeadersAction->setEnabled(enabled);
copyAsSQLAction->setEnabled(enabled);
printAction->setEnabled(enabled);
// Hide filter actions when there isn't any filters
bool hasFilters = m_tableHeader->hasFilters();
@@ -267,6 +276,9 @@ ExtendedTableWidget::ExtendedTableWidget(QWidget* parent) :
connect(pasteAction, &QAction::triggered, [&]() {
paste();
});
connect(printAction, &QAction::triggered, [&]() {
openPrintDialog();
});
}
void ExtendedTableWidget::reloadSettings()
@@ -280,9 +292,10 @@ void ExtendedTableWidget::reloadSettings()
verticalHeader()->setDefaultSectionSize(verticalHeader()->fontMetrics().height()+10);
}
void ExtendedTableWidget::copy(const bool withHeaders, const bool inSQL )
void ExtendedTableWidget::copyMimeData(const QModelIndexList& fromIndices, QMimeData* mimeData, const bool withHeaders, const bool inSQL)
{
QModelIndexList indices = selectionModel()->selectedIndexes();
QModelIndexList indices = fromIndices;
// Remove all indices from hidden columns, because if we don't we might copy data from hidden columns as well which is very
// unintuitive; especially copying the rowid column when selecting all columns of a table is a problem because pasting the data
@@ -360,7 +373,8 @@ void ExtendedTableWidget::copy(const bool withHeaders, const bool inSQL )
m_generatorStamp = QString("<meta name=\"generator\" content=\"%1\"><meta name=\"date\" content=\"%2\">").arg(QApplication::applicationName().toHtmlEscaped(), now);
htmlResult.append(m_generatorStamp);
// TODO: is this really needed by Excel, since we use <pre> for multi-line cells?
htmlResult.append("<style type=\"text/css\">br{mso-data-placement:same-cell;}</style></head><body><table>");
htmlResult.append("<style type=\"text/css\">br{mso-data-placement:same-cell;}</style></head><body>"
"<table border=1 cellspacing=0 cellpadding=2>");
int currentRow = indices.first().row();
@@ -450,7 +464,6 @@ void ExtendedTableWidget::copy(const bool withHeaders, const bool inSQL )
}
sqlResult.append(");");
QMimeData *mimeData = new QMimeData;
if ( inSQL )
{
mimeData->setText(sqlResult);
@@ -458,6 +471,12 @@ void ExtendedTableWidget::copy(const bool withHeaders, const bool inSQL )
mimeData->setHtml(htmlResult + "</td></tr></table></body></html>");
mimeData->setText(result);
}
}
void ExtendedTableWidget::copy(const bool withHeaders, const bool inSQL )
{
QMimeData *mimeData = new QMimeData;
copyMimeData(selectionModel()->selectedIndexes(), mimeData, withHeaders, inSQL);
qApp->clipboard()->setMimeData(mimeData);
}
@@ -653,6 +672,8 @@ void ExtendedTableWidget::keyPressEvent(QKeyEvent* event)
} else if(event->matches(QKeySequence::Paste)) {
// Call a custom paste method when Ctrl-V is pressed
paste();
} else if(event->matches(QKeySequence::Print)) {
openPrintDialog();
} else if(event->modifiers().testFlag(Qt::ControlModifier) && event->modifiers().testFlag(Qt::ShiftModifier) && (event->key() == Qt::Key_C)) {
// Call copy with headers when Ctrl-Shift-C is pressed
copy(true, false);
@@ -832,3 +853,35 @@ void ExtendedTableWidget::selectTableLines(int firstLine, int count)
selectionModel()->select(QItemSelection(topLeft, bottomRight), QItemSelectionModel::Select | QItemSelectionModel::Rows);
}
void ExtendedTableWidget::openPrintDialog()
{
QMimeData *mimeData = new QMimeData;
QModelIndexList indices;
// Print the selection, if active, or the entire table otherwise.
// Given that simply clicking over a cell, selects it, one-cell selections are ignored.
if (selectionModel()->hasSelection() && selectionModel()->selectedIndexes().count() > 1)
indices = selectionModel()->selectedIndexes();
else
for (int row=0; row < model()->rowCount(); row++)
for (int column=0; column < model()->columnCount(); column++)
indices << model()->index(row, column);
// Copy the specified indices content to mimeData for getting the HTML representation of
// the table with headers. We can then print it using an HTML text document.
copyMimeData(indices, mimeData, true, false);
QTextDocument *document = new QTextDocument();
document->setHtml(mimeData->html());
QPrinter printer;
QPrintDialog *dialog = new QPrintDialog(&printer, NULL);
if (dialog->exec() == QDialog::Accepted) {
document->print(&printer);
}
delete document;
delete mimeData;
}

View File

@@ -8,6 +8,7 @@
#include <QStyledItemDelegate>
class QMenu;
class QMimeData;
class FilterTableHeader;
namespace sqlb { class ObjectIdentifier; }
@@ -50,9 +51,11 @@ signals:
void selectedRowsToBeDeleted();
private:
void copyMimeData(const QModelIndexList& fromIndices, QMimeData* mimeData, const bool withHeaders, const bool inSQL);
void copy(const bool withHeaders, const bool inSQL);
void paste();
QString escapeCopiedData(const QByteArray& data) const;
void openPrintDialog();
void useAsFilter(const QString& filterOperator, bool binary = false);
void duplicateUpperCell();