summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Swift/Controllers/Chat/ChatController.cpp20
-rw-r--r--Swift/Controllers/Roster/RosterController.cpp2
-rw-r--r--Swift/Controllers/UIInterfaces/ChatWindow.h1
-rw-r--r--Swift/Controllers/UnitTest/MockChatWindow.h1
-rw-r--r--Swift/QtUI/QtChatWindow.cpp7
-rw-r--r--Swift/QtUI/QtChatWindow.h2
-rw-r--r--Swiften/FileTransfer/FileTransferManager.cpp9
-rw-r--r--Swiften/FileTransfer/FileTransferManager.h3
-rw-r--r--Swiften/FileTransfer/FileTransferManagerImpl.cpp3
9 files changed, 37 insertions, 11 deletions
diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp
index 10cf54b..65d65a6 100644
--- a/Swift/Controllers/Chat/ChatController.cpp
+++ b/Swift/Controllers/Chat/ChatController.cpp
@@ -1,62 +1,63 @@
/*
* Copyright (c) 2010-2014 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include <Swift/Controllers/Chat/ChatController.h>
#include <boost/bind.hpp>
#include <boost/smart_ptr/make_shared.hpp>
#include <stdio.h>
-#include <Swiften/Base/format.h>
-#include <Swiften/Base/Algorithm.h>
#include <Swiften/Avatars/AvatarManager.h>
+#include <Swiften/Base/Algorithm.h>
+#include <Swiften/Base/DateTime.h>
+#include <Swiften/Base/foreach.h>
+#include <Swiften/Base/format.h>
+#include <Swiften/Base/Log.h>
#include <Swiften/Chat/ChatStateNotifier.h>
#include <Swiften/Chat/ChatStateTracker.h>
-#include <Swiften/Client/StanzaChannel.h>
+#include <Swiften/Client/ClientBlockListManager.h>
#include <Swiften/Client/NickResolver.h>
+#include <Swiften/Client/StanzaChannel.h>
#include <Swiften/Disco/EntityCapsProvider.h>
-#include <Swiften/Base/foreach.h>
-#include <Swiften/Base/DateTime.h>
#include <Swiften/Elements/DeliveryReceipt.h>
#include <Swiften/Elements/DeliveryReceiptRequest.h>
#include <Swiften/Elements/Idle.h>
-#include <Swiften/Base/Log.h>
-#include <Swiften/Client/ClientBlockListManager.h>
+#include <Swiften/FileTransfer/FileTransferManager.h>
#include <Swift/Controllers/Intl.h>
#include <Swift/Controllers/UIInterfaces/ChatWindowFactory.h>
#include <Swift/Controllers/XMPPEvents/EventController.h>
#include <Swift/Controllers/FileTransfer/FileTransferController.h>
#include <Swift/Controllers/StatusUtil.h>
#include <Swift/Controllers/UIEvents/UIEventStream.h>
#include <Swift/Controllers/UIEvents/SendFileUIEvent.h>
#include <Swift/Controllers/UIEvents/AcceptWhiteboardSessionUIEvent.h>
#include <Swift/Controllers/UIEvents/CancelWhiteboardSessionUIEvent.h>
#include <Swift/Controllers/UIEvents/ShowWhiteboardUIEvent.h>
#include <Swift/Controllers/UIEvents/RequestChangeBlockStateUIEvent.h>
#include <Swift/Controllers/UIEvents/InviteToMUCUIEvent.h>
#include <Swift/Controllers/UIEvents/RequestInviteToMUCUIEvent.h>
#include <Swift/Controllers/SettingConstants.h>
#include <Swift/Controllers/Highlighter.h>
#include <Swift/Controllers/Chat/ChatMessageParser.h>
namespace Swift {
/**
* The controller does not gain ownership of the stanzaChannel, nor the factory.
*/
ChatController::ChatController(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &contact, NickResolver* nickResolver, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool isInMUC, bool useDelayForLatency, UIEventStream* eventStream, EventController* eventController, TimerFactory* timerFactory, EntityCapsProvider* entityCapsProvider, bool userWantsReceipts, SettingsProvider* settings, HistoryController* historyController, MUCRegistry* mucRegistry, HighlightManager* highlightManager, ClientBlockListManager* clientBlockListManager, ChatMessageParser* chatMessageParser, AutoAcceptMUCInviteDecider* autoAcceptMUCInviteDecider)
: ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, contact, presenceOracle, avatarManager, useDelayForLatency, eventStream, eventController, timerFactory, entityCapsProvider, historyController, mucRegistry, highlightManager, chatMessageParser, autoAcceptMUCInviteDecider), eventStream_(eventStream), userWantsReceipts_(userWantsReceipts), settings_(settings), clientBlockListManager_(clientBlockListManager) {
isInMUC_ = isInMUC;
lastWasPresence_ = false;
chatStateNotifier_ = new ChatStateNotifier(stanzaChannel, contact, entityCapsProvider);
chatStateTracker_ = new ChatStateTracker();
nickResolver_ = nickResolver;
presenceOracle_->onPresenceChange.connect(boost::bind(&ChatController::handlePresenceChange, this, _1));
chatStateTracker_->onChatStateChange.connect(boost::bind(&ChatWindow::setContactChatState, chatWindow_, _1));
stanzaChannel_->onStanzaAcked.connect(boost::bind(&ChatController::handleStanzaAcked, this, _1));
nickResolver_->onNickChanged.connect(boost::bind(&ChatController::handleContactNickChanged, this, _1, _2));
std::string nick = nickResolver_->jidToNick(toJID_);
@@ -103,70 +104,75 @@ ChatController::ChatController(const JID& self, StanzaChannel* stanzaChannel, IQ
void ChatController::handleContactNickChanged(const JID& jid, const std::string& /*oldNick*/) {
if (jid.toBare() == toJID_.toBare()) {
chatWindow_->setName(nickResolver_->jidToNick(jid));
}
}
ChatController::~ChatController() {
eventStream_->onUIEvent.disconnect(boost::bind(&ChatController::handleUIEvent, this, _1));
settings_->onSettingChanged.disconnect(boost::bind(&ChatController::handleSettingChanged, this, _1));
nickResolver_->onNickChanged.disconnect(boost::bind(&ChatController::handleContactNickChanged, this, _1, _2));
delete chatStateNotifier_;
delete chatStateTracker_;
}
JID ChatController::getBaseJID() {
return isInMUC_ ? toJID_ : ChatControllerBase::getBaseJID();
}
void ChatController::cancelReplaces() {
lastWasPresence_ = false;
}
void ChatController::handleBareJIDCapsChanged(const JID& /*jid*/) {
DiscoInfo::ref disco = entityCapsProvider_->getCaps(toJID_);
if (disco) {
if (disco->hasFeature(DiscoInfo::MessageCorrectionFeature)) {
chatWindow_->setCorrectionEnabled(ChatWindow::Yes);
} else {
chatWindow_->setCorrectionEnabled(ChatWindow::No);
}
if (disco->hasFeature(DiscoInfo::MessageDeliveryReceiptsFeature)) {
contactSupportsReceipts_ = ChatWindow::Yes;
} else {
contactSupportsReceipts_ = ChatWindow::No;
}
+ if (FileTransferManager::isSupportedBy(disco)) {
+ chatWindow_->setFileTransferEnabled(ChatWindow::Yes);
+ } else {
+ chatWindow_->setFileTransferEnabled(ChatWindow::No);
+ }
} else {
SWIFT_LOG(debug) << "No disco info :(" << std::endl;
chatWindow_->setCorrectionEnabled(ChatWindow::Maybe);
contactSupportsReceipts_ = ChatWindow::Maybe;
}
checkForDisplayingDisplayReceiptsAlert();
}
void ChatController::setToJID(const JID& jid) {
chatStateNotifier_->setContact(jid);
ChatControllerBase::setToJID(jid);
Presence::ref presence;
if (isInMUC_) {
presence = presenceOracle_->getLastPresence(jid);
} else {
presence = jid.isBare() ? presenceOracle_->getHighestPriorityPresence(jid.toBare()) : presenceOracle_->getLastPresence(jid);
}
chatStateNotifier_->setContactIsOnline(presence && presence->getType() == Presence::Available);
handleBareJIDCapsChanged(toJID_);
}
void ChatController::setAvailableServerFeatures(boost::shared_ptr<DiscoInfo> info) {
ChatControllerBase::setAvailableServerFeatures(info);
if (iqRouter_->isAvailable() && info->hasFeature(DiscoInfo::BlockingCommandFeature)) {
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));
handleBlockingStateChanged();
}
}
bool ChatController::isIncomingMessageFromMe(boost::shared_ptr<Message>) {
diff --git a/Swift/Controllers/Roster/RosterController.cpp b/Swift/Controllers/Roster/RosterController.cpp
index 4016f81..d2d024c 100644
--- a/Swift/Controllers/Roster/RosterController.cpp
+++ b/Swift/Controllers/Roster/RosterController.cpp
@@ -324,46 +324,46 @@ void RosterController::handleSubscriptionRequest(const JID& jid, const std::stri
boost::shared_ptr<StanzaEvent> event(eventPointer);
eventController_->handleIncomingEvent(event);
}
void RosterController::handleSubscriptionRequestAccepted(SubscriptionRequestEvent* event) {
subscriptionManager_->confirmSubscription(event->getJID());
if (!xmppRoster_->containsJID(event->getJID()) || xmppRoster_->getSubscriptionStateForJID(event->getJID()) == RosterItemPayload::None || xmppRoster_->getSubscriptionStateForJID(event->getJID()) == RosterItemPayload::From) {
subscriptionManager_->requestSubscription(event->getJID());
}
}
void RosterController::handleSubscriptionRequestDeclined(SubscriptionRequestEvent* event) {
subscriptionManager_->cancelSubscription(event->getJID());
}
void RosterController::handleAvatarChanged(const JID& jid) {
boost::filesystem::path path = avatarManager_->getAvatarPath(jid);
roster_->applyOnItems(SetAvatar(jid, path));
if (jid.equals(myJID_, JID::WithoutResource)) {
mainWindow_->setMyAvatarPath(pathToString(path));
}
}
boost::optional<XMPPRosterItem> RosterController::getItem(const JID& jid) const {
return xmppRoster_->getItem(jid);
}
std::set<std::string> RosterController::getGroups() const {
return xmppRoster_->getGroups();
}
void RosterController::handleOnCapsChanged(const JID& jid) {
DiscoInfo::ref info = entityCapsManager_->getCaps(jid);
if (info) {
std::set<ContactRosterItem::Feature> features;
- if (info->hasFeature(DiscoInfo::JingleFeature) && info->hasFeature(DiscoInfo::JingleFTFeature) && info->hasFeature(DiscoInfo::JingleTransportsIBBFeature)) {
+ if (FileTransferManager::isSupportedBy(info)) {
features.insert(ContactRosterItem::FileTransferFeature);
}
if (info->hasFeature(DiscoInfo::WhiteboardFeature)) {
features.insert(ContactRosterItem::WhiteboardFeature);
}
roster_->applyOnItems(SetAvailableFeatures(jid, features));
}
}
}
diff --git a/Swift/Controllers/UIInterfaces/ChatWindow.h b/Swift/Controllers/UIInterfaces/ChatWindow.h
index 096a59a..ba4b397 100644
--- a/Swift/Controllers/UIInterfaces/ChatWindow.h
+++ b/Swift/Controllers/UIInterfaces/ChatWindow.h
@@ -101,70 +101,71 @@ namespace Swift {
/** Add message to window.
* @return id of added message (for acks).
*/
virtual std::string addMessage(const ChatMessage& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const boost::posix_time::ptime& time, const HighlightAction& highlight) = 0;
/** Adds action to window.
* @return id of added message (for acks);
*/
virtual std::string addAction(const ChatMessage& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const boost::posix_time::ptime& time, const HighlightAction& highlight) = 0;
virtual void addSystemMessage(const ChatMessage& message, Direction direction) = 0;
virtual void addPresenceMessage(const ChatMessage& message, Direction direction) = 0;
virtual void addErrorMessage(const ChatMessage& message) = 0;
virtual void replaceMessage(const ChatMessage& message, const std::string& id, const boost::posix_time::ptime& time, const HighlightAction& highlight) = 0;
virtual void replaceWithAction(const ChatMessage& message, const std::string& id, const boost::posix_time::ptime& time, const HighlightAction& highlight) = 0;
// File transfer related stuff
virtual std::string addFileTransfer(const std::string& senderName, bool senderIsSelf, const std::string& filename, const boost::uintmax_t sizeInBytes) = 0;
virtual void setFileTransferProgress(std::string, const int percentageDone) = 0;
virtual void setFileTransferStatus(std::string, const FileTransferState state, const std::string& msg = "") = 0;
virtual void addMUCInvitation(const std::string& senderName, const JID& jid, const std::string& reason, const std::string& password, bool direct = true, bool isImpromptu = false, bool isContinuation = false) = 0;
virtual std::string addWhiteboardRequest(bool senderIsSelf) = 0;
virtual void setWhiteboardSessionStatus(std::string id, const ChatWindow::WhiteboardSessionState state) = 0;
// message receipts
virtual void setMessageReceiptState(const std::string& id, ChatWindow::ReceiptState state) = 0;
virtual void setContactChatState(ChatState::ChatStateType state) = 0;
virtual void setName(const std::string& name) = 0;
virtual void show() = 0;
virtual void activate() = 0;
virtual void setAvailableSecurityLabels(const std::vector<SecurityLabelsCatalog::Item>& labels) = 0;
virtual void setSecurityLabelsEnabled(bool enabled) = 0;
virtual void setCorrectionEnabled(Tristate enabled) = 0;
+ virtual void setFileTransferEnabled(Tristate enabled) = 0;
virtual void setUnreadMessageCount(int count) = 0;
virtual void convertToMUC(MUCType mucType) = 0;
// virtual TreeWidget *getTreeWidget() = 0;
virtual void setSecurityLabelsError() = 0;
virtual SecurityLabelsCatalog::Item getSelectedSecurityLabel() = 0;
virtual void setInputEnabled(bool enabled) = 0;
virtual void setRosterModel(Roster* model) = 0;
virtual void setTabComplete(TabComplete* completer) = 0;
virtual void replaceLastMessage(const ChatMessage& message) = 0;
virtual void setAckState(const std::string& id, AckState state) = 0;
virtual void flash() = 0;
virtual void setSubject(const std::string& subject) = 0;
virtual void setAffiliations(MUCOccupant::Affiliation, const std::vector<JID>&) = 0;
virtual void setAvailableRoomActions(const std::vector<RoomAction> &actions) = 0;
virtual void setBlockingState(BlockingState state) = 0;
virtual void setCanInitiateImpromptuChats(bool supportsImpromptu) = 0;
virtual void showBookmarkWindow(const MUCBookmark& bookmark) = 0;
/**
* 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).
*/
virtual void setAlert(const std::string& alertText, const std::string& buttonText = "") = 0;
/**
* Removes an alert.
*/
virtual void cancelAlert() = 0;
/**
* Actions that can be performed on the selected occupant.
*/
virtual void setAvailableOccupantActions(const std::vector<OccupantAction>& actions) = 0;
/**
* A room configuration has been requested, show the form.
diff --git a/Swift/Controllers/UnitTest/MockChatWindow.h b/Swift/Controllers/UnitTest/MockChatWindow.h
index c2e2c9f..e4c2548 100644
--- a/Swift/Controllers/UnitTest/MockChatWindow.h
+++ b/Swift/Controllers/UnitTest/MockChatWindow.h
@@ -26,69 +26,70 @@ namespace Swift {
virtual void addSystemMessage(const ChatMessage& /*message*/, Direction /*direction*/) {}
virtual void addPresenceMessage(const ChatMessage& /*message*/, Direction /*direction*/) {}
virtual void addErrorMessage(const ChatMessage& /*message*/) {}
virtual void replaceMessage(const ChatMessage& /*message*/, const std::string& /*id*/, const boost::posix_time::ptime& /*time*/, const HighlightAction& /*highlight*/) {}
virtual void replaceWithAction(const ChatMessage& /*message*/, const std::string& /*id*/, const boost::posix_time::ptime& /*time*/, const HighlightAction& /*highlight*/) {}
virtual void replaceLastMessage(const ChatMessage& /*message*/) {}
// File transfer related stuff
virtual std::string addFileTransfer(const std::string& /*senderName*/, bool /*senderIsSelf*/,const std::string& /*filename*/, const boost::uintmax_t /*sizeInBytes*/) { return 0; }
virtual void setFileTransferProgress(std::string /*id*/, const int /*alreadyTransferedBytes*/) { }
virtual void setFileTransferStatus(std::string /*id*/, const FileTransferState /*state*/, const std::string& /*msg*/) { }
virtual void setMessageReceiptState(const std::string &/* id */, ReceiptState /* state */) { }
virtual void setContactChatState(ChatState::ChatStateType /*state*/) {}
virtual void setName(const std::string& name) {name_ = name;}
virtual void show() {}
virtual void activate() {}
virtual void setAvailableSecurityLabels(const std::vector<SecurityLabelsCatalog::Item>& labels) {labels_ = labels;}
virtual void setSecurityLabelsEnabled(bool enabled) {labelsEnabled_ = enabled;}
virtual void setUnreadMessageCount(int /*count*/) {}
virtual void convertToMUC(MUCType /*mucType*/) {}
virtual void setSecurityLabelsError() {}
virtual SecurityLabelsCatalog::Item getSelectedSecurityLabel() {return label_;}
virtual void setInputEnabled(bool /*enabled*/) {}
virtual void setRosterModel(Roster* roster) { roster_ = roster; }
Roster* getRosterModel() { return roster_; }
virtual void setTabComplete(TabComplete*) {}
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 void setCorrectionEnabled(Tristate /*enabled*/) {}
+ virtual void setFileTransferEnabled(Tristate /*enabled*/) {}
void setAvailableOccupantActions(const std::vector<OccupantAction>&/* actions*/) {}
void setSubject(const std::string& /*subject*/) {}
virtual void showRoomConfigurationForm(Form::ref) {}
virtual void addMUCInvitation(const std::string& /*senderName*/, const JID& /*jid*/, const std::string& /*reason*/, const std::string& /*password*/, bool = true, bool = false, bool = false) {}
virtual std::string addWhiteboardRequest(bool) {return "";}
virtual void setWhiteboardSessionStatus(std::string, const ChatWindow::WhiteboardSessionState){}
virtual void setAffiliations(MUCOccupant::Affiliation, const std::vector<JID>&) {}
virtual void setAvailableRoomActions(const std::vector<RoomAction> &) {}
virtual void setBlockingState(BlockingState) {}
virtual void setCanInitiateImpromptuChats(bool /*supportsImpromptu*/) {}
virtual void showBookmarkWindow(const MUCBookmark& /*bookmark*/) {}
std::string bodyFromMessage(const ChatMessage& message) {
boost::shared_ptr<ChatTextMessagePart> text;
foreach (boost::shared_ptr<ChatMessagePart> part, message.getParts()) {
if ((text = boost::dynamic_pointer_cast<ChatTextMessagePart>(part))) {
return text->text;
}
}
return "";
}
std::string name_;
std::string lastMessageBody_;
std::vector<SecurityLabelsCatalog::Item> labels_;
bool labelsEnabled_;
SecurityLabelsCatalog::Item label_;
Roster* roster_;
};
}
diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp
index f58c11b..f0d2038 100644
--- a/Swift/QtUI/QtChatWindow.cpp
+++ b/Swift/QtUI/QtChatWindow.cpp
@@ -35,70 +35,71 @@
#include <Swiften/Base/Log.h>
#include <Swift/Controllers/Roster/ContactRosterItem.h>
#include <Swift/Controllers/Roster/Roster.h>
#include <Swift/Controllers/Roster/RosterItem.h>
#include <Swift/Controllers/Settings/SettingsProvider.h>
#include <Swift/Controllers/UIEvents/UIEventStream.h>
#include <Swift/Controllers/UIEvents/SendFileUIEvent.h>
#include <Swift/Controllers/UIEvents/JoinMUCUIEvent.h>
#include <SwifTools/TabComplete.h>
#include <Swift/QtUI/Roster/QtOccupantListWidget.h>
#include <Swift/QtUI/QtAddBookmarkWindow.h>
#include <Swift/QtUI/QtPlainChatView.h>
#include <Swift/QtUI/QtSettingsProvider.h>
#include <Swift/QtUI/QtScaledAvatarCache.h>
#include <Swift/QtUI/QtTextEdit.h>
#include <Swift/QtUI/QtUISettingConstants.h>
#include <Swift/QtUI/QtUtilities.h>
#include <Swift/QtUI/QtWebKitChatView.h>
namespace Swift {
QtChatWindow::QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventStream* eventStream, SettingsProvider* settings) : QtTabbable(), contact_(contact), eventStream_(eventStream), blockingState_(BlockingUnsupported), isMUC_(false), supportsImpromptuChat_(false) {
settings_ = settings;
unreadCount_ = 0;
inputEnabled_ = true;
completer_ = NULL;
affiliationEditor_ = NULL;
theme_ = theme;
isCorrection_ = false;
labelModel_ = NULL;
correctionEnabled_ = Maybe;
+ fileTransferEnabled_ = Maybe;
updateTitleWithUnreadCount();
#ifdef SWIFT_EXPERIMENTAL_FT
setAcceptDrops(true);
#endif
alertStyleSheet_ = "background: rgb(255, 255, 153); color: black";
QBoxLayout *layout = new QBoxLayout(QBoxLayout::TopToBottom, this);
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();
subjectLayout_ = new QBoxLayout(QBoxLayout::LeftToRight);
subject_ = new QLineEdit(this);
subjectLayout_->addWidget(subject_);
setSubject("");
subject_->setReadOnly(true);
QPushButton* actionButton_ = new QPushButton(this);
actionButton_->setIcon(QIcon(":/icons/actions.png"));
@@ -354,70 +355,74 @@ void QtChatWindow::handleCurrentLabelChanged(int index) {
}
const SecurityLabelsCatalog::Item& label = labelModel_->availableLabels_[index];
if (label.getLabel()) {
QPalette palette = labelsWidget_->palette();
//palette.setColor(QPalette::Base, P2QSTRING(label.getLabel()->getBackgroundColor()));
palette.setColor(labelsWidget_->backgroundRole(), P2QSTRING(label.getLabel()->getBackgroundColor()));
palette.setColor(labelsWidget_->foregroundRole(), P2QSTRING(label.getLabel()->getForegroundColor()));
labelsWidget_->setPalette(palette);
midBar_->setPalette(palette);
labelsWidget_->setAutoFillBackground(true);
}
else {
labelsWidget_->setAutoFillBackground(false);
labelsWidget_->setPalette(defaultLabelsPalette_);
midBar_->setPalette(defaultLabelsPalette_);
}
}
void QtChatWindow::setSecurityLabelsError() {
labelsWidget_->setEnabled(false);
}
void QtChatWindow::setSecurityLabelsEnabled(bool enabled) {
if (enabled) {
labelsWidget_->setEnabled(true);
labelsWidget_->show();
} else {
labelsWidget_->hide();
}
}
void QtChatWindow::setCorrectionEnabled(Tristate enabled) {
correctionEnabled_ = enabled;
}
+void QtChatWindow::setFileTransferEnabled(Tristate enabled) {
+ fileTransferEnabled_ = enabled;
+}
+
SecurityLabelsCatalog::Item QtChatWindow::getSelectedSecurityLabel() {
assert(labelsWidget_->isEnabled());
assert(labelsWidget_->currentIndex() >= 0 && static_cast<size_t>(labelsWidget_->currentIndex()) < labelModel_->availableLabels_.size());
return labelModel_->availableLabels_[labelsWidget_->currentIndex()];
}
void QtChatWindow::closeEvent(QCloseEvent* event) {
event->accept();
emit windowClosing();
onClosed();
}
void QtChatWindow::convertToMUC(MUCType mucType) {
impromptu_ = (mucType == ImpromptuMUC);
treeWidget_->setMessageTarget(impromptu_ ? QtTreeWidget::MessageDisplayJID : QtTreeWidget::MessageDefaultJID);
isMUC_ = true;
treeWidget_->show();
subject_->setVisible(!impromptu_);
}
void QtChatWindow::qAppFocusChanged(QWidget* /*old*/, QWidget* /*now*/) {
if (isWidgetSelected()) {
lastLineTracker_.setHasFocus(true);
input_->setFocus();
onAllMessagesRead();
}
else {
lastLineTracker_.setHasFocus(false);
}
}
void QtChatWindow::setInputEnabled(bool enabled) {
inputEnabled_ = enabled;
if (!enabled) {
if (mucConfigurationWindow_) {
@@ -518,71 +523,71 @@ void QtChatWindow::show() {
QWidget::show();
}
emit windowOpening();
}
void QtChatWindow::activate() {
if (isWindow()) {
QWidget::show();
}
emit wantsToActivate();
input_->setFocus();
}
void QtChatWindow::resizeEvent(QResizeEvent*) {
emit geometryChanged();
}
void QtChatWindow::moveEvent(QMoveEvent*) {
emit geometryChanged();
}
void QtChatWindow::dragEnterEvent(QDragEnterEvent *event) {
if (event->mimeData()->hasUrls() && event->mimeData()->urls().size() == 1) {
// TODO: check whether contact actually supports file transfer
if (!isMUC_) {
event->acceptProposedAction();
}
} else if (event->mimeData()->hasFormat("application/vnd.swift.contact-jid-list")) {
if (isMUC_ || supportsImpromptuChat_) {
event->acceptProposedAction();
}
}
}
void QtChatWindow::dropEvent(QDropEvent *event) {
- if (event->mimeData()->hasUrls()) {
+ if (fileTransferEnabled_ == ChatWindow::Yes && event->mimeData()->hasUrls()) {
if (event->mimeData()->urls().size() == 1) {
onSendFileRequest(Q2PSTRING(event->mimeData()->urls().at(0).toLocalFile()));
} else {
std::string messageText(Q2PSTRING(tr("Sending of multiple files at once isn't supported at this time.")));
ChatMessage message;
message.append(boost::make_shared<ChatTextMessagePart>(messageText));
addSystemMessage(message, DefaultDirection);
}
} else if (event->mimeData()->hasFormat("application/vnd.swift.contact-jid-list")) {
QByteArray dataBytes = event->mimeData()->data("application/vnd.swift.contact-jid-list");
QDataStream dataStream(&dataBytes, QIODevice::ReadOnly);
std::vector<JID> invites;
while (!dataStream.atEnd()) {
QString jidString;
dataStream >> jidString;
invites.push_back(Q2PSTRING(jidString));
}
onInviteToChat(invites);
}
}
void QtChatWindow::setAvailableOccupantActions(const std::vector<OccupantAction>& actions) {
treeWidget_->setAvailableOccupantActions(actions);
}
void QtChatWindow::setSubject(const std::string& subject) {
//subject_->setVisible(!subject.empty());
subject_->setText(P2QSTRING(subject));
subject_->setToolTip(P2QSTRING(subject));
subject_->setCursorPosition(0);
}
void QtChatWindow::handleActionButtonClicked() {
QMenu contextMenu;
QAction* changeSubject = NULL;
diff --git a/Swift/QtUI/QtChatWindow.h b/Swift/QtUI/QtChatWindow.h
index de7e45e..95edcd0 100644
--- a/Swift/QtUI/QtChatWindow.h
+++ b/Swift/QtUI/QtChatWindow.h
@@ -104,115 +104,117 @@ namespace Swift {
void setAvailableSecurityLabels(const std::vector<SecurityLabelsCatalog::Item>& labels);
void setSecurityLabelsEnabled(bool enabled);
void setSecurityLabelsError();
SecurityLabelsCatalog::Item getSelectedSecurityLabel();
void setName(const std::string& name);
void setInputEnabled(bool enabled);
QtTabbable::AlertType getWidgetAlertState();
void setContactChatState(ChatState::ChatStateType state);
void setRosterModel(Roster* roster);
void setTabComplete(TabComplete* completer);
int getCount();
void replaceLastMessage(const ChatMessage& message);
void setAckState(const std::string& id, AckState state);
// message receipts
void setMessageReceiptState(const std::string& id, ChatWindow::ReceiptState state);
void flash();
QByteArray getSplitterState();
virtual void setAvailableOccupantActions(const std::vector<OccupantAction>& actions);
void setSubject(const std::string& subject);
void showRoomConfigurationForm(Form::ref);
void addMUCInvitation(const std::string& senderName, const JID& jid, const std::string& reason, const std::string& password, bool direct = true, bool isImpromptu = false, bool isContinuation = false);
void setAffiliations(MUCOccupant::Affiliation, const std::vector<JID>&);
void setAvailableRoomActions(const std::vector<RoomAction>& actions);
void setBlockingState(BlockingState state);
virtual void setCanInitiateImpromptuChats(bool supportsImpromptu);
virtual void showBookmarkWindow(const MUCBookmark& bookmark);
public slots:
void handleChangeSplitterState(QByteArray state);
void handleFontResized(int fontSizeSteps);
void setAlert(const std::string& alertText, const std::string& buttonText = "");
void cancelAlert();
void setCorrectionEnabled(Tristate enabled);
+ void setFileTransferEnabled(Tristate enabled);
signals:
void geometryChanged();
void splitterMoved();
void fontResized(int);
protected slots:
void qAppFocusChanged(QWidget* old, QWidget* now);
void closeEvent(QCloseEvent* event);
void resizeEvent(QResizeEvent* event);
void moveEvent(QMoveEvent* event);
void dragEnterEvent(QDragEnterEvent *event);
void dropEvent(QDropEvent *event);
protected:
void showEvent(QShowEvent* event);
private slots:
void handleLogCleared();
void returnPressed();
void handleInputChanged();
void handleCursorPositionChanged();
void handleKeyPressEvent(QKeyEvent* event);
void handleSplitterMoved(int pos, int index);
void handleAlertButtonClicked();
void handleActionButtonClicked();
void handleAffiliationEditorAccepted();
void handleCurrentLabelChanged(int);
private:
void updateTitleWithUnreadCount();
void tabComplete();
void beginCorrection();
void cancelCorrection();
void handleSettingChanged(const std::string& setting);
void handleOccupantSelectionChanged(RosterItem* item);
void handleAppendedToLog();
int unreadCount_;
bool contactIsTyping_;
LastLineTracker lastLineTracker_;
QString contact_;
QString lastSentMessage_;
QTextCursor tabCompleteCursor_;
QtChatView* messageLog_;
QtChatTheme* theme_;
QtTextEdit* input_;
QWidget* midBar_;
QBoxLayout* subjectLayout_;
QComboBox* labelsWidget_;
QtOccupantListWidget* treeWidget_;
QLabel* correctingLabel_;
QLabel* alertLabel_;
QWidget* alertWidget_;
QPushButton* alertButton_;
TabComplete* completer_;
QLineEdit* subject_;
bool isCorrection_;
bool inputClearing_;
bool tabCompletion_;
UIEventStream* eventStream_;
bool inputEnabled_;
QSplitter *logRosterSplitter_;
Tristate correctionEnabled_;
+ Tristate fileTransferEnabled_;
QString alertStyleSheet_;
QPointer<QtMUCConfigurationWindow> mucConfigurationWindow_;
QPointer<QtAffiliationEditor> affiliationEditor_;
SettingsProvider* settings_;
std::vector<ChatWindow::RoomAction> availableRoomActions_;
QPalette defaultLabelsPalette_;
LabelModel* labelModel_;
BlockingState blockingState_;
bool impromptu_;
bool isMUC_;
bool supportsImpromptuChat_;
};
}
diff --git a/Swiften/FileTransfer/FileTransferManager.cpp b/Swiften/FileTransfer/FileTransferManager.cpp
index 69be852..0c7d894 100644
--- a/Swiften/FileTransfer/FileTransferManager.cpp
+++ b/Swiften/FileTransfer/FileTransferManager.cpp
@@ -1,14 +1,23 @@
/*
* Copyright (c) 2011 Tobias Markmann
* Licensed under the simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#include <Swiften/FileTransfer/FileTransferManager.h>
namespace Swift {
FileTransferManager::~FileTransferManager() {
}
+bool FileTransferManager::isSupportedBy(const DiscoInfo::ref info) {
+ if (info) {
+ return info->hasFeature(DiscoInfo::JingleFeature)
+ && info->hasFeature(DiscoInfo::JingleFTFeature)
+ && (info->hasFeature(DiscoInfo::JingleTransportsIBBFeature) || info->hasFeature(DiscoInfo::JingleTransportsS5BFeature));
+ }
+ return false;
+}
+
}
diff --git a/Swiften/FileTransfer/FileTransferManager.h b/Swiften/FileTransfer/FileTransferManager.h
index 3b793c5..bc6530b 100644
--- a/Swiften/FileTransfer/FileTransferManager.h
+++ b/Swiften/FileTransfer/FileTransferManager.h
@@ -1,50 +1,53 @@
/*
* Copyright (c) 2011 Tobias Markmann
* Licensed under the simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
/*
* Copyright (c) 2013 Remko Tronçon
* Licensed under the GNU General Public License.
* See the COPYING file for more information.
*/
#pragma once
#include <string>
#include <boost/filesystem/path.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <Swiften/Base/API.h>
#include <Swiften/Base/boost_bsignals.h>
+#include <Swiften/Elements/DiscoInfo.h>
#include <Swiften/JID/JID.h>
#include <Swiften/FileTransfer/FileTransferOptions.h>
#include <Swiften/FileTransfer/OutgoingFileTransfer.h>
#include <Swiften/FileTransfer/IncomingFileTransfer.h>
namespace Swift {
class ReadBytestream;
class SWIFTEN_API FileTransferManager {
public:
virtual ~FileTransferManager();
virtual OutgoingFileTransfer::ref createOutgoingFileTransfer(
const JID& to,
const boost::filesystem::path& filepath,
const std::string& description,
boost::shared_ptr<ReadBytestream> bytestream,
const FileTransferOptions& = FileTransferOptions()) = 0;
virtual OutgoingFileTransfer::ref createOutgoingFileTransfer(
const JID& to,
const std::string& filename,
const std::string& description,
const boost::uintmax_t sizeInBytes,
const boost::posix_time::ptime& lastModified,
boost::shared_ptr<ReadBytestream> bytestream,
const FileTransferOptions& = FileTransferOptions()) = 0;
+ static bool isSupportedBy(const DiscoInfo::ref info);
+
boost::signal<void (IncomingFileTransfer::ref)> onIncomingFileTransfer;
};
}
diff --git a/Swiften/FileTransfer/FileTransferManagerImpl.cpp b/Swiften/FileTransfer/FileTransferManagerImpl.cpp
index b832d7e..04a2332 100644
--- a/Swiften/FileTransfer/FileTransferManagerImpl.cpp
+++ b/Swiften/FileTransfer/FileTransferManagerImpl.cpp
@@ -79,72 +79,71 @@ FileTransferManagerImpl::FileTransferManagerImpl(
incomingFTManager = new IncomingFileTransferManager(
jingleSessionManager,
iqRouter,
transporterFactory,
timerFactory,
crypto);
incomingFTManager->onIncomingFileTransfer.connect(onIncomingFileTransfer);
}
FileTransferManagerImpl::~FileTransferManagerImpl() {
delete s5bServerManager;
delete incomingFTManager;
delete outgoingFTManager;
delete transporterFactory;
}
void FileTransferManagerImpl::start() {
}
void FileTransferManagerImpl::stop() {
s5bServerManager->stop();
}
boost::optional<JID> FileTransferManagerImpl::highestPriorityJIDSupportingFileTransfer(const JID& bareJID) {
JID fullReceipientJID;
int priority = INT_MIN;
//getAllPresence(bareJID) gives you all presences for the bare JID (i.e. all resources) Remko Tronçon @ 11:11
std::vector<Presence::ref> presences = presenceOracle->getAllPresence(bareJID);
//iterate over them
foreach(Presence::ref pres, presences) {
if (pres->getPriority() > priority) {
// look up caps from the jid
DiscoInfo::ref info = capsProvider->getCaps(pres->getFrom());
- if (info && info->hasFeature(DiscoInfo::JingleFeature) && info->hasFeature(DiscoInfo::JingleFTFeature) && (info->hasFeature(DiscoInfo::JingleTransportsIBBFeature) || info->hasFeature(DiscoInfo::JingleTransportsS5BFeature))) {
-
+ if (isSupportedBy(info)) {
priority = pres->getPriority();
fullReceipientJID = pres->getFrom();
}
}
}
return fullReceipientJID.isValid() ? boost::optional<JID>(fullReceipientJID) : boost::optional<JID>();
}
OutgoingFileTransfer::ref FileTransferManagerImpl::createOutgoingFileTransfer(
const JID& to,
const boost::filesystem::path& filepath,
const std::string& description,
boost::shared_ptr<ReadBytestream> bytestream,
const FileTransferOptions& config) {
#if BOOST_FILESYSTEM_VERSION == 2 // TODO: Delete this when boost 1.44 becomes a minimum requirement, and we no longer need v2
std::string filename = filepath.filename();
#else
std::string filename = pathToString(filepath.filename());
#endif
boost::uintmax_t sizeInBytes = boost::filesystem::file_size(filepath);
boost::posix_time::ptime lastModified = boost::posix_time::from_time_t(boost::filesystem::last_write_time(filepath));
return createOutgoingFileTransfer(to, filename, description, sizeInBytes, lastModified, bytestream, config);
}
OutgoingFileTransfer::ref FileTransferManagerImpl::createOutgoingFileTransfer(
const JID& to,
const std::string& filename,
const std::string& description,
const boost::uintmax_t sizeInBytes,
const boost::posix_time::ptime& lastModified,
boost::shared_ptr<ReadBytestream> bytestream,
const FileTransferOptions& config) {
StreamInitiationFileInfo fileInfo;