diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index e88ba331c..d434bc26e 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -49,8 +49,8 @@ namespace { PhotosData photosData; DocumentsData documentsData; - typedef QHash ImageLinksData; - ImageLinksData imageLinksData; + typedef QHash LocationsData; + LocationsData locationsData; typedef QHash WebPagesData; WebPagesData webPagesData; @@ -1671,27 +1671,14 @@ namespace App { return result; } - ImageLinkData *imageLink(const QString &imageLink) { - ImageLinksData::const_iterator i = imageLinksData.constFind(imageLink); - if (i == imageLinksData.cend()) { - i = imageLinksData.insert(imageLink, new ImageLinkData(imageLink)); + LocationData *location(const LocationCoords &coords) { + LocationsData::const_iterator i = locationsData.constFind(coords); + if (i == locationsData.cend()) { + i = locationsData.insert(coords, new LocationData(coords)); } return i.value(); } - ImageLinkData *imageLinkSet(const QString &imageLink, ImageLinkType type) { - ImageLinksData::const_iterator i = imageLinksData.constFind(imageLink); - ImageLinkData *result; - if (i == imageLinksData.cend()) { - result = new ImageLinkData(imageLink); - imageLinksData.insert(imageLink, result); - result->type = type; - } else { - result = i.value(); - } - return result; - } - void forgetMedia() { lastPhotos.clear(); lastPhotosMap.clear(); @@ -1701,7 +1688,7 @@ namespace App { for (DocumentsData::const_iterator i = ::documentsData.cbegin(), e = ::documentsData.cend(); i != e; ++i) { i.value()->forget(); } - for (ImageLinksData::const_iterator i = imageLinksData.cbegin(), e = imageLinksData.cend(); i != e; ++i) { + for (LocationsData::const_iterator i = ::locationsData.cbegin(), e = ::locationsData.cend(); i != e; ++i) { i.value()->thumb->forget(); } } diff --git a/Telegram/SourceFiles/app.h b/Telegram/SourceFiles/app.h index a23c92c39..b206d462e 100644 --- a/Telegram/SourceFiles/app.h +++ b/Telegram/SourceFiles/app.h @@ -134,8 +134,7 @@ namespace App { DocumentData *documentSet(const DocumentId &document, DocumentData *convert, const uint64 &access, int32 date, const QVector &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size, const StorageImageLocation &thumbLocation); WebPageData *webPage(const WebPageId &webPage); WebPageData *webPageSet(const WebPageId &webPage, WebPageData *convert, const QString &, const QString &url, const QString &displayUrl, const QString &siteName, const QString &title, const QString &description, PhotoData *photo, DocumentData *doc, int32 duration, const QString &author, int32 pendingTill); - ImageLinkData *imageLink(const QString &imageLink); - ImageLinkData *imageLinkSet(const QString &imageLink, ImageLinkType type); + LocationData *location(const LocationCoords &coords); void forgetMedia(); MTPPhoto photoFromUserPhoto(MTPint userId, MTPint date, const MTPUserProfilePhoto &photo); diff --git a/Telegram/SourceFiles/gui/text.cpp b/Telegram/SourceFiles/gui/text.cpp index 958401f1f..591a6d782 100644 --- a/Telegram/SourceFiles/gui/text.cpp +++ b/Telegram/SourceFiles/gui/text.cpp @@ -955,13 +955,13 @@ void CustomTextLink::onClick(Qt::MouseButton button) const { } void LocationLink::onClick(Qt::MouseButton button) const { - if (!psLaunchMaps(_lat, _lon)) { + if (!psLaunchMaps(_coords)) { QDesktopServices::openUrl(_text); } } void LocationLink::setup() { - QString latlon = _lat + ',' + _lon; + QString latlon(qsl("%1,%2").arg(_coords.lat).arg(_coords.lon)); _text = qsl("https://maps.google.com/maps?q=") + latlon + qsl("&ll=") + latlon + qsl("&z=16"); } diff --git a/Telegram/SourceFiles/gui/text.h b/Telegram/SourceFiles/gui/text.h index 7e270d81e..944d83fff 100644 --- a/Telegram/SourceFiles/gui/text.h +++ b/Telegram/SourceFiles/gui/text.h @@ -424,12 +424,29 @@ private: }; +struct LocationCoords { + LocationCoords() : lat(0), lon(0) { + } + LocationCoords(float64 lat, float64 lon) : lat(lat), lon(lon) { + } + float64 lat, lon; +}; +inline bool operator==(const LocationCoords &a, const LocationCoords &b) { + return (a.lat == b.lat) && (a.lon == b.lon); +} +inline bool operator<(const LocationCoords &a, const LocationCoords &b) { + return (a.lat < b.lat) || ((a.lat == b.lat) && (a.lon < b.lon)); +} +inline uint qHash(const LocationCoords &t, uint seed = 0) { + return qHash(QtPrivate::QHashCombine().operator()(qHash(t.lat), t.lon), seed); +} + class LocationLink : public ITextLink { TEXT_LINK_CLASS(LocationLink) public: - LocationLink(const QString &lat, const QString &lon) : _lat(lat), _lon(lon) { + LocationLink(const LocationCoords &coords) : _coords(coords) { setup(); } @@ -450,7 +467,8 @@ public: private: void setup(); - QString _lat, _lon, _text; + LocationCoords _coords; + QString _text; }; diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index 4a69bdd3d..30ab9b24e 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -5612,10 +5612,10 @@ HistoryWebPage::~HistoryWebPage() { } namespace { - ImageLinkManager manager; + LocationManager manager; } -void ImageLinkManager::init() { +void LocationManager::init() { if (manager) delete manager; manager = new QNetworkAccessManager(); App::setProxySettings(*manager); @@ -5635,11 +5635,11 @@ void ImageLinkManager::init() { black = new ImagePtr(p, "PNG"); } -void ImageLinkManager::reinit() { +void LocationManager::reinit() { if (manager) App::setProxySettings(*manager); } -void ImageLinkManager::deinit() { +void LocationManager::deinit() { if (manager) { delete manager; manager = 0; @@ -5664,33 +5664,27 @@ void deinitImageLinkManager() { manager.deinit(); } -void ImageLinkManager::getData(ImageLinkData *data) { +void LocationManager::getData(LocationData *data) { if (!manager) { DEBUG_LOG(("App Error: getting image link data without manager init!")); return failed(data); } - QString url; - switch (data->type) { - case GoogleMapsLink: { - int32 w = st::locationSize.width(), h = st::locationSize.height(); - int32 zoom = 13, scale = 1; - if (cScale() == dbisTwo || cRetina()) { - scale = 2; - } else { - w = convertScale(w); - h = convertScale(h); - } - url = qsl("https://maps.googleapis.com/maps/api/staticmap?center=") + data->id.mid(9) + qsl("&zoom=%1&size=%2x%3&maptype=roadmap&scale=%4&markers=color:red|size:big|").arg(zoom).arg(w).arg(h).arg(scale) + data->id.mid(9) + qsl("&sensor=false"); - QNetworkReply *reply = manager->get(QNetworkRequest(QUrl(url))); - imageLoadings[reply] = data; - } break; - default: { - failed(data); - } break; + + int32 w = st::locationSize.width(), h = st::locationSize.height(); + int32 zoom = 13, scale = 1; + if (cScale() == dbisTwo || cRetina()) { + scale = 2; + } else { + w = convertScale(w); + h = convertScale(h); } + QString coords = qsl("%1,%2").arg(data->coords.lat).arg(data->coords.lon); + QString url = qsl("https://maps.googleapis.com/maps/api/staticmap?center=") + coords + qsl("&zoom=%1&size=%2x%3&maptype=roadmap&scale=%4&markers=color:red|size:big|").arg(zoom).arg(w).arg(h).arg(scale) + coords + qsl("&sensor=false"); + QNetworkReply *reply = manager->get(QNetworkRequest(QUrl(url))); + imageLoadings[reply] = data; } -void ImageLinkManager::onFinished(QNetworkReply *reply) { +void LocationManager::onFinished(QNetworkReply *reply) { if (!manager) return; if (reply->error() != QNetworkReply::NoError) return onFailed(reply); @@ -5700,9 +5694,9 @@ void ImageLinkManager::onFinished(QNetworkReply *reply) { if (status == 301 || status == 302) { QString loc = reply->header(QNetworkRequest::LocationHeader).toString(); if (!loc.isEmpty()) { - QMap::iterator i = dataLoadings.find(reply); + QMap::iterator i = dataLoadings.find(reply); if (i != dataLoadings.cend()) { - ImageLinkData *d = i.value(); + LocationData *d = i.value(); if (serverRedirects.constFind(d) == serverRedirects.cend()) { serverRedirects.insert(d, 1); } else if (++serverRedirects[d] > MaxHttpRedirects) { @@ -5713,7 +5707,7 @@ void ImageLinkManager::onFinished(QNetworkReply *reply) { dataLoadings.insert(manager->get(QNetworkRequest(loc)), d); return; } else if ((i = imageLoadings.find(reply)) != imageLoadings.cend()) { - ImageLinkData *d = i.value(); + LocationData *d = i.value(); if (serverRedirects.constFind(d) == serverRedirects.cend()) { serverRedirects.insert(d, 1); } else if (++serverRedirects[d] > MaxHttpRedirects) { @@ -5732,8 +5726,8 @@ void ImageLinkManager::onFinished(QNetworkReply *reply) { } } - ImageLinkData *d = 0; - QMap::iterator i = dataLoadings.find(reply); + LocationData *d = 0; + QMap::iterator i = dataLoadings.find(reply); if (i != dataLoadings.cend()) { d = i.value(); dataLoadings.erase(i); @@ -5744,9 +5738,7 @@ void ImageLinkManager::onFinished(QNetworkReply *reply) { DEBUG_LOG(("JSON Error: Bad json received in onFinished() for image link")); return onFailed(reply); } - switch (d->type) { - case GoogleMapsLink: failed(d); break; - } + failed(d); if (App::main()) App::main()->update(); } else { @@ -5777,11 +5769,11 @@ void ImageLinkManager::onFinished(QNetworkReply *reply) { } } -void ImageLinkManager::onFailed(QNetworkReply *reply) { +void LocationManager::onFailed(QNetworkReply *reply) { if (!manager) return; - ImageLinkData *d = 0; - QMap::iterator i = dataLoadings.find(reply); + LocationData *d = 0; + QMap::iterator i = dataLoadings.find(reply); if (i != dataLoadings.cend()) { d = i.value(); dataLoadings.erase(i); @@ -5792,19 +5784,19 @@ void ImageLinkManager::onFailed(QNetworkReply *reply) { imageLoadings.erase(i); } } - DEBUG_LOG(("Network Error: failed to get data for image link %1, error %2").arg(d ? d->id : 0).arg(reply->errorString())); + DEBUG_LOG(("Network Error: failed to get data for image link %1,%2 error %3").arg(d ? d->coords.lat : 0).arg(d ? d->coords.lon : 0).arg(reply->errorString())); if (d) { failed(d); } } -void ImageLinkManager::failed(ImageLinkData *data) { +void LocationManager::failed(LocationData *data) { data->loading = false; data->thumb = *black; serverRedirects.remove(data); } -void ImageLinkData::load() { +void LocationData::load() { if (!thumb->isNull()) return thumb->load(false, false); if (loading) return; @@ -5812,7 +5804,7 @@ void ImageLinkData::load() { manager.getData(this); } -HistoryImageLink::HistoryImageLink(const QString &url, const QString &title, const QString &description) : HistoryMedia(), +HistoryLocation::HistoryLocation(const LocationCoords &coords, const QString &title, const QString &description) : HistoryMedia(), _title(st::msgMinWidth), _description(st::msgMinWidth) { if (!title.isEmpty()) { @@ -5822,16 +5814,11 @@ _description(st::msgMinWidth) { _description.setText(st::webPageDescriptionFont, textClean(description), _webpageDescriptionOptions); } - QRegularExpressionMatch m = QRegularExpression(qsl("^location:(-?\\d+(?:\\.\\d+)?),(-?\\d+(?:\\.\\d+)?)$")).match(url); - if (m.hasMatch()) { - _link.reset(new LocationLink(m.captured(1), m.captured(2))); - _data = App::imageLinkSet(url, GoogleMapsLink); - } else { - _link.reset(new TextLink(url)); - } + _link.reset(new LocationLink(coords)); + _data = App::location(coords); } -void HistoryImageLink::initDimensions(const HistoryItem *parent) { +void HistoryLocation::initDimensions(const HistoryItem *parent) { bool bubble = parent->hasBubble(); int32 tw = fullWidth(), th = fullHeight(); @@ -5862,7 +5849,7 @@ void HistoryImageLink::initDimensions(const HistoryItem *parent) { } } -int32 HistoryImageLink::resize(int32 width, const HistoryItem *parent) { +int32 HistoryLocation::resize(int32 width, const HistoryItem *parent) { bool bubble = parent->hasBubble(); _width = qMin(width, _maxw); @@ -5903,7 +5890,7 @@ int32 HistoryImageLink::resize(int32 width, const HistoryItem *parent) { return _height; } -void HistoryImageLink::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const { +void HistoryLocation::draw(Painter &p, const HistoryItem *parent, const QRect &r, bool selected, uint64 ms) const { if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return; int32 skipx = 0, skipy = 0, width = _width, height = _height; bool bubble = parent->hasBubble(); @@ -5967,7 +5954,7 @@ void HistoryImageLink::draw(Painter &p, const HistoryItem *parent, const QRect & } } -void HistoryImageLink::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent) const { +void HistoryLocation::getState(TextLinkPtr &lnk, HistoryCursorState &state, int32 x, int32 y, const HistoryItem *parent) const { if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return; int32 skipx = 0, skipy = 0, width = _width, height = _height; bool bubble = parent->hasBubble(); @@ -6009,40 +5996,20 @@ void HistoryImageLink::getState(TextLinkPtr &lnk, HistoryCursorState &state, int } } -const QString HistoryImageLink::inDialogsText() const { - if (_data) { - switch (_data->type) { - case GoogleMapsLink: return lang(lng_maps_point); - } - } - return QString(); +const QString HistoryLocation::inDialogsText() const { + return lang(lng_maps_point); } -const QString HistoryImageLink::inHistoryText() const { - if (_data) { - switch (_data->type) { - case GoogleMapsLink: return qsl("[ ") + lang(lng_maps_point) + qsl(" : ") + _link->text() + qsl(" ]"); - } - } - return qsl("[ Link : ") + _link->text() + qsl(" ]"); +const QString HistoryLocation::inHistoryText() const { + return qsl("[ ") + lang(lng_maps_point) + qsl(" : ") + _link->text() + qsl(" ]"); } -int32 HistoryImageLink::fullWidth() const { - if (_data) { - switch (_data->type) { - case GoogleMapsLink: return st::locationSize.width(); - } - } - return st::minPhotoSize; +int32 HistoryLocation::fullWidth() const { + return st::locationSize.width(); } -int32 HistoryImageLink::fullHeight() const { - if (_data) { - switch (_data->type) { - case GoogleMapsLink: return st::locationSize.height(); - } - } - return st::minPhotoSize; +int32 HistoryLocation::fullHeight() const { + return st::locationSize.height(); } void ViaInlineBotLink::onClick(Qt::MouseButton button) const { @@ -6285,14 +6252,14 @@ void HistoryMessage::initMedia(const MTPMessageMedia *media, QString ¤tTex const MTPGeoPoint &point(media->c_messageMediaGeo().vgeo); if (point.type() == mtpc_geoPoint) { const MTPDgeoPoint &d(point.c_geoPoint()); - _media = new HistoryImageLink(qsl("location:%1,%2").arg(d.vlat.v).arg(d.vlong.v)); + _media = new HistoryLocation(LocationCoords(d.vlat.v, d.vlong.v)); } } break; case mtpc_messageMediaVenue: { const MTPDmessageMediaVenue &d(media->c_messageMediaVenue()); if (d.vgeo.type() == mtpc_geoPoint) { const MTPDgeoPoint &g(d.vgeo.c_geoPoint()); - _media = new HistoryImageLink(qsl("location:%1,%2").arg(g.vlat.v).arg(g.vlong.v), qs(d.vtitle), qs(d.vaddress)); + _media = new HistoryLocation(LocationCoords(g.vlat.v, g.vlong.v), qs(d.vtitle), qs(d.vaddress)); } } break; case mtpc_messageMediaPhoto: { diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h index 237670ecf..436997fbe 100644 --- a/Telegram/SourceFiles/history.h +++ b/Telegram/SourceFiles/history.h @@ -120,7 +120,7 @@ enum HistoryMediaType { MediaTypeFile, MediaTypeGif, MediaTypeSticker, - MediaTypeImageLink, + MediaTypeLocation, MediaTypeWebPage, MediaTypeMusicFile, MediaTypeVoiceFile, @@ -1973,59 +1973,54 @@ void initImageLinkManager(); void reinitImageLinkManager(); void deinitImageLinkManager(); -enum ImageLinkType { - InvalidImageLink = 0, - GoogleMapsLink -}; -struct ImageLinkData { - ImageLinkData(const QString &id) : id(id), type(InvalidImageLink), loading(false) { +struct LocationData { + LocationData(const LocationCoords &coords) : coords(coords), loading(false) { } - QString id; + LocationCoords coords; ImagePtr thumb; - ImageLinkType type; bool loading; void load(); }; -class ImageLinkManager : public QObject { +class LocationManager : public QObject { Q_OBJECT public: - ImageLinkManager() : manager(0), black(0) { + LocationManager() : manager(0), black(0) { } void init(); void reinit(); void deinit(); - void getData(ImageLinkData *data); + void getData(LocationData *data); - ~ImageLinkManager() { + ~LocationManager() { deinit(); } - public slots: +public slots: void onFinished(QNetworkReply *reply); void onFailed(QNetworkReply *reply); private: - void failed(ImageLinkData *data); + void failed(LocationData *data); QNetworkAccessManager *manager; - QMap dataLoadings, imageLoadings; - QMap serverRedirects; + QMap dataLoadings, imageLoadings; + QMap serverRedirects; ImagePtr *black; }; -class HistoryImageLink : public HistoryMedia { +class HistoryLocation : public HistoryMedia { public: - HistoryImageLink(const QString &url, const QString &title = QString(), const QString &description = QString()); + HistoryLocation(const LocationCoords &coords, const QString &title = QString(), const QString &description = QString()); HistoryMediaType type() const { - return MediaTypeImageLink; + return MediaTypeLocation; } HistoryMedia *clone() const { - return new HistoryImageLink(*this); + return new HistoryLocation(*this); } void initDimensions(const HistoryItem *parent); @@ -2049,7 +2044,7 @@ public: } private: - ImageLinkData *_data; + LocationData *_data; Text _title, _description; TextLinkPtr _link; diff --git a/Telegram/SourceFiles/pspecific_linux.cpp b/Telegram/SourceFiles/pspecific_linux.cpp index 7221645bc..650c51f10 100644 --- a/Telegram/SourceFiles/pspecific_linux.cpp +++ b/Telegram/SourceFiles/pspecific_linux.cpp @@ -1494,6 +1494,6 @@ bool linuxMoveFile(const char *from, const char *to) { return true; } -bool psLaunchMaps(const QString &lat, const QString &lon) { +bool psLaunchMaps(const LocationCoords &coords) { return false; } diff --git a/Telegram/SourceFiles/pspecific_linux.h b/Telegram/SourceFiles/pspecific_linux.h index 748a5639c..0804e8deb 100644 --- a/Telegram/SourceFiles/pspecific_linux.h +++ b/Telegram/SourceFiles/pspecific_linux.h @@ -195,4 +195,4 @@ public: bool linuxMoveFile(const char *from, const char *to); -bool psLaunchMaps(const QString &lat, const QString &lon); +bool psLaunchMaps(const LocationCoords &coords); diff --git a/Telegram/SourceFiles/pspecific_mac.cpp b/Telegram/SourceFiles/pspecific_mac.cpp index 2f8971696..854ff00d2 100644 --- a/Telegram/SourceFiles/pspecific_mac.cpp +++ b/Telegram/SourceFiles/pspecific_mac.cpp @@ -910,8 +910,8 @@ QByteArray psPathBookmark(const QString &path) { return objc_pathBookmark(path); } -bool psLaunchMaps(const QString &lat, const QString &lon) { - return QDesktopServices::openUrl(qsl("https://maps.apple.com/?q=Point&z=16&ll=%1,%2").arg(lat).arg(lon)); +bool psLaunchMaps(const LocationCoords &coords) { + return QDesktopServices::openUrl(qsl("https://maps.apple.com/?q=Point&z=16&ll=%1,%2").arg(coords.lat).arg(coords.lon)); } QString strNotificationAboutThemeChange() { diff --git a/Telegram/SourceFiles/pspecific_mac.h b/Telegram/SourceFiles/pspecific_mac.h index 979e9825f..596f9c866 100644 --- a/Telegram/SourceFiles/pspecific_mac.h +++ b/Telegram/SourceFiles/pspecific_mac.h @@ -224,4 +224,4 @@ QString strNeedToReload(); QString strNeedToRefresh1(); QString strNeedToRefresh2(); -bool psLaunchMaps(const QString &lat, const QString &lon); +bool psLaunchMaps(const LocationCoords &coords); diff --git a/Telegram/SourceFiles/pspecific_wnd.cpp b/Telegram/SourceFiles/pspecific_wnd.cpp index 6b91561eb..1a2e46140 100644 --- a/Telegram/SourceFiles/pspecific_wnd.cpp +++ b/Telegram/SourceFiles/pspecific_wnd.cpp @@ -3660,6 +3660,6 @@ bool InitToastManager() { return true; } -bool psLaunchMaps(const QString &lat, const QString &lon) { - return QDesktopServices::openUrl(qsl("bingmaps:?lvl=16&collection=point.") + lat + '_' + lon + '_' + qsl("Point")); +bool psLaunchMaps(const LocationCoords &coords) { + return QDesktopServices::openUrl(qsl("bingmaps:?lvl=16&collection=point.%1_%2_Point").arg(coords.lat).arg(coords.lon)); } diff --git a/Telegram/SourceFiles/pspecific_wnd.h b/Telegram/SourceFiles/pspecific_wnd.h index 90bc466c4..0f149ad29 100644 --- a/Telegram/SourceFiles/pspecific_wnd.h +++ b/Telegram/SourceFiles/pspecific_wnd.h @@ -195,4 +195,4 @@ public: }; -bool psLaunchMaps(const QString &lat, const QString &lon); +bool psLaunchMaps(const LocationCoords &coords); diff --git a/Telegram/SourceFiles/window.cpp b/Telegram/SourceFiles/window.cpp index c3ecdbd68..3431edfd5 100644 --- a/Telegram/SourceFiles/window.cpp +++ b/Telegram/SourceFiles/window.cpp @@ -521,6 +521,12 @@ void Window::clearWidgets() { intro->rpcClear(); intro = 0; } + if (_mediaView) { + if (!_mediaView->isHidden()) { + _mediaView->hide(); + } + _mediaView->rpcClear(); + } title->updateBackButton(); updateGlobalMenu(); }