forked from mirror/nheko
Add placeholder UI for showing replies in the text entry widget. Existing quoting capability has been removed (Temporarily), as it was replaced with the new reply capability. Replies sent from nheko do not currently appear correctly in the timeline (this will be fixed in a future commit).remotes/origin/0.7.0-dev
parent
b9dde957a8
commit
9159b9ce22
@ -0,0 +1,83 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include <QHBoxLayout> |
||||||
|
#include <QLabel> |
||||||
|
#include <QPoint> |
||||||
|
#include <QWidget> |
||||||
|
|
||||||
|
#include "../AvatarProvider.h" |
||||||
|
#include "../Cache.h" |
||||||
|
#include "../ChatPage.h" |
||||||
|
|
||||||
|
class Avatar; |
||||||
|
struct SearchResult; |
||||||
|
|
||||||
|
class PopupItem : public QWidget |
||||||
|
{ |
||||||
|
Q_OBJECT |
||||||
|
|
||||||
|
Q_PROPERTY(QColor hoverColor READ hoverColor WRITE setHoverColor) |
||||||
|
Q_PROPERTY(bool hovering READ hovering WRITE setHovering) |
||||||
|
|
||||||
|
public: |
||||||
|
PopupItem(QWidget *parent); |
||||||
|
|
||||||
|
QString selectedText() const { return QString(); } |
||||||
|
QColor hoverColor() const { return hoverColor_; } |
||||||
|
void setHoverColor(QColor &color) { hoverColor_ = color; } |
||||||
|
|
||||||
|
bool hovering() const { return hovering_; } |
||||||
|
void setHovering(const bool hover) { hovering_ = hover; }; |
||||||
|
|
||||||
|
protected: |
||||||
|
void paintEvent(QPaintEvent *event) override; |
||||||
|
|
||||||
|
signals: |
||||||
|
void clicked(const QString &text); |
||||||
|
|
||||||
|
protected: |
||||||
|
QHBoxLayout *topLayout_; |
||||||
|
Avatar *avatar_; |
||||||
|
QColor hoverColor_; |
||||||
|
|
||||||
|
//! Set if the item is currently being
|
||||||
|
//! hovered during tab completion (cycling).
|
||||||
|
bool hovering_; |
||||||
|
}; |
||||||
|
|
||||||
|
class UserItem : public PopupItem |
||||||
|
{ |
||||||
|
Q_OBJECT |
||||||
|
|
||||||
|
public: |
||||||
|
UserItem(QWidget *parent, const QString &user_id); |
||||||
|
QString selectedText() const { return userId_; } |
||||||
|
void updateItem(const QString &user_id); |
||||||
|
|
||||||
|
protected: |
||||||
|
void mousePressEvent(QMouseEvent *event) override; |
||||||
|
|
||||||
|
private: |
||||||
|
void resolveAvatar(const QString &user_id); |
||||||
|
|
||||||
|
QLabel *userName_; |
||||||
|
QString userId_; |
||||||
|
}; |
||||||
|
|
||||||
|
class RoomItem : public PopupItem |
||||||
|
{ |
||||||
|
Q_OBJECT |
||||||
|
|
||||||
|
public: |
||||||
|
RoomItem(QWidget *parent, const RoomSearchResult &res); |
||||||
|
QString selectedText() const { return roomId_; } |
||||||
|
void updateItem(const RoomSearchResult &res); |
||||||
|
|
||||||
|
protected: |
||||||
|
void mousePressEvent(QMouseEvent *event) override; |
||||||
|
|
||||||
|
private: |
||||||
|
QLabel *roomName_; |
||||||
|
QString roomId_; |
||||||
|
RoomSearchResult info_; |
||||||
|
}; |
@ -0,0 +1,60 @@ |
|||||||
|
#include <QPaintEvent> |
||||||
|
#include <QLabel> |
||||||
|
#include <QPainter> |
||||||
|
#include <QStyleOption> |
||||||
|
|
||||||
|
#include "../Config.h" |
||||||
|
#include "../Utils.h" |
||||||
|
#include "../ui/Avatar.h" |
||||||
|
#include "../ui/DropShadow.h" |
||||||
|
#include "ReplyPopup.h" |
||||||
|
|
||||||
|
ReplyPopup::ReplyPopup(QWidget *parent) |
||||||
|
: QWidget(parent) |
||||||
|
{ |
||||||
|
setAttribute(Qt::WA_ShowWithoutActivating, true); |
||||||
|
setWindowFlags(Qt::ToolTip | Qt::NoDropShadowWindowHint); |
||||||
|
|
||||||
|
layout_ = new QVBoxLayout(this); |
||||||
|
layout_->setMargin(0); |
||||||
|
layout_->setSpacing(0); |
||||||
|
} |
||||||
|
|
||||||
|
void |
||||||
|
ReplyPopup::setReplyContent(const QString &user, const QString &msg, const QString &srcEvent) |
||||||
|
{ |
||||||
|
QLayoutItem *child; |
||||||
|
while ((child = layout_->takeAt(0)) != 0) { |
||||||
|
delete child->widget(); |
||||||
|
delete child; |
||||||
|
} |
||||||
|
// Create a new widget if there isn't already one in that
|
||||||
|
// layout position.
|
||||||
|
// if (!item) {
|
||||||
|
auto userItem = new UserItem(this, user); |
||||||
|
auto *text = new QLabel(this); |
||||||
|
text->setText(msg); |
||||||
|
auto *event = new QLabel(this); |
||||||
|
event->setText(srcEvent); |
||||||
|
connect(userItem, &UserItem::clicked, this, &ReplyPopup::userSelected); |
||||||
|
layout_->addWidget(userItem); |
||||||
|
layout_->addWidget(text); |
||||||
|
layout_->addWidget(event); |
||||||
|
// } else {
|
||||||
|
// Update the current widget with the new data.
|
||||||
|
// auto userWidget = qobject_cast<UserItem *>(item->widget());
|
||||||
|
// if (userWidget)
|
||||||
|
// userWidget->updateItem(users.at(i).user_id);
|
||||||
|
// }
|
||||||
|
|
||||||
|
adjustSize(); |
||||||
|
} |
||||||
|
|
||||||
|
void |
||||||
|
ReplyPopup::paintEvent(QPaintEvent *) |
||||||
|
{ |
||||||
|
QStyleOption opt; |
||||||
|
opt.init(this); |
||||||
|
QPainter p(this); |
||||||
|
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); |
||||||
|
} |
@ -0,0 +1,32 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include <QHBoxLayout> |
||||||
|
#include <QLabel> |
||||||
|
#include <QPoint> |
||||||
|
#include <QWidget> |
||||||
|
|
||||||
|
#include "../AvatarProvider.h" |
||||||
|
#include "../Cache.h" |
||||||
|
#include "../ChatPage.h" |
||||||
|
#include "PopupItem.h" |
||||||
|
|
||||||
|
class ReplyPopup : public QWidget |
||||||
|
{ |
||||||
|
Q_OBJECT |
||||||
|
|
||||||
|
public: |
||||||
|
explicit ReplyPopup(QWidget *parent = nullptr); |
||||||
|
|
||||||
|
public slots: |
||||||
|
void setReplyContent(const QString &user, const QString &msg, const QString &srcEvent); |
||||||
|
|
||||||
|
protected: |
||||||
|
void paintEvent(QPaintEvent *event) override; |
||||||
|
|
||||||
|
signals: |
||||||
|
void userSelected(const QString &user); |
||||||
|
|
||||||
|
private: |
||||||
|
QVBoxLayout *layout_; |
||||||
|
|
||||||
|
}; |
@ -0,0 +1,156 @@ |
|||||||
|
#include <QPaintEvent> |
||||||
|
#include <QPainter> |
||||||
|
#include <QStyleOption> |
||||||
|
|
||||||
|
#include "../Config.h" |
||||||
|
#include "SuggestionsPopup.h" |
||||||
|
#include "../Utils.h" |
||||||
|
#include "../ui/Avatar.h" |
||||||
|
#include "../ui/DropShadow.h" |
||||||
|
|
||||||
|
SuggestionsPopup::SuggestionsPopup(QWidget *parent) |
||||||
|
: QWidget(parent) |
||||||
|
{ |
||||||
|
setAttribute(Qt::WA_ShowWithoutActivating, true); |
||||||
|
setWindowFlags(Qt::ToolTip | Qt::NoDropShadowWindowHint); |
||||||
|
|
||||||
|
layout_ = new QVBoxLayout(this); |
||||||
|
layout_->setMargin(0); |
||||||
|
layout_->setSpacing(0); |
||||||
|
} |
||||||
|
|
||||||
|
void |
||||||
|
SuggestionsPopup::addRooms(const std::vector<RoomSearchResult> &rooms) |
||||||
|
{ |
||||||
|
if (rooms.empty()) { |
||||||
|
hide(); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
const size_t layoutCount = layout_->count(); |
||||||
|
const size_t roomCount = rooms.size(); |
||||||
|
|
||||||
|
// Remove the extra widgets from the layout.
|
||||||
|
if (roomCount < layoutCount) |
||||||
|
removeLayoutItemsAfter(roomCount - 1); |
||||||
|
|
||||||
|
for (size_t i = 0; i < roomCount; ++i) { |
||||||
|
auto item = layout_->itemAt(i); |
||||||
|
|
||||||
|
// Create a new widget if there isn't already one in that
|
||||||
|
// layout position.
|
||||||
|
if (!item) { |
||||||
|
auto room = new RoomItem(this, rooms.at(i)); |
||||||
|
connect(room, &RoomItem::clicked, this, &SuggestionsPopup::itemSelected); |
||||||
|
layout_->addWidget(room); |
||||||
|
} else { |
||||||
|
// Update the current widget with the new data.
|
||||||
|
auto room = qobject_cast<RoomItem *>(item->widget()); |
||||||
|
if (room) |
||||||
|
room->updateItem(rooms.at(i)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
resetSelection(); |
||||||
|
adjustSize(); |
||||||
|
|
||||||
|
resize(geometry().width(), 40 * rooms.size()); |
||||||
|
|
||||||
|
selectNextSuggestion(); |
||||||
|
} |
||||||
|
|
||||||
|
void |
||||||
|
SuggestionsPopup::addUsers(const QVector<SearchResult> &users) |
||||||
|
{ |
||||||
|
if (users.isEmpty()) { |
||||||
|
hide(); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
const size_t layoutCount = layout_->count(); |
||||||
|
const size_t userCount = users.size(); |
||||||
|
|
||||||
|
// Remove the extra widgets from the layout.
|
||||||
|
if (userCount < layoutCount) |
||||||
|
removeLayoutItemsAfter(userCount - 1); |
||||||
|
|
||||||
|
for (size_t i = 0; i < userCount; ++i) { |
||||||
|
auto item = layout_->itemAt(i); |
||||||
|
|
||||||
|
// Create a new widget if there isn't already one in that
|
||||||
|
// layout position.
|
||||||
|
if (!item) { |
||||||
|
auto user = new UserItem(this, users.at(i).user_id); |
||||||
|
connect(user, &UserItem::clicked, this, &SuggestionsPopup::itemSelected); |
||||||
|
layout_->addWidget(user); |
||||||
|
} else { |
||||||
|
// Update the current widget with the new data.
|
||||||
|
auto userWidget = qobject_cast<UserItem *>(item->widget()); |
||||||
|
if (userWidget) |
||||||
|
userWidget->updateItem(users.at(i).user_id); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
resetSelection(); |
||||||
|
adjustSize(); |
||||||
|
|
||||||
|
selectNextSuggestion(); |
||||||
|
} |
||||||
|
|
||||||
|
void |
||||||
|
SuggestionsPopup::hoverSelection() |
||||||
|
{ |
||||||
|
resetHovering(); |
||||||
|
setHovering(selectedItem_); |
||||||
|
update(); |
||||||
|
} |
||||||
|
|
||||||
|
void |
||||||
|
SuggestionsPopup::selectNextSuggestion() |
||||||
|
{ |
||||||
|
selectedItem_++; |
||||||
|
if (selectedItem_ >= layout_->count()) |
||||||
|
selectFirstItem(); |
||||||
|
|
||||||
|
hoverSelection(); |
||||||
|
} |
||||||
|
|
||||||
|
void |
||||||
|
SuggestionsPopup::selectPreviousSuggestion() |
||||||
|
{ |
||||||
|
selectedItem_--; |
||||||
|
if (selectedItem_ < 0) |
||||||
|
selectLastItem(); |
||||||
|
|
||||||
|
hoverSelection(); |
||||||
|
} |
||||||
|
|
||||||
|
void |
||||||
|
SuggestionsPopup::resetHovering() |
||||||
|
{ |
||||||
|
for (int i = 0; i < layout_->count(); ++i) { |
||||||
|
const auto item = qobject_cast<PopupItem *>(layout_->itemAt(i)->widget()); |
||||||
|
|
||||||
|
if (item) |
||||||
|
item->setHovering(false); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void |
||||||
|
SuggestionsPopup::setHovering(int pos) |
||||||
|
{ |
||||||
|
const auto &item = layout_->itemAt(pos); |
||||||
|
const auto &widget = qobject_cast<PopupItem *>(item->widget()); |
||||||
|
|
||||||
|
if (widget) |
||||||
|
widget->setHovering(true); |
||||||
|
} |
||||||
|
|
||||||
|
void |
||||||
|
SuggestionsPopup::paintEvent(QPaintEvent *) |
||||||
|
{ |
||||||
|
QStyleOption opt; |
||||||
|
opt.init(this); |
||||||
|
QPainter p(this); |
||||||
|
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); |
||||||
|
} |
Loading…
Reference in new issue