mirror of https://github.com/procxx/kepka.git
structs.h: move rest of chat/peer related structs to data_peer.h
Related to #174 and #240. Partially inspired by upstream commit https://github.com/telegramdesktop/tdesktop/commit/ffc20e4
This commit is contained in:
parent
4cdf1c446e
commit
559a584dc1
|
@ -24,15 +24,21 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
|
#include <QScrollBar>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QSize>
|
#include <QSize>
|
||||||
|
#include <QTextEdit>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
|
||||||
|
#include "core/click_handler.h" // LeftButtonClickHandler
|
||||||
#include "data/data_types.h"
|
#include "data/data_types.h"
|
||||||
|
#include "data/data_photo.h" // PhotoData
|
||||||
#include "ui/images.h" // StorageKey, ImagePtr, StorageImageLocation
|
#include "ui/images.h" // StorageKey, ImagePtr, StorageImageLocation
|
||||||
|
|
||||||
#include "scheme.h"
|
#include "scheme.h"
|
||||||
|
|
||||||
|
#include "private/qfixed_p.h" // QFIXED_MAX, warn: temporary, should be eliminated.
|
||||||
|
|
||||||
class HistoryItem;
|
class HistoryItem;
|
||||||
|
|
||||||
enum LocationType {
|
enum LocationType {
|
||||||
|
@ -322,3 +328,229 @@ private:
|
||||||
|
|
||||||
void destroyLoaderDelayed(mtpFileLoader *newValue = nullptr) const;
|
void destroyLoaderDelayed(mtpFileLoader *newValue = nullptr) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static const WebPageId CancelledWebPageId = 0xFFFFFFFFFFFFFFFFULL;
|
||||||
|
|
||||||
|
inline bool operator==(const FullMsgId &a, const FullMsgId &b) {
|
||||||
|
return (a.channel == b.channel) && (a.msg == b.msg);
|
||||||
|
}
|
||||||
|
inline bool operator!=(const FullMsgId &a, const FullMsgId &b) {
|
||||||
|
return !(a == b);
|
||||||
|
}
|
||||||
|
inline bool operator<(const FullMsgId &a, const FullMsgId &b) {
|
||||||
|
if (a.msg < b.msg) return true;
|
||||||
|
if (a.msg > b.msg) return false;
|
||||||
|
return a.channel < b.channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr bool isClientMsgId(MsgId id) {
|
||||||
|
return id >= StartClientMsgId && id < EndClientMsgId;
|
||||||
|
}
|
||||||
|
|
||||||
|
class UserData;
|
||||||
|
class ChatData;
|
||||||
|
class ChannelData;
|
||||||
|
|
||||||
|
typedef QMap<char, QPixmap> PreparedPhotoThumbs;
|
||||||
|
|
||||||
|
bool fileIsImage(const QString &name, const QString &mime);
|
||||||
|
|
||||||
|
namespace Serialize {
|
||||||
|
class Document;
|
||||||
|
} // namespace Serialize
|
||||||
|
|
||||||
|
class AudioMsgId {
|
||||||
|
public:
|
||||||
|
enum class Type {
|
||||||
|
Unknown,
|
||||||
|
Voice,
|
||||||
|
Song,
|
||||||
|
Video,
|
||||||
|
};
|
||||||
|
|
||||||
|
AudioMsgId() = default;
|
||||||
|
AudioMsgId(DocumentData *audio, const FullMsgId &msgId, quint32 playId = 0)
|
||||||
|
: _audio(audio)
|
||||||
|
, _contextId(msgId)
|
||||||
|
, _playId(playId) {
|
||||||
|
setTypeFromAudio();
|
||||||
|
}
|
||||||
|
|
||||||
|
Type type() const {
|
||||||
|
return _type;
|
||||||
|
}
|
||||||
|
DocumentData *audio() const {
|
||||||
|
return _audio;
|
||||||
|
}
|
||||||
|
FullMsgId contextId() const {
|
||||||
|
return _contextId;
|
||||||
|
}
|
||||||
|
quint32 playId() const {
|
||||||
|
return _playId;
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit operator bool() const {
|
||||||
|
return _audio != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setTypeFromAudio() {
|
||||||
|
if (_audio->voice() || _audio->isRoundVideo()) {
|
||||||
|
_type = Type::Voice;
|
||||||
|
} else if (_audio->isVideo()) {
|
||||||
|
_type = Type::Video;
|
||||||
|
} else if (_audio->tryPlaySong()) {
|
||||||
|
_type = Type::Song;
|
||||||
|
} else {
|
||||||
|
_type = Type::Unknown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DocumentData *_audio = nullptr;
|
||||||
|
Type _type = Type::Unknown;
|
||||||
|
FullMsgId _contextId;
|
||||||
|
quint32 _playId = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool operator<(const AudioMsgId &a, const AudioMsgId &b) {
|
||||||
|
if (quintptr(a.audio()) < quintptr(b.audio())) {
|
||||||
|
return true;
|
||||||
|
} else if (quintptr(b.audio()) < quintptr(a.audio())) {
|
||||||
|
return false;
|
||||||
|
} else if (a.contextId() < b.contextId()) {
|
||||||
|
return true;
|
||||||
|
} else if (b.contextId() < a.contextId()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return (a.playId() < b.playId());
|
||||||
|
}
|
||||||
|
inline bool operator==(const AudioMsgId &a, const AudioMsgId &b) {
|
||||||
|
return a.audio() == b.audio() && a.contextId() == b.contextId() && a.playId() == b.playId();
|
||||||
|
}
|
||||||
|
inline bool operator!=(const AudioMsgId &a, const AudioMsgId &b) {
|
||||||
|
return !(a == b);
|
||||||
|
}
|
||||||
|
|
||||||
|
class DocumentClickHandler : public LeftButtonClickHandler {
|
||||||
|
public:
|
||||||
|
DocumentClickHandler(DocumentData *document)
|
||||||
|
: _document(document) {}
|
||||||
|
DocumentData *document() const {
|
||||||
|
return _document;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
DocumentData *_document;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DocumentSaveClickHandler : public DocumentClickHandler {
|
||||||
|
public:
|
||||||
|
using DocumentClickHandler::DocumentClickHandler;
|
||||||
|
static void doSave(DocumentData *document, bool forceSavingAs = false);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void onClickImpl() const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DocumentOpenClickHandler : public DocumentClickHandler {
|
||||||
|
public:
|
||||||
|
using DocumentClickHandler::DocumentClickHandler;
|
||||||
|
static void doOpen(DocumentData *document, HistoryItem *context, ActionOnLoad action = ActionOnLoadOpen);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void onClickImpl() const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GifOpenClickHandler : public DocumentOpenClickHandler {
|
||||||
|
public:
|
||||||
|
using DocumentOpenClickHandler::DocumentOpenClickHandler;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void onClickImpl() const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class VoiceSeekClickHandler : public DocumentOpenClickHandler {
|
||||||
|
public:
|
||||||
|
using DocumentOpenClickHandler::DocumentOpenClickHandler;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void onClickImpl() const override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class DocumentCancelClickHandler : public DocumentClickHandler {
|
||||||
|
public:
|
||||||
|
using DocumentClickHandler::DocumentClickHandler;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void onClickImpl() const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum WebPageType { WebPagePhoto, WebPageVideo, WebPageProfile, WebPageArticle };
|
||||||
|
inline WebPageType toWebPageType(const QString &type) {
|
||||||
|
if (type == qstr("photo")) return WebPagePhoto;
|
||||||
|
if (type == qstr("video")) return WebPageVideo;
|
||||||
|
if (type == qstr("profile")) return WebPageProfile;
|
||||||
|
return WebPageArticle;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct WebPageData {
|
||||||
|
WebPageData(const WebPageId &id, WebPageType type = WebPageArticle, const QString &url = QString(),
|
||||||
|
const QString &displayUrl = QString(), const QString &siteName = QString(),
|
||||||
|
const QString &title = QString(), const TextWithEntities &description = TextWithEntities(),
|
||||||
|
DocumentData *doc = nullptr, PhotoData *photo = nullptr, qint32 duration = 0,
|
||||||
|
const QString &author = QString(), qint32 pendingTill = -1);
|
||||||
|
|
||||||
|
void forget() {
|
||||||
|
if (document) document->forget();
|
||||||
|
if (photo) photo->forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
WebPageId id;
|
||||||
|
WebPageType type;
|
||||||
|
QString url, displayUrl, siteName, title;
|
||||||
|
TextWithEntities description;
|
||||||
|
qint32 duration;
|
||||||
|
QString author;
|
||||||
|
PhotoData *photo;
|
||||||
|
DocumentData *document;
|
||||||
|
qint32 pendingTill;
|
||||||
|
};
|
||||||
|
|
||||||
|
QString saveFileName(const QString &title, const QString &filter, const QString &prefix, QString name, bool savingAs,
|
||||||
|
const QDir &dir = QDir());
|
||||||
|
MsgId clientMsgId();
|
||||||
|
|
||||||
|
struct MessageCursor {
|
||||||
|
MessageCursor() = default;
|
||||||
|
MessageCursor(int position, int anchor, int scroll)
|
||||||
|
: position(position)
|
||||||
|
, anchor(anchor)
|
||||||
|
, scroll(scroll) {}
|
||||||
|
MessageCursor(const QTextEdit *edit) {
|
||||||
|
fillFrom(edit);
|
||||||
|
}
|
||||||
|
void fillFrom(const QTextEdit *edit) {
|
||||||
|
QTextCursor c = edit->textCursor();
|
||||||
|
position = c.position();
|
||||||
|
anchor = c.anchor();
|
||||||
|
QScrollBar *s = edit->verticalScrollBar();
|
||||||
|
scroll = (s && (s->value() != s->maximum())) ? s->value() : QFIXED_MAX;
|
||||||
|
}
|
||||||
|
void applyTo(QTextEdit *edit) {
|
||||||
|
auto cursor = edit->textCursor();
|
||||||
|
cursor.setPosition(anchor, QTextCursor::MoveAnchor);
|
||||||
|
cursor.setPosition(position, QTextCursor::KeepAnchor);
|
||||||
|
edit->setTextCursor(cursor);
|
||||||
|
if (auto scrollbar = edit->verticalScrollBar()) {
|
||||||
|
scrollbar->setValue(scroll);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int position = 0;
|
||||||
|
int anchor = 0;
|
||||||
|
int scroll = QFIXED_MAX;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool operator==(const MessageCursor &a, const MessageCursor &b) {
|
||||||
|
return (a.position == b.position) && (a.anchor == b.anchor) && (a.scroll == b.scroll);
|
||||||
|
}
|
||||||
|
|
|
@ -34,230 +34,3 @@
|
||||||
#include "data/data_types.h"
|
#include "data/data_types.h"
|
||||||
#include "data/data_photo.h"
|
#include "data/data_photo.h"
|
||||||
#include "data/data_document.h"
|
#include "data/data_document.h"
|
||||||
|
|
||||||
typedef quint64 PeerId;
|
|
||||||
|
|
||||||
static const WebPageId CancelledWebPageId = 0xFFFFFFFFFFFFFFFFULL;
|
|
||||||
|
|
||||||
inline bool operator==(const FullMsgId &a, const FullMsgId &b) {
|
|
||||||
return (a.channel == b.channel) && (a.msg == b.msg);
|
|
||||||
}
|
|
||||||
inline bool operator!=(const FullMsgId &a, const FullMsgId &b) {
|
|
||||||
return !(a == b);
|
|
||||||
}
|
|
||||||
inline bool operator<(const FullMsgId &a, const FullMsgId &b) {
|
|
||||||
if (a.msg < b.msg) return true;
|
|
||||||
if (a.msg > b.msg) return false;
|
|
||||||
return a.channel < b.channel;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline constexpr bool isClientMsgId(MsgId id) {
|
|
||||||
return id >= StartClientMsgId && id < EndClientMsgId;
|
|
||||||
}
|
|
||||||
|
|
||||||
class UserData;
|
|
||||||
class ChatData;
|
|
||||||
class ChannelData;
|
|
||||||
|
|
||||||
typedef QMap<char, QPixmap> PreparedPhotoThumbs;
|
|
||||||
|
|
||||||
bool fileIsImage(const QString &name, const QString &mime);
|
|
||||||
|
|
||||||
namespace Serialize {
|
|
||||||
class Document;
|
|
||||||
} // namespace Serialize
|
|
||||||
|
|
||||||
class AudioMsgId {
|
|
||||||
public:
|
|
||||||
enum class Type {
|
|
||||||
Unknown,
|
|
||||||
Voice,
|
|
||||||
Song,
|
|
||||||
Video,
|
|
||||||
};
|
|
||||||
|
|
||||||
AudioMsgId() = default;
|
|
||||||
AudioMsgId(DocumentData *audio, const FullMsgId &msgId, quint32 playId = 0)
|
|
||||||
: _audio(audio)
|
|
||||||
, _contextId(msgId)
|
|
||||||
, _playId(playId) {
|
|
||||||
setTypeFromAudio();
|
|
||||||
}
|
|
||||||
|
|
||||||
Type type() const {
|
|
||||||
return _type;
|
|
||||||
}
|
|
||||||
DocumentData *audio() const {
|
|
||||||
return _audio;
|
|
||||||
}
|
|
||||||
FullMsgId contextId() const {
|
|
||||||
return _contextId;
|
|
||||||
}
|
|
||||||
quint32 playId() const {
|
|
||||||
return _playId;
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit operator bool() const {
|
|
||||||
return _audio != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void setTypeFromAudio() {
|
|
||||||
if (_audio->voice() || _audio->isRoundVideo()) {
|
|
||||||
_type = Type::Voice;
|
|
||||||
} else if (_audio->isVideo()) {
|
|
||||||
_type = Type::Video;
|
|
||||||
} else if (_audio->tryPlaySong()) {
|
|
||||||
_type = Type::Song;
|
|
||||||
} else {
|
|
||||||
_type = Type::Unknown;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DocumentData *_audio = nullptr;
|
|
||||||
Type _type = Type::Unknown;
|
|
||||||
FullMsgId _contextId;
|
|
||||||
quint32 _playId = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline bool operator<(const AudioMsgId &a, const AudioMsgId &b) {
|
|
||||||
if (quintptr(a.audio()) < quintptr(b.audio())) {
|
|
||||||
return true;
|
|
||||||
} else if (quintptr(b.audio()) < quintptr(a.audio())) {
|
|
||||||
return false;
|
|
||||||
} else if (a.contextId() < b.contextId()) {
|
|
||||||
return true;
|
|
||||||
} else if (b.contextId() < a.contextId()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return (a.playId() < b.playId());
|
|
||||||
}
|
|
||||||
inline bool operator==(const AudioMsgId &a, const AudioMsgId &b) {
|
|
||||||
return a.audio() == b.audio() && a.contextId() == b.contextId() && a.playId() == b.playId();
|
|
||||||
}
|
|
||||||
inline bool operator!=(const AudioMsgId &a, const AudioMsgId &b) {
|
|
||||||
return !(a == b);
|
|
||||||
}
|
|
||||||
|
|
||||||
class DocumentClickHandler : public LeftButtonClickHandler {
|
|
||||||
public:
|
|
||||||
DocumentClickHandler(DocumentData *document)
|
|
||||||
: _document(document) {}
|
|
||||||
DocumentData *document() const {
|
|
||||||
return _document;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
DocumentData *_document;
|
|
||||||
};
|
|
||||||
|
|
||||||
class DocumentSaveClickHandler : public DocumentClickHandler {
|
|
||||||
public:
|
|
||||||
using DocumentClickHandler::DocumentClickHandler;
|
|
||||||
static void doSave(DocumentData *document, bool forceSavingAs = false);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void onClickImpl() const override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class DocumentOpenClickHandler : public DocumentClickHandler {
|
|
||||||
public:
|
|
||||||
using DocumentClickHandler::DocumentClickHandler;
|
|
||||||
static void doOpen(DocumentData *document, HistoryItem *context, ActionOnLoad action = ActionOnLoadOpen);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void onClickImpl() const override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class GifOpenClickHandler : public DocumentOpenClickHandler {
|
|
||||||
public:
|
|
||||||
using DocumentOpenClickHandler::DocumentOpenClickHandler;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void onClickImpl() const override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class VoiceSeekClickHandler : public DocumentOpenClickHandler {
|
|
||||||
public:
|
|
||||||
using DocumentOpenClickHandler::DocumentOpenClickHandler;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void onClickImpl() const override {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class DocumentCancelClickHandler : public DocumentClickHandler {
|
|
||||||
public:
|
|
||||||
using DocumentClickHandler::DocumentClickHandler;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void onClickImpl() const override;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum WebPageType { WebPagePhoto, WebPageVideo, WebPageProfile, WebPageArticle };
|
|
||||||
inline WebPageType toWebPageType(const QString &type) {
|
|
||||||
if (type == qstr("photo")) return WebPagePhoto;
|
|
||||||
if (type == qstr("video")) return WebPageVideo;
|
|
||||||
if (type == qstr("profile")) return WebPageProfile;
|
|
||||||
return WebPageArticle;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct WebPageData {
|
|
||||||
WebPageData(const WebPageId &id, WebPageType type = WebPageArticle, const QString &url = QString(),
|
|
||||||
const QString &displayUrl = QString(), const QString &siteName = QString(),
|
|
||||||
const QString &title = QString(), const TextWithEntities &description = TextWithEntities(),
|
|
||||||
DocumentData *doc = nullptr, PhotoData *photo = nullptr, qint32 duration = 0,
|
|
||||||
const QString &author = QString(), qint32 pendingTill = -1);
|
|
||||||
|
|
||||||
void forget() {
|
|
||||||
if (document) document->forget();
|
|
||||||
if (photo) photo->forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
WebPageId id;
|
|
||||||
WebPageType type;
|
|
||||||
QString url, displayUrl, siteName, title;
|
|
||||||
TextWithEntities description;
|
|
||||||
qint32 duration;
|
|
||||||
QString author;
|
|
||||||
PhotoData *photo;
|
|
||||||
DocumentData *document;
|
|
||||||
qint32 pendingTill;
|
|
||||||
};
|
|
||||||
|
|
||||||
QString saveFileName(const QString &title, const QString &filter, const QString &prefix, QString name, bool savingAs,
|
|
||||||
const QDir &dir = QDir());
|
|
||||||
MsgId clientMsgId();
|
|
||||||
|
|
||||||
struct MessageCursor {
|
|
||||||
MessageCursor() = default;
|
|
||||||
MessageCursor(int position, int anchor, int scroll)
|
|
||||||
: position(position)
|
|
||||||
, anchor(anchor)
|
|
||||||
, scroll(scroll) {}
|
|
||||||
MessageCursor(const QTextEdit *edit) {
|
|
||||||
fillFrom(edit);
|
|
||||||
}
|
|
||||||
void fillFrom(const QTextEdit *edit) {
|
|
||||||
QTextCursor c = edit->textCursor();
|
|
||||||
position = c.position();
|
|
||||||
anchor = c.anchor();
|
|
||||||
QScrollBar *s = edit->verticalScrollBar();
|
|
||||||
scroll = (s && (s->value() != s->maximum())) ? s->value() : QFIXED_MAX;
|
|
||||||
}
|
|
||||||
void applyTo(QTextEdit *edit) {
|
|
||||||
auto cursor = edit->textCursor();
|
|
||||||
cursor.setPosition(anchor, QTextCursor::MoveAnchor);
|
|
||||||
cursor.setPosition(position, QTextCursor::KeepAnchor);
|
|
||||||
edit->setTextCursor(cursor);
|
|
||||||
if (auto scrollbar = edit->verticalScrollBar()) {
|
|
||||||
scrollbar->setValue(scroll);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int position = 0;
|
|
||||||
int anchor = 0;
|
|
||||||
int scroll = QFIXED_MAX;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline bool operator==(const MessageCursor &a, const MessageCursor &b) {
|
|
||||||
return (a.position == b.position) && (a.anchor == b.anchor) && (a.scroll == b.scroll);
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue