forward-by-drag-n-drop done for images, documents, stickers and messages-by-date

This commit is contained in:
John Preston 2015-06-27 16:02:00 +03:00
parent d81d6bbeaa
commit 8e82b8894d
24 changed files with 339 additions and 172 deletions

View File

@ -1249,7 +1249,7 @@ void AudioCaptureInner::onStart() {
char err[AV_ERROR_MAX_STRING_SIZE] = { 0 };
AVOutputFormat *fmt = 0;
while ((fmt = av_oformat_next(fmt))) {
if (fmt->name == QLatin1String("opus")) {
if (fmt->name == qstr("opus")) {
break;
}
}

View File

@ -264,12 +264,12 @@ void SessionsBox::gotAuthorizations(const MTPaccount_Authorizations &result) {
QString appName, appVer = qs(d.vapp_version), systemVer = qs(d.vsystem_version), deviceModel = qs(d.vdevice_model);
if (d.vapi_id.v == 2040 || d.vapi_id.v == 17349) {
appName = (d.vapi_id.v == 2040) ? qsl("Telegram Desktop") : qsl("Telegram Desktop (GitHub)");
// if (systemVer == QLatin1String("windows")) {
appName = (d.vapi_id.v == 2040) ? qstr("Telegram Desktop") : qstr("Telegram Desktop (GitHub)");
// if (systemVer == qstr("windows")) {
// deviceModel = qsl("Windows");
// } else if (systemVer == QLatin1String("os x")) {
// } else if (systemVer == qstr("os x")) {
// deviceModel = qsl("OS X");
// } else if (systemVer == QLatin1String("linux")) {
// } else if (systemVer == qstr("linux")) {
// deviceModel = qsl("Linux");
// }
if (appVer == QString::number(appVer.toInt())) {
@ -293,7 +293,7 @@ void SessionsBox::gotAuthorizations(const MTPaccount_Authorizations &result) {
MTPint active = d.vdate_active.v ? d.vdate_active : d.vdate_created;
data.activeTime = active.v;
data.info = qs(d.vdevice_model) + QLatin1String(", ") + (platform.isEmpty() ? QString() : platform + ' ') + qs(d.vsystem_version);
data.info = qs(d.vdevice_model) + qstr(", ") + (platform.isEmpty() ? QString() : platform + ' ') + qs(d.vsystem_version);
data.ip = qs(d.vip) + (country.isEmpty() ? QString() : QString::fromUtf8(" \xe2\x80\x93 ") + country);
if (!data.hash || (d.vflags.v & 1)) {
data.active = QString();

View File

@ -1776,7 +1776,10 @@ void DialogsWidget::dragEnterEvent(QDragEnterEvent *e) {
if (App::main()->selectingPeer()) return;
_dragInScroll = false;
_dragForward = cWideMode() && e->mimeData()->hasFormat(qsl("application/x-td-forward-selected"));
_dragForward = e->mimeData()->hasFormat(qsl("application/x-td-forward-selected"));
if (!_dragForward) _dragForward = e->mimeData()->hasFormat(qsl("application/x-td-forward-pressed-link"));
if (!_dragForward) _dragForward = e->mimeData()->hasFormat(qsl("application/x-td-forward-pressed"));
if (_dragForward && !cWideMode()) _dragForward = false;
if (_dragForward) {
e->setDropAction(Qt::CopyAction);
e->accept();
@ -1836,11 +1839,7 @@ void DialogsWidget::dropEvent(QDropEvent *e) {
PeerData *p = list.updateFromParentDrag(mapToGlobal(e->pos()));
if (p) {
e->acceptProposedAction();
if (e->mimeData()->hasFormat(qsl("application/x-td-forward-selected"))) {
App::main()->onForward(p->id, true);
} else {
App::main()->onFilesDrop(p->id, e->mimeData());
}
App::main()->onFilesOrForwardDrop(p->id, e->mimeData());
}
}
}

View File

@ -2784,6 +2784,7 @@ void MentionsDropdown::updateFiltered(bool toDown) {
}
}
} else if (_user->botInfo) {
if (!_user->botInfo->inited) App::api()->requestFullPeer(_user);
cnt = _user->botInfo->commands.size();
bots.insert(_user, true);
}

View File

@ -25,9 +25,9 @@ void filedialogInit() {
if (cDialogLastPath().isEmpty()) {
#ifdef Q_OS_WIN
// hack to restore previous dir without hurting performance
QSettings settings(QSettings::UserScope, QLatin1String("QtProject"));
settings.beginGroup(QLatin1String("Qt"));
QByteArray sd = settings.value(QLatin1String("filedialog")).toByteArray();
QSettings settings(QSettings::UserScope, qstr("QtProject"));
settings.beginGroup(qstr("Qt"));
QByteArray sd = settings.value(qstr("filedialog")).toByteArray();
QDataStream stream(&sd, QIODevice::ReadOnly);
if (!stream.atEnd()) {
int version = 3, _QFileDialogMagic = 190;

View File

@ -303,7 +303,7 @@ void FlatTextarea::getSingleEmojiFragment(QString &text, QTextFragment &fragment
}
if (f.isImageFormat() && !t.isEmpty() && t.at(0).unicode() == QChar::ObjectReplacementCharacter) {
QString imageName = static_cast<QTextImageFormat*>(&f)->name();
if (imageName.startsWith(QLatin1String("emoji://e."))) {
if (imageName.startsWith(qstr("emoji://e."))) {
fragment = fr;
text = t;
return;
@ -387,7 +387,7 @@ QString FlatTextarea::getText(int32 start, int32 end) const {
case QChar::ObjectReplacementCharacter:
if (emojiText.isEmpty() && f.isImageFormat()) {
QString imageName = static_cast<QTextImageFormat*>(&f)->name();
if (imageName.startsWith(QLatin1String("emoji://e."))) {
if (imageName.startsWith(qstr("emoji://e."))) {
if (EmojiPtr emoji = emojiFromUrl(imageName)) {
emojiText = emojiString(emoji);
}

View File

@ -259,13 +259,23 @@ public:
virtual QString encoded() const {
return QString();
}
virtual const QLatin1String &type() const = 0;
virtual ~ITextLink() {
}
};
#define TEXT_LINK_CLASS(ClassName) public: \
const QLatin1String &type() const { \
static const QLatin1String _type(qstr(#ClassName)); \
return _type; \
}
typedef QSharedPointer<ITextLink> TextLinkPtr;
class TextLink : public ITextLink {
TEXT_LINK_CLASS(TextLink)
public:
TextLink(const QString &url, bool fullDisplayed = true) : _url(url), _fullDisplayed(fullDisplayed) {
@ -305,6 +315,8 @@ private:
};
class EmailLink : public ITextLink {
TEXT_LINK_CLASS(EmailLink)
public:
EmailLink(const QString &email) : _email(email) {
@ -335,6 +347,8 @@ private:
};
class MentionLink : public ITextLink {
TEXT_LINK_CLASS(MentionLink)
public:
MentionLink(const QString &tag) : _tag(tag) {
@ -361,6 +375,8 @@ private:
};
class HashtagLink : public ITextLink {
TEXT_LINK_CLASS(HashtagLink)
public:
HashtagLink(const QString &tag) : _tag(tag) {
@ -387,6 +403,8 @@ private:
};
class BotCommandLink : public ITextLink {
TEXT_LINK_CLASS(BotCommandLink)
public:
BotCommandLink(const QString &cmd) : _cmd(cmd) {

View File

@ -1777,7 +1777,7 @@ bool HistoryPhoto::hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 w
return (x >= 0 && y >= 0 && x < width && y < _height);
}
void HistoryPhoto::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width) const {
void HistoryPhoto::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width) const {
if (width < 0) width = w;
if (width < 1) return;
@ -1812,7 +1812,7 @@ void HistoryPhoto::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, co
}
} else if (fwd) {
if (y >= fwdFrom && y < fwdFrom + st::msgServiceNameFont->height) {
return fwd->getForwardedState(lnk, inText, x - st::mediaPadding.left(), width - st::mediaPadding.left() - st::mediaPadding.right());
return fwd->getForwardedState(lnk, state, x - st::mediaPadding.left(), width - st::mediaPadding.left() - st::mediaPadding.right());
}
}
height -= st::mediaPadding.bottom();
@ -1820,7 +1820,9 @@ void HistoryPhoto::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, co
if (!_caption.isEmpty()) {
height -= _caption.countHeight(width) + st::webPagePhotoSkip;
if (x >= skipx && y >= height + st::webPagePhotoSkip && x < skipx + width && y < _height) {
return _caption.getState(lnk, inText, x - skipx, y - height - st::webPagePhotoSkip, width);
bool inText = false;
_caption.getState(lnk, inText, x - skipx, y - height - st::webPagePhotoSkip, width);
state = inText ? HistoryInTextCursorState : HistoryDefaultCursorState;
}
}
}
@ -2128,7 +2130,7 @@ bool HistoryVideo::hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 w
return (x >= 0 && y >= 0 && x < width && y < _height);
}
void HistoryVideo::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width) const {
void HistoryVideo::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width) const {
if (width < 0) width = w;
if (width < 1) return;
@ -2180,7 +2182,7 @@ void HistoryVideo::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, co
}
} else if (fwd) {
if (y >= fwdFrom && y < skipy) {
return fwd->getForwardedState(lnk, inText, x - st::mediaPadding.left(), width - st::mediaPadding.left() - st::mediaPadding.right());
return fwd->getForwardedState(lnk, state, x - st::mediaPadding.left(), width - st::mediaPadding.left() - st::mediaPadding.right());
}
}
@ -2190,7 +2192,9 @@ void HistoryVideo::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, co
return;
}
if (!_caption.isEmpty() && x >= st::mediaPadding.left() && x < st::mediaPadding.left() + tw && y >= skipy + st::mediaPadding.top() + st::mediaThumbSize + st::webPagePhotoSkip) {
return _caption.getState(lnk, inText, x - st::mediaPadding.left(), y - skipy - st::mediaPadding.top() - st::mediaThumbSize - st::webPagePhotoSkip, tw);
bool inText = false;
_caption.getState(lnk, inText, x - st::mediaPadding.left(), y - skipy - st::mediaPadding.top() - st::mediaThumbSize - st::webPagePhotoSkip, tw);
state = inText ? HistoryInTextCursorState : HistoryDefaultCursorState;
}
}
@ -2617,7 +2621,7 @@ bool HistoryAudio::hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 w
return (x >= 0 && y >= 0 && x < width && y < _height);
}
void HistoryAudio::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width) const {
void HistoryAudio::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width) const {
if (width < 0) width = w;
if (width < 1) return;
@ -2665,7 +2669,7 @@ void HistoryAudio::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, co
}
} else if (fwd) {
if (y >= fwdFrom && y < skipy) {
return fwd->getForwardedState(lnk, inText, x - st::mediaPadding.left(), width - st::mediaPadding.left() - st::mediaPadding.right());
return fwd->getForwardedState(lnk, state, x - st::mediaPadding.left(), width - st::mediaPadding.left() - st::mediaPadding.right());
}
}
@ -2959,7 +2963,7 @@ int32 HistoryDocument::countHeight(const HistoryItem *parent, int32 width) const
return _height;
}
void HistoryDocument::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width) const {
void HistoryDocument::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width) const {
if (width < 0) width = w;
if (width < 1) return;
@ -3013,7 +3017,7 @@ void HistoryDocument::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y,
}
} else if (fwd) {
if (y >= fwdFrom && y < skipy) {
return fwd->getForwardedState(lnk, inText, x - st::mediaPadding.left(), width - st::mediaPadding.left() - st::mediaPadding.right());
return fwd->getForwardedState(lnk, state, x - st::mediaPadding.left(), width - st::mediaPadding.left() - st::mediaPadding.right());
}
}
@ -3204,7 +3208,7 @@ int32 HistorySticker::countHeight(const HistoryItem *parent, int32 width) const
return _minh;
}
void HistorySticker::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width) const {
void HistorySticker::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width) const {
if (width < 0) width = w;
if (width < 1) return;
@ -3285,7 +3289,7 @@ bool HistoryContact::hasPoint(int32 x, int32 y, const HistoryItem *parent, int32
return (x >= 0 && y <= 0 && x < w && y < _height);
}
void HistoryContact::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width) const {
void HistoryContact::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width) const {
if (width < 0) width = w;
const HistoryReply *reply = toHistoryReply(parent);
@ -3318,7 +3322,7 @@ void HistoryContact::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y,
}
} else if (fwd) {
if (y >= fwdFrom && y < skipy) {
return fwd->getForwardedState(lnk, inText, x - st::mediaPadding.left(), width - st::mediaPadding.left() - st::mediaPadding.right());
return fwd->getForwardedState(lnk, state, x - st::mediaPadding.left(), width - st::mediaPadding.left() - st::mediaPadding.right());
}
}
@ -3468,7 +3472,7 @@ void HistoryWebPage::initDimensions(const HistoryItem *parent) {
if (data->photo && data->type != WebPagePhoto && data->type != WebPageVideo) {
if (data->type == WebPageProfile) {
_asArticle = true;
} else if (data->siteName == QLatin1String("Twitter") || data->siteName == QLatin1String("Facebook")) {
} else if (data->siteName == qstr("Twitter") || data->siteName == qstr("Facebook")) {
_asArticle = false;
} else {
_asArticle = true;
@ -3532,9 +3536,9 @@ void HistoryWebPage::initDimensions(const HistoryItem *parent) {
QString text = textClean(data->description);
if (!_asArticle && !data->photo) text += textcmdSkipBlock(parent->timeWidth(true), st::msgDateFont->height - st::msgDateDelta.y());
const TextParseOptions *opts = &_webpageDescriptionOptions;
if (data->siteName == QLatin1String("Twitter")) {
if (data->siteName == qstr("Twitter")) {
opts = &_twitterDescriptionOptions;
} else if (data->siteName == QLatin1String("Instagram")) {
} else if (data->siteName == qstr("Instagram")) {
opts = &_instagramDescriptionOptions;
}
_description.setText(st::webPageDescriptionFont, text, *opts);
@ -3689,7 +3693,7 @@ void HistoryWebPage::draw(QPainter &p, const HistoryItem *parent, bool selected,
}
if (data->type == WebPageVideo) {
if (data->siteName == QLatin1String("YouTube")) {
if (data->siteName == qstr("YouTube")) {
p.drawPixmap(QPoint((pixwidth - st::youtubeIcon.pxWidth()) / 2, (pixheight - st::youtubeIcon.pxHeight()) / 2), App::sprite(), st::youtubeIcon);
} else {
p.drawPixmap(QPoint((pixwidth - st::videoIcon.pxWidth()) / 2, (pixheight - st::videoIcon.pxHeight()) / 2), App::sprite(), st::videoIcon);
@ -3814,7 +3818,7 @@ bool HistoryWebPage::hasPoint(int32 x, int32 y, const HistoryItem *parent, int32
return (x >= 0 && y >= 0 && x < width && y < _height);
}
void HistoryWebPage::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width) const {
void HistoryWebPage::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width) const {
if (width < 0) width = w;
if (width < 1) return;
@ -3855,11 +3859,14 @@ void HistoryWebPage::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y,
} else if (!data->photo) {
articleLines = 3;
}
if (y >= 0 && y < st::webPageDescriptionFont->height * articleLines) {
int32 desch = qMin(_description.countHeight(width), st::webPageDescriptionFont->height * articleLines);
if (y >= 0 && y < desch) {
bool inText = false;
_description.getState(lnk, inText, x, y, availw);
state = inText ? HistoryInTextCursorState : HistoryDefaultCursorState;
return;
}
y -= qMin(_description.countHeight(width), st::webPageDescriptionFont->height * articleLines);
y -= desch;
}
if (_siteNameWidth || !_title.isEmpty() || !_description.isEmpty()) {
y -= st::webPagePhotoSkip;
@ -4568,7 +4575,7 @@ bool HistoryImageLink::hasPoint(int32 x, int32 y, const HistoryItem *parent, int
return (x >= 0 && y >= 0 && x < width && y < _height);
}
void HistoryImageLink::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width) const {
void HistoryImageLink::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width) const {
if (width < 0) width = w;
int skipx = 0, skipy = 0, height = _height;
const HistoryReply *reply = toHistoryReply(parent);
@ -4601,7 +4608,7 @@ void HistoryImageLink::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y
}
} else if (fwd) {
if (y >= fwdFrom && y < fwdFrom + st::msgServiceNameFont->height) {
return fwd->getForwardedState(lnk, inText, x - st::mediaPadding.left(), width - st::mediaPadding.left() - st::mediaPadding.right());
return fwd->getForwardedState(lnk, state, x - st::mediaPadding.left(), width - st::mediaPadding.left() - st::mediaPadding.right());
}
}
height -= st::mediaPadding.bottom();
@ -5026,8 +5033,8 @@ bool HistoryMessage::hasPoint(int32 x, int32 y) const {
return r.contains(x, y);
}
void HistoryMessage::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y) const {
inText = false;
void HistoryMessage::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y) const {
state = HistoryDefaultCursorState;
lnk = TextLinkPtr();
int32 left = out() ? st::msgMargin.right() : st::msgMargin.left(), width = _history->width - st::msgMargin.left() - st::msgMargin.right(), mwidth = st::msgMaxWidth;
@ -5055,31 +5062,46 @@ void HistoryMessage::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y)
width = _maxw;
}
if (justMedia()) {
_media->getState(lnk, inText, x - left, y - st::msgMargin.top(), this);
_media->getState(lnk, state, x - left, y - st::msgMargin.top(), this);
return;
}
QRect r(left, st::msgMargin.top(), width, _height - st::msgMargin.top() - st::msgMargin.bottom());
if (!out() && _history->peer->chat) { // from user left name
if (x >= r.left() + st::msgPadding.left() && y >= r.top() + st::msgPadding.top() && y < r.top() + st::msgPadding.top() + st::msgNameFont->height && x < r.right() - st::msgPadding.right() && x < r.left() + st::msgPadding.left() + _from->nameText.maxWidth()) {
if (x >= r.left() + st::msgPadding.left() && y >= r.top() + st::msgPadding.top() && y < r.top() + st::msgPadding.top() + st::msgNameFont->height && x < r.left() + r.width() - st::msgPadding.right() && x < r.left() + st::msgPadding.left() + _from->nameText.maxWidth()) {
lnk = _from->lnk;
return;
}
r.setTop(r.top() + st::msgNameFont->height);
}
return getStateFromMessageText(lnk, inText, x, y, r);
getStateFromMessageText(lnk, state, x, y, r);
}
void HistoryMessage::getStateFromMessageText(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const QRect &r) const {
void HistoryMessage::getStateFromMessageText(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const QRect &r) const {
int32 dateX = r.right() - st::msgPadding.right() + st::msgDateDelta.x() - timeWidth(true) + st::msgDateSpace;
int32 dateY = r.bottom() - st::msgPadding.bottom() + st::msgDateDelta.y() - st::msgDateFont->height;
bool inDate = QRect(dateX, dateY, timeWidth(true) - st::msgDateSpace, st::msgDateFont->height).contains(x, y);
QRect trect(r.marginsAdded(-st::msgPadding));
TextLinkPtr medialnk;
if (_media && _media->isDisplayed()) {
if (y >= trect.bottom() - _media->height() && y < trect.bottom()) {
_media->getState(lnk, inText, x - trect.left(), y + _media->height() - trect.bottom(), this);
_media->getState(lnk, state, x - trect.left(), y + _media->height() - trect.bottom(), this);
if (inDate) state = HistoryInDateCursorState;
return;
}
trect.setBottom(trect.bottom() - _media->height() - st::msgPadding.bottom());
}
bool inText = false;
_text.getState(lnk, inText, x - trect.x(), y - trect.y(), trect.width());
if (inDate) {
state = HistoryInDateCursorState;
} else if (inText) {
state = HistoryInTextCursorState;
} else {
state = HistoryDefaultCursorState;
}
}
void HistoryMessage::getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y) const {
@ -5268,9 +5290,9 @@ bool HistoryForwarded::hasPoint(int32 x, int32 y) const {
return HistoryMessage::hasPoint(x, y);
}
void HistoryForwarded::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y) const {
void HistoryForwarded::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y) const {
lnk = TextLinkPtr();
inText = false;
state = HistoryDefaultCursorState;
if (!justMedia()) {
int32 left = out() ? st::msgMargin.right() : st::msgMargin.left(), width = _history->width - st::msgMargin.left() - st::msgMargin.right();
@ -5281,7 +5303,7 @@ void HistoryForwarded::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y
if (!out() && _history->peer->chat) { // from user left photo
if (x >= left && x < left + st::msgPhotoSize) {
return HistoryMessage::getState(lnk, inText, x, y);
return HistoryMessage::getState(lnk, state, x, y);
}
// width -= st::msgPhotoSkip;
left += st::msgPhotoSkip;
@ -5296,28 +5318,28 @@ void HistoryForwarded::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y
if (!out() && _history->peer->chat) {
style::font nameFont(st::msgNameFont);
if (y >= r.top() + st::msgPadding.top() && y < r.top() + st::msgPadding.top() + nameFont->height) {
return HistoryMessage::getState(lnk, inText, x, y);
return HistoryMessage::getState(lnk, state, x, y);
}
r.setTop(r.top() + nameFont->height);
}
QRect trect(r.marginsAdded(-st::msgPadding));
if (y >= trect.top() && y < trect.top() + st::msgServiceNameFont->height) {
return getForwardedState(lnk, inText, x - trect.left(), trect.right() - trect.left());
return getForwardedState(lnk, state, x - trect.left(), trect.right() - trect.left());
}
y -= st::msgServiceNameFont->height;
}
return HistoryMessage::getState(lnk, inText, x, y);
return HistoryMessage::getState(lnk, state, x, y);
}
void HistoryForwarded::getStateFromMessageText(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const QRect &r) const {
void HistoryForwarded::getStateFromMessageText(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const QRect &r) const {
QRect realr(r);
realr.setHeight(r.height() - st::msgServiceNameFont->height);
HistoryMessage::getStateFromMessageText(lnk, inText, x, y, realr);
HistoryMessage::getStateFromMessageText(lnk, state, x, y, realr);
}
void HistoryForwarded::getForwardedState(TextLinkPtr &lnk, bool &inText, int32 x, int32 w) const {
inText = false;
void HistoryForwarded::getForwardedState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 w) const {
state = HistoryDefaultCursorState;
if (x >= fromWidth && x < w && x < fromWidth + fwdFromName.maxWidth()) {
lnk = fwdFrom->lnk;
} else {
@ -5571,9 +5593,9 @@ bool HistoryReply::hasPoint(int32 x, int32 y) const {
return HistoryMessage::hasPoint(x, y);
}
void HistoryReply::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y) const {
void HistoryReply::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y) const {
lnk = TextLinkPtr();
inText = false;
state = HistoryDefaultCursorState;
if (!justMedia()) {
int32 left = out() ? st::msgMargin.right() : st::msgMargin.left(), width = _history->width - st::msgMargin.left() - st::msgMargin.right();
@ -5584,7 +5606,7 @@ void HistoryReply::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y) co
if (!out() && _history->peer->chat) { // from user left photo
if (x >= left && x < left + st::msgPhotoSize) {
return HistoryMessage::getState(lnk, inText, x, y);
return HistoryMessage::getState(lnk, state, x, y);
}
// width -= st::msgPhotoSkip;
left += st::msgPhotoSkip;
@ -5599,7 +5621,7 @@ void HistoryReply::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y) co
if (!out() && _history->peer->chat) {
style::font nameFont(st::msgNameFont);
if (y >= r.top() + st::msgPadding.top() && y < r.top() + st::msgPadding.top() + nameFont->height) {
return HistoryMessage::getState(lnk, inText, x, y);
return HistoryMessage::getState(lnk, state, x, y);
}
r.setTop(r.top() + nameFont->height);
}
@ -5614,15 +5636,15 @@ void HistoryReply::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y) co
}
y -= h;
}
return HistoryMessage::getState(lnk, inText, x, y);
return HistoryMessage::getState(lnk, state, x, y);
}
void HistoryReply::getStateFromMessageText(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const QRect &r) const {
void HistoryReply::getStateFromMessageText(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const QRect &r) const {
int32 h = st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom();
QRect realr(r);
realr.setHeight(r.height() - h);
HistoryMessage::getStateFromMessageText(lnk, inText, x, y, realr);
HistoryMessage::getStateFromMessageText(lnk, state, x, y, realr);
}
void HistoryReply::getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y) const {
@ -5861,9 +5883,9 @@ bool HistoryServiceMsg::hasPoint(int32 x, int32 y) const {
return QRect(left, st::msgServiceMargin.top(), width, height).contains(x, y);
}
void HistoryServiceMsg::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y) const {
void HistoryServiceMsg::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y) const {
lnk = TextLinkPtr();
inText = false;
state = HistoryDefaultCursorState;
int32 left = st::msgServiceMargin.left(), width = _history->width - st::msgServiceMargin.left() - st::msgServiceMargin.left(), height = _height - st::msgServiceMargin.top() - st::msgServiceMargin.bottom(); // two small margins
if (width < 1) return;
@ -5873,10 +5895,11 @@ void HistoryServiceMsg::getState(TextLinkPtr &lnk, bool &inText, int32 x, int32
}
QRect trect(QRect(left, st::msgServiceMargin.top(), width, height).marginsAdded(-st::msgServicePadding));
if (trect.contains(x, y)) {
return _text.getState(lnk, inText, x - trect.x(), y - trect.y(), trect.width(), Qt::AlignCenter);
}
if (_media) {
_media->getState(lnk, inText, x - st::msgServiceMargin.left() - (width - _media->maxWidth()) / 2, y - st::msgServiceMargin.top() - height - st::msgServiceMargin.top(), this);
bool inText = false;
_text.getState(lnk, inText, x - trect.x(), y - trect.y(), trect.width(), Qt::AlignCenter);
state = inText ? HistoryInTextCursorState : HistoryDefaultCursorState;
} else if (_media) {
_media->getState(lnk, state, x - st::msgServiceMargin.left() - (width - _media->maxWidth()) / 2, y - st::msgServiceMargin.top() - height - st::msgServiceMargin.top(), this);
}
}

View File

@ -636,6 +636,12 @@ class HistoryReply; // dynamic_cast optimize
class HistoryMessage; // dynamic_cast optimize
class HistoryForwarded; // dynamic_cast optimize
enum HistoryCursorState {
HistoryDefaultCursorState,
HistoryInTextCursorState,
HistoryInDateCursorState
};
class HistoryMedia;
class HistoryItem : public HistoryElem {
public:
@ -698,9 +704,9 @@ public:
virtual bool hasPoint(int32 x, int32 y) const {
return false;
}
virtual void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y) const {
virtual void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y) const {
lnk = TextLinkPtr();
inText = false;
state = HistoryDefaultCursorState;
}
virtual void getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y) const { // from text
upon = hasPoint(x, y);
@ -788,6 +794,8 @@ protected:
};
class MessageLink : public ITextLink {
TEXT_LINK_CLASS(MessageLink)
public:
MessageLink(PeerId peer, MsgId msgid) : _peer(peer), _msgid(msgid) {
}
@ -828,7 +836,7 @@ public:
w = qMin(width, _maxw);
return _height;
}
virtual void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const = 0;
virtual void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const = 0;
virtual void draw(QPainter &p, const HistoryItem *parent, bool selected, int32 width = -1) const = 0;
virtual bool uploading() const {
return false;
@ -891,7 +899,7 @@ public:
const QString inHistoryText() const;
const Text &captionForClone() const;
bool hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const;
void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const;
void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const;
HistoryMedia *clone() const;
PhotoData *photo() const {
@ -939,7 +947,7 @@ public:
const QString inDialogsText() const;
const QString inHistoryText() const;
bool hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const;
void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const;
void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const;
bool uploading() const {
return (data->status == FileUploading);
}
@ -979,7 +987,7 @@ public:
const QString inDialogsText() const;
const QString inHistoryText() const;
bool hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const;
void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const;
void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const;
bool uploading() const {
return (data->status == FileUploading);
}
@ -1022,7 +1030,7 @@ public:
bool uploading() const {
return (data->status == FileUploading);
}
void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const;
void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const;
HistoryMedia *clone() const;
DocumentData *document() {
@ -1067,7 +1075,7 @@ public:
const QString inHistoryText() const;
bool hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const;
int32 countHeight(const HistoryItem *parent, int32 width = -1) const;
void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const;
void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const;
HistoryMedia *clone() const;
DocumentData *document() {
@ -1102,7 +1110,7 @@ public:
const QString inDialogsText() const;
const QString inHistoryText() const;
bool hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width) const;
void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width) const;
void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width) const;
HistoryMedia *clone() const;
void updateFrom(const MTPMessageMedia &media);
@ -1132,7 +1140,7 @@ public:
const QString inDialogsText() const;
const QString inHistoryText() const;
bool hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const;
void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const;
void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const;
HistoryMedia *clone() const;
void regItem(HistoryItem *item);
@ -1225,7 +1233,7 @@ public:
const QString inDialogsText() const;
const QString inHistoryText() const;
bool hasPoint(int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const;
void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const;
void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const;
HistoryMedia *clone() const;
bool isImageLink() const {
@ -1267,8 +1275,8 @@ public:
int32 resize(int32 width, bool dontRecountText = false, const HistoryItem *parent = 0);
bool hasPoint(int32 x, int32 y) const;
void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y) const;
virtual void getStateFromMessageText(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const QRect &r) const;
void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y) const;
virtual void getStateFromMessageText(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const QRect &r) const;
void getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y) const;
uint32 adjustSelection(uint16 from, uint16 to, TextSelectType type) const {
@ -1343,9 +1351,9 @@ public:
void drawMessageText(QPainter &p, const QRect &trect, uint32 selection) const;
int32 resize(int32 width, bool dontRecountText = false, const HistoryItem *parent = 0);
bool hasPoint(int32 x, int32 y) const;
void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y) const;
void getStateFromMessageText(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const QRect &r) const;
void getForwardedState(TextLinkPtr &lnk, bool &inText, int32 x, int32 w) const;
void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y) const;
void getStateFromMessageText(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const QRect &r) const;
void getForwardedState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 w) const;
void getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y) const;
QDateTime dateForwarded() const {
@ -1396,8 +1404,8 @@ public:
void drawMessageText(QPainter &p, const QRect &trect, uint32 selection) const;
int32 resize(int32 width, bool dontRecountText = false, const HistoryItem *parent = 0);
bool hasPoint(int32 x, int32 y) const;
void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y) const;
void getStateFromMessageText(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const QRect &r) const;
void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y) const;
void getStateFromMessageText(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const QRect &r) const;
void getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y) const;
UserData *replyTo() const {
@ -1437,7 +1445,7 @@ public:
void draw(QPainter &p, uint32 selection) const;
int32 resize(int32 width, bool dontRecountText = false, const HistoryItem *parent = 0);
bool hasPoint(int32 x, int32 y) const;
void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y) const;
void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y) const;
void getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y) const;
uint32 adjustSelection(uint16 from, uint16 to, TextSelectType type) const {
return _text.adjustSelection(from, to, type);
@ -1478,9 +1486,9 @@ class HistoryDateMsg : public HistoryServiceMsg {
public:
HistoryDateMsg(History *history, HistoryBlock *block, const QDate &date);
void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y) const {
void getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y) const {
lnk = TextLinkPtr();
inText = false;
state = HistoryDefaultCursorState;
}
void getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y) const {
symbol = 0xFFFF;

View File

@ -47,6 +47,7 @@ HistoryList::HistoryList(HistoryWidget *historyWidget, ScrollArea *scroll, Histo
, _dragAction(NoDrag)
, _dragSelType(TextSelectLetters)
, _dragItem(0)
, _dragCursorState(HistoryDefaultCursorState)
, _dragWasInactive(false)
, _dragSelFrom(0)
, _dragSelTo(0)
@ -396,8 +397,7 @@ void HistoryList::dragActionStart(const QPoint &screenPos, Qt::MouseButton butto
_dragStartPos = mapMouseToItem(mapFromGlobal(screenPos), _dragItem);
_dragWasInactive = App::wnd()->inactivePress();
if (_dragWasInactive) App::wnd()->inactivePress(false);
bool textLink = textlnkDown() && !textlnkDown()->encoded().isEmpty();
if (textLink) {
if (textlnkDown()) {
_dragAction = PrepareDrag;
} else if (!_selected.isEmpty()) {
if (_selected.cbegin().value() == FullItemSel) {
@ -451,18 +451,22 @@ void HistoryList::dragActionStart(const QPoint &screenPos, Qt::MouseButton butto
if (uponSelected) {
_dragAction = PrepareDrag; // start text drag
} else if (!_dragWasInactive) {
if (afterDragSymbol) ++_dragSymbol;
uint32 selStatus = (_dragSymbol << 16) | _dragSymbol;
if (selStatus != FullItemSel && (_selected.isEmpty() || _selected.cbegin().value() != FullItemSel)) {
if (!_selected.isEmpty()) {
updateMsg(_selected.cbegin().key());
_selected.clear();
}
_selected.insert(_dragItem, selStatus);
_dragAction = Selecting;
updateMsg(_dragItem);
if (dynamic_cast<HistorySticker*>(App::pressedItem()->getMedia()) || _dragCursorState == HistoryInDateCursorState) {
_dragAction = PrepareDrag; // start sticker drag or by-date drag
} else {
_dragAction = PrepareSelect;
if (afterDragSymbol) ++_dragSymbol;
uint32 selStatus = (_dragSymbol << 16) | _dragSymbol;
if (selStatus != FullItemSel && (_selected.isEmpty() || _selected.cbegin().value() != FullItemSel)) {
if (!_selected.isEmpty()) {
updateMsg(_selected.cbegin().key());
_selected.clear();
}
_selected.insert(_dragItem, selStatus);
_dragAction = Selecting;
updateMsg(_dragItem);
} else {
_dragAction = PrepareSelect;
}
}
}
} else if (!_dragWasInactive) {
@ -529,6 +533,18 @@ void HistoryList::dragActionFinish(const QPoint &screenPos, Qt::MouseButton butt
if (textlnkOver()) {
if (textlnkDown() == textlnkOver() && _dragAction != Dragging) {
needClick = textlnkDown();
QLatin1String lnkType = needClick->type();
bool lnkPhoto = (lnkType == qstr("PhotoLink")),
lnkVideo = (lnkType == qstr("VideoOpenLink")),
lnkAudio = (lnkType == qstr("AudioOpenLink")),
lnkDocument = (lnkType == qstr("DocumentOpenLink")),
lnkContact = (lnkType == qstr("PeerLink") && dynamic_cast<HistoryContact*>(App::pressedLinkItem() ? App::pressedLinkItem()->getMedia() : 0));
if (_dragAction == PrepareDrag && !_dragWasInactive && !_selected.isEmpty() && _selected.cbegin().value() == FullItemSel && button != Qt::RightButton) {
if (lnkPhoto || lnkVideo || lnkAudio || lnkDocument || lnkContact) {
needClick = TextLinkPtr();
}
}
}
}
if (textlnkDown()) {
@ -553,7 +569,7 @@ void HistoryList::dragActionFinish(const QPoint &screenPos, Qt::MouseButton butt
dragActionCancel();
return;
}
if (_dragAction == PrepareSelect && !needClick && !_dragWasInactive && !_selected.isEmpty() && _selected.cbegin().value() == FullItemSel) {
if (_dragAction == PrepareSelect && !_dragWasInactive && !_selected.isEmpty() && _selected.cbegin().value() == FullItemSel) {
SelectedItems::iterator i = _selected.find(_dragItem);
if (i == _selected.cend() && !_dragItem->serviceMsg() && _dragItem->id > 0) {
if (_selected.size() < MaxSelectedItems) {
@ -566,11 +582,16 @@ void HistoryList::dragActionFinish(const QPoint &screenPos, Qt::MouseButton butt
_selected.erase(i);
}
updateMsg(_dragItem);
} else if (_dragAction == PrepareDrag && !needClick && !_dragWasInactive && button != Qt::RightButton) {
} else if (_dragAction == PrepareDrag && !_dragWasInactive && button != Qt::RightButton) {
SelectedItems::iterator i = _selected.find(_dragItem);
if (i != _selected.cend() && i.value() == FullItemSel) {
_selected.erase(i);
updateMsg(_dragItem);
} else if (i == _selected.cend() && !_dragItem->serviceMsg() && _dragItem->id > 0 && !_selected.isEmpty() && _selected.cbegin().value() == FullItemSel) {
if (_selected.size() < MaxSelectedItems) {
_selected.insert(_dragItem, FullItemSel);
updateMsg(_dragItem);
}
} else {
_selected.clear();
parentWidget()->update();
@ -1211,16 +1232,19 @@ void HistoryList::onUpdateSelected() {
linkTipTimer.start(1000);
Qt::CursorShape cur = style::cur_default;
bool inText = false, lnkChanged = false, lnkInDesc = false;
HistoryCursorState cursorState = HistoryDefaultCursorState;
bool lnkChanged = false, lnkInDesc = false;
TextLinkPtr lnk;
if (point.y() < ySkip) {
if (botInfo && !botInfo->text.isEmpty() && botDescHeight > 0) {
bool inText = false;
botInfo->text.getState(lnk, inText, point.x() - botDescRect.left() - st::msgPadding.left(), point.y() - botDescRect.top() - st::msgPadding.top() - st::botDescSkip - st::msgNameFont->height, botDescWidth);
cursorState = inText ? HistoryInTextCursorState : HistoryDefaultCursorState;
lnkInDesc = true;
}
} else if (item) {
item->getState(lnk, inText, m.x(), m.y());
item->getState(lnk, cursorState, m.x(), m.y());
}
if (lnk != textlnkOver()) {
lnkChanged = true;
@ -1244,10 +1268,13 @@ void HistoryList::onUpdateSelected() {
}
if (_dragAction == NoDrag) {
_dragCursorState = cursorState;
if (lnk) {
cur = style::cur_pointer;
} else if (inText && (_selected.isEmpty() || _selected.cbegin().value() != FullItemSel)) {
} else if (_dragCursorState == HistoryInTextCursorState && (_selected.isEmpty() || _selected.cbegin().value() != FullItemSel)) {
cur = style::cur_text;
} else if (_dragCursorState == HistoryInDateCursorState) {
// cur = style::cur_cross;
}
} else if (item) {
if (item != _dragItem || (m - _dragStartPos).manhattanLength() >= QApplication::startDragDistance()) {
@ -1307,6 +1334,38 @@ void HistoryList::onUpdateSelected() {
drag->setMimeData(mimeData);
drag->exec();
return;
} else {
HistoryItem *pressedLnkItem = App::pressedLinkItem(), *pressedItem = App::pressedItem();
QLatin1String lnkType = (textlnkDown() && pressedLnkItem) ? textlnkDown()->type() : qstr("");
bool lnkPhoto = (lnkType == qstr("PhotoLink")),
lnkVideo = (lnkType == qstr("VideoOpenLink")),
lnkAudio = (lnkType == qstr("AudioOpenLink")),
lnkDocument = (lnkType == qstr("DocumentOpenLink")),
lnkContact = (lnkType == qstr("PeerLink") && dynamic_cast<HistoryContact*>(pressedLnkItem->getMedia())),
dragSticker = dynamic_cast<HistorySticker*>(pressedItem ? pressedItem->getMedia() : 0),
dragByDate = (_dragCursorState == HistoryInDateCursorState);
if (lnkPhoto || lnkVideo || lnkAudio || lnkDocument || lnkContact || dragSticker || dragByDate) {
QDrag *drag = new QDrag(App::wnd());
QMimeData *mimeData = new QMimeData;
if (dragSticker || dragByDate) {
mimeData->setData(qsl("application/x-td-forward-pressed"), "1");
} else {
mimeData->setData(qsl("application/x-td-forward-pressed-link"), "1");
}
if (lnkDocument) {
QString already = static_cast<DocumentOpenLink*>(textlnkDown().data())->document()->already(true);
if (!already.isEmpty()) {
QList<QUrl> urls;
urls.push_back(QUrl::fromLocalFile(already));
mimeData->setUrls(urls);
}
}
drag->setMimeData(mimeData);
drag->exec(Qt::CopyAction);
return;
}
}
} else if (_dragAction == PrepareSelect) {
_dragAction = Selecting;
@ -2000,7 +2059,7 @@ void HistoryHider::forward() {
} else if (_sendPath) {
parent()->onSendPaths(offered->id);
} else {
parent()->onForward(offered->id, _forwardSelected);
parent()->onForward(offered->id, _forwardSelected ? ForwardSelectedMessages : ForwardContextMessage);
}
}
emit forwarded();
@ -2056,7 +2115,7 @@ bool HistoryHider::offerPeer(PeerId peer) {
} else {
PeerId to = offered->id;
offered = 0;
parent()->onForward(to, _forwardSelected);
parent()->onForward(to, _forwardSelected ? ForwardSelectedMessages : ForwardContextMessage);
startHide();
return false;
}
@ -3834,7 +3893,7 @@ bool HistoryWidget::eventFilter(QObject *obj, QEvent *e) {
}
DragState HistoryWidget::getDragState(const QMimeData *d) {
if (!d) return DragStateNone;
if (!d || d->hasFormat(qsl("application/x-td-forward-pressed-link"))) return DragStateNone;
if (d->hasImage()) return DragStateImage;

View File

@ -148,6 +148,7 @@ private:
TextSelectType _dragSelType;
QPoint _dragStartPos, _dragPos;
HistoryItem *_dragItem;
HistoryCursorState _dragCursorState;
uint16 _dragSymbol;
bool _dragWasInactive;

View File

@ -26,6 +26,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
namespace {
class SignUpLink : public ITextLink {
TEXT_LINK_CLASS(SignUpLink)
public:
SignUpLink(IntroPhone *widget) : _widget(widget) {

View File

@ -71,28 +71,28 @@ void LangLoader::foundKeyValue(LangKey key) {
}
QString Translator::translate(const char *context, const char *sourceText, const char *disambiguation, int n) const {
if (QLatin1String("QMenuBar") == context) {
if (QLatin1String("Services") == sourceText) return lang(lng_mac_menu_services);
if (QLatin1String("Hide %1") == sourceText) return lng_mac_menu_hide_telegram(lt_telegram, qsl("%1"));
if (QLatin1String("Hide Others") == sourceText) return lang(lng_mac_menu_hide_others);
if (QLatin1String("Show All") == sourceText) return lang(lng_mac_menu_show_all);
if (QLatin1String("Preferences...") == sourceText) return lang(lng_mac_menu_preferences);
if (QLatin1String("Quit %1") == sourceText) return lng_mac_menu_quit_telegram(lt_telegram, qsl("%1"));
if (QLatin1String("About %1") == sourceText) return lng_mac_menu_about_telegram(lt_telegram, qsl("%1"));
if (qstr("QMenuBar") == context) {
if (qstr("Services") == sourceText) return lang(lng_mac_menu_services);
if (qstr("Hide %1") == sourceText) return lng_mac_menu_hide_telegram(lt_telegram, qsl("%1"));
if (qstr("Hide Others") == sourceText) return lang(lng_mac_menu_hide_others);
if (qstr("Show All") == sourceText) return lang(lng_mac_menu_show_all);
if (qstr("Preferences...") == sourceText) return lang(lng_mac_menu_preferences);
if (qstr("Quit %1") == sourceText) return lng_mac_menu_quit_telegram(lt_telegram, qsl("%1"));
if (qstr("About %1") == sourceText) return lng_mac_menu_about_telegram(lt_telegram, qsl("%1"));
return QString();
}
if (QLatin1String("QWidgetTextControl") == context || QLatin1String("QLineEdit") == context) {
if (QLatin1String("&Undo") == sourceText) return lang((cPlatform() == dbipWindows) ? lng_wnd_menu_undo : ((cPlatform() == dbipMac) ? lng_mac_menu_undo : lng_linux_menu_undo));
if (QLatin1String("&Redo") == sourceText) return lang((cPlatform() == dbipWindows) ? lng_wnd_menu_redo : ((cPlatform() == dbipMac) ? lng_mac_menu_redo : lng_linux_menu_redo));
if (QLatin1String("Cu&t") == sourceText) return lang(lng_mac_menu_cut);
if (QLatin1String("&Copy") == sourceText) return lang(lng_mac_menu_copy);
if (QLatin1String("&Paste") == sourceText) return lang(lng_mac_menu_paste);
if (QLatin1String("Delete") == sourceText) return lang(lng_mac_menu_delete);
if (QLatin1String("Select All") == sourceText) return lang(lng_mac_menu_select_all);
if (qstr("QWidgetTextControl") == context || qstr("QLineEdit") == context) {
if (qstr("&Undo") == sourceText) return lang((cPlatform() == dbipWindows) ? lng_wnd_menu_undo : ((cPlatform() == dbipMac) ? lng_mac_menu_undo : lng_linux_menu_undo));
if (qstr("&Redo") == sourceText) return lang((cPlatform() == dbipWindows) ? lng_wnd_menu_redo : ((cPlatform() == dbipMac) ? lng_mac_menu_redo : lng_linux_menu_redo));
if (qstr("Cu&t") == sourceText) return lang(lng_mac_menu_cut);
if (qstr("&Copy") == sourceText) return lang(lng_mac_menu_copy);
if (qstr("&Paste") == sourceText) return lang(lng_mac_menu_paste);
if (qstr("Delete") == sourceText) return lang(lng_mac_menu_delete);
if (qstr("Select All") == sourceText) return lang(lng_mac_menu_select_all);
return QString();
}
if (QLatin1String("QUnicodeControlCharacterMenu") == context) {
if (QLatin1String("Insert Unicode control character") == sourceText) return lang(lng_menu_insert_unicode);
if (qstr("QUnicodeControlCharacterMenu") == context) {
if (qstr("Insert Unicode control character") == sourceText) return lang(lng_menu_insert_unicode);
return QString();
}
return QString();

View File

@ -2780,7 +2780,7 @@ namespace Local {
if (!QDir(di.filePath()).removeRecursively()) result = false;
} else {
QString path = di.filePath();
if (!path.endsWith(QLatin1String("map0")) && !path.endsWith(QLatin1String("map1"))) {
if (!path.endsWith(qstr("map0")) && !path.endsWith(qstr("map1"))) {
if (!QFile::remove(di.filePath())) result = false;
}
}

View File

@ -409,17 +409,27 @@ _failDifferenceTimeout(1), _lastUpdateTime(0), _cachedX(0), _cachedY(0), _backgr
_api->init();
}
void MainWidget::onForward(const PeerId &peer, bool forwardSelected) {
void MainWidget::onForward(const PeerId &peer, ForwardWhatMessages what) {
history.cancelReply();
_toForward.clear();
if (forwardSelected) {
if (what == ForwardSelectedMessages) {
if (overview) {
overview->fillSelectedItems(_toForward, false);
} else {
history.fillSelectedItems(_toForward, false);
}
} else if (App::contextItem() && dynamic_cast<HistoryMessage*>(App::contextItem()) && App::contextItem()->id > 0) {
_toForward.insert(App::contextItem()->id, App::contextItem());
} else {
HistoryItem *item = 0;
if (what == ForwardContextMessage) {
item = App::contextItem();
} else if (what == ForwardPressedMessage) {
item = App::pressedItem();
} else if (what == ForwardPressedLinkMessage) {
item = App::pressedLinkItem();
}
if (dynamic_cast<HistoryMessage*>(item) && item->id > 0) {
_toForward.insert(item->id, item);
}
}
updateForwardingTexts();
showPeer(peer, 0, false, true);
@ -571,9 +581,17 @@ void MainWidget::onSendPaths(const PeerId &peer) {
history.onSendPaths(peer);
}
void MainWidget::onFilesDrop(const PeerId &peer, const QMimeData *data) {
showPeer(peer, 0, false, true);
history.onFilesDrop(data);
void MainWidget::onFilesOrForwardDrop(const PeerId &peer, const QMimeData *data) {
if (data->hasFormat(qsl("application/x-td-forward-selected"))) {
onForward(peer, ForwardSelectedMessages);
} else if (data->hasFormat(qsl("application/x-td-forward-pressed-link"))) {
onForward(peer, ForwardPressedLinkMessage);
} else if (data->hasFormat(qsl("application/x-td-forward-pressed"))) {
onForward(peer, ForwardPressedMessage);
} else {
showPeer(peer, 0, false, true);
history.onFilesDrop(data);
}
}
void MainWidget::noHider(HistoryHider *destroyed) {
@ -1429,7 +1447,7 @@ void MainWidget::audioPlayProgress(AudioData *audio) {
audioPlayer()->clearStoppedAtStart(audio);
QString already = audio->already(true);
if (already.isEmpty() && !audio->data.isEmpty()) {
bool mp3 = (audio->mime == QLatin1String("audio/mp3"));
bool mp3 = (audio->mime == qstr("audio/mp3"));
QString filename = saveFileName(lang(lng_save_audio), mp3 ? qsl("MP3 Audio (*.mp3);;All files (*.*)") : qsl("OGG Opus Audio (*.ogg);;All files (*.*)"), qsl("audio"), mp3 ? qsl(".mp3") : qsl(".ogg"), false);
if (!filename.isEmpty()) {
QFile f(filename);
@ -2560,18 +2578,18 @@ bool MainWidget::started() {
void MainWidget::openLocalUrl(const QString &url) {
QString u(url.trimmed());
if (u.startsWith(QLatin1String("tg://resolve"), Qt::CaseInsensitive)) {
if (u.startsWith(qstr("tg://resolve"), Qt::CaseInsensitive)) {
QRegularExpressionMatch m = QRegularExpression(qsl("^tg://resolve/?\\?domain=([a-zA-Z0-9\\.\\_]+)(&(start|startgroup)=([a-zA-Z0-9\\.\\_\\-]+))?(&|$)"), QRegularExpression::CaseInsensitiveOption).match(u);
if (m.hasMatch()) {
QString start = m.captured(3), startToken = m.captured(4);
openUserByName(m.captured(1), (start == qsl("startgroup")), startToken);
}
} else if (u.startsWith(QLatin1String("tg://join"), Qt::CaseInsensitive)) {
} else if (u.startsWith(qstr("tg://join"), Qt::CaseInsensitive)) {
QRegularExpressionMatch m = QRegularExpression(qsl("^tg://join/?\\?invite=([a-zA-Z0-9\\.\\_\\-]+)(&|$)"), QRegularExpression::CaseInsensitiveOption).match(u);
if (m.hasMatch()) {
joinGroupByHash(m.captured(1));
}
} else if (u.startsWith(QLatin1String("tg://addstickers"), Qt::CaseInsensitive)) {
} else if (u.startsWith(qstr("tg://addstickers"), Qt::CaseInsensitive)) {
QRegularExpressionMatch m = QRegularExpression(qsl("^tg://addstickers/?\\?set=([a-zA-Z0-9\\.\\_]+)(&|$)"), QRegularExpression::CaseInsensitiveOption).match(u);
if (m.hasMatch()) {
stickersBox(MTP_inputStickerSetShortName(MTP_string(m.captured(1))));

View File

@ -163,6 +163,13 @@ public:
}
};
enum ForwardWhatMessages {
ForwardSelectedMessages,
ForwardContextMessage,
ForwardPressedMessage,
ForwardPressedLinkMessage
};
class MainWidget : public QWidget, public Animated, public RPCSender {
Q_OBJECT
@ -254,10 +261,10 @@ public:
void shareContactLayer(UserData *contact);
void hiderLayer(HistoryHider *h);
void noHider(HistoryHider *destroyed);
void onForward(const PeerId &peer, bool forwardSelected);
void onForward(const PeerId &peer, ForwardWhatMessages what);
void onShareContact(const PeerId &peer, UserData *contact);
void onSendPaths(const PeerId &peer);
void onFilesDrop(const PeerId &peer, const QMimeData *data);
void onFilesOrForwardDrop(const PeerId &peer, const QMimeData *data);
bool selectingPeer(bool withConfirm = false);
void offerPeer(PeerId peer);
void focusPeerSelect();

View File

@ -26,6 +26,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
namespace {
class SaveMsgLink : public ITextLink {
TEXT_LINK_CLASS(SaveMsgLink)
public:
SaveMsgLink(MediaView *view) : _view(view) {
@ -826,33 +828,33 @@ void MediaView::displayDocument(DocumentData *doc, HistoryItem *item) {
style::sprite thumbs[] = { st::mvDocBlue, st::mvDocGreen, st::mvDocRed, st::mvDocYellow };
style::color colors[] = { st::mvDocBlueColor, st::mvDocGreenColor, st::mvDocRedColor, st::mvDocYellowColor };
QString name = _doc->name.toLower(), mime = _doc->mime.toLower();
if (name.endsWith(QLatin1String(".doc")) ||
name.endsWith(QLatin1String(".txt")) ||
name.endsWith(QLatin1String(".psd")) ||
mime.startsWith(QLatin1String("text/"))
if (name.endsWith(qstr(".doc")) ||
name.endsWith(qstr(".txt")) ||
name.endsWith(qstr(".psd")) ||
mime.startsWith(qstr("text/"))
) {
_docIcon = thumbs[0];
_docIconColor = colors[0];
} else if (
name.endsWith(QLatin1String(".xls")) ||
name.endsWith(QLatin1String(".csv"))
name.endsWith(qstr(".xls")) ||
name.endsWith(qstr(".csv"))
) {
_docIcon = thumbs[1];
_docIconColor = colors[1];
} else if (
name.endsWith(QLatin1String(".pdf")) ||
name.endsWith(QLatin1String(".ppt")) ||
name.endsWith(QLatin1String(".key"))
name.endsWith(qstr(".pdf")) ||
name.endsWith(qstr(".ppt")) ||
name.endsWith(qstr(".key"))
) {
_docIcon = thumbs[2];
_docIconColor = colors[2];
} else if (
name.endsWith(QLatin1String(".zip")) ||
name.endsWith(QLatin1String(".rar")) ||
name.endsWith(QLatin1String(".ai")) ||
name.endsWith(QLatin1String(".mp3")) ||
name.endsWith(QLatin1String(".mov")) ||
name.endsWith(QLatin1String(".avi"))
name.endsWith(qstr(".zip")) ||
name.endsWith(qstr(".rar")) ||
name.endsWith(qstr(".ai")) ||
name.endsWith(qstr(".mp3")) ||
name.endsWith(qstr(".mov")) ||
name.endsWith(qstr(".avi"))
) {
_docIcon = thumbs[3];
_docIconColor = colors[3];

View File

@ -824,9 +824,9 @@ void OverviewInner::onUpdateSelected() {
}
left += st::msgPhotoSkip;
}
bool inText = false;
HistoryCursorState cursorState = HistoryDefaultCursorState;
TextLinkPtr link;
media->getState(link, inText, m.x() - left, m.y() - y - st::msgMargin.top(), item, w);
media->getState(link, cursorState, m.x() - left, m.y() - y - st::msgMargin.top(), item, w);
if (link) lnk = link;
}
} else {
@ -841,7 +841,7 @@ void OverviewInner::onUpdateSelected() {
m = mapMouseToItem(m, _mousedItem, _mousedItemIndex);
Qt::CursorShape cur = style::cur_default;
bool inText = false, lnkChanged = false;
bool lnkChanged = false;
if (lnk != textlnkOver()) {
lnkChanged = true;
updateMsg(App::hoveredLinkItem());

View File

@ -1076,9 +1076,9 @@ void ProfileInner::updateInvitationLink() {
} else {
_createInvitationLink.setText(lang(lng_group_invite_create_new));
_invitationText = _peerChat->invitationUrl;
if (_invitationText.startsWith(QLatin1String("http://"), Qt::CaseInsensitive)) {
if (_invitationText.startsWith(qstr("http://"), Qt::CaseInsensitive)) {
_invitationText = _invitationText.mid(7);
} else if (_invitationText.startsWith(QLatin1String("https://"), Qt::CaseInsensitive)) {
} else if (_invitationText.startsWith(qstr("https://"), Qt::CaseInsensitive)) {
_invitationText = _invitationText.mid(8);
}
}

View File

@ -352,7 +352,7 @@ namespace {
public:
_PsInitializer() {
QString cdesktop = QString(getenv("XDG_CURRENT_DESKTOP")).toLower();
noQtTrayIcon = (cdesktop == QLatin1String("unity")) || (cdesktop == QLatin1String("pantheon")) || (cdesktop == QLatin1String("gnome"));
noQtTrayIcon = (cdesktop == qstr("unity")) || (cdesktop == qstr("pantheon")) || (cdesktop == qstr("gnome"));
if (noQtTrayIcon) cSetSupportTray(false);
std::cout << "libs init..\n";
@ -460,7 +460,7 @@ namespace {
void setupUnity() {
if (!useGtkBase || !noQtTrayIcon) return;
QLibrary lib_unity(QLatin1String("unity"), 9, 0);
QLibrary lib_unity(qstr("unity"), 9, 0);
if (!loadLibrary(lib_unity, "unity", 9)) return;
if (!loadFunction(lib_unity, "unity_launcher_entry_get_for_desktop_id", ps_unity_launcher_entry_get_for_desktop_id)) return;

View File

@ -731,14 +731,14 @@ void SettingsInner::keyPressEvent(QKeyEvent *e) {
int32 size = _secretText.size(), from = 0;
while (size > from) {
QStringRef str(_secretText.midRef(from));
if (str == QLatin1String("debugmode")) {
if (str == qstr("debugmode")) {
QString text = cDebug() ? qsl("Do you want to disable DEBUG logs?") : qsl("Do you want to enable DEBUG logs?\n\nAll network events will be logged.");
ConfirmBox *box = new ConfirmBox(text);
connect(box, SIGNAL(confirmed()), App::app(), SLOT(onSwitchDebugMode()));
App::wnd()->showLayer(box);
from = size;
break;
} else if (str == QLatin1String("testmode")) {
} else if (str == qstr("testmode")) {
QString text = cTestMode() ? qsl("Do you want to disable TEST mode?") : qsl("Do you want to enable TEST mode?\n\nYou will be switched to test cloud.");
ConfirmBox *box = new ConfirmBox(text);
connect(box, SIGNAL(confirmed()), App::app(), SLOT(onSwitchTestMode()));

View File

@ -455,7 +455,7 @@ void AudioOpenLink::onClick(Qt::MouseButton button) const {
if (data->status != FileReady) return;
bool mp3 = (data->mime == QLatin1String("audio/mp3"));
bool mp3 = (data->mime == qstr("audio/mp3"));
QString filename = saveFileName(lang(lng_save_audio), mp3 ? qsl("MP3 Audio (*.mp3);;All files (*.*)") : qsl("OGG Opus Audio (*.ogg);;All files (*.*)"), qsl("audio"), mp3 ? qsl(".mp3") : qsl(".ogg"), false);
if (!filename.isEmpty()) {
data->openOnSave = 1;
@ -476,7 +476,7 @@ void AudioSaveLink::doSave(AudioData *data, bool forceSavingAs) {
} else {
QFileInfo alreadyInfo(already);
QDir alreadyDir(already.isEmpty() ? QDir() : alreadyInfo.dir());
bool mp3 = (data->mime == QLatin1String("audio/mp3"));
bool mp3 = (data->mime == qstr("audio/mp3"));
QString name = already.isEmpty() ? (mp3 ? qsl(".mp3") : qsl(".ogg")) : alreadyInfo.fileName();
QString filename = saveFileName(lang(lng_save_audio), mp3 ? qsl("MP3 Audio (*.mp3);;All files (*.*)") : qsl("OGG Opus Audio (*.ogg);;All files (*.*)"), qsl("audio"), name, forceSavingAs, alreadyDir);
if (!filename.isEmpty()) {

View File

@ -106,6 +106,8 @@ struct PeerData {
static const uint64 UserNoAccess = 0xFFFFFFFFFFFFFFFFULL;
class PeerLink : public ITextLink {
TEXT_LINK_CLASS(PeerLink)
public:
PeerLink(PeerData *peer) : _peer(peer) {
}
@ -234,6 +236,8 @@ struct PhotoData {
};
class PhotoLink : public ITextLink {
TEXT_LINK_CLASS(PhotoLink)
public:
PhotoLink(PhotoData *photo) : _photo(photo), _peer(0) {
}
@ -313,6 +317,8 @@ struct VideoData {
};
class VideoLink : public ITextLink {
TEXT_LINK_CLASS(VideoLink)
public:
VideoLink(VideoData *video) : _video(video) {
}
@ -325,6 +331,8 @@ private:
};
class VideoSaveLink : public VideoLink {
TEXT_LINK_CLASS(VideoSaveLink)
public:
VideoSaveLink(VideoData *video) : VideoLink(video) {
}
@ -333,6 +341,8 @@ public:
};
class VideoOpenLink : public VideoLink {
TEXT_LINK_CLASS(VideoOpenLink)
public:
VideoOpenLink(VideoData *video) : VideoLink(video) {
}
@ -340,6 +350,8 @@ public:
};
class VideoCancelLink : public VideoLink {
TEXT_LINK_CLASS(VideoCancelLink)
public:
VideoCancelLink(VideoData *video) : VideoLink(video) {
}
@ -400,6 +412,8 @@ struct AudioData {
};
class AudioLink : public ITextLink {
TEXT_LINK_CLASS(AudioLink)
public:
AudioLink(AudioData *audio) : _audio(audio) {
}
@ -412,6 +426,8 @@ private:
};
class AudioSaveLink : public AudioLink {
TEXT_LINK_CLASS(AudioSaveLink)
public:
AudioSaveLink(AudioData *audio) : AudioLink(audio) {
}
@ -420,6 +436,8 @@ public:
};
class AudioOpenLink : public AudioLink {
TEXT_LINK_CLASS(AudioOpenLink)
public:
AudioOpenLink(AudioData *audio) : AudioLink(audio) {
}
@ -427,6 +445,8 @@ public:
};
class AudioCancelLink : public AudioLink {
TEXT_LINK_CLASS(AudioCancelLink)
public:
AudioCancelLink(AudioData *audio) : AudioLink(audio) {
}
@ -518,6 +538,8 @@ struct DocumentData {
};
class DocumentLink : public ITextLink {
TEXT_LINK_CLASS(DocumentLink)
public:
DocumentLink(DocumentData *document) : _document(document) {
}
@ -530,6 +552,8 @@ private:
};
class DocumentSaveLink : public DocumentLink {
TEXT_LINK_CLASS(DocumentSaveLink)
public:
DocumentSaveLink(DocumentData *document) : DocumentLink(document) {
}
@ -538,6 +562,8 @@ public:
};
class DocumentOpenLink : public DocumentLink {
TEXT_LINK_CLASS(DocumentOpenLink)
public:
DocumentOpenLink(DocumentData *document) : DocumentLink(document) {
}
@ -545,6 +571,8 @@ public:
};
class DocumentCancelLink : public DocumentLink {
TEXT_LINK_CLASS(DocumentCancelLink)
public:
DocumentCancelLink(DocumentData *document) : DocumentLink(document) {
}
@ -558,9 +586,9 @@ enum WebPageType {
WebPageArticle
};
inline WebPageType toWebPageType(const QString &type) {
if (type == QLatin1String("photo")) return WebPagePhoto;
if (type == QLatin1String("video")) return WebPageVideo;
if (type == QLatin1String("profile")) return WebPageProfile;
if (type == qstr("photo")) return WebPagePhoto;
if (type == qstr("video")) return WebPageVideo;
if (type == qstr("profile")) return WebPageProfile;
return WebPageArticle;
}

View File

@ -199,6 +199,7 @@ private:
};
#define qsl(s) QStringLiteral(s)
#define qstr(s) QLatin1String(s, sizeof(s) - 1)
static const QRegularExpression::PatternOptions reMultiline(QRegularExpression::DotMatchesEverythingOption | QRegularExpression::MultilineOption);