|
32 | 32 | #include <QDebug> |
33 | 33 | #include <QFrame> |
34 | 34 | #include <QHBoxLayout> |
| 35 | +#include <QHostAddress> |
35 | 36 | #include <QLabel> |
36 | 37 | #include <QPushButton> |
37 | 38 | #include <QStyle> |
38 | 39 |
|
39 | 40 | #include "base/bittorrent/session.h" |
40 | 41 | #include "base/bittorrent/sessionstatus.h" |
| 42 | +#include "base/net/geoipmanager.h" |
41 | 43 | #include "base/preferences.h" |
42 | 44 | #include "base/utils/misc.h" |
43 | 45 | #include "speedlimitdialog.h" |
@@ -104,9 +106,13 @@ StatusBar::StatusBar(QWidget *parent) |
104 | 106 | m_freeDiskSpaceLbl->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred); |
105 | 107 | m_freeDiskSpaceSeparator = createSeparator(m_freeDiskSpaceLbl); |
106 | 108 |
|
107 | | - m_lastExternalIPsLbl = new QLabel(tr("External IP: N/A")); |
108 | | - m_lastExternalIPsLbl->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred); |
109 | | - m_lastExternalIPsSeparator = createSeparator(m_lastExternalIPsLbl); |
| 109 | + m_externalIPsContainer = new QWidget(this); |
| 110 | + m_externalIPsContainer->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred); |
| 111 | + auto *externalIPsLayout = new QHBoxLayout(m_externalIPsContainer); |
| 112 | + externalIPsLayout->setContentsMargins(0, 0, 0, 0); |
| 113 | + externalIPsLayout->setSpacing(0); |
| 114 | + externalIPsLayout->addWidget(new QLabel(tr("External IP: N/A"), m_externalIPsContainer)); |
| 115 | + m_lastExternalIPsSeparator = createSeparator(m_externalIPsContainer); |
110 | 116 |
|
111 | 117 | m_DHTLbl = new QLabel(tr("DHT: %1 nodes").arg(0), this); |
112 | 118 | m_DHTLbl->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred); |
@@ -135,7 +141,7 @@ StatusBar::StatusBar(QWidget *parent) |
135 | 141 | layout->addWidget(m_freeDiskSpaceLbl); |
136 | 142 | layout->addWidget(m_freeDiskSpaceSeparator); |
137 | 143 |
|
138 | | - layout->addWidget(m_lastExternalIPsLbl); |
| 144 | + layout->addWidget(m_externalIPsContainer); |
139 | 145 | layout->addWidget(m_lastExternalIPsSeparator); |
140 | 146 |
|
141 | 147 | layout->addWidget(m_DHTLbl); |
@@ -251,23 +257,92 @@ void StatusBar::updateExternalAddressesLabel() |
251 | 257 | { |
252 | 258 | const QString lastExternalIPv4Address = BitTorrent::Session::instance()->lastExternalIPv4Address(); |
253 | 259 | const QString lastExternalIPv6Address = BitTorrent::Session::instance()->lastExternalIPv6Address(); |
254 | | - QString addressText = tr("External IP: N/A"); |
| 260 | + const bool resolveCountries = Preferences::instance()->resolvePeerCountries(); |
| 261 | + |
| 262 | + if ((lastExternalIPv4Address == m_cachedExternalIPv4) |
| 263 | + && (lastExternalIPv6Address == m_cachedExternalIPv6) |
| 264 | + && (resolveCountries == m_cachedResolveCountries)) |
| 265 | + { |
| 266 | + return; |
| 267 | + } |
| 268 | + |
| 269 | + m_cachedExternalIPv4 = lastExternalIPv4Address; |
| 270 | + m_cachedExternalIPv6 = lastExternalIPv6Address; |
| 271 | + m_cachedResolveCountries = resolveCountries; |
| 272 | + |
| 273 | + QHBoxLayout *const externalIPsLayout = qobject_cast<QHBoxLayout *>(m_externalIPsContainer->layout()); |
| 274 | + Q_ASSERT(externalIPsLayout); |
| 275 | + |
| 276 | + while (QLayoutItem *item = externalIPsLayout->takeAt(0)) |
| 277 | + { |
| 278 | + if (QWidget *w = item->widget()) |
| 279 | + w->deleteLater(); |
| 280 | + delete item; |
| 281 | + } |
255 | 282 |
|
256 | 283 | const bool hasIPv4Address = !lastExternalIPv4Address.isEmpty(); |
257 | 284 | const bool hasIPv6Address = !lastExternalIPv6Address.isEmpty(); |
258 | 285 |
|
259 | | - if (hasIPv4Address && hasIPv6Address) |
260 | | - addressText = tr("External IPs: %1, %2").arg(lastExternalIPv4Address, lastExternalIPv6Address); |
261 | | - else if (hasIPv4Address || hasIPv6Address) |
262 | | - addressText = tr("External IP: %1%2").arg(lastExternalIPv4Address, lastExternalIPv6Address); |
| 286 | + Net::GeoIPManager *const geoIP = Net::GeoIPManager::instance(); |
263 | 287 |
|
264 | | - m_lastExternalIPsLbl->setText(addressText); |
| 288 | + QString prefix; |
| 289 | + if (!hasIPv4Address && !hasIPv6Address) |
| 290 | + prefix = tr("External IP: N/A"); |
| 291 | + else if (hasIPv4Address && hasIPv6Address) |
| 292 | + prefix = tr("External IPs: "); |
| 293 | + else |
| 294 | + prefix = tr("External IP: "); |
| 295 | + |
| 296 | + externalIPsLayout->addWidget(new QLabel(prefix, m_externalIPsContainer)); |
| 297 | + |
| 298 | + const auto addIPWithOptionalFlag = [this, externalIPsLayout, resolveCountries, geoIP] |
| 299 | + (const QString &address) |
| 300 | + { |
| 301 | + if (address.isEmpty()) |
| 302 | + return; |
| 303 | + QString countryCode; |
| 304 | + QString countryName; |
| 305 | + if (resolveCountries && geoIP) |
| 306 | + { |
| 307 | + const QHostAddress hostAddr(address); |
| 308 | + if (!hostAddr.isNull()) |
| 309 | + { |
| 310 | + countryCode = geoIP->lookup(hostAddr); |
| 311 | + if (!countryCode.isEmpty()) |
| 312 | + { |
| 313 | + countryName = Net::GeoIPManager::CountryName(countryCode); |
| 314 | + countryCode = countryCode.toLower(); |
| 315 | + } |
| 316 | + } |
| 317 | + } |
| 318 | + if (!countryCode.isEmpty()) |
| 319 | + { |
| 320 | + const QIcon flagIcon = UIThemeManager::instance()->getFlagIcon(countryCode); |
| 321 | + if (!flagIcon.isNull()) |
| 322 | + { |
| 323 | + QLabel *flagLbl = new QLabel(m_externalIPsContainer); |
| 324 | + flagLbl->setPixmap(flagIcon.pixmap(Utils::Gui::smallIconSize())); |
| 325 | + flagLbl->setToolTip(countryName); |
| 326 | + flagLbl->setContentsMargins(0, 0, 3, 0); |
| 327 | + externalIPsLayout->addWidget(flagLbl); |
| 328 | + } |
| 329 | + } |
| 330 | + auto *ipLbl = new QLabel(address, m_externalIPsContainer); |
| 331 | + externalIPsLayout->addWidget(ipLbl); |
| 332 | + }; |
| 333 | + |
| 334 | + if (hasIPv4Address) |
| 335 | + addIPWithOptionalFlag(lastExternalIPv4Address); |
| 336 | + if (hasIPv4Address && hasIPv6Address) |
| 337 | + externalIPsLayout->addWidget(new QLabel(u", "_s, m_externalIPsContainer)); |
| 338 | + if (hasIPv6Address) |
| 339 | + addIPWithOptionalFlag(lastExternalIPv6Address); |
265 | 340 | } |
266 | 341 |
|
267 | 342 | void StatusBar::updateExternalAddressesVisibility() |
268 | 343 | { |
269 | 344 | const bool isVisible = Preferences::instance()->isStatusbarExternalIPDisplayed(); |
270 | | - m_lastExternalIPsLbl->setVisible(isVisible); |
| 345 | + m_externalIPsContainer->setVisible(isVisible); |
271 | 346 | m_lastExternalIPsSeparator->setVisible(isVisible); |
272 | 347 | } |
273 | 348 |
|
|
0 commit comments