2021-03-03 09:24:35 +00:00
|
|
|
/*
|
|
|
|
This file is part of Telegram Desktop,
|
|
|
|
the official desktop application for the Telegram messaging service.
|
|
|
|
|
|
|
|
For license and copyright information please follow this link:
|
|
|
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|
|
|
*/
|
|
|
|
#include "editor/scene.h"
|
|
|
|
|
|
|
|
#include "editor/scene_item_canvas.h"
|
|
|
|
#include "editor/scene_item_line.h"
|
2021-03-14 09:46:17 +00:00
|
|
|
#include "editor/scene_item_sticker.h"
|
2021-03-03 09:24:35 +00:00
|
|
|
#include "ui/rp_widget.h"
|
|
|
|
|
|
|
|
#include <QGraphicsSceneMouseEvent>
|
|
|
|
|
|
|
|
namespace Editor {
|
2021-03-08 16:31:48 +00:00
|
|
|
namespace {
|
|
|
|
|
2021-03-10 15:51:23 +00:00
|
|
|
using ItemPtr = Scene::ItemPtr;
|
|
|
|
|
2021-03-08 16:31:48 +00:00
|
|
|
bool SkipMouseEvent(not_null<QGraphicsSceneMouseEvent*> event) {
|
|
|
|
return event->isAccepted() || (event->button() == Qt::RightButton);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace
|
2021-03-03 09:24:35 +00:00
|
|
|
|
|
|
|
Scene::Scene(const QRectF &rect)
|
|
|
|
: QGraphicsScene(rect)
|
2021-03-10 15:51:23 +00:00
|
|
|
, _canvas(std::make_shared<ItemCanvas>()) {
|
|
|
|
QGraphicsScene::addItem(_canvas.get());
|
2021-03-08 16:31:48 +00:00
|
|
|
_canvas->clearPixmap();
|
|
|
|
|
|
|
|
_canvas->grabContentRequests(
|
|
|
|
) | rpl::start_with_next([=](ItemCanvas::Content &&content) {
|
2021-03-10 15:51:23 +00:00
|
|
|
const auto item = std::make_shared<ItemLine>(
|
|
|
|
std::move(content.pixmap));
|
2021-03-08 16:31:48 +00:00
|
|
|
item->setPos(content.position);
|
|
|
|
addItem(item);
|
|
|
|
_canvas->setZValue(++_lastLineZ);
|
2021-03-03 09:24:35 +00:00
|
|
|
}, _lifetime);
|
|
|
|
}
|
|
|
|
|
2021-03-10 15:51:23 +00:00
|
|
|
void Scene::addItem(std::shared_ptr<NumberedItem> item) {
|
|
|
|
if (!item) {
|
|
|
|
return;
|
|
|
|
}
|
2021-03-14 09:44:49 +00:00
|
|
|
item->setNumber(_itemNumber++);
|
2021-03-10 15:51:23 +00:00
|
|
|
QGraphicsScene::addItem(item.get());
|
|
|
|
_items.push_back(std::move(item));
|
2021-03-08 16:31:48 +00:00
|
|
|
_addsItem.fire({});
|
2021-03-14 09:44:49 +00:00
|
|
|
}
|
|
|
|
|
2021-03-10 15:51:23 +00:00
|
|
|
void Scene::removeItem(not_null<QGraphicsItem*> item) {
|
|
|
|
const auto it = ranges::find_if(_items, [&](const ItemPtr &i) {
|
|
|
|
return i.get() == item;
|
|
|
|
});
|
|
|
|
if (it == end(_items)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
removeItem(*it);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Scene::removeItem(const ItemPtr &item) {
|
|
|
|
_items.erase(ranges::remove(_items, item), end(_items));
|
|
|
|
}
|
|
|
|
|
2021-03-03 09:24:35 +00:00
|
|
|
void Scene::mousePressEvent(QGraphicsSceneMouseEvent *event) {
|
|
|
|
QGraphicsScene::mousePressEvent(event);
|
2021-03-08 16:31:48 +00:00
|
|
|
if (SkipMouseEvent(event)) {
|
2021-03-03 09:24:35 +00:00
|
|
|
return;
|
|
|
|
}
|
2021-03-08 16:31:48 +00:00
|
|
|
_canvas->handleMousePressEvent(event);
|
2021-03-03 09:24:35 +00:00
|
|
|
_mousePresses.fire({});
|
|
|
|
}
|
|
|
|
|
|
|
|
void Scene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
|
|
|
|
QGraphicsScene::mouseReleaseEvent(event);
|
2021-03-08 16:31:48 +00:00
|
|
|
if (SkipMouseEvent(event)) {
|
2021-03-03 09:24:35 +00:00
|
|
|
return;
|
|
|
|
}
|
2021-03-08 16:31:48 +00:00
|
|
|
_canvas->handleMouseReleaseEvent(event);
|
2021-03-03 09:24:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Scene::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
|
|
|
|
QGraphicsScene::mouseMoveEvent(event);
|
2021-03-08 16:31:48 +00:00
|
|
|
if (SkipMouseEvent(event)) {
|
2021-03-03 09:24:35 +00:00
|
|
|
return;
|
|
|
|
}
|
2021-03-08 16:31:48 +00:00
|
|
|
_canvas->handleMouseMoveEvent(event);
|
2021-03-03 09:24:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Scene::applyBrush(const QColor &color, float size) {
|
2021-03-08 16:31:48 +00:00
|
|
|
_canvas->applyBrush(color, size);
|
2021-03-03 09:24:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
rpl::producer<> Scene::mousePresses() const {
|
|
|
|
return _mousePresses.events();
|
|
|
|
}
|
|
|
|
|
2021-03-08 16:31:48 +00:00
|
|
|
rpl::producer<> Scene::addsItem() const {
|
|
|
|
return _addsItem.events();
|
|
|
|
}
|
|
|
|
|
2021-03-10 15:51:23 +00:00
|
|
|
std::vector<ItemPtr> Scene::items(
|
|
|
|
Qt::SortOrder order) const {
|
|
|
|
auto copyItems = _items;
|
2021-03-14 09:44:49 +00:00
|
|
|
|
2021-03-10 15:51:23 +00:00
|
|
|
ranges::sort(copyItems, [&](ItemPtr a, ItemPtr b) {
|
|
|
|
const auto numA = qgraphicsitem_cast<NumberedItem*>(
|
|
|
|
a.get())->number();
|
|
|
|
const auto numB = qgraphicsitem_cast<NumberedItem*>(
|
|
|
|
b.get())->number();
|
2021-03-14 09:44:49 +00:00
|
|
|
return (order == Qt::AscendingOrder) ? (numA < numB) : (numA > numB);
|
|
|
|
});
|
|
|
|
|
2021-03-10 15:51:23 +00:00
|
|
|
return copyItems;
|
2021-03-14 09:44:49 +00:00
|
|
|
}
|
|
|
|
|
2021-03-14 09:46:17 +00:00
|
|
|
std::vector<MTPInputDocument> Scene::attachedStickers() const {
|
|
|
|
const auto allItems = items();
|
|
|
|
|
|
|
|
return ranges::views::all(
|
|
|
|
allItems
|
2021-03-10 15:51:23 +00:00
|
|
|
) | ranges::views::filter([](const ItemPtr &i) {
|
2021-03-14 09:46:17 +00:00
|
|
|
return i->isVisible() && (i->type() == ItemSticker::Type);
|
2021-03-10 15:51:23 +00:00
|
|
|
}) | ranges::views::transform([](const ItemPtr &i) {
|
|
|
|
return qgraphicsitem_cast<ItemSticker*>(i.get())->sticker();
|
2021-03-14 09:46:17 +00:00
|
|
|
}) | ranges::to_vector;
|
|
|
|
}
|
|
|
|
|
2021-03-03 09:24:35 +00:00
|
|
|
Scene::~Scene() {
|
2021-03-10 15:51:23 +00:00
|
|
|
// Prevent destroying by scene of all items.
|
|
|
|
QGraphicsScene::removeItem(_canvas.get());
|
|
|
|
for (const auto &item : items()) {
|
|
|
|
// Scene loses ownership of an item.
|
|
|
|
QGraphicsScene::removeItem(item.get());
|
|
|
|
}
|
2021-03-03 09:24:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace Editor
|