1 /*
2 Drawpile - a collaborative drawing program.
3
4 Copyright (C) 2019 Calle Laakkonen
5
6 Drawpile is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 Drawpile is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Drawpile. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "chatbox.h"
21 #include "chatwidget.h"
22 #include "chatwindow.h"
23 #include "useritemdelegate.h"
24 #include "document.h"
25 #include "canvas/canvasmodel.h"
26 #include "canvas/userlist.h"
27 #include "net/client.h"
28
29 #include <QResizeEvent>
30 #include <QSplitter>
31 #include <QListView>
32 #include <QVBoxLayout>
33 #include <QMetaObject>
34
35 namespace widgets {
36
ChatBox(Document * doc,QWidget * parent)37 ChatBox::ChatBox(Document *doc, QWidget *parent)
38 : QWidget(parent)
39 {
40 QSplitter *chatsplitter = new QSplitter(Qt::Horizontal, this);
41 chatsplitter->setChildrenCollapsible(false);
42 m_chatWidget = new ChatWidget(this);
43 chatsplitter->addWidget(m_chatWidget);
44
45 m_userList = new QListView(this);
46 m_userList->setSelectionMode(QListView::NoSelection);
47 m_userItemDelegate = new UserItemDelegate(this);
48 m_userItemDelegate->setDocument(doc);
49 m_userList->setItemDelegate(m_userItemDelegate);
50 chatsplitter->addWidget(m_userList);
51
52 chatsplitter->setStretchFactor(0, 5);
53 chatsplitter->setStretchFactor(1, 1);
54
55 auto *layout = new QVBoxLayout;
56 layout->addWidget(chatsplitter);
57 layout->setMargin(0);
58 setLayout(layout);
59
60 connect(m_chatWidget, &ChatWidget::message, this, &ChatBox::message);
61 connect(m_chatWidget, &ChatWidget::detachRequested, this, &ChatBox::detachFromParent);
62
63 connect(doc, &Document::canvasChanged, this, &ChatBox::onCanvasChanged);
64 connect(doc, &Document::serverLoggedIn, this, &ChatBox::onServerLogin);
65
66 connect(doc, &Document::sessionPreserveChatChanged, m_chatWidget, &ChatWidget::setPreserveMode);
67 connect(doc->client(), &net::Client::serverMessage, m_chatWidget, &ChatWidget::systemMessage);
68 connect(doc->client(), &net::Client::youWereKicked, m_chatWidget, &ChatWidget::kicked);
69
70 connect(m_userItemDelegate, &widgets::UserItemDelegate::opCommand, doc->client(), &net::Client::sendMessage);
71 connect(m_userItemDelegate, &widgets::UserItemDelegate::requestPrivateChat, m_chatWidget, &ChatWidget::openPrivateChat);
72 }
73
onCanvasChanged(canvas::CanvasModel * canvas)74 void ChatBox::onCanvasChanged(canvas::CanvasModel *canvas)
75 {
76 m_userList->setModel(canvas->userlist()->onlineUsers());
77 m_chatWidget->setUserList(canvas->userlist());
78
79 connect(canvas, &canvas::CanvasModel::chatMessageReceived, m_chatWidget, &ChatWidget::receiveMessage);
80 connect(canvas, &canvas::CanvasModel::markerMessageReceived, m_chatWidget, &ChatWidget::receiveMarker);
81 connect(canvas, &canvas::CanvasModel::userJoined, m_chatWidget, &ChatWidget::userJoined);
82 connect(canvas, &canvas::CanvasModel::userLeft, m_chatWidget, &ChatWidget::userParted);
83 }
84
onServerLogin()85 void ChatBox::onServerLogin()
86 {
87 m_chatWidget->loggedIn(static_cast<Document*>(sender())->client()->myId());
88 }
89
focusInput()90 void ChatBox::focusInput()
91 {
92 m_chatWidget->focusInput();
93 }
94
detachFromParent()95 void ChatBox::detachFromParent()
96 {
97 if(!parent() || qobject_cast<ChatWindow*>(parent()))
98 return;
99
100 m_state = State::Detached;
101
102 const auto siz = size();
103
104 QObject *oldParent = parent();
105
106 m_chatWidget->setAttached(false);
107
108 auto *window = new ChatWindow(this);
109 connect(window, &ChatWindow::closing, this, &ChatBox::reattachNowPlease);
110 connect(window, &ChatWindow::closing, this, &ChatBox::reattachToParent);
111 connect(oldParent, &QObject::destroyed, window, &QObject::deleteLater);
112
113 window->show();
114 window->resize(siz);
115 }
116
reattachToParent()117 void ChatBox::reattachToParent()
118 {
119 m_state = State::Expanded;
120 m_chatWidget->setAttached(true);
121 }
122
resizeEvent(QResizeEvent * event)123 void ChatBox::resizeEvent(QResizeEvent *event)
124 {
125 QWidget::resizeEvent(event);
126 if(event->size().height() == 0) {
127 if(m_state == State::Expanded) {
128 emit expandedChanged(false);
129 m_state = State::Collapsed;
130 }
131
132 } else if(m_state == State::Collapsed) {
133 m_state = State::Expanded;
134 emit expandedChanged(true);
135 }
136 }
137
138 }
139