From ba014d0033ac083210f8899a55bf0a0866763284 Mon Sep 17 00:00:00 2001 From: Nick Tiskov Date: Fri, 5 Jul 2013 17:29:07 +0400 Subject: [PATCH 1/2] Allow to sort peer list either by country or by IP --- src/properties/peerlistdelegate.h | 2 +- src/properties/peerlistsortmodel.h | 70 ++++++++++++++++++++++++++++++ src/properties/peerlistwidget.cpp | 15 ++++--- src/properties/peerlistwidget.h | 3 +- src/properties/properties.pri | 1 + 5 files changed, 83 insertions(+), 8 deletions(-) create mode 100644 src/properties/peerlistsortmodel.h diff --git a/src/properties/peerlistdelegate.h b/src/properties/peerlistdelegate.h index 08112e64e..91120d1ef 100644 --- a/src/properties/peerlistdelegate.h +++ b/src/properties/peerlistdelegate.h @@ -39,7 +39,7 @@ class PeerListDelegate: public QItemDelegate { Q_OBJECT public: - enum PeerListColumns {IP, CONNECTION, FLAGS, CLIENT, PROGRESS, DOWN_SPEED, UP_SPEED, + enum PeerListColumns {COUNTRY, IP, CONNECTION, FLAGS, CLIENT, PROGRESS, DOWN_SPEED, UP_SPEED, TOT_DOWN, TOT_UP, IP_HIDDEN, COL_COUNT}; public: diff --git a/src/properties/peerlistsortmodel.h b/src/properties/peerlistsortmodel.h new file mode 100644 index 000000000..3a4eb26dc --- /dev/null +++ b/src/properties/peerlistsortmodel.h @@ -0,0 +1,70 @@ +/* + * Bittorrent Client using Qt4 and libtorrent. + * Copyright (C) 2013 Nick Tiskov + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + * + * Contact : daymansmail@gmail.com + */ + +#ifndef PEERLISTSORTMODEL_H +#define PEERLISTSORTMODEL_H + +#include +#include +#include "peerlistdelegate.h" + +class PeerListSortModel : public QSortFilterProxyModel { + Q_OBJECT + +public: + PeerListSortModel(QObject *parent = 0) : QSortFilterProxyModel(parent) {} + +protected: + bool lessThan(const QModelIndex &left, const QModelIndex &right) const { + if (sortColumn() == PeerListDelegate::IP) { + const QStringList ipLeft = sourceModel()->data(left).toString().split('.'); + const QStringList ipRight = sourceModel()->data(right).toString().split('.'); + if ((ipRight.size() & ipLeft.size()) != 4) // One row in model + return false; + Q_ASSERT(ipLeft.size() == 4); + Q_ASSERT(ipRight.size() == 4); + + int i = 0; + while (i < 4) { + int l = ipLeft.at(i).toInt(); + int r = ipRight.at(i).toInt(); + if (l < r) + return true; + else if (l > r) + return false; + ++i; + } + return false; + } + return QSortFilterProxyModel::lessThan(left, right); + } +}; + +#endif // PEERLISTSORTMODEL_H diff --git a/src/properties/peerlistwidget.cpp b/src/properties/peerlistwidget.cpp index f09b9e390..358260da9 100644 --- a/src/properties/peerlistwidget.cpp +++ b/src/properties/peerlistwidget.cpp @@ -61,6 +61,7 @@ PeerListWidget::PeerListWidget(PropertiesWidget *parent): setSelectionMode(QAbstractItemView::ExtendedSelection); // List Model m_listModel = new QStandardItemModel(0, PeerListDelegate::COL_COUNT); + m_listModel->setHeaderData(PeerListDelegate::COUNTRY, Qt::Horizontal, QVariant()); // Country flag column m_listModel->setHeaderData(PeerListDelegate::IP, Qt::Horizontal, tr("IP")); m_listModel->setHeaderData(PeerListDelegate::FLAGS, Qt::Horizontal, tr("Flags")); m_listModel->setHeaderData(PeerListDelegate::CONNECTION, Qt::Horizontal, tr("Connection")); @@ -71,7 +72,7 @@ PeerListWidget::PeerListWidget(PropertiesWidget *parent): m_listModel->setHeaderData(PeerListDelegate::TOT_DOWN, Qt::Horizontal, tr("Downloaded", "i.e: total data downloaded")); m_listModel->setHeaderData(PeerListDelegate::TOT_UP, Qt::Horizontal, tr("Uploaded", "i.e: total data uploaded")); // Proxy model to support sorting without actually altering the underlying model - m_proxyModel = new QSortFilterProxyModel(); + m_proxyModel = new PeerListSortModel(); m_proxyModel->setDynamicSortFilter(true); m_proxyModel->setSourceModel(m_listModel); setModel(m_proxyModel); @@ -82,6 +83,8 @@ PeerListWidget::PeerListWidget(PropertiesWidget *parent): showColumn(i); hideColumn(PeerListDelegate::IP_HIDDEN); hideColumn(PeerListDelegate::COL_COUNT); + if (!Preferences().resolvePeerCountries()) + hideColumn(PeerListDelegate::COUNTRY); //To also migitate the above issue, we have to resize each column when //its size is 0, because explicitely 'showing' the column isn't enough //in the above scenario. @@ -370,9 +373,9 @@ QStandardItem* PeerListWidget::addPeer(const QString& ip, const peer_info& peer) if (m_displayFlags) { const QIcon ico = GeoIPManager::CountryISOCodeToIcon(peer.country); if (!ico.isNull()) { - m_listModel->setData(m_listModel->index(row, PeerListDelegate::IP), ico, Qt::DecorationRole); + m_listModel->setData(m_listModel->index(row, PeerListDelegate::COUNTRY), ico, Qt::DecorationRole); const QString country_name = GeoIPManager::CountryISOCodeToName(peer.country); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::IP), country_name, Qt::ToolTipRole); + m_listModel->setData(m_listModel->index(row, PeerListDelegate::COUNTRY), country_name, Qt::ToolTipRole); } else { m_missingFlags.insert(ip); } @@ -394,9 +397,9 @@ void PeerListWidget::updatePeer(const QString& ip, const peer_info& peer) { if (m_displayFlags) { const QIcon ico = GeoIPManager::CountryISOCodeToIcon(peer.country); if (!ico.isNull()) { - m_listModel->setData(m_listModel->index(row, PeerListDelegate::IP), ico, Qt::DecorationRole); + m_listModel->setData(m_listModel->index(row, PeerListDelegate::COUNTRY), ico, Qt::DecorationRole); const QString country_name = GeoIPManager::CountryISOCodeToName(peer.country); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::IP), country_name, Qt::ToolTipRole); + m_listModel->setData(m_listModel->index(row, PeerListDelegate::COUNTRY), country_name, Qt::ToolTipRole); m_missingFlags.remove(ip); } } @@ -420,7 +423,7 @@ void PeerListWidget::handleResolved(const QString &ip, const QString &hostname) void PeerListWidget::handleSortColumnChanged(int col) { - if (col == 0) { + if (col == PeerListDelegate::COUNTRY) { qDebug("Sorting by decoration"); m_proxyModel->setSortRole(Qt::ToolTipRole); } else { diff --git a/src/properties/peerlistwidget.h b/src/properties/peerlistwidget.h index 23a3d5271..a67da17e7 100644 --- a/src/properties/peerlistwidget.h +++ b/src/properties/peerlistwidget.h @@ -36,6 +36,7 @@ #include #include #include +#include "peerlistsortmodel.h" #include "qtorrenthandle.h" #include "misc.h" @@ -88,7 +89,7 @@ private: private: QStandardItemModel *m_listModel; PeerListDelegate *m_listDelegate; - QSortFilterProxyModel *m_proxyModel; + PeerListSortModel *m_proxyModel; QHash m_peerItems; QHash m_peerEndpoints; QSet m_missingFlags; diff --git a/src/properties/properties.pri b/src/properties/properties.pri index 48736b0e1..3072ee0d0 100644 --- a/src/properties/properties.pri +++ b/src/properties/properties.pri @@ -10,6 +10,7 @@ HEADERS += $$PWD/propertieswidget.h \ $$PWD/trackerlist.h \ $$PWD/downloadedpiecesbar.h \ $$PWD/peerlistdelegate.h \ + $$PWD/peerlistsortmodel.h \ $$PWD/peeraddition.h \ $$PWD/trackersadditiondlg.h \ $$PWD/pieceavailabilitybar.h \ From c8d51e91f415dcef4ce77569cb8d9ac794c41c5f Mon Sep 17 00:00:00 2001 From: Nick Tiskov Date: Sat, 6 Jul 2013 04:07:09 +0400 Subject: [PATCH 2/2] Remove obsolete IP_HIDDEN column from peer list. --- src/properties/peerlistdelegate.h | 2 +- src/properties/peerlistwidget.cpp | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/properties/peerlistdelegate.h b/src/properties/peerlistdelegate.h index 91120d1ef..fd66636ec 100644 --- a/src/properties/peerlistdelegate.h +++ b/src/properties/peerlistdelegate.h @@ -40,7 +40,7 @@ class PeerListDelegate: public QItemDelegate { public: enum PeerListColumns {COUNTRY, IP, CONNECTION, FLAGS, CLIENT, PROGRESS, DOWN_SPEED, UP_SPEED, - TOT_DOWN, TOT_UP, IP_HIDDEN, COL_COUNT}; + TOT_DOWN, TOT_UP, COL_COUNT}; public: PeerListDelegate(QObject *parent) : QItemDelegate(parent) {} diff --git a/src/properties/peerlistwidget.cpp b/src/properties/peerlistwidget.cpp index 358260da9..2ce1d4a6b 100644 --- a/src/properties/peerlistwidget.cpp +++ b/src/properties/peerlistwidget.cpp @@ -79,16 +79,15 @@ PeerListWidget::PeerListWidget(PropertiesWidget *parent): //Explicitly set the column visibility. When columns are added/removed //between versions this prevents some of them being hidden due to //incorrect restoreState() being used. - for (unsigned int i=0; imapToSource(index).row(); - QString myip = m_listModel->data(m_listModel->index(row, PeerListDelegate::IP_HIDDEN)).toString(); + QString myip = m_listModel->data(m_listModel->index(row, PeerListDelegate::IP)).toString(); selectedPeerIPs << myip; } // Add Peer Action @@ -369,7 +368,6 @@ QStandardItem* PeerListWidget::addPeer(const QString& ip, const peer_info& peer) // Adding Peer to peer list m_listModel->insertRow(row); m_listModel->setData(m_listModel->index(row, PeerListDelegate::IP), ip); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::IP_HIDDEN), ip); if (m_displayFlags) { const QIcon ico = GeoIPManager::CountryISOCodeToIcon(peer.country); if (!ico.isNull()) {