#include "tagitem.h" #include "tagscene.h" #include #include #include #include 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(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); }