From 4b34eb76b5f2b0f209f88a0c2fe827d3eedde670 Mon Sep 17 00:00:00 2001 From: mgr Date: Sun, 23 Sep 2018 18:26:57 +0200 Subject: [PATCH] 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. --- src/ExtendedTableWidget.cpp | 61 ++++++++++++++++++++++++++++++++++--- src/ExtendedTableWidget.h | 3 ++ 2 files changed, 60 insertions(+), 4 deletions(-) diff --git a/src/ExtendedTableWidget.cpp b/src/ExtendedTableWidget.cpp index 9e33a2f0..439f4d63 100644 --- a/src/ExtendedTableWidget.cpp +++ b/src/ExtendedTableWidget.cpp @@ -16,6 +16,10 @@ #include #include #include +#include +#include +#include + #include #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("").arg(QApplication::applicationName().toHtmlEscaped(), now); htmlResult.append(m_generatorStamp); // TODO: is this really needed by Excel, since we use
 for multi-line cells?
-    htmlResult.append("");
+    htmlResult.append(""
+                      "
"); 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 + "
"); 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; +} diff --git a/src/ExtendedTableWidget.h b/src/ExtendedTableWidget.h index bd374502..ad4772b4 100644 --- a/src/ExtendedTableWidget.h +++ b/src/ExtendedTableWidget.h @@ -8,6 +8,7 @@ #include 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();