mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-04-01 23:00:58 +00:00
new photo viewer done, testing, added compressed checkbox in send-from-clipboard
This commit is contained in:
parent
f62db48251
commit
d26afe1b64
@ -341,6 +341,7 @@ lng_context_forward_selected: "Forward Selected";
|
|||||||
lng_context_delete_selected: "Delete Selected";
|
lng_context_delete_selected: "Delete Selected";
|
||||||
lng_context_clear_selection: "Clear Selection";
|
lng_context_clear_selection: "Clear Selection";
|
||||||
lng_really_send_image: "Do you want to send this image?";
|
lng_really_send_image: "Do you want to send this image?";
|
||||||
|
lng_send_image_compressed: "Send compressed image";
|
||||||
|
|
||||||
lng_forward_choose: "Choose recipient...";
|
lng_forward_choose: "Choose recipient...";
|
||||||
lng_forward_confirm: "Forward to {recipient}?";
|
lng_forward_confirm: "Forward to {recipient}?";
|
||||||
@ -398,6 +399,15 @@ lng_search_no_results: "No messages found";
|
|||||||
lng_search_one_result: "Found {count} message";
|
lng_search_one_result: "Found {count} message";
|
||||||
lng_search_n_results: "Found {count} messages";
|
lng_search_n_results: "Found {count} messages";
|
||||||
|
|
||||||
|
lng_mediaview_close: "Close";
|
||||||
|
lng_mediaview_save: "Save as";
|
||||||
|
lng_mediaview_forward: "Forward";
|
||||||
|
lng_mediaview_delete: "Delete";
|
||||||
|
lng_mediaview_single_photo: "Single Photo";
|
||||||
|
lng_mediaview_group_photo: "Group Photo";
|
||||||
|
lng_mediaview_profile_photo: "Profile Photo";
|
||||||
|
lng_mediaview_n_of_count: "{n} of {count}";
|
||||||
|
|
||||||
// Mac specific
|
// Mac specific
|
||||||
|
|
||||||
lng_mac_choose_app: "Choose Application";
|
lng_mac_choose_app: "Choose Application";
|
||||||
|
@ -975,6 +975,8 @@ boxBG: white;//rgb(228, 233, 240);
|
|||||||
boxGrayTitle: #777;
|
boxGrayTitle: #777;
|
||||||
|
|
||||||
confirmWidth: 364px;
|
confirmWidth: 364px;
|
||||||
|
confirmMaxHeight: 320px;
|
||||||
|
confirmCompressedSkip: 10px;
|
||||||
addContactWidth: 364px;
|
addContactWidth: 364px;
|
||||||
addContactPadding: margins(18px, 24px, 18px, 24px);
|
addContactPadding: margins(18px, 24px, 18px, 24px);
|
||||||
addContactDelta: 14px;
|
addContactDelta: 14px;
|
||||||
@ -1439,11 +1441,45 @@ emojiPanDuration: 200;
|
|||||||
emojiPanHover: #f0f0f0;
|
emojiPanHover: #f0f0f0;
|
||||||
emojiPanRound: 2px;
|
emojiPanRound: 2px;
|
||||||
|
|
||||||
medviewNavBarWidth: 200px;
|
medviewNavBarWidth: 120px;
|
||||||
medviewTopSkip: 50px;
|
medviewTopSkip: 66px;
|
||||||
medviewBottomSkip: 50px;
|
medviewBottomSkip: 66px;
|
||||||
medviewLightOpacity: 0.75;
|
medviewMainWidth: 600px;
|
||||||
|
medviewLightOpacity: 0.7;
|
||||||
|
medviewDarkOpacity: 0.8;
|
||||||
|
medviewLightNav: 0.5;
|
||||||
|
medviewHeaderFont: font(semibold 18px);
|
||||||
|
medviewDateFont: font(fsize);
|
||||||
|
medviewNameTop: 3px;
|
||||||
|
medviewDateTop: 25px;
|
||||||
|
medviewHeaderColor: #ffffffc0;
|
||||||
|
medviewNameColor: medviewHeaderColor;
|
||||||
|
medviewNameOverColor: #fff;
|
||||||
|
medviewDarkNav: 1;
|
||||||
medviewMinWidth: 600;
|
medviewMinWidth: 600;
|
||||||
|
medviewLeft: sprite(0px, 340px, 22px, 40px);
|
||||||
|
medviewRight: sprite(22px, 340px, 22px, 40px);
|
||||||
|
medviewDeltaFromLastAction: 5px;
|
||||||
|
medviewSwipeDistance: 80px;
|
||||||
|
medviewButton: flatButton(btnDefFlat) {
|
||||||
|
color: #ffffff80;
|
||||||
|
overColor: #fff;
|
||||||
|
downColor: #fff;
|
||||||
|
|
||||||
|
bgColor: #0000;
|
||||||
|
overBgColor: #00000055;
|
||||||
|
downBgColor: #00000055;
|
||||||
|
|
||||||
|
width: 100px;
|
||||||
|
height: 46px;
|
||||||
|
|
||||||
|
textTop: 13px;
|
||||||
|
overTextTop: 13px;
|
||||||
|
downTextTop: 14px;
|
||||||
|
|
||||||
|
font: font(16px);
|
||||||
|
overFont: font(16px);
|
||||||
|
}
|
||||||
|
|
||||||
// Mac specific
|
// Mac specific
|
||||||
|
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 24 KiB |
Binary file not shown.
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 51 KiB |
@ -24,6 +24,7 @@ Copyright (c) 2014 John Preston, https://tdesktop.com
|
|||||||
#include "photosendbox.h"
|
#include "photosendbox.h"
|
||||||
|
|
||||||
PhotoSendBox::PhotoSendBox(const ReadyLocalMedia &img) : _img(img),
|
PhotoSendBox::PhotoSendBox(const ReadyLocalMedia &img) : _img(img),
|
||||||
|
_compressed(this, lang(lng_send_image_compressed), true),
|
||||||
_sendButton(this, lang(lng_send_button), st::btnSelectDone),
|
_sendButton(this, lang(lng_send_button), st::btnSelectDone),
|
||||||
_cancelButton(this, lang(lng_cancel), st::btnSelectCancel),
|
_cancelButton(this, lang(lng_cancel), st::btnSelectCancel),
|
||||||
a_opacity(0, 1) {
|
a_opacity(0, 1) {
|
||||||
@ -48,7 +49,7 @@ PhotoSendBox::PhotoSendBox(const ReadyLocalMedia &img) : _img(img),
|
|||||||
if (_thumb.width() < _thumbw) {
|
if (_thumb.width() < _thumbw) {
|
||||||
_thumbw = (_thumb.width() > 20) ? _thumb.width() : 20;
|
_thumbw = (_thumb.width() > 20) ? _thumb.width() : 20;
|
||||||
}
|
}
|
||||||
int32 maxthumbh = qRound(1.5 * _thumbw);
|
int32 maxthumbh = qMin(qRound(1.5 * _thumbw), int(st::confirmMaxHeight));
|
||||||
_thumbh = qRound(th * float64(_thumbw) / tw);
|
_thumbh = qRound(th * float64(_thumbw) / tw);
|
||||||
if (_thumbh > maxthumbh) {
|
if (_thumbh > maxthumbh) {
|
||||||
_thumbw = qRound(_thumbw * float64(maxthumbh) / _thumbh);
|
_thumbw = qRound(_thumbw * float64(maxthumbh) / _thumbh);
|
||||||
@ -57,7 +58,7 @@ PhotoSendBox::PhotoSendBox(const ReadyLocalMedia &img) : _img(img),
|
|||||||
_thumbw = 10;
|
_thumbw = 10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_height = _thumbh + st::boxPadding.top() + st::boxFont->height + st::boxPadding.bottom() + st::boxPadding.bottom() + _sendButton.height();
|
_height = _thumbh + st::boxPadding.top() + st::boxFont->height + st::boxPadding.bottom() + st::boxPadding.bottom() + _compressed.height() + _sendButton.height();
|
||||||
|
|
||||||
_thumb = QPixmap::fromImage(_thumb.toImage().scaled(_thumbw, _thumbh, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
_thumb = QPixmap::fromImage(_thumb.toImage().scaled(_thumbw, _thumbh, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||||
|
|
||||||
@ -77,6 +78,7 @@ void PhotoSendBox::parentResized() {
|
|||||||
setGeometry((s.width() - _width) / 2, (s.height() - _height) / 2, _width, _height);
|
setGeometry((s.width() - _width) / 2, (s.height() - _height) / 2, _width, _height);
|
||||||
_sendButton.move(_width - _sendButton.width(), _height - _sendButton.height());
|
_sendButton.move(_width - _sendButton.width(), _height - _sendButton.height());
|
||||||
_cancelButton.move(0, _height - _cancelButton.height());
|
_cancelButton.move(0, _height - _cancelButton.height());
|
||||||
|
_compressed.move((width() - _compressed.width()) / 2, _height - _cancelButton.height() - _compressed.height() - st::confirmCompressedSkip);
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,11 +109,16 @@ void PhotoSendBox::animStep(float64 ms) {
|
|||||||
}
|
}
|
||||||
_sendButton.setOpacity(a_opacity.current());
|
_sendButton.setOpacity(a_opacity.current());
|
||||||
_cancelButton.setOpacity(a_opacity.current());
|
_cancelButton.setOpacity(a_opacity.current());
|
||||||
|
_compressed.setOpacity(a_opacity.current());
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhotoSendBox::onSend() {
|
void PhotoSendBox::onSend() {
|
||||||
if (App::main()) App::main()->confirmSendImage(_img);
|
if (_compressed.checked()) {
|
||||||
|
if (App::main()) App::main()->confirmSendImage(_img);
|
||||||
|
} else {
|
||||||
|
if (App::main()) App::main()->confirmSendImageUncompressed();
|
||||||
|
}
|
||||||
emit closed();
|
emit closed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ private:
|
|||||||
|
|
||||||
ReadyLocalMedia _img;
|
ReadyLocalMedia _img;
|
||||||
int32 _width, _height, _thumbw, _thumbh;
|
int32 _width, _height, _thumbw, _thumbh;
|
||||||
|
FlatCheckbox _compressed;
|
||||||
FlatButton _sendButton, _cancelButton;
|
FlatButton _sendButton, _cancelButton;
|
||||||
QPixmap _thumb;
|
QPixmap _thumb;
|
||||||
|
|
||||||
|
@ -66,6 +66,8 @@ enum {
|
|||||||
|
|
||||||
AutoSearchTimeout = 900, // 0.9 secs
|
AutoSearchTimeout = 900, // 0.9 secs
|
||||||
SearchPerPage = 50,
|
SearchPerPage = 50,
|
||||||
|
MediaOverviewStartPerPage = 5,
|
||||||
|
MediaOverviewPreloadCount = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
|
@ -58,8 +58,9 @@ namespace anim {
|
|||||||
const float64 ¤t() const {
|
const float64 ¤t() const {
|
||||||
return _cur;
|
return _cur;
|
||||||
}
|
}
|
||||||
void update(const float64 &dt, transition func) {
|
fvalue &update(const float64 &dt, transition func) {
|
||||||
_cur = _from + (*func)(_delta, dt);
|
_cur = _from + (*func)(_delta, dt);
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
void finish() {
|
void finish() {
|
||||||
_cur = _from + _delta;
|
_cur = _from + _delta;
|
||||||
@ -92,8 +93,9 @@ namespace anim {
|
|||||||
int32 current() const {
|
int32 current() const {
|
||||||
return _cur;
|
return _cur;
|
||||||
}
|
}
|
||||||
void update(const float64 &dt, transition func) {
|
ivalue &update(const float64 &dt, transition func) {
|
||||||
_cur = qRound(_from + (*func)(_delta, dt));
|
_cur = qRound(_from + (*func)(_delta, dt));
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
void finish() {
|
void finish() {
|
||||||
_cur = qRound(_from + _delta);
|
_cur = qRound(_from + _delta);
|
||||||
@ -143,11 +145,12 @@ namespace anim {
|
|||||||
const QColor ¤t() const {
|
const QColor ¤t() const {
|
||||||
return _cur;
|
return _cur;
|
||||||
}
|
}
|
||||||
void update(const float64 &dt, transition func) {
|
cvalue &update(const float64 &dt, transition func) {
|
||||||
_cur.setRedF(_from_r + (*func)(_delta_r, dt));
|
_cur.setRedF(_from_r + (*func)(_delta_r, dt));
|
||||||
_cur.setGreenF(_from_g + (*func)(_delta_g, dt));
|
_cur.setGreenF(_from_g + (*func)(_delta_g, dt));
|
||||||
_cur.setBlueF(_from_b + (*func)(_delta_b, dt));
|
_cur.setBlueF(_from_b + (*func)(_delta_b, dt));
|
||||||
_cur.setAlphaF(_from_a + (*func)(_delta_a, dt));
|
_cur.setAlphaF(_from_a + (*func)(_delta_a, dt));
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
void finish() {
|
void finish() {
|
||||||
_cur.setRedF(_from_r + _delta_r);
|
_cur.setRedF(_from_r + _delta_r);
|
||||||
|
@ -68,14 +68,14 @@ bool _filedialogGetFiles(QStringList &files, QByteArray &remoteContent, const QS
|
|||||||
remoteContent = QByteArray();
|
remoteContent = QByteArray();
|
||||||
QString file;
|
QString file;
|
||||||
if (multipleFiles >= 0) {
|
if (multipleFiles >= 0) {
|
||||||
files = QFileDialog::getOpenFileNames(App::wnd(), caption, startFile, filter);
|
files = QFileDialog::getOpenFileNames(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, startFile, filter);
|
||||||
return !files.isEmpty();
|
return !files.isEmpty();
|
||||||
} else if (multipleFiles < -1) {
|
} else if (multipleFiles < -1) {
|
||||||
file = QFileDialog::getExistingDirectory(App::wnd(), caption);
|
file = QFileDialog::getExistingDirectory(App::wnd() ? App::wnd()->filedialogParent() : 0, caption);
|
||||||
} else if (multipleFiles < 0) {
|
} else if (multipleFiles < 0) {
|
||||||
file = QFileDialog::getSaveFileName(App::wnd(), caption, startFile, filter);
|
file = QFileDialog::getSaveFileName(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, startFile, filter);
|
||||||
} else {
|
} else {
|
||||||
file = QFileDialog::getOpenFileName(App::wnd(), caption, startFile, filter);
|
file = QFileDialog::getOpenFileName(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, startFile, filter);
|
||||||
}
|
}
|
||||||
if (file.isEmpty()) {
|
if (file.isEmpty()) {
|
||||||
files = QStringList();
|
files = QStringList();
|
||||||
@ -89,7 +89,7 @@ bool _filedialogGetFiles(QStringList &files, QByteArray &remoteContent, const QS
|
|||||||
filedialogInit();
|
filedialogInit();
|
||||||
|
|
||||||
// hack for fast non-native dialog create
|
// hack for fast non-native dialog create
|
||||||
QFileDialog dialog(App::wnd(), caption, cDialogHelperPathFinal(), filter);
|
QFileDialog dialog(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, cDialogHelperPathFinal(), filter);
|
||||||
|
|
||||||
dialog.setModal(true);
|
dialog.setModal(true);
|
||||||
if (multipleFiles >= 0) { // open file or files
|
if (multipleFiles >= 0) { // open file or files
|
||||||
@ -171,7 +171,7 @@ bool filedialogGetDir(QString &dir, const QString &caption) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString filedialogDefaultName(const QString &prefix, const QString &extension, const QString &path) {
|
QString filedialogDefaultName(const QString &prefix, const QString &extension, const QString &path, bool skipExistance) {
|
||||||
filedialogInit();
|
filedialogInit();
|
||||||
|
|
||||||
time_t t = time(NULL);
|
time_t t = time(NULL);
|
||||||
@ -180,11 +180,17 @@ QString filedialogDefaultName(const QString &prefix, const QString &extension, c
|
|||||||
|
|
||||||
QChar zero('0');
|
QChar zero('0');
|
||||||
|
|
||||||
QDir dir(path.isEmpty() ? cDialogLastPath() : path);
|
QString name;
|
||||||
QString base = prefix + QString("_%1-%2-%3_%4-%5-%6").arg(tm.tm_year + 1900).arg(tm.tm_mon + 1, 2, 10, zero).arg(tm.tm_mday, 2, 10, zero).arg(tm.tm_hour, 2, 10, zero).arg(tm.tm_min, 2, 10, zero).arg(tm.tm_sec, 2, 10, zero);
|
QString base = prefix + QString("_%1-%2-%3_%4-%5-%6").arg(tm.tm_year + 1900).arg(tm.tm_mon + 1, 2, 10, zero).arg(tm.tm_mday, 2, 10, zero).arg(tm.tm_hour, 2, 10, zero).arg(tm.tm_min, 2, 10, zero).arg(tm.tm_sec, 2, 10, zero);
|
||||||
QString nameBase = dir.absolutePath() + '/' + base, name = nameBase + extension;
|
if (skipExistance) {
|
||||||
for (int i = 0; QFileInfo(name).exists(); ++i) {
|
name = base + extension;
|
||||||
name = nameBase + QString(" (%1)").arg(i + 2) + extension;
|
} else {
|
||||||
|
QDir dir(path.isEmpty() ? cDialogLastPath() : path);
|
||||||
|
QString nameBase = dir.absolutePath() + '/' + base;
|
||||||
|
name = nameBase + extension;
|
||||||
|
for (int i = 0; QFileInfo(name).exists(); ++i) {
|
||||||
|
name = nameBase + QString(" (%1)").arg(i + 2) + extension;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
@ -23,4 +23,4 @@ bool filedialogGetOpenFile(QString &file, QByteArray &remoteContent, const QStri
|
|||||||
bool filedialogGetSaveFile(QString &file, const QString &caption, const QString &filter, const QString &startName);
|
bool filedialogGetSaveFile(QString &file, const QString &caption, const QString &filter, const QString &startName);
|
||||||
bool filedialogGetDir(QString &dir, const QString &caption);
|
bool filedialogGetDir(QString &dir, const QString &caption);
|
||||||
|
|
||||||
QString filedialogDefaultName(const QString &prefix, const QString &extension, const QString &path = QString());
|
QString filedialogDefaultName(const QString &prefix, const QString &extension, const QString &path = QString(), bool skipExistance = false);
|
||||||
|
@ -78,6 +78,92 @@ const QPixmap &Image::pix(int32 w, int32 h) const {
|
|||||||
return i.value();
|
return i.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QPixmap &Image::pixBlurred(int32 w, int32 h) const {
|
||||||
|
restore();
|
||||||
|
checkload();
|
||||||
|
|
||||||
|
if (w <= 0 || !width() || !height()) {
|
||||||
|
w = width() * cIntRetinaFactor();
|
||||||
|
} else if (cRetina()) {
|
||||||
|
w *= cIntRetinaFactor();
|
||||||
|
h *= cIntRetinaFactor();
|
||||||
|
}
|
||||||
|
uint64 k = 0x8000000000000000L | (uint64(w) << 32) | uint64(h);
|
||||||
|
Sizes::const_iterator i = _sizesCache.constFind(k);
|
||||||
|
if (i == _sizesCache.cend()) {
|
||||||
|
QPixmap p(pixBlurredNoCache(w, h));
|
||||||
|
if (cRetina()) p.setDevicePixelRatio(cRetinaFactor());
|
||||||
|
i = _sizesCache.insert(k, p);
|
||||||
|
if (!p.isNull()) {
|
||||||
|
globalAquiredSize += int64(p.width()) * p.height() * 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return i.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
QPixmap Image::pixBlurredNoCache(int32 w, int32 h) const {
|
||||||
|
return pixNoCache(w, h);
|
||||||
|
restore();
|
||||||
|
loaded();
|
||||||
|
|
||||||
|
const QPixmap &p(pixData());
|
||||||
|
if (p.isNull()) return blank()->pix();
|
||||||
|
|
||||||
|
QImage img;
|
||||||
|
if (h <= 0) {
|
||||||
|
img = p.toImage().scaledToWidth(w, Qt::SmoothTransformation);
|
||||||
|
} else {
|
||||||
|
img = p.toImage().scaled(w, h, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||||
|
}
|
||||||
|
QImage::Format fmt = img.format();
|
||||||
|
if (fmt != QImage::Format_RGB32 && fmt != QImage::Format_ARGB32 && fmt != QImage::Format_ARGB32_Premultiplied) {
|
||||||
|
QImage tmp(img.width(), img.height(), QImage::Format_ARGB32);
|
||||||
|
{
|
||||||
|
QPainter p(&tmp);
|
||||||
|
p.drawImage(0, 0, img);
|
||||||
|
}
|
||||||
|
img = tmp;
|
||||||
|
}
|
||||||
|
QImage fromimg = img;
|
||||||
|
|
||||||
|
uchar *bits = img.bits();
|
||||||
|
const uchar *from = fromimg.bits();
|
||||||
|
if (bits && from) {
|
||||||
|
int width = img.width(), height = img.height();
|
||||||
|
for (int i = 0; i < width; ++i) {
|
||||||
|
for (int j = 0; j < height; ++j) {
|
||||||
|
uint32 a = 0, b = 0, c = 0;
|
||||||
|
for (int index = i - 32; index < i + 32; ++index) {
|
||||||
|
int fullindex = 4 * (j * width + ((index < 0) ? 0 : (index >= width ? (width - 1) : index))), coef = 4;
|
||||||
|
a += from[fullindex + 1] * coef;
|
||||||
|
b += from[fullindex + 2] * coef;
|
||||||
|
c += from[fullindex + 3] * coef;
|
||||||
|
}
|
||||||
|
int fullindex = 4 * (j * width + i);
|
||||||
|
bits[fullindex + 1] = uchar(a >> 8);
|
||||||
|
bits[fullindex + 2] = uchar(b >> 8);
|
||||||
|
bits[fullindex + 3] = uchar(c >> 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < width; ++i) {
|
||||||
|
for (int j = 0; j < height; ++j) {
|
||||||
|
uint32 a = 0, b = 0, c = 0;
|
||||||
|
for (int index = j - 32; index < j + 32; ++index) {
|
||||||
|
int fullindex = 4 * (((index < 0) ? 0 : (index >= height ? (height - 1) : index)) * width + i), coef = 4;
|
||||||
|
a += from[fullindex + 1] * coef;
|
||||||
|
b += from[fullindex + 2] * coef;
|
||||||
|
c += from[fullindex + 3] * coef;
|
||||||
|
}
|
||||||
|
int fullindex = 4 * (j * width + i);
|
||||||
|
bits[fullindex + 1] = uchar(a >> 8);
|
||||||
|
bits[fullindex + 2] = uchar(b >> 8);
|
||||||
|
bits[fullindex + 3] = uchar(c >> 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QPixmap::fromImage(img);
|
||||||
|
}
|
||||||
|
|
||||||
QPixmap Image::pixNoCache(int32 w, int32 h, bool smooth) const {
|
QPixmap Image::pixNoCache(int32 w, int32 h, bool smooth) const {
|
||||||
restore();
|
restore();
|
||||||
loaded();
|
loaded();
|
||||||
|
@ -28,7 +28,9 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const QPixmap &pix(int32 w = 0, int32 h = 0) const;
|
const QPixmap &pix(int32 w = 0, int32 h = 0) const;
|
||||||
|
const QPixmap &pixBlurred(int32 w = 0, int32 h = 0) const;
|
||||||
QPixmap pixNoCache(int32 w = 0, int32 h = 0, bool smooth = false) const;
|
QPixmap pixNoCache(int32 w = 0, int32 h = 0, bool smooth = false) const;
|
||||||
|
QPixmap pixBlurredNoCache(int32 w, int32 h = 0) const;
|
||||||
|
|
||||||
virtual int32 width() const = 0;
|
virtual int32 width() const = 0;
|
||||||
virtual int32 height() const = 0;
|
virtual int32 height() const = 0;
|
||||||
|
@ -2642,6 +2642,10 @@ int32 Text::countHeight(int32 w) const {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Text::replaceFont(style::font f) {
|
||||||
|
_font = f;
|
||||||
|
}
|
||||||
|
|
||||||
void Text::draw(QPainter &painter, int32 left, int32 top, int32 w, style::align align, int32 yFrom, int32 yTo, uint16 selectedFrom, uint16 selectedTo) const {
|
void Text::draw(QPainter &painter, int32 left, int32 top, int32 w, style::align align, int32 yFrom, int32 yTo, uint16 selectedFrom, uint16 selectedTo) const {
|
||||||
// painter.fillRect(QRect(left, top, w, countHeight(w)), QColor(0, 0, 0, 32)); // debug
|
// painter.fillRect(QRect(left, top, w, countHeight(w)), QColor(0, 0, 0, 32)); // debug
|
||||||
TextPainter p(&painter, this);
|
TextPainter p(&painter, this);
|
||||||
|
@ -373,6 +373,8 @@ public:
|
|||||||
return _minHeight;
|
return _minHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void replaceFont(style::font f); // does not recount anything, use at your own risk!
|
||||||
|
|
||||||
void draw(QPainter &p, int32 left, int32 top, int32 width, style::align align = style::al_left, int32 yFrom = 0, int32 yTo = -1, uint16 selectedFrom = 0, uint16 selectedTo = 0) const;
|
void draw(QPainter &p, int32 left, int32 top, int32 width, style::align align = style::al_left, int32 yFrom = 0, int32 yTo = -1, uint16 selectedFrom = 0, uint16 selectedTo = 0) const;
|
||||||
void drawElided(QPainter &p, int32 left, int32 top, int32 width, int32 lines = 1, style::align align = style::al_left, int32 yFrom = 0, int32 yTo = -1) const;
|
void drawElided(QPainter &p, int32 left, int32 top, int32 width, int32 lines = 1, style::align align = style::al_left, int32 yFrom = 0, int32 yTo = -1) const;
|
||||||
|
|
||||||
|
@ -223,7 +223,9 @@ void ChatData::setPhoto(const MTPChatPhoto &p, const PhotoId &phId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PhotoLink::onClick(Qt::MouseButton button) const {
|
void PhotoLink::onClick(Qt::MouseButton button) const {
|
||||||
if (button == Qt::LeftButton) App::wnd()->showPhoto(this, App::hoveredLinkItem());
|
if (button == Qt::LeftButton) {
|
||||||
|
App::wnd()->showPhoto(this, App::hoveredLinkItem());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString saveFileName(const QString &title, const QString &filter, const QString &prefix, QString name, bool savingAs, const QDir &dir = QDir()) {
|
QString saveFileName(const QString &title, const QString &filter, const QString &prefix, QString name, bool savingAs, const QDir &dir = QDir()) {
|
||||||
@ -657,6 +659,7 @@ History::History(const PeerId &peerId) : width(0), height(0)
|
|||||||
, posInDialogs(0)
|
, posInDialogs(0)
|
||||||
, typingText(st::dlgRichMinWidth)
|
, typingText(st::dlgRichMinWidth)
|
||||||
, myTyping(0)
|
, myTyping(0)
|
||||||
|
, _photosOverviewCount(-1) // not loaded yet
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1081,6 +1084,14 @@ HistoryItem *History::doAddToBack(HistoryBlock *to, bool newBlock, HistoryItem *
|
|||||||
if (newMsg) {
|
if (newMsg) {
|
||||||
newItemAdded(adding);
|
newItemAdded(adding);
|
||||||
}
|
}
|
||||||
|
HistoryMedia *media = adding->getMedia(true);
|
||||||
|
if (media && media->type() == MediaTypePhoto) {
|
||||||
|
if (_photosOverviewIds.constFind(adding->id) == _photosOverviewIds.cend()) {
|
||||||
|
_photosOverview.push_front(adding->id);
|
||||||
|
_photosOverviewIds.insert(adding->id);
|
||||||
|
if (App::wnd()) App::wnd()->mediaOverviewUpdated(peer);
|
||||||
|
}
|
||||||
|
}
|
||||||
return adding;
|
return adding;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1163,6 +1174,20 @@ void History::addToFront(const QVector<MTPMessage> &slice) {
|
|||||||
push_front(block);
|
push_front(block);
|
||||||
addToH += block->height;
|
addToH += block->height;
|
||||||
++skip;
|
++skip;
|
||||||
|
|
||||||
|
if (loadedAtBottom()) { // add photos to overview
|
||||||
|
for (int32 i = block->size(); i > 0; --i) {
|
||||||
|
HistoryItem *item = (*block)[i - 1];
|
||||||
|
HistoryMedia *media = item->getMedia(true);
|
||||||
|
if (media && media->type() == MediaTypePhoto) {
|
||||||
|
if (_photosOverviewIds.constFind(item->id) == _photosOverviewIds.cend()) {
|
||||||
|
_photosOverview.push_front(item->id);
|
||||||
|
_photosOverviewIds.insert(item->id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (App::wnd()) App::wnd()->mediaOverviewUpdated(peer);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
delete block;
|
delete block;
|
||||||
}
|
}
|
||||||
@ -1225,6 +1250,7 @@ void History::addToBack(const QVector<MTPMessage> &slice) {
|
|||||||
}
|
}
|
||||||
if (i == e) break;
|
if (i == e) break;
|
||||||
}
|
}
|
||||||
|
bool wasLoadedAtBottom = loadedAtBottom();
|
||||||
if (block->size()) {
|
if (block->size()) {
|
||||||
block->y = height;
|
block->y = height;
|
||||||
push_back(block);
|
push_back(block);
|
||||||
@ -1234,6 +1260,23 @@ void History::addToBack(const QVector<MTPMessage> &slice) {
|
|||||||
fixLastMessage(true);
|
fixLastMessage(true);
|
||||||
delete block;
|
delete block;
|
||||||
}
|
}
|
||||||
|
if (!wasLoadedAtBottom && loadedAtBottom()) { // add all loaded photos to overview
|
||||||
|
_photosOverview.clear();
|
||||||
|
_photosOverviewIds.clear();
|
||||||
|
_photosOverviewCount = -1; // full count unknown
|
||||||
|
for (int32 i = 0; i < size(); ++i) {
|
||||||
|
HistoryBlock *b = (*this)[i];
|
||||||
|
for (int32 j = 0; j < b->size(); ++j) {
|
||||||
|
HistoryItem *item = (*b)[j];
|
||||||
|
HistoryMedia *media = item->getMedia(true);
|
||||||
|
if (media && media->type() == MediaTypePhoto) {
|
||||||
|
_photosOverview.push_back(item->id);
|
||||||
|
_photosOverviewIds.insert(item->id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (App::wnd()) App::wnd()->mediaOverviewUpdated(peer);
|
||||||
|
}
|
||||||
if (wasEmpty && !isEmpty()) {
|
if (wasEmpty && !isEmpty()) {
|
||||||
HistoryBlock *dateBlock = new HistoryBlock(this);
|
HistoryBlock *dateBlock = new HistoryBlock(this);
|
||||||
HistoryItem *dayItem = createDayServiceMsg(this, dateBlock, front()->front()->date);
|
HistoryItem *dayItem = createDayServiceMsg(this, dateBlock, front()->front()->date);
|
||||||
@ -1469,6 +1512,10 @@ void History::clear(bool leaveItems) {
|
|||||||
if (showFrom) {
|
if (showFrom) {
|
||||||
showFrom = 0;
|
showFrom = 0;
|
||||||
}
|
}
|
||||||
|
_photosOverview.clear();
|
||||||
|
_photosOverviewIds.clear();
|
||||||
|
_photosOverviewCount = -1; // full count unknown
|
||||||
|
if (App::wnd()) App::wnd()->mediaOverviewUpdated(peer);
|
||||||
for (Parent::const_iterator i = cbegin(), e = cend(); i != e; ++i) {
|
for (Parent::const_iterator i = cbegin(), e = cend(); i != e; ++i) {
|
||||||
if (leaveItems) {
|
if (leaveItems) {
|
||||||
(*i)->clear(true);
|
(*i)->clear(true);
|
||||||
@ -1664,6 +1711,31 @@ void HistoryItem::markRead() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HistoryItem::destroy() {
|
||||||
|
if (!out()) markRead();
|
||||||
|
bool wasAtBottom = history()->loadedAtBottom();
|
||||||
|
_history->removeNotification(this);
|
||||||
|
detach();
|
||||||
|
if (history()->last == this) {
|
||||||
|
history()->fixLastMessage(wasAtBottom);
|
||||||
|
}
|
||||||
|
HistoryMedia *m = getMedia(true);
|
||||||
|
if (m && m->type() == MediaTypePhoto && !history()->_photosOverviewIds.isEmpty()) {
|
||||||
|
History::MediaOverviewIds::iterator i = history()->_photosOverviewIds.find(id);
|
||||||
|
if (i != history()->_photosOverviewIds.cend()) {
|
||||||
|
history()->_photosOverviewIds.erase(i);
|
||||||
|
for (History::MediaOverview::iterator i = history()->_photosOverview.begin(), e = history()->_photosOverview.end(); i != e; ++i) {
|
||||||
|
if ((*i) == id) {
|
||||||
|
history()->_photosOverview.erase(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (App::wnd()) App::wnd()->mediaOverviewUpdated(history()->peer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
void HistoryItem::detach() {
|
void HistoryItem::detach() {
|
||||||
if (_history && _history->unreadBar == this) {
|
if (_history && _history->unreadBar == this) {
|
||||||
_history->unreadBar = 0;
|
_history->unreadBar = 0;
|
||||||
@ -1705,8 +1777,17 @@ HistoryItem *regItem(HistoryItem *item, bool returnExisting) {
|
|||||||
|
|
||||||
HistoryPhoto::HistoryPhoto(const MTPDphoto &photo, int32 width) : data(App::feedPhoto(photo))
|
HistoryPhoto::HistoryPhoto(const MTPDphoto &photo, int32 width) : data(App::feedPhoto(photo))
|
||||||
, openl(new PhotoLink(data))
|
, openl(new PhotoLink(data))
|
||||||
, w(width)
|
, w(width) {
|
||||||
{
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
HistoryPhoto::HistoryPhoto(PeerData *chat, const MTPDphoto &photo, int32 width) : data(App::feedPhoto(photo))
|
||||||
|
, openl(new PhotoLink(data, chat))
|
||||||
|
, w(width) {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryPhoto::init() {
|
||||||
int32 tw = data->full->width(), th = data->full->height();
|
int32 tw = data->full->width(), th = data->full->height();
|
||||||
if (!tw || !th) {
|
if (!tw || !th) {
|
||||||
tw = th = 1;
|
tw = th = 1;
|
||||||
@ -1767,11 +1848,11 @@ HistoryMedia *HistoryPhoto::clone() const {
|
|||||||
void HistoryPhoto::draw(QPainter &p, const HistoryItem *parent, const QString &time, int32 timeWidth, bool selected) const {
|
void HistoryPhoto::draw(QPainter &p, const HistoryItem *parent, const QString &time, int32 timeWidth, bool selected) const {
|
||||||
data->full->load(false, false);
|
data->full->load(false, false);
|
||||||
bool out = parent->out();
|
bool out = parent->out();
|
||||||
if (parent != App::contextItem() || App::wnd()->photoShown() != data) {
|
if (parent != App::contextItem()/* || App::wnd()->photoShown() != data*/) {
|
||||||
if (data->full->loaded()) {
|
if (data->full->loaded()) {
|
||||||
p.drawPixmap(0, 0, data->full->pix(_maxw, _height));
|
p.drawPixmap(0, 0, data->full->pix(_maxw, _height));
|
||||||
} else {
|
} else {
|
||||||
p.drawPixmap(0, 0, data->thumb->pix(_maxw, _height));
|
p.drawPixmap(0, 0, data->thumb->pixBlurred(_maxw, _height));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selected) {
|
if (selected) {
|
||||||
@ -2718,7 +2799,7 @@ QString HistoryMessage::selectedText(uint32 selection) const {
|
|||||||
return _text.original(selectedFrom, selectedTo);
|
return _text.original(selectedFrom, selectedTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryMedia *HistoryMessage::getMedia() const {
|
HistoryMedia *HistoryMessage::getMedia(bool inOverview) const {
|
||||||
return media;
|
return media;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3030,7 +3111,9 @@ QString HistoryMessage::notificationText() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
HistoryMessage::~HistoryMessage() {
|
HistoryMessage::~HistoryMessage() {
|
||||||
if (media) media->unregItem(this);
|
if (media) {
|
||||||
|
media->unregItem(this);
|
||||||
|
}
|
||||||
delete media;
|
delete media;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3249,7 +3332,7 @@ QString HistoryServiceMsg::messageByAction(const MTPmessageAction &action, TextL
|
|||||||
case mtpc_messageActionChatEditPhoto: {
|
case mtpc_messageActionChatEditPhoto: {
|
||||||
const MTPDmessageActionChatEditPhoto &d(action.c_messageActionChatEditPhoto());
|
const MTPDmessageActionChatEditPhoto &d(action.c_messageActionChatEditPhoto());
|
||||||
if (d.vphoto.type() == mtpc_photo) {
|
if (d.vphoto.type() == mtpc_photo) {
|
||||||
media = new HistoryPhoto(d.vphoto.c_photo(), 100);
|
media = new HistoryPhoto(history()->peer, d.vphoto.c_photo(), 100);
|
||||||
}
|
}
|
||||||
return lang(lng_action_changed_photo);
|
return lang(lng_action_changed_photo);
|
||||||
} break;
|
} break;
|
||||||
@ -3457,6 +3540,10 @@ QString HistoryServiceMsg::notificationText() const {
|
|||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HistoryMedia *HistoryServiceMsg::getMedia(bool inOverview) const {
|
||||||
|
return inOverview ? 0 : media;
|
||||||
|
}
|
||||||
|
|
||||||
HistoryServiceMsg::~HistoryServiceMsg() {
|
HistoryServiceMsg::~HistoryServiceMsg() {
|
||||||
delete media;
|
delete media;
|
||||||
}
|
}
|
||||||
|
@ -135,8 +135,9 @@ private:
|
|||||||
const PeerData *_peer;
|
const PeerData *_peer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct PhotoData;
|
||||||
struct UserData : public PeerData {
|
struct UserData : public PeerData {
|
||||||
UserData(const PeerId &id) : PeerData(id), lnk(new PeerLink(this)), onlineTill(0), contact(-1) {
|
UserData(const PeerId &id) : PeerData(id), lnk(new PeerLink(this)), onlineTill(0), contact(-1), photosCount(-1) {
|
||||||
}
|
}
|
||||||
void setPhoto(const MTPUserProfilePhoto &photo);
|
void setPhoto(const MTPUserProfilePhoto &photo);
|
||||||
void setName(const QString &first, const QString &last, const QString &phoneName);
|
void setName(const QString &first, const QString &last, const QString &phoneName);
|
||||||
@ -151,6 +152,10 @@ struct UserData : public PeerData {
|
|||||||
TextLinkPtr lnk;
|
TextLinkPtr lnk;
|
||||||
int32 onlineTill;
|
int32 onlineTill;
|
||||||
int32 contact; // -1 - not contact, cant add (self, empty, deleted, foreign), 0 - not contact, can add (request), 1 - contact
|
int32 contact; // -1 - not contact, cant add (self, empty, deleted, foreign), 0 - not contact, can add (request), 1 - contact
|
||||||
|
|
||||||
|
typedef QList<PhotoData*> Photos;
|
||||||
|
Photos photos;
|
||||||
|
int32 photosCount; // -1 not loaded, 0 all loaded
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ChatData : public PeerData {
|
struct ChatData : public PeerData {
|
||||||
@ -193,15 +198,21 @@ struct PhotoData {
|
|||||||
|
|
||||||
class PhotoLink : public ITextLink {
|
class PhotoLink : public ITextLink {
|
||||||
public:
|
public:
|
||||||
PhotoLink(PhotoData *photo) : _photo(photo) {
|
PhotoLink(PhotoData *photo) : _photo(photo), _peer(0) {
|
||||||
|
}
|
||||||
|
PhotoLink(PhotoData *photo, PeerData *peer) : _photo(photo), _peer(peer) {
|
||||||
}
|
}
|
||||||
void onClick(Qt::MouseButton button) const;
|
void onClick(Qt::MouseButton button) const;
|
||||||
PhotoData *photo() const {
|
PhotoData *photo() const {
|
||||||
return _photo;
|
return _photo;
|
||||||
}
|
}
|
||||||
|
PeerData *peer() const {
|
||||||
|
return _peer;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PhotoData *_photo;
|
PhotoData *_photo;
|
||||||
|
PeerData *_peer;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FileStatus {
|
enum FileStatus {
|
||||||
@ -695,6 +706,12 @@ struct History : public QList<HistoryBlock*> {
|
|||||||
bool updateTyping(uint64 ms = 0, uint32 dots = 0, bool force = false);
|
bool updateTyping(uint64 ms = 0, uint32 dots = 0, bool force = false);
|
||||||
uint64 myTyping;
|
uint64 myTyping;
|
||||||
|
|
||||||
|
typedef QList<MsgId> MediaOverview;
|
||||||
|
typedef QSet<MsgId> MediaOverviewIds;
|
||||||
|
MediaOverview _photosOverview;
|
||||||
|
MediaOverviewIds _photosOverviewIds;
|
||||||
|
int32 _photosOverviewCount; // -1 - not loaded, 0 - all loaded, > 0 - count, but not all loaded
|
||||||
|
|
||||||
static const int32 ScrollMax = INT_MAX;
|
static const int32 ScrollMax = INT_MAX;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1018,6 +1035,7 @@ protected:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class HistoryMedia;
|
||||||
class HistoryItem : public HistoryElem {
|
class HistoryItem : public HistoryElem {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -1048,16 +1066,7 @@ public:
|
|||||||
const HistoryBlock *block() const {
|
const HistoryBlock *block() const {
|
||||||
return _block;
|
return _block;
|
||||||
}
|
}
|
||||||
void destroy() {
|
void destroy();
|
||||||
if (!out()) markRead();
|
|
||||||
bool wasAtBottom = history()->loadedAtBottom();
|
|
||||||
_history->removeNotification(this);
|
|
||||||
detach();
|
|
||||||
if (history()->last == this) {
|
|
||||||
history()->fixLastMessage(wasAtBottom);
|
|
||||||
}
|
|
||||||
delete this;
|
|
||||||
}
|
|
||||||
void detach();
|
void detach();
|
||||||
void detachFast();
|
void detachFast();
|
||||||
bool detached() const {
|
bool detached() const {
|
||||||
@ -1117,6 +1126,10 @@ public:
|
|||||||
int32 y, id;
|
int32 y, id;
|
||||||
QDateTime date;
|
QDateTime date;
|
||||||
|
|
||||||
|
virtual HistoryMedia *getMedia(bool inOverview = false) const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
virtual ~HistoryItem();
|
virtual ~HistoryItem();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -1177,6 +1190,9 @@ class HistoryPhoto : public HistoryMedia {
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
HistoryPhoto(const MTPDphoto &photo, int32 width = 0);
|
HistoryPhoto(const MTPDphoto &photo, int32 width = 0);
|
||||||
|
HistoryPhoto(PeerData *chat, const MTPDphoto &photo, int32 width = 0);
|
||||||
|
|
||||||
|
void init();
|
||||||
|
|
||||||
void draw(QPainter &p, const HistoryItem *parent, const QString &time, int32 timeWidth, bool selected) const;
|
void draw(QPainter &p, const HistoryItem *parent, const QString &time, int32 timeWidth, bool selected) const;
|
||||||
int32 resize(int32 width);
|
int32 resize(int32 width);
|
||||||
@ -1189,6 +1205,10 @@ public:
|
|||||||
bool getPhotoCoords(PhotoData *photo, int32 &x, int32 &y, int32 &w) const;
|
bool getPhotoCoords(PhotoData *photo, int32 &x, int32 &y, int32 &w) const;
|
||||||
HistoryMedia *clone() const;
|
HistoryMedia *clone() const;
|
||||||
|
|
||||||
|
PhotoData *photo() const {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PhotoData *data;
|
PhotoData *data;
|
||||||
TextLinkPtr openl;
|
TextLinkPtr openl;
|
||||||
@ -1369,7 +1389,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString selectedText(uint32 selection) const;
|
QString selectedText(uint32 selection) const;
|
||||||
HistoryMedia *getMedia() const;
|
HistoryMedia *getMedia(bool inOverview = false) const;
|
||||||
|
|
||||||
~HistoryMessage();
|
~HistoryMessage();
|
||||||
|
|
||||||
@ -1446,6 +1466,8 @@ public:
|
|||||||
}
|
}
|
||||||
QString selectedText(uint32 selection) const;
|
QString selectedText(uint32 selection) const;
|
||||||
|
|
||||||
|
HistoryMedia *getMedia(bool inOverview = false) const;
|
||||||
|
|
||||||
~HistoryServiceMsg();
|
~HistoryServiceMsg();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -2669,9 +2669,19 @@ void HistoryWidget::uploadImage(const QImage &img) {
|
|||||||
if (!hist || confirmImageId) return;
|
if (!hist || confirmImageId) return;
|
||||||
|
|
||||||
App::wnd()->activateWindow();
|
App::wnd()->activateWindow();
|
||||||
|
confirmImage = img;
|
||||||
confirmImageId = imageLoader.append(img, histPeer->id, ToPreparePhoto);
|
confirmImageId = imageLoader.append(img, histPeer->id, ToPreparePhoto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HistoryWidget::uploadConfirmImageUncompressed() {
|
||||||
|
if (!hist || !confirmImageId || confirmImage.isNull()) return;
|
||||||
|
|
||||||
|
App::wnd()->activateWindow();
|
||||||
|
imageLoader.append(confirmImage, histPeer->id, ToPrepareDocument);
|
||||||
|
confirmImageId = 0;
|
||||||
|
confirmImage = QImage();
|
||||||
|
}
|
||||||
|
|
||||||
void HistoryWidget::uploadMedias(const QStringList &files, ToPrepareMediaType type) {
|
void HistoryWidget::uploadMedias(const QStringList &files, ToPrepareMediaType type) {
|
||||||
if (!hist) return;
|
if (!hist) return;
|
||||||
|
|
||||||
@ -2706,6 +2716,7 @@ void HistoryWidget::onPhotoFailed(quint64 id) {
|
|||||||
void HistoryWidget::confirmSendImage(const ReadyLocalMedia &img) {
|
void HistoryWidget::confirmSendImage(const ReadyLocalMedia &img) {
|
||||||
if (img.id == confirmImageId) {
|
if (img.id == confirmImageId) {
|
||||||
confirmImageId = 0;
|
confirmImageId = 0;
|
||||||
|
confirmImage = QImage();
|
||||||
}
|
}
|
||||||
MsgId newId = clientMsgId();
|
MsgId newId = clientMsgId();
|
||||||
|
|
||||||
@ -2737,6 +2748,7 @@ void HistoryWidget::confirmSendImage(const ReadyLocalMedia &img) {
|
|||||||
|
|
||||||
void HistoryWidget::cancelSendImage() {
|
void HistoryWidget::cancelSendImage() {
|
||||||
confirmImageId = 0;
|
confirmImageId = 0;
|
||||||
|
confirmImage = QImage();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryWidget::onPhotoUploaded(MsgId newId, const MTPInputFile &file) {
|
void HistoryWidget::onPhotoUploaded(MsgId newId, const MTPInputFile &file) {
|
||||||
|
@ -291,6 +291,7 @@ public:
|
|||||||
|
|
||||||
void destroyData();
|
void destroyData();
|
||||||
void uploadImage(const QImage &img);
|
void uploadImage(const QImage &img);
|
||||||
|
void uploadConfirmImageUncompressed();
|
||||||
void uploadMedias(const QStringList &files, ToPrepareMediaType type);
|
void uploadMedias(const QStringList &files, ToPrepareMediaType type);
|
||||||
void uploadMedia(const QByteArray &fileContent, ToPrepareMediaType type);
|
void uploadMedia(const QByteArray &fileContent, ToPrepareMediaType type);
|
||||||
void confirmSendImage(const ReadyLocalMedia &img);
|
void confirmSendImage(const ReadyLocalMedia &img);
|
||||||
@ -427,6 +428,7 @@ private:
|
|||||||
mtpRequestId loadingRequestId;
|
mtpRequestId loadingRequestId;
|
||||||
|
|
||||||
int64 serviceImageCacheSize;
|
int64 serviceImageCacheSize;
|
||||||
|
QImage confirmImage;
|
||||||
PhotoId confirmImageId;
|
PhotoId confirmImageId;
|
||||||
|
|
||||||
QString titlePeerText;
|
QString titlePeerText;
|
||||||
|
@ -125,328 +125,3 @@ BackgroundWidget::~BackgroundWidget() {
|
|||||||
w->deleteLater();
|
w->deleteLater();
|
||||||
if (_hidden) _hidden->deleteLater();
|
if (_hidden) _hidden->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
LayerWidget::LayerWidget(QWidget *parent, PhotoData *photo, HistoryItem *item) : QWidget(parent)
|
|
||||||
, photo(photo)
|
|
||||||
, video(0)
|
|
||||||
, aBackground(0)
|
|
||||||
, aOver(0)
|
|
||||||
, iX(App::wnd()->width() / 2)
|
|
||||||
, iY(App::wnd()->height() / 2)
|
|
||||||
, iW(0)
|
|
||||||
, iCoordFunc(anim::sineInOut)
|
|
||||||
, aBackgroundFunc(anim::easeOutCirc)
|
|
||||||
, aOverFunc(anim::linear)
|
|
||||||
, hiding(false)
|
|
||||||
, _touchPress(false)
|
|
||||||
, _touchMove(false)
|
|
||||||
, _touchRightButton(false)
|
|
||||||
, _menu(0)
|
|
||||||
{
|
|
||||||
int32 x, y, w;
|
|
||||||
if (App::wnd()->getPhotoCoords(photo, x, y, w)) {
|
|
||||||
iX = anim::ivalue(x);
|
|
||||||
iY = anim::ivalue(y);
|
|
||||||
iW = anim::ivalue(w);
|
|
||||||
}
|
|
||||||
photo->full->load();
|
|
||||||
setGeometry(0, 0, App::wnd()->width(), App::wnd()->height());
|
|
||||||
aBackground.start(1);
|
|
||||||
aOver.start(1);
|
|
||||||
anim::start(this);
|
|
||||||
show();
|
|
||||||
setFocus();
|
|
||||||
App::contextItem(item);
|
|
||||||
|
|
||||||
setAttribute(Qt::WA_AcceptTouchEvents);
|
|
||||||
_touchTimer.setSingleShot(true);
|
|
||||||
connect(&_touchTimer, SIGNAL(timeout()), this, SLOT(onTouchTimer()));
|
|
||||||
}
|
|
||||||
|
|
||||||
LayerWidget::LayerWidget(QWidget *parent, VideoData *video, HistoryItem *item) : QWidget(parent)
|
|
||||||
, photo(0)
|
|
||||||
, video(video)
|
|
||||||
, aBackground(0)
|
|
||||||
, aOver(0)
|
|
||||||
, iX(App::wnd()->width() / 2)
|
|
||||||
, iY(App::wnd()->height() / 2)
|
|
||||||
, iW(0)
|
|
||||||
, iCoordFunc(anim::sineInOut)
|
|
||||||
, aBackgroundFunc(anim::easeOutCirc)
|
|
||||||
, aOverFunc(anim::linear)
|
|
||||||
, hiding(false)
|
|
||||||
, _touchPress(false)
|
|
||||||
, _touchMove(false)
|
|
||||||
, _touchRightButton(false)
|
|
||||||
, _menu(0)
|
|
||||||
{
|
|
||||||
int32 x, y, w;
|
|
||||||
if (App::wnd()->getVideoCoords(video, x, y, w)) {
|
|
||||||
iX = anim::ivalue(x);
|
|
||||||
iY = anim::ivalue(y);
|
|
||||||
iW = anim::ivalue(w);
|
|
||||||
}
|
|
||||||
setGeometry(0, 0, App::wnd()->width(), App::wnd()->height());
|
|
||||||
aBackground.start(1);
|
|
||||||
aOver.start(1);
|
|
||||||
anim::start(this);
|
|
||||||
show();
|
|
||||||
setFocus();
|
|
||||||
App::contextItem(item);
|
|
||||||
|
|
||||||
setAttribute(Qt::WA_AcceptTouchEvents);
|
|
||||||
_touchTimer.setSingleShot(true);
|
|
||||||
connect(&_touchTimer, SIGNAL(timeout()), this, SLOT(onTouchTimer()));
|
|
||||||
}
|
|
||||||
|
|
||||||
PhotoData *LayerWidget::photoShown() {
|
|
||||||
return hiding ? 0 : photo;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LayerWidget::onTouchTimer() {
|
|
||||||
_touchRightButton = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LayerWidget::event(QEvent *e) {
|
|
||||||
if (e->type() == QEvent::TouchBegin || e->type() == QEvent::TouchUpdate || e->type() == QEvent::TouchEnd || e->type() == QEvent::TouchCancel) {
|
|
||||||
QTouchEvent *ev = static_cast<QTouchEvent*>(e);
|
|
||||||
if (ev->device()->type() == QTouchDevice::TouchScreen) {
|
|
||||||
touchEvent(ev);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return QWidget::event(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LayerWidget::touchEvent(QTouchEvent *e) {
|
|
||||||
switch (e->type()) {
|
|
||||||
case QEvent::TouchBegin:
|
|
||||||
if (_touchPress || e->touchPoints().isEmpty()) return;
|
|
||||||
_touchTimer.start(QApplication::startDragTime());
|
|
||||||
_touchPress = true;
|
|
||||||
_touchMove = _touchRightButton = false;
|
|
||||||
_touchStart = e->touchPoints().cbegin()->screenPos().toPoint();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case QEvent::TouchUpdate:
|
|
||||||
if (!_touchPress || e->touchPoints().isEmpty()) return;
|
|
||||||
if (!_touchMove && (e->touchPoints().cbegin()->screenPos().toPoint() - _touchStart).manhattanLength() >= QApplication::startDragDistance()) {
|
|
||||||
_touchMove = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case QEvent::TouchEnd:
|
|
||||||
if (!_touchPress) return;
|
|
||||||
if (!_touchMove && App::wnd()) {
|
|
||||||
Qt::MouseButton btn(_touchRightButton ? Qt::RightButton : Qt::LeftButton);
|
|
||||||
QPoint mapped(mapFromGlobal(_touchStart)), winMapped(App::wnd()->mapFromGlobal(_touchStart));
|
|
||||||
|
|
||||||
QMouseEvent pressEvent(QEvent::MouseButtonPress, mapped, winMapped, _touchStart, btn, Qt::MouseButtons(btn), Qt::KeyboardModifiers());
|
|
||||||
pressEvent.accept();
|
|
||||||
mousePressEvent(&pressEvent);
|
|
||||||
|
|
||||||
QMouseEvent releaseEvent(QEvent::MouseButtonRelease, mapped, winMapped, _touchStart, btn, Qt::MouseButtons(btn), Qt::KeyboardModifiers());
|
|
||||||
mouseReleaseEvent(&releaseEvent);
|
|
||||||
|
|
||||||
if (_touchRightButton) {
|
|
||||||
QContextMenuEvent contextEvent(QContextMenuEvent::Mouse, mapped, _touchStart);
|
|
||||||
contextMenuEvent(&contextEvent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_touchTimer.stop();
|
|
||||||
_touchPress = _touchMove = _touchRightButton = false;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case QEvent::TouchCancel:
|
|
||||||
_touchPress = false;
|
|
||||||
_touchTimer.stop();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LayerWidget::onMenuDestroy(QObject *obj) {
|
|
||||||
if (_menu == obj) {
|
|
||||||
_menu = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LayerWidget::paintEvent(QPaintEvent *e) {
|
|
||||||
bool trivial = (rect() == e->rect());
|
|
||||||
|
|
||||||
QPainter p(this);
|
|
||||||
if (!trivial) {
|
|
||||||
p.setClipRect(e->rect());
|
|
||||||
}
|
|
||||||
p.setOpacity(st::layerAlpha * aBackground.current());
|
|
||||||
p.fillRect(rect(), st::layerBG->b);
|
|
||||||
if (iW.current()) {
|
|
||||||
if (!hiding) p.setOpacity(aOver.current());
|
|
||||||
if (animating()) {
|
|
||||||
const QPixmap &pm((photo ? (photo->full->loaded() ? photo->full : photo->thumb) : video->thumb)->pix());
|
|
||||||
int32 h = pm.width() ? (pm.height() * iW.current() / pm.width()) : 1;
|
|
||||||
p.drawPixmap(iX.current(), iY.current(), iW.current(), h, pm);
|
|
||||||
if (!hiding) {
|
|
||||||
p.setOpacity(1);
|
|
||||||
p.setClipRect(App::wnd()->photoRect(), Qt::IntersectClip);
|
|
||||||
p.drawPixmap(iX.current(), iY.current(), iW.current(), h, pm);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const QPixmap &pm((photo ? (photo->full->loaded() ? photo->full : photo->thumb) : video->thumb)->pixNoCache(iW.current(), 0, !animating()));
|
|
||||||
p.drawPixmap(iX.current(), iY.current(), pm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LayerWidget::keyPressEvent(QKeyEvent *e) {
|
|
||||||
if (!_menu && e->key() == Qt::Key_Escape) {
|
|
||||||
startHide();
|
|
||||||
} else if (photo && photo->full->loaded() && (e == QKeySequence::Save || e == QKeySequence::SaveAs)) {
|
|
||||||
QString file;
|
|
||||||
if (filedialogGetSaveFile(file, lang(lng_save_photo), qsl("JPEG Image (*.jpg);;All files (*.*)"), filedialogDefaultName(qsl("photo"), qsl(".jpg")))) {
|
|
||||||
if (!file.isEmpty()) {
|
|
||||||
photo->full->pix().toImage().save(file, "JPG");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (photo && photo->full->loaded() && (e->key() == Qt::Key_Copy || (e->key() == Qt::Key_C && e->modifiers().testFlag(Qt::ControlModifier)))) {
|
|
||||||
QApplication::clipboard()->setPixmap(photo->full->pix());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LayerWidget::mousePressEvent(QMouseEvent *e) {
|
|
||||||
if (_menu) return;
|
|
||||||
if (e->button() == Qt::LeftButton) startHide();
|
|
||||||
}
|
|
||||||
|
|
||||||
void LayerWidget::contextMenuEvent(QContextMenuEvent *e) {
|
|
||||||
if (photo && photo->full->loaded() && !hiding) {
|
|
||||||
if (_menu) {
|
|
||||||
_menu->deleteLater();
|
|
||||||
_menu = 0;
|
|
||||||
}
|
|
||||||
_menu = new QMenu(this);
|
|
||||||
_menu->addAction(lang(lng_context_save_image), this, SLOT(saveContextImage()))->setEnabled(true);
|
|
||||||
_menu->addAction(lang(lng_context_copy_image), this, SLOT(copyContextImage()))->setEnabled(true);
|
|
||||||
_menu->addAction(lang(lng_context_close_image), this, SLOT(startHide()))->setEnabled(true);
|
|
||||||
if (App::contextItem()) {
|
|
||||||
if (dynamic_cast<HistoryMessage*>(App::contextItem())) {
|
|
||||||
_menu->addAction(lang(lng_context_forward_image), this, SLOT(forwardMessage()))->setEnabled(true);
|
|
||||||
}
|
|
||||||
_menu->addAction(lang(lng_context_delete_image), this, SLOT(deleteMessage()))->setEnabled(true);
|
|
||||||
} else if ((App::self() && App::self()->photoId == photo->id) || (photo->chat && photo->chat->photoId == photo->id)) {
|
|
||||||
_menu->addAction(lang(lng_context_delete_image), this, SLOT(deleteMessage()))->setEnabled(true);
|
|
||||||
}
|
|
||||||
_menu->setAttribute(Qt::WA_DeleteOnClose);
|
|
||||||
|
|
||||||
_menu->setAttribute(Qt::WA_DeleteOnClose);
|
|
||||||
connect(_menu, SIGNAL(destroyed(QObject*)), this, SLOT(onMenuDestroy(QObject*)));
|
|
||||||
_menu->popup(e->globalPos());
|
|
||||||
e->accept();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LayerWidget::deleteMessage() {
|
|
||||||
if (!App::contextItem()) {
|
|
||||||
if (App::self() && photo && App::self()->photoId == photo->id) {
|
|
||||||
App::app()->peerClearPhoto(App::self()->id);
|
|
||||||
} else if (photo->chat && photo->chat->photoId == photo->id) {
|
|
||||||
App::app()->peerClearPhoto(photo->chat->id);
|
|
||||||
}
|
|
||||||
startHide();
|
|
||||||
} else {
|
|
||||||
App::wnd()->layerHidden();
|
|
||||||
App::main()->deleteLayer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LayerWidget::forwardMessage() {
|
|
||||||
startHide();
|
|
||||||
App::main()->forwardLayer();
|
|
||||||
}
|
|
||||||
|
|
||||||
void LayerWidget::saveContextImage() {
|
|
||||||
if (!photo || !photo->full->loaded() || hiding) return;
|
|
||||||
|
|
||||||
QString file;
|
|
||||||
if (filedialogGetSaveFile(file, lang(lng_save_photo), qsl("JPEG Image (*.jpg);;All files (*.*)"), filedialogDefaultName(qsl("photo"), qsl(".jpg")))) {
|
|
||||||
if (!file.isEmpty()) {
|
|
||||||
photo->full->pix().toImage().save(file, "JPG");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LayerWidget::copyContextImage() {
|
|
||||||
if (!photo || !photo->full->loaded() || hiding) return;
|
|
||||||
|
|
||||||
QApplication::clipboard()->setPixmap(photo->full->pix());
|
|
||||||
}
|
|
||||||
|
|
||||||
void LayerWidget::startHide() {
|
|
||||||
hiding = true;
|
|
||||||
aBackground.start(0);
|
|
||||||
anim::start(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LayerWidget::resizeEvent(QResizeEvent *e) {
|
|
||||||
int32 w = width() - st::layerPadding.left() - st::layerPadding.right(), h = height() - st::layerPadding.top() - st::layerPadding.bottom();
|
|
||||||
int32 iw = (photo ? photo->full : video->thumb)->width(), ih = (photo ? photo->full : video->thumb)->height();
|
|
||||||
if (!iw || !ih) {
|
|
||||||
iw = ih = 1;
|
|
||||||
} else {
|
|
||||||
switch (cScale()) {
|
|
||||||
case dbisOneAndQuarter: iw = qRound(float64(iw) * 1.25 - 0.01); ih = qRound(float64(ih) * 1.25 - 0.01); break;
|
|
||||||
case dbisOneAndHalf: iw = qRound(float64(iw) * 1.5 - 0.01); ih = qRound(float64(ih) * 1.5 - 0.01); break;
|
|
||||||
case dbisTwo: iw *= 2; ih *= 2; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (w >= iw && h >= ih) {
|
|
||||||
iW.start(iw);
|
|
||||||
iX.start(st::layerPadding.left() + (w - iw) / 2);
|
|
||||||
iY.start(st::layerPadding.top() + (h - ih) / 2);
|
|
||||||
} else if (w * ih > iw * h) {
|
|
||||||
int32 nw = qRound(iw * float64(h) / ih);
|
|
||||||
iW.start(nw);
|
|
||||||
iX.start(st::layerPadding.left() + (w - nw) / 2);
|
|
||||||
iY.start(st::layerPadding.top());
|
|
||||||
} else {
|
|
||||||
int32 nh = qRound(ih * float64(w) / iw);
|
|
||||||
iW.start(w);
|
|
||||||
iX.start(st::layerPadding.left());
|
|
||||||
iY.start(st::layerPadding.top() + (h - nh) / 2);
|
|
||||||
}
|
|
||||||
if (!animating() || hiding) {
|
|
||||||
iX.finish();
|
|
||||||
iY.finish();
|
|
||||||
iW.finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LayerWidget::animStep(float64 ms) {
|
|
||||||
float64 dt = ms / (hiding ? st::layerHideDuration : st::layerSlideDuration);
|
|
||||||
bool res = true;
|
|
||||||
if (dt >= 1) {
|
|
||||||
aBackground.finish();
|
|
||||||
aOver.finish();
|
|
||||||
iX.finish();
|
|
||||||
iY.finish();
|
|
||||||
iW.finish();
|
|
||||||
if (hiding) {
|
|
||||||
QTimer::singleShot(0, App::wnd(), SLOT(layerHidden()));
|
|
||||||
}
|
|
||||||
res = false;
|
|
||||||
} else {
|
|
||||||
aBackground.update(dt, aBackgroundFunc);
|
|
||||||
if (!hiding) {
|
|
||||||
aOver.update(dt, aOverFunc);
|
|
||||||
iX.update(dt, iCoordFunc);
|
|
||||||
iY.update(dt, iCoordFunc);
|
|
||||||
iW.update(dt, iCoordFunc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
update();
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
LayerWidget::~LayerWidget() {
|
|
||||||
if (App::wnd()) App::wnd()->noLayer(this);
|
|
||||||
delete _menu;
|
|
||||||
}
|
|
||||||
|
@ -81,54 +81,3 @@ private:
|
|||||||
|
|
||||||
BoxShadow shadow;
|
BoxShadow shadow;
|
||||||
};
|
};
|
||||||
|
|
||||||
class LayerWidget : public QWidget, public Animated {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
LayerWidget(QWidget *parent, PhotoData *photo, HistoryItem *item);
|
|
||||||
LayerWidget(QWidget *parent, VideoData *video, HistoryItem *item);
|
|
||||||
|
|
||||||
PhotoData *photoShown();
|
|
||||||
|
|
||||||
bool event(QEvent *e);
|
|
||||||
void touchEvent(QTouchEvent *e);
|
|
||||||
void paintEvent(QPaintEvent *e);
|
|
||||||
void keyPressEvent(QKeyEvent *e);
|
|
||||||
void mousePressEvent(QMouseEvent *e);
|
|
||||||
void resizeEvent(QResizeEvent *e);
|
|
||||||
void contextMenuEvent(QContextMenuEvent *e);
|
|
||||||
|
|
||||||
bool animStep(float64 ms);
|
|
||||||
|
|
||||||
~LayerWidget();
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
|
|
||||||
void onTouchTimer();
|
|
||||||
|
|
||||||
void saveContextImage();
|
|
||||||
void copyContextImage();
|
|
||||||
void startHide();
|
|
||||||
|
|
||||||
void deleteMessage();
|
|
||||||
void forwardMessage();
|
|
||||||
|
|
||||||
void onMenuDestroy(QObject *obj);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
PhotoData *photo;
|
|
||||||
VideoData *video;
|
|
||||||
anim::fvalue aBackground, aOver;
|
|
||||||
anim::ivalue iX, iY, iW;
|
|
||||||
anim::transition iCoordFunc, aBackgroundFunc, aOverFunc;
|
|
||||||
bool hiding;
|
|
||||||
|
|
||||||
bool _touchPress, _touchMove, _touchRightButton;
|
|
||||||
QTimer _touchTimer;
|
|
||||||
QPoint _touchStart;
|
|
||||||
|
|
||||||
QMenu *_menu;
|
|
||||||
};
|
|
||||||
|
@ -17,6 +17,7 @@ Copyright (c) 2014 John Preston, https://tdesktop.com
|
|||||||
*/
|
*/
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "localimageloader.h"
|
#include "localimageloader.h"
|
||||||
|
#include "gui/filedialog.h"
|
||||||
#include <libexif/exif-data.h>
|
#include <libexif/exif-data.h>
|
||||||
|
|
||||||
LocalImageLoaderPrivate::LocalImageLoaderPrivate(int32 currentUser, LocalImageLoader *loader, QThread *thread) : QObject(0)
|
LocalImageLoaderPrivate::LocalImageLoaderPrivate(int32 currentUser, LocalImageLoader *loader, QThread *thread) : QObject(0)
|
||||||
@ -99,9 +100,20 @@ void LocalImageLoaderPrivate::prepareImages() {
|
|||||||
filesize = data.size();
|
filesize = data.size();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
type = ToPreparePhoto; // only photo from QImage
|
if (type == ToPrepareDocument) {
|
||||||
filename = qsl("Untitled.jpg");
|
filename = filedialogDefaultName(qsl("image"), qsl(".png"), QString(), true);
|
||||||
filesize = 0;
|
QMimeType mimeType = QMimeDatabase().mimeTypeForName("image/png");
|
||||||
|
data = QByteArray();
|
||||||
|
{
|
||||||
|
QBuffer b(&data);
|
||||||
|
img.save(&b, "PNG");
|
||||||
|
}
|
||||||
|
filesize = data.size();
|
||||||
|
} else {
|
||||||
|
type = ToPreparePhoto; // only photo from QImage
|
||||||
|
filename = qsl("Untitled.jpg");
|
||||||
|
filesize = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((img.isNull() && (type != ToPrepareDocument || !filesize)) || type == ToPrepareAuto || (img.isNull() && file.isEmpty() && data.isEmpty())) { // if could not decide what type
|
if ((img.isNull() && (type != ToPrepareDocument || !filesize)) || type == ToPrepareAuto || (img.isNull() && file.isEmpty() && data.isEmpty())) { // if could not decide what type
|
||||||
|
@ -678,6 +678,10 @@ void MainWidget::confirmSendImage(const ReadyLocalMedia &img) {
|
|||||||
history.confirmSendImage(img);
|
history.confirmSendImage(img);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWidget::confirmSendImageUncompressed() {
|
||||||
|
history.uploadConfirmImageUncompressed();
|
||||||
|
}
|
||||||
|
|
||||||
void MainWidget::cancelSendImage() {
|
void MainWidget::cancelSendImage() {
|
||||||
history.cancelSendImage();
|
history.cancelSendImage();
|
||||||
}
|
}
|
||||||
@ -802,6 +806,9 @@ PeerData *MainWidget::profilePeer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MainWidget::showPeerProfile(const PeerData *peer, bool back) {
|
void MainWidget::showPeerProfile(const PeerData *peer, bool back) {
|
||||||
|
App::wnd()->hideSettings();
|
||||||
|
if (profile && profile->peer() == peer) return;
|
||||||
|
|
||||||
dialogs.enableShadow(false);
|
dialogs.enableShadow(false);
|
||||||
_topBar.enableShadow(false);
|
_topBar.enableShadow(false);
|
||||||
QPixmap animCache = myGrab(this, history.geometry()), animTopBarCache = myGrab(this, QRect(_topBar.x(), _topBar.y(), _topBar.width(), st::topBarHeight));
|
QPixmap animCache = myGrab(this, history.geometry()), animTopBarCache = myGrab(this, QRect(_topBar.x(), _topBar.y(), _topBar.width(), st::topBarHeight));
|
||||||
@ -1573,9 +1580,24 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
|||||||
HistoryItem *msgRow = App::histItemById(msg);
|
HistoryItem *msgRow = App::histItemById(msg);
|
||||||
if (msgRow) {
|
if (msgRow) {
|
||||||
App::historyUnregItem(msgRow);
|
App::historyUnregItem(msgRow);
|
||||||
|
History *h = msgRow->history();
|
||||||
|
History::MediaOverviewIds::iterator i = h->_photosOverviewIds.find(msgRow->id);
|
||||||
|
if (i != h->_photosOverviewIds.cend()) {
|
||||||
|
h->_photosOverviewIds.erase(i);
|
||||||
|
if (h->_photosOverviewIds.constFind(d.vid.v) == h->_photosOverviewIds.cend()) {
|
||||||
|
h->_photosOverviewIds.insert(d.vid.v);
|
||||||
|
for (int32 i = 0, l = h->_photosOverview.size(); i != l; ++i) {
|
||||||
|
if (h->_photosOverview.at(i) == msgRow->id) {
|
||||||
|
h->_photosOverview[i] = d.vid.v;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (App::wnd()) App::wnd()->changingMsgId(msgRow, d.vid.v);
|
||||||
msgRow->id = d.vid.v;
|
msgRow->id = d.vid.v;
|
||||||
if (!App::historyRegItem(msgRow)) {
|
if (!App::historyRegItem(msgRow)) {
|
||||||
msgUpdated(msgRow->history()->peer->id, msgRow);
|
msgUpdated(h->peer->id, msgRow);
|
||||||
} else {
|
} else {
|
||||||
msgRow->destroy();
|
msgRow->destroy();
|
||||||
history.peerMessagesUpdated();
|
history.peerMessagesUpdated();
|
||||||
@ -1668,14 +1690,27 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
|||||||
if (user) {
|
if (user) {
|
||||||
user->setPhoto(d.vphoto);
|
user->setPhoto(d.vphoto);
|
||||||
user->photo->load();
|
user->photo->load();
|
||||||
if (false && !d.vprevious.v && d.vuser_id.v != MTP::authedId() && d.vphoto.type() == mtpc_userProfilePhoto) {
|
if (d.vprevious.v) {
|
||||||
MTPPhoto photo(App::photoFromUserPhoto(MTP_int(user->id & 0xFFFFFFFF), d.vdate, d.vphoto));
|
user->photosCount = -1;
|
||||||
HistoryMedia *media = new HistoryPhoto(photo.c_photo(), 100);
|
user->photos.clear();
|
||||||
if (App::history(user->id)->loadedAtBottom()) {
|
} else {
|
||||||
App::history(user->id)->addToBackService(clientMsgId(), date(d.vdate), lang(lng_action_user_photo).replace(qsl("{from}"), user->name), false, true, media);
|
if (user->photoId) {
|
||||||
|
if (user->photosCount > 0) ++user->photosCount;
|
||||||
|
user->photos.push_front(App::photo(user->photoId));
|
||||||
|
} else {
|
||||||
|
user->photosCount = -1;
|
||||||
|
user->photos.clear();
|
||||||
|
}
|
||||||
|
if (false && d.vuser_id.v != MTP::authedId() && d.vphoto.type() == mtpc_userProfilePhoto) {
|
||||||
|
MTPPhoto photo(App::photoFromUserPhoto(MTP_int(user->id & 0xFFFFFFFF), d.vdate, d.vphoto));
|
||||||
|
HistoryMedia *media = new HistoryPhoto(photo.c_photo(), 100);
|
||||||
|
if (App::history(user->id)->loadedAtBottom()) {
|
||||||
|
App::history(user->id)->addToBackService(clientMsgId(), date(d.vdate), lang(lng_action_user_photo).replace(qsl("{from}"), user->name), false, true, media);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (App::main()) App::main()->peerUpdated(user);
|
if (App::main()) App::main()->peerUpdated(user);
|
||||||
|
if (App::wnd()) App::wnd()->mediaOverviewUpdated(user);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
@ -141,6 +141,7 @@ public:
|
|||||||
QRect historyRect() const;
|
QRect historyRect() const;
|
||||||
|
|
||||||
void confirmSendImage(const ReadyLocalMedia &img);
|
void confirmSendImage(const ReadyLocalMedia &img);
|
||||||
|
void confirmSendImageUncompressed();
|
||||||
void cancelSendImage();
|
void cancelSendImage();
|
||||||
|
|
||||||
void destroyData();
|
void destroyData();
|
||||||
|
@ -19,33 +19,291 @@ Copyright (c) 2014 John Preston, https://tdesktop.com
|
|||||||
#include "lang.h"
|
#include "lang.h"
|
||||||
|
|
||||||
#include "mediaview.h"
|
#include "mediaview.h"
|
||||||
|
#include "mainwidget.h"
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
|
#include "application.h"
|
||||||
|
#include "gui/filedialog.h"
|
||||||
|
|
||||||
MediaView::MediaView() : QWidget(App::wnd()),
|
MediaView::MediaView() : QWidget(App::wnd()),
|
||||||
_photo(0), _maxWidth(0), _maxHeight(0), _x(0), _y(0), _w(0) {
|
_photo(0), _maxWidth(0), _maxHeight(0), _x(0), _y(0), _w(0), _full(false),
|
||||||
|
_history(0), _peer(0), _user(0), _from(0), _index(-1), _msgid(0), _loadRequest(0), _over(OverNone), _down(OverNone), _lastAction(-st::medviewDeltaFromLastAction, -st::medviewDeltaFromLastAction),
|
||||||
|
_close(this, lang(lng_mediaview_close), st::medviewButton),
|
||||||
|
_save(this, lang(lng_mediaview_save), st::medviewButton),
|
||||||
|
_forward(this, lang(lng_mediaview_forward), st::medviewButton),
|
||||||
|
_delete(this, lang(lng_mediaview_delete), st::medviewButton),
|
||||||
|
_menu(0), _receiveMouse(true), _touchPress(false), _touchMove(false), _touchRightButton(false),
|
||||||
|
_leftNavVisible(false), _rightNavVisible(false) {
|
||||||
setWindowFlags(Qt::FramelessWindowHint | Qt::BypassWindowManagerHint | Qt::Tool | Qt::NoDropShadowWindowHint);
|
setWindowFlags(Qt::FramelessWindowHint | Qt::BypassWindowManagerHint | Qt::Tool | Qt::NoDropShadowWindowHint);
|
||||||
moveToScreen();
|
moveToScreen();
|
||||||
setAttribute(Qt::WA_PaintOnScreen, true);
|
setAttribute(Qt::WA_PaintOnScreen, true);
|
||||||
setAttribute(Qt::WA_NoSystemBackground, true);
|
setAttribute(Qt::WA_NoSystemBackground, true);
|
||||||
setAttribute(Qt::WA_TranslucentBackground, true);
|
setAttribute(Qt::WA_TranslucentBackground, true);
|
||||||
|
setMouseTracking(true);
|
||||||
hide();
|
hide();
|
||||||
|
|
||||||
|
connect(&_close, SIGNAL(clicked()), this, SLOT(onClose()));
|
||||||
|
connect(&_save, SIGNAL(clicked()), this, SLOT(onSave()));
|
||||||
|
connect(&_forward, SIGNAL(clicked()), this, SLOT(onForward()));
|
||||||
|
connect(&_delete, SIGNAL(clicked()), this, SLOT(onDelete()));
|
||||||
|
|
||||||
|
connect(App::wnd()->windowHandle(), SIGNAL(activeChanged()), this, SLOT(onCheckActive()));
|
||||||
|
|
||||||
|
setAttribute(Qt::WA_AcceptTouchEvents);
|
||||||
|
_touchTimer.setSingleShot(true);
|
||||||
|
connect(&_touchTimer, SIGNAL(timeout()), this, SLOT(onTouchTimer()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaView::moveToScreen() {
|
void MediaView::moveToScreen() {
|
||||||
QPoint wndCenter(App::wnd()->x() + App::wnd()->width() / 2, App::wnd()->y() + App::wnd()->height() / 2);
|
QPoint wndCenter(App::wnd()->x() + App::wnd()->width() / 2, App::wnd()->y() + App::wnd()->height() / 2);
|
||||||
QRect geom = QDesktopWidget().screenGeometry(wndCenter);
|
QRect geom = QDesktopWidget().screenGeometry(wndCenter);
|
||||||
|
_avail = QDesktopWidget().availableGeometry(wndCenter);
|
||||||
if (geom != geometry()) {
|
if (geom != geometry()) {
|
||||||
setGeometry(geom);
|
setGeometry(geom);
|
||||||
}
|
}
|
||||||
_maxWidth = width() - 2 * st::medviewNavBarWidth;
|
if (!geom.contains(_avail)) {
|
||||||
_maxHeight = height() - st::medviewTopSkip - st::medviewBottomSkip;
|
_avail = geom;
|
||||||
|
}
|
||||||
|
_avail.setX(_avail.x() - geom.x());
|
||||||
|
_avail.setY(_avail.y() - geom.y());
|
||||||
|
_maxWidth = _avail.width() - 2 * st::medviewNavBarWidth;
|
||||||
|
_maxHeight = _avail.height() - st::medviewTopSkip - st::medviewBottomSkip;
|
||||||
|
_leftNav = QRect(0, 0, st::medviewNavBarWidth, height());
|
||||||
|
_rightNav = QRect(width() - st::medviewNavBarWidth, 0, st::medviewNavBarWidth, height());
|
||||||
|
_close.move(_avail.x() + (_avail.width() + st::medviewMainWidth) / 2 - _close.width(), _avail.y() + (st::medviewTopSkip - _close.height()) / 2);
|
||||||
|
_save.move(_avail.x() + (_avail.width() - st::medviewMainWidth) / 2, _avail.y() + (st::medviewTopSkip - _save.height()) / 2);
|
||||||
|
_delete.move(_avail.x() + (_avail.width() + st::medviewMainWidth) / 2 - _delete.width(), _avail.y() + _avail.height() - (st::medviewTopSkip + _delete.height()) / 2);
|
||||||
|
_forward.move(_avail.x() + (_avail.width() - st::medviewMainWidth) / 2, _avail.y() + _avail.height() - (st::medviewTopSkip + _forward.height()) / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaView::showPhoto(PhotoData *photo, const QRect &opaque) {
|
void MediaView::mediaOverviewUpdated(PeerData *peer) {
|
||||||
|
if (_history && _history->peer == peer) {
|
||||||
|
_index = -1;
|
||||||
|
for (int i = 0, l = _history->_photosOverview.size(); i < l; ++i) {
|
||||||
|
if (_history->_photosOverview.at(i) == _msgid) {
|
||||||
|
_index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateControls();
|
||||||
|
} else if (_user == peer) {
|
||||||
|
_index = -1;
|
||||||
|
for (int i = 0, l = _user->photos.size(); i < l; ++i) {
|
||||||
|
if (_user->photos.at(i) == _photo) {
|
||||||
|
_index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateControls();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaView::changingMsgId(HistoryItem *row, MsgId newId) {
|
||||||
|
if (row->id == _msgid) {
|
||||||
|
_msgid = newId;
|
||||||
|
}
|
||||||
|
mediaOverviewUpdated(row->history()->peer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaView::updateControls() {
|
||||||
|
if (!_photo) return;
|
||||||
|
|
||||||
|
_close.show();
|
||||||
|
if (_photo->full->loaded()) {
|
||||||
|
_save.show();
|
||||||
|
} else {
|
||||||
|
_save.hide();
|
||||||
|
}
|
||||||
|
if (_history) {
|
||||||
|
HistoryItem *item = App::histItemById(_msgid);
|
||||||
|
if (dynamic_cast<HistoryMessage*>(item)) {
|
||||||
|
_forward.show();
|
||||||
|
} else {
|
||||||
|
_forward.hide();
|
||||||
|
}
|
||||||
|
_delete.show();
|
||||||
|
} else {
|
||||||
|
_forward.hide();
|
||||||
|
if (App::self() && _photo && App::self()->photoId == _photo->id || _photo->chat && _photo->chat->photoId == _photo->id) {
|
||||||
|
_delete.show();
|
||||||
|
} else {
|
||||||
|
_delete.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QDateTime d(date(_photo->date)), dNow(date(unixtime()));
|
||||||
|
if (d.date() == dNow.date()) {
|
||||||
|
_dateText = lang(lng_status_lastseen_today).replace(qsl("{time}"), d.time().toString(qsl("hh:mm")));
|
||||||
|
} else if (d.date().addDays(1) == dNow.date()) {
|
||||||
|
_dateText = lang(lng_status_lastseen_yesterday).replace(qsl("{time}"), d.time().toString(qsl("hh:mm")));
|
||||||
|
} else {
|
||||||
|
_dateText = lang(lng_status_lastseen_date_time).replace(qsl("{date}"), d.date().toString(qsl("dd.MM.yy"))).replace(qsl("{time}"), d.time().toString(qsl("hh:mm")));
|
||||||
|
}
|
||||||
|
int32 nameWidth = _from->nameText.maxWidth(), maxWidth = _delete.x() - _forward.x() - _forward.width(), dateWidth = st::medviewDateFont->m.width(_dateText);
|
||||||
|
if (nameWidth > maxWidth) {
|
||||||
|
nameWidth = maxWidth;
|
||||||
|
}
|
||||||
|
_nameNav = QRect(_forward.x() + _forward.width() + (maxWidth - nameWidth) / 2, _forward.y() + st::medviewNameTop, nameWidth, st::msgNameFont->height);
|
||||||
|
_dateNav = QRect(_forward.x() + _forward.width() + (maxWidth - dateWidth) / 2, _forward.y() + st::medviewDateTop, dateWidth, st::medviewDateFont->height);
|
||||||
|
updateHeader();
|
||||||
|
_leftNavVisible = (_index > 0 || (_index == 0 && _history && _history->_photosOverview.size() < _history->_photosOverviewCount));
|
||||||
|
_rightNavVisible = (_index >= 0 && (
|
||||||
|
(_history && _index + 1 < _history->_photosOverview.size()) ||
|
||||||
|
(_user && (_index + 1 < _user->photos.size() || _index + 1 < _user->photosCount))));
|
||||||
|
updateOver(mapFromGlobal(QCursor::pos()));
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MediaView::animStep(float64 msp) {
|
||||||
|
uint64 ms = getms();
|
||||||
|
for (Showing::iterator i = _animations.begin(); i != _animations.end();) {
|
||||||
|
int64 start = i.value();
|
||||||
|
switch (i.key()) {
|
||||||
|
case OverLeftNav: update(_leftNav); break;
|
||||||
|
case OverRightNav: update(_rightNav); break;
|
||||||
|
case OverName: update(_nameNav); break;
|
||||||
|
case OverDate: update(_dateNav); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
float64 dt = float64(ms - start) / st::medviewButton.duration;
|
||||||
|
if (dt >= 1) {
|
||||||
|
_animOpacities.remove(i.key());
|
||||||
|
i = _animations.erase(i);
|
||||||
|
} else {
|
||||||
|
_animOpacities[i.key()].update(dt, anim::linear);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return !_animations.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
MediaView::~MediaView() {
|
||||||
|
delete _menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaView::onClose() {
|
||||||
|
if (App::wnd()) App::wnd()->layerHidden();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaView::onSave() {
|
||||||
|
if (!_photo || !_photo->full->loaded()) return;
|
||||||
|
|
||||||
|
QString file;
|
||||||
|
if (filedialogGetSaveFile(file, lang(lng_save_photo), qsl("JPEG Image (*.jpg);;All files (*.*)"), filedialogDefaultName(qsl("photo"), qsl(".jpg")))) {
|
||||||
|
if (!file.isEmpty()) {
|
||||||
|
_photo->full->pix().toImage().save(file, "JPG");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaView::onForward() {
|
||||||
|
HistoryItem *item = App::histItemById(_msgid);
|
||||||
|
if (!_msgid || !item) return;
|
||||||
|
|
||||||
|
if (App::wnd()) {
|
||||||
|
onClose();
|
||||||
|
if (App::main()) {
|
||||||
|
App::contextItem(item);
|
||||||
|
App::main()->forwardLayer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaView::onDelete() {
|
||||||
|
onClose();
|
||||||
|
if (!_msgid) {
|
||||||
|
if (App::self() && _photo && App::self()->photoId == _photo->id) {
|
||||||
|
App::app()->peerClearPhoto(App::self()->id);
|
||||||
|
} else if (_photo->chat && _photo->chat->photoId == _photo->id) {
|
||||||
|
App::app()->peerClearPhoto(_photo->chat->id);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
HistoryItem *item = App::histItemById(_msgid);
|
||||||
|
if (item) {
|
||||||
|
App::contextItem(item);
|
||||||
|
App::main()->deleteLayer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaView::onCopy() {
|
||||||
|
if (!_photo || !_photo->full->loaded()) return;
|
||||||
|
|
||||||
|
QApplication::clipboard()->setPixmap(_photo->full->pix());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaView::showPhoto(PhotoData *photo, HistoryItem *context) {
|
||||||
|
_history = context->history();
|
||||||
|
_peer = 0;
|
||||||
|
_user = 0;
|
||||||
|
|
||||||
|
_loadRequest = 0;
|
||||||
|
_over = OverNone;
|
||||||
|
if (!_animations.isEmpty()) {
|
||||||
|
_animations.clear();
|
||||||
|
anim::stop(this);
|
||||||
|
}
|
||||||
|
if (!_animOpacities.isEmpty()) _animOpacities.clear();
|
||||||
|
setCursor(style::cur_default);
|
||||||
|
|
||||||
|
_index = -1;
|
||||||
|
_msgid = context->id;
|
||||||
|
for (int i = 0, l = _history->_photosOverview.size(); i < l; ++i) {
|
||||||
|
if (_history->_photosOverview.at(i) == _msgid) {
|
||||||
|
_index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_history->_photosOverviewCount < 0) {
|
||||||
|
loadPhotosBack();
|
||||||
|
}
|
||||||
|
|
||||||
|
showPhoto(photo);
|
||||||
|
preloadPhotos(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaView::showPhoto(PhotoData *photo, PeerData *context) {
|
||||||
|
_history = 0;
|
||||||
|
_peer = context;
|
||||||
|
_user = context->chat ? 0 : context->asUser();
|
||||||
|
|
||||||
|
_loadRequest = 0;
|
||||||
|
_over = OverNone;
|
||||||
|
if (!_animations.isEmpty()) {
|
||||||
|
_animations.clear();
|
||||||
|
anim::stop(this);
|
||||||
|
}
|
||||||
|
if (!_animOpacities.isEmpty()) _animOpacities.clear();
|
||||||
|
setCursor(style::cur_default);
|
||||||
|
|
||||||
|
_msgid = 0;
|
||||||
|
_index = -1;
|
||||||
|
if (_user) {
|
||||||
|
if (_user->photos.isEmpty() && _user->photosCount < 0 && _user->photoId) {
|
||||||
|
_index = 0;
|
||||||
|
}
|
||||||
|
for (int i = 0, l = _user->photos.size(); i < l; ++i) {
|
||||||
|
if (_user->photos.at(i) == photo) {
|
||||||
|
_index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_user->photosCount < 0) {
|
||||||
|
loadPhotosBack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
showPhoto(photo);
|
||||||
|
preloadPhotos(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaView::showPhoto(PhotoData *photo) {
|
||||||
_photo = photo;
|
_photo = photo;
|
||||||
_opaqueRect = opaque;
|
MTP::clearLoaderPriorities();
|
||||||
_photo->full->load();
|
_photo->full->load();
|
||||||
|
_full = false;
|
||||||
|
_current = QPixmap();
|
||||||
_w = photo->full->width();
|
_w = photo->full->width();
|
||||||
|
_down = OverNone;
|
||||||
int h = photo->full->height();
|
int h = photo->full->height();
|
||||||
switch (cScale()) {
|
switch (cScale()) {
|
||||||
case dbisOneAndQuarter: _w = qRound(float64(_w) * 1.25 - 0.01); h = qRound(float64(h) * 1.25 - 0.01); break;
|
case dbisOneAndQuarter: _w = qRound(float64(_w) * 1.25 - 0.01); h = qRound(float64(h) * 1.25 - 0.01); break;
|
||||||
@ -60,8 +318,10 @@ void MediaView::showPhoto(PhotoData *photo, const QRect &opaque) {
|
|||||||
_w = qRound(_w * _maxHeight / float64(h));
|
_w = qRound(_w * _maxHeight / float64(h));
|
||||||
h = _maxHeight;
|
h = _maxHeight;
|
||||||
}
|
}
|
||||||
_x = (width() - _w) / 2;
|
_x = _avail.x() + (_avail.width() - _w) / 2;
|
||||||
_y = (height() - h) / 2;
|
_y = _avail.y() + (_avail.height() - h) / 2;
|
||||||
|
_from = App::user(_photo->user);
|
||||||
|
updateControls();
|
||||||
if (isHidden()) {
|
if (isHidden()) {
|
||||||
moveToScreen();
|
moveToScreen();
|
||||||
bool wm = testAttribute(Qt::WA_Mapped), wv = testAttribute(Qt::WA_WState_Visible);
|
bool wm = testAttribute(Qt::WA_Mapped), wv = testAttribute(Qt::WA_WState_Visible);
|
||||||
@ -74,27 +334,520 @@ void MediaView::showPhoto(PhotoData *photo, const QRect &opaque) {
|
|||||||
if (!wv) setAttribute(Qt::WA_WState_Visible, false);
|
if (!wv) setAttribute(Qt::WA_WState_Visible, false);
|
||||||
show();
|
show();
|
||||||
}
|
}
|
||||||
update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaView::paintEvent(QPaintEvent *e) {
|
void MediaView::paintEvent(QPaintEvent *e) {
|
||||||
QPainter p(this);
|
QPainter p(this);
|
||||||
|
QRect r(e->rect());
|
||||||
|
|
||||||
|
// main bg
|
||||||
p.setOpacity(st::medviewLightOpacity);
|
p.setOpacity(st::medviewLightOpacity);
|
||||||
p.fillRect(QRect(0, 0, st::medviewNavBarWidth, height()), st::black->b);
|
QRect r_bg(st::medviewNavBarWidth, 0, width() - 2 * st::medviewNavBarWidth, height());
|
||||||
p.fillRect(QRect(width() - st::medviewNavBarWidth, 0, st::medviewNavBarWidth, height()), st::black->b);
|
if (r_bg.intersects(r)) p.fillRect(r_bg.intersected(r), st::black->b);
|
||||||
p.fillRect(QRect(st::medviewNavBarWidth, 0, width() - 2 * st::medviewNavBarWidth, height()), st::black->b);
|
|
||||||
|
// header
|
||||||
p.setOpacity(1);
|
p.setOpacity(1);
|
||||||
p.drawPixmap(_x, _y, (_photo->full->loaded() ? _photo->full : _photo->thumb)->pixNoCache(_w, 0, true));
|
p.setPen(st::medviewHeaderColor->p);
|
||||||
|
p.setFont(st::medviewHeaderFont->f);
|
||||||
|
QRect r_header(_save.x() + _save.width(), _save.y(), _close.x() - _save.x() - _save.width(), _save.height());
|
||||||
|
if (r_header.intersects(r)) p.drawText(r_header, _header, style::al_center);
|
||||||
|
|
||||||
|
// name
|
||||||
|
p.setPen(nameDateColor(overLevel(OverName)));
|
||||||
|
if (_over == OverName) _from->nameText.replaceFont(st::msgNameFont->underline());
|
||||||
|
if (_nameNav.intersects(r)) _from->nameText.drawElided(p, _nameNav.left(), _nameNav.top(), _nameNav.width());
|
||||||
|
if (_over == OverName) _from->nameText.replaceFont(st::msgNameFont);
|
||||||
|
|
||||||
|
// date
|
||||||
|
p.setPen(nameDateColor(overLevel(OverDate)));
|
||||||
|
p.setFont((_over == OverDate ? st::medviewDateFont->underline() : st::medviewDateFont)->f);
|
||||||
|
if (_dateNav.intersects(r)) p.drawText(_dateNav.left(), _dateNav.top() + st::medviewDateFont->ascent, _dateText);
|
||||||
|
|
||||||
|
// left nav bar
|
||||||
|
if (_leftNavVisible) {
|
||||||
|
float64 o = overLevel(OverLeftNav);
|
||||||
|
p.setOpacity(o * st::medviewDarkOpacity + (1 - o) * st::medviewLightOpacity);
|
||||||
|
if (_leftNav.intersects(r)) p.fillRect(_leftNav.intersected(r), st::black->b);
|
||||||
|
p.setOpacity(o * st::medviewDarkNav + (1 - o) * st::medviewLightNav);
|
||||||
|
QPoint p_left((st::medviewNavBarWidth - st::medviewLeft.pxWidth()) / 2, (height() - st::medviewLeft.pxHeight()) / 2);
|
||||||
|
if (QRect(p_left.x(), p_left.y(), st::medviewLeft.pxWidth(), st::medviewLeft.pxHeight()).intersects(r)) {
|
||||||
|
p.drawPixmap(p_left, App::sprite(), st::medviewLeft);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
p.setOpacity(st::medviewLightOpacity);
|
||||||
|
if (_leftNav.intersects(r)) p.fillRect(_leftNav.intersected(r), st::black->b);
|
||||||
|
}
|
||||||
|
|
||||||
|
// right nav bar
|
||||||
|
if (_rightNavVisible) {
|
||||||
|
float64 o = overLevel(OverRightNav);
|
||||||
|
p.setOpacity(o * st::medviewDarkOpacity + (1 - o) * st::medviewLightOpacity);
|
||||||
|
if (_rightNav.intersects(r)) p.fillRect(_rightNav.intersected(r), st::black->b);
|
||||||
|
p.setOpacity(o * st::medviewDarkNav + (1 - o) * st::medviewLightNav);
|
||||||
|
QPoint p_right(width() - (st::medviewNavBarWidth + st::medviewRight.pxWidth()) / 2, (height() - st::medviewRight.pxHeight()) / 2);
|
||||||
|
if (QRect(p_right.x(), p_right.y(), st::medviewRight.pxWidth(), st::medviewRight.pxHeight()).intersects(r)) {
|
||||||
|
p.drawPixmap(p_right, App::sprite(), st::medviewRight);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
p.setOpacity(st::medviewLightOpacity);
|
||||||
|
if (_rightNav.intersects(r)) p.fillRect(_rightNav.intersected(r), st::black->b);
|
||||||
|
}
|
||||||
|
|
||||||
|
// photo
|
||||||
|
p.setOpacity(1);
|
||||||
|
if (!_full && _photo->full->loaded()) {
|
||||||
|
_current = _photo->full->pixNoCache(_w, 0, true);
|
||||||
|
_full = true;
|
||||||
|
} else if (_current.isNull() && _photo->thumb->loaded()) {
|
||||||
|
_current = _photo->thumb->pixBlurredNoCache(_w);
|
||||||
|
}
|
||||||
|
if (QRect(_x, _y, _current.width() / cIntRetinaFactor(), _current.height() / cIntRetinaFactor()).intersects(r)) {
|
||||||
|
p.drawPixmap(_x, _y, _current);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaView::keyPressEvent(QKeyEvent *e) {
|
void MediaView::keyPressEvent(QKeyEvent *e) {
|
||||||
if (e->key() == Qt::Key_Escape) {
|
if (!_menu && e->key() == Qt::Key_Escape) {
|
||||||
App::wnd()->layerHidden();
|
onClose();
|
||||||
|
} else if (e == QKeySequence::Save || e == QKeySequence::SaveAs) {
|
||||||
|
onSave();
|
||||||
|
} else if (e->key() == Qt::Key_Copy || (e->key() == Qt::Key_C && e->modifiers().testFlag(Qt::ControlModifier))) {
|
||||||
|
onCopy();
|
||||||
|
} else if (e->key() == Qt::Key_Left) {
|
||||||
|
moveToPhoto(-1);
|
||||||
|
} else if (e->key() == Qt::Key_Right) {
|
||||||
|
moveToPhoto(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaView::moveToPhoto(int32 delta) {
|
||||||
|
if (_index < 0) return;
|
||||||
|
|
||||||
|
int32 newIndex = _index + delta;
|
||||||
|
if (_history) {
|
||||||
|
if (newIndex >= 0 && newIndex < _history->_photosOverview.size()) {
|
||||||
|
_index = newIndex;
|
||||||
|
if (HistoryItem *item = App::histItemById(_history->_photosOverview[_index])) {
|
||||||
|
_msgid = item->id;
|
||||||
|
HistoryPhoto *photo = dynamic_cast<HistoryPhoto*>(item->getMedia());
|
||||||
|
if (photo) {
|
||||||
|
showPhoto(photo->photo());
|
||||||
|
preloadPhotos(delta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (delta < 0 && _index < MediaOverviewStartPerPage) {
|
||||||
|
loadPhotosBack();
|
||||||
|
}
|
||||||
|
} else if (_user) {
|
||||||
|
if (newIndex >= 0 && newIndex < _user->photos.size()) {
|
||||||
|
_index = newIndex;
|
||||||
|
showPhoto(_user->photos[_index]);
|
||||||
|
preloadPhotos(delta);
|
||||||
|
}
|
||||||
|
if (delta > 0 && _index > _user->photos.size() - MediaOverviewStartPerPage) {
|
||||||
|
loadPhotosBack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaView::preloadPhotos(int32 delta) {
|
||||||
|
if (_index < 0) return;
|
||||||
|
|
||||||
|
int32 from = _index + (delta ? delta : -1), to = _index + (delta ? delta * MediaOverviewPreloadCount : 1);
|
||||||
|
if (from > to) qSwap(from, to);
|
||||||
|
if (_history) {
|
||||||
|
for (int32 i = from; i <= to; ++i) {
|
||||||
|
if (i >= 0 && i < _history->_photosOverview.size() && i != _index) {
|
||||||
|
if (HistoryItem *item = App::histItemById(_history->_photosOverview[i])) {
|
||||||
|
HistoryPhoto *photo = dynamic_cast<HistoryPhoto*>(item->getMedia());
|
||||||
|
if (photo) {
|
||||||
|
photo->photo()->full->load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (_user) {
|
||||||
|
for (int32 i = from; i <= to; ++i) {
|
||||||
|
if (i >= 0 && i < _user->photos.size() && i != _index) {
|
||||||
|
_user->photos[i]->thumb->load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int32 i = from; i <= to; ++i) {
|
||||||
|
if (i >= 0 && i < _user->photos.size() && i != _index) {
|
||||||
|
_user->photos[i]->full->load();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaView::mousePressEvent(QMouseEvent *e) {
|
void MediaView::mousePressEvent(QMouseEvent *e) {
|
||||||
|
updateOver(e->pos());
|
||||||
|
if (_menu || !_receiveMouse) return;
|
||||||
|
|
||||||
if (e->button() == Qt::LeftButton) {
|
if (e->button() == Qt::LeftButton) {
|
||||||
App::wnd()->layerHidden();
|
_down = OverNone;
|
||||||
|
if (_over == OverLeftNav && _index >= 0) {
|
||||||
|
moveToPhoto(-1);
|
||||||
|
_lastAction = e->pos();
|
||||||
|
} else if (_over == OverRightNav && _index >= 0) {
|
||||||
|
moveToPhoto(1);
|
||||||
|
_lastAction = e->pos();
|
||||||
|
} else if (_over == OverName) {
|
||||||
|
_down = OverName;
|
||||||
|
} else if (_over == OverDate) {
|
||||||
|
_down = OverDate;
|
||||||
|
} else {
|
||||||
|
int32 w = st::medviewMainWidth + (st::medviewTopSkip - _save.height()), l = _avail.x() + (_avail.width() - w) / 2;
|
||||||
|
if (!QRect(l, _avail.y(), w, st::medviewTopSkip).contains(e->pos()) && !QRect(l, _avail.y() + _avail.height() - st::medviewBottomSkip, w, st::medviewBottomSkip).contains(e->pos())) {
|
||||||
|
if ((e->pos() - _lastAction).manhattanLength() >= st::medviewDeltaFromLastAction) {
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MediaView::mouseMoveEvent(QMouseEvent *e) {
|
||||||
|
updateOver(e->pos());
|
||||||
|
if (_lastAction.x() >= 0 && (e->pos() - _lastAction).manhattanLength() >= st::medviewDeltaFromLastAction) {
|
||||||
|
_lastAction = QPoint(-st::medviewDeltaFromLastAction, -st::medviewDeltaFromLastAction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MediaView::updateOverState(OverState newState) {
|
||||||
|
bool result = true;
|
||||||
|
if (_over != newState) {
|
||||||
|
if (_over != OverNone) {
|
||||||
|
_animations[_over] = getms();
|
||||||
|
ShowingOpacities::iterator i = _animOpacities.find(_over);
|
||||||
|
if (i != _animOpacities.end()) {
|
||||||
|
i->start(0);
|
||||||
|
} else {
|
||||||
|
_animOpacities.insert(_over, anim::fvalue(1, 0));
|
||||||
|
}
|
||||||
|
anim::start(this);
|
||||||
|
if (newState != OverNone) update();
|
||||||
|
} else {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
_over = newState;
|
||||||
|
if (newState != OverNone) {
|
||||||
|
_animations[_over] = getms();
|
||||||
|
ShowingOpacities::iterator i = _animOpacities.find(_over);
|
||||||
|
if (i != _animOpacities.end()) {
|
||||||
|
i->start(1);
|
||||||
|
} else {
|
||||||
|
_animOpacities.insert(_over, anim::fvalue(0, 1));
|
||||||
|
}
|
||||||
|
anim::start(this);
|
||||||
|
setCursor(style::cur_pointer);
|
||||||
|
} else {
|
||||||
|
setCursor(style::cur_default);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaView::updateOver(const QPoint &pos) {
|
||||||
|
if (_leftNavVisible && _leftNav.contains(pos)) {
|
||||||
|
if (!updateOverState(OverLeftNav)) {
|
||||||
|
update(_leftNav);
|
||||||
|
}
|
||||||
|
} else if (_rightNavVisible && _rightNav.contains(pos)) {
|
||||||
|
if (!updateOverState(OverRightNav)) {
|
||||||
|
update(_rightNav);
|
||||||
|
}
|
||||||
|
} else if (_nameNav.contains(pos)) {
|
||||||
|
if (!updateOverState(OverName)) {
|
||||||
|
update(_nameNav);
|
||||||
|
}
|
||||||
|
} else if (_msgid && _dateNav.contains(pos)) {
|
||||||
|
if (!updateOverState(OverDate)) {
|
||||||
|
update(_dateNav);
|
||||||
|
}
|
||||||
|
} else if (_over != OverNone) {
|
||||||
|
if (_over == OverLeftNav) {
|
||||||
|
update(_leftNav);
|
||||||
|
} else if (_over == OverRightNav) {
|
||||||
|
update(_rightNav);
|
||||||
|
} else if (_over == OverName) {
|
||||||
|
update(_nameNav);
|
||||||
|
} else if (_over == OverDate) {
|
||||||
|
update(_dateNav);
|
||||||
|
}
|
||||||
|
updateOverState(OverNone);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaView::mouseReleaseEvent(QMouseEvent *e) {
|
||||||
|
updateOver(e->pos());
|
||||||
|
if (_over == OverName && _down == OverName) {
|
||||||
|
if (App::wnd()) {
|
||||||
|
onClose();
|
||||||
|
if (App::main()) App::main()->showPeerProfile(_from);
|
||||||
|
}
|
||||||
|
} else if (_over == OverDate && _down == OverDate && _msgid) {
|
||||||
|
HistoryItem *item = App::histItemById(_msgid);
|
||||||
|
if (item) {
|
||||||
|
if (App::wnd()) {
|
||||||
|
onClose();
|
||||||
|
if (App::main()) App::main()->showPeer(item->history()->peer->id, _msgid, false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_down = OverNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaView::contextMenuEvent(QContextMenuEvent *e) {
|
||||||
|
if (_photo && _photo->full->loaded() && (e->reason() != QContextMenuEvent::Mouse || QRect(_x, _y, _current.width() / cIntRetinaFactor(), _current.height() / cIntRetinaFactor()).contains(e->pos()))) {
|
||||||
|
|
||||||
|
if (_menu) {
|
||||||
|
_menu->deleteLater();
|
||||||
|
_menu = 0;
|
||||||
|
}
|
||||||
|
_menu = new QMenu(this);
|
||||||
|
_menu->addAction(lang(lng_context_save_image), this, SLOT(onSave()))->setEnabled(true);
|
||||||
|
_menu->addAction(lang(lng_context_copy_image), this, SLOT(onCopy()))->setEnabled(true);
|
||||||
|
_menu->addAction(lang(lng_context_close_image), this, SLOT(onClose()))->setEnabled(true);
|
||||||
|
if (_msgid) {
|
||||||
|
_menu->addAction(lang(lng_context_forward_image), this, SLOT(onForward()))->setEnabled(true);
|
||||||
|
_menu->addAction(lang(lng_context_delete_image), this, SLOT(onDelete()))->setEnabled(true);
|
||||||
|
} else if ((App::self() && App::self()->photoId == _photo->id) || (_photo->chat && _photo->chat->photoId == _photo->id)) {
|
||||||
|
_menu->addAction(lang(lng_context_delete_image), this, SLOT(onDelete()))->setEnabled(true);
|
||||||
|
}
|
||||||
|
_menu->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
connect(_menu, SIGNAL(destroyed(QObject*)), this, SLOT(onMenuDestroy(QObject*)));
|
||||||
|
_menu->popup(e->globalPos());
|
||||||
|
e->accept();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaView::touchEvent(QTouchEvent *e) {
|
||||||
|
switch (e->type()) {
|
||||||
|
case QEvent::TouchBegin:
|
||||||
|
if (_touchPress || e->touchPoints().isEmpty()) return;
|
||||||
|
_touchTimer.start(QApplication::startDragTime());
|
||||||
|
_touchPress = true;
|
||||||
|
_touchMove = _touchRightButton = false;
|
||||||
|
_touchStart = e->touchPoints().cbegin()->screenPos().toPoint();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QEvent::TouchUpdate:
|
||||||
|
if (!_touchPress || e->touchPoints().isEmpty()) return;
|
||||||
|
if (!_touchMove && (e->touchPoints().cbegin()->screenPos().toPoint() - _touchStart).manhattanLength() >= QApplication::startDragDistance()) {
|
||||||
|
_touchMove = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QEvent::TouchEnd:
|
||||||
|
if (!_touchPress) return;
|
||||||
|
if (!_touchMove && App::wnd()) {
|
||||||
|
Qt::MouseButton btn(_touchRightButton ? Qt::RightButton : Qt::LeftButton);
|
||||||
|
QPoint mapped(mapFromGlobal(_touchStart)), winMapped(App::wnd()->mapFromGlobal(_touchStart));
|
||||||
|
|
||||||
|
QMouseEvent pressEvent(QEvent::MouseButtonPress, mapped, winMapped, _touchStart, btn, Qt::MouseButtons(btn), Qt::KeyboardModifiers());
|
||||||
|
pressEvent.accept();
|
||||||
|
mousePressEvent(&pressEvent);
|
||||||
|
|
||||||
|
QMouseEvent releaseEvent(QEvent::MouseButtonRelease, mapped, winMapped, _touchStart, btn, Qt::MouseButtons(btn), Qt::KeyboardModifiers());
|
||||||
|
mouseReleaseEvent(&releaseEvent);
|
||||||
|
|
||||||
|
if (_touchRightButton) {
|
||||||
|
QContextMenuEvent contextEvent(QContextMenuEvent::Mouse, mapped, _touchStart);
|
||||||
|
contextMenuEvent(&contextEvent);
|
||||||
|
}
|
||||||
|
} else if (_touchMove) {
|
||||||
|
if ((!_leftNavVisible || !_leftNav.contains(_touchStart)) && (!_rightNavVisible && !_rightNav.contains(_touchStart))) {
|
||||||
|
QPoint d = (e->touchPoints().cbegin()->screenPos().toPoint() - _touchStart);
|
||||||
|
if (d.x() * d.x() > d.y() * d.y() && (d.x() > st::medviewSwipeDistance || d.x() < -st::medviewSwipeDistance)) {
|
||||||
|
moveToPhoto(d.x() > 0 ? 1 : -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_touchTimer.stop();
|
||||||
|
_touchPress = _touchMove = _touchRightButton = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QEvent::TouchCancel:
|
||||||
|
_touchPress = false;
|
||||||
|
_touchTimer.stop();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MediaView::event(QEvent *e) {
|
||||||
|
if (e->type() == QEvent::TouchBegin || e->type() == QEvent::TouchUpdate || e->type() == QEvent::TouchEnd || e->type() == QEvent::TouchCancel) {
|
||||||
|
QTouchEvent *ev = static_cast<QTouchEvent*>(e);
|
||||||
|
if (ev->device()->type() == QTouchDevice::TouchScreen) {
|
||||||
|
touchEvent(ev);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QWidget::event(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaView::onMenuDestroy(QObject *obj) {
|
||||||
|
if (_menu == obj) {
|
||||||
|
_menu = 0;
|
||||||
|
}
|
||||||
|
_receiveMouse = false;
|
||||||
|
QTimer::singleShot(0, this, SLOT(receiveMouse()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaView::receiveMouse() {
|
||||||
|
_receiveMouse = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaView::onCheckActive() {
|
||||||
|
if (App::wnd() && isVisible()) {
|
||||||
|
if (App::wnd()->isActiveWindow()) {
|
||||||
|
activateWindow();
|
||||||
|
setFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaView::onTouchTimer() {
|
||||||
|
_touchRightButton = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaView::loadPhotosBack() {
|
||||||
|
if (_loadRequest || _index < 0) return;
|
||||||
|
|
||||||
|
if (_history && _history->_photosOverviewCount != 0) {
|
||||||
|
MsgId minId = 0;
|
||||||
|
for (History::MediaOverviewIds::const_iterator i = _history->_photosOverviewIds.cbegin(), e = _history->_photosOverviewIds.cend(); i != e; ++i) {
|
||||||
|
if (*i > 0) {
|
||||||
|
minId = *i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int32 limit = (_index < MediaOverviewStartPerPage && _history->_photosOverview.size() > MediaOverviewStartPerPage) ? SearchPerPage : MediaOverviewStartPerPage;
|
||||||
|
_loadRequest = MTP::send(MTPmessages_Search(_history->peer->input, MTPstring(), MTP_inputMessagesFilterPhotos(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(minId), MTP_int(limit)), rpcDone(&MediaView::photosLoaded, _history));
|
||||||
|
} else if (_user && _user->photosCount != 0) {
|
||||||
|
int32 limit = (_index < MediaOverviewStartPerPage && _user->photos.size() > MediaOverviewStartPerPage) ? SearchPerPage : MediaOverviewStartPerPage;
|
||||||
|
_loadRequest = MTP::send(MTPphotos_GetUserPhotos(_user->inputUser, MTP_int(_user->photos.size()), MTP_int(0), MTP_int(limit)), rpcDone(&MediaView::userPhotosLoaded, _user));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaView::photosLoaded(History *h, const MTPmessages_Messages &msgs, mtpRequestId req) {
|
||||||
|
if (req == _loadRequest) {
|
||||||
|
_loadRequest = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QVector<MTPMessage> *v = 0;
|
||||||
|
switch (msgs.type()) {
|
||||||
|
case mtpc_messages_messages: {
|
||||||
|
const MTPDmessages_messages &d(msgs.c_messages_messages());
|
||||||
|
App::feedUsers(d.vusers);
|
||||||
|
App::feedChats(d.vchats);
|
||||||
|
v = &d.vmessages.c_vector().v;
|
||||||
|
h->_photosOverviewCount = 0;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case mtpc_messages_messagesSlice: {
|
||||||
|
const MTPDmessages_messagesSlice &d(msgs.c_messages_messagesSlice());
|
||||||
|
App::feedUsers(d.vusers);
|
||||||
|
App::feedChats(d.vchats);
|
||||||
|
h->_photosOverviewCount = d.vcount.v;
|
||||||
|
v = &d.vmessages.c_vector().v;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h->_photosOverviewCount > 0) {
|
||||||
|
for (History::MediaOverviewIds::const_iterator i = h->_photosOverviewIds.cbegin(), e = h->_photosOverviewIds.cend(); i != e; ++i) {
|
||||||
|
if (*i < 0) {
|
||||||
|
++h->_photosOverviewCount;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (v->isEmpty()) {
|
||||||
|
h->_photosOverviewCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (QVector<MTPMessage>::const_iterator i = v->cbegin(), e = v->cend(); i != e; ++i) {
|
||||||
|
HistoryItem *item = App::histories().addToBack(*i, -1);
|
||||||
|
if (item && h->_photosOverviewIds.constFind(item->id) == h->_photosOverviewIds.cend()) {
|
||||||
|
h->_photosOverviewIds.insert(item->id);
|
||||||
|
h->_photosOverview.push_front(item->id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (App::wnd()) App::wnd()->mediaOverviewUpdated(h->peer);
|
||||||
|
preloadPhotos(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaView::userPhotosLoaded(UserData *u, const MTPphotos_Photos &photos, mtpRequestId req) {
|
||||||
|
if (req == _loadRequest) {
|
||||||
|
_loadRequest = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QVector<MTPPhoto> *v = 0;
|
||||||
|
switch (photos.type()) {
|
||||||
|
case mtpc_photos_photos: {
|
||||||
|
const MTPDphotos_photos &d(photos.c_photos_photos());
|
||||||
|
App::feedUsers(d.vusers);
|
||||||
|
v = &d.vphotos.c_vector().v;
|
||||||
|
u->photosCount = 0;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case mtpc_photos_photosSlice: {
|
||||||
|
const MTPDphotos_photosSlice &d(photos.c_photos_photosSlice());
|
||||||
|
App::feedUsers(d.vusers);
|
||||||
|
u->photosCount = d.vcount.v;
|
||||||
|
v = &d.vphotos.c_vector().v;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v->isEmpty()) {
|
||||||
|
u->photosCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (QVector<MTPPhoto>::const_iterator i = v->cbegin(), e = v->cend(); i != e; ++i) {
|
||||||
|
PhotoData *photo = App::feedPhoto(*i);
|
||||||
|
photo->thumb->load();
|
||||||
|
u->photos.push_back(photo);
|
||||||
|
}
|
||||||
|
if (App::wnd()) App::wnd()->mediaOverviewUpdated(u);
|
||||||
|
preloadPhotos(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaView::updateHeader() {
|
||||||
|
int32 index = _index, count = 0;
|
||||||
|
if (_history) {
|
||||||
|
count = _history->_photosOverviewCount ? _history->_photosOverviewCount : _history->_photosOverview.size();
|
||||||
|
if (index >= 0) index += count - _history->_photosOverview.size();
|
||||||
|
} else if (_user) {
|
||||||
|
count = _user->photosCount ? _user->photosCount : _user->photos.size();
|
||||||
|
}
|
||||||
|
if (_index >= 0 && _index < count && count > 1) {
|
||||||
|
_header = lang(lng_mediaview_n_of_count).replace(qsl("{n}"), QString::number(index + 1)).replace(qsl("{count}"), QString::number(count));
|
||||||
|
} else if (_user) {
|
||||||
|
_header = lang(lng_mediaview_profile_photo);
|
||||||
|
} else if (_peer) {
|
||||||
|
_header = lang(lng_mediaview_group_photo);
|
||||||
|
} else {
|
||||||
|
_header = lang(lng_mediaview_single_photo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float64 MediaView::overLevel(OverState control) {
|
||||||
|
ShowingOpacities::const_iterator i = _animOpacities.constFind(control);
|
||||||
|
return (i == _animOpacities.cend()) ? (_over == control ? 1 : 0) : i->current();
|
||||||
|
}
|
||||||
|
|
||||||
|
QColor MediaView::nameDateColor(float64 over) {
|
||||||
|
float64 mover = 1 - over;
|
||||||
|
QColor result;
|
||||||
|
result.setRedF(over * st::medviewNameOverColor->c.redF() + mover * st::medviewNameColor->c.redF());
|
||||||
|
result.setGreenF(over * st::medviewNameOverColor->c.greenF() + mover * st::medviewNameColor->c.greenF());
|
||||||
|
result.setBlueF(over * st::medviewNameOverColor->c.blueF() + mover * st::medviewNameColor->c.blueF());
|
||||||
|
result.setAlphaF(over * st::medviewNameOverColor->c.alphaF() + mover * st::medviewNameColor->c.alphaF());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
@ -17,7 +17,7 @@ Copyright (c) 2014 John Preston, https://tdesktop.com
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
class MediaView : public QWidget {
|
class MediaView : public QWidget, public RPCSender, public Animated {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -28,16 +28,96 @@ public:
|
|||||||
|
|
||||||
void keyPressEvent(QKeyEvent *e);
|
void keyPressEvent(QKeyEvent *e);
|
||||||
void mousePressEvent(QMouseEvent *e);
|
void mousePressEvent(QMouseEvent *e);
|
||||||
|
void mouseMoveEvent(QMouseEvent *e);
|
||||||
|
void mouseReleaseEvent(QMouseEvent *e);
|
||||||
|
void contextMenuEvent(QContextMenuEvent *e);
|
||||||
|
void touchEvent(QTouchEvent *e);
|
||||||
|
|
||||||
void showPhoto(PhotoData *photo, const QRect &opaque);
|
bool event(QEvent *e);
|
||||||
|
|
||||||
|
void updateOver(const QPoint &mpos);
|
||||||
|
|
||||||
|
void showPhoto(PhotoData *photo, HistoryItem *context);
|
||||||
|
void showPhoto(PhotoData *photo, PeerData *context);
|
||||||
void moveToScreen();
|
void moveToScreen();
|
||||||
|
void moveToPhoto(int32 delta);
|
||||||
|
void preloadPhotos(int32 delta);
|
||||||
|
|
||||||
|
void mediaOverviewUpdated(PeerData *peer);
|
||||||
|
void changingMsgId(HistoryItem *row, MsgId newId);
|
||||||
|
void updateControls();
|
||||||
|
|
||||||
|
bool animStep(float64 dt);
|
||||||
|
|
||||||
|
~MediaView();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
void onClose();
|
||||||
|
void onSave();
|
||||||
|
void onForward();
|
||||||
|
void onDelete();
|
||||||
|
void onCopy();
|
||||||
|
void onMenuDestroy(QObject *obj);
|
||||||
|
void receiveMouse();
|
||||||
|
|
||||||
|
void onCheckActive();
|
||||||
|
void onTouchTimer();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
void showPhoto(PhotoData *photo);
|
||||||
|
void loadPhotosBack();
|
||||||
|
|
||||||
|
void photosLoaded(History *h, const MTPmessages_Messages &msgs, mtpRequestId req);
|
||||||
|
void userPhotosLoaded(UserData *u, const MTPphotos_Photos &photos, mtpRequestId req);
|
||||||
|
|
||||||
|
void updateHeader();
|
||||||
|
|
||||||
QTimer _timer;
|
QTimer _timer;
|
||||||
PhotoData *_photo;
|
PhotoData *_photo;
|
||||||
QRect _opaqueRect;
|
QRect _avail, _leftNav, _rightNav, _nameNav, _dateNav;
|
||||||
|
bool _leftNavVisible, _rightNavVisible;
|
||||||
|
QString _dateText;
|
||||||
|
|
||||||
int32 _maxWidth, _maxHeight, _x, _y, _w;
|
int32 _maxWidth, _maxHeight, _x, _y, _w;
|
||||||
|
QPixmap _current;
|
||||||
|
bool _full;
|
||||||
|
|
||||||
|
History *_history; // if conversation photos overview
|
||||||
|
PeerData *_peer;
|
||||||
|
UserData *_user, *_from; // if user profile photos overview
|
||||||
|
int32 _index; // index in photos array, -1 if just photo
|
||||||
|
MsgId _msgid; // msgId of current photo
|
||||||
|
|
||||||
|
QString _header;
|
||||||
|
|
||||||
|
mtpRequestId _loadRequest;
|
||||||
|
|
||||||
|
enum OverState {
|
||||||
|
OverNone,
|
||||||
|
OverLeftNav,
|
||||||
|
OverRightNav,
|
||||||
|
OverName,
|
||||||
|
OverDate
|
||||||
|
};
|
||||||
|
OverState _over, _down;
|
||||||
|
QPoint _lastAction;
|
||||||
|
|
||||||
|
FlatButton _close, _save, _forward, _delete;
|
||||||
|
QMenu *_menu;
|
||||||
|
bool _receiveMouse;
|
||||||
|
|
||||||
|
bool _touchPress, _touchMove, _touchRightButton;
|
||||||
|
QTimer _touchTimer;
|
||||||
|
QPoint _touchStart;
|
||||||
|
|
||||||
|
typedef QMap<OverState, uint64> Showing;
|
||||||
|
Showing _animations;
|
||||||
|
typedef QMap<OverState, anim::fvalue> ShowingOpacities;
|
||||||
|
ShowingOpacities _animOpacities;
|
||||||
|
|
||||||
|
bool updateOverState(OverState newState);
|
||||||
|
float64 overLevel(OverState control);
|
||||||
|
QColor nameDateColor(float64 over);
|
||||||
};
|
};
|
||||||
|
@ -62,7 +62,7 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee
|
|||||||
} else if (_peerChat->photoId) {
|
} else if (_peerChat->photoId) {
|
||||||
PhotoData *ph = App::photo(_peerChat->photoId);
|
PhotoData *ph = App::photo(_peerChat->photoId);
|
||||||
if (ph->date) {
|
if (ph->date) {
|
||||||
_photoLink = TextLinkPtr(new PhotoLink(ph));
|
_photoLink = TextLinkPtr(new PhotoLink(ph, _peer));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_loadingId = MTP::send(MTPmessages_GetFullChat(App::peerToMTP(_peerChat->id).c_peerChat().vchat_id), rpcDone(&ProfileInner::gotFullChat));
|
_loadingId = MTP::send(MTPmessages_GetFullChat(App::peerToMTP(_peerChat->id).c_peerChat().vchat_id), rpcDone(&ProfileInner::gotFullChat));
|
||||||
@ -213,7 +213,7 @@ void ProfileInner::gotFullUser(const MTPUserFull &user) {
|
|||||||
App::feedUsers(MTP_vector<MTPUser>(QVector<MTPUser>(1, d.vuser)));
|
App::feedUsers(MTP_vector<MTPUser>(QVector<MTPUser>(1, d.vuser)));
|
||||||
PhotoData *userPhoto = _peerUser->photoId ? App::photo(_peerUser->photoId) : 0;
|
PhotoData *userPhoto = _peerUser->photoId ? App::photo(_peerUser->photoId) : 0;
|
||||||
if (userPhoto && userPhoto->date) {
|
if (userPhoto && userPhoto->date) {
|
||||||
_photoLink = TextLinkPtr(new PhotoLink(userPhoto));
|
_photoLink = TextLinkPtr(new PhotoLink(userPhoto, _peer));
|
||||||
} else {
|
} else {
|
||||||
_photoLink = TextLinkPtr();
|
_photoLink = TextLinkPtr();
|
||||||
}
|
}
|
||||||
@ -249,7 +249,7 @@ void ProfileInner::peerUpdated(PeerData *data) {
|
|||||||
} else {
|
} else {
|
||||||
if (_peerChat->photoId) photo = App::photo(_peerChat->photoId);
|
if (_peerChat->photoId) photo = App::photo(_peerChat->photoId);
|
||||||
}
|
}
|
||||||
_photoLink = (photo && photo->date) ? TextLinkPtr(new PhotoLink(photo)) : TextLinkPtr();
|
_photoLink = (photo && photo->date) ? TextLinkPtr(new PhotoLink(photo, _peer)) : TextLinkPtr();
|
||||||
if (_peer->name != _nameCache) {
|
if (_peer->name != _nameCache) {
|
||||||
_nameCache = _peer->name;
|
_nameCache = _peer->name;
|
||||||
_nameText.setText(st::profileNameFont, _nameCache, _textNameOptions);
|
_nameText.setText(st::profileNameFont, _nameCache, _textNameOptions);
|
||||||
|
@ -155,7 +155,7 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : QWidget(parent),
|
|||||||
if (_self) {
|
if (_self) {
|
||||||
_nameText.setText(st::setNameFont, _nameCache, _textNameOptions);
|
_nameText.setText(st::setNameFont, _nameCache, _textNameOptions);
|
||||||
PhotoData *selfPhoto = _self->photoId ? App::photo(_self->photoId) : 0;
|
PhotoData *selfPhoto = _self->photoId ? App::photo(_self->photoId) : 0;
|
||||||
if (selfPhoto && selfPhoto->date) _photoLink = TextLinkPtr(new PhotoLink(selfPhoto));
|
if (selfPhoto && selfPhoto->date) _photoLink = TextLinkPtr(new PhotoLink(selfPhoto, _self));
|
||||||
MTP::send(MTPusers_GetFullUser(_self->inputUser), rpcDone(&SettingsInner::gotFullSelf));
|
MTP::send(MTPusers_GetFullUser(_self->inputUser), rpcDone(&SettingsInner::gotFullSelf));
|
||||||
|
|
||||||
connect(App::main(), SIGNAL(peerPhotoChanged(PeerData *)), this, SLOT(peerUpdated(PeerData *)));
|
connect(App::main(), SIGNAL(peerPhotoChanged(PeerData *)), this, SLOT(peerUpdated(PeerData *)));
|
||||||
@ -257,7 +257,7 @@ void SettingsInner::peerUpdated(PeerData *data) {
|
|||||||
if (_self->photoId) {
|
if (_self->photoId) {
|
||||||
PhotoData *selfPhoto = App::photo(_self->photoId);
|
PhotoData *selfPhoto = App::photo(_self->photoId);
|
||||||
if (selfPhoto->date) {
|
if (selfPhoto->date) {
|
||||||
_photoLink = TextLinkPtr(new PhotoLink(selfPhoto));
|
_photoLink = TextLinkPtr(new PhotoLink(selfPhoto, _self));
|
||||||
} else {
|
} else {
|
||||||
_photoLink = TextLinkPtr();
|
_photoLink = TextLinkPtr();
|
||||||
MTP::send(MTPusers_GetFullUser(_self->inputUser), rpcDone(&SettingsInner::gotFullSelf));
|
MTP::send(MTPusers_GetFullUser(_self->inputUser), rpcDone(&SettingsInner::gotFullSelf));
|
||||||
@ -612,7 +612,7 @@ void SettingsInner::gotFullSelf(const MTPUserFull &self) {
|
|||||||
App::feedUsers(MTP_vector<MTPUser>(QVector<MTPUser>(1, self.c_userFull().vuser)));
|
App::feedUsers(MTP_vector<MTPUser>(QVector<MTPUser>(1, self.c_userFull().vuser)));
|
||||||
PhotoData *selfPhoto = _self->photoId ? App::photo(_self->photoId) : 0;
|
PhotoData *selfPhoto = _self->photoId ? App::photo(_self->photoId) : 0;
|
||||||
if (selfPhoto && selfPhoto->date) {
|
if (selfPhoto && selfPhoto->date) {
|
||||||
_photoLink = TextLinkPtr(new PhotoLink(selfPhoto));
|
_photoLink = TextLinkPtr(new PhotoLink(selfPhoto, _self));
|
||||||
} else {
|
} else {
|
||||||
_photoLink = TextLinkPtr();
|
_photoLink = TextLinkPtr();
|
||||||
}
|
}
|
||||||
|
@ -336,7 +336,7 @@ NotifyWindow::~NotifyWindow() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Window::Window(QWidget *parent) : PsMainWindow(parent),
|
Window::Window(QWidget *parent) : PsMainWindow(parent),
|
||||||
intro(0), main(0), settings(0), layer(0), layerBG(0), _topWidget(0), _mediaView(0),
|
intro(0), main(0), settings(0), layerBG(0), _topWidget(0), _mediaView(0),
|
||||||
_connecting(0), _tempDeleter(0), _tempDeleterThread(0), myIcon(QPixmap::fromImage(icon256)), dragging(false), _inactivePress(false) {
|
_connecting(0), _tempDeleter(0), _tempDeleterThread(0), myIcon(QPixmap::fromImage(icon256)), dragging(false), _inactivePress(false) {
|
||||||
|
|
||||||
if (objectName().isEmpty())
|
if (objectName().isEmpty())
|
||||||
@ -391,6 +391,10 @@ void Window::init() {
|
|||||||
psUpdateWorkmode();
|
psUpdateWorkmode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QWidget *Window::filedialogParent() {
|
||||||
|
return (_mediaView && _mediaView->isVisible()) ? (QWidget*)_mediaView : (QWidget*)this;
|
||||||
|
}
|
||||||
|
|
||||||
void Window::clearWidgets() {
|
void Window::clearWidgets() {
|
||||||
layerHidden();
|
layerHidden();
|
||||||
if (settings) {
|
if (settings) {
|
||||||
@ -547,29 +551,23 @@ SettingsWidget *Window::settingsWidget() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Window::showPhoto(const PhotoLink *lnk, HistoryItem *item) {
|
void Window::showPhoto(const PhotoLink *lnk, HistoryItem *item) {
|
||||||
return showPhoto(lnk->photo(), item);
|
return lnk->peer() ? showPhoto(lnk->photo(), lnk->peer()) : showPhoto(lnk->photo(), item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Window::showPhoto(PhotoData *photo, HistoryItem *item) {
|
void Window::showPhoto(PhotoData *photo, HistoryItem *item) {
|
||||||
layerHidden();
|
layerHidden();
|
||||||
_mediaView->showPhoto(photo, QRect());
|
_mediaView->showPhoto(photo, item);
|
||||||
_mediaView->activateWindow();
|
_mediaView->activateWindow();
|
||||||
_mediaView->setFocus();
|
_mediaView->setFocus();
|
||||||
// layer = new LayerWidget(this, photo, item);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PhotoData *Window::photoShown() {
|
void Window::showPhoto(PhotoData *photo, PeerData *peer) {
|
||||||
return layer ? layer->photoShown() : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
void Window::showVideo(const VideoOpenLink *lnk, HistoryItem *item) {
|
|
||||||
layerHidden();
|
layerHidden();
|
||||||
VideoData *video = App::video(lnk->video());
|
_mediaView->showPhoto(photo, peer);
|
||||||
layer = new LayerWidget(this, video, item);
|
_mediaView->activateWindow();
|
||||||
|
_mediaView->setFocus();
|
||||||
}
|
}
|
||||||
/**/
|
|
||||||
void Window::showLayer(LayeredWidget *w) {
|
void Window::showLayer(LayeredWidget *w) {
|
||||||
layerHidden();
|
layerHidden();
|
||||||
layerBG = new BackgroundWidget(this, w);
|
layerBG = new BackgroundWidget(this, w);
|
||||||
@ -594,8 +592,6 @@ void Window::hideConnecting() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Window::replaceLayer(LayeredWidget *w) {
|
void Window::replaceLayer(LayeredWidget *w) {
|
||||||
if (layer) layer->deleteLater();
|
|
||||||
layer = 0;
|
|
||||||
if (layerBG) {
|
if (layerBG) {
|
||||||
layerBG->replaceInner(w);
|
layerBG->replaceInner(w);
|
||||||
} else {
|
} else {
|
||||||
@ -607,13 +603,13 @@ void Window::hideLayer() {
|
|||||||
if (layerBG) {
|
if (layerBG) {
|
||||||
layerBG->onClose();
|
layerBG->onClose();
|
||||||
}
|
}
|
||||||
if (layer) {
|
if (_mediaView && !_mediaView->isHidden()) {
|
||||||
layer->startHide();
|
_mediaView->hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Window::layerShown() {
|
bool Window::layerShown() {
|
||||||
return !!layer || !!layerBG || !!_topWidget;
|
return !!layerBG || !!_topWidget;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Window::historyIsActive(int state) const {
|
bool Window::historyIsActive(int state) const {
|
||||||
@ -627,11 +623,9 @@ void Window::checkHistoryActivation(int state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Window::layerHidden() {
|
void Window::layerHidden() {
|
||||||
if (layer) layer->deleteLater();
|
|
||||||
layer = 0;
|
|
||||||
if (layerBG) layerBG->deleteLater();
|
if (layerBG) layerBG->deleteLater();
|
||||||
layerBG = 0;
|
layerBG = 0;
|
||||||
if (_mediaView) _mediaView->hide();
|
if (_mediaView && !_mediaView->isHidden()) _mediaView->hide();
|
||||||
if (main) main->setInnerFocus();
|
if (main) main->setInnerFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -685,7 +679,7 @@ HitTestType Window::hitTest(const QPoint &p) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
HitTestType titleTest = title->hitTest(p - title->geometry().topLeft());
|
HitTestType titleTest = title->hitTest(p - title->geometry().topLeft());
|
||||||
if (titleTest && (!layer || titleTest != HitTestCaption)) {
|
if (titleTest) {
|
||||||
return titleTest;
|
return titleTest;
|
||||||
} else if (x >= 0 && y >= 0 && x < w && y < h) {
|
} else if (x >= 0 && y >= 0 && x < w && y < h) {
|
||||||
return HitTestClient;
|
return HitTestClient;
|
||||||
@ -826,13 +820,6 @@ void Window::noMain(MainWidget *was) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::noLayer(LayerWidget *was) {
|
|
||||||
if (was == layer) {
|
|
||||||
layer = 0;
|
|
||||||
}
|
|
||||||
fixOrder();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::noBox(BackgroundWidget *was) {
|
void Window::noBox(BackgroundWidget *was) {
|
||||||
if (was == layerBG) {
|
if (was == layerBG) {
|
||||||
layerBG = 0;
|
layerBG = 0;
|
||||||
@ -841,7 +828,6 @@ void Window::noBox(BackgroundWidget *was) {
|
|||||||
|
|
||||||
void Window::fixOrder() {
|
void Window::fixOrder() {
|
||||||
title->raise();
|
title->raise();
|
||||||
if (layer) layer->raise();
|
|
||||||
if (layerBG) layerBG->raise();
|
if (layerBG) layerBG->raise();
|
||||||
if (_topWidget) _topWidget->raise();
|
if (_topWidget) _topWidget->raise();
|
||||||
if (_connecting) _connecting->raise();
|
if (_connecting) _connecting->raise();
|
||||||
@ -890,7 +876,6 @@ TitleWidget *Window::getTitle() {
|
|||||||
|
|
||||||
void Window::resizeEvent(QResizeEvent *e) {
|
void Window::resizeEvent(QResizeEvent *e) {
|
||||||
title->setGeometry(QRect(0, 0, width(), st::titleHeight + st::titleShadow));
|
title->setGeometry(QRect(0, 0, width(), st::titleHeight + st::titleShadow));
|
||||||
if (layer) layer->resize(width(), height());
|
|
||||||
if (layerBG) layerBG->resize(width(), height());
|
if (layerBG) layerBG->resize(width(), height());
|
||||||
if (_connecting) _connecting->setGeometry(0, height() - _connecting->height(), _connecting->width(), _connecting->height());
|
if (_connecting) _connecting->setGeometry(0, height() - _connecting->height(), _connecting->width(), _connecting->height());
|
||||||
emit resized(QSize(width(), height() - st::titleHeight));
|
emit resized(QSize(width(), height() - st::titleHeight));
|
||||||
@ -1206,7 +1191,7 @@ void Window::notifyUpdateAllPhotos() {
|
|||||||
(*i)->updatePeerPhoto();
|
(*i)->updatePeerPhoto();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_mediaView) _mediaView->update();
|
if (_mediaView) _mediaView->updateControls();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::notifyUpdateAll() {
|
void Window::notifyUpdateAll() {
|
||||||
@ -1231,6 +1216,7 @@ QImage Window::iconLarge() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Window::sendPaths() {
|
void Window::sendPaths() {
|
||||||
|
if (_mediaView && !_mediaView->isHidden()) _mediaView->hide();
|
||||||
if (settings) {
|
if (settings) {
|
||||||
hideSettings();
|
hideSettings();
|
||||||
} else {
|
} else {
|
||||||
@ -1243,6 +1229,16 @@ void Window::sendPaths() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Window::mediaOverviewUpdated(PeerData *peer) {
|
||||||
|
if (!_mediaView || _mediaView->isHidden()) return;
|
||||||
|
_mediaView->mediaOverviewUpdated(peer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::changingMsgId(HistoryItem *row, MsgId newId) {
|
||||||
|
if (!_mediaView || _mediaView->isHidden()) return;
|
||||||
|
_mediaView->changingMsgId(row, newId);
|
||||||
|
}
|
||||||
|
|
||||||
Window::~Window() {
|
Window::~Window() {
|
||||||
notifyClearFast();
|
notifyClearFast();
|
||||||
delete _tempDeleter;
|
delete _tempDeleter;
|
||||||
@ -1253,6 +1249,5 @@ Window::~Window() {
|
|||||||
delete trayIconMenu;
|
delete trayIconMenu;
|
||||||
delete intro;
|
delete intro;
|
||||||
delete main;
|
delete main;
|
||||||
delete layer;
|
|
||||||
delete settings;
|
delete settings;
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,6 @@ class TitleWidget;
|
|||||||
class IntroWidget;
|
class IntroWidget;
|
||||||
class MainWidget;
|
class MainWidget;
|
||||||
class SettingsWidget;
|
class SettingsWidget;
|
||||||
class LayerWidget;
|
|
||||||
class BackgroundWidget;
|
class BackgroundWidget;
|
||||||
class LayeredWidget;
|
class LayeredWidget;
|
||||||
|
|
||||||
@ -135,6 +134,8 @@ public:
|
|||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
|
QWidget *filedialogParent();
|
||||||
|
|
||||||
bool eventFilter(QObject *obj, QEvent *evt);
|
bool eventFilter(QObject *obj, QEvent *evt);
|
||||||
|
|
||||||
void inactivePress(bool inactive);
|
void inactivePress(bool inactive);
|
||||||
@ -173,9 +174,8 @@ public:
|
|||||||
|
|
||||||
void hideSettings(bool fast = false);
|
void hideSettings(bool fast = false);
|
||||||
void showPhoto(const PhotoLink *lnk, HistoryItem *item = 0);
|
void showPhoto(const PhotoLink *lnk, HistoryItem *item = 0);
|
||||||
void showPhoto(PhotoData *photo, HistoryItem *item = 0);
|
void showPhoto(PhotoData *photo, HistoryItem *item);
|
||||||
// void showVideo(const VideoOpenLink *lnk, HistoryItem *item = 0);
|
void showPhoto(PhotoData *photo, PeerData *item);
|
||||||
PhotoData *photoShown();
|
|
||||||
void showLayer(LayeredWidget *w);
|
void showLayer(LayeredWidget *w);
|
||||||
void replaceLayer(LayeredWidget *w);
|
void replaceLayer(LayeredWidget *w);
|
||||||
void hideLayer();
|
void hideLayer();
|
||||||
@ -194,7 +194,6 @@ public:
|
|||||||
void noIntro(IntroWidget *was);
|
void noIntro(IntroWidget *was);
|
||||||
void noSettings(SettingsWidget *was);
|
void noSettings(SettingsWidget *was);
|
||||||
void noMain(MainWidget *was);
|
void noMain(MainWidget *was);
|
||||||
void noLayer(LayerWidget *was);
|
|
||||||
void noBox(BackgroundWidget *was);
|
void noBox(BackgroundWidget *was);
|
||||||
|
|
||||||
void topWidget(QWidget *w);
|
void topWidget(QWidget *w);
|
||||||
@ -228,6 +227,9 @@ public:
|
|||||||
|
|
||||||
void sendPaths();
|
void sendPaths();
|
||||||
|
|
||||||
|
void mediaOverviewUpdated(PeerData *peer);
|
||||||
|
void changingMsgId(HistoryItem *row, MsgId newId);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
void checkHistoryActivation(int state = -1);
|
void checkHistoryActivation(int state = -1);
|
||||||
@ -263,7 +265,6 @@ private:
|
|||||||
IntroWidget *intro;
|
IntroWidget *intro;
|
||||||
MainWidget *main;
|
MainWidget *main;
|
||||||
SettingsWidget *settings;
|
SettingsWidget *settings;
|
||||||
LayerWidget *layer;
|
|
||||||
BackgroundWidget *layerBG;
|
BackgroundWidget *layerBG;
|
||||||
|
|
||||||
QWidget *_topWidget; // temp hack for CountrySelect
|
QWidget *_topWidget; // temp hack for CountrySelect
|
||||||
|
Loading…
Reference in New Issue
Block a user