diff --git a/tools/chatgui/src/channeldelegate.cpp b/tools/chatgui/src/channeldelegate.cpp index b0be4612..03a11075 100644 --- a/tools/chatgui/src/channeldelegate.cpp +++ b/tools/chatgui/src/channeldelegate.cpp @@ -12,6 +12,13 @@ QRect ChannelDelegate::inviteButtonRect(const QRect &itemRect) { InviteBtnSize, InviteBtnSize); } +QRect ChannelDelegate::inviteByLinkButtonRect(const QRect &itemRect) { + const int margin = 6; + return QRect(itemRect.right() - margin - InviteBtnSize * 2 - InviteBtnGap, + itemRect.bottom() - margin - InviteBtnSize, + InviteBtnSize, InviteBtnSize); +} + void ChannelDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { painter->save(); @@ -169,6 +176,29 @@ void ChannelDelegate::paint(QPainter *painter, const QStyleOptionViewItem &optio painter->drawLine(plusRect.left() + 5, plusRect.center().y(), plusRect.right() - 5, plusRect.center().y()); + /* ── invite-by-link button (left of plus, orange square with arrow) ── */ + QRect invRect = inviteByLinkButtonRect(option.rect); + bool invHovered = index.data(ChannelInviteByLinkBtnHoveredRole).toInt() != 0; + painter->setRenderHint(QPainter::Antialiasing); + if (invHovered) { + painter->setBrush(QColor(0xE6, 0x7E, 0x22)); + painter->setPen(Qt::NoPen); + painter->drawRoundedRect(invRect, 3, 3); + painter->setPen(QPen(Qt::white, 1.5)); + } else { + painter->setBrush(QColor(0xE6, 0x7E, 0x22, 110)); + painter->setPen(Qt::NoPen); + painter->drawRoundedRect(invRect, 3, 3); + painter->setPen(QPen(QColor(0xE6, 0x7E, 0x22), 1.5)); + } + /* arrow pointing into a box: →| or a simple arrow-left: ← */ + int cx = invRect.center().x(), cy = invRect.center().y(); + int dx = 3; + painter->drawLine(cx + dx, cy - 3, cx - dx, cy); + painter->drawLine(cx + dx, cy + 3, cx - dx, cy); + painter->drawLine(cx + dx + 1, cy, cx + dx + 1, cy - 3 + 1); + painter->drawLine(cx + dx + 1, cy, cx + dx + 1, cy + 3 - 1); + painter->restore(); } diff --git a/tools/chatgui/src/channeldelegate.h b/tools/chatgui/src/channeldelegate.h index 2be95c15..ebeef847 100644 --- a/tools/chatgui/src/channeldelegate.h +++ b/tools/chatgui/src/channeldelegate.h @@ -10,6 +10,7 @@ enum ChannelDataRole { ChannelPeersOnlineRole = Qt::UserRole + 3, /* int: count of online peers */ ChannelAutoConnectActiveRole = Qt::UserRole + 4, /* bool: 1 if auto-connect in progress */ ChannelInviteBtnHoveredRole = Qt::UserRole + 5, /* bool: 1 when mouse hovers invite button */ + ChannelInviteByLinkBtnHoveredRole = Qt::UserRole + 8, /* bool: hover for invite-by-link button */ ChannelUnreadCountRole = Qt::UserRole + 6, /* int: unread message count, 0 if none */ ChannelLastMsgAtRole = Qt::UserRole + 7 /* qint64: last message timestamp for sorting */ }; @@ -25,5 +26,7 @@ public: const QModelIndex &index) const override; static constexpr int InviteBtnSize = 18; + static constexpr int InviteBtnGap = 2; static QRect inviteButtonRect(const QRect &itemRect); + static QRect inviteByLinkButtonRect(const QRect &itemRect); }; diff --git a/tools/chatgui/src/channellist.cpp b/tools/chatgui/src/channellist.cpp index 878e653b..f152969c 100644 --- a/tools/chatgui/src/channellist.cpp +++ b/tools/chatgui/src/channellist.cpp @@ -19,13 +19,19 @@ class ChannelListView : public QListView { public: using QListView::QListView; -signals: + signals: void inviteClicked(const QString& channelId); + void inviteByLinkClicked(const QString& channelId); protected: void mousePressEvent(QMouseEvent* e) override { QModelIndex idx = indexAt(e->pos()); if (!idx.isValid()) return; + QRect invRect = ChannelDelegate::inviteByLinkButtonRect(visualRect(idx)); + if (invRect.contains(e->pos())) { + emit inviteByLinkClicked(idx.data(ChannelChannelIdRole).toString()); + return; + } QRect plusRect = ChannelDelegate::inviteButtonRect(visualRect(idx)); if (plusRect.contains(e->pos())) { emit inviteClicked(idx.data(ChannelChannelIdRole).toString()); @@ -34,19 +40,28 @@ protected: QListView::mousePressEvent(e); } void mouseMoveEvent(QMouseEvent* e) override { - int prevRow = m_hoveredInviteRow; + int prevInv = m_hoveredInviteRow; + int prevInvBy = m_hoveredInviteByLinkRow; m_hoveredInviteRow = -1; + m_hoveredInviteByLinkRow = -1; QModelIndex idx = indexAt(e->pos()); if (idx.isValid()) { + QRect invRect = ChannelDelegate::inviteByLinkButtonRect(visualRect(idx)); QRect plusRect = ChannelDelegate::inviteButtonRect(visualRect(idx)); - if (plusRect.contains(e->pos())) + if (invRect.contains(e->pos())) + m_hoveredInviteByLinkRow = idx.row(); + else if (plusRect.contains(e->pos())) m_hoveredInviteRow = idx.row(); } - if (m_hoveredInviteRow != prevRow) { - model()->setData(model()->index(prevRow, 0), 0, ChannelInviteBtnHoveredRole); + if (m_hoveredInviteRow != prevInv) + model()->setData(model()->index(prevInv, 0), 0, ChannelInviteBtnHoveredRole); + if (m_hoveredInviteRow >= 0) model()->setData(model()->index(m_hoveredInviteRow, 0), 1, ChannelInviteBtnHoveredRole); - } - setCursor(m_hoveredInviteRow >= 0 ? Qt::PointingHandCursor : Qt::ArrowCursor); + if (m_hoveredInviteByLinkRow != prevInvBy) + model()->setData(model()->index(prevInvBy, 0), 0, ChannelInviteByLinkBtnHoveredRole); + if (m_hoveredInviteByLinkRow >= 0) + model()->setData(model()->index(m_hoveredInviteByLinkRow, 0), 1, ChannelInviteByLinkBtnHoveredRole); + setCursor((m_hoveredInviteRow >= 0 || m_hoveredInviteByLinkRow >= 0) ? Qt::PointingHandCursor : Qt::ArrowCursor); QListView::mouseMoveEvent(e); } QItemSelectionModel::SelectionFlags selectionCommand(const QModelIndex& idx, const QEvent* e) const override { @@ -63,6 +78,7 @@ protected: private: int m_hoveredInviteRow = -1; + int m_hoveredInviteByLinkRow = -1; }; static QIcon makeChannelIcon(const QColor &color, const QString &letter) { @@ -134,20 +150,6 @@ ChannelList::ChannelList(DbManager* db, QWidget *parent) connect(createBtn, &QPushButton::clicked, this, [this] { emit createGroupRequested(); }); fl->addWidget(createBtn); - auto *inviteBtn = new QPushButton("INV", footer); - inviteBtn->setFixedSize(36, 28); - inviteBtn->setToolTip(QString::fromUtf8("Пригласить в канал по ссылке")); - inviteBtn->setStyleSheet( - "QPushButton { border: 1.5px solid #E67E22; border-radius: 6px;" - " font-size: 11px; font-weight: bold; color: #E67E22; background: transparent; }" - "QPushButton:hover { background: #E67E22; color: white; }"); - connect(inviteBtn, &QPushButton::clicked, this, [this] { - QModelIndex cur = m_listView->currentIndex(); - if (cur.isValid()) - emit inviteByLinkRequested(cur.data(ChannelChannelIdRole).toString()); - }); - fl->addWidget(inviteBtn); - auto *plusBtn = new QPushButton("+", footer); plusBtn->setFixedSize(28, 28); plusBtn->setToolTip(QString::fromUtf8("Присоединиться")); @@ -169,6 +171,8 @@ ChannelList::ChannelList(DbManager* db, QWidget *parent) }); connect(static_cast(m_listView), &ChannelListView::inviteClicked, this, &ChannelList::inviteRequested); + connect(static_cast(m_listView), &ChannelListView::inviteByLinkClicked, + this, &ChannelList::inviteByLinkRequested); } void ChannelList::loadChannels() {