/* 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" #include "editor/scene_item_sticker.h" #include "ui/rp_widget.h" #include namespace Editor { namespace { using ItemPtr = Scene::ItemPtr; bool SkipMouseEvent(not_null event) { return event->isAccepted() || (event->button() == Qt::RightButton); } } // namespace Scene::Scene(const QRectF &rect) : QGraphicsScene(rect) , _canvas(std::make_shared()) { QGraphicsScene::addItem(_canvas.get()); _canvas->clearPixmap(); _canvas->grabContentRequests( ) | rpl::start_with_next([=](ItemCanvas::Content &&content) { const auto item = std::make_shared( std::move(content.pixmap)); item->setPos(content.position); addItem(item); _canvas->setZValue(++_lastLineZ); }, _lifetime); } void Scene::addItem(std::shared_ptr item) { if (!item) { return; } item->setNumber(_itemNumber++); QGraphicsScene::addItem(item.get()); _items.push_back(std::move(item)); _addsItem.fire({}); } void Scene::removeItem(not_null 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)); } void Scene::mousePressEvent(QGraphicsSceneMouseEvent *event) { QGraphicsScene::mousePressEvent(event); if (SkipMouseEvent(event)) { return; } _canvas->handleMousePressEvent(event); _mousePresses.fire({}); } void Scene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { QGraphicsScene::mouseReleaseEvent(event); if (SkipMouseEvent(event)) { return; } _canvas->handleMouseReleaseEvent(event); } void Scene::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { QGraphicsScene::mouseMoveEvent(event); if (SkipMouseEvent(event)) { return; } _canvas->handleMouseMoveEvent(event); } void Scene::applyBrush(const QColor &color, float size) { _canvas->applyBrush(color, size); } rpl::producer<> Scene::mousePresses() const { return _mousePresses.events(); } rpl::producer<> Scene::addsItem() const { return _addsItem.events(); } std::vector Scene::items( Qt::SortOrder order) const { auto copyItems = _items; ranges::sort(copyItems, [&](ItemPtr a, ItemPtr b) { const auto numA = qgraphicsitem_cast( a.get())->number(); const auto numB = qgraphicsitem_cast( b.get())->number(); return (order == Qt::AscendingOrder) ? (numA < numB) : (numA > numB); }); return copyItems; } std::vector Scene::attachedStickers() const { const auto allItems = items(); return ranges::views::all( allItems ) | ranges::views::filter([](const ItemPtr &i) { return i->isVisible() && (i->type() == ItemSticker::Type); }) | ranges::views::transform([](const ItemPtr &i) { return qgraphicsitem_cast(i.get())->sticker(); }) | ranges::to_vector; } Scene::~Scene() { // 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()); } } } // namespace Editor