fixed comflicts with upstream

This commit is contained in:
csoler 2020-09-27 20:51:05 +02:00
commit c640fd779d
72 changed files with 670 additions and 2320 deletions

View File

@ -43,8 +43,9 @@
#include <retroshare/rsexpr.h>
/* Images for context menu icons */
#define IMAGE_START ":/images/download.png"
#define IMAGE_REMOVE ":/images/delete.png"
#define IMAGE_START ":/icons/png/download.png"
#define IMAGE_SEARCHAGAIN ":/images/update.png"
#define IMAGE_REMOVE ":/images/delete.png"
#define IMAGE_REMOVEALL ":/images/deleteall.png"
#define IMAGE_DIRECTORY ":/images/folder16.png"
#define IMAGE_OPENFOLDER ":/images/folderopen.png"
@ -670,14 +671,14 @@ void SearchDialog::searchSummaryWidgetCustomPopupMenu( QPoint /*point*/ )
QMenu contextMnu(this);
QTreeWidgetItem* ci = ui.searchSummaryWidget->currentItem();
QAction* action = contextMnu.addAction(tr("Search again"), this, SLOT(searchAgain()));
QAction* action = contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_SEARCHAGAIN),tr("Search again"), this, SLOT(searchAgain()));
if (!ci || ci->data(SS_DATA_COL, ROLE_KEYWORDS).toString().isEmpty()) {
action->setDisabled(true);
}
contextMnu.addAction(QIcon(IMAGE_REMOVE), tr("Remove"), this, SLOT(searchRemove()));
contextMnu.addAction(QIcon(IMAGE_REMOVE), tr("Remove All"), this, SLOT(searchRemoveAll()));
contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_REMOVE), tr("Remove"), this, SLOT(searchRemove()));
contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_REMOVEALL), tr("Remove All"), this, SLOT(searchRemoveAll()));
contextMnu.addSeparator();
action = contextMnu.addAction(QIcon(IMAGE_COPYLINK), tr("Copy RetroShare Link"), this, SLOT(copySearchLink()));
action = contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_COPYLINK), tr("Copy RetroShare Link"), this, SLOT(copySearchLink()));
if (!ci || ci->data(SS_DATA_COL, ROLE_KEYWORDS).toString().isEmpty()) {
action->setDisabled(true);
}

View File

@ -37,6 +37,7 @@
#include "util/RsAction.h"
#include "util/misc.h"
#include "util/rstime.h"
#include "util/rsdir.h"
#include <retroshare/rsexpr.h>
#include <retroshare/rsfiles.h>
@ -55,7 +56,7 @@
#include <set>
/* Images for context menu icons */
#define IMAGE_DOWNLOAD ":/images/download16.png"
#define IMAGE_DOWNLOAD ":/icons/png/download.png"
#define IMAGE_PLAY ":/images/start.png"
#define IMAGE_HASH_BUSY ":/images/settings.png"
#define IMAGE_HASH_DONE ":/images/accepted16.png"
@ -72,8 +73,9 @@
#define IMAGE_COLLMODIF ":/icons/png/pencil-edit-button.png"
#define IMAGE_COLLVIEW ":/images/find.png"
#define IMAGE_COLLOPEN ":/icons/collections.png"
#define IMAGE_EDITSHARE ":/images/edit_16.png"
#define IMAGE_EDITSHARE ":/icons/png/pencil-edit-button.png"
#define IMAGE_MYFILES ":/icons/svg/folders1.svg"
#define IMAGE_UNSHAREEXTRA ":/images/button_cancel.png"
/*define viewType_CB value */
#define VIEW_TYPE_TREE 0
@ -232,7 +234,7 @@ SharedFilesDialog::SharedFilesDialog(bool remote_mode, QWidget *parent)
sendlinkAct = new QAction(QIcon(IMAGE_COPYLINK), tr( "Send retroshare Links" ), this );
connect( sendlinkAct , SIGNAL( triggered() ), this, SLOT( sendLinkTo( ) ) );
removeExtraFileAct = new QAction(QIcon(), tr( "Stop sharing this file" ), this );
removeExtraFileAct = new QAction(QIcon(IMAGE_UNSHAREEXTRA), tr( "Stop sharing this file" ), this );
connect( removeExtraFileAct , SIGNAL( triggered() ), this, SLOT( removeExtraFile() ) );
collCreateAct= new QAction(QIcon(IMAGE_COLLCREATE), tr("Create Collection..."), this) ;
@ -634,22 +636,31 @@ void SharedFilesDialog::copyLinks(const QModelIndexList& lst, bool remote,QList<
RetroShareLink link = RetroShareLink::createFileTree(dir_name,ft->mTotalSize,ft->mTotalFiles,QString::fromStdString(ft->toRadix64())) ;
if(link.valid())
urls.push_back(link) ;
}
else
{
if(details.hash.isNull())
{
has_unhashed_files = true;
continue;
}
RetroShareLink link = RetroShareLink::createFile(QString::fromUtf8(details.name.c_str()), details.count, details.hash.toStdString().c_str());
if (link.valid()) {
urls.push_back(link) ;
}
}
}
if(link.valid())
urls.push_back(link) ;
}
else
{
if(details.hash.isNull())
{
has_unhashed_files = true;
continue;
}
QString name;
if(details.type == DIR_TYPE_EXTRA_FILE)
{
std::string dir,file;
RsDirUtil::splitDirFromFile(details.name,dir,file) ;
name = QString::fromStdString(file);
}
else
name = QString::fromUtf8(details.name.c_str());
RetroShareLink link = RetroShareLink::createFile(name, details.count, details.hash.toStdString().c_str());
if (link.valid()) {
urls.push_back(link) ;
}
}
}
}
void SharedFilesDialog::copyLink (const QModelIndexList& lst, bool remote)
@ -875,8 +886,8 @@ void LocalSharedFilesDialog::openfolder()
{
std::cerr << "SharedFilesDialog::openfolder" << std::endl;
QModelIndexList qmil = getSelected();
model->openSelected(qmil);
QModelIndexList qmil = getSelected();
model->openSelected(qmil, true);
}
void SharedFilesDialog::preModDirectories(bool local)
@ -1143,11 +1154,12 @@ void LocalSharedFilesDialog::spawnCustomPopupMenu( QPoint point )
break;
case DIR_TYPE_EXTRA_FILE:
contextMnu.addAction(openfileAct) ;
contextMnu.addSeparator() ;//------------------------------------
contextMnu.addAction(copylinkAct) ;
contextMnu.addAction(sendlinkAct) ;
contextMnu.addAction(removeExtraFileAct) ;
contextMnu.addAction(openfileAct) ;
contextMnu.addAction(openfolderAct) ;
contextMnu.addSeparator() ;//------------------------------------
contextMnu.addAction(copylinkAct) ;
contextMnu.addAction(sendlinkAct) ;
contextMnu.addAction(removeExtraFileAct) ;
break ;

View File

@ -88,10 +88,6 @@
<property name="text">
<string>Configure shared directories</string>
</property>
<property name="icon">
<iconset resource="../images.qrc">
<normaloff>:/images/add-share24.png</normaloff>:/images/add-share24.png</iconset>
</property>
</widget>
</item>
<item>

View File

@ -110,7 +110,7 @@
#define RSID_FILTER_BANNED 0x0020
#define RSID_FILTER_ALL 0xffff
#define IMAGE_EDIT ":/images/edit_16.png"
#define IMAGE_EDIT ":/icons/png/pencil-edit-button.png"
#define IMAGE_CREATE ":/icons/circle_new_128.png"
#define IMAGE_INVITED ":/icons/bullet_yellow_128.png"
#define IMAGE_MEMBER ":/icons/bullet_green_128.png"

View File

@ -146,8 +146,8 @@
#define IMAGE_ADDSHARE ":/images/directoryadd_24x24_shadow.png"
#define IMAGE_OPTIONS ":/images/settings.png"
#define IMAGE_UNFINISHED ":/images/underconstruction.png"
#define IMAGE_MINIMIZE ":/images/window_nofullscreen.png"
#define IMAGE_MAXIMIZE ":/images/window_fullscreen.png"
#define IMAGE_MINIMIZE ":/icons/fullscreen.png"
#define IMAGE_MAXIMIZE ":/icons/fullscreen-exit.png"
#define IMAGE_PLUGINS ":/images/extension_32.png"

View File

@ -29,6 +29,7 @@
#include "gui/Identity/IdDetailsDialog.h"
#include "gui/Identity/IdDialog.h"
#include "gui/MainWindow.h"
#include "gui/common/FilesDefs.h"
#include "retroshare/rspeers.h"
#include "retroshare/rsidentity.h"
@ -440,7 +441,7 @@ void PeopleDialog::iw_AddButtonClickedExt()
{
QMenu contextMnu( this );
QMenu *mnu = contextMnu.addMenu(QIcon(":/icons/png/circles.png"),tr("Invite to Circle")) ;
QMenu *mnu = contextMnu.addMenu(FilesDefs::getIconFromQtResourcePath(":/icons/png/circles.png"),tr("Invite to Circle")) ;
std::map<RsGxsGroupId, CircleWidget*>::iterator itCurs;
for( itCurs =_ext_circles_widgets.begin(); itCurs != _ext_circles_widgets.end(); ++itCurs)
@ -459,7 +460,7 @@ void PeopleDialog::iw_AddButtonClickedExt()
if(own_identities.size() <= 1)
{
QAction *action = contextMnu.addAction(QIcon(":/images/chat_24.png"), tr("Chat with this person"), this, SLOT(chatIdentity()));
QAction *action = contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(":/icons/png/chats.png"), tr("Chat with this person"), this, SLOT(chatIdentity()));
if(own_identities.empty())
action->setEnabled(false) ;
@ -468,7 +469,7 @@ void PeopleDialog::iw_AddButtonClickedExt()
}
else
{
QMenu *mnu = contextMnu.addMenu(QIcon(":/icons/png/chats.png"),tr("Chat with this person as...")) ;
QMenu *mnu = contextMnu.addMenu(FilesDefs::getIconFromQtResourcePath(":/icons/png/chats.png"),tr("Chat with this person as...")) ;
for(std::list<RsGxsId>::const_iterator it=own_identities.begin();it!=own_identities.end();++it)
{
@ -485,20 +486,20 @@ void PeopleDialog::iw_AddButtonClickedExt()
}
}
QAction *actionsendmsg = contextMnu.addAction(QIcon(":/icons/mail/write-mail.png"), tr("Send message"), this, SLOT(sendMessage()));
QAction *actionsendmsg = contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(":/icons/mail/write-mail.png"), tr("Send message"), this, SLOT(sendMessage()));
actionsendmsg->setData( QString::fromStdString(dest->groupInfo().mMeta.mGroupId.toStdString()));
QAction *actionsendinvite = contextMnu.addAction(QIcon(":/icons/mail/write-mail.png"), tr("Send invite"), this, SLOT(sendInvite()));
QAction *actionsendinvite = contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(":/icons/mail/write-mail.png"), tr("Send invite"), this, SLOT(sendInvite()));
actionsendinvite->setData( QString::fromStdString(dest->groupInfo().mMeta.mGroupId.toStdString()));
contextMnu.addSeparator();
QAction *actionaddcontact = contextMnu.addAction(QIcon(""), tr("Add to Contacts"), this, SLOT(addtoContacts()));
QAction *actionaddcontact = contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(""), tr("Add to Contacts"), this, SLOT(addtoContacts()));
actionaddcontact->setData( QString::fromStdString(dest->groupInfo().mMeta.mGroupId.toStdString()));
contextMnu.addSeparator();
QAction *actionDetails = contextMnu.addAction(QIcon(":/images/info16.png"), tr("Person details"), this, SLOT(personDetails()));
QAction *actionDetails = contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(":/images/info16.png"), tr("Person details"), this, SLOT(personDetails()));
actionDetails->setData( QString::fromStdString(dest->groupInfo().mMeta.mGroupId.toStdString()));
contextMnu.exec(QCursor::pos());

View File

@ -521,7 +521,19 @@ QVariant TreeStyle_RDM::displayRole(const DirDetails& details,int coln) const
case COLUMN_SIZE:
return misc::friendlyUnit(details.count);
case COLUMN_AGE:
return (details.type == DIR_TYPE_FILE)?(misc::timeRelativeToNow(details.max_mtime)):QString();
{
if(details.type == DIR_TYPE_FILE)
return misc::timeRelativeToNow(details.max_mtime);
else if(details.type == DIR_TYPE_EXTRA_FILE)
{
FileInfo fi;
if (rsFiles->FileDetails(details.hash, RS_FILE_HINTS_EXTRA , fi))
return misc::timeRelativeToNow((rstime_t)fi.age-(30 * 3600 * 24)); // AFI_DEFAULT_PERIOD
return QString();
}
else
return QString();
}
case COLUMN_FRIEND_ACCESS:
return QVariant();
case COLUMN_WN_VISU_DIR:
@ -1370,7 +1382,7 @@ void RetroshareDirModel::getFileInfoFromIndexList(const QModelIndexList& list, s
* OLD RECOMMEND SYSTEM - DISABLED
******/
void RetroshareDirModel::openSelected(const QModelIndexList &qmil)
void RetroshareDirModel::openSelected(const QModelIndexList &qmil, bool openDir)
{
#ifdef RDM_DEBUG
std::cerr << "RetroshareDirModel::openSelected()" << std::endl;
@ -1393,12 +1405,15 @@ void RetroshareDirModel::openSelected(const QModelIndexList &qmil)
QDir dir(QString::fromUtf8((*it).path.c_str()));
QString dest;
if ((*it).type & DIR_TYPE_FILE || (*it).type & DIR_TYPE_EXTRA_FILE) {
if ((*it).type & DIR_TYPE_FILE || (!openDir && (*it).type & DIR_TYPE_EXTRA_FILE)) {
dest = dir.absoluteFilePath(QString::fromUtf8(it->name.c_str()));
} else if ((*it).type & DIR_TYPE_DIR) {
dest = dir.absolutePath();
} else if (openDir) // extra
{
QDir d = QFileInfo(it->name.c_str()).absoluteDir();
dest = d.absolutePath();
}
std::cerr << "Opening this file: " << dest.toStdString() << std::endl ;
RsUrlHandler::openUrl(QUrl::fromLocalFile(dest));

View File

@ -82,7 +82,7 @@ class RetroshareDirModel : public QAbstractItemModel
int getType ( const QModelIndex & index ) const ;
void getFileInfoFromIndexList(const QModelIndexList& list, std::list<DirDetails>& files_info) ;
void openSelected(const QModelIndexList &list);
void openSelected(const QModelIndexList &list, bool openDir = false);
void getFilePaths(const QModelIndexList &list, std::list<std::string> &fullpaths);
void getFilePath(const QModelIndex& index, std::string& fullpath);
void changeAgeIndicator(uint32_t indicator) { ageIndicator = indicator; }

View File

@ -42,7 +42,7 @@
/* Images for context menu icons */
#define IMAGE_CANCEL ":/images/delete.png"
#define IMAGE_EDIT ":/images/edit_16.png"
#define IMAGE_EDIT ":/icons/png/pencil-edit-button.png"
#define COLUMN_PATH 0
#define COLUMN_VIRTUALNAME 1

View File

@ -74,7 +74,7 @@
#define IMAGE_FORUMAUTHD ":/images/konv_message2.png"
#define IMAGE_COPYLINK ":/images/copyrslink.png"
#define IMAGE_WIKI ":/icons/png/wiki.png"
#define IMAGE_EDIT ":/images/edit_16.png"
#define IMAGE_EDIT ":/icons/png/pencil-edit-button.png"
/** Constructor */

View File

@ -70,7 +70,7 @@
#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_EDIT ":/icons/png/pencil-edit-button.png"
#define IMAGE_REMOVE ":/images/delete.png"
#define IMAGE_EXPAND ":/images/edit_add24.png"
#define IMAGE_COLLAPSE ":/images/edit_remove24.png"

View File

@ -527,6 +527,8 @@ void GroupTreeWidget::fillGroupItems(QTreeWidgetItem *categoryItem, const QList<
tooltip += "\n" + tr("Description") + ": " + itemInfo.description;
tooltip += "\n" + tr("Id") + ": " + itemInfo.id;
item->setToolTip(COLUMN_NAME, tooltip);
item->setToolTip(COLUMN_UNREAD, tooltip);
item->setToolTip(COLUMN_POPULARITY, tooltip);

View File

@ -65,8 +65,8 @@
<string>Display</string>
</property>
<property name="icon">
<iconset resource="../images.qrc">
<normaloff>:/images/looknfeel.png</normaloff>:/images/looknfeel.png</iconset>
<iconset resource="../icons.qrc">
<normaloff>:/icons/svg/design.svg</normaloff>:/icons/svg/design.svg</iconset>
</property>
<property name="iconSize">
<size>
@ -147,6 +147,7 @@
</customwidgets>
<resources>
<include location="../images.qrc"/>
<include location="../icons.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -69,7 +69,7 @@
#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_EDIT ":/icons/png/pencil-edit-button.png"
#define IMAGE_REMOVE ":/images/delete.png"
#define IMAGE_EXPAND ":/images/edit_add24.png"
#define IMAGE_COLLAPSE ":/images/edit_remove24.png"

View File

@ -46,7 +46,7 @@
#define IMAGE_INFO ":/images/info16.png"
//#define IMAGE_GROUPAUTHD ":/images/konv_message2.png"
#define IMAGE_COPYLINK ":/images/copyrslink.png"
#define IMAGE_EDIT ":/images/edit_16.png"
#define IMAGE_EDIT ":/icons/png/pencil-edit-button.png"
#define IMAGE_SHARE ":/images/share-icon-16.png"
#define IMAGE_TABNEW ":/images/tab-new.png"
#define IMAGE_DELETE ":/images/delete.png"

View File

@ -72,13 +72,18 @@ CreateGxsChannelMsg::CreateGxsChannelMsg(const RsGxsGroupId &cId, RsGxsMessageId
connect(addFileButton, SIGNAL(clicked() ), this , SLOT(addExtraFile()));
connect(addfilepushButton, SIGNAL(clicked() ), this , SLOT(addExtraFile()));
connect(subjectEdit,SIGNAL(textChanged(const QString&)),this,SLOT(updatePreviewText(const QString&)));
connect(subjectEdit,SIGNAL(textChanged(const QString&)),this,SLOT(updatePreviewText(const QString&)));
connect(addThumbnailButton, SIGNAL(clicked() ), this , SLOT(addThumbnail()));
connect(thumbNailCb, SIGNAL(toggled(bool)), this, SLOT(allowAutoMediaThumbNail(bool)));
connect(stackedWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenu(QPoint)));
connect(generateCheckBox, SIGNAL(toggled(bool)), generateSpinBox, SLOT(setEnabled(bool)));
connect(aspectRatio_CB,SIGNAL(currentIndexChanged(int)),this,SLOT(changeAspectRatio(int)));
connect(aspectRatio_CB,SIGNAL(currentIndexChanged(int)),this,SLOT(changeAspectRatio(int)));
channelpostButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/comment.png"));
attachmentsButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/attachements.png"));
addThumbnailButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/add-image.png"));
addfilepushButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/add-file.png"));
aspectRatio_CB->setItemIcon(0,FilesDefs::getIconFromQtResourcePath(":/icons/svg/ratio-auto.svg"));
aspectRatio_CB->setItemIcon(1,FilesDefs::getIconFromQtResourcePath(":/icons/svg/ratio-1-1.svg"));
@ -106,6 +111,9 @@ CreateGxsChannelMsg::CreateGxsChannelMsg(const RsGxsGroupId &cId, RsGxsMessageId
generateCheckBox->hide();
generateSpinBox->hide();
#endif
/* load settings */
processSettings(true);
}
CreateGxsChannelMsg::~CreateGxsChannelMsg()
@ -114,6 +122,29 @@ CreateGxsChannelMsg::~CreateGxsChannelMsg()
#ifdef CHANNELS_FRAME_CATCHER
delete fCatcher;
#endif
// save settings
processSettings(false);
}
void CreateGxsChannelMsg::processSettings(bool load)
{
Settings->beginGroup(QString("CreateGxsChannelMsg"));
if (load) {
// load settings
// state of Ratio combobox
int index = Settings->value("aspectRatio_CB", 0).toInt();
aspectRatio_CB->setCurrentIndex(index);
} else {
// save settings
// state of Ratio combobox
Settings->setValue("aspectRatio_CB", aspectRatio_CB->currentIndex());
}
Settings->endGroup();
}
void CreateGxsChannelMsg::changeAspectRatio(int s)

View File

@ -72,6 +72,7 @@ private slots:
void on_channelpostButton_clicked();
void on_attachmentsButton_clicked();
private:
void processSettings(bool load);
void loadChannelInfo();
void loadOriginalChannelPostInfo();
void saveChannelInfo(const RsGroupMetaData &group);

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>881</width>
<height>383</height>
<height>328</height>
</rect>
</property>
<property name="acceptDrops">
@ -39,13 +39,6 @@
<property name="verticalSpacing">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="HeaderFrame" name="headerFrame">
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QFrame" name="mainFrame">
<property name="frameShape">
@ -64,6 +57,19 @@
<property name="verticalSpacing">
<number>0</number>
</property>
<item row="0" column="1">
<widget class="QPushButton" name="attachmentsButton">
<property name="text">
<string>Attachments</string>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
<item row="1" column="0" colspan="3">
<widget class="QStackedWidget" name="stackedWidget">
<property name="mouseTracking">
@ -79,207 +85,188 @@
<number>0</number>
</property>
<widget class="QWidget" name="stackedWidgetPage1">
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<layout class="QGridLayout" name="gridLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<item row="0" column="0" rowspan="4">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="ChannelPostThumbnailView" name="preview_W" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
<widget class="ChannelPostThumbnailView" name="preview_W" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>6</number>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<item>
<layout class="QHBoxLayout" name="channelNameHLayout">
<property name="topMargin">
<number>6</number>
</property>
<item>
<widget class="QLabel" name="channelNameLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Channel Post to:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="channelName">
<property name="enabled">
<bool>true</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="channelAttachLabel">
<property name="text">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>1</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="channelNameHLayout">
<property name="topMargin">
<number>6</number>
</property>
<item>
<widget class="QLabel" name="channelNameLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Channel Post to:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="channelName">
<property name="enabled">
<bool>true</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="1">
<widget class="QLabel" name="channelAttachLabel">
<property name="text">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:600;&quot;&gt;Attachments:&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;img src=&quot;:/images/feedback_arrow.png&quot; /&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:8pt;&quot;&gt; Use Drag and Drop / Add Files button, to Hash new files.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;img src=&quot;:/images/feedback_arrow.png&quot; /&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:8pt;&quot;&gt; Copy/Paste RetroShare links from your shares&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</property>
</widget>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="addThumbnailButton">
<property name="text">
<string>Add Channel Thumbnail</string>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="aspectRatio_CB">
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<item>
<property name="text">
<string>Auto</string>
</property>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="addThumbnailButton">
<property name="text">
<string>Add Channel Thumbnail</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/icons/png/add-image.png</normaloff>:/icons/png/add-image.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="aspectRatio_CB">
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<item>
<property name="text">
<string>Auto</string>
</property>
</item>
<item>
<property name="text">
<string>1:1</string>
</property>
</item>
<item>
<property name="text">
<string>3:4</string>
</property>
</item>
<item>
<property name="text">
<string>16:9</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QPushButton" name="addfilepushButton">
<property name="text">
<string>Add File to Attach</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/icons/png/add-file.png</normaloff>:/icons/png/add-file.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
<property name="text">
<string>1:1</string>
</property>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="topMargin">
<number>9</number>
</property>
<item>
<widget class="QLineEdit" name="subjectEdit">
<property name="placeholderText">
<string>Title</string>
</property>
</widget>
</item>
</layout>
<property name="text">
<string>3:4</string>
</property>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>1</height>
</size>
</property>
</spacer>
<property name="text">
<string>16:9</string>
</property>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QPushButton" name="addfilepushButton">
<property name="text">
<string>Add File to Attach</string>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="RichTextEdit" name="RichTextEditWidget" native="true"/>
<item row="3" column="1">
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="topMargin">
<number>9</number>
</property>
<item>
<widget class="QLineEdit" name="subjectEdit">
<property name="placeholderText">
<string>Title</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="4" column="0" colspan="2">
<widget class="RichTextEdit" name="RichTextEditWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
@ -342,7 +329,7 @@ p, li { white-space: pre-wrap; }
<rect>
<x>0</x>
<y>0</y>
<width>84</width>
<width>842</width>
<height>24</height>
</rect>
</property>
@ -416,23 +403,6 @@ p, li { white-space: pre-wrap; }
</widget>
</widget>
</item>
<item row="0" column="0">
<widget class="QPushButton" name="channelpostButton">
<property name="text">
<string>Channel Post</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/icons/png/comment.png</normaloff>:/icons/png/comment.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
<item row="0" column="2">
<spacer name="horizontalSpacer">
<property name="orientation">
@ -446,14 +416,10 @@ p, li { white-space: pre-wrap; }
</property>
</spacer>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="attachmentsButton">
<item row="0" column="0">
<widget class="QPushButton" name="channelpostButton">
<property name="text">
<string>Attachments</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/icons/png/attachements.png</normaloff>:/icons/png/attachements.png</iconset>
<string>Channel Post</string>
</property>
<property name="iconSize">
<size>
@ -500,6 +466,13 @@ p, li { white-space: pre-wrap; }
</layout>
</widget>
</item>
<item row="0" column="0">
<widget class="HeaderFrame" name="headerFrame">
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>

View File

@ -1,251 +0,0 @@
/*******************************************************************************
* retroshare-gui/src/gui/gxschannels/GxsChannelFilesWidget.cpp *
* *
* Copyright 2014 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 <QDateTime>
#include "GxsChannelFilesWidget.h"
#include "ui_GxsChannelFilesWidget.h"
#include "GxsChannelFilesStatusWidget.h"
#include "GxsChannelPostsWidget.h"
#include "gui/feeds/GxsChannelPostItem.h"
#include "gui/common/RSTreeWidgetItem.h"
#include "util/misc.h"
#include "util/DateTime.h"
#include "gui/gxs/GxsFeedItem.h"
#include "retroshare/rsgxschannels.h"
#define COLUMN_FILENAME 0
#define COLUMN_SIZE 1
#define COLUMN_STATUS 2
#define COLUMN_TITLE 3
#define COLUMN_PUBLISHED 4
#define COLUMN_COUNT 5
#define COLUMN_DATA 0
#define ROLE_SORT Qt::UserRole
#define ROLE_GROUP_ID Qt::UserRole + 1
#define ROLE_MESSAGE_ID Qt::UserRole + 2
#define ROLE_FILE_HASH Qt::UserRole + 3
#define ROLE_MSG Qt::UserRole + 4
Q_DECLARE_METATYPE(Sha1CheckSum)
GxsChannelFilesWidget::GxsChannelFilesWidget(QWidget *parent) :
QWidget(parent), ui(new Ui::GxsChannelFilesWidget)
{
ui->setupUi(this);
mFeedItem = NULL;
/* Connect signals */
connect(ui->treeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)));
/* Sort */
mCompareRole = new RSTreeWidgetItemCompareRole;
mCompareRole->setRole(COLUMN_SIZE, ROLE_SORT);
mCompareRole->setRole(COLUMN_PUBLISHED, ROLE_SORT);
/* Filter */
mFilterType = 0;
/* Initialize file tree */
ui->treeWidget->setColumnCount(COLUMN_COUNT);
QTreeWidgetItem *headerItem = ui->treeWidget->headerItem();
headerItem->setText(COLUMN_FILENAME, tr("Filename"));
headerItem->setText(COLUMN_SIZE, tr("Size"));
headerItem->setText(COLUMN_TITLE, tr("Title"));
headerItem->setText(COLUMN_PUBLISHED, tr("Published"));
headerItem->setText(COLUMN_STATUS, tr("Status"));
ui->treeWidget->setColumnWidth(COLUMN_FILENAME, 400);
ui->treeWidget->setColumnWidth(COLUMN_SIZE, 80);
ui->treeWidget->setColumnWidth(COLUMN_PUBLISHED, 150);
}
GxsChannelFilesWidget::~GxsChannelFilesWidget()
{
delete(mCompareRole);
delete ui;
}
void GxsChannelFilesWidget::addFiles(const RsGxsChannelPost& post, bool related)
{
if (related) {
removeItems(post.mMeta.mGroupId, post.mMeta.mMsgId);
}
std::list<RsGxsFile>::const_iterator fileIt;
for (fileIt = post.mFiles.begin(); fileIt != post.mFiles.end(); ++fileIt) {
const RsGxsFile &file = *fileIt;
QTreeWidgetItem *treeItem = new RSTreeWidgetItem(mCompareRole);
treeItem->setText(COLUMN_FILENAME, QString::fromUtf8(file.mName.c_str()));
treeItem->setText(COLUMN_SIZE, misc::friendlyUnit(file.mSize));
treeItem->setData(COLUMN_SIZE, ROLE_SORT, (qulonglong)file.mSize);
treeItem->setText(COLUMN_TITLE, QString::fromUtf8(post.mMeta.mMsgName.c_str()));
treeItem->setText(COLUMN_PUBLISHED, DateTime::formatDateTime(post.mMeta.mPublishTs));
treeItem->setData(COLUMN_PUBLISHED, ROLE_SORT, QDateTime::fromTime_t(post.mMeta.mPublishTs));
treeItem->setData(COLUMN_DATA, ROLE_GROUP_ID, qVariantFromValue(post.mMeta.mGroupId));
treeItem->setData(COLUMN_DATA, ROLE_MESSAGE_ID, qVariantFromValue(post.mMeta.mMsgId));
treeItem->setData(COLUMN_DATA, ROLE_FILE_HASH, qVariantFromValue(file.mHash));
treeItem->setData(COLUMN_DATA, ROLE_MSG, QString::fromUtf8(post.mMsg.c_str()));
treeItem->setTextAlignment(COLUMN_SIZE, Qt::AlignRight) ;
ui->treeWidget->addTopLevelItem(treeItem);
QWidget *statusWidget = new GxsChannelFilesStatusWidget(file);
ui->treeWidget->setItemWidget(treeItem, COLUMN_STATUS, statusWidget);
filterItem(treeItem);
}
}
void GxsChannelFilesWidget::clear()
{
ui->treeWidget->clear();
closeFeedItem();
}
void GxsChannelFilesWidget::setFilter(const QString &text, int type)
{
if (mFilterText == text && mFilterType == type) {
return;
}
mFilterText = text;
mFilterType = type;
filterItems();
}
void GxsChannelFilesWidget::setFilterText(const QString &text)
{
setFilter(text, mFilterType);
}
void GxsChannelFilesWidget::setFilterType(int type)
{
setFilter(mFilterText, type);
}
void GxsChannelFilesWidget::filterItems()
{
QTreeWidgetItemIterator it(ui->treeWidget);
QTreeWidgetItem *treeItem;
while ((treeItem = *it) != NULL) {
++it;
filterItem(treeItem);
}
}
void GxsChannelFilesWidget::filterItem(QTreeWidgetItem *treeItem)
{
bool visible = mFilterText.isEmpty();
switch (mFilterType) {
case GxsChannelPostsWidget::FILTER_TITLE:
visible = treeItem->text(COLUMN_TITLE).contains(mFilterText, Qt::CaseInsensitive);
break;
case GxsChannelPostsWidget::FILTER_MSG:
visible = treeItem->data(COLUMN_DATA, ROLE_MSG).toString().contains(mFilterText, Qt::CaseInsensitive);
break;
case GxsChannelPostsWidget::FILTER_FILE_NAME:
visible = treeItem->text(COLUMN_FILENAME).contains(mFilterText, Qt::CaseInsensitive);
break;
}
treeItem->setHidden(!visible);
}
//QTreeWidgetItem *GxsChannelFilesWidget::findFile(const RsGxsGroupId &groupId, const RsGxsMessageId &messageId, const RsFileHash &fileHash)
//{
// QTreeWidgetItemIterator it(ui->treeWidget);
// QTreeWidgetItem *treeItem;
// while ((treeItem = *it) != NULL) {
// ++it;
// if (fileHash != treeItem->data(COLUMN_DATA, ROLE_FILE_HASH).value<RsFileHash>()) {
// continue;
// }
// if (messageId != treeItem->data(COLUMN_DATA, ROLE_MESSAGE_ID).value<RsGxsMessageId>()) {
// continue;
// }
// if (groupId != treeItem->data(COLUMN_DATA, ROLE_GROUP_ID).value<RsGxsGroupId>()) {
// continue;
// }
// return treeItem;
// }
// return NULL;
//}
void GxsChannelFilesWidget::removeItems(const RsGxsGroupId &groupId, const RsGxsMessageId &messageId)
{
QTreeWidgetItemIterator it(ui->treeWidget);
QTreeWidgetItem *treeItem;
while ((treeItem = *it) != NULL) {
++it;
if (messageId != treeItem->data(COLUMN_DATA, ROLE_MESSAGE_ID).value<RsGxsMessageId>()) {
continue;
}
if (groupId != treeItem->data(COLUMN_DATA, ROLE_GROUP_ID).value<RsGxsGroupId>()) {
continue;
}
delete(treeItem);
}
}
void GxsChannelFilesWidget::closeFeedItem()
{
if (mFeedItem) {
delete(mFeedItem);
mFeedItem = NULL;
}
ui->feedItemFrame->hide();
}
void GxsChannelFilesWidget::currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem */*previous*/)
{
if (!current) {
closeFeedItem();
return;
}
RsGxsGroupId groupId = current->data(COLUMN_DATA, ROLE_GROUP_ID).value<RsGxsGroupId>();
RsGxsMessageId messageId = current->data(COLUMN_DATA, ROLE_MESSAGE_ID).value<RsGxsMessageId>();
if (mFeedItem) {
if (mFeedItem->groupId() == groupId && mFeedItem->messageId() == messageId) {
return;
}
closeFeedItem();
}
mFeedItem = new GxsChannelPostItem(NULL, 0, groupId, messageId, true, true);
ui->feedItemFrame->show();
ui->feedItemFrame->layout()->addWidget(mFeedItem);
}

View File

@ -1,76 +0,0 @@
/*******************************************************************************
* retroshare-gui/src/gui/gxschannels/GxsChannelFilesWidget.h *
* *
* Copyright 2014 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/>. *
* *
*******************************************************************************/
#ifndef GXSCHANNELFILESWIDGET_H
#define GXSCHANNELFILESWIDGET_H
#include <QWidget>
#include "retroshare/rsgxsifacetypes.h"
struct RsGxsChannelPost;
class RSTreeWidgetItemCompareRole;
class QTreeWidgetItem;
class GxsFeedItem;
namespace Ui {
class GxsChannelFilesWidget;
}
class GxsChannelFilesWidget : public QWidget
{
Q_OBJECT
public:
explicit GxsChannelFilesWidget(QWidget *parent = 0);
~GxsChannelFilesWidget();
void addFiles(const RsGxsChannelPost &post, bool related);
void clear();
public slots:
void setFilter(const QString &text, int type);
void setFilterText(const QString &text);
void setFilterType(int type);
private:
// QTreeWidgetItem *findFile(const RsGxsGroupId &groupId, const RsGxsMessageId &messageId, const RsFileHash &fileHash);
void removeItems(const RsGxsGroupId &groupId, const RsGxsMessageId &messageId);
void closeFeedItem();
void filterItems();
void filterItem(QTreeWidgetItem *treeItem);
private slots:
void currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous);
private:
/* Sort */
RSTreeWidgetItemCompareRole *mCompareRole;
/* Filter */
QString mFilterText;
int mFilterType;
GxsFeedItem *mFeedItem;
Ui::GxsChannelFilesWidget *ui;
};
#endif // GXSCHANNELFILESWIDGET_H

View File

@ -1,934 +0,0 @@
/*******************************************************************************
* retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidget.cpp *
* *
* Copyright 2013 by Robert Fernie <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 <QDateTime>
#include <QSignalMapper>
#include "retroshare/rsgxscircles.h"
#include "GxsChannelPostsWidget.h"
#include "ui_GxsChannelPostsWidget.h"
#include "gui/feeds/GxsChannelPostItem.h"
#include "gui/gxs/GxsIdDetails.h"
#include "gui/gxschannels/CreateGxsChannelMsg.h"
#include "gui/common/UIStateHelper.h"
#include "gui/settings/rsharesettings.h"
#include "gui/feeds/SubFileItem.h"
#include "gui/notifyqt.h"
#include "gui/RetroShareLink.h"
#include "util/HandleRichText.h"
#include "util/DateTime.h"
#include "util/qtthreadsutils.h"
#include <algorithm>
#define CHAN_DEFAULT_IMAGE ":/icons/png/channels.png"
#define ROLE_PUBLISH FEED_TREEWIDGET_SORTROLE
/****
* #define DEBUG_CHANNEL
***/
/* View mode */
#define VIEW_MODE_FEEDS 1
#define VIEW_MODE_FILES 2
/** Constructor */
GxsChannelPostsWidget::GxsChannelPostsWidget(const RsGxsGroupId &channelId, QWidget *parent) :
GxsMessageFramePostWidget(rsGxsChannels, parent),
ui(new Ui::GxsChannelPostsWidget)
{
/* Invoke the Qt Designer generated object setup routine */
ui->setupUi(this);
/* Setup UI helper */
mStateHelper->addWidget(mTokenTypeAllPosts, ui->progressBar, UISTATE_LOADING_VISIBLE);
mStateHelper->addWidget(mTokenTypeAllPosts, ui->loadingLabel, UISTATE_LOADING_VISIBLE);
mStateHelper->addWidget(mTokenTypeAllPosts, ui->filterLineEdit);
mStateHelper->addWidget(mTokenTypePosts, ui->loadingLabel, UISTATE_LOADING_VISIBLE);
mStateHelper->addLoadPlaceholder(mTokenTypeGroupData, ui->nameLabel);
mStateHelper->addWidget(mTokenTypeGroupData, ui->postButton);
mStateHelper->addWidget(mTokenTypeGroupData, ui->logoLabel);
mStateHelper->addWidget(mTokenTypeGroupData, ui->subscribeToolButton);
/* Connect signals */
connect(ui->postButton, SIGNAL(clicked()), this, SLOT(createMsg()));
connect(ui->subscribeToolButton, SIGNAL(subscribe(bool)), this, SLOT(subscribeGroup(bool)));
connect(NotifyQt::getInstance(), SIGNAL(settingsChanged()), this, SLOT(settingsChanged()));
ui->postButton->setText(tr("Add new post"));
/* add filter actions */
ui->filterLineEdit->addFilter(QIcon(), tr("Title"), FILTER_TITLE, tr("Search Title"));
ui->filterLineEdit->addFilter(QIcon(), tr("Message"), FILTER_MSG, tr("Search Message"));
ui->filterLineEdit->addFilter(QIcon(), tr("Filename"), FILTER_FILE_NAME, tr("Search Filename"));
connect(ui->filterLineEdit, SIGNAL(textChanged(QString)), ui->feedWidget, SLOT(setFilterText(QString)));
connect(ui->filterLineEdit, SIGNAL(textChanged(QString)), ui->fileWidget, SLOT(setFilterText(QString)));
connect(ui->filterLineEdit, SIGNAL(filterChanged(int)), this, SLOT(filterChanged(int)));
/* Initialize view button */
//setViewMode(VIEW_MODE_FEEDS); see processSettings
ui->infoWidget->hide();
QSignalMapper *signalMapper = new QSignalMapper(this);
connect(ui->feedToolButton, SIGNAL(clicked()), signalMapper, SLOT(map()));
connect(ui->fileToolButton, SIGNAL(clicked()), signalMapper, SLOT(map()));
signalMapper->setMapping(ui->feedToolButton, VIEW_MODE_FEEDS);
signalMapper->setMapping(ui->fileToolButton, VIEW_MODE_FILES);
connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(setViewMode(int)));
/*************** Setup Left Hand Side (List of Channels) ****************/
ui->loadingLabel->hide();
ui->progressBar->hide();
ui->nameLabel->setMinimumWidth(20);
/* Initialize feed widget */
ui->feedWidget->setSortRole(ROLE_PUBLISH, Qt::DescendingOrder);
ui->feedWidget->setFilterCallback(filterItem);
/* load settings */
processSettings(true);
/* Initialize subscribe button */
QIcon icon;
icon.addPixmap(FilesDefs::getPixmapFromQtResourcePath(":/images/redled.png"), QIcon::Normal, QIcon::On);
icon.addPixmap(FilesDefs::getPixmapFromQtResourcePath(":/images/start.png"), QIcon::Normal, QIcon::Off);
mAutoDownloadAction = new QAction(icon, "", this);
mAutoDownloadAction->setCheckable(true);
connect(mAutoDownloadAction, SIGNAL(triggered()), this, SLOT(toggleAutoDownload()));
ui->subscribeToolButton->addSubscribedAction(mAutoDownloadAction);
/* Initialize GUI */
setAutoDownload(false);
settingsChanged();
setGroupId(channelId);
mEventHandlerId = 0;
// Needs to be asynced because this function is called by another thread!
rsEvents->registerEventsHandler(
[this](std::shared_ptr<const RsEvent> event)
{ RsQThreadUtils::postToObject([=](){ handleEvent_main_thread(event); }, this ); },
mEventHandlerId, RsEventType::GXS_CHANNELS );
}
void GxsChannelPostsWidget::handleEvent_main_thread(std::shared_ptr<const RsEvent> event)
{
const RsGxsChannelEvent *e = dynamic_cast<const RsGxsChannelEvent*>(event.get());
if(!e)
return;
switch(e->mChannelEventCode)
{
case RsChannelEventCode::NEW_CHANNEL: // [[fallthrough]];
case RsChannelEventCode::UPDATED_CHANNEL: // [[fallthrough]];
case RsChannelEventCode::NEW_MESSAGE: // [[fallthrough]];
case RsChannelEventCode::UPDATED_MESSAGE:
if(e->mChannelGroupId == groupId())
updateDisplay(true);
break;
case RsChannelEventCode::READ_STATUS_CHANGED:
if (FeedItem *feedItem = ui->feedWidget->findFeedItem(GxsChannelPostItem::computeIdentifier(e->mChannelMsgId)))
if (GxsChannelPostItem *channelPostItem = dynamic_cast<GxsChannelPostItem*>(feedItem))
channelPostItem->setReadStatus(false,!channelPostItem->isUnread());
//channelPostItem->setReadStatus(false,e->Don't get read status. Will be more easier and accurate);
break;
default:
break;
}
}
GxsChannelPostsWidget::~GxsChannelPostsWidget()
{
rsEvents->unregisterEventsHandler(mEventHandlerId);
// save settings
processSettings(false);
delete(mAutoDownloadAction);
delete ui;
}
void GxsChannelPostsWidget::processSettings(bool load)
{
Settings->beginGroup(QString("ChannelPostsWidget"));
if (load) {
// load settings
/* Filter */
ui->filterLineEdit->setCurrentFilter(Settings->value("filter", FILTER_TITLE).toInt());
/* View mode */
setViewMode(Settings->value("viewMode", VIEW_MODE_FEEDS).toInt());
} else {
// save settings
/* Filter */
Settings->setValue("filter", ui->filterLineEdit->currentFilter());
/* View mode */
Settings->setValue("viewMode", viewMode());
}
Settings->endGroup();
}
void GxsChannelPostsWidget::settingsChanged()
{
mUseThread = Settings->getChannelLoadThread();
mStateHelper->setWidgetVisible(ui->progressBar, mUseThread);
}
void GxsChannelPostsWidget::groupNameChanged(const QString &name)
{
if (groupId().isNull()) {
ui->nameLabel->setText(tr("No Channel Selected"));
ui->logoLabel->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/icons/png/channels.png"));
} else {
ui->nameLabel->setText(name);
}
}
QIcon GxsChannelPostsWidget::groupIcon()
{
if (mStateHelper->isLoading(mTokenTypeGroupData) || mStateHelper->isLoading(mTokenTypeAllPosts)) {
return FilesDefs::getIconFromQtResourcePath(":/images/kalarm.png");
}
// if (mNewCount) {
// return FilesDefs::getIconFromQtResourcePath(":/images/message-state-new.png");
// }
return QIcon();
}
/*************************************************************************************/
/*************************************************************************************/
/*************************************************************************************/
QScrollArea *GxsChannelPostsWidget::getScrollArea()
{
return NULL;
}
void GxsChannelPostsWidget::deleteFeedItem(FeedItem *feedItem, uint32_t /*type*/)
{
if (!feedItem)
return;
ui->feedWidget->removeFeedItem(feedItem);
}
void GxsChannelPostsWidget::openChat(const RsPeerId & /*peerId*/)
{
}
// Callback from Widget->FeedHolder->ServiceDialog->CommentContainer->CommentDialog,
void GxsChannelPostsWidget::openComments(uint32_t /*type*/, const RsGxsGroupId &groupId, const QVector<RsGxsMessageId>& msg_versions,const RsGxsMessageId &msgId, const QString &title)
{
emit loadComment(groupId, msg_versions,msgId, title);
}
void GxsChannelPostsWidget::createMsg()
{
if (groupId().isNull()) {
return;
}
if (!IS_GROUP_SUBSCRIBED(subscribeFlags())) {
return;
}
CreateGxsChannelMsg *msgDialog = new CreateGxsChannelMsg(groupId());
msgDialog->show();
/* window will destroy itself! */
}
void GxsChannelPostsWidget::insertChannelDetails(const RsGxsChannelGroup &group)
{
/* IMAGE */
QPixmap chanImage;
if (group.mImage.mData != NULL) {
GxsIdDetails::loadPixmapFromData(group.mImage.mData, group.mImage.mSize, chanImage,GxsIdDetails::ORIGINAL);
} else {
chanImage = FilesDefs::getPixmapFromQtResourcePath(CHAN_DEFAULT_IMAGE);
}
ui->logoLabel->setPixmap(chanImage);
if (group.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_PUBLISH)
{
mStateHelper->setWidgetEnabled(ui->postButton, true);
}
else
{
mStateHelper->setWidgetEnabled(ui->postButton, false);
}
ui->subscribeToolButton->setSubscribed(IS_GROUP_SUBSCRIBED(group.mMeta.mSubscribeFlags));
mStateHelper->setWidgetEnabled(ui->subscribeToolButton, true);
bool autoDownload ;
rsGxsChannels->getChannelAutoDownload(group.mMeta.mGroupId,autoDownload);
setAutoDownload(autoDownload);
RetroShareLink link;
if (IS_GROUP_SUBSCRIBED(group.mMeta.mSubscribeFlags)) {
ui->feedToolButton->setEnabled(true);
ui->fileToolButton->setEnabled(true);
ui->infoWidget->hide();
setViewMode(viewMode());
ui->subscribeToolButton->setText(tr("Subscribed") + " " + QString::number(group.mMeta.mPop) );
ui->infoPosts->clear();
ui->infoDescription->clear();
} else {
ui->infoPosts->setText(QString::number(group.mMeta.mVisibleMsgCount));
if(group.mMeta.mLastPost==0)
ui->infoLastPost->setText(tr("Never"));
else
ui->infoLastPost->setText(DateTime::formatLongDateTime(group.mMeta.mLastPost));
QString formatDescription = QString::fromUtf8(group.mDescription.c_str());
unsigned int formatFlag = RSHTML_FORMATTEXT_EMBED_LINKS;
// embed smileys ?
if (Settings->valueFromGroup(QString("ChannelPostsWidget"), QString::fromUtf8("Emoteicons_ChannelDecription"), true).toBool()) {
formatFlag |= RSHTML_FORMATTEXT_EMBED_SMILEYS;
}
formatDescription = RsHtml().formatText(NULL, formatDescription, formatFlag);
ui->infoDescription->setText(formatDescription);
ui->infoAdministrator->setId(group.mMeta.mAuthorId) ;
link = RetroShareLink::createMessage(group.mMeta.mAuthorId, "");
ui->infoAdministrator->setText(link.toHtml());
ui->infoCreated->setText(DateTime::formatLongDateTime(group.mMeta.mPublishTs));
QString distrib_string ( "[unknown]" );
switch(group.mMeta.mCircleType)
{
case GXS_CIRCLE_TYPE_PUBLIC: distrib_string = tr("Public") ;
break ;
case GXS_CIRCLE_TYPE_EXTERNAL:
{
RsGxsCircleDetails det ;
// !! What we need here is some sort of CircleLabel, which loads the circle and updates the label when done.
if(rsGxsCircles->getCircleDetails(group.mMeta.mCircleId,det))
distrib_string = tr("Restricted to members of circle \"")+QString::fromUtf8(det.mCircleName.c_str()) +"\"";
else
distrib_string = tr("Restricted to members of circle ")+QString::fromStdString(group.mMeta.mCircleId.toStdString()) ;
}
break ;
case GXS_CIRCLE_TYPE_YOUR_EYES_ONLY: distrib_string = tr("Your eyes only");
break ;
case GXS_CIRCLE_TYPE_LOCAL: distrib_string = tr("You and your friend nodes");
break ;
default:
std::cerr << "(EE) badly initialised group distribution ID = " << group.mMeta.mCircleType << std::endl;
}
ui->infoDistribution->setText(distrib_string);
ui->infoWidget->show();
ui->feedWidget->hide();
ui->fileWidget->hide();
ui->feedToolButton->setEnabled(false);
ui->fileToolButton->setEnabled(false);
ui->subscribeToolButton->setText(tr("Subscribe ") + " " + QString::number(group.mMeta.mPop) );
}
}
int GxsChannelPostsWidget::viewMode()
{
if (ui->feedToolButton->isChecked()) {
return VIEW_MODE_FEEDS;
} else if (ui->fileToolButton->isChecked()) {
return VIEW_MODE_FILES;
}
/* Default */
return VIEW_MODE_FEEDS;
}
void GxsChannelPostsWidget::setViewMode(int viewMode)
{
switch (viewMode) {
case VIEW_MODE_FEEDS:
ui->feedWidget->show();
ui->fileWidget->hide();
ui->feedToolButton->setChecked(true);
ui->fileToolButton->setChecked(false);
break;
case VIEW_MODE_FILES:
ui->feedWidget->hide();
ui->fileWidget->show();
ui->feedToolButton->setChecked(false);
ui->fileToolButton->setChecked(true);
break;
default:
setViewMode(VIEW_MODE_FEEDS);
return;
}
}
void GxsChannelPostsWidget::filterChanged(int filter)
{
ui->feedWidget->setFilterType(filter);
ui->fileWidget->setFilterType(filter);
}
/*static*/ bool GxsChannelPostsWidget::filterItem(FeedItem *feedItem, const QString &text, int filter)
{
GxsChannelPostItem *item = dynamic_cast<GxsChannelPostItem*>(feedItem);
if (!item) {
return true;
}
bool bVisible = text.isEmpty();
if (!bVisible)
{
switch(filter)
{
case FILTER_TITLE:
bVisible = item->getTitleLabel().contains(text,Qt::CaseInsensitive);
break;
case FILTER_MSG:
bVisible = item->getMsgLabel().contains(text,Qt::CaseInsensitive);
break;
case FILTER_FILE_NAME:
{
std::list<SubFileItem *> fileItems = item->getFileItems();
std::list<SubFileItem *>::iterator lit;
for(lit = fileItems.begin(); lit != fileItems.end(); ++lit)
{
SubFileItem *fi = *lit;
QString fileName = QString::fromUtf8(fi->FileName().c_str());
bVisible = (bVisible || fileName.contains(text,Qt::CaseInsensitive));
}
break;
}
default:
bVisible = true;
break;
}
}
return bVisible;
}
#ifdef TODO
void GxsChannelPostsWidget::createPostItemFromMetaData(const RsGxsMsgMetaData& meta,bool related)
{
GxsChannelPostItem *item = NULL;
RsGxsChannelPost post;
if(!meta.mOrigMsgId.isNull())
{
FeedItem *feedItem = ui->feedWidget->findFeedItem(GxsChannelPostItem::computeIdentifier(meta.mOrigMsgId)) ;
item = dynamic_cast<GxsChannelPostItem*>(feedItem);
if(item)
{
post = feedItem->post();
ui->feedWidget->removeFeedItem(item) ;
post.mOlderVersions.insert(post.mMeta.mMsgId);
GxsChannelPostItem *item = new GxsChannelPostItem(this, 0, post, true, false,post.mOlderVersions);
ui->feedWidget->addFeedItem(item, ROLE_PUBLISH, QDateTime::fromTime_t(post.mMeta.mPublishTs));
return ;
}
}
if (related)
{
FeedItem *feedItem = ui->feedWidget->findFeedItem(GxsChannelPostItem::computeIdentifier(meta.mMsgId)) ;
item = dynamic_cast<GxsChannelPostItem*>(feedItem);
}
if (item)
{
item->setPost(post);
ui->feedWidget->setSort(item, ROLE_PUBLISH, QDateTime::fromTime_t(meta.mPublishTs));
}
else
{
GxsChannelPostItem *item = new GxsChannelPostItem(this, 0, meta.mGroupId,meta.mMsgId, true, true);
ui->feedWidget->addFeedItem(item, ROLE_PUBLISH, QDateTime::fromTime_t(post.mMeta.mPublishTs));
}
#ifdef TODO
ui->fileWidget->addFiles(post, related);
#endif
}
#endif
void GxsChannelPostsWidget::createPostItem(const RsGxsChannelPost& post, bool related)
{
GxsChannelPostItem *item = NULL;
const RsMsgMetaData& meta(post.mMeta);
if(!meta.mOrigMsgId.isNull())
{
FeedItem *feedItem = ui->feedWidget->findFeedItem(GxsChannelPostItem::computeIdentifier(meta.mOrigMsgId)) ;
item = dynamic_cast<GxsChannelPostItem*>(feedItem);
if(item)
{
std::set<RsGxsMessageId> older_versions(item->olderVersions()); // we make a copy because the item will be deleted
ui->feedWidget->removeFeedItem(item) ;
older_versions.insert(meta.mMsgId);
GxsChannelPostItem *item = new GxsChannelPostItem(this, 0, mGroup.mMeta,meta.mMsgId, true, false,older_versions);
ui->feedWidget->addFeedItem(item, ROLE_PUBLISH, QDateTime::fromTime_t(meta.mPublishTs));
return ;
}
}
if (related)
{
FeedItem *feedItem = ui->feedWidget->findFeedItem(GxsChannelPostItem::computeIdentifier(meta.mMsgId)) ;
item = dynamic_cast<GxsChannelPostItem*>(feedItem);
}
if (item)
{
item->setPost(post);
ui->feedWidget->setSort(item, ROLE_PUBLISH, QDateTime::fromTime_t(meta.mPublishTs));
}
else
{
GxsChannelPostItem *item = new GxsChannelPostItem(this, 0, mGroup.mMeta,meta.mMsgId, true, true);
ui->feedWidget->addFeedItem(item, ROLE_PUBLISH, QDateTime::fromTime_t(meta.mPublishTs));
}
ui->fileWidget->addFiles(post, related);
}
void GxsChannelPostsWidget::fillThreadCreatePost(const QVariant &post, bool related, int current, int count)
{
/* show fill progress */
if (count) {
ui->progressBar->setValue(current * ui->progressBar->maximum() / count);
}
if (!post.canConvert<RsGxsChannelPost>()) {
return;
}
createPostItem(post.value<RsGxsChannelPost>(), related);
}
void GxsChannelPostsWidget::insertChannelPosts(std::vector<RsGxsChannelPost>& posts, GxsMessageFramePostThread *thread, bool related)
{
if (related && thread) {
std::cerr << "GxsChannelPostsWidget::insertChannelPosts fill only related posts as thread is not possible" << std::endl;
return;
}
int count = posts.size();
int pos = 0;
if (!thread) {
ui->feedWidget->setSortingEnabled(false);
}
// collect new versions of posts if any
#ifdef DEBUG_CHANNEL
std::cerr << "Inserting channel posts" << std::endl;
#endif
std::vector<uint32_t> new_versions ;
for (uint32_t i=0;i<posts.size();++i)
{
if(posts[i].mMeta.mOrigMsgId == posts[i].mMeta.mMsgId)
posts[i].mMeta.mOrigMsgId.clear();
#ifdef DEBUG_CHANNEL
std::cerr << " " << i << ": msg_id=" << posts[i].mMeta.mMsgId << ": orig msg id = " << posts[i].mMeta.mOrigMsgId << std::endl;
#endif
if(!posts[i].mMeta.mOrigMsgId.isNull())
new_versions.push_back(i) ;
}
#ifdef DEBUG_CHANNEL
std::cerr << "New versions: " << new_versions.size() << std::endl;
#endif
if(!new_versions.empty())
{
#ifdef DEBUG_CHANNEL
std::cerr << " New versions present. Replacing them..." << std::endl;
std::cerr << " Creating search map." << std::endl;
#endif
// make a quick search map
std::map<RsGxsMessageId,uint32_t> search_map ;
for (uint32_t i=0;i<posts.size();++i)
search_map[posts[i].mMeta.mMsgId] = i ;
for(uint32_t i=0;i<new_versions.size();++i)
{
#ifdef DEBUG_CHANNEL
std::cerr << " Taking care of new version at index " << new_versions[i] << std::endl;
#endif
uint32_t current_index = new_versions[i] ;
uint32_t source_index = new_versions[i] ;
#ifdef DEBUG_CHANNEL
RsGxsMessageId source_msg_id = posts[source_index].mMeta.mMsgId ;
#endif
// What we do is everytime we find a replacement post, we climb up the replacement graph until we find the original post
// (or the most recent version of it). When we reach this post, we replace it with the data of the source post.
// In the mean time, all other posts have their MsgId cleared, so that the posts are removed from the list.
//std::vector<uint32_t> versions ;
std::map<RsGxsMessageId,uint32_t>::const_iterator vit ;
while(search_map.end() != (vit=search_map.find(posts[current_index].mMeta.mOrigMsgId)))
{
#ifdef DEBUG_CHANNEL
std::cerr << " post at index " << current_index << " replaces a post at position " << vit->second ;
#endif
// Now replace the post only if the new versionis more recent. It may happen indeed that the same post has been corrected multiple
// times. In this case, we only need to replace the post with the newest version
//uint32_t prev_index = current_index ;
current_index = vit->second ;
if(posts[current_index].mMeta.mMsgId.isNull()) // This handles the branching situation where this post has been already erased. No need to go down further.
{
#ifdef DEBUG_CHANNEL
std::cerr << " already erased. Stopping." << std::endl;
#endif
break ;
}
if(posts[current_index].mMeta.mPublishTs < posts[source_index].mMeta.mPublishTs)
{
#ifdef DEBUG_CHANNEL
std::cerr << " and is more recent => following" << std::endl;
#endif
for(std::set<RsGxsMessageId>::const_iterator itt(posts[current_index].mOlderVersions.begin());itt!=posts[current_index].mOlderVersions.end();++itt)
posts[source_index].mOlderVersions.insert(*itt);
posts[source_index].mOlderVersions.insert(posts[current_index].mMeta.mMsgId);
posts[current_index].mMeta.mMsgId.clear(); // clear the msg Id so the post will be ignored
}
#ifdef DEBUG_CHANNEL
else
std::cerr << " but is older -> Stopping" << std::endl;
#endif
}
}
}
#ifdef DEBUG_CHANNEL
std::cerr << "Now adding posts..." << std::endl;
#endif
for (std::vector<RsGxsChannelPost>::const_reverse_iterator it = posts.rbegin(); it != posts.rend(); ++it)
{
#ifdef DEBUG_CHANNEL
std::cerr << " adding post: " << (*it).mMeta.mMsgId ;
#endif
if(!(*it).mMeta.mMsgId.isNull())
{
#ifdef DEBUG_CHANNEL
std::cerr << " added" << std::endl;
#endif
if (thread && thread->stopped())
break;
if (thread)
thread->emitAddPost(QVariant::fromValue(*it), related, ++pos, count);
else
createPostItem(*it, related);
}
#ifdef DEBUG_CHANNEL
else
std::cerr << " skipped" << std::endl;
#endif
}
if (!thread) {
ui->feedWidget->setSortingEnabled(true);
}
}
void GxsChannelPostsWidget::clearPosts()
{
ui->feedWidget->clear();
ui->fileWidget->clear();
}
void GxsChannelPostsWidget::blank()
{
mStateHelper->setWidgetEnabled(ui->postButton, false);
mStateHelper->setWidgetEnabled(ui->subscribeToolButton, false);
clearPosts();
groupNameChanged(QString());
ui->infoWidget->hide();
ui->feedWidget->show();
ui->fileWidget->hide();
}
bool GxsChannelPostsWidget::navigatePostItem(const RsGxsMessageId &msgId)
{
FeedItem *feedItem = ui->feedWidget->findFeedItem(GxsChannelPostItem::computeIdentifier(msgId));
if (!feedItem) {
return false;
}
return ui->feedWidget->scrollTo(feedItem, true);
}
void GxsChannelPostsWidget::subscribeGroup(bool subscribe)
{
RsGxsGroupId grpId(groupId());
if (grpId.isNull()) return;
RsThread::async([=]()
{
rsGxsChannels->subscribeToChannel(grpId, subscribe);
} );
}
void GxsChannelPostsWidget::setAutoDownload(bool autoDl)
{
mAutoDownloadAction->setChecked(autoDl);
mAutoDownloadAction->setText(autoDl ? tr("Disable Auto-Download") : tr("Enable Auto-Download"));
}
void GxsChannelPostsWidget::toggleAutoDownload()
{
RsGxsGroupId grpId = groupId();
if (grpId.isNull()) {
return;
}
bool autoDownload;
if(!rsGxsChannels->getChannelAutoDownload(grpId, autoDownload))
{
std::cerr << __PRETTY_FUNCTION__ << " failed to get autodownload value "
<< "for channel: " << grpId.toStdString() << std::endl;
return;
}
RsThread::async([this, grpId, autoDownload]()
{
if(!rsGxsChannels->setChannelAutoDownload(grpId, !autoDownload))
{
std::cerr << __PRETTY_FUNCTION__ << " failed to set autodownload "
<< "for channel: " << grpId.toStdString() << std::endl;
return;
}
// RsQThreadUtils::postToObject( [=]()
// {
// /* Here it goes any code you want to be executed on the Qt Gui
// * thread, for example to update the data model with new information
// * after a blocking call to RetroShare API complete, note that
// * Qt::QueuedConnection is important!
// */
//
// std::cerr << __PRETTY_FUNCTION__ << " Has been executed on GUI "
// << "thread but was scheduled by async thread" << std::endl;
// }, this );
});
}
bool GxsChannelPostsWidget::insertGroupData(const RsGxsGenericGroupData *data)
{
const RsGxsChannelGroup *d = dynamic_cast<const RsGxsChannelGroup*>(data);
if(!d)
{
RsErr() << __PRETTY_FUNCTION__ << " Cannot dynamic cast input data (" << (void*)data << " to RsGxsGenericGroupData. Something bad happenned." << std::endl;
return false;
}
insertChannelDetails(*d);
return true;
}
void GxsChannelPostsWidget::getMsgData(const std::set<RsGxsMessageId>& msgIds,std::vector<RsGxsGenericMsgData*>& psts)
{
std::vector<RsGxsChannelPost> posts;
std::vector<RsGxsComment> comments;
std::vector<RsGxsVote> votes;
rsGxsChannels->getChannelContent( groupId(),msgIds,posts,comments,votes );
psts.clear();
for(auto& post: posts)
psts.push_back(new RsGxsChannelPost(post));
}
void GxsChannelPostsWidget::getAllMsgData(std::vector<RsGxsGenericMsgData*>& psts)
{
std::vector<RsGxsChannelPost> posts;
std::vector<RsGxsComment> comments;
std::vector<RsGxsVote> votes;
rsGxsChannels->getChannelAllContent( groupId(),posts,comments,votes );
psts.clear();
for(auto& post: posts)
psts.push_back(new RsGxsChannelPost(post));
}
bool GxsChannelPostsWidget::getGroupData(RsGxsGenericGroupData *& data)
{
if(groupId().isNull())
{
RsErr() << __PRETTY_FUNCTION__ << " Trying to get data about null group!!" << std::endl;
return false;
}
std::vector<RsGxsChannelGroup> groups;
if(rsGxsChannels->getChannelsInfo(std::list<RsGxsGroupId>({groupId()}),groups) && groups.size()==1)
{
data = new RsGxsChannelGroup(groups[0]);
mGroup = groups[0]; // make a local copy to pass on to items
return true;
}
else
{
RsGxsChannelGroup distant_group;
if(rsGxsChannels->getDistantSearchResultGroupData(groupId(),distant_group))
{
insertChannelDetails(distant_group);
data = new RsGxsChannelGroup(distant_group);
mGroup = distant_group; // make a local copy to pass on to items
return true ;
}
}
return false;
}
void GxsChannelPostsWidget::insertAllPosts(const std::vector<RsGxsGenericMsgData*>& posts, GxsMessageFramePostThread *thread)
{
std::vector<RsGxsChannelPost> cposts;
for(auto post: posts) // This is not so nice but we have somehow to convert to RsGxsChannelPost at some time, and the cposts list is being modified in the insert method.
cposts.push_back(*static_cast<RsGxsChannelPost*>(post));
insertChannelPosts(cposts, thread, false);
}
void GxsChannelPostsWidget::insertPosts(const std::vector<RsGxsGenericMsgData*>& posts)
{
std::vector<RsGxsChannelPost> cposts;
for(auto post: posts) // This is not so nice but we have somehow to convert to RsGxsChannelPost at some timer, and the cposts list is being modified in the insert method.
cposts.push_back(*static_cast<RsGxsChannelPost*>(post));
insertChannelPosts(cposts, NULL, true);
}
class GxsChannelPostsReadData
{
public:
GxsChannelPostsReadData(bool read)
{
mRead = read;
mLastToken = 0;
}
public:
bool mRead;
uint32_t mLastToken;
};
static void setAllMessagesReadCallback(FeedItem *feedItem, void *data)
{
GxsChannelPostItem *channelPostItem = dynamic_cast<GxsChannelPostItem*>(feedItem);
if (!channelPostItem) {
return;
}
GxsChannelPostsReadData *readData = (GxsChannelPostsReadData*) data;
bool isRead = !channelPostItem->isUnread() ;
if(channelPostItem->isLoaded() && (isRead == readData->mRead))
return ;
RsGxsGrpMsgIdPair msgPair = std::make_pair(channelPostItem->groupId(), channelPostItem->messageId());
rsGxsChannels->setMessageReadStatus(readData->mLastToken, msgPair, readData->mRead);
}
void GxsChannelPostsWidget::setAllMessagesReadDo(bool read, uint32_t &token)
{
if (groupId().isNull() || !IS_GROUP_SUBSCRIBED(subscribeFlags())) {
return;
}
GxsChannelPostsReadData data(read);
ui->feedWidget->withAll(setAllMessagesReadCallback, &data);
token = data.mLastToken;
}

View File

@ -1,117 +0,0 @@
/*******************************************************************************
* retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidget.h *
* *
* Copyright 2013 by Robert Fernie <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/>. *
* *
*******************************************************************************/
#ifndef _GXS_CHANNELPOSTSWIDGET_H
#define _GXS_CHANNELPOSTSWIDGET_H
#include <map>
#include "gui/gxs/GxsMessageFramePostWidget.h"
#include "gui/feeds/FeedHolder.h"
namespace Ui {
class GxsChannelPostsWidget;
}
class GxsChannelPostItem;
class QTreeWidgetItem;
class FeedItem;
class GxsChannelPostsWidget : public GxsMessageFramePostWidget, public FeedHolder
{
Q_OBJECT
public:
/* Filters */
enum Filter {
FILTER_TITLE = 1,
FILTER_MSG = 2,
FILTER_FILE_NAME = 3
};
public:
/** Default Constructor */
GxsChannelPostsWidget(const RsGxsGroupId &channelId, QWidget *parent = 0);
/** Default Destructor */
~GxsChannelPostsWidget();
/* GxsMessageFrameWidget */
virtual QIcon groupIcon();
/* FeedHolder */
virtual QScrollArea *getScrollArea();
virtual void deleteFeedItem(FeedItem *feedItem, uint32_t type);
virtual void openChat(const RsPeerId& peerId);
virtual void openComments(uint32_t type, const RsGxsGroupId &groupId, const QVector<RsGxsMessageId> &msg_versions, const RsGxsMessageId &msgId, const QString &title);
protected:
/* GxsMessageFramePostWidget */
virtual void groupNameChanged(const QString &name);
virtual bool insertGroupData(const RsGxsGenericGroupData *data) override;
virtual void clearPosts();
virtual bool useThread() { return mUseThread; }
virtual void fillThreadCreatePost(const QVariant &post, bool related, int current, int count);
virtual bool navigatePostItem(const RsGxsMessageId& msgId);
virtual void blank() ;
virtual bool getGroupData(RsGxsGenericGroupData *& data) override;
virtual void getMsgData(const std::set<RsGxsMessageId>& msgIds,std::vector<RsGxsGenericMsgData*>& posts) override;
virtual void getAllMsgData(std::vector<RsGxsGenericMsgData*>& posts) override;
virtual void insertPosts(const std::vector<RsGxsGenericMsgData*>& posts) override;
virtual void insertAllPosts(const std::vector<RsGxsGenericMsgData*>& posts, GxsMessageFramePostThread *thread) override;
/* GxsMessageFrameWidget */
virtual void setAllMessagesReadDo(bool read, uint32_t &token);
private slots:
void createMsg();
void toggleAutoDownload();
void subscribeGroup(bool subscribe);
void filterChanged(int filter);
void setViewMode(int viewMode);
void settingsChanged();
private:
void processSettings(bool load);
void setAutoDownload(bool autoDl);
static bool filterItem(FeedItem *feedItem, const QString &text, int filter);
int viewMode();
void insertChannelDetails(const RsGxsChannelGroup &group);
void insertChannelPosts(std::vector<RsGxsChannelPost>& posts, GxsMessageFramePostThread *thread, bool related);
void createPostItem(const RsGxsChannelPost &post, bool related);
void handleEvent_main_thread(std::shared_ptr<const RsEvent> event);
private:
QAction *mAutoDownloadAction;
RsGxsChannelGroup mGroup;
bool mUseThread;
RsEventsHandlerId_t mEventHandlerId ;
/* UI - from Designer */
Ui::GxsChannelPostsWidget *ui;
};
#endif

View File

@ -1,593 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GxsChannelPostsWidget</class>
<widget class="QWidget" name="GxsChannelPostsWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>977</width>
<height>628</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>4</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QFrame" name="headFrame">
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="leftMargin">
<number>4</number>
</property>
<property name="topMargin">
<number>4</number>
</property>
<property name="rightMargin">
<number>4</number>
</property>
<property name="bottomMargin">
<number>4</number>
</property>
<item>
<widget class="QLabel" name="logoLabel">
<property name="minimumSize">
<size>
<width>64</width>
<height>64</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>64</width>
<height>64</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../images.qrc">:/images/channels.png</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="StyledElidedLabel" name="nameLabel">
<property name="palette">
<palette>
<active/>
<inactive/>
<disabled/>
</palette>
</property>
<property name="text">
<string notr="true">Channel Name</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="toolBarFrame">
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>4</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item>
<widget class="SubscribeToolButton" name="subscribeToolButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string notr="true">Subscribe</string>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="popupMode">
<enum>QToolButton::MenuButtonPopup</enum>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextBesideIcon</enum>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="postButton">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="toolTip">
<string>Post to Channel</string>
</property>
<property name="text">
<string>Add new post</string>
</property>
<property name="icon">
<iconset resource="../icons.qrc">
<normaloff>:/icons/png/add.png</normaloff>:/icons/png/add.png</iconset>
</property>
<property name="iconSize">
<size>
<width>32</width>
<height>16</height>
</size>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextBesideIcon</enum>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::MinimumExpanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="loadingLabel">
<property name="text">
<string>Loading</string>
</property>
</widget>
</item>
<item>
<widget class="QProgressBar" name="progressBar">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>10</height>
</size>
</property>
<property name="maximum">
<number>1000</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="viewModeLayout">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QToolButton" name="feedToolButton">
<property name="toolTip">
<string>Show feeds</string>
</property>
<property name="icon">
<iconset resource="../images.qrc">
<normaloff>:/images/view-feeds.png</normaloff>:/images/view-feeds.png</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="fileToolButton">
<property name="toolTip">
<string>Show files</string>
</property>
<property name="icon">
<iconset resource="../images.qrc">
<normaloff>:/images/view-files.png</normaloff>:/images/view-files.png</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="LineEditClear" name="filterLineEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>200</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Search channels</string>
</property>
<property name="frame">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="infoWidget" native="true">
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QFrame" name="infoFrame">
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Channel details</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>9</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<item row="1" column="0">
<widget class="QLabel" name="infoLastPostLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Last Post:</string>
</property>
</widget>
</item>
<item row="6" column="0" colspan="3">
<widget class="QTextBrowser" name="infoDescription">
<property name="html">
<string notr="true">&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:8pt;&quot;&gt;Description&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
<property name="openLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="infoDescriptionLabel">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Description:</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_2">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Created:</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Administrator:</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="infoPostsLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Posts:</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_3">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Distribution:</string>
</property>
</widget>
</item>
<item row="4" column="1" colspan="2">
<widget class="QLabel" name="infoCreated">
<property name="text">
<string>unknown</string>
</property>
</widget>
</item>
<item row="3" column="1" colspan="2">
<widget class="QLabel" name="infoDistribution">
<property name="text">
<string>unknown</string>
</property>
</widget>
</item>
<item row="2" column="1" colspan="2">
<widget class="GxsIdLabel" name="infoAdministrator">
<property name="text">
<string>unknown</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<widget class="QLabel" name="infoLastPost">
<property name="text">
<string notr="true">unknown</string>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QLabel" name="infoPosts">
<property name="text">
<string notr="true">0</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="GxsChannelFilesWidget" name="fileWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="RSFeedWidget" name="feedWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
<action name="actionFeeds">
<property name="text">
<string>Feeds</string>
</property>
</action>
<action name="actionFiles">
<property name="text">
<string>Files</string>
</property>
</action>
<zorder>toolBarFrame</zorder>
<zorder>headFrame</zorder>
<zorder>feedWidget</zorder>
<zorder>fileWidget</zorder>
<zorder>infoWidget</zorder>
</widget>
<customwidgets>
<customwidget>
<class>GxsIdLabel</class>
<extends>QLabel</extends>
<header>gui/gxs/GxsIdLabel.h</header>
</customwidget>
<customwidget>
<class>SubscribeToolButton</class>
<extends>QToolButton</extends>
<header>gui/common/SubscribeToolButton.h</header>
</customwidget>
<customwidget>
<class>StyledElidedLabel</class>
<extends>QLabel</extends>
<header>gui/common/StyledElidedLabel.h</header>
</customwidget>
<customwidget>
<class>LineEditClear</class>
<extends>QLineEdit</extends>
<header location="global">gui/common/LineEditClear.h</header>
</customwidget>
<customwidget>
<class>GxsChannelFilesWidget</class>
<extends>QWidget</extends>
<header>gui/gxschannels/GxsChannelFilesWidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>RSFeedWidget</class>
<extends>QWidget</extends>
<header>gui/common/RSFeedWidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../icons.qrc"/>
<include location="../images.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -75,9 +75,10 @@ QColor SelectedColor = QRgb(0xff308dc7);
#define COLUMN_SIZE_FONT_FACTOR_H 10
#define STAR_OVERLAY_IMAGE ":icons/star_overlay_128.png"
#define IMAGE_COPYLINK ":/images/copyrslink.png"
#define IMAGE_COPYLINK ":icons/png/copy.png"
#define IMAGE_GRID_VIEW ":icons/png/menu.png"
#define IMAGE_DOWNLOAD ":icons/png/download.png"
#define IMAGE_UNREAD ":icons/png/message.png"
Q_DECLARE_METATYPE(ChannelPostFileInfo)
@ -492,12 +493,12 @@ void GxsChannelPostsWidgetWithModel::postContextMenu(const QPoint&)
menu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_DOWNLOAD), tr("Download files"), this, SLOT(download()));
if(!IS_MSG_UNREAD(post.mMeta.mMsgStatus) && !IS_MSG_NEW(post.mMeta.mMsgStatus))
menu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_COPYLINK), tr("Mark as unread"), this, SLOT(markMessageUnread()));
menu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_UNREAD), tr("Mark as unread"), this, SLOT(markMessageUnread()));
}
menu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_COPYLINK), tr("Copy RetroShare Link"), this, SLOT(copyMessageLink()));
if(IS_GROUP_PUBLISHER(mGroup.mMeta.mSubscribeFlags))
menu.addAction(FilesDefs::getIconFromQtResourcePath(":/images/edit_16.png"), tr("Edit"), this, SLOT(editPost()));
menu.addAction(FilesDefs::getIconFromQtResourcePath(":/icons/png/pencil-edit-button.png"), tr("Edit"), this, SLOT(editPost()));
menu.exec(QCursor::pos());
}

View File

@ -445,10 +445,13 @@ QVariant RsGxsForumModel::textColorRole(const ForumModelPostEntry& fmpe,int /*co
if( (fmpe.mPostFlags & ForumModelPostEntry::FLAG_POST_IS_MISSING))
return QVariant(mTextColorMissing);
if(IS_MSG_UNREAD(fmpe.mMsgStatus) || (fmpe.mPostFlags & ForumModelPostEntry::FLAG_POST_IS_PINNED))
if(IS_MSG_UNREAD(fmpe.mMsgStatus))
return QVariant(mTextColorUnread);
else
return QVariant(mTextColorRead);
if(fmpe.mPostFlags & ForumModelPostEntry::FLAG_POST_IS_PINNED)
return QVariant(mTextColorPinned);
else
return QVariant(mTextColorRead);
return QVariant();
}
@ -593,10 +596,10 @@ QVariant RsGxsForumModel::pinnedRole(const ForumModelPostEntry& fmpe,int /*colum
QVariant RsGxsForumModel::backgroundRole(const ForumModelPostEntry& fmpe,int /*column*/) const
{
if(fmpe.mPostFlags & ForumModelPostEntry::FLAG_POST_IS_PINNED)
return QVariant(QBrush(QColor(255,200,180)));
return QVariant(QBrush(mBackgroundColorPinned));
if(mFilteringEnabled && (fmpe.mPostFlags & ForumModelPostEntry::FLAG_POST_PASSES_FILTER))
return QVariant(QBrush(QColor(255,240,210)));
return QVariant(QBrush(mBackgroundColorFiltered));
return QVariant();
}

View File

@ -116,6 +116,10 @@ public:
void setTextColorUnreadChildren(QColor color) { mTextColorUnreadChildren = color;}
void setTextColorNotSubscribed (QColor color) { mTextColorNotSubscribed = color;}
void setTextColorMissing (QColor color) { mTextColorMissing = color;}
void setTextColorPinned (QColor color) { mTextColorPinned = color;}
void setBackgroundColorPinned (QColor color) { mBackgroundColorPinned = color;}
void setBackgroundColorFiltered (QColor color) { mBackgroundColorFiltered = color;}
void setMsgReadStatus(const QModelIndex &i, bool read_status, bool with_children);
void setFilter(int column, const QStringList &strings, uint32_t &count) ;
@ -202,6 +206,10 @@ private:
QColor mTextColorUnreadChildren;
QColor mTextColorNotSubscribed ;
QColor mTextColorMissing ;
QColor mTextColorPinned ;
QColor mBackgroundColorPinned;
QColor mBackgroundColorFiltered;
friend class const_iterator;
};

View File

@ -62,7 +62,7 @@
#define IMAGE_MESSAGE ":/icons/mail/compose.png"
#define IMAGE_REPLY ":/icons/mail/reply.png"
#define IMAGE_MESSAGEREPLY ":/icons/mail/write-mail.png"
#define IMAGE_MESSAGEEDIT ":/images/edit_16.png"
#define IMAGE_MESSAGEEDIT ":/icons/png/pencil-edit-button.png"
#define IMAGE_MESSAGEREMOVE ":/images/mail_delete.png"
#define IMAGE_DOWNLOAD ":/images/start.png"
#define IMAGE_DOWNLOADALL ":/images/startall.png"
@ -230,6 +230,11 @@ void GxsForumThreadWidget::setTextColorUnread (QColor color) { mTextColor
void GxsForumThreadWidget::setTextColorUnreadChildren(QColor color) { mTextColorUnreadChildren = color; mThreadModel->setTextColorUnreadChildren(color);}
void GxsForumThreadWidget::setTextColorNotSubscribed (QColor color) { mTextColorNotSubscribed = color; mThreadModel->setTextColorNotSubscribed (color);}
void GxsForumThreadWidget::setTextColorMissing (QColor color) { mTextColorMissing = color; mThreadModel->setTextColorMissing (color);}
// Suppose to be different from unread one
void GxsForumThreadWidget::setTextColorPinned (QColor color) { mTextColorPinned = color; mThreadModel->setTextColorPinned (color);}
void GxsForumThreadWidget::setBackgroundColorPinned (QColor color) { mBackgroundColorPinned = color; mThreadModel->setBackgroundColorPinned (color);}
void GxsForumThreadWidget::setBackgroundColorFiltered(QColor color) { mBackgroundColorFiltered = color; mThreadModel->setBackgroundColorFiltered (color);}
GxsForumThreadWidget::GxsForumThreadWidget(const RsGxsGroupId &forumId, QWidget *parent) :
GxsMessageFrameWidget(rsGxsForums, parent),
@ -331,6 +336,9 @@ GxsForumThreadWidget::GxsForumThreadWidget(const RsGxsGroupId &forumId, QWidget
ttheader->hideSection (RsGxsForumModel::COLUMN_THREAD_MSGID);
ttheader->hideSection (RsGxsForumModel::COLUMN_THREAD_DATA);
ttheader->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ttheader, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(headerContextMenuRequested(QPoint)));
ui->progressBar->hide();
ui->progressText->hide();
@ -343,6 +351,8 @@ GxsForumThreadWidget::GxsForumThreadWidget(const RsGxsGroupId &forumId, QWidget
// load settings
processSettings(true);
mDisplayBannedText = false;
blankPost();
ui->subscribeToolButton->setToolTip(tr( "<p>Subscribing to the forum will gather \
@ -611,6 +621,11 @@ void GxsForumThreadWidget::threadListCustomPopupMenu(QPoint /*point*/)
QAction* expandAll = new QAction(tr("Expand all"), &contextMnu);
connect(expandAll, SIGNAL(triggered()), ui->threadTreeWidget, SLOT(expandAll()));
#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
QAction* expandSubtree = new QAction(tr("Expand subtree"), &contextMnu);
connect(expandSubtree, SIGNAL(triggered()), this, SLOT(expandSubtree()));
#endif
QAction* collapseAll = new QAction(tr( "Collapse all"), &contextMnu);
connect(collapseAll, SIGNAL(triggered()), ui->threadTreeWidget, SLOT(collapseAll()));
@ -629,11 +644,19 @@ void GxsForumThreadWidget::threadListCustomPopupMenu(QPoint /*point*/)
QAction *showinpeopleAct = new QAction(FilesDefs::getIconFromQtResourcePath(":/images/info16.png"), tr("Show author in people tab"), &contextMnu);
connect(showinpeopleAct, SIGNAL(triggered()), this, SLOT(showInPeopleTab()));
bool has_children = false;
if (has_current_post) {
has_children = !current_post.mChildren.empty();
}
if (IS_GROUP_SUBSCRIBED(mForumGroup.mMeta.mSubscribeFlags))
{
markMsgAsReadChildren->setEnabled(current_post.mPostFlags & ForumModelPostEntry::FLAG_POST_HAS_UNREAD_CHILDREN);
markMsgAsUnreadChildren->setEnabled(current_post.mPostFlags & ForumModelPostEntry::FLAG_POST_HAS_READ_CHILDREN);
#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
expandSubtree->setEnabled(has_children);
#endif
replyAct->setEnabled (true);
replyauthorAct->setEnabled (true);
}
@ -645,6 +668,22 @@ void GxsForumThreadWidget::threadListCustomPopupMenu(QPoint /*point*/)
markMsgAsUnreadChildren->setDisabled(true);
replyAct->setDisabled (true);
replyauthorAct->setDisabled (true);
#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
expandSubtree->setDisabled(true);
expandSubtree->setVisible(false);
#endif
}
// disable visibility for childless
if (has_current_post) {
// still no setEnabled
markMsgAsRead->setVisible(IS_MSG_UNREAD(current_post.mMsgStatus));
markMsgAsUnread->setVisible(!IS_MSG_UNREAD(current_post.mMsgStatus));
#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
expandSubtree->setVisible(has_children);
#endif
markMsgAsReadChildren->setVisible(has_children);
markMsgAsUnreadChildren->setVisible(has_children);
}
if(has_current_post)
@ -678,7 +717,7 @@ void GxsForumThreadWidget::threadListCustomPopupMenu(QPoint /*point*/)
}
contextMnu.addAction(replyAct);
contextMnu.addAction(newthreadAct);
contextMnu.addAction(newthreadAct);
QAction* action = contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_COPYLINK), tr("Copy RetroShare Link"), this, SLOT(copyMessageLink()));
action->setEnabled(!groupId().isNull() && !mThreadId.isNull());
contextMnu.addSeparator();
@ -688,6 +727,9 @@ void GxsForumThreadWidget::threadListCustomPopupMenu(QPoint /*point*/)
contextMnu.addAction(markMsgAsUnreadChildren);
contextMnu.addSeparator();
contextMnu.addAction(expandAll);
#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
contextMnu.addAction(expandSubtree);
#endif
contextMnu.addAction(collapseAll);
if(has_current_post)
@ -739,6 +781,64 @@ void GxsForumThreadWidget::contextMenuTextBrowser(QPoint point)
delete(contextMnu);
}
void GxsForumThreadWidget::headerContextMenuRequested(const QPoint &pos)
{
QMenu* header_context_menu = new QMenu(tr("Show column"), this);
QAction* title = header_context_menu->addAction(QIcon(), tr("Title"));
title->setCheckable(true);
title->setChecked(!ui->threadTreeWidget->isColumnHidden(RsGxsForumModel::COLUMN_THREAD_TITLE));
title->setData(RsGxsForumModel::COLUMN_THREAD_TITLE);
connect(title, SIGNAL(toggled(bool)), this, SLOT(changeHeaderColumnVisibility(bool)));
QAction* read = header_context_menu->addAction(QIcon(), tr("Read"));
read->setCheckable(true);
read->setChecked(!ui->threadTreeWidget->isColumnHidden(RsGxsForumModel::COLUMN_THREAD_READ));
read->setData(RsGxsForumModel::COLUMN_THREAD_READ);
connect(read, SIGNAL(toggled(bool)), this, SLOT(changeHeaderColumnVisibility(bool)));
QAction* date = header_context_menu->addAction(QIcon(), tr("Date"));
date->setCheckable(true);
date->setChecked(!ui->threadTreeWidget->isColumnHidden(RsGxsForumModel::COLUMN_THREAD_DATE));
date->setData(RsGxsForumModel::COLUMN_THREAD_DATE);
connect(date, SIGNAL(toggled(bool)), this, SLOT(changeHeaderColumnVisibility(bool)));
QAction* distribution = header_context_menu->addAction(QIcon(), tr("Distribution"));
distribution->setCheckable(true);
distribution->setChecked(!ui->threadTreeWidget->isColumnHidden(RsGxsForumModel::COLUMN_THREAD_DISTRIBUTION));
distribution->setData(RsGxsForumModel::COLUMN_THREAD_DISTRIBUTION);
connect(distribution, SIGNAL(toggled(bool)), this, SLOT(changeHeaderColumnVisibility(bool)));
// QAction* author = header_context_menu->addAction(QIcon(), tr("Author"));
// author->setCheckable(true);
// author->setChecked(!ui->threadTreeWidget->isColumnHidden(RsGxsForumModel::COLUMN_THREAD_AUTHOR));
// author->setData(RsGxsForumModel::COLUMN_THREAD_AUTHOR);
// connect(author, SIGNAL(toggled(bool)), this, SLOT(changeHeaderColumnVisibility(bool)));
QAction* show_text_from_banned = header_context_menu->addAction(QIcon(), tr("Show text from banned persons"));
show_text_from_banned->setCheckable(true);
show_text_from_banned->setChecked(mDisplayBannedText);
connect(show_text_from_banned, SIGNAL(toggled(bool)), this, SLOT(showBannedText(bool)));
header_context_menu->exec(mapToGlobal(pos));
delete(header_context_menu);
}
void GxsForumThreadWidget::changeHeaderColumnVisibility(bool visibility) {
QAction* the_action = qobject_cast<QAction*>(sender());
if ( !the_action ) {
return;
}
ui->threadTreeWidget->setColumnHidden(the_action->data().toInt(), !visibility);
}
void GxsForumThreadWidget::showBannedText(bool display) {
mDisplayBannedText = display;
if (!mThreadId.isNull()) {
updateMessageData(mThreadId);
}
}
#ifdef TODO
bool GxsForumThreadWidget::eventFilter(QObject *obj, QEvent *event)
{
@ -916,6 +1016,9 @@ void GxsForumThreadWidget::updateForumDescription(bool success)
if (!mThreadId.isNull())
return;
// still call it to not left leftovers from previous post if any
blankPost();
RsIdentityDetails details;
rsIdentity->getIdDetails(mForumGroup.mMeta.mAuthorId,details);
@ -1042,6 +1145,7 @@ void GxsForumThreadWidget::insertMessage()
/* blank text, incase we get nothing */
blankPost();
ui->nextUnreadButton->setEnabled(true);
// We use this instead of getCurrentIndex() because right here the currentIndex() is not set yet.
@ -1158,6 +1262,7 @@ void GxsForumThreadWidget::insertMessageData(const RsGxsForumMsg &msg)
bool redacted =
(overall_reputation == RsReputationLevel::LOCALLY_NEGATIVE);
// TODO enabled even when there are no new message
ui->nextUnreadButton->setEnabled(true);
ui->lineLeft->show();
ui->time_label->setText(DateTime::formatLongDateTime(msg.mMeta.mPublishTs));
@ -1167,32 +1272,46 @@ void GxsForumThreadWidget::insertMessageData(const RsGxsForumMsg &msg)
ui->by_label->show();
ui->threadTreeWidget->setFocus();
QString banned_text_info = "";
if(redacted) {
QString extraTxt = tr( "<p><font color=\"#ff0000\"><b>The author of this message (with ID %1) is banned.</b>").arg(QString::fromStdString(msg.mMeta.mAuthorId.toStdString())) ;
extraTxt += tr( "<UL><li><b><font color=\"#ff0000\">Messages from this author are not forwarded. </font></b></li>") ;
extraTxt += tr( "<li><b><font color=\"#ff0000\">Messages from this author are replaced by this text. </font></b></li></ul>") ;
extraTxt += tr( "<p><b><font color=\"#ff0000\">You can force the visibility and forwarding of messages by setting a different opinion for that Id in People's tab.</font></b></p>") ;
ui->downloadButton->setDisabled(true);
if (!mDisplayBannedText) {
QString extraTxt = tr( "<p><font color=\"#ff0000\"><b>The author of this message (with ID %1) is banned.</b>").arg(QString::fromStdString(msg.mMeta.mAuthorId.toStdString())) ;
extraTxt += tr( "<UL><li><b><font color=\"#ff0000\">Messages from this author are not forwarded. </font></b></li>") ;
extraTxt += tr( "<li><b><font color=\"#ff0000\">Messages from this author are replaced by this text. </font></b></li></ul>") ;
extraTxt += tr( "<p><b><font color=\"#ff0000\">You can force the visibility and forwarding of messages by setting a different opinion for that Id in People's tab.</font></b></p>") ;
ui->postText->setHtml(extraTxt) ;
} else {
uint32_t flags = RSHTML_FORMATTEXT_EMBED_LINKS;
if(Settings->getForumLoadEmoticons())
flags |= RSHTML_FORMATTEXT_EMBED_SMILEYS ;
flags |= RSHTML_OPTIMIZEHTML_MASK;
ui->postText->setHtml(extraTxt) ;
return;
}
else {
RsIdentityDetails details;
rsIdentity->getIdDetails(msg.mMeta.mAuthorId, details);
QString name = GxsIdDetails::getName(details);
QColor backgroundColor = ui->postText->palette().base().color();
qreal desiredContrast = Settings->valueFromGroup("Forum",
"MinimumContrast", 4.5).toDouble();
int desiredMinimumFontSize = Settings->valueFromGroup("Forum",
"MinimumFontSize", 10).toInt();
QString extraTxt = RsHtml().formatText(ui->postText->document(),
QString::fromUtf8(msg.mMsg.c_str()), flags
, backgroundColor, desiredContrast, desiredMinimumFontSize
);
ui->postText->setHtml(extraTxt);
banned_text_info += "<p><font color=\"#e00000\"><b>" + tr( "The author of this message (with ID %1) is banned. And named by name ( %2 )").arg(QString::fromStdString(msg.mMeta.mAuthorId.toStdString()), name) + "</b>";
banned_text_info += "<ul><li><b><font color=\"#e00000\">" + tr( "Messages from this author are not forwarded.") + "</font></b></li></ul>";
banned_text_info += "<p><b><font color=\"#e00000\">" + tr( "You can force the visibility and forwarding of messages by setting a different opinion for that Id in People's tab.") + "</font></b></p><hr>";
}
}
uint32_t flags = RSHTML_FORMATTEXT_EMBED_LINKS;
if(Settings->getForumLoadEmoticons())
flags |= RSHTML_FORMATTEXT_EMBED_SMILEYS ;
flags |= RSHTML_OPTIMIZEHTML_MASK;
QColor backgroundColor = ui->postText->palette().base().color();
qreal desiredContrast = Settings->valueFromGroup("Forum",
"MinimumContrast", 4.5).toDouble();
int desiredMinimumFontSize = Settings->valueFromGroup("Forum",
"MinimumFontSize", 10).toInt();
QString extraTxt = banned_text_info + RsHtml().formatText(ui->postText->document(),
QString::fromUtf8(msg.mMsg.c_str()), flags
, backgroundColor, desiredContrast, desiredMinimumFontSize
);
ui->postText->setHtml(extraTxt);
QStringList urls;
RsHtml::findAnchors(ui->postText->toHtml(), urls);
ui->downloadButton->setEnabled(urls.count() > 0);
@ -1340,6 +1459,20 @@ void GxsForumThreadWidget::setAllMessagesReadDo(bool read, uint32_t &/*token*/)
markMsgAsReadUnread(read, true, true);
}
#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
void GxsForumThreadWidget::expandSubtree() {
QAction* the_action = qobject_cast<QAction*>(sender());
if (!the_action) {
return;
}
const QModelIndex current_index = ui->threadTreeWidget->currentIndex();
if (!current_index.isValid()) {
return;
}
ui->threadTreeWidget->expandRecursively(current_index);
}
#endif
bool GxsForumThreadWidget::navigate(const RsGxsMessageId &msgId)
{
QModelIndex source_index = mThreadModel->getIndexOfMessage(msgId);
@ -1683,10 +1816,26 @@ void GxsForumThreadWidget::filterItems(const QString& text)
// We do this in order to trigger a new filtering action in the proxy model.
mThreadProxyModel->setFilterRegExp(QRegExp(QString(RsGxsForumModel::FilterString))) ;
if(!lst.empty())
if(!lst.empty())
ui->threadTreeWidget->expandAll();
else
else {
// currentIndex() not on the clicked message, so not this way
// if (!mThreadId.isNull()) {
// an_index = mThreadProxyModel->mapToSource(ui->threadTreeWidget->currentIndex());
// }
ui->threadTreeWidget->collapseAll();
if (!mThreadId.isNull()) {
// ...but this one
QModelIndex an_index = mThreadModel->getIndexOfMessage(mThreadId);
if (an_index.isValid()) {
QModelIndex the_index = mThreadProxyModel->mapFromSource(an_index);
ui->threadTreeWidget->setCurrentIndex(the_index);
ui->threadTreeWidget->scrollTo(the_index);
// don't change focus
// ui->threadTreeWidget->setFocus();
}
}
}
if(count > 0)
ui->filterLineEdit->setToolTip(tr("No result.")) ;

View File

@ -52,6 +52,10 @@ class GxsForumThreadWidget : public GxsMessageFrameWidget
Q_PROPERTY(QColor textColorUnreadChildren READ textColorUnreadChildren WRITE setTextColorUnreadChildren)
Q_PROPERTY(QColor textColorNotSubscribed READ textColorNotSubscribed WRITE setTextColorNotSubscribed)
Q_PROPERTY(QColor textColorMissing READ textColorMissing WRITE setTextColorMissing)
Q_PROPERTY(QColor textColorPinned READ textColorPinned WRITE setTextColorPinned)
Q_PROPERTY(QColor backgroundColorPinned READ backgroundColorPinned WRITE setBackgroundColorPinned)
Q_PROPERTY(QColor backgroundColorFiltered READ backgroundColorFiltered WRITE setBackgroundColorFiltered)
public:
explicit GxsForumThreadWidget(const RsGxsGroupId &forumId, QWidget *parent = NULL);
@ -62,12 +66,20 @@ public:
QColor textColorUnreadChildren() const { return mTextColorUnreadChildren; }
QColor textColorNotSubscribed() const { return mTextColorNotSubscribed; }
QColor textColorMissing() const { return mTextColorMissing; }
QColor textColorPinned() const { return mTextColorPinned; }
QColor backgroundColorPinned() const { return mBackgroundColorPinned; }
QColor backgroundColorFiltered() const { return mBackgroundColorFiltered; }
void setTextColorRead (QColor color) ;
void setTextColorUnread (QColor color) ;
void setTextColorUnreadChildren(QColor color) ;
void setTextColorNotSubscribed (QColor color) ;
void setTextColorMissing (QColor color) ;
void setTextColorPinned (QColor color) ;
void setBackgroundColorPinned (QColor color);
void setBackgroundColorFiltered (QColor color);
/* GxsMessageFrameWidget */
virtual void groupIdChanged();
@ -97,6 +109,7 @@ private slots:
/** Create the context popup menu and it's submenus */
void threadListCustomPopupMenu(QPoint point);
void contextMenuTextBrowser(QPoint point);
void headerContextMenuRequested(const QPoint& pos);
void changedSelection(const QModelIndex &, const QModelIndex &);
void changedThread(QModelIndex index);
@ -144,6 +157,12 @@ private slots:
void filterColumnChanged(int column);
void filterItems(const QString &text);
#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
void expandSubtree();
#endif
void changeHeaderColumnVisibility(bool visibility);
void showBannedText(bool display);
private:
void insertMessageData(const RsGxsForumMsg &msg);
bool getCurrentPost(ForumModelPostEntry& fmpe) const ;
@ -192,6 +211,7 @@ private:
GxsForumsFillThread *mFillThread;
unsigned int mUnreadCount;
unsigned int mNewCount;
bool mDisplayBannedText;
/* Color definitions (for standard see qss.default) */
QColor mTextColorRead;
@ -199,6 +219,10 @@ private:
QColor mTextColorUnreadChildren;
QColor mTextColorNotSubscribed;
QColor mTextColorMissing;
QColor mTextColorPinned;
QColor mBackgroundColorPinned;
QColor mBackgroundColorFiltered;
RsGxsMessageId mNavigatePendingMsgId;
QList<RsGxsMessageId> mIgnoredMsgId;

View File

@ -1,6 +1,7 @@
<RCC>
<qresource prefix="/">
<file>icons/onion.png</file>
<file>icons/svg/design.svg</file>
<file>icons/svg/hidden.svg</file>
<file>icons/svg/ratio-auto.svg</file>
<file>icons/svg/ratio-1-1.svg</file>

View File

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<path style="fill:#8B8992;" d="M299.493,502h-90v-86h90V502z M239.493,482h30v-36h-30L239.493,482L239.493,482z"/>
<polygon style="fill:#57555C;" points="255.993,446 269.493,446 269.493,482 255.993,482 255.993,502 299.493,502 299.493,416
255.993,416 "/>
<path style="fill:#9BC9FF;" d="M480.493,376h-449V136h449V376z"/>
<rect x="255.99" y="136" style="fill:#009AE5;" width="224.5" height="240"/>
<rect x="179.49" y="482" style="fill:#005ECE;" width="150" height="30"/>
<path style="fill:#B87FD9;" d="M239.493,376h-90V171h90V376z"/>
<path style="fill:#8034AD;" d="M239.493,376h-45V171h45V376z"/>
<path style="fill:#8B8992;" d="M289.686,131H98.301L59.39,0h57.243c20.439,0,44.228,7.314,62.86,20.502V0h149.103L289.686,131z"/>
<polygon style="fill:#57555C;" points="328.596,0 193.993,0 193.993,131 289.686,131 "/>
<path style="fill:#E3CEF0;" d="M248.493,201h-108c-24.813,0-45-20.187-45-45v-55h198v55C293.493,180.813,273.306,201,248.493,201z"
/>
<path style="fill:#D5B4E8;" d="M194.493,101v100h54c24.813,0,45-20.187,45-45v-55H194.493z"/>
<path style="fill:#E0E0E2;" d="M427.705,118.346c-9.131,0-18.141-2.394-26.261-7.082c-12.189-7.038-20.909-18.401-24.551-31.997
c-3.643-13.595-1.774-27.795,5.264-39.984s18.401-20.908,31.997-24.551l50.898-13.638l13.637,50.898
c3.643,13.595,1.774,27.795-5.264,39.984s-18.4,20.909-31.996,24.551C436.89,117.744,432.281,118.346,427.705,118.346z"/>
<path style="fill:#ACABB1;" d="M478.688,51.992L465.051,1.094h-0.001l-63.606,110.169l0,0c8.12,4.688,17.13,7.083,26.261,7.082
c4.577,0,9.185-0.602,13.724-1.818c13.595-3.643,24.958-12.362,31.996-24.551C480.462,79.787,482.331,65.587,478.688,51.992z"/>
<path style="fill:#FFE477;" d="M280.915,410.025l-77.942-45l125-216.506l77.942,45L280.915,410.025z"/>
<rect x="301.424" y="165.518" transform="matrix(-0.866 -0.5 0.5 -0.866 459.1859 704.0723)" style="fill:#FFA733;" width="44.999" height="249.995"/>
<path style="fill:#FF9A00;" d="M402.462,226.167l-101.036-58.333l87.069-98.688l55.898,32.273L402.462,226.167z"/>
<polygon style="fill:#E67500;" points="444.393,101.419 416.444,85.283 351.944,197 402.462,226.167 "/>
<path style="fill:#005ECE;" d="M480.493,446h-449V346h449V446z"/>
<g>
<rect x="255.99" y="346" style="fill:#003F8A;" width="224.5" height="100"/>
<rect x="254.49" y="482" style="fill:#003F8A;" width="75" height="30"/>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -17,7 +17,6 @@
<file>images/inbox_22.png</file>
<file>images/blue_lock.png</file>
<file>images/blue_lock_open.png</file>
<file>images/edit_24.png</file>
<file>images/streaming.png</file>
<file>images/white-bubble-64.png</file>
<file>images/orange-bubble-64.png</file>
@ -49,7 +48,6 @@
<file>images/dht16.png</file>
<file>images/dht32.png</file>
<file>images/edit-clear-history.png</file>
<file>images/edit_16.png</file>
<file>images/feedback_arrow.png</file>
<file>images/feedback_arrow_hover.png</file>
<file>images/firewall_24.png</file>
@ -79,11 +77,7 @@
<file>images/avatarstatus-bg-away-70.png</file>
<file>images/avatarstatus-bg-busy-70.png</file>
<file>images/avatarstatus-bg-offline-70.png</file>
<file>images/configure.png</file>
<file>images/copyrslink.png</file>
<file>images/contacts24.png</file>
<file>images/contactsclosed24.png</file>
<file>images/connection.png</file>
<file>images/Client0.png</file>
<file>images/Client1.png</file>
<file>images/Client2.png</file>
@ -102,7 +96,6 @@
<file>images/FileTypePicture.png</file>
<file>images/FileTypeProgram.png</file>
<file>images/FileTypeVideo.png</file>
<file>images/fonts.png</file>
<file>images/foldermail.png</file>
<file>images/folderopen.png</file>
<file>images/fileopen.png</file>
@ -111,14 +104,11 @@
<file>images/graph-notdownload.png</file>
<file>images/graph-checking.png</file>
<file>images/graph-blue.png</file>
<file>images/add-share24.png</file>
<file>images/avatar_background.png</file>
<file>images/button_cancel.png</file>
<file>images/chat.png</file>
<file>images/chat_24.png</file>
<file>images/cancel.png</file>
<file>images/close-down.png</file>
<file>images/close_normal.png</file>
<file>images/copy.png</file>
<file>images/delete.png</file>
<file>images/deleteall.png</file>
@ -128,13 +118,8 @@
<file>images/diskSave.png</file>
<file>images/document_save.png</file>
<file>images/down.png</file>
<file>images/down_24x24.png</file>
<file>images/download.png</file>
<file>images/download16.png</file>
<file>images/edit_add24.png</file>
<file>images/edit-bold.png</file>
<file>images/edit-italic.png</file>
<file>images/edit-underline.png</file>
<file>images/edit_remove24.png</file>
<file>images/disabled_plugin_48.png</file>
<file>images/expand_frame.png</file>
@ -224,7 +209,6 @@
<file>images/ledoff1.png</file>
<file>images/ledon1.png</file>
<file>images/locale.png</file>
<file>images/looknfeel.png</file>
<file>images/logo/logo_16.png</file>
<file>images/logo/logo_24.png</file>
<file>images/logo/logo_24_0.png</file>
@ -260,7 +244,6 @@
<file>images/mute-off-16.png</file>
<file>images/mute-on-16.png</file>
<file>images/new-mail-alert.png</file>
<file>images/newmsg.png</file>
<file>images/no_avatar_70.png</file>
<file>images/no_avatar_background.png</file>
<file>images/openimage.png</file>
@ -269,7 +252,6 @@
<file>images/pasterslink.png</file>
<file>images/package_games1.png</file>
<file>images/pin32.png</file>
<file>images/print24.png</file>
<file>images/priorityauto.png</file>
<file>images/priorityhigh.png</file>
<file>images/prioritylow.png</file>
@ -278,17 +260,10 @@
<file>images/preview.png</file>
<file>images/player_play.png</file>
<file>images/quick_restart24.png</file>
<file>images/quote_24.png</file>
<file>images/redled.png</file>
<file>images/greenled.png</file>
<file>images/grayled.png</file>
<file>images/yellowled.png</file>
<file>images/rate-1.png</file>
<file>images/rate-2.png</file>
<file>images/rate-3.png</file>
<file>images/rate-4.png</file>
<file>images/rate-5.png</file>
<file>images/rating.png</file>
<file>images/records.png</file>
<file>images/replymail-pressed.png</file>
<file>images/replymail24.png</file>
@ -320,7 +295,6 @@
<file>images/tab-dock.png</file>
<file>images/tab-undock.png</file>
<file>images/tab-new.png</file>
<file>images/tag24.png</file>
<file>images/transferupdown.png</file>
<file>images/tools_wizard.png</file>
<file>images/uploads.png</file>
@ -384,8 +358,6 @@
<file>images/view_calendar_month.png</file>
<file>images/view_calendar_list.png</file>
<file>images/view_split_top_bottom.png</file>
<file>images/window_fullscreen.png</file>
<file>images/window_nofullscreen.png</file>
<file>qss/chat/standard/private/info.xml</file>
<file>qss/chat/standard/private/incoming.htm</file>
<file>qss/chat/standard/private/outgoing.htm</file>
@ -454,8 +426,6 @@
<file>images/share-icon-16.png</file>
<file>images/toasterEnable.png</file>
<file>images/toasterDisable.png</file>
<file>images/view-feeds.png</file>
<file>images/view-files.png</file>
<file>images/emblem-web.png</file>
<file>images/rsmessenger48.png</file>
<file>images/SmileyText.png</file>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 876 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 578 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 823 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 343 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 307 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 320 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 613 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 826 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 621 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 742 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 388 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 334 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 623 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 647 B

View File

@ -127,8 +127,8 @@
<string>Display</string>
</property>
<property name="icon">
<iconset resource="../images.qrc">
<normaloff>:/images/looknfeel.png</normaloff>:/images/looknfeel.png</iconset>
<iconset resource="../icons.qrc">
<normaloff>:/icons/svg/design.svg</normaloff>:/icons/svg/design.svg</iconset>
</property>
<property name="iconSize">
<size>

View File

@ -138,6 +138,10 @@ ForumsDialog, GxsForumThreadWidget
qproperty-textColorUnreadChildren: darkgray;
qproperty-textColorNotSubscribed: black;
qproperty-textColorMissing: darkRed;
qproperty-textColorPinned: darkOrange;
qproperty-backgroundColorPinned: rgb(255, 200, 180);
qproperty-backgroundColorFiltered: rgb(255, 240, 210);
}
GroupTreeWidget

View File

@ -35,6 +35,8 @@
#include <retroshare/rsstatus.h>
#include <retroshare/rspeers.h>
#include <retroshare/rsservicecontrol.h>
#include "rsitems/rsserviceids.h"
#include <QTextDocument>
#define NOT_IMPLEMENTED std::cerr << __PRETTY_FUNCTION__ << ": not yet implemented." << std::endl;
@ -531,6 +533,45 @@ void RSPermissionMatrixWidget::paintEvent(QPaintEvent *)
_max_height = S*fMATRIX_START_Y + (peer_ids.size()+3) * S*fROW_SIZE ;
_max_width = matrix_start_x + (service_ids.size()+3) * S*fCOL_SIZE ;
if(n_row_selected == -1)
{
for(uint32_t i=0;i<service_ids.size();++i)
{
if(_current_service_id == service_ids[i])
{
//uint16_t serviceOrig = (uint16_t)((service_ids[i] - (((uint32_t)RS_PKT_VERSION_SERVICE) << 24) ) >> 8);
uint16_t serviceOrig=(service_ids[i]>>8) & 0xffff;
QTextDocument td;
td.setHtml(ServiceDescription(serviceOrig));
QString service_name = "Service: 0x"+ QString::number(serviceOrig,16) + " " + QString::fromStdString(rsServiceControl->getServiceName(service_ids[i]));
QBrush brush ;
brush.setColor(QColor::fromHsvF(0.0f,0.0f,1.0f,0.8f));
brush.setStyle(Qt::SolidPattern) ;
QPen pen ;
pen.setWidth(1) ;
pen.setBrush(FOREGROUND_COLOR) ;
_painter->setPen(pen) ;
QRect position = computeNodePosition(0,i,false) ;
int popup_x = position.x() + (50 * S / 14.0);
int popup_y = position.y() - (10 * S / 14.0) + line_height;
int popup_width = std::max((int)td.size().width(), fm.width(service_name)) + S;
int popup_height = td.size().height() + line_height*2;
while (popup_x + popup_width > _max_width)
popup_x -= S;
if (popup_y + popup_height > _max_height)
popup_y -= popup_height;
QRect info_pos(popup_x, popup_y, popup_width, popup_height) ;
_painter->fillRect(info_pos,brush) ;
_painter->drawRect(info_pos) ;
float x = info_pos.x() + 5*S/14.0 ;
float y = info_pos.y() + line_height + 1*S/14.0 ;
_painter->drawText(QPointF(x,y), service_name) ; y += line_height ;
_painter->translate(QPointF(popup_x, popup_y+2*line_height));
td.drawContents(_painter);
}
}
}
/* Stop the painter */
_painter->end();
}
@ -611,4 +652,33 @@ void RSPermissionMatrixWidget::userPermissionSwitched(uint32_t /* ServiceId */,c
NOT_IMPLEMENTED ;
}
QString RSPermissionMatrixWidget::ServiceDescription(uint16_t serviceid)
{
switch(serviceid)
{
case RS_SERVICE_TYPE_DISC: return tr("Location info exchange between friends. Helps to find actual address in case of dynamic IPs<br>Without it you will have to rely on DHT only for getting fresh addresses");
case RS_SERVICE_TYPE_CHAT: return tr("Used by direct F2F chat, distant chat and chat lobbies");
case RS_SERVICE_TYPE_MSG: return tr("Mailing service. Also required for direct f2f chat");
case RS_SERVICE_TYPE_TURTLE: return tr("Anonymous routing. Used by file transfers and file search,<br> distant chat, distant mail and distant channels/etc sync");
case RS_SERVICE_TYPE_HEARTBEAT: return tr("Checks if peers alive");
case RS_SERVICE_TYPE_FILE_TRANSFER: return tr("File transfer. If you kill it - you won't be able to dl files from friend shares. Anonymous access unnaffected");
case RS_SERVICE_TYPE_GROUTER: return tr("Used by distant mail for immediate delivery using anonymous tunnels (turtle router)");
case RS_SERVICE_TYPE_FILE_DATABASE: return tr("Exchange shared directories info, aka browsable(visible) files");
case RS_SERVICE_TYPE_SERVICEINFO: return tr("Allows your node to tell to your friends which service are ON on your side, and vice-versa");
case RS_SERVICE_TYPE_BWCTRL: return tr("Speed management");
case RS_SERVICE_TYPE_GXS_TUNNEL: return tr("Used by distant chat, distant mail, and distant channels sync for transfer data using anonymous tunnels");
case RS_SERVICE_TYPE_BANLIST: return tr("IP filter lists exchange");
case RS_SERVICE_TYPE_STATUS: return tr("Share user status like online, away, busy with friends");
case RS_SERVICE_GXS_TYPE_GXSID: return tr("Identity data exchange. Required by all identities-related functions like chats, forums, mail, etc");
case RS_SERVICE_GXS_TYPE_PHOTO: return tr("RS_SERVICE_GXS_TYPE_PHOTO");
case RS_SERVICE_GXS_TYPE_WIKI: return tr("RS_SERVICE_GXS_TYPE_WIKI");
case RS_SERVICE_GXS_TYPE_FORUMS: return tr("Transfer Forums");
case RS_SERVICE_GXS_TYPE_POSTED: return tr("Transfer Posted");
case RS_SERVICE_GXS_TYPE_CHANNELS: return tr("Transfer Channels");
case RS_SERVICE_GXS_TYPE_GXSCIRCLE: return tr("Transfer Circles");
case RS_SERVICE_GXS_TYPE_REPUTATION:return tr("Votes exchange - bans/upvotes for Identities");
case RS_SERVICE_TYPE_GXS_TRANS: return tr("Used by distant mail for deferred delivery - stored at friends when target offline");
case RS_SERVICE_TYPE_RTT: return tr("Measures the Round Trip Time between you and your friends");
default: return tr("unknown");
}
}

View File

@ -59,6 +59,7 @@ class RSPermissionMatrixWidget: public QFrame
public:
RSPermissionMatrixWidget(QWidget *parent=NULL);
virtual ~RSPermissionMatrixWidget() ;
QString ServiceDescription(uint16_t serviceid);
public slots:
void setHideOffline(bool hide);

View File

@ -49,7 +49,6 @@
/* Images for toolbar icons */
#define IMAGE_RETROSHARE ":/images/RetroShare16.png"
#define IMAGE_ABOUT ":/images/informations_24x24.png"
#define IMAGE_CLOSE ":/images/close_normal.png"
#define IMAGE_LIBRARY ":/icons/collections.png"
#define IMAGE_PLUGINS ":/images/extension_32.png"
#define IMAGE_WIKI ":/images/wikibook_32.png"

View File

@ -42,7 +42,6 @@
#include <QLabel>
/* Images for context menu icons */
#define IMAGE_DOWNLOAD ":/images/download16.png"
#define IMAGE_PLAY ":/images/start.png"
#define IMAGE_HASH_BUSY ":/images/settings.png"
#define IMAGE_MSG ":/images/message-mail.png"

View File

@ -181,7 +181,6 @@ void PhotoDialog::photoTreeWidgetCustomPopupMenu( QPoint point )
connect(rateUnratedAct, SIGNAL(triggered()), this, SLOT(rateUnrated()));
QMenu *ratingMenu = new QMenu(tr("Rating"), this);
ratingMenu->setIcon(QIcon(":/images/rating.png"));
ratingMenu->addAction(rateExcellenAct);
ratingMenu->addAction(rateGoodAct);
ratingMenu->addAction(rateAverageAct);

View File

@ -93,6 +93,10 @@ ForumsDialog, GxsForumThreadWidget
qproperty-textColorUnreadChildren: red;
qproperty-textColorNotSubscribed: white;
qproperty-textColorMissing: darkred;
qproperty-textColorPinned: #D07000;
qproperty-backgroundColorPinned: #202020;
qproperty-backgroundColorFiltered: darkGreen;
}
QMenuBar

View File

@ -1356,11 +1356,9 @@ gxschannels {
HEADERS += gui/gxschannels/GxsChannelDialog.h \
gui/gxschannels/GxsChannelGroupDialog.h \
gui/gxschannels/CreateGxsChannelMsg.h \
gui/gxschannels/GxsChannelPostsWidget.h \
gui/gxschannels/GxsChannelPostsWidgetWithModel.h \
gui/gxschannels/GxsChannelPostsModel.h \
gui/gxschannels/GxsChannelPostFilesModel.h \
gui/gxschannels/GxsChannelFilesWidget.h \
gui/gxschannels/GxsChannelPostThumbnail.h \
gui/gxschannels/GxsChannelFilesStatusWidget.h \
gui/feeds/GxsChannelGroupItem.h \
@ -1369,19 +1367,15 @@ gxschannels {
FORMS += \
gui/gxschannels/GxsChannelPostsWidgetWithModel.ui \
gui/gxschannels/GxsChannelPostsWidget.ui \
gui/gxschannels/GxsChannelFilesWidget.ui \
gui/gxschannels/GxsChannelFilesStatusWidget.ui \
gui/gxschannels/CreateGxsChannelMsg.ui \
gui/feeds/GxsChannelGroupItem.ui \
gui/feeds/GxsChannelPostItem.ui
SOURCES += gui/gxschannels/GxsChannelDialog.cpp \
gui/gxschannels/GxsChannelPostsWidget.cpp \
gui/gxschannels/GxsChannelPostsWidgetWithModel.cpp \
gui/gxschannels/GxsChannelPostsModel.cpp \
gui/gxschannels/GxsChannelPostFilesModel.cpp \
gui/gxschannels/GxsChannelFilesWidget.cpp \
gui/gxschannels/GxsChannelPostThumbnail.cpp \
gui/gxschannels/GxsChannelFilesStatusWidget.cpp \
gui/gxschannels/GxsChannelGroupDialog.cpp \