Skip to content

Commit

Permalink
Merge pull request #990 from Quick-Event/nefunkcni-copy-qe2
Browse files Browse the repository at this point in the history
Nefunkční copy&paste v záložce Úseky/Etapy #969
  • Loading branch information
fvacek authored Nov 3, 2024
2 parents 8874a52 + c4b7746 commit eb792c9
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 92 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,5 @@ Makefile*
*.qmlproject.user.*

_work/*
build
doc/book
2 changes: 1 addition & 1 deletion libqf/libqfqmlwidgets/src/framework/logwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ LogWidgetTableView::LogWidgetTableView(QWidget *parent)
void LogWidgetTableView::copy()
{
qfLogFuncFrame();
qf::qmlwidgets::TableView::copySelectionToClipboard(this);
TableView::copySelectionToClipboard(this);
}

class LogFilterProxyModel : public QSortFilterProxyModel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ DlgTableViewCopySpecial::DlgTableViewCopySpecial(QWidget *parent)
{
ui = new Ui::DlgTableViewCopySpecial;
ui->setupUi(this);

ui->lstReplaceEscapes->addItem(tr("Quote field if needed"), static_cast<int>(TableView::ReplaceEscapes::QuoteIfNeeded));
ui->lstReplaceEscapes->addItem(tr("Never"), static_cast<int>(TableView::ReplaceEscapes::Never));
ui->lstReplaceEscapes->addItem(tr("Always"), static_cast<int>(TableView::ReplaceEscapes::Always));
ui->lstReplaceEscapes->setCurrentIndex(0);
}

DlgTableViewCopySpecial::~DlgTableViewCopySpecial()
Expand All @@ -30,8 +35,8 @@ QString DlgTableViewCopySpecial::rowsSeparator()
return ui->edRowsSeparator->text();
}

bool DlgTableViewCopySpecial::replaceEscapes()
qf::qmlwidgets::TableView::ReplaceEscapes DlgTableViewCopySpecial::replaceEscapes()
{
return ui->chkReplaceEscapes->isChecked();
return static_cast<TableView::ReplaceEscapes>(ui->lstReplaceEscapes->currentData().toInt());
}

4 changes: 3 additions & 1 deletion libqf/libqfqmlwidgets/src/internal/dlgtableviewcopyspecial.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

#include <QDialog>

#include "../tableview.h"

namespace qf {
namespace qmlwidgets {
namespace internal {
Expand All @@ -21,7 +23,7 @@ class DlgTableViewCopySpecial : public QDialog
QString fieldsSeparator();
QString rowsSeparator();
QString fieldsQuotes();
bool replaceEscapes();
qf::qmlwidgets::TableView::ReplaceEscapes replaceEscapes();
private:
Ui::DlgTableViewCopySpecial *ui;
};
Expand Down
30 changes: 15 additions & 15 deletions libqf/libqfqmlwidgets/src/internal/dlgtableviewcopyspecial.ui
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>140</height>
<width>404</width>
<height>181</height>
</rect>
</property>
<property name="windowTitle">
Expand Down Expand Up @@ -37,17 +37,17 @@
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<item row="1" column="1">
<widget class="QLineEdit" name="edRowsSeparator">
<property name="text">
<string>fields quotes</string>
<string>\n</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="edRowsSeparator">
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>\n</string>
<string>fields quotes</string>
</property>
</widget>
</item>
Expand All @@ -58,25 +58,25 @@
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QCheckBox" name="chkReplaceEscapes">
<property name="toolTip">
<string>Replace nonprintable characters with escape sequencies</string>
</property>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>replace escapes</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="lstReplaceEscapes"/>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Vertical</enum>
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
</property>
</widget>
</item>
Expand Down
137 changes: 66 additions & 71 deletions libqf/libqfqmlwidgets/src/tableview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,44 +144,9 @@ QAbstractProxyModel* TableView::lastProxyModel() const
return ret;
}

void TableView::copySelectionToClipboard(QTableView *table_view)
void TableView::copySelectionToClipboard(const QTableView *table_view)
{
qfLogFuncFrame();
auto *m = table_view->model();
if(!m)
return;
int n = 0;
QString rows;
QItemSelection sel = table_view->selectionModel()->selection();
foreach(const QItemSelectionRange &sel1, sel) {
if(sel1.isValid()) {
for(int row=sel1.top(); row<=sel1.bottom(); row++) {
QString cells;
for(int col=sel1.left(); col<=sel1.right(); col++) {
QModelIndex ix = m->index(row, col);
QString s;
s = ix.data(Qt::DisplayRole).toString();
static constexpr bool replace_escapes = true;
if(replace_escapes) {
s.replace('\r', QStringLiteral("\\r"));
s.replace('\n', QStringLiteral("\\n"));
s.replace('\t', QStringLiteral("\\t"));
}
if(col > sel1.left())
cells += '\t';
cells += s;
}
if(n++ > 0)
rows += '\n';
rows += cells;
}
}
}
if(!rows.isEmpty()) {
//qfInfo() << "\tSetting clipboard:" << rows;
QClipboard *clipboard = QApplication::clipboard();
clipboard->setText(rows);
}
copySpecial_helper(table_view, "\t", "\n", "", ReplaceEscapes::QuoteIfNeeded);
}

void TableView::setModel(QAbstractItemModel *model)
Expand Down Expand Up @@ -537,14 +502,14 @@ int TableView::reloadRow(int row_no)
void TableView::copy()
{
qfLogFuncFrame();
copySpecial_helper("\t", "\n", QString(), true);
copySelectionToClipboard();
}

void TableView::copySpecial()
{
internal::DlgTableViewCopySpecial dlg(this);
if(dlg.exec()) {
copySpecial_helper(dlg.fieldsSeparator(), dlg.rowsSeparator(), dlg.fieldsQuotes(), dlg.replaceEscapes());
copySpecial_helper(this, dlg.fieldsSeparator(), dlg.rowsSeparator(), dlg.fieldsQuotes(), dlg.replaceEscapes());
}
}

Expand Down Expand Up @@ -1974,48 +1939,78 @@ void TableView::createActions()
}
}

void TableView::copySpecial_helper(const QString &fields_separator, const QString &rows_separator, const QString &field_quotes, bool replace_escapes)
void TableView::copySpecial_helper(const QTableView *table_view, const QString &fields_separator, const QString &rows_separator, const QString &field_quotes, ReplaceEscapes replace_escapes)
{
qfLogFuncFrame();
auto *m = model();
auto *m = table_view->model();
if(!m)
return;
int n = 0;
QString rows;
QItemSelection sel = selectionModel()->selection();
foreach(QItemSelectionRange sel1, sel) {
//QItemSelectionRange sel1 = sel.value(0);
if(sel1.isValid()) {
//qfInfo() << "sel count:" << sel.count() << "sel range left:" << sel1.left() << "right:" << sel1.right() << "top:" << sel1.top() << "bottom:" << sel1.bottom();
for(int row=sel1.top(); row<=sel1.bottom(); row++) {
QString cells;
for(int col=sel1.left(); col<=sel1.right(); col++) {
QModelIndex ix = m->index(row, col);
QString s;
if(!ix.data(qf::core::model::TableModel::ValueIsNullRole).toBool()) {
s = ix.data(Qt::DisplayRole).toString();
if(s.isEmpty()) {
QVariant v = ix.data(Qt::CheckStateRole);
if(v.isValid()) {
s = (v.toInt() == Qt::Checked)? QStringLiteral("True"): QStringLiteral("False");
}
auto selection_union = [](const QItemSelection &selection) {
QMap<int, QList<int>> res;
foreach(QItemSelectionRange sel, selection) {
for(int row = sel.top(); row <= sel.bottom(); row++) {
for(int col = sel.left(); col <= sel.right(); col++) {
auto &cols = res[row];
if (auto lower = std::lower_bound(cols.begin(), cols.end(), col); lower == cols.end()) {
cols << col;
}
else {
if (*lower != col) {
cols.insert((lower - cols.begin()), col);
}
}
if(replace_escapes) {
s.replace('\r', QStringLiteral("\\r"));
s.replace('\n', QStringLiteral("\\n"));
s.replace('\t', QStringLiteral("\\t"));
}
}
}
return res;
};
QString rows;
int row_cnt = 0;
auto sel = selection_union(table_view->selectionModel()->selection());
QMapIterator<int, QList<int>> it(sel);
while (it.hasNext()) {
it.next();
auto row = it.key();
auto cols = it.value();
int col_cnt = 0;
QString cells;
for (auto col : cols) {
QModelIndex ix = m->index(row, col);
QString s;
if(!ix.data(qf::core::model::TableModel::ValueIsNullRole).toBool()) {
s = ix.data(Qt::DisplayRole).toString();
if(s.isEmpty()) {
QVariant v = ix.data(Qt::CheckStateRole);
if(v.isValid()) {
s = (v.toInt() == Qt::Checked)? QStringLiteral("True"): QStringLiteral("False");
}
//qfInfo() << ix.row() << '\t' << ix.column() << '\t' << s;
if(col > sel1.left())
cells += fields_separator;
cells += (field_quotes + s + field_quotes);
}
if(n++ > 0)
rows += rows_separator;
rows += cells;
}
if(replace_escapes == ReplaceEscapes::Always) {
s.replace('\r', QStringLiteral("\\r"));
s.replace('\n', QStringLiteral("\\n"));
s.replace('\t', QStringLiteral("\\t"));
}
if(replace_escapes == ReplaceEscapes::QuoteIfNeeded) {
if (s.indexOf('\n') >= 0
|| s.indexOf('\r') >= 0
|| s.indexOf('\t') >= 0
) {
s = (field_quotes + s + field_quotes);
}
}
else {
s = (field_quotes + s + field_quotes);
}
//qfInfo() << "row:" << row << "col:" << col << "index:" << ix.row() << ',' << ix.column() << '\t' << s;
if(col_cnt++ > 0) {
cells += fields_separator;
}
cells += s;
}
if(row_cnt++ > 0)
rows += rows_separator;
rows += cells;
}
if(!rows.isEmpty()) {
qfDebug() << "\tSetting clipboard:" << rows;
Expand Down
6 changes: 4 additions & 2 deletions libqf/libqfqmlwidgets/src/tableview.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,9 @@ class QFQMLWIDGETS_DECL_EXPORT TableView : public QTableView, public framework::

Q_SIGNAL void sqlException(const QString &what, const QString &where, const QString &stack_trace);

static void copySelectionToClipboard(QTableView *table_view);
enum class ReplaceEscapes {Never, Always, QuoteIfNeeded};
static void copySelectionToClipboard(const QTableView *table_view);
void copySelectionToClipboard() const { copySelectionToClipboard(this); }

Q_SLOT void loadPersistentSettings();
Q_SLOT void savePersistentSettings();
Expand Down Expand Up @@ -193,7 +195,7 @@ class QFQMLWIDGETS_DECL_EXPORT TableView : public QTableView, public framework::
virtual void createActions();

void setValueInSelection_helper(const QVariant &new_val);
void copySpecial_helper(const QString &fields_separator, const QString &rows_separator, const QString &field_quotes, bool replace_escapes);
static void copySpecial_helper(const QTableView *table_view, const QString &fields_separator, const QString &rows_separator, const QString &field_quotes, ReplaceEscapes replace_escapes);
Q_SLOT void generateSequenceInSelection();

//static const int StandardContextMenuActionsGroups = AllActions & ~(SetValueActions | BlobActions | PasteActions);
Expand Down

0 comments on commit eb792c9

Please sign in to comment.