Added saving of color and size of brush from photo editor to settings.

This commit is contained in:
23rd 2021-02-17 03:01:19 +03:00
parent dc7f440902
commit e322733e20
5 changed files with 104 additions and 25 deletions

View File

@ -113,7 +113,8 @@ QByteArray Settings::serialize() const {
+ sizeof(qint64)
+ sizeof(qint32) * 2
+ Serialize::bytearraySize(windowPosition)
+ sizeof(qint32);
+ sizeof(qint32)
+ Serialize::bytearraySize(_photoEditorBrush);
for (const auto &[id, rating] : recentEmojiPreloadData) {
size += Serialize::stringSize(id) + sizeof(quint16);
}
@ -216,7 +217,8 @@ QByteArray Settings::serialize() const {
<< qint32(_workMode.current())
<< proxy
<< qint32(_hiddenGroupCallTooltips.value())
<< qint32(_disableOpenGL ? 1 : 0);
<< qint32(_disableOpenGL ? 1 : 0)
<< _photoEditorBrush;
}
return result;
}
@ -297,6 +299,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
qint32 workMode = static_cast<qint32>(_workMode.current());
QByteArray proxy;
qint32 hiddenGroupCallTooltips = qint32(_hiddenGroupCallTooltips.value());
QByteArray photoEditorBrush = _photoEditorBrush;
stream >> themesAccentColors;
if (!stream.atEnd()) {
@ -444,6 +447,9 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
if (!stream.atEnd()) {
stream >> disableOpenGL;
}
if (!stream.atEnd()) {
stream >> photoEditorBrush;
}
if (stream.status() != QDataStream::Ok) {
LOG(("App Error: "
"Bad data for Core::Settings::constructFromSerialized()"));
@ -573,6 +579,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
? Tooltip::Microphone
: Tooltip(0));
}();
_photoEditorBrush = photoEditorBrush;
}
QString Settings::getSoundPath(const QString &key) const {

View File

@ -434,6 +434,13 @@ public:
_videoPipGeometry = geometry;
}
[[nodiscard]] QByteArray photoEditorBrush() const {
return _photoEditorBrush;
}
void setPhotoEditorBrush(QByteArray brush) {
_photoEditorBrush = brush;
}
[[nodiscard]] float64 rememberedSongVolume() const {
return _rememberedSongVolume;
}
@ -696,6 +703,8 @@ private:
bool _rememberedSoundNotifyFromTray = false;
bool _rememberedFlashBounceNotifyFromTray = false;
QByteArray _photoEditorBrush;
};
} // namespace Core

View File

@ -17,7 +17,7 @@ namespace Editor {
namespace {
constexpr auto kPrecision = 1000;
constexpr auto kMinBrushSize = 0.1;
constexpr auto kMinBrushSize = 0.1f;
constexpr auto kMouseSkip = 1.4;
constexpr auto kMinInnerHeight = 0.2;
@ -83,7 +83,9 @@ inline float64 InterpolationRatio(int from, int to, int result) {
} // namespace
ColorPicker::ColorPicker(not_null<Ui::RpWidget*> parent)
ColorPicker::ColorPicker(
not_null<Ui::RpWidget*> parent,
const Brush &savedBrush)
: _circleColor(Qt::white)
, _width(st::photoEditorColorPickerWidth)
, _lineHeight(st::photoEditorColorPickerLineHeight)
@ -93,7 +95,14 @@ ColorPicker::ColorPicker(not_null<Ui::RpWidget*> parent)
, _outlinedStop(FindOutlinedStop(_circleColor, _gradientStops, _width))
, _gradientBrush(
GradientBrush(QPoint(_width, _lineHeight / 2), _gradientStops))
, _brush(Brush{ .sizeRatio = kMinBrushSize, .color = QColor() }) {
, _brush(Brush{
.sizeRatio = (savedBrush.sizeRatio
? savedBrush.sizeRatio
: kMinBrushSize),
.color = (savedBrush.color.isValid()
? savedBrush.color
: _gradientStops.front().second),
}) {
_colorLine->resize(_width, _lineHeight);
_canvasForCircle->resize(
_width + circleHeight(kMax),
@ -101,6 +110,8 @@ ColorPicker::ColorPicker(not_null<Ui::RpWidget*> parent)
_canvasForCircle->setAttribute(Qt::WA_TransparentForMouseEvents);
_down.pos = QPoint(colorToPosition(savedBrush.color), 0);
_colorLine->paintRequest(
) | rpl::start_with_next([=] {
Painter p(_colorLine);
@ -146,6 +157,9 @@ ColorPicker::ColorPicker(not_null<Ui::RpWidget*> parent)
}
const auto e = static_cast<QMouseEvent*>(event.get());
updateMousePosition(e->pos(), progress);
if (isRelease) {
_saveBrushRequests.fire_copy(_brush);
}
_canvasForCircle->update();
}, _colorLine->lifetime());
@ -168,18 +182,14 @@ void ColorPicker::updateMousePosition(const QPoint &pos, float64 progress) {
const auto from = 0;
const auto to = bottom - skip;
const auto size = (mappedY > to)
? _brush.current().sizeRatio // Don't change value.
: std::clamp(
1. - InterpolationRatio(from, to, _down.pos.y()),
// Don't change the brush size when we are on the color line.
if (mappedY <= to) {
_brush.sizeRatio = std::clamp(
float(1. - InterpolationRatio(from, to, _down.pos.y())),
kMinBrushSize,
1.);
const auto color = positionToColor(_down.pos.x());
_brush = Brush{
.sizeRatio = float(size),
.color = color,
};
1.f);
}
_brush.color = positionToColor(_down.pos.x());
}
void ColorPicker::moveLine(const QPoint &position) {
@ -239,9 +249,9 @@ void ColorPicker::paintCircle(Painter &p) {
const auto innerH = InterpolateF(
h * kMinInnerHeight,
h * kMaxInnerHeight,
_brush.current().sizeRatio);
_brush.sizeRatio);
p.setBrush(_brush.current().color);
p.setBrush(_brush.color);
const auto innerRect = QRectF(
r.x() + (r.width() - innerH) / 2.,
@ -297,8 +307,18 @@ void ColorPicker::setVisible(bool visible) {
_canvasForCircle->setVisible(visible);
}
rpl::producer<Brush> ColorPicker::brushValue() const {
return _brush.value();
rpl::producer<Brush> ColorPicker::saveBrushRequests() const {
return _saveBrushRequests.events();
}
int ColorPicker::colorToPosition(const QColor &color) const {
const auto step = 1. / kPrecision;
for (auto i = 0.; i <= 1.; i += step) {
if (positionToColor(i * _width) == color) {
return i * _width;
}
}
return 0;
}
} // namespace Editor

View File

@ -25,17 +25,18 @@ public:
std::optional<int> nextStopPos = std::nullopt;
};
ColorPicker(not_null<Ui::RpWidget*> parent);
ColorPicker(not_null<Ui::RpWidget*> parent, const Brush &savedBrush);
void moveLine(const QPoint &position);
void setVisible(bool visible);
rpl::producer<Brush> brushValue() const;
rpl::producer<Brush> saveBrushRequests() const;
private:
void paintCircle(Painter &p);
void paintOutline(Painter &p, const QRectF &rect);
QColor positionToColor(int x) const;
int colorToPosition(const QColor &color) const;
int circleHeight(float64 progress = 0.) const;
void updateMousePosition(const QPoint &pos, float64 progress);
@ -54,10 +55,12 @@ private:
QPoint pos;
bool pressed = false;
} _down;
rpl::variable<Brush> _brush;
Brush _brush;
Ui::Animations::Simple _circleAnimation;
rpl::event_stream<Brush> _saveBrushRequests;
};
} // namespace Editor

View File

@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "editor/photo_editor.h"
#include "core/application.h"
#include "core/core_settings.h"
#include "editor/color_picker.h"
#include "editor/photo_editor_content.h"
#include "editor/photo_editor_controls.h"
@ -14,6 +16,32 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_editor.h"
namespace Editor {
namespace {
constexpr auto kPrecision = 100000;
[[nodiscard]] QByteArray Serialize(const Brush &brush) {
auto result = QByteArray();
auto stream = QDataStream(&result, QIODevice::WriteOnly);
stream.setVersion(QDataStream::Qt_5_3);
stream << qint32(brush.sizeRatio * kPrecision) << brush.color;
stream.device()->close();
return result;
}
[[nodiscard]] Brush Deserialize(const QByteArray &data) {
auto stream = QDataStream(data);
auto result = Brush();
auto size = qint32(0);
stream >> size >> result.color;
result.sizeRatio = size / float(kPrecision);
return (stream.status() != QDataStream::Ok)
? Brush()
: result;
}
} // namespace
PhotoEditor::PhotoEditor(
not_null<Ui::RpWidget*> parent,
@ -28,7 +56,10 @@ PhotoEditor::PhotoEditor(
_modifications,
_undoController))
, _controls(base::make_unique_q<PhotoEditorControls>(this, _undoController))
, _colorPicker(std::make_unique<ColorPicker>(this)) {
, _colorPicker(std::make_unique<ColorPicker>(
this,
Deserialize(Core::App().settings().photoEditorBrush()))) {
sizeValue(
) | rpl::start_with_next([=](const QSize &size) {
if (size.isEmpty()) {
@ -97,9 +128,18 @@ PhotoEditor::PhotoEditor(
}
}, lifetime());
_colorPicker->brushValue(
rpl::single(
Deserialize(Core::App().settings().photoEditorBrush())
) | rpl::then(
_colorPicker->saveBrushRequests()
) | rpl::start_with_next([=](const Brush &brush) {
_content->applyBrush(brush);
const auto serialized = Serialize(brush);
if (Core::App().settings().photoEditorBrush() != serialized) {
Core::App().settings().setPhotoEditorBrush(serialized);
Core::App().saveSettingsDelayed();
}
}, lifetime());
}