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..bc5ea3e06 100644 --- a/retroshare-gui/src/gui/NetworkDialog.cpp +++ b/retroshare-gui/src/gui/NetworkDialog.cpp @@ -71,7 +71,7 @@ #define COLUMN_LAST_USED 5 #define COLUMN_COUNT 6 -RsPeerId getNeighRsCertId(QTreeWidgetItem *i); +//RsPeerId getNeighRsCertId(QTreeWidgetItem *i); /****** * #define NET_DEBUG 1 @@ -81,85 +81,64 @@ 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); + //list data model + float f = QFontMetricsF(font()).height()/14.0 ; + PGPIdItemModel = new pgpid_item_model(neighs, f, this); + PGPIdItemProxy = new pgpid_item_proxy(this); + connect(ui.onlyTrustedKeys, SIGNAL(toggled(bool)), PGPIdItemProxy, SLOT(use_only_trusted_keys(bool))); + PGPIdItemProxy->setSourceModel(PGPIdItemModel); + PGPIdItemProxy->setFilterKeyColumn(COLUMN_PEERNAME); + PGPIdItemProxy->setFilterCaseSensitivity(Qt::CaseInsensitive); + PGPIdItemProxy->setSortRole(Qt::EditRole); //use edit role to get raw data since we do not have edit for this model. + 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())); + - compareNetworkRole = new RSTreeWidgetItemCompareRole; - compareNetworkRole->setRole(COLUMN_LAST_USED, ROLE_SORT); /* 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); + 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); - - 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.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 +156,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; @@ -271,13 +250,17 @@ void NetworkDialog::removeUnusedKeys() } QMessageBox::warning(NULL,tr("Keyring info"),tr("Key removal has failed. Your keyring remains intact.\n\nReported error:")+" "+error_string ) ; } - insertConnect() ; + updateDisplay(); +// insertConnect() ; } 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 +283,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,225 +344,14 @@ 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); - - std::list neighs; //these are GPG ids - std::list::iterator it; - rsPeers->getGPGAllList(neighs); - - /* get a link to the table */ - QTreeWidget *connectWidget = ui.connectTreeWidget; - /* disable sorting while editing the table */ - 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; - } - - 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) ; - - /** - * Determinated the Background Color - */ - QColor backgrndcolor; - - if (detail.accept_connection) - { - item -> setText(COLUMN_CHECK, "0"); - item -> setIcon(COLUMN_CHECK,(QIcon(IMAGE_AUTHED))); - if (detail.ownsign) - { - backgrndcolor = backgroundColorOwnSign(); - } - else - { - backgrndcolor = backgroundColorAcceptConnection(); - } - } - 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))); - } - } - - // Color each Background column in the Network Tab except the first one => 1-9 - // whith the determinated color - for(int i = 0; i setBackground(i,QBrush(backgrndcolor)); - - if( (detail.accept_connection || detail.validLvl >= RS_TRUST_LVL_MARGINAL) || !ui.onlyTrustedKeys->isChecked()) - connectWidget->addTopLevelItem(item); - } - - // add self to network. - RsPeerDetails ownGPGDetails; - rsPeers->getGPGDetails(rsPeers->getGPGOwnId(), ownGPGDetails); - /* make a widget per friend */ - 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(); - } else { - self_item = new RSTreeWidgetItem(compareNetworkRole, 0); - self_item->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless); - } - self_item -> setText(COLUMN_CHECK, "0"); - self_item->setIcon(COLUMN_CHECK,(QIcon(IMAGE_AUTHED))); - self_item->setText(COLUMN_PEERNAME, QString::fromUtf8(ownGPGDetails.name.c_str()) + " (" + tr("yourself") + ")"); - self_item->setText(COLUMN_I_AUTH_PEER,"N/A"); - self_item->setText(COLUMN_PEERID, QString::fromStdString(ownGPGDetails.gpg_id.toStdString())); - - // Color each Background column in the Network Tab except the first one => 1-9 - for(int i=0;isetBackground(i,backgroundColorSelf()) ; - } - connectWidget->addTopLevelItem(self_item); - - /* enable sorting */ - connectWidget->setSortingEnabled(true); - /* update display */ - connectWidget->update(); - - 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) +/*RsPeerId getNeighRsCertId(QTreeWidgetItem *i) { RsPeerId id ( (i -> text(COLUMN_PEERID)).toStdString() ); return id; -} +} */ void NetworkDialog::on_actionAddFriend_activated() { // /* Create a new input dialog, which allows users to create files, too */ @@ -700,44 +477,23 @@ 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) -{ - int filterColumn = ui.filterLineEdit->currentFilter(); - int count = ui.connectTreeWidget->topLevelItemCount (); - for (int index = 0; index < count; ++index) { - filterItem(ui.connectTreeWidget->topLevelItem(index), text, filterColumn); - } + +void NetworkDialog::updateDisplay() +{ + if (!rsPeers) + return; + //update ids list + std::list new_neighs; + rsPeers->getGPGAllList(new_neighs); + //refresh model + PGPIdItemModel->data_updated(new_neighs); } -bool NetworkDialog::filterItem(QTreeWidgetItem *item, const QString &text, int filterColumn) -{ - bool visible = true; - - if (text.isEmpty() == false) { - if (item->text(filterColumn).contains(text, Qt::CaseInsensitive) == false) { - visible = false; - } - } - - int visibleChildCount = 0; - int count = item->childCount(); - for (int index = 0; index < count; ++index) { - if (filterItem(item->child(index), text, filterColumn)) { - ++visibleChildCount; - } - } - - if (visible || visibleChildCount) { - item->setHidden(false); - } else { - item->setHidden(true); - } - - return (visible || visibleChildCount); -} diff --git a/retroshare-gui/src/gui/NetworkDialog.h b/retroshare-gui/src/gui/NetworkDialog.h index 2d90e98e7..5c73c0a51 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; } @@ -58,7 +62,7 @@ public: void setBackgroundColorDenied(QColor color) { mBackgroundColorDenied = color; } private: - void insertConnect(); +// void insertConnect(); // std::string loadneighbour(); /* void loadneighbour(); */ //void updateNewDiscoveryInfo() ; @@ -68,7 +72,7 @@ protected: private slots: - void removeUnusedKeys() ; + void removeUnusedKeys() ; void makeFriend() ; void denyFriend() ; // void deleteCert() ; @@ -104,14 +108,15 @@ 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; - bool filterItem(QTreeWidgetItem *item, const QString &text, int filterColumn); +// bool filterItem(QTreeWidgetItem *item, const QString &text, int filterColumn); /* Color definitions (for standard see qss.default) */ QColor mBackgroundColorSelf; @@ -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..f9ed410eb --- /dev/null +++ b/retroshare-gui/src/gui/NetworkDialog/pgpid_item_model.cpp @@ -0,0 +1,342 @@ +#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 option +*/ +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("Connections")); + 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(); +} + + +int pgpid_item_model::rowCount(const QModelIndex &/*parent*/) const +{ + return neighs.size(); +} + +int pgpid_item_model::columnCount(const QModelIndex &/*parent*/) const +{ + return COLUMN_COUNT; +} + + +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::EditRole) //some columns return raw data for editrole, used for proper filtering + { + switch(index.column()) + { + case COLUMN_LAST_USED: + return detail.lastUsed; + break; + case COLUMN_I_AUTH_PEER: + { + if (detail.ownsign) + return RS_TRUST_LVL_ULTIMATE; + return detail.trustLvl; + } + break; + case COLUMN_PEER_AUTH_ME: + return detail.hasSignedMe; + break; + case COLUMN_CHECK: + return detail.accept_connection; + break; + default: + break; + } + + } + if(role == Qt::DisplayRole || role == Qt::EditRole) + { + 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 )) ; + + + return lst_used_str; + } + break; + case COLUMN_CHECK: + { + if (detail.accept_connection) + { + return tr("Accepted"); + } + else + { + return tr(" - "); + } + } + 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(); +} + + +//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; + + new_size = new_neighs.size(); + //set model data to new cleaned up data + neighs = new_neighs; + neighs.sort(); + neighs.unique(); //remove possible dups + + //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 + //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..8dc31d276 --- /dev/null +++ b/retroshare-gui/src/gui/NetworkDialog/pgpid_item_model.h @@ -0,0 +1,40 @@ +#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; + + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const 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..6fb62dd78 --- /dev/null +++ b/retroshare-gui/src/gui/NetworkDialog/pgpid_item_proxy.cpp @@ -0,0 +1,48 @@ +#include "pgpid_item_proxy.h" + +//TODO: include only required headers here +#include +#include +#include +#include + + +//TODO: set this defines in one place +// Defines for key list columns +#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 + + + +pgpid_item_proxy::pgpid_item_proxy(QObject *parent) : + QSortFilterProxyModel(parent) +{ + +} + +void pgpid_item_proxy::use_only_trusted_keys(bool val) +{ + only_trusted_keys = val; + filterChanged(); +} + +bool pgpid_item_proxy::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const +{ + if(only_trusted_keys) + { + if(!rsPeers) + return false; + RsPgpId peer_id (sourceModel()->data(sourceModel()->index(sourceRow, COLUMN_PEERID, sourceParent)).toString().toStdString()); + RsPeerDetails details; + if(!rsPeers->getGPGDetails(peer_id, details)) + return false; + if(details.validLvl < RS_TRUST_LVL_MARGINAL) + return false; + } + return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent); +} 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..e67eeeee8 --- /dev/null +++ b/retroshare-gui/src/gui/NetworkDialog/pgpid_item_proxy.h @@ -0,0 +1,21 @@ +#ifndef PGPID_ITEM_PROXY_H +#define PGPID_ITEM_PROXY_H + +#include + +class pgpid_item_proxy : + public QSortFilterProxyModel +{ + Q_OBJECT + +public: + pgpid_item_proxy(QObject *parent = nullptr); + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; +public slots: + void use_only_trusted_keys(bool val); + +private: + bool only_trusted_keys = false; +}; + +#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 6b3211392..d3a4c05c1 100644 --- a/retroshare-gui/src/retroshare-gui.pro +++ b/retroshare-gui/src/retroshare-gui.pro @@ -565,8 +565,9 @@ HEADERS += rshare.h \ gui/statistics/BWGraph.h \ util/RsSyntaxHighlighter.h \ util/imageutil.h \ + gui/NetworkDialog/pgpid_item_model.h \ + gui/NetworkDialog/pgpid_item_proxy.h \ gui/common/RsCollection.h - # gui/ForumsDialog.h \ # gui/forums/ForumDetails.h \ # gui/forums/EditForumDetails.h \ @@ -925,8 +926,9 @@ SOURCES += main.cpp \ gui/statistics/BWGraph.cpp \ util/RsSyntaxHighlighter.cpp \ util/imageutil.cpp \ + gui/NetworkDialog/pgpid_item_model.cpp \ + gui/NetworkDialog/pgpid_item_proxy.cpp \ gui/common/RsCollection.cpp - # gui/ForumsDialog.cpp \ # gui/forums/ForumDetails.cpp \ # gui/forums/EditForumDetails.cpp \