up to 64 realtime combinated interfaces

This commit is contained in:
John Preston 2016-01-25 18:18:07 +03:00
parent c8d7d23ee6
commit a677f784f5
5 changed files with 216 additions and 70 deletions

View File

@ -293,9 +293,9 @@ void LayoutAbstractFileItem::setStatusSize(int32 newSize, int32 fullSize, int32
}
}
LayoutOverviewDate::LayoutOverviewDate(const QDate &date, bool month)
: _date(date)
, _text(month ? langMonthFull(date) : langDayOfMonthFull(date)) {
LayoutOverviewDate::LayoutOverviewDate(const QDate &date, bool month) : LayoutItem(OverviewItemInfo::Bit())
, _date(date)
, _text(month ? langMonthFull(date) : langDayOfMonthFull(date)) {
}
void LayoutOverviewDate::initDimensions() {
@ -311,7 +311,7 @@ void LayoutOverviewDate::paint(Painter &p, const QRect &clip, uint32 selection,
}
}
LayoutOverviewPhoto::LayoutOverviewPhoto(PhotoData *photo, HistoryItem *parent) : LayoutMediaItem(parent)
LayoutOverviewPhoto::LayoutOverviewPhoto(PhotoData *photo, HistoryItem *parent) : LayoutMediaItem(0, parent)
, _data(photo)
, _link(new PhotoLink(photo))
, _goodLoaded(false) {
@ -385,7 +385,7 @@ void LayoutOverviewPhoto::getState(TextLinkPtr &link, HistoryCursorState &cursor
}
}
LayoutOverviewVideo::LayoutOverviewVideo(VideoData *video, HistoryItem *parent) : LayoutAbstractFileItem(parent)
LayoutOverviewVideo::LayoutOverviewVideo(VideoData *video, HistoryItem *parent) : LayoutAbstractFileItem(0, parent)
, _data(video)
, _duration(formatDurationText(_data->duration))
, _thumbLoaded(false) {
@ -550,7 +550,7 @@ void LayoutOverviewVideo::updateStatusText() const {
}
}
LayoutOverviewAudio::LayoutOverviewAudio(AudioData *audio, HistoryItem *parent) : LayoutAbstractFileItem(parent)
LayoutOverviewAudio::LayoutOverviewAudio(AudioData *audio, HistoryItem *parent) : LayoutAbstractFileItem(OverviewItemInfo::Bit(), parent)
, _data(audio)
, _namel(new AudioOpenLink(_data)) {
setLinks(new AudioOpenLink(_data), new AudioOpenLink(_data), new AudioCancelLink(_data));
@ -738,7 +738,7 @@ bool LayoutOverviewAudio::updateStatusText() const {
return showPause;
}
LayoutOverviewDocument::LayoutOverviewDocument(DocumentData *document, HistoryItem *parent) : LayoutAbstractFileItem(parent)
LayoutOverviewDocument::LayoutOverviewDocument(DocumentData *document, HistoryItem *parent) : LayoutAbstractFileItem(OverviewItemInfo::Bit(), parent)
, _data(document)
, _msgl(new MessageLink(parent))
, _namel(new DocumentOpenLink(_data))
@ -1061,7 +1061,7 @@ namespace {
}
}
LayoutOverviewLink::LayoutOverviewLink(HistoryMedia *media, HistoryItem *parent) : LayoutMediaItem(parent)
LayoutOverviewLink::LayoutOverviewLink(HistoryMedia *media, HistoryItem *parent) : LayoutMediaItem(OverviewItemInfo::Bit(), parent)
, _titlew(0)
, _page(0)
, _pixw(0)
@ -1319,8 +1319,8 @@ LayoutOverviewLink::Link::Link(const QString &url, const QString &text)
, lnk(linkFromUrl(url)) {
}
LayoutInlineItem::LayoutInlineItem(InlineResult *result, DocumentData *doc, PhotoData *photo)
: _result(result)
LayoutInlineItem::LayoutInlineItem(InlineResult *result, DocumentData *doc, PhotoData *photo) : LayoutItem(0)
, _result(result)
, _doc(doc)
, _photo(photo)
, _position(0) {

View File

@ -101,11 +101,9 @@ public:
};
class LayoutMediaItem;
class OverviewItemInfo;
class LayoutItem {
class LayoutItem : public Interfaces {
public:
LayoutItem() : _maxw(0), _minh(0) {
LayoutItem(uint64 i_mask) : Interfaces(i_mask), _maxw(0), _minh(0) {
}
int32 maxWidth() const {
@ -163,12 +161,6 @@ public:
virtual DocumentData *getDocument() const {
return 0;
}
virtual OverviewItemInfo *getOverviewItemInfo() {
return 0;
}
virtual const OverviewItemInfo *getOverviewItemInfo() const {
return 0;
}
MsgId msgId() const {
const HistoryItem *item = getItem();
return item ? item->id : 0;
@ -182,7 +174,7 @@ protected:
class LayoutMediaItem : public LayoutItem {
public:
LayoutMediaItem(HistoryItem *parent) : _parent(parent) {
LayoutMediaItem(uint64 i_mask, HistoryItem *parent) : LayoutItem(i_mask), _parent(parent) {
}
virtual LayoutMediaItem *toLayoutMediaItem() {
@ -202,7 +194,7 @@ protected:
class LayoutRadialProgressItem : public LayoutMediaItem {
public:
LayoutRadialProgressItem(HistoryItem *parent) : LayoutMediaItem(parent)
LayoutRadialProgressItem(uint64 i_mask, HistoryItem *parent) : LayoutMediaItem(i_mask, parent)
, _radial(0)
, a_iconOver(0, 0)
, _a_iconOver(animation(this, &LayoutRadialProgressItem::step_iconOver)) {
@ -248,7 +240,7 @@ private:
class LayoutAbstractFileItem : public LayoutRadialProgressItem {
public:
LayoutAbstractFileItem(HistoryItem *parent) : LayoutRadialProgressItem(parent) {
LayoutAbstractFileItem(uint64 i_mask, HistoryItem *parent) : LayoutRadialProgressItem(i_mask, parent) {
}
protected:
@ -276,7 +268,7 @@ public:
};
class OverviewItemInfo {
class OverviewItemInfo : public BasicInterface<OverviewItemInfo> {
public:
OverviewItemInfo() : _top(0) {
}
@ -299,16 +291,7 @@ public:
virtual void initDimensions();
virtual void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const;
virtual OverviewItemInfo *getOverviewItemInfo() {
return &_info;
}
virtual const OverviewItemInfo *getOverviewItemInfo() const {
return &_info;
}
private:
OverviewItemInfo _info;
QDate _date;
QString _text;
@ -374,13 +357,6 @@ public:
virtual void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const;
virtual void getState(TextLinkPtr &link, HistoryCursorState &cursor, int32 x, int32 y) const;
virtual OverviewItemInfo *getOverviewItemInfo() {
return &_info;
}
virtual const OverviewItemInfo *getOverviewItemInfo() const {
return &_info;
}
protected:
virtual float64 dataProgress() const {
return _data->progress();
@ -396,7 +372,6 @@ protected:
}
private:
OverviewItemInfo _info;
AudioData *_data;
TextLinkPtr _namel;
@ -419,12 +394,6 @@ public:
virtual DocumentData *getDocument() const {
return _data;
}
virtual OverviewItemInfo *getOverviewItemInfo() {
return &_info;
}
virtual const OverviewItemInfo *getOverviewItemInfo() const {
return &_info;
}
protected:
virtual float64 dataProgress() const {
@ -441,7 +410,6 @@ protected:
}
private:
OverviewItemInfo _info;
DocumentData *_data;
TextLinkPtr _msgl, _namel;
@ -468,15 +436,7 @@ public:
virtual void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const;
virtual void getState(TextLinkPtr &link, HistoryCursorState &cursor, int32 x, int32 y) const;
virtual OverviewItemInfo *getOverviewItemInfo() {
return &_info;
}
virtual const OverviewItemInfo *getOverviewItemInfo() const {
return &_info;
}
private:
OverviewItemInfo _info;
TextLinkPtr _photol;
QString _title, _letter;

View File

@ -355,7 +355,7 @@ void OverviewInner::repaintItem(MsgId itemId, int32 itemIndex) {
int32 row = (_photosToAdd + shownAtIndex) / _photosInRow, col = (_photosToAdd + shownAtIndex) % _photosInRow;
update(int32(col * w), _marginTop + int32(row * vsize), qCeil(w), vsize);
} else {
int32 top = _items.at(itemIndex)->getOverviewItemInfo()->top();
int32 top = _items.at(itemIndex)->Get<OverviewItemInfo>()->top();
if (_reversed) top = _height - top;
update(_rowsLeft, _marginTop + top, _rowWidth, _items.at(itemIndex)->height());
}
@ -729,7 +729,7 @@ QPoint OverviewInner::mapMouseToItem(QPoint p, MsgId itemId, int32 itemIndex) {
p.setX(p.x() - int32(col * w) - st::overviewPhotoSkip);
p.setY(p.y() - _marginTop - row * (_rowWidth + st::overviewPhotoSkip) - st::overviewPhotoSkip);
} else {
int32 top = _items.at(itemIndex)->getOverviewItemInfo()->top();
int32 top = _items.at(itemIndex)->Get<OverviewItemInfo>()->top();
if (_reversed) top = _height - top;
p.setY(p.y() - _marginTop - top);
}
@ -765,7 +765,7 @@ int32 OverviewInner::itemTop(const FullMsgId &msgId) const {
int32 itemIndex = -1;
fixItemIndex(itemIndex, (msgId.channel == _channel) ? msgId.msg : ((_migrated && msgId.channel == _migrated->channelId()) ? -msgId.msg : 0));
if (itemIndex >= 0) {
int32 top = _items.at(itemIndex)->getOverviewItemInfo()->top();
int32 top = _items.at(itemIndex)->Get<OverviewItemInfo>()->top();
if (_reversed) top = _height - top;
return _marginTop + top;
}
@ -879,10 +879,10 @@ void OverviewInner::paintEvent(QPaintEvent *e) {
int32 y = 0, w = _rowWidth;
for (int32 j = 0, l = _items.size(); j < l; ++j) {
int32 i = _reversed ? (l - j - 1) : j, nexti = _reversed ? (i - 1) : (i + 1);
int32 nextItemTop = (j + 1 == l) ? (_reversed ? 0 : _height) : _items.at(nexti)->getOverviewItemInfo()->top();
int32 nextItemTop = (j + 1 == l) ? (_reversed ? 0 : _height) : _items.at(nexti)->Get<OverviewItemInfo>()->top();
if (_reversed) nextItemTop = _height - nextItemTop;
if (_marginTop + nextItemTop > r.top()) {
OverviewItemInfo *info = _items.at(i)->getOverviewItemInfo();
OverviewItemInfo *info = _items.at(i)->Get<OverviewItemInfo>();
int32 curY = info->top();
if (_reversed) curY = _height - curY;
if (_marginTop + curY >= r.y() + r.height()) break;
@ -944,10 +944,10 @@ void OverviewInner::onUpdateSelected() {
for (int32 j = 0, l = _items.size(); j < l; ++j) {
bool lastItem = (j + 1 == l);
int32 i = _reversed ? (l - j - 1) : j, nexti = _reversed ? (i - 1) : (i + 1);
int32 nextItemTop = lastItem ? (_reversed ? 0 : _height) : _items.at(nexti)->getOverviewItemInfo()->top();
int32 nextItemTop = lastItem ? (_reversed ? 0 : _height) : _items.at(nexti)->Get<OverviewItemInfo>()->top();
if (_reversed) nextItemTop = _height - nextItemTop;
if (_marginTop + nextItemTop > m.y() || lastItem) {
int32 top = _items.at(i)->getOverviewItemInfo()->top();
int32 top = _items.at(i)->Get<OverviewItemInfo>()->top();
if (_reversed) top = _height - top;
if (!_items.at(i)->toLayoutMediaItem()) { // day item
int32 h = _items.at(i)->height();
@ -956,11 +956,11 @@ void OverviewInner::onUpdateSelected() {
if (i > 0 && (beforeItem || i == _items.size() - 1)) {
--i;
if (!_items.at(i)->toLayoutMediaItem()) break; // wtf
top = _items.at(i)->getOverviewItemInfo()->top();
top = _items.at(i)->Get<OverviewItemInfo>()->top();
} else if (i < _items.size() - 1 && (!beforeItem || !i)) {
++i;
if (!_items.at(i)->toLayoutMediaItem()) break; // wtf
top = _items.at(i)->getOverviewItemInfo()->top();
top = _items.at(i)->Get<OverviewItemInfo>()->top();
} else {
break; // wtf
}
@ -1385,7 +1385,7 @@ int32 OverviewInner::resizeToWidth(int32 nwidth, int32 scrollTop, int32 minHeigh
for (int32 i = 0, l = _items.size(); i < l; ++i) {
int32 h = _items.at(i)->resizeGetHeight(_rowWidth);
if (resize) {
_items.at(i)->getOverviewItemInfo()->setTop(_height + (_reversed ? h : 0));
_items.at(i)->Get<OverviewItemInfo>()->setTop(_height + (_reversed ? h : 0));
_height += h;
}
}
@ -1746,7 +1746,7 @@ void OverviewInner::mediaOverviewUpdated() {
if (allGood) {
if (_items.size() > index && complexMsgId(_items.at(index)->getItem()) == msgid) {
if (withDates) prevDate = _items.at(index)->getItem()->date.date();
top = _items.at(index)->getOverviewItemInfo()->top();
top = _items.at(index)->Get<OverviewItemInfo>()->top();
if (!_reversed) {
top += _items.at(index)->height();
}
@ -1756,7 +1756,7 @@ void OverviewInner::mediaOverviewUpdated() {
if (_items.size() > index + 1 && !_items.at(index)->toLayoutMediaItem() && complexMsgId(_items.at(index + 1)->getItem()) == msgid) { // day item
++index;
if (withDates) prevDate = _items.at(index)->getItem()->date.date();
top = _items.at(index)->getOverviewItemInfo()->top();
top = _items.at(index)->Get<OverviewItemInfo>()->top();
if (!_reversed) {
top += _items.at(index)->height();
}
@ -1877,7 +1877,7 @@ void OverviewInner::repaintItem(const HistoryItem *msg) {
if (history == _migrated) msgid = -msgid;
for (int32 i = 0, l = _items.size(); i != l; ++i) {
if (complexMsgId(_items.at(i)->getItem()) == msgid) {
int32 top = _items.at(i)->getOverviewItemInfo()->top();
int32 top = _items.at(i)->Get<OverviewItemInfo>()->top();
if (_reversed) top = _height - top;
update(_rowsLeft, _marginTop + top, _rowWidth, _items.at(i)->height());
break;
@ -1982,7 +1982,7 @@ int32 OverviewInner::setLayoutItem(int32 index, LayoutItem *item, int32 top) {
_items.push_back(item);
}
int32 h = item->resizeGetHeight(_rowWidth);
if (OverviewItemInfo *info = item->getOverviewItemInfo()) {
if (OverviewItemInfo *info = item->Get<OverviewItemInfo>()) {
info->setTop(top + (_reversed ? h : 0));
}
return h;

View File

@ -34,6 +34,39 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
#include "audio.h"
#include "localstorage.h"
class InterfacesMetadatasMap : public QMap<uint64, InterfacesMetadata*> {
public:
~InterfacesMetadatasMap() {
for (const_iterator i = cbegin(), e = cend(); i != e; ++i) {
delete i.value();
}
}
};
const InterfacesMetadata *GetInterfacesMetadata(uint64 mask) {
typedef QMap<uint64, InterfacesMetadata*> InterfacesMetadatasMap;
static InterfacesMetadatasMap InterfacesMetadatas;
static QMutex InterfacesMetadatasMutex;
QMutexLocker lock(&InterfacesMetadatasMutex);
InterfacesMetadatasMap::const_iterator i = InterfacesMetadatas.constFind(mask);
if (i == InterfacesMetadatas.cend()) {
InterfacesMetadata *meta = new InterfacesMetadata(mask);
if (!meta) { // terminate if we can't allocate memory
throw "Can't allocate memory!";
}
i = InterfacesMetadatas.insert(mask, meta);
}
return i.value();
}
InterfaceWrapStruct InterfaceWraps[64] = {
{ 0, 0, 0 }
};
QAtomicInt InterfaceIndexLast(0);
namespace {
int32 peerColorIndex(const PeerId &peer) {
int32 myId(MTP::authedId()), peerId(peerToBareInt(peer));

View File

@ -20,6 +20,159 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
*/
#pragma once
class Interfaces;
typedef void(*InterfaceConstruct)(void *location, Interfaces *interfaces);
typedef void(*InterfaceDestruct)(void *location);
struct InterfaceWrapStruct {
int Size;
InterfaceConstruct Construct;
InterfaceDestruct Destruct;
};
template <int Value, int Denominator>
struct CeilDivideMinimumOne {
static const int Result = ((Value / Denominator) + ((!Value || (Value % Denominator)) ? 1 : 0));
};
template <typename Type>
struct InterfaceWrapTemplate {
static const int Size = CeilDivideMinimumOne<sizeof(Type), sizeof(uint64)>::Result * sizeof(uint64);
static void Construct(void *location, Interfaces *interfaces) {
(new (location) Type())->interfaces = interfaces;
}
static void Destruct(void *location) {
((Type*)location)->~Type();
}
};
extern InterfaceWrapStruct InterfaceWraps[64];
extern QAtomicInt InterfaceIndexLast;
template <typename Type>
class BasicInterface {
public:
static int Index() {
static QAtomicInt _index(0);
if (int index = _index.loadAcquire()) {
return index - 1;
}
while (true) {
int last = InterfaceIndexLast.loadAcquire();
if (InterfaceIndexLast.testAndSetOrdered(last, last + 1)) {
t_assert(last < 64);
if (_index.testAndSetOrdered(0, last + 1)) {
InterfaceWraps[last] = { InterfaceWrapTemplate<Type>::Size, InterfaceWrapTemplate<Type>::Construct, InterfaceWrapTemplate<Type>::Destruct };
}
break;
}
}
return _index.loadAcquire() - 1;
}
static const uint64 Bit() {
return (1 << Index());
}
Interfaces *interfaces = 0;
};
class InterfacesMetadata {
public:
InterfacesMetadata(uint64 mask) : _mask(mask), size(0), last(64) {
for (int i = 0; i < 64; ++i) {
uint64 m = (1 << i);
if (_mask & m) {
int s = InterfaceWraps[i].Size;
if (s) {
offsets[i] = size;
size += s;
} else {
offsets[i] = -1;
}
} else if (_mask < m) {
last = i;
for (; i < 64; ++i) {
offsets[i] = -1;
}
} else {
offsets[i] = -1;
}
}
}
int size, last;
int offsets[64];
private:
uint64 _mask;
};
const InterfacesMetadata *GetInterfacesMetadata(uint64 mask);
class Interfaces {
public:
Interfaces(uint64 mask = 0) : _meta(GetInterfacesMetadata(mask)), _data(0) {
if (_meta->size) {
_data = malloc(_meta->size);
if (!_data) { // terminate if we can't allocate memory
throw "Can't allocate memory!";
}
for (int i = 0; i < _meta->last; ++i) {
int offset = _meta->offsets[i];
if (offset >= 0) {
try {
InterfaceWraps[i].Construct(_dataptrunsafe(offset), this);
} catch (...) {
while (i > 0) {
--i;
offset = _meta->offsets[--i];
if (offset >= 0) {
InterfaceWraps[i].Destruct(_dataptrunsafe(offset));
}
}
throw;
}
}
}
}
}
~Interfaces() {
if (_data) {
for (int i = 0; i < _meta->last; ++i) {
int offset = _meta->offsets[i];
if (offset >= 0) {
InterfaceWraps[i].Destruct(_dataptrunsafe(offset));
}
}
free(_data);
}
}
template <typename Type>
Type *Get() {
return (Type*)_dataptr(_meta->offsets[Type::Index()]);
}
template <typename Type>
const Type *Get() const {
return (const Type*)_dataptr(_meta->offsets[Type::Index()]);
}
private:
void *_dataptrunsafe(int skip) const {
return (char*)_data + skip;
}
void *_dataptr(int skip) const {
return (skip >= 0) ? _dataptrunsafe(skip) : 0;
}
const InterfacesMetadata *_meta;
void *_data;
};
typedef int32 ChannelId;
static const ChannelId NoChannel = 0;