From c04bf0f0754cde77f3f28aecfec65316be2159c2 Mon Sep 17 00:00:00 2001 From: mwganson Date: Thu, 14 Nov 2024 01:31:04 +0000 Subject: [PATCH] [core] add copy table and paste table context menu items to App::PropertyVectorList property editor, addresses issue #17804 --- src/Gui/VectorListEditor.cpp | 92 ++++++++++++++++++++++++++++++++++++ src/Gui/VectorListEditor.h | 4 ++ 2 files changed, 96 insertions(+) diff --git a/src/Gui/VectorListEditor.cpp b/src/Gui/VectorListEditor.cpp index 40d584ab51..cb181b6893 100644 --- a/src/Gui/VectorListEditor.cpp +++ b/src/Gui/VectorListEditor.cpp @@ -26,6 +26,12 @@ #include "ui_VectorListEditor.h" #include "QuantitySpinBox.h" +#include + +#include +#include +#include + using namespace Gui; @@ -132,6 +138,74 @@ void VectorTableModel::setValues(const QList& d) endResetModel(); } +void Gui::VectorTableModel::copyToClipboard() const +{ + QString clipboardText; + QTextStream stream(&clipboardText); + + for (const auto& vector : vectors) { + stream << QString::number(vector.x, 'f', decimals) << '\t' + << QString::number(vector.y, 'f', decimals) << '\t' + << QString::number(vector.z, 'f', decimals) << '\n'; + } + + QApplication::clipboard()->setText(clipboardText); +} + +void Gui::VectorTableModel::pasteFromClipboard() +{ + QClipboard *clipboard = QApplication::clipboard(); + QStringList lines = clipboard->text().split(QLatin1Char('\n')); + bool okAll = !lines.empty(); + QList newVectors; + QLatin1Char tab('\t'); + QLatin1Char semicolon(';'); + QLatin1Char comma(','); + + for (const QString& line : lines) { + if (line.isEmpty()) { + continue; + } + QChar delimiter = line.count(tab) == 2 ? tab + : line.count(semicolon) == 2 ? semicolon + : line.count(comma) == 2 ? comma + : QChar(QChar::Null); + + if (delimiter.isNull()) { + okAll = false; + break; + } + + QStringList components = line.split(delimiter); + + if (components.size() == 3) { + bool okX, okY, okZ; + double x = components.at(0).toDouble(&okX); + double y = components.at(1).toDouble(&okY); + double z = components.at(2).toDouble(&okZ); + + if (!okX || !okY || !okZ) { + okAll = false; + break; + } + newVectors.append(Base::Vector3d(x, y, z)); + } + else { + okAll = false; + break; + } + } + + if (okAll) { + setValues(newVectors); + } + else { + QString msg(tr("Unsupported format. Must be 3 values per row separated by tabs, semicolons, or commas:") + QLatin1String("\n")); + msg += clipboard->text(); + Base::Console().Error(msg.toStdString().c_str()); + } +} + const QList& VectorTableModel::values() const { return vectors; @@ -238,10 +312,28 @@ VectorListEditor::VectorListEditor(int decimals, QWidget* parent) connect(ui->toolButtonRemove, &QToolButton::clicked, this, &VectorListEditor::removeRow); connect(ui->toolButtonAccept, &QToolButton::clicked, this, &VectorListEditor::acceptCurrent); connect(ui->tableWidget, &QTableView::clicked, this, &VectorListEditor::clickedRow); + + ui->tableWidget->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->tableWidget, &QWidget::customContextMenuRequested, this, &VectorListEditor::showContextMenu); + } VectorListEditor::~VectorListEditor() = default; +void VectorListEditor::showContextMenu(const QPoint& pos) +{ + QMenu contextMenu(ui->tableWidget); + QAction *copyAction = contextMenu.addAction(tr("Copy table")); + connect(copyAction, &QAction::triggered, model, &VectorTableModel::copyToClipboard); + copyAction->setEnabled(!data.empty()); + + QAction *pasteAction = contextMenu.addAction(tr("Paste table")); + connect(pasteAction, &QAction::triggered, model, &VectorTableModel::pasteFromClipboard); + pasteAction->setEnabled(QApplication::clipboard()->mimeData()->hasText()); + + contextMenu.exec(ui->tableWidget->viewport()->mapToGlobal(pos)); +} + void VectorListEditor::setValues(const QList& v) { data = v; diff --git a/src/Gui/VectorListEditor.h b/src/Gui/VectorListEditor.h index 875bc47ef1..c7b55d3cff 100644 --- a/src/Gui/VectorListEditor.h +++ b/src/Gui/VectorListEditor.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -49,6 +50,8 @@ public: QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QModelIndex parent(const QModelIndex &index) const override; void setValues(const QList& d); + void copyToClipboard() const; + void pasteFromClipboard(); const QList& values() const; bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override; bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override; @@ -100,6 +103,7 @@ private Q_SLOTS: void acceptCurrent(); void setCurrentRow(int); void clickedRow(const QModelIndex&); + void showContextMenu(const QPoint&); private: std::unique_ptr ui;