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

View File

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

View File

@ -2508,19 +2508,26 @@ namespace {
#endif // !TDESKTOP_DISABLE_NETWORK_PROXY
}
void complexAdjustRect(RectParts corners, QRect &rect, RectParts &parts) {
if (corners & RectPart::TopLeft) {
if (!(corners & RectPart::BottomLeft)) {
parts = RectPart::NoTopBottom | RectPart::FullTop;
rect.setHeight(rect.height() + msgRadius());
void rectWithCorners(Painter &p, QRect rect, const style::color &bg, RoundCorners index, RectParts corners) {
auto parts = RectPart::Top
| RectPart::NoTopBottom
| RectPart::Bottom
| 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)
? SelectedOverlaySmallCorners
: SelectedOverlayLargeCorners;
auto overlayParts = RectPart::Full | RectPart::None;
if (radius == ImageRoundRadius::Large) {
complexAdjustRect(corners, rect, overlayParts);
}
roundRect(p, rect, p.textPalette().selectOverlay, overlayCorners, nullptr, overlayParts);
const auto bg = p.textPalette().selectOverlay;
rectWithCorners(p, rect, bg, overlayCorners, corners);
}
}
void complexLocationRect(Painter &p, QRect rect, ImageRoundRadius radius, RectParts corners) {
auto parts = RectPart::Full | RectPart::None;
complexAdjustRect(corners, rect, parts);
roundRect(p, rect, st::msgInBg, MessageInCorners, nullptr, parts);
rectWithCorners(p, rect, st::msgInBg, MessageInCorners, corners);
}
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));
if (paintTopRounded || paintBottomRounded) {
auto parts = RectPart::None | 0;
parts |= RectPart::None;
if (paintTopRounded) parts |= RectPart::FullTop;
if (paintBottomRounded) parts |= RectPart::FullBottom;
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/buttons.h"
#include "ui/widgets/input_fields.h"
#include "ui/empty_userpic.h"
#include "ui/grouped_layout.h"
#include "styles/style_history.h"
#include "styles/style_boxes.h"
@ -42,15 +41,10 @@ constexpr auto kMinPreviewWidth = 20;
} // namespace
SendFilesBox::SendFilesBox(QWidget*, QImage image, CompressConfirm compressed)
: _image(image)
, _compressConfirm(compressed)
, _caption(this, st::confirmCaptionArea, langFactory(lng_photo_caption)) {
_list.files.push_back({ QString() });
prepareSingleFileLayout();
}
SendFilesBox::SendFilesBox(QWidget*, Storage::PreparedList &&list, CompressConfirm compressed)
SendFilesBox::SendFilesBox(
QWidget*,
Storage::PreparedList &&list,
CompressConfirm compressed)
: _list(std::move(list))
, _compressConfirm(compressed)
, _caption(
@ -66,34 +60,54 @@ SendFilesBox::SendFilesBox(QWidget*, Storage::PreparedList &&list, CompressConfi
void SendFilesBox::prepareSingleFileLayout() {
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) {
_compressConfirm = CompressConfirm::None;
}
if (!_image.isNull()) {
auto image = _image;
if (!preview.isNull()) {
if (!_animated && _compressConfirm == CompressConfirm::None) {
auto originalWidth = image.width();
auto originalHeight = image.height();
auto originalWidth = preview.width();
auto originalHeight = preview.height();
auto thumbWidth = st::msgFileThumbSize;
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;
_fileThumb = Images::pixmap(image, thumbWidth * cIntRetinaFactor(), 0, options, st::msgFileThumbSize, st::msgFileThumbSize);
auto options = Images::Option::Smooth
| 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 {
auto maxW = 0;
auto maxH = 0;
if (_animated) {
auto limitW = st::sendMediaPreviewSize;
auto limitH = st::confirmMaxHeight;
maxW = qMax(image.width(), 1);
maxH = qMax(image.height(), 1);
maxW = qMax(preview.width(), 1);
maxH = qMax(preview.height(), 1);
if (maxW * limitH > maxH * limitW) {
if (maxW < limitW) {
maxH = maxH * limitW / maxW;
@ -105,16 +119,22 @@ void SendFilesBox::prepareSingleFileLayout() {
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 originalHeight = image.height();
auto originalWidth = preview.width();
auto originalHeight = preview.height();
if (!originalWidth || !originalHeight) {
originalWidth = originalHeight = 1;
}
_previewWidth = st::sendMediaPreviewSize;
if (image.width() < _previewWidth) {
_previewWidth = qMax(image.width(), kMinPreviewWidth);
if (preview.width() < _previewWidth) {
_previewWidth = qMax(preview.width(), kMinPreviewWidth);
}
auto maxthumbh = qMin(qRound(1.5 * _previewWidth), st::confirmMaxHeight);
_previewHeight = qRound(originalHeight * float64(_previewWidth) / originalWidth);
@ -125,9 +145,13 @@ void SendFilesBox::prepareSingleFileLayout() {
}
_previewLeft = (st::boxWideWidth - _previewWidth) / 2;
image = std::move(image).scaled(_previewWidth * cIntRetinaFactor(), _previewHeight * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
image = Images::prepareOpaque(std::move(image));
_preview = App::pixmapFromImageInPlace(std::move(image));
preview = std::move(preview).scaled(
_previewWidth * cIntRetinaFactor(),
_previewHeight * cIntRetinaFactor(),
Qt::IgnoreAspectRatio,
Qt::SmoothTransformation);
preview = Images::prepareOpaque(std::move(preview));
_preview = App::pixmapFromImageInPlace(std::move(preview));
_preview.setDevicePixelRatio(cRetinaFactor());
prepareGifPreview();
@ -191,9 +215,12 @@ void SendFilesBox::prepareDocumentLayout() {
const auto &file = _list.files.front();
const auto filepath = file.path;
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);
_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));
_fileIsImage = true;
} 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() {
Expects(controller() != nullptr);
@ -304,9 +297,7 @@ void SendFilesBox::prepare() {
}
base::lambda<QString()> SendFilesBox::getSendButtonText() const {
if (!_contactPhone.isEmpty()) {
return langFactory(lng_send_button);
} else if (_compressed && _compressed->checked()) {
if (_compressed && _compressed->checked()) {
return [count = _list.files.size()] {
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);
if (_fileThumb.isNull()) {
if (_contactPhone.isNull()) {
QRect inner(rtlrect(x + st::msgFilePadding.left(), y + st::msgFilePadding.top(), st::msgFileSize, st::msgFileSize, width()));
p.setPen(Qt::NoPen);
p.setBrush(st::msgFileOutBg);
QRect inner(rtlrect(x + st::msgFilePadding.left(), y + st::msgFilePadding.top(), st::msgFileSize, st::msgFileSize, width()));
p.setPen(Qt::NoPen);
p.setBrush(st::msgFileOutBg);
{
PainterHighQualityEnabler hq(p);
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);
{
PainterHighQualityEnabler hq(p);
p.drawEllipse(inner);
}
auto &icon = _fileIsAudio ? st::historyFileOutPlay : _fileIsImage ? st::historyFileOutImage : st::historyFileOutDocument;
icon.paintInCenter(p, inner);
} else {
QRect rthumb(rtlrect(x + st::msgFileThumbPadding.left(), y + st::msgFileThumbPadding.top(), st::msgFileThumbSize, st::msgFileThumbSize, width()));
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();
_confirmedCallback(
std::move(_list),
_animated ? QImage() : _image,
compressed,
caption,
ctrlShiftEnter);

View File

@ -28,17 +28,22 @@ namespace Ui {
class Checkbox;
class RoundButton;
class InputArea;
class EmptyUserpic;
struct GroupMediaLayout;
} // namespace Ui
class SendFilesBox : public BoxContent {
public:
SendFilesBox(QWidget*, QImage image, CompressConfirm compressed);
SendFilesBox(QWidget*, Storage::PreparedList &&list, CompressConfirm compressed);
SendFilesBox(QWidget*, const QString &phone, const QString &firstname, const QString &lastname);
SendFilesBox(
QWidget*,
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);
}
void setCancelledCallback(base::lambda<void()> callback) {
@ -58,7 +63,6 @@ protected:
private:
void prepareSingleFileLayout();
void prepareDocumentLayout();
void tryToReadSingleFile();
void prepareGifPreview();
void clipCallback(Media::Clip::Notification notification);
@ -73,7 +77,6 @@ private:
QString _titleText;
Storage::PreparedList _list;
QImage _image;
CompressConfirm _compressConfirm = CompressConfirm::None;
bool _animated = false;
@ -91,12 +94,11 @@ private:
QString _statusText;
int _statusWidth = 0;
QString _contactPhone;
QString _contactFirstName;
QString _contactLastName;
std::unique_ptr<Ui::EmptyUserpic> _contactPhotoEmpty;
base::lambda<void(Storage::PreparedList &&list, const QImage &image, bool compressed, const QString &caption, bool ctrlShiftEnter)> _confirmedCallback;
base::lambda<void(
Storage::PreparedList &&list,
bool compressed,
const QString &caption,
bool ctrlShiftEnter)> _confirmedCallback;
base::lambda<void()> _cancelledCallback;
bool _confirmed = false;
@ -111,7 +113,11 @@ class SendAlbumBox : public BoxContent {
public:
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);
}
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 "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;
QByteArray remoteContent;
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;
}
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;
if (directoryPath.isEmpty()) {
if (cDialogLastPath().isEmpty()) {
@ -69,7 +78,10 @@ QString filedialogDefaultName(const QString &prefix, const QString &extension, c
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);
int32 extIndex = name.lastIndexOf('.');
QString prefix = name, extension;
@ -130,19 +142,30 @@ void UnsafeLaunchDefault(const QString &filepath) {
namespace FileDialog {
void GetOpenPath(const QString &caption, const QString &filter, base::lambda<void(const OpenResult &result)> callback, base::lambda<void()> failed) {
base::TaskQueue::Main().Put([caption, filter, callback = std::move(callback), failed = std::move(failed)] {
void GetOpenPath(
const QString &caption,
const QString &filter,
base::lambda<void(OpenResult &&result)> callback,
base::lambda<void()> failed) {
base::TaskQueue::Main().Put([=] {
auto files = QStringList();
auto remoteContent = QByteArray();
if (Platform::FileDialog::Get(files, remoteContent, caption, filter, FileDialog::internal::Type::ReadFile)
&& ((!files.isEmpty() && !files[0].isEmpty()) || !remoteContent.isEmpty())) {
const auto success = Platform::FileDialog::Get(
files,
remoteContent,
caption,
filter,
FileDialog::internal::Type::ReadFile);
if (success
&& ((!files.isEmpty() && !files[0].isEmpty())
|| !remoteContent.isEmpty())) {
if (callback) {
auto result = OpenResult();
if (!files.isEmpty() && !files[0].isEmpty()) {
result.paths.push_back(files[0]);
}
result.remoteContent = remoteContent;
callback(result);
callback(std::move(result));
}
} else if (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) {
base::TaskQueue::Main().Put([caption, filter, callback = std::move(callback), failed = std::move(failed)] {
void GetOpenPaths(
const QString &caption,
const QString &filter,
base::lambda<void(OpenResult &&result)> callback,
base::lambda<void()> failed) {
base::TaskQueue::Main().Put([=] {
auto files = QStringList();
auto remoteContent = QByteArray();
if (Platform::FileDialog::Get(files, remoteContent, caption, filter, FileDialog::internal::Type::ReadFiles)
&& (!files.isEmpty() || !remoteContent.isEmpty())) {
const auto success = Platform::FileDialog::Get(
files,
remoteContent,
caption,
filter,
FileDialog::internal::Type::ReadFiles);
if (success && (!files.isEmpty() || !remoteContent.isEmpty())) {
if (callback) {
auto result = OpenResult();
result.paths = files;
result.remoteContent = remoteContent;
callback(result);
callback(std::move(result));
}
} else if (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) {
base::TaskQueue::Main().Put([caption, filter, initialPath, callback = std::move(callback), failed = std::move(failed)] {
void GetWritePath(
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();
if (filedialogGetSaveFile(file, caption, filter, initialPath)) {
if (callback) {
callback(file);
callback(std::move(file));
}
} else if (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) {
base::TaskQueue::Main().Put([caption, initialPath, callback = std::move(callback), failed = std::move(failed)] {
void GetFolder(
const QString &caption,
const QString &initialPath,
base::lambda<void(QString &&result)> callback,
base::lambda<void()> failed) {
base::TaskQueue::Main().Put([=] {
auto files = QStringList();
auto remoteContent = QByteArray();
if (Platform::FileDialog::Get(files, remoteContent, caption, QString(), FileDialog::internal::Type::ReadFolder, initialPath)
&& !files.isEmpty() && !files[0].isEmpty()) {
const auto success = Platform::FileDialog::Get(
files,
remoteContent,
caption,
QString(),
FileDialog::internal::Type::ReadFolder,
initialPath);
if (success && !files.isEmpty() && !files[0].isEmpty()) {
if (callback) {
callback(files[0]);
callback(std::move(files[0]));
}
} else if (failed) {
failed();

View File

@ -23,10 +23,22 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "base/observer.h"
// 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 filedialogNextFilename(const QString &name, const QString &cur, const QString &path = QString());
QString filedialogDefaultName(
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 {
@ -54,10 +66,27 @@ struct OpenResult {
QStringList paths;
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 GetOpenPaths(const QString &caption, const QString &filter, base::lambda<void(const OpenResult &result)> callback, base::lambda<void()> failed = base::lambda<void()>());
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()>());
void GetFolder(const QString &caption, const QString &initialPath, base::lambda<void(const QString &result)> callback, base::lambda<void()> failed = base::lambda<void()>());
void GetOpenPath(
const QString &caption,
const QString &filter,
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();
@ -72,7 +101,13 @@ enum class Type {
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 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*)));
_field->installEventFilter(_fieldAutocomplete);
_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());
updateFieldSubmitSettings();
@ -3094,18 +3097,22 @@ void HistoryWidget::chooseAttach() {
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()) {
return;
}
if (!result.remoteContent.isEmpty()) {
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) {
confirmSendingFiles(
image,
result.remoteContent,
std::move(image),
std::move(result.remoteContent),
CompressConfirm::Auto);
} else {
uploadFile(result.remoteContent, SendMediaType::File);
@ -3936,42 +3943,27 @@ template <typename SendCallback>
bool HistoryWidget::showSendFilesBox(
object_ptr<SendFilesBox> box,
const QString &insertTextOnCancel,
const QString *addedComment,
SendCallback callback) {
App::wnd()->activateWindow();
auto withComment = (addedComment != nullptr);
const auto confirmedCallback = [=, sendCallback = std::move(callback)](
Storage::PreparedList &&list,
const QImage &image,
bool compressed,
const QString &caption,
bool ctrlShiftEnter) {
if (!canWriteMessage()) return;
const auto replyTo = replyToId();
if (withComment) {
// This call will clear replyToId().
onSend(ctrlShiftEnter);
}
sendCallback(
std::move(list),
image,
compressed,
caption,
replyTo);
replyToId());
};
box->setConfirmedCallback(
base::lambda_guarded(this, std::move(confirmedCallback)));
if (withComment) {
auto was = _field->getTextWithTags();
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] {
if (!insertTextOnCancel.isEmpty()) {
box->setCancelledCallback(base::lambda_guarded(this, [=] {
_field->textCursor().insertText(insertTextOnCancel);
}));
}
@ -4013,37 +4005,32 @@ bool HistoryWidget::showSendingFilesError(
}
bool HistoryWidget::confirmSendingFiles(const QStringList &files) {
return confirmSendingFiles(files, CompressConfirm::Auto, nullptr);
return confirmSendingFiles(files, CompressConfirm::Auto);
}
bool HistoryWidget::confirmSendingFiles(const QMimeData *data) {
return confirmSendingFiles(data, CompressConfirm::Auto, nullptr);
return confirmSendingFiles(data, CompressConfirm::Auto);
}
bool HistoryWidget::confirmSendingFiles(
const QList<QUrl> &files,
CompressConfirm compressed,
const QString *addedComment) {
CompressConfirm compressed) {
return confirmSendingFiles(
Storage::PrepareMediaList(files, st::sendMediaPreviewSize),
compressed,
addedComment);
compressed);
}
bool HistoryWidget::confirmSendingFiles(
const QStringList &files,
CompressConfirm compressed,
const QString *addedComment) {
CompressConfirm compressed) {
return confirmSendingFiles(
Storage::PrepareMediaList(files, st::sendMediaPreviewSize),
compressed,
addedComment);
compressed);
}
bool HistoryWidget::confirmSendingFiles(
Storage::PreparedList &&list,
CompressConfirm compressed,
const QString *addedComment) {
CompressConfirm compressed) {
if (showSendingFilesError(list)) {
return false;
}
@ -4057,8 +4044,6 @@ bool HistoryWidget::confirmSendingFiles(
uploadFilesAfterConfirmation(
std::move(list),
QByteArray(),
QImage(),
SendMediaType::Photo,
caption,
replyToId(),
@ -4071,7 +4056,6 @@ bool HistoryWidget::confirmSendingFiles(
const auto insertTextOnCancel = QString();
auto sendCallback = [this](
Storage::PreparedList &&list,
const QImage &image,
bool compressed,
const QString &caption,
MsgId replyTo) {
@ -4080,8 +4064,6 @@ bool HistoryWidget::confirmSendingFiles(
: SendMediaType::File;
uploadFilesAfterConfirmation(
std::move(list),
QByteArray(),
image,
type,
caption,
replyTo);
@ -4094,22 +4076,20 @@ bool HistoryWidget::confirmSendingFiles(
return showSendFilesBox(
Box<SendFilesBox>(std::move(list), boxCompressConfirm),
insertTextOnCancel,
addedComment,
std::move(sendCallback));
}
}
bool HistoryWidget::confirmSendingFiles(
const QImage &image,
const QByteArray &content,
QImage &&image,
QByteArray &&content,
CompressConfirm compressed,
const QString &insertTextOnCancel) {
if (!canWriteMessage() || image.isNull()) return false;
App::wnd()->activateWindow();
auto sendCallback = [this, content](
auto sendCallback = [this](
Storage::PreparedList &&list,
const QImage &image,
bool compressed,
const QString &caption,
MsgId replyTo) {
@ -4118,16 +4098,17 @@ bool HistoryWidget::confirmSendingFiles(
: SendMediaType::File;
uploadFilesAfterConfirmation(
std::move(list),
content,
image,
type,
caption,
replyTo);
};
auto list = Storage::PrepareMediaFromImage(
std::move(image),
std::move(content),
st::sendMediaPreviewSize);
return showSendFilesBox(
Box<SendFilesBox>(image, compressed),
Box<SendFilesBox>(std::move(list), compressed),
insertTextOnCancel,
nullptr,
std::move(sendCallback));
}
@ -4152,7 +4133,7 @@ bool HistoryWidget::confirmSendingFiles(
auto image = qvariant_cast<QImage>(data->imageData());
if (!image.isNull()) {
confirmSendingFiles(
image,
std::move(image),
QByteArray(),
compressed,
insertTextOnCancel);
@ -4162,31 +4143,6 @@ bool HistoryWidget::confirmSendingFiles(
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(
Storage::PreparedList &&list,
SendMediaType type) {
@ -4195,8 +4151,6 @@ void HistoryWidget::uploadFiles(
auto caption = QString();
uploadFilesAfterConfirmation(
std::move(list),
QByteArray(),
QImage(),
type,
caption,
replyToId());
@ -4204,8 +4158,6 @@ void HistoryWidget::uploadFiles(
void HistoryWidget::uploadFilesAfterConfirmation(
Storage::PreparedList &&list,
const QByteArray &content,
const QImage &image,
SendMediaType type,
QString caption,
MsgId replyTo,
@ -4216,8 +4168,6 @@ void HistoryWidget::uploadFilesAfterConfirmation(
options.replyTo = replyTo;
Auth().api().sendFiles(
std::move(list),
content,
image,
type,
caption,
album,

View File

@ -497,24 +497,37 @@ private:
void unreadMentionsAnimationFinish();
void sendButtonClicked();
bool confirmShareContact(const QString &phone, const QString &fname, const QString &lname, const QString *addedComment = nullptr);
bool confirmSendingFiles(const QList<QUrl> &files, CompressConfirm compressed, const QString *addedComment = nullptr);
bool confirmSendingFiles(const QStringList &files, CompressConfirm compressed, const QString *addedComment = nullptr);
bool confirmSendingFiles(const QImage &image, const 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, const QString *addedComment = nullptr);
bool confirmSendingFiles(
const QList<QUrl> &files,
CompressConfirm compressed);
bool confirmSendingFiles(
const QStringList &files,
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;
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 uploadFile(const QByteArray &fileContent, SendMediaType type);
// If an empty filepath is found we upload (possible) "image" with (possible) "content".
void uploadFilesAfterConfirmation(
Storage::PreparedList &&list,
const QByteArray &content,
const QImage &image,
SendMediaType type,
QString caption,
MsgId replyTo,

View File

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

View File

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

View File

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

View File

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