181 lines
4.6 KiB
C++
181 lines
4.6 KiB
C++
#include "lineedittag.h"
|
|
|
|
#include <QKeyEvent>
|
|
#include <QPainter>
|
|
#include <QDebug>
|
|
#include <QPainterPath>
|
|
|
|
LineEditTag::LineEditTag(QWidget *parent)
|
|
: QLineEdit (parent)
|
|
{
|
|
setMinimumHeight(24);
|
|
}
|
|
|
|
LineEditTag::~LineEditTag()
|
|
{
|
|
|
|
}
|
|
|
|
QStringList LineEditTag::getTags() const
|
|
{
|
|
return tags;
|
|
}
|
|
|
|
QString LineEditTag::getTagsStr() const
|
|
{
|
|
return tags.join(' ');
|
|
}
|
|
|
|
void LineEditTag::setTags(const QString& tags)
|
|
{
|
|
if (!tags.isEmpty())
|
|
{
|
|
this->tags = tags.split(' ');
|
|
clear();
|
|
update();
|
|
}
|
|
}
|
|
|
|
void LineEditTag::setTags(const QStringList& tags)
|
|
{
|
|
if (!tags.isEmpty())
|
|
{
|
|
this->tags = tags;
|
|
clear();
|
|
update();
|
|
}
|
|
}
|
|
|
|
void LineEditTag::addTag()
|
|
{
|
|
if (!text().isEmpty())
|
|
{
|
|
tags.append(text());
|
|
clear();
|
|
update();
|
|
}
|
|
}
|
|
|
|
void LineEditTag::leaveEvent(QEvent *evt)
|
|
{
|
|
QLineEdit::leaveEvent(evt);
|
|
cursorPos = clickedPos = QPoint();
|
|
}
|
|
|
|
void LineEditTag::keyPressEvent(QKeyEvent *evt)
|
|
{
|
|
if (evt->key() == Qt::Key_Return || evt->key() == Qt::Key_Enter || evt->key() == Qt::Key_Space)
|
|
{
|
|
evt->accept();
|
|
addTag();
|
|
}
|
|
else
|
|
{
|
|
QLineEdit::keyPressEvent(evt);
|
|
}
|
|
}
|
|
|
|
void LineEditTag::mousePressEvent(QMouseEvent *evt)
|
|
{
|
|
clickedPos = evt->pos();
|
|
QLineEdit::mousePressEvent(evt);
|
|
}
|
|
|
|
void LineEditTag::mouseMoveEvent(QMouseEvent *evt)
|
|
{
|
|
QLineEdit::mouseMoveEvent(evt);
|
|
cursorPos = evt->pos();
|
|
}
|
|
|
|
void LineEditTag::paintEvent(QPaintEvent *evt)
|
|
{
|
|
QLineEdit::paintEvent(evt);
|
|
|
|
QPainter painter(this);
|
|
painter.setRenderHint(QPainter::Antialiasing);
|
|
|
|
QFontMetrics fm = fontMetrics();
|
|
QRectF r = rect();
|
|
double space = double(r.height()-fm.height())/2;
|
|
int padding = 4;
|
|
int cross_size = int(r.height()-space*2);
|
|
r.setX(padding);
|
|
r.setY(double(r.height()-fm.height())/4);
|
|
QPen pen = painter.pen();
|
|
QBrush brush = painter.brush();
|
|
// Stackoverflow tag like
|
|
QColor tag_bg(225, 236, 244);
|
|
QColor tag_txt(44, 87, 119);
|
|
int x_offset = padding;
|
|
int idx = 0;
|
|
for (const QString& tag : tags)
|
|
{
|
|
QRect tag_rect = fm.boundingRect(tag);
|
|
r.setWidth(tag_rect.width()+(padding*2)+(padding+cross_size));
|
|
r.setHeight(tag_rect.height()+space);
|
|
QRectF cross_rect = QRectF(r.x()+r.width()-cross_size-padding, space, cross_size, cross_size);
|
|
if (cross_rect.contains(clickedPos))
|
|
{
|
|
clickedPos = QPoint();
|
|
tags.removeAt(idx);
|
|
}
|
|
else
|
|
{
|
|
QPainterPath tag_path;
|
|
tag_path.addRoundedRect(r, 2, 2);
|
|
// Draw tag background and text
|
|
painter.fillPath(tag_path, QBrush(tag_bg));
|
|
painter.setPen(tag_txt);
|
|
painter.drawText(QRectF(r.x()+padding, 0, tag_rect.width(), height()), Qt::AlignVCenter, tag);
|
|
// Draw the cross to remove tag
|
|
bool isHovered = r.contains(cursorPos);
|
|
if (isHovered)
|
|
{
|
|
// Manage the hovered
|
|
QPainterPath cross_path;
|
|
cross_path.addRoundedRect(cross_rect, 2, 2);
|
|
painter.fillPath(cross_path, QBrush(tag_txt));
|
|
// Manage the remove tag mouse cursor
|
|
if (cross_rect.contains(cursorPos))
|
|
{
|
|
setCursor(Qt::PointingHandCursor);
|
|
}
|
|
else
|
|
{
|
|
setCursor(Qt::ArrowCursor);
|
|
}
|
|
}
|
|
pen.setWidth(2);
|
|
pen.setColor( (isHovered ? tag_bg : tag_txt) );
|
|
painter.setPen(pen);
|
|
QPointF topL = cross_rect.topLeft(), topR = cross_rect.topRight(), botL = cross_rect.bottomLeft(), botR = cross_rect.bottomRight();
|
|
topL.setX(topL.x()+3);
|
|
topL.setY(topL.y()+3);
|
|
topR.setX(topR.x()-3);
|
|
topR.setY(topR.y()+3);
|
|
botL.setX(botL.x()+3);
|
|
botL.setY(botL.y()-3);
|
|
botR.setX(botR.x()-3);
|
|
botR.setY(botR.y()-3);
|
|
painter.drawLine(topL, botR);
|
|
painter.drawLine(topR, botL);
|
|
|
|
x_offset += r.width()+(padding);
|
|
r.setX(x_offset);
|
|
idx++;
|
|
}
|
|
}
|
|
|
|
if (textMargins().left() != (x_offset))
|
|
{
|
|
if (tags.isEmpty())
|
|
{
|
|
setTextMargins(0, 0, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
setTextMargins(x_offset-padding, 0, 0, 0);
|
|
}
|
|
}
|
|
}
|