diff --git a/CHANGELOG.md b/CHANGELOG.md index f2bc1ea2d..e21c44a4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -97,6 +97,7 @@ - Dev: Load less message history upon reconnects. (#5001) - Dev: BREAKING: Replace custom `import()` with normal Lua `require()`. (#5014) - Dev: Fixed most compiler warnings. (#5028) +- Dev: Added the ability to show `ChannelView`s without a `Split`. (#4747) ## 2.4.6 diff --git a/src/widgets/dialogs/EmotePopup.cpp b/src/widgets/dialogs/EmotePopup.cpp index 0c9aebe30..6e8983927 100644 --- a/src/widgets/dialogs/EmotePopup.cpp +++ b/src/widgets/dialogs/EmotePopup.cpp @@ -240,7 +240,7 @@ EmotePopup::EmotePopup(QWidget *parent) }; auto makeView = [&](QString tabTitle, bool addToNotebook = true) { - auto *view = new ChannelView(); + auto *view = new ChannelView(nullptr); view->setOverrideFlags(MessageElementFlags{ MessageElementFlag::Default, MessageElementFlag::AlwaysShow, diff --git a/src/widgets/helper/ChannelView.cpp b/src/widgets/helper/ChannelView.cpp index da3d3367f..474ff55c3 100644 --- a/src/widgets/helper/ChannelView.cpp +++ b/src/widgets/helper/ChannelView.cpp @@ -277,8 +277,22 @@ std::pair getWordBounds(MessageLayout *layout, namespace chatterino { -ChannelView::ChannelView(BaseWidget *parent, Split *split, Context context, +ChannelView::ChannelView(QWidget *parent, Context context, size_t messagesLimit) + : ChannelView(InternalCtor{}, parent, nullptr, context, messagesLimit) +{ +} + +ChannelView::ChannelView(QWidget *parent, Split *split, Context context, size_t messagesLimit) + : ChannelView(InternalCtor{}, parent, split, context, messagesLimit) +{ + assert(parent != nullptr && split != nullptr && + "This constructor should only be used with non-null values (see " + "documentation)"); +} + +ChannelView::ChannelView(InternalCtor /*tag*/, QWidget *parent, Split *split, + Context context, size_t messagesLimit) : BaseWidget(parent) , split_(split) , scrollBar_(new Scrollbar(messagesLimit, this)) @@ -1347,7 +1361,10 @@ bool ChannelView::scrollToMessage(const MessagePtr &message) } this->scrollToMessageLayout(messagesSnapshot[messageIdx].get(), messageIdx); - getApp()->windows->select(this->split_); + if (this->split_) + { + getApp()->windows->select(this->split_); + } return true; } @@ -1376,7 +1393,10 @@ bool ChannelView::scrollToMessageId(const QString &messageId) } this->scrollToMessageLayout(messagesSnapshot[messageIdx].get(), messageIdx); - getApp()->windows->select(this->split_); + if (this->split_) + { + getApp()->windows->select(this->split_); + } return true; } @@ -2349,7 +2369,7 @@ void ChannelView::addMessageContextMenuItems(QMenu *menu, bool isSearch = this->context_ == Context::Search; bool isReplyOrUserCard = (this->context_ == Context::ReplyThread || this->context_ == Context::UserCard) && - this->split_; + this->split_ != nullptr; bool isMentions = this->channel()->getType() == Channel::Type::TwitchMentions; bool isAutomod = this->channel()->getType() == Channel::Type::TwitchAutomod; @@ -2580,7 +2600,14 @@ void ChannelView::hideEvent(QHideEvent * /*event*/) void ChannelView::showUserInfoPopup(const QString &userName, QString alternativePopoutChannel) { - assert(this->split_ != nullptr); + if (!this->split_) + { + qCWarning(chatterinoCommon) + << "Tried to show user info for" << userName + << "but the channel view doesn't belong to a split."; + return; + } + auto *userPopup = new UserInfoPopup(getSettings()->autoCloseUserPopup, this->split_); @@ -2879,7 +2906,9 @@ void ChannelView::scrollUpdateRequested() void ChannelView::setInputReply(const MessagePtr &message) { - if (message == nullptr) + assertInGuiThread(); + + if (message == nullptr || this->split_ == nullptr) { return; } @@ -2917,6 +2946,14 @@ void ChannelView::showReplyThreadPopup(const MessagePtr &message) return; } + if (!this->split_) + { + qCWarning(chatterinoCommon) + << "Tried to show reply thread popup but the " + "channel view doesn't belong to a split."; + return; + } + auto *popup = new ReplyThreadPopup(getSettings()->autoCloseThreadPopup, this->split_); diff --git a/src/widgets/helper/ChannelView.hpp b/src/widgets/helper/ChannelView.hpp index 08da3ae06..71b439540 100644 --- a/src/widgets/helper/ChannelView.hpp +++ b/src/widgets/helper/ChannelView.hpp @@ -75,7 +75,23 @@ public: Search, }; - explicit ChannelView(BaseWidget *parent = nullptr, Split *split = nullptr, + /// Creates a channel view without a split. + /// In such a view, usercards and reply-threads can't be opened. + /// + /// @param parent The parent of this widget. Can be `nullptr`. + /// @param context The context in which this view is shown (e.g. as a usercard). + /// @param messagesLimit The maximum amount of messages this view will display. + explicit ChannelView(QWidget *parent, Context context = Context::None, + size_t messagesLimit = 1000); + + /// Creates a channel view in a split. + /// + /// @param parent The parent of this widget. + /// @param split The split containing this widget. + /// @a split must be in the widget tree of @a parent. + /// @param context The context in which this view is shown (e.g. as a usercard). + /// @param messagesLimit The maximum amount of messages this view will display. + explicit ChannelView(QWidget *parent, Split *split, Context context = Context::None, size_t messagesLimit = 1000); @@ -192,6 +208,12 @@ protected: QPoint &relativePos, int &index); private: + struct InternalCtor { + }; + + ChannelView(InternalCtor tag, QWidget *parent, Split *split, + Context context, size_t messagesLimit); + void initializeLayout(); void initializeScrollbar(); void initializeSignals(); @@ -270,7 +292,7 @@ private: ChannelPtr channel_ = nullptr; ChannelPtr underlyingChannel_ = nullptr; ChannelPtr sourceChannel_ = nullptr; - Split *split_ = nullptr; + Split *split_; Scrollbar *scrollBar_; EffectLabel *goToBottom_{};