Avoid accidental truncation of cell data

For table cells with text larger than 32768 characters, the data gets
truncated. If the user doesn't notice this somehow and hits the Escape
key the truncated data is written back to the database resulting in a
possible data loss.

This problem is fixed by this commit in two ways:
1) The maximum length of the editor widgets is increased to the maximum
value making this problem much more unlikely.
2) If the user is still hitting this value, i.e. the text is truncated
anyway, the widget is put into read only mode and no data is written
back to the database.

See issue #1281.
This commit is contained in:
Martin Kleusberg
2017-12-31 12:47:44 +01:00
parent e7a810913f
commit a98cd8e8f9
2 changed files with 62 additions and 0 deletions

View File

@@ -15,6 +15,8 @@
#include <QBuffer>
#include <QMenu>
#include <QDateTime>
#include <QLineEdit>
#include <limits>
QList<QByteArrayList> ExtendedTableWidget::m_buffer;
QString ExtendedTableWidget::m_generatorStamp;
@@ -89,6 +91,46 @@ QList<QByteArrayList> parseClipboard(QString clipboard)
}
ExtendedTableWidgetEditorDelegate::ExtendedTableWidgetEditorDelegate(QObject* parent)
: QStyledItemDelegate(parent)
{
}
QWidget* ExtendedTableWidgetEditorDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/) const
{
// Just create a normal line editor but set the maximum length to the highest possible value instead of the default 32768.
QLineEdit* editor = new QLineEdit(parent);
editor->setMaxLength(std::numeric_limits<int>::max());
return editor;
}
void ExtendedTableWidgetEditorDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
{
QLineEdit* lineedit = static_cast<QLineEdit*>(editor);
// Set the data for the line editor
QString data = index.data(Qt::EditRole).toString();
lineedit->setText(data);
// Put the editor in read only mode if the actual data is larger than the maximum length to avoid accidental truncation of the data
lineedit->setReadOnly(data.size() > lineedit->maxLength());
}
void ExtendedTableWidgetEditorDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
{
// Only apply the data back to the model if the editor is not in read only mode to avoid accidental truncation of the data
QLineEdit* lineedit = static_cast<QLineEdit*>(editor);
if(!lineedit->isReadOnly())
model->setData(index, lineedit->text());
}
void ExtendedTableWidgetEditorDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& /*index*/) const
{
editor->setGeometry(option.rect);
}
ExtendedTableWidget::ExtendedTableWidget(QWidget* parent) :
QTableView(parent)
{
@@ -122,6 +164,10 @@ ExtendedTableWidget::ExtendedTableWidget(QWidget* parent) :
m_contextMenu->addAction(pasteAction);
setContextMenuPolicy(Qt::CustomContextMenu);
// Create and set up delegate
m_editorDelegate = new ExtendedTableWidgetEditorDelegate(this);
setItemDelegate(m_editorDelegate);
// This is only for displaying the shortcut in the context menu.
// An entry in keyPressEvent is still needed.
nullAction->setShortcut(QKeySequence(tr("Alt+Del")));

View File

@@ -5,11 +5,26 @@
#include <QSet>
#include <QDropEvent>
#include <QDragMoveEvent>
#include <QStyledItemDelegate>
class QMenu;
class FilterTableHeader;
namespace sqlb { class ObjectIdentifier; }
// We use this class to provide editor widgets for the ExtendedTableWidget. It's used for every cell in the table view.
class ExtendedTableWidgetEditorDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
explicit ExtendedTableWidgetEditorDelegate(QObject* parent = nullptr);
QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
void setEditorData(QWidget* editor, const QModelIndex& index) const override;
void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override;
void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
};
class ExtendedTableWidget : public QTableView
{
Q_OBJECT
@@ -55,6 +70,7 @@ protected:
FilterTableHeader* m_tableHeader;
QMenu* m_contextMenu;
ExtendedTableWidgetEditorDelegate* m_editorDelegate;
};
#endif