mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-12-13 18:04:34 -05:00
365 lines
11 KiB
C++
365 lines
11 KiB
C++
/*******************************************************************************
|
|
* retroshare-gui/src/gui/NetworkDialog/pgpid_item_model.cpp *
|
|
* *
|
|
* Copyright (C) 2018 by Retroshare Team <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 "pgpid_item_model.h"
|
|
#include <time.h>
|
|
#include <retroshare/rspeers.h>
|
|
#include <QIcon>
|
|
#include <QBrush>
|
|
|
|
|
|
/*TODO:
|
|
* using list here for internal data storage is not best option
|
|
*/
|
|
pgpid_item_model::pgpid_item_model(std::list<RsPgpId> &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 the trust level you indicated 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<RsPgpId>::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 and sorting
|
|
{
|
|
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;
|
|
}
|
|
|
|
}
|
|
//we using editrole only where it is useful, for other data we use display, so no "else if" here
|
|
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 || rsPeers->getGPGOwnId() == detail.gpg_id)
|
|
return tr("Accepted");
|
|
else
|
|
return tr("Denied");
|
|
}
|
|
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)
|
|
{
|
|
if (detail.accept_connection)
|
|
{
|
|
if (detail.ownsign)
|
|
{
|
|
return QBrush(mBackgroundColorOwnSign);
|
|
}
|
|
else
|
|
{
|
|
return QBrush(mBackgroundColorAcceptConnection);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (detail.hasSignedMe)
|
|
{
|
|
return QBrush(mBackgroundColorHasSignedMe);
|
|
}
|
|
else
|
|
{
|
|
return QBrush(mBackgroundColorDenied);
|
|
}
|
|
}
|
|
}
|
|
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<RsPgpId> &new_neighs)
|
|
{
|
|
|
|
//shit code follow (rewrite this please)
|
|
size_t old_size = neighs.size(), new_size = 0;
|
|
std::list<RsPgpId> 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, new_size);
|
|
insertRows(old_size, new_size - old_size);
|
|
endInsertRows();
|
|
}
|
|
else if(new_size < old_size)
|
|
{
|
|
beginRemoveRows(QModelIndex(), new_size, old_size);
|
|
removeRows(old_size, 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
|
|
}
|
|
|