merged with upstream/master

This commit is contained in:
mr-alice 2016-09-01 19:52:31 +02:00
commit ade6017f74
469 changed files with 88476 additions and 59565 deletions

View file

@ -116,9 +116,7 @@ FriendList::FriendList(QWidget *parent) :
mShowGroups(true),
mShowState(false),
mHideUnconnected(false),
groupsHasChanged(false),
openGroups(NULL),
openPeers(NULL)
groupsHasChanged(false)
{
ui->setupUi(this);
@ -142,7 +140,7 @@ FriendList::FriendList(QWidget *parent) :
mActionSortByState = new QAction(tr("Sort by state"), this);
mActionSortByState->setCheckable(true);
connect(mActionSortByState, SIGNAL(toggled(bool)), this, SLOT(sortByState(bool)));
ui->peerTreeWidget->addHeaderContextMenuAction(mActionSortByState);
ui->peerTreeWidget->addContextMenuAction(mActionSortByState);
/* Set sort */
sortByColumn(COLUMN_NAME, Qt::AscendingOrder);
@ -189,8 +187,9 @@ void FriendList::addToolButton(QToolButton *toolButton)
/* Initialize button */
toolButton->setAutoRaise(true);
toolButton->setIconSize(ui->displayButton->iconSize());
toolButton->setFocusPolicy(ui->displayButton->focusPolicy());
float S = QFontMetricsF(ui->filterLineEdit->font()).height() ;
toolButton->setIconSize(QSize(S*1.5,S*1.5));
toolButton->setFocusPolicy(Qt::NoFocus);
ui->titleBarFrame->layout()->addWidget(toolButton);
}
@ -219,7 +218,17 @@ void FriendList::processSettings(bool load)
int arrayIndex = Settings->beginReadArray("Groups");
for (int index = 0; index < arrayIndex; ++index) {
Settings->setArrayIndex(index);
addGroupToExpand(Settings->value("open").toString().toStdString());
std::string gids = Settings->value("open").toString().toStdString();
RsGroupInfo ginfo ;
if(rsPeers->getGroupInfoByName(gids,ginfo)) // backward compatibility
addGroupToExpand(ginfo.id) ;
else if(rsPeers->getGroupInfo(RsNodeGroupId(gids),ginfo)) // backward compatibility
addGroupToExpand(ginfo.id) ;
else
std::cerr << "(EE) Cannot find group info for openned group \"" << gids << "\"" << std::endl;
}
Settings->endArray();
} else {
@ -236,11 +245,11 @@ void FriendList::processSettings(bool load)
// open groups
Settings->beginWriteArray("Groups");
int arrayIndex = 0;
std::set<std::string> expandedPeers;
std::set<RsNodeGroupId> expandedPeers;
getExpandedGroups(expandedPeers);
foreach (std::string groupId, expandedPeers) {
foreach (RsNodeGroupId groupId, expandedPeers) {
Settings->setArrayIndex(arrayIndex++);
Settings->setValue("open", QString::fromStdString(groupId));
Settings->setValue("open", QString::fromStdString(groupId.toStdString()));
}
Settings->endArray();
}
@ -273,9 +282,9 @@ void FriendList::peerTreeWidgetCustomPopupMenu()
{
QTreeWidgetItem *c = getCurrentPeer();
QMenu contextMnu(this);
QMenu *contextMenu = new QMenu(this);
QWidget *widget = new QWidget(&contextMnu);
QWidget *widget = new QWidget(contextMenu);
widget->setStyleSheet( ".QWidget{background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 #FEFEFE, stop:1 #E8E8E8); border: 1px solid #CCCCCC;}");
// create menu header
@ -284,8 +293,9 @@ void FriendList::peerTreeWidgetCustomPopupMenu()
hbox->setSpacing(6);
QLabel *iconLabel = new QLabel(widget);
iconLabel->setPixmap(QPixmap(":/images/user/friends24.png"));
iconLabel->setMaximumSize(iconLabel->frameSize().height() + 24, 24);
QPixmap pix = QPixmap(":/images/user/friends24.png").scaledToHeight(QFontMetricsF(iconLabel->font()).height()*1.5);
iconLabel->setPixmap(pix);
iconLabel->setMaximumSize(iconLabel->frameSize().height() + pix.height(), pix.width());
hbox->addWidget(iconLabel);
QLabel *textLabel = new QLabel("<strong>RetroShare</strong>", widget);
@ -298,7 +308,7 @@ void FriendList::peerTreeWidgetCustomPopupMenu()
QWidgetAction *widgetAction = new QWidgetAction(this);
widgetAction->setDefaultWidget(widget);
contextMnu.addAction(widgetAction);
contextMenu->addAction(widgetAction);
// create menu entries
if (c)
@ -328,23 +338,23 @@ void FriendList::peerTreeWidgetCustomPopupMenu()
{
bool standard = c->data(COLUMN_DATA, ROLE_STANDARD).toBool();
contextMnu.addAction(QIcon(IMAGE_MSG), tr("Send message to whole group"), this, SLOT(msgfriend()));
contextMnu.addSeparator();
contextMnu.addAction(QIcon(IMAGE_EDIT), tr("Edit Group"), this, SLOT(editGroup()));
contextMenu->addAction(QIcon(IMAGE_MSG), tr("Send message to whole group"), this, SLOT(msgfriend()));
contextMenu->addSeparator();
contextMenu->addAction(QIcon(IMAGE_EDIT), tr("Edit Group"), this, SLOT(editGroup()));
QAction *action = contextMnu.addAction(QIcon(IMAGE_REMOVE), tr("Remove Group"), this, SLOT(removeGroup()));
QAction *action = contextMenu->addAction(QIcon(IMAGE_REMOVE), tr("Remove Group"), this, SLOT(removeGroup()));
action->setDisabled(standard);
}
break;
case TYPE_GPG:
{
contextMnu.addAction(QIcon(IMAGE_CHAT), tr("Chat"), this, SLOT(chatfriendproxy()));
contextMnu.addAction(QIcon(IMAGE_MSG), tr("Send message"), this, SLOT(msgfriend()));
contextMenu->addAction(QIcon(IMAGE_CHAT), tr("Chat"), this, SLOT(chatfriendproxy()));
contextMenu->addAction(QIcon(IMAGE_MSG), tr("Send message"), this, SLOT(msgfriend()));
contextMnu.addSeparator();
contextMenu->addSeparator();
contextMnu.addAction(QIcon(IMAGE_FRIENDINFO), tr("Details"), this, SLOT(configurefriend()));
contextMnu.addAction(QIcon(IMAGE_DENYFRIEND), tr("Deny"), this, SLOT(removefriend()));
contextMenu->addAction(QIcon(IMAGE_FRIENDINFO), tr("Details"), this, SLOT(configurefriend()));
contextMenu->addAction(QIcon(IMAGE_DENYFRIEND), tr("Deny"), this, SLOT(removefriend()));
if(mShowGroups)
{
@ -366,19 +376,19 @@ void FriendList::peerTreeWidgetCustomPopupMenu()
if (std::find(groupIt->peerIds.begin(), groupIt->peerIds.end(), gpgId) == groupIt->peerIds.end()) {
if (parent) {
if (addToGroupMenu == NULL) {
addToGroupMenu = new QMenu(tr("Add to group"), &contextMnu);
addToGroupMenu = new QMenu(tr("Add to group"), contextMenu);
}
QAction* addToGroupAction = new QAction(GroupDefs::name(*groupIt), addToGroupMenu);
addToGroupAction->setData(QString::fromStdString(groupIt->id));
addToGroupAction->setData(QString::fromStdString(groupIt->id.toStdString()));
connect(addToGroupAction, SIGNAL(triggered()), this, SLOT(addToGroup()));
addToGroupMenu->addAction(addToGroupAction);
}
if (moveToGroupMenu == NULL) {
moveToGroupMenu = new QMenu(tr("Move to group"), &contextMnu);
moveToGroupMenu = new QMenu(tr("Move to group"), contextMenu);
}
QAction* moveToGroupAction = new QAction(GroupDefs::name(*groupIt), moveToGroupMenu);
moveToGroupAction->setData(QString::fromStdString(groupIt->id));
moveToGroupAction->setData(QString::fromStdString(groupIt->id.toStdString()));
connect(moveToGroupAction, SIGNAL(triggered()), this, SLOT(moveToGroup()));
moveToGroupMenu->addAction(moveToGroupAction);
} else {
@ -386,7 +396,7 @@ void FriendList::peerTreeWidgetCustomPopupMenu()
}
}
QMenu *groupsMenu = contextMnu.addMenu(QIcon(IMAGE_GROUP16), tr("Groups"));
QMenu *groupsMenu = contextMenu->addMenu(QIcon(IMAGE_GROUP16), tr("Groups"));
groupsMenu->addAction(QIcon(IMAGE_EXPAND), tr("Create new group"), this, SLOT(createNewGroup()));
if (addToGroupMenu || moveToGroupMenu || foundGroup) {
@ -418,45 +428,48 @@ void FriendList::peerTreeWidgetCustomPopupMenu()
case TYPE_SSL:
{
contextMnu.addAction(QIcon(IMAGE_CHAT), tr("Chat"), this, SLOT(chatfriendproxy()));
contextMnu.addAction(QIcon(IMAGE_MSG), tr("Send message"), this, SLOT(msgfriend()));
contextMenu->addAction(QIcon(IMAGE_CHAT), tr("Chat"), this, SLOT(chatfriendproxy()));
contextMenu->addAction(QIcon(IMAGE_MSG), tr("Send message"), this, SLOT(msgfriend()));
contextMnu.addSeparator();
contextMenu->addSeparator();
contextMnu.addAction(QIcon(IMAGE_FRIENDINFO), tr("Details"), this, SLOT(configurefriend()));
contextMenu->addAction(QIcon(IMAGE_FRIENDINFO), tr("Details"), this, SLOT(configurefriend()));
if (type == TYPE_GPG || type == TYPE_SSL) {
contextMnu.addAction(QIcon(IMAGE_EXPORTFRIEND), tr("Recommend this Friend to..."), this, SLOT(recommendfriend()));
contextMenu->addAction(QIcon(IMAGE_EXPORTFRIEND), tr("Recommend this Friend to..."), this, SLOT(recommendfriend()));
}
contextMnu.addAction(QIcon(IMAGE_CONNECT), tr("Attempt to connect"), this, SLOT(connectfriend()));
contextMenu->addAction(QIcon(IMAGE_CONNECT), tr("Attempt to connect"), this, SLOT(connectfriend()));
contextMnu.addAction(QIcon(IMAGE_COPYLINK), tr("Copy certificate link"), this, SLOT(copyFullCertificate()));
contextMenu->addAction(QIcon(IMAGE_COPYLINK), tr("Copy certificate link"), this, SLOT(copyFullCertificate()));
//this is a SSL key
contextMnu.addAction(QIcon(IMAGE_REMOVEFRIEND), tr("Remove Friend Node"), this, SLOT(removefriend()));
//this is a SSL key
contextMenu->addAction(QIcon(IMAGE_REMOVEFRIEND), tr("Remove Friend Node"), this, SLOT(removefriend()));
}
}
}
contextMnu.addSeparator();
contextMenu->addSeparator();
QAction *action = contextMnu.addAction(QIcon(IMAGE_PASTELINK), tr("Paste certificate link"), this, SLOT(pastePerson()));
if (RSLinkClipboard::empty(RetroShareLink::TYPE_CERTIFICATE))
action->setDisabled(true);
QAction *action = contextMenu->addAction(QIcon(IMAGE_PASTELINK), tr("Paste certificate link"), this, SLOT(pastePerson()));
if (RSLinkClipboard::empty(RetroShareLink::TYPE_CERTIFICATE))
action->setDisabled(true);
contextMnu.addAction(QIcon(IMAGE_EXPAND), tr("Expand all"), ui->peerTreeWidget, SLOT(expandAll()));
contextMnu.addAction(QIcon(IMAGE_COLLAPSE), tr("Collapse all"), ui->peerTreeWidget, SLOT(collapseAll()));
contextMenu->addAction(QIcon(IMAGE_EXPAND), tr("Expand all"), ui->peerTreeWidget, SLOT(expandAll()));
contextMenu->addAction(QIcon(IMAGE_COLLAPSE), tr("Collapse all"), ui->peerTreeWidget, SLOT(collapseAll()));
contextMnu.exec(QCursor::pos());
contextMenu = ui->peerTreeWidget->createStandardContextMenu(contextMenu);
contextMenu->exec(QCursor::pos());
delete contextMenu;
}
void FriendList::createNewGroup()
{
CreateGroup createGrpDialog ("", this);
CreateGroup createGrpDialog (RsNodeGroupId(), this);
createGrpDialog.exec();
}
@ -596,7 +609,7 @@ void FriendList::insertPeers()
if (mShowGroups && groupsHasChanged) {
if (parent) {
if (parent->type() == TYPE_GROUP) {
std::string groupId = getRsId(parent);
RsNodeGroupId groupId(getRsId(parent));
// the parent is a group, check if the gpg id is assigned to the group
for (groupIt = groupInfoList.begin(); groupIt != groupInfoList.end(); ++groupIt) {
@ -630,7 +643,7 @@ void FriendList::insertPeers()
}
} else if (groupsHasChanged) {
// remove deleted groups
std::string groupId = getRsId(item);
RsNodeGroupId groupId ( getRsId(item));
for (groupIt = groupInfoList.begin(); groupIt != groupInfoList.end(); ++groupIt) {
if (groupIt->id == groupId) {
break;
@ -671,7 +684,7 @@ void FriendList::insertPeers()
int itemCount = peerTreeWidget->topLevelItemCount();
for (int index = 0; index < itemCount; ++index) {
QTreeWidgetItem *groupItemLoop = peerTreeWidget->topLevelItem(index);
if (groupItemLoop->type() == TYPE_GROUP && getRsId(groupItemLoop) == groupInfo->id) {
if (groupItemLoop->type() == TYPE_GROUP && RsNodeGroupId(getRsId(groupItemLoop)) == groupInfo->id) {
groupItem = groupItemLoop;
break;
}
@ -690,7 +703,7 @@ void FriendList::insertPeers()
groupItem->setForeground(COLUMN_NAME, QBrush(textColorGroup()));
/* used to find back the item */
groupItem->setData(COLUMN_DATA, ROLE_ID, QString::fromStdString(groupInfo->id));
groupItem->setData(COLUMN_DATA, ROLE_ID, QString::fromStdString(groupInfo->id.toStdString()));
groupItem->setData(COLUMN_DATA, ROLE_STANDARD, (groupInfo->flag & RS_GROUP_FLAG_STANDARD) ? true : false);
/* Sort data */
@ -716,7 +729,7 @@ void FriendList::insertPeers()
}
}
if (openGroups != NULL && openGroups->find(groupInfo->id) != openGroups->end()) {
if (openGroups.find(groupInfo->id) != openGroups.end()) {
groupItem->setExpanded(true);
}
@ -1168,9 +1181,9 @@ void FriendList::insertPeers()
gpgItem->setData(COLUMN_NAME, ROLE_FILTER, gpgName);
gpgItem->setData(COLUMN_LAST_CONTACT, Qt::DisplayRole, showInfoAtGpgItem ? QVariant(bestLastContact) : "");
gpgItem->setData(COLUMN_LAST_CONTACT, ROLE_SORT_NAME, showInfoAtGpgItem ? QVariant(bestLastContact) : "");
gpgItem->setData(COLUMN_LAST_CONTACT, ROLE_SORT_NAME, QVariant(bestLastContact));
gpgItem->setText(COLUMN_IP, showInfoAtGpgItem ? bestIP : "");
gpgItem->setData(COLUMN_IP, ROLE_SORT_NAME, showInfoAtGpgItem ? bestIP : "");
gpgItem->setData(COLUMN_IP, ROLE_SORT_NAME, bestIP);
/* Sort data */
gpgItem->setData(COLUMN_NAME, ROLE_SORT_NAME, gpgName);
@ -1182,7 +1195,7 @@ void FriendList::insertPeers()
gpgItem->setFont(i, gpgFont);
}
if (openPeers != NULL && openPeers->find(gpgId.toStdString()) != openPeers->end()) {
if (openPeers.find(gpgId.toStdString()) != openPeers.end()) {
gpgItem->setExpanded(true);
}
}
@ -1217,14 +1230,6 @@ void FriendList::insertPeers()
}
groupsHasChanged = false;
if (openGroups != NULL) {
delete(openGroups);
openGroups = NULL;
}
if (openPeers != NULL) {
delete(openPeers);
openPeers = NULL;
}
ui->peerTreeWidget->resort();
}
@ -1232,13 +1237,13 @@ void FriendList::insertPeers()
/**
* Returns a list with all groupIds that are expanded
*/
bool FriendList::getExpandedGroups(std::set<std::string> &groups) const
bool FriendList::getExpandedGroups(std::set<RsNodeGroupId> &groups) const
{
int itemCount = ui->peerTreeWidget->topLevelItemCount();
for (int index = 0; index < itemCount; ++index) {
QTreeWidgetItem *item = ui->peerTreeWidget->topLevelItem(index);
if (item->type() == TYPE_GROUP && item->isExpanded()) {
groups.insert(item->data(COLUMN_DATA, ROLE_ID).toString().toStdString());
groups.insert(RsNodeGroupId(item->data(COLUMN_DATA, ROLE_ID).toString().toStdString()));
}
}
return true;
@ -1626,7 +1631,7 @@ void FriendList::getSslIdsFromItem(QTreeWidgetItem *item, std::list<RsPeerId> &s
case TYPE_GROUP:
{
RsGroupInfo groupInfo;
if (rsPeers->getGroupInfo(peerId, groupInfo)) {
if (rsPeers->getGroupInfo(RsNodeGroupId(peerId), groupInfo)) {
std::set<RsPgpId>::iterator gpgIt;
for (gpgIt = groupInfo.peerIds.begin(); gpgIt != groupInfo.peerIds.end(); ++gpgIt) {
rsPeers->getAssociatedSSLIds(*gpgIt, sslIds);
@ -1649,10 +1654,10 @@ void FriendList::addToGroup()
return;
}
std::string groupId = qobject_cast<QAction*>(sender())->data().toString().toStdString();
RsNodeGroupId groupId ( qobject_cast<QAction*>(sender())->data().toString().toStdString());
RsPgpId gpgId ( getRsId(c));
if (gpgId.isNull() || groupId.empty()) {
if (gpgId.isNull() || groupId.isNull()) {
return;
}
@ -1675,15 +1680,15 @@ void FriendList::moveToGroup()
return;
}
std::string groupId = qobject_cast<QAction*>(sender())->data().toString().toStdString();
RsNodeGroupId groupId ( qobject_cast<QAction*>(sender())->data().toString().toStdString());
RsPgpId gpgId ( getRsId(c));
if (gpgId.isNull() || groupId.empty()) {
if (gpgId.isNull() || groupId.isNull()) {
return;
}
// remove from all groups
rsPeers->assignPeerToGroup("", gpgId, false);
rsPeers->assignPeerToGroup(RsNodeGroupId(), gpgId, false);
// automatically expand the group, the peer is added to
addGroupToExpand(groupId);
@ -1704,7 +1709,7 @@ void FriendList::removeFromGroup()
return;
}
std::string groupId = qobject_cast<QAction*>(sender())->data().toString().toStdString();
RsNodeGroupId groupId ( qobject_cast<QAction*>(sender())->data().toString().toStdString());
RsPgpId gpgId ( getRsId(c));
if (gpgId.isNull()) {
@ -1727,14 +1732,13 @@ void FriendList::editGroup()
return;
}
std::string groupId = getRsId(c);
RsNodeGroupId groupId ( getRsId(c));
if (groupId.empty()) {
return;
if (!groupId.isNull())
{
CreateGroup editGrpDialog(groupId, this);
editGrpDialog.exec();
}
CreateGroup editGrpDialog(groupId, this);
editGrpDialog.exec();
}
void FriendList::removeGroup()
@ -1749,13 +1753,10 @@ void FriendList::removeGroup()
return;
}
std::string groupId = getRsId(c);
RsNodeGroupId groupId ( getRsId(c));
if (groupId.empty()) {
return;
}
rsPeers->removeGroup(groupId);
if (!groupId.isNull())
rsPeers->removeGroup(groupId);
}
void FriendList::exportFriendlistClicked()
@ -2089,7 +2090,7 @@ bool FriendList::importFriendlist(QString &fileName, bool &errorPeers, bool &err
// get name and flags and try to get the group ID
std::string groupName = group.attribute("name").toStdString();
uint32_t flag = group.attribute("flag").toInt();
std::string groupId;
RsNodeGroupId groupId;
if(getOrCreateGroup(groupName, flag, groupId)) {
// group id found!
QDomElement pgpID = group.firstChildElement("pgpID");
@ -2123,7 +2124,7 @@ bool FriendList::importFriendlist(QString &fileName, bool &errorPeers, bool &err
* @param id groupd id for the given name
* @return success or fail
*/
bool FriendList::getGroupIdByName(const std::string &name, std::string &id)
bool FriendList::getGroupIdByName(const std::string &name, RsNodeGroupId &id)
{
std::list<RsGroupInfo> grpList;
if(!rsPeers->getGroupInfoList(grpList))
@ -2146,14 +2147,14 @@ bool FriendList::getGroupIdByName(const std::string &name, std::string &id)
* @param id groupd id
* @return success or failure
*/
bool FriendList::getOrCreateGroup(const std::string &name, const uint &flag, std::string &id)
bool FriendList::getOrCreateGroup(const std::string &name, const uint &flag, RsNodeGroupId &id)
{
if(getGroupIdByName(name, id))
return true;
// -> create one
RsGroupInfo grp;
grp.id = "0"; // RS will generate an ID
grp.id.clear(); // RS will generate an ID
grp.name = name;
grp.flag = flag;
@ -2271,12 +2272,9 @@ void FriendList::filterItems(const QString &text)
* Add a groupId to the openGroups list. These groups
* will be expanded, when they're added to the QTreeWidget
*/
void FriendList::addGroupToExpand(const std::string &groupId)
void FriendList::addGroupToExpand(const RsNodeGroupId &groupId)
{
if (openGroups == NULL) {
openGroups = new std::set<std::string>;
}
openGroups->insert(groupId);
openGroups.insert(groupId);
}
/**
@ -2285,24 +2283,21 @@ void FriendList::addGroupToExpand(const std::string &groupId)
*/
void FriendList::addPeerToExpand(const std::string &gpgId)
{
if (openPeers == NULL) {
openPeers = new std::set<std::string>;
}
openPeers->insert(gpgId);
openPeers.insert(gpgId);
}
void FriendList::createDisplayMenu()
{
QMenu *displayMenu = new QMenu(this);
QMenu *displayMenu = new QMenu(tr("Show Items"), this);
connect(displayMenu, SIGNAL(aboutToShow()), this, SLOT(updateMenu()));
displayMenu->addAction(ui->actionHideOfflineFriends);
displayMenu->addAction(ui->actionShowState);
displayMenu->addAction(ui->actionShowGroups);
displayMenu->addAction(ui->actionExportFriendlist);
displayMenu->addAction(ui->actionImportFriendlist);
ui->displayButton->setMenu(displayMenu);
ui->peerTreeWidget->addContextMenuMenu(displayMenu);
ui->peerTreeWidget->addContextMenuAction(ui->actionExportFriendlist);
ui->peerTreeWidget->addContextMenuAction(ui->actionImportFriendlist);
}
void FriendList::updateMenu()

View file

@ -63,8 +63,8 @@ public:
// Add a tool button to the tool area
void addToolButton(QToolButton *toolButton);
void processSettings(bool load);
void addGroupToExpand(const std::string &groupId);
bool getExpandedGroups(std::set<std::string> &groups) const;
void addGroupToExpand(const RsNodeGroupId &groupId);
bool getExpandedGroups(std::set<RsNodeGroupId> &groups) const;
void addPeerToExpand(const std::string &gpgId);
bool getExpandedPeers(std::set<std::string> &peers) const;
@ -119,8 +119,9 @@ private:
QString mFilterText;
bool groupsHasChanged;
std::set<std::string> *openGroups;
std::set<std::string> *openPeers;
std::set<RsNodeGroupId> openGroups;
#warning this would needs an ID, not a std::string.
std::set<std::string> openPeers;
/* Color definitions (for standard see qss.default) */
QColor mTextColorGroup;
@ -129,8 +130,8 @@ private:
QTreeWidgetItem *getCurrentPeer() const;
void getSslIdsFromItem(QTreeWidgetItem *item, std::list<RsPeerId> &sslIds);
bool getOrCreateGroup(const std::string &name, const uint &flag, std::string &id);
bool getGroupIdByName(const std::string &name, std::string &id);
bool getOrCreateGroup(const std::string &name, const uint &flag, RsNodeGroupId &id);
bool getGroupIdByName(const std::string &name, RsNodeGroupId &id);
bool importExportFriendlistFileDialog(QString &fileName, bool import);
bool exportFriendlist(QString &fileName);

View file

@ -53,38 +53,6 @@
<item>
<widget class="LineEditClear" name="filterLineEdit"/>
</item>
<item>
<widget class="QToolButton" name="displayButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>30</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="toolTip">
<string>Display</string>
</property>
<property name="icon">
<iconset resource="../images.qrc">
<normaloff>:/images/looknfeel.png</normaloff>:/images/looknfeel.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="popupMode">
<enum>QToolButton::InstantPopup</enum>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
@ -188,8 +156,6 @@
<header>gui/common/RSTreeWidget.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../images.qrc"/>
</resources>
<resources/>
<connections/>
</ui>

View file

@ -108,7 +108,7 @@ FriendSelectionWidget::FriendSelectionWidget(QWidget *parent)
mActionSortByState = new QAction(tr("Sort by state"), this);
mActionSortByState->setCheckable(true);
connect(mActionSortByState, SIGNAL(toggled(bool)), this, SLOT(sortByState(bool)));
ui->friendList->addHeaderContextMenuAction(mActionSortByState);
ui->friendList->addContextMenuAction(mActionSortByState);
/* initialize list */
ui->friendList->setColumnCount(COLUMN_COUNT);
@ -271,9 +271,9 @@ void FriendSelectionWidget::secured_fillList()
selectedIds<RsPeerId,IDTYPE_SSL>(sslIdsSelected,true);
}
std::set<std::string> groupIdsSelected;
std::set<RsNodeGroupId> groupIdsSelected;
if (mShowTypes & SHOW_GROUP) {
selectedIds<std::string,IDTYPE_GROUP>(groupIdsSelected,true);
selectedIds<RsNodeGroupId,IDTYPE_GROUP>(groupIdsSelected,true);
}
std::set<RsPgpId> gpgIdsSelected;
@ -305,6 +305,9 @@ void FriendSelectionWidget::secured_fillList()
else
rsPeers->getGPGAcceptedList(gpgIds);
// add own pgp id to the list
gpgIds.push_back(rsPeers->getGPGOwnId()) ;
std::list<RsPeerId> sslIds;
std::list<RsPeerId>::iterator sslIt;
@ -347,7 +350,7 @@ void FriendSelectionWidget::secured_fillList()
groupItem->setTextAlignment(COLUMN_NAME, Qt::AlignLeft | Qt::AlignVCenter);
groupItem->setIcon(COLUMN_NAME, QIcon(IMAGE_GROUP16));
groupItem->setData(COLUMN_DATA, ROLE_ID, QString::fromStdString(groupInfo->id));
groupItem->setData(COLUMN_DATA, ROLE_ID, QString::fromStdString(groupInfo->id.toStdString()));
groupItem->setExpanded(true);
@ -363,7 +366,7 @@ void FriendSelectionWidget::secured_fillList()
groupItem->setCheckState(0, Qt::Unchecked);
}
emit itemAdded(IDTYPE_GROUP, QString::fromStdString(groupInfo->id), groupItem);
emit itemAdded(IDTYPE_GROUP, QString::fromStdString(groupInfo->id.toStdString()), groupItem);
if (std::find(groupIdsSelected.begin(), groupIdsSelected.end(), groupInfo->id) != groupIdsSelected.end()) {
setSelected(mListModus, groupItem, true);
@ -805,16 +808,16 @@ void FriendSelectionWidget::addContextMenuAction(QAction *action)
void FriendSelectionWidget::contextMenuRequested(const QPoint &/*pos*/)
{
QMenu contextMenu(this);
QMenu *contextMenu = new QMenu(this);
if (mListModus == MODUS_CHECK) {
contextMenu.addAction(QIcon(), tr("Mark all"), this, SLOT(selectAll()));
contextMenu.addAction(QIcon(), tr("Mark none"), this, SLOT(deselectAll()));
contextMenu->addAction(QIcon(), tr("Mark all"), this, SLOT(selectAll()));
contextMenu->addAction(QIcon(), tr("Mark none"), this, SLOT(deselectAll()));
}
if (!mContextMenuActions.isEmpty()) {
bool addSeparator = false;
if (!contextMenu.isEmpty()) {
if (!contextMenu->isEmpty()) {
// Check for visible action
foreach (QAction *action, mContextMenuActions) {
if (action->isVisible()) {
@ -825,17 +828,19 @@ void FriendSelectionWidget::contextMenuRequested(const QPoint &/*pos*/)
}
if (addSeparator) {
contextMenu.addSeparator();
contextMenu->addSeparator();
}
contextMenu.addActions(mContextMenuActions);
contextMenu->addActions(mContextMenuActions);
}
if (contextMenu.isEmpty()) {
return;
contextMenu = ui->friendList->createStandardContextMenu(contextMenu);
if (!contextMenu->isEmpty()) {
contextMenu->exec(QCursor::pos());
}
contextMenu.exec(QCursor::pos());
delete contextMenu;
}
void FriendSelectionWidget::itemDoubleClicked(QTreeWidgetItem *item, int /*column*/)

View file

@ -0,0 +1,117 @@
/*
* Retroshare Gxs Support
*
* Copyright 2012-2013 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2.1 as published by the Free Software Foundation.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#include "GroupChooser.h"
#include <algorithm>
#include <iostream>
#include <retroshare/rspeers.h>
/** Constructor */
GroupChooser::GroupChooser(QWidget *parent)
: QComboBox(parent), mFlags(0)
{
return;
}
void GroupChooser::loadGroups(uint32_t chooserFlags, const RsNodeGroupId& defaultId)
{
mFlags = chooserFlags;
mDefaultGroupId = defaultId;
loadGroups();
}
bool GroupChooser::makeNodeGroupDesc(const RsGroupInfo& info, QString &desc)
{
desc.clear();
if(info.name.empty())
desc = tr("[Unknown]") ;
else
desc = "\"" + QString::fromUtf8(info.name.c_str()) + "\"";
desc += " [" ;
desc += QString::fromStdString(info.id.toStdString().substr(0,3));
desc += "...";
desc += QString::fromStdString(info.id.toStdString().substr(info.id.toStdString().length()-2,2));
desc += "]";
return true;
}
void GroupChooser::loadGroups()
{
std::list<RsGroupInfo> ids;
rsPeers->getGroupInfoList(ids);
if (ids.empty())
{
std::cerr << "GroupChooser::loadGroups() ERROR no ids";
std::cerr << std::endl;
return;
}
int i = 0;
int def = -1;
for( std::list<RsGroupInfo>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
{
/* add to Chooser */
QString str;
if (!makeNodeGroupDesc(*it, str))
{
std::cerr << "GroupChooser::loadGroups() ERROR Desc for Id: " << it->id;
std::cerr << std::endl;
continue;
}
QString id = QString::fromStdString(it->id.toStdString());
addItem(str, id);
if (mDefaultGroupId == it->id)
def = i;
}
if (def >= 0)
{
setCurrentIndex(def);
}
}
bool GroupChooser::getChosenGroup(RsNodeGroupId& id)
{
if (count() < 1)
return false;
int idx = currentIndex();
QVariant var = itemData(idx);
id = RsNodeGroupId(var.toString().toStdString());
return true;
}

View file

@ -0,0 +1,45 @@
/*
* Retroshare Gxs Support
*
* Copyright 2012-2013 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2.1 as published by the Free Software Foundation.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#pragma once
#include <QComboBox>
#include <retroshare/rspeers.h>
class GroupChooser : public QComboBox
{
public:
GroupChooser(QWidget *parent = NULL);
void loadGroups(uint32_t chooserFlags, const RsNodeGroupId& defaultId);
bool getChosenGroup(RsNodeGroupId& id);
static bool makeNodeGroupDesc(const RsGroupInfo& info, QString &desc);
private:
void loadGroups();
uint32_t mFlags;
RsNodeGroupId mDefaultGroupId;
};

View file

@ -51,7 +51,7 @@ const QString GroupDefs::name(const RsGroupInfo &groupInfo)
return qApp->translate("GroupDefs", "Favorites");
}
std::cerr << "GroupDefs::name: Unknown group id requested " << groupInfo.id;
std::cerr << "GroupDefs::name: Unknown group id requested " << groupInfo.id << std::endl;
return "";
}

View file

@ -20,7 +20,7 @@ GroupSelectionBox::GroupSelectionBox(QWidget *parent)
void GroupSelectionBox::fillGroups()
{
std::list<std::string> selectedIds;
std::list<RsNodeGroupId> selectedIds;
selectedGroupIds(selectedIds);
clear();
@ -30,7 +30,7 @@ void GroupSelectionBox::fillGroups()
for (std::list<RsGroupInfo>::const_iterator it(groupIds.begin()); it != groupIds.end(); ++it) {
QListWidgetItem *item = new QListWidgetItem(GroupDefs::name(*it));
item->setData(ROLE_ID, QString::fromStdString(it->id));
item->setData(ROLE_ID, QString::fromStdString(it->id.toStdString()));
item->setBackgroundColor(QColor(183,236,181));
addItem(item);
}
@ -38,27 +38,27 @@ void GroupSelectionBox::fillGroups()
setSelectedGroupIds(selectedIds);
}
void GroupSelectionBox::selectedGroupIds(std::list<std::string> &groupIds) const
void GroupSelectionBox::selectedGroupIds(std::list<RsNodeGroupId> &groupIds) const
{
int itemCount = count();
for (int i = 0; i < itemCount; ++i) {
QListWidgetItem *listItem = item(i);
if (listItem->checkState() == Qt::Checked) {
groupIds.push_back(item(i)->data(ROLE_ID).toString().toStdString());
groupIds.push_back(RsNodeGroupId(item(i)->data(ROLE_ID).toString().toStdString()));
std::cerr << "Adding selected item " << groupIds.back() << std::endl;
}
}
}
void GroupSelectionBox::setSelectedGroupIds(const std::list<std::string>& groupIds)
void GroupSelectionBox::setSelectedGroupIds(const std::list<RsNodeGroupId>& groupIds)
{
int itemCount = count();
for (int i = 0; i < itemCount; ++i) {
QListWidgetItem *listItem = item(i);
if (std::find(groupIds.begin(), groupIds.end(), listItem->data(ROLE_ID).toString().toStdString()) != groupIds.end()) {
if (std::find(groupIds.begin(), groupIds.end(), RsNodeGroupId(listItem->data(ROLE_ID).toString().toStdString())) != groupIds.end()) {
listItem->setCheckState(Qt::Checked);
} else {
listItem->setCheckState(Qt::Unchecked);

View file

@ -1,4 +1,5 @@
#include <QListWidget>
#include <retroshare/rsids.h>
class GroupSelectionBox: public QListWidget
{
@ -7,10 +8,10 @@ class GroupSelectionBox: public QListWidget
public:
GroupSelectionBox(QWidget *parent);
void selectedGroupIds(std::list<std::string> &groupIds) const;
void selectedGroupIds(std::list<RsNodeGroupId> &groupIds) const;
void selectedGroupNames(QList<QString> &groupNames) const;
void setSelectedGroupIds(const std::list<std::string> &groupIds);
void setSelectedGroupIds(const std::list<RsNodeGroupId> &groupIds);
private slots:
void fillGroups();

View file

@ -14,7 +14,16 @@
<property name="spacing">
<number>2</number>
</property>
<property name="margin">
<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>
@ -32,7 +41,16 @@
<enum>QFrame::Sunken</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="margin">
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item>
@ -52,8 +70,8 @@
</property>
<property name="iconSize">
<size>
<width>32</width>
<height>16</height>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="popupMode">

View file

@ -26,15 +26,28 @@
RSImageBlockWidget::RSImageBlockWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::RSImageBlockWidget)
ui(new Ui::RSImageBlockWidget),
mAutoHide(false), mAutoHideHeight(4), mAutoHideTimeToStart(3000), mAutoHideDuration(3000)
{
ui->setupUi(this);
mDefaultRect = this->geometry();
ui->infoFrame->installEventFilter(this);
mTimer = new RsProtectedTimer(this);
mTimer->setSingleShot(true);
connect(mTimer, SIGNAL(timeout()), this, SLOT(startAutoHide()));
mAnimation = new QPropertyAnimation(this, "geometry");
connect(ui->loadImagesButton, SIGNAL(clicked()), this, SIGNAL(showImages()));
}
RSImageBlockWidget::~RSImageBlockWidget()
{
delete mAnimation;
mTimer->stop();
delete mTimer;
delete ui;
}
@ -64,3 +77,61 @@ void RSImageBlockWidget::addButtonAction(const QString &text, const QObject *rec
connect(action, SIGNAL(triggered()), this, SIGNAL(showImages()));
}
}
bool RSImageBlockWidget::eventFilter(QObject *obj, QEvent *event)
{
if (mAutoHide) {
if (event->type() == QEvent::Show) {
mTimer->start(mAutoHideTimeToStart);
}
if (event->type() == QEvent::Hide) {
mTimer->stop();
}
if (event->type() == QEvent::Enter) {
mAnimation->stop();
this->setGeometry(mDefaultRect);
this->updateGeometry();
mTimer->start(mAutoHideTimeToStart);
mAnimation->setCurrentTime(0);
}
}
if (mAnimation->currentTime() == 0) {
mDefaultRect = this->geometry();
} else if (mAnimation->state() == QAbstractAnimation::Running) {
this->updateGeometry();
}
// pass the event on to the parent class
return QObject::eventFilter(obj, event);
}
void RSImageBlockWidget::setAutoHide(const bool value)
{
if(value && !mAutoHide) {
if (this->isVisible()) mTimer->start(mAutoHideTimeToStart);
} else if (!value && mAutoHide) {
mTimer->stop();
}
mAutoHide = value;
}
void RSImageBlockWidget::startAutoHide()
{
QRect r = mDefaultRect;
r.setHeight(mAutoHideHeight);
this->setSizePolicy(QSizePolicy::Ignored,QSizePolicy::Preferred);
mAnimation->setDuration(mAutoHideDuration);
mAnimation->setStartValue(mDefaultRect);
mAnimation->setEndValue(r);
mAnimation->start();
}
QSize RSImageBlockWidget::sizeHint() const
{
if (mAnimation->currentTime() == 0) {
return mDefaultRect.size();
} else {
return mAnimation->currentValue().toRect().size();
}
}

View file

@ -22,8 +22,11 @@
#ifndef RSIMAGEBLOCKWIDGET_H
#define RSIMAGEBLOCKWIDGET_H
#include <QPropertyAnimation>
#include <QWidget>
#include "util/RsProtectedTimer.h"
namespace Ui {
class RSImageBlockWidget;
}
@ -32,17 +35,48 @@ class RSImageBlockWidget : public QWidget
{
Q_OBJECT
Q_PROPERTY(bool autoHide READ autoHide WRITE setAutoHide)
Q_PROPERTY(int autoHideHeight READ autoHideHeight WRITE setAutoHideHeight)
Q_PROPERTY(int autoHideTimeToStart READ autoHideTimeToStart WRITE setAutoHideTimeToStart)
Q_PROPERTY(int autoHideDuration READ autoHideDuration WRITE setAutoHideDuration)
public:
explicit RSImageBlockWidget(QWidget *parent = 0);
~RSImageBlockWidget();
void addButtonAction(const QString &text, const QObject *receiver, const char *member, bool standardAction);
virtual QSize sizeHint() const;//To update parent layout.
virtual QSize minimumSizeHint() const { return sizeHint();}//To update parent layout.
bool autoHide() { return mAutoHide; }
int autoHideHeight() { return mAutoHideHeight; }
int autoHideTimeToStart() { return mAutoHideTimeToStart; }
int autoHideDuration() { return mAutoHideDuration; }
void setAutoHide(const bool value);
void setAutoHideHeight(const int value) { mAutoHideHeight = value; }
void setAutoHideTimeToStart(const int value) { mAutoHideTimeToStart = value; }
void setAutoHideDuration(const int value) { mAutoHideDuration = value; }
signals:
void showImages();
private slots:
void startAutoHide();
protected:
bool eventFilter(QObject *obj, QEvent *event);
private:
Ui::RSImageBlockWidget *ui;
QPropertyAnimation *mAnimation;
QRect mDefaultRect;
RsProtectedTimer *mTimer;
bool mAutoHide;
int mAutoHideHeight;
int mAutoHideTimeToStart;
int mAutoHideDuration;
};
#endif // RSIMAGEBLOCKWIDGET_H

View file

@ -13,11 +13,20 @@
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<layout class="QHBoxLayout" name="RSImageBlockWidgetHLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<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>
@ -92,8 +101,17 @@
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="margin">
<layout class="QHBoxLayout" name="infoFrameHLayout">
<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>
@ -114,7 +132,7 @@
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<spacer name="infoFrameHSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>

View file

@ -1,11 +1,14 @@
#include <iostream>
#include <QDir>
#include <QDesktopServices>
#include <QPainter>
#include "RSTextBrowser.h"
#include "RSImageBlockWidget.h"
#include <retroshare/rsinit.h> //To get RsAccounts
RSTextBrowser::RSTextBrowser(QWidget *parent) :
QTextBrowser(parent)
{
@ -74,25 +77,33 @@ void RSTextBrowser::paintEvent(QPaintEvent *event)
QVariant RSTextBrowser::loadResource(int type, const QUrl &name)
{
// case 1: always trust the image if it comes from an internal resource
if(name.scheme().compare("qrc",Qt::CaseInsensitive)==0 && type == QTextDocument::ImageResource)
return QTextBrowser::loadResource(type, name);
// case 2: only display if the user allows it. Data resources can be bad (svg bombs) but we filter them out globally at the network layer.
// It would be good to add here a home-made resource loader that only loads images and not svg crap, just in case.
if(name.scheme().compare("data",Qt::CaseInsensitive)==0 && mShowImages)
return QTextBrowser::loadResource(type, name);
// case 3: otherwise, do not display
std::cerr << "TEXTBROWSER: refusing load ressource request: type=" << type << " scheme=" << name.scheme().toStdString() << ", url=" << name.toString().toStdString() << std::endl;
if (mImageBlockWidget)
mImageBlockWidget->show();
// case 1: always trust the image if it comes from an internal resource.
return QPixmap(":/trolltech/styles/commonstyle/images/file-16.png");
if(name.scheme().compare("qrc",Qt::CaseInsensitive)==0 && type == QTextDocument::ImageResource)
return QTextBrowser::loadResource(type, name);
// case 2: always trust the image if it comes from local Config or Data directories.
if(name.scheme().compare("file",Qt::CaseInsensitive)==0 && type == QTextDocument::ImageResource) {
if (name.path().startsWith(QDir(QString::fromUtf8(RsAccounts::ConfigDirectory().c_str())).absolutePath().prepend("/"),Qt::CaseInsensitive)
|| name.path().startsWith(QDir(QString::fromUtf8(RsAccounts::DataDirectory().c_str())).absolutePath().prepend("/"),Qt::CaseInsensitive))
return QTextBrowser::loadResource(type, name);
}
// case 3: only display if the user allows it. Data resources can be bad (svg bombs) but we filter them out globally at the network layer.
// It would be good to add here a home-made resource loader that only loads images and not svg crap, just in case.
if(name.scheme().compare("data",Qt::CaseInsensitive)==0 && mShowImages)
return QTextBrowser::loadResource(type, name);
// case 4: otherwise, do not display
std::cerr << "TEXTBROWSER: refusing load ressource request: type=" << type << " scheme=" << name.scheme().toStdString() << ", url=" << name.toString().toStdString() << std::endl;
if (mImageBlockWidget)
mImageBlockWidget->show();
return QPixmap(":/images/imageblocked_24.png");
}
void RSTextBrowser::setImageBlockWidget(RSImageBlockWidget *widget)

View file

@ -18,13 +18,16 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
****************************************************************/
#include <QPainter>
#include <QMouseEvent>
#include <QHeaderView>
#include <QMenu>
#include "RSTreeWidget.h"
#include <QHBoxLayout>
#include <QHeaderView>
#include <QLabel>
#include <QMenu>
#include <QMouseEvent>
#include <QPainter>
#include <QWidgetAction>
#include "gui/settings/rsharesettings.h"
RSTreeWidget::RSTreeWidget(QWidget *parent) : QTreeWidget(parent)
@ -164,16 +167,54 @@ void RSTreeWidget::setColumnCustomizable(int column, bool customizable)
mColumnCustomizable[column] = customizable;
}
void RSTreeWidget::addHeaderContextMenuAction(QAction *action)
void RSTreeWidget::addContextMenuAction(QAction *action)
{
mHeaderContextMenuActions.push_back(action);
mContextMenuActions.push_back(action);
}
void RSTreeWidget::headerContextMenuRequested(const QPoint &pos)
void RSTreeWidget::addContextMenuMenu(QMenu *menu)
{
QMenu contextMenu(this);
mContextMenuMenus.push_back(menu);
}
QMenu *RSTreeWidget::createStandardContextMenu(QMenu *contextMenu)
{
if (!contextMenu){
contextMenu = new QMenu(this);
contextMenu->addSeparator();
}
if(!mContextMenuActions.isEmpty() || mEnableColumnCustomize ||!mContextMenuActions.isEmpty() || !mContextMenuMenus.isEmpty()) {
QWidget *widget = new QWidget(contextMenu);
widget->setStyleSheet( ".QWidget{background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 #FEFEFE, stop:1 #E8E8E8); border: 1px solid #CCCCCC;}");
// create menu header
QHBoxLayout *hbox = new QHBoxLayout(widget);
hbox->setMargin(0);
hbox->setSpacing(6);
QLabel *iconLabel = new QLabel(widget);
QPixmap pix = QPixmap(":/images/settings.png").scaledToHeight(QFontMetricsF(iconLabel->font()).height()*1.5);
iconLabel->setPixmap(pix);
iconLabel->setMaximumSize(iconLabel->frameSize().height() + pix.height(), pix.width());
hbox->addWidget(iconLabel);
QLabel *textLabel = new QLabel("<strong>" + tr("Tree View Options") + "</strong>", widget);
hbox->addWidget(textLabel);
QSpacerItem *spacerItem = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
hbox->addItem(spacerItem);
widget->setLayout(hbox);
QWidgetAction *widgetAction = new QWidgetAction(this);
widgetAction->setDefaultWidget(widget);
contextMenu->addAction(widgetAction);
}
if (mEnableColumnCustomize) {
QMenu *headerMenu = contextMenu->addMenu(QIcon(),tr("Show Headers"));
QTreeWidgetItem *item = headerItem();
int columnCount = item->columnCount();
for (int column = 0; column < columnCount; ++column) {
@ -181,18 +222,18 @@ void RSTreeWidget::headerContextMenuRequested(const QPoint &pos)
if (it != mColumnCustomizable.end() && *it == false) {
continue;
}
QAction *action = contextMenu.addAction(QIcon(), item->text(column), this, SLOT(columnVisible()));
QAction *action = headerMenu->addAction(QIcon(), item->text(column), this, SLOT(columnVisible()));
action->setCheckable(true);
action->setData(column);
action->setChecked(!isColumnHidden(column));
}
}
if (!mHeaderContextMenuActions.isEmpty()) {
if (!mContextMenuActions.isEmpty()) {
bool addSeparator = false;
if (!contextMenu.isEmpty()) {
if (!contextMenu->isEmpty()) {
// Check for visible action
foreach (QAction *action, mHeaderContextMenuActions) {
foreach (QAction *action, mContextMenuActions) {
if (action->isVisible()) {
addSeparator = true;
break;
@ -201,17 +242,31 @@ void RSTreeWidget::headerContextMenuRequested(const QPoint &pos)
}
if (addSeparator) {
contextMenu.addSeparator();
contextMenu->addSeparator();
}
contextMenu.addActions(mHeaderContextMenuActions);
contextMenu->addActions(mContextMenuActions);
}
if (contextMenu.isEmpty()) {
if (!mContextMenuMenus.isEmpty()) {
foreach(QMenu *menu, mContextMenuMenus) {
contextMenu->addSeparator();
contextMenu->addMenu(menu);
}
}
return contextMenu;
}
void RSTreeWidget::headerContextMenuRequested(const QPoint &pos)
{
QMenu *contextMenu = createStandardContextMenu(NULL);
if (contextMenu->isEmpty()) {
return;
}
contextMenu.exec(mapToGlobal(pos));
contextMenu->exec(mapToGlobal(pos));
delete contextMenu;
}
void RSTreeWidget::columnVisible()

View file

@ -46,7 +46,11 @@ public:
void resort();
// Add QAction to context menu (action won't be deleted)
void addHeaderContextMenuAction(QAction *action);
void addContextMenuAction(QAction *action);
// Add QMenu to context menu (menu won't be deleted)
void addContextMenuMenu(QMenu *menu);
// Get Default context menu (Columns choice and menus added)
QMenu *createStandardContextMenu(QMenu *menu);
signals:
void signalMouseMiddleButtonClicked(QTreeWidgetItem *item);
@ -68,7 +72,8 @@ private:
bool mEnableColumnCustomize;
quint32 mSettingsVersion;
QMap<int, bool> mColumnCustomizable;
QList<QAction*> mHeaderContextMenuActions;
QList<QAction*> mContextMenuActions;
QList<QMenu*> mContextMenuMenus;
};
#endif

View file

@ -160,6 +160,7 @@ RsCollectionDialog::RsCollectionDialog(const QString& collectionFileName
connect(ui._addRecur_PB, SIGNAL(clicked()), this, SLOT(addRecursive()));
connect(ui._remove_PB, SIGNAL(clicked()), this, SLOT(remove()));
connect(ui._makeDir_PB, SIGNAL(clicked()), this, SLOT(makeDir()));
connect(ui._removeDuplicate_CB, SIGNAL(clicked(bool)), this, SLOT(updateRemoveDuplicate(bool)));
connect(ui._cancel_PB, SIGNAL(clicked()), this, SLOT(cancel()));
connect(ui._save_PB, SIGNAL(clicked()), this, SLOT(save()));
connect(ui._download_PB, SIGNAL(clicked()), this, SLOT(download()));
@ -190,6 +191,7 @@ RsCollectionDialog::RsCollectionDialog(const QString& collectionFileName
// 5 Activate button follow creationMode
ui._changeFile->setVisible(_creationMode && !_readOnly);
ui._makeDir_PB->setVisible(_creationMode && !_readOnly);
ui._removeDuplicate_CB->setVisible(_creationMode && !_readOnly);
ui._save_PB->setVisible(_creationMode && !_readOnly);
ui._treeViewFrame->setVisible(_creationMode && !_readOnly);
ui._download_PB->setVisible(!_creationMode && !_readOnly);
@ -408,7 +410,10 @@ bool RsCollectionDialog::addChild(QTreeWidgetItem* parent, const std::vector<Col
if (colFileInfo.type == DIR_TYPE_DIR){
founds = ui._fileEntriesTW->findItems(colFileInfo.path + "/" +colFileInfo.name, Qt::MatchExactly | Qt::MatchRecursive, COLUMN_FILEPATH);
} else {
founds = ui._fileEntriesTW->findItems(colFileInfo.hash, Qt::MatchExactly | Qt::MatchRecursive, COLUMN_HASH);
founds = ui._fileEntriesTW->findItems(colFileInfo.path + "/" +colFileInfo.name, Qt::MatchExactly | Qt::MatchRecursive, COLUMN_FILEPATH);
if (ui._removeDuplicate_CB->isChecked()) {
founds << ui._fileEntriesTW->findItems(colFileInfo.hash, Qt::MatchExactly | Qt::MatchRecursive, COLUMN_HASH);
}
}
if (founds.empty()) {
QTreeWidgetItem *item = new QTreeWidgetItem;
@ -493,7 +498,8 @@ bool RsCollectionDialog::addChild(QTreeWidgetItem* parent, const std::vector<Col
if (colFileInfo.type == DIR_TYPE_DIR) {
wrong_chars |= addChild(founds.at(0), colFileInfo.children);
} }
}
}
}
return wrong_chars;
}
@ -799,7 +805,7 @@ bool RsCollectionDialog::addAllChild(QFileInfo &fileInfoParent
*/
void RsCollectionDialog::remove()
{
bool removeOnlyFile=false;
bool removeOnlyFile=false;
QString listDir;
// First, check if selection contains directories
for (int curs = 0; curs < ui._fileEntriesTW->selectedItems().count(); ++curs)
@ -827,9 +833,29 @@ void RsCollectionDialog::remove()
//msgBox->setInformativeText(); If text too long, no scroll, so I add an text edit
QGridLayout* layout = qobject_cast<QGridLayout*>(msgBox->layout());
if (layout) {
QTextEdit* edit = new QTextEdit(tr("Do you want to remove them and all their children, too? <br>") + listDir);
int newRow = 1;
for (int row = layout->count()-1; row >= 0; --row) {
for (int col = layout->columnCount()-1; col >= 0; --col) {
QLayoutItem *item = layout->itemAtPosition(row, col);
if (item) {
int index = layout->indexOf(item->widget());
int r=0, c=0, rSpan=0, cSpan=0;
layout->getItemPosition(index, &r, &c, &rSpan, &cSpan);
if (r>0) {
layout->removeItem(item);
layout->addItem(item, r+3, c, rSpan, cSpan);
} else if (rSpan>1) {
newRow = rSpan + 1;
}
}
}
}
QLabel *label = new QLabel(tr("Do you want to remove them and all their children, too?"));
layout->addWidget(label,newRow, 0, 1, layout->columnCount(), Qt::AlignHCenter );
QTextEdit *edit = new QTextEdit(listDir);
edit->setReadOnly(true);
layout->addWidget(edit,0 ,1);
edit->setWordWrapMode(QTextOption::NoWrap);
layout->addWidget(edit,newRow+1, 0, 1, layout->columnCount(), Qt::AlignHCenter );
}
msgBox->setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
@ -854,20 +880,49 @@ void RsCollectionDialog::remove()
}//if (!listDir.isEmpty())
//Remove wanted items
for (int curs = 0; curs < ui._fileEntriesTW->selectedItems().count(); ++curs)
{// Have to call ui._fileEntriesTW->selectedItems().count() each time as selected change
QTreeWidgetItem *item = NULL;
item= ui._fileEntriesTW->selectedItems().at(curs);
int leftItem = 0;
// Have to call ui._fileEntriesTW->selectedItems().count() each time as selected change
while (ui._fileEntriesTW->selectedItems().count() > leftItem) {
QTreeWidgetItem *item = ui._fileEntriesTW->selectedItems().at(leftItem);
if (item != getRootItem()){
if ((item->data(COLUMN_HASH, ROLE_TYPE).toUInt() != DIR_TYPE_DIR) || !removeOnlyFile) {
if (!removeItem(item, removeOnlyFile)) {
++leftItem;
}
} else {
//Get Root change index
++leftItem;
}
}
updateSizes() ;
}
bool RsCollectionDialog::removeItem(QTreeWidgetItem *item, bool &removeOnlyFile)
{
if (item){
if ((item->data(COLUMN_HASH, ROLE_TYPE).toUInt() != DIR_TYPE_DIR) || !removeOnlyFile) {
int leftItem = 0;
while (item->childCount() > leftItem) {
if (!removeItem(item->child(0), removeOnlyFile)) {
++leftItem;
}
}
if (leftItem == 0) {
//First uncheck item to update parent informations
item->setCheckState(COLUMN_FILE,Qt::Unchecked);
QTreeWidgetItem *parent = item->parent();
parent->removeChild(item);
curs = 0;//Cause we don't know how many child of this item was selected (and don't want iterate them ;) )
return true;
} else {
if (!removeOnlyFile) {
std::cerr << "(EE) RsCollectionDialog::removeItem This could never happen." << std::endl;
}
}
}//if (item != getRootItem())*
}//for (int curs = 0; curs < count; ++curs)
}
}
return false;
}
/** Process each item to make a new RsCollection item */
@ -1063,6 +1118,94 @@ void RsCollectionDialog::itemChanged(QTreeWidgetItem *item, int col)
}
/**
* @brief RsCollectionDialog::updateRemoveDuplicate Remove all duplicate file when checked.
* @param checked
*/
void RsCollectionDialog::updateRemoveDuplicate(bool checked)
{
if (checked) {
bool bRemoveAll = false;
QTreeWidgetItemIterator it(ui._fileEntriesTW);
QTreeWidgetItem *item;
while ((item = *it) != NULL) {
++it;
if (item->data(COLUMN_HASH, ROLE_TYPE).toUInt() != DIR_TYPE_DIR) {
QList<QTreeWidgetItem*> founds;
founds << ui._fileEntriesTW->findItems(item->text(COLUMN_HASH), Qt::MatchExactly | Qt::MatchRecursive, COLUMN_HASH);
if (founds.count() > 1) {
bool bRemove = false;
if (!bRemoveAll) {
QMessageBox* msgBox = new QMessageBox(QMessageBox::Information, "", "");
msgBox->setText("Warning, duplicate file found.");
//msgBox->setInformativeText(); If text too long, no scroll, so I add an text edit
msgBox->setStandardButtons(QMessageBox::YesToAll | QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
msgBox->setDefaultButton(QMessageBox::Yes);
QGridLayout* layout = qobject_cast<QGridLayout*>(msgBox->layout());
if (layout) {
int newRow = 1;
for (int row = layout->count()-1; row >= 0; --row) {
for (int col = layout->columnCount()-1; col >= 0; --col) {
QLayoutItem *item = layout->itemAtPosition(row, col);
if (item) {
int index = layout->indexOf(item->widget());
int r=0, c=0, rSpan=0, cSpan=0;
layout->getItemPosition(index, &r, &c, &rSpan, &cSpan);
if (r>0) {
layout->removeItem(item);
layout->addItem(item, r+3, c, rSpan, cSpan);
} else if (rSpan>1) {
newRow = rSpan + 1;
}
}
}
}
QLabel *label = new QLabel(tr("Do you want to remove this file from the list?"));
layout->addWidget(label,newRow, 0, 1, layout->columnCount(), Qt::AlignHCenter );
QTextEdit *edit = new QTextEdit(item->text(COLUMN_FILEPATH));
edit->setReadOnly(true);
edit->setWordWrapMode(QTextOption::NoWrap);
layout->addWidget(edit,newRow+1, 0, 1, layout->columnCount(), Qt::AlignHCenter );
}
int ret = msgBox->exec();
switch (ret) {
case QMessageBox::YesToAll: {
bRemoveAll = true;
}
break;
case QMessageBox::Yes: {
bRemove = true;
}
break;
case QMessageBox::No:
break;
case QMessageBox::Cancel: {
delete msgBox;
ui._removeDuplicate_CB->setChecked(false);
return;
}
break;
default:
// should never be reached
break;
}
delete msgBox;
}
if (bRemove || bRemoveAll) {
//First uncheck item to update parent informations
item->setCheckState(COLUMN_FILE,Qt::Unchecked);
item->parent()->removeChild(item);
}
}
}
}
}
}
/**
* @brief RsCollectionDialog::cancel: Cancel RScollection editing or donwloading
*/

View file

@ -56,6 +56,7 @@ private slots:
void makeDir() ;
void fileHashingFinished(QList<HashedFile> hashedFiles) ;
void itemChanged(QTreeWidgetItem* item,int col) ;
void updateRemoveDuplicate(bool checked);
void cancel() ;
void download() ;
void save() ;
@ -68,6 +69,7 @@ private:
QTreeWidgetItem* getRootItem();
bool updateList();
bool addChild(QTreeWidgetItem *parent, const std::vector<ColFileInfo> &child);
bool removeItem(QTreeWidgetItem *item, bool &removeOnlyFile) ;
void addRecursive(bool recursive) ;
bool addAllChild(QFileInfo &fileInfoParent
, QMap<QString, QString > &dirToAdd

View file

@ -21,7 +21,16 @@
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<property name="margin">
<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>
<property name="spacing">
@ -59,7 +68,16 @@
<enum>QFrame::Plain</enum>
</property>
<layout class="QVBoxLayout">
<property name="margin">
<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>
@ -83,7 +101,16 @@
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<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>
@ -197,7 +224,16 @@
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<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>
@ -207,7 +243,16 @@
</property>
<widget class="QFrame" name="_treeViewFrame">
<layout class="QHBoxLayout">
<property name="margin">
<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>
@ -359,6 +404,13 @@
</item>
<item>
<layout class="QHBoxLayout">
<item>
<widget class="QCheckBox" name="_removeDuplicate_CB">
<property name="text">
<string>Remove Duplicate</string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation">
@ -405,12 +457,6 @@
</widget>
</item>
</layout>
<zorder></zorder>
<zorder></zorder>
<zorder>_mainSplitter</zorder>
<zorder>_listSplitter</zorder>
<zorder></zorder>
<zorder>_mainSplitter</zorder>
</widget>
</item>
</layout>