2018-11-11 14:41:06 -05:00
/*******************************************************************************
* gui / common / RSFeedWidget . cpp *
* *
* Copyright ( C ) 2014 , 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/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2014-08-01 10:49:58 -04:00
# include <QKeyEvent>
2014-11-24 18:55:51 -05:00
# include <QScrollBar>
2014-08-01 10:49:58 -04:00
# include "RSFeedWidget.h"
# include "ui_RSFeedWidget.h"
# include "RSTreeWidgetItem.h"
# include "gui/feeds/FeedItem.h"
2015-03-12 09:59:56 -04:00
# include <iostream>
2014-08-01 10:49:58 -04:00
2019-12-19 17:34:10 -05:00
# define COLUMN_FEED 0
# define COLUMN_IDENTIFIER 1
2014-08-01 10:49:58 -04:00
2014-11-24 18:55:51 -05:00
# define SINGLE_STEP 15
/* Redefine single step for srolling */
class RSFeedWidgetScrollBar : public QScrollBar
{
public :
RSFeedWidgetScrollBar ( QWidget * parent = 0 ) : QScrollBar ( parent ) { }
void sliderChange ( SliderChange change )
{
if ( change = = SliderStepsChange ) {
if ( singleStep ( ) > SINGLE_STEP ) {
/* Set our own value */
setSingleStep ( SINGLE_STEP ) ;
return ;
}
}
QScrollBar : : sliderChange ( change ) ;
}
} ;
2014-08-01 10:49:58 -04:00
RSFeedWidget : : RSFeedWidget ( QWidget * parent )
: QWidget ( parent ) , ui ( new Ui : : RSFeedWidget )
{
/* Invoke the Qt Designer generated object setup routine */
ui - > setupUi ( this ) ;
/* Sort */
mFeedCompareRole = new RSTreeWidgetItemCompareRole ;
/* Filter */
mFilterCallback = NULL ;
mFilterType = 0 ;
/* Remove */
mEnableRemove = false ;
2014-11-15 12:24:49 -05:00
/* Options */
mCountChangedDisabled = 0 ;
2014-08-01 10:49:58 -04:00
ui - > treeWidget - > installEventFilter ( this ) ;
2014-11-24 18:55:51 -05:00
ui - > treeWidget - > setVerticalScrollBar ( new RSFeedWidgetScrollBar ) ;
2019-12-19 17:34:10 -05:00
ui - > treeWidget - > setColumnCount ( 2 ) ;
ui - > treeWidget - > setColumnHidden ( COLUMN_IDENTIFIER , true ) ;
2014-08-01 10:49:58 -04:00
}
RSFeedWidget : : ~ RSFeedWidget ( )
{
delete ( mFeedCompareRole ) ;
delete ( ui ) ;
}
bool RSFeedWidget : : eventFilter ( QObject * object , QEvent * event )
{
if ( object = = ui - > treeWidget ) {
if ( event - > type ( ) = = QEvent : : KeyPress ) {
QKeyEvent * keyEvent = static_cast < QKeyEvent * > ( event ) ;
if ( keyEvent ) {
if ( keyEvent - > key ( ) = = Qt : : Key_Plus | | keyEvent - > key ( ) = = Qt : : Key_Minus ) {
bool open = ( keyEvent - > key ( ) = = Qt : : Key_Plus ) ;
QList < FeedItem * > feedItems ;
selectedFeedItems ( feedItems ) ;
foreach ( FeedItem * feedItem , feedItems ) {
feedItem - > expand ( open ) ;
}
return true ; // eat event
}
if ( mEnableRemove & & keyEvent - > key ( ) = = Qt : : Key_Delete ) {
QList < QTreeWidgetItem * > selectedItems = ui - > treeWidget - > selectedItems ( ) ;
foreach ( QTreeWidgetItem * treeItem , selectedItems ) {
FeedItem * feedItem = feedItemFromTreeItem ( treeItem ) ;
if ( feedItem ) {
disconnectSignals ( feedItem ) ;
2015-03-12 09:59:56 -04:00
feedRemoved ( feedItem ) ;
2014-08-01 10:49:58 -04:00
delete ( feedItem ) ;
}
delete ( treeItem ) ;
}
2014-11-15 12:24:49 -05:00
if ( ! mCountChangedDisabled ) {
emit feedCountChanged ( ) ;
}
2014-08-01 10:49:58 -04:00
return true ; // eat event
}
}
}
}
/* Pass the event on to the parent class */
return QWidget : : eventFilter ( object , event ) ;
}
2015-03-12 09:59:56 -04:00
void RSFeedWidget : : feedAdded ( FeedItem * feedItem , QTreeWidgetItem * treeItem )
{
}
void RSFeedWidget : : feedRemoved ( FeedItem * feedItem )
{
}
void RSFeedWidget : : feedsCleared ( )
{
}
2014-08-01 10:49:58 -04:00
void RSFeedWidget : : connectSignals ( FeedItem * feedItem )
{
connect ( feedItem , SIGNAL ( feedItemDestroyed ( FeedItem * ) ) , this , SLOT ( feedItemDestroyed ( FeedItem * ) ) ) ;
connect ( feedItem , SIGNAL ( sizeChanged ( FeedItem * ) ) , this , SLOT ( feedItemSizeChanged ( FeedItem * ) ) ) ;
}
void RSFeedWidget : : disconnectSignals ( FeedItem * feedItem )
{
disconnect ( feedItem , SIGNAL ( feedItemDestroyed ( FeedItem * ) ) , this , SLOT ( feedItemDestroyed ( FeedItem * ) ) ) ;
disconnect ( feedItem , SIGNAL ( sizeChanged ( FeedItem * ) ) , this , SLOT ( feedItemSizeChanged ( FeedItem * ) ) ) ;
}
2015-02-09 16:13:07 -05:00
QString RSFeedWidget : : placeholderText ( )
{
return ui - > treeWidget - > placeholderText ( ) ;
}
void RSFeedWidget : : setPlaceholderText ( const QString & placeholderText )
{
ui - > treeWidget - > setPlaceholderText ( placeholderText ) ;
}
2014-08-01 10:49:58 -04:00
FeedItem * RSFeedWidget : : feedItemFromTreeItem ( QTreeWidgetItem * treeItem )
{
return dynamic_cast < FeedItem * > ( ui - > treeWidget - > itemWidget ( treeItem , COLUMN_FEED ) ) ;
}
void RSFeedWidget : : addFeedItem ( FeedItem * feedItem , Qt : : ItemDataRole sortRole , const QVariant & value )
{
if ( ! feedItem ) {
return ;
}
QTreeWidgetItem * treeItem = new RSTreeWidgetItem ( mFeedCompareRole ) ;
treeItem - > setData ( COLUMN_FEED , sortRole , value ) ;
2019-12-19 17:34:10 -05:00
treeItem - > setData ( COLUMN_IDENTIFIER , Qt : : DisplayRole , QString : : fromStdString ( feedItem - > uniqueIdentifier ( ) ) ) ;
2014-08-01 10:49:58 -04:00
ui - > treeWidget - > addTopLevelItem ( treeItem ) ;
ui - > treeWidget - > setItemWidget ( treeItem , 0 , feedItem ) ;
2015-03-12 09:59:56 -04:00
feedAdded ( feedItem , treeItem ) ;
2014-08-01 10:49:58 -04:00
connectSignals ( feedItem ) ;
filterItem ( treeItem , feedItem ) ;
2014-11-15 12:24:49 -05:00
if ( ! mCountChangedDisabled ) {
emit feedCountChanged ( ) ;
}
2014-08-01 10:49:58 -04:00
}
void RSFeedWidget : : addFeedItem ( FeedItem * feedItem , const QMap < Qt : : ItemDataRole , QVariant > & sort )
{
if ( ! feedItem ) {
return ;
}
QTreeWidgetItem * treeItem = new RSTreeWidgetItem ( mFeedCompareRole ) ;
QMap < Qt : : ItemDataRole , QVariant > : : const_iterator it ;
for ( it = sort . begin ( ) ; it ! = sort . end ( ) ; + + it ) {
treeItem - > setData ( COLUMN_FEED , it . key ( ) , it . value ( ) ) ;
}
ui - > treeWidget - > addTopLevelItem ( treeItem ) ;
2019-12-19 17:34:10 -05:00
treeItem - > setData ( COLUMN_FEED , Qt : : DisplayRole , QString : : fromStdString ( feedItem - > uniqueIdentifier ( ) ) ) ;
2014-08-01 10:49:58 -04:00
ui - > treeWidget - > setItemWidget ( treeItem , 0 , feedItem ) ;
2015-03-12 09:59:56 -04:00
feedAdded ( feedItem , treeItem ) ;
2014-08-01 10:49:58 -04:00
connectSignals ( feedItem ) ;
filterItem ( treeItem , feedItem ) ;
2014-11-15 12:24:49 -05:00
if ( ! mCountChangedDisabled ) {
emit feedCountChanged ( ) ;
}
2014-08-01 10:49:58 -04:00
}
void RSFeedWidget : : setSort ( FeedItem * feedItem , Qt : : ItemDataRole sortRole , const QVariant & value )
{
2019-12-19 17:34:10 -05:00
if ( ! feedItem )
2014-08-01 10:49:58 -04:00
return ;
2019-12-19 17:34:10 -05:00
QTreeWidgetItem * treeItem = findTreeWidgetItem ( feedItem - > uniqueIdentifier ( ) ) ;
if ( ! treeItem )
2014-08-01 10:49:58 -04:00
return ;
treeItem - > setData ( COLUMN_FEED , sortRole , value ) ;
}
void RSFeedWidget : : setSort ( FeedItem * feedItem , const QMap < Qt : : ItemDataRole , QVariant > & sort )
{
if ( ! feedItem ) {
return ;
}
2019-12-19 17:34:10 -05:00
QTreeWidgetItem * treeItem = findTreeWidgetItem ( feedItem - > uniqueIdentifier ( ) ) ;
if ( ! treeItem )
2014-08-01 10:49:58 -04:00
return ;
QMap < Qt : : ItemDataRole , QVariant > : : const_iterator it ;
for ( it = sort . begin ( ) ; it ! = sort . end ( ) ; + + it ) {
treeItem - > setData ( COLUMN_FEED , it . key ( ) , it . value ( ) ) ;
}
}
void RSFeedWidget : : clear ( )
{
2014-11-15 12:24:49 -05:00
/* Disconnect signals */
QTreeWidgetItemIterator it ( ui - > treeWidget ) ;
QTreeWidgetItem * treeItem ;
while ( ( treeItem = * it ) ! = NULL ) {
+ + it ;
FeedItem * feedItem = feedItemFromTreeItem ( treeItem ) ;
if ( feedItem ) {
disconnectSignals ( feedItem ) ;
}
}
2015-03-12 09:59:56 -04:00
feedsCleared ( ) ;
2014-11-15 12:24:49 -05:00
/* Clear items */
2014-08-01 10:49:58 -04:00
ui - > treeWidget - > clear ( ) ;
2014-11-15 12:24:49 -05:00
if ( ! mCountChangedDisabled ) {
emit feedCountChanged ( ) ;
}
2014-08-01 10:49:58 -04:00
}
void RSFeedWidget : : setSortRole ( Qt : : ItemDataRole role , Qt : : SortOrder order )
{
setSortingEnabled ( true ) ;
mFeedCompareRole - > setRole ( COLUMN_FEED , role ) ;
ui - > treeWidget - > sortItems ( COLUMN_FEED , order ) ;
}
void RSFeedWidget : : setSortingEnabled ( bool enable )
{
ui - > treeWidget - > setSortingEnabled ( enable ) ;
}
void RSFeedWidget : : setFilterCallback ( RSFeedWidgetFilterCallbackFunction callback )
{
mFilterCallback = callback ;
filterItems ( ) ;
}
void RSFeedWidget : : setFilter ( const QString & text , int type )
{
if ( mFilterText = = text & & mFilterType = = type ) {
return ;
}
mFilterText = text ;
mFilterType = type ;
filterItems ( ) ;
}
void RSFeedWidget : : setFilterText ( const QString & text )
{
setFilter ( text , mFilterType ) ;
}
void RSFeedWidget : : setFilterType ( int type )
{
setFilter ( mFilterText , type ) ;
}
void RSFeedWidget : : filterItems ( )
{
if ( ! mFilterCallback ) {
return ;
}
QTreeWidgetItemIterator it ( ui - > treeWidget ) ;
QTreeWidgetItem * item ;
while ( ( item = * it ) ! = NULL ) {
+ + it ;
FeedItem * feedItem = feedItemFromTreeItem ( item ) ;
if ( ! feedItem ) {
continue ;
}
filterItem ( item , feedItem ) ;
}
}
void RSFeedWidget : : filterItem ( QTreeWidgetItem * treeItem , FeedItem * feedItem )
{
if ( ! mFilterCallback ) {
return ;
}
treeItem - > setHidden ( ! mFilterCallback ( feedItem , mFilterText , mFilterType ) ) ;
}
void RSFeedWidget : : enableRemove ( bool enable )
{
mEnableRemove = enable ;
}
2014-11-15 12:24:49 -05:00
void RSFeedWidget : : enableCountChangedSignal ( bool enable )
{
if ( enable ) {
- - mCountChangedDisabled ;
if ( mCountChangedDisabled < 0 ) {
std : : cerr < < " RSFeedWidget::enableCountChangedSignal error disable count change signal " < < std : : endl ;
mCountChangedDisabled = 0 ;
}
} else {
+ + mCountChangedDisabled ;
}
}
2014-08-01 10:49:58 -04:00
void RSFeedWidget : : setSelectionMode ( QAbstractItemView : : SelectionMode mode )
{
ui - > treeWidget - > setSelectionMode ( mode ) ;
}
2014-11-15 12:24:49 -05:00
int RSFeedWidget : : feedItemCount ( )
{
return ui - > treeWidget - > topLevelItemCount ( ) ;
}
FeedItem * RSFeedWidget : : feedItem ( int index )
{
QTreeWidgetItem * treeItem = ui - > treeWidget - > topLevelItem ( index ) ;
if ( ! treeItem ) {
return NULL ;
}
return feedItemFromTreeItem ( treeItem ) ;
}
2014-08-01 10:49:58 -04:00
void RSFeedWidget : : removeFeedItem ( FeedItem * feedItem )
{
if ( ! feedItem ) {
return ;
}
2019-12-19 17:34:10 -05:00
QTreeWidgetItem * treeItem = findTreeWidgetItem ( feedItem - > uniqueIdentifier ( ) ) ;
2019-12-19 15:04:18 -05:00
if ( treeItem )
{
int treeItem_index = ui - > treeWidget - > indexOfTopLevelItem ( treeItem ) ;
if ( treeItem_index < 0 )
{
std : : cerr < < " (EE) Cannot remove designated item \" " < < feedItem - > uniqueIdentifier ( ) < < " \" : not found! " < < std : : endl ;
return ;
}
2019-12-19 17:34:10 -05:00
feedRemoved ( feedItem ) ;
disconnectSignals ( feedItem ) ;
delete ui - > treeWidget - > takeTopLevelItem ( treeItem_index ) ;
2019-12-19 15:04:18 -05:00
}
2014-11-15 12:24:49 -05:00
if ( ! mCountChangedDisabled ) {
emit feedCountChanged ( ) ;
}
2014-08-01 10:49:58 -04:00
}
void RSFeedWidget : : feedItemSizeChanged ( FeedItem */ * feedItem */ )
{
if ( updatesEnabled ( ) ) {
setUpdatesEnabled ( false ) ;
QApplication : : processEvents ( ) ;
setUpdatesEnabled ( true ) ;
} else {
QApplication : : processEvents ( ) ;
}
ui - > treeWidget - > doItemsLayout ( ) ;
}
void RSFeedWidget : : feedItemDestroyed ( FeedItem * feedItem )
{
/* No need to disconnect when object will be destroyed */
2019-12-19 17:34:10 -05:00
QTreeWidgetItem * treeItem = findTreeWidgetItem ( feedItem - > uniqueIdentifier ( ) ) ;
2015-03-12 09:59:56 -04:00
feedRemoved ( feedItem ) ;
2019-12-19 17:34:10 -05:00
if ( treeItem )
2014-08-01 10:49:58 -04:00
delete ( treeItem ) ;
2014-11-15 12:24:49 -05:00
2019-12-19 17:34:10 -05:00
if ( ! mCountChangedDisabled )
2014-11-15 12:24:49 -05:00
emit feedCountChanged ( ) ;
2014-08-01 10:49:58 -04:00
}
2019-12-19 17:34:10 -05:00
QTreeWidgetItem * RSFeedWidget : : findTreeWidgetItem ( const std : : string & identifier )
2014-08-01 10:49:58 -04:00
{
2019-12-19 17:34:10 -05:00
std : : cerr < < " FindTreeWidgetItem: looking for \" " < < identifier < < " \" " < < std : : endl ;
QList < QTreeWidgetItem * > list = ui - > treeWidget - > findItems ( QString : : fromStdString ( identifier ) , Qt : : MatchExactly , COLUMN_IDENTIFIER ) ;
2014-08-01 10:49:58 -04:00
2019-12-19 17:34:10 -05:00
if ( list . empty ( ) )
{
std : : cerr < < " not found! " < < std : : endl ;
return nullptr ;
}
else if ( list . size ( ) = = 1 )
{
std : : cerr < < " found! " < < std : : endl ;
return list . front ( ) ;
}
else
{
std : : cerr < < " (EE) More than a single item with identifier \" " < < identifier < < " \" in the feed tree widget. This shouldn't happen! " < < std : : endl ;
return nullptr ;
}
2014-08-01 10:49:58 -04:00
}
2014-10-25 19:52:33 -04:00
bool RSFeedWidget : : scrollTo ( FeedItem * feedItem , bool focus )
{
2019-12-19 17:34:10 -05:00
QTreeWidgetItem * item = findTreeWidgetItem ( feedItem - > uniqueIdentifier ( ) ) ;
if ( ! feedItem )
2014-10-25 19:52:33 -04:00
return false ;
ui - > treeWidget - > scrollToItem ( item ) ;
ui - > treeWidget - > setCurrentItem ( item ) ;
2019-12-19 17:34:10 -05:00
if ( focus )
2014-10-25 19:52:33 -04:00
ui - > treeWidget - > setFocus ( ) ;
return true ;
}
2014-11-15 12:24:49 -05:00
void RSFeedWidget : : withAll ( RSFeedWidgetCallbackFunction callback , void * data )
2014-08-01 10:49:58 -04:00
{
if ( ! callback ) {
return ;
}
QTreeWidgetItemIterator it ( ui - > treeWidget ) ;
QTreeWidgetItem * treeItem ;
while ( ( treeItem = * it ) ! = NULL ) {
+ + it ;
FeedItem * feedItem = feedItemFromTreeItem ( treeItem ) ;
if ( ! feedItem ) {
continue ;
}
callback ( feedItem , data ) ;
}
}
2019-12-15 10:46:22 -05:00
FeedItem * RSFeedWidget : : findFeedItem ( const std : : string & identifier )
2014-08-01 10:49:58 -04:00
{
QTreeWidgetItemIterator it ( ui - > treeWidget ) ;
2019-12-15 10:46:22 -05:00
QTreeWidgetItem * treeItem = NULL ;
2019-12-03 16:30:13 -05:00
// this search could probably be automatised by giving the tree items the identifier as data for some specific role, then calling QTreeWidget::findItems()
# warning TODO
2014-08-01 10:49:58 -04:00
while ( ( treeItem = * it ) ! = NULL ) {
+ + it ;
FeedItem * feedItem = feedItemFromTreeItem ( treeItem ) ;
if ( ! feedItem ) {
continue ;
}
2019-12-15 12:40:42 -05:00
// (cyril) It seems that a local variable must be used to store this identifier.
// Directly comparing identifier such as in:
// if(feedItem->uniqueIdentifier() == identifier)
// causes a crash. I dont know why! If someone ever finds why, please tell me.
std : : string id = feedItem - > uniqueIdentifier ( ) ;
2019-12-19 15:04:18 -05:00
std : : cerr < < " Comparing \" " < < id < < " \" " ;
std : : cerr < < " to " < < identifier < < " \" " < < " pthread_t = " < < pthread_self ( ) < < std : : endl ;
2019-12-15 12:40:42 -05:00
if ( id = = identifier )
2014-08-01 10:49:58 -04:00
return feedItem ;
}
return NULL ;
}
void RSFeedWidget : : selectedFeedItems ( QList < FeedItem * > & feedItems )
{
foreach ( QTreeWidgetItem * treeItem , ui - > treeWidget - > selectedItems ( ) ) {
FeedItem * feedItem = feedItemFromTreeItem ( treeItem ) ;
if ( ! feedItem ) {
continue ;
}
feedItems . push_back ( feedItem ) ;
}
}