mirror-chatterino2/src/widgets/notebookpage.cpp

357 lines
8.8 KiB
C++
Raw Normal View History

2017-06-11 09:31:45 +02:00
#include "widgets/notebookpage.hpp"
#include "colorscheme.hpp"
#include "widgets/chatwidget.hpp"
#include "widgets/notebook.hpp"
2017-06-11 09:31:45 +02:00
#include "widgets/notebooktab.hpp"
2016-12-29 17:31:07 +01:00
#include <QDebug>
2017-01-18 04:52:47 +01:00
#include <QHBoxLayout>
#include <QMimeData>
2017-01-29 12:26:22 +01:00
#include <QObject>
2017-01-18 04:52:47 +01:00
#include <QPainter>
#include <QVBoxLayout>
#include <QWidget>
#include <boost/foreach.hpp>
2017-01-18 04:52:47 +01:00
2017-04-14 17:52:22 +02:00
namespace chatterino {
namespace widgets {
2017-01-18 21:30:23 +01:00
2017-01-01 02:30:42 +01:00
bool NotebookPage::isDraggingSplit = false;
2017-06-10 22:48:28 +02:00
ChatWidget *NotebookPage::draggingSplit = nullptr;
2017-01-01 02:30:42 +01:00
std::pair<int, int> NotebookPage::dropPosition = std::pair<int, int>(-1, -1);
NotebookPage::NotebookPage(ChannelManager &_channelManager, Notebook *parent, NotebookTab *_tab)
: BaseWidget(parent->colorScheme, parent)
, channelManager(_channelManager)
, tab(_tab)
2017-04-12 17:46:44 +02:00
, _parentbox(this)
, _chatWidgets()
, _preview(this)
2016-12-29 17:31:07 +01:00
{
2016-12-30 18:00:25 +01:00
tab->page = this;
2017-01-01 02:30:42 +01:00
setHidden(true);
setAcceptDrops(true);
2017-04-12 17:46:44 +02:00
_parentbox.addSpacing(2);
_parentbox.addLayout(&_hbox);
_parentbox.setMargin(0);
2017-01-01 02:30:42 +01:00
2017-04-12 17:46:44 +02:00
_hbox.setSpacing(1);
_hbox.setMargin(0);
2017-01-01 02:30:42 +01:00
}
2017-04-12 17:46:44 +02:00
const std::vector<ChatWidget *> &NotebookPage::getChatWidgets() const
2017-01-01 02:30:42 +01:00
{
2017-04-12 17:46:44 +02:00
return _chatWidgets;
}
NotebookTab *NotebookPage::getTab() const
{
return this->tab;
2017-04-12 17:46:44 +02:00
}
void NotebookPage::addChat(bool openChannelNameDialog)
2017-05-29 21:26:55 +02:00
{
ChatWidget *w = this->createChatWidget();
2017-05-29 21:26:55 +02:00
if (openChannelNameDialog) {
w->showChangeChannelPopup();
}
addToLayout(w, std::pair<int, int>(-1, -1));
}
2017-04-12 17:46:44 +02:00
std::pair<int, int> NotebookPage::removeFromLayout(ChatWidget *widget)
{
// remove from chatWidgets vector
for (auto it = _chatWidgets.begin(); it != _chatWidgets.end(); ++it) {
if (*it == widget) {
2017-04-12 17:46:44 +02:00
_chatWidgets.erase(it);
break;
}
}
2017-04-12 17:46:44 +02:00
// remove from box and return location
for (int i = 0; i < _hbox.count(); ++i) {
auto vbox = static_cast<QVBoxLayout *>(_hbox.itemAt(i));
2017-01-01 02:30:42 +01:00
2017-01-11 18:52:09 +01:00
for (int j = 0; j < vbox->count(); ++j) {
2017-04-12 17:46:44 +02:00
if (vbox->itemAt(j)->widget() != widget) {
2017-01-11 18:52:09 +01:00
continue;
2017-04-12 17:46:44 +02:00
}
2017-01-01 02:30:42 +01:00
2017-06-10 22:48:28 +02:00
widget->setParent(nullptr);
2017-01-01 02:30:42 +01:00
bool isLastItem = vbox->count() == 0;
2017-01-11 18:52:09 +01:00
if (isLastItem) {
2017-04-12 17:46:44 +02:00
_hbox.removeItem(vbox);
2017-01-01 02:30:42 +01:00
delete vbox;
}
2017-01-11 18:52:09 +01:00
return std::pair<int, int>(i, isLastItem ? -1 : j);
2017-01-01 02:30:42 +01:00
}
}
return std::pair<int, int>(-1, -1);
}
2017-04-12 17:46:44 +02:00
void NotebookPage::addToLayout(ChatWidget *widget,
std::pair<int, int> position = std::pair<int, int>(-1, -1))
2017-01-01 02:30:42 +01:00
{
2017-04-12 17:46:44 +02:00
_chatWidgets.push_back(widget);
2017-01-01 02:30:42 +01:00
// add vbox at the end
2017-04-12 17:46:44 +02:00
if (position.first < 0 || position.first >= _hbox.count()) {
2017-01-01 02:30:42 +01:00
auto vbox = new QVBoxLayout();
vbox->addWidget(widget);
2017-04-12 17:46:44 +02:00
_hbox.addLayout(vbox, 1);
2017-01-01 02:30:42 +01:00
return;
}
// insert vbox
2017-01-11 18:52:09 +01:00
if (position.second == -1) {
2017-01-01 02:30:42 +01:00
auto vbox = new QVBoxLayout();
vbox->addWidget(widget);
2017-04-12 17:46:44 +02:00
_hbox.insertLayout(position.first, vbox, 1);
2017-01-01 02:30:42 +01:00
return;
}
// add to existing vbox
2017-04-12 17:46:44 +02:00
auto vbox = static_cast<QVBoxLayout *>(_hbox.itemAt(position.first));
2017-01-01 02:30:42 +01:00
2017-04-12 17:46:44 +02:00
vbox->insertWidget(std::max(0, std::min(vbox->count(), position.second)), widget);
2017-01-01 02:30:42 +01:00
}
2017-04-12 17:46:44 +02:00
void NotebookPage::enterEvent(QEvent *)
{
2017-04-12 17:46:44 +02:00
if (_hbox.count() == 0) {
this->setCursor(QCursor(Qt::PointingHandCursor));
2017-01-11 18:52:09 +01:00
} else {
this->setCursor(QCursor(Qt::ArrowCursor));
}
}
2017-04-12 17:46:44 +02:00
void NotebookPage::leaveEvent(QEvent *)
{
}
2017-04-12 17:46:44 +02:00
void NotebookPage::mouseReleaseEvent(QMouseEvent *event)
{
2017-04-12 17:46:44 +02:00
if (_hbox.count() == 0 && event->button() == Qt::LeftButton) {
2017-01-29 11:38:00 +01:00
// "Add Chat" was clicked
this->addToLayout(this->createChatWidget(), std::pair<int, int>(-1, -1));
this->setCursor(QCursor(Qt::ArrowCursor));
}
}
2017-04-12 17:46:44 +02:00
void NotebookPage::dragEnterEvent(QDragEnterEvent *event)
2017-01-01 02:30:42 +01:00
{
2017-01-11 18:52:09 +01:00
if (!event->mimeData()->hasFormat("chatterino/split"))
return;
2017-01-01 02:30:42 +01:00
2017-01-11 18:52:09 +01:00
if (isDraggingSplit) {
2017-04-12 17:46:44 +02:00
return;
}
_dropRegions.clear();
if (_hbox.count() == 0) {
_dropRegions.push_back(DropRegion(rect(), std::pair<int, int>(-1, -1)));
} else {
for (int i = 0; i < _hbox.count() + 1; ++i) {
_dropRegions.push_back(DropRegion(QRect(((i * 4 - 1) * width() / _hbox.count()) / 4, 0,
width() / _hbox.count() / 2 + 1, height() + 1),
std::pair<int, int>(i, -1)));
}
2017-01-01 02:30:42 +01:00
2017-04-12 17:46:44 +02:00
for (int i = 0; i < _hbox.count(); ++i) {
auto vbox = static_cast<QVBoxLayout *>(_hbox.itemAt(i));
2017-04-12 17:46:44 +02:00
for (int j = 0; j < vbox->count() + 1; ++j) {
_dropRegions.push_back(DropRegion(
QRect(i * width() / _hbox.count(), ((j * 2 - 1) * height() / vbox->count()) / 2,
width() / _hbox.count() + 1, height() / vbox->count() + 1),
2017-01-24 19:51:57 +01:00
2017-04-12 17:46:44 +02:00
std::pair<int, int>(i, j)));
2017-01-01 02:30:42 +01:00
}
}
2017-04-12 17:46:44 +02:00
}
2017-01-01 02:30:42 +01:00
2017-04-12 17:46:44 +02:00
setPreviewRect(event->pos());
2017-01-01 02:30:42 +01:00
2017-04-12 17:46:44 +02:00
event->acceptProposedAction();
2017-01-01 02:30:42 +01:00
}
2017-04-12 17:46:44 +02:00
void NotebookPage::dragMoveEvent(QDragMoveEvent *event)
2017-01-01 02:30:42 +01:00
{
setPreviewRect(event->pos());
}
2017-04-12 17:46:44 +02:00
void NotebookPage::setPreviewRect(QPoint mousePos)
2017-01-01 02:30:42 +01:00
{
2017-04-12 17:46:44 +02:00
for (DropRegion region : _dropRegions) {
2017-01-11 18:52:09 +01:00
if (region.rect.contains(mousePos)) {
2017-04-12 17:46:44 +02:00
_preview.setBounds(region.rect);
2017-01-24 19:51:57 +01:00
2017-04-12 17:46:44 +02:00
if (!_preview.isVisible()) {
_preview.show();
_preview.raise();
2017-01-24 19:51:57 +01:00
}
2017-01-01 02:30:42 +01:00
dropPosition = region.position;
return;
}
}
2017-01-24 19:51:57 +01:00
2017-04-12 17:46:44 +02:00
_preview.hide();
2017-01-01 02:30:42 +01:00
}
2017-04-12 17:46:44 +02:00
void NotebookPage::dragLeaveEvent(QDragLeaveEvent *event)
2017-01-01 02:30:42 +01:00
{
2017-04-12 17:46:44 +02:00
_preview.hide();
2017-01-01 02:30:42 +01:00
}
2017-04-12 17:46:44 +02:00
void NotebookPage::dropEvent(QDropEvent *event)
2017-01-01 02:30:42 +01:00
{
2017-01-11 18:52:09 +01:00
if (isDraggingSplit) {
2017-01-01 02:30:42 +01:00
event->acceptProposedAction();
NotebookPage::draggingSplit->setParent(this);
addToLayout(NotebookPage::draggingSplit, dropPosition);
}
2017-04-12 17:46:44 +02:00
_preview.hide();
2016-12-30 18:00:25 +01:00
}
2017-04-12 17:46:44 +02:00
void NotebookPage::paintEvent(QPaintEvent *)
2016-12-30 18:00:25 +01:00
{
QPainter painter(this);
2017-04-12 17:46:44 +02:00
if (_hbox.count() == 0) {
painter.fillRect(rect(), this->colorScheme.ChatBackground);
2017-01-01 02:30:42 +01:00
painter.fillRect(0, 0, width(), 2, this->colorScheme.TabSelectedBackground);
2017-01-01 02:30:42 +01:00
painter.setPen(this->colorScheme.Text);
painter.drawText(rect(), "Add Chat", QTextOption(Qt::AlignCenter));
2017-01-11 18:52:09 +01:00
} else {
painter.fillRect(rect(), this->colorScheme.TabSelectedBackground);
2016-12-30 18:00:25 +01:00
painter.fillRect(0, 0, width(), 2, this->colorScheme.TabSelectedBackground);
}
2016-12-29 17:31:07 +01:00
}
2017-04-12 17:46:44 +02:00
static std::pair<int, int> getWidgetPositionInLayout(QLayout *layout, const ChatWidget *chatWidget)
2017-01-29 12:26:22 +01:00
{
for (int i = 0; i < layout->count(); ++i) {
printf("xD\n");
}
return std::make_pair(-1, -1);
}
2017-04-12 17:46:44 +02:00
std::pair<int, int> NotebookPage::getChatPosition(const ChatWidget *chatWidget)
2017-01-29 12:26:22 +01:00
{
2017-04-12 17:46:44 +02:00
auto layout = _hbox.layout();
2017-01-29 12:26:22 +01:00
if (layout == nullptr) {
return std::make_pair(-1, -1);
}
return getWidgetPositionInLayout(layout, chatWidget);
}
ChatWidget *NotebookPage::createChatWidget()
{
return new ChatWidget(this->channelManager, this);
}
2017-04-12 17:46:44 +02:00
void NotebookPage::load(const boost::property_tree::ptree &tree)
{
2017-01-29 11:38:00 +01:00
try {
2017-01-29 12:26:22 +01:00
int column = 0;
for (const auto &v : tree.get_child("columns.")) {
int row = 0;
for (const auto &innerV : v.second.get_child("")) {
auto widget = this->createChatWidget();
2017-01-29 12:26:22 +01:00
widget->load(innerV.second);
2017-04-12 17:46:44 +02:00
addToLayout(widget, std::pair<int, int>(column, row));
2017-01-29 12:26:22 +01:00
++row;
}
++column;
2017-01-29 11:38:00 +01:00
}
} catch (boost::property_tree::ptree_error &) {
// can't read tabs
}
}
2017-04-12 17:46:44 +02:00
static void saveFromLayout(QLayout *layout, boost::property_tree::ptree &tree)
2017-01-29 12:26:22 +01:00
{
for (int i = 0; i < layout->count(); ++i) {
auto item = layout->itemAt(i);
auto innerLayout = item->layout();
if (innerLayout != nullptr) {
boost::property_tree::ptree innerLayoutTree;
saveFromLayout(innerLayout, innerLayoutTree);
if (innerLayoutTree.size() > 0) {
tree.push_back(std::make_pair("", innerLayoutTree));
}
continue;
}
auto widget = item->widget();
if (widget == nullptr) {
// This layoutitem does not manage a widget for some reason
continue;
}
ChatWidget *chatWidget = qobject_cast<ChatWidget *>(widget);
if (chatWidget != nullptr) {
boost::property_tree::ptree chat = chatWidget->save();
tree.push_back(std::make_pair("", chat));
continue;
}
}
}
2017-04-12 17:46:44 +02:00
boost::property_tree::ptree NotebookPage::save()
2017-01-29 11:38:00 +01:00
{
boost::property_tree::ptree tree;
2017-04-12 17:46:44 +02:00
auto layout = _hbox.layout();
2017-01-29 12:26:22 +01:00
saveFromLayout(layout, tree);
/*
2017-04-12 17:46:44 +02:00
for (const auto &chat : chatWidgets) {
2017-01-29 11:38:00 +01:00
boost::property_tree::ptree child = chat->save();
2017-01-29 12:26:22 +01:00
// Set child position
child.put("position", "5,3");
2017-01-29 11:38:00 +01:00
tree.push_back(std::make_pair("", child));
}
2017-01-29 12:26:22 +01:00
*/
2017-01-29 11:38:00 +01:00
return tree;
2017-01-18 21:30:23 +01:00
}
2017-04-14 17:52:22 +02:00
} // namespace widgets
} // namespace chatterino