mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 02:01:40 -05:00
merged new photoview
This commit is contained in:
commit
17c0b06d85
29 changed files with 1288 additions and 492 deletions
|
@ -341,6 +341,7 @@ lng_context_forward_selected: "Forward Selected";
|
|||
lng_context_delete_selected: "Delete Selected";
|
||||
lng_context_clear_selection: "Clear Selection";
|
||||
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_confirm: "Forward to {recipient}?";
|
||||
|
@ -398,6 +399,15 @@ lng_search_no_results: "No messages found";
|
|||
lng_search_one_result: "Found {count} message";
|
||||
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
|
||||
|
||||
lng_mac_choose_app: "Choose Application";
|
||||
|
|
|
@ -975,6 +975,8 @@ boxBG: white;//rgb(228, 233, 240);
|
|||
boxGrayTitle: #777;
|
||||
|
||||
confirmWidth: 364px;
|
||||
confirmMaxHeight: 320px;
|
||||
confirmCompressedSkip: 10px;
|
||||
addContactWidth: 364px;
|
||||
addContactPadding: margins(18px, 24px, 18px, 24px);
|
||||
addContactDelta: 14px;
|
||||
|
@ -1439,11 +1441,45 @@ emojiPanDuration: 200;
|
|||
emojiPanHover: #f0f0f0;
|
||||
emojiPanRound: 2px;
|
||||
|
||||
medviewNavBarWidth: 200px;
|
||||
medviewTopSkip: 50px;
|
||||
medviewBottomSkip: 50px;
|
||||
medviewLightOpacity: 0.75;
|
||||
medviewNavBarWidth: 120px;
|
||||
medviewTopSkip: 66px;
|
||||
medviewBottomSkip: 66px;
|
||||
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;
|
||||
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
|
||||
|
||||
|
|
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"
|
||||
|
||||
PhotoSendBox::PhotoSendBox(const ReadyLocalMedia &img) : _img(img),
|
||||
_compressed(this, lang(lng_send_image_compressed), true),
|
||||
_sendButton(this, lang(lng_send_button), st::btnSelectDone),
|
||||
_cancelButton(this, lang(lng_cancel), st::btnSelectCancel),
|
||||
a_opacity(0, 1) {
|
||||
|
@ -48,7 +49,7 @@ PhotoSendBox::PhotoSendBox(const ReadyLocalMedia &img) : _img(img),
|
|||
if (_thumb.width() < _thumbw) {
|
||||
_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);
|
||||
if (_thumbh > maxthumbh) {
|
||||
_thumbw = qRound(_thumbw * float64(maxthumbh) / _thumbh);
|
||||
|
@ -57,7 +58,7 @@ PhotoSendBox::PhotoSendBox(const ReadyLocalMedia &img) : _img(img),
|
|||
_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));
|
||||
|
||||
|
@ -77,6 +78,7 @@ void PhotoSendBox::parentResized() {
|
|||
setGeometry((s.width() - _width) / 2, (s.height() - _height) / 2, _width, _height);
|
||||
_sendButton.move(_width - _sendButton.width(), _height - _sendButton.height());
|
||||
_cancelButton.move(0, _height - _cancelButton.height());
|
||||
_compressed.move((width() - _compressed.width()) / 2, _height - _cancelButton.height() - _compressed.height() - st::confirmCompressedSkip);
|
||||
update();
|
||||
}
|
||||
|
||||
|
@ -107,11 +109,16 @@ void PhotoSendBox::animStep(float64 ms) {
|
|||
}
|
||||
_sendButton.setOpacity(a_opacity.current());
|
||||
_cancelButton.setOpacity(a_opacity.current());
|
||||
_compressed.setOpacity(a_opacity.current());
|
||||
update();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ private:
|
|||
|
||||
ReadyLocalMedia _img;
|
||||
int32 _width, _height, _thumbw, _thumbh;
|
||||
FlatCheckbox _compressed;
|
||||
FlatButton _sendButton, _cancelButton;
|
||||
QPixmap _thumb;
|
||||
|
||||
|
|
|
@ -66,6 +66,8 @@ enum {
|
|||
|
||||
AutoSearchTimeout = 900, // 0.9 secs
|
||||
SearchPerPage = 50,
|
||||
MediaOverviewStartPerPage = 5,
|
||||
MediaOverviewPreloadCount = 4,
|
||||
};
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
|
|
|
@ -58,8 +58,9 @@ namespace anim {
|
|||
const float64 ¤t() const {
|
||||
return _cur;
|
||||
}
|
||||
void update(const float64 &dt, transition func) {
|
||||
fvalue &update(const float64 &dt, transition func) {
|
||||
_cur = _from + (*func)(_delta, dt);
|
||||
return *this;
|
||||
}
|
||||
void finish() {
|
||||
_cur = _from + _delta;
|
||||
|
@ -92,8 +93,9 @@ namespace anim {
|
|||
int32 current() const {
|
||||
return _cur;
|
||||
}
|
||||
void update(const float64 &dt, transition func) {
|
||||
ivalue &update(const float64 &dt, transition func) {
|
||||
_cur = qRound(_from + (*func)(_delta, dt));
|
||||
return *this;
|
||||
}
|
||||
void finish() {
|
||||
_cur = qRound(_from + _delta);
|
||||
|
@ -143,11 +145,12 @@ namespace anim {
|
|||
const QColor ¤t() const {
|
||||
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.setGreenF(_from_g + (*func)(_delta_g, dt));
|
||||
_cur.setBlueF(_from_b + (*func)(_delta_b, dt));
|
||||
_cur.setAlphaF(_from_a + (*func)(_delta_a, dt));
|
||||
return *this;
|
||||
}
|
||||
void finish() {
|
||||
_cur.setRedF(_from_r + _delta_r);
|
||||
|
|
|
@ -68,14 +68,14 @@ bool _filedialogGetFiles(QStringList &files, QByteArray &remoteContent, const QS
|
|||
remoteContent = QByteArray();
|
||||
QString file;
|
||||
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();
|
||||
} else if (multipleFiles < -1) {
|
||||
file = QFileDialog::getExistingDirectory(App::wnd(), caption);
|
||||
file = QFileDialog::getExistingDirectory(App::wnd() ? App::wnd()->filedialogParent() : 0, caption);
|
||||
} 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 {
|
||||
file = QFileDialog::getOpenFileName(App::wnd(), caption, startFile, filter);
|
||||
file = QFileDialog::getOpenFileName(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, startFile, filter);
|
||||
}
|
||||
if (file.isEmpty()) {
|
||||
files = QStringList();
|
||||
|
@ -89,7 +89,7 @@ bool _filedialogGetFiles(QStringList &files, QByteArray &remoteContent, const QS
|
|||
filedialogInit();
|
||||
|
||||
// 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);
|
||||
if (multipleFiles >= 0) { // open file or files
|
||||
|
@ -171,7 +171,7 @@ bool filedialogGetDir(QString &dir, const QString &caption) {
|
|||
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();
|
||||
|
||||
time_t t = time(NULL);
|
||||
|
@ -180,11 +180,17 @@ QString filedialogDefaultName(const QString &prefix, const QString &extension, c
|
|||
|
||||
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 nameBase = dir.absolutePath() + '/' + base, name = nameBase + extension;
|
||||
for (int i = 0; QFileInfo(name).exists(); ++i) {
|
||||
name = nameBase + QString(" (%1)").arg(i + 2) + extension;
|
||||
if (skipExistance) {
|
||||
name = base + 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;
|
||||
}
|
||||
|
|
|
@ -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 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();
|
||||
}
|
||||
|
||||
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 {
|
||||
restore();
|
||||
loaded();
|
||||
|
|
|
@ -28,7 +28,9 @@ public:
|
|||
return true;
|
||||
}
|
||||
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 pixBlurredNoCache(int32 w, int32 h = 0) const;
|
||||
|
||||
virtual int32 width() const = 0;
|
||||
virtual int32 height() const = 0;
|
||||
|
|
|
@ -2642,6 +2642,10 @@ int32 Text::countHeight(int32 w) const {
|
|||
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 {
|
||||
// painter.fillRect(QRect(left, top, w, countHeight(w)), QColor(0, 0, 0, 32)); // debug
|
||||
TextPainter p(&painter, this);
|
||||
|
|
|
@ -373,6 +373,8 @@ public:
|
|||
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 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 {
|
||||
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()) {
|
||||
|
@ -657,6 +659,7 @@ History::History(const PeerId &peerId) : width(0), height(0)
|
|||
, posInDialogs(0)
|
||||
, typingText(st::dlgRichMinWidth)
|
||||
, myTyping(0)
|
||||
, _photosOverviewCount(-1) // not loaded yet
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -1081,6 +1084,14 @@ HistoryItem *History::doAddToBack(HistoryBlock *to, bool newBlock, HistoryItem *
|
|||
if (newMsg) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1163,6 +1174,20 @@ void History::addToFront(const QVector<MTPMessage> &slice) {
|
|||
push_front(block);
|
||||
addToH += block->height;
|
||||
++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 {
|
||||
delete block;
|
||||
}
|
||||
|
@ -1225,6 +1250,7 @@ void History::addToBack(const QVector<MTPMessage> &slice) {
|
|||
}
|
||||
if (i == e) break;
|
||||
}
|
||||
bool wasLoadedAtBottom = loadedAtBottom();
|
||||
if (block->size()) {
|
||||
block->y = height;
|
||||
push_back(block);
|
||||
|
@ -1234,6 +1260,23 @@ void History::addToBack(const QVector<MTPMessage> &slice) {
|
|||
fixLastMessage(true);
|
||||
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()) {
|
||||
HistoryBlock *dateBlock = new HistoryBlock(this);
|
||||
HistoryItem *dayItem = createDayServiceMsg(this, dateBlock, front()->front()->date);
|
||||
|
@ -1469,6 +1512,10 @@ void History::clear(bool leaveItems) {
|
|||
if (showFrom) {
|
||||
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) {
|
||||
if (leaveItems) {
|
||||
(*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() {
|
||||
if (_history && _history->unreadBar == this) {
|
||||
_history->unreadBar = 0;
|
||||
|
@ -1705,8 +1777,17 @@ HistoryItem *regItem(HistoryItem *item, bool returnExisting) {
|
|||
|
||||
HistoryPhoto::HistoryPhoto(const MTPDphoto &photo, int32 width) : data(App::feedPhoto(photo))
|
||||
, 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();
|
||||
if (!tw || !th) {
|
||||
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 {
|
||||
data->full->load(false, false);
|
||||
bool out = parent->out();
|
||||
if (parent != App::contextItem() || App::wnd()->photoShown() != data) {
|
||||
if (parent != App::contextItem()/* || App::wnd()->photoShown() != data*/) {
|
||||
if (data->full->loaded()) {
|
||||
p.drawPixmap(0, 0, data->full->pix(_maxw, _height));
|
||||
} else {
|
||||
p.drawPixmap(0, 0, data->thumb->pix(_maxw, _height));
|
||||
p.drawPixmap(0, 0, data->thumb->pixBlurred(_maxw, _height));
|
||||
}
|
||||
|
||||
if (selected) {
|
||||
|
@ -2718,7 +2799,7 @@ QString HistoryMessage::selectedText(uint32 selection) const {
|
|||
return _text.original(selectedFrom, selectedTo);
|
||||
}
|
||||
|
||||
HistoryMedia *HistoryMessage::getMedia() const {
|
||||
HistoryMedia *HistoryMessage::getMedia(bool inOverview) const {
|
||||
return media;
|
||||
}
|
||||
|
||||
|
@ -3030,7 +3111,9 @@ QString HistoryMessage::notificationText() const {
|
|||
}
|
||||
|
||||
HistoryMessage::~HistoryMessage() {
|
||||
if (media) media->unregItem(this);
|
||||
if (media) {
|
||||
media->unregItem(this);
|
||||
}
|
||||
delete media;
|
||||
}
|
||||
|
||||
|
@ -3249,7 +3332,7 @@ QString HistoryServiceMsg::messageByAction(const MTPmessageAction &action, TextL
|
|||
case mtpc_messageActionChatEditPhoto: {
|
||||
const MTPDmessageActionChatEditPhoto &d(action.c_messageActionChatEditPhoto());
|
||||
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);
|
||||
} break;
|
||||
|
@ -3457,6 +3540,10 @@ QString HistoryServiceMsg::notificationText() const {
|
|||
return msg;
|
||||
}
|
||||
|
||||
HistoryMedia *HistoryServiceMsg::getMedia(bool inOverview) const {
|
||||
return inOverview ? 0 : media;
|
||||
}
|
||||
|
||||
HistoryServiceMsg::~HistoryServiceMsg() {
|
||||
delete media;
|
||||
}
|
||||
|
|
|
@ -135,8 +135,9 @@ private:
|
|||
const PeerData *_peer;
|
||||
};
|
||||
|
||||
struct PhotoData;
|
||||
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 setName(const QString &first, const QString &last, const QString &phoneName);
|
||||
|
@ -151,6 +152,10 @@ struct UserData : public PeerData {
|
|||
TextLinkPtr lnk;
|
||||
int32 onlineTill;
|
||||
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 {
|
||||
|
@ -193,15 +198,21 @@ struct PhotoData {
|
|||
|
||||
class PhotoLink : public ITextLink {
|
||||
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;
|
||||
PhotoData *photo() const {
|
||||
return _photo;
|
||||
}
|
||||
PeerData *peer() const {
|
||||
return _peer;
|
||||
}
|
||||
|
||||
private:
|
||||
PhotoData *_photo;
|
||||
PeerData *_peer;
|
||||
};
|
||||
|
||||
enum FileStatus {
|
||||
|
@ -695,6 +706,12 @@ struct History : public QList<HistoryBlock*> {
|
|||
bool updateTyping(uint64 ms = 0, uint32 dots = 0, bool force = false);
|
||||
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;
|
||||
};
|
||||
|
||||
|
@ -1018,6 +1035,7 @@ protected:
|
|||
|
||||
};
|
||||
|
||||
class HistoryMedia;
|
||||
class HistoryItem : public HistoryElem {
|
||||
public:
|
||||
|
||||
|
@ -1048,16 +1066,7 @@ public:
|
|||
const HistoryBlock *block() const {
|
||||
return _block;
|
||||
}
|
||||
void destroy() {
|
||||
if (!out()) markRead();
|
||||
bool wasAtBottom = history()->loadedAtBottom();
|
||||
_history->removeNotification(this);
|
||||
detach();
|
||||
if (history()->last == this) {
|
||||
history()->fixLastMessage(wasAtBottom);
|
||||
}
|
||||
delete this;
|
||||
}
|
||||
void destroy();
|
||||
void detach();
|
||||
void detachFast();
|
||||
bool detached() const {
|
||||
|
@ -1117,6 +1126,10 @@ public:
|
|||
int32 y, id;
|
||||
QDateTime date;
|
||||
|
||||
virtual HistoryMedia *getMedia(bool inOverview = false) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual ~HistoryItem();
|
||||
|
||||
protected:
|
||||
|
@ -1177,6 +1190,9 @@ class HistoryPhoto : public HistoryMedia {
|
|||
public:
|
||||
|
||||
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;
|
||||
int32 resize(int32 width);
|
||||
|
@ -1189,6 +1205,10 @@ public:
|
|||
bool getPhotoCoords(PhotoData *photo, int32 &x, int32 &y, int32 &w) const;
|
||||
HistoryMedia *clone() const;
|
||||
|
||||
PhotoData *photo() const {
|
||||
return data;
|
||||
}
|
||||
|
||||
private:
|
||||
PhotoData *data;
|
||||
TextLinkPtr openl;
|
||||
|
@ -1369,7 +1389,7 @@ public:
|
|||
}
|
||||
|
||||
QString selectedText(uint32 selection) const;
|
||||
HistoryMedia *getMedia() const;
|
||||
HistoryMedia *getMedia(bool inOverview = false) const;
|
||||
|
||||
~HistoryMessage();
|
||||
|
||||
|
@ -1446,6 +1466,8 @@ public:
|
|||
}
|
||||
QString selectedText(uint32 selection) const;
|
||||
|
||||
HistoryMedia *getMedia(bool inOverview = false) const;
|
||||
|
||||
~HistoryServiceMsg();
|
||||
|
||||
protected:
|
||||
|
|
|
@ -2669,9 +2669,19 @@ void HistoryWidget::uploadImage(const QImage &img) {
|
|||
if (!hist || confirmImageId) return;
|
||||
|
||||
App::wnd()->activateWindow();
|
||||
confirmImage = img;
|
||||
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) {
|
||||
if (!hist) return;
|
||||
|
||||
|
@ -2706,6 +2716,7 @@ void HistoryWidget::onPhotoFailed(quint64 id) {
|
|||
void HistoryWidget::confirmSendImage(const ReadyLocalMedia &img) {
|
||||
if (img.id == confirmImageId) {
|
||||
confirmImageId = 0;
|
||||
confirmImage = QImage();
|
||||
}
|
||||
MsgId newId = clientMsgId();
|
||||
|
||||
|
@ -2737,6 +2748,7 @@ void HistoryWidget::confirmSendImage(const ReadyLocalMedia &img) {
|
|||
|
||||
void HistoryWidget::cancelSendImage() {
|
||||
confirmImageId = 0;
|
||||
confirmImage = QImage();
|
||||
}
|
||||
|
||||
void HistoryWidget::onPhotoUploaded(MsgId newId, const MTPInputFile &file) {
|
||||
|
|
|
@ -291,6 +291,7 @@ public:
|
|||
|
||||
void destroyData();
|
||||
void uploadImage(const QImage &img);
|
||||
void uploadConfirmImageUncompressed();
|
||||
void uploadMedias(const QStringList &files, ToPrepareMediaType type);
|
||||
void uploadMedia(const QByteArray &fileContent, ToPrepareMediaType type);
|
||||
void confirmSendImage(const ReadyLocalMedia &img);
|
||||
|
@ -427,6 +428,7 @@ private:
|
|||
mtpRequestId loadingRequestId;
|
||||
|
||||
int64 serviceImageCacheSize;
|
||||
QImage confirmImage;
|
||||
PhotoId confirmImageId;
|
||||
|
||||
QString titlePeerText;
|
||||
|
|
|
@ -125,328 +125,3 @@ BackgroundWidget::~BackgroundWidget() {
|
|||
w->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;
|
||||
};
|
||||
|
||||
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 "localimageloader.h"
|
||||
#include "gui/filedialog.h"
|
||||
#include <libexif/exif-data.h>
|
||||
|
||||
LocalImageLoaderPrivate::LocalImageLoaderPrivate(int32 currentUser, LocalImageLoader *loader, QThread *thread) : QObject(0)
|
||||
|
@ -99,9 +100,20 @@ void LocalImageLoaderPrivate::prepareImages() {
|
|||
filesize = data.size();
|
||||
}
|
||||
} else {
|
||||
type = ToPreparePhoto; // only photo from QImage
|
||||
filename = qsl("Untitled.jpg");
|
||||
filesize = 0;
|
||||
if (type == ToPrepareDocument) {
|
||||
filename = filedialogDefaultName(qsl("image"), qsl(".png"), QString(), true);
|
||||
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
|
||||
|
|
|
@ -678,6 +678,10 @@ void MainWidget::confirmSendImage(const ReadyLocalMedia &img) {
|
|||
history.confirmSendImage(img);
|
||||
}
|
||||
|
||||
void MainWidget::confirmSendImageUncompressed() {
|
||||
history.uploadConfirmImageUncompressed();
|
||||
}
|
||||
|
||||
void MainWidget::cancelSendImage() {
|
||||
history.cancelSendImage();
|
||||
}
|
||||
|
@ -802,6 +806,9 @@ PeerData *MainWidget::profilePeer() {
|
|||
}
|
||||
|
||||
void MainWidget::showPeerProfile(const PeerData *peer, bool back) {
|
||||
App::wnd()->hideSettings();
|
||||
if (profile && profile->peer() == peer) return;
|
||||
|
||||
dialogs.enableShadow(false);
|
||||
_topBar.enableShadow(false);
|
||||
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);
|
||||
if (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;
|
||||
if (!App::historyRegItem(msgRow)) {
|
||||
msgUpdated(msgRow->history()->peer->id, msgRow);
|
||||
msgUpdated(h->peer->id, msgRow);
|
||||
} else {
|
||||
msgRow->destroy();
|
||||
history.peerMessagesUpdated();
|
||||
|
@ -1668,14 +1690,27 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
|||
if (user) {
|
||||
user->setPhoto(d.vphoto);
|
||||
user->photo->load();
|
||||
if (false && !d.vprevious.v && 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 (d.vprevious.v) {
|
||||
user->photosCount = -1;
|
||||
user->photos.clear();
|
||||
} else {
|
||||
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::wnd()) App::wnd()->mediaOverviewUpdated(user);
|
||||
}
|
||||
} break;
|
||||
|
||||
|
|
|
@ -141,6 +141,7 @@ public:
|
|||
QRect historyRect() const;
|
||||
|
||||
void confirmSendImage(const ReadyLocalMedia &img);
|
||||
void confirmSendImageUncompressed();
|
||||
void cancelSendImage();
|
||||
|
||||
void destroyData();
|
||||
|
|
|
@ -19,32 +19,289 @@ Copyright (c) 2014 John Preston, https://tdesktop.com
|
|||
#include "lang.h"
|
||||
|
||||
#include "mediaview.h"
|
||||
#include "mainwidget.h"
|
||||
#include "window.h"
|
||||
#include "application.h"
|
||||
#include "gui/filedialog.h"
|
||||
|
||||
MediaView::MediaView() : QWidget(App::wnd()),
|
||||
_photo(0), _maxWidth(0), _maxHeight(0), _x(0), _y(0), _w(0) {
|
||||
_photo(0), _leftNavVisible(false), _rightNavVisible(false), _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) {
|
||||
setWindowFlags(Qt::FramelessWindowHint | Qt::BypassWindowManagerHint | Qt::Tool | Qt::NoDropShadowWindowHint);
|
||||
moveToScreen();
|
||||
setAttribute(Qt::WA_NoSystemBackground, true);
|
||||
setAttribute(Qt::WA_TranslucentBackground, true);
|
||||
setMouseTracking(true);
|
||||
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() {
|
||||
QPoint wndCenter(App::wnd()->x() + App::wnd()->width() / 2, App::wnd()->y() + App::wnd()->height() / 2);
|
||||
QRect geom = QDesktopWidget().screenGeometry(wndCenter);
|
||||
_avail = QDesktopWidget().availableGeometry(wndCenter);
|
||||
if (geom != geometry()) {
|
||||
setGeometry(geom);
|
||||
}
|
||||
_maxWidth = width() - 2 * st::medviewNavBarWidth;
|
||||
_maxHeight = height() - st::medviewTopSkip - st::medviewBottomSkip;
|
||||
if (!geom.contains(_avail)) {
|
||||
_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;
|
||||
_opaqueRect = opaque;
|
||||
MTP::clearLoaderPriorities();
|
||||
_photo->full->load();
|
||||
_full = false;
|
||||
_current = QPixmap();
|
||||
_w = photo->full->width();
|
||||
_down = OverNone;
|
||||
int h = photo->full->height();
|
||||
switch (cScale()) {
|
||||
case dbisOneAndQuarter: _w = qRound(float64(_w) * 1.25 - 0.01); h = qRound(float64(h) * 1.25 - 0.01); break;
|
||||
|
@ -59,8 +316,10 @@ void MediaView::showPhoto(PhotoData *photo, const QRect &opaque) {
|
|||
_w = qRound(_w * _maxHeight / float64(h));
|
||||
h = _maxHeight;
|
||||
}
|
||||
_x = (width() - _w) / 2;
|
||||
_y = (height() - h) / 2;
|
||||
_x = _avail.x() + (_avail.width() - _w) / 2;
|
||||
_y = _avail.y() + (_avail.height() - h) / 2;
|
||||
_from = App::user(_photo->user);
|
||||
updateControls();
|
||||
if (isHidden()) {
|
||||
moveToScreen();
|
||||
#ifdef Q_OS_WIN
|
||||
|
@ -75,32 +334,539 @@ void MediaView::showPhoto(PhotoData *photo, const QRect &opaque) {
|
|||
#endif
|
||||
show();
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
void MediaView::paintEvent(QPaintEvent *e) {
|
||||
QPainter p(this);
|
||||
|
||||
QRect r(e->rect());
|
||||
|
||||
QPainter::CompositionMode m = p.compositionMode();
|
||||
p.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
|
||||
// main bg
|
||||
p.setOpacity(st::medviewLightOpacity);
|
||||
p.fillRect(QRect(0, 0, st::medviewNavBarWidth, height()), st::black->b);
|
||||
p.fillRect(QRect(width() - st::medviewNavBarWidth, 0, st::medviewNavBarWidth, height()), st::black->b);
|
||||
p.fillRect(QRect(st::medviewNavBarWidth, 0, width() - 2 * st::medviewNavBarWidth, height()), st::black->b);
|
||||
QRect r_bg(st::medviewNavBarWidth, 0, width() - 2 * st::medviewNavBarWidth, height());
|
||||
if (r_bg.intersects(r)) p.fillRect(r_bg.intersected(r), st::black->b);
|
||||
|
||||
// left nav bar bg
|
||||
if (_leftNav.intersects(r)) {
|
||||
if (_leftNavVisible) {
|
||||
float64 o = overLevel(OverLeftNav);
|
||||
p.setOpacity(o * st::medviewDarkOpacity + (1 - o) * st::medviewLightOpacity);
|
||||
p.fillRect(_leftNav.intersected(r), st::black->b);
|
||||
} else {
|
||||
p.setOpacity(st::medviewLightOpacity);
|
||||
p.fillRect(_leftNav.intersected(r), st::black->b);
|
||||
}
|
||||
}
|
||||
|
||||
// right nav bar
|
||||
if (_rightNav.intersects(r)) {
|
||||
if (_rightNavVisible) {
|
||||
float64 o = overLevel(OverRightNav);
|
||||
p.setOpacity(o * st::medviewDarkOpacity + (1 - o) * st::medviewLightOpacity);
|
||||
p.fillRect(_rightNav.intersected(r), st::black->b);
|
||||
} else {
|
||||
p.setOpacity(st::medviewLightOpacity);
|
||||
p.fillRect(_rightNav.intersected(r), st::black->b);
|
||||
}
|
||||
}
|
||||
|
||||
p.setCompositionMode(m);
|
||||
|
||||
// header
|
||||
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) {
|
||||
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)) {
|
||||
float64 o = overLevel(OverLeftNav);
|
||||
p.setOpacity(o * st::medviewDarkNav + (1 - o) * st::medviewLightNav);
|
||||
p.drawPixmap(p_left, App::sprite(), st::medviewLeft);
|
||||
}
|
||||
}
|
||||
|
||||
// right nav bar
|
||||
if (_rightNavVisible) {
|
||||
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)) {
|
||||
float64 o = overLevel(OverRightNav);
|
||||
p.setOpacity(o * st::medviewDarkNav + (1 - o) * st::medviewLightNav);
|
||||
p.drawPixmap(p_right, App::sprite(), st::medviewRight);
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
if (e->key() == Qt::Key_Escape) {
|
||||
App::wnd()->layerHidden();
|
||||
if (!_menu && e->key() == Qt::Key_Escape) {
|
||||
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) {
|
||||
updateOver(e->pos());
|
||||
if (_menu || !_receiveMouse) return;
|
||||
|
||||
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
|
||||
|
||||
class MediaView : public QWidget {
|
||||
class MediaView : public QWidget, public RPCSender, public Animated {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
@ -28,16 +28,96 @@ public:
|
|||
|
||||
void keyPressEvent(QKeyEvent *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 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:
|
||||
|
||||
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;
|
||||
PhotoData *_photo;
|
||||
QRect _opaqueRect;
|
||||
QRect _avail, _leftNav, _rightNav, _nameNav, _dateNav;
|
||||
bool _leftNavVisible, _rightNavVisible;
|
||||
QString _dateText;
|
||||
|
||||
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) {
|
||||
PhotoData *ph = App::photo(_peerChat->photoId);
|
||||
if (ph->date) {
|
||||
_photoLink = TextLinkPtr(new PhotoLink(ph));
|
||||
_photoLink = TextLinkPtr(new PhotoLink(ph, _peer));
|
||||
}
|
||||
} else {
|
||||
_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)));
|
||||
PhotoData *userPhoto = _peerUser->photoId ? App::photo(_peerUser->photoId) : 0;
|
||||
if (userPhoto && userPhoto->date) {
|
||||
_photoLink = TextLinkPtr(new PhotoLink(userPhoto));
|
||||
_photoLink = TextLinkPtr(new PhotoLink(userPhoto, _peer));
|
||||
} else {
|
||||
_photoLink = TextLinkPtr();
|
||||
}
|
||||
|
@ -249,7 +249,7 @@ void ProfileInner::peerUpdated(PeerData *data) {
|
|||
} else {
|
||||
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) {
|
||||
_nameCache = _peer->name;
|
||||
_nameText.setText(st::profileNameFont, _nameCache, _textNameOptions);
|
||||
|
|
|
@ -155,7 +155,7 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : QWidget(parent),
|
|||
if (_self) {
|
||||
_nameText.setText(st::setNameFont, _nameCache, _textNameOptions);
|
||||
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));
|
||||
|
||||
connect(App::main(), SIGNAL(peerPhotoChanged(PeerData *)), this, SLOT(peerUpdated(PeerData *)));
|
||||
|
@ -257,7 +257,7 @@ void SettingsInner::peerUpdated(PeerData *data) {
|
|||
if (_self->photoId) {
|
||||
PhotoData *selfPhoto = App::photo(_self->photoId);
|
||||
if (selfPhoto->date) {
|
||||
_photoLink = TextLinkPtr(new PhotoLink(selfPhoto));
|
||||
_photoLink = TextLinkPtr(new PhotoLink(selfPhoto, _self));
|
||||
} else {
|
||||
_photoLink = TextLinkPtr();
|
||||
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)));
|
||||
PhotoData *selfPhoto = _self->photoId ? App::photo(_self->photoId) : 0;
|
||||
if (selfPhoto && selfPhoto->date) {
|
||||
_photoLink = TextLinkPtr(new PhotoLink(selfPhoto));
|
||||
_photoLink = TextLinkPtr(new PhotoLink(selfPhoto, _self));
|
||||
} else {
|
||||
_photoLink = TextLinkPtr();
|
||||
}
|
||||
|
|
|
@ -336,7 +336,7 @@ NotifyWindow::~NotifyWindow() {
|
|||
}
|
||||
|
||||
Window::Window(QWidget *parent) : PsMainWindow(parent),
|
||||
intro(0), main(0), settings(0), layer(0), layerBG(0), _topWidget(0),
|
||||
intro(0), main(0), settings(0), layerBG(0), _topWidget(0),
|
||||
_connecting(0), _tempDeleter(0), _tempDeleterThread(0), myIcon(QPixmap::fromImage(icon256)), dragging(false), _inactivePress(false), _mediaView(0) {
|
||||
|
||||
if (objectName().isEmpty())
|
||||
|
@ -391,6 +391,10 @@ void Window::init() {
|
|||
psUpdateWorkmode();
|
||||
}
|
||||
|
||||
QWidget *Window::filedialogParent() {
|
||||
return (_mediaView && _mediaView->isVisible()) ? (QWidget*)_mediaView : (QWidget*)this;
|
||||
}
|
||||
|
||||
void Window::clearWidgets() {
|
||||
layerHidden();
|
||||
if (settings) {
|
||||
|
@ -547,29 +551,23 @@ SettingsWidget *Window::settingsWidget() {
|
|||
}
|
||||
|
||||
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) {
|
||||
layerHidden();
|
||||
_mediaView->showPhoto(photo, QRect());
|
||||
_mediaView->showPhoto(photo, item);
|
||||
_mediaView->activateWindow();
|
||||
_mediaView->setFocus();
|
||||
// layer = new LayerWidget(this, photo, item);
|
||||
}
|
||||
|
||||
PhotoData *Window::photoShown() {
|
||||
return layer ? layer->photoShown() : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
void Window::showVideo(const VideoOpenLink *lnk, HistoryItem *item) {
|
||||
void Window::showPhoto(PhotoData *photo, PeerData *peer) {
|
||||
layerHidden();
|
||||
VideoData *video = App::video(lnk->video());
|
||||
layer = new LayerWidget(this, video, item);
|
||||
_mediaView->showPhoto(photo, peer);
|
||||
_mediaView->activateWindow();
|
||||
_mediaView->setFocus();
|
||||
}
|
||||
/**/
|
||||
|
||||
void Window::showLayer(LayeredWidget *w) {
|
||||
layerHidden();
|
||||
layerBG = new BackgroundWidget(this, w);
|
||||
|
@ -594,8 +592,6 @@ void Window::hideConnecting() {
|
|||
}
|
||||
|
||||
void Window::replaceLayer(LayeredWidget *w) {
|
||||
if (layer) layer->deleteLater();
|
||||
layer = 0;
|
||||
if (layerBG) {
|
||||
layerBG->replaceInner(w);
|
||||
} else {
|
||||
|
@ -607,13 +603,13 @@ void Window::hideLayer() {
|
|||
if (layerBG) {
|
||||
layerBG->onClose();
|
||||
}
|
||||
if (layer) {
|
||||
layer->startHide();
|
||||
if (_mediaView && !_mediaView->isHidden()) {
|
||||
_mediaView->hide();
|
||||
}
|
||||
}
|
||||
|
||||
bool Window::layerShown() {
|
||||
return !!layer || !!layerBG || !!_topWidget;
|
||||
return !!layerBG || !!_topWidget;
|
||||
}
|
||||
|
||||
bool Window::historyIsActive(int state) const {
|
||||
|
@ -627,11 +623,9 @@ void Window::checkHistoryActivation(int state) {
|
|||
}
|
||||
|
||||
void Window::layerHidden() {
|
||||
if (layer) layer->deleteLater();
|
||||
layer = 0;
|
||||
if (layerBG) layerBG->deleteLater();
|
||||
layerBG = 0;
|
||||
if (_mediaView) _mediaView->hide();
|
||||
if (_mediaView && !_mediaView->isHidden()) _mediaView->hide();
|
||||
if (main) main->setInnerFocus();
|
||||
}
|
||||
|
||||
|
@ -685,7 +679,7 @@ HitTestType Window::hitTest(const QPoint &p) const {
|
|||
}
|
||||
}
|
||||
HitTestType titleTest = title->hitTest(p - title->geometry().topLeft());
|
||||
if (titleTest && (!layer || titleTest != HitTestCaption)) {
|
||||
if (titleTest) {
|
||||
return titleTest;
|
||||
} else if (x >= 0 && y >= 0 && x < w && y < h) {
|
||||
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) {
|
||||
if (was == layerBG) {
|
||||
layerBG = 0;
|
||||
|
@ -841,7 +828,6 @@ void Window::noBox(BackgroundWidget *was) {
|
|||
|
||||
void Window::fixOrder() {
|
||||
title->raise();
|
||||
if (layer) layer->raise();
|
||||
if (layerBG) layerBG->raise();
|
||||
if (_topWidget) _topWidget->raise();
|
||||
if (_connecting) _connecting->raise();
|
||||
|
@ -890,7 +876,6 @@ TitleWidget *Window::getTitle() {
|
|||
|
||||
void Window::resizeEvent(QResizeEvent *e) {
|
||||
title->setGeometry(QRect(0, 0, width(), st::titleHeight + st::titleShadow));
|
||||
if (layer) layer->resize(width(), height());
|
||||
if (layerBG) layerBG->resize(width(), height());
|
||||
if (_connecting) _connecting->setGeometry(0, height() - _connecting->height(), _connecting->width(), _connecting->height());
|
||||
emit resized(QSize(width(), height() - st::titleHeight));
|
||||
|
@ -1206,7 +1191,7 @@ void Window::notifyUpdateAllPhotos() {
|
|||
(*i)->updatePeerPhoto();
|
||||
}
|
||||
}
|
||||
if (_mediaView) _mediaView->update();
|
||||
if (_mediaView) _mediaView->updateControls();
|
||||
}
|
||||
|
||||
void Window::notifyUpdateAll() {
|
||||
|
@ -1231,6 +1216,7 @@ QImage Window::iconLarge() const {
|
|||
}
|
||||
|
||||
void Window::sendPaths() {
|
||||
if (_mediaView && !_mediaView->isHidden()) _mediaView->hide();
|
||||
if (settings) {
|
||||
hideSettings();
|
||||
} 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() {
|
||||
notifyClearFast();
|
||||
delete _tempDeleter;
|
||||
|
@ -1253,6 +1249,5 @@ Window::~Window() {
|
|||
delete trayIconMenu;
|
||||
delete intro;
|
||||
delete main;
|
||||
delete layer;
|
||||
delete settings;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@ class TitleWidget;
|
|||
class IntroWidget;
|
||||
class MainWidget;
|
||||
class SettingsWidget;
|
||||
class LayerWidget;
|
||||
class BackgroundWidget;
|
||||
class LayeredWidget;
|
||||
|
||||
|
@ -135,6 +134,8 @@ public:
|
|||
|
||||
void init();
|
||||
|
||||
QWidget *filedialogParent();
|
||||
|
||||
bool eventFilter(QObject *obj, QEvent *evt);
|
||||
|
||||
void inactivePress(bool inactive);
|
||||
|
@ -173,9 +174,8 @@ public:
|
|||
|
||||
void hideSettings(bool fast = false);
|
||||
void showPhoto(const PhotoLink *lnk, HistoryItem *item = 0);
|
||||
void showPhoto(PhotoData *photo, HistoryItem *item = 0);
|
||||
// void showVideo(const VideoOpenLink *lnk, HistoryItem *item = 0);
|
||||
PhotoData *photoShown();
|
||||
void showPhoto(PhotoData *photo, HistoryItem *item);
|
||||
void showPhoto(PhotoData *photo, PeerData *item);
|
||||
void showLayer(LayeredWidget *w);
|
||||
void replaceLayer(LayeredWidget *w);
|
||||
void hideLayer();
|
||||
|
@ -194,7 +194,6 @@ public:
|
|||
void noIntro(IntroWidget *was);
|
||||
void noSettings(SettingsWidget *was);
|
||||
void noMain(MainWidget *was);
|
||||
void noLayer(LayerWidget *was);
|
||||
void noBox(BackgroundWidget *was);
|
||||
|
||||
void topWidget(QWidget *w);
|
||||
|
@ -228,6 +227,9 @@ public:
|
|||
|
||||
void sendPaths();
|
||||
|
||||
void mediaOverviewUpdated(PeerData *peer);
|
||||
void changingMsgId(HistoryItem *row, MsgId newId);
|
||||
|
||||
public slots:
|
||||
|
||||
void checkHistoryActivation(int state = -1);
|
||||
|
@ -263,7 +265,6 @@ private:
|
|||
IntroWidget *intro;
|
||||
MainWidget *main;
|
||||
SettingsWidget *settings;
|
||||
LayerWidget *layer;
|
||||
BackgroundWidget *layerBG;
|
||||
|
||||
QWidget *_topWidget; // temp hack for CountrySelect
|
||||
|
|
Loading…
Add table
Reference in a new issue