Added ability to open photo editor in SendFilesBox with left-click.

This commit is contained in:
23rd 2021-04-26 01:50:16 +03:00
parent 6975b04e6b
commit 18154e403a
9 changed files with 99 additions and 47 deletions

View file

@ -13,6 +13,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
#include "styles/style_layers.h" #include "styles/style_layers.h"
#include <QtWidgets/QApplication>
namespace Ui { namespace Ui {
namespace { namespace {
@ -25,15 +27,12 @@ AlbumPreview::AlbumPreview(
gsl::span<Ui::PreparedFile> items, gsl::span<Ui::PreparedFile> items,
SendFilesWay way) SendFilesWay way)
: RpWidget(parent) : RpWidget(parent)
, _sendWay(way) { , _sendWay(way)
, _dragTimer([=] { switchToDrag(); }) {
setMouseTracking(true); setMouseTracking(true);
prepareThumbs(items); prepareThumbs(items);
updateSize(); updateSize();
updateFileRows(); updateFileRows();
AddPhotoEditorMenu(this, [=] {
_thumbModified.fire(thumbIndex(thumbUnderCursor()));
});
} }
AlbumPreview::~AlbumPreview() = default; AlbumPreview::~AlbumPreview() = default;
@ -372,6 +371,13 @@ void AlbumPreview::changeThumbByIndex(int index) {
_thumbChanged.fire(std::move(index)); _thumbChanged.fire(std::move(index));
} }
void AlbumPreview::modifyThumbByIndex(int index) {
if (index < 0) {
return;
}
_thumbModified.fire(std::move(index));
}
void AlbumPreview::thumbButtonsCallback( void AlbumPreview::thumbButtonsCallback(
not_null<AlbumThumbnail*> thumb, not_null<AlbumThumbnail*> thumb,
AttachButtonType type) { AttachButtonType type) {
@ -381,6 +387,10 @@ void AlbumPreview::thumbButtonsCallback(
case AttachButtonType::None: return; case AttachButtonType::None: return;
case AttachButtonType::Edit: changeThumbByIndex(index); break; case AttachButtonType::Edit: changeThumbByIndex(index); break;
case AttachButtonType::Delete: deleteThumbByIndex(index); break; case AttachButtonType::Delete: deleteThumbByIndex(index); break;
case AttachButtonType::Modify:
cancelDrag();
modifyThumbByIndex(index);
break;
} }
} }
@ -391,17 +401,21 @@ void AlbumPreview::mousePressEvent(QMouseEvent *e) {
const auto position = e->pos(); const auto position = e->pos();
cancelDrag(); cancelDrag();
if (const auto thumb = findThumb(position)) { if (const auto thumb = findThumb(position)) {
if (thumb->buttonsContainPoint(e->pos())) { _draggedStartPosition = position;
_pressedButtonType = thumb->buttonTypeFromPoint(e->pos()); _pressedThumb = thumb;
_pressedButtonType = thumb->buttonTypeFromPoint(position);
const auto isAlbum = _sendWay.sendImagesAsPhotos()
&& _sendWay.groupFiles();
if (!isAlbum) {
return; return;
} }
_paintedAbove = _suggestedThumb = _draggedThumb = thumb;
_draggedStartPosition = position; if (_pressedButtonType == AttachButtonType::None) {
_shrinkAnimation.start( switchToDrag();
[=] { update(); }, } else if (_pressedButtonType == AttachButtonType::Modify) {
0., _dragTimer.callOnce(QApplication::startDragTime());
1., }
AlbumThumbnail::kShrinkDuration);
} }
} }
@ -410,6 +424,10 @@ void AlbumPreview::mouseMoveEvent(QMouseEvent *e) {
applyCursor(style::cur_default); applyCursor(style::cur_default);
return; return;
} }
if (_dragTimer.isActive()) {
_dragTimer.cancel();
switchToDrag();
}
const auto isAlbum = _sendWay.sendImagesAsPhotos() const auto isAlbum = _sendWay.sendImagesAsPhotos()
&& _sendWay.groupFiles(); && _sendWay.groupFiles();
if (isAlbum && _draggedThumb) { if (isAlbum && _draggedThumb) {
@ -420,7 +438,7 @@ void AlbumPreview::mouseMoveEvent(QMouseEvent *e) {
} else { } else {
const auto thumb = findThumb(e->pos()); const auto thumb = findThumb(e->pos());
const auto regularCursor = isAlbum const auto regularCursor = isAlbum
? style::cur_sizeall ? style::cur_pointer
: style::cur_default; : style::cur_default;
const auto cursor = thumb const auto cursor = thumb
? (thumb->buttonsContainPoint(e->pos()) ? (thumb->buttonsContainPoint(e->pos())
@ -492,18 +510,30 @@ void AlbumPreview::mouseReleaseEvent(QMouseEvent *e) {
_draggedThumb = nullptr; _draggedThumb = nullptr;
_suggestedThumb = nullptr; _suggestedThumb = nullptr;
update(); update();
} else if (const auto thumb = findThumb(e->pos())) { } else if (const auto thumb = base::take(_pressedThumb)) {
if (thumb->buttonsContainPoint(e->pos())) { const auto was = _pressedButtonType;
const auto was = _pressedButtonType; const auto now = thumb->buttonTypeFromPoint(e->pos());
const auto now = thumb->buttonTypeFromPoint(e->pos()); if (was == now) {
if (was == now) { thumbButtonsCallback(thumb, now);
thumbButtonsCallback(thumb, now);
}
} }
} }
_pressedButtonType = AttachButtonType::None; _pressedButtonType = AttachButtonType::None;
} }
void AlbumPreview::switchToDrag() {
_paintedAbove
= _suggestedThumb
= _draggedThumb
= base::take(_pressedThumb);
_shrinkAnimation.start(
[=] { update(); },
0.,
1.,
AlbumThumbnail::kShrinkDuration);
applyCursor(style::cur_sizeall);
update();
}
rpl::producer<int> AlbumPreview::thumbModified() const { rpl::producer<int> AlbumPreview::thumbModified() const {
return _thumbModified.events(); return _thumbModified.events();
} }

View file

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/rp_widget.h" #include "ui/rp_widget.h"
#include "ui/chat/attach/attach_send_files_way.h" #include "ui/chat/attach/attach_send_files_way.h"
#include "base/timer.h"
namespace Ui { namespace Ui {
@ -57,10 +58,13 @@ private:
AlbumThumbnail *thumbUnderCursor(); AlbumThumbnail *thumbUnderCursor();
void deleteThumbByIndex(int index); void deleteThumbByIndex(int index);
void changeThumbByIndex(int index); void changeThumbByIndex(int index);
void modifyThumbByIndex(int index);
void thumbButtonsCallback( void thumbButtonsCallback(
not_null<AlbumThumbnail*> thumb, not_null<AlbumThumbnail*> thumb,
AttachButtonType type); AttachButtonType type);
void switchToDrag();
void paintAlbum(Painter &p) const; void paintAlbum(Painter &p) const;
void paintPhotos(Painter &p, QRect clip) const; void paintPhotos(Painter &p, QRect clip) const;
void paintFiles(Painter &p, QRect clip) const; void paintFiles(Painter &p, QRect clip) const;
@ -87,8 +91,10 @@ private:
AlbumThumbnail *_draggedThumb = nullptr; AlbumThumbnail *_draggedThumb = nullptr;
AlbumThumbnail *_suggestedThumb = nullptr; AlbumThumbnail *_suggestedThumb = nullptr;
AlbumThumbnail *_paintedAbove = nullptr; AlbumThumbnail *_paintedAbove = nullptr;
AlbumThumbnail *_pressedThumb = nullptr;
QPoint _draggedStartPosition; QPoint _draggedStartPosition;
base::Timer _dragTimer;
AttachButtonType _pressedButtonType = AttachButtonType::None; AttachButtonType _pressedButtonType = AttachButtonType::None;
rpl::event_stream<int> _thumbDeleted; rpl::event_stream<int> _thumbDeleted;

View file

@ -29,6 +29,7 @@ AlbumThumbnail::AlbumThumbnail(
: _layout(layout) : _layout(layout)
, _fullPreview(file.preview) , _fullPreview(file.preview)
, _shrinkSize(int(std::ceil(st::historyMessageRadius / 1.4))) , _shrinkSize(int(std::ceil(st::historyMessageRadius / 1.4)))
, _isPhoto(file.type == PreparedFile::Type::Photo)
, _isVideo(file.type == PreparedFile::Type::Video) , _isVideo(file.type == PreparedFile::Type::Video)
, _buttonsRect(st::sendBoxAlbumGroupRadius, st::roundedBg) { , _buttonsRect(st::sendBoxAlbumGroupRadius, st::roundedBg) {
Expects(!_fullPreview.isNull()); Expects(!_fullPreview.isNull());
@ -229,6 +230,8 @@ void AlbumThumbnail::paintInAlbum(
{ x, y }, { x, y },
geometry.width(), geometry.width(),
shrinkProgress); shrinkProgress);
_lastRectOfModify = QRect(QPoint(x, y), geometry.size());
} }
void AlbumThumbnail::prepareCache(QSize size, int shrink) { void AlbumThumbnail::prepareCache(QSize size, int shrink) {
@ -376,21 +379,29 @@ void AlbumThumbnail::drawSimpleFrame(Painter &p, QRect to, QSize size) const {
} }
void AlbumThumbnail::paintPhoto(Painter &p, int left, int top, int outerWidth) { void AlbumThumbnail::paintPhoto(Painter &p, int left, int top, int outerWidth) {
const auto width = _photo.width() / style::DevicePixelRatio(); const auto size = _photo.size() / style::DevicePixelRatio();
p.drawPixmapLeft( p.drawPixmapLeft(
left + (st::sendMediaPreviewSize - width) / 2, left + (st::sendMediaPreviewSize - size.width()) / 2,
top, top,
outerWidth, outerWidth,
_photo); _photo);
const auto topLeft = QPoint{ left, top };
_lastRectOfButtons = paintButtons( _lastRectOfButtons = paintButtons(
p, p,
{ left, top }, topLeft,
st::sendMediaPreviewSize, st::sendMediaPreviewSize,
0); 0);
_lastRectOfModify = QRect(topLeft, size);
} }
void AlbumThumbnail::paintFile(Painter &p, int left, int top, int outerWidth) { void AlbumThumbnail::paintFile(
Painter &p,
int left,
int top,
int outerWidth) {
const auto &st = st::attachPreviewThumbLayout; const auto &st = st::attachPreviewThumbLayout;
const auto textLeft = left + st.thumbSize + st.padding.right(); const auto textLeft = left + st.thumbSize + st.padding.right();
@ -411,6 +422,10 @@ void AlbumThumbnail::paintFile(Painter &p, int left, int top, int outerWidth) {
outerWidth, outerWidth,
_status, _status,
_statusWidth); _statusWidth);
_lastRectOfModify = QRect(
QPoint(left, top),
_fileThumb.size() / style::DevicePixelRatio());
} }
bool AlbumThumbnail::containsPoint(QPoint position) const { bool AlbumThumbnail::containsPoint(QPoint position) const {
@ -418,14 +433,18 @@ bool AlbumThumbnail::containsPoint(QPoint position) const {
} }
bool AlbumThumbnail::buttonsContainPoint(QPoint position) const { bool AlbumThumbnail::buttonsContainPoint(QPoint position) const {
return _lastRectOfButtons.contains(position); return (_isPhoto
? _lastRectOfModify
: _lastRectOfButtons).contains(position);
} }
AttachButtonType AlbumThumbnail::buttonTypeFromPoint(QPoint position) const { AttachButtonType AlbumThumbnail::buttonTypeFromPoint(QPoint position) const {
if (!buttonsContainPoint(position)) { if (!buttonsContainPoint(position)) {
return AttachButtonType::None; return AttachButtonType::None;
} }
return (position.x() < _lastRectOfButtons.center().x()) return !_lastRectOfButtons.contains(position)
? AttachButtonType::Modify
: (position.x() < _lastRectOfButtons.center().x())
? AttachButtonType::Edit ? AttachButtonType::Edit
: AttachButtonType::Delete; : AttachButtonType::Delete;
} }

View file

@ -70,7 +70,9 @@ private:
GroupMediaLayout _layout; GroupMediaLayout _layout;
std::optional<QRect> _animateFromGeometry; std::optional<QRect> _animateFromGeometry;
const QImage _fullPreview; const QImage _fullPreview;
const int _shrinkSize = 0; const int _shrinkSize;
const bool _isPhoto;
const bool _isVideo;
QPixmap _albumImage; QPixmap _albumImage;
QImage _albumCache; QImage _albumCache;
QPoint _albumPosition; QPoint _albumPosition;
@ -81,12 +83,12 @@ private:
QString _status; QString _status;
int _nameWidth = 0; int _nameWidth = 0;
int _statusWidth = 0; int _statusWidth = 0;
bool _isVideo = false;
float64 _suggestedMove = 0.; float64 _suggestedMove = 0.;
Animations::Simple _suggestedMoveAnimation; Animations::Simple _suggestedMoveAnimation;
int _lastShrinkValue = 0; int _lastShrinkValue = 0;
RoundRect _buttonsRect; RoundRect _buttonsRect;
QRect _lastRectOfModify;
QRect _lastRectOfButtons; QRect _lastRectOfButtons;
object_ptr<IconButton> _editMedia = { nullptr }; object_ptr<IconButton> _editMedia = { nullptr };

View file

@ -276,16 +276,4 @@ QPixmap PrepareSongCoverForThumbnail(QImage image, int size) {
&st::songCoverOverlayFg)); &st::songCoverOverlayFg));
} }
void AddPhotoEditorMenu(not_null<Ui::RpWidget*> parent, Fn<void()> callback) {
const auto menu = std::make_shared<base::unique_qptr<Ui::PopupMenu>>();
parent->events(
) | rpl::start_with_next([=](not_null<QEvent*> e) {
if (e->type() == QEvent::ContextMenu) {
*menu = base::make_unique_q<Ui::PopupMenu>(parent);
(*menu)->addAction("Photo Editor", callback);
(*menu)->popup(QCursor::pos());
}
}, parent->lifetime());
}
} // namespace Ui } // namespace Ui

View file

@ -138,6 +138,4 @@ struct PreparedGroup {
[[nodiscard]] QPixmap PrepareSongCoverForThumbnail(QImage image, int size); [[nodiscard]] QPixmap PrepareSongCoverForThumbnail(QImage image, int size);
void AddPhotoEditorMenu(not_null<Ui::RpWidget*> parent, Fn<void()> callback);
} // namespace Ui } // namespace Ui

View file

@ -14,6 +14,7 @@ namespace Ui {
enum class AttachButtonType { enum class AttachButtonType {
Edit, Edit,
Delete, Delete,
Modify,
None, None,
}; };

View file

@ -68,6 +68,7 @@ SingleMediaPreview::SingleMediaPreview(
, _gifPaused(std::move(gifPaused)) , _gifPaused(std::move(gifPaused))
, _animated(animated) , _animated(animated)
, _sticker(sticker) , _sticker(sticker)
, _photoEditorButton(base::make_unique_q<AbstractButton>(this))
, _editMedia(this, st::sendBoxAlbumGroupButtonMedia) , _editMedia(this, st::sendBoxAlbumGroupButtonMedia)
, _deleteMedia(this, st::sendBoxAlbumGroupButtonMedia) , _deleteMedia(this, st::sendBoxAlbumGroupButtonMedia)
, _buttonsRect(st::sendBoxAlbumGroupRadius, st::roundedBg) { , _buttonsRect(st::sendBoxAlbumGroupRadius, st::roundedBg) {
@ -76,8 +77,6 @@ SingleMediaPreview::SingleMediaPreview(
_deleteMedia->setIconOverride(&st::sendBoxAlbumGroupButtonMediaDelete); _deleteMedia->setIconOverride(&st::sendBoxAlbumGroupButtonMediaDelete);
preparePreview(preview, animatedPreviewPath); preparePreview(preview, animatedPreviewPath);
Ui::AddPhotoEditorMenu(this, [=] { _modifyRequests.fire({}); });
} }
SingleMediaPreview::~SingleMediaPreview() = default; SingleMediaPreview::~SingleMediaPreview() = default;
@ -91,7 +90,7 @@ rpl::producer<> SingleMediaPreview::editRequests() const {
} }
rpl::producer<> SingleMediaPreview::modifyRequests() const { rpl::producer<> SingleMediaPreview::modifyRequests() const {
return _modifyRequests.events(); return _photoEditorButton->clicks() | rpl::to_empty;
} }
void SingleMediaPreview::preparePreview( void SingleMediaPreview::preparePreview(
@ -159,6 +158,13 @@ void SingleMediaPreview::preparePreview(
prepareAnimatedPreview(animatedPreviewPath); prepareAnimatedPreview(animatedPreviewPath);
_photoEditorButton->resize(_previewWidth, _previewHeight);
_photoEditorButton->moveToLeft(_previewLeft, 0);
_photoEditorButton->setVisible(!_sticker
&& !_gifPreview
&& !_lottiePreview
&& !_animated);
resize(width(), _previewHeight); resize(width(), _previewHeight);
} }

View file

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once #pragma once
#include "ui/rp_widget.h" #include "ui/rp_widget.h"
#include "ui/abstract_button.h"
#include "ui/round_rect.h" #include "ui/round_rect.h"
#include "media/clip/media_clip_reader.h" #include "media/clip/media_clip_reader.h"
#include "base/object_ptr.h" #include "base/object_ptr.h"
@ -62,6 +63,7 @@ private:
Media::Clip::ReaderPointer _gifPreview; Media::Clip::ReaderPointer _gifPreview;
std::unique_ptr<Lottie::SinglePlayer> _lottiePreview; std::unique_ptr<Lottie::SinglePlayer> _lottiePreview;
base::unique_qptr<AbstractButton> _photoEditorButton;
object_ptr<IconButton> _editMedia = { nullptr }; object_ptr<IconButton> _editMedia = { nullptr };
object_ptr<IconButton> _deleteMedia = { nullptr }; object_ptr<IconButton> _deleteMedia = { nullptr };
RoundRect _buttonsRect; RoundRect _buttonsRect;