Skip to content

Commit

Permalink
Clipboard improvements: HTML and avoid pasting image from LibreCalc
Browse files Browse the repository at this point in the history
Both "Copy" and "Copy with Headers" write in HTML and text format to the
system clipboard, when the selection includes more than one cell. This lets
the pasting application choose the most appropriate format.

Images have now no precedence over text when requesting the clipboard
content, so pasting from applications like LibreCalc, that set both formats
in the clipboard, works as expected, instead of pasting an image of the
copied text.

Copying and pasting inside the DB4S should not be affected, since the
application requests the text format and uses the internal buffer when
necessary (binary data included).

Related issue: #1058
  • Loading branch information
mgrojo committed Nov 18, 2017
1 parent 28d53ef commit e60e9ff
Showing 1 changed file with 43 additions and 16 deletions.
59 changes: 43 additions & 16 deletions src/ExtendedTableWidget.cpp
Expand Up @@ -6,6 +6,7 @@


#include <QApplication> #include <QApplication>
#include <QClipboard> #include <QClipboard>
#include <QMimeData>
#include <QKeySequence> #include <QKeySequence>
#include <QKeyEvent> #include <QKeyEvent>
#include <QScrollBar> #include <QScrollBar>
Expand Down Expand Up @@ -163,7 +164,7 @@ void ExtendedTableWidget::copy(const bool withHeaders)
m_buffer.clear(); m_buffer.clear();


// If a single cell is selected, copy it to clipboard // If a single cell is selected, copy it to clipboard
if (indices.size() == 1) { if (!withHeaders && indices.size() == 1) {
QImage img; QImage img;
QVariant data = m->data(indices.first(), Qt::EditRole); QVariant data = m->data(indices.first(), Qt::EditRole);


Expand All @@ -183,8 +184,6 @@ void ExtendedTableWidget::copy(const bool withHeaders)


if (text.contains('\n')) if (text.contains('\n'))
text = QString("\"%1\"").arg(text); text = QString("\"%1\"").arg(text);
if (withHeaders)
text.prepend(model()->headerData(indices.front().column(), Qt::Horizontal, Qt::DisplayRole).toString() + "\r\n");
qApp->clipboard()->setText(text); qApp->clipboard()->setText(text);
return; return;
} }
Expand Down Expand Up @@ -216,30 +215,52 @@ void ExtendedTableWidget::copy(const bool withHeaders)
return; return;
} }


// Multiple cells case: write a table both in HTML and text formats to clipboard

QModelIndex first = indices.first(); QModelIndex first = indices.first();
QString result; QString result;
QString htmlResult = "<html><header><style>br{mso-data-placement:same-cell;}</style></header><body><table>";
int currentRow = 0; int currentRow = 0;


const QString fieldSepHtml = "</td><td>";
const QString rowSepHtml = "</td></tr><tr><td>";
const QString fieldSepText = "\t";
const QString rowSepText = "\r\n";

// Table headers
if (withHeaders) { if (withHeaders) {
htmlResult.append("<tr><th>");
int firstColumn = indices.front().column(); int firstColumn = indices.front().column();
for(int i = firstColumn; i <= indices.back().column(); i++) { for(int i = firstColumn; i <= indices.back().column(); i++) {
QString headerText = model()->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString(); QString headerText = model()->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString();
if (i != firstColumn) if (i != firstColumn) {
result.append("\t"); result.append(fieldSepText);
htmlResult.append("</th><th>");
}
result.append(QString("\"%1\"").arg(headerText)); result.append(QString("\"%1\"").arg(headerText));
htmlResult.append(headerText);
} }
result.append("\r\n"); result.append(rowSepText);
htmlResult.append("</th></tr>");
} }
for(const QModelIndex& index : indices) {
if (first == index) { /* first index */ }
else if (index.row() != currentRow)
result.append("\r\n");
else
result.append("\t");


// Table data rows
for(const QModelIndex& index : indices) {
// Separators
if (first == index)
htmlResult.append("<tr><td>");
else if (index.row() != currentRow) {
result.append(rowSepText);
htmlResult.append(rowSepHtml);
} else {
result.append(fieldSepText);
htmlResult.append(fieldSepHtml);
}
currentRow = index.row(); currentRow = index.row();
QVariant data = index.data(Qt::EditRole); QVariant data = index.data(Qt::EditRole);


// Table cell data
htmlResult.append(data.toString().toHtmlEscaped());
// non-NULL data is enquoted, whilst NULL isn't // non-NULL data is enquoted, whilst NULL isn't
if (!data.isNull()) { if (!data.isNull()) {
QString text = data.toString(); QString text = data.toString();
Expand All @@ -248,7 +269,11 @@ void ExtendedTableWidget::copy(const bool withHeaders)
} }
} }


qApp->clipboard()->setText(result); QMimeData *mimeData = new QMimeData;
mimeData->setHtml(htmlResult + "</td></tr></table></body></html>");
mimeData->setText(result);
qApp->clipboard()->setMimeData(mimeData);

} }


void ExtendedTableWidget::paste() void ExtendedTableWidget::paste()
Expand All @@ -263,9 +288,11 @@ void ExtendedTableWidget::paste()


SqliteTableModel* m = qobject_cast<SqliteTableModel*>(model()); SqliteTableModel* m = qobject_cast<SqliteTableModel*>(model());


// If clipboard contains image - just insert it // If clipboard contains image and not text - just insert the image
QImage img = qApp->clipboard()->image(); const QMimeData* mimeClipboard = qApp->clipboard()->mimeData();
if (!img.isNull()) {
if (mimeClipboard->hasImage() && !mimeClipboard->hasText()) {
QImage img = qApp->clipboard()->image();
QByteArray ba; QByteArray ba;
QBuffer buffer(&ba); QBuffer buffer(&ba);
buffer.open(QIODevice::WriteOnly); buffer.open(QIODevice::WriteOnly);
Expand Down

0 comments on commit e60e9ff

Please sign in to comment.