numberator/tagitem.cpp
2020-12-17 15:43:37 +01:00

134 lines
4.8 KiB
C++

#include "tagitem.h"
#include "tagscene.h"
#include <QPainter>
#include <QGuiApplication>
#include <QGraphicsScene>
#include <QGraphicsSceneMouseEvent>
TagItem::TagItem(const Tag &tag)
: valid(true)
, m_margins(2, 2, 2, 2)
{
setFlags(QGraphicsItem::ItemIsSelectable
| QGraphicsItem::ItemIsFocusable
| QGraphicsItem::ItemIgnoresTransformations
| QGraphicsItem::ItemSendsGeometryChanges);
QFont font(QGuiApplication::font());
font.setPointSize(12);
setFont(font);
tagUpdated(tag);
}
void TagItem::tagUpdated(const Tag &tag)
{
m_tag = tag;
qDebug() << "TagItem updated" << tag.name << tag.anchor;
setText(tag.name);
setPos(tag.anchor);
}
QRectF TagItem::boundingRect() const
{
QRectF parentRect(QGraphicsSimpleTextItem::boundingRect());
parentRect.translate(-(parentRect.bottomRight() - parentRect.topLeft()) * 0.5);
return parentRect.marginsAdded(m_margins);
}
/* For some reason this is not exposed through the public API so we have to copy-paste it here m( */
static void paintSelectionHighlightBorder(QPainter *painter, const QStyleOptionGraphicsItem *option, TagItem *item)
{
const QRectF mbrect = painter->transform().mapRect(item->boundingRect());
if (qMin(mbrect.width(), mbrect.height()) < qreal(1.0))
return;
const qreal pad = item->pen().widthF() / 2;
const qreal penWidth = 0; // cosmetic pen
const QColor fgcolor = option->palette.windowText().color();
const QColor bgcolor( // ensure good contrast against fgcolor
fgcolor.red() > 127 ? 0 : 255,
fgcolor.green() > 127 ? 0 : 255,
fgcolor.blue() > 127 ? 0 : 255);
painter->setPen(QPen(bgcolor, penWidth, Qt::SolidLine));
painter->setBrush(Qt::NoBrush);
painter->drawRect(item->boundingRect().adjusted(pad, pad, -pad, -pad));
painter->setPen(QPen(option->palette.windowText(), 0, Qt::DashLine));
painter->setBrush(Qt::NoBrush);
painter->drawRect(item->boundingRect().adjusted(pad, pad, -pad, -pad));
}
void TagItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
bool selectionHighlight = option->state & (QStyle::State_Selected | QStyle::State_HasFocus);
if (selectionHighlight)
painter->setBrush(QColor("#80aaaaff"));
else
painter->setBrush(QColor("#80ffffff"));
painter->drawRect(boundingRect());
QRectF parentRect(QGraphicsSimpleTextItem::boundingRect());
QPointF pos = (parentRect.bottomRight() - parentRect.topLeft()) * 0.5;
painter->translate(-pos);
QStyleOptionGraphicsItem newOption(*option);
newOption.state = ~(QStyle::State_Selected |QStyle::State_HasFocus);
QGraphicsSimpleTextItem::paint(painter, &newOption, widget);
painter->translate(pos);
if (selectionHighlight)
paintSelectionHighlightBorder(painter, option, this);
}
QPainterPath TagItem::shape() const
{
QPainterPath path;
return QGraphicsItem::shape();
}
QVariant TagItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
{
//qDebug() << "itemChange" << m_tag.name << this->boundingRect() << change;
if (change == ItemSceneChange) {
assert(qvariant_cast<TagScene *>(value)); /* TagItems must only be used in TagScene. */
} else if (change == ItemPositionChange) {
/* https://gist.github.com/csukuangfj/c2a06416062bec9ed99eddd705c21275#file-qgraphicsscenetest-cpp-L90
*
*/
/* FIXME */
} else if (change == ItemSelectedChange) {
if (!value.toBool())
setFlag(QGraphicsItem::ItemIsMovable, false);
}
return QGraphicsItem::itemChange(change, value);
}
void TagItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton) {
QPoint delta = event->screenPos() - event->buttonDownScreenPos(Qt::LeftButton);
int pixelThreshold = 10;
if (QPoint::dotProduct(delta, delta) > pixelThreshold*pixelThreshold)
dragAboveThreshold = true;
if (!dragAboveThreshold) {
// patch up event to prevent small movements
event->setPos(event->buttonDownPos(Qt::LeftButton));
event->setScenePos(event->buttonDownScenePos(Qt::LeftButton));
event->setScreenPos(event->buttonDownScreenPos(Qt::LeftButton));
}
}
QGraphicsItem::mouseMoveEvent(event);
}
void TagItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
Q_UNUSED(event);
dragAboveThreshold = false;
if (isSelected())
setFlag(QGraphicsItem::ItemIsMovable, true);
else
setFlag(QGraphicsItem::ItemIsMovable, false);
QGraphicsItem::mouseReleaseEvent(event);
}