From cc379dcf8aeba3c7f259b7e40c9ea2d7a137aa7a Mon Sep 17 00:00:00 2001 From: Richard Maudsley <richard.maudsley@isode.com> Date: Tue, 22 Jul 2014 11:00:15 +0100 Subject: Fix displaying blocked user warning with bound JID chats. Support multiple alert messages. Test-Information: Block a user while the JID is unbound and verify that the yellow warning bar is displayed. Send bidirectional messages to bind the JID then repeat the block request and confirm that the yellow warning bar is displayed and that the user is indeed blocked. Open several alert messages, check that each one can be individually closed via cancelAlert. Change-Id: I120e393c028d15fd5f92154b44a8817cbc41edc9 diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp index 9b65c9f..786b4e9 100644 --- a/Swift/Controllers/Chat/ChatController.cpp +++ b/Swift/Controllers/Chat/ChatController.cpp @@ -169,8 +169,8 @@ void ChatController::setAvailableServerFeatures(boost::shared_ptr<DiscoInfo> inf boost::shared_ptr<BlockList> blockList = clientBlockListManager_->getBlockList(); blockingOnStateChangedConnection_ = blockList->onStateChanged.connect(boost::bind(&ChatController::handleBlockingStateChanged, this)); - blockingOnItemAddedConnection_ = blockList->onItemAdded.connect(boost::bind(&ChatController::handleBlockingItemAdded, this, _1)); - blockingOnItemRemovedConnection_ = blockList->onItemRemoved.connect(boost::bind(&ChatController::handleBlockingItemRemoved, this, _1)); + blockingOnItemAddedConnection_ = blockList->onItemAdded.connect(boost::bind(&ChatController::handleBlockingStateChanged, this)); + blockingOnItemRemovedConnection_ = blockList->onItemRemoved.connect(boost::bind(&ChatController::handleBlockingStateChanged, this)); handleBlockingStateChanged(); } @@ -248,11 +248,14 @@ void ChatController::handleSettingChanged(const std::string& settingPath) { void ChatController::checkForDisplayingDisplayReceiptsAlert() { if (userWantsReceipts_ && (contactSupportsReceipts_ == ChatWindow::No)) { - chatWindow_->setAlert(QT_TRANSLATE_NOOP("", "This chat doesn't support delivery receipts.")); + deliveryReceiptAlert_ = chatWindow_->addAlert(QT_TRANSLATE_NOOP("", "This chat doesn't support delivery receipts.")); } else if (userWantsReceipts_ && (contactSupportsReceipts_ == ChatWindow::Maybe)) { - chatWindow_->setAlert(QT_TRANSLATE_NOOP("", "This chat may not support delivery receipts. You might not receive delivery receipts for the messages you sent.")); + deliveryReceiptAlert_ = chatWindow_->addAlert(QT_TRANSLATE_NOOP("", "This chat may not support delivery receipts. You might not receive delivery receipts for the messages you sent.")); } else { - chatWindow_->cancelAlert(); + if (deliveryReceiptAlert_) { + chatWindow_->removeAlert(*deliveryReceiptAlert_); + deliveryReceiptAlert_.reset(); + } } } @@ -260,32 +263,20 @@ void ChatController::handleBlockingStateChanged() { boost::shared_ptr<BlockList> blockList = clientBlockListManager_->getBlockList(); if (blockList->getState() == BlockList::Available) { if (isInMUC_ ? blockList->isBlocked(toJID_) : blockList->isBlocked(toJID_.toBare())) { - chatWindow_->setAlert(QT_TRANSLATE_NOOP("", "You've currently blocked this contact. To continue your conversation you have to unblock the contact first.")); + blockedContactAlert_ = chatWindow_->addAlert(QT_TRANSLATE_NOOP("", "You've currently blocked this contact. To continue your conversation you have to unblock the contact first.")); chatWindow_->setInputEnabled(false); chatWindow_->setBlockingState(ChatWindow::IsBlocked); } else { + if (blockedContactAlert_) { + chatWindow_->removeAlert(*blockedContactAlert_); + blockedContactAlert_.reset(); + } + chatWindow_->setInputEnabled(true); chatWindow_->setBlockingState(ChatWindow::IsUnblocked); } } } -void ChatController::handleBlockingItemAdded(const JID& jid) { - if (toJID_ == (isInMUC_ ? jid: jid.toBare())) { - chatWindow_->setAlert(QT_TRANSLATE_NOOP("", "You've currently blocked this contact. To continue your conversation you have to unblock the contact first.")); - chatWindow_->setInputEnabled(false); - chatWindow_->setBlockingState(ChatWindow::IsBlocked); - } -} - -void ChatController::handleBlockingItemRemoved(const JID& jid) { - if (toJID_ == (isInMUC_ ? jid: jid.toBare())) { - // FIXME: Support for different types of alerts. - chatWindow_->cancelAlert(); - chatWindow_->setInputEnabled(true); - chatWindow_->setBlockingState(ChatWindow::IsUnblocked); - } -} - void ChatController::handleBlockUserRequest() { if (isInMUC_) { eventStream_->send(boost::make_shared<RequestChangeBlockStateUIEvent>(RequestChangeBlockStateUIEvent::Blocked, toJID_)); diff --git a/Swift/Controllers/Chat/ChatController.h b/Swift/Controllers/Chat/ChatController.h index 2e92be7..998b437 100644 --- a/Swift/Controllers/Chat/ChatController.h +++ b/Swift/Controllers/Chat/ChatController.h @@ -72,9 +72,6 @@ namespace Swift { void checkForDisplayingDisplayReceiptsAlert(); void handleBlockingStateChanged(); - void handleBlockingItemAdded(const JID&); - void handleBlockingItemRemoved(const JID&); - void handleBlockUserRequest(); void handleUnblockUserRequest(); @@ -108,6 +105,9 @@ namespace Swift { boost::bsignals::scoped_connection blockingOnStateChangedConnection_; boost::bsignals::scoped_connection blockingOnItemAddedConnection_; boost::bsignals::scoped_connection blockingOnItemRemovedConnection_; + + boost::optional<ChatWindow::AlertID> deliveryReceiptAlert_; + boost::optional<ChatWindow::AlertID> blockedContactAlert_; }; } diff --git a/Swift/Controllers/UIInterfaces/ChatWindow.h b/Swift/Controllers/UIInterfaces/ChatWindow.h index 81d26c8..f2f5f76 100644 --- a/Swift/Controllers/UIInterfaces/ChatWindow.h +++ b/Swift/Controllers/UIInterfaces/ChatWindow.h @@ -153,16 +153,23 @@ namespace Swift { virtual void setBlockingState(BlockingState state) = 0; virtual void setCanInitiateImpromptuChats(bool supportsImpromptu) = 0; virtual void showBookmarkWindow(const MUCBookmark& bookmark) = 0; + + /** + * A handle that uniquely identities an alert message. + */ + typedef int AlertID; /** * Set an alert on the window. * @param alertText Description of alert (required). * @param buttonText Button text to use (optional, no button is shown if empty). + * @return A handle to the alert message. */ - virtual void setAlert(const std::string& alertText, const std::string& buttonText = "") = 0; + virtual AlertID addAlert(const std::string& alertText, const std::string& buttonText = "") = 0; /** * Removes an alert. + * @param id An alert ID previously returned from setAlert */ - virtual void cancelAlert() = 0; + virtual void removeAlert(const AlertID id) = 0; /** * Actions that can be performed on the selected occupant. diff --git a/Swift/Controllers/UnitTest/MockChatWindow.h b/Swift/Controllers/UnitTest/MockChatWindow.h index 5e6606b..ef7216b 100644 --- a/Swift/Controllers/UnitTest/MockChatWindow.h +++ b/Swift/Controllers/UnitTest/MockChatWindow.h @@ -56,8 +56,8 @@ namespace Swift { void setAckState(const std::string& /*id*/, AckState /*state*/) {} virtual void flash() {} - virtual void setAlert(const std::string& /*alertText*/, const std::string& /*buttonText*/) {} - virtual void cancelAlert() {} + virtual AlertID addAlert(const std::string& /*alertText*/, const std::string& /*buttonText*/) { return 0; } + virtual void removeAlert(const AlertID /*id*/) {} virtual void setCorrectionEnabled(Tristate /*enabled*/) {} virtual void setFileTransferEnabled(Tristate /*enabled*/) {} void setAvailableOccupantActions(const std::vector<OccupantAction>&/* actions*/) {} diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp index 47eeac0..574a0a2 100644 --- a/Swift/QtUI/QtChatWindow.cpp +++ b/Swift/QtUI/QtChatWindow.cpp @@ -57,7 +57,7 @@ namespace Swift { -QtChatWindow::QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventStream* eventStream, SettingsProvider* settings) : QtTabbable(), contact_(contact), eventStream_(eventStream), blockingState_(BlockingUnsupported), isMUC_(false), supportsImpromptuChat_(false) { +QtChatWindow::QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventStream* eventStream, SettingsProvider* settings) : QtTabbable(), contact_(contact), nextAlertId_(0), eventStream_(eventStream), blockingState_(BlockingUnsupported), isMUC_(false), supportsImpromptuChat_(false) { settings_ = settings; unreadCount_ = 0; inputEnabled_ = true; @@ -80,20 +80,8 @@ QtChatWindow::QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventSt layout->setContentsMargins(0,0,0,0); layout->setSpacing(2); - alertWidget_ = new QWidget(this); - QHBoxLayout* alertLayout = new QHBoxLayout(alertWidget_); - layout->addWidget(alertWidget_); - alertLabel_ = new QLabel(this); - alertLayout->addWidget(alertLabel_); - alertButton_ = new QPushButton(this); - connect (alertButton_, SIGNAL(clicked()), this, SLOT(handleAlertButtonClicked())); - alertLayout->addWidget(alertButton_); - QPalette palette = alertWidget_->palette(); - palette.setColor(QPalette::Window, QColor(Qt::yellow)); - palette.setColor(QPalette::WindowText, QColor(Qt::black)); - alertWidget_->setStyleSheet(alertStyleSheet_); - alertLabel_->setStyleSheet(alertStyleSheet_); - alertWidget_->hide(); + alertLayout_ = new QVBoxLayout(this); + layout->addLayout(alertLayout_); subjectLayout_ = new QBoxLayout(QBoxLayout::LeftToRight); subject_ = new QLineEdit(this); @@ -214,19 +202,41 @@ void QtChatWindow::handleAlertButtonClicked() { onAlertButtonClicked(); } -void QtChatWindow::setAlert(const std::string& alertText, const std::string& buttonText) { - alertLabel_->setText(alertText.c_str()); +QtChatWindow::AlertID QtChatWindow::addAlert(const std::string& alertText, const std::string& buttonText) { + QWidget* alertWidget = new QWidget(this); + QHBoxLayout* alertLayout = new QHBoxLayout(alertWidget); + alertLayout_->addWidget(alertWidget); + QLabel* alertLabel = new QLabel(this); + alertLayout->addWidget(alertLabel); + alertButton_ = new QPushButton(this); + connect (alertButton_, SIGNAL(clicked()), this, SLOT(handleAlertButtonClicked())); + alertLayout->addWidget(alertButton_); + QPalette palette = alertWidget->palette(); + palette.setColor(QPalette::Window, QColor(Qt::yellow)); + palette.setColor(QPalette::WindowText, QColor(Qt::black)); + alertWidget->setStyleSheet(alertStyleSheet_); + alertLabel->setStyleSheet(alertStyleSheet_); + + alertLabel->setText(alertText.c_str()); if (buttonText.empty()) { alertButton_->hide(); } else { alertButton_->setText(buttonText.c_str()); alertButton_->show(); } - alertWidget_->show(); + + AlertID id = nextAlertId_++; + alertWidgets_[id] = alertWidget; + return id; } -void QtChatWindow::cancelAlert() { - alertWidget_->hide(); +void QtChatWindow::removeAlert(const AlertID id) { + std::map<AlertID, QWidget*>::iterator i = alertWidgets_.find(id); + if (i != alertWidgets_.end()) { + alertLayout_->removeWidget(i->second); + delete i->second; + alertWidgets_.erase(i); + } } void QtChatWindow::setTabComplete(TabComplete* completer) { @@ -256,9 +266,9 @@ void QtChatWindow::handleKeyPressEvent(QKeyEvent* event) { void QtChatWindow::beginCorrection() { if (correctionEnabled_ == ChatWindow::Maybe) { - setAlert(Q2PSTRING(tr("This chat may not support message correction. If you send a correction anyway, it may appear as a duplicate message"))); + correctingAlert_ = addAlert(Q2PSTRING(tr("This chat may not support message correction. If you send a correction anyway, it may appear as a duplicate message"))); } else if (correctionEnabled_ == ChatWindow::No) { - setAlert(Q2PSTRING(tr("This chat does not support message correction. If you send a correction anyway, it will appear as a duplicate message"))); + correctingAlert_ = addAlert(Q2PSTRING(tr("This chat does not support message correction. If you send a correction anyway, it will appear as a duplicate message"))); } QTextCursor cursor = input_->textCursor(); cursor.select(QTextCursor::Document); @@ -272,7 +282,10 @@ void QtChatWindow::beginCorrection() { } void QtChatWindow::cancelCorrection() { - cancelAlert(); + if (correctingAlert_) { + removeAlert(*correctingAlert_); + correctingAlert_.reset(); + } QTextCursor cursor = input_->textCursor(); cursor.select(QTextCursor::Document); cursor.removeSelectedText(); diff --git a/Swift/QtUI/QtChatWindow.h b/Swift/QtUI/QtChatWindow.h index b3a3f5e..45eaa6f 100644 --- a/Swift/QtUI/QtChatWindow.h +++ b/Swift/QtUI/QtChatWindow.h @@ -134,8 +134,8 @@ namespace Swift { public slots: void handleChangeSplitterState(QByteArray state); void handleFontResized(int fontSizeSteps); - void setAlert(const std::string& alertText, const std::string& buttonText = ""); - void cancelAlert(); + AlertID addAlert(const std::string& alertText, const std::string& buttonText = ""); + void removeAlert(const AlertID id); void setCorrectionEnabled(Tristate enabled); void setFileTransferEnabled(Tristate enabled); @@ -193,8 +193,10 @@ namespace Swift { QComboBox* labelsWidget_; QtOccupantListWidget* treeWidget_; QLabel* correctingLabel_; - QLabel* alertLabel_; - QWidget* alertWidget_; + boost::optional<AlertID> correctingAlert_; + QVBoxLayout* alertLayout_; + std::map<AlertID, QWidget*> alertWidgets_; + AlertID nextAlertId_; QPushButton* alertButton_; TabComplete* completer_; QLineEdit* subject_; -- cgit v0.10.2-6-g49f6