Added file preview to shared media drag.

This commit is contained in:
23rd
2026-06-25 12:35:10 +03:00
parent 8fa4ccb9f9
commit ff3eb41541
3 changed files with 93 additions and 49 deletions
@@ -2148,10 +2148,19 @@ void ListWidget::performDrag() {
auto mimeData = std::make_unique<QMimeData>();
mimeData->setUrls({ QUrl::fromLocalFile(filepath) });
auto pixmap = QPixmap();
if (const auto layout = _provider->lookupLayout(_pressState.item)) {
if (const auto file = dynamic_cast<Overview::Layout::Document*>(
layout)) {
pixmap = Ui::PixmapFromImage(file->dragPreviewImage());
}
}
// This call enters event loop and can destroy any QObject.
_controller->parentController()->widget()->launchDrag(
std::move(mimeData),
crl::guard(this, [=] { mouseActionUpdate(QCursor::pos()); }));
crl::guard(this, [=] { mouseActionUpdate(QCursor::pos()); }),
std::move(pixmap));
}
void ListWidget::mouseActionFinish(
@@ -1385,54 +1385,7 @@ void Document::paint(Painter &p, const QRect &clip, TextSelection selection, con
QRect rthumb(style::rtlrect(0, st::linksBorder + _st.filePadding.top(), _st.fileThumbSize, _st.fileThumbSize, _width));
if (clip.intersects(rthumb)) {
if (wthumb) {
ensureDataMediaCreated();
const auto good = _data->isSvgImage()
? _dataMedia->goodThumbnail()
: nullptr;
const auto thumbnail = good
? good
: _dataMedia->thumbnail();
const auto blurred = _dataMedia->thumbnailInline();
if (thumbnail || blurred) {
if (_thumb.isNull() || (thumbnail && !_thumbLoaded)) {
_thumbLoaded = (thumbnail != nullptr);
const auto options = Images::Option::RoundSmall
| (_thumbLoaded
? Images::Option()
: Images::Option::Blur);
const auto image = thumbnail ? thumbnail : blurred;
_thumb = image->pixNoCache(
_thumbw * style::DevicePixelRatio(),
{
.options = options,
.outer = QSize(
_st.fileThumbSize,
_st.fileThumbSize),
});
}
p.drawPixmap(rthumb.topLeft(), _thumb);
} else {
p.setPen(Qt::NoPen);
p.setBrush(st::overviewFileThumbBg);
p.drawRoundedRect(
rthumb,
st::roundRadiusSmall,
st::roundRadiusSmall);
}
} else {
p.setPen(Qt::NoPen);
p.setBrush(_generic.color);
p.drawRoundedRect(
rthumb,
st::roundRadiusSmall,
st::roundRadiusSmall);
if (!radial && loaded && !_ext.isEmpty()) {
p.setFont(st::overviewFileExtFont);
p.setPen(st::overviewFileExtFg);
p.drawText(rthumb.left() + (rthumb.width() - _extw) / 2, rthumb.top() + st::overviewFileExtTop + st::overviewFileExtFont->ascent, _ext);
}
}
paintThumbnail(p, rthumb, wthumb, !radial && loaded);
if (selected) {
p.setPen(Qt::NoPen);
p.setBrush(st::defaultTextPalette.selectOverlay);
@@ -1516,6 +1469,85 @@ void Document::paint(Painter &p, const QRect &clip, TextSelection selection, con
paintCheckbox(p, { checkLeft, checkTop }, selected, context);
}
void Document::paintThumbnail(
Painter &p,
QRect rthumb,
bool wthumb,
bool withExt) {
if (wthumb) {
ensureDataMediaCreated();
const auto good = _data->isSvgImage()
? _dataMedia->goodThumbnail()
: nullptr;
const auto thumbnail = good
? good
: _dataMedia->thumbnail();
const auto blurred = _dataMedia->thumbnailInline();
if (thumbnail || blurred) {
if (_thumb.isNull() || (thumbnail && !_thumbLoaded)) {
_thumbLoaded = (thumbnail != nullptr);
const auto options = Images::Option::RoundSmall
| (_thumbLoaded
? Images::Option()
: Images::Option::Blur);
const auto image = thumbnail ? thumbnail : blurred;
_thumb = image->pixNoCache(
_thumbw * style::DevicePixelRatio(),
{
.options = options,
.outer = QSize(
_st.fileThumbSize,
_st.fileThumbSize),
});
}
p.drawPixmap(rthumb.topLeft(), _thumb);
} else {
p.setPen(Qt::NoPen);
p.setBrush(st::overviewFileThumbBg);
p.drawRoundedRect(
rthumb,
st::roundRadiusSmall,
st::roundRadiusSmall);
}
} else {
p.setPen(Qt::NoPen);
p.setBrush(_generic.color);
p.drawRoundedRect(
rthumb,
st::roundRadiusSmall,
st::roundRadiusSmall);
if (withExt && !_ext.isEmpty()) {
p.setFont(st::overviewFileExtFont);
p.setPen(st::overviewFileExtFg);
p.drawText(
rthumb.left() + (rthumb.width() - _extw) / 2,
rthumb.top()
+ st::overviewFileExtTop
+ st::overviewFileExtFont->ascent,
_ext);
}
}
}
QImage Document::dragPreviewImage() {
ensureDataMediaCreated();
const auto ratio = style::DevicePixelRatio();
auto result = QImage(
QSize(_st.fileThumbSize, _st.fileThumbSize) * ratio,
QImage::Format_ARGB32_Premultiplied);
result.setDevicePixelRatio(ratio);
result.fill(Qt::transparent);
auto p = Painter(&result);
auto hq = PainterHighQualityEnabler(p);
paintThumbnail(
p,
QRect(0, 0, _st.fileThumbSize, _st.fileThumbSize),
withThumb(),
true);
return result;
}
void Document::drawCornerDownload(QPainter &p, bool selected, const PaintContext *context) const {
if (dataLoaded()
|| _data->loadedInMediaCache()
@@ -422,6 +422,8 @@ public:
void clearHeavyPart() override;
[[nodiscard]] QImage dragPreviewImage();
protected:
float64 dataProgress() const override;
bool dataFinished() const override;
@@ -438,6 +440,7 @@ private:
[[nodiscard]] bool songLayout() const;
void ensureDataMediaCreated() const;
void paintThumbnail(Painter &p, QRect rthumb, bool wthumb, bool withExt);
not_null<DocumentData*> _data;
mutable std::shared_ptr<Data::DocumentMedia> _dataMedia;