mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Added saving and discarding between modes in photo editor.
This commit is contained in:
parent
0adcd37030
commit
8eca57f419
9 changed files with 167 additions and 33 deletions
|
@ -29,6 +29,10 @@ std::shared_ptr<QGraphicsScene> EnsureScene(PhotoModifications &mods) {
|
||||||
return mods.paint;
|
return mods.paint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto FilterItems(QGraphicsItem *i) {
|
||||||
|
return i->type() == QGraphicsItemGroup::Type;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Paint::Paint(
|
Paint::Paint(
|
||||||
|
@ -38,7 +42,8 @@ Paint::Paint(
|
||||||
: RpWidget(parent)
|
: RpWidget(parent)
|
||||||
, _scene(EnsureScene(modifications))
|
, _scene(EnsureScene(modifications))
|
||||||
, _view(base::make_unique_q<QGraphicsView>(_scene.get(), this))
|
, _view(base::make_unique_q<QGraphicsView>(_scene.get(), this))
|
||||||
, _imageSize(imageSize) {
|
, _imageSize(imageSize)
|
||||||
|
, _startItemsCount(itemsCount()) {
|
||||||
Expects(modifications.paint != nullptr);
|
Expects(modifications.paint != nullptr);
|
||||||
|
|
||||||
_view->show();
|
_view->show();
|
||||||
|
@ -49,7 +54,6 @@ Paint::Paint(
|
||||||
_scene->setSceneRect(0, 0, imageSize.width(), imageSize.height());
|
_scene->setSceneRect(0, 0, imageSize.width(), imageSize.height());
|
||||||
|
|
||||||
initDrawing();
|
initDrawing();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Paint::applyTransform(QRect geometry, int angle, bool flipped) {
|
void Paint::applyTransform(QRect geometry, int angle, bool flipped) {
|
||||||
|
@ -120,14 +124,38 @@ void Paint::initDrawing() {
|
||||||
base::install_event_filter(this, _scene.get(), std::move(callback));
|
base::install_event_filter(this, _scene.get(), std::move(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Paint::applyMode(PhotoEditorMode mode) {
|
|
||||||
setAttribute(
|
|
||||||
Qt::WA_TransparentForMouseEvents,
|
|
||||||
mode == PhotoEditorMode::Transform);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<QGraphicsScene> Paint::saveScene() const {
|
std::shared_ptr<QGraphicsScene> Paint::saveScene() const {
|
||||||
return _scene;
|
return _scene;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Paint::cancel() {
|
||||||
|
const auto items = _scene->items(Qt::AscendingOrder);
|
||||||
|
const auto filtered = ranges::views::all(
|
||||||
|
items
|
||||||
|
) | ranges::views::filter(FilterItems) | ranges::to_vector;
|
||||||
|
|
||||||
|
if (filtered.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto i = 0; i < filtered.size(); i++) {
|
||||||
|
const auto &item = filtered[i];
|
||||||
|
if (i < _startItemsCount) {
|
||||||
|
if (!item->isVisible()) {
|
||||||
|
item->show();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_scene->removeItem(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Paint::keepResult() {
|
||||||
|
_startItemsCount = itemsCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
int Paint::itemsCount() const {
|
||||||
|
return ranges::count_if(_scene->items(), FilterItems);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Editor
|
} // namespace Editor
|
||||||
|
|
|
@ -27,15 +27,19 @@ public:
|
||||||
[[nodiscard]] std::shared_ptr<QGraphicsScene> saveScene() const;
|
[[nodiscard]] std::shared_ptr<QGraphicsScene> saveScene() const;
|
||||||
|
|
||||||
void applyTransform(QRect geometry, int angle, bool flipped);
|
void applyTransform(QRect geometry, int angle, bool flipped);
|
||||||
void applyMode(PhotoEditorMode mode);
|
void cancel();
|
||||||
|
void keepResult();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initDrawing();
|
void initDrawing();
|
||||||
|
int itemsCount() const;
|
||||||
|
|
||||||
const std::shared_ptr<QGraphicsScene> _scene;
|
const std::shared_ptr<QGraphicsScene> _scene;
|
||||||
const base::unique_qptr<QGraphicsView> _view;
|
const base::unique_qptr<QGraphicsView> _view;
|
||||||
const QSize _imageSize;
|
const QSize _imageSize;
|
||||||
|
|
||||||
|
int _startItemsCount = 0;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
QPointF lastPoint;
|
QPointF lastPoint;
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,12 @@ PhotoEditor::PhotoEditor(
|
||||||
_controls->setGeometry(controlsRect);
|
_controls->setGeometry(controlsRect);
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
|
|
||||||
|
_mode.value(
|
||||||
|
) | rpl::start_with_next([=](const PhotoEditorMode &mode) {
|
||||||
|
_content->applyMode(mode);
|
||||||
|
_controls->applyMode(mode);
|
||||||
|
}, lifetime());
|
||||||
|
|
||||||
_controls->rotateRequests(
|
_controls->rotateRequests(
|
||||||
) | rpl::start_with_next([=](int angle) {
|
) | rpl::start_with_next([=](int angle) {
|
||||||
_modifications.angle += 90;
|
_modifications.angle += 90;
|
||||||
|
@ -52,9 +58,31 @@ PhotoEditor::PhotoEditor(
|
||||||
|
|
||||||
_controls->paintModeRequests(
|
_controls->paintModeRequests(
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::start_with_next([=] {
|
||||||
_content->applyMode(PhotoEditorMode::Paint);
|
_mode = PhotoEditorMode{
|
||||||
|
.mode = PhotoEditorMode::Mode::Paint,
|
||||||
|
.action = PhotoEditorMode::Action::None,
|
||||||
|
};
|
||||||
|
}, lifetime());
|
||||||
|
|
||||||
|
_controls->doneRequests(
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
if (_mode.current().mode == PhotoEditorMode::Mode::Paint) {
|
||||||
|
_mode = PhotoEditorMode{
|
||||||
|
.mode = PhotoEditorMode::Mode::Transform,
|
||||||
|
.action = PhotoEditorMode::Action::Save,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, lifetime());
|
||||||
|
|
||||||
|
_controls->cancelRequests(
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
if (_mode.current().mode == PhotoEditorMode::Mode::Paint) {
|
||||||
|
_mode = PhotoEditorMode{
|
||||||
|
.mode = PhotoEditorMode::Mode::Transform,
|
||||||
|
.action = PhotoEditorMode::Action::Discard,
|
||||||
|
};
|
||||||
|
}
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
_content->applyMode(PhotoEditorMode::Transform);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhotoEditor::save() {
|
void PhotoEditor::save() {
|
||||||
|
|
|
@ -35,6 +35,10 @@ private:
|
||||||
base::unique_qptr<PhotoEditorContent> _content;
|
base::unique_qptr<PhotoEditorContent> _content;
|
||||||
base::unique_qptr<PhotoEditorControls> _controls;
|
base::unique_qptr<PhotoEditorControls> _controls;
|
||||||
|
|
||||||
|
rpl::variable<PhotoEditorMode> _mode = PhotoEditorMode{
|
||||||
|
.mode = PhotoEditorMode::Mode::Transform,
|
||||||
|
.action = PhotoEditorMode::Action::None,
|
||||||
|
};
|
||||||
rpl::event_stream<PhotoModifications> _done;
|
rpl::event_stream<PhotoModifications> _done;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,9 +11,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
namespace Editor {
|
namespace Editor {
|
||||||
|
|
||||||
enum class PhotoEditorMode {
|
struct PhotoEditorMode {
|
||||||
Transform,
|
enum class Mode {
|
||||||
Paint,
|
Transform,
|
||||||
|
Paint,
|
||||||
|
} mode = Mode::Transform;
|
||||||
|
|
||||||
|
enum class Action {
|
||||||
|
None,
|
||||||
|
Save,
|
||||||
|
Discard,
|
||||||
|
} action = Action::None;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PhotoModifications {
|
struct PhotoModifications {
|
||||||
|
|
|
@ -93,9 +93,17 @@ void PhotoEditorContent::save(PhotoModifications &modifications) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhotoEditorContent::applyMode(PhotoEditorMode mode) {
|
void PhotoEditorContent::applyMode(const PhotoEditorMode &mode) {
|
||||||
_crop->setVisible(mode == PhotoEditorMode::Transform);
|
const auto isTransform = (mode.mode == PhotoEditorMode::Mode::Transform);
|
||||||
_paint->applyMode(mode);
|
_crop->setVisible(isTransform);
|
||||||
|
|
||||||
|
_paint->setAttribute(Qt::WA_TransparentForMouseEvents, isTransform);
|
||||||
|
|
||||||
|
if (mode.action == PhotoEditorMode::Action::Discard) {
|
||||||
|
_paint->cancel();
|
||||||
|
} else if (mode.action == PhotoEditorMode::Action::Save) {
|
||||||
|
_paint->keepResult();
|
||||||
|
}
|
||||||
_mode = mode;
|
_mode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ public:
|
||||||
PhotoModifications modifications);
|
PhotoModifications modifications);
|
||||||
|
|
||||||
void applyModifications(PhotoModifications modifications);
|
void applyModifications(PhotoModifications modifications);
|
||||||
void applyMode(PhotoEditorMode mode);
|
void applyMode(const PhotoEditorMode &mode);
|
||||||
void save(PhotoModifications &modifications);
|
void save(PhotoModifications &modifications);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -136,15 +136,25 @@ PhotoEditorControls::PhotoEditorControls(
|
||||||
bool doneControls)
|
bool doneControls)
|
||||||
: RpWidget(parent)
|
: RpWidget(parent)
|
||||||
, _bg(st::mediaviewSaveMsgBg)
|
, _bg(st::mediaviewSaveMsgBg)
|
||||||
, _buttonsContainer(base::make_unique_q<HorizontalContainer>(this))
|
, _transformButtons(base::make_unique_q<HorizontalContainer>(this))
|
||||||
|
, _paintButtons(base::make_unique_q<HorizontalContainer>(this))
|
||||||
, _rotateButton(base::make_unique_q<Ui::IconButton>(
|
, _rotateButton(base::make_unique_q<Ui::IconButton>(
|
||||||
_buttonsContainer,
|
_transformButtons,
|
||||||
st::photoEditorRotateButton))
|
st::photoEditorRotateButton))
|
||||||
, _flipButton(base::make_unique_q<Ui::IconButton>(
|
, _flipButton(base::make_unique_q<Ui::IconButton>(
|
||||||
_buttonsContainer,
|
_transformButtons,
|
||||||
st::photoEditorFlipButton))
|
st::photoEditorFlipButton))
|
||||||
, _paintModeButton(base::make_unique_q<Ui::IconButton>(
|
, _paintModeButton(base::make_unique_q<Ui::IconButton>(
|
||||||
_buttonsContainer,
|
_transformButtons,
|
||||||
|
st::photoEditorPaintModeButton))
|
||||||
|
, _undoButton(base::make_unique_q<Ui::IconButton>(
|
||||||
|
_paintButtons,
|
||||||
|
st::photoEditorUndoButton))
|
||||||
|
, _redoButton(base::make_unique_q<Ui::IconButton>(
|
||||||
|
_paintButtons,
|
||||||
|
st::photoEditorRedoButton))
|
||||||
|
, _paintModeButtonActive(base::make_unique_q<Ui::IconButton>(
|
||||||
|
_paintButtons,
|
||||||
st::photoEditorPaintModeButton))
|
st::photoEditorPaintModeButton))
|
||||||
, _cancel(base::make_unique_q<EdgeButton>(
|
, _cancel(base::make_unique_q<EdgeButton>(
|
||||||
this,
|
this,
|
||||||
|
@ -163,7 +173,12 @@ PhotoEditorControls::PhotoEditorControls(
|
||||||
st::lightButtonFg,
|
st::lightButtonFg,
|
||||||
st::photoEditorRotateButton.ripple)) {
|
st::photoEditorRotateButton.ripple)) {
|
||||||
|
|
||||||
_buttonsContainer->updateChildrenPosition();
|
_transformButtons->updateChildrenPosition();
|
||||||
|
_paintButtons->updateChildrenPosition();
|
||||||
|
|
||||||
|
_paintModeButtonActive->setIconOverride(
|
||||||
|
&st::photoEditorPaintModeButton.iconOver);
|
||||||
|
_paintModeButtonActive->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||||
|
|
||||||
paintRequest(
|
paintRequest(
|
||||||
) | rpl::start_with_next([=](const QRect &clip) {
|
) | rpl::start_with_next([=](const QRect &clip) {
|
||||||
|
@ -171,21 +186,30 @@ PhotoEditorControls::PhotoEditorControls(
|
||||||
|
|
||||||
p.setPen(Qt::NoPen);
|
p.setPen(Qt::NoPen);
|
||||||
p.setBrush(_bg);
|
p.setBrush(_bg);
|
||||||
p.drawRect(_buttonsContainer->geometry());
|
p.drawRect(_transformButtons->geometry());
|
||||||
|
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
|
|
||||||
sizeValue(
|
rpl::combine(
|
||||||
) | rpl::start_with_next([=](const QSize &size) {
|
sizeValue(),
|
||||||
|
_mode.value()
|
||||||
|
) | rpl::start_with_next([=](
|
||||||
|
const QSize &size,
|
||||||
|
const PhotoEditorMode &mode) {
|
||||||
|
if (size.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_buttonsContainer->moveToLeft(
|
const auto ¤t = _transformButtons->isHidden()
|
||||||
(size.width() - _buttonsContainer->width()) / 2,
|
? _paintButtons
|
||||||
|
: _transformButtons;
|
||||||
|
|
||||||
|
current->moveToLeft(
|
||||||
|
(size.width() - current->width()) / 2,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
_cancel->moveToLeft(_buttonsContainer->x() - _cancel->width(), 0);
|
_cancel->moveToLeft(current->x() - _cancel->width(), 0);
|
||||||
_done->moveToLeft(
|
_done->moveToLeft(current->x() + current->width(), 0);
|
||||||
_buttonsContainer->x() + _buttonsContainer->width(),
|
|
||||||
0);
|
|
||||||
|
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
|
|
||||||
|
@ -203,4 +227,19 @@ rpl::producer<> PhotoEditorControls::paintModeRequests() const {
|
||||||
return _paintModeButton->clicks() | rpl::to_empty;
|
return _paintModeButton->clicks() | rpl::to_empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rpl::producer<> PhotoEditorControls::doneRequests() const {
|
||||||
|
return _done->clicks() | rpl::to_empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
rpl::producer<> PhotoEditorControls::cancelRequests() const {
|
||||||
|
return _cancel->clicks() | rpl::to_empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhotoEditorControls::applyMode(const PhotoEditorMode &mode) {
|
||||||
|
using Mode = PhotoEditorMode::Mode;
|
||||||
|
_transformButtons->setVisible(mode.mode == Mode::Transform);
|
||||||
|
_paintButtons->setVisible(mode.mode == Mode::Paint);
|
||||||
|
_mode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Editor
|
} // namespace Editor
|
||||||
|
|
|
@ -9,6 +9,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
#include "ui/rp_widget.h"
|
#include "ui/rp_widget.h"
|
||||||
|
|
||||||
|
#include "editor/photo_editor_common.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class IconButton;
|
class IconButton;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
@ -27,17 +29,30 @@ public:
|
||||||
[[nodiscard]] rpl::producer<int> rotateRequests() const;
|
[[nodiscard]] rpl::producer<int> rotateRequests() const;
|
||||||
[[nodiscard]] rpl::producer<> flipRequests() const;
|
[[nodiscard]] rpl::producer<> flipRequests() const;
|
||||||
[[nodiscard]] rpl::producer<> paintModeRequests() const;
|
[[nodiscard]] rpl::producer<> paintModeRequests() const;
|
||||||
|
[[nodiscard]] rpl::producer<> doneRequests() const;
|
||||||
|
[[nodiscard]] rpl::producer<> cancelRequests() const;
|
||||||
|
|
||||||
|
void applyMode(const PhotoEditorMode &mode);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
const style::color &_bg;
|
const style::color &_bg;
|
||||||
const base::unique_qptr<HorizontalContainer> _buttonsContainer;
|
const base::unique_qptr<HorizontalContainer> _transformButtons;
|
||||||
|
const base::unique_qptr<HorizontalContainer> _paintButtons;
|
||||||
|
|
||||||
const base::unique_qptr<Ui::IconButton> _rotateButton;
|
const base::unique_qptr<Ui::IconButton> _rotateButton;
|
||||||
const base::unique_qptr<Ui::IconButton> _flipButton;
|
const base::unique_qptr<Ui::IconButton> _flipButton;
|
||||||
const base::unique_qptr<Ui::IconButton> _paintModeButton;
|
const base::unique_qptr<Ui::IconButton> _paintModeButton;
|
||||||
|
|
||||||
|
const base::unique_qptr<Ui::IconButton> _undoButton;
|
||||||
|
const base::unique_qptr<Ui::IconButton> _redoButton;
|
||||||
|
const base::unique_qptr<Ui::IconButton> _paintModeButtonActive;
|
||||||
|
|
||||||
const base::unique_qptr<EdgeButton> _cancel;
|
const base::unique_qptr<EdgeButton> _cancel;
|
||||||
const base::unique_qptr<EdgeButton> _done;
|
const base::unique_qptr<EdgeButton> _done;
|
||||||
|
|
||||||
|
rpl::variable<PhotoEditorMode> _mode;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Editor
|
} // namespace Editor
|
||||||
|
|
Loading…
Add table
Reference in a new issue