From a7fb55381ab4a5c470bf891b31ac6e201611a2c1 Mon Sep 17 00:00:00 2001 From: Richard Maudsley Date: Wed, 9 Apr 2014 08:53:12 +0100 Subject: Fix crash in QtUserSearchWindow. Avoid storing pointers to items in vectors. Using shared_ptr for Contact items. Change-Id: I3baa05fc058011b2beca14dc620ab794988a2b37 diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp index 919a3d6..654f735 100644 --- a/Swift/Controllers/Chat/ChatsManager.cpp +++ b/Swift/Controllers/Chat/ChatsManager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2013 Kevin Smith + * Copyright (c) 2010-2014 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -929,11 +929,11 @@ std::vector ChatsManager::getRecentChats() const { return std::vector(recentChats_.begin(), recentChats_.end()); } -std::vector Swift::ChatsManager::getContacts() { - std::vector result; +std::vector Swift::ChatsManager::getContacts() { + std::vector result; foreach (ChatListWindow::Chat chat, recentChats_) { if (!chat.isMUC) { - result.push_back(Contact(chat.chatName.empty() ? chat.jid.toString() : chat.chatName, chat.jid, chat.statusType, chat.avatarPath)); + result.push_back(boost::make_shared(chat.chatName.empty() ? chat.jid.toString() : chat.chatName, chat.jid, chat.statusType, chat.avatarPath)); } } return result; diff --git a/Swift/Controllers/Chat/ChatsManager.h b/Swift/Controllers/Chat/ChatsManager.h index 979d52a..88a0986 100644 --- a/Swift/Controllers/Chat/ChatsManager.h +++ b/Swift/Controllers/Chat/ChatsManager.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2013 Kevin Smith + * Copyright (c) 2010-2014 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -73,7 +73,7 @@ namespace Swift { void setServerDiscoInfo(boost::shared_ptr info); void handleIncomingMessage(boost::shared_ptr message); std::vector getRecentChats() const; - virtual std::vector getContacts(); + virtual std::vector getContacts(); boost::signal onImpromptuMUCServiceDiscovered; diff --git a/Swift/Controllers/Chat/UserSearchController.cpp b/Swift/Controllers/Chat/UserSearchController.cpp index 7844c1b..8503609 100644 --- a/Swift/Controllers/Chat/UserSearchController.cpp +++ b/Swift/Controllers/Chat/UserSearchController.cpp @@ -215,7 +215,7 @@ void UserSearchController::handlePresenceChanged(Presence::ref presence) { void UserSearchController::handleJIDUpdateRequested(const std::vector& jids) { if (window_) { - std::vector updates; + std::vector updates; foreach(const JID& jid, jids) { updates.push_back(convertJIDtoContact(jid)); } @@ -224,40 +224,40 @@ void UserSearchController::handleJIDUpdateRequested(const std::vector& jids } void UserSearchController::handleJIDAddRequested(const std::vector& jids) { - std::vector contacts; + std::vector contacts; foreach(const JID& jid, jids) { contacts.push_back(convertJIDtoContact(jid)); } window_->addContacts(contacts); } -Contact UserSearchController::convertJIDtoContact(const JID& jid) { - Contact contact; - contact.jid = jid; +Contact::ref UserSearchController::convertJIDtoContact(const JID& jid) { + Contact::ref contact = boost::make_shared(); + contact->jid = jid; // name lookup boost::optional rosterItem = rosterController_->getItem(jid); if (rosterItem && !rosterItem->getName().empty()) { - contact.name = rosterItem->getName(); + contact->name = rosterItem->getName(); } else { VCard::ref vcard = vcardManager_->getVCard(jid); if (vcard && !vcard->getFullName().empty()) { - contact.name = vcard->getFullName(); + contact->name = vcard->getFullName(); } else { - contact.name = jid.toString(); + contact->name = jid.toString(); } } // presence lookup Presence::ref presence = presenceOracle_->getHighestPriorityPresence(jid); if (presence) { - contact.statusType = presence->getShow(); + contact->statusType = presence->getShow(); } else { - contact.statusType = StatusShow::None; + contact->statusType = StatusShow::None; } // avatar lookup - contact.avatarPath = avatarManager_->getAvatarPath(jid); + contact->avatarPath = avatarManager_->getAvatarPath(jid); return contact; } diff --git a/Swift/Controllers/Chat/UserSearchController.h b/Swift/Controllers/Chat/UserSearchController.h index fc4c8e9..d630580 100644 --- a/Swift/Controllers/Chat/UserSearchController.h +++ b/Swift/Controllers/Chat/UserSearchController.h @@ -7,18 +7,20 @@ #pragma once #include + #include #include -#include - -#include #include -#include + +#include +#include #include #include #include -#include #include +#include +#include +#include namespace Swift { class UIEventStream; @@ -32,7 +34,6 @@ namespace Swift { class ContactSuggester; class AvatarManager; class PresenceOracle; - class Contact; class UserSearchResult { public: @@ -68,7 +69,7 @@ namespace Swift { void handlePresenceChanged(Presence::ref presence); void handleJIDUpdateRequested(const std::vector& jids); void handleJIDAddRequested(const std::vector& jids); - Contact convertJIDtoContact(const JID& jid); + Contact::ref convertJIDtoContact(const JID& jid); void endDiscoWalker(); void initializeUserWindow(); diff --git a/Swift/Controllers/Contact.h b/Swift/Controllers/Contact.h index 039cd23..ceba152 100644 --- a/Swift/Controllers/Contact.h +++ b/Swift/Controllers/Contact.h @@ -4,8 +4,15 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + #pragma once +#include #include #include @@ -13,8 +20,10 @@ namespace Swift { -class Contact { +class Contact : public boost::enable_shared_from_this { public: + typedef boost::shared_ptr ref; + Contact(); Contact(const std::string& name, const JID& jid, StatusShow::Type statusType, const boost::filesystem::path& path); diff --git a/Swift/Controllers/ContactProvider.h b/Swift/Controllers/ContactProvider.h index 9ce371f..0e56de5 100644 --- a/Swift/Controllers/ContactProvider.h +++ b/Swift/Controllers/ContactProvider.h @@ -4,6 +4,12 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + #pragma once #include @@ -15,7 +21,7 @@ namespace Swift { class ContactProvider { public: virtual ~ContactProvider(); - virtual std::vector getContacts() = 0; + virtual std::vector getContacts() = 0; }; } diff --git a/Swift/Controllers/ContactSuggester.cpp b/Swift/Controllers/ContactSuggester.cpp index f1104b0..41e0261 100644 --- a/Swift/Controllers/ContactSuggester.cpp +++ b/Swift/Controllers/ContactSuggester.cpp @@ -4,6 +4,12 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + #include #include @@ -34,25 +40,22 @@ void ContactSuggester::addContactProvider(ContactProvider* provider) { contactProviders_.push_back(provider); } -bool ContactSuggester::matchContact(const std::string& search, const Contact& c) { - return fuzzyMatch(c.name, search) || fuzzyMatch(c.jid.toString(), search); +bool ContactSuggester::matchContact(const std::string& search, const Contact::ref& c) { + return fuzzyMatch(c->name, search) || fuzzyMatch(c->jid.toString(), search); } -std::vector ContactSuggester::getSuggestions(const std::string& search) const { - std::vector results; +std::vector ContactSuggester::getSuggestions(const std::string& search) const { + std::vector results; foreach(ContactProvider* provider, contactProviders_) { append(results, provider->getContacts()); } - std::sort(results.begin(), results.end(), - lambda::bind(&Contact::jid, lambda::_1) < lambda::bind(&Contact::jid, lambda::_2)); - results.erase(std::unique(results.begin(), results.end(), - lambda::bind(&Contact::jid, lambda::_1) == lambda::bind(&Contact::jid, lambda::_2)), - results.end()); + std::sort(results.begin(), results.end(), ContactSuggester::contactLexicographicalSortPredicate); + results.erase(std::unique(results.begin(), results.end(), ContactSuggester::contactEqualityPredicate), results.end()); results.erase(std::remove_if(results.begin(), results.end(), !lambda::bind(&ContactSuggester::matchContact, search, lambda::_1)), results.end()); - std::sort(results.begin(), results.end(), ContactSuggester::chatSortPredicate); + std::sort(results.begin(), results.end(), ContactSuggester::contactSmartSortPredicate); return results; } @@ -69,11 +72,19 @@ bool ContactSuggester::fuzzyMatch(std::string text, std::string match) { return true; } -bool ContactSuggester::chatSortPredicate(const Contact& a, const Contact& b) { - if (a.statusType == b.statusType) { - return a.name.compare(b.name) < 0; +bool ContactSuggester::contactLexicographicalSortPredicate(const Contact::ref& a, const Contact::ref& b) { + return a->jid < b->jid; +} + +bool ContactSuggester::contactEqualityPredicate(const Contact::ref& a, const Contact::ref& b) { + return a->jid == b->jid; +} + +bool ContactSuggester::contactSmartSortPredicate(const Contact::ref& a, const Contact::ref& b) { + if (a->statusType == b->statusType) { + return a->name.compare(b->name) < 0; } else { - return a.statusType < b.statusType; + return a->statusType < b->statusType; } } diff --git a/Swift/Controllers/ContactSuggester.h b/Swift/Controllers/ContactSuggester.h index 137e5d3..67b912c 100644 --- a/Swift/Controllers/ContactSuggester.h +++ b/Swift/Controllers/ContactSuggester.h @@ -4,6 +4,12 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + #pragma once #include @@ -21,14 +27,16 @@ namespace Swift { void addContactProvider(ContactProvider* provider); - std::vector getSuggestions(const std::string& search) const; + std::vector getSuggestions(const std::string& search) const; private: - static bool matchContact(const std::string& search, const Contact& c); + static bool matchContact(const std::string& search, const Contact::ref& c); /** * Performs fuzzy matching on the string text. Matches when each character of match string is present in sequence in text string. */ static bool fuzzyMatch(std::string text, std::string match); - static bool chatSortPredicate(const Contact& a, const Contact& b); + static bool contactLexicographicalSortPredicate(const Contact::ref& a, const Contact::ref& b); + static bool contactEqualityPredicate(const Contact::ref& a, const Contact::ref& b); + static bool contactSmartSortPredicate(const Contact::ref& a, const Contact::ref& b); private: std::vector contactProviders_; diff --git a/Swift/Controllers/ContactsFromXMPPRoster.cpp b/Swift/Controllers/ContactsFromXMPPRoster.cpp index 15a7767..7559962 100644 --- a/Swift/Controllers/ContactsFromXMPPRoster.cpp +++ b/Swift/Controllers/ContactsFromXMPPRoster.cpp @@ -4,6 +4,12 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + #include #include @@ -21,13 +27,13 @@ ContactsFromXMPPRoster::ContactsFromXMPPRoster(XMPPRoster* roster, AvatarManager ContactsFromXMPPRoster::~ContactsFromXMPPRoster() { } -std::vector ContactsFromXMPPRoster::getContacts() { - std::vector results; +std::vector ContactsFromXMPPRoster::getContacts() { + std::vector results; std::vector rosterItems = roster_->getItems(); foreach(const XMPPRosterItem& rosterItem, rosterItems) { - Contact contact(rosterItem.getName().empty() ? rosterItem.getJID().toString() : rosterItem.getName(), rosterItem.getJID(), StatusShow::None,""); - contact.statusType = presenceOracle_->getHighestPriorityPresence(contact.jid) ? presenceOracle_->getHighestPriorityPresence(contact.jid)->getShow() : StatusShow::None; - contact.avatarPath = avatarManager_->getAvatarPath(contact.jid); + Contact::ref contact = boost::make_shared(rosterItem.getName().empty() ? rosterItem.getJID().toString() : rosterItem.getName(), rosterItem.getJID(), StatusShow::None,""); + contact->statusType = presenceOracle_->getHighestPriorityPresence(contact->jid) ? presenceOracle_->getHighestPriorityPresence(contact->jid)->getShow() : StatusShow::None; + contact->avatarPath = avatarManager_->getAvatarPath(contact->jid); results.push_back(contact); } return results; diff --git a/Swift/Controllers/ContactsFromXMPPRoster.h b/Swift/Controllers/ContactsFromXMPPRoster.h index 3815a99..4adc606 100644 --- a/Swift/Controllers/ContactsFromXMPPRoster.h +++ b/Swift/Controllers/ContactsFromXMPPRoster.h @@ -4,6 +4,12 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + #pragma once #include @@ -19,7 +25,7 @@ class ContactsFromXMPPRoster : public ContactProvider { ContactsFromXMPPRoster(XMPPRoster* roster, AvatarManager* avatarManager, PresenceOracle* presenceOracle); virtual ~ContactsFromXMPPRoster(); - virtual std::vector getContacts(); + virtual std::vector getContacts(); private: XMPPRoster* roster_; AvatarManager* avatarManager_; diff --git a/Swift/Controllers/UIInterfaces/UserSearchWindow.h b/Swift/Controllers/UIInterfaces/UserSearchWindow.h index 0245f34..56992cc 100644 --- a/Swift/Controllers/UIInterfaces/UserSearchWindow.h +++ b/Swift/Controllers/UIInterfaces/UserSearchWindow.h @@ -32,14 +32,14 @@ namespace Swift { virtual void setSearchFields(boost::shared_ptr fields) = 0; virtual void setNameSuggestions(const std::vector& suggestions) = 0; virtual void prepopulateJIDAndName(const JID& jid, const std::string& name) = 0; - virtual void setContactSuggestions(const std::vector& suggestions) = 0; + virtual void setContactSuggestions(const std::vector& suggestions) = 0; virtual void setJIDs(const std::vector&) = 0; virtual void setRoomJID(const JID& roomJID) = 0; virtual std::string getReason() const = 0; virtual std::vector getJIDs() const = 0; virtual void setCanStartImpromptuChats(bool supportsImpromptu) = 0; - virtual void updateContacts(const std::vector& contacts) = 0; - virtual void addContacts(const std::vector& contacts) = 0; + virtual void updateContacts(const std::vector& contacts) = 0; + virtual void addContacts(const std::vector& contacts) = 0; virtual void show() = 0; diff --git a/Swift/QtUI/UserSearch/ContactListDelegate.cpp b/Swift/QtUI/UserSearch/ContactListDelegate.cpp index 29cab83..56c479b 100644 --- a/Swift/QtUI/UserSearch/ContactListDelegate.cpp +++ b/Swift/QtUI/UserSearch/ContactListDelegate.cpp @@ -4,6 +4,12 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + #include #include #include @@ -21,7 +27,7 @@ void ContactListDelegate::paint(QPainter* painter, const QStyleOptionViewItem& o if (!index.isValid()) { return; } - const Contact* contact = static_cast(index.internalPointer()); + const Contact::ref contact = static_cast(index.internalPointer())->shared_from_this(); QColor nameColor = index.data(Qt::TextColorRole).value(); QString avatarPath = index.data(ContactListModel::AvatarRole).value(); QIcon presenceIcon =index.data(ChatListRecentItem::PresenceIconRole).isValid() && !index.data(ChatListRecentItem::PresenceIconRole).value().isNull() diff --git a/Swift/QtUI/UserSearch/ContactListModel.cpp b/Swift/QtUI/UserSearch/ContactListModel.cpp index 907142f..ef6383c 100644 --- a/Swift/QtUI/UserSearch/ContactListModel.cpp +++ b/Swift/QtUI/UserSearch/ContactListModel.cpp @@ -52,16 +52,20 @@ QDataStream& operator >>(QDataStream& in, StatusShow::Type& e){ ContactListModel::ContactListModel(bool editable) : QAbstractItemModel(), editable_(editable) { } -void ContactListModel::setList(const std::vector& list) { +void ContactListModel::setList(const std::vector& list) { emit layoutAboutToBeChanged(); contacts_ = list; emit layoutChanged(); } -const std::vector& ContactListModel::getList() const { +const std::vector& ContactListModel::getList() const { return contacts_; } +Contact::ref ContactListModel::getContact(const size_t i) const { + return contacts_[i]; +} + Qt::ItemFlags ContactListModel::flags(const QModelIndex& index) const { Qt::ItemFlags flags = QAbstractItemModel::flags(index); if (index.isValid()) { @@ -78,9 +82,9 @@ int ContactListModel::columnCount(const QModelIndex&) const { QVariant ContactListModel::data(const QModelIndex& index, int role) const { if (boost::numeric_cast(index.row()) < contacts_.size()) { - const Contact& contact = contacts_[index.row()]; + const Contact::ref& contact = contacts_[index.row()]; if (role == Qt::EditRole) { - return P2QSTRING(contact.jid.toString()); + return P2QSTRING(contact->jid.toString()); } return dataForContact(contact, role); } else { @@ -93,7 +97,7 @@ QModelIndex ContactListModel::index(int row, int column, const QModelIndex& pare return QModelIndex(); } - return boost::numeric_cast(row) < contacts_.size() ? createIndex(row, column, (void*)&(contacts_[row])) : QModelIndex(); + return boost::numeric_cast(row) < contacts_.size() ? createIndex(row, column, contacts_[row].get()) : QModelIndex(); } QModelIndex ContactListModel::parent(const QModelIndex& index) const { @@ -118,18 +122,18 @@ bool ContactListModel::removeRows(int row, int /*count*/, const QModelIndex& /*p return false; } -QVariant ContactListModel::dataForContact(const Contact& contact, int role) const { +QVariant ContactListModel::dataForContact(const Contact::ref& contact, int role) const { switch (role) { - case Qt::DisplayRole: return P2QSTRING(contact.name); - case DetailTextRole: return P2QSTRING(contact.jid.toString()); - case AvatarRole: return QVariant(P2QSTRING(pathToString(contact.avatarPath))); + case Qt::DisplayRole: return P2QSTRING(contact->name); + case DetailTextRole: return P2QSTRING(contact->jid.toString()); + case AvatarRole: return QVariant(P2QSTRING(pathToString(contact->avatarPath))); case PresenceIconRole: return getPresenceIconForContact(contact); default: return QVariant(); } } -QIcon ContactListModel::getPresenceIconForContact(const Contact& contact) const { - return QIcon(statusShowTypeToIconPath(contact.statusType)); +QIcon ContactListModel::getPresenceIconForContact(const Contact::ref& contact) const { + return QIcon(statusShowTypeToIconPath(contact->statusType)); } } diff --git a/Swift/QtUI/UserSearch/ContactListModel.h b/Swift/QtUI/UserSearch/ContactListModel.h index 6ca505e..e582ac4 100644 --- a/Swift/QtUI/UserSearch/ContactListModel.h +++ b/Swift/QtUI/UserSearch/ContactListModel.h @@ -36,8 +36,9 @@ namespace Swift { public: ContactListModel(bool editable); - void setList(const std::vector& list); - const std::vector& getList() const; + void setList(const std::vector& list); + const std::vector& getList() const; + Contact::ref getContact(const size_t i) const; Qt::ItemFlags flags(const QModelIndex& index) const; int columnCount(const QModelIndex& parent = QModelIndex()) const; @@ -48,16 +49,16 @@ namespace Swift { bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex()); private: - QVariant dataForContact(const Contact& contact, int role) const; - QIcon getPresenceIconForContact(const Contact& contact) const; + QVariant dataForContact(const Contact::ref& contact, int role) const; + QIcon getPresenceIconForContact(const Contact::ref& contact) const; signals: - void onListChanged(std::vector list); + void onListChanged(std::vector list); void onJIDsDropped(const std::vector& contact); private: bool editable_; - std::vector contacts_; + std::vector contacts_; }; } diff --git a/Swift/QtUI/UserSearch/QtContactListWidget.cpp b/Swift/QtUI/UserSearch/QtContactListWidget.cpp index 6ad1169..4adc929 100644 --- a/Swift/QtUI/UserSearch/QtContactListWidget.cpp +++ b/Swift/QtUI/UserSearch/QtContactListWidget.cpp @@ -26,7 +26,7 @@ QtContactListWidget::QtContactListWidget(QWidget* parent, SettingsProvider* sett contactListModel_ = new ContactListModel(true); setModel(contactListModel_); - connect(contactListModel_, SIGNAL(onListChanged(std::vector)), this, SIGNAL(onListChanged(std::vector))); + connect(contactListModel_, SIGNAL(onListChanged(std::vector)), this, SIGNAL(onListChanged(std::vector))); connect(contactListModel_, SIGNAL(onJIDsDropped(std::vector)), this, SIGNAL(onJIDsAdded(std::vector))); setSelectionMode(QAbstractItemView::SingleSelection); @@ -61,23 +61,27 @@ QtContactListWidget::~QtContactListWidget() { delete removableItemDelegate_; } -void QtContactListWidget::setList(const std::vector& list) { +void QtContactListWidget::setList(const std::vector& list) { contactListModel_->setList(list); } -std::vector QtContactListWidget::getList() const { +std::vector QtContactListWidget::getList() const { return contactListModel_->getList(); } +Contact::ref QtContactListWidget::getContact(const size_t i) { + return contactListModel_->getContact(i); +} + void QtContactListWidget::setMaximumNoOfContactsToOne(bool limited) { limited_ = limited; } -void QtContactListWidget::updateContacts(const std::vector& contactUpdates) { - std::vector contacts = contactListModel_->getList(); - foreach(const Contact& contactUpdate, contactUpdates) { +void QtContactListWidget::updateContacts(const std::vector& contactUpdates) { + std::vector contacts = contactListModel_->getList(); + foreach(const Contact::ref& contactUpdate, contactUpdates) { for(size_t n = 0; n < contacts.size(); n++) { - if (contactUpdate.jid == contacts[n].jid) { + if (contactUpdate->jid == contacts[n]->jid) { contacts[n] = contactUpdate; break; } diff --git a/Swift/QtUI/UserSearch/QtContactListWidget.h b/Swift/QtUI/UserSearch/QtContactListWidget.h index a83b47a..601d320 100644 --- a/Swift/QtUI/UserSearch/QtContactListWidget.h +++ b/Swift/QtUI/UserSearch/QtContactListWidget.h @@ -36,15 +36,16 @@ public: QtContactListWidget(QWidget* parent, SettingsProvider* settings); virtual ~QtContactListWidget(); - void setList(const std::vector& list); - std::vector getList() const; + void setList(const std::vector& list); + std::vector getList() const; + Contact::ref getContact(const size_t i); void setMaximumNoOfContactsToOne(bool limited); public slots: - void updateContacts(const std::vector& contactUpdates); + void updateContacts(const std::vector& contactUpdates); signals: - void onListChanged(std::vector list); + void onListChanged(std::vector list); void onJIDsAdded(const std::vector& jids); private: diff --git a/Swift/QtUI/UserSearch/QtSuggestingJIDInput.cpp b/Swift/QtUI/UserSearch/QtSuggestingJIDInput.cpp index de935d9..a4a4610 100644 --- a/Swift/QtUI/UserSearch/QtSuggestingJIDInput.cpp +++ b/Swift/QtUI/UserSearch/QtSuggestingJIDInput.cpp @@ -4,6 +4,12 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + #include #include #include @@ -23,7 +29,7 @@ namespace Swift { -QtSuggestingJIDInput::QtSuggestingJIDInput(QWidget* parent, SettingsProvider* settings) : QLineEdit(parent), settings_(settings), currentContact_(NULL) { +QtSuggestingJIDInput::QtSuggestingJIDInput(QWidget* parent, SettingsProvider* settings) : QLineEdit(parent), settings_(settings) { treeViewPopup_ = new QTreeView(); treeViewPopup_->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint); //treeViewPopup_->setAttribute(Qt::WA_ShowWithoutActivating); @@ -57,30 +63,31 @@ QtSuggestingJIDInput::~QtSuggestingJIDInput() { delete treeViewPopup_; } -const Contact* QtSuggestingJIDInput::getContact() { - if (currentContact_ != NULL) { +Contact::ref QtSuggestingJIDInput::getContact() { + if (!!currentContact_) { return currentContact_; - } else { - if (!text().isEmpty()) { - JID jid(Q2PSTRING(text())); - if (jid.isValid()) { - manualContact_.name = jid.toString(); - manualContact_.jid = jid; - return &manualContact_; - } + } + + if (!text().isEmpty()) { + JID jid(Q2PSTRING(text())); + if (jid.isValid()) { + Contact::ref manualContact = boost::make_shared(); + manualContact->name = jid.toString(); + manualContact->jid = jid; + return manualContact; } - return NULL; } + return boost::shared_ptr(); } -void QtSuggestingJIDInput::setSuggestions(const std::vector& suggestions) { +void QtSuggestingJIDInput::setSuggestions(const std::vector& suggestions) { contactListModel_->setList(suggestions); positionPopup(); if (!suggestions.empty()) { treeViewPopup_->setCurrentIndex(contactListModel_->index(0, 0)); showPopup(); } else { - currentContact_ = NULL; + currentContact_.reset(); } } @@ -100,12 +107,12 @@ void QtSuggestingJIDInput::keyPressEvent(QKeyEvent* event) { } else if (event->key() == Qt::Key_Return && treeViewPopup_->isVisible()) { QModelIndex index = treeViewPopup_->currentIndex(); if (!contactListModel_->getList().empty() && index.isValid()) { - currentContact_ = &contactListModel_->getList()[index.row()]; + currentContact_ = contactListModel_->getContact(index.row()); setText(P2QSTRING(currentContact_->jid.toString())); hidePopup(); clearFocus(); } else { - currentContact_ = NULL; + currentContact_.reset(); } editingDone(); } else { @@ -130,7 +137,7 @@ void QtSuggestingJIDInput::handleSettingsChanged(const std::string& setting) { void QtSuggestingJIDInput::handleClicked(const QModelIndex& index) { if (index.isValid()) { - currentContact_ = &contactListModel_->getList()[index.row()]; + currentContact_ = contactListModel_->getContact(index.row()); setText(""); onUserSelected(currentContact_->jid); hidePopup(); diff --git a/Swift/QtUI/UserSearch/QtSuggestingJIDInput.h b/Swift/QtUI/UserSearch/QtSuggestingJIDInput.h index 9ec0512..25e7d42 100644 --- a/Swift/QtUI/UserSearch/QtSuggestingJIDInput.h +++ b/Swift/QtUI/UserSearch/QtSuggestingJIDInput.h @@ -4,6 +4,12 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + #pragma once #include @@ -23,9 +29,9 @@ class QtSuggestingJIDInput : public QLineEdit { QtSuggestingJIDInput(QWidget* parent, SettingsProvider* settings); virtual ~QtSuggestingJIDInput(); - const Contact* getContact(); + Contact::ref getContact(); - void setSuggestions(const std::vector& suggestions); + void setSuggestions(const std::vector& suggestions); boost::signal onUserSelected; @@ -52,8 +58,7 @@ class QtSuggestingJIDInput : public QLineEdit { ContactListModel* contactListModel_; QTreeView* treeViewPopup_; ContactListDelegate* contactListDelegate_; - Contact manualContact_; - const Contact* currentContact_; + Contact::ref currentContact_; }; } diff --git a/Swift/QtUI/UserSearch/QtUserSearchFirstMultiJIDPage.cpp b/Swift/QtUI/UserSearch/QtUserSearchFirstMultiJIDPage.cpp index 47d62d9..597c88b 100644 --- a/Swift/QtUI/UserSearch/QtUserSearchFirstMultiJIDPage.cpp +++ b/Swift/QtUI/UserSearch/QtUserSearchFirstMultiJIDPage.cpp @@ -47,7 +47,7 @@ QtUserSearchFirstMultiJIDPage::QtUserSearchFirstMultiJIDPage(UserSearchWindow::T jid_ = new QtSuggestingJIDInput(this, settings); horizontalLayout_6->insertWidget(0, jid_); - connect(contactList_, SIGNAL(onListChanged(std::vector)), this, SLOT(emitCompletenessCheck())); + connect(contactList_, SIGNAL(onListChanged(std::vector)), this, SLOT(emitCompletenessCheck())); connect(jid_, SIGNAL(editingDone()), this, SLOT(handleEditingDone())); setAcceptDrops(true); diff --git a/Swift/QtUI/UserSearch/QtUserSearchWindow.cpp b/Swift/QtUI/UserSearch/QtUserSearchWindow.cpp index ed0fae2..c154c8f 100644 --- a/Swift/QtUI/UserSearch/QtUserSearchWindow.cpp +++ b/Swift/QtUI/UserSearch/QtUserSearchWindow.cpp @@ -130,20 +130,20 @@ void QtUserSearchWindow::handleAccepted() { break; case ChatToContact: if (contactVector_.size() == 1) { - boost::shared_ptr event(new RequestChatUIEvent(contactVector_[0].jid)); + boost::shared_ptr event(new RequestChatUIEvent(contactVector_[0]->jid)); eventStream_->send(event); break; } - foreach(const Contact& contact, contactVector_) { - jids.push_back(contact.jid); + foreach(Contact::ref contact, contactVector_) { + jids.push_back(contact->jid); } eventStream_->send(boost::make_shared(jids, JID(), Q2PSTRING(firstMultiJIDPage_->reason_->text()))); break; case InviteToChat: - foreach(const Contact& contact, contactVector_) { - jids.push_back(contact.jid); + foreach(Contact::ref contact, contactVector_) { + jids.push_back(contact->jid); } eventStream_->send(boost::make_shared(roomJID_, jids, Q2PSTRING(firstMultiJIDPage_->reason_->text()))); break; @@ -156,9 +156,8 @@ void QtUserSearchWindow::handleContactSuggestionRequested(const QString& text) { } void QtUserSearchWindow::addContact() { - if (firstMultiJIDPage_->jid_->getContact() != 0) { - Contact contact = *(firstMultiJIDPage_->jid_->getContact()); - contactVector_.push_back(contact); + if (!!firstMultiJIDPage_->jid_->getContact()) { + contactVector_.push_back(firstMultiJIDPage_->jid_->getContact()); } firstMultiJIDPage_->contactList_->setList(contactVector_); firstMultiJIDPage_->emitCompletenessCheck(); @@ -271,7 +270,7 @@ JID QtUserSearchWindow::getContactJID() const { } void QtUserSearchWindow::addSearchedJIDToList(const JID& jid) { - Contact contact(jid, jid.toString(), StatusShow::None, ""); + Contact::ref contact = boost::make_shared(jid, jid.toString(), StatusShow::None, ""); contactVector_.push_back(contact); firstMultiJIDPage_->contactList_->setList(contactVector_); firstMultiJIDPage_->emitCompletenessCheck(); @@ -336,7 +335,7 @@ void QtUserSearchWindow::prepopulateJIDAndName(const JID& jid, const std::string detailsPage_->setName(name); } -void QtUserSearchWindow::setContactSuggestions(const std::vector& suggestions) { +void QtUserSearchWindow::setContactSuggestions(const std::vector& suggestions) { if (type_ == AddContact) { firstPage_->jid_->setSuggestions(suggestions); } else { @@ -361,8 +360,8 @@ std::string QtUserSearchWindow::getReason() const { std::vector QtUserSearchWindow::getJIDs() const { std::vector jids; - foreach (const Contact& contact, contactVector_) { - jids.push_back(contact.jid); + foreach (Contact::ref contact, contactVector_) { + jids.push_back(contact->jid); } return jids; } @@ -374,19 +373,19 @@ void QtUserSearchWindow::setCanStartImpromptuChats(bool supportsImpromptu) { } } -void QtUserSearchWindow::updateContacts(const std::vector& contacts) { +void QtUserSearchWindow::updateContacts(const std::vector& contacts) { if (type_ != AddContact) { firstMultiJIDPage_->contactList_->updateContacts(contacts); } } -void QtUserSearchWindow::addContacts(const std::vector& contacts) { +void QtUserSearchWindow::addContacts(const std::vector& contacts) { if (type_ != AddContact) { /* prevent duplicate JIDs from appearing in the contact list */ - foreach (const Contact& newContact, contacts) { + foreach (Contact::ref newContact, contacts) { bool found = false; - foreach (const Contact& oldContact, contactVector_) { - if (newContact.jid == oldContact.jid) { + foreach (Contact::ref oldContact, contactVector_) { + if (newContact->jid == oldContact->jid) { found = true; break; } @@ -405,7 +404,7 @@ void QtUserSearchWindow::handleAddViaSearch() { next(); } -void QtUserSearchWindow::handleListChanged(std::vector list) { +void QtUserSearchWindow::handleListChanged(std::vector list) { contactVector_ = list; if (type_ == ChatToContact) { firstMultiJIDPage_->groupBox->setEnabled(supportsImpromptu_ ? 1 : (contactVector_.size() < 1)); @@ -470,7 +469,7 @@ void QtUserSearchWindow::setFirstPage(QString title) { connect(firstMultiJIDPage_->jid_, SIGNAL(textEdited(QString)), this, SLOT(handleContactSuggestionRequested(QString))); firstMultiJIDPage_->jid_->onUserSelected.connect(boost::bind(&QtUserSearchWindow::addSearchedJIDToList, this, _1)); connect(firstMultiJIDPage_->addViaSearchButton_, SIGNAL(clicked()), this, SLOT(handleAddViaSearch())); - connect(firstMultiJIDPage_->contactList_, SIGNAL(onListChanged(std::vector)), this, SLOT(handleListChanged(std::vector))); + connect(firstMultiJIDPage_->contactList_, SIGNAL(onListChanged(std::vector)), this, SLOT(handleListChanged(std::vector))); connect(firstMultiJIDPage_->contactList_, SIGNAL(onJIDsAdded(std::vector)), this, SLOT(handleJIDsAdded(std::vector))); connect(firstMultiJIDPage_, SIGNAL(onJIDsDropped(std::vector)), this, SLOT(handleJIDsAdded(std::vector))); setPage(1, firstMultiJIDPage_); diff --git a/Swift/QtUI/UserSearch/QtUserSearchWindow.h b/Swift/QtUI/UserSearch/QtUserSearchWindow.h index 941e455..bb89e51 100644 --- a/Swift/QtUI/UserSearch/QtUserSearchWindow.h +++ b/Swift/QtUI/UserSearch/QtUserSearchWindow.h @@ -43,14 +43,14 @@ namespace Swift { virtual void setSearchFields(boost::shared_ptr fields); virtual void setNameSuggestions(const std::vector& suggestions); virtual void prepopulateJIDAndName(const JID& jid, const std::string& name); - virtual void setContactSuggestions(const std::vector& suggestions); + virtual void setContactSuggestions(const std::vector& suggestions); virtual void setJIDs(const std::vector &jids); virtual void setRoomJID(const JID &roomJID); virtual std::string getReason() const; virtual std::vector getJIDs() const; virtual void setCanStartImpromptuChats(bool supportsImpromptu); - virtual void updateContacts(const std::vector &contacts); - virtual void addContacts(const std::vector& contacts); + virtual void updateContacts(const std::vector &contacts); + virtual void addContacts(const std::vector& contacts); protected: virtual int nextId() const; @@ -62,7 +62,7 @@ namespace Swift { void handleContactSuggestionRequested(const QString& text); void addContact(); void handleAddViaSearch(); - void handleListChanged(std::vector list); + void handleListChanged(std::vector list); void handleJIDsAdded(std::vector jids); private: @@ -91,7 +91,7 @@ namespace Swift { JID myServer_; JID roomJID_; int lastPage_; - std::vector contactVector_; + std::vector contactVector_; SettingsProvider* settings_; bool searchNext_; bool supportsImpromptu_; -- cgit v0.10.2-6-g49f6