context bots started, all callbacks done by pointers

This commit is contained in:
John Preston 2015-12-29 00:20:04 +03:00
parent 43e173567f
commit 77228d358d
22 changed files with 416 additions and 237 deletions

View File

@ -1430,9 +1430,10 @@ namespace App {
return ::self;
}
PeerData *peerByName(const QString &username) {
PeerData *peerByName(const QStringRef &username) {
QStringRef uname(username.trimmed());
for (PeersData::const_iterator i = peersData.cbegin(), e = peersData.cend(); i != e; ++i) {
if (!i.value()->userName().compare(username.trimmed(), Qt::CaseInsensitive)) {
if (!i.value()->userName().compare(uname, Qt::CaseInsensitive)) {
return i.value()->asUser();
}
}
@ -2471,10 +2472,6 @@ namespace App {
::gifItems.remove(reader);
}
const GifItems &gifItems() {
return ::gifItems;
}
void stopGifItems() {
if (!::gifItems.isEmpty()) {
GifItems gifs = ::gifItems;

View File

@ -132,7 +132,10 @@ namespace App {
ChatData *chat(int32 chat_id);
ChannelData *channel(int32 channel_id);
UserData *self();
PeerData *peerByName(const QString &username);
PeerData *peerByName(const QStringRef &username);
inline PeerData *peerByName(const QString &username) {
return peerByName(username.midRef(0));
}
QString peerName(const PeerData *peer, bool forDialogs = false);
PhotoData *photo(const PhotoId &photo);
PhotoData *photoSet(const PhotoId &photo, PhotoData *convert, const uint64 &access, int32 date, const ImagePtr &thumb, const ImagePtr &medium, const ImagePtr &full);
@ -240,7 +243,6 @@ namespace App {
void regGifItem(ClipReader *reader, HistoryItem *item);
void unregGifItem(ClipReader *reader);
const GifItems &gifItems();
void stopGifItems();
void regMuted(PeerData *peer, int32 changeIn);

View File

@ -107,18 +107,6 @@ namespace Ui {
return false;
}
void clipRepaint(ClipReader *reader) {
const GifItems &items(App::gifItems());
GifItems::const_iterator it = items.constFind(reader);
if (it != items.cend()) {
if (reader->currentDisplayed()) {
return;
}
Ui::repaintHistoryItem(it.value());
}
if (Window *w = App::wnd()) w->ui_clipRepaint(reader);
}
void repaintHistoryItem(const HistoryItem *item) {
if (!item) return;
if (MainWidget *m = App::main()) m->ui_repaintHistoryItem(item);
@ -168,35 +156,6 @@ namespace Notify {
if (MainWidget *m = App::main()) m->notify_clipStopperHidden(type);
}
void clipReinit(ClipReader *reader) {
const GifItems &items(App::gifItems());
GifItems::const_iterator it = items.constFind(reader);
if (it != items.cend()) {
HistoryItem *item = it.value();
bool stopped = false;
if (reader->paused()) {
if (MainWidget *m = App::main()) {
if (!m->isItemVisible(item)) { // stop animation if it is not visible
if (HistoryMedia *media = item->getMedia()) {
media->stopInline(item);
if (DocumentData *document = media->getDocument()) { // forget data from memory
document->forget();
}
stopped = true;
}
}
}
}
if (!stopped) {
item->initDimensions(); // can delete reader and items entry it
Notify::historyItemResized(item);
Notify::historyItemLayoutChanged(item);
}
}
if (Window *w = App::wnd()) w->notify_clipReinit(reader);
}
void historyItemResized(const HistoryItem *item, bool scrollToIt) {
if (MainWidget *m = App::main()) m->notify_historyItemResized(item, scrollToIt);
}

View File

@ -48,8 +48,6 @@ namespace Ui { // openssl doesn't allow me to use UI :(
bool isMediaViewShown();
bool isGifBeingChosen();
void clipRepaint(ClipReader *reader);
void repaintHistoryItem(const HistoryItem *item);
void repaintSavedGif(const LayoutSavedGif *layout);
bool isSavedGifVisible(const LayoutSavedGif *reader);
@ -86,8 +84,6 @@ namespace Notify {
void clipStopperHidden(ClipStopperType type);
void clipReinit(ClipReader *reader);
void historyItemResized(const HistoryItem *item, bool scrollToIt = false);
inline void historyItemsResized() {
historyItemResized(0);

View File

@ -106,7 +106,7 @@ namespace anim {
void Animation::start() {
if (!_manager) return;
_cb->start();
_cb.start();
_manager->start(this);
_animating = true;
}
@ -179,14 +179,8 @@ void AnimationManager::timeout() {
}
}
void AnimationManager::clipReinit(ClipReader *reader, qint32 threadIndex) {
ClipReader::callback(reader, threadIndex, ClipReaderReinit);
Notify::clipReinit(reader);
}
void AnimationManager::clipRepaint(ClipReader *reader, qint32 threadIndex) {
ClipReader::callback(reader, threadIndex, ClipReaderRepaint);
Ui::clipRepaint(reader);
void AnimationManager::clipCallback(ClipReader *reader, qint32 threadIndex, qint32 notification) {
ClipReader::callback(reader, threadIndex, ClipReaderNotification(notification));
}
QPixmap _prepareFrame(const ClipFrameRequest &request, const QImage &original, QImage &cache, bool hasAlpha) {
@ -225,7 +219,7 @@ QPixmap _prepareFrame(const ClipFrameRequest &request, const QImage &original, Q
return QPixmap::fromImage(original, Qt::ColorOnly);
}
ClipReader::ClipReader(const FileLocation &location, const QByteArray &data, Callback *cb)
ClipReader::ClipReader(const FileLocation &location, const QByteArray &data, Callback::Creator cb)
: _cb(cb)
, _state(ClipReading)
, _width(0)
@ -257,7 +251,7 @@ ClipReader::ClipReader(const FileLocation &location, const QByteArray &data, Cal
void ClipReader::callback(ClipReader *reader, int32 threadIndex, ClipReaderNotification notification) {
// check if reader is not deleted already
if (_clipManagers.size() > threadIndex && _clipManagers.at(threadIndex)->carries(reader)) {
if (reader->_cb) reader->_cb->call(notification);
reader->_cb.call(notification);
}
}
@ -351,8 +345,6 @@ void ClipReader::error() {
ClipReader::~ClipReader() {
stop();
delete _cb;
setBadPointer(_cb);
}
class ClipReaderImplementation {
@ -448,8 +440,7 @@ public:
}
~QtGifReaderImplementation() {
delete _reader;
setBadPointer(_reader);
deleteAndMark(_reader);
}
private:
@ -917,8 +908,8 @@ public:
~ClipReaderPrivate() {
stop();
setBadPointer(_location);
setBadPointer(_implementation);
deleteAndMark(_location);
deleteAndMark(_implementation);
_data.clear();
}
@ -958,8 +949,7 @@ ClipReadManager::ClipReadManager(QThread *thread) : _processingInThread(0), _nee
_timer.moveToThread(thread);
connect(&_timer, SIGNAL(timeout()), this, SLOT(process()));
connect(this, SIGNAL(reinit(ClipReader*,qint32)), _manager, SLOT(clipReinit(ClipReader*,qint32)));
connect(this, SIGNAL(repaint(ClipReader*,qint32)), _manager, SLOT(clipRepaint(ClipReader*,qint32)));
connect(this, SIGNAL(callback(ClipReader*,qint32,qint32)), _manager, SLOT(clipCallback(ClipReader*,qint32,qint32)));
}
void ClipReadManager::append(ClipReader *reader, const FileLocation &location, const QByteArray &data) {
@ -995,7 +985,7 @@ bool ClipReadManager::handleProcessResult(ClipReaderPrivate *reader, ClipProcess
if (result == ClipProcessError) {
if (it != _readerPointers.cend()) {
it.key()->error();
emit reinit(it.key(), it.key()->threadIndex());
emit callback(it.key(), it.key()->threadIndex(), ClipReaderReinit);
_readerPointers.erase(it);
it = _readerPointers.end();
@ -1025,9 +1015,9 @@ bool ClipReadManager::handleProcessResult(ClipReaderPrivate *reader, ClipProcess
it.key()->_currentOriginal = reader->_currentOriginal;
it.key()->_currentDisplayed.set(false);
if (result == ClipProcessReinit) {
emit reinit(it.key(), it.key()->threadIndex());
emit callback(it.key(), it.key()->threadIndex(), ClipReaderReinit);
} else if (result == ClipProcessRepaint) {
emit repaint(it.key(), it.key()->threadIndex());
emit callback(it.key(), it.key()->threadIndex(), ClipReaderRepaint);
}
}
return true;

View File

@ -198,28 +198,44 @@ namespace anim {
class Animation;
class AnimationImplementation {
public:
virtual void start() {}
virtual void step(Animation *a, uint64 ms, bool timer) = 0;
virtual ~AnimationImplementation() {}
};
class AnimationCreator {
public:
AnimationCreator(AnimationImplementation *ptr) : _ptr(ptr) {}
AnimationCreator(const AnimationCreator &other) : _ptr(other.create()) {}
AnimationImplementation *create() const { return exchange(_ptr); }
~AnimationCreator() { deleteAndMark(_ptr); }
private:
AnimationCreator &operator=(const AnimationCreator &other);
mutable AnimationImplementation *_ptr;
};
class AnimationCallbacks {
public:
virtual void start() {
}
virtual void step(Animation *a, uint64 ms, bool timer) = 0;
virtual ~AnimationCallbacks() {
}
AnimationCallbacks(const AnimationCreator &creator) : _implementation(creator.create()) {}
void start() { _implementation->start(); }
void step(Animation *a, uint64 ms, bool timer) { _implementation->step(a, ms, timer); }
~AnimationCallbacks() { deleteAndMark(_implementation); }
private:
AnimationCallbacks(const AnimationCallbacks &other);
AnimationCallbacks &operator=(const AnimationCallbacks &other);
AnimationImplementation *_implementation;
};
class Animation {
public:
Animation(AnimationCallbacks *cb) : _cb(cb), _animating(false) {
Animation(AnimationCreator cb) : _cb(cb), _animating(false) {
}
void start();
void stop();
void step(uint64 ms, bool timer = false) {
_cb->step(this, ms, timer);
_cb.step(this, ms, timer);
}
void step() {
@ -232,20 +248,16 @@ public:
~Animation() {
if (_animating) stop();
delete _cb;
}
private:
Animation(const Animation &);
Animation &operator=(const Animation &);
AnimationCallbacks *_cb;
AnimationCallbacks _cb;
bool _animating;
};
template <typename Type>
class AnimationCallbacksRelative : public AnimationCallbacks {
class AnimationCallbacksRelative : public AnimationImplementation {
public:
typedef void (Type::*Method)(float64, bool);
@ -267,12 +279,12 @@ private:
};
template <typename Type>
AnimationCallbacks *animation(Type *obj, typename AnimationCallbacksRelative<Type>::Method method) {
return new AnimationCallbacksRelative<Type>(obj, method);
AnimationCreator animation(Type *obj, typename AnimationCallbacksRelative<Type>::Method method) {
return AnimationCreator(new AnimationCallbacksRelative<Type>(obj, method));
}
template <typename Type>
class AnimationCallbacksAbsolute : public AnimationCallbacks {
class AnimationCallbacksAbsolute : public AnimationImplementation {
public:
typedef void (Type::*Method)(uint64, bool);
@ -289,12 +301,12 @@ private:
};
template <typename Type>
AnimationCallbacks *animation(Type *obj, typename AnimationCallbacksAbsolute<Type>::Method method) {
return new AnimationCallbacksAbsolute<Type>(obj, method);
AnimationCreator animation(Type *obj, typename AnimationCallbacksAbsolute<Type>::Method method) {
return AnimationCreator(new AnimationCallbacksAbsolute<Type>(obj, method));
}
template <typename Type, typename Param>
class AnimationCallbacksRelativeWithParam : public AnimationCallbacks {
class AnimationCallbacksRelativeWithParam : public AnimationImplementation {
public:
typedef void (Type::*Method)(Param, float64, bool);
@ -317,12 +329,12 @@ private:
};
template <typename Type, typename Param>
AnimationCallbacks *animation(Param param, Type *obj, typename AnimationCallbacksRelativeWithParam<Type, Param>::Method method) {
return new AnimationCallbacksRelativeWithParam<Type, Param>(param, obj, method);
AnimationCreator animation(Param param, Type *obj, typename AnimationCallbacksRelativeWithParam<Type, Param>::Method method) {
return AnimationCreator(new AnimationCallbacksRelativeWithParam<Type, Param>(param, obj, method));
}
template <typename Type, typename Param>
class AnimationCallbacksAbsoluteWithParam : public AnimationCallbacks {
class AnimationCallbacksAbsoluteWithParam : public AnimationImplementation {
public:
typedef void (Type::*Method)(Param, uint64, bool);
@ -340,15 +352,15 @@ private:
};
template <typename Type, typename Param>
AnimationCallbacks *animation(Param param, Type *obj, typename AnimationCallbacksAbsoluteWithParam<Type, Param>::Method method) {
return new AnimationCallbacksAbsoluteWithParam<Type, Param>(param, obj, method);
AnimationCreator animation(Param param, Type *obj, typename AnimationCallbacksAbsoluteWithParam<Type, Param>::Method method) {
return AnimationCreator(new AnimationCallbacksAbsoluteWithParam<Type, Param>(param, obj, method));
}
template <typename AnimType>
class SimpleAnimation {
public:
typedef Function<void> Callbacks;
typedef Function<void> Callback;
SimpleAnimation() : _data(0) {
}
@ -373,11 +385,10 @@ public:
return animating(ms) ? current() : def;
}
void setup(const typename AnimType::Type &from, Callbacks *update) {
void setup(const typename AnimType::Type &from, Callback::Creator update) {
if (!_data) {
_data = new Data(from, update, animation(this, &SimpleAnimation<AnimType>::step));
} else {
delete update;
_data->a = AnimType(from, from);
}
}
@ -392,26 +403,21 @@ public:
}
~SimpleAnimation() {
delete _data;
setBadPointer(_data);
deleteAndMark(_data);
}
private:
typedef struct _Data {
_Data(const typename AnimType::Type &from, Callbacks *update, AnimationCallbacks *acb)
_Data(const typename AnimType::Type &from, Callback::Creator update, AnimationCreator acb)
: a(from, from)
, _a(acb)
, update(update)
, duration(0)
, transition(anim::linear) {
}
~_Data() {
delete update;
setBadPointer(update);
}
AnimType a;
Animation _a;
Callbacks *update;
Callback update;
float64 duration;
anim::transition transition;
} Data;
@ -426,7 +432,7 @@ private:
_data->a.update(dt, _data->transition);
}
if (timer) {
_data->update->call();
_data->update.call();
}
if (!_data->_a.animating()) {
delete _data;
@ -456,8 +462,7 @@ public:
public slots:
void timeout();
void clipReinit(ClipReader *reader, qint32 threadIndex);
void clipRepaint(ClipReader *reader, qint32 threadIndex);
void clipCallback(ClipReader *reader, qint32 threadIndex, qint32 notification);
private:
typedef QMap<Animation*, NullType> AnimatingObjects;
@ -519,7 +524,7 @@ public:
typedef Function1<void, ClipReaderNotification> Callback;
ClipReader(const FileLocation &location, const QByteArray &data, Callback *cb = 0);
ClipReader(const FileLocation &location, const QByteArray &data, Callback::Creator cb);
static void callback(ClipReader *reader, int32 threadIndex, ClipReaderNotification notification); // reader can be deleted
void setAutoplay() {
@ -560,7 +565,7 @@ public:
private:
Callback *_cb;
Callback _cb;
ClipState _state;
@ -612,8 +617,7 @@ signals:
void processDelayed();
void reinit(ClipReader *reader, qint32 threadIndex);
void repaint(ClipReader *reader, qint32 threadIndex);
void callback(ClipReader *reader, qint32 threadIndex, qint32 notification);
public slots:

View File

@ -252,10 +252,43 @@ EmojiPtr FlatTextarea::getSingleEmoji() const {
return 0;
}
void FlatTextarea::getMentionHashtagBotCommandStart(QString &start) const {
void FlatTextarea::getMentionHashtagBotCommandStart(QString &start, UserData *&contextBot, QString &lookedUpUsername) const {
int32 pos = textCursor().position();
if (textCursor().anchor() != pos) return;
// check context bot query
const QString &text(getLastText());
int32 size = text.size();
if (size > 2 && text.at(0) == '@' && text.at(1).isLetter()) {
int32 usernameStart = 1, usernameLength = 1;
for (int32 i = usernameStart + 1, l = text.size(); i < l; ++i) {
if (text.at(i).isLetterOrNumber() || text.at(i).unicode() == '_') {
++usernameLength;
continue;
}
if (!text.at(i).isSpace()) {
usernameLength = 0;
}
break;
}
if (usernameLength) {
UserData *bot = 0;
if (contextBot && !contextBot->username.compare(text.midRef(1, usernameLength))) {
bot = contextBot;
} else {
PeerData *peer = App::peerByName(text.midRef(1, usernameLength));
if (peer) {
if (peer->isUser()) {
bot = peer->asUser();
} else {
}
}
}
}
}
// check mention / hashtag / bot command
QTextDocument *doc(document());
QTextBlock block = doc->findBlock(pos);
for (QTextBlock::Iterator iter = block.begin(); !iter.atEnd(); ++iter) {

View File

@ -24,6 +24,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
#include "style.h"
#include "animation.h"
class UserData;
class FlatTextarea : public QTextEdit {
Q_OBJECT
T_WIDGET
@ -62,7 +63,7 @@ public:
QSize minimumSizeHint() const;
EmojiPtr getSingleEmoji() const;
void getMentionHashtagBotCommandStart(QString &start) const;
void getMentionHashtagBotCommandStart(QString &start, UserData *&contextBot, QString &lookedUpUsername) const;
void removeSingleEmoji();
bool hasText() const;

View File

@ -2966,6 +2966,42 @@ void HistoryItem::setId(MsgId newId) {
id = newId;
}
void HistoryItem::clipCallback(ClipReaderNotification notification) {
HistoryMedia *media = getMedia();
if (!media) return;
ClipReader *reader = media ? media->getClipReader() : 0;
if (!reader) return;
switch (notification) {
case ClipReaderReinit: {
bool stopped = false;
if (reader->paused()) {
if (MainWidget *m = App::main()) {
if (!m->isItemVisible(this)) { // stop animation if it is not visible
media->stopInline(this);
if (DocumentData *document = media->getDocument()) { // forget data from memory
document->forget();
}
stopped = true;
}
}
}
if (!stopped) {
initDimensions();
Notify::historyItemResized(this);
Notify::historyItemLayoutChanged(this);
}
} break;
case ClipReaderRepaint: {
if (!reader->currentDisplayed()) {
Ui::repaintHistoryItem(this);
}
} break;
}
}
HistoryItem::~HistoryItem() {
App::historyUnregItem(this);
if (id < 0 && App::uploader()) {
@ -2981,14 +3017,14 @@ HistoryItem *regItem(HistoryItem *item) {
return item;
}
RadialAnimation::RadialAnimation(AnimationCallbacks *callbacks)
RadialAnimation::RadialAnimation(AnimationCreator creator)
: _firstStart(0)
, _lastStart(0)
, _lastTime(0)
, _opacity(0)
, a_arcEnd(0, 0)
, a_arcStart(0, FullArcLength)
, _animation(callbacks) {
, _animation(creator) {
}
@ -3171,10 +3207,7 @@ void HistoryFileMedia::checkAnimationFinished() {
}
HistoryFileMedia::~HistoryFileMedia() {
if (_animation) {
delete _animation;
setBadPointer(_animation);
}
deleteAndMark(_animation);
}
HistoryPhoto::HistoryPhoto(const MTPDphoto &photo, const QString &caption, HistoryItem *parent) : HistoryFileMedia()
@ -4713,7 +4746,7 @@ bool HistoryGif::playInline(HistoryItem *parent) {
if (!cAutoPlayGif()) {
App::stopGifItems();
}
_gif = new ClipReader(_data->location(), _data->data());
_gif = new ClipReader(_data->location(), _data->data(), func(parent, &HistoryItem::clipCallback));
App::regGifItem(_gif, parent);
}
return true;
@ -4734,8 +4767,7 @@ void HistoryGif::stopInline(HistoryItem *parent) {
HistoryGif::~HistoryGif() {
if (gif()) {
App::unregGifItem(_gif);
delete _gif;
setBadPointer(_gif);
deleteAndMark(_gif);
}
}
@ -5518,8 +5550,7 @@ ImagePtr HistoryWebPage::replyPreview() {
}
HistoryWebPage::~HistoryWebPage() {
delete _attach;
setBadPointer(_attach);
deleteAndMark(_attach);
}
namespace {

View File

@ -1022,6 +1022,8 @@ public:
return !out() && !history()->peer->isUser() && !fromChannel();
}
void clipCallback(ClipReaderNotification notification);
virtual ~HistoryItem();
protected:
@ -1072,7 +1074,7 @@ HistoryItem *regItem(HistoryItem *item);
class RadialAnimation {
public:
RadialAnimation(AnimationCallbacks *callbacks);
RadialAnimation(AnimationCreator creator);
float64 opacity() const {
return _opacity;
@ -1141,6 +1143,9 @@ public:
virtual DocumentData *getDocument() {
return 0;
}
virtual ClipReader *getClipReader() {
return 0;
}
virtual bool playInline(HistoryItem *item) {
return false;
@ -1246,7 +1251,7 @@ protected:
virtual bool dataLoaded() const = 0;
struct AnimationData {
AnimationData(AnimationCallbacks *thumbOverCallbacks, AnimationCallbacks *radialCallbacks) : a_thumbOver(0, 0)
AnimationData(AnimationCreator thumbOverCallbacks, AnimationCreator radialCallbacks) : a_thumbOver(0, 0)
, _a_thumbOver(thumbOverCallbacks)
, radial(radialCallbacks) {
}
@ -1589,6 +1594,9 @@ public:
DocumentData *getDocument() {
return _data;
}
ClipReader *getClipReader() {
return gif();
}
bool playInline(HistoryItem *item);
void stopInline(HistoryItem *item);

View File

@ -5288,7 +5288,7 @@ void HistoryWidget::checkMentionDropdown() {
if (!_history || _a_show.animating()) return;
QString start;
_field.getMentionHashtagBotCommandStart(start);
_field.getMentionHashtagBotCommandStart(start, _contextBot, _contextBotUsername);
if (!start.isEmpty()) {
if (start.at(0) == '#' && cRecentWriteHashtags().isEmpty() && cRecentSearchHashtags().isEmpty()) Local::readRecentHashtags();
if (start.at(0) == '@' && _peer->isUser()) return;

View File

@ -761,6 +761,8 @@ private:
CollapseButton _collapseComments;
MentionsDropdown _attachMention;
UserData *_contextBot;
QString _contextBotUsername;
bool isBotStart() const;
bool isBlocked() const;

View File

@ -338,7 +338,11 @@ void StickerPreviewWidget::clipCallback(ClipReaderNotification notification) {
update();
} break;
case ClipReaderRepaint: update(); break;
case ClipReaderRepaint: {
if (gif() && !_gif->currentDisplayed()) {
update();
}
} break;
}
}

View File

@ -260,10 +260,7 @@ void LayoutRadialProgressItem::checkRadialFinished() {
}
LayoutRadialProgressItem::~LayoutRadialProgressItem() {
if (_radial) {
delete _radial;
setBadPointer(_radial);
}
deleteAndMark(_radial);
}
void LayoutAbstractFileItem::setStatusSize(int32 newSize, int32 fullSize, int32 duration, qint64 realDuration) const {
@ -1318,7 +1315,7 @@ void LayoutSavedGif::notify_over(bool over) {
if (!_data->loaded()) {
ensureAnimation();
if (over == !(_state & StateOver)) {
EnsureAnimation(_animation->_a_over, (_state & StateOver) ? 1 : 0, (func(this, &LayoutSavedGif::update)));
EnsureAnimation(_animation->_a_over, (_state & StateOver) ? 1 : 0, func(this, &LayoutSavedGif::update));
_animation->_a_over.start(over ? 1 : 0, st::stickersRowDuration);
}
}
@ -1450,8 +1447,7 @@ void LayoutSavedGif::preload() {
}
LayoutSavedGif::~LayoutSavedGif() {
delete _animation;
setBadPointer(_animation);
deleteAndMark(_animation);
}
void LayoutSavedGif::ensureAnimation() const {
@ -1501,7 +1497,11 @@ void LayoutSavedGif::clipCallback(ClipReaderNotification notification) {
update();
} break;
case ClipReaderRepaint: update(); break;
case ClipReaderRepaint: {
if (gif() && !_gif->currentDisplayed()) {
update();
}
} break;
}
}

View File

@ -517,9 +517,9 @@ private:
void update();
struct AnimationData {
AnimationData(AnimationCallbacks *radialCallbacks)
AnimationData(AnimationCreator creator)
: over(false)
, radial(radialCallbacks) {
, radial(creator) {
}
bool over;
FloatAnimation _a_over;

View File

@ -2454,8 +2454,7 @@ namespace Local {
virtual void readFromStream(QDataStream &stream, quint64 &first, quint64 &second, quint32 &type, QByteArray &data) = 0;
virtual void clearInMap() = 0;
virtual ~AbstractCachedLoadTask() {
delete _result;
setBadPointer(_result);
deleteAndMark(_result);
}
protected:

View File

@ -474,10 +474,8 @@ void MediaView::step_radial(uint64 ms, bool timer) {
}
MediaView::~MediaView() {
delete _gif;
setBadPointer(_gif);
delete _menu;
setBadPointer(_menu);
deleteAndMark(_gif);
deleteAndMark(_menu);
}
void MediaView::showSaveMsgFile() {
@ -603,14 +601,11 @@ void MediaView::onDocClick() {
}
}
void MediaView::ui_clipRepaint(ClipReader *reader) {
if (reader == _gif) {
update(_x, _y, _w, _h);
}
}
void MediaView::clipCallback(ClipReaderNotification notification) {
if (!_gif) return;
void MediaView::notify_clipReinit(ClipReader *reader) {
if (reader == _gif) {
switch (notification) {
case ClipReaderReinit: {
if (HistoryItem *item = App::histItemById(_msgmigrated ? 0 : _channel, _msgid)) {
if (_gif->state() == ClipError) {
_current = QPixmap();
@ -619,6 +614,13 @@ void MediaView::notify_clipReinit(ClipReader *reader) {
} else {
stopGif();
}
} break;
case ClipReaderRepaint: {
if (!_gif->currentDisplayed()) {
update(_x, _y, _w, _h);
}
} break;
}
}
@ -953,7 +955,7 @@ void MediaView::displayDocument(DocumentData *doc, HistoryItem *item) { // empty
if (_doc->dimensions.width() && _doc->dimensions.height()) {
_current = _doc->thumb->pixNoCache(_doc->dimensions.width(), _doc->dimensions.height(), true, true, false, _doc->dimensions.width(), _doc->dimensions.height());
}
_gif = new ClipReader(location, _doc->data());
_gif = new ClipReader(location, _doc->data(), func(this, &MediaView::clipCallback));
}
} else if (location.accessEnable()) {
if (_doc->isAnimation()) {
@ -961,7 +963,7 @@ void MediaView::displayDocument(DocumentData *doc, HistoryItem *item) { // empty
if (_doc->dimensions.width() && _doc->dimensions.height()) {
_current = _doc->thumb->pixNoCache(_doc->dimensions.width(), _doc->dimensions.height(), true, true, false, _doc->dimensions.width(), _doc->dimensions.height());
}
_gif = new ClipReader(location, _doc->data());
_gif = new ClipReader(location, _doc->data(), func(this, &MediaView::clipCallback));
}
} else {
if (QImageReader(location.name()).canRead()) {

View File

@ -71,9 +71,7 @@ public:
void activateControls();
void onDocClick();
void ui_clipRepaint(ClipReader *reader);
void notify_clipReinit(ClipReader *reader);
void clipCallback(ClipReaderNotification notification);
~MediaView();

View File

@ -661,8 +661,7 @@ ImagePtr PhotoData::makeReplyPreview() {
}
PhotoData::~PhotoData() {
delete uploadingData;
setBadPointer(uploadingData);
deleteAndMark(uploadingData);
}
void PhotoLink::onClick(Qt::MouseButton button) const {

View File

@ -20,14 +20,32 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
*/
#pragma once
template <typename Type>
void setBadPointer(Type *&link) {
link = reinterpret_cast<Type*>(0x00000bad);
template <typename T>
void deleteAndMark(T *&link) {
delete link;
link = reinterpret_cast<T*>(0x00000BAD);
}
template <typename T>
T *exchange(T *&ptr) {
T *result = 0;
qSwap(result, ptr);
return result;
}
struct NullType {
};
template <typename T>
class OrderedSet : public QMap<T, NullType> {
public:
void insert(const T &v) {
QMap<T, NullType>::insert(v, NullType());
}
};
//typedef unsigned char uchar; // Qt has uchar
typedef qint16 int16;
typedef quint16 uint16;
@ -473,68 +491,219 @@ static int32 QuarterArcLength = (FullArcLength / 4);
static int32 MinArcLength = (FullArcLength / 360);
static int32 AlmostFullArcLength = (FullArcLength - MinArcLength);
template <typename ReturnType>
template <typename I>
inline void destroyImplementation(I *&ptr) {
if (ptr) {
ptr->destroy();
ptr = 0;
}
deleteAndMark(ptr);
}
template <typename R>
class FunctionImplementation {
public:
virtual R call() = 0;
virtual void destroy() { delete this; }
virtual ~FunctionImplementation() {}
};
template <typename R>
class NullFunctionImplementation : public FunctionImplementation<R> {
public:
virtual R call() { return R(); }
virtual void destroy() {}
static NullFunctionImplementation<R> SharedInstance;
};
template <typename R>
NullFunctionImplementation<R> NullFunctionImplementation<R>::SharedInstance;
template <typename R>
class FunctionCreator {
public:
FunctionCreator(FunctionImplementation<R> *ptr) : _ptr(ptr) {}
FunctionCreator(const FunctionCreator<R> &other) : _ptr(other.create()) {}
FunctionImplementation<R> *create() const { return exchange(_ptr); }
~FunctionCreator() { destroyImplementation(_ptr); }
private:
FunctionCreator<R> &operator=(const FunctionCreator<R> &other);
mutable FunctionImplementation<R> *_ptr;
};
template <typename R>
class Function {
public:
virtual ReturnType call() = 0;
virtual ~Function() {
}
};
template <typename Object, typename ReturnType>
class ObjectFunction : public Function<ReturnType> {
public:
typedef ReturnType (Object::*Method)();
ObjectFunction(Object *obj, Method method) : _obj(obj), _method(method) {
}
virtual ReturnType call() {
return (_obj->*_method)();
}
typedef FunctionCreator<R> Creator;
static Creator Null() { return Creator(&NullFunctionImplementation<R>::SharedInstance); }
Function(const Creator &creator) : _implementation(creator.create()) {}
R call() { return _implementation->call(); }
~Function() { destroyImplementation(_implementation); }
private:
Object *_obj;
Method _method;
Function(const Function<R> &other);
Function<R> &operator=(const Function<R> &other);
FunctionImplementation<R> *_implementation;
};
template <typename Object, typename ReturnType>
Function<ReturnType> *func(Object *obj, ReturnType (Object::*method)()) {
return new ObjectFunction<Object, ReturnType>(obj, method);
template <typename R>
class WrappedFunction : public FunctionImplementation<R> {
public:
typedef R(*Method)();
WrappedFunction(Method method) : _method(method) {}
virtual R call() { return (*_method)(); }
private:
Method _method;
};
template <typename R>
inline FunctionCreator<R> func(R(*method)()) {
return FunctionCreator<R>(new WrappedFunction<R>(method));
}
template <typename O, typename R>
class ObjectFunction : public FunctionImplementation<R> {
public:
typedef R(O::*Method)();
ObjectFunction(O *obj, Method method) : _obj(obj), _method(method) {}
virtual R call() { return (_obj->*_method)(); }
private:
O *_obj;
Method _method;
};
template <typename O, typename R>
inline FunctionCreator<R> func(O *obj, R(O::*method)()) {
return FunctionCreator<R>(new ObjectFunction<O, R>(obj, method));
}
template <typename ReturnType, typename ArgumentType1>
template <typename R, typename A1>
class Function1Implementation {
public:
virtual R call(A1 a1) = 0;
virtual void destroy() { delete this; }
virtual ~Function1Implementation() {}
};
template <typename R, typename A1>
class NullFunction1Implementation : public Function1Implementation<R, A1> {
public:
virtual R call(A1 a1) { return R(); }
virtual void destroy() {}
static NullFunction1Implementation<R, A1> SharedInstance;
};
template <typename R, typename A1>
NullFunction1Implementation<R, A1> NullFunction1Implementation<R, A1>::SharedInstance;
template <typename R, typename A1>
class Function1Creator {
public:
Function1Creator(Function1Implementation<R, A1> *ptr) : _ptr(ptr) {}
Function1Creator(const Function1Creator<R, A1> &other) : _ptr(other.create()) {}
Function1Implementation<R, A1> *create() const { return exchange(_ptr); }
~Function1Creator() { destroyImplementation(_ptr); }
private:
Function1Creator<R, A1> &operator=(const Function1Creator<R, A1> &other);
mutable Function1Implementation<R, A1> *_ptr;
};
template <typename R, typename A1>
class Function1 {
public:
virtual ReturnType call(ArgumentType1 arg1) = 0;
virtual ~Function1() {
}
};
template <typename Object, typename ReturnType, typename ArgumentType1>
class ObjectFunction1 : public Function1<ReturnType, ArgumentType1> {
public:
typedef ReturnType (Object::*Method)(ArgumentType1);
ObjectFunction1(Object *obj, Method method) : _obj(obj), _method(method) {
}
virtual ReturnType call(ArgumentType1 arg1) {
return (_obj->*_method)(arg1);
}
typedef Function1Creator<R, A1> Creator;
static Creator Null() { return Creator(&NullFunction1Implementation<R, A1>::SharedInstance); }
Function1(const Creator &creator) : _implementation(creator.create()) {}
R call(A1 a1) { return _implementation->call(a1); }
~Function1() { _implementation->destroy(); }
private:
Object *_obj;
Method _method;
Function1(const Function1<R, A1> &other);
Function1<R, A1> &operator=(const Function1<R, A1> &other);
Function1Implementation<R, A1> *_implementation;
};
template <typename Object, typename ReturnType, typename ArgumentType1>
Function1<ReturnType, ArgumentType1> *func(Object *obj, ReturnType (Object::*method)(ArgumentType1)) {
return new ObjectFunction1<Object, ReturnType, ArgumentType1>(obj, method);
template <typename R, typename A1>
class WrappedFunction1 : public Function1Implementation<R, A1> {
public:
typedef R(*Method)(A1);
WrappedFunction1(Method method) : _method(method) {}
virtual R call(A1 a1) { return (*_method)(a1); }
private:
Method _method;
};
template <typename R, typename A1>
inline Function1Creator<R, A1> func(R(*method)(A1)) {
return Function1Creator<R, A1>(new WrappedFunction1<R, A1>(method));
}
template <typename O, typename R, typename A1>
class ObjectFunction1 : public Function1Implementation<R, A1> {
public:
typedef R(O::*Method)(A1);
ObjectFunction1(O *obj, Method method) : _obj(obj), _method(method) {}
virtual R call(A1 a1) { return (_obj->*_method)(a1); }
private:
O *_obj;
Method _method;
};
template <typename O, typename R, typename A1>
Function1Creator<R, A1> func(O *obj, R(O::*method)(A1)) {
return Function1Creator<R, A1>(new ObjectFunction1<O, R, A1>(obj, method));
}
template <typename R, typename A1, typename A2>
class Function2Implementation {
public:
virtual R call(A1 a1, A2 a2) = 0;
virtual void destroy() { delete this; }
virtual ~Function2Implementation() {}
};
template <typename R, typename A1, typename A2>
class NullFunction2Implementation : public Function2Implementation<R, A1, A2> {
public:
virtual R call(A1 a1, A2 a2) { return R(); }
virtual void destroy() {}
static NullFunction2Implementation<R, A1, A2> SharedInstance;
};
template <typename R, typename A1, typename A2>
NullFunction2Implementation<R, A1, A2> NullFunction2Implementation<R, A1, A2>::SharedInstance;
template <typename R, typename A1, typename A2>
class Function2Creator {
public:
Function2Creator(Function2Implementation<R, A1, A2> *ptr) : _ptr(ptr) {}
Function2Creator(const Function2Creator<R, A1, A2> &other) : _ptr(other.create()) {}
Function2Implementation<R, A1, A2> *create() const { return exchange(_ptr); }
~Function2Creator() { destroyImplementation(_ptr); }
private:
Function2Creator<R, A1, A2> &operator=(const Function2Creator<R, A1, A2> &other);
mutable Function2Implementation<R, A1, A2> *_ptr;
};
template <typename R, typename A1, typename A2>
class Function2 {
public:
typedef Function2Creator<R, A1, A2> Creator;
static Creator Null() { return Creator(&NullFunction2Implementation<R, A1, A2>::SharedInstance); }
Function2(const Creator &creator) : _implementation(creator.create()) {}
R call(A1 a1, A2 a2) { return _implementation->call(a1, a2); }
~Function2() { destroyImplementation(_implementation); }
private:
Function2(const Function2<R, A1, A2> &other);
Function2<R, A1, A2> &operator=(const Function2<R, A1, A2> &other);
Function2Implementation<R, A1, A2> *_implementation;
};
template <typename R, typename A1, typename A2>
class WrappedFunction2 : public Function2Implementation<R, A1, A2> {
public:
typedef R(*Method)(A1, A2);
WrappedFunction2(Method method) : _method(method) {}
virtual R call(A1 a1, A2 a2) { return (*_method)(a1, a2); }
private:
Method _method;
};
template <typename R, typename A1, typename A2>
Function2Creator<R, A1, A2> func(R(*method)(A1, A2)) {
return Function2Creator<R, A1, A2>(new WrappedFunction2<R, A1, A2>(method));
}
template <typename O, typename R, typename A1, typename A2>
class ObjectFunction2 : public Function2Implementation<R, A1, A2> {
public:
typedef R(O::*Method)(A1, A2);
ObjectFunction2(O *obj, Method method) : _obj(obj), _method(method) {}
virtual R call(A1 a1, A2 a2) { return (_obj->*_method)(a1, a2); }
private:
O *_obj;
Method _method;
};
template <typename O, typename R, typename A1, typename A2>
Function2Creator<R, A1, A2> func(O *obj, R(O::*method)(A1, A2)) {
return Function2Creator<R, A1, A2>(new ObjectFunction2<O, R, A1, A2>(obj, method));
}

View File

@ -795,12 +795,6 @@ void Window::showDocument(DocumentData *doc, HistoryItem *item) {
_mediaView->setFocus();
}
void Window::ui_clipRepaint(ClipReader *reader) {
if (_mediaView && !_mediaView->isHidden()) {
_mediaView->ui_clipRepaint(reader);
}
}
void Window::ui_showLayer(LayeredWidget *box, ShowLayerOptions options) {
if (box) {
bool fast = (options.testFlag(ForceFastShowLayer)) || Ui::isLayerShown();
@ -846,12 +840,6 @@ bool Window::ui_isMediaViewShown() {
return _mediaView && !_mediaView->isHidden();
}
void Window::notify_clipReinit(ClipReader *reader) {
if (_mediaView && !_mediaView->isHidden()) {
_mediaView->notify_clipReinit(reader);
}
}
void Window::showConnecting(const QString &text, const QString &reconnect) {
if (_connecting) {
_connecting->set(text, reconnect);

View File

@ -237,13 +237,10 @@ public:
return contentOverlapped(QRect(w->mapToGlobal(r.boundingRect().topLeft()), r.boundingRect().size()));
}
void ui_clipRepaint(ClipReader *reader);
void ui_showLayer(LayeredWidget *box, ShowLayerOptions options);
bool ui_isLayerShown();
bool ui_isMediaViewShown();
void notify_clipReinit(ClipReader *reader);
public slots:
void updateIsActive(int timeout = 0);