From 29a45f828f5d6a49a1a9a6b088a9d6cab00b3f9a Mon Sep 17 00:00:00 2001 From: Gluzskiy Alexandr Date: Sun, 8 Oct 2017 00:09:56 +0300 Subject: retroshare: pgpid ui performance patch --- .../retroshare/files/abstractitemmodel_test.patch | 1180 ++++++++++++++++++++ 1 file changed, 1180 insertions(+) create mode 100644 net-p2p/retroshare/files/abstractitemmodel_test.patch (limited to 'net-p2p/retroshare/files/abstractitemmodel_test.patch') diff --git a/net-p2p/retroshare/files/abstractitemmodel_test.patch b/net-p2p/retroshare/files/abstractitemmodel_test.patch new file mode 100644 index 0000000..0a3fde5 --- /dev/null +++ b/net-p2p/retroshare/files/abstractitemmodel_test.patch @@ -0,0 +1,1180 @@ +diff --git a/RetroShare.pro b/RetroShare.pro +index 833173029..d22af1418 100644 +--- a/RetroShare.pro ++++ b/RetroShare.pro +@@ -56,12 +56,6 @@ retroshare_qml_app { + } + } + +-retroshare_plugins { +- SUBDIRS += plugins +- plugins.file = plugins/plugins.pro +- plugins.depends = retroshare_gui +- plugins.target = plugins +-} + + wikipoos { + SUBDIRS += pegmarkdown +diff --git a/retroshare-gui/src/gui/NetworkDialog.cpp b/retroshare-gui/src/gui/NetworkDialog.cpp +index bdeda264c..76dc61aa4 100644 +--- a/retroshare-gui/src/gui/NetworkDialog.cpp ++++ b/retroshare-gui/src/gui/NetworkDialog.cpp +@@ -81,85 +81,67 @@ static const unsigned int ROLE_SORT = Qt::UserRole + 1 ; + + /** Constructor */ + NetworkDialog::NetworkDialog(QWidget *parent) +-: RsAutoUpdatePage(10000,parent) // updates every 10 sec. + { + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + +- connect( ui.connectTreeWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( connectTreeWidgetCostumPopupMenu( QPoint ) ) ); +- connect( ui.connectTreeWidget, SIGNAL( itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT( peerdetails () ) ); +- + connect( ui.filterLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(filterItems(QString))); + connect( ui.filterLineEdit, SIGNAL(filterChanged(int)), this, SLOT(filterColumnChanged(int))); + + connect( ui.onlyTrustedKeys, SIGNAL(clicked()), this, SLOT(securedUpdateDisplay())); + +- /* hide the Tree +/- */ +- ui.connectTreeWidget -> setRootIsDecorated( false ); +- ui.connectTreeWidget -> setColumnCount(6); + +- compareNetworkRole = new RSTreeWidgetItemCompareRole; +- compareNetworkRole->setRole(COLUMN_LAST_USED, ROLE_SORT); ++/* compareNetworkRole = new RSTreeWidgetItemCompareRole; ++ compareNetworkRole->setRole(COLUMN_LAST_USED, ROLE_SORT); */ ++ ++ //list data model ++ float f = QFontMetricsF(font()).height()/14.0 ; ++ PGPIdItemModel = new pgpid_item_model(neighs, f, this); ++ PGPIdItemProxy = new pgpid_item_proxy(this); ++ PGPIdItemProxy->setSourceModel(PGPIdItemModel); ++ PGPIdItemProxy->setFilterKeyColumn(COLUMN_PEERNAME); ++ PGPIdItemProxy->setFilterCaseSensitivity(Qt::CaseInsensitive); ++ ui.connectTreeWidget->setModel(PGPIdItemProxy); ++ ui.connectTreeWidget->setContextMenuPolicy(Qt::CustomContextMenu); ++ ui.connectTreeWidget->verticalHeader()->hide(); ++ ui.connectTreeWidget->setShowGrid(false); ++ ui.connectTreeWidget->setUpdatesEnabled(true); ++ ui.connectTreeWidget->setSortingEnabled(true); ++ ui.connectTreeWidget->setSelectionBehavior(QAbstractItemView::SelectRows); ++ connect(ui.connectTreeWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( connectTreeWidgetCostumPopupMenu( QPoint ) ) ); ++ connect(ui.connectTreeWidget, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(peerdetails())); ++ ++ + + /* Set header resize modes and initial section sizes */ +- QHeaderView * _header = ui.connectTreeWidget->header () ; ++/* QHeaderView * _header = ui.connectTreeWidget->header () ; + QHeaderView_setSectionResizeModeColumn(_header, COLUMN_CHECK, QHeaderView::Custom); + QHeaderView_setSectionResizeModeColumn(_header, COLUMN_PEERNAME, QHeaderView::Interactive); + QHeaderView_setSectionResizeModeColumn(_header, COLUMN_I_AUTH_PEER, QHeaderView::Interactive); + QHeaderView_setSectionResizeModeColumn(_header, COLUMN_PEER_AUTH_ME, QHeaderView::Interactive); + QHeaderView_setSectionResizeModeColumn(_header, COLUMN_PEERID, QHeaderView::Interactive); +- QHeaderView_setSectionResizeModeColumn(_header, COLUMN_LAST_USED, QHeaderView::Interactive); +- +- _header->model()->setHeaderData(COLUMN_CHECK, Qt::Horizontal, tr("")); +- _header->model()->setHeaderData(COLUMN_PEERNAME, Qt::Horizontal, tr("Profile")); +- _header->model()->setHeaderData(COLUMN_I_AUTH_PEER, Qt::Horizontal, tr("Trust level")); +- _header->model()->setHeaderData(COLUMN_PEER_AUTH_ME, Qt::Horizontal, tr("Has signed your key?")); +- _header->model()->setHeaderData(COLUMN_PEERID, Qt::Horizontal, tr("Id")); +- _header->model()->setHeaderData(COLUMN_LAST_USED, Qt::Horizontal, tr("Last used")); +- +- _header->model()->setHeaderData(COLUMN_CHECK, Qt::Horizontal, tr(" Do you accept connections signed by this profile?"),Qt::ToolTipRole); +- _header->model()->setHeaderData(COLUMN_PEERNAME, Qt::Horizontal, tr("Name of the profile"),Qt::ToolTipRole); +- _header->model()->setHeaderData(COLUMN_I_AUTH_PEER, Qt::Horizontal, tr("This column indicates trust level and whether you signed the profile PGP key"),Qt::ToolTipRole); +- _header->model()->setHeaderData(COLUMN_PEER_AUTH_ME, Qt::Horizontal, tr("Did that peer sign your own profile PGP key"),Qt::ToolTipRole); +- _header->model()->setHeaderData(COLUMN_PEERID, Qt::Horizontal, tr("PGP Key Id of that profile"),Qt::ToolTipRole); +- _header->model()->setHeaderData(COLUMN_LAST_USED, Qt::Horizontal, tr("Last time this key was used (received time, or to check connection)"),Qt::ToolTipRole); ++ QHeaderView_setSectionResizeModeColumn(_header, COLUMN_LAST_USED, QHeaderView::Interactive); */ + +- float f = QFontMetricsF(font()).height()/14.0 ; +- +- _header->resizeSection ( COLUMN_CHECK, 25*f ); +- _header->resizeSection ( COLUMN_PEERNAME, 200*f ); +- _header->resizeSection ( COLUMN_I_AUTH_PEER, 200*f ); +- _header->resizeSection ( COLUMN_PEER_AUTH_ME, 200*f ); +- _header->resizeSection ( COLUMN_LAST_USED, 75*f ); + +- // set header text aligment +- QTreeWidgetItem * headerItem = ui.connectTreeWidget->headerItem(); +- headerItem->setTextAlignment(COLUMN_CHECK, Qt::AlignHCenter | Qt::AlignVCenter); +- headerItem->setTextAlignment(COLUMN_PEERNAME, Qt::AlignHCenter | Qt::AlignVCenter); +- headerItem->setTextAlignment(COLUMN_I_AUTH_PEER, Qt::AlignHCenter | Qt::AlignVCenter); +- headerItem->setTextAlignment(COLUMN_PEER_AUTH_ME, Qt::AlignHCenter | Qt::AlignVCenter); +- headerItem->setTextAlignment(COLUMN_PEERID, Qt::AlignVCenter); +- headerItem->setTextAlignment(COLUMN_LAST_USED, Qt::AlignVCenter); +- +- headerItem->setText(0,QString()) ; ++ ui.onlyTrustedKeys->setMinimumWidth(20*f); + +- ui.connectTreeWidget->sortItems( COLUMN_PEERNAME, Qt::AscendingOrder ); + +- ui.onlyTrustedKeys->setMinimumWidth(20*f); + +- QMenu *menu = new QMenu(); ++/* QMenu *menu = new QMenu(); + menu->addAction(ui.actionTabsright); + menu->addAction(ui.actionTabswest); + menu->addAction(ui.actionTabssouth); + menu->addAction(ui.actionTabsnorth); + menu->addSeparator(); + menu->addAction(ui.actionTabsTriangular); +- menu->addAction(ui.actionTabsRounded); ++ menu->addAction(ui.actionTabsRounded); */ + + /* add filter actions */ + ui.filterLineEdit->addFilter(QIcon(), tr("Name"), COLUMN_PEERNAME, tr("Search name")); + ui.filterLineEdit->addFilter(QIcon(), tr("Peer ID"), COLUMN_PEERID, tr("Search peer ID")); + ui.filterLineEdit->setCurrentFilter(COLUMN_PEERNAME); ++ connect(ui.filterLineEdit, SIGNAL(textChanged(QString)), PGPIdItemProxy, SLOT(setFilterWildcard(QString))); ++ + } + + void NetworkDialog::changeEvent(QEvent *e) +@@ -177,14 +159,14 @@ void NetworkDialog::changeEvent(QEvent *e) + + void NetworkDialog::connectTreeWidgetCostumPopupMenu( QPoint /*point*/ ) + { +- //std::cerr << "NetworkDialog::connectTreeWidgetCostumPopupMenu( QPoint point ) called" << std::endl; +- QTreeWidgetItem *wi = getCurrentNeighbour(); +- if (!wi) +- return; ++ ++ QModelIndexList l = ui.connectTreeWidget->selectionModel()->selection().indexes(); ++ if(l.empty()) ++ return; + + QMenu *contextMnu = new QMenu; + +- RsPgpId peer_id(wi->text(COLUMN_PEERID).toStdString()) ; ++ RsPgpId peer_id(ui.connectTreeWidget->model()->data(ui.connectTreeWidget->model()->index(l.begin()->row(), COLUMN_PEERID)).toString().toStdString()) ; + + // That's what context menus are made for + RsPeerDetails detail; +@@ -276,8 +258,11 @@ void NetworkDialog::removeUnusedKeys() + + void NetworkDialog::denyFriend() + { +- QTreeWidgetItem *wi = getCurrentNeighbour(); +- RsPgpId peer_id( wi->text(COLUMN_PEERID).toStdString() ); ++ QModelIndexList l = ui.connectTreeWidget->selectionModel()->selection().indexes(); ++ if(l.empty()) ++ return; ++ ++ RsPgpId peer_id(ui.connectTreeWidget->model()->data(ui.connectTreeWidget->model()->index(l.begin()->row(), COLUMN_PEERID)).toString().toStdString()); + rsPeers->removeFriend(peer_id) ; + + securedUpdateDisplay(); +@@ -300,27 +285,32 @@ void NetworkDialog::denyFriend() + + void NetworkDialog::makeFriend() + { +- PGPKeyDialog::showIt(RsPgpId(getCurrentNeighbour()->text(COLUMN_PEERID).toStdString()), PGPKeyDialog::PageDetails); ++ ++ QModelIndexList l = ui.connectTreeWidget->selectionModel()->selection().indexes(); ++ if(l.empty()) ++ return; ++ ++ PGPKeyDialog::showIt(RsPgpId(ui.connectTreeWidget->model()->data(ui.connectTreeWidget->model()->index(l.begin()->row(), COLUMN_PEERID)).toString().toStdString()), PGPKeyDialog::PageDetails); + } + + /** Shows Peer Information/Auth Dialog */ + void NetworkDialog::peerdetails() + { +- QTreeWidgetItem* item = getCurrentNeighbour(); +- if (item == NULL) { +- return; +- } +- PGPKeyDialog::showIt(RsPgpId(item->text(COLUMN_PEERID).toStdString()), PGPKeyDialog::PageDetails); ++ QModelIndexList l = ui.connectTreeWidget->selectionModel()->selection().indexes(); ++ if(l.empty()) ++ return; ++ ++ PGPKeyDialog::showIt(RsPgpId(ui.connectTreeWidget->model()->data(ui.connectTreeWidget->model()->index(l.begin()->row(), COLUMN_PEERID)).toString().toStdString()), PGPKeyDialog::PageDetails); + } + + void NetworkDialog::copyLink() + { +- QTreeWidgetItem *wi = getCurrentNeighbour(); +- if (wi == NULL) { +- return; +- } ++ QModelIndexList l = ui.connectTreeWidget->selectionModel()->selection().indexes(); ++ if(l.empty()) ++ return; + +- RsPgpId peer_id ( wi->text(COLUMN_PEERID).toStdString() ) ; ++ ++ RsPgpId peer_id (ui.connectTreeWidget->model()->data(ui.connectTreeWidget->model()->index(l.begin()->row(), COLUMN_PEERID)).toString().toStdString()) ; + + QList urls; + RetroShareLink link = RetroShareLink::createPerson(peer_id); +@@ -356,137 +346,39 @@ void NetworkDialog::copyLink() + // /* window will destroy itself! */ + //} + +-void NetworkDialog::updateDisplay() +-{ +- insertConnect() ; +-} +- + /* get the list of Neighbours from the RsIface. */ + void NetworkDialog::insertConnect() + { + // static time_t last_time = 0 ; + +- if (!rsPeers) +- return; +- +-// // Because this is called from a qt signal, there's no limitation between calls. +- time_t now = time(NULL); ++// if (!rsPeers) ++// return; + +- std::list neighs; //these are GPG ids +- std::list::iterator it; +- rsPeers->getGPGAllList(neighs); ++ //these are GPG ids ++// std::list::iterator it; ++// rsPeers->getGPGAllList(neighs); + + /* get a link to the table */ +- QTreeWidget *connectWidget = ui.connectTreeWidget; ++// QTreeView *connectWidget = ui.connectTreeWidget; + /* disable sorting while editing the table */ +- connectWidget->setSortingEnabled(false); ++// connectWidget->setSortingEnabled(false); + + //remove items +- int index = 0; +- while (index < connectWidget->topLevelItemCount()) +- { +- RsPgpId gpg_widget_id( (connectWidget->topLevelItem(index))->text(COLUMN_PEERID).toStdString() ); +- RsPeerDetails detail; +- if ( (!rsPeers->getGPGDetails(gpg_widget_id, detail)) || (ui.onlyTrustedKeys->isChecked() && (detail.validLvl < RS_TRUST_LVL_MARGINAL && !detail.accept_connection))) +- delete (connectWidget->takeTopLevelItem(index)); +- else +- ++index; +- } ++// int index = 0; + +- for(it = neighs.begin(); it != neighs.end(); ++it) +- { ++/* for(it = neighs.begin(); it != neighs.end(); ++it) ++ { + #ifdef NET_DEBUG + std::cerr << "NetworkDialog::insertConnect() inserting gpg key : " << *it << std::endl; +-#endif +- if (*it == rsPeers->getGPGOwnId()) { +- continue; +- } +- +- RsPeerDetails detail; +- if (!rsPeers->getGPGDetails(*it, detail)) +- { +- continue; /* BAD */ +- } +- +- /* make a widget per friend */ +- QTreeWidgetItem *item; +- QList list = connectWidget->findItems(QString::fromStdString( (*it).toStdString() ), Qt::MatchExactly, COLUMN_PEERID); +- if (list.size() == 1) { +- item = list.front(); +- } else { +- //create new item +-#ifdef NET_DEBUG +- std::cerr << "NetworkDialog::insertConnect() creating new tree widget item : " << *it << std::endl; +-#endif +- item = new RSTreeWidgetItem(compareNetworkRole, 0); +- item -> setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless); +- +- int S = QFontMetricsF(font()).height() ; +- item -> setSizeHint(COLUMN_CHECK, QSize( S,S ) ); +- +- /* (1) Person */ +- item -> setText(COLUMN_PEERNAME, QString::fromUtf8(detail.name.c_str())); +- +- /* (4) key id */ +- item -> setText(COLUMN_PEERID, QString::fromStdString(detail.gpg_id.toStdString())); +- } +- +- //QString TrustLevelString ; +- +- /* (2) Key validity */ +- if (detail.ownsign) +- { +- item -> setText(COLUMN_I_AUTH_PEER, tr("Personal signature")); +- item -> setToolTip(COLUMN_I_AUTH_PEER, tr("PGP key signed by you")); +- } +- else +- switch(detail.trustLvl) +- { +- case RS_TRUST_LVL_MARGINAL: item->setText(COLUMN_I_AUTH_PEER,tr("Marginally trusted peer")) ; break; +- case RS_TRUST_LVL_FULL: +- case RS_TRUST_LVL_ULTIMATE: item->setText(COLUMN_I_AUTH_PEER,tr("Fully trusted peer")) ; break ; +- case RS_TRUST_LVL_UNKNOWN: +- case RS_TRUST_LVL_UNDEFINED: +- case RS_TRUST_LVL_NEVER: +- default: item->setText(2,tr("Untrusted peer")) ; break ; +- } +- +- /* (3) has me auth */ +- QString PeerAuthenticationString ; +- +- if (detail.hasSignedMe) +- PeerAuthenticationString = tr("Yes"); +- else +- PeerAuthenticationString = tr("No"); +- +- item->setText(COLUMN_PEER_AUTH_ME,PeerAuthenticationString) ; +- +- uint64_t last_time_used = now - detail.lastUsed ; +- QString lst_used_str ; +- +- if(last_time_used < 3600) +- lst_used_str = tr("Last hour") ; +- else if(last_time_used < 86400) +- lst_used_str = tr("Today") ; +- else if(last_time_used > 86400 * 15000) +- lst_used_str = tr("Never"); +- else +- lst_used_str = tr("%1 days ago").arg((int)( last_time_used / 86400 )) ; +- +- QString lst_used_sort_str = QString::number(detail.lastUsed,'f',10); +- +- item->setText(COLUMN_LAST_USED,lst_used_str) ; +- item->setData(COLUMN_LAST_USED,ROLE_SORT,lst_used_sort_str) ; ++#endif */ + + /** + * Determinated the Background Color + */ +- QColor backgrndcolor; ++/* QColor backgrndcolor; + + if (detail.accept_connection) + { +- item -> setText(COLUMN_CHECK, "0"); +- item -> setIcon(COLUMN_CHECK,(QIcon(IMAGE_AUTHED))); + if (detail.ownsign) + { + backgrndcolor = backgroundColorOwnSign(); +@@ -498,19 +390,14 @@ void NetworkDialog::insertConnect() + } + else + { +- item -> setText(COLUMN_CHECK, "1"); + + if (detail.hasSignedMe) + { + backgrndcolor = backgroundColorHasSignedMe(); +- item -> setIcon(COLUMN_CHECK,(QIcon(IMAGE_DENIED))); +- for(int k=0;k setToolTip(k, QString::fromUtf8(detail.name.c_str()) + tr(" has authenticated you. \nRight-click and select 'make friend' to be able to connect.")); + } + else + { + backgrndcolor = backgroundColorDenied(); +- item -> setIcon(COLUMN_CHECK,(QIcon(IMAGE_DENIED))); + } + } + +@@ -520,14 +407,14 @@ void NetworkDialog::insertConnect() + item -> setBackground(i,QBrush(backgrndcolor)); + + if( (detail.accept_connection || detail.validLvl >= RS_TRUST_LVL_MARGINAL) || !ui.onlyTrustedKeys->isChecked()) +- connectWidget->addTopLevelItem(item); +- } ++ connectWidget->addTopLevelItem(item); */ ++// } + + // add self to network. +- RsPeerDetails ownGPGDetails; +- rsPeers->getGPGDetails(rsPeers->getGPGOwnId(), ownGPGDetails); ++// RsPeerDetails ownGPGDetails; ++// rsPeers->getGPGDetails(rsPeers->getGPGOwnId(), ownGPGDetails); + /* make a widget per friend */ +- QTreeWidgetItem *self_item; ++/* QTreeWidgetItem *self_item; + QList list = connectWidget->findItems(QString::fromStdString(ownGPGDetails.gpg_id.toStdString()), Qt::MatchExactly, COLUMN_PEERID); + if (list.size() == 1) { + self_item = list.front(); +@@ -546,28 +433,19 @@ void NetworkDialog::insertConnect() + { + self_item->setBackground(i,backgroundColorSelf()) ; + } +- connectWidget->addTopLevelItem(self_item); ++ connectWidget->addTopLevelItem(self_item); */ + + /* enable sorting */ +- connectWidget->setSortingEnabled(true); ++// connectWidget->setSortingEnabled(true); + /* update display */ +- connectWidget->update(); ++// connectWidget->update(); + +- if (ui.filterLineEdit->text().isEmpty() == false) { +- filterItems(ui.filterLineEdit->text()); +- } ++// if (ui.filterLineEdit->text().isEmpty() == false) { ++// filterItems(ui.filterLineEdit->text()); ++// } + + } + +-QTreeWidgetItem *NetworkDialog::getCurrentNeighbour() +-{ +- if (ui.connectTreeWidget->selectedItems().size() != 0) +- { +- return ui.connectTreeWidget -> currentItem(); +- } +- +- return NULL; +-} + + /* Utility Fns */ + RsPeerId getNeighRsCertId(QTreeWidgetItem *i) +@@ -700,12 +578,14 @@ void NetworkDialog::on_actionCreate_New_Profile_activated() + // Settings->endGroup(); + // } + +-void NetworkDialog::filterColumnChanged(int) ++void NetworkDialog::filterColumnChanged(int col) + { +- filterItems(ui.filterLineEdit->text()); ++ if(PGPIdItemProxy) ++ PGPIdItemProxy->setFilterKeyColumn(col); ++ //filterItems(ui.filterLineEdit->text()); + } + +-void NetworkDialog::filterItems(const QString &text) ++/*void NetworkDialog::filterItems(const QString &text) + { + int filterColumn = ui.filterLineEdit->currentFilter(); + +@@ -713,7 +593,7 @@ void NetworkDialog::filterItems(const QString &text) + for (int index = 0; index < count; ++index) { + filterItem(ui.connectTreeWidget->topLevelItem(index), text, filterColumn); + } +-} ++}*/ + + bool NetworkDialog::filterItem(QTreeWidgetItem *item, const QString &text, int filterColumn) + { +@@ -741,3 +621,15 @@ bool NetworkDialog::filterItem(QTreeWidgetItem *item, const QString &text, int f + + return (visible || visibleChildCount); + } ++ ++void NetworkDialog::updateDisplay() ++{ ++ if (!rsPeers) ++ return; ++ //update ids list ++ std::list new_neighs; ++ rsPeers->getGPGAllList(new_neighs); ++ //refresh model ++ PGPIdItemModel->data_updated(new_neighs); ++} ++ +diff --git a/retroshare-gui/src/gui/NetworkDialog.h b/retroshare-gui/src/gui/NetworkDialog.h +index 2d90e98e7..084b04126 100644 +--- a/retroshare-gui/src/gui/NetworkDialog.h ++++ b/retroshare-gui/src/gui/NetworkDialog.h +@@ -25,6 +25,11 @@ + + #include "ui_NetworkDialog.h" + #include "RsAutoUpdatePage.h" ++#include "gui/NetworkDialog/pgpid_item_model.h" ++#include "gui/NetworkDialog/pgpid_item_proxy.h" ++ ++//tmp ++class QTreeWidgetItem; + + class RSTreeWidgetItemCompareRole ; + +@@ -42,9 +47,8 @@ public: + /** Default Constructor */ + NetworkDialog(QWidget *parent = 0); + +- //void load(); + virtual void updateDisplay() ; // overloaded from RsAutoUpdatePage +- ++ + QColor backgroundColorSelf() const { return mBackgroundColorSelf; } + QColor backgroundColorOwnSign() const { return mBackgroundColorOwnSign; } + QColor backgroundColorAcceptConnection() const { return mBackgroundColorAcceptConnection; } +@@ -68,7 +72,7 @@ protected: + + private slots: + +- void removeUnusedKeys() ; ++ void removeUnusedKeys() ; + void makeFriend() ; + void denyFriend() ; + // void deleteCert() ; +@@ -104,10 +108,11 @@ private slots: + // void on_actionTabsTriangular_activated(); + + void filterColumnChanged(int); +- void filterItems(const QString &text); ++// void filterItems(const QString &text); ++ ++ + + private: +- QTreeWidgetItem *getCurrentNeighbour(); + + // class NetworkView *networkview; + +@@ -122,6 +127,12 @@ private: + + RSTreeWidgetItemCompareRole *compareNetworkRole ; + ++ //iinternal long lived data ++ std::list neighs; ++ ++ pgpid_item_model *PGPIdItemModel; ++ pgpid_item_proxy *PGPIdItemProxy; ++ + /** Qt Designer generated object */ + Ui::NetworkDialog ui; + }; +diff --git a/retroshare-gui/src/gui/NetworkDialog.ui b/retroshare-gui/src/gui/NetworkDialog.ui +index 3c0fb4c93..833fb542b 100644 +--- a/retroshare-gui/src/gui/NetworkDialog.ui ++++ b/retroshare-gui/src/gui/NetworkDialog.ui +@@ -41,7 +41,7 @@ + + Qt::Vertical + +- ++ + + + 0 +@@ -66,63 +66,6 @@ + 16 + + +- +- true +- +- +- true +- +- +- true +- +- +- true +- +- +- true +- +- +- true +- +- +- 200 +- +- +- true +- +- +- +- +- +- +- +- +- Profile +- +- +- +- +- Did I authenticated peer +- +- +- Did I sign his PGP key +- +- +- +- +- Has signed my key +- +- +- +- +- Cert Id +- +- +- +- +- Last used +- +- + + + +diff --git a/retroshare-gui/src/gui/NetworkDialog/pgpid_item_model.cpp b/retroshare-gui/src/gui/NetworkDialog/pgpid_item_model.cpp +new file mode 100644 +index 000000000..e6f9eaa90 +--- /dev/null ++++ b/retroshare-gui/src/gui/NetworkDialog/pgpid_item_model.cpp +@@ -0,0 +1,375 @@ ++#include "pgpid_item_model.h" ++#include ++#include ++ ++#define IMAGE_AUTHED ":/images/accepted16.png" ++#define IMAGE_DENIED ":/images/denied16.png" ++#define IMAGE_TRUSTED ":/images/rs-2.png" ++ ++/*TODO: ++ * using list here for internal data storage is not best options ++*/ ++pgpid_item_model::pgpid_item_model(std::list &neighs_, float &_font_height, QObject *parent) ++ : QAbstractTableModel(parent), neighs(neighs_), font_height(_font_height) ++{ ++} ++ ++QVariant pgpid_item_model::headerData(int section, Qt::Orientation orientation, int role) const ++{ ++ if(orientation == Qt::Horizontal) ++ { ++ if(role == Qt::ToolTipRole) ++ { ++ switch(section) ++ { ++ case COLUMN_CHECK: ++ return QString(tr(" Do you accept connections signed by this profile?")); ++ break; ++ case COLUMN_PEERNAME: ++ return QString(tr("Name of the profile")); ++ break; ++ case COLUMN_I_AUTH_PEER: ++ return QString(tr("This column indicates trust level and whether you signed the profile PGP key")); ++ break; ++ case COLUMN_PEER_AUTH_ME: ++ return QString(tr("Did that peer sign your own profile PGP key")); ++ break; ++ case COLUMN_PEERID: ++ return QString(tr("PGP Key Id of that profile")); ++ break; ++ case COLUMN_LAST_USED: ++ return QString(tr("Last time this key was used (received time, or to check connection)")); ++ break; ++ } ++ } ++ else if(role == Qt::DisplayRole) ++ { ++ switch(section) ++ { ++ case COLUMN_CHECK: ++ return QString(tr("")); ++ break; ++ case COLUMN_PEERNAME: ++ return QString(tr("Profile")); ++ break; ++ case COLUMN_I_AUTH_PEER: ++ return QString(tr("Trust level")); ++ break; ++ case COLUMN_PEER_AUTH_ME: ++ return QString(tr("Has signed your key?")); ++ break; ++ case COLUMN_PEERID: ++ return QString(tr("Id")); ++ break; ++ case COLUMN_LAST_USED: ++ return QString(tr("Last used")); ++ break; ++ } ++ } ++ else if (role == Qt::TextAlignmentRole) ++ { ++ switch(section) ++ { ++ default: ++ return (uint32_t)(Qt::AlignHCenter | Qt::AlignVCenter); ++ break; ++ } ++ } ++ else if(role == Qt::SizeHintRole) ++ { ++ switch(section) ++ { ++ case COLUMN_CHECK: ++ return 25*font_height; ++ break; ++ case COLUMN_PEERNAME: case COLUMN_I_AUTH_PEER: case COLUMN_PEER_AUTH_ME: ++ return 200*font_height; ++ break; ++ case COLUMN_LAST_USED: ++ return 75*font_height; ++ break; ++ } ++ ++ } ++ } ++ return QVariant(); ++} ++ ++/*QModelIndex pgpid_item_model::index(int row, int column, const QModelIndex &parent) const ++{ ++ return createIndex(row, column); ++}*/ ++ ++/*QModelIndex pgpid_item_model::parent(const QModelIndex &index) const ++{ ++ if(index.row() > -1 && index.column() > -1) ++ return createIndex(-1, -1); ++ if (!index.isValid()) ++ return QModelIndex(); ++ return QModelIndex(); ++}*/ ++ ++/*bool pgpid_item_model::hasChildren(const QModelIndex &parent) const ++{ ++ if(parent.column() == -1 && parent.row() == -1) ++ return true; ++ return false; ++} */ ++ ++int pgpid_item_model::rowCount(const QModelIndex &/*parent*/) const ++{ ++ return neighs.size(); ++} ++ ++int pgpid_item_model::columnCount(const QModelIndex &/*parent*/) const ++{ ++ return COLUMN_COUNT; ++} ++ ++//bool pgpid_item_model::insertRows(int position, int rows, const QModelIndex &/*index*/) ++//{ ++// beginInsertRows(QModelIndex(), position, position+rows-1); ++// endInsertRows(); ++// return true; ++//} ++ ++//bool pgpid_item_model::removeRows(int position, int rows, const QModelIndex &/*index*/) ++//{ ++// beginRemoveRows(QModelIndex(), position, position+rows-1); ++// endRemoveRows(); ++// return true; ++//} ++ ++ ++QVariant pgpid_item_model::data(const QModelIndex &index, int role) const ++{ ++ if (!index.isValid()) ++ return QVariant(); ++ ++ if((unsigned)index.row() >= neighs.size()) ++ return QVariant(); ++ ++ ++ //shit code (please rewrite it) ++ ++ std::list::iterator it = neighs.begin(); ++ for(int i = 0; i < index.row(); i++) ++ it++; ++ RsPeerDetails detail; ++ if (!rsPeers->getGPGDetails(*it, detail)) ++ return QVariant(); ++ //shit code end ++ if(role == Qt::DisplayRole) ++ { ++ switch(index.column()) ++ { ++ case COLUMN_PEERNAME: ++ return QString::fromUtf8(detail.name.c_str()); ++ break; ++ case COLUMN_PEERID: ++ return QString::fromStdString(detail.gpg_id.toStdString()); ++ break; ++ case COLUMN_I_AUTH_PEER: ++ { ++ if (detail.ownsign) ++ return tr("Personal signature"); ++ else ++ { ++ switch(detail.trustLvl) ++ { ++ case RS_TRUST_LVL_MARGINAL: return tr("Marginally trusted peer") ; break; ++ case RS_TRUST_LVL_FULL: ++ case RS_TRUST_LVL_ULTIMATE: return tr("Fully trusted peer") ; break ; ++ case RS_TRUST_LVL_UNKNOWN: ++ case RS_TRUST_LVL_UNDEFINED: ++ case RS_TRUST_LVL_NEVER: ++ default: return tr("Untrusted peer") ; break ; ++ } ++ } ++ } ++ break; ++ case COLUMN_PEER_AUTH_ME: ++ { ++ if (detail.hasSignedMe) ++ return tr("Yes"); ++ else ++ return tr("No"); ++ } ++ break; ++ case COLUMN_LAST_USED: ++ { ++ time_t now = time(NULL); ++ uint64_t last_time_used = now - detail.lastUsed ; ++ QString lst_used_str ; ++ ++ if(last_time_used < 3600) ++ lst_used_str = tr("Last hour") ; ++ else if(last_time_used < 86400) ++ lst_used_str = tr("Today") ; ++ else if(last_time_used > 86400 * 15000) ++ lst_used_str = tr("Never"); ++ else ++ lst_used_str = tr("%1 days ago").arg((int)( last_time_used / 86400 )) ; ++ ++// QString lst_used_sort_str = QString::number(detail.lastUsed,'f',10); ++ ++ return lst_used_str; ++// item->setData(COLUMN_LAST_USED,ROLE_SORT,lst_used_sort_str) ; ++ } ++ break; ++ case COLUMN_CHECK: ++ { ++ if (detail.accept_connection) ++ { ++ return QString("0"); ++ } ++ else ++ { ++ return QString("1"); ++ } ++ } ++ break; ++ ++ ++ } ++ } ++ else if(role == Qt::ToolTipRole) ++ { ++ switch(index.column()) ++ { ++ case COLUMN_I_AUTH_PEER: ++ { ++ if (detail.ownsign) ++ return tr("PGP key signed by you"); ++ } ++ break; ++ default: ++ { ++ if (!detail.accept_connection && detail.hasSignedMe) ++ { ++ return QString::fromUtf8(detail.name.c_str()) + tr(" has authenticated you. \nRight-click and select 'make friend' to be able to connect."); ++ } ++ } ++ break; ++ ++ } ++ } ++ else if(role == Qt::DecorationRole) ++ { ++ switch(index.column()) ++ { ++ case COLUMN_CHECK: ++ { ++ if (detail.accept_connection) ++ return QIcon(IMAGE_AUTHED); ++ else ++ return QIcon(IMAGE_DENIED); ++ ++ } ++ break; ++ } ++ } ++ else if(role == Qt::BackgroundRole) ++ { ++ switch(index.column()) ++ { ++ default: ++ { ++ //TODO: add access to bckground colors from networkdialog ++ if (detail.accept_connection) ++ { ++ if (detail.ownsign) ++ ; ++ } ++ } ++ break; ++ ++ } ++ } ++ ++ ++ return QVariant(); ++} ++ ++/*void pgpid_item_model::sort(int column, Qt::SortOrder order) ++{ ++ ++} */ ++ ++ ++//following code is just a poc, it's still suboptimal, unefficient, but much better then existing rs code ++ ++void pgpid_item_model::data_updated(std::list &new_neighs) ++{ ++ ++ //shit code follow (rewrite this please) ++ size_t old_size = neighs.size(), new_size = 0; ++ std::list old_neighs = neighs; ++ ++ //find all bad elements in list ++ std::list bad_elements; ++ for(std::list::iterator it = new_neighs.begin(); it != new_neighs.end(); ++it) ++ { ++ if (*it == rsPeers->getGPGOwnId()) ++ bad_elements.push_back(*it); ++ RsPeerDetails detail; ++ if (!rsPeers->getGPGDetails(*it, detail)) ++ bad_elements.push_back(*it); ++ ++ } ++ //remove all bad elements from list ++ for(std::list::iterator it = bad_elements.begin(); it != bad_elements.end(); ++it) ++ { ++ std::list::iterator it2 = std::find(new_neighs.begin(), new_neighs.end(), *it); ++ if(it2 != new_neighs.end()) ++ new_neighs.remove(*it2); ++ } ++ new_size = new_neighs.size(); ++ //set model data to new cleaned up data ++ neighs = new_neighs; ++ ++ //reflect actual row count in model ++ if(old_size < new_size) ++ { ++ beginInsertRows(QModelIndex(), old_size - 1, old_size - 1 + new_size - old_size); ++ insertRows(old_size - 1 , new_size - old_size); ++ endInsertRows(); ++ } ++ else if(new_size < old_size) ++ { ++ beginRemoveRows(QModelIndex(), new_size - 1, new_size - 1 + old_size - new_size); ++ removeRows(old_size - 1, old_size - new_size); ++ endRemoveRows(); ++ } ++ //update data in ui, to avoid unnecessary redraw and ui updates, updating only changed elements ++ //i guessing what order is unchanged between rsPeers->getGPGAllList() calls ++ //TODO: libretroshare should implement a way to obtain only changed elements via some signalling non-blocking api. ++ { ++ size_t ii1 = 0; ++ for(auto i1 = neighs.begin(), end1 = neighs.end(), i2 = old_neighs.begin(), end2 = old_neighs.end(); i1 != end1; ++i1, ++i2, ii1++) ++ { ++ if(i2 == end2) ++ break; ++ if(*i1 != *i2) ++ { ++ QModelIndex topLeft = createIndex(ii1,0), bottomRight = createIndex(ii1, COLUMN_COUNT-1); ++ emit dataChanged(topLeft, bottomRight); ++ } ++ } ++ } ++ if(new_size > old_size) ++ { ++ QModelIndex topLeft = createIndex(old_size ? old_size -1 : 0 ,0), bottomRight = createIndex(new_size -1, COLUMN_COUNT-1); ++ emit dataChanged(topLeft, bottomRight); ++ } ++ //dirty solution for initial data fetch ++ //TODO: do it properly! ++ if(!old_size) ++ { ++ beginResetModel(); ++ endResetModel(); ++ } ++ ++ //shit code end ++} ++ +diff --git a/retroshare-gui/src/gui/NetworkDialog/pgpid_item_model.h b/retroshare-gui/src/gui/NetworkDialog/pgpid_item_model.h +new file mode 100644 +index 000000000..84bae523b +--- /dev/null ++++ b/retroshare-gui/src/gui/NetworkDialog/pgpid_item_model.h +@@ -0,0 +1,48 @@ ++#ifndef KEY_ITEM_MODEL_H ++#define KEY_ITEM_MODEL_H ++ ++#include ++#include ++ ++#define COLUMN_CHECK 0 ++#define COLUMN_PEERNAME 1 ++#define COLUMN_I_AUTH_PEER 2 ++#define COLUMN_PEER_AUTH_ME 3 ++#define COLUMN_PEERID 4 ++#define COLUMN_LAST_USED 5 ++#define COLUMN_COUNT 6 ++ ++ ++class pgpid_item_model : public QAbstractTableModel ++{ ++ Q_OBJECT ++ ++public: ++ explicit pgpid_item_model(std::list &neighs, float &font_height, QObject *parent = nullptr); ++ ++ // Header: ++ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; ++ ++ // Basic functionality: ++// QModelIndex index(int row, int column, ++// const QModelIndex &parent = QModelIndex()) const override; ++// QModelIndex parent(const QModelIndex &index) const override; ++// bool hasChildren(const QModelIndex &parent = QModelIndex()) const override; ++ ++ int rowCount(const QModelIndex &parent = QModelIndex()) const override; ++ int columnCount(const QModelIndex &parent = QModelIndex()) const override; ++// bool insertRows(int position, int rows, const QModelIndex &index = QModelIndex()) override; ++// bool removeRows(int position, int rows, const QModelIndex &index = QModelIndex()) override; ++ ++ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; ++ ++// void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override; ++public slots: ++ void data_updated(std::list &new_neighs); ++ ++private: ++ std::list &neighs; ++ float &font_height; ++}; ++ ++#endif // KEY_ITEM_MODEL_H +diff --git a/retroshare-gui/src/gui/NetworkDialog/pgpid_item_proxy.cpp b/retroshare-gui/src/gui/NetworkDialog/pgpid_item_proxy.cpp +new file mode 100644 +index 000000000..da42db568 +--- /dev/null ++++ b/retroshare-gui/src/gui/NetworkDialog/pgpid_item_proxy.cpp +@@ -0,0 +1,50 @@ ++#include "pgpid_item_proxy.h" ++ ++pgpid_item_proxy::pgpid_item_proxy(QObject *parent) : ++ //QAbstractProxyModel(parent) ++ QSortFilterProxyModel(parent) ++{ ++ ++} ++ ++ ++/*QModelIndex pgpid_item_proxy::mapFromSource(const QModelIndex &sourceIndex) const ++{ ++ if(sourceIndex.isValid()) ++ return createIndex(sourceIndex.row(), sourceIndex.column(), sourceIndex.internalPointer()); ++ else ++ return QModelIndex(); ++} ++ ++ ++QModelIndex pgpid_item_proxy::mapToSource(const QModelIndex &proxyIndex) const ++{ ++ if(proxyIndex.isValid()) ++ return sourceModel()->index(proxyIndex.row(), proxyIndex.column()); ++ else ++ return QModelIndex();} ++ ++ ++QModelIndex pgpid_item_proxy::index(int row, int column, const QModelIndex &parent) const ++{ ++ const QModelIndex sourceParent = mapToSource(parent); ++ const QModelIndex sourceIndex = sourceModel()->index(row, column, sourceParent); ++ return mapFromSource(sourceIndex); ++} ++ ++QModelIndex pgpid_item_proxy::parent(const QModelIndex &child) const ++{ ++ const QModelIndex sourceIndex = mapToSource(child); ++ const QModelIndex sourceParent = sourceIndex.parent(); ++ return mapFromSource(sourceParent); ++} ++int pgpid_item_proxy::rowCount(const QModelIndex &parent) const ++{ ++ //TODO: ++ return sourceModel()->rowCount(parent); ++} ++int pgpid_item_proxy::columnCount(const QModelIndex &parent) const ++{ ++ return sourceModel()->columnCount(parent); ++} ++*/ +diff --git a/retroshare-gui/src/gui/NetworkDialog/pgpid_item_proxy.h b/retroshare-gui/src/gui/NetworkDialog/pgpid_item_proxy.h +new file mode 100644 +index 000000000..d33bc9666 +--- /dev/null ++++ b/retroshare-gui/src/gui/NetworkDialog/pgpid_item_proxy.h +@@ -0,0 +1,23 @@ ++#ifndef PGPID_ITEM_PROXY_H ++#define PGPID_ITEM_PROXY_H ++ ++#include ++ ++class pgpid_item_proxy : ++ //public QAbstractProxyModel ++ public QSortFilterProxyModel ++{ ++ Q_OBJECT ++ ++public: ++ pgpid_item_proxy(QObject *parent = nullptr); ++/* virtual QModelIndex mapFromSource(const QModelIndex &sourceIndex) const; ++ QModelIndex mapToSource(const QModelIndex &proxyIndex) const; ++ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; ++ QModelIndex parent(const QModelIndex &child) const; ++ int rowCount(const QModelIndex &parent = QModelIndex()) const; ++ int columnCount(const QModelIndex &parent = QModelIndex()) const; ++*/ ++}; ++ ++#endif // PGPID_ITEM_PROXY_H +diff --git a/retroshare-gui/src/main.cpp b/retroshare-gui/src/main.cpp +index 2430a1984..8dfa43c48 100644 +--- a/retroshare-gui/src/main.cpp ++++ b/retroshare-gui/src/main.cpp +@@ -416,7 +416,7 @@ feenableexcept(FE_INVALID | FE_DIVBYZERO); + QObject::connect(notify,SIGNAL(chatStatusChanged(const QString&,const QString&,bool)),w->friendsDialog,SLOT(updatePeerStatusString(const QString&,const QString&,bool))); + QObject::connect(notify,SIGNAL(ownStatusMessageChanged()),w->friendsDialog,SLOT(loadmypersonalstatus())); + +- QObject::connect(notify,SIGNAL(logInfoChanged(const QString&)) ,w->friendsDialog->networkDialog,SLOT(setLogInfo(QString))) ; ++// QObject::connect(notify,SIGNAL(logInfoChanged(const QString&)) ,w->friendsDialog->networkDialog,SLOT(setLogInfo(QString))) ; + QObject::connect(notify,SIGNAL(discInfoChanged()) ,w->friendsDialog->networkView,SLOT(update()),Qt::QueuedConnection) ; + QObject::connect(notify,SIGNAL(errorOccurred(int,int,const QString&)),w,SLOT(displayErrorMessage(int,int,const QString&))) ; + +diff --git a/retroshare-gui/src/retroshare-gui.pro b/retroshare-gui/src/retroshare-gui.pro +index b7bc361ce..6c4c821d1 100644 +--- a/retroshare-gui/src/retroshare-gui.pro ++++ b/retroshare-gui/src/retroshare-gui.pro +@@ -565,7 +565,9 @@ HEADERS += rshare.h \ + gui/GetStartedDialog.h \ + gui/statistics/BWGraph.h \ + util/RsSyntaxHighlighter.h \ +- util/imageutil.h ++ util/imageutil.h \ ++ gui/NetworkDialog/pgpid_item_model.h \ ++ gui/NetworkDialog/pgpid_item_proxy.h + + # gui/ForumsDialog.h \ + # gui/forums/ForumDetails.h \ +@@ -925,7 +927,9 @@ SOURCES += main.cpp \ + gui/statistics/RttStatistics.cpp \ + gui/statistics/BWGraph.cpp \ + util/RsSyntaxHighlighter.cpp \ +- util/imageutil.cpp ++ util/imageutil.cpp \ ++ gui/NetworkDialog/pgpid_item_model.cpp \ ++ gui/NetworkDialog/pgpid_item_proxy.cpp + + # gui/ForumsDialog.cpp \ + # gui/forums/ForumDetails.cpp \ -- cgit v1.2.3