diff --git a/retroshare-gui/src/gui/common/FriendSelectionWidget.cpp b/retroshare-gui/src/gui/common/FriendSelectionWidget.cpp index 19b8c63c6..079b97f0f 100644 --- a/retroshare-gui/src/gui/common/FriendSelectionWidget.cpp +++ b/retroshare-gui/src/gui/common/FriendSelectionWidget.cpp @@ -21,6 +21,7 @@ ****************************************************************/ #include +#include #include "FriendSelectionWidget.h" #include "ui_FriendSelectionWidget.h" #include "gui/gxs/GxsIdDetails.h" @@ -44,8 +45,11 @@ #define IDDIALOG_IDLIST 1 -#define ROLE_ID Qt::UserRole -#define ROLE_SORT Qt::UserRole + 1 +#define ROLE_ID Qt::UserRole +#define ROLE_SORT_GROUP Qt::UserRole + 1 +#define ROLE_SORT_STANDARD_GROUP Qt::UserRole + 2 +#define ROLE_SORT_NAME Qt::UserRole + 3 +#define ROLE_SORT_STATE Qt::UserRole + 4 #define IMAGE_GROUP16 ":/images/user/group16.png" #define IMAGE_FRIENDINFO ":/images/peerdetails_16x16.png" @@ -94,15 +98,17 @@ FriendSelectionWidget::FriendSelectionWidget(QWidget *parent) connect(ui->friendList, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuRequested(QPoint))); connect(ui->friendList, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(itemDoubleClicked(QTreeWidgetItem*,int))); connect(ui->friendList, SIGNAL(itemChanged(QTreeWidgetItem*,int)), this, SLOT(itemChanged(QTreeWidgetItem*,int))); - connect(ui->selectAll_PB, SIGNAL(clicked()), this, SLOT(selectAll())); - connect(ui->deselectAll_PB, SIGNAL(clicked()), this, SLOT(deselectAll())); + connect(ui->friendList, SIGNAL(itemSelectionChanged()), this, SIGNAL(itemSelectionChanged())); connect(ui->filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterItems(QString))); connect(NotifyQt::getInstance(), SIGNAL(groupsChanged(int)), this, SLOT(groupsChanged(int))); connect(NotifyQt::getInstance(), SIGNAL(peerStatusChanged(const QString&,int)), this, SLOT(peerStatusChanged(const QString&,int))); mCompareRole = new RSTreeWidgetItemCompareRole; - mCompareRole->setRole(COLUMN_NAME, ROLE_SORT); + mActionSortByState = new QAction(tr("Sort by state"), this); + mActionSortByState->setCheckable(true); + connect(mActionSortByState, SIGNAL(toggled(bool)), this, SLOT(setSortByState(bool))); + ui->friendList->addHeaderContextMenuAction(mActionSortByState); /* initialize list */ ui->friendList->setColumnCount(COLUMN_COUNT); @@ -110,6 +116,7 @@ FriendSelectionWidget::FriendSelectionWidget(QWidget *parent) /* sort list by name ascending */ ui->friendList->sortItems(COLUMN_NAME, Qt::AscendingOrder); + setSortByState(false); ui->filterLineEdit->setPlaceholderText(tr("Search Friends")); ui->filterLineEdit->showFilterIcon(); @@ -156,17 +163,6 @@ void FriendSelectionWidget::setModus(Modus modus) break; } - if(modus == MODUS_CHECK) - { - ui->selectAll_PB->setHidden(false) ; - ui->deselectAll_PB->setHidden(false) ; - } - else - { - ui->selectAll_PB->setHidden(true) ; - ui->deselectAll_PB->setHidden(true) ; - } - fillList(); } @@ -216,8 +212,12 @@ static void initSslItem(QTreeWidgetItem *item, const RsPeerDetails &detail, cons } item->setIcon(COLUMN_NAME, QIcon(StatusDefs::imageUser(state))); - item->setData(COLUMN_DATA, ROLE_ID, QString::fromStdString(detail.id.toStdString())); - item->setData(COLUMN_DATA, ROLE_SORT, "2 " + name); + item->setData(COLUMN_DATA, ROLE_ID, QString::fromStdString(detail.id.toStdString())); + + item->setData(COLUMN_NAME, ROLE_SORT_GROUP, 1); + item->setData(COLUMN_NAME, ROLE_SORT_STANDARD_GROUP, 0); + item->setData(COLUMN_NAME, ROLE_SORT_STATE, (state != (int) RS_STATUS_OFFLINE) ? 0 : 1); + item->setData(COLUMN_NAME, ROLE_SORT_NAME, name); } void FriendSelectionWidget::fillList() @@ -349,7 +349,11 @@ void FriendSelectionWidget::secured_fillList() QString groupName = GroupDefs::name(*groupInfo); groupItem->setText(COLUMN_NAME, groupName); - groupItem->setData(COLUMN_DATA, ROLE_SORT, ((groupInfo->flag & RS_GROUP_FLAG_STANDARD) ? "0 " : "1 ") + groupName); + + groupItem->setData(COLUMN_NAME, ROLE_SORT_GROUP, 0); + groupItem->setData(COLUMN_NAME, ROLE_SORT_STANDARD_GROUP, (groupInfo->flag & RS_GROUP_FLAG_STANDARD) ? 0 : 1); + groupItem->setData(COLUMN_NAME, ROLE_SORT_STATE, 0); + groupItem->setData(COLUMN_NAME, ROLE_SORT_NAME, groupName); if (mListModus == MODUS_CHECK) { groupItem->setCheckState(0, Qt::Unchecked); @@ -411,8 +415,12 @@ void FriendSelectionWidget::secured_fillList() gpgItem->setFlags(Qt::ItemIsUserCheckable | gpgItem->flags()); gpgItem->setIcon(COLUMN_NAME, QIcon(StatusDefs::imageUser(state))); - gpgItem->setData(COLUMN_DATA, ROLE_ID, QString::fromStdString(detail.gpg_id.toStdString())); - gpgItem->setData(COLUMN_DATA, ROLE_SORT, "2 " + name); + gpgItem->setData(COLUMN_DATA, ROLE_ID, QString::fromStdString(detail.gpg_id.toStdString())); + + gpgItem->setData(COLUMN_NAME, ROLE_SORT_GROUP, 1); + gpgItem->setData(COLUMN_NAME, ROLE_SORT_STANDARD_GROUP, 0); + gpgItem->setData(COLUMN_NAME, ROLE_SORT_STATE, (state != (int) RS_STATUS_OFFLINE) ? 0 : 1); + gpgItem->setData(COLUMN_NAME, ROLE_SORT_NAME, name); if (mListModus == MODUS_CHECK) { gpgItem->setCheckState(0, Qt::Unchecked); @@ -542,7 +550,12 @@ void FriendSelectionWidget::secured_fillList() gxsItem->setFlags(Qt::ItemIsUserCheckable | gxsItem->flags()); gxsItem->setIcon(COLUMN_NAME, identicon); gxsItem->setData(COLUMN_DATA, ROLE_ID, QString::fromStdString(detail.mId.toStdString())); - gxsItem->setData(COLUMN_DATA, ROLE_SORT, "2 " + name); + + gxsItem->setData(COLUMN_NAME, ROLE_SORT_GROUP, 1); + gxsItem->setData(COLUMN_NAME, ROLE_SORT_STANDARD_GROUP, 0); +//TODO: online state for gxs items + gxsItem->setData(COLUMN_NAME, ROLE_SORT_STATE, 1); + gxsItem->setData(COLUMN_NAME, ROLE_SORT_NAME, name); if (mListModus == MODUS_CHECK) gxsItem->setCheckState(0, Qt::Unchecked); @@ -573,6 +586,8 @@ void FriendSelectionWidget::secured_fillList() mInFillList = false; + ui->friendList->resort(); + emit contentChanged(); } void FriendSelectionWidget::updateDisplay(bool) @@ -658,6 +673,7 @@ void FriendSelectionWidget::peerStatusChanged(const QString& peerId, int status) switch (idTypeFromItem(item)) { case IDTYPE_NONE: case IDTYPE_GROUP: + case IDTYPE_GXS: break; case IDTYPE_GPG: { @@ -672,6 +688,8 @@ void FriendSelectionWidget::peerStatusChanged(const QString& peerId, int status) item->setTextColor(COLUMN_NAME, color); item->setIcon(COLUMN_NAME, QIcon(StatusDefs::imageUser(gpgStatus))); + item->setData(COLUMN_NAME, ROLE_SORT_STATE, (gpgStatus != (int) RS_STATUS_OFFLINE) ? 0 : 1); + bFoundGPG = true; } } @@ -689,6 +707,8 @@ void FriendSelectionWidget::peerStatusChanged(const QString& peerId, int status) item->setTextColor(COLUMN_NAME, color); item->setIcon(COLUMN_NAME, QIcon(StatusDefs::imageUser(status))); + item->setData(COLUMN_NAME, ROLE_SORT_STATE, (status != (int) RS_STATUS_OFFLINE) ? 0 : 1); + bFoundSSL = true; } } @@ -714,11 +734,48 @@ void FriendSelectionWidget::peerStatusChanged(const QString& peerId, int status) } } } + + ui->friendList->resort(); } -void FriendSelectionWidget::contextMenuRequested(const QPoint &pos) +void FriendSelectionWidget::addContextMenuAction(QAction *action) { - emit customContextMenuRequested(pos); + mContextMenuActions.push_back(action); +} + +void FriendSelectionWidget::contextMenuRequested(const QPoint &/*pos*/) +{ + QMenu contextMenu(this); + + if (mListModus == MODUS_CHECK) { + 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()) { + // Check for visible action + foreach (QAction *action, mContextMenuActions) { + if (action->isVisible()) { + addSeparator = true; + break; + } + } + } + + if (addSeparator) { + contextMenu.addSeparator(); + } + + contextMenu.addActions(mContextMenuActions); + } + + if (contextMenu.isEmpty()) { + return; + } + + contextMenu.exec(QCursor::pos()); } void FriendSelectionWidget::itemDoubleClicked(QTreeWidgetItem *item, int /*column*/) @@ -1030,3 +1087,28 @@ std::string FriendSelectionWidget::idFromItem(QTreeWidgetItem *item) return item->data(COLUMN_DATA, ROLE_ID).toString().toStdString(); } +void FriendSelectionWidget::setSortByState(bool sort) +{ + // Add changes also in FriendSelectionWidget::sortByState + mCompareRole->setRole(COLUMN_NAME, ROLE_SORT_GROUP); + mCompareRole->addRole(COLUMN_NAME, ROLE_SORT_STANDARD_GROUP); + + if (sort) { + mCompareRole->addRole(COLUMN_NAME, ROLE_SORT_STATE); + mCompareRole->addRole(COLUMN_NAME, ROLE_SORT_NAME); + + mActionSortByState->setChecked(true); + } else { + mCompareRole->addRole(COLUMN_NAME, ROLE_SORT_NAME); + mCompareRole->addRole(COLUMN_NAME, ROLE_SORT_STATE); + + mActionSortByState->setChecked(false); + } + + ui->friendList->resort(); +} + +bool FriendSelectionWidget::sortByState() +{ + return mActionSortByState->isChecked(); +} diff --git a/retroshare-gui/src/gui/common/FriendSelectionWidget.h b/retroshare-gui/src/gui/common/FriendSelectionWidget.h index 92bd6d0fc..40e7ed579 100644 --- a/retroshare-gui/src/gui/common/FriendSelectionWidget.h +++ b/retroshare-gui/src/gui/common/FriendSelectionWidget.h @@ -80,6 +80,8 @@ public: int addColumn(const QString &title); void start(); + bool sortByState(); + int selectedItemCount(); std::string selectedId(IdType &idType); @@ -109,6 +111,9 @@ public: void setTextColorOnline(QColor color) { mTextColorOnline = color; } + // Add QAction to context menu (action won't be deleted) + void addContextMenuAction(QAction *action); + protected: void changeEvent(QEvent *e); @@ -118,9 +123,12 @@ protected: signals: void itemAdded(int idType, const QString &id, QTreeWidgetItem *item); void contentChanged(); - void customContextMenuRequested(const QPoint &pos); void doubleClicked(int idType, const QString &id); void itemChanged(int idType, const QString &id, QTreeWidgetItem *item, int column); + void itemSelectionChanged(); + +public slots: + void setSortByState(bool sort); private slots: void groupsChanged(int type); @@ -142,6 +150,7 @@ private: void requestGXSIdList() ; +private: bool mStarted; RSTreeWidgetItemCompareRole *mCompareRole; Modus mListModus; @@ -150,6 +159,7 @@ private: bool mInGpgItemChanged; bool mInSslItemChanged; bool mInFillList; + QAction *mActionSortByState; /* Color definitions (for standard see qss.default) */ QColor mTextColorOnline; @@ -160,6 +170,7 @@ private: std::vector gxsIds ; TokenQueue *mIdQueue ; + QList mContextMenuActions; }; Q_DECLARE_OPERATORS_FOR_FLAGS(FriendSelectionWidget::ShowTypes) diff --git a/retroshare-gui/src/gui/common/FriendSelectionWidget.ui b/retroshare-gui/src/gui/common/FriendSelectionWidget.ui index 2ad0972b0..23d98c9b6 100644 --- a/retroshare-gui/src/gui/common/FriendSelectionWidget.ui +++ b/retroshare-gui/src/gui/common/FriendSelectionWidget.ui @@ -26,24 +26,10 @@ - - - - All - - - - - - - None - - - - + 20 @@ -80,6 +66,11 @@ QLineEdit
gui/common/LineEditClear.h
+ + RSTreeWidget + QTreeWidget +
gui/common/RSTreeWidget.h
+
diff --git a/retroshare-gui/src/gui/msgs/MessageComposer.cpp b/retroshare-gui/src/gui/msgs/MessageComposer.cpp index 08ff494ea..16c58a20c 100644 --- a/retroshare-gui/src/gui/msgs/MessageComposer.cpp +++ b/retroshare-gui/src/gui/msgs/MessageComposer.cpp @@ -128,6 +128,7 @@ MessageComposer::MessageComposer(QWidget *parent, Qt::WindowFlags flags) setupEditActions(); setupViewActions(); setupInsertActions(); + setupContactActions(); m_compareRole = new RSTreeWidgetItemCompareRole; m_compareRole->setRole(COLUMN_CONTACT_NAME, ROLE_CONTACT_SORT); @@ -210,8 +211,8 @@ MessageComposer::MessageComposer(QWidget *parent, Qt::WindowFlags flags) connect(NotifyQt::getInstance(), SIGNAL(peerStatusChanged(const QString&,int)), this, SLOT(peerStatusChanged(const QString&,int))); connect(ui.friendSelectionWidget, SIGNAL(contentChanged()), this, SLOT(buildCompleter())); - connect(ui.friendSelectionWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuMsgSendList(QPoint))); connect(ui.friendSelectionWidget, SIGNAL(doubleClicked(int,QString)), this, SLOT(addTo())); + connect(ui.friendSelectionWidget, SIGNAL(itemSelectionChanged()), this, SLOT(friendSelectionChanged())); /* hide the Tree +/- */ ui.msgFileList -> setRootIsDecorated( false ); @@ -698,35 +699,6 @@ void MessageComposer::contextMenuFileList(QPoint) contextMnu.exec(QCursor::pos()); } -void MessageComposer::contextMenuMsgSendList(QPoint) -{ - QMenu contextMnu(this); - - int selectedCount = ui.friendSelectionWidget->selectedItemCount(); - - FriendSelectionWidget::IdType idType; - ui.friendSelectionWidget->selectedId(idType); - - QAction *action = contextMnu.addAction(QIcon(), tr("Add to \"To\""), this, SLOT(addTo())); - action->setEnabled(selectedCount); - action = contextMnu.addAction(QIcon(), tr("Add to \"CC\""), this, SLOT(addCc())); - action->setEnabled(selectedCount); - action = contextMnu.addAction(QIcon(), tr("Add to \"BCC\""), this, SLOT(addBcc())); - action->setEnabled(selectedCount); - action = contextMnu.addAction(QIcon(), tr("Add as Recommend"), this, SLOT(addRecommend())); - action->setEnabled(selectedCount); - - contextMnu.addSeparator(); - - action = contextMnu.addAction(QIcon(IMAGE_FRIENDINFO), tr("Friend Details"), this, SLOT(friendDetails())); - action->setEnabled(selectedCount == 1 && idType == FriendSelectionWidget::IDTYPE_SSL); - - action = contextMnu.addAction(QIcon(), tr("Person Details"), this, SLOT(identityDetails())); - action->setEnabled(selectedCount == 1 && idType == FriendSelectionWidget::IDTYPE_GXS); - - contextMnu.exec(QCursor::pos()); -} - void MessageComposer::pasteRecommended() { QList links; @@ -2009,6 +1981,31 @@ void MessageComposer::setupFormatActions() } +void MessageComposer::setupContactActions() +{ + mActionAddTo = new QAction(tr("Add to \"To\""), this); + connect(mActionAddTo, SIGNAL(triggered(bool)), this, SLOT(addTo())); + mActionAddCC = new QAction(tr("Add to \"CC\""), this); + connect(mActionAddCC, SIGNAL(triggered(bool)), this, SLOT(addCc())); + mActionAddBCC = new QAction(tr("Add to \"BCC\""), this); + connect(mActionAddBCC, SIGNAL(triggered(bool)), this, SLOT(addBcc())); + mActionAddRecommend = new QAction(tr("Add as Recommend"), this); + connect(mActionAddRecommend, SIGNAL(triggered(bool)), this, SLOT(addRecommend())); + mActionContactDetails = new QAction(QIcon(IMAGE_FRIENDINFO), tr("Details"), this); + connect(mActionContactDetails, SIGNAL(triggered(bool)), this, SLOT(contactDetails())); + + ui.friendSelectionWidget->addContextMenuAction(mActionAddTo); + ui.friendSelectionWidget->addContextMenuAction(mActionAddCC); + ui.friendSelectionWidget->addContextMenuAction(mActionAddBCC); + ui.friendSelectionWidget->addContextMenuAction(mActionAddRecommend); + + QAction *action = new QAction(this); + action->setSeparator(true); + ui.friendSelectionWidget->addContextMenuAction(action); + + ui.friendSelectionWidget->addContextMenuAction(mActionContactDetails); +} + void MessageComposer::textBold() { QTextCharFormat fmt; @@ -2577,6 +2574,27 @@ void MessageComposer::filterComboBoxChanged(int i) } +void MessageComposer::friendSelectionChanged() +{ + std::set peerIds; + ui.friendSelectionWidget->selectedIds(peerIds, false); + + std::set gxsIds; + ui.friendSelectionWidget->selectedIds(gxsIds, false); + + int selectedCount = peerIds.size() + gxsIds.size(); + + mActionAddTo->setEnabled(selectedCount); + mActionAddCC->setEnabled(selectedCount); + mActionAddBCC->setEnabled(selectedCount); + mActionAddRecommend->setEnabled(selectedCount); + + FriendSelectionWidget::IdType idType; + ui.friendSelectionWidget->selectedId(idType); + + mActionContactDetails->setEnabled(selectedCount == 1 && (idType == FriendSelectionWidget::IDTYPE_SSL || idType == FriendSelectionWidget::IDTYPE_GXS)); +} + void MessageComposer::addTo() { addContact(TO); @@ -2613,35 +2631,37 @@ void MessageComposer::addRecommend() ui.msgText->setFocus(Qt::OtherFocusReason); } -void MessageComposer::friendDetails() +void MessageComposer::contactDetails() { FriendSelectionWidget::IdType idType; std::string id = ui.friendSelectionWidget->selectedId(idType); - if (id.empty() || idType != FriendSelectionWidget::IDTYPE_SSL) { + if (id.empty()) { return; } - ConfCertDialog::showIt(RsPeerId(id), ConfCertDialog::PageDetails); -} + switch (idType) { + case FriendSelectionWidget::IDTYPE_NONE: + case FriendSelectionWidget::IDTYPE_GROUP: + case FriendSelectionWidget::IDTYPE_GPG: + break; + case FriendSelectionWidget::IDTYPE_SSL: + ConfCertDialog::showIt(RsPeerId(id), ConfCertDialog::PageDetails); + break; + case FriendSelectionWidget::IDTYPE_GXS: + { + if (RsGxsGroupId(id).isNull()) { + return; + } -void MessageComposer::identityDetails() -{ - FriendSelectionWidget::IdType idType; - std::string id = ui.friendSelectionWidget->selectedId(idType); + IdDetailsDialog *dialog = new IdDetailsDialog(RsGxsGroupId(id)); + dialog->show(); - if (id.empty() || idType != FriendSelectionWidget::IDTYPE_GXS) { - return; + /* Dialog will destroy itself */ + } + break; } - if (RsGxsGroupId(id).isNull()) { - return; - } - - IdDetailsDialog *dialog = new IdDetailsDialog(RsGxsGroupId(id)); - dialog->show(); - - /* Dialog will destroy itself */ } void MessageComposer::tagAboutToShow() diff --git a/retroshare-gui/src/gui/msgs/MessageComposer.h b/retroshare-gui/src/gui/msgs/MessageComposer.h index 6f2811730..ad286d858 100644 --- a/retroshare-gui/src/gui/msgs/MessageComposer.h +++ b/retroshare-gui/src/gui/msgs/MessageComposer.h @@ -97,7 +97,6 @@ protected: private slots: /* toggle Contacts DockWidget */ void contextMenuFileList(QPoint); - void contextMenuMsgSendList(QPoint); void pasteRecommended(); void on_contactsdockWidget_visibilityChanged(bool visible); void toggleContacts(); @@ -153,10 +152,10 @@ private slots: void addBcc(); void addRecommend(); void editingRecipientFinished(); - void friendDetails(); - void identityDetails(); + void contactDetails(); void peerStatusChanged(const QString& peer_id, int status); + void friendSelectionChanged(); void tagAboutToShow(); void tagSet(int tagId, bool set); @@ -179,6 +178,7 @@ private: void setupViewActions(); void setupInsertActions(); void setupFormatActions(); + void setupContactActions(); bool load(const QString &f); bool maybeSave(); @@ -222,6 +222,11 @@ private: *actionUpperRoman; QAction *contactSidebarAction; + QAction *mActionAddTo; + QAction *mActionAddCC; + QAction *mActionAddBCC; + QAction *mActionAddRecommend; + QAction *mActionContactDetails; QTreeView *channelstreeView;