Added saving and discarding between modes in photo editor.

This commit is contained in:
23rd 2021-03-14 12:39:55 +03:00
parent 0adcd37030
commit 8eca57f419
9 changed files with 167 additions and 33 deletions

View file

@ -29,6 +29,10 @@ std::shared_ptr<QGraphicsScene> EnsureScene(PhotoModifications &mods) {
return mods.paint;
}
auto FilterItems(QGraphicsItem *i) {
return i->type() == QGraphicsItemGroup::Type;
}
} // namespace
Paint::Paint(
@ -38,7 +42,8 @@ Paint::Paint(
: RpWidget(parent)
, _scene(EnsureScene(modifications))
, _view(base::make_unique_q<QGraphicsView>(_scene.get(), this))
, _imageSize(imageSize) {
, _imageSize(imageSize)
, _startItemsCount(itemsCount()) {
Expects(modifications.paint != nullptr);
_view->show();
@ -49,7 +54,6 @@ Paint::Paint(
_scene->setSceneRect(0, 0, imageSize.width(), imageSize.height());
initDrawing();
}
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));
}
void Paint::applyMode(PhotoEditorMode mode) {
setAttribute(
Qt::WA_TransparentForMouseEvents,
mode == PhotoEditorMode::Transform);
}
std::shared_ptr<QGraphicsScene> Paint::saveScene() const {
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

View file

@ -27,15 +27,19 @@ public:
[[nodiscard]] std::shared_ptr<QGraphicsScene> saveScene() const;
void applyTransform(QRect geometry, int angle, bool flipped);
void applyMode(PhotoEditorMode mode);
void cancel();
void keepResult();
private:
void initDrawing();
int itemsCount() const;
const std::shared_ptr<QGraphicsScene> _scene;
const base::unique_qptr<QGraphicsView> _view;
const QSize _imageSize;
int _startItemsCount = 0;
struct {
QPointF lastPoint;

View file

@ -35,6 +35,12 @@ PhotoEditor::PhotoEditor(
_controls->setGeometry(controlsRect);
}, lifetime());
_mode.value(
) | rpl::start_with_next([=](const PhotoEditorMode &mode) {
_content->applyMode(mode);
_controls->applyMode(mode);
}, lifetime());
_controls->rotateRequests(
) | rpl::start_with_next([=](int angle) {
_modifications.angle += 90;
@ -52,9 +58,31 @@ PhotoEditor::PhotoEditor(
_controls->paintModeRequests(
) | 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());
_content->applyMode(PhotoEditorMode::Transform);
}
void PhotoEditor::save() {

View file

@ -35,6 +35,10 @@ private:
base::unique_qptr<PhotoEditorContent> _content;
base::unique_qptr<PhotoEditorControls> _controls;
rpl::variable<PhotoEditorMode> _mode = PhotoEditorMode{
.mode = PhotoEditorMode::Mode::Transform,
.action = PhotoEditorMode::Action::None,
};
rpl::event_stream<PhotoModifications> _done;
};

View file

@ -11,9 +11,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Editor {
enum class PhotoEditorMode {
Transform,
Paint,
struct PhotoEditorMode {
enum class Mode {
Transform,
Paint,
} mode = Mode::Transform;
enum class Action {
None,
Save,
Discard,
} action = Action::None;
};
struct PhotoModifications {

View file

@ -93,9 +93,17 @@ void PhotoEditorContent::save(PhotoModifications &modifications) {
}
}
void PhotoEditorContent::applyMode(PhotoEditorMode mode) {
_crop->setVisible(mode == PhotoEditorMode::Transform);
_paint->applyMode(mode);
void PhotoEditorContent::applyMode(const PhotoEditorMode &mode) {
const auto isTransform = (mode.mode == PhotoEditorMode::Mode::Transform);
_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;
}

View file

@ -24,7 +24,7 @@ public:
PhotoModifications modifications);
void applyModifications(PhotoModifications modifications);
void applyMode(PhotoEditorMode mode);
void applyMode(const PhotoEditorMode &mode);
void save(PhotoModifications &modifications);
private:

View file

@ -136,15 +136,25 @@ PhotoEditorControls::PhotoEditorControls(
bool doneControls)
: RpWidget(parent)
, _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>(
_buttonsContainer,
_transformButtons,
st::photoEditorRotateButton))
, _flipButton(base::make_unique_q<Ui::IconButton>(
_buttonsContainer,
_transformButtons,
st::photoEditorFlipButton))
, _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))
, _cancel(base::make_unique_q<EdgeButton>(
this,
@ -163,7 +173,12 @@ PhotoEditorControls::PhotoEditorControls(
st::lightButtonFg,
st::photoEditorRotateButton.ripple)) {
_buttonsContainer->updateChildrenPosition();
_transformButtons->updateChildrenPosition();
_paintButtons->updateChildrenPosition();
_paintModeButtonActive->setIconOverride(
&st::photoEditorPaintModeButton.iconOver);
_paintModeButtonActive->setAttribute(Qt::WA_TransparentForMouseEvents);
paintRequest(
) | rpl::start_with_next([=](const QRect &clip) {
@ -171,21 +186,30 @@ PhotoEditorControls::PhotoEditorControls(
p.setPen(Qt::NoPen);
p.setBrush(_bg);
p.drawRect(_buttonsContainer->geometry());
p.drawRect(_transformButtons->geometry());
}, lifetime());
sizeValue(
) | rpl::start_with_next([=](const QSize &size) {
rpl::combine(
sizeValue(),
_mode.value()
) | rpl::start_with_next([=](
const QSize &size,
const PhotoEditorMode &mode) {
if (size.isEmpty()) {
return;
}
_buttonsContainer->moveToLeft(
(size.width() - _buttonsContainer->width()) / 2,
const auto &current = _transformButtons->isHidden()
? _paintButtons
: _transformButtons;
current->moveToLeft(
(size.width() - current->width()) / 2,
0);
_cancel->moveToLeft(_buttonsContainer->x() - _cancel->width(), 0);
_done->moveToLeft(
_buttonsContainer->x() + _buttonsContainer->width(),
0);
_cancel->moveToLeft(current->x() - _cancel->width(), 0);
_done->moveToLeft(current->x() + current->width(), 0);
}, lifetime());
@ -203,4 +227,19 @@ rpl::producer<> PhotoEditorControls::paintModeRequests() const {
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

View file

@ -9,6 +9,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/rp_widget.h"
#include "editor/photo_editor_common.h"
namespace Ui {
class IconButton;
} // namespace Ui
@ -27,17 +29,30 @@ public:
[[nodiscard]] rpl::producer<int> rotateRequests() const;
[[nodiscard]] rpl::producer<> flipRequests() const;
[[nodiscard]] rpl::producer<> paintModeRequests() const;
[[nodiscard]] rpl::producer<> doneRequests() const;
[[nodiscard]] rpl::producer<> cancelRequests() const;
void applyMode(const PhotoEditorMode &mode);
private:
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> _flipButton;
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> _done;
rpl::variable<PhotoEditorMode> _mode;
};
} // namespace Editor