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

View file

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

View file

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

View file

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

View file

@ -276,16 +276,4 @@ QPixmap PrepareSongCoverForThumbnail(QImage image, int size) {
&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

View file

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

View file

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

View file

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

View file

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