diff --git a/retroshare-gui/src/gui/ChatLobbyWidget.cpp b/retroshare-gui/src/gui/ChatLobbyWidget.cpp index 46d5116e8..25c476953 100644 --- a/retroshare-gui/src/gui/ChatLobbyWidget.cpp +++ b/retroshare-gui/src/gui/ChatLobbyWidget.cpp @@ -418,9 +418,7 @@ void ChatLobbyWidget::addChatPage(ChatLobbyDialog *d) if(_lobby_infos.find(d->id()) == _lobby_infos.end()) { - ui.stackedWidget->addWidget(d) ; - - connect(d,SIGNAL(lobbyLeave(ChatLobbyId)),this,SLOT(unsubscribeChatLobby(ChatLobbyId))) ; + connect(d,SIGNAL(dialogClose(ChatDialog*)),this,SLOT(dialogClose(ChatDialog*))); connect(d,SIGNAL(typingEventReceived(ChatLobbyId)),this,SLOT(updateTypingStatus(ChatLobbyId))) ; connect(d,SIGNAL(messageReceived(bool,ChatLobbyId,QDateTime,QString,QString)),this,SLOT(updateMessageChanged(bool,ChatLobbyId,QDateTime,QString,QString))) ; connect(d,SIGNAL(peerJoined(ChatLobbyId)),this,SLOT(updatePeerEntering(ChatLobbyId))) ; @@ -429,14 +427,33 @@ void ChatLobbyWidget::addChatPage(ChatLobbyDialog *d) ChatLobbyId id = d->id(); _lobby_infos[id].dialog = d ; _lobby_infos[id].default_icon = QIcon() ; - _lobby_infos[id].last_typing_event = time(NULL) ; + _lobby_infos[id].last_typing_event = time(nullptr) ; - ChatLobbyInfo linfo ; - if(rsMsgs->getChatLobbyInfo(id,linfo)) - _lobby_infos[id].default_icon = (linfo.lobby_flags & RS_CHAT_LOBBY_FLAGS_PUBLIC) ? QIcon(IMAGE_PUBLIC):QIcon(IMAGE_PRIVATE) ; - else - std::cerr << "(EE) cannot find info for room " << std::hex << id << std::dec << std::endl; + ChatLobbyInfo linfo ; + if(rsMsgs->getChatLobbyInfo(id,linfo)) + _lobby_infos[id].default_icon = (linfo.lobby_flags & RS_CHAT_LOBBY_FLAGS_PUBLIC) ? QIcon(IMAGE_PUBLIC):QIcon(IMAGE_PRIVATE) ; + else + std::cerr << "(EE) cannot find info for room " << std::hex << id << std::dec << std::endl; } + + ui.stackedWidget->addWidget(d) ; +} + +void ChatLobbyWidget::removeChatPage(ChatLobbyDialog *d) +{ + // check that the page already exist. + + if(_lobby_infos.find(d->id()) != _lobby_infos.end()) + { + ui.stackedWidget->removeWidget(d) ; + } +} + +void ChatLobbyWidget::dialogClose(ChatDialog* cd) +{ + ChatLobbyDialog* d = dynamic_cast(cd); + if(_lobby_infos.find(d->id()) != _lobby_infos.end()) + unsubscribeChatLobby(d->id()); } void ChatLobbyWidget::setCurrentChatPage(ChatLobbyDialog *d) @@ -708,7 +725,7 @@ void ChatLobbyWidget::createChatLobby() void ChatLobbyWidget::showLobby(QTreeWidgetItem *item) { - if (item == NULL || item->type() != TYPE_LOBBY) { + if (item == nullptr || item->type() != TYPE_LOBBY) { showBlankPage(0) ; return; } @@ -718,7 +735,11 @@ void ChatLobbyWidget::showLobby(QTreeWidgetItem *item) if(_lobby_infos.find(id) == _lobby_infos.end()) showBlankPage(id) ; else - ui.stackedWidget->setCurrentWidget(_lobby_infos[id].dialog) ; + { + _lobby_infos[id].dialog->showDialog(RS_CHAT_FOCUS); + if (_lobby_infos[id].dialog->isWindowed()) + showBlankPage(id, true); + } } // this function is for the case where we don't have any identity yet @@ -772,17 +793,17 @@ bool ChatLobbyWidget::showLobbyAnchor(ChatLobbyId id, QString anchor) { QTreeWidgetItem *item = getTreeWidgetItem(id) ; - if(item != NULL) { + if(item != nullptr) { if(item->type() == TYPE_LOBBY) { if(_lobby_infos.find(id) == _lobby_infos.end()) { showBlankPage(id) ; } else { - //ChatLobbyDialog cldChatLobby =_lobby_infos[id].dialog; - ui.stackedWidget->setCurrentWidget(_lobby_infos[id].dialog) ; - ChatLobbyDialog *cldCW=NULL ; - if (NULL != (cldCW = dynamic_cast(ui.stackedWidget->currentWidget()))) - cldCW->getChatWidget()->scrollToAnchor(anchor); + _lobby_infos[id].dialog->showDialog(RS_CHAT_FOCUS); + if (_lobby_infos[id].dialog->isWindowed()) + showBlankPage(id, true); + + _lobby_infos[id].dialog->getChatWidget()->scrollToAnchor(anchor); } ui.lobbyTreeWidget->setCurrentItem(item); @@ -857,20 +878,20 @@ void ChatLobbyWidget::autoSubscribeLobby(QTreeWidgetItem *item) subscribeChatLobbyAtItem(item); } -void ChatLobbyWidget::showBlankPage(ChatLobbyId id) +void ChatLobbyWidget::showBlankPage(ChatLobbyId id, bool subscribed /*= false*/) { // show the default blank page. ui.stackedWidget->setCurrentWidget(ui._lobby_blank_page) ; // Update information std::vector lobbies; - rsMsgs->getListOfNearbyChatLobbies(lobbies); + rsMsgs->getListOfNearbyChatLobbies(lobbies); - std::list my_ids ; - rsIdentity->getOwnIds(my_ids) ; + std::list my_ids ; + rsIdentity->getOwnIds(my_ids) ; + + trimAnonIds(my_ids) ; - trimAnonIds(my_ids) ; - for(std::vector::const_iterator it(lobbies.begin());it!=lobbies.end();++it) if( (*it).lobby_id == id) { @@ -881,8 +902,10 @@ void ChatLobbyWidget::showBlankPage(ChatLobbyId id) ui.lobbysec_lineEdit->setText( (( (*it).lobby_flags & RS_CHAT_LOBBY_FLAGS_PGP_SIGNED)?tr("No anonymous IDs"):tr("Anonymous IDs accepted")) ); ui.lobbypeers_lineEdit->setText( QString::number((*it).total_number_of_peers) ); - QString text = tr("You're not subscribed to this chat room; Double click-it to enter and chat.") ; - + QString text = tr("You're subscribed to this chat room; Double click to show window and chat.") ; + if (!subscribed) + { + text = tr("You're not subscribed to this chat room; Double click-it to enter and chat.") ; if(my_ids.empty()) { if( (*it).lobby_flags & RS_CHAT_LOBBY_FLAGS_PGP_SIGNED) @@ -890,8 +913,9 @@ void ChatLobbyWidget::showBlankPage(ChatLobbyId id) else text += "\n\n"+tr("You will need to create an identity in order to join chat rooms.") ; } + } - ui.lobbyInfoLabel->setText(text); + ui.lobbyInfoLabel->setText(text); return ; } @@ -1037,6 +1061,8 @@ void ChatLobbyWidget::unsubscribeChatLobby(ChatLobbyId id) } ui.stackedWidget->removeWidget(it->second.dialog) ; + disconnect(it->second.dialog,SIGNAL(dialogClose(ChatDialog*)),this,SLOT(dialogClose(ChatDialog*))); + it->second.dialog->leaveLobby(); _lobby_infos.erase(it) ; } diff --git a/retroshare-gui/src/gui/ChatLobbyWidget.h b/retroshare-gui/src/gui/ChatLobbyWidget.h index 8c6f07081..415c28bc2 100644 --- a/retroshare-gui/src/gui/ChatLobbyWidget.h +++ b/retroshare-gui/src/gui/ChatLobbyWidget.h @@ -38,6 +38,7 @@ class RSTreeWidgetItemCompareRole; class ChatTabWidget ; +class ChatDialog ; class ChatLobbyDialog ; class QTextBrowser ; @@ -69,6 +70,7 @@ public: void setCurrentChatPage(ChatLobbyDialog *) ; // used by ChatLobbyDialog to raise. void addChatPage(ChatLobbyDialog *) ; + void removeChatPage(ChatLobbyDialog *) ; bool showLobbyAnchor(ChatLobbyId id, QString anchor) ; uint unreadCount(); @@ -77,6 +79,7 @@ signals: void unreadCountChanged(uint unreadCount); protected slots: + void dialogClose(ChatDialog*); void lobbyChanged(); void lobbyTreeWidgetCustomPopupMenu(QPoint); void createChatLobby(); @@ -87,7 +90,7 @@ protected slots: void displayChatLobbyEvent(qulonglong lobby_id, int event_type, const RsGxsId& gxs_id, const QString& str); void readChatLobbyInvites(); void showLobby(QTreeWidgetItem *lobby_item) ; - void showBlankPage(ChatLobbyId id) ; + void showBlankPage(ChatLobbyId id, bool subscribed = false) ; void unsubscribeChatLobby(ChatLobbyId id) ; void createIdentityAndSubscribe(); void subscribeChatLobbyAs() ; diff --git a/retroshare-gui/src/gui/chat/ChatLobbyDialog.cpp b/retroshare-gui/src/gui/chat/ChatLobbyDialog.cpp index 21784401d..8b5ab7fde 100644 --- a/retroshare-gui/src/gui/chat/ChatLobbyDialog.cpp +++ b/retroshare-gui/src/gui/chat/ChatLobbyDialog.cpp @@ -62,7 +62,7 @@ const static uint32_t timeToInactivity = 60 * 10; // in seconds /** Default constructor */ ChatLobbyDialog::ChatLobbyDialog(const ChatLobbyId& lid, QWidget *parent, Qt::WindowFlags flags) - : ChatDialog(parent, flags), lobbyId(lid), + : ChatDialog(parent, flags), lobbyId(lid), mWindowedSetted(false), mPCWindow(nullptr), bullet_red_128(":/icons/bullet_red_128.png"), bullet_grey_128(":/icons/bullet_grey_128.png"), bullet_green_128(":/icons/bullet_green_128.png"), bullet_yellow_128(":/icons/bullet_yellow_128.png") { @@ -129,6 +129,15 @@ ChatLobbyDialog::ChatLobbyDialog(const ChatLobbyId& lid, QWidget *parent, Qt::Wi double scaler_factor = S > 25 ? 2.4 : 1.8; QSize icon_size(scaler_factor * S, scaler_factor * S); + // Add a button to undock dialog. + // + undockButton = new QToolButton; + undockButton->setText(QString()); + undockButton->setAutoRaise(true); + connect(undockButton, SIGNAL(clicked()), this , SLOT(toggleWindowed())); + + getChatWidget()->addTitleBarWidget(undockButton) ; + // Add a button to invite friends. // inviteFriendsButton = new QToolButton ; @@ -201,8 +210,12 @@ ChatLobbyDialog::ChatLobbyDialog(const ChatLobbyId& lid, QWidget *parent, Qt::Wi void ChatLobbyDialog::leaveLobby() { - emit lobbyLeave(id()) ; + emit dialogClose(this); + + if (mPCWindow) + mPCWindow = nullptr;// Windows deleted by events just before. } + void ChatLobbyDialog::inviteFriends() { std::cerr << "Inviting friends" << std::endl; @@ -404,12 +417,8 @@ void ChatLobbyDialog::init(const ChatId &/*id*/, const QString &/*title*/) lastUpdateListTime = 0; - // add to window - - ChatLobbyWidget *chatLobbyPage = dynamic_cast(MainWindow::getPage(MainWindow::ChatLobby)); - if (chatLobbyPage) { - chatLobbyPage->addChatPage(this) ; - } + // add to stacked lobby list + setWindowed(false); /** List of muted Participants */ mutedParticipants.clear() ; @@ -421,11 +430,15 @@ void ChatLobbyDialog::init(const ChatId &/*id*/, const QString &/*title*/) /** Destructor. */ ChatLobbyDialog::~ChatLobbyDialog() { - // announce leaving of lobby - + if (mPCWindow) + { + mPCWindow->removeDialog(this); + mPCWindow = nullptr; + } // check that the lobby still exists. - if (mChatId.isLobbyId()) - rsMsgs->sendLobbyStatusPeerLeaving(mChatId.toLobbyId()); + // announce leaving of lobby + if (mChatId.isLobbyId()) + rsMsgs->sendLobbyStatusPeerLeaving(mChatId.toLobbyId()); // save settings processSettings(false); @@ -910,11 +923,17 @@ void ChatLobbyDialog::showDialog(uint chatflags) { if (chatflags & RS_CHAT_FOCUS) { - MainWindow::showWindow(MainWindow::ChatLobby); - MainPage *p = MainWindow::getPage(MainWindow::ChatLobby); + if (isWindowed() && mPCWindow) { + mPCWindow->showDialog(this, chatflags); + } + else + { + MainWindow::showWindow(MainWindow::ChatLobby); + MainPage *p = MainWindow::getPage(MainWindow::ChatLobby); - if(p != NULL) - dynamic_cast(p)->setCurrentChatPage(this) ; + if(p) + dynamic_cast(p)->setCurrentChatPage(this) ; + } } } @@ -941,3 +960,54 @@ void ChatLobbyDialog::filterIds() ui.participantsList->filterItems(filterColumn, text); } + +void ChatLobbyDialog::setWindowed(bool windowed) +{ + if (mWindowedSetted && (windowed == isWindowed()) ) + { + RsErr() << __PRETTY_FUNCTION__ << " Attempt to set windowed same as last state." << std::endl; + return; + } + mWindowedSetted = true; + // just empiric values + qreal S = QFontMetricsF(font()).height(); + int size = static_cast(S > 25.0 ? 2.4 * S : 1.8 * S); + QSize icon_size(size, size); + + QIcon icon ; + // chatLobbyPage could be NULL for first autosubscribe lobby as Dialog is created before main widget + ChatLobbyWidget *chatLobbyPage = dynamic_cast(MainWindow::getPage(MainWindow::ChatLobby)); + if (!mPCWindow) + mPCWindow = PopupChatWindow::getWindow(true); + + if (windowed) + { + if (chatLobbyPage) + chatLobbyPage->removeChatPage(this); + if (mPCWindow) + mPCWindow->addDialog(this); + + undockButton->setToolTip(tr("Redock to Main window")); + icon.addPixmap(QPixmap(":/icons/png/dock.png")) ; + undockButton->setIcon(icon) ; + undockButton->setIconSize(icon_size); + } + else + { + if (mPCWindow) + { + mPCWindow->removeDialog(this); + mPCWindow = nullptr; + } + if (chatLobbyPage) + chatLobbyPage->addChatPage(this); + + undockButton->setToolTip(tr("Undock to a new window")); + icon.addPixmap(QPixmap(":/icons/png/undock.png")) ; + undockButton->setIcon(icon) ; + undockButton->setIconSize(icon_size); + } + show(); + if (chatLobbyPage)// If not defined, we are on autosubscribe loop of lobby widget constructor. So don't recall it. + showDialog(RS_CHAT_FOCUS); +} diff --git a/retroshare-gui/src/gui/chat/ChatLobbyDialog.h b/retroshare-gui/src/gui/chat/ChatLobbyDialog.h index 688cfb1c9..1f22284f9 100644 --- a/retroshare-gui/src/gui/chat/ChatLobbyDialog.h +++ b/retroshare-gui/src/gui/chat/ChatLobbyDialog.h @@ -25,6 +25,7 @@ #include "ui_ChatLobbyDialog.h" #include "gui/common/RSTreeWidgetItem.h" #include "ChatDialog.h" +#include "PopupChatWindow.h" Q_DECLARE_METATYPE(RsGxsId) Q_DECLARE_METATYPE(QList) @@ -51,16 +52,20 @@ public: ChatLobbyId id() const { return lobbyId ;} void sortParcipants(); + inline bool isWindowed() const { return dynamic_cast(this->window()) != nullptr; } + +public slots: + void leaveLobby() ; private slots: void participantsTreeWidgetCustomPopupMenu( QPoint point ); void textBrowserAskContextMenu(QMenu* contextMnu, QString anchorForPosition, const QPoint point); void inviteFriends() ; - void leaveLobby() ; void filterChanged(const QString &text); - void showInPeopleTab(); + void showInPeopleTab(); + void toggleWindowed(){setWindowed(!isWindowed());} + void setWindowed(bool windowed); signals: - void lobbyLeave(ChatLobbyId) ; void typingEventReceived(ChatLobbyId) ; void messageReceived(bool incoming, ChatLobbyId lobby_id, QDateTime time, QString senderName, QString msg) ; void peerJoined(ChatLobbyId) ; @@ -103,9 +108,13 @@ private: RSTreeWidgetItemCompareRole *mParticipantCompareRole ; - QToolButton *inviteFriendsButton ; + QToolButton *undockButton ; + QToolButton *inviteFriendsButton ; QToolButton *unsubscribeButton ; + bool mWindowedSetted; + PopupChatWindow* mPCWindow; + /** Qt Designer generated object */ Ui::ChatLobbyDialog ui; diff --git a/retroshare-gui/src/gui/chat/PopupChatWindow.cpp b/retroshare-gui/src/gui/chat/PopupChatWindow.cpp index 17c2c38c3..6d6502c5f 100644 --- a/retroshare-gui/src/gui/chat/PopupChatWindow.cpp +++ b/retroshare-gui/src/gui/chat/PopupChatWindow.cpp @@ -64,15 +64,13 @@ static PopupChatWindow *instance = NULL; } /** Default constructor */ -PopupChatWindow::PopupChatWindow(bool tabbed, QWidget *parent, Qt::WindowFlags flags) : QMainWindow(parent, flags) +PopupChatWindow::PopupChatWindow(bool tabbed, QWidget *parent, Qt::WindowFlags flags) + : QMainWindow(parent, flags),tabbedWindow(tabbed),firstShow(true) + , chatDialog(nullptr),mEmptyIcon(nullptr) { /* Invoke Qt Designer generated QObject setup routine */ ui.setupUi(this); - - tabbedWindow = tabbed; - firstShow = true; - chatDialog = NULL; - mEmptyIcon = NULL; + setAttribute(Qt::WA_DeleteOnClose); ui.tabWidget->setVisible(tabbedWindow); @@ -204,15 +202,16 @@ void PopupChatWindow::addDialog(ChatDialog *dialog) if (tabbedWindow) { ui.tabWidget->addDialog(dialog); } else { - ui.horizontalLayout->addWidget(dialog); + ui.chatcentralLayout->addWidget(dialog); dialog->addToParent(this); - ui.horizontalLayout->setContentsMargins(0, 0, 0, 0); - chatId = dialog->getChatId(); + ui.chatcentralLayout->setContentsMargins(0, 0, 0, 0); + chatId = dialog->getChatId(); chatDialog = dialog; calculateStyle(dialog); + calculateTitle(dialog); /* signal toggled is called */ - ui.actionSetOnTop->setChecked(PeerSettings->getPrivateChatOnTop(chatId)); + ui.actionSetOnTop->setChecked(PeerSettings->getPrivateChatOnTop(chatId)); QObject::connect(dialog, SIGNAL(dialogClose(ChatDialog*)), this, SLOT(dialogClose(ChatDialog*))); } @@ -233,14 +232,15 @@ void PopupChatWindow::removeDialog(ChatDialog *dialog) deleteLater(); } } else { - QObject::disconnect(dialog, SIGNAL(dialogClose(ChatDialog*)), this, SLOT(dialogClose(ChatDialog*))); if (chatDialog == dialog) { + QObject::disconnect(dialog, SIGNAL(dialogClose(ChatDialog*)), this, SLOT(dialogClose(ChatDialog*))); saveSettings(); dialog->removeFromParent(this); - ui.horizontalLayout->removeWidget(dialog); - chatDialog = NULL; - chatId = ChatId(); + ui.chatcentralLayout->removeWidget(dialog); + chatDialog = nullptr; + chatId = ChatId(); + close(); deleteLater(); } } diff --git a/retroshare-gui/src/gui/chat/PopupChatWindow.ui b/retroshare-gui/src/gui/chat/PopupChatWindow.ui index f85a570b6..ea6ea79af 100644 --- a/retroshare-gui/src/gui/chat/PopupChatWindow.ui +++ b/retroshare-gui/src/gui/chat/PopupChatWindow.ui @@ -17,7 +17,7 @@ MainWindow - + 5 diff --git a/retroshare-gui/src/gui/icons.qrc b/retroshare-gui/src/gui/icons.qrc index 5a3696343..4c1ce6a62 100644 --- a/retroshare-gui/src/gui/icons.qrc +++ b/retroshare-gui/src/gui/icons.qrc @@ -69,6 +69,7 @@ icons/png/chat-lobbies.png icons/png/circles.png icons/png/digital-key.png + icons/png/dock.png icons/png/empty-circle.png icons/png/enter.png icons/png/exit.png @@ -121,6 +122,7 @@ icons/png/thumbs-neutral.png icons/png/thumbs-up.png icons/png/typing.png + icons/png/undock.png icons/png/video.png icons/quit_128.png icons/search_red_128.png diff --git a/retroshare-gui/src/gui/icons/png/dock.png b/retroshare-gui/src/gui/icons/png/dock.png new file mode 100644 index 000000000..2e191961b Binary files /dev/null and b/retroshare-gui/src/gui/icons/png/dock.png differ diff --git a/retroshare-gui/src/gui/icons/png/undock.png b/retroshare-gui/src/gui/icons/png/undock.png new file mode 100644 index 000000000..10052db9a Binary files /dev/null and b/retroshare-gui/src/gui/icons/png/undock.png differ diff --git a/retroshare-gui/src/gui/icons/svg/dock.svg b/retroshare-gui/src/gui/icons/svg/dock.svg new file mode 100644 index 000000000..2847da24c --- /dev/null +++ b/retroshare-gui/src/gui/icons/svg/dock.svg @@ -0,0 +1,95 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/retroshare-gui/src/gui/icons/svg/undock.svg b/retroshare-gui/src/gui/icons/svg/undock.svg new file mode 100644 index 000000000..1c8d25c50 --- /dev/null +++ b/retroshare-gui/src/gui/icons/svg/undock.svg @@ -0,0 +1,95 @@ + + + +image/svg+xml \ No newline at end of file