diff --git a/retroshare-gui/src/gui/MainWindow.cpp b/retroshare-gui/src/gui/MainWindow.cpp index 06a76c4ff..5d46e5639 100644 --- a/retroshare-gui/src/gui/MainWindow.cpp +++ b/retroshare-gui/src/gui/MainWindow.cpp @@ -214,9 +214,6 @@ MainWindow::MainWindow(QWidget* parent, Qt::WFlags flags) /* Select the first action */ grp->actions()[0]->setChecked(true); - /* also an empty list of chat windows */ - messengerWindow->setChatDialog(peersDialog); - /** StatusBar section ********/ peerstatus = new PeerStatus(); statusBar()->addWidget(peerstatus); diff --git a/retroshare-gui/src/gui/MessengerWindow.cpp b/retroshare-gui/src/gui/MessengerWindow.cpp index 77029fa98..208e7d442 100644 --- a/retroshare-gui/src/gui/MessengerWindow.cpp +++ b/retroshare-gui/src/gui/MessengerWindow.cpp @@ -26,6 +26,8 @@ #include "rsiface/rsiface.h" #include "rsiface/rspeers.h" #include "rsiface/rsmsgs.h" +#include "rsiface/rsstatus.h" +#include "rsiface/rsnotify.h" #include "rshare.h" #include "MessengerWindow.h" @@ -54,15 +56,20 @@ #include #include - /* Images for context menu icons */ #define IMAGE_REMOVEFRIEND ":/images/removefriend16.png" #define IMAGE_EXPIORTFRIEND ":/images/exportpeers_16x16.png" #define IMAGE_CHAT ":/images/chat.png" -#define IMAGE_SENDMESSAGE ":/images/message-mail.png" +#define IMAGE_MSG ":/images/message-mail.png" +#define IMAGE_CONNECT ":/images/connect_friend.png" +#define IMAGE_PEERINFO ":/images/peerdetails_16x16.png" +#define IMAGE_AVAIBLE ":/images/user/identityavaiblecyan24.png" +#define IMAGE_CONNECT2 ":/images/reload24.png" + /* Images for Status icons */ #define IMAGE_ONLINE ":/images/im-user.png" #define IMAGE_OFFLINE ":/images/im-user-offline.png" + /* Images for Status icons */ #define IMAGE_ON ":/images/contract_hover.png" #define IMAGE_OFF ":/images/expand_hover.png" @@ -96,22 +103,22 @@ MessengerWindow::MessengerWindow(QWidget* parent, Qt::WFlags flags) /* Invoke the Qt Designer generated object setup routine */ ui.setupUi(this); - connect( ui.messengertreeWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( messengertreeWidgetCostumPopupMenu( QPoint ) ) ); + connect( ui.messengertreeWidget, SIGNAL(itemDoubleClicked ( QTreeWidgetItem *, int)), this, SLOT(chatfriend())); connect( ui.avatarButton, SIGNAL(clicked()), SLOT(getAvatar())); connect( ui.shareButton, SIGNAL(clicked()), SLOT(openShareManager())); - - connect( ui.addIMAccountButton, SIGNAL(clicked( bool ) ), this , SLOT( addFriend2() ) ); - - connect( ui.messengertreeWidget, SIGNAL(itemDoubleClicked ( QTreeWidgetItem *, int)), this, SLOT(chatfriend2())); + connect( ui.addIMAccountButton, SIGNAL(clicked( bool ) ), this , SLOT( addFriend() ) ); /* to hide the header */ ui.messengertreeWidget->header()->hide(); /* Set header resize modes and initial section sizes */ - ui.messengertreeWidget->setColumnCount(1); + ui.messengertreeWidget->setColumnCount(4); + ui.messengertreeWidget->setColumnHidden ( 3, true); + ui.messengertreeWidget->setColumnHidden ( 2, true); + //ui.messengertreeWidget->sortItems( 0, Qt::AscendingOrder ); QHeaderView * _header = ui.messengertreeWidget->header () ; _header->setResizeMode (0, QHeaderView::Interactive); @@ -123,17 +130,18 @@ MessengerWindow::MessengerWindow(QWidget* parent, Qt::WFlags flags) _rsLogoBarmessenger = new LogoBar(ui.logoframe); Widget::createLayout(ui.logoframe)->addWidget(_rsLogoBarmessenger); - ui.statuscomboBox->setMinimumWidth(20); ui.messagelineEdit->setMinimumWidth(20); - ui.searchlineEdit->setMinimumWidth(20); - updateAvatar(); - insertPeers(); itemFont = QFont("ARIAL", 10); itemFont.setBold(true); - + + insertPeers(); + updateAvatar(); loadmystatus(); + loadstatus(); + + displayMenu(); /* Hide platform specific features */ #ifdef Q_WS_WIN @@ -146,211 +154,595 @@ void MessengerWindow::messengertreeWidgetCostumPopupMenu( QPoint point ) QMenu contextMnu( this ); QMouseEvent *mevent = new QMouseEvent( QEvent::MouseButtonPress, point, Qt::RightButton, Qt::RightButton, Qt::NoModifier ); + QAction* expandAll = new QAction(tr( "Expand all" ), this ); + connect( expandAll , SIGNAL( triggered() ), ui.messengertreeWidget, SLOT (expandAll()) ); + + QAction* collapseAll = new QAction(tr( "Collapse all" ), this ); + connect( collapseAll , SIGNAL( triggered() ), ui.messengertreeWidget, SLOT(collapseAll()) ); + chatAct = new QAction(QIcon(IMAGE_CHAT), tr( "Chat" ), this ); - connect( chatAct , SIGNAL( triggered() ), this, SLOT( chatfriend2() ) ); - - sendMessageAct = new QAction(QIcon(IMAGE_SENDMESSAGE), tr( "Send Message" ), this ); + connect( chatAct , SIGNAL( triggered() ), this, SLOT( chatfriend() ) ); + + sendMessageAct = new QAction(QIcon(IMAGE_MSG), tr( "Message Friend" ), this ); connect( sendMessageAct , SIGNAL( triggered() ), this, SLOT( sendMessage() ) ); - connectfriendAct = new QAction( tr( "Connect To Friend" ), this ); - connect( connectfriendAct , SIGNAL( triggered() ), this, SLOT( connectfriend2() ) ); - - /************ Do we want these options here??? - * - * - configurefriendAct = new QAction( tr( "Configure Friend" ), this ); - connect( configurefriendAct , SIGNAL( triggered() ), this, SLOT( configurefriend2() ) ); - - exportfriendAct = new QAction(QIcon(IMAGE_EXPIORTFRIEND), tr( "Export Friend" ), this ); - connect( exportfriendAct , SIGNAL( triggered() ), this, SLOT( exportfriend2() ) ); - * - * - *********/ - - removefriend2Act = new QAction(QIcon(IMAGE_REMOVEFRIEND), tr( "Remove Friend" ), this ); - connect( removefriend2Act , SIGNAL( triggered() ), this, SLOT( removefriend2() ) ); + connectfriendAct = new QAction(QIcon(IMAGE_CONNECT), tr( "Connect To Friend" ), this ); + connect( connectfriendAct , SIGNAL( triggered() ), this, SLOT( connectfriend() ) ); + configurefriendAct = new QAction(QIcon(IMAGE_PEERINFO), tr( "Peer Details" ), this ); + connect( configurefriendAct , SIGNAL( triggered() ), this, SLOT( configurefriend() ) ); + + //profileviewAct = new QAction(QIcon(IMAGE_PEERINFO), tr( "Profile View" ), this ); + //connect( profileviewAct , SIGNAL( triggered() ), this, SLOT( viewprofile() ) ); + + exportfriendAct = new QAction(QIcon(IMAGE_EXPIORTFRIEND), tr( "Export Friend" ), this ); + connect( exportfriendAct , SIGNAL( triggered() ), this, SLOT( exportfriend() ) ); + + QTreeWidgetItem *c = getCurrentPeer(); + if (c->type() == 0) { + //this is a GPG key + removefriendAct = new QAction(QIcon(IMAGE_REMOVEFRIEND), tr( "Deny Friend" ), this ); + } else { + removefriendAct = new QAction(QIcon(IMAGE_REMOVEFRIEND), tr( "Remove Friend Location" ), this ); + } + connect( removefriendAct , SIGNAL( triggered() ), this, SLOT( removefriend() ) ); + + + QWidget *widget = new QWidget(); + widget->setStyleSheet( ".QWidget{background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 #FEFEFE, stop:1 #E8E8E8); border: 1px solid #CCCCCC;}"); + + QHBoxLayout *hbox = new QHBoxLayout(); + hbox->setMargin(0); + hbox->setSpacing(6); + + iconLabel = new QLabel( this ); + iconLabel->setPixmap(QPixmap::QPixmap(":/images/user/friends24.png")); + iconLabel->setMaximumSize( iconLabel->frameSize().height() + 24, 24 ); + hbox->addWidget(iconLabel); + + if (c->type() == 0) { + //this is a GPG key + textLabel = new QLabel( tr("GPG Key"), this ); + } else { + textLabel = new QLabel( tr("RetroShare instance"), this ); + } + + hbox->addWidget(textLabel); + + spacerItem = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + hbox->addItem(spacerItem); + + widget->setLayout( hbox ); + + QWidgetAction *widgetAction = new QWidgetAction(this); + widgetAction->setDefaultWidget(widget); contextMnu.clear(); + contextMnu.addAction( widgetAction); contextMnu.addAction( chatAct); contextMnu.addAction( sendMessageAct); - contextMnu.addSeparator(); - contextMnu.addAction( connectfriendAct); - contextMnu.addAction( removefriend2Act); - - /**** Do we want these options here??? - * - * contextMnu.addAction( configurefriendAct); - contextMnu.addAction( exportfriendAct); - * - * - ****/ - + //contextMnu.addAction( profileviewAct); + if (c->type() != 0) { + //this is a SSL key + contextMnu.addAction( connectfriendAct); + } + contextMnu.addAction( removefriendAct); + //contextMnu.addAction( exportfriendAct); + contextMnu.addSeparator(); + contextMnu.addAction( expandAll); + contextMnu.addAction( collapseAll); contextMnu.exec( mevent->globalPos() ); } +void MessengerWindow::updateMessengerDisplay() +{ + // add self nick and Avatar to Friends. + RsPeerDetails pd ; + if (rsPeers->getPeerDetails(rsPeers->getOwnId(),pd)) { + } + + insertPeers() ; +} + /* get the list of peers from the RsIface. */ void MessengerWindow::insertPeers() { - if (!rsPeers) - { - + std::list gpgFriends; + std::list::iterator it; + + if (!rsPeers) { /* not ready yet! */ + std::cerr << "PeersDialog::insertPeers() not ready yet : rsPeers unintialized." << std::endl; return; } - std::list peers; - std::list::iterator it; + rsPeers->getGPGAcceptedList(gpgFriends); + + //add own gpg id, if we have more than on location (ssl client) + std::list ownSslContacts; + rsPeers->getSSLChildListOfGPGId(rsPeers->getGPGOwnId(), ownSslContacts); + if (ownSslContacts.size() > 0) { + gpgFriends.push_back(rsPeers->getGPGOwnId()); + } - rsPeers->getFriendList(peers); - /* get a link to the table */ - QTreeWidget *peerWidget = ui.messengertreeWidget; + QTreeWidget *peertreeWidget = ui.messengertreeWidget; - /* have two lists: online / offline */ - QList online_items; - QList offline_items; - - for(it = peers.begin(); it != peers.end(); it++) - { - RsPeerDetails details; - if (!rsPeers->getPeerDetails(*it, details)) - { - continue; /* BAD */ + //remove items that are not fiends anymore + int index = 0; + while (index < peertreeWidget->topLevelItemCount()) { + std::string gpg_widget_id = (peertreeWidget->topLevelItem(index))->text(3).toStdString(); + std::list::iterator gpgfriendIt; + bool found = false; + for (gpgfriendIt = gpgFriends.begin(); gpgfriendIt != gpgFriends.end(); gpgfriendIt++) { + if (gpg_widget_id == *gpgfriendIt) { + found = true; + break; } - - /* make a widget per friend */ - QTreeWidgetItem *item = new QTreeWidgetItem((QTreeWidget*)0); + } + if (!found) { + peertreeWidget->takeTopLevelItem(index); + } else { + index++; + } + } - /* add all the labels */ - /* (0) Person */ - if (rsMsgs->getCustomStateString(details.id) != "") - { - item -> setText( 0, QString::fromStdString(details.name) + tr(" - ") + QString::fromStdString(rsMsgs->getCustomStateString(details.id))); - } - else - { - item -> setText(0, QString::fromStdString(details.name)); - } - - /* Hidden ones: RsCertId */ - item -> setText(4, QString::fromStdString(details.id)); + //add the gpg friends + for(it = gpgFriends.begin(); it != gpgFriends.end(); it++) { + std::cerr << "" << *it << std::endl; +// if (*it == rsPeers->getGPGOwnId()) { +// continue; +// } - /* add to the list */ - if (details.state & RS_PEER_STATE_CONNECTED) - { - online_items.append(item); - item -> setIcon(0,(QIcon(IMAGE_ONLINE))); - item -> setFont(0,itemFont); - } - else - { - offline_items.append(item); - item -> setIcon(0,(QIcon(IMAGE_OFFLINE))); - } - } + /* make a widget per friend */ + QTreeWidgetItem *gpg_item; + QList list = peertreeWidget->findItems(QString::fromStdString(*it), Qt::MatchExactly, 3); + if (list.size() == 1) { + gpg_item = list.front(); + } else { + gpg_item = new QTreeWidgetItem(0); //set type to 0 for custom popup menu + gpg_item->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless); + } - /* remove old items */ - peerWidget->clear(); - peerWidget->setColumnCount(1); + RsPeerDetails detail; + if ((!rsPeers->getPeerDetails(*it, detail) || !detail.accept_connection) + && detail.gpg_id != rsPeers->getGPGOwnId()) { + //don't accept anymore connection, remove from the view + peertreeWidget->takeTopLevelItem(peertreeWidget->indexOfTopLevelItem(gpg_item)); + continue; + } - if (online_items.size() > 0) - { - QTreeWidgetItem *item = new QTreeWidgetItem((QTreeWidget*)0); + //use to mark item as updated + gpg_item->setData(0, Qt::UserRole, true); - /* add all the labels */ - /* (0) Person */ - item -> setText(0, tr("Online")); - item -> addChildren(online_items); - item -> setFont(0,itemFont); + gpg_item -> setTextAlignment(0, Qt::AlignLeft | Qt::AlignVCenter ); - //item -> setIcon(0,(QIcon(IMAGE_ON))); - peerWidget->addTopLevelItem(item); - peerWidget->expandItem(item); - } + /* not displayed, used to find back the item */ + gpg_item -> setText(3, QString::fromStdString(detail.id)); - if (offline_items.size() > 0) - { - QTreeWidgetItem *item = new QTreeWidgetItem((QTreeWidget*)0); + //remove items that are not friends anymore + int childIndex = 0; + while (childIndex < gpg_item->childCount()) { + std::string ssl_id = (gpg_item->child(childIndex))->text(3).toStdString(); + if (!rsPeers->isFriend(ssl_id)) { + gpg_item->takeChild(childIndex); + } else { + childIndex++; + } + } - /* add all the labels */ - /* (0) Person */ - item -> setText(0, tr("Offline")); - item -> addChildren(offline_items); - item -> setFont(0,itemFont); - - peerWidget->addTopLevelItem(item); - peerWidget->expandItem(item); - //item -> setIcon(0,(QIcon(IMAGE_OFF))); - } + //update the childs (ssl certs) + bool gpg_connected = false; + bool gpg_online = false; + std::list sslContacts; + rsPeers->getSSLChildListOfGPGId(detail.gpg_id, sslContacts); + for(std::list::iterator sslIt = sslContacts.begin(); sslIt != sslContacts.end(); sslIt++) { + QTreeWidgetItem *sslItem; - peerWidget->update(); /* update display */ + //find the corresponding sslItem child item of the gpg item + bool newChild = true; + for (int childIndex = 0; childIndex < gpg_item->childCount(); childIndex++) { + if (gpg_item->child(childIndex)->text(3).toStdString() == *sslIt) { + sslItem = gpg_item->child(childIndex); + newChild = false; + break; + } + } + if (newChild) { + sslItem = new QTreeWidgetItem(1); //set type to 1 for custom popup menu + } + + RsPeerDetails sslDetail; + if (!rsPeers->getPeerDetails(*sslIt, sslDetail) || !rsPeers->isFriend(*sslIt)) { + std::cerr << "Removing widget from the view : id : " << *sslIt << std::endl; + //child has disappeared, remove it from the gpg_item + gpg_item->removeChild(sslItem); + } + + /* not displayed, used to find back the item */ + sslItem -> setText(3, QString::fromStdString(sslDetail.id)); + + if (rsMsgs->getCustomStateString(sslDetail.id) != "") { + sslItem -> setText( 0, tr("location : ") + QString::fromStdString(sslDetail.location) ); + sslItem -> setToolTip( 0, tr("location : ") + QString::fromStdString(sslDetail.location) + tr(" - ") + QString::fromStdString(rsMsgs->getCustomStateString(sslDetail.id))); + gpg_item -> setText(0, QString::fromStdString(detail.name) + tr("\n") + QString::fromStdString(rsMsgs->getCustomStateString(sslDetail.id))); + + } else { + sslItem -> setText( 0, tr("location : ") + QString::fromStdString(sslDetail.location)); + sslItem -> setToolTip( 0, tr("location : ") + QString::fromStdString(sslDetail.location)); + gpg_item -> setText(0, QString::fromStdString(detail.name) + tr("\n") + QString::fromStdString(sslDetail.location)); + } + + + /* not displayed, used to find back the item */ + sslItem -> setText(1, QString::fromStdString(sslDetail.autoconnect)); + + int i; + if (sslDetail.state & RS_PEER_STATE_CONNECTED) { + sslItem->setHidden(false); + gpg_connected = true; + + /* change color and icon */ + sslItem -> setIcon(0,(QIcon(":/images/connect_established.png"))); + sslItem -> setIcon(1,(QIcon(":/images/encrypted32.png"))); + QFont font; + font.setBold(true); + for(i = 0; i < 3; i++) { + sslItem -> setTextColor(i,(Qt::darkBlue)); + sslItem -> setFont(i,font); + } + } else if (sslDetail.state & RS_PEER_STATE_ONLINE) { + sslItem->setHidden(ui.actionHide_Offline_Friends->isChecked()); + gpg_online = true; + + QFont font; + font.setBold(true); + for(i = 0; i < 3; i++) { + sslItem -> setTextColor(i,(Qt::black)); + sslItem -> setFont(i,font); + } + } else { + sslItem->setHidden(ui.actionHide_Offline_Friends->isChecked()); + if (sslDetail.autoconnect !="Offline") { + sslItem -> setIcon(0, (QIcon(":/images/connect_creating.png"))); + } else { + sslItem -> setIcon(0, (QIcon(":/images/connect_no.png"))); + } + + QFont font; + font.setBold(false); + for(i = 0; i < 3; i++) { + sslItem -> setTextColor(i,(Qt::black)); + sslItem -> setFont(i,font); + } + } + + #ifdef PEERS_DEBUG + std::cerr << "PeersDialog::insertPeers() inserting sslItem." << std::endl; + #endif + /* add sl child to the list. If item is already in the list, it won't be duplicated thanks to Qt */ + gpg_item->addChild(sslItem); + if (newChild) { + gpg_item->setExpanded(true); + } + } + + int i = 0; + if (gpg_connected) { + gpg_item->setHidden(false); + gpg_item -> setIcon(0,(QIcon(IMAGE_ONLINE))); + gpg_item -> setText(1, tr("Online")); + + QFont font; + font.setBold(true); + for(i = 0; i < 3; i++) { + gpg_item -> setTextColor(i,(Qt::darkBlue)); + gpg_item -> setFont(i,font); + } + } else if (gpg_online) { + gpg_item->setHidden(ui.actionHide_Offline_Friends->isChecked()); + gpg_item -> setIcon(0,(QIcon(IMAGE_AVAIBLE))); + gpg_item -> setText(1, tr("Available")); + QFont font; + font.setBold(true); + for(i = 0; i < 3; i++) { + gpg_item -> setTextColor(i,(Qt::black)); + gpg_item -> setFont(i,font); + } + } else { + gpg_item->setHidden(ui.actionHide_Offline_Friends->isChecked()); + gpg_item -> setIcon(0,(QIcon(IMAGE_OFFLINE))); + gpg_item -> setText(1, tr("Offline")); + QFont font; + font.setBold(false); + for(i = 0; i < 3; i++) { + gpg_item -> setTextColor(i,(Qt::black)); + gpg_item -> setFont(i,font); + } + } + + /* add gpg item to the list. If item is already in the list, it won't be duplicated thanks to Qt */ + peertreeWidget->addTopLevelItem(gpg_item); + } } /* Utility Fns */ -std::string getMessengerPeerRsCertId(QTreeWidgetItem *i) +std::string getPeersRsCertId(QTreeWidgetItem *i) { - std::string id = (i -> text(4)).toStdString(); + std::string id = (i -> text(3)).toStdString(); return id; } +/** Add a Friend ShortCut */ +void MessengerWindow::addFriend() +{ + ConnectFriendWizard* connwiz = new ConnectFriendWizard(this); + // set widget to be deleted after close + connwiz->setAttribute( Qt::WA_DeleteOnClose, true); + + connwiz->show(); + +} /** Open a QFileDialog to browse for export a file. */ -void MessengerWindow::exportfriend2() +void MessengerWindow::exportfriend() { + QTreeWidgetItem *c = getCurrentPeer(); + +#ifdef PEERS_DEBUG + std::cerr << "PeersDialog::exportfriend()" << std::endl; +#endif + if (!c) + { +#ifdef PEERS_DEBUG + std::cerr << "PeersDialog::exportfriend() None Selected -- sorry" << std::endl; +#endif + return; + } + + std::string id = getPeersRsCertId(c); + QString fileName = QFileDialog::getSaveFileName(this, tr("Save Certificate"), "", + tr("Certificates (*.pqi)")); + + std::string file = fileName.toStdString(); + if (file != "") + { +#ifdef PEERS_DEBUG + std::cerr << "PeersDialog::exportfriend() Saving to: " << file << std::endl; + std::cerr << std::endl; +#endif + if (rsPeers) + { + rsPeers->saveCertificateToFile(id, file); + } + } } - -void MessengerWindow::allowfriend2() +void MessengerWindow::chatfriend() { - -} + QTreeWidgetItem *i = getCurrentPeer(); - -void MessengerWindow::connectfriend2() -{ - bool isOnline; - QTreeWidgetItem *i = getCurrentPeer(isOnline); if (!i) - return; + return; - std::string id = (i -> text(4)).toStdString(); - if (rsPeers->isOnline(id)) - { -#ifdef MSG_DEBUG - std::cerr << "MessengerWindow::connectfriend2() Already online" << std::endl; -#endif + //std::string name = (i -> text(2)).toStdString(); + std::string id = (i -> text(3)).toStdString(); + + bool oneLocationConnected = false; + + RsPeerDetails detail; + if (!rsPeers->getPeerDetails(id, detail)) { + return; } - else - { -#ifdef MSG_DEBUG - std::cerr << "MessengerWindow::connectfriend2() Trying" << std::endl; -#endif - rsPeers->connectAttempt(getMessengerPeerRsCertId(i)); + + if (detail.isOnlyGPGdetail) { + //let's get the ssl child details, and open all the chat boxes + std::list sslIds; + rsPeers->getSSLChildListOfGPGId(detail.gpg_id, sslIds); + for (std::list::iterator it = sslIds.begin(); it != sslIds.end(); it++) { + RsPeerDetails sslDetails; + if (rsPeers->getPeerDetails(*it, sslDetails)) { + if (sslDetails.state & RS_PEER_STATE_CONNECTED) { + oneLocationConnected = true; + getPrivateChat(*it, sslDetails.name + " - " + sslDetails.location, RS_CHAT_REOPEN); + } + } + } + } else { + if (detail.state & RS_PEER_STATE_CONNECTED) { + oneLocationConnected = true; + getPrivateChat(id, detail.name + " - " + detail.location, RS_CHAT_REOPEN); + } } + + if (!oneLocationConnected) { + /* info dialog */ + QMessageBox::StandardButton sb = QMessageBox::question ( NULL, + "Friend Not Online", + "Your Friend is offline \nDo you want to send them a Message instead", + (QMessageBox::Yes | QMessageBox::No)); + if (sb == QMessageBox::Yes) { + sendMessage(); + } + } + return; } -void MessengerWindow::setaddressfriend2() +QTreeWidgetItem *MessengerWindow::getCurrentPeer() { - + /* get the current, and extract the Id */ + + /* get a link to the table */ + QTreeWidget *peerWidget = ui.messengertreeWidget; + QTreeWidgetItem *item = peerWidget -> currentItem(); + if (!item) + { +#ifdef PEERS_DEBUG + std::cerr << "Invalid Current Item" << std::endl; +#endif + return NULL; + } + +#ifdef PEERS_DEBUG + /* Display the columns of this item. */ + std::ostringstream out; + out << "CurrentPeerItem: " << std::endl; + + for(int i = 1; i < 6; i++) + { + QString txt = item -> text(i); + out << "\t" << i << ":" << txt.toStdString() << std::endl; + } + std::cerr << out.str(); +#endif + return item; } -void MessengerWindow::trustfriend2() +/* So from the Peers Dialog we can call the following control Functions: + * (1) Remove Current. FriendRemove(id) + * (2) Allow/DisAllow. FriendStatus(id, accept) + * (2) Connect. FriendConnectAttempt(id, accept) + * (3) Set Address. FriendSetAddress(id, str, port) + * (4) Set Trust. FriendTrustSignature(id, bool) + * (5) Configure (GUI Only) -> 3/4 + * + * All of these rely on the finding of the current Id. + */ + + +void MessengerWindow::removefriend() { - + QTreeWidgetItem *c = getCurrentPeer(); +#ifdef PEERS_DEBUG + std::cerr << "PeersDialog::removefriend()" << std::endl; +#endif + if (!c) + { +#ifdef PEERS_DEBUG + std::cerr << "PeersDialog::removefriend() Noone Selected -- sorry" << std::endl; +#endif + return; + } + + if (rsPeers) + { + rsPeers->removeFriend(getPeersRsCertId(c)); + emit friendsUpdated() ; + } } +void MessengerWindow::connectfriend() +{ + QTreeWidgetItem *c = getCurrentPeer(); +#ifdef PEERS_DEBUG + std::cerr << "PeersDialog::connectfriend()" << std::endl; +#endif + if (!c) + { +#ifdef PEERS_DEBUG + std::cerr << "PeersDialog::connectfriend() Noone Selected -- sorry" << std::endl; +#endif + return; + } + if (rsPeers) + { + rsPeers->connectAttempt(getPeersRsCertId(c)); + c -> setIcon(0,(QIcon(IMAGE_CONNECT2))); + } +} /* GUI stuff -> don't do anything directly with Control */ -void MessengerWindow::configurefriend2() +void MessengerWindow::configurefriend() { - + ConfCertDialog::show(getPeersRsCertId(getCurrentPeer())); } +void MessengerWindow::updatePeersAvatar(const QString& peer_id) +{ + std::cerr << "PeersDialog: Got notified of new avatar for peer " << peer_id.toStdString() << std::endl ; + + PopupChatDialog *pcd = getPrivateChat(peer_id.toStdString(),rsPeers->getPeerName(peer_id.toStdString()), 0); + pcd->updatePeerAvatar(peer_id.toStdString()); +} + +//============================================================================ + +PopupChatDialog * +MessengerWindow::getPrivateChat(std::string id, std::string name, uint chatflags) +{ + /* see if it exists already */ + PopupChatDialog *popupchatdialog = NULL; + bool show = false; + + if (chatflags & RS_CHAT_REOPEN) + { + show = true; + std::cerr << "reopen flag so: enable SHOW popupchatdialog()"; + std::cerr << std::endl; + } + + + std::map::iterator it; + if (chatDialogs.end() != (it = chatDialogs.find(id))) + { + /* exists already */ + popupchatdialog = it->second; + } + else + { + popupchatdialog = new PopupChatDialog(id, name); + chatDialogs[id] = popupchatdialog; + + if (chatflags & RS_CHAT_OPEN_NEW) + { + std::cerr << "new chat so: enable SHOW popupchatdialog()"; + std::cerr << std::endl; + + show = true; + } + } + + if (show) + { + std::cerr << "SHOWING popupchatdialog()"; + std::cerr << std::endl; + + popupchatdialog->show(); + } + + /* now only do these if the window is visible */ + if (popupchatdialog->isVisible()) + { + if (chatflags & RS_CHAT_FOCUS) + { + std::cerr << "focus chat flag so: GETFOCUS popupchatdialog()"; + std::cerr << std::endl; + + popupchatdialog->getfocus(); + } + else + { + std::cerr << "no focus chat flag so: FLASH popupchatdialog()"; + std::cerr << std::endl; + + popupchatdialog->flash(); + } + } + else + { + std::cerr << "not visible ... so leave popupchatdialog()"; + std::cerr << std::endl; + } + + return popupchatdialog; +} + +//============================================================================ + /** Overloads the default show */ void MessengerWindow::show() @@ -374,13 +766,6 @@ void MessengerWindow::closeEvent (QCloseEvent * event) event->ignore(); } -/** Shows MessagesPopupDialog */ -void MessengerWindow::showMessagesPopup() -{ - static MessagesPopupDialog* messagespopup = new MessagesPopupDialog(this); - messagespopup->show(); -} - /** Shows Share Manager */ void MessengerWindow::openShareManager() { @@ -388,74 +773,29 @@ void MessengerWindow::openShareManager() } -/** Shows Messages */ -/*void MessengerWindow::showMessages(MainWindow::Page page) -{ - showWindow(page); -}*/ - - -void MessengerWindow::setChatDialog(PeersDialog *cd) -{ - chatDialog = cd; -} - -void MessengerWindow::chatfriend2() -{ - bool isOnline; - QTreeWidgetItem *i = getCurrentPeer(isOnline); - if (!i) - return; - - std::string name = (i -> text(0)).toStdString(); - std::string id = (i -> text(4)).toStdString(); - - if (!(rsPeers->isOnline(id))) - { - /* info dialog */ - QMessageBox::StandardButton sb = QMessageBox::question ( NULL, - "Friend Not Online", - "Your Friend is offline \nDo You want to send them a Message instead", - (QMessageBox::Yes | QMessageBox::No )); - if (sb == QMessageBox::Yes) - { - rsicontrol -> ClearInMsg(); - rsicontrol -> SetInMsg(id, true); - - /* create a message */ - ChanMsgDialog *nMsgDialog = new ChanMsgDialog(true); - - nMsgDialog->newMsg(); - nMsgDialog->show(); - } - return; - } - - /* must reference ChatDialog */ - if (chatDialog) - { - chatDialog->getPrivateChat(id, name, true); - } -} - void MessengerWindow::sendMessage() { - bool isOnline; -#ifdef MSG_DEBUG - std::cerr << "SharedFilesDialog::msgfriend()" << std::endl; +#ifdef MESSENGERWINDOW_DEBUG + std::cerr << "SharedFilesDialog::sendMessage()" << std::endl; #endif - QTreeWidgetItem *i = getCurrentPeer(isOnline); + QTreeWidgetItem *i = getCurrentPeer(); if (!i) return; - //std::string status = (i -> text(0)).toStdString(); - std::string name = (i -> text(0)).toStdString(); - std::string id = (i -> text(4)).toStdString(); + std::string status = (i -> text(1)).toStdString(); + std::string name = (i -> text(2)).toStdString(); + std::string id = (i -> text(3)).toStdString(); rsicontrol -> ClearInMsg(); rsicontrol -> SetInMsg(id, true); + std::list sslIds; + rsPeers->getSSLChildListOfGPGId(id, sslIds); + for (std::list::iterator it = sslIds.begin(); it != sslIds.end(); it++) { + //put all sslChilds in message list + rsicontrol -> SetInMsg(*it, true); + } /* create a message */ ChanMsgDialog *nMsgDialog = new ChanMsgDialog(true); @@ -464,52 +804,8 @@ void MessengerWindow::sendMessage() nMsgDialog->show(); } -QTreeWidgetItem *MessengerWindow::getCurrentPeer(bool &isOnline) -{ - /* get the current, and extract the Id */ - - /* get a link to the table */ - QTreeWidget *peerWidget = ui.messengertreeWidget; - QTreeWidgetItem *item = peerWidget -> currentItem(); - if (!item) - { -#ifdef MSG_DEBUG - std::cerr << "Invalid Current Item" << std::endl; -#endif - return NULL; - } - - /* check if parent is online or offline */ - QTreeWidgetItem *parent = item->parent(); - if ((!parent) || - (parent == peerWidget->invisibleRootItem())) - { -#ifdef MSG_DEBUG - std::cerr << "Selected Parent Invalid Item" << std::endl; -#endif - return NULL; - } - - isOnline = (parent->text(0) == "Online"); - - return item; -} - -void MessengerWindow::removefriend2() -{ - bool isOnline; - QTreeWidgetItem *c = getCurrentPeer(isOnline); -#ifdef MSG_DEBUG - std::cerr << "MessengerWindow::removefriend2()" << std::endl; -#endif - if (!c) - { -#ifdef MSG_DEBUG - std::cerr << "MessengerWindow::removefriend2() Noone Selected -- sorry" << std::endl; -#endif - return; - } - rsPeers->removeFriend(getMessengerPeerRsCertId(c)); +LogoBar & MessengerWindow::getLogoBar() const { + return *_rsLogoBarmessenger; } void MessengerWindow::changeAvatarClicked() @@ -518,22 +814,6 @@ void MessengerWindow::changeAvatarClicked() updateAvatar(); } - -/** Add a Friend ShortCut */ -void MessengerWindow::addFriend2() -{ - ConnectFriendWizard* connwiz = new ConnectFriendWizard(this); - // set widget to be deleted after close - connwiz->setAttribute( Qt::WA_DeleteOnClose, true); - - connwiz->show(); - -} - -LogoBar & MessengerWindow::getLogoBar() const { - return *_rsLogoBarmessenger; -} - void MessengerWindow::updateAvatar() { unsigned char *data = NULL; @@ -582,3 +862,76 @@ void MessengerWindow::loadmystatus() { ui.messagelineEdit->setText(QString::fromStdString(rsMsgs->getCustomStateString())); } + +void MessengerWindow::on_actionSort_Peers_Descending_Order_activated() +{ + ui.messengertreeWidget->sortItems ( 0, Qt::DescendingOrder ); +} + +void MessengerWindow::on_actionSort_Peers_Ascending_Order_activated() +{ + ui.messengertreeWidget->sortItems ( 0, Qt::AscendingOrder ); +} + +void MessengerWindow::on_actionRoot_is_decorated_activated() +{ + ui.messengertreeWidget->setRootIsDecorated(true); +} + +void MessengerWindow::on_actionRoot_isnot_decorated_activated() +{ + ui.messengertreeWidget->setRootIsDecorated(false); +} + +void MessengerWindow::displayMenu() +{ + QMenu *lookmenu = new QMenu(); + lookmenu->addAction(ui.actionSort_Peers_Descending_Order); + lookmenu->addAction(ui.actionSort_Peers_Ascending_Order); + lookmenu->addAction(ui.actionHide_Offline_Friends); + + QMenu *viewMenu = new QMenu( tr("View"), this ); + viewMenu->addAction(ui.actionRoot_is_decorated); + viewMenu->addAction(ui.actionRoot_isnot_decorated); + lookmenu->addMenu( viewMenu); + + ui.displaypushButton->setMenu(lookmenu); + +} + +/** Load own status Online,Away,Busy **/ +void MessengerWindow::loadstatus() +{ + /* load up configuration from rsPeers */ + /*RsPeerDetails detail; + if (!rsPeers->getPeerDetails(rsPeers->getOwnId(), detail)) + { + return; + } + + StatusInfo si; + if (!rsStatus->getStatus(detail.id, si)) + { + return; + }*/ + + /* set status mode */ + /*int statusIndex = 0; + switch(si.status) + { + case RS_STATUS_OFFLINE: + statusIndex = 3; + break; + case RS_STATUS_AWAY: + statusIndex = 2; + break; + case RS_STATUS_BUSY: + statusIndex = 1; + break; + default: + case RS_STATUS_ONLINE: + statusIndex = 0; + break; + } + ui.statuscomboBox->setCurrentIndex(statusIndex);*/ +} diff --git a/retroshare-gui/src/gui/MessengerWindow.h b/retroshare-gui/src/gui/MessengerWindow.h index 5082c7300..721381b8e 100644 --- a/retroshare-gui/src/gui/MessengerWindow.h +++ b/retroshare-gui/src/gui/MessengerWindow.h @@ -25,13 +25,14 @@ #include "mainpage.h" #include "ui_MessengerWindow.h" -#include "NetworkDialog.h" + #include #include +#include "chat/PopupChatDialog.h" + class LogoBar; class PeersDialog; -//class MainWindow; class MessengerWindow : public RWindow { @@ -39,21 +40,22 @@ class MessengerWindow : public RWindow public: - void setChatDialog(PeersDialog *cd); - - - NetworkDialog *networkDialog2; + PopupChatDialog *getPrivateChat(std::string id, std::string name, uint chatflags); QPixmap picture; static MessengerWindow* getInstance(); static void releaseInstance(); + + virtual void updateMessengerDisplay() ; // overloaded from RsAutoUpdatePage public slots: void insertPeers(); /** Called when this dialog is to be displayed */ void show(); + void updatePeersAvatar(const QString& peer_id); + LogoBar & getLogoBar() const; protected: @@ -68,37 +70,42 @@ private slots: /** Create the context popup menu and it's submenus */ void messengertreeWidgetCostumPopupMenu( QPoint point ); - /** Export friend in Friends Dialog */ - void exportfriend2(); + /** Add a new friend */ + void addFriend(); + /** Export friend */ + void exportfriend(); /** Remove friend */ - void removefriend2(); + void removefriend(); /** start a chat with a friend **/ - void chatfriend2(); - - void sendMessage(); - - void configurefriend2(); - - void addFriend2(); - - void getAvatar(); + void chatfriend(); + /** start Messages Composer **/ + void sendMessage(); + /** start to connect to a friend **/ + void connectfriend(); + /** show peers details for each friend **/ + void configurefriend(); + /** Open Shared Manager **/ void openShareManager(); - - void showMessagesPopup(); - - //void showMessages(MainWindow::Page page = MainWindow::Messages); - - /** RsServer Friend Calls */ - void allowfriend2(); - void connectfriend2(); - void setaddressfriend2(); - void trustfriend2(); + + /** get own last stored Avatar**/ + void getAvatar(); void changeAvatarClicked(); void updateAvatar(); - void loadmystatus(); + void loadmystatus(); + void loadstatus(); + + void on_actionSort_Peers_Descending_Order_activated(); + void on_actionSort_Peers_Ascending_Order_activated(); + void on_actionRoot_is_decorated_activated(); + void on_actionRoot_isnot_decorated_activated(); + + void displayMenu(); + +signals: + void friendsUpdated() ; private: @@ -107,12 +114,14 @@ private: /* (1) Update Display */ /* (2) Utility Fns */ - QTreeWidgetItem *getCurrentPeer(bool &isOnline); + QTreeWidgetItem *getCurrentPeer(); - PeersDialog *chatDialog; - - //MainWindow* mainWindow; + std::map chatDialogs; + class QLabel *iconLabel, *textLabel; + class QWidget *widget; + class QWidgetAction *widgetAction; + class QSpacerItem *spacerItem; /** Define the popup menus for the Context menu */ QMenu* contextMnu; @@ -122,7 +131,7 @@ private: QAction* connectfriendAct; QAction* configurefriendAct; QAction* exportfriendAct; - QAction* removefriend2Act; + QAction* removefriendAct; QTreeView *messengertreeWidget; diff --git a/retroshare-gui/src/gui/MessengerWindow.ui b/retroshare-gui/src/gui/MessengerWindow.ui index a815c1b20..d7367f9f4 100644 --- a/retroshare-gui/src/gui/MessengerWindow.ui +++ b/retroshare-gui/src/gui/MessengerWindow.ui @@ -6,7 +6,7 @@ 0 0 - 270 + 295 511 @@ -58,7 +58,7 @@ stop: 0.9 #4c4c4c, stop: 1 #333333); 0 - + @@ -130,7 +130,7 @@ p, li { white-space: pre-wrap; } - :/images/donline.png:/images/donline.png + :/images/im-user.png:/images/im-user.png @@ -139,16 +139,7 @@ p, li { white-space: pre-wrap; } - :/images/dbusy.png:/images/dbusy.png - - - - - Be right Back - - - - :/images/dbrb.png:/images/dbrb.png + :/images/im-user-busy.png:/images/im-user-busy.png @@ -157,25 +148,7 @@ p, li { white-space: pre-wrap; } - :/images/daway.png:/images/daway.png - - - - - In a Call - - - - :/images/dphone.png:/images/dphone.png - - - - - Out of lunch - - - - :/images/dlunch.png:/images/dlunch.png + :/images/im-user-away.png:/images/im-user-away.png @@ -184,7 +157,7 @@ p, li { white-space: pre-wrap; } - :/images/dhidden.png:/images/dhidden.png + :/images/im-user-offline.png:/images/im-user-offline.png @@ -222,7 +195,7 @@ p, li { white-space: pre-wrap; } - + Qt::Horizontal @@ -235,9 +208,76 @@ p, li { white-space: pre-wrap; } + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Add a Friend</p></body></html> + + + + + + + :/images/user/add_user24.png:/images/user/add_user24.png + + + + 24 + 24 + + + + Qt::ToolButtonTextBesideIcon + + + true + + + + + + + QPushButton::menu-indicator { +subcontrol-origin: padding; +subcontrol-position: bottom right; +} + + + + + + + + + :/images/looknfeel.png:/images/looknfeel.png + + + + 24 + 24 + + + + true + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + @@ -257,55 +297,19 @@ p, li { white-space: pre-wrap; } 18 + + 22 + 0 - - - - - - - - - <html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Add a Friend</p></body></html> - - - - - - - :/images/user/add_user24.png:/images/user/add_user24.png - - - - 24 - 24 - - - - Qt::ToolButtonTextBesideIcon - - - true - + + false + - - - - QFrame::NoFrame - - - QFrame::Raised - - - @@ -313,11 +317,56 @@ p, li { white-space: pre-wrap; } 0 0 - 270 + 295 21 + + + + :/images/sort_decrease.png:/images/sort_decrease.png + + + Sort Descending Order + + + Sort Descending Order + + + + + + :/images/sort_incr.png:/images/sort_incr.png + + + Sort Ascending Order + + + Sort Ascending Order + + + + + Set root is Decorated + + + Set Root Decorated + + + + + Set Root is not Decorated + + + + + true + + + Hide Offline Friends + + diff --git a/retroshare-gui/src/gui/images.qrc b/retroshare-gui/src/gui/images.qrc index 752c42883..40dc5e146 100644 --- a/retroshare-gui/src/gui/images.qrc +++ b/retroshare-gui/src/gui/images.qrc @@ -55,6 +55,9 @@ images/Client2.png images/Client3.png images/Client4.png + images/closenormal.png + images/closehover.png + images/closepressed.png images/denied16.png images/filetype-association.png images/FileTypeAny.png @@ -216,6 +219,8 @@ images/info16.png images/im-user.png images/im-user-offline.png + images/im-user-away.png + images/im-user-busy.png images/informations_24x24.png images/invite-friend24.png images/invitefriendlabel.png @@ -271,6 +276,7 @@ images/message-mail-forwarded.png images/message-news.png images/message.png + images/messages_new.png images/messenger.png images/mystatus_bg.png images/network.png @@ -281,6 +287,7 @@ images/new-mail-alert.png images/new_forum16.png images/nopic.png + images/no_avatar.png images/pasterslink.png images/package_games1.png images/peerdetails_16x16.png @@ -336,6 +343,8 @@ images/status_unknown.png images/startall.png images/server_24x24.png + images/sort_incr.png + images/sort_decrease.png images/sound.png images/transferupdown.png images/tools_wizard.png diff --git a/retroshare-gui/src/gui/images/closehover.png b/retroshare-gui/src/gui/images/closehover.png new file mode 100644 index 000000000..a9a991434 Binary files /dev/null and b/retroshare-gui/src/gui/images/closehover.png differ diff --git a/retroshare-gui/src/gui/images/closenormal.png b/retroshare-gui/src/gui/images/closenormal.png new file mode 100644 index 000000000..ba30c1a34 Binary files /dev/null and b/retroshare-gui/src/gui/images/closenormal.png differ diff --git a/retroshare-gui/src/gui/images/closepressed.png b/retroshare-gui/src/gui/images/closepressed.png new file mode 100644 index 000000000..90c0e6681 Binary files /dev/null and b/retroshare-gui/src/gui/images/closepressed.png differ diff --git a/retroshare-gui/src/gui/images/messages_new.png b/retroshare-gui/src/gui/images/messages_new.png new file mode 100644 index 000000000..2e688f390 Binary files /dev/null and b/retroshare-gui/src/gui/images/messages_new.png differ diff --git a/retroshare-gui/src/gui/images/no_avatar.png b/retroshare-gui/src/gui/images/no_avatar.png new file mode 100644 index 000000000..eac675fdd Binary files /dev/null and b/retroshare-gui/src/gui/images/no_avatar.png differ diff --git a/retroshare-gui/src/gui/images/sort_decrease.png b/retroshare-gui/src/gui/images/sort_decrease.png new file mode 100644 index 000000000..3d58baf4e Binary files /dev/null and b/retroshare-gui/src/gui/images/sort_decrease.png differ diff --git a/retroshare-gui/src/gui/images/sort_incr.png b/retroshare-gui/src/gui/images/sort_incr.png new file mode 100644 index 000000000..1fbf09dce Binary files /dev/null and b/retroshare-gui/src/gui/images/sort_incr.png differ