Remove special case in SendFilesBox for an image.

This commit is contained in:
John Preston 2017-12-21 20:15:37 +04:00
parent ec515080b5
commit ff65daa9fe
14 changed files with 367 additions and 299 deletions

View File

@ -2729,8 +2729,6 @@ void ApiWrap::sendVoiceMessage(
void ApiWrap::sendFiles( void ApiWrap::sendFiles(
Storage::PreparedList &&list, Storage::PreparedList &&list,
const QByteArray &content,
const QImage &image,
SendMediaType type, SendMediaType type,
QString caption, QString caption,
std::shared_ptr<SendingAlbum> album, std::shared_ptr<SendingAlbum> album,
@ -2759,23 +2757,14 @@ void ApiWrap::sendFiles(
default: Unexpected("AlbumType in uploadFilesAfterConfirmation"); default: Unexpected("AlbumType in uploadFilesAfterConfirmation");
} }
} }
if (file.path.isEmpty() && (!image.isNull() || !content.isNull())) { tasks.push_back(std::make_unique<FileLoadTask>(
tasks.push_back(std::make_unique<FileLoadTask>( file.path,
content, file.content,
image, std::move(file.information),
type, type,
to, to,
caption, caption,
album)); album));
} else {
tasks.push_back(std::make_unique<FileLoadTask>(
file.path,
std::move(file.information),
type,
to,
caption,
album));
}
} }
if (album) { if (album) {
_sendingAlbums.emplace(album->groupId, album); _sendingAlbums.emplace(album->groupId, album);
@ -2794,8 +2783,9 @@ void ApiWrap::sendFile(
auto to = FileLoadTaskOptions(options); auto to = FileLoadTaskOptions(options);
auto caption = QString(); auto caption = QString();
_fileLoader->addTask(std::make_unique<FileLoadTask>( _fileLoader->addTask(std::make_unique<FileLoadTask>(
QString(),
fileContent, fileContent,
QImage(), nullptr,
type, type,
to, to,
caption)); caption));

View File

@ -197,8 +197,6 @@ public:
const SendOptions &options); const SendOptions &options);
void sendFiles( void sendFiles(
Storage::PreparedList &&list, Storage::PreparedList &&list,
const QByteArray &content,
const QImage &image,
SendMediaType type, SendMediaType type,
QString caption, QString caption,
std::shared_ptr<SendingAlbum> album, std::shared_ptr<SendingAlbum> album,

View File

@ -2508,19 +2508,26 @@ namespace {
#endif // !TDESKTOP_DISABLE_NETWORK_PROXY #endif // !TDESKTOP_DISABLE_NETWORK_PROXY
} }
void complexAdjustRect(RectParts corners, QRect &rect, RectParts &parts) { void rectWithCorners(Painter &p, QRect rect, const style::color &bg, RoundCorners index, RectParts corners) {
if (corners & RectPart::TopLeft) { auto parts = RectPart::Top
if (!(corners & RectPart::BottomLeft)) { | RectPart::NoTopBottom
parts = RectPart::NoTopBottom | RectPart::FullTop; | RectPart::Bottom
rect.setHeight(rect.height() + msgRadius()); | corners;
roundRect(p, rect, bg, index, nullptr, parts);
if ((corners & RectPart::AllCorners) != RectPart::AllCorners) {
const auto size = ::corners[index].p[0].width() / cIntRetinaFactor();
if (!(corners & RectPart::TopLeft)) {
p.fillRect(rect.x(), rect.y(), size, size, bg);
}
if (!(corners & RectPart::TopRight)) {
p.fillRect(rect.x() + rect.width() - size, rect.y(), size, size, bg);
}
if (!(corners & RectPart::BottomLeft)) {
p.fillRect(rect.x(), rect.y() + rect.height() - size, size, size, bg);
}
if (!(corners & RectPart::BottomRight)) {
p.fillRect(rect.x() + rect.width() - size, rect.y() + rect.height() - size, size, size, bg);
} }
} else if (corners & RectPart::BottomLeft) {
parts = RectPart::NoTopBottom | RectPart::FullBottom;
rect.setTop(rect.y() - msgRadius());
} else {
parts = RectPart::NoTopBottom;
rect.setTop(rect.y() - msgRadius());
rect.setHeight(rect.height() + msgRadius());
} }
} }
@ -2534,18 +2541,13 @@ namespace {
auto overlayCorners = (radius == ImageRoundRadius::Small) auto overlayCorners = (radius == ImageRoundRadius::Small)
? SelectedOverlaySmallCorners ? SelectedOverlaySmallCorners
: SelectedOverlayLargeCorners; : SelectedOverlayLargeCorners;
auto overlayParts = RectPart::Full | RectPart::None; const auto bg = p.textPalette().selectOverlay;
if (radius == ImageRoundRadius::Large) { rectWithCorners(p, rect, bg, overlayCorners, corners);
complexAdjustRect(corners, rect, overlayParts);
}
roundRect(p, rect, p.textPalette().selectOverlay, overlayCorners, nullptr, overlayParts);
} }
} }
void complexLocationRect(Painter &p, QRect rect, ImageRoundRadius radius, RectParts corners) { void complexLocationRect(Painter &p, QRect rect, ImageRoundRadius radius, RectParts corners) {
auto parts = RectPart::Full | RectPart::None; rectWithCorners(p, rect, st::msgInBg, MessageInCorners, corners);
complexAdjustRect(corners, rect, parts);
roundRect(p, rect, st::msgInBg, MessageInCorners, nullptr, parts);
} }
QImage *cornersMask(ImageRoundRadius radius) { QImage *cornersMask(ImageRoundRadius radius) {

View File

@ -250,7 +250,6 @@ void AbstractBox::paintEvent(QPaintEvent *e) {
auto paintBottomRounded = clip.intersects(QRect(0, height() - st::boxRadius, width(), st::boxRadius)); auto paintBottomRounded = clip.intersects(QRect(0, height() - st::boxRadius, width(), st::boxRadius));
if (paintTopRounded || paintBottomRounded) { if (paintTopRounded || paintBottomRounded) {
auto parts = RectPart::None | 0; auto parts = RectPart::None | 0;
parts |= RectPart::None;
if (paintTopRounded) parts |= RectPart::FullTop; if (paintTopRounded) parts |= RectPart::FullTop;
if (paintBottomRounded) parts |= RectPart::FullBottom; if (paintBottomRounded) parts |= RectPart::FullBottom;
App::roundRect(p, rect(), st::boxBg, BoxCorners, nullptr, parts); App::roundRect(p, rect(), st::boxBg, BoxCorners, nullptr, parts);

View File

@ -29,7 +29,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "ui/widgets/checkbox.h" #include "ui/widgets/checkbox.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h" #include "ui/widgets/input_fields.h"
#include "ui/empty_userpic.h"
#include "ui/grouped_layout.h" #include "ui/grouped_layout.h"
#include "styles/style_history.h" #include "styles/style_history.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
@ -42,15 +41,10 @@ constexpr auto kMinPreviewWidth = 20;
} // namespace } // namespace
SendFilesBox::SendFilesBox(QWidget*, QImage image, CompressConfirm compressed) SendFilesBox::SendFilesBox(
: _image(image) QWidget*,
, _compressConfirm(compressed) Storage::PreparedList &&list,
, _caption(this, st::confirmCaptionArea, langFactory(lng_photo_caption)) { CompressConfirm compressed)
_list.files.push_back({ QString() });
prepareSingleFileLayout();
}
SendFilesBox::SendFilesBox(QWidget*, Storage::PreparedList &&list, CompressConfirm compressed)
: _list(std::move(list)) : _list(std::move(list))
, _compressConfirm(compressed) , _compressConfirm(compressed)
, _caption( , _caption(
@ -66,34 +60,54 @@ SendFilesBox::SendFilesBox(QWidget*, Storage::PreparedList &&list, CompressConfi
void SendFilesBox::prepareSingleFileLayout() { void SendFilesBox::prepareSingleFileLayout() {
Expects(_list.files.size() == 1); Expects(_list.files.size() == 1);
if (!_list.files.front().path.isEmpty()) {
tryToReadSingleFile(); const auto &file = _list.files[0];
auto preview = QImage();
if (const auto image = base::get_if<FileMediaInformation::Image>(
&file.information->media)) {
preview = image->data;
_animated = image->animated;
} else if (const auto video = base::get_if<FileMediaInformation::Video>(
&file.information->media)) {
preview = video->thumbnail;
_animated = true;
} }
if (!Storage::ValidateThumbDimensions(_image.width(), _image.height()) if (!Storage::ValidateThumbDimensions(preview.width(), preview.height())
|| _animated) { || _animated) {
_compressConfirm = CompressConfirm::None; _compressConfirm = CompressConfirm::None;
} }
if (!_image.isNull()) { if (!preview.isNull()) {
auto image = _image;
if (!_animated && _compressConfirm == CompressConfirm::None) { if (!_animated && _compressConfirm == CompressConfirm::None) {
auto originalWidth = image.width(); auto originalWidth = preview.width();
auto originalHeight = image.height(); auto originalHeight = preview.height();
auto thumbWidth = st::msgFileThumbSize; auto thumbWidth = st::msgFileThumbSize;
if (originalWidth > originalHeight) { if (originalWidth > originalHeight) {
thumbWidth = (originalWidth * st::msgFileThumbSize) / originalHeight; thumbWidth = (originalWidth * st::msgFileThumbSize)
/ originalHeight;
} }
auto options = Images::Option::Smooth | Images::Option::RoundedSmall | Images::Option::RoundedTopLeft | Images::Option::RoundedTopRight | Images::Option::RoundedBottomLeft | Images::Option::RoundedBottomRight; auto options = Images::Option::Smooth
_fileThumb = Images::pixmap(image, thumbWidth * cIntRetinaFactor(), 0, options, st::msgFileThumbSize, st::msgFileThumbSize); | Images::Option::RoundedSmall
| Images::Option::RoundedTopLeft
| Images::Option::RoundedTopRight
| Images::Option::RoundedBottomLeft
| Images::Option::RoundedBottomRight;
_fileThumb = Images::pixmap(
preview,
thumbWidth * cIntRetinaFactor(),
0,
options,
st::msgFileThumbSize,
st::msgFileThumbSize);
} else { } else {
auto maxW = 0; auto maxW = 0;
auto maxH = 0; auto maxH = 0;
if (_animated) { if (_animated) {
auto limitW = st::sendMediaPreviewSize; auto limitW = st::sendMediaPreviewSize;
auto limitH = st::confirmMaxHeight; auto limitH = st::confirmMaxHeight;
maxW = qMax(image.width(), 1); maxW = qMax(preview.width(), 1);
maxH = qMax(image.height(), 1); maxH = qMax(preview.height(), 1);
if (maxW * limitH > maxH * limitW) { if (maxW * limitH > maxH * limitW) {
if (maxW < limitW) { if (maxW < limitW) {
maxH = maxH * limitW / maxW; maxH = maxH * limitW / maxW;
@ -105,16 +119,22 @@ void SendFilesBox::prepareSingleFileLayout() {
maxH = limitH; maxH = limitH;
} }
} }
image = Images::prepare(image, maxW * cIntRetinaFactor(), maxH * cIntRetinaFactor(), Images::Option::Smooth | Images::Option::Blurred, maxW, maxH); preview = Images::prepare(
preview,
maxW * cIntRetinaFactor(),
maxH * cIntRetinaFactor(),
Images::Option::Smooth | Images::Option::Blurred,
maxW,
maxH);
} }
auto originalWidth = image.width(); auto originalWidth = preview.width();
auto originalHeight = image.height(); auto originalHeight = preview.height();
if (!originalWidth || !originalHeight) { if (!originalWidth || !originalHeight) {
originalWidth = originalHeight = 1; originalWidth = originalHeight = 1;
} }
_previewWidth = st::sendMediaPreviewSize; _previewWidth = st::sendMediaPreviewSize;
if (image.width() < _previewWidth) { if (preview.width() < _previewWidth) {
_previewWidth = qMax(image.width(), kMinPreviewWidth); _previewWidth = qMax(preview.width(), kMinPreviewWidth);
} }
auto maxthumbh = qMin(qRound(1.5 * _previewWidth), st::confirmMaxHeight); auto maxthumbh = qMin(qRound(1.5 * _previewWidth), st::confirmMaxHeight);
_previewHeight = qRound(originalHeight * float64(_previewWidth) / originalWidth); _previewHeight = qRound(originalHeight * float64(_previewWidth) / originalWidth);
@ -125,9 +145,13 @@ void SendFilesBox::prepareSingleFileLayout() {
} }
_previewLeft = (st::boxWideWidth - _previewWidth) / 2; _previewLeft = (st::boxWideWidth - _previewWidth) / 2;
image = std::move(image).scaled(_previewWidth * cIntRetinaFactor(), _previewHeight * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); preview = std::move(preview).scaled(
image = Images::prepareOpaque(std::move(image)); _previewWidth * cIntRetinaFactor(),
_preview = App::pixmapFromImageInPlace(std::move(image)); _previewHeight * cIntRetinaFactor(),
Qt::IgnoreAspectRatio,
Qt::SmoothTransformation);
preview = Images::prepareOpaque(std::move(preview));
_preview = App::pixmapFromImageInPlace(std::move(preview));
_preview.setDevicePixelRatio(cRetinaFactor()); _preview.setDevicePixelRatio(cRetinaFactor());
prepareGifPreview(); prepareGifPreview();
@ -191,9 +215,12 @@ void SendFilesBox::prepareDocumentLayout() {
const auto &file = _list.files.front(); const auto &file = _list.files.front();
const auto filepath = file.path; const auto filepath = file.path;
if (filepath.isEmpty()) { if (filepath.isEmpty()) {
const auto data = base::get_if<FileMediaInformation::Image>(
&file.information->media);
const auto image = data ? data->data : QImage();
auto filename = filedialogDefaultName(qsl("image"), qsl(".png"), QString(), true); auto filename = filedialogDefaultName(qsl("image"), qsl(".png"), QString(), true);
_nameText.setText(st::semiboldTextStyle, filename, _textNameOptions); _nameText.setText(st::semiboldTextStyle, filename, _textNameOptions);
_statusText = qsl("%1x%2").arg(_image.width()).arg(_image.height()); _statusText = qsl("%1x%2").arg(image.width()).arg(image.height());
_statusWidth = qMax(_nameText.maxWidth(), st::normalFont->width(_statusText)); _statusWidth = qMax(_nameText.maxWidth(), st::normalFont->width(_statusText));
_fileIsImage = true; _fileIsImage = true;
} else { } else {
@ -227,40 +254,6 @@ void SendFilesBox::prepareDocumentLayout() {
} }
} }
void SendFilesBox::tryToReadSingleFile() {
auto &file = _list.files.front();
auto filepath = file.path;
auto filemime = mimeTypeForFile(QFileInfo(filepath)).name();
if (!file.information) {
file.information = FileLoadTask::ReadMediaInformation(
filepath,
QByteArray(),
filemime);
}
if (const auto image = base::get_if<FileMediaInformation::Image>(
&file.information->media)) {
_image = image->data;
_animated = image->animated;
} else if (const auto video = base::get_if<FileMediaInformation::Video>(
&file.information->media)) {
_image = video->thumbnail;
_animated = true;
}
}
SendFilesBox::SendFilesBox(QWidget*, const QString &phone, const QString &firstname, const QString &lastname)
: _contactPhone(phone)
, _contactFirstName(firstname)
, _contactLastName(lastname) {
auto name = lng_full_name(lt_first_name, _contactFirstName, lt_last_name, _contactLastName);
_nameText.setText(st::semiboldTextStyle, name, _textNameOptions);
_statusText = _contactPhone;
_statusWidth = qMax(_nameText.maxWidth(), st::normalFont->width(_statusText));
_contactPhotoEmpty = std::make_unique<Ui::EmptyUserpic>(
Data::PeerUserpicColor(0),
name);
}
void SendFilesBox::prepare() { void SendFilesBox::prepare() {
Expects(controller() != nullptr); Expects(controller() != nullptr);
@ -304,9 +297,7 @@ void SendFilesBox::prepare() {
} }
base::lambda<QString()> SendFilesBox::getSendButtonText() const { base::lambda<QString()> SendFilesBox::getSendButtonText() const {
if (!_contactPhone.isEmpty()) { if (_compressed && _compressed->checked()) {
return langFactory(lng_send_button);
} else if (_compressed && _compressed->checked()) {
return [count = _list.files.size()] { return [count = _list.files.size()] {
return lng_send_photos(lt_count, count); return lng_send_photos(lt_count, count);
}; };
@ -429,21 +420,17 @@ void SendFilesBox::paintEvent(QPaintEvent *e) {
App::roundRect(p, x, y, w, h, st::msgOutBg, MessageOutCorners, &st::msgOutShadow); App::roundRect(p, x, y, w, h, st::msgOutBg, MessageOutCorners, &st::msgOutShadow);
if (_fileThumb.isNull()) { if (_fileThumb.isNull()) {
if (_contactPhone.isNull()) { QRect inner(rtlrect(x + st::msgFilePadding.left(), y + st::msgFilePadding.top(), st::msgFileSize, st::msgFileSize, width()));
QRect inner(rtlrect(x + st::msgFilePadding.left(), y + st::msgFilePadding.top(), st::msgFileSize, st::msgFileSize, width())); p.setPen(Qt::NoPen);
p.setPen(Qt::NoPen); p.setBrush(st::msgFileOutBg);
p.setBrush(st::msgFileOutBg);
{ {
PainterHighQualityEnabler hq(p); PainterHighQualityEnabler hq(p);
p.drawEllipse(inner); p.drawEllipse(inner);
}
auto &icon = _fileIsAudio ? st::historyFileOutPlay : _fileIsImage ? st::historyFileOutImage : st::historyFileOutDocument;
icon.paintInCenter(p, inner);
} else {
_contactPhotoEmpty->paint(p, x + st::msgFilePadding.left(), y + st::msgFilePadding.top(), width(), st::msgFileSize);
} }
auto &icon = _fileIsAudio ? st::historyFileOutPlay : _fileIsImage ? st::historyFileOutImage : st::historyFileOutDocument;
icon.paintInCenter(p, inner);
} else { } else {
QRect rthumb(rtlrect(x + st::msgFileThumbPadding.left(), y + st::msgFileThumbPadding.top(), st::msgFileThumbSize, st::msgFileThumbSize, width())); QRect rthumb(rtlrect(x + st::msgFileThumbPadding.left(), y + st::msgFileThumbPadding.top(), st::msgFileThumbSize, st::msgFileThumbSize, width()));
p.drawPixmap(rthumb.topLeft(), _fileThumb); p.drawPixmap(rthumb.topLeft(), _fileThumb);
@ -496,7 +483,6 @@ void SendFilesBox::send(bool ctrlShiftEnter) {
auto caption = _caption ? TextUtilities::PrepareForSending(_caption->getLastText(), TextUtilities::PrepareTextOption::CheckLinks) : QString(); auto caption = _caption ? TextUtilities::PrepareForSending(_caption->getLastText(), TextUtilities::PrepareTextOption::CheckLinks) : QString();
_confirmedCallback( _confirmedCallback(
std::move(_list), std::move(_list),
_animated ? QImage() : _image,
compressed, compressed,
caption, caption,
ctrlShiftEnter); ctrlShiftEnter);

View File

@ -28,17 +28,22 @@ namespace Ui {
class Checkbox; class Checkbox;
class RoundButton; class RoundButton;
class InputArea; class InputArea;
class EmptyUserpic;
struct GroupMediaLayout; struct GroupMediaLayout;
} // namespace Ui } // namespace Ui
class SendFilesBox : public BoxContent { class SendFilesBox : public BoxContent {
public: public:
SendFilesBox(QWidget*, QImage image, CompressConfirm compressed); SendFilesBox(
SendFilesBox(QWidget*, Storage::PreparedList &&list, CompressConfirm compressed); QWidget*,
SendFilesBox(QWidget*, const QString &phone, const QString &firstname, const QString &lastname); Storage::PreparedList &&list,
CompressConfirm compressed);
void setConfirmedCallback(base::lambda<void(Storage::PreparedList &&list, const QImage &image, bool compressed, const QString &caption, bool ctrlShiftEnter)> callback) { void setConfirmedCallback(
base::lambda<void(
Storage::PreparedList &&list,
bool compressed,
const QString &caption,
bool ctrlShiftEnter)> callback) {
_confirmedCallback = std::move(callback); _confirmedCallback = std::move(callback);
} }
void setCancelledCallback(base::lambda<void()> callback) { void setCancelledCallback(base::lambda<void()> callback) {
@ -58,7 +63,6 @@ protected:
private: private:
void prepareSingleFileLayout(); void prepareSingleFileLayout();
void prepareDocumentLayout(); void prepareDocumentLayout();
void tryToReadSingleFile();
void prepareGifPreview(); void prepareGifPreview();
void clipCallback(Media::Clip::Notification notification); void clipCallback(Media::Clip::Notification notification);
@ -73,7 +77,6 @@ private:
QString _titleText; QString _titleText;
Storage::PreparedList _list; Storage::PreparedList _list;
QImage _image;
CompressConfirm _compressConfirm = CompressConfirm::None; CompressConfirm _compressConfirm = CompressConfirm::None;
bool _animated = false; bool _animated = false;
@ -91,12 +94,11 @@ private:
QString _statusText; QString _statusText;
int _statusWidth = 0; int _statusWidth = 0;
QString _contactPhone; base::lambda<void(
QString _contactFirstName; Storage::PreparedList &&list,
QString _contactLastName; bool compressed,
std::unique_ptr<Ui::EmptyUserpic> _contactPhotoEmpty; const QString &caption,
bool ctrlShiftEnter)> _confirmedCallback;
base::lambda<void(Storage::PreparedList &&list, const QImage &image, bool compressed, const QString &caption, bool ctrlShiftEnter)> _confirmedCallback;
base::lambda<void()> _cancelledCallback; base::lambda<void()> _cancelledCallback;
bool _confirmed = false; bool _confirmed = false;
@ -111,7 +113,11 @@ class SendAlbumBox : public BoxContent {
public: public:
SendAlbumBox(QWidget*, Storage::PreparedList &&list); SendAlbumBox(QWidget*, Storage::PreparedList &&list);
void setConfirmedCallback(base::lambda<void(Storage::PreparedList &&list, const QString &caption, bool ctrlShiftEnter)> callback) { void setConfirmedCallback(
base::lambda<void(
Storage::PreparedList &&list,
const QString &caption,
bool ctrlShiftEnter)> callback) {
_confirmedCallback = std::move(callback); _confirmedCallback = std::move(callback);
} }
void setCancelledCallback(base::lambda<void()> callback) { void setCancelledCallback(base::lambda<void()> callback) {

View File

@ -26,7 +26,11 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "base/task_queue.h" #include "base/task_queue.h"
#include "messenger.h" #include "messenger.h"
bool filedialogGetSaveFile(QString &file, const QString &caption, const QString &filter, const QString &initialPath) { bool filedialogGetSaveFile(
QString &file,
const QString &caption,
const QString &filter,
const QString &initialPath) {
QStringList files; QStringList files;
QByteArray remoteContent; QByteArray remoteContent;
bool result = Platform::FileDialog::Get(files, remoteContent, caption, filter, FileDialog::internal::Type::WriteFile, initialPath); bool result = Platform::FileDialog::Get(files, remoteContent, caption, filter, FileDialog::internal::Type::WriteFile, initialPath);
@ -34,7 +38,12 @@ bool filedialogGetSaveFile(QString &file, const QString &caption, const QString
return result; return result;
} }
QString filedialogDefaultName(const QString &prefix, const QString &extension, const QString &path, bool skipExistance, int fileTime) { QString filedialogDefaultName(
const QString &prefix,
const QString &extension,
const QString &path,
bool skipExistance,
int fileTime) {
auto directoryPath = path; auto directoryPath = path;
if (directoryPath.isEmpty()) { if (directoryPath.isEmpty()) {
if (cDialogLastPath().isEmpty()) { if (cDialogLastPath().isEmpty()) {
@ -69,7 +78,10 @@ QString filedialogDefaultName(const QString &prefix, const QString &extension, c
return name; return name;
} }
QString filedialogNextFilename(const QString &name, const QString &cur, const QString &path) { QString filedialogNextFilename(
const QString &name,
const QString &cur,
const QString &path) {
QDir dir(path.isEmpty() ? cDialogLastPath() : path); QDir dir(path.isEmpty() ? cDialogLastPath() : path);
int32 extIndex = name.lastIndexOf('.'); int32 extIndex = name.lastIndexOf('.');
QString prefix = name, extension; QString prefix = name, extension;
@ -130,19 +142,30 @@ void UnsafeLaunchDefault(const QString &filepath) {
namespace FileDialog { namespace FileDialog {
void GetOpenPath(const QString &caption, const QString &filter, base::lambda<void(const OpenResult &result)> callback, base::lambda<void()> failed) { void GetOpenPath(
base::TaskQueue::Main().Put([caption, filter, callback = std::move(callback), failed = std::move(failed)] { const QString &caption,
const QString &filter,
base::lambda<void(OpenResult &&result)> callback,
base::lambda<void()> failed) {
base::TaskQueue::Main().Put([=] {
auto files = QStringList(); auto files = QStringList();
auto remoteContent = QByteArray(); auto remoteContent = QByteArray();
if (Platform::FileDialog::Get(files, remoteContent, caption, filter, FileDialog::internal::Type::ReadFile) const auto success = Platform::FileDialog::Get(
&& ((!files.isEmpty() && !files[0].isEmpty()) || !remoteContent.isEmpty())) { files,
remoteContent,
caption,
filter,
FileDialog::internal::Type::ReadFile);
if (success
&& ((!files.isEmpty() && !files[0].isEmpty())
|| !remoteContent.isEmpty())) {
if (callback) { if (callback) {
auto result = OpenResult(); auto result = OpenResult();
if (!files.isEmpty() && !files[0].isEmpty()) { if (!files.isEmpty() && !files[0].isEmpty()) {
result.paths.push_back(files[0]); result.paths.push_back(files[0]);
} }
result.remoteContent = remoteContent; result.remoteContent = remoteContent;
callback(result); callback(std::move(result));
} }
} else if (failed) { } else if (failed) {
failed(); failed();
@ -150,17 +173,26 @@ void GetOpenPath(const QString &caption, const QString &filter, base::lambda<voi
}); });
} }
void GetOpenPaths(const QString &caption, const QString &filter, base::lambda<void(const OpenResult &result)> callback, base::lambda<void()> failed) { void GetOpenPaths(
base::TaskQueue::Main().Put([caption, filter, callback = std::move(callback), failed = std::move(failed)] { const QString &caption,
const QString &filter,
base::lambda<void(OpenResult &&result)> callback,
base::lambda<void()> failed) {
base::TaskQueue::Main().Put([=] {
auto files = QStringList(); auto files = QStringList();
auto remoteContent = QByteArray(); auto remoteContent = QByteArray();
if (Platform::FileDialog::Get(files, remoteContent, caption, filter, FileDialog::internal::Type::ReadFiles) const auto success = Platform::FileDialog::Get(
&& (!files.isEmpty() || !remoteContent.isEmpty())) { files,
remoteContent,
caption,
filter,
FileDialog::internal::Type::ReadFiles);
if (success && (!files.isEmpty() || !remoteContent.isEmpty())) {
if (callback) { if (callback) {
auto result = OpenResult(); auto result = OpenResult();
result.paths = files; result.paths = files;
result.remoteContent = remoteContent; result.remoteContent = remoteContent;
callback(result); callback(std::move(result));
} }
} else if (failed) { } else if (failed) {
failed(); failed();
@ -168,12 +200,17 @@ void GetOpenPaths(const QString &caption, const QString &filter, base::lambda<vo
}); });
} }
void GetWritePath(const QString &caption, const QString &filter, const QString &initialPath, base::lambda<void(const QString &result)> callback, base::lambda<void()> failed) { void GetWritePath(
base::TaskQueue::Main().Put([caption, filter, initialPath, callback = std::move(callback), failed = std::move(failed)] { const QString &caption,
const QString &filter,
const QString &initialPath,
base::lambda<void(QString &&result)> callback,
base::lambda<void()> failed) {
base::TaskQueue::Main().Put([=] {
auto file = QString(); auto file = QString();
if (filedialogGetSaveFile(file, caption, filter, initialPath)) { if (filedialogGetSaveFile(file, caption, filter, initialPath)) {
if (callback) { if (callback) {
callback(file); callback(std::move(file));
} }
} else if (failed) { } else if (failed) {
failed(); failed();
@ -181,14 +218,24 @@ void GetWritePath(const QString &caption, const QString &filter, const QString &
}); });
} }
void GetFolder(const QString &caption, const QString &initialPath, base::lambda<void(const QString &result)> callback, base::lambda<void()> failed) { void GetFolder(
base::TaskQueue::Main().Put([caption, initialPath, callback = std::move(callback), failed = std::move(failed)] { const QString &caption,
const QString &initialPath,
base::lambda<void(QString &&result)> callback,
base::lambda<void()> failed) {
base::TaskQueue::Main().Put([=] {
auto files = QStringList(); auto files = QStringList();
auto remoteContent = QByteArray(); auto remoteContent = QByteArray();
if (Platform::FileDialog::Get(files, remoteContent, caption, QString(), FileDialog::internal::Type::ReadFolder, initialPath) const auto success = Platform::FileDialog::Get(
&& !files.isEmpty() && !files[0].isEmpty()) { files,
remoteContent,
caption,
QString(),
FileDialog::internal::Type::ReadFolder,
initialPath);
if (success && !files.isEmpty() && !files[0].isEmpty()) {
if (callback) { if (callback) {
callback(files[0]); callback(std::move(files[0]));
} }
} else if (failed) { } else if (failed) {
failed(); failed();

View File

@ -23,10 +23,22 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "base/observer.h" #include "base/observer.h"
// legacy // legacy
bool filedialogGetSaveFile(QString &file, const QString &caption, const QString &filter, const QString &initialPath); bool filedialogGetSaveFile(
QString &file,
const QString &caption,
const QString &filter,
const QString &initialPath);
QString filedialogDefaultName(const QString &prefix, const QString &extension, const QString &path = QString(), bool skipExistance = false, int fileTime = 0); QString filedialogDefaultName(
QString filedialogNextFilename(const QString &name, const QString &cur, const QString &path = QString()); const QString &prefix,
const QString &extension,
const QString &path = QString(),
bool skipExistance = false,
int fileTime = 0);
QString filedialogNextFilename(
const QString &name,
const QString &cur,
const QString &path = QString());
namespace File { namespace File {
@ -54,10 +66,27 @@ struct OpenResult {
QStringList paths; QStringList paths;
QByteArray remoteContent; QByteArray remoteContent;
}; };
void GetOpenPath(const QString &caption, const QString &filter, base::lambda<void(const OpenResult &result)> callback, base::lambda<void()> failed = base::lambda<void()>()); void GetOpenPath(
void GetOpenPaths(const QString &caption, const QString &filter, base::lambda<void(const OpenResult &result)> callback, base::lambda<void()> failed = base::lambda<void()>()); const QString &caption,
void GetWritePath(const QString &caption, const QString &filter, const QString &initialPath, base::lambda<void(const QString &result)> callback, base::lambda<void()> failed = base::lambda<void()>()); const QString &filter,
void GetFolder(const QString &caption, const QString &initialPath, base::lambda<void(const QString &result)> callback, base::lambda<void()> failed = base::lambda<void()>()); base::lambda<void(OpenResult &&result)> callback,
base::lambda<void()> failed = base::lambda<void()>());
void GetOpenPaths(
const QString &caption,
const QString &filter,
base::lambda<void(OpenResult &&result)> callback,
base::lambda<void()> failed = base::lambda<void()>());
void GetWritePath(
const QString &caption,
const QString &filter,
const QString &initialPath,
base::lambda<void(QString &&result)> callback,
base::lambda<void()> failed = base::lambda<void()>());
void GetFolder(
const QString &caption,
const QString &initialPath,
base::lambda<void(QString &&result)> callback,
base::lambda<void()> failed = base::lambda<void()>());
QString AllFilesFilter(); QString AllFilesFilter();
@ -72,7 +101,13 @@ enum class Type {
void InitLastPathDefault(); void InitLastPathDefault();
bool GetDefault(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter, ::FileDialog::internal::Type type, QString startFile); bool GetDefault(
QStringList &files,
QByteArray &remoteContent,
const QString &caption,
const QString &filter,
::FileDialog::internal::Type type,
QString startFile);
} // namespace internal } // namespace internal
} // namespace FileDialog } // namespace FileDialog

View File

@ -498,7 +498,10 @@ HistoryWidget::HistoryWidget(QWidget *parent, not_null<Window::Controller*> cont
connect(_fieldAutocomplete, SIGNAL(moderateKeyActivate(int,bool*)), this, SLOT(onModerateKeyActivate(int,bool*))); connect(_fieldAutocomplete, SIGNAL(moderateKeyActivate(int,bool*)), this, SLOT(onModerateKeyActivate(int,bool*)));
_field->installEventFilter(_fieldAutocomplete); _field->installEventFilter(_fieldAutocomplete);
_field->setInsertFromMimeDataHook([this](const QMimeData *data) { _field->setInsertFromMimeDataHook([this](const QMimeData *data) {
return confirmSendingFiles(data, CompressConfirm::Auto, data->text()); return confirmSendingFiles(
data,
CompressConfirm::Auto,
data->text());
}); });
_emojiSuggestions.create(this, _field.data()); _emojiSuggestions.create(this, _field.data());
updateFieldSubmitSettings(); updateFieldSubmitSettings();
@ -3094,18 +3097,22 @@ void HistoryWidget::chooseAttach() {
auto filter = FileDialog::AllFilesFilter() + qsl(";;Image files (*") + cImgExtensions().join(qsl(" *")) + qsl(")"); auto filter = FileDialog::AllFilesFilter() + qsl(";;Image files (*") + cImgExtensions().join(qsl(" *")) + qsl(")");
FileDialog::GetOpenPaths(lang(lng_choose_files), filter, base::lambda_guarded(this, [this](const FileDialog::OpenResult &result) { FileDialog::GetOpenPaths(lang(lng_choose_files), filter, base::lambda_guarded(this, [this](FileDialog::OpenResult &&result) {
if (result.paths.isEmpty() && result.remoteContent.isEmpty()) { if (result.paths.isEmpty() && result.remoteContent.isEmpty()) {
return; return;
} }
if (!result.remoteContent.isEmpty()) { if (!result.remoteContent.isEmpty()) {
auto animated = false; auto animated = false;
auto image = App::readImage(result.remoteContent, nullptr, false, &animated); auto image = App::readImage(
result.remoteContent,
nullptr,
false,
&animated);
if (!image.isNull() && !animated) { if (!image.isNull() && !animated) {
confirmSendingFiles( confirmSendingFiles(
image, std::move(image),
result.remoteContent, std::move(result.remoteContent),
CompressConfirm::Auto); CompressConfirm::Auto);
} else { } else {
uploadFile(result.remoteContent, SendMediaType::File); uploadFile(result.remoteContent, SendMediaType::File);
@ -3936,42 +3943,27 @@ template <typename SendCallback>
bool HistoryWidget::showSendFilesBox( bool HistoryWidget::showSendFilesBox(
object_ptr<SendFilesBox> box, object_ptr<SendFilesBox> box,
const QString &insertTextOnCancel, const QString &insertTextOnCancel,
const QString *addedComment,
SendCallback callback) { SendCallback callback) {
App::wnd()->activateWindow(); App::wnd()->activateWindow();
auto withComment = (addedComment != nullptr);
const auto confirmedCallback = [=, sendCallback = std::move(callback)]( const auto confirmedCallback = [=, sendCallback = std::move(callback)](
Storage::PreparedList &&list, Storage::PreparedList &&list,
const QImage &image,
bool compressed, bool compressed,
const QString &caption, const QString &caption,
bool ctrlShiftEnter) { bool ctrlShiftEnter) {
if (!canWriteMessage()) return; if (!canWriteMessage()) return;
const auto replyTo = replyToId();
if (withComment) {
// This call will clear replyToId().
onSend(ctrlShiftEnter);
}
sendCallback( sendCallback(
std::move(list), std::move(list),
image,
compressed, compressed,
caption, caption,
replyTo); replyToId());
}; };
box->setConfirmedCallback( box->setConfirmedCallback(
base::lambda_guarded(this, std::move(confirmedCallback))); base::lambda_guarded(this, std::move(confirmedCallback)));
if (withComment) { if (!insertTextOnCancel.isEmpty()) {
auto was = _field->getTextWithTags(); box->setCancelledCallback(base::lambda_guarded(this, [=] {
setFieldText({ *addedComment, TextWithTags::Tags() });
box->setCancelledCallback(base::lambda_guarded(this, [this, was] {
setFieldText(was);
}));
} else if (!insertTextOnCancel.isEmpty()) {
box->setCancelledCallback(base::lambda_guarded(this, [this, insertTextOnCancel] {
_field->textCursor().insertText(insertTextOnCancel); _field->textCursor().insertText(insertTextOnCancel);
})); }));
} }
@ -4013,37 +4005,32 @@ bool HistoryWidget::showSendingFilesError(
} }
bool HistoryWidget::confirmSendingFiles(const QStringList &files) { bool HistoryWidget::confirmSendingFiles(const QStringList &files) {
return confirmSendingFiles(files, CompressConfirm::Auto, nullptr); return confirmSendingFiles(files, CompressConfirm::Auto);
} }
bool HistoryWidget::confirmSendingFiles(const QMimeData *data) { bool HistoryWidget::confirmSendingFiles(const QMimeData *data) {
return confirmSendingFiles(data, CompressConfirm::Auto, nullptr); return confirmSendingFiles(data, CompressConfirm::Auto);
} }
bool HistoryWidget::confirmSendingFiles( bool HistoryWidget::confirmSendingFiles(
const QList<QUrl> &files, const QList<QUrl> &files,
CompressConfirm compressed, CompressConfirm compressed) {
const QString *addedComment) {
return confirmSendingFiles( return confirmSendingFiles(
Storage::PrepareMediaList(files, st::sendMediaPreviewSize), Storage::PrepareMediaList(files, st::sendMediaPreviewSize),
compressed, compressed);
addedComment);
} }
bool HistoryWidget::confirmSendingFiles( bool HistoryWidget::confirmSendingFiles(
const QStringList &files, const QStringList &files,
CompressConfirm compressed, CompressConfirm compressed) {
const QString *addedComment) {
return confirmSendingFiles( return confirmSendingFiles(
Storage::PrepareMediaList(files, st::sendMediaPreviewSize), Storage::PrepareMediaList(files, st::sendMediaPreviewSize),
compressed, compressed);
addedComment);
} }
bool HistoryWidget::confirmSendingFiles( bool HistoryWidget::confirmSendingFiles(
Storage::PreparedList &&list, Storage::PreparedList &&list,
CompressConfirm compressed, CompressConfirm compressed) {
const QString *addedComment) {
if (showSendingFilesError(list)) { if (showSendingFilesError(list)) {
return false; return false;
} }
@ -4057,8 +4044,6 @@ bool HistoryWidget::confirmSendingFiles(
uploadFilesAfterConfirmation( uploadFilesAfterConfirmation(
std::move(list), std::move(list),
QByteArray(),
QImage(),
SendMediaType::Photo, SendMediaType::Photo,
caption, caption,
replyToId(), replyToId(),
@ -4071,7 +4056,6 @@ bool HistoryWidget::confirmSendingFiles(
const auto insertTextOnCancel = QString(); const auto insertTextOnCancel = QString();
auto sendCallback = [this]( auto sendCallback = [this](
Storage::PreparedList &&list, Storage::PreparedList &&list,
const QImage &image,
bool compressed, bool compressed,
const QString &caption, const QString &caption,
MsgId replyTo) { MsgId replyTo) {
@ -4080,8 +4064,6 @@ bool HistoryWidget::confirmSendingFiles(
: SendMediaType::File; : SendMediaType::File;
uploadFilesAfterConfirmation( uploadFilesAfterConfirmation(
std::move(list), std::move(list),
QByteArray(),
image,
type, type,
caption, caption,
replyTo); replyTo);
@ -4094,22 +4076,20 @@ bool HistoryWidget::confirmSendingFiles(
return showSendFilesBox( return showSendFilesBox(
Box<SendFilesBox>(std::move(list), boxCompressConfirm), Box<SendFilesBox>(std::move(list), boxCompressConfirm),
insertTextOnCancel, insertTextOnCancel,
addedComment,
std::move(sendCallback)); std::move(sendCallback));
} }
} }
bool HistoryWidget::confirmSendingFiles( bool HistoryWidget::confirmSendingFiles(
const QImage &image, QImage &&image,
const QByteArray &content, QByteArray &&content,
CompressConfirm compressed, CompressConfirm compressed,
const QString &insertTextOnCancel) { const QString &insertTextOnCancel) {
if (!canWriteMessage() || image.isNull()) return false; if (!canWriteMessage() || image.isNull()) return false;
App::wnd()->activateWindow(); App::wnd()->activateWindow();
auto sendCallback = [this, content]( auto sendCallback = [this](
Storage::PreparedList &&list, Storage::PreparedList &&list,
const QImage &image,
bool compressed, bool compressed,
const QString &caption, const QString &caption,
MsgId replyTo) { MsgId replyTo) {
@ -4118,16 +4098,17 @@ bool HistoryWidget::confirmSendingFiles(
: SendMediaType::File; : SendMediaType::File;
uploadFilesAfterConfirmation( uploadFilesAfterConfirmation(
std::move(list), std::move(list),
content,
image,
type, type,
caption, caption,
replyTo); replyTo);
}; };
auto list = Storage::PrepareMediaFromImage(
std::move(image),
std::move(content),
st::sendMediaPreviewSize);
return showSendFilesBox( return showSendFilesBox(
Box<SendFilesBox>(image, compressed), Box<SendFilesBox>(std::move(list), compressed),
insertTextOnCancel, insertTextOnCancel,
nullptr,
std::move(sendCallback)); std::move(sendCallback));
} }
@ -4152,7 +4133,7 @@ bool HistoryWidget::confirmSendingFiles(
auto image = qvariant_cast<QImage>(data->imageData()); auto image = qvariant_cast<QImage>(data->imageData());
if (!image.isNull()) { if (!image.isNull()) {
confirmSendingFiles( confirmSendingFiles(
image, std::move(image),
QByteArray(), QByteArray(),
compressed, compressed,
insertTextOnCancel); insertTextOnCancel);
@ -4162,31 +4143,6 @@ bool HistoryWidget::confirmSendingFiles(
return false; return false;
} }
bool HistoryWidget::confirmShareContact(
const QString &phone,
const QString &fname,
const QString &lname,
const QString *addedComment) {
if (!canWriteMessage()) return false;
auto sendCallback = [=](
Storage::PreparedList &&list,
const QImage &image,
bool compressed,
const QString &caption,
MsgId replyTo) {
auto options = ApiWrap::SendOptions(_history);
options.replyTo = replyTo;
Auth().api().shareContact(phone, fname, lname, options);
};
const auto insertTextOnCancel = QString();
return showSendFilesBox(
Box<SendFilesBox>(phone, fname, lname),
insertTextOnCancel,
addedComment,
std::move(sendCallback));
}
void HistoryWidget::uploadFiles( void HistoryWidget::uploadFiles(
Storage::PreparedList &&list, Storage::PreparedList &&list,
SendMediaType type) { SendMediaType type) {
@ -4195,8 +4151,6 @@ void HistoryWidget::uploadFiles(
auto caption = QString(); auto caption = QString();
uploadFilesAfterConfirmation( uploadFilesAfterConfirmation(
std::move(list), std::move(list),
QByteArray(),
QImage(),
type, type,
caption, caption,
replyToId()); replyToId());
@ -4204,8 +4158,6 @@ void HistoryWidget::uploadFiles(
void HistoryWidget::uploadFilesAfterConfirmation( void HistoryWidget::uploadFilesAfterConfirmation(
Storage::PreparedList &&list, Storage::PreparedList &&list,
const QByteArray &content,
const QImage &image,
SendMediaType type, SendMediaType type,
QString caption, QString caption,
MsgId replyTo, MsgId replyTo,
@ -4216,8 +4168,6 @@ void HistoryWidget::uploadFilesAfterConfirmation(
options.replyTo = replyTo; options.replyTo = replyTo;
Auth().api().sendFiles( Auth().api().sendFiles(
std::move(list), std::move(list),
content,
image,
type, type,
caption, caption,
album, album,

View File

@ -497,24 +497,37 @@ private:
void unreadMentionsAnimationFinish(); void unreadMentionsAnimationFinish();
void sendButtonClicked(); void sendButtonClicked();
bool confirmShareContact(const QString &phone, const QString &fname, const QString &lname, const QString *addedComment = nullptr); bool confirmSendingFiles(
bool confirmSendingFiles(const QList<QUrl> &files, CompressConfirm compressed, const QString *addedComment = nullptr); const QList<QUrl> &files,
bool confirmSendingFiles(const QStringList &files, CompressConfirm compressed, const QString *addedComment = nullptr); CompressConfirm compressed);
bool confirmSendingFiles(const QImage &image, const QByteArray &content, CompressConfirm compressed, const QString &insertTextOnCancel = QString()); bool confirmSendingFiles(
bool confirmSendingFiles(const QMimeData *data, CompressConfirm compressed, const QString &insertTextOnCancel = QString()); const QStringList &files,
bool confirmSendingFiles(Storage::PreparedList &&list, CompressConfirm compressed, const QString *addedComment = nullptr); CompressConfirm compressed);
bool confirmSendingFiles(
QImage &&image,
QByteArray &&content,
CompressConfirm compressed,
const QString &insertTextOnCancel = QString());
bool confirmSendingFiles(
const QMimeData *data,
CompressConfirm compressed,
const QString &insertTextOnCancel = QString());
bool confirmSendingFiles(
Storage::PreparedList &&list,
CompressConfirm compressed);
bool showSendingFilesError(const Storage::PreparedList &list) const; bool showSendingFilesError(const Storage::PreparedList &list) const;
template <typename SendCallback> template <typename SendCallback>
bool showSendFilesBox(object_ptr<SendFilesBox> box, const QString &insertTextOnCancel, const QString *addedComment, SendCallback callback); bool showSendFilesBox(
object_ptr<SendFilesBox> box,
const QString &insertTextOnCancel,
SendCallback callback);
void uploadFiles(Storage::PreparedList &&list, SendMediaType type); void uploadFiles(Storage::PreparedList &&list, SendMediaType type);
void uploadFile(const QByteArray &fileContent, SendMediaType type); void uploadFile(const QByteArray &fileContent, SendMediaType type);
// If an empty filepath is found we upload (possible) "image" with (possible) "content".
void uploadFilesAfterConfirmation( void uploadFilesAfterConfirmation(
Storage::PreparedList &&list, Storage::PreparedList &&list,
const QByteArray &content,
const QImage &image,
SendMediaType type, SendMediaType type,
QString caption, QString caption,
MsgId replyTo, MsgId replyTo,

View File

@ -202,6 +202,7 @@ FileLoadResult::FileLoadResult(
FileLoadTask::FileLoadTask( FileLoadTask::FileLoadTask(
const QString &filepath, const QString &filepath,
const QByteArray &content,
std::unique_ptr<FileMediaInformation> information, std::unique_ptr<FileMediaInformation> information,
SendMediaType type, SendMediaType type,
const FileLoadTo &to, const FileLoadTo &to,
@ -211,23 +212,8 @@ FileLoadTask::FileLoadTask(
, _to(to) , _to(to)
, _album(std::move(album)) , _album(std::move(album))
, _filepath(filepath) , _filepath(filepath)
, _information(std::move(information))
, _type(type)
, _caption(caption) {
}
FileLoadTask::FileLoadTask(
const QByteArray &content,
const QImage &image,
SendMediaType type,
const FileLoadTo &to,
const QString &caption,
std::shared_ptr<SendingAlbum> album)
: _id(rand_value<uint64>())
, _to(to)
, _album(std::move(album))
, _content(content) , _content(content)
, _image(image) , _information(std::move(information))
, _type(type) , _type(type)
, _caption(caption) { , _caption(caption) {
} }
@ -361,6 +347,14 @@ bool FileLoadTask::CheckForImage(
} }
return QImage(); return QImage();
})(); })();
return FillImageInformation(std::move(image), animated, result);
}
bool FileLoadTask::FillImageInformation(
QImage &&image,
bool animated,
std::unique_ptr<FileMediaInformation> &result) {
Expects(result != nullptr);
if (image.isNull()) { if (image.isNull()) {
return false; return false;
@ -395,7 +389,7 @@ void FileLoadTask::process() {
auto isVideo = false; auto isVideo = false;
auto isVoice = (_type == SendMediaType::Audio); auto isVoice = (_type == SendMediaType::Audio);
auto fullimage = base::take(_image); auto fullimage = QImage();
auto info = _filepath.isEmpty() ? QFileInfo() : QFileInfo(_filepath); auto info = _filepath.isEmpty() ? QFileInfo() : QFileInfo(_filepath);
if (info.exists()) { if (info.exists()) {
if (info.isDir()) { if (info.isDir()) {
@ -428,6 +422,12 @@ void FileLoadTask::process() {
filename = filedialogDefaultName(qsl("audio"), qsl(".ogg"), QString(), true); filename = filedialogDefaultName(qsl("audio"), qsl(".ogg"), QString(), true);
filemime = "audio/ogg"; filemime = "audio/ogg";
} else { } else {
if (_information) {
if (auto image = base::get_if<FileMediaInformation::Image>(
&_information->media)) {
fullimage = base::take(image->data);
}
}
auto mimeType = mimeTypeForData(_content); auto mimeType = mimeTypeForData(_content);
filemime = mimeType.name(); filemime = mimeType.name();
if (filemime != stickerMime) { if (filemime != stickerMime) {

View File

@ -282,17 +282,15 @@ public:
const QString &filepath, const QString &filepath,
const QByteArray &content, const QByteArray &content,
const QString &filemime); const QString &filemime);
static bool FillImageInformation(
QImage &&image,
bool animated,
std::unique_ptr<FileMediaInformation> &result);
FileLoadTask( FileLoadTask(
const QString &filepath, const QString &filepath,
std::unique_ptr<FileMediaInformation> information,
SendMediaType type,
const FileLoadTo &to,
const QString &caption,
std::shared_ptr<SendingAlbum> album = nullptr);
FileLoadTask(
const QByteArray &content, const QByteArray &content,
const QImage &image, std::unique_ptr<FileMediaInformation> information,
SendMediaType type, SendMediaType type,
const FileLoadTo &to, const FileLoadTo &to,
const QString &caption, const QString &caption,
@ -312,9 +310,18 @@ public:
void finish(); void finish();
private: private:
static bool CheckForSong(const QString &filepath, const QByteArray &content, std::unique_ptr<FileMediaInformation> &result); static bool CheckForSong(
static bool CheckForVideo(const QString &filepath, const QByteArray &content, std::unique_ptr<FileMediaInformation> &result); const QString &filepath,
static bool CheckForImage(const QString &filepath, const QByteArray &content, std::unique_ptr<FileMediaInformation> &result); const QByteArray &content,
std::unique_ptr<FileMediaInformation> &result);
static bool CheckForVideo(
const QString &filepath,
const QByteArray &content,
std::unique_ptr<FileMediaInformation> &result);
static bool CheckForImage(
const QString &filepath,
const QByteArray &content,
std::unique_ptr<FileMediaInformation> &result);
template <typename Mimes, typename Extensions> template <typename Mimes, typename Extensions>
static bool CheckMimeOrExtensions(const QString &filepath, const QString &filemime, Mimes &mimes, Extensions &extensions); static bool CheckMimeOrExtensions(const QString &filepath, const QString &filemime, Mimes &mimes, Extensions &extensions);
@ -330,7 +337,6 @@ private:
QString _filepath; QString _filepath;
QByteArray _content; QByteArray _content;
std::unique_ptr<FileMediaInformation> _information; std::unique_ptr<FileMediaInformation> _information;
QImage _image;
int32 _duration = 0; int32 _duration = 0;
VoiceWaveform _waveform; VoiceWaveform _waveform;
SendMediaType _type; SendMediaType _type;

View File

@ -61,11 +61,22 @@ bool PrepareAlbumMediaIsWaiting(
// Use some special thread queue, like a separate QThreadPool. // Use some special thread queue, like a separate QThreadPool.
base::TaskQueue::Normal().Put([&, previewWidth] { base::TaskQueue::Normal().Put([&, previewWidth] {
const auto guard = gsl::finally([&] { semaphore.release(); }); const auto guard = gsl::finally([&] { semaphore.release(); });
const auto filemime = mimeTypeForFile(QFileInfo(file.path)).name(); if (!file.path.isEmpty()) {
file.information = FileLoadTask::ReadMediaInformation( file.mime = mimeTypeForFile(QFileInfo(file.path)).name();
file.path, file.information = FileLoadTask::ReadMediaInformation(
QByteArray(), file.path,
filemime); QByteArray(),
file.mime);
} else if (!file.content.isEmpty()) {
file.mime = mimeTypeForData(file.content).name();
file.information = FileLoadTask::ReadMediaInformation(
QString(),
file.content,
file.mime);
} else {
Assert(file.information != nullptr);
}
using Image = FileMediaInformation::Image; using Image = FileMediaInformation::Image;
using Video = FileMediaInformation::Video; using Video = FileMediaInformation::Video;
if (const auto image = base::get_if<Image>( if (const auto image = base::get_if<Image>(
@ -94,17 +105,14 @@ bool PrepareAlbumMediaIsWaiting(
void PrepareAlbum(PreparedList &result, int previewWidth) { void PrepareAlbum(PreparedList &result, int previewWidth) {
const auto count = int(result.files.size()); const auto count = int(result.files.size());
if ((count < 2) || (count > kMaxAlbumCount)) { if (count > kMaxAlbumCount) {
return; return;
} }
result.albumIsPossible = true; result.albumIsPossible = (count > 1);
auto waiting = 0; auto waiting = 0;
QSemaphore semaphore; QSemaphore semaphore;
for (auto &file : result.files) { for (auto &file : result.files) {
if (!result.albumIsPossible) {
break;
}
if (PrepareAlbumMediaIsWaiting(semaphore, file, previewWidth)) { if (PrepareAlbumMediaIsWaiting(semaphore, file, previewWidth)) {
++waiting; ++waiting;
} }
@ -226,11 +234,34 @@ PreparedList PrepareMediaList(const QStringList &files, int previewWidth) {
if (filesize > App::kImageSizeLimit || !toCompress) { if (filesize > App::kImageSizeLimit || !toCompress) {
result.allFilesForCompress = false; result.allFilesForCompress = false;
} }
result.files.push_back({ file }); result.files.emplace_back(file);
} }
PrepareAlbum(result, previewWidth); PrepareAlbum(result, previewWidth);
return result; return result;
} }
PreparedList PrepareMediaFromImage(
QImage &&image,
QByteArray &&content,
int previewWidth) {
auto result = Storage::PreparedList();
result.allFilesForCompress = ValidateThumbDimensions(
image.width(),
image.height());
auto file = PreparedFile(QString());
file.content = content;
if (file.content.isEmpty()) {
file.information = std::make_unique<FileMediaInformation>();
const auto animated = false;
FileLoadTask::FillImageInformation(
std::move(image),
animated,
file.information);
}
result.files.push_back(std::move(file));
PrepareAlbum(result, previewWidth);
return result;
}
} // namespace Storage } // namespace Storage

View File

@ -46,8 +46,9 @@ struct PreparedFile {
~PreparedFile(); ~PreparedFile();
QString path; QString path;
QByteArray content;
QString mime;
std::unique_ptr<FileMediaInformation> information; std::unique_ptr<FileMediaInformation> information;
base::optional<QImage> large;
QImage preview; QImage preview;
AlbumType type = AlbumType::None; AlbumType type = AlbumType::None;
@ -79,5 +80,9 @@ struct PreparedList {
bool ValidateThumbDimensions(int width, int height); bool ValidateThumbDimensions(int width, int height);
PreparedList PrepareMediaList(const QList<QUrl> &files, int previewWidth); PreparedList PrepareMediaList(const QList<QUrl> &files, int previewWidth);
PreparedList PrepareMediaList(const QStringList &files, int previewWidth); PreparedList PrepareMediaList(const QStringList &files, int previewWidth);
PreparedList PrepareMediaFromImage(
QImage &&image,
QByteArray &&content,
int previewWidth);
} // namespace Storage } // namespace Storage