mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-12-12 01:14:29 -05:00
281 lines
11 KiB
C++
281 lines
11 KiB
C++
/*******************************************************************************
|
|
* gui/NetworkDialog.cpp *
|
|
* *
|
|
* Copyright (c) 2006 Crypton <retroshare.project@gmail.com> *
|
|
* *
|
|
* This program is free software: you can redistribute it and/or modify *
|
|
* it under the terms of the GNU Affero General Public License as *
|
|
* published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU Affero General Public License *
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
|
* *
|
|
*******************************************************************************/
|
|
|
|
#include <QTreeWidget>
|
|
#include <QDebug>
|
|
#include <QTimer>
|
|
#include <QTime>
|
|
#include <QMenu>
|
|
#include <QSortFilterProxyModel>
|
|
|
|
#include <retroshare/rsiface.h>
|
|
#include <retroshare/rspeers.h>
|
|
#include <retroshare/rsdisc.h>
|
|
#include <retroshare/rsmsgs.h>
|
|
|
|
#include "common/vmessagebox.h"
|
|
#include "common/RSTreeWidgetItem.h"
|
|
#include <gui/common/FriendSelectionDialog.h>
|
|
#include "gui/msgs/MessageComposer.h"
|
|
#include "gui/profile/ProfileManager.h"
|
|
#include "NetworkDialog.h"
|
|
//#include "TrustView.h"
|
|
#include "NetworkView.h"
|
|
#include "GenCertDialog.h"
|
|
#include "connect/PGPKeyDialog.h"
|
|
#include "settings/rsharesettings.h"
|
|
#include "RetroShareLink.h"
|
|
#include "util/QtVersion.h"
|
|
|
|
#include <time.h>
|
|
|
|
/* Images for context menu icons */
|
|
#define IMAGE_PEERDETAILS ":/images/info16.png"
|
|
#define IMAGE_MAKEFRIEND ":/images/user/add_user16.png"
|
|
#define IMAGE_COPYLINK ":/images/copyrslink.png"
|
|
#define IMAGE_MESSAGE ":/icons/mail/write-mail.png"
|
|
|
|
/******
|
|
* #define NET_DEBUG 1
|
|
*****/
|
|
|
|
/** Constructor */
|
|
NetworkDialog::NetworkDialog(QWidget */*parent*/)
|
|
{
|
|
/* Invoke the Qt Designer generated object setup routine */
|
|
ui.setupUi(this);
|
|
|
|
connect( ui.filterLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(filterItems(QString)));
|
|
connect( ui.filterLineEdit, SIGNAL(filterChanged(int)), this, SLOT(filterColumnChanged(int)));
|
|
|
|
|
|
//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);
|
|
ui.connectTreeWidget->setSelectionMode(QAbstractItemView::SingleSelection);
|
|
connect(ui.connectTreeWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( connectTreeWidgetCostumPopupMenu( QPoint ) ) );
|
|
connect(ui.connectTreeWidget, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(peerdetails()));
|
|
|
|
ui.onlyTrustedKeys->setMinimumWidth(20*f);
|
|
|
|
/* 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)
|
|
{
|
|
QWidget::changeEvent(e);
|
|
switch (e->type()) {
|
|
case QEvent::StyleChange:
|
|
securedUpdateDisplay();
|
|
break;
|
|
default:
|
|
// remove compiler warnings
|
|
break;
|
|
}
|
|
}
|
|
|
|
void NetworkDialog::connectTreeWidgetCostumPopupMenu( QPoint /*point*/ )
|
|
{
|
|
|
|
QModelIndexList l = ui.connectTreeWidget->selectionModel()->selection().indexes();
|
|
if(l.empty())
|
|
{
|
|
return;
|
|
}
|
|
|
|
QMenu *contextMnu = new QMenu;
|
|
|
|
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;
|
|
if(!rsPeers->getGPGDetails(peer_id, detail)) // that is not suppose to fail.
|
|
return ;
|
|
|
|
if(peer_id == rsPeers->getGPGOwnId())
|
|
contextMnu->addAction(QIcon(), tr("Export/create a new node"), this, SLOT(on_actionExportKey_activated()));
|
|
|
|
contextMnu->addAction(QIcon(IMAGE_PEERDETAILS), tr("Profile details..."), this, SLOT(peerdetails()));
|
|
contextMnu->addSeparator() ;
|
|
contextMnu->addAction(QIcon(), tr("Remove unused keys..."), this, SLOT(removeUnusedKeys()));
|
|
|
|
contextMnu->exec(QCursor::pos());
|
|
}
|
|
|
|
void NetworkDialog::removeUnusedKeys()
|
|
{
|
|
std::set<RsPgpId> pre_selected ;
|
|
std::list<RsPgpId> ids ;
|
|
|
|
rsPeers->getGPGAllList(ids) ;
|
|
RsPeerDetails details ;
|
|
time_t now = time(NULL) ;
|
|
time_t THREE_MONTHS = 3*31*24*60*60 ;//3*DayPerMonth*HoursPerDay*MinPerHour*SecPerMin
|
|
|
|
for(std::list<RsPgpId>::const_iterator it(ids.begin());it!=ids.end();++it)
|
|
{
|
|
rsPeers->getGPGDetails(*it,details) ;
|
|
|
|
if(rsPeers->haveSecretKey(*it))
|
|
{
|
|
std::cerr << "Skipping public/secret key pair " << *it << std::endl;
|
|
continue ;
|
|
}
|
|
if(now > (time_t) (THREE_MONTHS + details.lastUsed) && !details.accept_connection)
|
|
{
|
|
std::cerr << "Adding " << *it << " to pre-selection." << std::endl;
|
|
pre_selected.insert(*it) ;
|
|
}
|
|
}
|
|
|
|
std::set<RsPgpId> selected = FriendSelectionDialog::selectFriends_PGP(NULL,
|
|
tr("Clean keyring"),
|
|
tr("The selected keys below haven't been used in the last 3 months. \nDo you want to delete them permanently ? \n\nNotes: Your old keyring will be backed up.\n The removal may fail when running multiple Retroshare instances on the same machine."),FriendSelectionWidget::MODUS_CHECK,FriendSelectionWidget::SHOW_GPG | FriendSelectionWidget::SHOW_NON_FRIEND_GPG,
|
|
pre_selected) ;
|
|
|
|
std::cerr << "Removing these keys from the keyring: " << std::endl;
|
|
for(std::set<RsPgpId>::const_iterator it(selected.begin());it!=selected.end();++it)
|
|
std::cerr << " " << *it << std::endl;
|
|
|
|
std::string backup_file ;
|
|
uint32_t error_code ;
|
|
|
|
if(selected.empty())
|
|
return ;
|
|
|
|
if( rsPeers->removeKeysFromPGPKeyring(selected,backup_file,error_code) )
|
|
QMessageBox::information(NULL,tr("Keyring info"),tr("%1 keys have been deleted from your keyring. \nFor security, your keyring was previously backed-up to file \n\n").arg(selected.size())+QString::fromStdString(backup_file) ) ;
|
|
else
|
|
{
|
|
QString error_string ;
|
|
|
|
switch(error_code)
|
|
{
|
|
default:
|
|
case PGP_KEYRING_REMOVAL_ERROR_NO_ERROR: error_string = tr("Unknown error") ;
|
|
break ;
|
|
case PGP_KEYRING_REMOVAL_ERROR_CANT_REMOVE_SECRET_KEYS: error_string = tr("Cannot delete secret keys") ;
|
|
break ;
|
|
case PGP_KEYRING_REMOVAL_ERROR_CANNOT_WRITE_BACKUP:
|
|
case PGP_KEYRING_REMOVAL_ERROR_CANNOT_CREATE_BACKUP: error_string = tr("Cannot create backup file. Check for permissions in pgp directory, disk space, etc.") ;
|
|
break ;
|
|
case PGP_KEYRING_REMOVAL_ERROR_DATA_INCONSISTENCY: error_string = tr("Data inconsistency in the keyring. This is most probably a bug. Please contact the developers.") ;
|
|
break ;
|
|
|
|
}
|
|
QMessageBox::warning(NULL,tr("Keyring info"),tr("Key removal has failed. Your keyring remains intact.\n\nReported error:")+" "+error_string ) ;
|
|
}
|
|
updateDisplay();
|
|
// insertConnect() ;
|
|
}
|
|
|
|
void NetworkDialog::denyFriend()
|
|
{
|
|
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();
|
|
}
|
|
|
|
void NetworkDialog::makeFriend()
|
|
{
|
|
|
|
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()
|
|
{
|
|
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()
|
|
{
|
|
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()) ;
|
|
|
|
QList<RetroShareLink> urls;
|
|
RetroShareLink link = RetroShareLink::createPerson(peer_id);
|
|
if (link.valid()) {
|
|
urls.push_back(link);
|
|
}
|
|
|
|
RSLinkClipboard::copyLinks(urls);
|
|
}
|
|
|
|
// void NetworkDialog::on_actionExportKey_activated()
|
|
// {
|
|
// ProfileManager prof ;
|
|
// prof.exec() ;
|
|
// }
|
|
|
|
void NetworkDialog::filterColumnChanged(int col)
|
|
{
|
|
if(PGPIdItemProxy)
|
|
PGPIdItemProxy->setFilterKeyColumn(col);
|
|
//filterItems(ui.filterLineEdit->text());
|
|
}
|
|
|
|
void NetworkDialog::updateDisplay()
|
|
{
|
|
if (!rsPeers)
|
|
return;
|
|
//update ids list
|
|
std::list<RsPgpId> new_neighs;
|
|
rsPeers->getGPGAllList(new_neighs);
|
|
//refresh model
|
|
PGPIdItemModel->data_updated(new_neighs);
|
|
}
|
|
|