1 #pragma once
2 
3 #include "common/Aliases.hpp"
4 #include "common/Channel.hpp"
5 #include "common/NullablePtr.hpp"
6 #include "pajlada/signals/signalholder.hpp"
7 #include "widgets/BaseWidget.hpp"
8 
9 #include <QFont>
10 #include <QShortcut>
11 #include <QVBoxLayout>
12 #include <QWidget>
13 
14 namespace chatterino {
15 
16 class ChannelView;
17 class SplitHeader;
18 class SplitInput;
19 class SplitContainer;
20 class SplitOverlay;
21 class SelectChannelDialog;
22 
23 // Each ChatWidget consists of three sub-elements that handle their own part of
24 // the chat widget: ChatWidgetHeader
25 //   - Responsible for rendering which channel the ChatWidget is in, and the
26 //   menu in the top-left of
27 //     the chat widget
28 // ChatWidgetView
29 //   - Responsible for rendering all chat messages, and the scrollbar
30 // ChatWidgetInput
31 //   - Responsible for rendering and handling user text input
32 //
33 // Each sub-element has a reference to the parent Chat Widget
34 class Split : public BaseWidget, pajlada::Signals::SignalHolder
35 {
36     friend class SplitInput;
37 
38     Q_OBJECT
39 
40 public:
41     explicit Split(QWidget *parent);
42 
43     ~Split() override;
44 
45     pajlada::Signals::NoArgSignal channelChanged;
46     pajlada::Signals::NoArgSignal focused;
47     pajlada::Signals::NoArgSignal focusLost;
48 
49     ChannelView &getChannelView();
50     SplitInput &getInput();
51 
52     IndirectChannel getIndirectChannel();
53     ChannelPtr getChannel();
54     void setChannel(IndirectChannel newChannel);
55 
56     void setFilters(const QList<QUuid> ids);
57     const QList<QUuid> getFilters() const;
58 
59     void setModerationMode(bool value);
60     bool getModerationMode() const;
61 
62     void insertTextToInput(const QString &text);
63 
64     void showChangeChannelPopup(const char *dialogTitle, bool empty,
65                                 std::function<void(bool)> callback);
66     void giveFocus(Qt::FocusReason reason);
67     bool hasFocus() const;
68     void updateGifEmotes();
69     void updateLastReadMessage();
70     void setIsTopRightSplit(bool value);
71 
72     void drag();
73 
74     bool isInContainer() const;
75 
76     void setContainer(SplitContainer *container);
77 
78     static pajlada::Signals::Signal<Qt::KeyboardModifiers>
79         modifierStatusChanged;
80     static Qt::KeyboardModifiers modifierStatus;
81 
82     enum class Action {
83         RefreshTab,
84         ResetMouseStatus,
85         AppendNewSplit,
86         Delete,
87 
88         SelectSplitLeft,
89         SelectSplitRight,
90         SelectSplitAbove,
91         SelectSplitBelow,
92     };
93 
94     pajlada::Signals::Signal<Action> actionRequested;
95     pajlada::Signals::Signal<ChannelPtr> openSplitRequested;
96 
97     // args: (SplitContainer::Direction dir, Split* parent)
98     pajlada::Signals::Signal<int, Split *> insertSplitRequested;
99 
100 protected:
101     void paintEvent(QPaintEvent *event) override;
102     void mouseMoveEvent(QMouseEvent *event) override;
103     void keyPressEvent(QKeyEvent *event) override;
104     void keyReleaseEvent(QKeyEvent *event) override;
105     void resizeEvent(QResizeEvent *event) override;
106     void enterEvent(QEvent *event) override;
107     void leaveEvent(QEvent *event) override;
108     void focusInEvent(QFocusEvent *event) override;
109 
110     void dragEnterEvent(QDragEnterEvent *event) override;
111     void dropEvent(QDropEvent *event) override;
112 
113 private:
114     void channelNameUpdated(const QString &newChannelName);
115     void handleModifiers(Qt::KeyboardModifiers modifiers);
116     void updateInputPlaceholder();
117 
118     /**
119      * @brief Opens twitch channel stream in a browser player (opens a formatted link)
120      */
121     void openChannelInBrowserPlayer(ChannelPtr channel);
122     /**
123      * @brief Opens twitch channel stream in streamlink app (if stream is live and streamlink is installed)
124      */
125     void openChannelInStreamlink(QString channelName);
126     /**
127      * @brief Opens twitch channel chat in a new chatterino tab
128      */
129     void joinChannelInNewTab(ChannelPtr channel);
130 
131     IndirectChannel channel_;
132 
133     bool moderationMode_{};
134     bool isTopRightSplit_{};
135 
136     bool isMouseOver_{};
137     bool isDragging_{};
138 
139     QVBoxLayout *vbox_;
140     SplitHeader *header_;
141     ChannelView *view_;
142     SplitInput *input_;
143     SplitOverlay *overlay_;
144 
145     NullablePtr<SelectChannelDialog> selectChannelDialog_;
146 
147     pajlada::Signals::Connection channelIDChangedConnection_;
148     pajlada::Signals::Connection usermodeChangedConnection_;
149     pajlada::Signals::Connection roomModeChangedConnection_;
150 
151     pajlada::Signals::Connection indirectChannelChangedConnection_;
152     pajlada::Signals::SignalHolder signalHolder_;
153 
154     std::vector<pajlada::Signals::ScopedConnection> managedConnections_;
155 
156 public slots:
157     void addSibling();
158     void deleteFromContainer();
159     void changeChannel();
160     void explainMoving();
161     void explainSplitting();
162     void popup();
163     void clear();
164     void openInBrowser();
165     void openModViewInBrowser();
166     void openWhispersInBrowser();
167     void openBrowserPlayer();
168     void openInStreamlink();
169     void openWithCustomScheme();
170     void copyToClipboard();
171     void setFiltersDialog();
172     void showSearch();
173     void showViewerList();
174     void openSubPage();
175     void reloadChannelAndSubscriberEmotes();
176     void reconnect();
177 };
178 
179 }  // namespace chatterino
180