From ecba4c2dab628e9f1e82086673a033632d507c27 Mon Sep 17 00:00:00 2001 From: Phenom Date: Wed, 2 May 2018 20:31:52 +0200 Subject: [PATCH] Add Context Menu for GxsId in lobby textBrowser. --- .../src/gui/chat/ChatLobbyDialog.cpp | 307 ++++++++++-------- retroshare-gui/src/gui/chat/ChatLobbyDialog.h | 10 +- retroshare-gui/src/gui/chat/ChatWidget.cpp | 74 ++--- retroshare-gui/src/gui/chat/ChatWidget.h | 4 + .../src/gui/common/RSTextBrowser.cpp | 27 ++ retroshare-gui/src/gui/common/RSTextBrowser.h | 2 + 6 files changed, 234 insertions(+), 190 deletions(-) diff --git a/retroshare-gui/src/gui/chat/ChatLobbyDialog.cpp b/retroshare-gui/src/gui/chat/ChatLobbyDialog.cpp index 918939917..e490af1b8 100644 --- a/retroshare-gui/src/gui/chat/ChatLobbyDialog.cpp +++ b/retroshare-gui/src/gui/chat/ChatLobbyDialog.cpp @@ -33,6 +33,7 @@ #include "gui/ChatLobbyWidget.h" #include "gui/FriendsDialog.h" #include "gui/MainWindow.h" +#include "gui/chat/ChatWidget.h" #include "gui/common/html.h" #include "gui/common/FriendSelectionDialog.h" #include "gui/common/RSTreeWidgetItem.h" @@ -97,7 +98,7 @@ ChatLobbyDialog::ChatLobbyDialog(const ChatLobbyId& lid, QWidget *parent, Qt::Wi votePositiveAct = new QAction(QIcon(":/icons/png/thumbs-up.png"), tr("Give positive opinion"), this); distantChatAct = new QAction(QIcon(":/images/chat_24.png"), tr("Start private chat"), this); sendMessageAct = new QAction(QIcon(":/images/mail_new.png"), tr("Send Message"), this); - showinpeopleAct = new QAction(QIcon(), tr("Show author in people tab"), this); + showInPeopleAct = new QAction(QIcon(), tr("Show author in people tab"), this); QActionGroup *sortgrp = new QActionGroup(this); actionSortByName = new QAction(QIcon(), tr("Sort by Name"), this); @@ -111,17 +112,13 @@ ChatLobbyDialog::ChatLobbyDialog(const ChatLobbyId& lid, QWidget *parent, Qt::Wi actionSortByActivity->setActionGroup(sortgrp); - connect(muteAct, SIGNAL(triggered()), this, SLOT(changePartipationState())); + connect(muteAct, SIGNAL(triggered()), this, SLOT(changeParticipationState())); connect(distantChatAct, SIGNAL(triggered()), this, SLOT(distantChatParticipant())); connect(sendMessageAct, SIGNAL(triggered()), this, SLOT(sendMessage())); connect(votePositiveAct, SIGNAL(triggered()), this, SLOT(voteParticipant())); connect(voteNeutralAct, SIGNAL(triggered()), this, SLOT(voteParticipant())); connect(voteNegativeAct, SIGNAL(triggered()), this, SLOT(voteParticipant())); - connect(showinpeopleAct, SIGNAL(triggered()), this, SLOT(showInPeopleTab())); - - votePositiveAct->setData(RsReputations::OPINION_POSITIVE); - voteNeutralAct->setData(RsReputations::OPINION_NEUTRAL); - voteNegativeAct->setData(RsReputations::OPINION_NEGATIVE); + connect(showInPeopleAct, SIGNAL(triggered()), this, SLOT(showInPeopleTab())); connect(actionSortByName, SIGNAL(triggered()), this, SLOT(sortParcipants())); connect(actionSortByActivity, SIGNAL(triggered()), this, SLOT(sortParcipants())); @@ -172,7 +169,8 @@ ChatLobbyDialog::ChatLobbyDialog(const ChatLobbyId& lid, QWidget *parent, Qt::Wi ui.chatWidget->addToolsAction(checkableAction); //getChatWidget()->addChatBarWidget(ownIdChooser); - + connect(ui.chatWidget, SIGNAL(textBrowserAskContextMenu(QMenu*,QString,QPoint)), this, SLOT(textBrowserAskContextMenu(QMenu*,QString,QPoint))); + connect(ownIdChooser,SIGNAL(currentIndexChanged(int)),this,SLOT(changeNickname())) ; @@ -226,33 +224,76 @@ void ChatLobbyDialog::inviteFriends() void ChatLobbyDialog::participantsTreeWidgetCustomPopupMenu(QPoint) { QList selectedItems = ui.participantsList->selectedItems(); + QList idList; + QList::iterator item; + for (item = selectedItems.begin(); item != selectedItems.end(); ++item) + { + RsGxsId gxs_id ; + dynamic_cast(*item)->getId(gxs_id) ; + idList.append(gxs_id); + } QMenu contextMnu(this); + contextMnu.addAction(actionSortByActivity); + contextMnu.addAction(actionSortByName); - contextMnu.addAction(distantChatAct); - contextMnu.addAction(sendMessageAct); - contextMnu.addSeparator(); - contextMnu.addAction(actionSortByActivity); - contextMnu.addAction(actionSortByName); - contextMnu.addSeparator(); - contextMnu.addAction(muteAct); - contextMnu.addAction(votePositiveAct); - contextMnu.addAction(voteNeutralAct); - contextMnu.addAction(voteNegativeAct); - contextMnu.addAction(showinpeopleAct); + contextMnu.addSeparator(); + + initParticipantsContextMenu(&contextMnu, idList); + + contextMnu.exec(QCursor::pos()); +} + +void ChatLobbyDialog::textBrowserAskContextMenu(QMenu* contextMnu, QString anchorForPosition, const QPoint /*point*/) +{ + if (anchorForPosition.startsWith(PERSONID)){ + QString strId = anchorForPosition.replace(PERSONID,""); + if (strId.contains(" ")) + strId.truncate(strId.indexOf(" ")); + + contextMnu->addSeparator(); + + QList idList; + idList.append(RsGxsId(strId.toStdString())); + initParticipantsContextMenu(contextMnu, idList); + } +} + +void ChatLobbyDialog::initParticipantsContextMenu(QMenu *contextMnu, QList idList) +{ + if (!contextMnu) + return; + + contextMnu->addAction(distantChatAct); + contextMnu->addAction(sendMessageAct); + contextMnu->addSeparator(); + contextMnu->addAction(muteAct); + contextMnu->addAction(votePositiveAct); + contextMnu->addAction(voteNeutralAct); + contextMnu->addAction(voteNegativeAct); + contextMnu->addAction(showInPeopleAct); distantChatAct->setEnabled(false); - sendMessageAct->setEnabled(selectedItems.count()==1); + sendMessageAct->setEnabled(true); + muteAct->setEnabled(false); muteAct->setCheckable(true); - muteAct->setEnabled(false); - muteAct->setChecked(false); - votePositiveAct->setEnabled(false); - voteNeutralAct->setEnabled(false); - voteNegativeAct->setEnabled(false); - showinpeopleAct->setEnabled(selectedItems.count()==1); - if(selectedItems.count()==1) - { - RsGxsId gxsid(selectedItems.at(0)->text(COLUMN_ID).toStdString()); + muteAct->setChecked(false); + votePositiveAct->setEnabled(false); + voteNeutralAct->setEnabled(false); + voteNegativeAct->setEnabled(false); + showInPeopleAct->setEnabled(idList.count()==1); + + distantChatAct->setData(QVariant::fromValue(idList)); + sendMessageAct->setData(QVariant::fromValue(idList)); + muteAct->setData(QVariant::fromValue(idList)); + votePositiveAct->setData(QVariant::fromValue(idList)); + voteNeutralAct->setData(QVariant::fromValue(idList)); + voteNegativeAct->setData(QVariant::fromValue(idList)); + showInPeopleAct->setData(QVariant::fromValue(idList)); + + if(idList.count()==1) + { + RsGxsId gxsid = idList.at(0); if(!gxsid.isNull() && !rsIdentity->isOwnId(gxsid)) { @@ -263,49 +304,56 @@ void ChatLobbyDialog::participantsTreeWidgetCustomPopupMenu(QPoint) muteAct->setEnabled(true); muteAct->setChecked(isParticipantMuted(gxsid)); } - } - contextMnu.exec(QCursor::pos()); + } } void ChatLobbyDialog::voteParticipant() { - QList selectedItems = ui.participantsList->selectedItems(); - if (selectedItems.isEmpty()) - return; - QList::iterator item; - - QAction *act = dynamic_cast(sender()) ; - if(!act) - { - std::cerr << "No sender! Some bug in the code." << std::endl; - return ; - } - - RsReputations::Opinion op = RsReputations::Opinion(act->data().toUInt()) ; - - for (item = selectedItems.begin(); item != selectedItems.end(); ++item) + QAction *act = dynamic_cast(sender()) ; + if(!act) { - RsGxsId nickname; - dynamic_cast(*item)->getId(nickname) ; + std::cerr << "No sender! Some bug in the code." << std::endl; + return ; + } - rsReputations->setOwnOpinion(nickname, op); - std::cerr << "Giving opinion to GXS id " << nickname << " to " << op<< std::endl; - dynamic_cast(*item)->forceUpdate(); - } + QList idList = act->data().value>(); + + RsReputations::Opinion op = RsReputations::OPINION_NEUTRAL ; + if (act == votePositiveAct) + op = RsReputations::OPINION_POSITIVE; + if (act == voteNegativeAct) + op = RsReputations::OPINION_NEGATIVE; + + for (QList::iterator item = idList.begin(); item != idList.end(); ++item) + { + rsReputations->setOwnOpinion(*item, op); + std::cerr << "Giving opinion to GXS id " << *item << " to " << op << std::endl; + } + + updateParticipantsList(); } void ChatLobbyDialog::showInPeopleTab() { - QList selectedItems = ui.participantsList->selectedItems(); - if (selectedItems.count()!=1) - return; - RsGxsId nickname; - dynamic_cast(*selectedItems.begin())->getId(nickname); - IdDialog *idDialog = dynamic_cast(MainWindow::getPage(MainWindow::People)); - if (!idDialog) - return ; - MainWindow::showWindow(MainWindow::People); - idDialog->navigate(nickname); + QAction *act = dynamic_cast(sender()) ; + if(!act) + { + std::cerr << "No sender! Some bug in the code." << std::endl; + return ; + } + + QList idList = act->data().value>(); + if (idList.count() != 1) + return; + + RsGxsId nickname = idList.at(0); + + IdDialog *idDialog = dynamic_cast(MainWindow::getPage(MainWindow::People)); + if (!idDialog) + return ; + MainWindow::showWindow(MainWindow::People); + + idDialog->navigate(nickname); } void ChatLobbyDialog::init(const ChatId &/*id*/, const QString &/*title*/) @@ -586,34 +634,28 @@ void ChatLobbyDialog::updateParticipantsList() } /** - * Called when a Participant in QTree get Clicked / Changed + * Called when a Participant get Clicked / Changed * * Check if the Checkbox altered and Mute User - * - * @todo auf rsid - * - * @param QTreeWidgetItem Participant to check */ -void ChatLobbyDialog::changePartipationState() +void ChatLobbyDialog::changeParticipationState() { - QList selectedItems = ui.participantsList->selectedItems(); - - if (selectedItems.isEmpty()) { - return; + QAction *act = dynamic_cast(sender()) ; + if(!act) + { + std::cerr << "No sender! Some bug in the code." << std::endl; + return ; } - QList::iterator item; - for (item = selectedItems.begin(); item != selectedItems.end(); ++item) { + QList idList = act->data().value>(); - RsGxsId gxs_id ; - dynamic_cast(*item)->getId(gxs_id) ; - - std::cerr << "check Partipation status for '" << gxs_id << std::endl; - - if (muteAct->isChecked()) { - muteParticipant(gxs_id); + for (QList::iterator item = idList.begin(); item != idList.end(); ++item) + { + std::cerr << "check Partipation status for '" << *item << std::endl; + if (act->isChecked()) { + muteParticipant(*item); } else { - unMuteParticipant(gxs_id); + unMuteParticipant(*item); } } @@ -650,75 +692,68 @@ void ChatLobbyDialog::participantsTreeWidgetDoubleClicked(QTreeWidgetItem *item, void ChatLobbyDialog::distantChatParticipant() { - std::cerr << " initiating distant chat" << std::endl; + QAction *act = dynamic_cast(sender()) ; + if(!act) + { + std::cerr << "No sender! Some bug in the code." << std::endl; + return ; + } - QList selectedItems = ui.participantsList->selectedItems(); + std::cerr << " initiating distant chat" << std::endl; - if (selectedItems.isEmpty()) - return; + QList idList = act->data().value>(); + if (idList.count() != 1) + return; - if(selectedItems.size() != 1) - return ; + RsGxsId gxs_id = idList.at(0); + if (gxs_id.isNull()) + return; - GxsIdRSTreeWidgetItem *item = dynamic_cast(selectedItems.front()); + RsGxsId own_id; + rsMsgs->getIdentityForChatLobby(lobbyId, own_id); - if(!item) - return ; + DistantChatPeerId tunnel_id; + uint32_t error_code ; - RsGxsId gxs_id ; - item->getId(gxs_id) ; - RsGxsId own_id; - - rsMsgs->getIdentityForChatLobby(lobbyId, own_id); - - uint32_t error_code ; - DistantChatPeerId tunnel_id; - - if(! rsMsgs->initiateDistantChatConnexion(gxs_id,own_id,tunnel_id,error_code)) - { - QString error_str ; - switch(error_code) - { - case RS_DISTANT_CHAT_ERROR_DECRYPTION_FAILED : error_str = tr("Decryption failed.") ; break ; - case RS_DISTANT_CHAT_ERROR_SIGNATURE_MISMATCH : error_str = tr("Signature mismatch") ; break ; - case RS_DISTANT_CHAT_ERROR_UNKNOWN_KEY : error_str = tr("Unknown key") ; break ; - case RS_DISTANT_CHAT_ERROR_UNKNOWN_HASH : error_str = tr("Unknown hash") ; break ; - default: - error_str = tr("Unknown error.") ; - } - QMessageBox::warning(NULL,tr("Cannot start distant chat"),tr("Distant chat cannot be initiated:")+" "+error_str - +QString::number(error_code)) ; - } + if(! rsMsgs->initiateDistantChatConnexion(gxs_id,own_id,tunnel_id,error_code)) + { + QString error_str ; + switch(error_code) + { + case RS_DISTANT_CHAT_ERROR_DECRYPTION_FAILED : error_str = tr("Decryption failed.") ; break ; + case RS_DISTANT_CHAT_ERROR_SIGNATURE_MISMATCH : error_str = tr("Signature mismatch") ; break ; + case RS_DISTANT_CHAT_ERROR_UNKNOWN_KEY : error_str = tr("Unknown key") ; break ; + case RS_DISTANT_CHAT_ERROR_UNKNOWN_HASH : error_str = tr("Unknown hash") ; break ; + default: + error_str = tr("Unknown error.") ; + } + QMessageBox::warning(NULL,tr("Cannot start distant chat"),tr("Distant chat cannot be initiated:")+" "+error_str + +QString::number(error_code)) ; + } } void ChatLobbyDialog::sendMessage() { + QAction *act = dynamic_cast(sender()) ; + if(!act) + { + std::cerr << "No sender! Some bug in the code." << std::endl; + return ; + } - QList selectedItems = ui.participantsList->selectedItems(); + QList idList = act->data().value>(); - if (selectedItems.isEmpty()) - return; + MessageComposer *nMsgDialog = MessageComposer::newMsg(); + if (nMsgDialog == NULL) + return; - QList::iterator item; - for (item = selectedItems.begin(); item != selectedItems.end(); ++item) { + for (QList::iterator item = idList.begin(); item != idList.end(); ++item) + nMsgDialog->addRecipient(MessageComposer::TO, *item); - RsGxsId gxs_id ; - dynamic_cast(*item)->getId(gxs_id) ; - - - MessageComposer *nMsgDialog = MessageComposer::newMsg(); - if (nMsgDialog == NULL) { - return; - } - - nMsgDialog->addRecipient(MessageComposer::TO, RsGxsId(gxs_id)); - nMsgDialog->show(); - nMsgDialog->activateWindow(); - - /* window will destroy itself! */ - - } + nMsgDialog->show(); + nMsgDialog->activateWindow(); + /* window will destroy itself! */ } diff --git a/retroshare-gui/src/gui/chat/ChatLobbyDialog.h b/retroshare-gui/src/gui/chat/ChatLobbyDialog.h index dbe178678..f70eb27a6 100644 --- a/retroshare-gui/src/gui/chat/ChatLobbyDialog.h +++ b/retroshare-gui/src/gui/chat/ChatLobbyDialog.h @@ -27,6 +27,8 @@ #include "gui/common/RSTreeWidgetItem.h" #include "ChatDialog.h" +Q_DECLARE_METATYPE(RsGxsId) + class GxsIdChooser ; class QToolButton; class QWidgetAction; @@ -51,6 +53,7 @@ public: private slots: void participantsTreeWidgetCustomPopupMenu( QPoint point ); + void textBrowserAskContextMenu(QMenu* contextMnu, QString anchorForPosition, const QPoint point); void inviteFriends() ; void leaveLobby() ; void filterChanged(const QString &text); @@ -77,7 +80,7 @@ protected: protected slots: void changeNickname(); - void changePartipationState(); + void changeParticipationState(); void distantChatParticipant(); void participantsTreeWidgetDoubleClicked(QTreeWidgetItem *item, int column); void sendMessage(); @@ -85,6 +88,7 @@ protected slots: private: void updateParticipantsList(); + void initParticipantsContextMenu(QMenu* contextMnu, QList idList); void filterIds(); @@ -117,8 +121,8 @@ private: QAction *actionSortByActivity; QWidgetAction *checkableAction; QAction *sendMessageAct; - QAction *showinpeopleAct; - + QAction *showInPeopleAct; + GxsIdChooser *ownIdChooser ; //icons cache QIcon bullet_red_128, bullet_grey_128, bullet_green_128, bullet_yellow_128; diff --git a/retroshare-gui/src/gui/chat/ChatWidget.cpp b/retroshare-gui/src/gui/chat/ChatWidget.cpp index c3b021458..a03e8616a 100644 --- a/retroshare-gui/src/gui/chat/ChatWidget.cpp +++ b/retroshare-gui/src/gui/chat/ChatWidget.cpp @@ -66,8 +66,6 @@ #define FMM 2.5//fontMetricsMultiplicator -#define PERSONID "PersonId:" - /***** * #define CHAT_DEBUG 1 *****/ @@ -594,31 +592,15 @@ bool ChatWidget::eventFilter(QObject *obj, QEvent *event) if (event->type() == QEvent::ToolTip) { QHelpEvent* helpEvent = static_cast(event); - QTextCursor cursor = ui->textBrowser->cursorForPosition(helpEvent->pos()); - cursor.select(QTextCursor::WordUnderCursor); - QString toolTipText = ""; - if (!cursor.selectedText().isEmpty()){ - QRegExp rx("textBrowser->getShowImages()){ - QString imageStr; - if (ui->textBrowser->checkImage(helpEvent->pos(), imageStr)) { - toolTipText = imageStr; - } - } else if (toolTipText.startsWith(PERSONID)){ - toolTipText = toolTipText.replace(PERSONID, tr("Person id: ") ); - toolTipText = toolTipText.append(tr("\nDouble click on it to add his name on text writer.") ); + QString toolTipText = ui->textBrowser->anchorForPosition(helpEvent->pos()); + if (toolTipText.isEmpty() && !ui->textBrowser->getShowImages()){ + QString imageStr; + if (ui->textBrowser->checkImage(helpEvent->pos(), imageStr)) { + toolTipText = imageStr; } + } else if (toolTipText.startsWith(PERSONID)){ + toolTipText = toolTipText.replace(PERSONID, tr("Person id: ") ); + toolTipText = toolTipText.append(tr("\nDouble click on it to add his name on text writer.") ); } if (!toolTipText.isEmpty()){ QToolTip::showText(helpEvent->globalPos(), toolTipText); @@ -710,32 +692,19 @@ bool ChatWidget::eventFilter(QObject *obj, QEvent *event) if (event->type() == QEvent::MouseButtonDblClick) { QMouseEvent* mouseEvent = static_cast(event); - QTextCursor cursor = ui->textBrowser->cursorForPosition(mouseEvent->pos()); - cursor.select(QTextCursor::WordUnderCursor); - if (!cursor.selectedText().isEmpty()){ - QRegExp rx("textBrowser->anchorForPosition(mouseEvent->pos()); + if (!anchor.isEmpty()){ + if (anchor.startsWith(PERSONID)){ + QString strId = anchor.replace(PERSONID,""); + if (strId.contains(" ")) + strId.truncate(strId.indexOf(" ")); - if (!anchors.isEmpty()){ - if (anchors.at(0).startsWith(PERSONID)){ - QString strId = QString(anchors.at(0)).replace(PERSONID,""); - if (strId.contains(" ")) - strId.truncate(strId.indexOf(" ")); - - RsGxsId mId = RsGxsId(strId.toStdString()); - if(!mId.isNull()) { - RsIdentityDetails details; - if (rsIdentity->getIdDetails(mId, details)){ - QString text = QString("@").append(GxsIdDetails::getName(details)).append(" "); - ui->chatTextEdit->textCursor().insertText(text); - } + RsGxsId mId = RsGxsId(strId.toStdString()); + if(!mId.isNull()) { + RsIdentityDetails details; + if (rsIdentity->getIdDetails(mId, details)){ + QString text = QString("@").append(GxsIdDetails::getName(details)).append(" "); + ui->chatTextEdit->textCursor().insertText(text); } } } @@ -1138,6 +1107,9 @@ void ChatWidget::contextMenuTextBrowser(QPoint point) contextMnu->addAction(ui->actionSave_image); } + QString anchor = ui->textBrowser->anchorForPosition(point); + emit textBrowserAskContextMenu(contextMnu, anchor, point); + contextMnu->exec(ui->textBrowser->viewport()->mapToGlobal(point)); delete(contextMnu); } diff --git a/retroshare-gui/src/gui/chat/ChatWidget.h b/retroshare-gui/src/gui/chat/ChatWidget.h index 30f2e8427..8de38620e 100644 --- a/retroshare-gui/src/gui/chat/ChatWidget.h +++ b/retroshare-gui/src/gui/chat/ChatWidget.h @@ -37,6 +37,9 @@ #include #include +//For PersonId anchor. +#define PERSONID "PersonId:" + class QAction; class QTextEdit; class QPushButton; @@ -137,6 +140,7 @@ signals: void infoChanged(ChatWidget*); void newMessage(ChatWidget*); void statusChanged(int); + void textBrowserAskContextMenu(QMenu* contextMnu, QString anchorForPosition, const QPoint point); protected: bool eventFilter(QObject *obj, QEvent *event); diff --git a/retroshare-gui/src/gui/common/RSTextBrowser.cpp b/retroshare-gui/src/gui/common/RSTextBrowser.cpp index 8a18b459f..03fbfe3de 100644 --- a/retroshare-gui/src/gui/common/RSTextBrowser.cpp +++ b/retroshare-gui/src/gui/common/RSTextBrowser.cpp @@ -243,3 +243,30 @@ bool RSTextBrowser::checkImage(QPoint pos, QString &imageStr) } return false; } + +/** + * @brief RSTextBrowser::anchorForPosition Replace anchorAt that doesn't works as expected. + * @param pos Where to get anchor from text + * @return anchor If text at pos is inside anchor, else empty string. + */ +QString RSTextBrowser::anchorForPosition(const QPoint &pos) const +{ + QTextCursor cursor = cursorForPosition(pos); + cursor.select(QTextCursor::WordUnderCursor); + QString anchor = ""; + if (!cursor.selectedText().isEmpty()){ + QRegExp rx("