Skip to content

Instantly share code, notes, and snippets.

@jniemann66
Created July 13, 2018 06:08
Show Gist options
  • Save jniemann66/9cf45f4a2a0e2822b7542eea948410c6 to your computer and use it in GitHub Desktop.
Save jniemann66/9cf45f4a2a0e2822b7542eea948410c6 to your computer and use it in GitHub Desktop.
Qt Swipe-To-Edit Delegate
#include "swipetoeditdelegate.h"
#include <QApplication>
#include <QDebug>
#include <QMouseEvent>
#include <QTextDocument>
SwipeToEditDelegate::SwipeToEditDelegate(QObject* parent) : QStyledItemDelegate(parent), minRectWidth(10), activationThreshold(0.5), color("red")
{
}
void SwipeToEditDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
painter->save();
if (option.state & QStyle::State_Selected)
painter->fillRect(option.rect, option.palette.highlight());
QRect r(option.rect.topRight() - QPoint((index.row() == lastIndex.row()) ? rectWidth : minRectWidth, 0), option.rect.bottomRight());
QColor _color(color);
_color.setAlpha(255 * r.width() / option.rect.width());
painter->fillRect(r, QBrush(_color));
if(r.width() > activationThreshold * option.rect.width()) {
QTextDocument document;
document.setHtml("<p style=\"color:white;text-align:left;\"><b>Edit ...</b></p>");
painter->translate(r.center());
document.drawContents(painter);
}
painter->restore();
}
bool SwipeToEditDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index)
{
switch (event->type()) {
case QEvent::MouseMove:
{
if(index.row() != lastIndex.row()) { // row changed - reset rectangle
rectWidth = minRectWidth;
return QStyledItemDelegate::editorEvent(event, model, option, index);
}
QPoint mousePos = static_cast<QMouseEvent*>(event)->pos();
int edgex = option.rect.right();
rectWidth = std::min(std::max(minRectWidth, edgex - mousePos.x()), option.rect.width() - minRectWidth);
if(rectWidth >= option.rect.width() - minRectWidth) {
// reached all the way to the end; user really wants to edit !
// (Also, once user moves into another cell, this delegate will no longer "hear" any events, which is problematic)
emit editRequest(index);
rectWidth = minRectWidth;
}
return true;
}
case QEvent::MouseButtonPress:
lastIndex = index;
rectWidth = minRectWidth;
break;
case QEvent::MouseButtonRelease:
if(index.row() == lastIndex.row() && rectWidth >= activationThreshold * option.rect.width()) {
emit editRequest(index);
}
lastIndex = index;
rectWidth = minRectWidth;
break;
default:
qDebug() << event;
break;
}
return QStyledItemDelegate::editorEvent(event, model, option, index);
}
QColor SwipeToEditDelegate::getColor() const
{
return color;
}
void SwipeToEditDelegate::setColor(const QColor& value)
{
color = value;
}
#ifndef SWIPETOEDITDELEGATE_H
#define SWIPETOEDITDELEGATE_H
#include <QObject>
#include <QStyledItemDelegate>
#include <QPainter>
class SwipeToEditDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
SwipeToEditDelegate(QObject* parent = nullptr);
QColor getColor() const;
void setColor(const QColor& value);
signals:
void editRequest(QModelIndex index);
protected:
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) override;
private:
int minRectWidth;
int rectWidth;
qreal activationThreshold;
QModelIndex lastIndex;
QColor color;
};
#endif // SWIPETOEDITDELEGATE_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment