2019-06-25 17:08:31 -04:00
/*******************************************************************************
* gui / common / NewFriendList . cpp *
* *
* Copyright ( C ) 2011 , 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 <algorithm>
# include <QShortcut>
# include <QWidgetAction>
# include <QDateTime>
# include <QPainter>
# include <QtXml>
# include "rsserver/rsaccounts.h"
# include "retroshare/rspeers.h"
# include "GroupDefs.h"
# include "gui/chat/ChatDialog.h"
# include "gui/common/AvatarDefs.h"
# include "gui/connect/ConfCertDialog.h"
# include "gui/connect/PGPKeyDialog.h"
# include "gui/connect/ConnectFriendWizard.h"
# include "gui/groups/CreateGroup.h"
# include "gui/msgs/MessageComposer.h"
# include "gui/notifyqt.h"
# include "gui/RetroShareLink.h"
# include "retroshare-gui/RsAutoUpdatePage.h"
# ifdef UNFINISHED_FD
# include "gui/unfinished/profile/ProfileView.h"
# endif
# include "RSTreeWidgetItem.h"
# include "StatusDefs.h"
# include "util/misc.h"
# include "vmessagebox.h"
# include "util/QtVersion.h"
# include "gui/chat/ChatUserNotify.h"
# include "gui/connect/ConnectProgressDialog.h"
# include "gui/common/ElidedLabel.h"
2019-06-28 05:12:44 -04:00
# include "NewFriendList.h"
2019-06-28 05:27:19 -04:00
# include "ui_NewFriendList.h"
2019-06-25 17:08:31 -04:00
/* Images for context menu icons */
# define IMAGE_DENYFRIEND ": / images / denied16.png"
# define IMAGE_REMOVEFRIEND ": / images / remove_user24.png"
# define IMAGE_EXPORTFRIEND ": / images / user / friend_suggestion16.png"
# define IMAGE_ADDFRIEND ": / images / user / add_user16.png"
# define IMAGE_FRIENDINFO ": / images / info16.png"
# define IMAGE_CHAT ": / images / chat_24.png"
# define IMAGE_MSG ": / images / mail_new.png"
# define IMAGE_CONNECT ": / images / connect_friend.png"
# define IMAGE_COPYLINK ": / images / copyrslink.png"
# define IMAGE_GROUP16 ": / images / user / group16.png"
# define IMAGE_EDIT ": / images / edit_16.png"
# define IMAGE_REMOVE ": / images / delete.png"
# define IMAGE_EXPAND ": / images / edit_add24.png"
# define IMAGE_COLLAPSE ": / images / edit_remove24.png"
/* Images for Status icons */
# define IMAGE_AVAILABLE ": / images / user / identityavaiblecyan24.png"
# define IMAGE_PASTELINK ": / images / pasterslink.png"
# define IMAGE_GROUP24 ": / images / user / group24.png"
# define COLUMN_DATA 0 // column for storing the userdata id
2019-08-23 14:21:57 -04:00
// #define ROLE_ID Qt::UserRole
// #define ROLE_STANDARD Qt::UserRole + 1
// #define ROLE_SORT_GROUP Qt::UserRole + 2
// #define ROLE_SORT_STANDARD_GROUP Qt::UserRole + 3
// #define ROLE_SORT_NAME Qt::UserRole + 4
// #define ROLE_SORT_STATE Qt::UserRole + 5
// #define ROLE_FILTER Qt::UserRole + 6
2019-06-25 17:08:31 -04:00
// states for sorting (equal values are possible)
// used in BuildSortString - state + name
# define PEER_STATE_ONLINE 1
# define PEER_STATE_BUSY 2
# define PEER_STATE_AWAY 3
# define PEER_STATE_AVAILABLE 4
# define PEER_STATE_INACTIVE 5
# define PEER_STATE_OFFLINE 6
/******
* # define FRIENDS_DEBUG 1
* * * * */
Q_DECLARE_METATYPE ( ElidedLabel * )
2019-08-06 16:52:07 -04:00
class FriendListSortFilterProxyModel : public QSortFilterProxyModel
{
public :
2019-08-12 06:49:04 -04:00
FriendListSortFilterProxyModel ( const QHeaderView * header , QObject * parent = NULL ) : QSortFilterProxyModel ( parent ) ,
m_header ( header ) ,
m_sortingEnabled ( false ) ,
2019-08-15 09:49:20 -04:00
m_showOfflineNodes ( true ) { }
2019-08-06 16:52:07 -04:00
bool lessThan ( const QModelIndex & left , const QModelIndex & right ) const override
{
2019-08-26 12:27:20 -04:00
bool is_group_1 = left . data ( RsFriendListModel : : TypeRole ) . toUInt ( ) = = ( uint ) RsFriendListModel : : ENTRY_TYPE_GROUP ;
bool is_group_2 = right . data ( RsFriendListModel : : TypeRole ) . toUInt ( ) = = ( uint ) RsFriendListModel : : ENTRY_TYPE_GROUP ;
if ( is_group_1 ^ is_group_2 ) // if the two are different, put the group first.
return is_group_1 ;
2019-08-15 09:49:20 -04:00
bool online1 = left . data ( RsFriendListModel : : OnlineRole ) . toBool ( ) ;
bool online2 = right . data ( RsFriendListModel : : OnlineRole ) . toBool ( ) ;
if ( online1 ! = online2 & & m_sortByState )
return ( m_header - > sortIndicatorOrder ( ) = = Qt : : AscendingOrder ) ? online1 : online2 ; // always put online nodes first
2019-08-06 16:52:07 -04:00
return left . data ( RsFriendListModel : : SortRole ) < right . data ( RsFriendListModel : : SortRole ) ;
}
bool filterAcceptsRow ( int source_row , const QModelIndex & source_parent ) const override
{
2019-09-15 14:53:12 -04:00
// do not show empty groups
QModelIndex index = sourceModel ( ) - > index ( source_row , 0 , source_parent ) ;
if ( index . data ( RsFriendListModel : : TypeRole ) = = RsFriendListModel : : ENTRY_TYPE_GROUP )
{
RsGroupInfo group_info ;
static_cast < RsFriendListModel * > ( sourceModel ( ) ) - > getGroupData ( index , group_info ) ;
if ( group_info . peerIds . empty ( ) )
return false ;
}
// Filter offline friends
if ( ! m_showOfflineNodes & & ! index . data ( RsFriendListModel : : OnlineRole ) . toBool ( ) )
2019-08-12 06:49:04 -04:00
return false ;
2019-09-15 14:53:12 -04:00
return index . data ( RsFriendListModel : : FilterRole ) . toString ( ) = = RsFriendListModel : : FilterString ;
2019-08-06 16:52:07 -04:00
}
void sort ( int column , Qt : : SortOrder order = Qt : : AscendingOrder ) override
{
if ( m_sortingEnabled )
return QSortFilterProxyModel : : sort ( column , order ) ;
}
void setSortingEnabled ( bool b ) { m_sortingEnabled = b ; }
void setSortByState ( bool b ) { m_sortByState = b ; }
2019-08-15 09:49:20 -04:00
void setShowOfflineNodes ( bool b ) { m_showOfflineNodes = b ; }
2019-08-12 06:49:04 -04:00
2019-08-15 09:49:20 -04:00
bool showOfflineNodes ( ) const { return m_showOfflineNodes ; }
2019-08-15 10:16:01 -04:00
bool sortByState ( ) const { return m_sortByState ; }
2019-08-06 16:52:07 -04:00
private :
const QHeaderView * m_header ;
bool m_sortingEnabled ;
bool m_sortByState ;
2019-08-15 09:49:20 -04:00
bool m_showOfflineNodes ;
2019-08-06 16:52:07 -04:00
} ;
2019-08-30 07:57:27 -04:00
NewFriendList : : NewFriendList ( QWidget * parent ) : /* RsAutoUpdatePage(5000,parent),*/ ui ( new Ui : : NewFriendList ( ) )
2019-06-25 17:08:31 -04:00
{
2019-06-28 18:14:27 -04:00
ui - > setupUi ( this ) ;
2019-06-28 05:27:19 -04:00
ui - > filterLineEdit - > setPlaceholderText ( tr ( " Search " ) ) ;
ui - > filterLineEdit - > showFilterIcon ( ) ;
2019-06-28 10:20:26 -04:00
mModel = new RsFriendListModel ( ) ;
2019-08-06 16:52:07 -04:00
mProxyModel = new FriendListSortFilterProxyModel ( ui - > peerTreeWidget - > header ( ) , this ) ;
mProxyModel - > setSourceModel ( mModel ) ;
mProxyModel - > setSortRole ( RsFriendListModel : : SortRole ) ;
mProxyModel - > setDynamicSortFilter ( false ) ;
mProxyModel - > setSortCaseSensitivity ( Qt : : CaseInsensitive ) ;
mProxyModel - > setFilterRole ( RsFriendListModel : : FilterRole ) ;
mProxyModel - > setFilterRegExp ( QRegExp ( RsFriendListModel : : FilterString ) ) ;
ui - > peerTreeWidget - > setModel ( mProxyModel ) ;
2019-06-28 10:20:26 -04:00
2019-06-25 17:08:31 -04:00
/* Add filter actions */
2019-08-06 16:52:07 -04:00
QString headerText = mModel - > headerData ( RsFriendListModel : : COLUMN_THREAD_NAME , Qt : : Horizontal , Qt : : DisplayRole ) . toString ( ) ;
ui - > filterLineEdit - > addFilter ( QIcon ( ) , headerText , RsFriendListModel : : COLUMN_THREAD_NAME , QString ( " %1 %2 " ) . arg ( tr ( " Search " ) , headerText ) ) ;
ui - > filterLineEdit - > addFilter ( QIcon ( ) , tr ( " ID " ) , RsFriendListModel : : COLUMN_THREAD_ID , tr ( " Search ID " ) ) ;
2019-06-25 17:08:31 -04:00
2019-08-20 15:27:59 -04:00
mActionSortByState = new QAction ( tr ( " Online friends on top " ) , this ) ;
2019-06-28 18:14:27 -04:00
mActionSortByState - > setCheckable ( true ) ;
2019-08-06 16:52:07 -04:00
//setting default filter by column as subject
ui - > filterLineEdit - > setCurrentFilter ( RsFriendListModel : : COLUMN_THREAD_NAME ) ;
ui - > peerTreeWidget - > setSortingEnabled ( true ) ;
2019-06-25 17:08:31 -04:00
/* Set sort */
2019-08-23 10:39:57 -04:00
sortColumn ( RsFriendListModel : : COLUMN_THREAD_NAME , Qt : : AscendingOrder ) ;
2019-08-06 16:52:07 -04:00
toggleSortByState ( false ) ;
2019-08-15 09:49:20 -04:00
// workaround for Qt bug, should be solved in next Qt release 4.7.0
2019-06-25 17:08:31 -04:00
// http://bugreports.qt.nokia.com/browse/QTBUG-8270
QShortcut * Shortcut = new QShortcut ( QKeySequence ( Qt : : Key_Delete ) , ui - > peerTreeWidget , 0 , 0 , Qt : : WidgetShortcut ) ;
2019-08-30 07:57:27 -04:00
connect ( Shortcut , SIGNAL ( activated ( ) ) , this , SLOT ( removefriend ( ) ) , Qt : : QueuedConnection ) ;
2019-06-25 17:08:31 -04:00
QFontMetricsF fontMetrics ( ui - > peerTreeWidget - > font ( ) ) ;
/* Set initial column width */
int fontWidth = fontMetrics . width ( " W " ) ;
2019-08-03 15:07:48 -04:00
ui - > peerTreeWidget - > setColumnWidth ( RsFriendListModel : : COLUMN_THREAD_NAME , 22 * fontWidth ) ;
ui - > peerTreeWidget - > setColumnWidth ( RsFriendListModel : : COLUMN_THREAD_IP , 15 * fontWidth ) ;
ui - > peerTreeWidget - > setColumnWidth ( RsFriendListModel : : COLUMN_THREAD_ID , 32 * fontWidth ) ;
ui - > peerTreeWidget - > setColumnWidth ( RsFriendListModel : : COLUMN_THREAD_LAST_CONTACT , 12 * fontWidth ) ;
2019-06-25 17:08:31 -04:00
int avatarHeight = fontMetrics . height ( ) * 3 ;
ui - > peerTreeWidget - > setIconSize ( QSize ( avatarHeight , avatarHeight ) ) ;
2019-08-21 16:39:07 -04:00
mModel - > checkInternalData ( true ) ;
2019-07-27 17:42:39 -04:00
2019-08-03 15:07:48 -04:00
QHeaderView * h = ui - > peerTreeWidget - > header ( ) ;
h - > setContextMenuPolicy ( Qt : : CustomContextMenu ) ;
2019-08-15 09:49:20 -04:00
connect ( ui - > peerTreeWidget - > header ( ) , SIGNAL ( sortIndicatorChanged ( int , Qt : : SortOrder ) ) , this , SLOT ( sortColumn ( int , Qt : : SortOrder ) ) ) ;
2019-09-04 15:35:17 -04:00
connect ( ui - > peerTreeWidget , SIGNAL ( expanded ( const QModelIndex & ) ) , this , SLOT ( itemExpanded ( const QModelIndex & ) ) ) ;
connect ( ui - > peerTreeWidget , SIGNAL ( collapsed ( const QModelIndex & ) ) , this , SLOT ( itemCollapsed ( const QModelIndex & ) ) ) ;
2019-08-15 09:49:20 -04:00
connect ( mActionSortByState , SIGNAL ( toggled ( bool ) ) , this , SLOT ( toggleSortByState ( bool ) ) ) ;
connect ( ui - > peerTreeWidget , SIGNAL ( customContextMenuRequested ( QPoint ) ) , this , SLOT ( peerTreeWidgetCustomPopupMenu ( ) ) ) ;
2019-08-20 08:57:44 -04:00
2019-08-30 07:57:27 -04:00
// Using Queued connections here is pretty important since the notifications may come from a different thread.
connect ( NotifyQt : : getInstance ( ) , SIGNAL ( friendsChanged ( ) ) , this , SLOT ( forceUpdateDisplay ( ) ) , Qt : : QueuedConnection ) ;
connect ( NotifyQt : : getInstance ( ) , SIGNAL ( groupsChanged ( int ) ) , this , SLOT ( forceUpdateDisplay ( ) ) , Qt : : QueuedConnection ) ;
connect ( NotifyQt : : getInstance ( ) , SIGNAL ( peerConnected ( const QString & ) ) , this , SLOT ( forceUpdateDisplay ( ) ) , Qt : : QueuedConnection ) ;
connect ( NotifyQt : : getInstance ( ) , SIGNAL ( peerDisconnected ( const QString & ) ) , this , SLOT ( forceUpdateDisplay ( ) ) , Qt : : QueuedConnection ) ;
2019-08-15 09:49:20 -04:00
connect ( ui - > actionShowOfflineFriends , SIGNAL ( triggered ( bool ) ) , this , SLOT ( setShowUnconnected ( bool ) ) ) ;
2019-08-30 07:57:27 -04:00
connect ( ui - > actionShowState , SIGNAL ( triggered ( bool ) ) , this , SLOT ( setShowState ( bool ) ) ) ;
connect ( ui - > actionShowGroups , SIGNAL ( triggered ( bool ) ) , this , SLOT ( setShowGroups ( bool ) ) ) ;
connect ( ui - > actionExportFriendlist , SIGNAL ( triggered ( ) ) , this , SLOT ( exportFriendlistClicked ( ) ) ) ;
connect ( ui - > actionImportFriendlist , SIGNAL ( triggered ( ) ) , this , SLOT ( importFriendlistClicked ( ) ) ) ;
2019-08-15 09:49:20 -04:00
2019-08-30 07:57:27 -04:00
connect ( ui - > filterLineEdit , SIGNAL ( textChanged ( QString ) ) , this , SLOT ( filterItems ( QString ) ) , Qt : : QueuedConnection ) ;
2019-08-15 09:49:20 -04:00
connect ( h , SIGNAL ( customContextMenuRequested ( QPoint ) ) , this , SLOT ( headerContextMenuRequested ( QPoint ) ) ) ;
2019-08-23 10:39:57 -04:00
// #ifdef RS_DIRECT_CHAT
// connect(ui->peerTreeWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(chatNode()));
// #endif
2019-06-25 17:08:31 -04:00
}
NewFriendList : : ~ NewFriendList ( )
{
delete ui ;
2019-08-03 15:07:48 -04:00
}
2019-09-04 15:35:17 -04:00
void NewFriendList : : itemExpanded ( const QModelIndex & index )
{
mModel - > expandItem ( mProxyModel - > mapToSource ( index ) ) ;
}
void NewFriendList : : itemCollapsed ( const QModelIndex & index )
{
mModel - > collapseItem ( mProxyModel - > mapToSource ( index ) ) ;
}
2019-08-06 16:52:07 -04:00
void NewFriendList : : sortColumn ( int col , Qt : : SortOrder so )
{
2019-08-23 10:39:57 -04:00
std : : set < QString > expanded_indexes ;
std : : set < QString > selected_indexes ;
saveExpandedPathsAndSelection ( expanded_indexes , selected_indexes ) ;
2019-08-06 16:52:07 -04:00
mProxyModel - > setSortingEnabled ( true ) ;
mProxyModel - > sort ( col , so ) ;
mProxyModel - > setSortingEnabled ( false ) ;
2019-08-23 10:39:57 -04:00
restoreExpandedPathsAndSelection ( expanded_indexes , selected_indexes ) ;
2019-08-06 16:52:07 -04:00
}
2019-08-03 15:07:48 -04:00
void NewFriendList : : headerContextMenuRequested ( QPoint p )
{
QMenu displayMenu ( tr ( " Show Items " ) , this ) ;
2019-08-15 09:49:20 -04:00
QWidget * widget = new QWidget ( & displayMenu ) ;
widget - > setStyleSheet ( " .QWidget{background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 #FEFEFE, stop:1 #E8E8E8); border: 1px solid #CCCCCC;} " ) ;
// create menu header
QHBoxLayout * hbox = new QHBoxLayout ( widget ) ;
hbox - > setMargin ( 0 ) ;
hbox - > setSpacing ( 6 ) ;
QLabel * iconLabel = new QLabel ( widget ) ;
QPixmap pix = QPixmap ( " :/images/user/friends24.png " ) . scaledToHeight ( QFontMetricsF ( iconLabel - > font ( ) ) . height ( ) * 1.5 ) ;
iconLabel - > setPixmap ( pix ) ;
iconLabel - > setMaximumSize ( iconLabel - > frameSize ( ) . height ( ) + pix . height ( ) , pix . width ( ) ) ;
hbox - > addWidget ( iconLabel ) ;
QLabel * textLabel = new QLabel ( " <strong>Show/hide...</strong> " , widget ) ;
hbox - > addWidget ( textLabel ) ;
QSpacerItem * spacerItem = new QSpacerItem ( 40 , 20 , QSizePolicy : : Expanding , QSizePolicy : : Minimum ) ;
hbox - > addItem ( spacerItem ) ;
widget - > setLayout ( hbox ) ;
QWidgetAction * widgetAction = new QWidgetAction ( this ) ;
widgetAction - > setDefaultWidget ( widget ) ;
displayMenu . addAction ( widgetAction ) ;
displayMenu . addAction ( mActionSortByState ) ;
2019-08-15 10:16:01 -04:00
mActionSortByState - > setChecked ( mProxyModel - > sortByState ( ) ) ;
2019-08-15 09:49:20 -04:00
displayMenu . addAction ( ui - > actionShowOfflineFriends ) ;
2019-08-03 15:07:48 -04:00
displayMenu . addAction ( ui - > actionShowState ) ;
displayMenu . addAction ( ui - > actionShowGroups ) ;
2019-08-15 09:49:20 -04:00
ui - > actionShowOfflineFriends - > setChecked ( mProxyModel - > showOfflineNodes ( ) ) ;
2019-08-15 13:43:41 -04:00
ui - > actionShowState - > setChecked ( mModel - > getDisplayStatusString ( ) ) ;
2019-08-11 05:46:49 -04:00
ui - > actionShowGroups - > setChecked ( mModel - > getDisplayGroups ( ) ) ;
2019-08-03 15:07:48 -04:00
QHeaderView * header = ui - > peerTreeWidget - > header ( ) ;
{
QAction * action = displayMenu . addAction ( QIcon ( ) , tr ( " Last contact " ) , this , SLOT ( toggleColumnVisible ( ) ) ) ;
action - > setCheckable ( true ) ;
action - > setData ( RsFriendListModel : : COLUMN_THREAD_LAST_CONTACT ) ;
action - > setChecked ( ! header - > isSectionHidden ( RsFriendListModel : : COLUMN_THREAD_LAST_CONTACT ) ) ;
}
{
QAction * action = displayMenu . addAction ( QIcon ( ) , tr ( " IP " ) , this , SLOT ( toggleColumnVisible ( ) ) ) ;
action - > setCheckable ( true ) ;
action - > setData ( RsFriendListModel : : COLUMN_THREAD_IP ) ;
action - > setChecked ( ! header - > isSectionHidden ( RsFriendListModel : : COLUMN_THREAD_IP ) ) ;
}
{
QAction * action = displayMenu . addAction ( QIcon ( ) , tr ( " ID " ) , this , SLOT ( toggleColumnVisible ( ) ) ) ;
action - > setCheckable ( true ) ;
action - > setData ( RsFriendListModel : : COLUMN_THREAD_ID ) ;
action - > setChecked ( ! header - > isSectionHidden ( RsFriendListModel : : COLUMN_THREAD_ID ) ) ;
}
displayMenu . exec ( QCursor : : pos ( ) ) ;
2019-06-25 17:08:31 -04:00
}
void NewFriendList : : addToolButton ( QToolButton * toolButton )
{
2019-08-20 15:27:59 -04:00
if ( ! toolButton )
2019-06-25 17:08:31 -04:00
return ;
/* Initialize button */
toolButton - > setAutoRaise ( true ) ;
float S = QFontMetricsF ( ui - > filterLineEdit - > font ( ) ) . height ( ) ;
toolButton - > setIconSize ( QSize ( S * 1.5 , S * 1.5 ) ) ;
toolButton - > setFocusPolicy ( Qt : : NoFocus ) ;
ui - > titleBarFrame - > layout ( ) - > addWidget ( toolButton ) ;
}
2019-08-22 07:13:04 -04:00
void NewFriendList : : saveExpandedPathsAndSelection ( std : : set < QString > & expanded_indexes , std : : set < QString > & selected_indexes )
{
# ifdef DEBUG_NEW_FRIEND_LIST
std : : cerr < < " Saving expended paths and selection... " < < std : : endl ;
# endif
for ( int row = 0 ; row < mProxyModel - > rowCount ( ) ; + + row )
recursSaveExpandedItems ( mProxyModel - > index ( row , 0 ) , QString ( ) , expanded_indexes , selected_indexes ) ;
}
void NewFriendList : : restoreExpandedPathsAndSelection ( const std : : set < QString > & expanded_indexes , const std : : set < QString > & selected_indexes )
{
# ifdef DEBUG_NEW_FRIEND_LIST
std : : cerr < < " Restoring expended paths and selection... " < < std : : endl ;
# endif
ui - > peerTreeWidget - > blockSignals ( true ) ;
for ( int row = 0 ; row < mProxyModel - > rowCount ( ) ; + + row )
recursRestoreExpandedItems ( mProxyModel - > index ( row , 0 ) , QString ( ) , expanded_indexes , selected_indexes ) ;
ui - > peerTreeWidget - > blockSignals ( false ) ;
}
void NewFriendList : : recursSaveExpandedItems ( const QModelIndex & index , const QString & parent_path , std : : set < QString > & exp , std : : set < QString > & sel )
{
QString local_path = parent_path + index . sibling ( index . row ( ) , RsFriendListModel : : COLUMN_THREAD_ID ) . data ( Qt : : DisplayRole ) . toString ( ) + " " ;
if ( ui - > peerTreeWidget - > selectionModel ( ) - > selection ( ) . contains ( index ) )
sel . insert ( local_path ) ;
if ( ui - > peerTreeWidget - > isExpanded ( index ) )
{
# ifdef DEBUG_NEW_FRIEND_LIST
std : : cerr < < " Index " < < local_path . toStdString ( ) < < " is expanded. " < < std : : endl ;
# endif
if ( index . isValid ( ) )
exp . insert ( local_path ) ;
for ( int row = 0 ; row < mProxyModel - > rowCount ( index ) ; + + row )
recursSaveExpandedItems ( index . child ( row , 0 ) , local_path , exp , sel ) ;
}
# ifdef DEBUG_NEW_FRIEND_LIST
else
std : : cerr < < " Index " < < local_path . toStdString ( ) < < " is not expanded. " < < std : : endl ;
# endif
}
void NewFriendList : : recursRestoreExpandedItems ( const QModelIndex & index , const QString & parent_path , const std : : set < QString > & exp , const std : : set < QString > & sel )
{
QString local_path = parent_path + index . sibling ( index . row ( ) , RsFriendListModel : : COLUMN_THREAD_ID ) . data ( Qt : : DisplayRole ) . toString ( ) + " " ;
# ifdef DEBUG_NEW_FRIEND_LIST
std : : cerr < < " at index " < < index . row ( ) < < " . data[1]= " < < local_path . toStdString ( ) < < std : : endl ;
# endif
if ( sel . find ( local_path ) ! = sel . end ( ) )
ui - > peerTreeWidget - > selectionModel ( ) - > select ( index , QItemSelectionModel : : Select | QItemSelectionModel : : Rows ) ;
if ( exp . find ( local_path ) ! = exp . end ( ) )
{
# ifdef DEBUG_NEW_FRIEND_LIST
std : : cerr < < " re expanding index " < < local_path . toStdString ( ) < < std : : endl ;
# endif
ui - > peerTreeWidget - > setExpanded ( index , true ) ;
for ( int row = 0 ; row < mProxyModel - > rowCount ( index ) ; + + row )
recursRestoreExpandedItems ( index . child ( row , 0 ) , local_path , exp , sel ) ;
}
}
2019-06-25 17:08:31 -04:00
void NewFriendList : : processSettings ( bool load )
{
// state of peer tree
2019-08-20 15:27:59 -04:00
if ( load ) // load settings
{
2019-06-25 17:08:31 -04:00
// states
2019-08-15 09:49:20 -04:00
setShowUnconnected ( ! Settings - > value ( " hideUnconnected " , mProxyModel - > showOfflineNodes ( ) ) . toBool ( ) ) ;
2019-08-15 13:43:41 -04:00
setShowState ( Settings - > value ( " showState " , mModel - > getDisplayStatusString ( ) ) . toBool ( ) ) ;
2019-08-11 05:46:49 -04:00
setShowGroups ( Settings - > value ( " showGroups " , mModel - > getDisplayGroups ( ) ) . toBool ( ) ) ;
2019-06-25 17:08:31 -04:00
2019-08-15 09:49:20 -04:00
setColumnVisible ( RsFriendListModel : : COLUMN_THREAD_IP , Settings - > value ( " showIP " , isColumnVisible ( RsFriendListModel : : COLUMN_THREAD_IP ) ) . toBool ( ) ) ;
setColumnVisible ( RsFriendListModel : : COLUMN_THREAD_ID , Settings - > value ( " showID " , isColumnVisible ( RsFriendListModel : : COLUMN_THREAD_ID ) ) . toBool ( ) ) ;
setColumnVisible ( RsFriendListModel : : COLUMN_THREAD_LAST_CONTACT , Settings - > value ( " showLastContact " , isColumnVisible ( RsFriendListModel : : COLUMN_THREAD_LAST_CONTACT ) ) . toBool ( ) ) ;
2019-06-25 17:08:31 -04:00
// sort
2019-08-15 10:16:01 -04:00
toggleSortByState ( Settings - > value ( " sortByState " , mProxyModel - > sortByState ( ) ) . toBool ( ) ) ;
2019-06-25 17:08:31 -04:00
// open groups
int arrayIndex = Settings - > beginReadArray ( " Groups " ) ;
for ( int index = 0 ; index < arrayIndex ; + + index ) {
Settings - > setArrayIndex ( index ) ;
std : : string gids = Settings - > value ( " open " ) . toString ( ) . toStdString ( ) ;
2019-08-26 12:27:20 -04:00
// RsGroupInfo ginfo ;
//
// if(rsPeers->getGroupInfoByName(gids,ginfo)) // backward compatibility
// addGroupToExpand(ginfo.id) ;
// else if(rsPeers->getGroupInfo(RsNodeGroupId(gids),ginfo)) // backward compatibility
// addGroupToExpand(ginfo.id) ;
// else
// std::cerr << "(EE) Cannot find group info for openned group \"" << gids << "\"" << std::endl;
2019-06-25 17:08:31 -04:00
}
Settings - > endArray ( ) ;
2019-08-20 15:27:59 -04:00
}
else
{
2019-06-25 17:08:31 -04:00
// save settings
// states
2019-08-15 09:49:20 -04:00
Settings - > setValue ( " hideUnconnected " , ! mProxyModel - > showOfflineNodes ( ) ) ;
2019-08-15 13:43:41 -04:00
Settings - > setValue ( " showState " , mModel - > getDisplayStatusString ( ) ) ;
2019-08-11 05:46:49 -04:00
Settings - > setValue ( " showGroups " , mModel - > getDisplayGroups ( ) ) ;
2019-06-25 17:08:31 -04:00
2019-08-15 09:49:20 -04:00
Settings - > setValue ( " showIP " , isColumnVisible ( RsFriendListModel : : COLUMN_THREAD_IP ) ) ;
Settings - > setValue ( " showID " , isColumnVisible ( RsFriendListModel : : COLUMN_THREAD_ID ) ) ;
Settings - > setValue ( " showLastContact " , isColumnVisible ( RsFriendListModel : : COLUMN_THREAD_LAST_CONTACT ) ) ;
2019-06-25 17:08:31 -04:00
// sort
2019-08-15 10:16:01 -04:00
Settings - > setValue ( " sortByState " , mProxyModel - > sortByState ( ) ) ;
2019-06-25 17:08:31 -04:00
2019-08-26 12:27:20 -04:00
// // open groups
// Settings->beginWriteArray("Groups");
// int arrayIndex = 0;
// std::set<RsNodeGroupId> expandedPeers;
// getExpandedGroups(expandedPeers);
// foreach (RsNodeGroupId groupId, expandedPeers) {
// Settings->setArrayIndex(arrayIndex++);
// Settings->setValue("open", QString::fromStdString(groupId.toStdString()));
// }
2019-06-25 17:08:31 -04:00
Settings - > endArray ( ) ;
}
}
2019-08-06 16:52:07 -04:00
void NewFriendList : : toggleSortByState ( bool sort )
{
mProxyModel - > setSortByState ( sort ) ;
2019-08-15 09:49:20 -04:00
mProxyModel - > setFilterRegExp ( QRegExp ( QString ( RsFriendListModel : : FilterString ) ) ) ; // triggers a re-display.
2019-08-06 16:52:07 -04:00
}
2019-06-25 17:08:31 -04:00
void NewFriendList : : changeEvent ( QEvent * e )
{
QWidget : : changeEvent ( e ) ;
switch ( e - > type ( ) ) {
case QEvent : : StyleChange :
break ;
default :
// remove compiler warnings
break ;
}
}
/**
* Creates the context popup menu and its submenus ,
* then shows it at the current cursor position .
*/
void NewFriendList : : peerTreeWidgetCustomPopupMenu ( )
{
2019-08-06 16:52:07 -04:00
QModelIndex index = getCurrentSourceIndex ( ) ;
2019-06-28 10:20:26 -04:00
RsFriendListModel : : EntryType type = mModel - > getType ( index ) ;
2019-06-25 17:08:31 -04:00
2019-06-28 10:20:26 -04:00
QMenu contextMenu ( this ) ;
2019-06-25 17:08:31 -04:00
2019-06-28 10:20:26 -04:00
QWidget * widget = new QWidget ( & contextMenu ) ;
2019-06-25 17:08:31 -04:00
widget - > setStyleSheet ( " .QWidget{background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 #FEFEFE, stop:1 #E8E8E8); border: 1px solid #CCCCCC;} " ) ;
// create menu header
QHBoxLayout * hbox = new QHBoxLayout ( widget ) ;
hbox - > setMargin ( 0 ) ;
hbox - > setSpacing ( 6 ) ;
QLabel * iconLabel = new QLabel ( widget ) ;
QPixmap pix = QPixmap ( " :/images/user/friends24.png " ) . scaledToHeight ( QFontMetricsF ( iconLabel - > font ( ) ) . height ( ) * 1.5 ) ;
iconLabel - > setPixmap ( pix ) ;
iconLabel - > setMaximumSize ( iconLabel - > frameSize ( ) . height ( ) + pix . height ( ) , pix . width ( ) ) ;
hbox - > addWidget ( iconLabel ) ;
2019-08-15 09:49:20 -04:00
QLabel * textLabel = new QLabel ( " <strong>Friend list</strong> " , widget ) ;
2019-06-25 17:08:31 -04:00
hbox - > addWidget ( textLabel ) ;
QSpacerItem * spacerItem = new QSpacerItem ( 40 , 20 , QSizePolicy : : Expanding , QSizePolicy : : Minimum ) ;
hbox - > addItem ( spacerItem ) ;
widget - > setLayout ( hbox ) ;
QWidgetAction * widgetAction = new QWidgetAction ( this ) ;
widgetAction - > setDefaultWidget ( widget ) ;
2019-06-28 10:20:26 -04:00
contextMenu . addAction ( widgetAction ) ;
2019-06-25 17:08:31 -04:00
// create menu entries
2019-06-28 10:20:26 -04:00
if ( index . isValid ( ) )
{
// define header
switch ( type ) {
case RsFriendListModel : : ENTRY_TYPE_GROUP :
//this is a GPG key
textLabel - > setText ( " <strong> " + tr ( " Group " ) + " </strong> " ) ;
break ;
case RsFriendListModel : : ENTRY_TYPE_PROFILE :
//this is a GPG key
textLabel - > setText ( " <strong> " + tr ( " Friend " ) + " </strong> " ) ;
break ;
case RsFriendListModel : : ENTRY_TYPE_NODE :
//this is a SSL key
textLabel - > setText ( " <strong> " + tr ( " Node " ) + " </strong> " ) ;
break ;
}
switch ( type )
{
case RsFriendListModel : : ENTRY_TYPE_GROUP :
{
RsGroupInfo group_info ;
mModel - > getGroupData ( index , group_info ) ;
bool standard = group_info . flag & RS_GROUP_FLAG_STANDARD ;
2019-06-25 17:08:31 -04:00
# ifdef RS_DIRECT_CHAT
2019-06-28 10:20:26 -04:00
contextMenu . addAction ( QIcon ( IMAGE_MSG ) , tr ( " Send message to whole group " ) , this , SLOT ( msgGroup ( ) ) ) ;
contextMenu . addSeparator ( ) ;
2019-06-25 17:08:31 -04:00
# endif // RS_DIRECT_CHAT
2019-06-28 10:20:26 -04:00
contextMenu . addAction ( QIcon ( IMAGE_EDIT ) , tr ( " Edit Group " ) , this , SLOT ( editGroup ( ) ) ) ;
2019-06-25 17:08:31 -04:00
2019-06-28 10:20:26 -04:00
QAction * action = contextMenu . addAction ( QIcon ( IMAGE_REMOVE ) , tr ( " Remove Group " ) , this , SLOT ( removeGroup ( ) ) ) ;
action - > setDisabled ( standard ) ;
}
break ;
2019-06-25 17:08:31 -04:00
2019-06-28 10:20:26 -04:00
case RsFriendListModel : : ENTRY_TYPE_PROFILE :
{
contextMenu . addAction ( QIcon ( IMAGE_FRIENDINFO ) , tr ( " Profile details " ) , this , SLOT ( configureProfile ( ) ) ) ;
2019-08-30 05:11:40 -04:00
contextMenu . addAction ( QIcon ( IMAGE_DENYFRIEND ) , tr ( " Deny connections " ) , this , SLOT ( removeProfile ( ) ) ) ;
2019-06-28 10:20:26 -04:00
RsFriendListModel : : RsProfileDetails details ;
mModel - > getProfileData ( index , details ) ;
2019-08-11 05:46:49 -04:00
if ( mModel - > getDisplayGroups ( ) )
2019-06-28 10:20:26 -04:00
{
QMenu * addToGroupMenu = NULL ;
QMenu * moveToGroupMenu = NULL ;
std : : list < RsGroupInfo > groupInfoList ;
rsPeers - > getGroupInfoList ( groupInfoList ) ;
GroupDefs : : sortByName ( groupInfoList ) ;
RsPgpId gpgId ( details . gpg_id ) ;
2019-08-23 14:21:57 -04:00
QModelIndex parent = mModel - > parent ( index ) ;
2019-06-28 10:20:26 -04:00
bool foundGroup = false ;
// add action for all groups, except the own group
for ( std : : list < RsGroupInfo > : : iterator groupIt = groupInfoList . begin ( ) ; groupIt ! = groupInfoList . end ( ) ; + + groupIt ) {
if ( std : : find ( groupIt - > peerIds . begin ( ) , groupIt - > peerIds . end ( ) , gpgId ) = = groupIt - > peerIds . end ( ) ) {
2019-08-23 14:21:57 -04:00
if ( parent . isValid ( ) )
{
if ( addToGroupMenu = = NULL )
addToGroupMenu = new QMenu ( tr ( " Add to group " ) , & contextMenu ) ;
QAction * addToGroupAction = new QAction ( GroupDefs : : name ( * groupIt ) , addToGroupMenu ) ;
addToGroupAction - > setData ( QString : : fromStdString ( groupIt - > id . toStdString ( ) ) ) ;
connect ( addToGroupAction , SIGNAL ( triggered ( ) ) , this , SLOT ( addToGroup ( ) ) ) ;
addToGroupMenu - > addAction ( addToGroupAction ) ;
}
2019-06-28 10:20:26 -04:00
if ( moveToGroupMenu = = NULL ) {
moveToGroupMenu = new QMenu ( tr ( " Move to group " ) , & contextMenu ) ;
}
QAction * moveToGroupAction = new QAction ( GroupDefs : : name ( * groupIt ) , moveToGroupMenu ) ;
moveToGroupAction - > setData ( QString : : fromStdString ( groupIt - > id . toStdString ( ) ) ) ;
connect ( moveToGroupAction , SIGNAL ( triggered ( ) ) , this , SLOT ( moveToGroup ( ) ) ) ;
moveToGroupMenu - > addAction ( moveToGroupAction ) ;
} else {
foundGroup = true ;
}
}
QMenu * groupsMenu = contextMenu . addMenu ( QIcon ( IMAGE_GROUP16 ) , tr ( " Groups " ) ) ;
groupsMenu - > addAction ( QIcon ( IMAGE_EXPAND ) , tr ( " Create new group " ) , this , SLOT ( createNewGroup ( ) ) ) ;
if ( addToGroupMenu | | moveToGroupMenu | | foundGroup ) {
if ( addToGroupMenu ) {
groupsMenu - > addMenu ( addToGroupMenu ) ;
}
if ( moveToGroupMenu ) {
groupsMenu - > addMenu ( moveToGroupMenu ) ;
}
2019-08-23 14:21:57 -04:00
if ( foundGroup )
{
2019-06-28 10:20:26 -04:00
// add remove from group
2019-08-23 14:21:57 -04:00
if ( parent . isValid ( ) & & mModel - > getType ( parent ) = = RsFriendListModel : : ENTRY_TYPE_GROUP )
{
RsGroupInfo info ;
mModel - > getGroupData ( parent , info ) ;
QAction * removeFromGroup = groupsMenu - > addAction ( tr ( " Remove from group " ) + QString : : fromUtf8 ( info . name . c_str ( ) ) ) ;
removeFromGroup - > setData ( parent . sibling ( parent . row ( ) , RsFriendListModel : : COLUMN_THREAD_ID ) . data ( Qt : : DisplayRole ) ) ;
connect ( removeFromGroup , SIGNAL ( triggered ( ) ) , this , SLOT ( removeFromGroup ( ) ) ) ;
}
2019-06-28 10:20:26 -04:00
QAction * removeFromAllGroups = groupsMenu - > addAction ( tr ( " Remove from all groups " ) ) ;
removeFromAllGroups - > setData ( " " ) ;
connect ( removeFromAllGroups , SIGNAL ( triggered ( ) ) , this , SLOT ( removeFromGroup ( ) ) ) ;
}
}
}
}
break ;
case RsFriendListModel : : ENTRY_TYPE_NODE :
{
2019-06-25 17:08:31 -04:00
# ifdef RS_DIRECT_CHAT
2019-06-28 16:36:19 -04:00
contextMenu . addAction ( QIcon ( IMAGE_CHAT ) , tr ( " Chat " ) , this , SLOT ( chatNode ( ) ) ) ;
2019-06-28 10:20:26 -04:00
contextMenu . addAction ( QIcon ( IMAGE_MSG ) , tr ( " Send message to this node " ) , this , SLOT ( msgNode ( ) ) ) ;
contextMenu . addSeparator ( ) ;
2019-06-25 17:08:31 -04:00
# endif // RS_DIRECT_CHAT
2019-06-28 10:20:26 -04:00
contextMenu . addAction ( QIcon ( IMAGE_FRIENDINFO ) , tr ( " Node details " ) , this , SLOT ( configureNode ( ) ) ) ;
2019-06-25 17:08:31 -04:00
2019-08-23 14:21:57 -04:00
if ( type = = RsFriendListModel : : ENTRY_TYPE_PROFILE | | type = = RsFriendListModel : : ENTRY_TYPE_NODE )
2019-06-28 10:20:26 -04:00
contextMenu . addAction ( QIcon ( IMAGE_EXPORTFRIEND ) , tr ( " Recommend this node to... " ) , this , SLOT ( recommendNode ( ) ) ) ;
2019-08-23 14:21:57 -04:00
2019-06-28 10:20:26 -04:00
RsFriendListModel : : RsNodeDetails details ;
mModel - > getNodeData ( index , details ) ;
2019-06-25 17:08:31 -04:00
2019-06-28 10:20:26 -04:00
if ( ! rsPeers - > isHiddenNode ( rsPeers - > getOwnId ( ) ) | | rsPeers - > isHiddenNode ( details . id ) )
2019-08-24 14:45:13 -04:00
contextMenu . addAction ( QIcon ( IMAGE_CONNECT ) , tr ( " Attempt to connect " ) , this , SLOT ( connectNode ( ) ) ) ;
2019-06-25 17:08:31 -04:00
2019-06-28 10:20:26 -04:00
contextMenu . addAction ( QIcon ( IMAGE_COPYLINK ) , tr ( " Copy certificate link " ) , this , SLOT ( copyFullCertificate ( ) ) ) ;
2019-06-25 17:08:31 -04:00
2019-06-28 10:20:26 -04:00
//this is a SSL key
contextMenu . addAction ( QIcon ( IMAGE_REMOVEFRIEND ) , tr ( " Remove Friend Node " ) , this , SLOT ( removefriend ( ) ) ) ;
2019-06-25 17:08:31 -04:00
2019-06-28 10:20:26 -04:00
}
}
2019-06-25 17:08:31 -04:00
2019-06-28 10:20:26 -04:00
}
2019-06-25 17:08:31 -04:00
2019-06-28 10:20:26 -04:00
contextMenu . addSeparator ( ) ;
2019-06-25 17:08:31 -04:00
2019-06-28 10:20:26 -04:00
QAction * action = contextMenu . addAction ( QIcon ( IMAGE_PASTELINK ) , tr ( " Paste certificate link " ) , this , SLOT ( pastePerson ( ) ) ) ;
2019-06-25 17:08:31 -04:00
if ( RSLinkClipboard : : empty ( RetroShareLink : : TYPE_CERTIFICATE ) )
action - > setDisabled ( true ) ;
2019-06-28 10:20:26 -04:00
contextMenu . addAction ( QIcon ( IMAGE_EXPAND ) , tr ( " Expand all " ) , ui - > peerTreeWidget , SLOT ( expandAll ( ) ) ) ;
contextMenu . addAction ( QIcon ( IMAGE_COLLAPSE ) , tr ( " Collapse all " ) , ui - > peerTreeWidget , SLOT ( collapseAll ( ) ) ) ;
2019-06-25 17:08:31 -04:00
2019-08-15 09:49:20 -04:00
contextMenu . addSeparator ( ) ;
contextMenu . addAction ( ui - > actionExportFriendlist ) ;
contextMenu . addAction ( ui - > actionImportFriendlist ) ;
2019-06-28 10:20:26 -04:00
// contextMenu = ui->peerTreeWidget->createStandardContextMenu(contextMenu);
2019-06-25 17:08:31 -04:00
2019-06-28 10:20:26 -04:00
contextMenu . exec ( QCursor : : pos ( ) ) ;
2019-06-25 17:08:31 -04:00
}
void NewFriendList : : createNewGroup ( )
{
CreateGroup createGrpDialog ( RsNodeGroupId ( ) , this ) ;
createGrpDialog . exec ( ) ;
}
static QIcon createAvatar ( const QPixmap & avatar , const QPixmap & overlay )
{
int avatarWidth = avatar . width ( ) ;
int avatarHeight = avatar . height ( ) ;
QPixmap pixmap ( avatar ) ;
int overlaySize = ( avatarWidth > avatarHeight ) ? ( avatarWidth / 2.5 ) : ( avatarHeight / 2.5 ) ;
int overlayX = avatarWidth - overlaySize ;
int overlayY = avatarHeight - overlaySize ;
QPainter painter ( & pixmap ) ;
painter . drawPixmap ( overlayX , overlayY , overlaySize , overlaySize , overlay ) ;
QIcon icon ;
icon . addPixmap ( pixmap ) ;
return icon ;
}
void NewFriendList : : addFriend ( )
{
std : : string groupId = getSelectedGroupId ( ) ;
ConnectFriendWizard connwiz ( this ) ;
if ( groupId . empty ( ) = = false ) {
connwiz . setGroup ( groupId ) ;
}
connwiz . exec ( ) ;
}
2019-06-28 10:20:26 -04:00
void NewFriendList : : msgProfile ( )
2019-06-25 17:08:31 -04:00
{
2019-06-28 10:20:26 -04:00
RsFriendListModel : : RsNodeDetails det ;
2019-06-25 17:08:31 -04:00
2019-06-28 10:20:26 -04:00
if ( ! getCurrentNode ( det ) )
2019-06-25 17:08:31 -04:00
return ;
2019-06-28 10:20:26 -04:00
MessageComposer : : msgFriend ( det . id ) ;
2019-06-25 17:08:31 -04:00
}
2019-06-28 10:20:26 -04:00
void NewFriendList : : msgGroup ( )
{
RsFriendListModel : : RsNodeDetails det ;
if ( ! getCurrentNode ( det ) )
return ;
2019-06-25 17:08:31 -04:00
2019-06-28 10:20:26 -04:00
MessageComposer : : msgFriend ( det . id ) ;
}
void NewFriendList : : msgNode ( )
2019-06-25 17:08:31 -04:00
{
2019-06-28 10:20:26 -04:00
RsFriendListModel : : RsNodeDetails det ;
2019-06-25 17:08:31 -04:00
2019-06-28 10:20:26 -04:00
if ( ! getCurrentNode ( det ) )
2019-06-25 17:08:31 -04:00
return ;
2019-06-28 10:20:26 -04:00
MessageComposer : : msgFriend ( det . id ) ;
}
2019-06-28 16:36:19 -04:00
void NewFriendList : : chatNode ( )
{
RsFriendListModel : : RsNodeDetails det ;
if ( ! getCurrentNode ( det ) )
return ;
ChatDialog : : chatFriend ( ChatId ( det . id ) ) ;
}
2019-06-25 17:08:31 -04:00
2019-06-28 10:20:26 -04:00
void NewFriendList : : recommendNode ( )
{
RsFriendListModel : : RsNodeDetails det ;
if ( ! getCurrentNode ( det ) )
2019-06-25 17:08:31 -04:00
return ;
2019-06-28 10:20:26 -04:00
MessageComposer : : recommendFriend ( std : : set < RsPeerId > ( { det . id } ) ) ;
2019-06-25 17:08:31 -04:00
}
void NewFriendList : : pastePerson ( )
{
//RSLinkClipboard::process(RetroShareLink::TYPE_PERSON);
RSLinkClipboard : : process ( RetroShareLink : : TYPE_CERTIFICATE ) ;
}
void NewFriendList : : copyFullCertificate ( )
{
2019-06-28 10:20:26 -04:00
RsFriendListModel : : RsNodeDetails det ;
if ( ! getCurrentNode ( det ) )
return ;
2019-06-25 17:08:31 -04:00
QList < RetroShareLink > urls ;
2019-06-28 10:20:26 -04:00
RetroShareLink link = RetroShareLink : : createCertificate ( det . id ) ;
2019-06-25 17:08:31 -04:00
urls . push_back ( link ) ;
std : : cerr < < " link: " < < std : : endl ;
std : : cerr < < link . toString ( ) . toStdString ( ) < < std : : endl ;
RSLinkClipboard : : copyLinks ( urls ) ;
}
/**
* Find out which group is selected
*
* @ return If a group item is selected , its groupId otherwise an empty string
*/
std : : string NewFriendList : : getSelectedGroupId ( ) const
{
2019-06-28 10:20:26 -04:00
RsGroupInfo ginfo ;
if ( ! getCurrentGroup ( ginfo ) )
return std : : string ( ) ;
2019-06-25 17:08:31 -04:00
2019-06-28 10:20:26 -04:00
return ginfo . id . toStdString ( ) ;
2019-06-25 17:08:31 -04:00
}
2019-08-06 16:52:07 -04:00
QModelIndex NewFriendList : : getCurrentSourceIndex ( ) const
2019-06-28 10:20:26 -04:00
{
QModelIndexList selectedIndexes = ui - > peerTreeWidget - > selectionModel ( ) - > selectedIndexes ( ) ;
if ( selectedIndexes . size ( ) ! = RsFriendListModel : : COLUMN_THREAD_NB_COLUMNS ) // check that a single row is selected
return QModelIndex ( ) ;
2019-08-06 16:52:07 -04:00
return mProxyModel - > mapToSource ( * selectedIndexes . begin ( ) ) ;
2019-06-28 10:20:26 -04:00
}
bool NewFriendList : : getCurrentGroup ( RsGroupInfo & info ) const
2019-06-25 17:08:31 -04:00
{
/* get the current, and extract the Id */
2019-08-06 16:52:07 -04:00
QModelIndex index = getCurrentSourceIndex ( ) ;
2019-06-25 17:08:31 -04:00
2019-06-28 10:20:26 -04:00
if ( ! index . isValid ( ) )
return false ;
return mModel - > getGroupData ( index , info ) ;
}
bool NewFriendList : : getCurrentNode ( RsFriendListModel : : RsNodeDetails & prof ) const
{
/* get the current, and extract the Id */
2019-08-06 16:52:07 -04:00
QModelIndex index = getCurrentSourceIndex ( ) ;
2019-06-28 10:20:26 -04:00
if ( ! index . isValid ( ) )
return false ;
return mModel - > getNodeData ( index , prof ) ;
}
bool NewFriendList : : getCurrentProfile ( RsFriendListModel : : RsProfileDetails & prof ) const
{
/* get the current, and extract the Id */
2019-08-06 16:52:07 -04:00
QModelIndex index = getCurrentSourceIndex ( ) ;
2019-06-28 10:20:26 -04:00
if ( ! index . isValid ( ) )
return false ;
return mModel - > getProfileData ( index , prof ) ;
2019-06-25 17:08:31 -04:00
}
# ifdef UNFINISHED_FD
/* GUI stuff -> don't do anything directly with Control */
void FriendsDialog : : viewprofile ( )
{
/* display Dialog */
QTreeWidgetItem * c = getCurrentPeer ( ) ;
// static ProfileView *profileview = new ProfileView();
if ( ! c )
return ;
/* set the Id */
std : : string id = getRsId ( c ) ;
profileview - > setPeerId ( id ) ;
profileview - > show ( ) ;
}
# endif
/* So from the Peers Dialog we can call the following control Functions:
* ( 1 ) Remove Current . FriendRemove ( id )
* ( 2 ) Allow / DisAllow . FriendStatus ( id , accept )
* ( 2 ) Connect . FriendConnectAttempt ( id , accept )
* ( 3 ) Set Address . FriendSetAddress ( id , str , port )
* ( 4 ) Set Trust . FriendTrustSignature ( id , bool )
* ( 5 ) Configure ( GUI Only ) - > 3 / 4
*
* All of these rely on the finding of the current Id .
*/
2019-06-28 10:20:26 -04:00
void NewFriendList : : removeNode ( )
2019-06-25 17:08:31 -04:00
{
2019-06-28 10:20:26 -04:00
RsFriendListModel : : RsNodeDetails det ;
if ( ! getCurrentNode ( det ) | | ! rsPeers )
2019-06-25 17:08:31 -04:00
return ;
2019-06-28 10:20:26 -04:00
if ( ( QMessageBox : : question ( this , " RetroShare " , tr ( " Do you want to remove this node? " ) , QMessageBox : : Yes | QMessageBox : : No , QMessageBox : : Yes ) ) = = QMessageBox : : Yes )
rsPeers - > removeFriendLocation ( det . id ) ;
2019-08-30 05:11:40 -04:00
checkInternalData ( true ) ;
2019-06-25 17:08:31 -04:00
}
2019-06-28 10:20:26 -04:00
void NewFriendList : : removeProfile ( )
2019-06-25 17:08:31 -04:00
{
2019-06-28 10:20:26 -04:00
RsFriendListModel : : RsProfileDetails det ;
if ( ! getCurrentProfile ( det ) | | ! rsPeers )
2019-06-25 17:08:31 -04:00
return ;
2019-06-28 10:20:26 -04:00
if ( ( QMessageBox : : question ( this , " RetroShare " , tr ( " Do you want to remove this Friend? " ) , QMessageBox : : Yes | QMessageBox : : No , QMessageBox : : Yes ) ) = = QMessageBox : : Yes )
rsPeers - > removeFriend ( det . gpg_id ) ;
2019-08-30 05:11:40 -04:00
checkInternalData ( true ) ;
2019-06-25 17:08:31 -04:00
}
2019-06-28 10:20:26 -04:00
void NewFriendList : : connectNode ( )
2019-06-25 17:08:31 -04:00
{
2019-06-28 10:20:26 -04:00
RsFriendListModel : : RsNodeDetails det ;
if ( ! getCurrentNode ( det ) | | ! rsPeers )
return ;
rsPeers - > connectAttempt ( det . id ) ;
ConnectProgressDialog : : showProgress ( det . id ) ;
2019-06-25 17:08:31 -04:00
}
2019-06-28 10:20:26 -04:00
/* GUI stuff -> don't do anything directly with Control */
void NewFriendList : : configureNode ( )
2019-06-25 17:08:31 -04:00
{
2019-06-28 10:20:26 -04:00
RsFriendListModel : : RsNodeDetails det ;
if ( ! getCurrentNode ( det ) )
2019-06-25 17:08:31 -04:00
return ;
2019-06-28 10:20:26 -04:00
ConfCertDialog : : showIt ( det . id , ConfCertDialog : : PageDetails ) ;
}
void NewFriendList : : configureProfile ( )
{
RsFriendListModel : : RsProfileDetails det ;
2019-06-25 17:08:31 -04:00
2019-06-28 10:20:26 -04:00
if ( ! getCurrentProfile ( det ) )
return ;
PGPKeyDialog : : showIt ( det . gpg_id , PGPKeyDialog : : PageDetails ) ;
2019-06-25 17:08:31 -04:00
}
void NewFriendList : : addToGroup ( )
{
2019-06-28 10:20:26 -04:00
RsFriendListModel : : RsProfileDetails det ;
if ( ! getCurrentProfile ( det ) | | ! rsPeers )
2019-06-25 17:08:31 -04:00
return ;
RsNodeGroupId groupId ( qobject_cast < QAction * > ( sender ( ) ) - > data ( ) . toString ( ) . toStdString ( ) ) ;
2019-06-28 10:20:26 -04:00
RsPgpId gpgId ( det . gpg_id ) ;
2019-06-25 17:08:31 -04:00
2019-06-28 10:20:26 -04:00
if ( gpgId . isNull ( ) | | groupId . isNull ( ) )
2019-06-25 17:08:31 -04:00
return ;
// automatically expand the group, the peer is added to
2019-08-26 12:27:20 -04:00
expandGroup ( groupId ) ;
2019-06-25 17:08:31 -04:00
// add to group
rsPeers - > assignPeerToGroup ( groupId , gpgId , true ) ;
2019-08-22 07:13:04 -04:00
checkInternalData ( true ) ;
2019-08-21 16:39:07 -04:00
}
void NewFriendList : : forceUpdateDisplay ( )
{
2019-08-22 07:13:04 -04:00
checkInternalData ( true ) ;
2019-08-21 16:39:07 -04:00
}
2019-08-30 07:57:27 -04:00
// void NewFriendList::updateDisplay()
// {
// checkInternalData(false);
// }
2019-06-25 17:08:31 -04:00
void NewFriendList : : moveToGroup ( )
{
2019-06-28 10:20:26 -04:00
RsFriendListModel : : RsProfileDetails pinfo ;
2019-06-25 17:08:31 -04:00
2019-06-28 10:20:26 -04:00
if ( ! getCurrentProfile ( pinfo ) )
2019-06-25 17:08:31 -04:00
return ;
RsNodeGroupId groupId ( qobject_cast < QAction * > ( sender ( ) ) - > data ( ) . toString ( ) . toStdString ( ) ) ;
2019-06-28 10:20:26 -04:00
RsPgpId gpgId ( pinfo . gpg_id ) ;
2019-06-25 17:08:31 -04:00
2019-06-28 10:20:26 -04:00
if ( gpgId . isNull ( ) | | groupId . isNull ( ) )
2019-06-25 17:08:31 -04:00
return ;
// remove from all groups
rsPeers - > assignPeerToGroup ( RsNodeGroupId ( ) , gpgId , false ) ;
// automatically expand the group, the peer is added to
2019-08-26 12:27:20 -04:00
expandGroup ( groupId ) ;
2019-06-25 17:08:31 -04:00
// add to group
rsPeers - > assignPeerToGroup ( groupId , gpgId , true ) ;
2019-08-22 07:13:04 -04:00
checkInternalData ( true ) ;
2019-06-25 17:08:31 -04:00
}
void NewFriendList : : removeFromGroup ( )
{
2019-06-28 10:20:26 -04:00
RsFriendListModel : : RsProfileDetails pinfo ;
2019-06-25 17:08:31 -04:00
2019-06-28 10:20:26 -04:00
if ( ! getCurrentProfile ( pinfo ) )
2019-06-25 17:08:31 -04:00
return ;
RsNodeGroupId groupId ( qobject_cast < QAction * > ( sender ( ) ) - > data ( ) . toString ( ) . toStdString ( ) ) ;
2019-06-28 10:20:26 -04:00
RsPgpId gpgId ( pinfo . gpg_id ) ;
2019-06-25 17:08:31 -04:00
2019-06-28 10:20:26 -04:00
if ( gpgId . isNull ( ) )
2019-06-25 17:08:31 -04:00
return ;
// remove from (all) group(s)
rsPeers - > assignPeerToGroup ( groupId , gpgId , false ) ;
2019-08-22 07:13:04 -04:00
checkInternalData ( true ) ;
2019-06-25 17:08:31 -04:00
}
void NewFriendList : : editGroup ( )
{
2019-06-28 10:20:26 -04:00
RsGroupInfo pinfo ;
2019-06-25 17:08:31 -04:00
2019-06-28 10:20:26 -04:00
if ( ! getCurrentGroup ( pinfo ) )
2019-06-25 17:08:31 -04:00
return ;
2019-06-28 10:20:26 -04:00
RsNodeGroupId groupId ( pinfo . id ) ;
2019-06-25 17:08:31 -04:00
if ( ! groupId . isNull ( ) )
{
CreateGroup editGrpDialog ( groupId , this ) ;
editGrpDialog . exec ( ) ;
}
2019-08-22 07:13:04 -04:00
checkInternalData ( true ) ;
2019-06-25 17:08:31 -04:00
}
void NewFriendList : : removeGroup ( )
{
2019-06-28 10:20:26 -04:00
RsGroupInfo pinfo ;
2019-06-25 17:08:31 -04:00
2019-06-28 10:20:26 -04:00
if ( ! getCurrentGroup ( pinfo ) )
2019-06-25 17:08:31 -04:00
return ;
2019-06-28 10:20:26 -04:00
rsPeers - > removeGroup ( pinfo . id ) ;
2019-08-22 07:13:04 -04:00
checkInternalData ( true ) ;
}
void NewFriendList : : checkInternalData ( bool force )
{
std : : set < QString > expanded_indexes ;
std : : set < QString > selected_indexes ;
2019-08-23 14:21:57 -04:00
saveExpandedPathsAndSelection ( expanded_indexes , selected_indexes ) ;
2019-08-22 07:13:04 -04:00
mModel - > checkInternalData ( force ) ;
2019-08-23 14:21:57 -04:00
restoreExpandedPathsAndSelection ( expanded_indexes , selected_indexes ) ;
2019-06-25 17:08:31 -04:00
}
void NewFriendList : : exportFriendlistClicked ( )
{
QString fileName ;
if ( ! importExportFriendlistFileDialog ( fileName , false ) )
// error was already shown - just return
return ;
if ( ! exportFriendlist ( fileName ) )
// error was already shown - just return
return ;
QMessageBox mbox ;
mbox . setIcon ( QMessageBox : : Information ) ;
mbox . setText ( tr ( " Done! " ) ) ;
mbox . setInformativeText ( tr ( " Your friendlist is stored at: \n " ) + fileName +
tr ( " \n (keep in mind that the file is unencrypted!) " ) ) ;
mbox . setStandardButtons ( QMessageBox : : Ok ) ;
mbox . exec ( ) ;
}
void NewFriendList : : importFriendlistClicked ( )
{
QString fileName ;
if ( ! importExportFriendlistFileDialog ( fileName , true ) )
// error was already shown - just return
return ;
bool errorPeers , errorGroups ;
if ( importFriendlist ( fileName , errorPeers , errorGroups ) ) {
QMessageBox mbox ;
mbox . setIcon ( QMessageBox : : Information ) ;
mbox . setText ( tr ( " Done! " ) ) ;
mbox . setInformativeText ( tr ( " Your friendlist was imported from: \n " ) + fileName ) ;
mbox . setStandardButtons ( QMessageBox : : Ok ) ;
mbox . exec ( ) ;
} else {
QMessageBox mbox ;
mbox . setIcon ( QMessageBox : : Warning ) ;
mbox . setText ( tr ( " Done - but errors happened! " ) ) ;
mbox . setInformativeText ( tr ( " Your friendlist was imported from: \n " ) + fileName +
( errorPeers ? tr ( " \n at least one peer was not added " ) : " " ) +
( errorGroups ? tr ( " \n at least one peer was not added to a group " ) : " " )
) ;
mbox . setStandardButtons ( QMessageBox : : Ok ) ;
mbox . exec ( ) ;
}
}
/**
* @ brief opens a file dialog to select a file containing a friendlist
* @ param fileName file containing a friendlist
* @ param import show dialog for importing ( true ) or exporting ( false ) friendlist
* @ return success or failure
*
* This function also shows an error message when no valid file was selected
*/
bool NewFriendList : : importExportFriendlistFileDialog ( QString & fileName , bool import )
{
bool res = true ;
if ( import ) {
res = misc : : getOpenFileName ( this , RshareSettings : : LASTDIR_CERT
, tr ( " Select file for importing your friendlist from " )
, tr ( " XML File (*.xml);;All Files (*) " )
, fileName
, QFileDialog : : DontConfirmOverwrite
) ;
} else {
res = misc : : getSaveFileName ( this , RshareSettings : : LASTDIR_CERT
, tr ( " Select a file for exporting your friendlist to " )
, tr ( " XML File (*.xml);;All Files (*) " )
, fileName , NULL
, ( QFileDialog : : Options ) 0
) ;
}
if ( res & & ! fileName . endsWith ( " .xml " , Qt : : CaseInsensitive ) )
fileName = fileName . append ( " .xml " ) ;
return res ;
}
/**
* @ brief exports friendlist to a given file
* @ param fileName file for storing friendlist
* @ return success or failure
*
* This function also shows an error message when the selected file is invalid / not writable
*/
bool NewFriendList : : exportFriendlist ( QString & fileName )
{
QDomDocument doc ( " FriendListWithGroups " ) ;
QDomElement root = doc . createElement ( " root " ) ;
doc . appendChild ( root ) ;
QFile file ( fileName ) ;
if ( ! file . open ( QIODevice : : WriteOnly | QIODevice : : Truncate | QIODevice : : Text ) ) {
// show error to user
QMessageBox mbox ;
mbox . setIcon ( QMessageBox : : Warning ) ;
mbox . setText ( tr ( " Error " ) ) ;
mbox . setInformativeText ( tr ( " File is not writeable! \n " ) + fileName ) ;
mbox . setStandardButtons ( QMessageBox : : Ok ) ;
mbox . exec ( ) ;
return false ;
}
std : : list < RsPgpId > gpg_ids ;
rsPeers - > getGPGAcceptedList ( gpg_ids ) ;
std : : list < RsGroupInfo > group_info_list ;
rsPeers - > getGroupInfoList ( group_info_list ) ;
QDomElement pgpIDs = doc . createElement ( " pgpIDs " ) ;
RsPeerDetails detailPGP ;
for ( std : : list < RsPgpId > : : iterator list_iter = gpg_ids . begin ( ) ; list_iter ! = gpg_ids . end ( ) ; list_iter + + ) {
rsPeers - > getGPGDetails ( * list_iter , detailPGP ) ;
QDomElement pgpID = doc . createElement ( " pgpID " ) ;
// these values aren't used and just stored for better human readability
pgpID . setAttribute ( " id " , QString : : fromStdString ( detailPGP . gpg_id . toStdString ( ) ) ) ;
pgpID . setAttribute ( " name " , QString : : fromUtf8 ( detailPGP . name . c_str ( ) ) ) ;
std : : list < RsPeerId > ssl_ids ;
rsPeers - > getAssociatedSSLIds ( * list_iter , ssl_ids ) ;
for ( std : : list < RsPeerId > : : iterator list_iter = ssl_ids . begin ( ) ; list_iter ! = ssl_ids . end ( ) ; list_iter + + ) {
RsPeerDetails detailSSL ;
if ( ! rsPeers - > getPeerDetails ( * list_iter , detailSSL ) )
continue ;
std : : string certificate = rsPeers - > GetRetroshareInvite ( detailSSL . id , true , true ) ;
// remove \n from certificate
certificate . erase ( std : : remove ( certificate . begin ( ) , certificate . end ( ) , ' \n ' ) , certificate . end ( ) ) ;
QDomElement sslID = doc . createElement ( " sslID " ) ;
// these values aren't used and just stored for better human readability
sslID . setAttribute ( " sslID " , QString : : fromStdString ( detailSSL . id . toStdString ( ) ) ) ;
if ( ! detailSSL . location . empty ( ) )
sslID . setAttribute ( " location " , QString : : fromUtf8 ( detailSSL . location . c_str ( ) ) ) ;
// required values
sslID . setAttribute ( " certificate " , QString : : fromStdString ( certificate ) ) ;
sslID . setAttribute ( " service_perm_flags " , detailSSL . service_perm_flags . toUInt32 ( ) ) ;
pgpID . appendChild ( sslID ) ;
}
pgpIDs . appendChild ( pgpID ) ;
}
root . appendChild ( pgpIDs ) ;
QDomElement groups = doc . createElement ( " groups " ) ;
for ( std : : list < RsGroupInfo > : : iterator list_iter = group_info_list . begin ( ) ; list_iter ! = group_info_list . end ( ) ; list_iter + + ) {
RsGroupInfo group_info = * list_iter ;
//skip groups without peers
if ( group_info . peerIds . empty ( ) )
continue ;
QDomElement group = doc . createElement ( " group " ) ;
// id is not needed since it may differ between locatiosn / pgp ids (groups are identified by name)
group . setAttribute ( " name " , QString : : fromUtf8 ( group_info . name . c_str ( ) ) ) ;
group . setAttribute ( " flag " , group_info . flag ) ;
for ( std : : set < RsPgpId > : : iterator i = group_info . peerIds . begin ( ) ; i ! = group_info . peerIds . end ( ) ; i + + ) {
QDomElement pgpID = doc . createElement ( " pgpID " ) ;
std : : string pid = i - > toStdString ( ) ;
pgpID . setAttribute ( " id " , QString : : fromStdString ( pid ) ) ;
group . appendChild ( pgpID ) ;
}
groups . appendChild ( group ) ;
}
root . appendChild ( groups ) ;
QTextStream ts ( & file ) ;
ts . setCodec ( " UTF-8 " ) ;
ts < < doc . toString ( ) ;
file . close ( ) ;
return true ;
}
/**
* @ brief helper function to show a message box
*/
2019-06-28 16:36:19 -04:00
static void showXMLParsingError ( )
2019-06-25 17:08:31 -04:00
{
// show error to user
QMessageBox mbox ;
mbox . setIcon ( QMessageBox : : Warning ) ;
mbox . setText ( QObject : : tr ( " Error " ) ) ;
mbox . setInformativeText ( QObject : : tr ( " unable to parse XML file! " ) ) ;
mbox . setStandardButtons ( QMessageBox : : Ok ) ;
mbox . exec ( ) ;
}
/**
* @ brief Imports friends from a given file
* @ param fileName file to load friends from
* @ param errorPeers an error occured while adding a peer
* @ param errorGroups an error occured while adding a peer to a group
* @ return success or failure ( an error can also happen when adding a peer and / or adding a peer to a group fails at least once )
*/
bool NewFriendList : : importFriendlist ( QString & fileName , bool & errorPeers , bool & errorGroups )
{
QDomDocument doc ;
// load from file
{
QFile file ( fileName ) ;
if ( ! file . open ( QIODevice : : ReadOnly ) ) {
// show error to user
QMessageBox mbox ;
mbox . setIcon ( QMessageBox : : Warning ) ;
mbox . setText ( tr ( " Error " ) ) ;
mbox . setInformativeText ( tr ( " File is not readable! \n " ) + fileName ) ;
mbox . setStandardButtons ( QMessageBox : : Ok ) ;
mbox . exec ( ) ;
return false ;
}
bool ok = doc . setContent ( & file ) ;
file . close ( ) ;
if ( ! ok ) {
showXMLParsingError ( ) ;
return false ;
}
}
QDomElement root = doc . documentElement ( ) ;
if ( root . tagName ( ) ! = " root " ) {
showXMLParsingError ( ) ;
return false ;
}
errorPeers = false ;
errorGroups = false ;
std : : string error_string ;
RsPeerDetails rsPeerDetails ;
RsPeerId rsPeerID ;
RsPgpId rsPgpID ;
// lock all events for faster processing
RsAutoUpdatePage : : lockAllEvents ( ) ;
// pgp and ssl IDs
QDomElement pgpIDs ;
{
QDomNodeList nodes = root . elementsByTagName ( " pgpIDs " ) ;
if ( nodes . isEmpty ( ) | | nodes . size ( ) ! = 1 ) {
showXMLParsingError ( ) ;
return false ;
}
pgpIDs = nodes . item ( 0 ) . toElement ( ) ;
if ( pgpIDs . isNull ( ) ) {
showXMLParsingError ( ) ;
return false ;
}
}
QDomNode pgpIDElem = pgpIDs . firstChildElement ( " pgpID " ) ;
while ( ! pgpIDElem . isNull ( ) ) {
QDomElement sslIDElem = pgpIDElem . firstChildElement ( " sslID " ) ;
while ( ! sslIDElem . isNull ( ) ) {
rsPeerID . clear ( ) ;
rsPgpID . clear ( ) ;
// load everything needed from the pubkey string
std : : string pubkey = sslIDElem . attribute ( " certificate " ) . toStdString ( ) ;
ServicePermissionFlags service_perm_flags ( sslIDElem . attribute ( " service_perm_flags " ) . toInt ( ) ) ;
if ( ! rsPeers - > acceptInvite ( pubkey , service_perm_flags ) ) {
errorPeers = true ;
std : : cerr < < " FriendList::importFriendlist(): failed to get peer detaisl from public key (SSL id: " < < sslIDElem . attribute ( " sslID " , " invalid " ) . toStdString ( ) < < " ) " < < std : : endl ;
}
sslIDElem = sslIDElem . nextSiblingElement ( " sslID " ) ;
}
pgpIDElem = pgpIDElem . nextSiblingElement ( " pgpID " ) ;
}
// groups
QDomElement groups ;
{
QDomNodeList nodes = root . elementsByTagName ( " groups " ) ;
if ( nodes . isEmpty ( ) | | nodes . size ( ) ! = 1 ) {
showXMLParsingError ( ) ;
return false ;
}
groups = nodes . item ( 0 ) . toElement ( ) ;
if ( groups . isNull ( ) ) {
showXMLParsingError ( ) ;
return false ;
}
}
QDomElement group = groups . firstChildElement ( " group " ) ;
while ( ! group . isNull ( ) ) {
// get name and flags and try to get the group ID
std : : string groupName = group . attribute ( " name " ) . toStdString ( ) ;
uint32_t flag = group . attribute ( " flag " ) . toInt ( ) ;
RsNodeGroupId groupId ;
if ( getOrCreateGroup ( groupName , flag , groupId ) ) {
// group id found!
QDomElement pgpID = group . firstChildElement ( " pgpID " ) ;
while ( ! pgpID . isNull ( ) ) {
// add pgp id to group
RsPgpId rsPgpId ( pgpID . attribute ( " id " ) . toStdString ( ) ) ;
if ( rsPgpID . isNull ( ) | | ! rsPeers - > assignPeerToGroup ( groupId , rsPgpId , true ) ) {
errorGroups = true ;
std : : cerr < < " FriendList::importFriendlist(): failed to add ' " < < rsPeers - > getGPGName ( rsPgpId ) < < " '' to group ' " < < groupName < < " ' " < < std : : endl ;
}
pgpID = pgpID . nextSiblingElement ( " pgpID " ) ;
}
pgpID = pgpID . nextSiblingElement ( " pgpID " ) ;
} else {
errorGroups = true ;
std : : cerr < < " FriendList::importFriendlist(): failed to find/create group ' " < < groupName < < " ' " < < std : : endl ;
}
group = group . nextSiblingElement ( " group " ) ;
}
// unlock events
RsAutoUpdatePage : : unlockAllEvents ( ) ;
return ! ( errorPeers | | errorGroups ) ;
}
/**
* @ brief Gets the groups ID for a given group name
* @ param name group name to search for
* @ param id groupd id for the given name
* @ return success or fail
*/
bool NewFriendList : : getGroupIdByName ( const std : : string & name , RsNodeGroupId & id )
{
std : : list < RsGroupInfo > grpList ;
if ( ! rsPeers - > getGroupInfoList ( grpList ) )
return false ;
foreach ( const RsGroupInfo & grp , grpList ) {
if ( grp . name = = name ) {
id = grp . id ;
return true ;
}
}
return false ;
}
/**
* @ brief Gets the groups ID for a given group name . If no groupd was it will create one
* @ param name group name to search for
* @ param flag flag to use when creating the group
* @ param id groupd id
* @ return success or failure
*/
2019-06-28 10:20:26 -04:00
bool NewFriendList : : getOrCreateGroup ( const std : : string & name , uint flag , RsNodeGroupId & id )
2019-06-25 17:08:31 -04:00
{
if ( getGroupIdByName ( name , id ) )
return true ;
// -> create one
RsGroupInfo grp ;
grp . id . clear ( ) ; // RS will generate an ID
grp . name = name ;
grp . flag = flag ;
if ( ! rsPeers - > addGroup ( grp ) )
return false ;
// try again
return getGroupIdByName ( name , id ) ;
}
2019-08-15 09:49:20 -04:00
void NewFriendList : : setShowUnconnected ( bool show )
2019-06-25 17:08:31 -04:00
{
2019-08-15 09:49:20 -04:00
mProxyModel - > setShowOfflineNodes ( show ) ;
2019-08-12 06:49:04 -04:00
mProxyModel - > setFilterRegExp ( QRegExp ( QString ( RsFriendListModel : : FilterString ) ) ) ; // triggers a re-display.
2019-06-25 17:08:31 -04:00
}
2019-08-15 09:49:20 -04:00
bool NewFriendList : : isColumnVisible ( int col ) const
{
return ! ui - > peerTreeWidget - > isColumnHidden ( col ) ;
}
2019-08-03 15:07:48 -04:00
void NewFriendList : : setColumnVisible ( int col , bool visible )
{
ui - > peerTreeWidget - > setColumnHidden ( col , ! visible ) ;
}
void NewFriendList : : toggleColumnVisible ( )
2019-06-25 17:08:31 -04:00
{
2019-08-03 15:07:48 -04:00
QAction * action = dynamic_cast < QAction * > ( sender ( ) ) ;
if ( ! action )
return ;
int column = action - > data ( ) . toInt ( ) ;
bool visible = action - > isChecked ( ) ;
2019-06-25 17:08:31 -04:00
ui - > peerTreeWidget - > setColumnHidden ( column , ! visible ) ;
}
void NewFriendList : : setShowState ( bool show )
{
2019-08-15 13:43:41 -04:00
mModel - > setDisplayStatusString ( show ) ;
2019-06-25 17:08:31 -04:00
}
void NewFriendList : : setShowGroups ( bool show )
{
2019-06-28 10:20:26 -04:00
mModel - > setDisplayGroups ( show ) ;
2019-06-25 17:08:31 -04:00
}
/**
* Hides all items that don ' t contain text in the name column .
*/
void NewFriendList : : filterItems ( const QString & text )
{
2019-06-28 10:20:26 -04:00
QStringList lst = text . split ( ' ' , QString : : SkipEmptyParts ) ;
2019-08-12 06:49:04 -04:00
int filterColumn = ui - > filterLineEdit - > currentFilter ( ) ;
2019-06-28 10:20:26 -04:00
if ( filterColumn = = 0 )
mModel - > setFilter ( RsFriendListModel : : FILTER_TYPE_NAME , lst ) ;
2019-08-23 14:21:57 -04:00
else
2019-06-28 10:20:26 -04:00
mModel - > setFilter ( RsFriendListModel : : FILTER_TYPE_ID , lst ) ;
2019-08-12 06:49:04 -04:00
// We do this in order to trigger a new filtering action in the proxy model.
mProxyModel - > setFilterRegExp ( QRegExp ( QString ( RsFriendListModel : : FilterString ) ) ) ;
if ( ! lst . empty ( ) )
ui - > peerTreeWidget - > expandAll ( ) ;
else
ui - > peerTreeWidget - > collapseAll ( ) ;
2019-06-25 17:08:31 -04:00
}
2019-08-26 12:27:20 -04:00
void NewFriendList : : expandGroup ( const RsNodeGroupId & gid )
2019-06-25 17:08:31 -04:00
{
2019-08-26 12:27:20 -04:00
QModelIndex index = mProxyModel - > mapFromSource ( mModel - > getIndexOfGroup ( gid ) ) ;
ui - > peerTreeWidget - > setExpanded ( index , true ) ;
2019-06-25 17:08:31 -04:00
}