summaryrefslogtreecommitdiff
path: root/tagitem.cpp
blob: 8c17ba6a19424d70af118f1451d97f24b6576856 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#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);
}