Change indentation to 4 spaces
This commit is contained in:
parent
e118f3882d
commit
cfca7157b9
165 changed files with 23146 additions and 23975 deletions
168
src/ui/Badge.cpp
168
src/ui/Badge.cpp
|
|
@ -9,214 +9,214 @@
|
|||
Badge::Badge(QWidget *parent)
|
||||
: OverlayWidget(parent)
|
||||
{
|
||||
init();
|
||||
init();
|
||||
}
|
||||
|
||||
Badge::Badge(const QIcon &icon, QWidget *parent)
|
||||
: OverlayWidget(parent)
|
||||
{
|
||||
init();
|
||||
setIcon(icon);
|
||||
init();
|
||||
setIcon(icon);
|
||||
}
|
||||
|
||||
Badge::Badge(const QString &text, QWidget *parent)
|
||||
: OverlayWidget(parent)
|
||||
{
|
||||
init();
|
||||
setText(text);
|
||||
init();
|
||||
setText(text);
|
||||
}
|
||||
|
||||
void
|
||||
Badge::init()
|
||||
{
|
||||
x_ = 0;
|
||||
y_ = 0;
|
||||
// TODO: Make padding configurable.
|
||||
padding_ = 5;
|
||||
diameter_ = 24;
|
||||
x_ = 0;
|
||||
y_ = 0;
|
||||
// TODO: Make padding configurable.
|
||||
padding_ = 5;
|
||||
diameter_ = 24;
|
||||
|
||||
setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
|
||||
QFont _font(font());
|
||||
_font.setPointSizeF(7.5);
|
||||
_font.setStyleName("Bold");
|
||||
QFont _font(font());
|
||||
_font.setPointSizeF(7.5);
|
||||
_font.setStyleName("Bold");
|
||||
|
||||
setFont(_font);
|
||||
setText("");
|
||||
setFont(_font);
|
||||
setText("");
|
||||
}
|
||||
|
||||
QString
|
||||
Badge::text() const
|
||||
{
|
||||
return text_;
|
||||
return text_;
|
||||
}
|
||||
|
||||
QIcon
|
||||
Badge::icon() const
|
||||
{
|
||||
return icon_;
|
||||
return icon_;
|
||||
}
|
||||
|
||||
QSize
|
||||
Badge::sizeHint() const
|
||||
{
|
||||
const int d = diameter();
|
||||
return QSize(d + 4, d + 4);
|
||||
const int d = diameter();
|
||||
return QSize(d + 4, d + 4);
|
||||
}
|
||||
|
||||
qreal
|
||||
Badge::relativeYPosition() const
|
||||
{
|
||||
return y_;
|
||||
return y_;
|
||||
}
|
||||
|
||||
qreal
|
||||
Badge::relativeXPosition() const
|
||||
{
|
||||
return x_;
|
||||
return x_;
|
||||
}
|
||||
|
||||
QPointF
|
||||
Badge::relativePosition() const
|
||||
{
|
||||
return QPointF(x_, y_);
|
||||
return QPointF(x_, y_);
|
||||
}
|
||||
|
||||
QColor
|
||||
Badge::backgroundColor() const
|
||||
{
|
||||
if (!background_color_.isValid())
|
||||
return QColor("black");
|
||||
if (!background_color_.isValid())
|
||||
return QColor("black");
|
||||
|
||||
return background_color_;
|
||||
return background_color_;
|
||||
}
|
||||
|
||||
QColor
|
||||
Badge::textColor() const
|
||||
{
|
||||
if (!text_color_.isValid())
|
||||
return QColor("white");
|
||||
if (!text_color_.isValid())
|
||||
return QColor("white");
|
||||
|
||||
return text_color_;
|
||||
return text_color_;
|
||||
}
|
||||
|
||||
void
|
||||
Badge::setTextColor(const QColor &color)
|
||||
{
|
||||
text_color_ = color;
|
||||
text_color_ = color;
|
||||
}
|
||||
|
||||
void
|
||||
Badge::setBackgroundColor(const QColor &color)
|
||||
{
|
||||
background_color_ = color;
|
||||
background_color_ = color;
|
||||
}
|
||||
|
||||
void
|
||||
Badge::setRelativePosition(const QPointF &pos)
|
||||
{
|
||||
setRelativePosition(pos.x(), pos.y());
|
||||
setRelativePosition(pos.x(), pos.y());
|
||||
}
|
||||
|
||||
void
|
||||
Badge::setRelativePosition(qreal x, qreal y)
|
||||
{
|
||||
x_ = x;
|
||||
y_ = y;
|
||||
update();
|
||||
x_ = x;
|
||||
y_ = y;
|
||||
update();
|
||||
}
|
||||
|
||||
void
|
||||
Badge::setRelativeXPosition(qreal x)
|
||||
{
|
||||
x_ = x;
|
||||
update();
|
||||
x_ = x;
|
||||
update();
|
||||
}
|
||||
|
||||
void
|
||||
Badge::setRelativeYPosition(qreal y)
|
||||
{
|
||||
y_ = y;
|
||||
update();
|
||||
y_ = y;
|
||||
update();
|
||||
}
|
||||
|
||||
void
|
||||
Badge::setIcon(const QIcon &icon)
|
||||
{
|
||||
icon_ = icon;
|
||||
update();
|
||||
icon_ = icon;
|
||||
update();
|
||||
}
|
||||
|
||||
void
|
||||
Badge::setText(const QString &text)
|
||||
{
|
||||
text_ = text;
|
||||
text_ = text;
|
||||
|
||||
if (!icon_.isNull())
|
||||
icon_ = QIcon();
|
||||
if (!icon_.isNull())
|
||||
icon_ = QIcon();
|
||||
|
||||
size_ = fontMetrics().size(Qt::TextShowMnemonic, text);
|
||||
size_ = fontMetrics().size(Qt::TextShowMnemonic, text);
|
||||
|
||||
update();
|
||||
update();
|
||||
}
|
||||
|
||||
void
|
||||
Badge::setDiameter(int diameter)
|
||||
{
|
||||
if (diameter > 0) {
|
||||
diameter_ = diameter;
|
||||
update();
|
||||
}
|
||||
if (diameter > 0) {
|
||||
diameter_ = diameter;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Badge::paintEvent(QPaintEvent *)
|
||||
{
|
||||
QPainter painter(this);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.translate(x_, y_);
|
||||
QPainter painter(this);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.translate(x_, y_);
|
||||
|
||||
QBrush brush;
|
||||
brush.setStyle(Qt::SolidPattern);
|
||||
QBrush brush;
|
||||
brush.setStyle(Qt::SolidPattern);
|
||||
|
||||
painter.setBrush(brush);
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.setBrush(brush);
|
||||
painter.setPen(Qt::NoPen);
|
||||
|
||||
const int d = diameter();
|
||||
const int d = diameter();
|
||||
|
||||
QRectF r(0, 0, d, d);
|
||||
r.translate(QPointF((width() - d), (height() - d)) / 2);
|
||||
QRectF r(0, 0, d, d);
|
||||
r.translate(QPointF((width() - d), (height() - d)) / 2);
|
||||
|
||||
if (icon_.isNull()) {
|
||||
QPen pen;
|
||||
// TODO: Make badge width configurable.
|
||||
pen.setWidth(1);
|
||||
pen.setColor(textColor());
|
||||
if (icon_.isNull()) {
|
||||
QPen pen;
|
||||
// TODO: Make badge width configurable.
|
||||
pen.setWidth(1);
|
||||
pen.setColor(textColor());
|
||||
|
||||
painter.setPen(pen);
|
||||
painter.drawEllipse(r);
|
||||
painter.setPen(pen);
|
||||
painter.drawEllipse(r);
|
||||
|
||||
painter.setPen(textColor());
|
||||
painter.setBrush(Qt::NoBrush);
|
||||
painter.drawText(r.translated(0, -0.5), Qt::AlignCenter, text_);
|
||||
} else {
|
||||
painter.drawEllipse(r);
|
||||
QRectF q(0, 0, 16, 16);
|
||||
q.moveCenter(r.center());
|
||||
QPixmap pixmap = icon().pixmap(16, 16);
|
||||
QPainter icon(&pixmap);
|
||||
icon.setCompositionMode(QPainter::CompositionMode_SourceIn);
|
||||
icon.fillRect(pixmap.rect(), textColor());
|
||||
painter.drawPixmap(q.toRect(), pixmap);
|
||||
}
|
||||
painter.setPen(textColor());
|
||||
painter.setBrush(Qt::NoBrush);
|
||||
painter.drawText(r.translated(0, -0.5), Qt::AlignCenter, text_);
|
||||
} else {
|
||||
painter.drawEllipse(r);
|
||||
QRectF q(0, 0, 16, 16);
|
||||
q.moveCenter(r.center());
|
||||
QPixmap pixmap = icon().pixmap(16, 16);
|
||||
QPainter icon(&pixmap);
|
||||
icon.setCompositionMode(QPainter::CompositionMode_SourceIn);
|
||||
icon.fillRect(pixmap.rect(), textColor());
|
||||
painter.drawPixmap(q.toRect(), pixmap);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
Badge::diameter() const
|
||||
{
|
||||
if (icon_.isNull()) {
|
||||
return qMax(size_.width(), size_.height()) + padding_;
|
||||
}
|
||||
if (icon_.isNull()) {
|
||||
return qMax(size_.width(), size_.height()) + padding_;
|
||||
}
|
||||
|
||||
return diameter_;
|
||||
return diameter_;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,54 +13,54 @@
|
|||
|
||||
class Badge : public OverlayWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QColor textColor WRITE setTextColor READ textColor)
|
||||
Q_PROPERTY(QColor backgroundColor WRITE setBackgroundColor READ backgroundColor)
|
||||
Q_PROPERTY(QPointF relativePosition WRITE setRelativePosition READ relativePosition)
|
||||
Q_PROPERTY(QColor textColor WRITE setTextColor READ textColor)
|
||||
Q_PROPERTY(QColor backgroundColor WRITE setBackgroundColor READ backgroundColor)
|
||||
Q_PROPERTY(QPointF relativePosition WRITE setRelativePosition READ relativePosition)
|
||||
|
||||
public:
|
||||
explicit Badge(QWidget *parent = nullptr);
|
||||
explicit Badge(const QIcon &icon, QWidget *parent = nullptr);
|
||||
explicit Badge(const QString &text, QWidget *parent = nullptr);
|
||||
explicit Badge(QWidget *parent = nullptr);
|
||||
explicit Badge(const QIcon &icon, QWidget *parent = nullptr);
|
||||
explicit Badge(const QString &text, QWidget *parent = nullptr);
|
||||
|
||||
void setBackgroundColor(const QColor &color);
|
||||
void setTextColor(const QColor &color);
|
||||
void setIcon(const QIcon &icon);
|
||||
void setRelativePosition(const QPointF &pos);
|
||||
void setRelativePosition(qreal x, qreal y);
|
||||
void setRelativeXPosition(qreal x);
|
||||
void setRelativeYPosition(qreal y);
|
||||
void setText(const QString &text);
|
||||
void setDiameter(int diameter);
|
||||
void setBackgroundColor(const QColor &color);
|
||||
void setTextColor(const QColor &color);
|
||||
void setIcon(const QIcon &icon);
|
||||
void setRelativePosition(const QPointF &pos);
|
||||
void setRelativePosition(qreal x, qreal y);
|
||||
void setRelativeXPosition(qreal x);
|
||||
void setRelativeYPosition(qreal y);
|
||||
void setText(const QString &text);
|
||||
void setDiameter(int diameter);
|
||||
|
||||
QIcon icon() const;
|
||||
QString text() const;
|
||||
QColor backgroundColor() const;
|
||||
QColor textColor() const;
|
||||
QPointF relativePosition() const;
|
||||
QSize sizeHint() const override;
|
||||
qreal relativeXPosition() const;
|
||||
qreal relativeYPosition() const;
|
||||
QIcon icon() const;
|
||||
QString text() const;
|
||||
QColor backgroundColor() const;
|
||||
QColor textColor() const;
|
||||
QPointF relativePosition() const;
|
||||
QSize sizeHint() const override;
|
||||
qreal relativeXPosition() const;
|
||||
qreal relativeYPosition() const;
|
||||
|
||||
int diameter() const;
|
||||
int diameter() const;
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
|
||||
private:
|
||||
void init();
|
||||
void init();
|
||||
|
||||
QColor background_color_;
|
||||
QColor text_color_;
|
||||
QColor background_color_;
|
||||
QColor text_color_;
|
||||
|
||||
QIcon icon_;
|
||||
QSize size_;
|
||||
QString text_;
|
||||
QIcon icon_;
|
||||
QSize size_;
|
||||
QString text_;
|
||||
|
||||
int padding_;
|
||||
int diameter_;
|
||||
int padding_;
|
||||
int diameter_;
|
||||
|
||||
qreal x_;
|
||||
qreal y_;
|
||||
qreal x_;
|
||||
qreal y_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -19,94 +19,89 @@ DropShadow::draw(QPainter &painter,
|
|||
qreal width,
|
||||
qreal height)
|
||||
{
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.setPen(Qt::NoPen);
|
||||
|
||||
QLinearGradient gradient;
|
||||
gradient.setColorAt(startPosition, start);
|
||||
gradient.setColorAt(endPosition0, end);
|
||||
QLinearGradient gradient;
|
||||
gradient.setColorAt(startPosition, start);
|
||||
gradient.setColorAt(endPosition0, end);
|
||||
|
||||
// Right
|
||||
QPointF right0(width - margin, height / 2);
|
||||
QPointF right1(width, height / 2);
|
||||
gradient.setStart(right0);
|
||||
gradient.setFinalStop(right1);
|
||||
painter.setBrush(QBrush(gradient));
|
||||
// Deprecated in 5.13: painter.drawRoundRect(
|
||||
// QRectF(QPointF(width - margin * radius, margin), QPointF(width, height -
|
||||
// margin)), 0.0, 0.0);
|
||||
painter.drawRoundedRect(
|
||||
QRectF(QPointF(width - margin * radius, margin), QPointF(width, height - margin)),
|
||||
0.0,
|
||||
0.0);
|
||||
// Right
|
||||
QPointF right0(width - margin, height / 2);
|
||||
QPointF right1(width, height / 2);
|
||||
gradient.setStart(right0);
|
||||
gradient.setFinalStop(right1);
|
||||
painter.setBrush(QBrush(gradient));
|
||||
// Deprecated in 5.13: painter.drawRoundRect(
|
||||
// QRectF(QPointF(width - margin * radius, margin), QPointF(width, height -
|
||||
// margin)), 0.0, 0.0);
|
||||
painter.drawRoundedRect(
|
||||
QRectF(QPointF(width - margin * radius, margin), QPointF(width, height - margin)), 0.0, 0.0);
|
||||
|
||||
// Left
|
||||
QPointF left0(margin, height / 2);
|
||||
QPointF left1(0, height / 2);
|
||||
gradient.setStart(left0);
|
||||
gradient.setFinalStop(left1);
|
||||
painter.setBrush(QBrush(gradient));
|
||||
painter.drawRoundedRect(
|
||||
QRectF(QPointF(margin * radius, margin), QPointF(0, height - margin)), 0.0, 0.0);
|
||||
// Left
|
||||
QPointF left0(margin, height / 2);
|
||||
QPointF left1(0, height / 2);
|
||||
gradient.setStart(left0);
|
||||
gradient.setFinalStop(left1);
|
||||
painter.setBrush(QBrush(gradient));
|
||||
painter.drawRoundedRect(
|
||||
QRectF(QPointF(margin * radius, margin), QPointF(0, height - margin)), 0.0, 0.0);
|
||||
|
||||
// Top
|
||||
QPointF top0(width / 2, margin);
|
||||
QPointF top1(width / 2, 0);
|
||||
gradient.setStart(top0);
|
||||
gradient.setFinalStop(top1);
|
||||
painter.setBrush(QBrush(gradient));
|
||||
painter.drawRoundedRect(
|
||||
QRectF(QPointF(width - margin, 0), QPointF(margin, margin)), 0.0, 0.0);
|
||||
// Top
|
||||
QPointF top0(width / 2, margin);
|
||||
QPointF top1(width / 2, 0);
|
||||
gradient.setStart(top0);
|
||||
gradient.setFinalStop(top1);
|
||||
painter.setBrush(QBrush(gradient));
|
||||
painter.drawRoundedRect(QRectF(QPointF(width - margin, 0), QPointF(margin, margin)), 0.0, 0.0);
|
||||
|
||||
// Bottom
|
||||
QPointF bottom0(width / 2, height - margin);
|
||||
QPointF bottom1(width / 2, height);
|
||||
gradient.setStart(bottom0);
|
||||
gradient.setFinalStop(bottom1);
|
||||
painter.setBrush(QBrush(gradient));
|
||||
painter.drawRoundedRect(
|
||||
QRectF(QPointF(margin, height - margin), QPointF(width - margin, height)), 0.0, 0.0);
|
||||
// Bottom
|
||||
QPointF bottom0(width / 2, height - margin);
|
||||
QPointF bottom1(width / 2, height);
|
||||
gradient.setStart(bottom0);
|
||||
gradient.setFinalStop(bottom1);
|
||||
painter.setBrush(QBrush(gradient));
|
||||
painter.drawRoundedRect(
|
||||
QRectF(QPointF(margin, height - margin), QPointF(width - margin, height)), 0.0, 0.0);
|
||||
|
||||
// BottomRight
|
||||
QPointF bottomright0(width - margin, height - margin);
|
||||
QPointF bottomright1(width, height);
|
||||
gradient.setStart(bottomright0);
|
||||
gradient.setFinalStop(bottomright1);
|
||||
gradient.setColorAt(endPosition1, end);
|
||||
painter.setBrush(QBrush(gradient));
|
||||
painter.drawRoundedRect(QRectF(bottomright0, bottomright1), 0.0, 0.0);
|
||||
// BottomRight
|
||||
QPointF bottomright0(width - margin, height - margin);
|
||||
QPointF bottomright1(width, height);
|
||||
gradient.setStart(bottomright0);
|
||||
gradient.setFinalStop(bottomright1);
|
||||
gradient.setColorAt(endPosition1, end);
|
||||
painter.setBrush(QBrush(gradient));
|
||||
painter.drawRoundedRect(QRectF(bottomright0, bottomright1), 0.0, 0.0);
|
||||
|
||||
// BottomLeft
|
||||
QPointF bottomleft0(margin, height - margin);
|
||||
QPointF bottomleft1(0, height);
|
||||
gradient.setStart(bottomleft0);
|
||||
gradient.setFinalStop(bottomleft1);
|
||||
gradient.setColorAt(endPosition1, end);
|
||||
painter.setBrush(QBrush(gradient));
|
||||
painter.drawRoundedRect(QRectF(bottomleft0, bottomleft1), 0.0, 0.0);
|
||||
// BottomLeft
|
||||
QPointF bottomleft0(margin, height - margin);
|
||||
QPointF bottomleft1(0, height);
|
||||
gradient.setStart(bottomleft0);
|
||||
gradient.setFinalStop(bottomleft1);
|
||||
gradient.setColorAt(endPosition1, end);
|
||||
painter.setBrush(QBrush(gradient));
|
||||
painter.drawRoundedRect(QRectF(bottomleft0, bottomleft1), 0.0, 0.0);
|
||||
|
||||
// TopLeft
|
||||
QPointF topleft0(margin, margin);
|
||||
QPointF topleft1(0, 0);
|
||||
gradient.setStart(topleft0);
|
||||
gradient.setFinalStop(topleft1);
|
||||
gradient.setColorAt(endPosition1, end);
|
||||
painter.setBrush(QBrush(gradient));
|
||||
painter.drawRoundedRect(QRectF(topleft0, topleft1), 0.0, 0.0);
|
||||
// TopLeft
|
||||
QPointF topleft0(margin, margin);
|
||||
QPointF topleft1(0, 0);
|
||||
gradient.setStart(topleft0);
|
||||
gradient.setFinalStop(topleft1);
|
||||
gradient.setColorAt(endPosition1, end);
|
||||
painter.setBrush(QBrush(gradient));
|
||||
painter.drawRoundedRect(QRectF(topleft0, topleft1), 0.0, 0.0);
|
||||
|
||||
// TopRight
|
||||
QPointF topright0(width - margin, margin);
|
||||
QPointF topright1(width, 0);
|
||||
gradient.setStart(topright0);
|
||||
gradient.setFinalStop(topright1);
|
||||
gradient.setColorAt(endPosition1, end);
|
||||
painter.setBrush(QBrush(gradient));
|
||||
painter.drawRoundedRect(QRectF(topright0, topright1), 0.0, 0.0);
|
||||
// TopRight
|
||||
QPointF topright0(width - margin, margin);
|
||||
QPointF topright1(width, 0);
|
||||
gradient.setStart(topright0);
|
||||
gradient.setFinalStop(topright1);
|
||||
gradient.setColorAt(endPosition1, end);
|
||||
painter.setBrush(QBrush(gradient));
|
||||
painter.drawRoundedRect(QRectF(topright0, topright1), 0.0, 0.0);
|
||||
|
||||
// Widget
|
||||
painter.setBrush(QBrush("#FFFFFF"));
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.drawRoundedRect(
|
||||
QRectF(QPointF(margin, margin), QPointF(width - margin, height - margin)),
|
||||
radius,
|
||||
radius);
|
||||
// Widget
|
||||
painter.setBrush(QBrush("#FFFFFF"));
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.drawRoundedRect(
|
||||
QRectF(QPointF(margin, margin), QPointF(width - margin, height - margin)), radius, radius);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,14 +11,14 @@ class QPainter;
|
|||
class DropShadow
|
||||
{
|
||||
public:
|
||||
static void draw(QPainter &painter,
|
||||
qint16 margin,
|
||||
qreal radius,
|
||||
QColor start,
|
||||
QColor end,
|
||||
qreal startPosition,
|
||||
qreal endPosition0,
|
||||
qreal endPosition1,
|
||||
qreal width,
|
||||
qreal height);
|
||||
static void draw(QPainter &painter,
|
||||
qint16 margin,
|
||||
qreal radius,
|
||||
QColor start,
|
||||
QColor end,
|
||||
qreal startPosition,
|
||||
qreal endPosition0,
|
||||
qreal endPosition1,
|
||||
qreal width,
|
||||
qreal height);
|
||||
};
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -14,174 +14,171 @@ class FlatButton;
|
|||
|
||||
class FlatButtonStateMachine : public QStateMachine
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(qreal overlayOpacity WRITE setOverlayOpacity READ overlayOpacity)
|
||||
Q_PROPERTY(
|
||||
qreal checkedOverlayProgress WRITE setCheckedOverlayProgress READ checkedOverlayProgress)
|
||||
Q_PROPERTY(qreal overlayOpacity WRITE setOverlayOpacity READ overlayOpacity)
|
||||
Q_PROPERTY(
|
||||
qreal checkedOverlayProgress WRITE setCheckedOverlayProgress READ checkedOverlayProgress)
|
||||
|
||||
public:
|
||||
explicit FlatButtonStateMachine(FlatButton *parent);
|
||||
~FlatButtonStateMachine() override;
|
||||
explicit FlatButtonStateMachine(FlatButton *parent);
|
||||
~FlatButtonStateMachine() override;
|
||||
|
||||
void setOverlayOpacity(qreal opacity);
|
||||
void setCheckedOverlayProgress(qreal opacity);
|
||||
void setOverlayOpacity(qreal opacity);
|
||||
void setCheckedOverlayProgress(qreal opacity);
|
||||
|
||||
inline qreal overlayOpacity() const;
|
||||
inline qreal checkedOverlayProgress() const;
|
||||
inline qreal overlayOpacity() const;
|
||||
inline qreal checkedOverlayProgress() const;
|
||||
|
||||
void startAnimations();
|
||||
void setupProperties();
|
||||
void updateCheckedStatus();
|
||||
void startAnimations();
|
||||
void setupProperties();
|
||||
void updateCheckedStatus();
|
||||
|
||||
signals:
|
||||
void buttonPressed();
|
||||
void buttonChecked();
|
||||
void buttonUnchecked();
|
||||
void buttonPressed();
|
||||
void buttonChecked();
|
||||
void buttonUnchecked();
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *watched, QEvent *event) override;
|
||||
bool eventFilter(QObject *watched, QEvent *event) override;
|
||||
|
||||
private:
|
||||
void addTransition(QObject *object, const char *signal, QState *fromState, QState *toState);
|
||||
void addTransition(QObject *object,
|
||||
QEvent::Type eventType,
|
||||
QState *fromState,
|
||||
QState *toState);
|
||||
void addTransition(QAbstractTransition *transition, QState *fromState, QState *toState);
|
||||
void addTransition(QObject *object, const char *signal, QState *fromState, QState *toState);
|
||||
void addTransition(QObject *object, QEvent::Type eventType, QState *fromState, QState *toState);
|
||||
void addTransition(QAbstractTransition *transition, QState *fromState, QState *toState);
|
||||
|
||||
FlatButton *const button_;
|
||||
FlatButton *const button_;
|
||||
|
||||
QState *const top_level_state_;
|
||||
QState *const config_state_;
|
||||
QState *const checkable_state_;
|
||||
QState *const checked_state_;
|
||||
QState *const unchecked_state_;
|
||||
QState *const neutral_state_;
|
||||
QState *const neutral_focused_state_;
|
||||
QState *const hovered_state_;
|
||||
QState *const hovered_focused_state_;
|
||||
QState *const pressed_state_;
|
||||
QState *const top_level_state_;
|
||||
QState *const config_state_;
|
||||
QState *const checkable_state_;
|
||||
QState *const checked_state_;
|
||||
QState *const unchecked_state_;
|
||||
QState *const neutral_state_;
|
||||
QState *const neutral_focused_state_;
|
||||
QState *const hovered_state_;
|
||||
QState *const hovered_focused_state_;
|
||||
QState *const pressed_state_;
|
||||
|
||||
qreal overlay_opacity_;
|
||||
qreal checked_overlay_progress_;
|
||||
qreal overlay_opacity_;
|
||||
qreal checked_overlay_progress_;
|
||||
|
||||
bool was_checked_;
|
||||
bool was_checked_;
|
||||
};
|
||||
|
||||
inline qreal
|
||||
FlatButtonStateMachine::overlayOpacity() const
|
||||
{
|
||||
return overlay_opacity_;
|
||||
return overlay_opacity_;
|
||||
}
|
||||
|
||||
inline qreal
|
||||
FlatButtonStateMachine::checkedOverlayProgress() const
|
||||
{
|
||||
return checked_overlay_progress_;
|
||||
return checked_overlay_progress_;
|
||||
}
|
||||
|
||||
class FlatButton : public QPushButton
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QColor foregroundColor WRITE setForegroundColor READ foregroundColor)
|
||||
Q_PROPERTY(QColor backgroundColor WRITE setBackgroundColor READ backgroundColor)
|
||||
Q_PROPERTY(QColor overlayColor WRITE setOverlayColor READ overlayColor)
|
||||
Q_PROPERTY(QColor disabledForegroundColor WRITE setDisabledForegroundColor READ
|
||||
disabledForegroundColor)
|
||||
Q_PROPERTY(QColor disabledBackgroundColor WRITE setDisabledBackgroundColor READ
|
||||
disabledBackgroundColor)
|
||||
Q_PROPERTY(qreal fontSize WRITE setFontSize READ fontSize)
|
||||
Q_PROPERTY(QColor foregroundColor WRITE setForegroundColor READ foregroundColor)
|
||||
Q_PROPERTY(QColor backgroundColor WRITE setBackgroundColor READ backgroundColor)
|
||||
Q_PROPERTY(QColor overlayColor WRITE setOverlayColor READ overlayColor)
|
||||
Q_PROPERTY(
|
||||
QColor disabledForegroundColor WRITE setDisabledForegroundColor READ disabledForegroundColor)
|
||||
Q_PROPERTY(
|
||||
QColor disabledBackgroundColor WRITE setDisabledBackgroundColor READ disabledBackgroundColor)
|
||||
Q_PROPERTY(qreal fontSize WRITE setFontSize READ fontSize)
|
||||
|
||||
public:
|
||||
explicit FlatButton(QWidget *parent = nullptr,
|
||||
ui::ButtonPreset preset = ui::ButtonPreset::FlatPreset);
|
||||
explicit FlatButton(const QString &text,
|
||||
QWidget *parent = nullptr,
|
||||
ui::ButtonPreset preset = ui::ButtonPreset::FlatPreset);
|
||||
FlatButton(const QString &text,
|
||||
ui::Role role,
|
||||
QWidget *parent = nullptr,
|
||||
ui::ButtonPreset preset = ui::ButtonPreset::FlatPreset);
|
||||
~FlatButton() override;
|
||||
explicit FlatButton(QWidget *parent = nullptr,
|
||||
ui::ButtonPreset preset = ui::ButtonPreset::FlatPreset);
|
||||
explicit FlatButton(const QString &text,
|
||||
QWidget *parent = nullptr,
|
||||
ui::ButtonPreset preset = ui::ButtonPreset::FlatPreset);
|
||||
FlatButton(const QString &text,
|
||||
ui::Role role,
|
||||
QWidget *parent = nullptr,
|
||||
ui::ButtonPreset preset = ui::ButtonPreset::FlatPreset);
|
||||
~FlatButton() override;
|
||||
|
||||
void applyPreset(ui::ButtonPreset preset);
|
||||
void applyPreset(ui::ButtonPreset preset);
|
||||
|
||||
void setBackgroundColor(const QColor &color);
|
||||
void setBackgroundMode(Qt::BGMode mode);
|
||||
void setBaseOpacity(qreal opacity);
|
||||
void setCheckable(bool value);
|
||||
void setCornerRadius(qreal radius);
|
||||
void setDisabledBackgroundColor(const QColor &color);
|
||||
void setDisabledForegroundColor(const QColor &color);
|
||||
void setFixedRippleRadius(qreal radius);
|
||||
void setFontSize(qreal size);
|
||||
void setForegroundColor(const QColor &color);
|
||||
void setHasFixedRippleRadius(bool value);
|
||||
void setIconPlacement(ui::ButtonIconPlacement placement);
|
||||
void setOverlayColor(const QColor &color);
|
||||
void setOverlayStyle(ui::OverlayStyle style);
|
||||
void setRippleStyle(ui::RippleStyle style);
|
||||
void setRole(ui::Role role);
|
||||
void setBackgroundColor(const QColor &color);
|
||||
void setBackgroundMode(Qt::BGMode mode);
|
||||
void setBaseOpacity(qreal opacity);
|
||||
void setCheckable(bool value);
|
||||
void setCornerRadius(qreal radius);
|
||||
void setDisabledBackgroundColor(const QColor &color);
|
||||
void setDisabledForegroundColor(const QColor &color);
|
||||
void setFixedRippleRadius(qreal radius);
|
||||
void setFontSize(qreal size);
|
||||
void setForegroundColor(const QColor &color);
|
||||
void setHasFixedRippleRadius(bool value);
|
||||
void setIconPlacement(ui::ButtonIconPlacement placement);
|
||||
void setOverlayColor(const QColor &color);
|
||||
void setOverlayStyle(ui::OverlayStyle style);
|
||||
void setRippleStyle(ui::RippleStyle style);
|
||||
void setRole(ui::Role role);
|
||||
|
||||
QColor foregroundColor() const;
|
||||
QColor backgroundColor() const;
|
||||
QColor overlayColor() const;
|
||||
QColor disabledForegroundColor() const;
|
||||
QColor disabledBackgroundColor() const;
|
||||
QColor foregroundColor() const;
|
||||
QColor backgroundColor() const;
|
||||
QColor overlayColor() const;
|
||||
QColor disabledForegroundColor() const;
|
||||
QColor disabledBackgroundColor() const;
|
||||
|
||||
qreal fontSize() const;
|
||||
qreal cornerRadius() const;
|
||||
qreal baseOpacity() const;
|
||||
qreal fontSize() const;
|
||||
qreal cornerRadius() const;
|
||||
qreal baseOpacity() const;
|
||||
|
||||
bool hasFixedRippleRadius() const;
|
||||
bool hasFixedRippleRadius() const;
|
||||
|
||||
ui::Role role() const;
|
||||
ui::OverlayStyle overlayStyle() const;
|
||||
ui::RippleStyle rippleStyle() const;
|
||||
ui::ButtonIconPlacement iconPlacement() const;
|
||||
ui::Role role() const;
|
||||
ui::OverlayStyle overlayStyle() const;
|
||||
ui::RippleStyle rippleStyle() const;
|
||||
ui::ButtonIconPlacement iconPlacement() const;
|
||||
|
||||
Qt::BGMode backgroundMode() const;
|
||||
Qt::BGMode backgroundMode() const;
|
||||
|
||||
QSize sizeHint() const override;
|
||||
QSize sizeHint() const override;
|
||||
|
||||
protected:
|
||||
int IconPadding = 0;
|
||||
int IconPadding = 0;
|
||||
|
||||
void checkStateSet() override;
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void checkStateSet() override;
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
|
||||
virtual void paintBackground(QPainter *painter);
|
||||
virtual void paintForeground(QPainter *painter);
|
||||
virtual void updateClipPath();
|
||||
virtual void paintBackground(QPainter *painter);
|
||||
virtual void paintForeground(QPainter *painter);
|
||||
virtual void updateClipPath();
|
||||
|
||||
void init();
|
||||
void init();
|
||||
|
||||
private:
|
||||
RippleOverlay *ripple_overlay_;
|
||||
FlatButtonStateMachine *state_machine_;
|
||||
RippleOverlay *ripple_overlay_;
|
||||
FlatButtonStateMachine *state_machine_;
|
||||
|
||||
ui::Role role_;
|
||||
ui::RippleStyle ripple_style_;
|
||||
ui::ButtonIconPlacement icon_placement_;
|
||||
ui::OverlayStyle overlay_style_;
|
||||
ui::Role role_;
|
||||
ui::RippleStyle ripple_style_;
|
||||
ui::ButtonIconPlacement icon_placement_;
|
||||
ui::OverlayStyle overlay_style_;
|
||||
|
||||
Qt::BGMode bg_mode_;
|
||||
Qt::BGMode bg_mode_;
|
||||
|
||||
QColor background_color_;
|
||||
QColor foreground_color_;
|
||||
QColor overlay_color_;
|
||||
QColor disabled_color_;
|
||||
QColor disabled_background_color_;
|
||||
QColor background_color_;
|
||||
QColor foreground_color_;
|
||||
QColor overlay_color_;
|
||||
QColor disabled_color_;
|
||||
QColor disabled_background_color_;
|
||||
|
||||
qreal fixed_ripple_radius_;
|
||||
qreal corner_radius_;
|
||||
qreal base_opacity_;
|
||||
qreal font_size_;
|
||||
qreal fixed_ripple_radius_;
|
||||
qreal corner_radius_;
|
||||
qreal base_opacity_;
|
||||
qreal font_size_;
|
||||
|
||||
bool use_fixed_ripple_radius_;
|
||||
bool use_fixed_ripple_radius_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -10,91 +10,91 @@
|
|||
FloatingButton::FloatingButton(const QIcon &icon, QWidget *parent)
|
||||
: RaisedButton(parent)
|
||||
{
|
||||
setFixedSize(DIAMETER, DIAMETER);
|
||||
setGeometry(buttonGeometry());
|
||||
setFixedSize(DIAMETER, DIAMETER);
|
||||
setGeometry(buttonGeometry());
|
||||
|
||||
if (parentWidget())
|
||||
parentWidget()->installEventFilter(this);
|
||||
if (parentWidget())
|
||||
parentWidget()->installEventFilter(this);
|
||||
|
||||
setFixedRippleRadius(50);
|
||||
setIcon(icon);
|
||||
raise();
|
||||
setFixedRippleRadius(50);
|
||||
setIcon(icon);
|
||||
raise();
|
||||
}
|
||||
|
||||
QRect
|
||||
FloatingButton::buttonGeometry() const
|
||||
{
|
||||
QWidget *parent = parentWidget();
|
||||
QWidget *parent = parentWidget();
|
||||
|
||||
if (!parent)
|
||||
return QRect();
|
||||
if (!parent)
|
||||
return QRect();
|
||||
|
||||
return QRect(parent->width() - (OFFSET_X + DIAMETER),
|
||||
parent->height() - (OFFSET_Y + DIAMETER),
|
||||
DIAMETER,
|
||||
DIAMETER);
|
||||
return QRect(parent->width() - (OFFSET_X + DIAMETER),
|
||||
parent->height() - (OFFSET_Y + DIAMETER),
|
||||
DIAMETER,
|
||||
DIAMETER);
|
||||
}
|
||||
|
||||
bool
|
||||
FloatingButton::event(QEvent *event)
|
||||
{
|
||||
if (!parent())
|
||||
return RaisedButton::event(event);
|
||||
|
||||
switch (event->type()) {
|
||||
case QEvent::ParentChange: {
|
||||
parent()->installEventFilter(this);
|
||||
setGeometry(buttonGeometry());
|
||||
break;
|
||||
}
|
||||
case QEvent::ParentAboutToChange: {
|
||||
parent()->installEventFilter(this);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!parent())
|
||||
return RaisedButton::event(event);
|
||||
|
||||
switch (event->type()) {
|
||||
case QEvent::ParentChange: {
|
||||
parent()->installEventFilter(this);
|
||||
setGeometry(buttonGeometry());
|
||||
break;
|
||||
}
|
||||
case QEvent::ParentAboutToChange: {
|
||||
parent()->installEventFilter(this);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return RaisedButton::event(event);
|
||||
}
|
||||
|
||||
bool
|
||||
FloatingButton::eventFilter(QObject *obj, QEvent *event)
|
||||
{
|
||||
const QEvent::Type type = event->type();
|
||||
const QEvent::Type type = event->type();
|
||||
|
||||
if (QEvent::Move == type || QEvent::Resize == type)
|
||||
setGeometry(buttonGeometry());
|
||||
if (QEvent::Move == type || QEvent::Resize == type)
|
||||
setGeometry(buttonGeometry());
|
||||
|
||||
return RaisedButton::eventFilter(obj, event);
|
||||
return RaisedButton::eventFilter(obj, event);
|
||||
}
|
||||
|
||||
void
|
||||
FloatingButton::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
Q_UNUSED(event);
|
||||
|
||||
QRect square = QRect(0, 0, DIAMETER, DIAMETER);
|
||||
square.moveCenter(rect().center());
|
||||
QRect square = QRect(0, 0, DIAMETER, DIAMETER);
|
||||
square.moveCenter(rect().center());
|
||||
|
||||
QPainter p(this);
|
||||
p.setRenderHints(QPainter::Antialiasing);
|
||||
QPainter p(this);
|
||||
p.setRenderHints(QPainter::Antialiasing);
|
||||
|
||||
QBrush brush;
|
||||
brush.setStyle(Qt::SolidPattern);
|
||||
brush.setColor(backgroundColor());
|
||||
QBrush brush;
|
||||
brush.setStyle(Qt::SolidPattern);
|
||||
brush.setColor(backgroundColor());
|
||||
|
||||
p.setBrush(brush);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.drawEllipse(square);
|
||||
p.setBrush(brush);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.drawEllipse(square);
|
||||
|
||||
QRect iconGeometry(0, 0, ICON_SIZE, ICON_SIZE);
|
||||
iconGeometry.moveCenter(square.center());
|
||||
QRect iconGeometry(0, 0, ICON_SIZE, ICON_SIZE);
|
||||
iconGeometry.moveCenter(square.center());
|
||||
|
||||
QPixmap pixmap = icon().pixmap(QSize(ICON_SIZE, ICON_SIZE));
|
||||
QPainter icon(&pixmap);
|
||||
icon.setCompositionMode(QPainter::CompositionMode_SourceIn);
|
||||
icon.fillRect(pixmap.rect(), foregroundColor());
|
||||
QPixmap pixmap = icon().pixmap(QSize(ICON_SIZE, ICON_SIZE));
|
||||
QPainter icon(&pixmap);
|
||||
icon.setCompositionMode(QPainter::CompositionMode_SourceIn);
|
||||
icon.fillRect(pixmap.rect(), foregroundColor());
|
||||
|
||||
p.drawPixmap(iconGeometry, pixmap);
|
||||
p.drawPixmap(iconGeometry, pixmap);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,17 +14,17 @@ constexpr int OFFSET_Y = 20;
|
|||
|
||||
class FloatingButton : public RaisedButton
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
FloatingButton(const QIcon &icon, QWidget *parent = nullptr);
|
||||
FloatingButton(const QIcon &icon, QWidget *parent = nullptr);
|
||||
|
||||
QSize sizeHint() const override { return QSize(DIAMETER, DIAMETER); };
|
||||
QRect buttonGeometry() const;
|
||||
QSize sizeHint() const override { return QSize(DIAMETER, DIAMETER); };
|
||||
QRect buttonGeometry() const;
|
||||
|
||||
protected:
|
||||
bool event(QEvent *event) override;
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
bool event(QEvent *event) override;
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -19,60 +19,60 @@ constexpr int HMargin = 20;
|
|||
InfoMessage::InfoMessage(QWidget *parent)
|
||||
: QWidget{parent}
|
||||
{
|
||||
initFont();
|
||||
initFont();
|
||||
}
|
||||
|
||||
InfoMessage::InfoMessage(QString msg, QWidget *parent)
|
||||
: QWidget{parent}
|
||||
, msg_{msg}
|
||||
{
|
||||
initFont();
|
||||
initFont();
|
||||
|
||||
QFontMetrics fm{font()};
|
||||
width_ = fm.horizontalAdvance(msg_) + HPadding * 2;
|
||||
height_ = fm.ascent() + 2 * VPadding;
|
||||
QFontMetrics fm{font()};
|
||||
width_ = fm.horizontalAdvance(msg_) + HPadding * 2;
|
||||
height_ = fm.ascent() + 2 * VPadding;
|
||||
|
||||
setFixedHeight(height_ + 2 * HMargin);
|
||||
setFixedHeight(height_ + 2 * HMargin);
|
||||
}
|
||||
|
||||
void
|
||||
InfoMessage::paintEvent(QPaintEvent *)
|
||||
{
|
||||
QPainter p(this);
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
p.setFont(font());
|
||||
QPainter p(this);
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
p.setFont(font());
|
||||
|
||||
// Center the box horizontally & vertically.
|
||||
auto textRegion = QRectF(width() / 2 - width_ / 2, HMargin, width_, height_);
|
||||
// Center the box horizontally & vertically.
|
||||
auto textRegion = QRectF(width() / 2 - width_ / 2, HMargin, width_, height_);
|
||||
|
||||
QPainterPath ppath;
|
||||
ppath.addRoundedRect(textRegion, height_ / 2, height_ / 2);
|
||||
QPainterPath ppath;
|
||||
ppath.addRoundedRect(textRegion, height_ / 2, height_ / 2);
|
||||
|
||||
p.setPen(Qt::NoPen);
|
||||
p.fillPath(ppath, boxColor());
|
||||
p.drawPath(ppath);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.fillPath(ppath, boxColor());
|
||||
p.drawPath(ppath);
|
||||
|
||||
p.setPen(QPen(textColor()));
|
||||
p.drawText(textRegion, Qt::AlignCenter, msg_);
|
||||
p.setPen(QPen(textColor()));
|
||||
p.drawText(textRegion, Qt::AlignCenter, msg_);
|
||||
}
|
||||
|
||||
DateSeparator::DateSeparator(QDateTime datetime, QWidget *parent)
|
||||
: InfoMessage{parent}
|
||||
{
|
||||
auto now = QDateTime::currentDateTime();
|
||||
auto now = QDateTime::currentDateTime();
|
||||
|
||||
QString fmt = QLocale::system().dateFormat(QLocale::LongFormat);
|
||||
QString fmt = QLocale::system().dateFormat(QLocale::LongFormat);
|
||||
|
||||
if (now.date().year() == datetime.date().year()) {
|
||||
QRegularExpression rx("[^a-zA-Z]*y+[^a-zA-Z]*");
|
||||
fmt = fmt.remove(rx);
|
||||
}
|
||||
if (now.date().year() == datetime.date().year()) {
|
||||
QRegularExpression rx("[^a-zA-Z]*y+[^a-zA-Z]*");
|
||||
fmt = fmt.remove(rx);
|
||||
}
|
||||
|
||||
msg_ = datetime.date().toString(fmt);
|
||||
msg_ = datetime.date().toString(fmt);
|
||||
|
||||
QFontMetrics fm{font()};
|
||||
width_ = fm.horizontalAdvance(msg_) + HPadding * 2;
|
||||
height_ = fm.ascent() + 2 * VPadding;
|
||||
QFontMetrics fm{font()};
|
||||
width_ = fm.horizontalAdvance(msg_) + HPadding * 2;
|
||||
height_ = fm.ascent() + 2 * VPadding;
|
||||
|
||||
setFixedHeight(height_ + 2 * HMargin);
|
||||
setFixedHeight(height_ + 2 * HMargin);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,47 +10,47 @@
|
|||
|
||||
class InfoMessage : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QColor textColor WRITE setTextColor READ textColor)
|
||||
Q_PROPERTY(QColor boxColor WRITE setBoxColor READ boxColor)
|
||||
Q_PROPERTY(QColor textColor WRITE setTextColor READ textColor)
|
||||
Q_PROPERTY(QColor boxColor WRITE setBoxColor READ boxColor)
|
||||
|
||||
public:
|
||||
explicit InfoMessage(QWidget *parent = nullptr);
|
||||
InfoMessage(QString msg, QWidget *parent = nullptr);
|
||||
explicit InfoMessage(QWidget *parent = nullptr);
|
||||
InfoMessage(QString msg, QWidget *parent = nullptr);
|
||||
|
||||
void setTextColor(QColor color) { textColor_ = color; }
|
||||
void setBoxColor(QColor color) { boxColor_ = color; }
|
||||
void saveDatetime(QDateTime datetime) { datetime_ = datetime; }
|
||||
void setTextColor(QColor color) { textColor_ = color; }
|
||||
void setBoxColor(QColor color) { boxColor_ = color; }
|
||||
void saveDatetime(QDateTime datetime) { datetime_ = datetime; }
|
||||
|
||||
QColor textColor() const { return textColor_; }
|
||||
QColor boxColor() const { return boxColor_; }
|
||||
QDateTime datetime() const { return datetime_; }
|
||||
QColor textColor() const { return textColor_; }
|
||||
QColor boxColor() const { return boxColor_; }
|
||||
QDateTime datetime() const { return datetime_; }
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void initFont()
|
||||
{
|
||||
QFont f;
|
||||
f.setWeight(QFont::Medium);
|
||||
setFont(f);
|
||||
}
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void initFont()
|
||||
{
|
||||
QFont f;
|
||||
f.setWeight(QFont::Medium);
|
||||
setFont(f);
|
||||
}
|
||||
|
||||
int width_;
|
||||
int height_;
|
||||
int width_;
|
||||
int height_;
|
||||
|
||||
QString msg_;
|
||||
QString msg_;
|
||||
|
||||
QDateTime datetime_;
|
||||
QDateTime datetime_;
|
||||
|
||||
QColor textColor_ = QColor("black");
|
||||
QColor boxColor_ = QColor("white");
|
||||
QColor textColor_ = QColor("black");
|
||||
QColor boxColor_ = QColor("white");
|
||||
};
|
||||
|
||||
class DateSeparator : public InfoMessage
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DateSeparator(QDateTime datetime, QWidget *parent = nullptr);
|
||||
DateSeparator(QDateTime datetime, QWidget *parent = nullptr);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -17,16 +17,16 @@ Label::Label(const QString &text, QWidget *parent, Qt::WindowFlags f)
|
|||
void
|
||||
Label::mousePressEvent(QMouseEvent *e)
|
||||
{
|
||||
pressPosition_ = e->pos();
|
||||
emit pressed(e);
|
||||
QLabel::mousePressEvent(e);
|
||||
pressPosition_ = e->pos();
|
||||
emit pressed(e);
|
||||
QLabel::mousePressEvent(e);
|
||||
}
|
||||
|
||||
void
|
||||
Label::mouseReleaseEvent(QMouseEvent *e)
|
||||
{
|
||||
emit released(e);
|
||||
if (pressPosition_ == e->pos())
|
||||
emit clicked(e);
|
||||
QLabel::mouseReleaseEvent(e);
|
||||
emit released(e);
|
||||
if (pressPosition_ == e->pos())
|
||||
emit clicked(e);
|
||||
QLabel::mouseReleaseEvent(e);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,22 +8,22 @@
|
|||
|
||||
class Label : public QLabel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Label(QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags());
|
||||
explicit Label(const QString &text,
|
||||
QWidget *parent = Q_NULLPTR,
|
||||
Qt::WindowFlags f = Qt::WindowFlags());
|
||||
explicit Label(QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags());
|
||||
explicit Label(const QString &text,
|
||||
QWidget *parent = Q_NULLPTR,
|
||||
Qt::WindowFlags f = Qt::WindowFlags());
|
||||
|
||||
signals:
|
||||
void clicked(QMouseEvent *e);
|
||||
void pressed(QMouseEvent *e);
|
||||
void released(QMouseEvent *e);
|
||||
void clicked(QMouseEvent *e);
|
||||
void pressed(QMouseEvent *e);
|
||||
void released(QMouseEvent *e);
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QMouseEvent *e) override;
|
||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
void mousePressEvent(QMouseEvent *e) override;
|
||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
|
||||
QPoint pressPosition_;
|
||||
QPoint pressPosition_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -14,70 +14,70 @@ LoadingIndicator::LoadingIndicator(QWidget *parent)
|
|||
, angle_(0)
|
||||
, color_(Qt::black)
|
||||
{
|
||||
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||
setFocusPolicy(Qt::NoFocus);
|
||||
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||
setFocusPolicy(Qt::NoFocus);
|
||||
|
||||
timer_ = new QTimer(this);
|
||||
connect(timer_, SIGNAL(timeout()), this, SLOT(onTimeout()));
|
||||
timer_ = new QTimer(this);
|
||||
connect(timer_, SIGNAL(timeout()), this, SLOT(onTimeout()));
|
||||
}
|
||||
|
||||
void
|
||||
LoadingIndicator::paintEvent(QPaintEvent *e)
|
||||
{
|
||||
Q_UNUSED(e)
|
||||
Q_UNUSED(e)
|
||||
|
||||
if (!timer_->isActive())
|
||||
return;
|
||||
if (!timer_->isActive())
|
||||
return;
|
||||
|
||||
QPainter painter(this);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
QPainter painter(this);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
int width = qMin(this->width(), this->height());
|
||||
int width = qMin(this->width(), this->height());
|
||||
|
||||
int outerRadius = (width - 4) * 0.5f;
|
||||
int innerRadius = outerRadius * 0.78f;
|
||||
int outerRadius = (width - 4) * 0.5f;
|
||||
int innerRadius = outerRadius * 0.78f;
|
||||
|
||||
int capsuleRadius = (outerRadius - innerRadius) / 2;
|
||||
int capsuleRadius = (outerRadius - innerRadius) / 2;
|
||||
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
QColor color = color_;
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
QColor color = color_;
|
||||
|
||||
color.setAlphaF(1.0f - (i / 8.0f));
|
||||
color.setAlphaF(1.0f - (i / 8.0f));
|
||||
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.setBrush(color);
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.setBrush(color);
|
||||
|
||||
qreal radius = capsuleRadius * (1.0f - (i / 16.0f));
|
||||
qreal radius = capsuleRadius * (1.0f - (i / 16.0f));
|
||||
|
||||
painter.save();
|
||||
painter.save();
|
||||
|
||||
painter.translate(rect().center());
|
||||
painter.rotate(angle_ - i * 45.0f);
|
||||
painter.translate(rect().center());
|
||||
painter.rotate(angle_ - i * 45.0f);
|
||||
|
||||
QPointF center = QPointF(-capsuleRadius, -innerRadius);
|
||||
painter.drawEllipse(center, radius * 2, radius * 2);
|
||||
QPointF center = QPointF(-capsuleRadius, -innerRadius);
|
||||
painter.drawEllipse(center, radius * 2, radius * 2);
|
||||
|
||||
painter.restore();
|
||||
}
|
||||
painter.restore();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LoadingIndicator::start()
|
||||
{
|
||||
timer_->start(interval_);
|
||||
show();
|
||||
timer_->start(interval_);
|
||||
show();
|
||||
}
|
||||
|
||||
void
|
||||
LoadingIndicator::stop()
|
||||
{
|
||||
timer_->stop();
|
||||
hide();
|
||||
timer_->stop();
|
||||
hide();
|
||||
}
|
||||
|
||||
void
|
||||
LoadingIndicator::onTimeout()
|
||||
{
|
||||
angle_ = (angle_ + 45) % 360;
|
||||
repaint();
|
||||
angle_ = (angle_ + 45) % 360;
|
||||
repaint();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,30 +12,30 @@ class QTimer;
|
|||
class QPaintEvent;
|
||||
class LoadingIndicator : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QColor color READ color WRITE setColor)
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QColor color READ color WRITE setColor)
|
||||
|
||||
public:
|
||||
LoadingIndicator(QWidget *parent = nullptr);
|
||||
LoadingIndicator(QWidget *parent = nullptr);
|
||||
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
QColor color() { return color_; }
|
||||
void setColor(QColor color) { color_ = color; }
|
||||
QColor color() { return color_; }
|
||||
void setColor(QColor color) { color_ = color; }
|
||||
|
||||
int interval() { return interval_; }
|
||||
void setInterval(int interval) { interval_ = interval; }
|
||||
int interval() { return interval_; }
|
||||
void setInterval(int interval) { interval_ = interval; }
|
||||
|
||||
private slots:
|
||||
void onTimeout();
|
||||
void onTimeout();
|
||||
|
||||
private:
|
||||
int interval_;
|
||||
int angle_;
|
||||
int interval_;
|
||||
int angle_;
|
||||
|
||||
QColor color_;
|
||||
QTimer *timer_;
|
||||
QColor color_;
|
||||
QTimer *timer_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -10,16 +10,16 @@
|
|||
|
||||
class Menu : public QMenu
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
Menu(QWidget *parent = nullptr)
|
||||
: QMenu(parent){};
|
||||
Menu(QWidget *parent = nullptr)
|
||||
: QMenu(parent){};
|
||||
|
||||
protected:
|
||||
void leaveEvent(QEvent *e) override
|
||||
{
|
||||
hide();
|
||||
void leaveEvent(QEvent *e) override
|
||||
{
|
||||
hide();
|
||||
|
||||
QMenu::leaveEvent(e);
|
||||
}
|
||||
QMenu::leaveEvent(e);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -19,160 +19,157 @@
|
|||
void
|
||||
MxcAnimatedImage::startDownload()
|
||||
{
|
||||
if (!room_)
|
||||
return;
|
||||
if (eventId_.isEmpty())
|
||||
return;
|
||||
if (!room_)
|
||||
return;
|
||||
if (eventId_.isEmpty())
|
||||
return;
|
||||
|
||||
auto event = room_->eventById(eventId_);
|
||||
if (!event) {
|
||||
nhlog::ui()->error("Failed to load media for event {}, event not found.",
|
||||
eventId_.toStdString());
|
||||
return;
|
||||
auto event = room_->eventById(eventId_);
|
||||
if (!event) {
|
||||
nhlog::ui()->error("Failed to load media for event {}, event not found.",
|
||||
eventId_.toStdString());
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray mimeType = QString::fromStdString(mtx::accessors::mimetype(*event)).toUtf8();
|
||||
|
||||
animatable_ = QMovie::supportedFormats().contains(mimeType.split('/').back());
|
||||
animatableChanged();
|
||||
|
||||
if (!animatable_)
|
||||
return;
|
||||
|
||||
QString mxcUrl = QString::fromStdString(mtx::accessors::url(*event));
|
||||
QString originalFilename = QString::fromStdString(mtx::accessors::filename(*event));
|
||||
|
||||
auto encryptionInfo = mtx::accessors::file(*event);
|
||||
|
||||
// If the message is a link to a non mxcUrl, don't download it
|
||||
if (!mxcUrl.startsWith("mxc://")) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString suffix = QMimeDatabase().mimeTypeForName(mimeType).preferredSuffix();
|
||||
|
||||
const auto url = mxcUrl.toStdString();
|
||||
const auto name = QString(mxcUrl).remove("mxc://");
|
||||
QFileInfo filename(QString("%1/media_cache/media/%2.%3")
|
||||
.arg(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))
|
||||
.arg(name)
|
||||
.arg(suffix));
|
||||
if (QDir::cleanPath(name) != name) {
|
||||
nhlog::net()->warn("mxcUrl '{}' is not safe, not downloading file", url);
|
||||
return;
|
||||
}
|
||||
|
||||
QDir().mkpath(filename.path());
|
||||
|
||||
QPointer<MxcAnimatedImage> self = this;
|
||||
|
||||
auto processBuffer = [this, mimeType, encryptionInfo, self](QIODevice &device) {
|
||||
if (!self)
|
||||
return;
|
||||
|
||||
if (buffer.isOpen()) {
|
||||
movie.stop();
|
||||
movie.setDevice(nullptr);
|
||||
buffer.close();
|
||||
}
|
||||
|
||||
QByteArray mimeType = QString::fromStdString(mtx::accessors::mimetype(*event)).toUtf8();
|
||||
|
||||
animatable_ = QMovie::supportedFormats().contains(mimeType.split('/').back());
|
||||
animatableChanged();
|
||||
|
||||
if (!animatable_)
|
||||
return;
|
||||
|
||||
QString mxcUrl = QString::fromStdString(mtx::accessors::url(*event));
|
||||
QString originalFilename = QString::fromStdString(mtx::accessors::filename(*event));
|
||||
|
||||
auto encryptionInfo = mtx::accessors::file(*event);
|
||||
|
||||
// If the message is a link to a non mxcUrl, don't download it
|
||||
if (!mxcUrl.startsWith("mxc://")) {
|
||||
return;
|
||||
if (encryptionInfo) {
|
||||
QByteArray ba = device.readAll();
|
||||
std::string temp(ba.constData(), ba.size());
|
||||
temp = mtx::crypto::to_string(mtx::crypto::decrypt_file(temp, encryptionInfo.value()));
|
||||
buffer.setData(temp.data(), temp.size());
|
||||
} else {
|
||||
buffer.setData(device.readAll());
|
||||
}
|
||||
buffer.open(QIODevice::ReadOnly);
|
||||
buffer.reset();
|
||||
|
||||
QString suffix = QMimeDatabase().mimeTypeForName(mimeType).preferredSuffix();
|
||||
QTimer::singleShot(0, this, [this, mimeType] {
|
||||
nhlog::ui()->info(
|
||||
"Playing movie with size: {}, {}", buffer.bytesAvailable(), buffer.isOpen());
|
||||
movie.setFormat(mimeType);
|
||||
movie.setDevice(&buffer);
|
||||
if (play_)
|
||||
movie.start();
|
||||
else
|
||||
movie.jumpToFrame(0);
|
||||
emit loadedChanged();
|
||||
update();
|
||||
});
|
||||
};
|
||||
|
||||
const auto url = mxcUrl.toStdString();
|
||||
const auto name = QString(mxcUrl).remove("mxc://");
|
||||
QFileInfo filename(QString("%1/media_cache/media/%2.%3")
|
||||
.arg(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))
|
||||
.arg(name)
|
||||
.arg(suffix));
|
||||
if (QDir::cleanPath(name) != name) {
|
||||
nhlog::net()->warn("mxcUrl '{}' is not safe, not downloading file", url);
|
||||
return;
|
||||
if (filename.isReadable()) {
|
||||
QFile f(filename.filePath());
|
||||
if (f.open(QIODevice::ReadOnly)) {
|
||||
processBuffer(f);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
QDir().mkpath(filename.path());
|
||||
http::client()->download(url,
|
||||
[filename, url, processBuffer](const std::string &data,
|
||||
const std::string &,
|
||||
const std::string &,
|
||||
mtx::http::RequestErr err) {
|
||||
if (err) {
|
||||
nhlog::net()->warn("failed to retrieve media {}: {} {}",
|
||||
url,
|
||||
err->matrix_error.error,
|
||||
static_cast<int>(err->status_code));
|
||||
return;
|
||||
}
|
||||
|
||||
QPointer<MxcAnimatedImage> self = this;
|
||||
try {
|
||||
QFile file(filename.filePath());
|
||||
|
||||
auto processBuffer = [this, mimeType, encryptionInfo, self](QIODevice &device) {
|
||||
if (!self)
|
||||
return;
|
||||
if (!file.open(QIODevice::WriteOnly))
|
||||
return;
|
||||
|
||||
if (buffer.isOpen()) {
|
||||
movie.stop();
|
||||
movie.setDevice(nullptr);
|
||||
buffer.close();
|
||||
}
|
||||
QByteArray ba(data.data(), (int)data.size());
|
||||
file.write(ba);
|
||||
file.close();
|
||||
|
||||
if (encryptionInfo) {
|
||||
QByteArray ba = device.readAll();
|
||||
std::string temp(ba.constData(), ba.size());
|
||||
temp = mtx::crypto::to_string(
|
||||
mtx::crypto::decrypt_file(temp, encryptionInfo.value()));
|
||||
buffer.setData(temp.data(), temp.size());
|
||||
} else {
|
||||
buffer.setData(device.readAll());
|
||||
}
|
||||
buffer.open(QIODevice::ReadOnly);
|
||||
buffer.reset();
|
||||
|
||||
QTimer::singleShot(0, this, [this, mimeType] {
|
||||
nhlog::ui()->info("Playing movie with size: {}, {}",
|
||||
buffer.bytesAvailable(),
|
||||
buffer.isOpen());
|
||||
movie.setFormat(mimeType);
|
||||
movie.setDevice(&buffer);
|
||||
if (play_)
|
||||
movie.start();
|
||||
else
|
||||
movie.jumpToFrame(0);
|
||||
emit loadedChanged();
|
||||
update();
|
||||
});
|
||||
};
|
||||
|
||||
if (filename.isReadable()) {
|
||||
QFile f(filename.filePath());
|
||||
if (f.open(QIODevice::ReadOnly)) {
|
||||
processBuffer(f);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
http::client()->download(
|
||||
url,
|
||||
[filename, url, processBuffer](const std::string &data,
|
||||
const std::string &,
|
||||
const std::string &,
|
||||
mtx::http::RequestErr err) {
|
||||
if (err) {
|
||||
nhlog::net()->warn("failed to retrieve media {}: {} {}",
|
||||
url,
|
||||
err->matrix_error.error,
|
||||
static_cast<int>(err->status_code));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
QFile file(filename.filePath());
|
||||
|
||||
if (!file.open(QIODevice::WriteOnly))
|
||||
return;
|
||||
|
||||
QByteArray ba(data.data(), (int)data.size());
|
||||
file.write(ba);
|
||||
file.close();
|
||||
|
||||
QBuffer buf(&ba);
|
||||
buf.open(QBuffer::ReadOnly);
|
||||
processBuffer(buf);
|
||||
} catch (const std::exception &e) {
|
||||
nhlog::ui()->warn("Error while saving file to: {}", e.what());
|
||||
}
|
||||
});
|
||||
QBuffer buf(&ba);
|
||||
buf.open(QBuffer::ReadOnly);
|
||||
processBuffer(buf);
|
||||
} catch (const std::exception &e) {
|
||||
nhlog::ui()->warn("Error while saving file to: {}", e.what());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
QSGNode *
|
||||
MxcAnimatedImage::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *)
|
||||
{
|
||||
if (!imageDirty)
|
||||
return oldNode;
|
||||
if (!imageDirty)
|
||||
return oldNode;
|
||||
|
||||
imageDirty = false;
|
||||
QSGImageNode *n = static_cast<QSGImageNode *>(oldNode);
|
||||
if (!n) {
|
||||
n = window()->createImageNode();
|
||||
n->setOwnsTexture(true);
|
||||
// n->setFlags(QSGNode::OwnedByParent | QSGNode::OwnsGeometry |
|
||||
// GSGNode::OwnsMaterial);
|
||||
n->setFlags(QSGNode::OwnedByParent);
|
||||
}
|
||||
imageDirty = false;
|
||||
QSGImageNode *n = static_cast<QSGImageNode *>(oldNode);
|
||||
if (!n) {
|
||||
n = window()->createImageNode();
|
||||
n->setOwnsTexture(true);
|
||||
// n->setFlags(QSGNode::OwnedByParent | QSGNode::OwnsGeometry |
|
||||
// GSGNode::OwnsMaterial);
|
||||
n->setFlags(QSGNode::OwnedByParent);
|
||||
}
|
||||
|
||||
// n->setTexture(nullptr);
|
||||
auto img = movie.currentImage();
|
||||
if (!img.isNull())
|
||||
n->setTexture(window()->createTextureFromImage(img));
|
||||
else {
|
||||
delete n;
|
||||
return nullptr;
|
||||
}
|
||||
// n->setTexture(nullptr);
|
||||
auto img = movie.currentImage();
|
||||
if (!img.isNull())
|
||||
n->setTexture(window()->createTextureFromImage(img));
|
||||
else {
|
||||
delete n;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
n->setSourceRect(img.rect());
|
||||
n->setRect(QRect(0, 0, width(), height()));
|
||||
n->setFiltering(QSGTexture::Linear);
|
||||
n->setMipmapFiltering(QSGTexture::Linear);
|
||||
n->setSourceRect(img.rect());
|
||||
n->setRect(QRect(0, 0, width(), height()));
|
||||
n->setFiltering(QSGTexture::Linear);
|
||||
n->setMipmapFiltering(QSGTexture::Linear);
|
||||
|
||||
return n;
|
||||
return n;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,78 +14,78 @@ class TimelineModel;
|
|||
// This is an AnimatedImage, that can draw encrypted images
|
||||
class MxcAnimatedImage : public QQuickItem
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(TimelineModel *roomm READ room WRITE setRoom NOTIFY roomChanged REQUIRED)
|
||||
Q_PROPERTY(QString eventId READ eventId WRITE setEventId NOTIFY eventIdChanged)
|
||||
Q_PROPERTY(bool animatable READ animatable NOTIFY animatableChanged)
|
||||
Q_PROPERTY(bool loaded READ loaded NOTIFY loadedChanged)
|
||||
Q_PROPERTY(bool play READ play WRITE setPlay NOTIFY playChanged)
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(TimelineModel *roomm READ room WRITE setRoom NOTIFY roomChanged REQUIRED)
|
||||
Q_PROPERTY(QString eventId READ eventId WRITE setEventId NOTIFY eventIdChanged)
|
||||
Q_PROPERTY(bool animatable READ animatable NOTIFY animatableChanged)
|
||||
Q_PROPERTY(bool loaded READ loaded NOTIFY loadedChanged)
|
||||
Q_PROPERTY(bool play READ play WRITE setPlay NOTIFY playChanged)
|
||||
public:
|
||||
MxcAnimatedImage(QQuickItem *parent = nullptr)
|
||||
: QQuickItem(parent)
|
||||
{
|
||||
connect(this, &MxcAnimatedImage::eventIdChanged, &MxcAnimatedImage::startDownload);
|
||||
connect(this, &MxcAnimatedImage::roomChanged, &MxcAnimatedImage::startDownload);
|
||||
connect(&movie, &QMovie::frameChanged, this, &MxcAnimatedImage::newFrame);
|
||||
setFlag(QQuickItem::ItemHasContents);
|
||||
// setAcceptHoverEvents(true);
|
||||
}
|
||||
MxcAnimatedImage(QQuickItem *parent = nullptr)
|
||||
: QQuickItem(parent)
|
||||
{
|
||||
connect(this, &MxcAnimatedImage::eventIdChanged, &MxcAnimatedImage::startDownload);
|
||||
connect(this, &MxcAnimatedImage::roomChanged, &MxcAnimatedImage::startDownload);
|
||||
connect(&movie, &QMovie::frameChanged, this, &MxcAnimatedImage::newFrame);
|
||||
setFlag(QQuickItem::ItemHasContents);
|
||||
// setAcceptHoverEvents(true);
|
||||
}
|
||||
|
||||
bool animatable() const { return animatable_; }
|
||||
bool loaded() const { return buffer.size() > 0; }
|
||||
bool play() const { return play_; }
|
||||
QString eventId() const { return eventId_; }
|
||||
TimelineModel *room() const { return room_; }
|
||||
void setEventId(QString newEventId)
|
||||
{
|
||||
if (eventId_ != newEventId) {
|
||||
eventId_ = newEventId;
|
||||
emit eventIdChanged();
|
||||
}
|
||||
bool animatable() const { return animatable_; }
|
||||
bool loaded() const { return buffer.size() > 0; }
|
||||
bool play() const { return play_; }
|
||||
QString eventId() const { return eventId_; }
|
||||
TimelineModel *room() const { return room_; }
|
||||
void setEventId(QString newEventId)
|
||||
{
|
||||
if (eventId_ != newEventId) {
|
||||
eventId_ = newEventId;
|
||||
emit eventIdChanged();
|
||||
}
|
||||
void setRoom(TimelineModel *room)
|
||||
{
|
||||
if (room_ != room) {
|
||||
room_ = room;
|
||||
emit roomChanged();
|
||||
}
|
||||
}
|
||||
void setRoom(TimelineModel *room)
|
||||
{
|
||||
if (room_ != room) {
|
||||
room_ = room;
|
||||
emit roomChanged();
|
||||
}
|
||||
void setPlay(bool newPlay)
|
||||
{
|
||||
if (play_ != newPlay) {
|
||||
play_ = newPlay;
|
||||
movie.setPaused(!play_);
|
||||
emit playChanged();
|
||||
}
|
||||
}
|
||||
void setPlay(bool newPlay)
|
||||
{
|
||||
if (play_ != newPlay) {
|
||||
play_ = newPlay;
|
||||
movie.setPaused(!play_);
|
||||
emit playChanged();
|
||||
}
|
||||
}
|
||||
|
||||
QSGNode *updatePaintNode(QSGNode *oldNode,
|
||||
QQuickItem::UpdatePaintNodeData *updatePaintNodeData) override;
|
||||
QSGNode *updatePaintNode(QSGNode *oldNode,
|
||||
QQuickItem::UpdatePaintNodeData *updatePaintNodeData) override;
|
||||
|
||||
signals:
|
||||
void roomChanged();
|
||||
void eventIdChanged();
|
||||
void animatableChanged();
|
||||
void loadedChanged();
|
||||
void playChanged();
|
||||
void roomChanged();
|
||||
void eventIdChanged();
|
||||
void animatableChanged();
|
||||
void loadedChanged();
|
||||
void playChanged();
|
||||
|
||||
private slots:
|
||||
void startDownload();
|
||||
void newFrame(int frame)
|
||||
{
|
||||
currentFrame = frame;
|
||||
imageDirty = true;
|
||||
update();
|
||||
}
|
||||
void startDownload();
|
||||
void newFrame(int frame)
|
||||
{
|
||||
currentFrame = frame;
|
||||
imageDirty = true;
|
||||
update();
|
||||
}
|
||||
|
||||
private:
|
||||
TimelineModel *room_ = nullptr;
|
||||
QString eventId_;
|
||||
QString filename_;
|
||||
bool animatable_ = false;
|
||||
QBuffer buffer;
|
||||
QMovie movie;
|
||||
int currentFrame = 0;
|
||||
bool imageDirty = true;
|
||||
bool play_ = true;
|
||||
TimelineModel *room_ = nullptr;
|
||||
QString eventId_;
|
||||
QString filename_;
|
||||
bool animatable_ = false;
|
||||
QBuffer buffer;
|
||||
QMovie movie;
|
||||
int currentFrame = 0;
|
||||
bool imageDirty = true;
|
||||
bool play_ = true;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -21,122 +21,119 @@
|
|||
void
|
||||
MxcMediaProxy::setVideoSurface(QAbstractVideoSurface *surface)
|
||||
{
|
||||
qDebug() << "Changing surface";
|
||||
m_surface = surface;
|
||||
setVideoOutput(m_surface);
|
||||
qDebug() << "Changing surface";
|
||||
m_surface = surface;
|
||||
setVideoOutput(m_surface);
|
||||
}
|
||||
|
||||
QAbstractVideoSurface *
|
||||
MxcMediaProxy::getVideoSurface()
|
||||
{
|
||||
return m_surface;
|
||||
return m_surface;
|
||||
}
|
||||
|
||||
void
|
||||
MxcMediaProxy::startDownload()
|
||||
{
|
||||
if (!room_)
|
||||
return;
|
||||
if (eventId_.isEmpty())
|
||||
return;
|
||||
if (!room_)
|
||||
return;
|
||||
if (eventId_.isEmpty())
|
||||
return;
|
||||
|
||||
auto event = room_->eventById(eventId_);
|
||||
if (!event) {
|
||||
nhlog::ui()->error("Failed to load media for event {}, event not found.",
|
||||
eventId_.toStdString());
|
||||
return;
|
||||
auto event = room_->eventById(eventId_);
|
||||
if (!event) {
|
||||
nhlog::ui()->error("Failed to load media for event {}, event not found.",
|
||||
eventId_.toStdString());
|
||||
return;
|
||||
}
|
||||
|
||||
QString mxcUrl = QString::fromStdString(mtx::accessors::url(*event));
|
||||
QString originalFilename = QString::fromStdString(mtx::accessors::filename(*event));
|
||||
QString mimeType = QString::fromStdString(mtx::accessors::mimetype(*event));
|
||||
|
||||
auto encryptionInfo = mtx::accessors::file(*event);
|
||||
|
||||
// If the message is a link to a non mxcUrl, don't download it
|
||||
if (!mxcUrl.startsWith("mxc://")) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString suffix = QMimeDatabase().mimeTypeForName(mimeType).preferredSuffix();
|
||||
|
||||
const auto url = mxcUrl.toStdString();
|
||||
const auto name = QString(mxcUrl).remove("mxc://");
|
||||
QFileInfo filename(QString("%1/media_cache/media/%2.%3")
|
||||
.arg(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))
|
||||
.arg(name)
|
||||
.arg(suffix));
|
||||
if (QDir::cleanPath(name) != name) {
|
||||
nhlog::net()->warn("mxcUrl '{}' is not safe, not downloading file", url);
|
||||
return;
|
||||
}
|
||||
|
||||
QDir().mkpath(filename.path());
|
||||
|
||||
QPointer<MxcMediaProxy> self = this;
|
||||
|
||||
auto processBuffer = [this, encryptionInfo, filename, self](QIODevice &device) {
|
||||
if (!self)
|
||||
return;
|
||||
|
||||
if (encryptionInfo) {
|
||||
QByteArray ba = device.readAll();
|
||||
std::string temp(ba.constData(), ba.size());
|
||||
temp = mtx::crypto::to_string(mtx::crypto::decrypt_file(temp, encryptionInfo.value()));
|
||||
buffer.setData(temp.data(), temp.size());
|
||||
} else {
|
||||
buffer.setData(device.readAll());
|
||||
}
|
||||
buffer.open(QIODevice::ReadOnly);
|
||||
buffer.reset();
|
||||
|
||||
QString mxcUrl = QString::fromStdString(mtx::accessors::url(*event));
|
||||
QString originalFilename = QString::fromStdString(mtx::accessors::filename(*event));
|
||||
QString mimeType = QString::fromStdString(mtx::accessors::mimetype(*event));
|
||||
QTimer::singleShot(0, this, [this, filename] {
|
||||
nhlog::ui()->info(
|
||||
"Playing buffer with size: {}, {}", buffer.bytesAvailable(), buffer.isOpen());
|
||||
this->setMedia(QMediaContent(filename.fileName()), &buffer);
|
||||
emit loadedChanged();
|
||||
});
|
||||
};
|
||||
|
||||
auto encryptionInfo = mtx::accessors::file(*event);
|
||||
|
||||
// If the message is a link to a non mxcUrl, don't download it
|
||||
if (!mxcUrl.startsWith("mxc://")) {
|
||||
return;
|
||||
if (filename.isReadable()) {
|
||||
QFile f(filename.filePath());
|
||||
if (f.open(QIODevice::ReadOnly)) {
|
||||
processBuffer(f);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
QString suffix = QMimeDatabase().mimeTypeForName(mimeType).preferredSuffix();
|
||||
http::client()->download(url,
|
||||
[filename, url, processBuffer](const std::string &data,
|
||||
const std::string &,
|
||||
const std::string &,
|
||||
mtx::http::RequestErr err) {
|
||||
if (err) {
|
||||
nhlog::net()->warn("failed to retrieve media {}: {} {}",
|
||||
url,
|
||||
err->matrix_error.error,
|
||||
static_cast<int>(err->status_code));
|
||||
return;
|
||||
}
|
||||
|
||||
const auto url = mxcUrl.toStdString();
|
||||
const auto name = QString(mxcUrl).remove("mxc://");
|
||||
QFileInfo filename(QString("%1/media_cache/media/%2.%3")
|
||||
.arg(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))
|
||||
.arg(name)
|
||||
.arg(suffix));
|
||||
if (QDir::cleanPath(name) != name) {
|
||||
nhlog::net()->warn("mxcUrl '{}' is not safe, not downloading file", url);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
QFile file(filename.filePath());
|
||||
|
||||
QDir().mkpath(filename.path());
|
||||
if (!file.open(QIODevice::WriteOnly))
|
||||
return;
|
||||
|
||||
QPointer<MxcMediaProxy> self = this;
|
||||
QByteArray ba(data.data(), (int)data.size());
|
||||
file.write(ba);
|
||||
file.close();
|
||||
|
||||
auto processBuffer = [this, encryptionInfo, filename, self](QIODevice &device) {
|
||||
if (!self)
|
||||
return;
|
||||
|
||||
if (encryptionInfo) {
|
||||
QByteArray ba = device.readAll();
|
||||
std::string temp(ba.constData(), ba.size());
|
||||
temp = mtx::crypto::to_string(
|
||||
mtx::crypto::decrypt_file(temp, encryptionInfo.value()));
|
||||
buffer.setData(temp.data(), temp.size());
|
||||
} else {
|
||||
buffer.setData(device.readAll());
|
||||
}
|
||||
buffer.open(QIODevice::ReadOnly);
|
||||
buffer.reset();
|
||||
|
||||
QTimer::singleShot(0, this, [this, filename] {
|
||||
nhlog::ui()->info("Playing buffer with size: {}, {}",
|
||||
buffer.bytesAvailable(),
|
||||
buffer.isOpen());
|
||||
this->setMedia(QMediaContent(filename.fileName()), &buffer);
|
||||
emit loadedChanged();
|
||||
});
|
||||
};
|
||||
|
||||
if (filename.isReadable()) {
|
||||
QFile f(filename.filePath());
|
||||
if (f.open(QIODevice::ReadOnly)) {
|
||||
processBuffer(f);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
http::client()->download(
|
||||
url,
|
||||
[filename, url, processBuffer](const std::string &data,
|
||||
const std::string &,
|
||||
const std::string &,
|
||||
mtx::http::RequestErr err) {
|
||||
if (err) {
|
||||
nhlog::net()->warn("failed to retrieve media {}: {} {}",
|
||||
url,
|
||||
err->matrix_error.error,
|
||||
static_cast<int>(err->status_code));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
QFile file(filename.filePath());
|
||||
|
||||
if (!file.open(QIODevice::WriteOnly))
|
||||
return;
|
||||
|
||||
QByteArray ba(data.data(), (int)data.size());
|
||||
file.write(ba);
|
||||
file.close();
|
||||
|
||||
QBuffer buf(&ba);
|
||||
buf.open(QBuffer::ReadOnly);
|
||||
processBuffer(buf);
|
||||
} catch (const std::exception &e) {
|
||||
nhlog::ui()->warn("Error while saving file to: {}", e.what());
|
||||
}
|
||||
});
|
||||
QBuffer buf(&ba);
|
||||
buf.open(QBuffer::ReadOnly);
|
||||
processBuffer(buf);
|
||||
} catch (const std::exception &e) {
|
||||
nhlog::ui()->warn("Error while saving file to: {}", e.what());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,61 +20,58 @@ class TimelineModel;
|
|||
// need the videoSurface property, so that part is really easy!
|
||||
class MxcMediaProxy : public QMediaPlayer
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(TimelineModel *roomm READ room WRITE setRoom NOTIFY roomChanged REQUIRED)
|
||||
Q_PROPERTY(QString eventId READ eventId WRITE setEventId NOTIFY eventIdChanged)
|
||||
Q_PROPERTY(QAbstractVideoSurface *videoSurface READ getVideoSurface WRITE setVideoSurface)
|
||||
Q_PROPERTY(bool loaded READ loaded NOTIFY loadedChanged)
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(TimelineModel *roomm READ room WRITE setRoom NOTIFY roomChanged REQUIRED)
|
||||
Q_PROPERTY(QString eventId READ eventId WRITE setEventId NOTIFY eventIdChanged)
|
||||
Q_PROPERTY(QAbstractVideoSurface *videoSurface READ getVideoSurface WRITE setVideoSurface)
|
||||
Q_PROPERTY(bool loaded READ loaded NOTIFY loadedChanged)
|
||||
public:
|
||||
MxcMediaProxy(QObject *parent = nullptr)
|
||||
: QMediaPlayer(parent)
|
||||
{
|
||||
connect(this, &MxcMediaProxy::eventIdChanged, &MxcMediaProxy::startDownload);
|
||||
connect(this, &MxcMediaProxy::roomChanged, &MxcMediaProxy::startDownload);
|
||||
connect(this,
|
||||
qOverload<QMediaPlayer::Error>(&MxcMediaProxy::error),
|
||||
[this](QMediaPlayer::Error error) {
|
||||
nhlog::ui()->info("Media player error {} and errorStr {}",
|
||||
error,
|
||||
this->errorString().toStdString());
|
||||
});
|
||||
connect(this,
|
||||
&MxcMediaProxy::mediaStatusChanged,
|
||||
[this](QMediaPlayer::MediaStatus status) {
|
||||
nhlog::ui()->info(
|
||||
"Media player status {} and error {}", status, this->error());
|
||||
});
|
||||
}
|
||||
MxcMediaProxy(QObject *parent = nullptr)
|
||||
: QMediaPlayer(parent)
|
||||
{
|
||||
connect(this, &MxcMediaProxy::eventIdChanged, &MxcMediaProxy::startDownload);
|
||||
connect(this, &MxcMediaProxy::roomChanged, &MxcMediaProxy::startDownload);
|
||||
connect(this,
|
||||
qOverload<QMediaPlayer::Error>(&MxcMediaProxy::error),
|
||||
[this](QMediaPlayer::Error error) {
|
||||
nhlog::ui()->info("Media player error {} and errorStr {}",
|
||||
error,
|
||||
this->errorString().toStdString());
|
||||
});
|
||||
connect(this, &MxcMediaProxy::mediaStatusChanged, [this](QMediaPlayer::MediaStatus status) {
|
||||
nhlog::ui()->info("Media player status {} and error {}", status, this->error());
|
||||
});
|
||||
}
|
||||
|
||||
bool loaded() const { return buffer.size() > 0; }
|
||||
QString eventId() const { return eventId_; }
|
||||
TimelineModel *room() const { return room_; }
|
||||
void setEventId(QString newEventId)
|
||||
{
|
||||
eventId_ = newEventId;
|
||||
emit eventIdChanged();
|
||||
}
|
||||
void setRoom(TimelineModel *room)
|
||||
{
|
||||
room_ = room;
|
||||
emit roomChanged();
|
||||
}
|
||||
void setVideoSurface(QAbstractVideoSurface *surface);
|
||||
QAbstractVideoSurface *getVideoSurface();
|
||||
bool loaded() const { return buffer.size() > 0; }
|
||||
QString eventId() const { return eventId_; }
|
||||
TimelineModel *room() const { return room_; }
|
||||
void setEventId(QString newEventId)
|
||||
{
|
||||
eventId_ = newEventId;
|
||||
emit eventIdChanged();
|
||||
}
|
||||
void setRoom(TimelineModel *room)
|
||||
{
|
||||
room_ = room;
|
||||
emit roomChanged();
|
||||
}
|
||||
void setVideoSurface(QAbstractVideoSurface *surface);
|
||||
QAbstractVideoSurface *getVideoSurface();
|
||||
|
||||
signals:
|
||||
void roomChanged();
|
||||
void eventIdChanged();
|
||||
void loadedChanged();
|
||||
void newBuffer(QMediaContent, QIODevice *buf);
|
||||
void roomChanged();
|
||||
void eventIdChanged();
|
||||
void loadedChanged();
|
||||
void newBuffer(QMediaContent, QIODevice *buf);
|
||||
|
||||
private slots:
|
||||
void startDownload();
|
||||
void startDownload();
|
||||
|
||||
private:
|
||||
TimelineModel *room_ = nullptr;
|
||||
QString eventId_;
|
||||
QString filename_;
|
||||
QBuffer buffer;
|
||||
QAbstractVideoSurface *m_surface = nullptr;
|
||||
TimelineModel *room_ = nullptr;
|
||||
QString eventId_;
|
||||
QString filename_;
|
||||
QBuffer buffer;
|
||||
QAbstractVideoSurface *m_surface = nullptr;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -14,16 +14,16 @@ NhekoCursorShape::NhekoCursorShape(QQuickItem *parent)
|
|||
Qt::CursorShape
|
||||
NhekoCursorShape::cursorShape() const
|
||||
{
|
||||
return cursor().shape();
|
||||
return cursor().shape();
|
||||
}
|
||||
|
||||
void
|
||||
NhekoCursorShape::setCursorShape(Qt::CursorShape cursorShape)
|
||||
{
|
||||
if (currentShape_ == cursorShape)
|
||||
return;
|
||||
if (currentShape_ == cursorShape)
|
||||
return;
|
||||
|
||||
currentShape_ = cursorShape;
|
||||
setCursor(cursorShape);
|
||||
emit cursorShapeChanged();
|
||||
currentShape_ = cursorShape;
|
||||
setCursor(cursorShape);
|
||||
emit cursorShapeChanged();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,20 +11,20 @@
|
|||
|
||||
class NhekoCursorShape : public QQuickItem
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(Qt::CursorShape cursorShape READ cursorShape WRITE setCursorShape NOTIFY
|
||||
cursorShapeChanged)
|
||||
Q_PROPERTY(
|
||||
Qt::CursorShape cursorShape READ cursorShape WRITE setCursorShape NOTIFY cursorShapeChanged)
|
||||
|
||||
public:
|
||||
explicit NhekoCursorShape(QQuickItem *parent = 0);
|
||||
explicit NhekoCursorShape(QQuickItem *parent = 0);
|
||||
|
||||
private:
|
||||
Qt::CursorShape cursorShape() const;
|
||||
void setCursorShape(Qt::CursorShape cursorShape);
|
||||
Qt::CursorShape cursorShape() const;
|
||||
void setCursorShape(Qt::CursorShape cursorShape);
|
||||
|
||||
Qt::CursorShape currentShape_;
|
||||
Qt::CursorShape currentShape_;
|
||||
|
||||
signals:
|
||||
void cursorShapeChanged();
|
||||
void cursorShapeChanged();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -16,28 +16,28 @@
|
|||
NhekoDropArea::NhekoDropArea(QQuickItem *parent)
|
||||
: QQuickItem(parent)
|
||||
{
|
||||
setFlags(ItemAcceptsDrops);
|
||||
setFlags(ItemAcceptsDrops);
|
||||
}
|
||||
|
||||
void
|
||||
NhekoDropArea::dragEnterEvent(QDragEnterEvent *event)
|
||||
{
|
||||
event->acceptProposedAction();
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
|
||||
void
|
||||
NhekoDropArea::dragMoveEvent(QDragMoveEvent *event)
|
||||
{
|
||||
event->acceptProposedAction();
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
|
||||
void
|
||||
NhekoDropArea::dropEvent(QDropEvent *event)
|
||||
{
|
||||
if (event) {
|
||||
auto model = ChatPage::instance()->timelineManager()->rooms()->getRoomById(roomid_);
|
||||
if (model) {
|
||||
model->input()->insertMimeData(event->mimeData());
|
||||
}
|
||||
if (event) {
|
||||
auto model = ChatPage::instance()->timelineManager()->rooms()->getRoomById(roomid_);
|
||||
if (model) {
|
||||
model->input()->insertMimeData(event->mimeData());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,29 +6,29 @@
|
|||
|
||||
class NhekoDropArea : public QQuickItem
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString roomid READ roomid WRITE setRoomid NOTIFY roomidChanged)
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString roomid READ roomid WRITE setRoomid NOTIFY roomidChanged)
|
||||
public:
|
||||
NhekoDropArea(QQuickItem *parent = nullptr);
|
||||
NhekoDropArea(QQuickItem *parent = nullptr);
|
||||
|
||||
signals:
|
||||
void roomidChanged(QString roomid);
|
||||
void roomidChanged(QString roomid);
|
||||
|
||||
public slots:
|
||||
void setRoomid(QString roomid)
|
||||
{
|
||||
if (roomid_ != roomid) {
|
||||
roomid_ = roomid;
|
||||
emit roomidChanged(roomid);
|
||||
}
|
||||
void setRoomid(QString roomid)
|
||||
{
|
||||
if (roomid_ != roomid) {
|
||||
roomid_ = roomid;
|
||||
emit roomidChanged(roomid);
|
||||
}
|
||||
QString roomid() const { return roomid_; }
|
||||
}
|
||||
QString roomid() const { return roomid_; }
|
||||
|
||||
protected:
|
||||
void dragEnterEvent(QDragEnterEvent *event) override;
|
||||
void dragMoveEvent(QDragMoveEvent *event) override;
|
||||
void dropEvent(QDropEvent *event) override;
|
||||
void dragEnterEvent(QDragEnterEvent *event) override;
|
||||
void dragMoveEvent(QDragMoveEvent *event) override;
|
||||
void dropEvent(QDropEvent *event) override;
|
||||
|
||||
private:
|
||||
QString roomid_;
|
||||
QString roomid_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -17,93 +17,93 @@
|
|||
|
||||
Nheko::Nheko()
|
||||
{
|
||||
connect(
|
||||
UserSettings::instance().get(), &UserSettings::themeChanged, this, &Nheko::colorsChanged);
|
||||
connect(ChatPage::instance(), &ChatPage::contentLoaded, this, &Nheko::updateUserProfile);
|
||||
connect(
|
||||
UserSettings::instance().get(), &UserSettings::themeChanged, this, &Nheko::colorsChanged);
|
||||
connect(ChatPage::instance(), &ChatPage::contentLoaded, this, &Nheko::updateUserProfile);
|
||||
}
|
||||
|
||||
void
|
||||
Nheko::updateUserProfile()
|
||||
{
|
||||
if (cache::client() && cache::client()->isInitialized())
|
||||
currentUser_.reset(
|
||||
new UserProfile("", utils::localUser(), ChatPage::instance()->timelineManager()));
|
||||
else
|
||||
currentUser_.reset();
|
||||
emit profileChanged();
|
||||
if (cache::client() && cache::client()->isInitialized())
|
||||
currentUser_.reset(
|
||||
new UserProfile("", utils::localUser(), ChatPage::instance()->timelineManager()));
|
||||
else
|
||||
currentUser_.reset();
|
||||
emit profileChanged();
|
||||
}
|
||||
|
||||
QPalette
|
||||
Nheko::colors() const
|
||||
{
|
||||
return Theme::paletteFromTheme(UserSettings::instance()->theme().toStdString());
|
||||
return Theme::paletteFromTheme(UserSettings::instance()->theme().toStdString());
|
||||
}
|
||||
|
||||
QPalette
|
||||
Nheko::inactiveColors() const
|
||||
{
|
||||
auto p = colors();
|
||||
p.setCurrentColorGroup(QPalette::ColorGroup::Inactive);
|
||||
return p;
|
||||
auto p = colors();
|
||||
p.setCurrentColorGroup(QPalette::ColorGroup::Inactive);
|
||||
return p;
|
||||
}
|
||||
|
||||
Theme
|
||||
Nheko::theme() const
|
||||
{
|
||||
return Theme(UserSettings::instance()->theme().toStdString());
|
||||
return Theme(UserSettings::instance()->theme().toStdString());
|
||||
}
|
||||
|
||||
void
|
||||
Nheko::openLink(QString link) const
|
||||
{
|
||||
QUrl url(link);
|
||||
// Open externally if we couldn't handle it internally
|
||||
if (!ChatPage::instance()->handleMatrixUri(url)) {
|
||||
QDesktopServices::openUrl(url);
|
||||
}
|
||||
QUrl url(link);
|
||||
// Open externally if we couldn't handle it internally
|
||||
if (!ChatPage::instance()->handleMatrixUri(url)) {
|
||||
QDesktopServices::openUrl(url);
|
||||
}
|
||||
}
|
||||
void
|
||||
Nheko::setStatusMessage(QString msg) const
|
||||
{
|
||||
ChatPage::instance()->setStatus(msg);
|
||||
ChatPage::instance()->setStatus(msg);
|
||||
}
|
||||
|
||||
UserProfile *
|
||||
Nheko::currentUser() const
|
||||
{
|
||||
nhlog::ui()->debug("Profile requested");
|
||||
nhlog::ui()->debug("Profile requested");
|
||||
|
||||
return currentUser_.get();
|
||||
return currentUser_.get();
|
||||
}
|
||||
|
||||
void
|
||||
Nheko::showUserSettingsPage() const
|
||||
{
|
||||
ChatPage::instance()->showUserSettingsPage();
|
||||
ChatPage::instance()->showUserSettingsPage();
|
||||
}
|
||||
|
||||
void
|
||||
Nheko::openLogoutDialog() const
|
||||
{
|
||||
MainWindow::instance()->openLogoutDialog();
|
||||
MainWindow::instance()->openLogoutDialog();
|
||||
}
|
||||
|
||||
void
|
||||
Nheko::openCreateRoomDialog() const
|
||||
{
|
||||
MainWindow::instance()->openCreateRoomDialog(
|
||||
[](const mtx::requests::CreateRoom &req) { ChatPage::instance()->createRoom(req); });
|
||||
MainWindow::instance()->openCreateRoomDialog(
|
||||
[](const mtx::requests::CreateRoom &req) { ChatPage::instance()->createRoom(req); });
|
||||
}
|
||||
|
||||
void
|
||||
Nheko::openJoinRoomDialog() const
|
||||
{
|
||||
MainWindow::instance()->openJoinRoomDialog(
|
||||
[](const QString &room_id) { ChatPage::instance()->joinRoom(room_id); });
|
||||
MainWindow::instance()->openJoinRoomDialog(
|
||||
[](const QString &room_id) { ChatPage::instance()->joinRoom(room_id); });
|
||||
}
|
||||
|
||||
void
|
||||
Nheko::reparent(QWindow *win) const
|
||||
{
|
||||
win->setTransientParent(MainWindow::instance()->windowHandle());
|
||||
win->setTransientParent(MainWindow::instance()->windowHandle());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,51 +15,51 @@ class QWindow;
|
|||
|
||||
class Nheko : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QPalette colors READ colors NOTIFY colorsChanged)
|
||||
Q_PROPERTY(QPalette inactiveColors READ inactiveColors NOTIFY colorsChanged)
|
||||
Q_PROPERTY(Theme theme READ theme NOTIFY colorsChanged)
|
||||
Q_PROPERTY(int avatarSize READ avatarSize CONSTANT)
|
||||
Q_PROPERTY(int paddingSmall READ paddingSmall CONSTANT)
|
||||
Q_PROPERTY(int paddingMedium READ paddingMedium CONSTANT)
|
||||
Q_PROPERTY(int paddingLarge READ paddingLarge CONSTANT)
|
||||
Q_PROPERTY(QPalette colors READ colors NOTIFY colorsChanged)
|
||||
Q_PROPERTY(QPalette inactiveColors READ inactiveColors NOTIFY colorsChanged)
|
||||
Q_PROPERTY(Theme theme READ theme NOTIFY colorsChanged)
|
||||
Q_PROPERTY(int avatarSize READ avatarSize CONSTANT)
|
||||
Q_PROPERTY(int paddingSmall READ paddingSmall CONSTANT)
|
||||
Q_PROPERTY(int paddingMedium READ paddingMedium CONSTANT)
|
||||
Q_PROPERTY(int paddingLarge READ paddingLarge CONSTANT)
|
||||
|
||||
Q_PROPERTY(UserProfile *currentUser READ currentUser NOTIFY profileChanged)
|
||||
Q_PROPERTY(UserProfile *currentUser READ currentUser NOTIFY profileChanged)
|
||||
|
||||
public:
|
||||
Nheko();
|
||||
Nheko();
|
||||
|
||||
QPalette colors() const;
|
||||
QPalette inactiveColors() const;
|
||||
Theme theme() const;
|
||||
QPalette colors() const;
|
||||
QPalette inactiveColors() const;
|
||||
Theme theme() const;
|
||||
|
||||
int avatarSize() const { return 40; }
|
||||
int avatarSize() const { return 40; }
|
||||
|
||||
int paddingSmall() const { return 4; }
|
||||
int paddingMedium() const { return 8; }
|
||||
int paddingLarge() const { return 20; }
|
||||
UserProfile *currentUser() const;
|
||||
int paddingSmall() const { return 4; }
|
||||
int paddingMedium() const { return 8; }
|
||||
int paddingLarge() const { return 20; }
|
||||
UserProfile *currentUser() const;
|
||||
|
||||
Q_INVOKABLE QFont monospaceFont() const
|
||||
{
|
||||
return QFontDatabase::systemFont(QFontDatabase::FixedFont);
|
||||
}
|
||||
Q_INVOKABLE void openLink(QString link) const;
|
||||
Q_INVOKABLE void setStatusMessage(QString msg) const;
|
||||
Q_INVOKABLE void showUserSettingsPage() const;
|
||||
Q_INVOKABLE void openLogoutDialog() const;
|
||||
Q_INVOKABLE void openCreateRoomDialog() const;
|
||||
Q_INVOKABLE void openJoinRoomDialog() const;
|
||||
Q_INVOKABLE void reparent(QWindow *win) const;
|
||||
Q_INVOKABLE QFont monospaceFont() const
|
||||
{
|
||||
return QFontDatabase::systemFont(QFontDatabase::FixedFont);
|
||||
}
|
||||
Q_INVOKABLE void openLink(QString link) const;
|
||||
Q_INVOKABLE void setStatusMessage(QString msg) const;
|
||||
Q_INVOKABLE void showUserSettingsPage() const;
|
||||
Q_INVOKABLE void openLogoutDialog() const;
|
||||
Q_INVOKABLE void openCreateRoomDialog() const;
|
||||
Q_INVOKABLE void openJoinRoomDialog() const;
|
||||
Q_INVOKABLE void reparent(QWindow *win) const;
|
||||
|
||||
public slots:
|
||||
void updateUserProfile();
|
||||
void updateUserProfile();
|
||||
|
||||
signals:
|
||||
void colorsChanged();
|
||||
void profileChanged();
|
||||
void colorsChanged();
|
||||
void profileChanged();
|
||||
|
||||
private:
|
||||
QScopedPointer<UserProfile> currentUser_;
|
||||
QScopedPointer<UserProfile> currentUser_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,50 +12,50 @@ OverlayModal::OverlayModal(QWidget *parent)
|
|||
: OverlayWidget(parent)
|
||||
, color_{QColor(30, 30, 30, 170)}
|
||||
{
|
||||
layout_ = new QVBoxLayout(this);
|
||||
layout_->setSpacing(0);
|
||||
layout_->setContentsMargins(10, 40, 10, 20);
|
||||
setContentAlignment(Qt::AlignCenter);
|
||||
layout_ = new QVBoxLayout(this);
|
||||
layout_->setSpacing(0);
|
||||
layout_->setContentsMargins(10, 40, 10, 20);
|
||||
setContentAlignment(Qt::AlignCenter);
|
||||
}
|
||||
|
||||
void
|
||||
OverlayModal::setWidget(QWidget *widget)
|
||||
{
|
||||
// Delete the previous widget
|
||||
if (layout_->count() > 0) {
|
||||
QLayoutItem *item;
|
||||
while ((item = layout_->takeAt(0)) != nullptr) {
|
||||
delete item->widget();
|
||||
delete item;
|
||||
}
|
||||
// Delete the previous widget
|
||||
if (layout_->count() > 0) {
|
||||
QLayoutItem *item;
|
||||
while ((item = layout_->takeAt(0)) != nullptr) {
|
||||
delete item->widget();
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
|
||||
layout_->addWidget(widget);
|
||||
content_ = widget;
|
||||
content_->setFocus();
|
||||
layout_->addWidget(widget);
|
||||
content_ = widget;
|
||||
content_->setFocus();
|
||||
}
|
||||
|
||||
void
|
||||
OverlayModal::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
Q_UNUSED(event);
|
||||
|
||||
QPainter painter(this);
|
||||
painter.fillRect(rect(), color_);
|
||||
QPainter painter(this);
|
||||
painter.fillRect(rect(), color_);
|
||||
}
|
||||
|
||||
void
|
||||
OverlayModal::mousePressEvent(QMouseEvent *e)
|
||||
{
|
||||
if (isDismissible_ && content_ && !content_->geometry().contains(e->pos()))
|
||||
hide();
|
||||
if (isDismissible_ && content_ && !content_->geometry().contains(e->pos()))
|
||||
hide();
|
||||
}
|
||||
|
||||
void
|
||||
OverlayModal::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
if (event->key() == Qt::Key_Escape) {
|
||||
event->accept();
|
||||
hide();
|
||||
}
|
||||
if (event->key() == Qt::Key_Escape) {
|
||||
event->accept();
|
||||
hide();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,25 +15,25 @@
|
|||
class OverlayModal : public OverlayWidget
|
||||
{
|
||||
public:
|
||||
OverlayModal(QWidget *parent);
|
||||
OverlayModal(QWidget *parent);
|
||||
|
||||
void setColor(QColor color) { color_ = color; }
|
||||
void setDismissible(bool state) { isDismissible_ = state; }
|
||||
void setColor(QColor color) { color_ = color; }
|
||||
void setDismissible(bool state) { isDismissible_ = state; }
|
||||
|
||||
void setContentAlignment(QFlags<Qt::AlignmentFlag> flag) { layout_->setAlignment(flag); }
|
||||
void setWidget(QWidget *widget);
|
||||
void setContentAlignment(QFlags<Qt::AlignmentFlag> flag) { layout_->setAlignment(flag); }
|
||||
void setWidget(QWidget *widget);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void keyPressEvent(QKeyEvent *event) override;
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void keyPressEvent(QKeyEvent *event) override;
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
|
||||
private:
|
||||
QWidget *content_;
|
||||
QVBoxLayout *layout_;
|
||||
QWidget *content_;
|
||||
QVBoxLayout *layout_;
|
||||
|
||||
QColor color_;
|
||||
QColor color_;
|
||||
|
||||
//! Decides whether or not the modal can be removed by clicking into it.
|
||||
bool isDismissible_ = true;
|
||||
//! Decides whether or not the modal can be removed by clicking into it.
|
||||
bool isDismissible_ = true;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -10,69 +10,69 @@
|
|||
OverlayWidget::OverlayWidget(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
if (parent) {
|
||||
parent->installEventFilter(this);
|
||||
setGeometry(overlayGeometry());
|
||||
raise();
|
||||
}
|
||||
if (parent) {
|
||||
parent->installEventFilter(this);
|
||||
setGeometry(overlayGeometry());
|
||||
raise();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
OverlayWidget::event(QEvent *event)
|
||||
{
|
||||
if (!parent())
|
||||
return QWidget::event(event);
|
||||
|
||||
switch (event->type()) {
|
||||
case QEvent::ParentChange: {
|
||||
parent()->installEventFilter(this);
|
||||
setGeometry(overlayGeometry());
|
||||
break;
|
||||
}
|
||||
case QEvent::ParentAboutToChange: {
|
||||
parent()->removeEventFilter(this);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!parent())
|
||||
return QWidget::event(event);
|
||||
|
||||
switch (event->type()) {
|
||||
case QEvent::ParentChange: {
|
||||
parent()->installEventFilter(this);
|
||||
setGeometry(overlayGeometry());
|
||||
break;
|
||||
}
|
||||
case QEvent::ParentAboutToChange: {
|
||||
parent()->removeEventFilter(this);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return QWidget::event(event);
|
||||
}
|
||||
|
||||
bool
|
||||
OverlayWidget::eventFilter(QObject *obj, QEvent *event)
|
||||
{
|
||||
switch (event->type()) {
|
||||
case QEvent::Move:
|
||||
case QEvent::Resize:
|
||||
setGeometry(overlayGeometry());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (event->type()) {
|
||||
case QEvent::Move:
|
||||
case QEvent::Resize:
|
||||
setGeometry(overlayGeometry());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return QWidget::eventFilter(obj, event);
|
||||
return QWidget::eventFilter(obj, event);
|
||||
}
|
||||
|
||||
QRect
|
||||
OverlayWidget::overlayGeometry() const
|
||||
{
|
||||
QWidget *widget = parentWidget();
|
||||
QWidget *widget = parentWidget();
|
||||
|
||||
if (!widget)
|
||||
return QRect();
|
||||
if (!widget)
|
||||
return QRect();
|
||||
|
||||
return widget->rect();
|
||||
return widget->rect();
|
||||
}
|
||||
|
||||
void
|
||||
OverlayWidget::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
Q_UNUSED(event);
|
||||
|
||||
QStyleOption opt;
|
||||
opt.init(this);
|
||||
QPainter p(this);
|
||||
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
|
||||
QStyleOption opt;
|
||||
opt.init(this);
|
||||
QPainter p(this);
|
||||
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,15 +11,15 @@ class QPainter;
|
|||
|
||||
class OverlayWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit OverlayWidget(QWidget *parent = nullptr);
|
||||
explicit OverlayWidget(QWidget *parent = nullptr);
|
||||
|
||||
protected:
|
||||
bool event(QEvent *event) override;
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
bool event(QEvent *event) override;
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
|
||||
QRect overlayGeometry() const;
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
QRect overlayGeometry() const;
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
};
|
||||
|
|
|
|||
218
src/ui/Painter.h
218
src/ui/Painter.h
|
|
@ -13,147 +13,141 @@
|
|||
class Painter : public QPainter
|
||||
{
|
||||
public:
|
||||
explicit Painter(QPaintDevice *device)
|
||||
: QPainter(device)
|
||||
{}
|
||||
explicit Painter(QPaintDevice *device)
|
||||
: QPainter(device)
|
||||
{}
|
||||
|
||||
void drawTextLeft(int x, int y, const QString &text)
|
||||
{
|
||||
QFontMetrics m(fontMetrics());
|
||||
drawText(x, y + m.ascent(), text);
|
||||
void drawTextLeft(int x, int y, const QString &text)
|
||||
{
|
||||
QFontMetrics m(fontMetrics());
|
||||
drawText(x, y + m.ascent(), text);
|
||||
}
|
||||
|
||||
void drawTextRight(int x, int y, int outerw, const QString &text, int textWidth = -1)
|
||||
{
|
||||
QFontMetrics m(fontMetrics());
|
||||
if (textWidth < 0) {
|
||||
textWidth = m.horizontalAdvance(text);
|
||||
}
|
||||
drawText((outerw - x - textWidth), y + m.ascent(), text);
|
||||
}
|
||||
|
||||
void drawTextRight(int x, int y, int outerw, const QString &text, int textWidth = -1)
|
||||
{
|
||||
QFontMetrics m(fontMetrics());
|
||||
if (textWidth < 0) {
|
||||
textWidth = m.horizontalAdvance(text);
|
||||
}
|
||||
drawText((outerw - x - textWidth), y + m.ascent(), text);
|
||||
}
|
||||
void drawPixmapLeft(int x, int y, const QPixmap &pix, const QRect &from)
|
||||
{
|
||||
drawPixmap(QPoint(x, y), pix, from);
|
||||
}
|
||||
|
||||
void drawPixmapLeft(int x, int y, const QPixmap &pix, const QRect &from)
|
||||
{
|
||||
drawPixmap(QPoint(x, y), pix, from);
|
||||
}
|
||||
void drawPixmapLeft(const QPoint &p, const QPixmap &pix, const QRect &from)
|
||||
{
|
||||
return drawPixmapLeft(p.x(), p.y(), pix, from);
|
||||
}
|
||||
|
||||
void drawPixmapLeft(const QPoint &p, const QPixmap &pix, const QRect &from)
|
||||
{
|
||||
return drawPixmapLeft(p.x(), p.y(), pix, from);
|
||||
}
|
||||
void drawPixmapLeft(int x, int y, int w, int h, const QPixmap &pix, const QRect &from)
|
||||
{
|
||||
drawPixmap(QRect(x, y, w, h), pix, from);
|
||||
}
|
||||
|
||||
void drawPixmapLeft(int x, int y, int w, int h, const QPixmap &pix, const QRect &from)
|
||||
{
|
||||
drawPixmap(QRect(x, y, w, h), pix, from);
|
||||
}
|
||||
void drawPixmapLeft(const QRect &r, const QPixmap &pix, const QRect &from)
|
||||
{
|
||||
return drawPixmapLeft(r.x(), r.y(), r.width(), r.height(), pix, from);
|
||||
}
|
||||
|
||||
void drawPixmapLeft(const QRect &r, const QPixmap &pix, const QRect &from)
|
||||
{
|
||||
return drawPixmapLeft(r.x(), r.y(), r.width(), r.height(), pix, from);
|
||||
}
|
||||
void drawPixmapLeft(int x, int y, int outerw, const QPixmap &pix)
|
||||
{
|
||||
Q_UNUSED(outerw);
|
||||
drawPixmap(QPoint(x, y), pix);
|
||||
}
|
||||
|
||||
void drawPixmapLeft(int x, int y, int outerw, const QPixmap &pix)
|
||||
{
|
||||
Q_UNUSED(outerw);
|
||||
drawPixmap(QPoint(x, y), pix);
|
||||
}
|
||||
void drawPixmapLeft(const QPoint &p, int outerw, const QPixmap &pix)
|
||||
{
|
||||
return drawPixmapLeft(p.x(), p.y(), outerw, pix);
|
||||
}
|
||||
|
||||
void drawPixmapLeft(const QPoint &p, int outerw, const QPixmap &pix)
|
||||
{
|
||||
return drawPixmapLeft(p.x(), p.y(), outerw, pix);
|
||||
}
|
||||
void drawPixmapRight(int x, int y, int outerw, const QPixmap &pix, const QRect &from)
|
||||
{
|
||||
drawPixmap(QPoint((outerw - x - (from.width() / pix.devicePixelRatio())), y), pix, from);
|
||||
}
|
||||
|
||||
void drawPixmapRight(int x, int y, int outerw, const QPixmap &pix, const QRect &from)
|
||||
{
|
||||
drawPixmap(
|
||||
QPoint((outerw - x - (from.width() / pix.devicePixelRatio())), y), pix, from);
|
||||
}
|
||||
void drawPixmapRight(const QPoint &p, int outerw, const QPixmap &pix, const QRect &from)
|
||||
{
|
||||
return drawPixmapRight(p.x(), p.y(), outerw, pix, from);
|
||||
}
|
||||
void
|
||||
drawPixmapRight(int x, int y, int w, int h, int outerw, const QPixmap &pix, const QRect &from)
|
||||
{
|
||||
drawPixmap(QRect((outerw - x - w), y, w, h), pix, from);
|
||||
}
|
||||
|
||||
void drawPixmapRight(const QPoint &p, int outerw, const QPixmap &pix, const QRect &from)
|
||||
{
|
||||
return drawPixmapRight(p.x(), p.y(), outerw, pix, from);
|
||||
}
|
||||
void drawPixmapRight(int x,
|
||||
int y,
|
||||
int w,
|
||||
int h,
|
||||
int outerw,
|
||||
const QPixmap &pix,
|
||||
const QRect &from)
|
||||
{
|
||||
drawPixmap(QRect((outerw - x - w), y, w, h), pix, from);
|
||||
}
|
||||
void drawPixmapRight(const QRect &r, int outerw, const QPixmap &pix, const QRect &from)
|
||||
{
|
||||
return drawPixmapRight(r.x(), r.y(), r.width(), r.height(), outerw, pix, from);
|
||||
}
|
||||
|
||||
void drawPixmapRight(const QRect &r, int outerw, const QPixmap &pix, const QRect &from)
|
||||
{
|
||||
return drawPixmapRight(r.x(), r.y(), r.width(), r.height(), outerw, pix, from);
|
||||
}
|
||||
void drawPixmapRight(int x, int y, int outerw, const QPixmap &pix)
|
||||
{
|
||||
drawPixmap(QPoint((outerw - x - (pix.width() / pix.devicePixelRatio())), y), pix);
|
||||
}
|
||||
|
||||
void drawPixmapRight(int x, int y, int outerw, const QPixmap &pix)
|
||||
{
|
||||
drawPixmap(QPoint((outerw - x - (pix.width() / pix.devicePixelRatio())), y), pix);
|
||||
}
|
||||
void drawPixmapRight(const QPoint &p, int outerw, const QPixmap &pix)
|
||||
{
|
||||
return drawPixmapRight(p.x(), p.y(), outerw, pix);
|
||||
}
|
||||
|
||||
void drawPixmapRight(const QPoint &p, int outerw, const QPixmap &pix)
|
||||
{
|
||||
return drawPixmapRight(p.x(), p.y(), outerw, pix);
|
||||
}
|
||||
void drawAvatar(const QPixmap &pix, int w, int h, int d)
|
||||
{
|
||||
QPainterPath pp;
|
||||
pp.addEllipse((w - d) / 2, (h - d) / 2, d, d);
|
||||
|
||||
void drawAvatar(const QPixmap &pix, int w, int h, int d)
|
||||
{
|
||||
QPainterPath pp;
|
||||
pp.addEllipse((w - d) / 2, (h - d) / 2, d, d);
|
||||
QRect region((w - d) / 2, (h - d) / 2, d, d);
|
||||
|
||||
QRect region((w - d) / 2, (h - d) / 2, d, d);
|
||||
setClipPath(pp);
|
||||
drawPixmap(region, pix);
|
||||
}
|
||||
|
||||
setClipPath(pp);
|
||||
drawPixmap(region, pix);
|
||||
}
|
||||
void drawLetterAvatar(const QString &c,
|
||||
const QColor &penColor,
|
||||
const QColor &brushColor,
|
||||
int w,
|
||||
int h,
|
||||
int d)
|
||||
{
|
||||
QRect region((w - d) / 2, (h - d) / 2, d, d);
|
||||
|
||||
void drawLetterAvatar(const QString &c,
|
||||
const QColor &penColor,
|
||||
const QColor &brushColor,
|
||||
int w,
|
||||
int h,
|
||||
int d)
|
||||
{
|
||||
QRect region((w - d) / 2, (h - d) / 2, d, d);
|
||||
setPen(Qt::NoPen);
|
||||
setBrush(brushColor);
|
||||
|
||||
setPen(Qt::NoPen);
|
||||
setBrush(brushColor);
|
||||
drawEllipse(region.center(), d / 2, d / 2);
|
||||
|
||||
drawEllipse(region.center(), d / 2, d / 2);
|
||||
setBrush(Qt::NoBrush);
|
||||
drawEllipse(region.center(), d / 2, d / 2);
|
||||
|
||||
setBrush(Qt::NoBrush);
|
||||
drawEllipse(region.center(), d / 2, d / 2);
|
||||
|
||||
setPen(penColor);
|
||||
drawText(region.translated(0, -1), Qt::AlignCenter, c);
|
||||
}
|
||||
setPen(penColor);
|
||||
drawText(region.translated(0, -1), Qt::AlignCenter, c);
|
||||
}
|
||||
};
|
||||
|
||||
class PainterHighQualityEnabler
|
||||
{
|
||||
public:
|
||||
PainterHighQualityEnabler(Painter &p)
|
||||
: _painter(p)
|
||||
{
|
||||
hints_ = QPainter::Antialiasing | QPainter::SmoothPixmapTransform |
|
||||
QPainter::TextAntialiasing;
|
||||
PainterHighQualityEnabler(Painter &p)
|
||||
: _painter(p)
|
||||
{
|
||||
hints_ =
|
||||
QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::TextAntialiasing;
|
||||
|
||||
_painter.setRenderHints(hints_);
|
||||
}
|
||||
_painter.setRenderHints(hints_);
|
||||
}
|
||||
|
||||
~PainterHighQualityEnabler()
|
||||
{
|
||||
if (hints_)
|
||||
_painter.setRenderHints(hints_, false);
|
||||
}
|
||||
~PainterHighQualityEnabler()
|
||||
{
|
||||
if (hints_)
|
||||
_painter.setRenderHints(hints_, false);
|
||||
}
|
||||
|
||||
PainterHighQualityEnabler(const PainterHighQualityEnabler &other) = delete;
|
||||
PainterHighQualityEnabler &operator=(const PainterHighQualityEnabler &other) = delete;
|
||||
PainterHighQualityEnabler(const PainterHighQualityEnabler &other) = delete;
|
||||
PainterHighQualityEnabler &operator=(const PainterHighQualityEnabler &other) = delete;
|
||||
|
||||
private:
|
||||
Painter &_painter;
|
||||
QPainter::RenderHints hints_ = {};
|
||||
Painter &_painter;
|
||||
QPainter::RenderHints hints_ = {};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -10,68 +10,68 @@
|
|||
void
|
||||
RaisedButton::init()
|
||||
{
|
||||
shadow_state_machine_ = new QStateMachine(this);
|
||||
normal_state_ = new QState;
|
||||
pressed_state_ = new QState;
|
||||
effect_ = new QGraphicsDropShadowEffect;
|
||||
shadow_state_machine_ = new QStateMachine(this);
|
||||
normal_state_ = new QState;
|
||||
pressed_state_ = new QState;
|
||||
effect_ = new QGraphicsDropShadowEffect;
|
||||
|
||||
effect_->setBlurRadius(7);
|
||||
effect_->setOffset(QPointF(0, 2));
|
||||
effect_->setColor(QColor(0, 0, 0, 75));
|
||||
effect_->setBlurRadius(7);
|
||||
effect_->setOffset(QPointF(0, 2));
|
||||
effect_->setColor(QColor(0, 0, 0, 75));
|
||||
|
||||
setBackgroundMode(Qt::OpaqueMode);
|
||||
setMinimumHeight(42);
|
||||
setGraphicsEffect(effect_);
|
||||
setBaseOpacity(0.3);
|
||||
setBackgroundMode(Qt::OpaqueMode);
|
||||
setMinimumHeight(42);
|
||||
setGraphicsEffect(effect_);
|
||||
setBaseOpacity(0.3);
|
||||
|
||||
shadow_state_machine_->addState(normal_state_);
|
||||
shadow_state_machine_->addState(pressed_state_);
|
||||
shadow_state_machine_->addState(normal_state_);
|
||||
shadow_state_machine_->addState(pressed_state_);
|
||||
|
||||
normal_state_->assignProperty(effect_, "offset", QPointF(0, 2));
|
||||
normal_state_->assignProperty(effect_, "blurRadius", 7);
|
||||
normal_state_->assignProperty(effect_, "offset", QPointF(0, 2));
|
||||
normal_state_->assignProperty(effect_, "blurRadius", 7);
|
||||
|
||||
pressed_state_->assignProperty(effect_, "offset", QPointF(0, 5));
|
||||
pressed_state_->assignProperty(effect_, "blurRadius", 29);
|
||||
pressed_state_->assignProperty(effect_, "offset", QPointF(0, 5));
|
||||
pressed_state_->assignProperty(effect_, "blurRadius", 29);
|
||||
|
||||
QAbstractTransition *transition;
|
||||
QAbstractTransition *transition;
|
||||
|
||||
transition = new QEventTransition(this, QEvent::MouseButtonPress);
|
||||
transition->setTargetState(pressed_state_);
|
||||
normal_state_->addTransition(transition);
|
||||
transition = new QEventTransition(this, QEvent::MouseButtonPress);
|
||||
transition->setTargetState(pressed_state_);
|
||||
normal_state_->addTransition(transition);
|
||||
|
||||
transition = new QEventTransition(this, QEvent::MouseButtonDblClick);
|
||||
transition->setTargetState(pressed_state_);
|
||||
normal_state_->addTransition(transition);
|
||||
transition = new QEventTransition(this, QEvent::MouseButtonDblClick);
|
||||
transition->setTargetState(pressed_state_);
|
||||
normal_state_->addTransition(transition);
|
||||
|
||||
transition = new QEventTransition(this, QEvent::MouseButtonRelease);
|
||||
transition->setTargetState(normal_state_);
|
||||
pressed_state_->addTransition(transition);
|
||||
transition = new QEventTransition(this, QEvent::MouseButtonRelease);
|
||||
transition->setTargetState(normal_state_);
|
||||
pressed_state_->addTransition(transition);
|
||||
|
||||
QPropertyAnimation *animation;
|
||||
QPropertyAnimation *animation;
|
||||
|
||||
animation = new QPropertyAnimation(effect_, "offset", this);
|
||||
animation->setDuration(100);
|
||||
shadow_state_machine_->addDefaultAnimation(animation);
|
||||
animation = new QPropertyAnimation(effect_, "offset", this);
|
||||
animation->setDuration(100);
|
||||
shadow_state_machine_->addDefaultAnimation(animation);
|
||||
|
||||
animation = new QPropertyAnimation(effect_, "blurRadius", this);
|
||||
animation->setDuration(100);
|
||||
shadow_state_machine_->addDefaultAnimation(animation);
|
||||
animation = new QPropertyAnimation(effect_, "blurRadius", this);
|
||||
animation->setDuration(100);
|
||||
shadow_state_machine_->addDefaultAnimation(animation);
|
||||
|
||||
shadow_state_machine_->setInitialState(normal_state_);
|
||||
shadow_state_machine_->start();
|
||||
shadow_state_machine_->setInitialState(normal_state_);
|
||||
shadow_state_machine_->start();
|
||||
}
|
||||
|
||||
RaisedButton::RaisedButton(QWidget *parent)
|
||||
: FlatButton(parent)
|
||||
{
|
||||
init();
|
||||
init();
|
||||
}
|
||||
|
||||
RaisedButton::RaisedButton(const QString &text, QWidget *parent)
|
||||
: FlatButton(parent)
|
||||
{
|
||||
init();
|
||||
setText(text);
|
||||
init();
|
||||
setText(text);
|
||||
}
|
||||
|
||||
RaisedButton::~RaisedButton() {}
|
||||
|
|
@ -79,15 +79,15 @@ RaisedButton::~RaisedButton() {}
|
|||
bool
|
||||
RaisedButton::event(QEvent *event)
|
||||
{
|
||||
if (QEvent::EnabledChange == event->type()) {
|
||||
if (isEnabled()) {
|
||||
shadow_state_machine_->start();
|
||||
effect_->setEnabled(true);
|
||||
} else {
|
||||
shadow_state_machine_->stop();
|
||||
effect_->setEnabled(false);
|
||||
}
|
||||
if (QEvent::EnabledChange == event->type()) {
|
||||
if (isEnabled()) {
|
||||
shadow_state_machine_->start();
|
||||
effect_->setEnabled(true);
|
||||
} else {
|
||||
shadow_state_machine_->stop();
|
||||
effect_->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
return FlatButton::event(event);
|
||||
return FlatButton::event(event);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,21 +12,21 @@
|
|||
|
||||
class RaisedButton : public FlatButton
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit RaisedButton(QWidget *parent = nullptr);
|
||||
explicit RaisedButton(const QString &text, QWidget *parent = nullptr);
|
||||
~RaisedButton() override;
|
||||
explicit RaisedButton(QWidget *parent = nullptr);
|
||||
explicit RaisedButton(const QString &text, QWidget *parent = nullptr);
|
||||
~RaisedButton() override;
|
||||
|
||||
protected:
|
||||
bool event(QEvent *event) override;
|
||||
bool event(QEvent *event) override;
|
||||
|
||||
private:
|
||||
void init();
|
||||
void init();
|
||||
|
||||
QStateMachine *shadow_state_machine_;
|
||||
QState *normal_state_;
|
||||
QState *pressed_state_;
|
||||
QGraphicsDropShadowEffect *effect_;
|
||||
QStateMachine *shadow_state_machine_;
|
||||
QState *normal_state_;
|
||||
QState *pressed_state_;
|
||||
QGraphicsDropShadowEffect *effect_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ Ripple::Ripple(const QPoint ¢er, QObject *parent)
|
|||
, opacity_(0)
|
||||
, center_(center)
|
||||
{
|
||||
init();
|
||||
init();
|
||||
}
|
||||
|
||||
Ripple::Ripple(const QPoint ¢er, RippleOverlay *overlay, QObject *parent)
|
||||
|
|
@ -26,86 +26,86 @@ Ripple::Ripple(const QPoint ¢er, RippleOverlay *overlay, QObject *parent)
|
|||
, opacity_(0)
|
||||
, center_(center)
|
||||
{
|
||||
init();
|
||||
init();
|
||||
}
|
||||
|
||||
void
|
||||
Ripple::setRadius(qreal radius)
|
||||
{
|
||||
Q_ASSERT(overlay_);
|
||||
Q_ASSERT(overlay_);
|
||||
|
||||
if (radius_ == radius)
|
||||
return;
|
||||
if (radius_ == radius)
|
||||
return;
|
||||
|
||||
radius_ = radius;
|
||||
overlay_->update();
|
||||
radius_ = radius;
|
||||
overlay_->update();
|
||||
}
|
||||
|
||||
void
|
||||
Ripple::setOpacity(qreal opacity)
|
||||
{
|
||||
Q_ASSERT(overlay_);
|
||||
Q_ASSERT(overlay_);
|
||||
|
||||
if (opacity_ == opacity)
|
||||
return;
|
||||
if (opacity_ == opacity)
|
||||
return;
|
||||
|
||||
opacity_ = opacity;
|
||||
overlay_->update();
|
||||
opacity_ = opacity;
|
||||
overlay_->update();
|
||||
}
|
||||
|
||||
void
|
||||
Ripple::setColor(const QColor &color)
|
||||
{
|
||||
if (brush_.color() == color)
|
||||
return;
|
||||
if (brush_.color() == color)
|
||||
return;
|
||||
|
||||
brush_.setColor(color);
|
||||
brush_.setColor(color);
|
||||
|
||||
if (overlay_)
|
||||
overlay_->update();
|
||||
if (overlay_)
|
||||
overlay_->update();
|
||||
}
|
||||
|
||||
void
|
||||
Ripple::setBrush(const QBrush &brush)
|
||||
{
|
||||
brush_ = brush;
|
||||
brush_ = brush;
|
||||
|
||||
if (overlay_)
|
||||
overlay_->update();
|
||||
if (overlay_)
|
||||
overlay_->update();
|
||||
}
|
||||
|
||||
void
|
||||
Ripple::destroy()
|
||||
{
|
||||
Q_ASSERT(overlay_);
|
||||
Q_ASSERT(overlay_);
|
||||
|
||||
overlay_->removeRipple(this);
|
||||
overlay_->removeRipple(this);
|
||||
}
|
||||
|
||||
QPropertyAnimation *
|
||||
Ripple::animate(const QByteArray &property, const QEasingCurve &easing, int duration)
|
||||
{
|
||||
QPropertyAnimation *animation = new QPropertyAnimation;
|
||||
animation->setTargetObject(this);
|
||||
animation->setPropertyName(property);
|
||||
animation->setEasingCurve(easing);
|
||||
animation->setDuration(duration);
|
||||
QPropertyAnimation *animation = new QPropertyAnimation;
|
||||
animation->setTargetObject(this);
|
||||
animation->setPropertyName(property);
|
||||
animation->setEasingCurve(easing);
|
||||
animation->setDuration(duration);
|
||||
|
||||
addAnimation(animation);
|
||||
addAnimation(animation);
|
||||
|
||||
return animation;
|
||||
return animation;
|
||||
}
|
||||
|
||||
void
|
||||
Ripple::init()
|
||||
{
|
||||
setOpacityStartValue(0.5);
|
||||
setOpacityEndValue(0);
|
||||
setRadiusStartValue(0);
|
||||
setRadiusEndValue(300);
|
||||
setOpacityStartValue(0.5);
|
||||
setOpacityEndValue(0);
|
||||
setRadiusStartValue(0);
|
||||
setRadiusEndValue(300);
|
||||
|
||||
brush_.setColor(Qt::black);
|
||||
brush_.setStyle(Qt::SolidPattern);
|
||||
brush_.setColor(Qt::black);
|
||||
brush_.setStyle(Qt::SolidPattern);
|
||||
|
||||
connect(this, SIGNAL(finished()), this, SLOT(destroy()));
|
||||
connect(this, SIGNAL(finished()), this, SLOT(destroy()));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,136 +14,136 @@ class RippleOverlay;
|
|||
|
||||
class Ripple : public QParallelAnimationGroup
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(qreal radius WRITE setRadius READ radius)
|
||||
Q_PROPERTY(qreal opacity WRITE setOpacity READ opacity)
|
||||
Q_PROPERTY(qreal radius WRITE setRadius READ radius)
|
||||
Q_PROPERTY(qreal opacity WRITE setOpacity READ opacity)
|
||||
|
||||
public:
|
||||
explicit Ripple(const QPoint ¢er, QObject *parent = nullptr);
|
||||
Ripple(const QPoint ¢er, RippleOverlay *overlay, QObject *parent = nullptr);
|
||||
explicit Ripple(const QPoint ¢er, QObject *parent = nullptr);
|
||||
Ripple(const QPoint ¢er, RippleOverlay *overlay, QObject *parent = nullptr);
|
||||
|
||||
inline void setOverlay(RippleOverlay *overlay);
|
||||
inline void setOverlay(RippleOverlay *overlay);
|
||||
|
||||
void setRadius(qreal radius);
|
||||
void setOpacity(qreal opacity);
|
||||
void setColor(const QColor &color);
|
||||
void setBrush(const QBrush &brush);
|
||||
void setRadius(qreal radius);
|
||||
void setOpacity(qreal opacity);
|
||||
void setColor(const QColor &color);
|
||||
void setBrush(const QBrush &brush);
|
||||
|
||||
inline qreal radius() const;
|
||||
inline qreal opacity() const;
|
||||
inline QColor color() const;
|
||||
inline QBrush brush() const;
|
||||
inline QPoint center() const;
|
||||
inline qreal radius() const;
|
||||
inline qreal opacity() const;
|
||||
inline QColor color() const;
|
||||
inline QBrush brush() const;
|
||||
inline QPoint center() const;
|
||||
|
||||
inline QPropertyAnimation *radiusAnimation() const;
|
||||
inline QPropertyAnimation *opacityAnimation() const;
|
||||
inline QPropertyAnimation *radiusAnimation() const;
|
||||
inline QPropertyAnimation *opacityAnimation() const;
|
||||
|
||||
inline void setOpacityStartValue(qreal value);
|
||||
inline void setOpacityEndValue(qreal value);
|
||||
inline void setRadiusStartValue(qreal value);
|
||||
inline void setRadiusEndValue(qreal value);
|
||||
inline void setDuration(int msecs);
|
||||
inline void setOpacityStartValue(qreal value);
|
||||
inline void setOpacityEndValue(qreal value);
|
||||
inline void setRadiusStartValue(qreal value);
|
||||
inline void setRadiusEndValue(qreal value);
|
||||
inline void setDuration(int msecs);
|
||||
|
||||
protected slots:
|
||||
void destroy();
|
||||
void destroy();
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(Ripple)
|
||||
Q_DISABLE_COPY(Ripple)
|
||||
|
||||
QPropertyAnimation *animate(const QByteArray &property,
|
||||
const QEasingCurve &easing = QEasingCurve::OutQuad,
|
||||
int duration = 800);
|
||||
QPropertyAnimation *animate(const QByteArray &property,
|
||||
const QEasingCurve &easing = QEasingCurve::OutQuad,
|
||||
int duration = 800);
|
||||
|
||||
void init();
|
||||
void init();
|
||||
|
||||
RippleOverlay *overlay_;
|
||||
RippleOverlay *overlay_;
|
||||
|
||||
QPropertyAnimation *const radius_anim_;
|
||||
QPropertyAnimation *const opacity_anim_;
|
||||
QPropertyAnimation *const radius_anim_;
|
||||
QPropertyAnimation *const opacity_anim_;
|
||||
|
||||
qreal radius_;
|
||||
qreal opacity_;
|
||||
qreal radius_;
|
||||
qreal opacity_;
|
||||
|
||||
QPoint center_;
|
||||
QBrush brush_;
|
||||
QPoint center_;
|
||||
QBrush brush_;
|
||||
};
|
||||
|
||||
inline void
|
||||
Ripple::setOverlay(RippleOverlay *overlay)
|
||||
{
|
||||
overlay_ = overlay;
|
||||
overlay_ = overlay;
|
||||
}
|
||||
|
||||
inline qreal
|
||||
Ripple::radius() const
|
||||
{
|
||||
return radius_;
|
||||
return radius_;
|
||||
}
|
||||
|
||||
inline qreal
|
||||
Ripple::opacity() const
|
||||
{
|
||||
return opacity_;
|
||||
return opacity_;
|
||||
}
|
||||
|
||||
inline QColor
|
||||
Ripple::color() const
|
||||
{
|
||||
return brush_.color();
|
||||
return brush_.color();
|
||||
}
|
||||
|
||||
inline QBrush
|
||||
Ripple::brush() const
|
||||
{
|
||||
return brush_;
|
||||
return brush_;
|
||||
}
|
||||
|
||||
inline QPoint
|
||||
Ripple::center() const
|
||||
{
|
||||
return center_;
|
||||
return center_;
|
||||
}
|
||||
|
||||
inline QPropertyAnimation *
|
||||
Ripple::radiusAnimation() const
|
||||
{
|
||||
return radius_anim_;
|
||||
return radius_anim_;
|
||||
}
|
||||
|
||||
inline QPropertyAnimation *
|
||||
Ripple::opacityAnimation() const
|
||||
{
|
||||
return opacity_anim_;
|
||||
return opacity_anim_;
|
||||
}
|
||||
|
||||
inline void
|
||||
Ripple::setOpacityStartValue(qreal value)
|
||||
{
|
||||
opacity_anim_->setStartValue(value);
|
||||
opacity_anim_->setStartValue(value);
|
||||
}
|
||||
|
||||
inline void
|
||||
Ripple::setOpacityEndValue(qreal value)
|
||||
{
|
||||
opacity_anim_->setEndValue(value);
|
||||
opacity_anim_->setEndValue(value);
|
||||
}
|
||||
|
||||
inline void
|
||||
Ripple::setRadiusStartValue(qreal value)
|
||||
{
|
||||
radius_anim_->setStartValue(value);
|
||||
radius_anim_->setStartValue(value);
|
||||
}
|
||||
|
||||
inline void
|
||||
Ripple::setRadiusEndValue(qreal value)
|
||||
{
|
||||
radius_anim_->setEndValue(value);
|
||||
radius_anim_->setEndValue(value);
|
||||
}
|
||||
|
||||
inline void
|
||||
Ripple::setDuration(int msecs)
|
||||
{
|
||||
radius_anim_->setDuration(msecs);
|
||||
opacity_anim_->setDuration(msecs);
|
||||
radius_anim_->setDuration(msecs);
|
||||
opacity_anim_->setDuration(msecs);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,56 +11,56 @@ RippleOverlay::RippleOverlay(QWidget *parent)
|
|||
: OverlayWidget(parent)
|
||||
, use_clip_(false)
|
||||
{
|
||||
setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
setAttribute(Qt::WA_NoSystemBackground);
|
||||
setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
setAttribute(Qt::WA_NoSystemBackground);
|
||||
}
|
||||
|
||||
void
|
||||
RippleOverlay::addRipple(Ripple *ripple)
|
||||
{
|
||||
ripple->setOverlay(this);
|
||||
ripples_.push_back(ripple);
|
||||
ripple->start();
|
||||
ripple->setOverlay(this);
|
||||
ripples_.push_back(ripple);
|
||||
ripple->start();
|
||||
}
|
||||
|
||||
void
|
||||
RippleOverlay::addRipple(const QPoint &position, qreal radius)
|
||||
{
|
||||
Ripple *ripple = new Ripple(position);
|
||||
ripple->setRadiusEndValue(radius);
|
||||
addRipple(ripple);
|
||||
Ripple *ripple = new Ripple(position);
|
||||
ripple->setRadiusEndValue(radius);
|
||||
addRipple(ripple);
|
||||
}
|
||||
|
||||
void
|
||||
RippleOverlay::removeRipple(Ripple *ripple)
|
||||
{
|
||||
if (ripples_.removeOne(ripple))
|
||||
delete ripple;
|
||||
if (ripples_.removeOne(ripple))
|
||||
delete ripple;
|
||||
}
|
||||
|
||||
void
|
||||
RippleOverlay::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
Q_UNUSED(event)
|
||||
|
||||
QPainter painter(this);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.setPen(Qt::NoPen);
|
||||
QPainter painter(this);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.setPen(Qt::NoPen);
|
||||
|
||||
if (use_clip_)
|
||||
painter.setClipPath(clip_path_);
|
||||
if (use_clip_)
|
||||
painter.setClipPath(clip_path_);
|
||||
|
||||
for (auto it = ripples_.constBegin(); it != ripples_.constEnd(); ++it)
|
||||
paintRipple(&painter, *it);
|
||||
for (auto it = ripples_.constBegin(); it != ripples_.constEnd(); ++it)
|
||||
paintRipple(&painter, *it);
|
||||
}
|
||||
|
||||
void
|
||||
RippleOverlay::paintRipple(QPainter *painter, Ripple *ripple)
|
||||
{
|
||||
const qreal radius = ripple->radius();
|
||||
const QPointF center = ripple->center();
|
||||
const qreal radius = ripple->radius();
|
||||
const QPointF center = ripple->center();
|
||||
|
||||
painter->setOpacity(ripple->opacity());
|
||||
painter->setBrush(ripple->brush());
|
||||
painter->drawEllipse(center, radius, radius);
|
||||
painter->setOpacity(ripple->opacity());
|
||||
painter->setBrush(ripple->brush());
|
||||
painter->drawEllipse(center, radius, radius);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,50 +12,50 @@ class Ripple;
|
|||
|
||||
class RippleOverlay : public OverlayWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit RippleOverlay(QWidget *parent = nullptr);
|
||||
explicit RippleOverlay(QWidget *parent = nullptr);
|
||||
|
||||
void addRipple(Ripple *ripple);
|
||||
void addRipple(const QPoint &position, qreal radius = 300);
|
||||
void addRipple(Ripple *ripple);
|
||||
void addRipple(const QPoint &position, qreal radius = 300);
|
||||
|
||||
void removeRipple(Ripple *ripple);
|
||||
void removeRipple(Ripple *ripple);
|
||||
|
||||
inline void setClipping(bool enable);
|
||||
inline bool hasClipping() const;
|
||||
inline void setClipping(bool enable);
|
||||
inline bool hasClipping() const;
|
||||
|
||||
inline void setClipPath(const QPainterPath &path);
|
||||
inline void setClipPath(const QPainterPath &path);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
|
||||
void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(RippleOverlay)
|
||||
Q_DISABLE_COPY(RippleOverlay)
|
||||
|
||||
void paintRipple(QPainter *painter, Ripple *ripple);
|
||||
void paintRipple(QPainter *painter, Ripple *ripple);
|
||||
|
||||
QList<Ripple *> ripples_;
|
||||
QPainterPath clip_path_;
|
||||
bool use_clip_;
|
||||
QList<Ripple *> ripples_;
|
||||
QPainterPath clip_path_;
|
||||
bool use_clip_;
|
||||
};
|
||||
|
||||
inline void
|
||||
RippleOverlay::setClipping(bool enable)
|
||||
{
|
||||
use_clip_ = enable;
|
||||
update();
|
||||
use_clip_ = enable;
|
||||
update();
|
||||
}
|
||||
|
||||
inline bool
|
||||
RippleOverlay::hasClipping() const
|
||||
{
|
||||
return use_clip_;
|
||||
return use_clip_;
|
||||
}
|
||||
|
||||
inline void
|
||||
RippleOverlay::setClipPath(const QPainterPath &path)
|
||||
{
|
||||
clip_path_ = path;
|
||||
update();
|
||||
clip_path_ = path;
|
||||
update();
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -19,121 +19,121 @@ class TextField;
|
|||
/// outside of main with the UI code.
|
||||
class ThreadProxy : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
signals:
|
||||
void error(const QString &msg);
|
||||
void nameEventSent(const QString &);
|
||||
void topicEventSent(const QString &);
|
||||
void stopLoading();
|
||||
void error(const QString &msg);
|
||||
void nameEventSent(const QString &);
|
||||
void topicEventSent(const QString &);
|
||||
void stopLoading();
|
||||
};
|
||||
|
||||
class EditModal : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
EditModal(const QString &roomId, QWidget *parent = nullptr);
|
||||
EditModal(const QString &roomId, QWidget *parent = nullptr);
|
||||
|
||||
void setFields(const QString &roomName, const QString &roomTopic);
|
||||
void setFields(const QString &roomName, const QString &roomTopic);
|
||||
|
||||
signals:
|
||||
void nameChanged(const QString &roomName);
|
||||
void topicChanged(const QString &topic);
|
||||
void nameChanged(const QString &roomName);
|
||||
void topicChanged(const QString &topic);
|
||||
|
||||
private slots:
|
||||
void topicEventSent(const QString &topic);
|
||||
void nameEventSent(const QString &name);
|
||||
void error(const QString &msg);
|
||||
void topicEventSent(const QString &topic);
|
||||
void nameEventSent(const QString &name);
|
||||
void error(const QString &msg);
|
||||
|
||||
void applyClicked();
|
||||
void applyClicked();
|
||||
|
||||
private:
|
||||
QString roomId_;
|
||||
QString initialName_;
|
||||
QString initialTopic_;
|
||||
QString roomId_;
|
||||
QString initialName_;
|
||||
QString initialTopic_;
|
||||
|
||||
QLabel *errorField_;
|
||||
QLabel *errorField_;
|
||||
|
||||
TextField *nameInput_;
|
||||
TextField *topicInput_;
|
||||
TextField *nameInput_;
|
||||
TextField *topicInput_;
|
||||
|
||||
QPushButton *applyBtn_;
|
||||
QPushButton *cancelBtn_;
|
||||
QPushButton *applyBtn_;
|
||||
QPushButton *cancelBtn_;
|
||||
};
|
||||
|
||||
class RoomSettings : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString roomId READ roomId CONSTANT)
|
||||
Q_PROPERTY(QString roomVersion READ roomVersion CONSTANT)
|
||||
Q_PROPERTY(QString roomName READ roomName NOTIFY roomNameChanged)
|
||||
Q_PROPERTY(QString roomTopic READ roomTopic NOTIFY roomTopicChanged)
|
||||
Q_PROPERTY(QString roomAvatarUrl READ roomAvatarUrl NOTIFY avatarUrlChanged)
|
||||
Q_PROPERTY(int memberCount READ memberCount CONSTANT)
|
||||
Q_PROPERTY(int notifications READ notifications NOTIFY notificationsChanged)
|
||||
Q_PROPERTY(int accessJoinRules READ accessJoinRules NOTIFY accessJoinRulesChanged)
|
||||
Q_PROPERTY(bool isLoading READ isLoading NOTIFY loadingChanged)
|
||||
Q_PROPERTY(bool canChangeAvatar READ canChangeAvatar CONSTANT)
|
||||
Q_PROPERTY(bool canChangeJoinRules READ canChangeJoinRules CONSTANT)
|
||||
Q_PROPERTY(bool canChangeNameAndTopic READ canChangeNameAndTopic CONSTANT)
|
||||
Q_PROPERTY(bool isEncryptionEnabled READ isEncryptionEnabled NOTIFY encryptionChanged)
|
||||
Q_PROPERTY(bool supportsKnocking READ supportsKnocking CONSTANT)
|
||||
Q_PROPERTY(bool supportsRestricted READ supportsRestricted CONSTANT)
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString roomId READ roomId CONSTANT)
|
||||
Q_PROPERTY(QString roomVersion READ roomVersion CONSTANT)
|
||||
Q_PROPERTY(QString roomName READ roomName NOTIFY roomNameChanged)
|
||||
Q_PROPERTY(QString roomTopic READ roomTopic NOTIFY roomTopicChanged)
|
||||
Q_PROPERTY(QString roomAvatarUrl READ roomAvatarUrl NOTIFY avatarUrlChanged)
|
||||
Q_PROPERTY(int memberCount READ memberCount CONSTANT)
|
||||
Q_PROPERTY(int notifications READ notifications NOTIFY notificationsChanged)
|
||||
Q_PROPERTY(int accessJoinRules READ accessJoinRules NOTIFY accessJoinRulesChanged)
|
||||
Q_PROPERTY(bool isLoading READ isLoading NOTIFY loadingChanged)
|
||||
Q_PROPERTY(bool canChangeAvatar READ canChangeAvatar CONSTANT)
|
||||
Q_PROPERTY(bool canChangeJoinRules READ canChangeJoinRules CONSTANT)
|
||||
Q_PROPERTY(bool canChangeNameAndTopic READ canChangeNameAndTopic CONSTANT)
|
||||
Q_PROPERTY(bool isEncryptionEnabled READ isEncryptionEnabled NOTIFY encryptionChanged)
|
||||
Q_PROPERTY(bool supportsKnocking READ supportsKnocking CONSTANT)
|
||||
Q_PROPERTY(bool supportsRestricted READ supportsRestricted CONSTANT)
|
||||
|
||||
public:
|
||||
RoomSettings(QString roomid, QObject *parent = nullptr);
|
||||
RoomSettings(QString roomid, QObject *parent = nullptr);
|
||||
|
||||
QString roomId() const;
|
||||
QString roomName() const;
|
||||
QString roomTopic() const;
|
||||
QString roomVersion() const;
|
||||
QString roomAvatarUrl();
|
||||
int memberCount() const;
|
||||
int notifications();
|
||||
int accessJoinRules();
|
||||
bool isLoading() const;
|
||||
//! Whether the user has enough power level to send m.room.join_rules events.
|
||||
bool canChangeJoinRules() const;
|
||||
//! Whether the user has enough power level to send m.room.name & m.room.topic events.
|
||||
bool canChangeNameAndTopic() const;
|
||||
//! Whether the user has enough power level to send m.room.avatar event.
|
||||
bool canChangeAvatar() const;
|
||||
bool isEncryptionEnabled() const;
|
||||
bool supportsKnocking() const;
|
||||
bool supportsRestricted() const;
|
||||
QString roomId() const;
|
||||
QString roomName() const;
|
||||
QString roomTopic() const;
|
||||
QString roomVersion() const;
|
||||
QString roomAvatarUrl();
|
||||
int memberCount() const;
|
||||
int notifications();
|
||||
int accessJoinRules();
|
||||
bool isLoading() const;
|
||||
//! Whether the user has enough power level to send m.room.join_rules events.
|
||||
bool canChangeJoinRules() const;
|
||||
//! Whether the user has enough power level to send m.room.name & m.room.topic events.
|
||||
bool canChangeNameAndTopic() const;
|
||||
//! Whether the user has enough power level to send m.room.avatar event.
|
||||
bool canChangeAvatar() const;
|
||||
bool isEncryptionEnabled() const;
|
||||
bool supportsKnocking() const;
|
||||
bool supportsRestricted() const;
|
||||
|
||||
Q_INVOKABLE void enableEncryption();
|
||||
Q_INVOKABLE void updateAvatar();
|
||||
Q_INVOKABLE void openEditModal();
|
||||
Q_INVOKABLE void changeAccessRules(int index);
|
||||
Q_INVOKABLE void changeNotifications(int currentIndex);
|
||||
Q_INVOKABLE void enableEncryption();
|
||||
Q_INVOKABLE void updateAvatar();
|
||||
Q_INVOKABLE void openEditModal();
|
||||
Q_INVOKABLE void changeAccessRules(int index);
|
||||
Q_INVOKABLE void changeNotifications(int currentIndex);
|
||||
|
||||
signals:
|
||||
void loadingChanged();
|
||||
void roomNameChanged();
|
||||
void roomTopicChanged();
|
||||
void avatarUrlChanged();
|
||||
void encryptionChanged();
|
||||
void notificationsChanged();
|
||||
void accessJoinRulesChanged();
|
||||
void displayError(const QString &errorMessage);
|
||||
void loadingChanged();
|
||||
void roomNameChanged();
|
||||
void roomTopicChanged();
|
||||
void avatarUrlChanged();
|
||||
void encryptionChanged();
|
||||
void notificationsChanged();
|
||||
void accessJoinRulesChanged();
|
||||
void displayError(const QString &errorMessage);
|
||||
|
||||
public slots:
|
||||
void stopLoading();
|
||||
void avatarChanged();
|
||||
void stopLoading();
|
||||
void avatarChanged();
|
||||
|
||||
private:
|
||||
void retrieveRoomInfo();
|
||||
void updateAccessRules(const std::string &room_id,
|
||||
const mtx::events::state::JoinRules &,
|
||||
const mtx::events::state::GuestAccess &);
|
||||
void retrieveRoomInfo();
|
||||
void updateAccessRules(const std::string &room_id,
|
||||
const mtx::events::state::JoinRules &,
|
||||
const mtx::events::state::GuestAccess &);
|
||||
|
||||
private:
|
||||
QString roomid_;
|
||||
bool usesEncryption_ = false;
|
||||
bool isLoading_ = false;
|
||||
RoomInfo info_;
|
||||
int notifications_ = 0;
|
||||
int accessRules_ = 0;
|
||||
QString roomid_;
|
||||
bool usesEncryption_ = false;
|
||||
bool isLoading_ = false;
|
||||
RoomInfo info_;
|
||||
int notifications_ = 0;
|
||||
int accessRules_ = 0;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -15,121 +15,121 @@ SnackBar::SnackBar(QWidget *parent)
|
|||
: OverlayWidget(parent)
|
||||
, offset_anim(this, "offset", this)
|
||||
{
|
||||
QFont font;
|
||||
font.setPointSizeF(font.pointSizeF() * 1.2);
|
||||
font.setWeight(50);
|
||||
setFont(font);
|
||||
QFont font;
|
||||
font.setPointSizeF(font.pointSizeF() * 1.2);
|
||||
font.setWeight(50);
|
||||
setFont(font);
|
||||
|
||||
boxHeight_ = QFontMetrics(font).height() * 2;
|
||||
offset_ = STARTING_OFFSET;
|
||||
position_ = SnackBarPosition::Top;
|
||||
boxHeight_ = QFontMetrics(font).height() * 2;
|
||||
offset_ = STARTING_OFFSET;
|
||||
position_ = SnackBarPosition::Top;
|
||||
|
||||
hideTimer_.setSingleShot(true);
|
||||
hideTimer_.setSingleShot(true);
|
||||
|
||||
offset_anim.setStartValue(1.0);
|
||||
offset_anim.setEndValue(0.0);
|
||||
offset_anim.setDuration(100);
|
||||
offset_anim.setEasingCurve(QEasingCurve::OutCubic);
|
||||
offset_anim.setStartValue(1.0);
|
||||
offset_anim.setEndValue(0.0);
|
||||
offset_anim.setDuration(100);
|
||||
offset_anim.setEasingCurve(QEasingCurve::OutCubic);
|
||||
|
||||
connect(this, &SnackBar::offsetChanged, this, [this]() mutable { repaint(); });
|
||||
connect(
|
||||
&offset_anim, &QPropertyAnimation::finished, this, [this]() { hideTimer_.start(10000); });
|
||||
connect(this, &SnackBar::offsetChanged, this, [this]() mutable { repaint(); });
|
||||
connect(
|
||||
&offset_anim, &QPropertyAnimation::finished, this, [this]() { hideTimer_.start(10000); });
|
||||
|
||||
connect(&hideTimer_, SIGNAL(timeout()), this, SLOT(hideMessage()));
|
||||
connect(&hideTimer_, SIGNAL(timeout()), this, SLOT(hideMessage()));
|
||||
|
||||
hide();
|
||||
hide();
|
||||
}
|
||||
|
||||
void
|
||||
SnackBar::start()
|
||||
{
|
||||
if (messages_.empty())
|
||||
return;
|
||||
if (messages_.empty())
|
||||
return;
|
||||
|
||||
show();
|
||||
raise();
|
||||
show();
|
||||
raise();
|
||||
|
||||
offset_anim.start();
|
||||
offset_anim.start();
|
||||
}
|
||||
|
||||
void
|
||||
SnackBar::hideMessage()
|
||||
{
|
||||
stopTimers();
|
||||
hide();
|
||||
stopTimers();
|
||||
hide();
|
||||
|
||||
if (!messages_.empty())
|
||||
// Moving on to the next message.
|
||||
messages_.pop_front();
|
||||
if (!messages_.empty())
|
||||
// Moving on to the next message.
|
||||
messages_.pop_front();
|
||||
|
||||
// Resetting the starting position of the widget.
|
||||
offset_ = STARTING_OFFSET;
|
||||
// Resetting the starting position of the widget.
|
||||
offset_ = STARTING_OFFSET;
|
||||
|
||||
if (!messages_.empty())
|
||||
start();
|
||||
if (!messages_.empty())
|
||||
start();
|
||||
}
|
||||
|
||||
void
|
||||
SnackBar::stopTimers()
|
||||
{
|
||||
hideTimer_.stop();
|
||||
hideTimer_.stop();
|
||||
}
|
||||
|
||||
void
|
||||
SnackBar::showMessage(const QString &msg)
|
||||
{
|
||||
messages_.push_back(msg);
|
||||
messages_.push_back(msg);
|
||||
|
||||
// There is already an active message.
|
||||
if (isVisible())
|
||||
return;
|
||||
// There is already an active message.
|
||||
if (isVisible())
|
||||
return;
|
||||
|
||||
start();
|
||||
start();
|
||||
}
|
||||
|
||||
void
|
||||
SnackBar::mousePressEvent(QMouseEvent *)
|
||||
{
|
||||
hideMessage();
|
||||
hideMessage();
|
||||
}
|
||||
|
||||
void
|
||||
SnackBar::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
Q_UNUSED(event)
|
||||
|
||||
if (messages_.empty())
|
||||
return;
|
||||
if (messages_.empty())
|
||||
return;
|
||||
|
||||
auto message_ = messages_.front();
|
||||
auto message_ = messages_.front();
|
||||
|
||||
QPainter p(this);
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
QPainter p(this);
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
QBrush brush;
|
||||
brush.setStyle(Qt::SolidPattern);
|
||||
brush.setColor(bgColor_);
|
||||
p.setBrush(brush);
|
||||
QBrush brush;
|
||||
brush.setStyle(Qt::SolidPattern);
|
||||
brush.setColor(bgColor_);
|
||||
p.setBrush(brush);
|
||||
|
||||
QRect r(0, 0, std::max(MIN_WIDTH, width() * MIN_WIDTH_PERCENTAGE), boxHeight_);
|
||||
QRect r(0, 0, std::max(MIN_WIDTH, width() * MIN_WIDTH_PERCENTAGE), boxHeight_);
|
||||
|
||||
p.setPen(Qt::white);
|
||||
QRect br = p.boundingRect(r, Qt::AlignHCenter | Qt::AlignTop | Qt::TextWordWrap, message_);
|
||||
p.setPen(Qt::white);
|
||||
QRect br = p.boundingRect(r, Qt::AlignHCenter | Qt::AlignTop | Qt::TextWordWrap, message_);
|
||||
|
||||
p.setPen(Qt::NoPen);
|
||||
r = br.united(r).adjusted(-BOX_PADDING, -BOX_PADDING, BOX_PADDING, BOX_PADDING);
|
||||
p.setPen(Qt::NoPen);
|
||||
r = br.united(r).adjusted(-BOX_PADDING, -BOX_PADDING, BOX_PADDING, BOX_PADDING);
|
||||
|
||||
const qreal s = 1 - offset_;
|
||||
const qreal s = 1 - offset_;
|
||||
|
||||
if (position_ == SnackBarPosition::Bottom)
|
||||
p.translate((width() - (r.width() - 2 * BOX_PADDING)) / 2,
|
||||
height() - BOX_PADDING - s * (r.height()));
|
||||
else
|
||||
p.translate((width() - (r.width() - 2 * BOX_PADDING)) / 2,
|
||||
s * (r.height()) - 2 * BOX_PADDING);
|
||||
if (position_ == SnackBarPosition::Bottom)
|
||||
p.translate((width() - (r.width() - 2 * BOX_PADDING)) / 2,
|
||||
height() - BOX_PADDING - s * (r.height()));
|
||||
else
|
||||
p.translate((width() - (r.width() - 2 * BOX_PADDING)) / 2,
|
||||
s * (r.height()) - 2 * BOX_PADDING);
|
||||
|
||||
br.moveCenter(r.center());
|
||||
p.drawRoundedRect(r.adjusted(0, 0, 0, 4), 4, 4);
|
||||
p.setPen(textColor_);
|
||||
p.drawText(br, Qt::AlignHCenter | Qt::AlignTop | Qt::TextWordWrap, message_);
|
||||
br.moveCenter(r.center());
|
||||
p.drawRoundedRect(r.adjusted(0, 0, 0, 4), 4, 4);
|
||||
p.setPen(textColor_);
|
||||
p.drawText(br, Qt::AlignHCenter | Qt::AlignTop | Qt::TextWordWrap, message_);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,79 +14,79 @@
|
|||
|
||||
enum class SnackBarPosition
|
||||
{
|
||||
Bottom,
|
||||
Top,
|
||||
Bottom,
|
||||
Top,
|
||||
};
|
||||
|
||||
class SnackBar : public OverlayWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QColor bgColor READ backgroundColor WRITE setBackgroundColor)
|
||||
Q_PROPERTY(QColor textColor READ textColor WRITE setTextColor)
|
||||
Q_PROPERTY(double offset READ offset WRITE setOffset NOTIFY offsetChanged)
|
||||
Q_PROPERTY(QColor bgColor READ backgroundColor WRITE setBackgroundColor)
|
||||
Q_PROPERTY(QColor textColor READ textColor WRITE setTextColor)
|
||||
Q_PROPERTY(double offset READ offset WRITE setOffset NOTIFY offsetChanged)
|
||||
|
||||
public:
|
||||
explicit SnackBar(QWidget *parent);
|
||||
explicit SnackBar(QWidget *parent);
|
||||
|
||||
QColor backgroundColor() const { return bgColor_; }
|
||||
void setBackgroundColor(const QColor &color)
|
||||
{
|
||||
bgColor_ = color;
|
||||
update();
|
||||
}
|
||||
QColor backgroundColor() const { return bgColor_; }
|
||||
void setBackgroundColor(const QColor &color)
|
||||
{
|
||||
bgColor_ = color;
|
||||
update();
|
||||
}
|
||||
|
||||
QColor textColor() const { return textColor_; }
|
||||
void setTextColor(const QColor &color)
|
||||
{
|
||||
textColor_ = color;
|
||||
update();
|
||||
}
|
||||
void setPosition(SnackBarPosition pos)
|
||||
{
|
||||
position_ = pos;
|
||||
update();
|
||||
}
|
||||
QColor textColor() const { return textColor_; }
|
||||
void setTextColor(const QColor &color)
|
||||
{
|
||||
textColor_ = color;
|
||||
update();
|
||||
}
|
||||
void setPosition(SnackBarPosition pos)
|
||||
{
|
||||
position_ = pos;
|
||||
update();
|
||||
}
|
||||
|
||||
double offset() { return offset_; }
|
||||
void setOffset(double offset)
|
||||
{
|
||||
if (offset != offset_) {
|
||||
offset_ = offset;
|
||||
emit offsetChanged();
|
||||
}
|
||||
double offset() { return offset_; }
|
||||
void setOffset(double offset)
|
||||
{
|
||||
if (offset != offset_) {
|
||||
offset_ = offset;
|
||||
emit offsetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public slots:
|
||||
void showMessage(const QString &msg);
|
||||
void showMessage(const QString &msg);
|
||||
|
||||
signals:
|
||||
void offsetChanged();
|
||||
void offsetChanged();
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
|
||||
private slots:
|
||||
void hideMessage();
|
||||
void hideMessage();
|
||||
|
||||
private:
|
||||
void stopTimers();
|
||||
void start();
|
||||
void stopTimers();
|
||||
void start();
|
||||
|
||||
QColor bgColor_;
|
||||
QColor textColor_;
|
||||
QColor bgColor_;
|
||||
QColor textColor_;
|
||||
|
||||
qreal bgOpacity_;
|
||||
qreal offset_;
|
||||
qreal bgOpacity_;
|
||||
qreal offset_;
|
||||
|
||||
std::deque<QString> messages_;
|
||||
std::deque<QString> messages_;
|
||||
|
||||
QTimer hideTimer_;
|
||||
QTimer hideTimer_;
|
||||
|
||||
double boxHeight_;
|
||||
double boxHeight_;
|
||||
|
||||
QPropertyAnimation offset_anim;
|
||||
QPropertyAnimation offset_anim;
|
||||
|
||||
SnackBarPosition position_;
|
||||
SnackBarPosition position_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -15,363 +15,363 @@
|
|||
TextField::TextField(QWidget *parent)
|
||||
: QLineEdit(parent)
|
||||
{
|
||||
// Get rid of the focus border on macOS.
|
||||
setAttribute(Qt::WA_MacShowFocusRect, 0);
|
||||
// Get rid of the focus border on macOS.
|
||||
setAttribute(Qt::WA_MacShowFocusRect, 0);
|
||||
|
||||
QPalette pal;
|
||||
QPalette pal;
|
||||
|
||||
state_machine_ = new TextFieldStateMachine(this);
|
||||
label_ = nullptr;
|
||||
label_font_size_ = 15;
|
||||
show_label_ = false;
|
||||
background_color_ = pal.color(QPalette::Window);
|
||||
is_valid_ = true;
|
||||
state_machine_ = new TextFieldStateMachine(this);
|
||||
label_ = nullptr;
|
||||
label_font_size_ = 15;
|
||||
show_label_ = false;
|
||||
background_color_ = pal.color(QPalette::Window);
|
||||
is_valid_ = true;
|
||||
|
||||
setFrame(false);
|
||||
setAttribute(Qt::WA_Hover);
|
||||
setMouseTracking(true);
|
||||
setTextMargins(0, 4, 0, 6);
|
||||
setFrame(false);
|
||||
setAttribute(Qt::WA_Hover);
|
||||
setMouseTracking(true);
|
||||
setTextMargins(0, 4, 0, 6);
|
||||
|
||||
state_machine_->start();
|
||||
QCoreApplication::processEvents();
|
||||
state_machine_->start();
|
||||
QCoreApplication::processEvents();
|
||||
}
|
||||
|
||||
void
|
||||
TextField::setBackgroundColor(const QColor &color)
|
||||
{
|
||||
background_color_ = color;
|
||||
background_color_ = color;
|
||||
}
|
||||
|
||||
QColor
|
||||
TextField::backgroundColor() const
|
||||
{
|
||||
return background_color_;
|
||||
return background_color_;
|
||||
}
|
||||
|
||||
void
|
||||
TextField::setShowLabel(bool value)
|
||||
{
|
||||
if (show_label_ == value) {
|
||||
return;
|
||||
}
|
||||
if (show_label_ == value) {
|
||||
return;
|
||||
}
|
||||
|
||||
show_label_ = value;
|
||||
show_label_ = value;
|
||||
|
||||
if (!label_ && value) {
|
||||
label_ = new TextFieldLabel(this);
|
||||
state_machine_->setLabel(label_);
|
||||
}
|
||||
if (!label_ && value) {
|
||||
label_ = new TextFieldLabel(this);
|
||||
state_machine_->setLabel(label_);
|
||||
}
|
||||
|
||||
if (value) {
|
||||
setContentsMargins(0, 23, 0, 0);
|
||||
} else {
|
||||
setContentsMargins(0, 0, 0, 0);
|
||||
}
|
||||
if (value) {
|
||||
setContentsMargins(0, 23, 0, 0);
|
||||
} else {
|
||||
setContentsMargins(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
TextField::hasLabel() const
|
||||
{
|
||||
return show_label_;
|
||||
return show_label_;
|
||||
}
|
||||
|
||||
void
|
||||
TextField::setValid(bool valid)
|
||||
{
|
||||
is_valid_ = valid;
|
||||
is_valid_ = valid;
|
||||
}
|
||||
|
||||
bool
|
||||
TextField::isValid() const
|
||||
{
|
||||
QString s = text();
|
||||
int pos = 0;
|
||||
if (regexp_.pattern().isEmpty()) {
|
||||
return is_valid_;
|
||||
}
|
||||
QRegularExpressionValidator v(QRegularExpression(regexp_), 0);
|
||||
return v.validate(s, pos) == QValidator::Acceptable;
|
||||
QString s = text();
|
||||
int pos = 0;
|
||||
if (regexp_.pattern().isEmpty()) {
|
||||
return is_valid_;
|
||||
}
|
||||
QRegularExpressionValidator v(QRegularExpression(regexp_), 0);
|
||||
return v.validate(s, pos) == QValidator::Acceptable;
|
||||
}
|
||||
|
||||
void
|
||||
TextField::setLabelFontSize(qreal size)
|
||||
{
|
||||
label_font_size_ = size;
|
||||
label_font_size_ = size;
|
||||
|
||||
if (label_) {
|
||||
QFont font(label_->font());
|
||||
font.setPointSizeF(size);
|
||||
label_->setFont(font);
|
||||
label_->update();
|
||||
}
|
||||
if (label_) {
|
||||
QFont font(label_->font());
|
||||
font.setPointSizeF(size);
|
||||
label_->setFont(font);
|
||||
label_->update();
|
||||
}
|
||||
}
|
||||
|
||||
qreal
|
||||
TextField::labelFontSize() const
|
||||
{
|
||||
return label_font_size_;
|
||||
return label_font_size_;
|
||||
}
|
||||
|
||||
void
|
||||
TextField::setLabel(const QString &label)
|
||||
{
|
||||
label_text_ = label;
|
||||
setShowLabel(true);
|
||||
label_->update();
|
||||
label_text_ = label;
|
||||
setShowLabel(true);
|
||||
label_->update();
|
||||
}
|
||||
|
||||
QString
|
||||
TextField::label() const
|
||||
{
|
||||
return label_text_;
|
||||
return label_text_;
|
||||
}
|
||||
|
||||
void
|
||||
TextField::setLabelColor(const QColor &color)
|
||||
{
|
||||
label_color_ = color;
|
||||
update();
|
||||
label_color_ = color;
|
||||
update();
|
||||
}
|
||||
|
||||
QColor
|
||||
TextField::labelColor() const
|
||||
{
|
||||
if (!label_color_.isValid()) {
|
||||
return QPalette().color(QPalette::Text);
|
||||
}
|
||||
if (!label_color_.isValid()) {
|
||||
return QPalette().color(QPalette::Text);
|
||||
}
|
||||
|
||||
return label_color_;
|
||||
return label_color_;
|
||||
}
|
||||
|
||||
void
|
||||
TextField::setInkColor(const QColor &color)
|
||||
{
|
||||
ink_color_ = color;
|
||||
update();
|
||||
ink_color_ = color;
|
||||
update();
|
||||
}
|
||||
|
||||
QColor
|
||||
TextField::inkColor() const
|
||||
{
|
||||
if (!ink_color_.isValid()) {
|
||||
return QPalette().color(QPalette::Text);
|
||||
}
|
||||
if (!ink_color_.isValid()) {
|
||||
return QPalette().color(QPalette::Text);
|
||||
}
|
||||
|
||||
return ink_color_;
|
||||
return ink_color_;
|
||||
}
|
||||
|
||||
void
|
||||
TextField::setUnderlineColor(const QColor &color)
|
||||
{
|
||||
underline_color_ = color;
|
||||
update();
|
||||
underline_color_ = color;
|
||||
update();
|
||||
}
|
||||
|
||||
void
|
||||
TextField::setRegexp(const QRegularExpression ®exp)
|
||||
{
|
||||
regexp_ = regexp;
|
||||
regexp_ = regexp;
|
||||
}
|
||||
|
||||
QColor
|
||||
TextField::underlineColor() const
|
||||
{
|
||||
if (!underline_color_.isValid()) {
|
||||
if ((hasAcceptableInput() && isValid()) || !isModified())
|
||||
return QPalette().color(QPalette::Highlight);
|
||||
else
|
||||
return Qt::red;
|
||||
}
|
||||
if (!underline_color_.isValid()) {
|
||||
if ((hasAcceptableInput() && isValid()) || !isModified())
|
||||
return QPalette().color(QPalette::Highlight);
|
||||
else
|
||||
return Qt::red;
|
||||
}
|
||||
|
||||
return underline_color_;
|
||||
return underline_color_;
|
||||
}
|
||||
|
||||
bool
|
||||
TextField::event(QEvent *event)
|
||||
{
|
||||
switch (event->type()) {
|
||||
case QEvent::Resize:
|
||||
case QEvent::Move: {
|
||||
if (label_)
|
||||
label_->setGeometry(rect());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (event->type()) {
|
||||
case QEvent::Resize:
|
||||
case QEvent::Move: {
|
||||
if (label_)
|
||||
label_->setGeometry(rect());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return QLineEdit::event(event);
|
||||
return QLineEdit::event(event);
|
||||
}
|
||||
|
||||
void
|
||||
TextField::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
QLineEdit::paintEvent(event);
|
||||
QLineEdit::paintEvent(event);
|
||||
|
||||
QPainter painter(this);
|
||||
QPainter painter(this);
|
||||
|
||||
if (text().isEmpty()) {
|
||||
painter.setOpacity(1 - state_machine_->progress());
|
||||
painter.fillRect(rect(), backgroundColor());
|
||||
}
|
||||
if (text().isEmpty()) {
|
||||
painter.setOpacity(1 - state_machine_->progress());
|
||||
painter.fillRect(rect(), backgroundColor());
|
||||
}
|
||||
|
||||
const int y = height() - 1;
|
||||
const int wd = width() - 5;
|
||||
const int y = height() - 1;
|
||||
const int wd = width() - 5;
|
||||
|
||||
QPen pen;
|
||||
pen.setWidth(1);
|
||||
pen.setColor(underlineColor());
|
||||
painter.setPen(pen);
|
||||
painter.setOpacity(1);
|
||||
painter.drawLine(2, y, wd, y);
|
||||
QPen pen;
|
||||
pen.setWidth(1);
|
||||
pen.setColor(underlineColor());
|
||||
painter.setPen(pen);
|
||||
painter.setOpacity(1);
|
||||
painter.drawLine(2, y, wd, y);
|
||||
|
||||
QBrush brush;
|
||||
brush.setStyle(Qt::SolidPattern);
|
||||
brush.setColor(inkColor());
|
||||
QBrush brush;
|
||||
brush.setStyle(Qt::SolidPattern);
|
||||
brush.setColor(inkColor());
|
||||
|
||||
const qreal progress = state_machine_->progress();
|
||||
const qreal progress = state_machine_->progress();
|
||||
|
||||
if (progress > 0) {
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.setBrush(brush);
|
||||
const int w = (1 - progress) * static_cast<qreal>(wd / 2);
|
||||
painter.drawRect(w + 2.5, height() - 2, wd - 2 * w, 2);
|
||||
}
|
||||
if (progress > 0) {
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.setBrush(brush);
|
||||
const int w = (1 - progress) * static_cast<qreal>(wd / 2);
|
||||
painter.drawRect(w + 2.5, height() - 2, wd - 2 * w, 2);
|
||||
}
|
||||
}
|
||||
|
||||
TextFieldStateMachine::TextFieldStateMachine(TextField *parent)
|
||||
: QStateMachine(parent)
|
||||
, text_field_(parent)
|
||||
{
|
||||
normal_state_ = new QState;
|
||||
focused_state_ = new QState;
|
||||
normal_state_ = new QState;
|
||||
focused_state_ = new QState;
|
||||
|
||||
label_ = nullptr;
|
||||
offset_anim_ = nullptr;
|
||||
color_anim_ = nullptr;
|
||||
progress_ = 0.0;
|
||||
label_ = nullptr;
|
||||
offset_anim_ = nullptr;
|
||||
color_anim_ = nullptr;
|
||||
progress_ = 0.0;
|
||||
|
||||
addState(normal_state_);
|
||||
addState(focused_state_);
|
||||
addState(normal_state_);
|
||||
addState(focused_state_);
|
||||
|
||||
setInitialState(normal_state_);
|
||||
setInitialState(normal_state_);
|
||||
|
||||
QEventTransition *transition;
|
||||
QPropertyAnimation *animation;
|
||||
QEventTransition *transition;
|
||||
QPropertyAnimation *animation;
|
||||
|
||||
transition = new QEventTransition(parent, QEvent::FocusIn);
|
||||
transition->setTargetState(focused_state_);
|
||||
normal_state_->addTransition(transition);
|
||||
transition = new QEventTransition(parent, QEvent::FocusIn);
|
||||
transition->setTargetState(focused_state_);
|
||||
normal_state_->addTransition(transition);
|
||||
|
||||
animation = new QPropertyAnimation(this, "progress", this);
|
||||
animation->setEasingCurve(QEasingCurve::InCubic);
|
||||
animation->setDuration(310);
|
||||
transition->addAnimation(animation);
|
||||
animation = new QPropertyAnimation(this, "progress", this);
|
||||
animation->setEasingCurve(QEasingCurve::InCubic);
|
||||
animation->setDuration(310);
|
||||
transition->addAnimation(animation);
|
||||
|
||||
transition = new QEventTransition(parent, QEvent::FocusOut);
|
||||
transition->setTargetState(normal_state_);
|
||||
focused_state_->addTransition(transition);
|
||||
transition = new QEventTransition(parent, QEvent::FocusOut);
|
||||
transition->setTargetState(normal_state_);
|
||||
focused_state_->addTransition(transition);
|
||||
|
||||
animation = new QPropertyAnimation(this, "progress", this);
|
||||
animation->setEasingCurve(QEasingCurve::OutCubic);
|
||||
animation->setDuration(310);
|
||||
transition->addAnimation(animation);
|
||||
animation = new QPropertyAnimation(this, "progress", this);
|
||||
animation->setEasingCurve(QEasingCurve::OutCubic);
|
||||
animation->setDuration(310);
|
||||
transition->addAnimation(animation);
|
||||
|
||||
normal_state_->assignProperty(this, "progress", 0);
|
||||
focused_state_->assignProperty(this, "progress", 1);
|
||||
normal_state_->assignProperty(this, "progress", 0);
|
||||
focused_state_->assignProperty(this, "progress", 1);
|
||||
|
||||
setupProperties();
|
||||
setupProperties();
|
||||
|
||||
connect(text_field_, SIGNAL(textChanged(QString)), this, SLOT(setupProperties()));
|
||||
connect(text_field_, SIGNAL(textChanged(QString)), this, SLOT(setupProperties()));
|
||||
}
|
||||
|
||||
void
|
||||
TextFieldStateMachine::setLabel(TextFieldLabel *label)
|
||||
{
|
||||
if (label_) {
|
||||
delete label_;
|
||||
}
|
||||
if (label_) {
|
||||
delete label_;
|
||||
}
|
||||
|
||||
if (offset_anim_) {
|
||||
removeDefaultAnimation(offset_anim_);
|
||||
delete offset_anim_;
|
||||
}
|
||||
if (offset_anim_) {
|
||||
removeDefaultAnimation(offset_anim_);
|
||||
delete offset_anim_;
|
||||
}
|
||||
|
||||
if (color_anim_) {
|
||||
removeDefaultAnimation(color_anim_);
|
||||
delete color_anim_;
|
||||
}
|
||||
if (color_anim_) {
|
||||
removeDefaultAnimation(color_anim_);
|
||||
delete color_anim_;
|
||||
}
|
||||
|
||||
label_ = label;
|
||||
label_ = label;
|
||||
|
||||
if (label_) {
|
||||
offset_anim_ = new QPropertyAnimation(label_, "offset", this);
|
||||
offset_anim_->setDuration(210);
|
||||
offset_anim_->setEasingCurve(QEasingCurve::OutCubic);
|
||||
addDefaultAnimation(offset_anim_);
|
||||
if (label_) {
|
||||
offset_anim_ = new QPropertyAnimation(label_, "offset", this);
|
||||
offset_anim_->setDuration(210);
|
||||
offset_anim_->setEasingCurve(QEasingCurve::OutCubic);
|
||||
addDefaultAnimation(offset_anim_);
|
||||
|
||||
color_anim_ = new QPropertyAnimation(label_, "color", this);
|
||||
color_anim_->setDuration(210);
|
||||
addDefaultAnimation(color_anim_);
|
||||
}
|
||||
color_anim_ = new QPropertyAnimation(label_, "color", this);
|
||||
color_anim_->setDuration(210);
|
||||
addDefaultAnimation(color_anim_);
|
||||
}
|
||||
|
||||
setupProperties();
|
||||
setupProperties();
|
||||
}
|
||||
|
||||
void
|
||||
TextFieldStateMachine::setupProperties()
|
||||
{
|
||||
if (label_) {
|
||||
const int m = text_field_->textMargins().top();
|
||||
if (label_) {
|
||||
const int m = text_field_->textMargins().top();
|
||||
|
||||
if (text_field_->text().isEmpty()) {
|
||||
normal_state_->assignProperty(label_, "offset", QPointF(0, 26));
|
||||
} else {
|
||||
normal_state_->assignProperty(label_, "offset", QPointF(0, 0 - m));
|
||||
}
|
||||
|
||||
focused_state_->assignProperty(label_, "offset", QPointF(0, 0 - m));
|
||||
focused_state_->assignProperty(label_, "color", text_field_->inkColor());
|
||||
normal_state_->assignProperty(label_, "color", text_field_->labelColor());
|
||||
|
||||
if (0 != label_->offset().y() && !text_field_->text().isEmpty()) {
|
||||
label_->setOffset(QPointF(0, 0 - m));
|
||||
} else if (!text_field_->hasFocus() && label_->offset().y() <= 0 &&
|
||||
text_field_->text().isEmpty()) {
|
||||
label_->setOffset(QPointF(0, 26));
|
||||
}
|
||||
if (text_field_->text().isEmpty()) {
|
||||
normal_state_->assignProperty(label_, "offset", QPointF(0, 26));
|
||||
} else {
|
||||
normal_state_->assignProperty(label_, "offset", QPointF(0, 0 - m));
|
||||
}
|
||||
|
||||
text_field_->update();
|
||||
focused_state_->assignProperty(label_, "offset", QPointF(0, 0 - m));
|
||||
focused_state_->assignProperty(label_, "color", text_field_->inkColor());
|
||||
normal_state_->assignProperty(label_, "color", text_field_->labelColor());
|
||||
|
||||
if (0 != label_->offset().y() && !text_field_->text().isEmpty()) {
|
||||
label_->setOffset(QPointF(0, 0 - m));
|
||||
} else if (!text_field_->hasFocus() && label_->offset().y() <= 0 &&
|
||||
text_field_->text().isEmpty()) {
|
||||
label_->setOffset(QPointF(0, 26));
|
||||
}
|
||||
}
|
||||
|
||||
text_field_->update();
|
||||
}
|
||||
|
||||
TextFieldLabel::TextFieldLabel(TextField *parent)
|
||||
: QWidget(parent)
|
||||
, text_field_(parent)
|
||||
{
|
||||
x_ = 0;
|
||||
y_ = 26;
|
||||
scale_ = 1;
|
||||
color_ = parent->labelColor();
|
||||
x_ = 0;
|
||||
y_ = 26;
|
||||
scale_ = 1;
|
||||
color_ = parent->labelColor();
|
||||
|
||||
QFont font;
|
||||
font.setWeight(60);
|
||||
font.setLetterSpacing(QFont::PercentageSpacing, 102);
|
||||
setFont(font);
|
||||
QFont font;
|
||||
font.setWeight(60);
|
||||
font.setLetterSpacing(QFont::PercentageSpacing, 102);
|
||||
setFont(font);
|
||||
}
|
||||
|
||||
void
|
||||
TextFieldLabel::paintEvent(QPaintEvent *)
|
||||
{
|
||||
if (!text_field_->hasLabel())
|
||||
return;
|
||||
if (!text_field_->hasLabel())
|
||||
return;
|
||||
|
||||
QPainter painter(this);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.scale(scale_, scale_);
|
||||
painter.setPen(color_);
|
||||
painter.setOpacity(1);
|
||||
QPainter painter(this);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.scale(scale_, scale_);
|
||||
painter.setPen(color_);
|
||||
painter.setOpacity(1);
|
||||
|
||||
QPointF pos(2 + x_, height() - 36 + y_);
|
||||
painter.drawText(pos.x(), pos.y(), text_field_->label());
|
||||
QPointF pos(2 + x_, height() - 36 + y_);
|
||||
painter.drawText(pos.x(), pos.y(), text_field_->label());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,163 +18,163 @@ class TextFieldStateMachine;
|
|||
|
||||
class TextField : public QLineEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QColor inkColor WRITE setInkColor READ inkColor)
|
||||
Q_PROPERTY(QColor labelColor WRITE setLabelColor READ labelColor)
|
||||
Q_PROPERTY(QColor underlineColor WRITE setUnderlineColor READ underlineColor)
|
||||
Q_PROPERTY(QColor backgroundColor WRITE setBackgroundColor READ backgroundColor)
|
||||
Q_PROPERTY(QColor inkColor WRITE setInkColor READ inkColor)
|
||||
Q_PROPERTY(QColor labelColor WRITE setLabelColor READ labelColor)
|
||||
Q_PROPERTY(QColor underlineColor WRITE setUnderlineColor READ underlineColor)
|
||||
Q_PROPERTY(QColor backgroundColor WRITE setBackgroundColor READ backgroundColor)
|
||||
|
||||
public:
|
||||
explicit TextField(QWidget *parent = nullptr);
|
||||
explicit TextField(QWidget *parent = nullptr);
|
||||
|
||||
void setInkColor(const QColor &color);
|
||||
void setBackgroundColor(const QColor &color);
|
||||
void setLabel(const QString &label);
|
||||
void setLabelColor(const QColor &color);
|
||||
void setLabelFontSize(qreal size);
|
||||
void setShowLabel(bool value);
|
||||
void setUnderlineColor(const QColor &color);
|
||||
void setRegexp(const QRegularExpression ®exp);
|
||||
void setValid(bool valid);
|
||||
void setInkColor(const QColor &color);
|
||||
void setBackgroundColor(const QColor &color);
|
||||
void setLabel(const QString &label);
|
||||
void setLabelColor(const QColor &color);
|
||||
void setLabelFontSize(qreal size);
|
||||
void setShowLabel(bool value);
|
||||
void setUnderlineColor(const QColor &color);
|
||||
void setRegexp(const QRegularExpression ®exp);
|
||||
void setValid(bool valid);
|
||||
|
||||
QColor inkColor() const;
|
||||
QColor labelColor() const;
|
||||
QColor underlineColor() const;
|
||||
QColor backgroundColor() const;
|
||||
QString label() const;
|
||||
bool hasLabel() const;
|
||||
bool isValid() const;
|
||||
qreal labelFontSize() const;
|
||||
QColor inkColor() const;
|
||||
QColor labelColor() const;
|
||||
QColor underlineColor() const;
|
||||
QColor backgroundColor() const;
|
||||
QString label() const;
|
||||
bool hasLabel() const;
|
||||
bool isValid() const;
|
||||
qreal labelFontSize() const;
|
||||
|
||||
protected:
|
||||
bool event(QEvent *event) override;
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
bool event(QEvent *event) override;
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
|
||||
private:
|
||||
void init();
|
||||
void init();
|
||||
|
||||
QColor ink_color_;
|
||||
QColor background_color_;
|
||||
QColor label_color_;
|
||||
QColor underline_color_;
|
||||
QString label_text_;
|
||||
TextFieldLabel *label_;
|
||||
TextFieldStateMachine *state_machine_;
|
||||
bool show_label_;
|
||||
QRegularExpression regexp_;
|
||||
bool is_valid_;
|
||||
qreal label_font_size_;
|
||||
QColor ink_color_;
|
||||
QColor background_color_;
|
||||
QColor label_color_;
|
||||
QColor underline_color_;
|
||||
QString label_text_;
|
||||
TextFieldLabel *label_;
|
||||
TextFieldStateMachine *state_machine_;
|
||||
bool show_label_;
|
||||
QRegularExpression regexp_;
|
||||
bool is_valid_;
|
||||
qreal label_font_size_;
|
||||
};
|
||||
|
||||
class TextFieldLabel : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(qreal scale WRITE setScale READ scale)
|
||||
Q_PROPERTY(QPointF offset WRITE setOffset READ offset)
|
||||
Q_PROPERTY(QColor color WRITE setColor READ color)
|
||||
Q_PROPERTY(qreal scale WRITE setScale READ scale)
|
||||
Q_PROPERTY(QPointF offset WRITE setOffset READ offset)
|
||||
Q_PROPERTY(QColor color WRITE setColor READ color)
|
||||
|
||||
public:
|
||||
TextFieldLabel(TextField *parent);
|
||||
TextFieldLabel(TextField *parent);
|
||||
|
||||
inline void setColor(const QColor &color);
|
||||
inline void setOffset(const QPointF &pos);
|
||||
inline void setScale(qreal scale);
|
||||
inline void setColor(const QColor &color);
|
||||
inline void setOffset(const QPointF &pos);
|
||||
inline void setScale(qreal scale);
|
||||
|
||||
inline QColor color() const;
|
||||
inline QPointF offset() const;
|
||||
inline qreal scale() const;
|
||||
inline QColor color() const;
|
||||
inline QPointF offset() const;
|
||||
inline qreal scale() const;
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
|
||||
private:
|
||||
TextField *const text_field_;
|
||||
TextField *const text_field_;
|
||||
|
||||
QColor color_;
|
||||
qreal scale_;
|
||||
qreal x_;
|
||||
qreal y_;
|
||||
QColor color_;
|
||||
qreal scale_;
|
||||
qreal x_;
|
||||
qreal y_;
|
||||
};
|
||||
|
||||
inline void
|
||||
TextFieldLabel::setColor(const QColor &color)
|
||||
{
|
||||
color_ = color;
|
||||
update();
|
||||
color_ = color;
|
||||
update();
|
||||
}
|
||||
|
||||
inline void
|
||||
TextFieldLabel::setOffset(const QPointF &pos)
|
||||
{
|
||||
x_ = pos.x();
|
||||
y_ = pos.y();
|
||||
update();
|
||||
x_ = pos.x();
|
||||
y_ = pos.y();
|
||||
update();
|
||||
}
|
||||
|
||||
inline void
|
||||
TextFieldLabel::setScale(qreal scale)
|
||||
{
|
||||
scale_ = scale;
|
||||
update();
|
||||
scale_ = scale;
|
||||
update();
|
||||
}
|
||||
|
||||
inline QPointF
|
||||
TextFieldLabel::offset() const
|
||||
{
|
||||
return QPointF(x_, y_);
|
||||
return QPointF(x_, y_);
|
||||
}
|
||||
inline qreal
|
||||
TextFieldLabel::scale() const
|
||||
{
|
||||
return scale_;
|
||||
return scale_;
|
||||
}
|
||||
inline QColor
|
||||
TextFieldLabel::color() const
|
||||
{
|
||||
return color_;
|
||||
return color_;
|
||||
}
|
||||
|
||||
class TextFieldStateMachine : public QStateMachine
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(qreal progress WRITE setProgress READ progress)
|
||||
Q_PROPERTY(qreal progress WRITE setProgress READ progress)
|
||||
|
||||
public:
|
||||
TextFieldStateMachine(TextField *parent);
|
||||
TextFieldStateMachine(TextField *parent);
|
||||
|
||||
inline void setProgress(qreal progress);
|
||||
void setLabel(TextFieldLabel *label);
|
||||
inline void setProgress(qreal progress);
|
||||
void setLabel(TextFieldLabel *label);
|
||||
|
||||
inline qreal progress() const;
|
||||
inline qreal progress() const;
|
||||
|
||||
public slots:
|
||||
void setupProperties();
|
||||
void setupProperties();
|
||||
|
||||
private:
|
||||
QPropertyAnimation *color_anim_;
|
||||
QPropertyAnimation *offset_anim_;
|
||||
QPropertyAnimation *color_anim_;
|
||||
QPropertyAnimation *offset_anim_;
|
||||
|
||||
QState *focused_state_;
|
||||
QState *normal_state_;
|
||||
QState *focused_state_;
|
||||
QState *normal_state_;
|
||||
|
||||
TextField *text_field_;
|
||||
TextFieldLabel *label_;
|
||||
TextField *text_field_;
|
||||
TextFieldLabel *label_;
|
||||
|
||||
qreal progress_;
|
||||
qreal progress_;
|
||||
};
|
||||
|
||||
inline void
|
||||
TextFieldStateMachine::setProgress(qreal progress)
|
||||
{
|
||||
progress_ = progress;
|
||||
text_field_->update();
|
||||
progress_ = progress;
|
||||
text_field_->update();
|
||||
}
|
||||
|
||||
inline qreal
|
||||
TextFieldStateMachine::progress() const
|
||||
{
|
||||
return progress_;
|
||||
return progress_;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,12 +14,12 @@
|
|||
bool
|
||||
ContextMenuFilter::eventFilter(QObject *obj, QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::MouseButtonPress) {
|
||||
emit contextMenuIsOpening();
|
||||
return true;
|
||||
}
|
||||
if (event->type() == QEvent::MouseButtonPress) {
|
||||
emit contextMenuIsOpening();
|
||||
return true;
|
||||
}
|
||||
|
||||
return QObject::eventFilter(obj, event);
|
||||
return QObject::eventFilter(obj, event);
|
||||
}
|
||||
|
||||
TextLabel::TextLabel(QWidget *parent)
|
||||
|
|
@ -29,94 +29,94 @@ TextLabel::TextLabel(QWidget *parent)
|
|||
TextLabel::TextLabel(const QString &text, QWidget *parent)
|
||||
: QTextBrowser(parent)
|
||||
{
|
||||
document()->setDefaultStyleSheet(QString("a {color: %1; }").arg(utils::linkColor()));
|
||||
document()->setDefaultStyleSheet(QString("a {color: %1; }").arg(utils::linkColor()));
|
||||
|
||||
setText(text);
|
||||
setOpenExternalLinks(true);
|
||||
setText(text);
|
||||
setOpenExternalLinks(true);
|
||||
|
||||
// Make it look and feel like an ordinary label.
|
||||
setReadOnly(true);
|
||||
setFrameStyle(QFrame::NoFrame);
|
||||
QPalette pal = palette();
|
||||
pal.setColor(QPalette::Base, Qt::transparent);
|
||||
setPalette(pal);
|
||||
// Make it look and feel like an ordinary label.
|
||||
setReadOnly(true);
|
||||
setFrameStyle(QFrame::NoFrame);
|
||||
QPalette pal = palette();
|
||||
pal.setColor(QPalette::Base, Qt::transparent);
|
||||
setPalette(pal);
|
||||
|
||||
// Wrap anywhere but prefer words, adjust minimum height on the fly.
|
||||
setLineWrapMode(QTextEdit::WidgetWidth);
|
||||
setWordWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
|
||||
connect(document()->documentLayout(),
|
||||
&QAbstractTextDocumentLayout::documentSizeChanged,
|
||||
this,
|
||||
&TextLabel::adjustHeight);
|
||||
document()->setDocumentMargin(0);
|
||||
// Wrap anywhere but prefer words, adjust minimum height on the fly.
|
||||
setLineWrapMode(QTextEdit::WidgetWidth);
|
||||
setWordWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
|
||||
connect(document()->documentLayout(),
|
||||
&QAbstractTextDocumentLayout::documentSizeChanged,
|
||||
this,
|
||||
&TextLabel::adjustHeight);
|
||||
document()->setDocumentMargin(0);
|
||||
|
||||
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||
setFixedHeight(0);
|
||||
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||
setFixedHeight(0);
|
||||
|
||||
connect(this, &TextLabel::linkActivated, this, &TextLabel::handleLinkActivation);
|
||||
connect(this, &TextLabel::linkActivated, this, &TextLabel::handleLinkActivation);
|
||||
|
||||
auto filter = new ContextMenuFilter(this);
|
||||
installEventFilter(filter);
|
||||
connect(filter, &ContextMenuFilter::contextMenuIsOpening, this, [this]() {
|
||||
contextMenuRequested_ = true;
|
||||
});
|
||||
auto filter = new ContextMenuFilter(this);
|
||||
installEventFilter(filter);
|
||||
connect(filter, &ContextMenuFilter::contextMenuIsOpening, this, [this]() {
|
||||
contextMenuRequested_ = true;
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
TextLabel::focusOutEvent(QFocusEvent *e)
|
||||
{
|
||||
QTextBrowser::focusOutEvent(e);
|
||||
QTextBrowser::focusOutEvent(e);
|
||||
|
||||
// We keep the selection available for the context menu.
|
||||
if (contextMenuRequested_) {
|
||||
contextMenuRequested_ = false;
|
||||
return;
|
||||
}
|
||||
// We keep the selection available for the context menu.
|
||||
if (contextMenuRequested_) {
|
||||
contextMenuRequested_ = false;
|
||||
return;
|
||||
}
|
||||
|
||||
QTextCursor cursor = textCursor();
|
||||
cursor.clearSelection();
|
||||
setTextCursor(cursor);
|
||||
QTextCursor cursor = textCursor();
|
||||
cursor.clearSelection();
|
||||
setTextCursor(cursor);
|
||||
}
|
||||
|
||||
void
|
||||
TextLabel::mousePressEvent(QMouseEvent *e)
|
||||
{
|
||||
link_ = (e->button() & Qt::LeftButton) ? anchorAt(e->pos()) : QString();
|
||||
QTextBrowser::mousePressEvent(e);
|
||||
link_ = (e->button() & Qt::LeftButton) ? anchorAt(e->pos()) : QString();
|
||||
QTextBrowser::mousePressEvent(e);
|
||||
}
|
||||
|
||||
void
|
||||
TextLabel::mouseReleaseEvent(QMouseEvent *e)
|
||||
{
|
||||
if (e->button() & Qt::LeftButton && !link_.isEmpty() && anchorAt(e->pos()) == link_) {
|
||||
emit linkActivated(link_);
|
||||
return;
|
||||
}
|
||||
if (e->button() & Qt::LeftButton && !link_.isEmpty() && anchorAt(e->pos()) == link_) {
|
||||
emit linkActivated(link_);
|
||||
return;
|
||||
}
|
||||
|
||||
QTextBrowser::mouseReleaseEvent(e);
|
||||
QTextBrowser::mouseReleaseEvent(e);
|
||||
}
|
||||
|
||||
void
|
||||
TextLabel::wheelEvent(QWheelEvent *event)
|
||||
{
|
||||
event->ignore();
|
||||
event->ignore();
|
||||
}
|
||||
|
||||
void
|
||||
TextLabel::handleLinkActivation(const QUrl &url)
|
||||
{
|
||||
auto parts = url.toString().split('/');
|
||||
auto defaultHandler = [](const QUrl &url) { QDesktopServices::openUrl(url); };
|
||||
auto parts = url.toString().split('/');
|
||||
auto defaultHandler = [](const QUrl &url) { QDesktopServices::openUrl(url); };
|
||||
|
||||
if (url.host() != "matrix.to" || parts.isEmpty())
|
||||
return defaultHandler(url);
|
||||
if (url.host() != "matrix.to" || parts.isEmpty())
|
||||
return defaultHandler(url);
|
||||
|
||||
try {
|
||||
using namespace mtx::identifiers;
|
||||
parse<User>(parts.last().toStdString());
|
||||
} catch (const std::exception &) {
|
||||
return defaultHandler(url);
|
||||
}
|
||||
try {
|
||||
using namespace mtx::identifiers;
|
||||
parse<User>(parts.last().toStdString());
|
||||
} catch (const std::exception &) {
|
||||
return defaultHandler(url);
|
||||
}
|
||||
|
||||
emit userProfileTriggered(parts.last());
|
||||
emit userProfileTriggered(parts.last());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,45 +15,45 @@ class QWheelEvent;
|
|||
|
||||
class ContextMenuFilter : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ContextMenuFilter(QWidget *parent)
|
||||
: QObject(parent)
|
||||
{}
|
||||
explicit ContextMenuFilter(QWidget *parent)
|
||||
: QObject(parent)
|
||||
{}
|
||||
|
||||
signals:
|
||||
void contextMenuIsOpening();
|
||||
void contextMenuIsOpening();
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
};
|
||||
|
||||
class TextLabel : public QTextBrowser
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TextLabel(const QString &text, QWidget *parent = nullptr);
|
||||
TextLabel(QWidget *parent = nullptr);
|
||||
TextLabel(const QString &text, QWidget *parent = nullptr);
|
||||
TextLabel(QWidget *parent = nullptr);
|
||||
|
||||
void wheelEvent(QWheelEvent *event) override;
|
||||
void clearLinks() { link_.clear(); }
|
||||
void wheelEvent(QWheelEvent *event) override;
|
||||
void clearLinks() { link_.clear(); }
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QMouseEvent *e) override;
|
||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
void focusOutEvent(QFocusEvent *e) override;
|
||||
void mousePressEvent(QMouseEvent *e) override;
|
||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
void focusOutEvent(QFocusEvent *e) override;
|
||||
|
||||
private slots:
|
||||
void adjustHeight(const QSizeF &size) { setFixedHeight(size.height()); }
|
||||
void handleLinkActivation(const QUrl &link);
|
||||
void adjustHeight(const QSizeF &size) { setFixedHeight(size.height()); }
|
||||
void handleLinkActivation(const QUrl &link);
|
||||
|
||||
signals:
|
||||
void userProfileTriggered(const QString &user_id);
|
||||
void linkActivated(const QUrl &link);
|
||||
void userProfileTriggered(const QString &user_id);
|
||||
void linkActivated(const QUrl &link);
|
||||
|
||||
private:
|
||||
QString link_;
|
||||
bool contextMenuRequested_ = false;
|
||||
QString link_;
|
||||
bool contextMenuRequested_ = false;
|
||||
};
|
||||
|
|
|
|||
116
src/ui/Theme.cpp
116
src/ui/Theme.cpp
|
|
@ -9,66 +9,66 @@ Q_DECLARE_METATYPE(Theme)
|
|||
QPalette
|
||||
Theme::paletteFromTheme(std::string_view theme)
|
||||
{
|
||||
[[maybe_unused]] static auto meta = qRegisterMetaType<Theme>("Theme");
|
||||
static QPalette original;
|
||||
if (theme == "light") {
|
||||
QPalette lightActive(
|
||||
/*windowText*/ QColor("#333"),
|
||||
/*button*/ QColor("white"),
|
||||
/*light*/ QColor(0xef, 0xef, 0xef),
|
||||
/*dark*/ QColor(70, 77, 93),
|
||||
/*mid*/ QColor(220, 220, 220),
|
||||
/*text*/ QColor("#333"),
|
||||
/*bright_text*/ QColor("#f2f5f8"),
|
||||
/*base*/ QColor("#fff"),
|
||||
/*window*/ QColor("white"));
|
||||
lightActive.setColor(QPalette::AlternateBase, QColor("#eee"));
|
||||
lightActive.setColor(QPalette::Highlight, QColor("#38a3d8"));
|
||||
lightActive.setColor(QPalette::HighlightedText, QColor("#f4f4f5"));
|
||||
lightActive.setColor(QPalette::ToolTipBase, lightActive.base().color());
|
||||
lightActive.setColor(QPalette::ToolTipText, lightActive.text().color());
|
||||
lightActive.setColor(QPalette::Link, QColor("#0077b5"));
|
||||
lightActive.setColor(QPalette::ButtonText, QColor("#555459"));
|
||||
return lightActive;
|
||||
} else if (theme == "dark") {
|
||||
QPalette darkActive(
|
||||
/*windowText*/ QColor("#caccd1"),
|
||||
/*button*/ QColor(0xff, 0xff, 0xff),
|
||||
/*light*/ QColor("#caccd1"),
|
||||
/*dark*/ QColor(60, 70, 77),
|
||||
/*mid*/ QColor("#202228"),
|
||||
/*text*/ QColor("#caccd1"),
|
||||
/*bright_text*/ QColor("#f4f5f8"),
|
||||
/*base*/ QColor("#202228"),
|
||||
/*window*/ QColor("#2d3139"));
|
||||
darkActive.setColor(QPalette::AlternateBase, QColor("#2d3139"));
|
||||
darkActive.setColor(QPalette::Highlight, QColor("#38a3d8"));
|
||||
darkActive.setColor(QPalette::HighlightedText, QColor("#f4f5f8"));
|
||||
darkActive.setColor(QPalette::ToolTipBase, darkActive.base().color());
|
||||
darkActive.setColor(QPalette::ToolTipText, darkActive.text().color());
|
||||
darkActive.setColor(QPalette::Link, QColor("#38a3d8"));
|
||||
darkActive.setColor(QPalette::ButtonText, "#828284");
|
||||
return darkActive;
|
||||
} else {
|
||||
return original;
|
||||
}
|
||||
[[maybe_unused]] static auto meta = qRegisterMetaType<Theme>("Theme");
|
||||
static QPalette original;
|
||||
if (theme == "light") {
|
||||
QPalette lightActive(
|
||||
/*windowText*/ QColor("#333"),
|
||||
/*button*/ QColor("white"),
|
||||
/*light*/ QColor(0xef, 0xef, 0xef),
|
||||
/*dark*/ QColor(70, 77, 93),
|
||||
/*mid*/ QColor(220, 220, 220),
|
||||
/*text*/ QColor("#333"),
|
||||
/*bright_text*/ QColor("#f2f5f8"),
|
||||
/*base*/ QColor("#fff"),
|
||||
/*window*/ QColor("white"));
|
||||
lightActive.setColor(QPalette::AlternateBase, QColor("#eee"));
|
||||
lightActive.setColor(QPalette::Highlight, QColor("#38a3d8"));
|
||||
lightActive.setColor(QPalette::HighlightedText, QColor("#f4f4f5"));
|
||||
lightActive.setColor(QPalette::ToolTipBase, lightActive.base().color());
|
||||
lightActive.setColor(QPalette::ToolTipText, lightActive.text().color());
|
||||
lightActive.setColor(QPalette::Link, QColor("#0077b5"));
|
||||
lightActive.setColor(QPalette::ButtonText, QColor("#555459"));
|
||||
return lightActive;
|
||||
} else if (theme == "dark") {
|
||||
QPalette darkActive(
|
||||
/*windowText*/ QColor("#caccd1"),
|
||||
/*button*/ QColor(0xff, 0xff, 0xff),
|
||||
/*light*/ QColor("#caccd1"),
|
||||
/*dark*/ QColor(60, 70, 77),
|
||||
/*mid*/ QColor("#202228"),
|
||||
/*text*/ QColor("#caccd1"),
|
||||
/*bright_text*/ QColor("#f4f5f8"),
|
||||
/*base*/ QColor("#202228"),
|
||||
/*window*/ QColor("#2d3139"));
|
||||
darkActive.setColor(QPalette::AlternateBase, QColor("#2d3139"));
|
||||
darkActive.setColor(QPalette::Highlight, QColor("#38a3d8"));
|
||||
darkActive.setColor(QPalette::HighlightedText, QColor("#f4f5f8"));
|
||||
darkActive.setColor(QPalette::ToolTipBase, darkActive.base().color());
|
||||
darkActive.setColor(QPalette::ToolTipText, darkActive.text().color());
|
||||
darkActive.setColor(QPalette::Link, QColor("#38a3d8"));
|
||||
darkActive.setColor(QPalette::ButtonText, "#828284");
|
||||
return darkActive;
|
||||
} else {
|
||||
return original;
|
||||
}
|
||||
}
|
||||
|
||||
Theme::Theme(std::string_view theme)
|
||||
{
|
||||
auto p = paletteFromTheme(theme);
|
||||
separator_ = p.mid().color();
|
||||
if (theme == "light") {
|
||||
sidebarBackground_ = QColor("#233649");
|
||||
alternateButton_ = QColor("#ccc");
|
||||
red_ = QColor("#a82353");
|
||||
} else if (theme == "dark") {
|
||||
sidebarBackground_ = QColor("#2d3139");
|
||||
alternateButton_ = QColor("#414A59");
|
||||
red_ = QColor("#a82353");
|
||||
} else {
|
||||
sidebarBackground_ = p.window().color();
|
||||
alternateButton_ = p.dark().color();
|
||||
red_ = QColor("red");
|
||||
}
|
||||
auto p = paletteFromTheme(theme);
|
||||
separator_ = p.mid().color();
|
||||
if (theme == "light") {
|
||||
sidebarBackground_ = QColor("#233649");
|
||||
alternateButton_ = QColor("#ccc");
|
||||
red_ = QColor("#a82353");
|
||||
} else if (theme == "dark") {
|
||||
sidebarBackground_ = QColor("#2d3139");
|
||||
alternateButton_ = QColor("#414A59");
|
||||
red_ = QColor("#a82353");
|
||||
} else {
|
||||
sidebarBackground_ = p.window().color();
|
||||
alternateButton_ = p.dark().color();
|
||||
red_ = QColor("red");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,62 +16,62 @@ const int AvatarSize = 40;
|
|||
|
||||
enum class ButtonPreset
|
||||
{
|
||||
FlatPreset,
|
||||
CheckablePreset
|
||||
FlatPreset,
|
||||
CheckablePreset
|
||||
};
|
||||
|
||||
enum class RippleStyle
|
||||
{
|
||||
CenteredRipple,
|
||||
PositionedRipple,
|
||||
NoRipple
|
||||
CenteredRipple,
|
||||
PositionedRipple,
|
||||
NoRipple
|
||||
};
|
||||
|
||||
enum class OverlayStyle
|
||||
{
|
||||
NoOverlay,
|
||||
TintedOverlay,
|
||||
GrayOverlay
|
||||
NoOverlay,
|
||||
TintedOverlay,
|
||||
GrayOverlay
|
||||
};
|
||||
|
||||
enum class Role
|
||||
{
|
||||
Default,
|
||||
Primary,
|
||||
Secondary
|
||||
Default,
|
||||
Primary,
|
||||
Secondary
|
||||
};
|
||||
|
||||
enum class ButtonIconPlacement
|
||||
{
|
||||
LeftIcon,
|
||||
RightIcon
|
||||
LeftIcon,
|
||||
RightIcon
|
||||
};
|
||||
|
||||
enum class ProgressType
|
||||
{
|
||||
DeterminateProgress,
|
||||
IndeterminateProgress
|
||||
DeterminateProgress,
|
||||
IndeterminateProgress
|
||||
};
|
||||
|
||||
} // namespace ui
|
||||
|
||||
class Theme : public QPalette
|
||||
{
|
||||
Q_GADGET
|
||||
Q_PROPERTY(QColor sidebarBackground READ sidebarBackground CONSTANT)
|
||||
Q_PROPERTY(QColor alternateButton READ alternateButton CONSTANT)
|
||||
Q_PROPERTY(QColor separator READ separator CONSTANT)
|
||||
Q_PROPERTY(QColor red READ red CONSTANT)
|
||||
Q_GADGET
|
||||
Q_PROPERTY(QColor sidebarBackground READ sidebarBackground CONSTANT)
|
||||
Q_PROPERTY(QColor alternateButton READ alternateButton CONSTANT)
|
||||
Q_PROPERTY(QColor separator READ separator CONSTANT)
|
||||
Q_PROPERTY(QColor red READ red CONSTANT)
|
||||
public:
|
||||
Theme() {}
|
||||
explicit Theme(std::string_view theme);
|
||||
static QPalette paletteFromTheme(std::string_view theme);
|
||||
Theme() {}
|
||||
explicit Theme(std::string_view theme);
|
||||
static QPalette paletteFromTheme(std::string_view theme);
|
||||
|
||||
QColor sidebarBackground() const { return sidebarBackground_; }
|
||||
QColor alternateButton() const { return alternateButton_; }
|
||||
QColor separator() const { return separator_; }
|
||||
QColor red() const { return red_; }
|
||||
QColor sidebarBackground() const { return sidebarBackground_; }
|
||||
QColor alternateButton() const { return alternateButton_; }
|
||||
QColor separator() const { return separator_; }
|
||||
QColor red() const { return red_; }
|
||||
|
||||
private:
|
||||
QColor sidebarBackground_, separator_, red_, alternateButton_;
|
||||
QColor sidebarBackground_, separator_, red_, alternateButton_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -11,32 +11,32 @@ ThemeManager::ThemeManager() {}
|
|||
QColor
|
||||
ThemeManager::themeColor(const QString &key) const
|
||||
{
|
||||
if (key == "Black")
|
||||
return QColor("#171919");
|
||||
if (key == "Black")
|
||||
return QColor("#171919");
|
||||
|
||||
else if (key == "BrightWhite")
|
||||
return QColor("#EBEBEB");
|
||||
else if (key == "FadedWhite")
|
||||
return QColor("#C9C9C9");
|
||||
else if (key == "MediumWhite")
|
||||
return QColor("#929292");
|
||||
else if (key == "BrightWhite")
|
||||
return QColor("#EBEBEB");
|
||||
else if (key == "FadedWhite")
|
||||
return QColor("#C9C9C9");
|
||||
else if (key == "MediumWhite")
|
||||
return QColor("#929292");
|
||||
|
||||
else if (key == "BrightGreen")
|
||||
return QColor("#1C3133");
|
||||
else if (key == "DarkGreen")
|
||||
return QColor("#577275");
|
||||
else if (key == "LightGreen")
|
||||
return QColor("#46A451");
|
||||
else if (key == "BrightGreen")
|
||||
return QColor("#1C3133");
|
||||
else if (key == "DarkGreen")
|
||||
return QColor("#577275");
|
||||
else if (key == "LightGreen")
|
||||
return QColor("#46A451");
|
||||
|
||||
else if (key == "Gray")
|
||||
return QColor("#5D6565");
|
||||
else if (key == "Red")
|
||||
return QColor("#E22826");
|
||||
else if (key == "Blue")
|
||||
return QColor("#81B3A9");
|
||||
else if (key == "Gray")
|
||||
return QColor("#5D6565");
|
||||
else if (key == "Red")
|
||||
return QColor("#E22826");
|
||||
else if (key == "Blue")
|
||||
return QColor("#81B3A9");
|
||||
|
||||
else if (key == "Transparent")
|
||||
return QColor(0, 0, 0, 0);
|
||||
else if (key == "Transparent")
|
||||
return QColor(0, 0, 0, 0);
|
||||
|
||||
return (QColor(0, 0, 0, 0));
|
||||
return (QColor(0, 0, 0, 0));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,23 +8,23 @@
|
|||
|
||||
class ThemeManager : public QCommonStyle
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
inline static ThemeManager &instance();
|
||||
inline static ThemeManager &instance();
|
||||
|
||||
QColor themeColor(const QString &key) const;
|
||||
QColor themeColor(const QString &key) const;
|
||||
|
||||
private:
|
||||
ThemeManager();
|
||||
ThemeManager();
|
||||
|
||||
ThemeManager(ThemeManager const &);
|
||||
void operator=(ThemeManager const &);
|
||||
ThemeManager(ThemeManager const &);
|
||||
void operator=(ThemeManager const &);
|
||||
};
|
||||
|
||||
inline ThemeManager &
|
||||
ThemeManager::instance()
|
||||
{
|
||||
static ThemeManager instance;
|
||||
return instance;
|
||||
static ThemeManager instance;
|
||||
return instance;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,84 +12,84 @@
|
|||
void
|
||||
Toggle::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
Q_UNUSED(event);
|
||||
}
|
||||
|
||||
Toggle::Toggle(QWidget *parent)
|
||||
: QAbstractButton{parent}
|
||||
{
|
||||
init();
|
||||
init();
|
||||
|
||||
connect(this, &QAbstractButton::toggled, this, &Toggle::setState);
|
||||
connect(this, &QAbstractButton::toggled, this, &Toggle::setState);
|
||||
}
|
||||
|
||||
void
|
||||
Toggle::setState(bool isEnabled)
|
||||
{
|
||||
setChecked(isEnabled);
|
||||
thumb_->setShift(isEnabled ? Position::Left : Position::Right);
|
||||
setupProperties();
|
||||
setChecked(isEnabled);
|
||||
thumb_->setShift(isEnabled ? Position::Left : Position::Right);
|
||||
setupProperties();
|
||||
}
|
||||
|
||||
void
|
||||
Toggle::init()
|
||||
{
|
||||
track_ = new ToggleTrack(this);
|
||||
thumb_ = new ToggleThumb(this);
|
||||
track_ = new ToggleTrack(this);
|
||||
thumb_ = new ToggleThumb(this);
|
||||
|
||||
setCursor(QCursor(Qt::PointingHandCursor));
|
||||
setCheckable(true);
|
||||
setChecked(false);
|
||||
setCursor(QCursor(Qt::PointingHandCursor));
|
||||
setCheckable(true);
|
||||
setChecked(false);
|
||||
|
||||
setState(false);
|
||||
setupProperties();
|
||||
setState(false);
|
||||
setupProperties();
|
||||
|
||||
QCoreApplication::processEvents();
|
||||
QCoreApplication::processEvents();
|
||||
}
|
||||
|
||||
void
|
||||
Toggle::setupProperties()
|
||||
{
|
||||
if (isEnabled()) {
|
||||
Position position = thumb_->shift();
|
||||
if (isEnabled()) {
|
||||
Position position = thumb_->shift();
|
||||
|
||||
thumb_->setThumbColor(trackColor());
|
||||
thumb_->setThumbColor(trackColor());
|
||||
|
||||
if (position == Position::Left)
|
||||
track_->setTrackColor(activeColor());
|
||||
else if (position == Position::Right)
|
||||
track_->setTrackColor(inactiveColor());
|
||||
}
|
||||
if (position == Position::Left)
|
||||
track_->setTrackColor(activeColor());
|
||||
else if (position == Position::Right)
|
||||
track_->setTrackColor(inactiveColor());
|
||||
}
|
||||
|
||||
update();
|
||||
update();
|
||||
}
|
||||
|
||||
void
|
||||
Toggle::setDisabledColor(const QColor &color)
|
||||
{
|
||||
disabledColor_ = color;
|
||||
setupProperties();
|
||||
disabledColor_ = color;
|
||||
setupProperties();
|
||||
}
|
||||
|
||||
void
|
||||
Toggle::setActiveColor(const QColor &color)
|
||||
{
|
||||
activeColor_ = color;
|
||||
setupProperties();
|
||||
activeColor_ = color;
|
||||
setupProperties();
|
||||
}
|
||||
|
||||
void
|
||||
Toggle::setInactiveColor(const QColor &color)
|
||||
{
|
||||
inactiveColor_ = color;
|
||||
setupProperties();
|
||||
inactiveColor_ = color;
|
||||
setupProperties();
|
||||
}
|
||||
|
||||
void
|
||||
Toggle::setTrackColor(const QColor &color)
|
||||
{
|
||||
trackColor_ = color;
|
||||
setupProperties();
|
||||
trackColor_ = color;
|
||||
setupProperties();
|
||||
}
|
||||
|
||||
ToggleThumb::ToggleThumb(Toggle *parent)
|
||||
|
|
@ -98,119 +98,119 @@ ToggleThumb::ToggleThumb(Toggle *parent)
|
|||
, position_{Position::Right}
|
||||
, offset_{0}
|
||||
{
|
||||
parent->installEventFilter(this);
|
||||
parent->installEventFilter(this);
|
||||
}
|
||||
|
||||
void
|
||||
ToggleThumb::setShift(Position position)
|
||||
{
|
||||
if (position_ != position) {
|
||||
position_ = position;
|
||||
updateOffset();
|
||||
}
|
||||
if (position_ != position) {
|
||||
position_ = position;
|
||||
updateOffset();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ToggleThumb::eventFilter(QObject *obj, QEvent *event)
|
||||
{
|
||||
const QEvent::Type type = event->type();
|
||||
const QEvent::Type type = event->type();
|
||||
|
||||
if (QEvent::Resize == type || QEvent::Move == type) {
|
||||
setGeometry(toggle_->rect().adjusted(8, 8, -8, -8));
|
||||
updateOffset();
|
||||
}
|
||||
if (QEvent::Resize == type || QEvent::Move == type) {
|
||||
setGeometry(toggle_->rect().adjusted(8, 8, -8, -8));
|
||||
updateOffset();
|
||||
}
|
||||
|
||||
return QWidget::eventFilter(obj, event);
|
||||
return QWidget::eventFilter(obj, event);
|
||||
}
|
||||
|
||||
void
|
||||
ToggleThumb::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
Q_UNUSED(event)
|
||||
|
||||
QPainter painter(this);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
QPainter painter(this);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
QBrush brush;
|
||||
brush.setStyle(Qt::SolidPattern);
|
||||
brush.setColor(toggle_->isEnabled() ? thumbColor_ : Qt::white);
|
||||
QBrush brush;
|
||||
brush.setStyle(Qt::SolidPattern);
|
||||
brush.setColor(toggle_->isEnabled() ? thumbColor_ : Qt::white);
|
||||
|
||||
painter.setBrush(brush);
|
||||
painter.setPen(Qt::NoPen);
|
||||
|
||||
int s;
|
||||
QRectF r;
|
||||
|
||||
s = height() - 10;
|
||||
r = QRectF(5 + offset_, 5, s, s);
|
||||
|
||||
painter.drawEllipse(r);
|
||||
|
||||
if (!toggle_->isEnabled()) {
|
||||
brush.setColor(toggle_->disabledColor());
|
||||
painter.setBrush(brush);
|
||||
painter.setPen(Qt::NoPen);
|
||||
|
||||
int s;
|
||||
QRectF r;
|
||||
|
||||
s = height() - 10;
|
||||
r = QRectF(5 + offset_, 5, s, s);
|
||||
|
||||
painter.drawEllipse(r);
|
||||
|
||||
if (!toggle_->isEnabled()) {
|
||||
brush.setColor(toggle_->disabledColor());
|
||||
painter.setBrush(brush);
|
||||
painter.drawEllipse(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ToggleThumb::updateOffset()
|
||||
{
|
||||
const QSize s(size());
|
||||
offset_ = position_ == Position::Left ? static_cast<qreal>(s.width() - s.height()) : 0;
|
||||
update();
|
||||
const QSize s(size());
|
||||
offset_ = position_ == Position::Left ? static_cast<qreal>(s.width() - s.height()) : 0;
|
||||
update();
|
||||
}
|
||||
|
||||
ToggleTrack::ToggleTrack(Toggle *parent)
|
||||
: QWidget{parent}
|
||||
, toggle_{parent}
|
||||
{
|
||||
Q_ASSERT(parent);
|
||||
Q_ASSERT(parent);
|
||||
|
||||
parent->installEventFilter(this);
|
||||
parent->installEventFilter(this);
|
||||
}
|
||||
|
||||
void
|
||||
ToggleTrack::setTrackColor(const QColor &color)
|
||||
{
|
||||
trackColor_ = color;
|
||||
update();
|
||||
trackColor_ = color;
|
||||
update();
|
||||
}
|
||||
|
||||
bool
|
||||
ToggleTrack::eventFilter(QObject *obj, QEvent *event)
|
||||
{
|
||||
const QEvent::Type type = event->type();
|
||||
const QEvent::Type type = event->type();
|
||||
|
||||
if (QEvent::Resize == type || QEvent::Move == type) {
|
||||
setGeometry(toggle_->rect());
|
||||
}
|
||||
if (QEvent::Resize == type || QEvent::Move == type) {
|
||||
setGeometry(toggle_->rect());
|
||||
}
|
||||
|
||||
return QWidget::eventFilter(obj, event);
|
||||
return QWidget::eventFilter(obj, event);
|
||||
}
|
||||
|
||||
void
|
||||
ToggleTrack::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
Q_UNUSED(event)
|
||||
|
||||
QPainter painter(this);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
QPainter painter(this);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
QBrush brush;
|
||||
if (toggle_->isEnabled()) {
|
||||
brush.setColor(trackColor_);
|
||||
painter.setOpacity(0.8);
|
||||
} else {
|
||||
brush.setColor(toggle_->disabledColor());
|
||||
painter.setOpacity(0.6);
|
||||
}
|
||||
QBrush brush;
|
||||
if (toggle_->isEnabled()) {
|
||||
brush.setColor(trackColor_);
|
||||
painter.setOpacity(0.8);
|
||||
} else {
|
||||
brush.setColor(toggle_->disabledColor());
|
||||
painter.setOpacity(0.6);
|
||||
}
|
||||
|
||||
brush.setStyle(Qt::SolidPattern);
|
||||
painter.setBrush(brush);
|
||||
painter.setPen(Qt::NoPen);
|
||||
brush.setStyle(Qt::SolidPattern);
|
||||
painter.setBrush(brush);
|
||||
painter.setPen(Qt::NoPen);
|
||||
|
||||
const int h = height() / 2;
|
||||
const QRect r(0, h / 2, width(), h);
|
||||
painter.drawRoundedRect(r.adjusted(14, 4, -14, -4), h / 2 - 4, h / 2 - 4);
|
||||
const int h = height() / 2;
|
||||
const QRect r(0, h / 2, width(), h);
|
||||
painter.drawRoundedRect(r.adjusted(14, 4, -14, -4), h / 2 - 4, h / 2 - 4);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,103 +12,103 @@ class ToggleThumb;
|
|||
|
||||
enum class Position
|
||||
{
|
||||
Left,
|
||||
Right
|
||||
Left,
|
||||
Right
|
||||
};
|
||||
|
||||
class Toggle : public QAbstractButton
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QColor activeColor WRITE setActiveColor READ activeColor)
|
||||
Q_PROPERTY(QColor disabledColor WRITE setDisabledColor READ disabledColor)
|
||||
Q_PROPERTY(QColor inactiveColor WRITE setInactiveColor READ inactiveColor)
|
||||
Q_PROPERTY(QColor trackColor WRITE setTrackColor READ trackColor)
|
||||
Q_PROPERTY(QColor activeColor WRITE setActiveColor READ activeColor)
|
||||
Q_PROPERTY(QColor disabledColor WRITE setDisabledColor READ disabledColor)
|
||||
Q_PROPERTY(QColor inactiveColor WRITE setInactiveColor READ inactiveColor)
|
||||
Q_PROPERTY(QColor trackColor WRITE setTrackColor READ trackColor)
|
||||
|
||||
public:
|
||||
Toggle(QWidget *parent = nullptr);
|
||||
Toggle(QWidget *parent = nullptr);
|
||||
|
||||
void setState(bool isEnabled);
|
||||
void setState(bool isEnabled);
|
||||
|
||||
void setActiveColor(const QColor &color);
|
||||
void setDisabledColor(const QColor &color);
|
||||
void setInactiveColor(const QColor &color);
|
||||
void setTrackColor(const QColor &color);
|
||||
void setActiveColor(const QColor &color);
|
||||
void setDisabledColor(const QColor &color);
|
||||
void setInactiveColor(const QColor &color);
|
||||
void setTrackColor(const QColor &color);
|
||||
|
||||
QColor activeColor() const { return activeColor_; };
|
||||
QColor disabledColor() const { return disabledColor_; };
|
||||
QColor inactiveColor() const { return inactiveColor_; };
|
||||
QColor trackColor() const { return trackColor_.isValid() ? trackColor_ : QColor("#eee"); };
|
||||
QColor activeColor() const { return activeColor_; };
|
||||
QColor disabledColor() const { return disabledColor_; };
|
||||
QColor inactiveColor() const { return inactiveColor_; };
|
||||
QColor trackColor() const { return trackColor_.isValid() ? trackColor_ : QColor("#eee"); };
|
||||
|
||||
QSize sizeHint() const override { return QSize(64, 48); };
|
||||
QSize sizeHint() const override { return QSize(64, 48); };
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
|
||||
private:
|
||||
void init();
|
||||
void setupProperties();
|
||||
void init();
|
||||
void setupProperties();
|
||||
|
||||
ToggleTrack *track_;
|
||||
ToggleThumb *thumb_;
|
||||
ToggleTrack *track_;
|
||||
ToggleThumb *thumb_;
|
||||
|
||||
QColor disabledColor_;
|
||||
QColor activeColor_;
|
||||
QColor inactiveColor_;
|
||||
QColor trackColor_;
|
||||
QColor disabledColor_;
|
||||
QColor activeColor_;
|
||||
QColor inactiveColor_;
|
||||
QColor trackColor_;
|
||||
};
|
||||
|
||||
class ToggleThumb : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QColor thumbColor WRITE setThumbColor READ thumbColor)
|
||||
Q_PROPERTY(QColor thumbColor WRITE setThumbColor READ thumbColor)
|
||||
|
||||
public:
|
||||
ToggleThumb(Toggle *parent);
|
||||
ToggleThumb(Toggle *parent);
|
||||
|
||||
Position shift() const { return position_; };
|
||||
qreal offset() const { return offset_; };
|
||||
QColor thumbColor() const { return thumbColor_; };
|
||||
Position shift() const { return position_; };
|
||||
qreal offset() const { return offset_; };
|
||||
QColor thumbColor() const { return thumbColor_; };
|
||||
|
||||
void setShift(Position position);
|
||||
void setThumbColor(const QColor &color)
|
||||
{
|
||||
thumbColor_ = color;
|
||||
update();
|
||||
};
|
||||
void setShift(Position position);
|
||||
void setThumbColor(const QColor &color)
|
||||
{
|
||||
thumbColor_ = color;
|
||||
update();
|
||||
};
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
|
||||
private:
|
||||
void updateOffset();
|
||||
void updateOffset();
|
||||
|
||||
Toggle *const toggle_;
|
||||
QColor thumbColor_;
|
||||
Toggle *const toggle_;
|
||||
QColor thumbColor_;
|
||||
|
||||
Position position_;
|
||||
qreal offset_;
|
||||
Position position_;
|
||||
qreal offset_;
|
||||
};
|
||||
|
||||
class ToggleTrack : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QColor trackColor WRITE setTrackColor READ trackColor)
|
||||
Q_PROPERTY(QColor trackColor WRITE setTrackColor READ trackColor)
|
||||
|
||||
public:
|
||||
ToggleTrack(Toggle *parent);
|
||||
ToggleTrack(Toggle *parent);
|
||||
|
||||
void setTrackColor(const QColor &color);
|
||||
QColor trackColor() const { return trackColor_; };
|
||||
void setTrackColor(const QColor &color);
|
||||
QColor trackColor() const { return trackColor_; };
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
|
||||
private:
|
||||
Toggle *const toggle_;
|
||||
QColor trackColor_;
|
||||
Toggle *const toggle_;
|
||||
QColor trackColor_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -27,210 +27,200 @@ UserProfile::UserProfile(QString roomid,
|
|||
, manager(manager_)
|
||||
, model(parent)
|
||||
{
|
||||
globalAvatarUrl = "";
|
||||
globalAvatarUrl = "";
|
||||
|
||||
connect(this,
|
||||
&UserProfile::globalUsernameRetrieved,
|
||||
this,
|
||||
&UserProfile::setGlobalUsername,
|
||||
Qt::QueuedConnection);
|
||||
connect(this,
|
||||
&UserProfile::globalUsernameRetrieved,
|
||||
this,
|
||||
&UserProfile::setGlobalUsername,
|
||||
Qt::QueuedConnection);
|
||||
|
||||
if (isGlobalUserProfile()) {
|
||||
getGlobalProfileData();
|
||||
}
|
||||
if (isGlobalUserProfile()) {
|
||||
getGlobalProfileData();
|
||||
}
|
||||
|
||||
if (!cache::client() || !cache::client()->isDatabaseReady() ||
|
||||
!ChatPage::instance()->timelineManager())
|
||||
return;
|
||||
if (!cache::client() || !cache::client()->isDatabaseReady() ||
|
||||
!ChatPage::instance()->timelineManager())
|
||||
return;
|
||||
|
||||
connect(cache::client(),
|
||||
&Cache::verificationStatusChanged,
|
||||
this,
|
||||
[this](const std::string &user_id) {
|
||||
if (user_id != this->userid_.toStdString())
|
||||
return;
|
||||
connect(
|
||||
cache::client(), &Cache::verificationStatusChanged, this, [this](const std::string &user_id) {
|
||||
if (user_id != this->userid_.toStdString())
|
||||
return;
|
||||
|
||||
auto status = cache::verificationStatus(user_id);
|
||||
if (!status)
|
||||
return;
|
||||
this->isUserVerified = status->user_verified;
|
||||
emit userStatusChanged();
|
||||
auto status = cache::verificationStatus(user_id);
|
||||
if (!status)
|
||||
return;
|
||||
this->isUserVerified = status->user_verified;
|
||||
emit userStatusChanged();
|
||||
|
||||
for (auto &deviceInfo : deviceList_.deviceList_) {
|
||||
deviceInfo.verification_status =
|
||||
std::find(status->verified_devices.begin(),
|
||||
status->verified_devices.end(),
|
||||
deviceInfo.device_id.toStdString()) ==
|
||||
status->verified_devices.end()
|
||||
? verification::UNVERIFIED
|
||||
: verification::VERIFIED;
|
||||
}
|
||||
deviceList_.reset(deviceList_.deviceList_);
|
||||
emit devicesChanged();
|
||||
});
|
||||
fetchDeviceList(this->userid_);
|
||||
for (auto &deviceInfo : deviceList_.deviceList_) {
|
||||
deviceInfo.verification_status =
|
||||
std::find(status->verified_devices.begin(),
|
||||
status->verified_devices.end(),
|
||||
deviceInfo.device_id.toStdString()) == status->verified_devices.end()
|
||||
? verification::UNVERIFIED
|
||||
: verification::VERIFIED;
|
||||
}
|
||||
deviceList_.reset(deviceList_.deviceList_);
|
||||
emit devicesChanged();
|
||||
});
|
||||
fetchDeviceList(this->userid_);
|
||||
}
|
||||
|
||||
QHash<int, QByteArray>
|
||||
DeviceInfoModel::roleNames() const
|
||||
{
|
||||
return {
|
||||
{DeviceId, "deviceId"},
|
||||
{DeviceName, "deviceName"},
|
||||
{VerificationStatus, "verificationStatus"},
|
||||
};
|
||||
return {
|
||||
{DeviceId, "deviceId"},
|
||||
{DeviceName, "deviceName"},
|
||||
{VerificationStatus, "verificationStatus"},
|
||||
};
|
||||
}
|
||||
|
||||
QVariant
|
||||
DeviceInfoModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid() || index.row() >= (int)deviceList_.size() || index.row() < 0)
|
||||
return {};
|
||||
if (!index.isValid() || index.row() >= (int)deviceList_.size() || index.row() < 0)
|
||||
return {};
|
||||
|
||||
switch (role) {
|
||||
case DeviceId:
|
||||
return deviceList_[index.row()].device_id;
|
||||
case DeviceName:
|
||||
return deviceList_[index.row()].display_name;
|
||||
case VerificationStatus:
|
||||
return QVariant::fromValue(deviceList_[index.row()].verification_status);
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
switch (role) {
|
||||
case DeviceId:
|
||||
return deviceList_[index.row()].device_id;
|
||||
case DeviceName:
|
||||
return deviceList_[index.row()].display_name;
|
||||
case VerificationStatus:
|
||||
return QVariant::fromValue(deviceList_[index.row()].verification_status);
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DeviceInfoModel::reset(const std::vector<DeviceInfo> &deviceList)
|
||||
{
|
||||
beginResetModel();
|
||||
this->deviceList_ = std::move(deviceList);
|
||||
endResetModel();
|
||||
beginResetModel();
|
||||
this->deviceList_ = std::move(deviceList);
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
DeviceInfoModel *
|
||||
UserProfile::deviceList()
|
||||
{
|
||||
return &this->deviceList_;
|
||||
return &this->deviceList_;
|
||||
}
|
||||
|
||||
QString
|
||||
UserProfile::userid()
|
||||
{
|
||||
return this->userid_;
|
||||
return this->userid_;
|
||||
}
|
||||
|
||||
QString
|
||||
UserProfile::displayName()
|
||||
{
|
||||
return isGlobalUserProfile() ? globalUsername : cache::displayName(roomid_, userid_);
|
||||
return isGlobalUserProfile() ? globalUsername : cache::displayName(roomid_, userid_);
|
||||
}
|
||||
|
||||
QString
|
||||
UserProfile::avatarUrl()
|
||||
{
|
||||
return isGlobalUserProfile() ? globalAvatarUrl : cache::avatarUrl(roomid_, userid_);
|
||||
return isGlobalUserProfile() ? globalAvatarUrl : cache::avatarUrl(roomid_, userid_);
|
||||
}
|
||||
|
||||
bool
|
||||
UserProfile::isGlobalUserProfile() const
|
||||
{
|
||||
return roomid_ == "";
|
||||
return roomid_ == "";
|
||||
}
|
||||
|
||||
crypto::Trust
|
||||
UserProfile::getUserStatus()
|
||||
{
|
||||
return isUserVerified;
|
||||
return isUserVerified;
|
||||
}
|
||||
|
||||
bool
|
||||
UserProfile::userVerificationEnabled() const
|
||||
{
|
||||
return hasMasterKey;
|
||||
return hasMasterKey;
|
||||
}
|
||||
bool
|
||||
UserProfile::isSelf() const
|
||||
{
|
||||
return this->userid_ == utils::localUser();
|
||||
return this->userid_ == utils::localUser();
|
||||
}
|
||||
|
||||
void
|
||||
UserProfile::fetchDeviceList(const QString &userID)
|
||||
{
|
||||
auto localUser = utils::localUser();
|
||||
auto localUser = utils::localUser();
|
||||
|
||||
if (!cache::client() || !cache::client()->isDatabaseReady())
|
||||
return;
|
||||
if (!cache::client() || !cache::client()->isDatabaseReady())
|
||||
return;
|
||||
|
||||
cache::client()->query_keys(
|
||||
userID.toStdString(),
|
||||
[other_user_id = userID.toStdString(), this](const UserKeyCache &other_user_keys,
|
||||
mtx::http::RequestErr err) {
|
||||
if (err) {
|
||||
nhlog::net()->warn("failed to query device keys: {},{}",
|
||||
mtx::errors::to_string(err->matrix_error.errcode),
|
||||
static_cast<int>(err->status_code));
|
||||
return;
|
||||
}
|
||||
cache::client()->query_keys(
|
||||
userID.toStdString(),
|
||||
[other_user_id = userID.toStdString(), this](const UserKeyCache &other_user_keys,
|
||||
mtx::http::RequestErr err) {
|
||||
if (err) {
|
||||
nhlog::net()->warn("failed to query device keys: {},{}",
|
||||
mtx::errors::to_string(err->matrix_error.errcode),
|
||||
static_cast<int>(err->status_code));
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure local key cache is up to date
|
||||
cache::client()->query_keys(
|
||||
utils::localUser().toStdString(),
|
||||
[other_user_id, other_user_keys, this](const UserKeyCache &,
|
||||
mtx::http::RequestErr err) {
|
||||
using namespace mtx;
|
||||
std::string local_user_id = utils::localUser().toStdString();
|
||||
// Ensure local key cache is up to date
|
||||
cache::client()->query_keys(
|
||||
utils::localUser().toStdString(),
|
||||
[other_user_id, other_user_keys, this](const UserKeyCache &,
|
||||
mtx::http::RequestErr err) {
|
||||
using namespace mtx;
|
||||
std::string local_user_id = utils::localUser().toStdString();
|
||||
|
||||
if (err) {
|
||||
nhlog::net()->warn(
|
||||
"failed to query device keys: {},{}",
|
||||
mtx::errors::to_string(err->matrix_error.errcode),
|
||||
static_cast<int>(err->status_code));
|
||||
return;
|
||||
}
|
||||
if (err) {
|
||||
nhlog::net()->warn("failed to query device keys: {},{}",
|
||||
mtx::errors::to_string(err->matrix_error.errcode),
|
||||
static_cast<int>(err->status_code));
|
||||
return;
|
||||
}
|
||||
|
||||
this->hasMasterKey = !other_user_keys.master_keys.keys.empty();
|
||||
this->hasMasterKey = !other_user_keys.master_keys.keys.empty();
|
||||
|
||||
std::vector<DeviceInfo> deviceInfo;
|
||||
auto devices = other_user_keys.device_keys;
|
||||
auto verificationStatus =
|
||||
cache::client()->verificationStatus(other_user_id);
|
||||
std::vector<DeviceInfo> deviceInfo;
|
||||
auto devices = other_user_keys.device_keys;
|
||||
auto verificationStatus = cache::client()->verificationStatus(other_user_id);
|
||||
|
||||
isUserVerified = verificationStatus.user_verified;
|
||||
emit userStatusChanged();
|
||||
isUserVerified = verificationStatus.user_verified;
|
||||
emit userStatusChanged();
|
||||
|
||||
for (const auto &d : devices) {
|
||||
auto device = d.second;
|
||||
verification::Status verified =
|
||||
verification::Status::UNVERIFIED;
|
||||
for (const auto &d : devices) {
|
||||
auto device = d.second;
|
||||
verification::Status verified = verification::Status::UNVERIFIED;
|
||||
|
||||
if (std::find(verificationStatus.verified_devices.begin(),
|
||||
verificationStatus.verified_devices.end(),
|
||||
device.device_id) !=
|
||||
verificationStatus.verified_devices.end() &&
|
||||
mtx::crypto::verify_identity_signature(
|
||||
device,
|
||||
DeviceId(device.device_id),
|
||||
UserId(other_user_id)))
|
||||
verified = verification::Status::VERIFIED;
|
||||
if (std::find(verificationStatus.verified_devices.begin(),
|
||||
verificationStatus.verified_devices.end(),
|
||||
device.device_id) != verificationStatus.verified_devices.end() &&
|
||||
mtx::crypto::verify_identity_signature(
|
||||
device, DeviceId(device.device_id), UserId(other_user_id)))
|
||||
verified = verification::Status::VERIFIED;
|
||||
|
||||
deviceInfo.push_back(
|
||||
{QString::fromStdString(d.first),
|
||||
QString::fromStdString(
|
||||
device.unsigned_info.device_display_name),
|
||||
verified});
|
||||
}
|
||||
deviceInfo.push_back(
|
||||
{QString::fromStdString(d.first),
|
||||
QString::fromStdString(device.unsigned_info.device_display_name),
|
||||
verified});
|
||||
}
|
||||
|
||||
this->deviceList_.queueReset(std::move(deviceInfo));
|
||||
emit devicesChanged();
|
||||
});
|
||||
});
|
||||
this->deviceList_.queueReset(std::move(deviceInfo));
|
||||
emit devicesChanged();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
UserProfile::banUser()
|
||||
{
|
||||
ChatPage::instance()->banUser(this->userid_, "");
|
||||
ChatPage::instance()->banUser(this->userid_, "");
|
||||
}
|
||||
|
||||
// void ignoreUser(){
|
||||
|
|
@ -240,188 +230,180 @@ UserProfile::banUser()
|
|||
void
|
||||
UserProfile::kickUser()
|
||||
{
|
||||
ChatPage::instance()->kickUser(this->userid_, "");
|
||||
ChatPage::instance()->kickUser(this->userid_, "");
|
||||
}
|
||||
|
||||
void
|
||||
UserProfile::startChat()
|
||||
{
|
||||
ChatPage::instance()->startChat(this->userid_);
|
||||
ChatPage::instance()->startChat(this->userid_);
|
||||
}
|
||||
|
||||
void
|
||||
UserProfile::changeUsername(QString username)
|
||||
{
|
||||
if (isGlobalUserProfile()) {
|
||||
// change global
|
||||
http::client()->set_displayname(
|
||||
username.toStdString(), [](mtx::http::RequestErr err) {
|
||||
if (err) {
|
||||
nhlog::net()->warn("could not change username");
|
||||
return;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// change room username
|
||||
mtx::events::state::Member member;
|
||||
member.display_name = username.toStdString();
|
||||
member.avatar_url =
|
||||
cache::avatarUrl(roomid_,
|
||||
QString::fromStdString(http::client()->user_id().to_string()))
|
||||
.toStdString();
|
||||
member.membership = mtx::events::state::Membership::Join;
|
||||
if (isGlobalUserProfile()) {
|
||||
// change global
|
||||
http::client()->set_displayname(username.toStdString(), [](mtx::http::RequestErr err) {
|
||||
if (err) {
|
||||
nhlog::net()->warn("could not change username");
|
||||
return;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// change room username
|
||||
mtx::events::state::Member member;
|
||||
member.display_name = username.toStdString();
|
||||
member.avatar_url =
|
||||
cache::avatarUrl(roomid_, QString::fromStdString(http::client()->user_id().to_string()))
|
||||
.toStdString();
|
||||
member.membership = mtx::events::state::Membership::Join;
|
||||
|
||||
updateRoomMemberState(std::move(member));
|
||||
}
|
||||
updateRoomMemberState(std::move(member));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
UserProfile::verify(QString device)
|
||||
{
|
||||
if (!device.isEmpty())
|
||||
manager->verifyDevice(userid_, device);
|
||||
else {
|
||||
manager->verifyUser(userid_);
|
||||
}
|
||||
if (!device.isEmpty())
|
||||
manager->verifyDevice(userid_, device);
|
||||
else {
|
||||
manager->verifyUser(userid_);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
UserProfile::unverify(QString device)
|
||||
{
|
||||
cache::markDeviceUnverified(userid_.toStdString(), device.toStdString());
|
||||
cache::markDeviceUnverified(userid_.toStdString(), device.toStdString());
|
||||
}
|
||||
|
||||
void
|
||||
UserProfile::setGlobalUsername(const QString &globalUser)
|
||||
{
|
||||
globalUsername = globalUser;
|
||||
emit displayNameChanged();
|
||||
globalUsername = globalUser;
|
||||
emit displayNameChanged();
|
||||
}
|
||||
|
||||
void
|
||||
UserProfile::changeAvatar()
|
||||
{
|
||||
const QString picturesFolder =
|
||||
QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
|
||||
const QString fileName = QFileDialog::getOpenFileName(
|
||||
nullptr, tr("Select an avatar"), picturesFolder, tr("All Files (*)"));
|
||||
const QString picturesFolder =
|
||||
QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
|
||||
const QString fileName = QFileDialog::getOpenFileName(
|
||||
nullptr, tr("Select an avatar"), picturesFolder, tr("All Files (*)"));
|
||||
|
||||
if (fileName.isEmpty())
|
||||
return;
|
||||
if (fileName.isEmpty())
|
||||
return;
|
||||
|
||||
QMimeDatabase db;
|
||||
QMimeType mime = db.mimeTypeForFile(fileName, QMimeDatabase::MatchContent);
|
||||
QMimeDatabase db;
|
||||
QMimeType mime = db.mimeTypeForFile(fileName, QMimeDatabase::MatchContent);
|
||||
|
||||
const auto format = mime.name().split("/")[0];
|
||||
const auto format = mime.name().split("/")[0];
|
||||
|
||||
QFile file{fileName, this};
|
||||
if (format != "image") {
|
||||
emit displayError(tr("The selected file is not an image"));
|
||||
return;
|
||||
}
|
||||
QFile file{fileName, this};
|
||||
if (format != "image") {
|
||||
emit displayError(tr("The selected file is not an image"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
emit displayError(tr("Error while reading file: %1").arg(file.errorString()));
|
||||
return;
|
||||
}
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
emit displayError(tr("Error while reading file: %1").arg(file.errorString()));
|
||||
return;
|
||||
}
|
||||
|
||||
const auto bin = file.peek(file.size());
|
||||
const auto payload = std::string(bin.data(), bin.size());
|
||||
const auto bin = file.peek(file.size());
|
||||
const auto payload = std::string(bin.data(), bin.size());
|
||||
|
||||
isLoading_ = true;
|
||||
emit loadingChanged();
|
||||
isLoading_ = true;
|
||||
emit loadingChanged();
|
||||
|
||||
// First we need to create a new mxc URI
|
||||
// (i.e upload media to the Matrix content repository) for the new avatar.
|
||||
http::client()->upload(
|
||||
payload,
|
||||
mime.name().toStdString(),
|
||||
QFileInfo(fileName).fileName().toStdString(),
|
||||
[this,
|
||||
payload,
|
||||
mimetype = mime.name().toStdString(),
|
||||
size = payload.size(),
|
||||
room_id = roomid_.toStdString(),
|
||||
content = std::move(bin)](const mtx::responses::ContentURI &res,
|
||||
mtx::http::RequestErr err) {
|
||||
// First we need to create a new mxc URI
|
||||
// (i.e upload media to the Matrix content repository) for the new avatar.
|
||||
http::client()->upload(
|
||||
payload,
|
||||
mime.name().toStdString(),
|
||||
QFileInfo(fileName).fileName().toStdString(),
|
||||
[this,
|
||||
payload,
|
||||
mimetype = mime.name().toStdString(),
|
||||
size = payload.size(),
|
||||
room_id = roomid_.toStdString(),
|
||||
content = std::move(bin)](const mtx::responses::ContentURI &res, mtx::http::RequestErr err) {
|
||||
if (err) {
|
||||
nhlog::ui()->error("Failed to upload image", err->matrix_error.error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isGlobalUserProfile()) {
|
||||
http::client()->set_avatar_url(res.content_uri, [this](mtx::http::RequestErr err) {
|
||||
if (err) {
|
||||
nhlog::ui()->error("Failed to upload image", err->matrix_error.error);
|
||||
return;
|
||||
nhlog::ui()->error("Failed to set user avatar url", err->matrix_error.error);
|
||||
}
|
||||
|
||||
if (isGlobalUserProfile()) {
|
||||
http::client()->set_avatar_url(
|
||||
res.content_uri, [this](mtx::http::RequestErr err) {
|
||||
if (err) {
|
||||
nhlog::ui()->error("Failed to set user avatar url",
|
||||
err->matrix_error.error);
|
||||
}
|
||||
isLoading_ = false;
|
||||
emit loadingChanged();
|
||||
getGlobalProfileData();
|
||||
});
|
||||
} else {
|
||||
// change room username
|
||||
mtx::events::state::Member member;
|
||||
member.display_name = cache::displayName(roomid_, userid_).toStdString();
|
||||
member.avatar_url = res.content_uri;
|
||||
member.membership = mtx::events::state::Membership::Join;
|
||||
|
||||
isLoading_ = false;
|
||||
emit loadingChanged();
|
||||
getGlobalProfileData();
|
||||
});
|
||||
} else {
|
||||
// change room username
|
||||
mtx::events::state::Member member;
|
||||
member.display_name = cache::displayName(roomid_, userid_).toStdString();
|
||||
member.avatar_url = res.content_uri;
|
||||
member.membership = mtx::events::state::Membership::Join;
|
||||
|
||||
updateRoomMemberState(std::move(member));
|
||||
}
|
||||
});
|
||||
updateRoomMemberState(std::move(member));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
UserProfile::updateRoomMemberState(mtx::events::state::Member member)
|
||||
{
|
||||
http::client()->send_state_event(roomid_.toStdString(),
|
||||
http::client()->user_id().to_string(),
|
||||
member,
|
||||
[](mtx::responses::EventId, mtx::http::RequestErr err) {
|
||||
if (err)
|
||||
nhlog::net()->error(
|
||||
"Failed to update room member state : ",
|
||||
err->matrix_error.error);
|
||||
});
|
||||
http::client()->send_state_event(
|
||||
roomid_.toStdString(),
|
||||
http::client()->user_id().to_string(),
|
||||
member,
|
||||
[](mtx::responses::EventId, mtx::http::RequestErr err) {
|
||||
if (err)
|
||||
nhlog::net()->error("Failed to update room member state : ", err->matrix_error.error);
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
UserProfile::updateAvatarUrl()
|
||||
{
|
||||
isLoading_ = false;
|
||||
emit loadingChanged();
|
||||
isLoading_ = false;
|
||||
emit loadingChanged();
|
||||
|
||||
emit avatarUrlChanged();
|
||||
emit avatarUrlChanged();
|
||||
}
|
||||
|
||||
bool
|
||||
UserProfile::isLoading() const
|
||||
{
|
||||
return isLoading_;
|
||||
return isLoading_;
|
||||
}
|
||||
|
||||
void
|
||||
UserProfile::getGlobalProfileData()
|
||||
{
|
||||
http::client()->get_profile(
|
||||
userid_.toStdString(),
|
||||
[this](const mtx::responses::Profile &res, mtx::http::RequestErr err) {
|
||||
if (err) {
|
||||
nhlog::net()->warn("failed to retrieve profile info for {}",
|
||||
userid_.toStdString());
|
||||
return;
|
||||
}
|
||||
http::client()->get_profile(
|
||||
userid_.toStdString(), [this](const mtx::responses::Profile &res, mtx::http::RequestErr err) {
|
||||
if (err) {
|
||||
nhlog::net()->warn("failed to retrieve profile info for {}", userid_.toStdString());
|
||||
return;
|
||||
}
|
||||
|
||||
emit globalUsernameRetrieved(QString::fromStdString(res.display_name));
|
||||
globalAvatarUrl = QString::fromStdString(res.avatar_url);
|
||||
emit avatarUrlChanged();
|
||||
});
|
||||
emit globalUsernameRetrieved(QString::fromStdString(res.display_name));
|
||||
globalAvatarUrl = QString::fromStdString(res.avatar_url);
|
||||
emit avatarUrlChanged();
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
UserProfile::openGlobalProfile()
|
||||
{
|
||||
emit manager->openGlobalUserProfile(userid_);
|
||||
emit manager->openGlobalUserProfile(userid_);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,9 +18,9 @@ Q_NAMESPACE
|
|||
|
||||
enum Status
|
||||
{
|
||||
VERIFIED,
|
||||
UNVERIFIED,
|
||||
BLOCKED
|
||||
VERIFIED,
|
||||
UNVERIFIED,
|
||||
BLOCKED
|
||||
};
|
||||
Q_ENUM_NS(Status)
|
||||
}
|
||||
|
|
@ -32,128 +32,127 @@ class TimelineViewManager;
|
|||
class DeviceInfo
|
||||
{
|
||||
public:
|
||||
DeviceInfo(const QString deviceID,
|
||||
const QString displayName,
|
||||
verification::Status verification_status_)
|
||||
: device_id(deviceID)
|
||||
, display_name(displayName)
|
||||
, verification_status(verification_status_)
|
||||
{}
|
||||
DeviceInfo()
|
||||
: verification_status(verification::UNVERIFIED)
|
||||
{}
|
||||
DeviceInfo(const QString deviceID,
|
||||
const QString displayName,
|
||||
verification::Status verification_status_)
|
||||
: device_id(deviceID)
|
||||
, display_name(displayName)
|
||||
, verification_status(verification_status_)
|
||||
{}
|
||||
DeviceInfo()
|
||||
: verification_status(verification::UNVERIFIED)
|
||||
{}
|
||||
|
||||
QString device_id;
|
||||
QString display_name;
|
||||
QString device_id;
|
||||
QString display_name;
|
||||
|
||||
verification::Status verification_status;
|
||||
verification::Status verification_status;
|
||||
};
|
||||
|
||||
class DeviceInfoModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Roles
|
||||
{
|
||||
DeviceId,
|
||||
DeviceName,
|
||||
VerificationStatus,
|
||||
};
|
||||
enum Roles
|
||||
{
|
||||
DeviceId,
|
||||
DeviceName,
|
||||
VerificationStatus,
|
||||
};
|
||||
|
||||
explicit DeviceInfoModel(QObject *parent = nullptr)
|
||||
{
|
||||
(void)parent;
|
||||
connect(this, &DeviceInfoModel::queueReset, this, &DeviceInfoModel::reset);
|
||||
};
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override
|
||||
{
|
||||
(void)parent;
|
||||
return (int)deviceList_.size();
|
||||
}
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
explicit DeviceInfoModel(QObject *parent = nullptr)
|
||||
{
|
||||
(void)parent;
|
||||
connect(this, &DeviceInfoModel::queueReset, this, &DeviceInfoModel::reset);
|
||||
};
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override
|
||||
{
|
||||
(void)parent;
|
||||
return (int)deviceList_.size();
|
||||
}
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
signals:
|
||||
void queueReset(const std::vector<DeviceInfo> &deviceList);
|
||||
void queueReset(const std::vector<DeviceInfo> &deviceList);
|
||||
public slots:
|
||||
void reset(const std::vector<DeviceInfo> &deviceList);
|
||||
void reset(const std::vector<DeviceInfo> &deviceList);
|
||||
|
||||
private:
|
||||
std::vector<DeviceInfo> deviceList_;
|
||||
std::vector<DeviceInfo> deviceList_;
|
||||
|
||||
friend class UserProfile;
|
||||
friend class UserProfile;
|
||||
};
|
||||
|
||||
class UserProfile : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString displayName READ displayName NOTIFY displayNameChanged)
|
||||
Q_PROPERTY(QString userid READ userid CONSTANT)
|
||||
Q_PROPERTY(QString avatarUrl READ avatarUrl NOTIFY avatarUrlChanged)
|
||||
Q_PROPERTY(DeviceInfoModel *deviceList READ deviceList NOTIFY devicesChanged)
|
||||
Q_PROPERTY(bool isGlobalUserProfile READ isGlobalUserProfile CONSTANT)
|
||||
Q_PROPERTY(int userVerified READ getUserStatus NOTIFY userStatusChanged)
|
||||
Q_PROPERTY(bool isLoading READ isLoading NOTIFY loadingChanged)
|
||||
Q_PROPERTY(
|
||||
bool userVerificationEnabled READ userVerificationEnabled NOTIFY userStatusChanged)
|
||||
Q_PROPERTY(bool isSelf READ isSelf CONSTANT)
|
||||
Q_PROPERTY(TimelineModel *room READ room CONSTANT)
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString displayName READ displayName NOTIFY displayNameChanged)
|
||||
Q_PROPERTY(QString userid READ userid CONSTANT)
|
||||
Q_PROPERTY(QString avatarUrl READ avatarUrl NOTIFY avatarUrlChanged)
|
||||
Q_PROPERTY(DeviceInfoModel *deviceList READ deviceList NOTIFY devicesChanged)
|
||||
Q_PROPERTY(bool isGlobalUserProfile READ isGlobalUserProfile CONSTANT)
|
||||
Q_PROPERTY(int userVerified READ getUserStatus NOTIFY userStatusChanged)
|
||||
Q_PROPERTY(bool isLoading READ isLoading NOTIFY loadingChanged)
|
||||
Q_PROPERTY(bool userVerificationEnabled READ userVerificationEnabled NOTIFY userStatusChanged)
|
||||
Q_PROPERTY(bool isSelf READ isSelf CONSTANT)
|
||||
Q_PROPERTY(TimelineModel *room READ room CONSTANT)
|
||||
public:
|
||||
UserProfile(QString roomid,
|
||||
QString userid,
|
||||
TimelineViewManager *manager_,
|
||||
TimelineModel *parent = nullptr);
|
||||
UserProfile(QString roomid,
|
||||
QString userid,
|
||||
TimelineViewManager *manager_,
|
||||
TimelineModel *parent = nullptr);
|
||||
|
||||
DeviceInfoModel *deviceList();
|
||||
DeviceInfoModel *deviceList();
|
||||
|
||||
QString userid();
|
||||
QString displayName();
|
||||
QString avatarUrl();
|
||||
bool isGlobalUserProfile() const;
|
||||
crypto::Trust getUserStatus();
|
||||
bool userVerificationEnabled() const;
|
||||
bool isSelf() const;
|
||||
bool isLoading() const;
|
||||
TimelineModel *room() const { return model; }
|
||||
QString userid();
|
||||
QString displayName();
|
||||
QString avatarUrl();
|
||||
bool isGlobalUserProfile() const;
|
||||
crypto::Trust getUserStatus();
|
||||
bool userVerificationEnabled() const;
|
||||
bool isSelf() const;
|
||||
bool isLoading() const;
|
||||
TimelineModel *room() const { return model; }
|
||||
|
||||
Q_INVOKABLE void verify(QString device = "");
|
||||
Q_INVOKABLE void unverify(QString device = "");
|
||||
Q_INVOKABLE void fetchDeviceList(const QString &userID);
|
||||
Q_INVOKABLE void banUser();
|
||||
// Q_INVOKABLE void ignoreUser();
|
||||
Q_INVOKABLE void kickUser();
|
||||
Q_INVOKABLE void startChat();
|
||||
Q_INVOKABLE void changeUsername(QString username);
|
||||
Q_INVOKABLE void changeAvatar();
|
||||
Q_INVOKABLE void openGlobalProfile();
|
||||
Q_INVOKABLE void verify(QString device = "");
|
||||
Q_INVOKABLE void unverify(QString device = "");
|
||||
Q_INVOKABLE void fetchDeviceList(const QString &userID);
|
||||
Q_INVOKABLE void banUser();
|
||||
// Q_INVOKABLE void ignoreUser();
|
||||
Q_INVOKABLE void kickUser();
|
||||
Q_INVOKABLE void startChat();
|
||||
Q_INVOKABLE void changeUsername(QString username);
|
||||
Q_INVOKABLE void changeAvatar();
|
||||
Q_INVOKABLE void openGlobalProfile();
|
||||
|
||||
signals:
|
||||
void userStatusChanged();
|
||||
void loadingChanged();
|
||||
void displayNameChanged();
|
||||
void avatarUrlChanged();
|
||||
void displayError(const QString &errorMessage);
|
||||
void globalUsernameRetrieved(const QString &globalUser);
|
||||
void devicesChanged();
|
||||
void userStatusChanged();
|
||||
void loadingChanged();
|
||||
void displayNameChanged();
|
||||
void avatarUrlChanged();
|
||||
void displayError(const QString &errorMessage);
|
||||
void globalUsernameRetrieved(const QString &globalUser);
|
||||
void devicesChanged();
|
||||
|
||||
public slots:
|
||||
void updateAvatarUrl();
|
||||
void updateAvatarUrl();
|
||||
|
||||
protected slots:
|
||||
void setGlobalUsername(const QString &globalUser);
|
||||
void setGlobalUsername(const QString &globalUser);
|
||||
|
||||
private:
|
||||
void updateRoomMemberState(mtx::events::state::Member member);
|
||||
void getGlobalProfileData();
|
||||
void updateRoomMemberState(mtx::events::state::Member member);
|
||||
void getGlobalProfileData();
|
||||
|
||||
private:
|
||||
QString roomid_, userid_;
|
||||
QString globalUsername;
|
||||
QString globalAvatarUrl;
|
||||
DeviceInfoModel deviceList_;
|
||||
crypto::Trust isUserVerified = crypto::Trust::Unverified;
|
||||
bool hasMasterKey = false;
|
||||
bool isLoading_ = false;
|
||||
TimelineViewManager *manager;
|
||||
TimelineModel *model;
|
||||
QString roomid_, userid_;
|
||||
QString globalUsername;
|
||||
QString globalAvatarUrl;
|
||||
DeviceInfoModel deviceList_;
|
||||
crypto::Trust isUserVerified = crypto::Trust::Unverified;
|
||||
bool hasMasterKey = false;
|
||||
bool isLoading_ = false;
|
||||
TimelineViewManager *manager;
|
||||
TimelineModel *model;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue