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; 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

View file

@ -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;

View file

@ -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() {

View file

@ -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;
}; };

View file

@ -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 {

View file

@ -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;
} }

View file

@ -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:

View file

@ -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 &current = _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

View file

@ -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