summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swift/QtUI/UserSearch')
-rw-r--r--Swift/QtUI/UserSearch/ContactListDelegate.cpp52
-rw-r--r--Swift/QtUI/UserSearch/ContactListDelegate.h30
-rw-r--r--Swift/QtUI/UserSearch/ContactListModel.cpp139
-rw-r--r--Swift/QtUI/UserSearch/ContactListModel.h64
-rw-r--r--Swift/QtUI/UserSearch/QtContactListWidget.cpp101
-rw-r--r--Swift/QtUI/UserSearch/QtContactListWidget.h63
-rw-r--r--Swift/QtUI/UserSearch/QtSuggestingJIDInput.cpp199
-rw-r--r--Swift/QtUI/UserSearch/QtSuggestingJIDInput.h66
-rw-r--r--Swift/QtUI/UserSearch/QtUserSearchDetailsPage.cpp3
-rw-r--r--Swift/QtUI/UserSearch/QtUserSearchFirstMultiJIDPage.cpp101
-rw-r--r--Swift/QtUI/UserSearch/QtUserSearchFirstMultiJIDPage.h52
-rw-r--r--Swift/QtUI/UserSearch/QtUserSearchFirstMultiJIDPage.ui222
-rw-r--r--Swift/QtUI/UserSearch/QtUserSearchFirstPage.cpp9
-rw-r--r--Swift/QtUI/UserSearch/QtUserSearchFirstPage.h6
-rw-r--r--Swift/QtUI/UserSearch/QtUserSearchFirstPage.ui35
-rw-r--r--Swift/QtUI/UserSearch/QtUserSearchWindow.cpp397
-rw-r--r--Swift/QtUI/UserSearch/QtUserSearchWindow.h36
17 files changed, 1499 insertions, 76 deletions
diff --git a/Swift/QtUI/UserSearch/ContactListDelegate.cpp b/Swift/QtUI/UserSearch/ContactListDelegate.cpp
new file mode 100644
index 0000000..56c479b
--- /dev/null
+++ b/Swift/QtUI/UserSearch/ContactListDelegate.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2013 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * 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 <Swift/QtUI/UserSearch/ContactListDelegate.h>
+#include <Swift/QtUI/UserSearch/ContactListModel.h>
+#include <Swift/Controllers/Contact.h>
+#include <Swift/QtUI/QtSwiftUtil.h>
+
+namespace Swift {
+
+ContactListDelegate::ContactListDelegate(bool compact) : compact_(compact) {
+}
+
+ContactListDelegate::~ContactListDelegate() {
+}
+
+void ContactListDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const {
+ if (!index.isValid()) {
+ return;
+ }
+ const Contact::ref contact = static_cast<Contact*>(index.internalPointer())->shared_from_this();
+ QColor nameColor = index.data(Qt::TextColorRole).value<QColor>();
+ QString avatarPath = index.data(ContactListModel::AvatarRole).value<QString>();
+ QIcon presenceIcon =index.data(ChatListRecentItem::PresenceIconRole).isValid() && !index.data(ChatListRecentItem::PresenceIconRole).value<QIcon>().isNull()
+ ? index.data(ChatListRecentItem::PresenceIconRole).value<QIcon>()
+ : QIcon(":/icons/offline.png");
+ QString name = P2QSTRING(contact->name);
+ QString statusText = P2QSTRING(contact->jid.toString());
+ common_.paintContact(painter, option, nameColor, avatarPath, presenceIcon, name, statusText, false, 0, compact_);
+}
+
+QSize ContactListDelegate::sizeHint(const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/ ) const {
+ QFontMetrics nameMetrics(common_.nameFont);
+ QFontMetrics statusMetrics(common_.detailFont);
+ int sizeByText = 2 * common_.verticalMargin + nameMetrics.height() + statusMetrics.height();
+ return QSize(150, sizeByText);
+}
+
+void ContactListDelegate::setCompact(bool compact) {
+ compact_ = compact;
+}
+
+}
diff --git a/Swift/QtUI/UserSearch/ContactListDelegate.h b/Swift/QtUI/UserSearch/ContactListDelegate.h
new file mode 100644
index 0000000..7680aba
--- /dev/null
+++ b/Swift/QtUI/UserSearch/ContactListDelegate.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <QStyledItemDelegate>
+
+#include <Swift/QtUI/Roster/DelegateCommons.h>
+
+namespace Swift {
+
+class ContactListDelegate : public QStyledItemDelegate {
+ public:
+ ContactListDelegate(bool compact);
+ virtual ~ContactListDelegate();
+
+ QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const;
+ void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
+
+ public slots:
+ void setCompact(bool compact);
+
+ private:
+ bool compact_;
+ DelegateCommons common_;
+};
+}
diff --git a/Swift/QtUI/UserSearch/ContactListModel.cpp b/Swift/QtUI/UserSearch/ContactListModel.cpp
new file mode 100644
index 0000000..ef6383c
--- /dev/null
+++ b/Swift/QtUI/UserSearch/ContactListModel.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2013 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * 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 <Swift/QtUI/UserSearch/ContactListModel.h>
+
+#include <QMimeData>
+
+#include <Swiften/Base/Path.h>
+#include <Swiften/Base/foreach.h>
+#include <Swiften/Elements/StatusShow.h>
+
+#include <Swift/QtUI/QtSwiftUtil.h>
+#include <Swift/QtUI/QtResourceHelper.h>
+
+namespace Swift {
+
+QDataStream& operator >>(QDataStream& in, StatusShow::Type& e){
+ quint32 buffer;
+ in >> buffer;
+ switch(buffer) {
+ case StatusShow::Online:
+ e = StatusShow::Online;
+ break;
+ case StatusShow::Away:
+ e = StatusShow::Away;
+ break;
+ case StatusShow::FFC:
+ e = StatusShow::FFC;
+ break;
+ case StatusShow::XA:
+ e = StatusShow::XA;
+ break;
+ case StatusShow::DND:
+ e = StatusShow::DND;
+ break;
+ default:
+ e = StatusShow::None;
+ break;
+ }
+ return in;
+}
+
+ContactListModel::ContactListModel(bool editable) : QAbstractItemModel(), editable_(editable) {
+}
+
+void ContactListModel::setList(const std::vector<Contact::ref>& list) {
+ emit layoutAboutToBeChanged();
+ contacts_ = list;
+ emit layoutChanged();
+}
+
+const std::vector<Contact::ref>& 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()) {
+ flags = flags & ~Qt::ItemIsDropEnabled;
+ } else {
+ flags = Qt::ItemIsDropEnabled | flags;
+ }
+ return flags;
+}
+
+int ContactListModel::columnCount(const QModelIndex&) const {
+ return editable_ ? 2 : 1;
+}
+
+QVariant ContactListModel::data(const QModelIndex& index, int role) const {
+ if (boost::numeric_cast<size_t>(index.row()) < contacts_.size()) {
+ const Contact::ref& contact = contacts_[index.row()];
+ if (role == Qt::EditRole) {
+ return P2QSTRING(contact->jid.toString());
+ }
+ return dataForContact(contact, role);
+ } else {
+ return QVariant();
+ }
+}
+
+QModelIndex ContactListModel::index(int row, int column, const QModelIndex& parent) const {
+ if (!hasIndex(row, column, parent)) {
+ return QModelIndex();
+ }
+
+ return boost::numeric_cast<size_t>(row) < contacts_.size() ? createIndex(row, column, contacts_[row].get()) : QModelIndex();
+}
+
+QModelIndex ContactListModel::parent(const QModelIndex& index) const {
+ if (!index.isValid()) {
+ return QModelIndex();
+ }
+ return QModelIndex();
+}
+
+int ContactListModel::rowCount(const QModelIndex& /*parent*/) const {
+ return contacts_.size();
+}
+
+bool ContactListModel::removeRows(int row, int /*count*/, const QModelIndex& /*parent*/) {
+ if (boost::numeric_cast<size_t>(row) < contacts_.size()) {
+ emit layoutAboutToBeChanged();
+ contacts_.erase(contacts_.begin() + row);
+ emit layoutChanged();
+ onListChanged(getList());
+ return true;
+ }
+ return false;
+}
+
+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 PresenceIconRole: return getPresenceIconForContact(contact);
+ default: return QVariant();
+ }
+}
+
+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
new file mode 100644
index 0000000..e582ac4
--- /dev/null
+++ b/Swift/QtUI/UserSearch/ContactListModel.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2013 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * 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 <vector>
+#include <boost/bind.hpp>
+#include <Swiften/Base/boost_bsignals.h>
+
+#include <QAbstractItemModel>
+
+#include <Swift/Controllers/Contact.h>
+#include <Swift/QtUI/ChatList/ChatListItem.h>
+#include <Swift/QtUI/ChatList/ChatListGroupItem.h>
+#include <Swift/QtUI/ChatList/ChatListRecentItem.h>
+
+namespace Swift {
+ class ContactListModel : public QAbstractItemModel {
+ Q_OBJECT
+ public:
+ enum ContactRoles {
+ DetailTextRole = Qt::UserRole,
+ AvatarRole = Qt::UserRole + 1,
+ PresenceIconRole = Qt::UserRole + 2
+ };
+
+ public:
+ ContactListModel(bool editable);
+
+ void setList(const std::vector<Contact::ref>& list);
+ const std::vector<Contact::ref>& getList() const;
+ Contact::ref getContact(const size_t i) const;
+
+ Qt::ItemFlags flags(const QModelIndex& index) const;
+ int columnCount(const QModelIndex& parent = QModelIndex()) const;
+ QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
+ QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const;
+ QModelIndex parent(const QModelIndex& index) const;
+ int rowCount(const QModelIndex& parent = QModelIndex()) const;
+ bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex());
+
+ private:
+ QVariant dataForContact(const Contact::ref& contact, int role) const;
+ QIcon getPresenceIconForContact(const Contact::ref& contact) const;
+
+ signals:
+ void onListChanged(std::vector<Contact::ref> list);
+ void onJIDsDropped(const std::vector<JID>& contact);
+
+ private:
+ bool editable_;
+ std::vector<Contact::ref> contacts_;
+ };
+
+}
diff --git a/Swift/QtUI/UserSearch/QtContactListWidget.cpp b/Swift/QtUI/UserSearch/QtContactListWidget.cpp
new file mode 100644
index 0000000..6504f3e
--- /dev/null
+++ b/Swift/QtUI/UserSearch/QtContactListWidget.cpp
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2013 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * 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 <Swift/QtUI/UserSearch/QtContactListWidget.h>
+
+#include <Swift/QtUI/UserSearch/ContactListModel.h>
+#include <Swift/QtUI/UserSearch/ContactListDelegate.h>
+#include <Swift/QtUI/QtUISettingConstants.h>
+#include <Swift/Controllers/Settings/SettingsProvider.h>
+#include <Swift/QtUI/QtVCardWidget/QtRemovableItemDelegate.h>
+
+#include <QHeaderView>
+
+namespace Swift {
+
+QtContactListWidget::QtContactListWidget(QWidget* parent, SettingsProvider* settings) : QTreeView(parent), settings_(settings), limited_(false) {
+ contactListModel_ = new ContactListModel(true);
+ setModel(contactListModel_);
+
+ connect(contactListModel_, SIGNAL(onListChanged(std::vector<Contact::ref>)), this, SIGNAL(onListChanged(std::vector<Contact::ref>)));
+ connect(contactListModel_, SIGNAL(onJIDsDropped(std::vector<JID>)), this, SIGNAL(onJIDsAdded(std::vector<JID>)));
+
+ setSelectionMode(QAbstractItemView::SingleSelection);
+ setSelectionBehavior(QAbstractItemView::SelectRows);
+ setUniformRowHeights(true);
+
+ setAlternatingRowColors(true);
+ setIndentation(0);
+ setHeaderHidden(true);
+ setExpandsOnDoubleClick(false);
+ setItemsExpandable(false);
+ setEditTriggers(QAbstractItemView::DoubleClicked);
+
+ contactListDelegate_ = new ContactListDelegate(settings->getSetting(QtUISettingConstants::COMPACT_ROSTER));
+ removableItemDelegate_ = new QtRemovableItemDelegate(style());
+
+ setItemDelegateForColumn(0, contactListDelegate_);
+ setItemDelegateForColumn(1, removableItemDelegate_);
+
+ header()->resizeSection(1, removableItemDelegate_->sizeHint(QStyleOptionViewItem(), QModelIndex()).width());
+
+ header()->setStretchLastSection(false);
+#if QT_VERSION >= 0x050000
+ header()->setSectionResizeMode(0, QHeaderView::Stretch);
+#else
+ header()->setResizeMode(0, QHeaderView::Stretch);
+#endif
+}
+
+QtContactListWidget::~QtContactListWidget() {
+ delete contactListDelegate_;
+ delete removableItemDelegate_;
+}
+
+void QtContactListWidget::setList(const std::vector<Contact::ref>& list) {
+ contactListModel_->setList(list);
+}
+
+std::vector<Contact::ref> 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;
+}
+
+bool QtContactListWidget::isFull() const {
+ return limited_ && (getList().size() == 1);
+}
+
+void QtContactListWidget::updateContacts(const std::vector<Contact::ref>& contactUpdates) {
+ std::vector<Contact::ref> contacts = contactListModel_->getList();
+ foreach(const Contact::ref& contactUpdate, contactUpdates) {
+ for(size_t n = 0; n < contacts.size(); n++) {
+ if (contactUpdate->jid == contacts[n]->jid) {
+ contacts[n] = contactUpdate;
+ break;
+ }
+ }
+ }
+ contactListModel_->setList(contacts);
+}
+
+void QtContactListWidget::handleSettingsChanged(const std::string&) {
+ contactListDelegate_->setCompact(settings_->getSetting(QtUISettingConstants::COMPACT_ROSTER));
+}
+
+}
diff --git a/Swift/QtUI/UserSearch/QtContactListWidget.h b/Swift/QtUI/UserSearch/QtContactListWidget.h
new file mode 100644
index 0000000..112f3ee
--- /dev/null
+++ b/Swift/QtUI/UserSearch/QtContactListWidget.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * 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 <vector>
+
+#include <QTreeView>
+
+#include <Swift/Controllers/Contact.h>
+#include <Swiften/Base/Log.h>
+
+#include <QDragEnterEvent>
+#include <QDragMoveEvent>
+#include <QDropEvent>
+
+namespace Swift {
+
+class ContactListDelegate;
+class ContactListModel;
+class SettingsProvider;
+class QtRemovableItemDelegate;
+
+class QtContactListWidget : public QTreeView {
+ Q_OBJECT
+public:
+ QtContactListWidget(QWidget* parent, SettingsProvider* settings);
+ virtual ~QtContactListWidget();
+
+ void setList(const std::vector<Contact::ref>& list);
+ std::vector<Contact::ref> getList() const;
+ Contact::ref getContact(const size_t i);
+ void setMaximumNoOfContactsToOne(bool limited);
+ bool isFull() const;
+
+public slots:
+ void updateContacts(const std::vector<Contact::ref>& contactUpdates);
+
+signals:
+ void onListChanged(std::vector<Contact::ref> list);
+ void onJIDsAdded(const std::vector<JID>& jids);
+
+private:
+ void handleSettingsChanged(const std::string&);
+
+private:
+ SettingsProvider* settings_;
+ ContactListModel* contactListModel_;
+ ContactListDelegate* contactListDelegate_;
+ QtRemovableItemDelegate* removableItemDelegate_;
+ bool limited_;
+};
+
+}
diff --git a/Swift/QtUI/UserSearch/QtSuggestingJIDInput.cpp b/Swift/QtUI/UserSearch/QtSuggestingJIDInput.cpp
new file mode 100644
index 0000000..57033d8
--- /dev/null
+++ b/Swift/QtUI/UserSearch/QtSuggestingJIDInput.cpp
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2013 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * 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 <Swift/QtUI/UserSearch/QtSuggestingJIDInput.h>
+#include <Swift/QtUI/UserSearch/ContactListDelegate.h>
+#include <Swift/Controllers/Settings/SettingsProvider.h>
+#include <Swift/QtUI/QtUISettingConstants.h>
+#include <Swift/QtUI/UserSearch/ContactListModel.h>
+
+#include <Swiften/Base/boost_bsignals.h>
+#include <boost/bind.hpp>
+
+#include <Swift/QtUI/QtSwiftUtil.h>
+
+#include <QAbstractItemView>
+#include <QApplication>
+#include <QDesktopWidget>
+#include <QKeyEvent>
+
+
+namespace Swift {
+
+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);
+ treeViewPopup_->setAlternatingRowColors(true);
+ treeViewPopup_->setIndentation(0);
+ treeViewPopup_->setHeaderHidden(true);
+ treeViewPopup_->setExpandsOnDoubleClick(false);
+ treeViewPopup_->setItemsExpandable(false);
+ treeViewPopup_->setSelectionMode(QAbstractItemView::SingleSelection);
+ treeViewPopup_->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
+ treeViewPopup_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ QSizePolicy policy(treeViewPopup_->sizePolicy());
+ policy.setVerticalPolicy(QSizePolicy::Expanding);
+ treeViewPopup_->setSizePolicy(policy);
+ treeViewPopup_->hide();
+ treeViewPopup_->setFocusProxy(this);
+ connect(treeViewPopup_, SIGNAL(clicked(QModelIndex)), this, SLOT(handleClicked(QModelIndex)));
+ connect(treeViewPopup_, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(handleClicked(QModelIndex)));
+
+ contactListModel_ = new ContactListModel(false);
+ treeViewPopup_->setModel(contactListModel_);
+
+ contactListDelegate_ = new ContactListDelegate(settings->getSetting(QtUISettingConstants::COMPACT_ROSTER));
+ treeViewPopup_->setItemDelegate(contactListDelegate_);
+
+ settings_->onSettingChanged.connect(boost::bind(&QtSuggestingJIDInput::handleSettingsChanged, this, _1));
+}
+
+QtSuggestingJIDInput::~QtSuggestingJIDInput() {
+ settings_->onSettingChanged.disconnect(boost::bind(&QtSuggestingJIDInput::handleSettingsChanged, this, _1));
+ delete treeViewPopup_;
+}
+
+Contact::ref QtSuggestingJIDInput::getContact() {
+ if (!!currentContact_) {
+ return currentContact_;
+ }
+
+ if (!text().isEmpty()) {
+ JID jid(Q2PSTRING(text()));
+ if (jid.isValid()) {
+ Contact::ref manualContact = boost::make_shared<Contact>();
+ manualContact->name = jid.toString();
+ manualContact->jid = jid;
+ return manualContact;
+ }
+ }
+ return boost::shared_ptr<Contact>();
+}
+
+void QtSuggestingJIDInput::setSuggestions(const std::vector<Contact::ref>& suggestions) {
+ contactListModel_->setList(suggestions);
+ positionPopup();
+ if (!suggestions.empty()) {
+ treeViewPopup_->setCurrentIndex(contactListModel_->index(0, 0));
+ showPopup();
+ } else {
+ currentContact_.reset();
+ hidePopup();
+ }
+}
+
+void QtSuggestingJIDInput::clear() {
+ setText("");
+ currentContact_.reset();
+}
+
+void QtSuggestingJIDInput::keyPressEvent(QKeyEvent* event) {
+ if (event->key() == Qt::Key_Up) {
+ if (contactListModel_->rowCount() > 0) {
+ int row = treeViewPopup_->currentIndex().row();
+ row = (row + contactListModel_->rowCount() - 1) % contactListModel_->rowCount();
+ treeViewPopup_->setCurrentIndex(contactListModel_->index(row, 0));
+ }
+ } else if (event->key() == Qt::Key_Down) {
+ if (contactListModel_->rowCount() > 0) {
+ int row = treeViewPopup_->currentIndex().row();
+ row = (row + contactListModel_->rowCount() + 1) % contactListModel_->rowCount();
+ treeViewPopup_->setCurrentIndex(contactListModel_->index(row, 0));
+ }
+ } else if (event->key() == Qt::Key_Return && treeViewPopup_->isVisible()) {
+ QModelIndex index = treeViewPopup_->currentIndex();
+ if (!contactListModel_->getList().empty() && index.isValid()) {
+ currentContact_ = contactListModel_->getContact(index.row());
+ if (currentContact_->jid.isValid()) {
+ setText(P2QSTRING(currentContact_->jid.toString()));
+ } else {
+ setText(P2QSTRING(currentContact_->name));
+ }
+ hidePopup();
+ clearFocus();
+ } else {
+ currentContact_.reset();
+ }
+ editingDone();
+ } else {
+ QLineEdit::keyPressEvent(event);
+ }
+}
+
+void QtSuggestingJIDInput::handleApplicationFocusChanged(QWidget* /*old*/, QWidget* /*now*/) {
+ /* Using the now argument gives use the wrong widget. This is part of the code needed
+ to prevent stealing of focus when opening a the suggestion window. */
+ QWidget* now = qApp->focusWidget();
+ if (!now || (now != treeViewPopup_ && now != this && !now->isAncestorOf(this) && !now->isAncestorOf(treeViewPopup_) && !this->isAncestorOf(now) && !treeViewPopup_->isAncestorOf(now))) {
+ hidePopup();
+ }
+}
+
+void QtSuggestingJIDInput::handleSettingsChanged(const std::string& setting) {
+ if (setting == QtUISettingConstants::COMPACT_ROSTER.getKey()) {
+ contactListDelegate_->setCompact(settings_->getSetting(QtUISettingConstants::COMPACT_ROSTER));
+ }
+}
+
+void QtSuggestingJIDInput::handleClicked(const QModelIndex& index) {
+ if (index.isValid()) {
+ currentContact_ = contactListModel_->getContact(index.row());
+ onUserSelected(currentContact_);
+ hidePopup();
+ }
+}
+
+void QtSuggestingJIDInput::positionPopup() {
+ QDesktopWidget* desktop = QApplication::desktop();
+ int screen = desktop->screenNumber(this);
+ QPoint point = mapToGlobal(QPoint(0, height()));
+ QRect geometry = desktop->availableGeometry(screen);
+ int x = point.x();
+ int y = point.y();
+ int width = this->width();
+ int height = 80;
+
+ int screenWidth = geometry.x() + geometry.width();
+ if (x + width > screenWidth) {
+ x = screenWidth - width;
+ }
+
+ height = treeViewPopup_->sizeHintForRow(0) * contactListModel_->rowCount();
+ height = height > 200 ? 200 : height;
+
+ int marginLeft;
+ int marginTop;
+ int marginRight;
+ int marginBottom;
+ treeViewPopup_->getContentsMargins(&marginLeft, &marginTop, &marginRight, &marginBottom);
+ height += marginTop + marginBottom;
+ width += marginLeft + marginRight;
+
+ treeViewPopup_->setGeometry(x, y, width, height);
+ treeViewPopup_->move(x, y);
+ treeViewPopup_->setMaximumWidth(width);
+}
+
+void QtSuggestingJIDInput::showPopup() {
+ treeViewPopup_->show();
+ activateWindow();
+ connect(qApp, SIGNAL(focusChanged(QWidget*, QWidget*)), this, SLOT(handleApplicationFocusChanged(QWidget*, QWidget*)), Qt::QueuedConnection);
+ setFocus();
+}
+
+void QtSuggestingJIDInput::hidePopup() {
+ disconnect(qApp, SIGNAL(focusChanged(QWidget*, QWidget*)), this, SLOT(handleApplicationFocusChanged(QWidget*, QWidget*)));
+ treeViewPopup_->hide();
+}
+
+}
diff --git a/Swift/QtUI/UserSearch/QtSuggestingJIDInput.h b/Swift/QtUI/UserSearch/QtSuggestingJIDInput.h
new file mode 100644
index 0000000..23e7b94
--- /dev/null
+++ b/Swift/QtUI/UserSearch/QtSuggestingJIDInput.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2013 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * 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 <QLineEdit>
+#include <QTreeView>
+#include <Swiften/Base/boost_bsignals.h>
+#include <Swift/Controllers/Contact.h>
+
+namespace Swift {
+
+class ContactListDelegate;
+class SettingsProvider;
+class ContactListModel;
+
+class QtSuggestingJIDInput : public QLineEdit {
+ Q_OBJECT
+ public:
+ QtSuggestingJIDInput(QWidget* parent, SettingsProvider* settings);
+ virtual ~QtSuggestingJIDInput();
+
+ Contact::ref getContact();
+
+ void setSuggestions(const std::vector<Contact::ref>& suggestions);
+
+ void clear();
+
+ boost::signal<void (const Contact::ref&)> onUserSelected;
+
+ signals:
+ void editingDone();
+
+ protected:
+ virtual void keyPressEvent(QKeyEvent* event);
+
+ private:
+ void handleSettingsChanged(const std::string& setting);
+
+ private slots:
+ void handleClicked(const QModelIndex& index);
+ void handleApplicationFocusChanged(QWidget* old, QWidget* now);
+
+ private:
+ void positionPopup();
+ void showPopup();
+ void hidePopup();
+
+ private:
+ SettingsProvider* settings_;
+ ContactListModel* contactListModel_;
+ QTreeView* treeViewPopup_;
+ ContactListDelegate* contactListDelegate_;
+ Contact::ref currentContact_;
+};
+
+}
diff --git a/Swift/QtUI/UserSearch/QtUserSearchDetailsPage.cpp b/Swift/QtUI/UserSearch/QtUserSearchDetailsPage.cpp
index f4189e7..d8c70b6 100644
--- a/Swift/QtUI/UserSearch/QtUserSearchDetailsPage.cpp
+++ b/Swift/QtUI/UserSearch/QtUserSearchDetailsPage.cpp
@@ -1,4 +1,4 @@
/*
- * Copyright (c) 2011 Remko Tronçon
+ * Copyright (c) 2011-2014 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
@@ -8,4 +8,5 @@
#include <QVBoxLayout>
+#include <QLabel>
#include <boost/bind.hpp>
diff --git a/Swift/QtUI/UserSearch/QtUserSearchFirstMultiJIDPage.cpp b/Swift/QtUI/UserSearch/QtUserSearchFirstMultiJIDPage.cpp
new file mode 100644
index 0000000..2c34aa6
--- /dev/null
+++ b/Swift/QtUI/UserSearch/QtUserSearchFirstMultiJIDPage.cpp
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2013 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * 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 "Swift/QtUI/UserSearch/QtUserSearchFirstMultiJIDPage.h"
+
+#include <QMessageBox>
+#include <QMimeData>
+#include <QUrl>
+
+#include "Swift/QtUI/QtSwiftUtil.h"
+#include <Swift/Controllers/Settings/SettingsProvider.h>
+#include <Swift/QtUI/UserSearch/QtContactListWidget.h>
+#include <Swift/QtUI/UserSearch/QtSuggestingJIDInput.h>
+
+namespace Swift {
+
+QtUserSearchFirstMultiJIDPage::QtUserSearchFirstMultiJIDPage(UserSearchWindow::Type type, const QString& title, SettingsProvider* settings) {
+ setupUi(this);
+ setTitle(title);
+ QString introText = "";
+ switch (type) {
+ case UserSearchWindow::AddContact:
+ introText = tr("Add another user to your contact list");
+ break;
+ case UserSearchWindow::ChatToContact:
+ introText = tr("Chat to another user");
+ break;
+ case UserSearchWindow::InviteToChat:
+ introText = tr("Invite contact to chat");
+ break;
+ }
+
+ setSubTitle(QString(tr("%1. If you know their address you can enter it directly, or you can search for them.")).arg(introText));
+
+ contactList_ = new QtContactListWidget(this, settings);
+ horizontalLayout_5->addWidget(contactList_);
+
+ jid_ = new QtSuggestingJIDInput(this, settings);
+ horizontalLayout_6->insertWidget(0, jid_);
+
+ connect(contactList_, SIGNAL(onListChanged(std::vector<Contact::ref>)), this, SLOT(emitCompletenessCheck()));
+ connect(jid_, SIGNAL(editingDone()), this, SLOT(handleEditingDone()));
+
+ setAcceptDrops(true);
+}
+
+bool QtUserSearchFirstMultiJIDPage::isComplete() const {
+ return !contactList_->getList().empty();
+}
+
+void QtUserSearchFirstMultiJIDPage::reset() {
+ jid_->clear();
+ reason_->clear();
+}
+
+void QtUserSearchFirstMultiJIDPage::emitCompletenessCheck() {
+ emit completeChanged();
+}
+
+void QtUserSearchFirstMultiJIDPage::handleEditingDone() {
+ addContactButton_->setFocus();
+}
+
+void QtUserSearchFirstMultiJIDPage::dragEnterEvent(QDragEnterEvent *event) {
+ if (event->mimeData()->hasFormat("application/vnd.swift.contact-jid-list")
+ || event->mimeData()->hasFormat("application/vnd.swift.contact-jid-muc")) {
+ if (!contactList_->isFull()) {
+ event->acceptProposedAction();
+ }
+ }
+}
+
+void QtUserSearchFirstMultiJIDPage::dropEvent(QDropEvent *event) {
+ 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> jids;
+ while (!dataStream.atEnd()) {
+ QString jidString;
+ dataStream >> jidString;
+ jids.push_back(Q2PSTRING(jidString));
+ }
+ onJIDsDropped(jids);
+ } else if (event->mimeData()->hasFormat("application/vnd.swift.contact-jid-muc")) {
+ QMessageBox* messageBox = new QMessageBox(this);
+ messageBox->setText(tr("You can't invite a room to chat."));
+ messageBox->setWindowTitle(tr("Error inviting room to chat"));
+ messageBox->show();
+ }
+}
+
+}
diff --git a/Swift/QtUI/UserSearch/QtUserSearchFirstMultiJIDPage.h b/Swift/QtUI/UserSearch/QtUserSearchFirstMultiJIDPage.h
new file mode 100644
index 0000000..431dd3c
--- /dev/null
+++ b/Swift/QtUI/UserSearch/QtUserSearchFirstMultiJIDPage.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2013 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * 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 <QWizardPage>
+
+#include <Swift/QtUI/UserSearch/ui_QtUserSearchFirstMultiJIDPage.h>
+#include <Swift/Controllers/UIInterfaces/UserSearchWindow.h>
+
+namespace Swift {
+ class UserSearchModel;
+ class UserSearchDelegate;
+ class UserSearchResult;
+ class UIEventStream;
+ class QtContactListWidget;
+ class ContactSuggester;
+ class AvatarManager;
+ class VCardManager;
+ class SettingsProvider;
+ class QtSuggestingJIDInput;
+
+ class QtUserSearchFirstMultiJIDPage : public QWizardPage, public Ui::QtUserSearchFirstMultiJIDPage {
+ Q_OBJECT
+ public:
+ QtUserSearchFirstMultiJIDPage(UserSearchWindow::Type type, const QString& title, SettingsProvider* settings);
+ virtual bool isComplete() const;
+ void reset();
+
+ signals:
+ void onJIDsDropped(std::vector<JID> jid);
+
+ public slots:
+ void emitCompletenessCheck();
+ void handleEditingDone();
+ virtual void dragEnterEvent(QDragEnterEvent *event);
+ virtual void dropEvent(QDropEvent *event);
+
+ public:
+ QtContactListWidget* contactList_;
+ QtSuggestingJIDInput* jid_;
+ };
+}
diff --git a/Swift/QtUI/UserSearch/QtUserSearchFirstMultiJIDPage.ui b/Swift/QtUI/UserSearch/QtUserSearchFirstMultiJIDPage.ui
new file mode 100644
index 0000000..4a87f41
--- /dev/null
+++ b/Swift/QtUI/UserSearch/QtUserSearchFirstMultiJIDPage.ui
@@ -0,0 +1,222 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>QtUserSearchFirstMultiJIDPage</class>
+ <widget class="QWizardPage" name="QtUserSearchFirstMultiJIDPage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>477</width>
+ <height>500</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string/>
+ </property>
+ <property name="title">
+ <string>Add a user</string>
+ </property>
+ <property name="subTitle">
+ <string>Add another user to your contact list. If you know their address you can add them directly, or you can search for them.</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="howLabel_">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_5"/>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="title">
+ <string>Choose another contact</string>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ <property name="checkable">
+ <bool>false</bool>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <property name="spacing">
+ <number>-1</number>
+ </property>
+ <property name="margin">
+ <number>6</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_6" stretch="0">
+ <property name="spacing">
+ <number>-1</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="addContactButton_">
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Add Contact</string>
+ </property>
+ <property name="default">
+ <bool>false</bool>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="Line" name="line">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QRadioButton" name="byLocalSearch_">
+ <property name="text">
+ <string>I'd like to search my server</string>
+ </property>
+ <property name="autoExclusive">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QRadioButton" name="byRemoteSearch_">
+ <property name="text">
+ <string>I'd like to search another server:</string>
+ </property>
+ <property name="autoExclusive">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="service_">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="addViaSearchButton_">
+ <property name="text">
+ <string>Add via Search</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Reason:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="reason_"/>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>77</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="errorLabel_">
+ <property name="text">
+ <string/>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/Swift/QtUI/UserSearch/QtUserSearchFirstPage.cpp b/Swift/QtUI/UserSearch/QtUserSearchFirstPage.cpp
index 7a91a98..af53a26 100644
--- a/Swift/QtUI/UserSearch/QtUserSearchFirstPage.cpp
+++ b/Swift/QtUI/UserSearch/QtUserSearchFirstPage.cpp
@@ -9,10 +9,17 @@
#include "Swift/QtUI/QtSwiftUtil.h"
+#include <Swiften/Base/Log.h>
+
namespace Swift {
-QtUserSearchFirstPage::QtUserSearchFirstPage(UserSearchWindow::Type type, const QString& title) {
+QtUserSearchFirstPage::QtUserSearchFirstPage(UserSearchWindow::Type type, const QString& title, SettingsProvider* settings) {
setupUi(this);
setTitle(title);
setSubTitle(QString(tr("%1. If you know their address you can enter it directly, or you can search for them.")).arg(type == UserSearchWindow::AddContact ? tr("Add another user to your contact list") : tr("Chat to another user")));
+ jid_ = new QtSuggestingJIDInput(this, settings);
+ horizontalLayout_2->addWidget(jid_);
+ setTabOrder(byJID_, jid_);
+ setTabOrder(jid_, byLocalSearch_);
+ setTabOrder(byLocalSearch_, byRemoteSearch_);
connect(jid_, SIGNAL(textChanged(const QString&)), this, SLOT(emitCompletenessCheck()));
connect(service_->lineEdit(), SIGNAL(textChanged(const QString&)), this, SLOT(emitCompletenessCheck()));
diff --git a/Swift/QtUI/UserSearch/QtUserSearchFirstPage.h b/Swift/QtUI/UserSearch/QtUserSearchFirstPage.h
index d23b87d..d7487b0 100644
--- a/Swift/QtUI/UserSearch/QtUserSearchFirstPage.h
+++ b/Swift/QtUI/UserSearch/QtUserSearchFirstPage.h
@@ -12,4 +12,6 @@
#include <Swift/Controllers/UIInterfaces/UserSearchWindow.h>
+#include <Swift/QtUI/UserSearch/QtSuggestingJIDInput.h>
+
namespace Swift {
class UserSearchModel;
@@ -21,8 +23,10 @@ namespace Swift {
Q_OBJECT
public:
- QtUserSearchFirstPage(UserSearchWindow::Type type, const QString& title);
+ QtUserSearchFirstPage(UserSearchWindow::Type type, const QString& title, SettingsProvider* settings);
virtual bool isComplete() const;
public slots:
void emitCompletenessCheck();
+ public:
+ QtSuggestingJIDInput* jid_;
};
}
diff --git a/Swift/QtUI/UserSearch/QtUserSearchFirstPage.ui b/Swift/QtUI/UserSearch/QtUserSearchFirstPage.ui
index 46a1277..24d401e 100644
--- a/Swift/QtUI/UserSearch/QtUserSearchFirstPage.ui
+++ b/Swift/QtUI/UserSearch/QtUserSearchFirstPage.ui
@@ -12,5 +12,5 @@
</property>
<property name="windowTitle">
- <string></string>
+ <string/>
</property>
<property name="title">
@@ -24,5 +24,5 @@
<widget class="QLabel" name="howLabel_">
<property name="text">
- <string></string>
+ <string/>
</property>
</widget>
@@ -35,19 +35,39 @@
<string>I know their address:</string>
</property>
+ <property name="autoExclusive">
+ <bool>true</bool>
+ </property>
</widget>
</item>
- <item>
- <widget class="QLineEdit" name="jid_"/>
- </item>
</layout>
</item>
<item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
<widget class="QRadioButton" name="byLocalSearch_">
<property name="text">
<string>I'd like to search my server</string>
</property>
+ <property name="autoExclusive">
+ <bool>true</bool>
+ </property>
</widget>
</item>
<item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
@@ -56,4 +76,7 @@
<string>I'd like to search another server:</string>
</property>
+ <property name="autoExclusive">
+ <bool>true</bool>
+ </property>
</widget>
</item>
@@ -89,5 +112,5 @@
<widget class="QLabel" name="errorLabel_">
<property name="text">
- <string></string>
+ <string/>
</property>
<property name="alignment">
diff --git a/Swift/QtUI/UserSearch/QtUserSearchWindow.cpp b/Swift/QtUI/UserSearch/QtUserSearchWindow.cpp
index 2b11d02..babe115 100644
--- a/Swift/QtUI/UserSearch/QtUserSearchWindow.cpp
+++ b/Swift/QtUI/UserSearch/QtUserSearchWindow.cpp
@@ -1,4 +1,4 @@
/*
- * Copyright (c) 2010 Kevin Smith
+ * Copyright (c) 2010-2014 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
@@ -11,58 +11,52 @@
#include <QWizardPage>
#include <QMovie>
+#include <boost/bind.hpp>
#include <boost/smart_ptr/make_shared.hpp>
#include <Swiften/Base/foreach.h>
-#include "Swift/Controllers/UIEvents/UIEventStream.h"
-#include "Swift/Controllers/UIEvents/RequestChatUIEvent.h"
-#include "Swift/Controllers/UIEvents/AddContactUIEvent.h"
-#include "Swift/QtUI/UserSearch/UserSearchModel.h"
-#include "Swift/QtUI/UserSearch/UserSearchDelegate.h"
-#include "Swift/QtUI/QtSwiftUtil.h"
-#include "Swift/QtUI/QtFormResultItemModel.h"
-#include "QtUserSearchFirstPage.h"
-#include "QtUserSearchFieldsPage.h"
-#include "QtUserSearchResultsPage.h"
-#include "QtUserSearchDetailsPage.h"
+#include <Swift/Controllers/UIEvents/UIEventStream.h>
+#include <Swift/Controllers/UIEvents/RequestChatUIEvent.h>
+#include <Swift/Controllers/UIEvents/AddContactUIEvent.h>
+#include <Swift/Controllers/UIEvents/CreateImpromptuMUCUIEvent.h>
+#include <Swift/Controllers/UIEvents/InviteToMUCUIEvent.h>
+#include <Swift/QtUI/UserSearch/UserSearchModel.h>
+#include <Swift/QtUI/UserSearch/UserSearchDelegate.h>
+#include <Swift/QtUI/QtSwiftUtil.h>
+#include <Swift/QtUI/QtFormResultItemModel.h>
+#include <Swift/QtUI/UserSearch/QtUserSearchFirstPage.h>
+#include <Swift/QtUI/UserSearch/QtUserSearchFirstMultiJIDPage.h>
+#include <Swift/QtUI/UserSearch/QtUserSearchFieldsPage.h>
+#include <Swift/QtUI/UserSearch/QtUserSearchResultsPage.h>
+#include <Swift/QtUI/UserSearch/QtUserSearchDetailsPage.h>
+#include <Swift/QtUI/UserSearch/QtContactListWidget.h>
+
+#include <Swiften/Base/Log.h>
namespace Swift {
-QtUserSearchWindow::QtUserSearchWindow(UIEventStream* eventStream, UserSearchWindow::Type type, const std::set<std::string>& groups) : eventStream_(eventStream), type_(type), model_(NULL) {
+QtUserSearchWindow::QtUserSearchWindow(UIEventStream* eventStream, UserSearchWindow::Type type, const std::set<std::string>& groups, SettingsProvider* settingsProvider) : eventStream_(eventStream), type_(type), model_(NULL), firstMultiJIDPage_(NULL), settings_(settingsProvider), searchNext_(false), supportsImpromptu_(false) {
setupUi(this);
-#ifndef Q_WS_MAC
+#ifndef Q_OS_MAC
setWindowIcon(QIcon(":/logo-icon-16.png"));
#endif
- QString title(type == UserSearchWindow::AddContact ? tr("Add Contact") : tr("Chat to User"));
+ QString title;
+ switch(type) {
+ case AddContact:
+ title = tr("Add Contact");
+ break;
+ case ChatToContact:
+ title = tr("Chat to Users");
+ break;
+ case InviteToChat:
+ title = tr("Add Users to Chat");
+ break;
+ }
setWindowTitle(title);
delegate_ = new UserSearchDelegate();
- firstPage_ = new QtUserSearchFirstPage(type, title);
- connect(firstPage_->byJID_, SIGNAL(toggled(bool)), this, SLOT(handleFirstPageRadioChange()));
- connect(firstPage_->byLocalSearch_, SIGNAL(toggled(bool)), this, SLOT(handleFirstPageRadioChange()));
- connect(firstPage_->byRemoteSearch_, SIGNAL(toggled(bool)), this, SLOT(handleFirstPageRadioChange()));
-#if QT_VERSION >= 0x040700
- firstPage_->jid_->setPlaceholderText(tr("alice@wonderland.lit"));
-#endif
- firstPage_->service_->setEnabled(false);
- setPage(1, firstPage_);
-
- fieldsPage_ = new QtUserSearchFieldsPage();
- fieldsPage_->fetchingThrobber_->setMovie(new QMovie(":/icons/throbber.gif", QByteArray(), this));
- fieldsPage_->fetchingThrobber_->movie()->stop();
- setPage(2, fieldsPage_);
-
- resultsPage_ = new QtUserSearchResultsPage();
-
-#ifdef SWIFT_PLATFORM_MACOSX
- resultsPage_->results_->setAlternatingRowColors(true);
-#endif
- if (type == AddContact) {
- connect(resultsPage_, SIGNAL(onUserTriggersContinue()), this, SLOT(next()));
- }
- else {
- connect(resultsPage_, SIGNAL(onUserTriggersContinue()), this, SLOT(accept()));
- }
- setPage(3, resultsPage_);
+ setFirstPage(title);
+ setSecondPage();
+ setThirdPage();
detailsPage_ = new QtUserSearchDetailsPage(groups);
@@ -79,5 +73,14 @@ QtUserSearchWindow::~QtUserSearchWindow() {
void QtUserSearchWindow::handleCurrentChanged(int page) {
- if (page == 2 && lastPage_ == 1) {
+ searchNext_ = false;
+ if (firstMultiJIDPage_) {
+ firstMultiJIDPage_->reset();
+ }
+ resultsPage_->emitCompletenessCheck();
+ if (page == 1 && lastPage_ == 3) {
+ addSearchedJIDToList(getContact());
+ setSecondPage();
+ }
+ else if (page == 2 && lastPage_ == 1) {
setError("");
/* next won't be called if JID is selected */
@@ -85,7 +88,20 @@ void QtUserSearchWindow::handleCurrentChanged(int page) {
clearForm();
onFormRequested(server);
+ setThirdPage();
}
else if (page == 3 && lastPage_ == 2) {
+ JID server = getServerToSearch();
handleSearch();
+
+ if (type_ == AddContact) {
+ bool remote = firstPage_->byRemoteSearch_->isChecked();
+ firstPage_->byRemoteSearch_->setChecked(remote);
+ firstPage_->service_->setEditText(P2QSTRING(server.toString()));
+ } else {
+ bool remote = firstMultiJIDPage_->byRemoteSearch_->isChecked();
+ setFirstPage();
+ firstMultiJIDPage_->byRemoteSearch_->setChecked(remote);
+ firstMultiJIDPage_->service_->setEditText(P2QSTRING(server.toString()));
+ }
}
else if (page == 4) {
@@ -98,20 +114,60 @@ void QtUserSearchWindow::handleCurrentChanged(int page) {
JID QtUserSearchWindow::getServerToSearch() {
+ if (type_ == AddContact) {
return firstPage_->byRemoteSearch_->isChecked() ? JID(Q2PSTRING(firstPage_->service_->currentText().trimmed())) : myServer_;
+ } else {
+ return firstMultiJIDPage_->byRemoteSearch_->isChecked() ? JID(Q2PSTRING(firstMultiJIDPage_->service_->currentText().trimmed())) : myServer_;
+ }
}
void QtUserSearchWindow::handleAccepted() {
- JID jid = getContactJID();
-
- if (type_ == AddContact) {
+ JID jid;
+ std::vector<JID> jids;
+ switch(type_) {
+ case AddContact:
+ jid = getContactJID();
eventStream_->send(boost::make_shared<AddContactUIEvent>(jid, detailsPage_->getName(), detailsPage_->getSelectedGroups()));
- }
- else {
- boost::shared_ptr<UIEvent> event(new RequestChatUIEvent(jid));
+ break;
+ case ChatToContact:
+ if (contactVector_.size() == 1) {
+ boost::shared_ptr<UIEvent> event(new RequestChatUIEvent(contactVector_[0]->jid));
eventStream_->send(event);
+ break;
+ }
+
+ foreach(Contact::ref contact, contactVector_) {
+ jids.push_back(contact->jid);
+ }
+
+ eventStream_->send(boost::make_shared<CreateImpromptuMUCUIEvent>(jids, JID(), Q2PSTRING(firstMultiJIDPage_->reason_->text())));
+ break;
+ case InviteToChat:
+ foreach(Contact::ref contact, contactVector_) {
+ jids.push_back(contact->jid);
+ }
+ eventStream_->send(boost::make_shared<InviteToMUCUIEvent>(roomJID_, jids, Q2PSTRING(firstMultiJIDPage_->reason_->text())));
+ break;
+ }
+}
+
+void QtUserSearchWindow::handleContactSuggestionRequested(const QString& text) {
+ std::string stdText = Q2PSTRING(text);
+ onContactSuggestionsRequested(stdText);
+}
+
+void QtUserSearchWindow::addContact() {
+ if (!!firstMultiJIDPage_->jid_->getContact()) {
+ contactVector_.push_back(firstMultiJIDPage_->jid_->getContact());
+ firstMultiJIDPage_->jid_->clear();
+ }
+ firstMultiJIDPage_->contactList_->setList(contactVector_);
+ firstMultiJIDPage_->emitCompletenessCheck();
+ if (type_ == ChatToContact) {
+ firstMultiJIDPage_->groupBox->setEnabled(supportsImpromptu_ ? 1 : (contactVector_.size() < 1));
}
}
int QtUserSearchWindow::nextId() const {
+ if (type_ == AddContact) {
switch (currentId()) {
case 1: return firstPage_->byJID_->isChecked() ? (type_ == AddContact ? 4 : -1) : 2;
@@ -121,4 +177,13 @@ int QtUserSearchWindow::nextId() const {
default: return -1;
}
+ } else {
+ switch (currentId()) {
+ case 1: return searchNext_ ? 2 : -1;
+ case 2: return 3;
+ case 3: return 1;
+ case 4: return -1;
+ default: return -1;
+ }
+ }
}
@@ -148,15 +213,16 @@ void QtUserSearchWindow::handleSearch() {
if (fieldsPage_->getFormWidget()) {
search->setForm(fieldsPage_->getFormWidget()->getCompletedForm());
+ search->getForm()->clearEmptyTextFields();
} else {
- if (fieldsPage_->nickInput_->isEnabled()) {
+ if (fieldsPage_->nickInput_->isEnabled() && !fieldsPage_->nickInput_->text().isEmpty()) {
search->setNick(Q2PSTRING(fieldsPage_->nickInput_->text()));
}
- if (fieldsPage_->firstInput_->isEnabled()) {
+ if (fieldsPage_->firstInput_->isEnabled() && !fieldsPage_->firstInput_->text().isEmpty()) {
search->setFirst(Q2PSTRING(fieldsPage_->firstInput_->text()));
}
- if (fieldsPage_->lastInput_->isEnabled()) {
+ if (fieldsPage_->lastInput_->isEnabled() && !fieldsPage_->lastInput_->text().isEmpty()) {
search->setLast(Q2PSTRING(fieldsPage_->lastInput_->text()));
}
- if (fieldsPage_->emailInput_->isEnabled()) {
+ if (fieldsPage_->emailInput_->isEnabled() && !fieldsPage_->emailInput_->text().isEmpty()) {
search->setEMail(Q2PSTRING(fieldsPage_->emailInput_->text()));
}
@@ -167,5 +233,13 @@ void QtUserSearchWindow::handleSearch() {
JID QtUserSearchWindow::getContactJID() const {
JID jid;
- if (!firstPage_->byJID_->isChecked()) {
+
+ bool useSearchResult;
+ if (type_ == AddContact) {
+ useSearchResult = !firstPage_->byJID_->isChecked();
+ } else {
+ useSearchResult = true;
+ }
+
+ if (useSearchResult) {
if (dynamic_cast<UserSearchModel*>(model_)) {
UserSearchResult* userItem = static_cast<UserSearchResult*>(resultsPage_->results_->currentIndex().internalPointer());
@@ -173,5 +247,5 @@ JID QtUserSearchWindow::getContactJID() const {
jid = userItem->getJID();
}
- } else {
+ } else if (dynamic_cast<QtFormResultItemModel*>(model_)) {
int row = resultsPage_->results_->currentIndex().row();
@@ -179,10 +253,10 @@ JID QtUserSearchWindow::getContactJID() const {
JID fallbackJid;
foreach(FormField::ref field, item) {
- if (boost::dynamic_pointer_cast<JIDSingleFormField>(field)) {
- jid = JID(field->getRawValues().at(0));
+ if (field->getType() == FormField::JIDSingleType) {
+ jid = JID(field->getJIDSingleValue());
break;
}
if (field->getName() == "jid") {
- fallbackJid = field->getRawValues().at(0);
+ fallbackJid = field->getValues()[0];
}
}
@@ -198,4 +272,19 @@ JID QtUserSearchWindow::getContactJID() const {
}
+Contact::ref QtUserSearchWindow::getContact() const {
+ return boost::make_shared<Contact>("", getContactJID(), StatusShow::None, "");
+}
+
+void QtUserSearchWindow::addSearchedJIDToList(const Contact::ref& contact) {
+ std::vector<JID> jids;
+ jids.push_back(contact->jid);
+ handleJIDsAdded(jids);
+ firstMultiJIDPage_->jid_->clear();
+}
+
+void QtUserSearchWindow::handleOnSearchedJIDSelected(const Contact::ref& contact) {
+ firstPage_->jid_->setText(P2QSTRING(contact->jid.toString()));
+}
+
void QtUserSearchWindow::show() {
clear();
@@ -204,4 +293,5 @@ void QtUserSearchWindow::show() {
void QtUserSearchWindow::addSavedServices(const std::vector<JID>& services) {
+ if (type_ == AddContact) {
firstPage_->service_->clear();
foreach (JID jid, services) {
@@ -209,4 +299,11 @@ void QtUserSearchWindow::addSavedServices(const std::vector<JID>& services) {
}
firstPage_->service_->clearEditText();
+ } else {
+ firstMultiJIDPage_->service_->clear();
+ foreach (JID jid, services) {
+ firstMultiJIDPage_->service_->addItem(P2QSTRING(jid.toString()));
+ }
+ firstMultiJIDPage_->service_->clearEditText();
+ }
}
@@ -221,5 +318,5 @@ void QtUserSearchWindow::setSearchFields(boost::shared_ptr<SearchPayload> fields
} else {
fieldsPage_->setFormWidget(NULL);
- bool enabled[8] = {fields->getNick(), fields->getNick(), fields->getFirst(), fields->getFirst(), fields->getLast(), fields->getLast(), fields->getEMail(), fields->getEMail()};
+ bool enabled[8] = {!!fields->getNick(), !!fields->getNick(), !!fields->getFirst(), !!fields->getFirst(), !!fields->getLast(), !!fields->getLast(), !!fields->getEMail(), !!fields->getEMail()};
QWidget* legacySearchWidgets[8] = {fieldsPage_->nickInputLabel_, fieldsPage_->nickInput_, fieldsPage_->firstInputLabel_, fieldsPage_->firstInput_, fieldsPage_->lastInputLabel_, fieldsPage_->lastInput_, fieldsPage_->emailInputLabel_, fieldsPage_->emailInput_};
for (int i = 0; i < 8; i++) {
@@ -246,4 +343,95 @@ void QtUserSearchWindow::prepopulateJIDAndName(const JID& jid, const std::string
}
+void QtUserSearchWindow::setContactSuggestions(const std::vector<Contact::ref>& suggestions) {
+ if (type_ == AddContact) {
+ firstPage_->jid_->setSuggestions(suggestions);
+ } else {
+ firstMultiJIDPage_->jid_->setSuggestions(suggestions);
+ }
+}
+
+void QtUserSearchWindow::setJIDs(const std::vector<JID> &jids) {
+ foreach(JID jid, jids) {
+ addSearchedJIDToList(boost::make_shared<Contact>("", jid, StatusShow::None, ""));
+ }
+ onJIDUpdateRequested(jids);
+}
+
+void QtUserSearchWindow::setRoomJID(const JID& roomJID) {
+ roomJID_ = roomJID;
+}
+
+std::string QtUserSearchWindow::getReason() const {
+ return Q2PSTRING(firstMultiJIDPage_->reason_->text());
+}
+
+std::vector<JID> QtUserSearchWindow::getJIDs() const {
+ std::vector<JID> jids;
+ foreach (Contact::ref contact, contactVector_) {
+ jids.push_back(contact->jid);
+ }
+ return jids;
+}
+
+void QtUserSearchWindow::setCanStartImpromptuChats(bool supportsImpromptu) {
+ supportsImpromptu_ = supportsImpromptu;
+ if (type_ == ChatToContact) {
+ firstMultiJIDPage_->contactList_->setMaximumNoOfContactsToOne(!supportsImpromptu_);
+ }
+}
+
+void QtUserSearchWindow::updateContacts(const std::vector<Contact::ref>& contacts) {
+ if (type_ != AddContact) {
+ firstMultiJIDPage_->contactList_->updateContacts(contacts);
+ }
+}
+
+void QtUserSearchWindow::addContacts(const std::vector<Contact::ref>& contacts) {
+ if (type_ != AddContact) {
+ /* prevent duplicate JIDs from appearing in the contact list */
+ foreach (Contact::ref newContact, contacts) {
+ bool found = false;
+ foreach (Contact::ref oldContact, contactVector_) {
+ if (newContact->jid == oldContact->jid) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ contactVector_.push_back(newContact);
+ }
+ }
+ if (!supportsImpromptu_ && contactVector_.size() > 1) {
+ contactVector_.resize(1); /* can't chat with more than one user */
+ }
+ firstMultiJIDPage_->contactList_->setList(contactVector_);
+ firstMultiJIDPage_->emitCompletenessCheck();
+ if (type_ == ChatToContact) {
+ firstMultiJIDPage_->groupBox->setEnabled(supportsImpromptu_ ? true : (contactVector_.size() < 1));
+ }
+ }
+}
+
+void QtUserSearchWindow::setCanSupplyDescription(bool allowed) {
+ firstMultiJIDPage_->label->setVisible(allowed);
+ firstMultiJIDPage_->reason_->setVisible(allowed);
+}
+
+void QtUserSearchWindow::handleAddViaSearch() {
+ searchNext_ = true;
+ next();
+}
+
+void QtUserSearchWindow::handleListChanged(std::vector<Contact::ref> list) {
+ contactVector_ = list;
+ if (type_ == ChatToContact) {
+ firstMultiJIDPage_->groupBox->setEnabled(supportsImpromptu_ ? 1 : (contactVector_.size() < 1));
+ }
+}
+
+void QtUserSearchWindow::handleJIDsAdded(std::vector<JID> jids) {
+ onJIDAddRequested(jids);
+}
+
void QtUserSearchWindow::setResults(const std::vector<UserSearchResult>& results) {
UserSearchModel *newModel = new UserSearchModel();
@@ -255,4 +443,5 @@ void QtUserSearchWindow::setResults(const std::vector<UserSearchResult>& results
model_ = newModel;
resultsPage_->setNoResults(model_->rowCount() == 0);
+ resultsPage_->emitCompletenessCheck();
}
@@ -263,8 +452,13 @@ void QtUserSearchWindow::setResultsForm(Form::ref results) {
resultsPage_->results_->setItemDelegate(new QItemDelegate());
resultsPage_->results_->setHeaderHidden(false);
+#if QT_VERSION >= 0x050000
+ resultsPage_->results_->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
+#else
resultsPage_->results_->header()->setResizeMode(QHeaderView::ResizeToContents);
+#endif
delete model_;
model_ = newModel;
resultsPage_->setNoResults(model_->rowCount() == 0);
+ resultsPage_->emitCompletenessCheck();
}
@@ -273,4 +467,61 @@ void QtUserSearchWindow::setSelectedService(const JID& jid) {
}
+void QtUserSearchWindow::setFirstPage(QString title) {
+ if (page(1) != 0) {
+ removePage(1);
+ }
+ if (type_ == AddContact) {
+ firstPage_ = new QtUserSearchFirstPage(type_, title.isEmpty() ? firstPage_->title() : title, settings_);
+ connect(firstPage_->jid_, SIGNAL(textEdited(QString)), this, SLOT(handleContactSuggestionRequested(QString)));
+ firstPage_->jid_->onUserSelected.connect(boost::bind(&QtUserSearchWindow::handleOnSearchedJIDSelected, this, _1));
+ connect(firstPage_->byJID_, SIGNAL(toggled(bool)), this, SLOT(handleFirstPageRadioChange()));
+ connect(firstPage_->byLocalSearch_, SIGNAL(toggled(bool)), this, SLOT(handleFirstPageRadioChange()));
+ connect(firstPage_->byRemoteSearch_, SIGNAL(toggled(bool)), this, SLOT(handleFirstPageRadioChange()));
+#if QT_VERSION >= 0x040700
+ firstPage_->jid_->setPlaceholderText(tr("alice@wonderland.lit"));
+#endif
+ firstPage_->service_->setEnabled(false);
+ setPage(1, firstPage_);
+ } else {
+ firstMultiJIDPage_ = new QtUserSearchFirstMultiJIDPage(type_, title.isEmpty() ? firstMultiJIDPage_->title() : title, settings_);
+ connect(firstMultiJIDPage_->addContactButton_, SIGNAL(clicked()), this, SLOT(addContact()));
+ 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<Contact::ref>)), this, SLOT(handleListChanged(std::vector<Contact::ref>)));
+ connect(firstMultiJIDPage_->contactList_, SIGNAL(onJIDsAdded(std::vector<JID>)), this, SLOT(handleJIDsAdded(std::vector<JID>)));
+ connect(firstMultiJIDPage_, SIGNAL(onJIDsDropped(std::vector<JID>)), this, SLOT(handleJIDsAdded(std::vector<JID>)));
+ setPage(1, firstMultiJIDPage_);
+ }
+}
+
+void QtUserSearchWindow::setSecondPage() {
+ if (page(2) != 0) {
+ removePage(2);
+ }
+ fieldsPage_ = new QtUserSearchFieldsPage();
+ fieldsPage_->fetchingThrobber_->setMovie(new QMovie(":/icons/throbber.gif", QByteArray(), this));
+ fieldsPage_->fetchingThrobber_->movie()->stop();
+ setPage(2, fieldsPage_);
+}
+
+void QtUserSearchWindow::setThirdPage() {
+ if (page(3) != 0) {
+ removePage(3);
+ }
+ resultsPage_ = new QtUserSearchResultsPage();
+
+#ifdef SWIFT_PLATFORM_MACOSX
+ resultsPage_->results_->setAlternatingRowColors(true);
+#endif
+ if (type_ == AddContact) {
+ connect(resultsPage_, SIGNAL(onUserTriggersContinue()), this, SLOT(next()));
+ }
+ else {
+ connect(resultsPage_, SIGNAL(onUserTriggersContinue()), this, SLOT(next()));
+ }
+ setPage(3, resultsPage_);
+}
+
void QtUserSearchWindow::clearForm() {
fieldsPage_->fetchingThrobber_->show();
@@ -288,19 +539,26 @@ void QtUserSearchWindow::clearForm() {
void QtUserSearchWindow::clear() {
- firstPage_->errorLabel_->setVisible(false);
QString howText;
if (type_ == AddContact) {
+ firstPage_->errorLabel_->setVisible(false);
howText = QString(tr("How would you like to find the user to add?"));
- }
- else {
- howText = QString(tr("How would you like to find the user to chat to?"));
- }
firstPage_->howLabel_->setText(howText);
firstPage_->byJID_->setChecked(true);
+ handleFirstPageRadioChange();
+ } else {
+ contactVector_.clear();
+ firstMultiJIDPage_->contactList_->setList(contactVector_);
+ firstMultiJIDPage_->errorLabel_->setVisible(false);
+ if (type_ == ChatToContact) {
+ howText = QString(tr("Who would you like to chat to?"));
+ } else if (type_ == InviteToChat) {
+ howText = QString(tr("Who do you want to invite to the chat?"));
+ }
+ firstMultiJIDPage_->howLabel_->setText(howText);
+ }
clearForm();
resultsPage_->results_->setModel(NULL);
delete model_;
model_ = NULL;
- handleFirstPageRadioChange();
restart();
lastPage_ = 1;
@@ -309,9 +567,18 @@ void QtUserSearchWindow::clear() {
void QtUserSearchWindow::setError(const QString& error) {
if (error.isEmpty()) {
+ if (type_ == AddContact) {
firstPage_->errorLabel_->hide();
+ } else {
+ firstMultiJIDPage_->errorLabel_->hide();
+ }
}
else {
+ if (type_ == AddContact) {
firstPage_->errorLabel_->setText(QString("<font color='red'>%1</font>").arg(error));
firstPage_->errorLabel_->show();
+ } else {
+ firstMultiJIDPage_->errorLabel_->setText(QString("<font color='red'>%1</font>").arg(error));
+ firstMultiJIDPage_->errorLabel_->show();
+ }
restart();
lastPage_ = 1;
diff --git a/Swift/QtUI/UserSearch/QtUserSearchWindow.h b/Swift/QtUI/UserSearch/QtUserSearchWindow.h
index 32e851a..255b8fe 100644
--- a/Swift/QtUI/UserSearch/QtUserSearchWindow.h
+++ b/Swift/QtUI/UserSearch/QtUserSearchWindow.h
@@ -1,4 +1,4 @@
/*
- * Copyright (c) 2010 Kevin Smith
+ * Copyright (c) 2010-2014 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
@@ -19,13 +19,15 @@ namespace Swift {
class UIEventStream;
class QtUserSearchFirstPage;
+ class QtUserSearchFirstMultiJIDPage;
class QtUserSearchFieldsPage;
class QtUserSearchResultsPage;
class QtUserSearchDetailsPage;
class QtFormResultItemModel;
+ class SettingsProvider;
class QtUserSearchWindow : public QWizard, public UserSearchWindow, private Ui::QtUserSearchWizard {
Q_OBJECT
public:
- QtUserSearchWindow(UIEventStream* eventStream, UserSearchWindow::Type type, const std::set<std::string>& groups);
+ QtUserSearchWindow(UIEventStream* eventStream, UserSearchWindow::Type type, const std::set<std::string>& groups, SettingsProvider* settingsProvider);
virtual ~QtUserSearchWindow();
@@ -42,11 +44,32 @@ namespace Swift {
virtual void setNameSuggestions(const std::vector<std::string>& suggestions);
virtual void prepopulateJIDAndName(const JID& jid, const std::string& name);
+ virtual void setContactSuggestions(const std::vector<Contact::ref>& suggestions);
+ virtual void setJIDs(const std::vector<JID> &jids);
+ virtual void setRoomJID(const JID &roomJID);
+ virtual std::string getReason() const;
+ virtual std::vector<JID> getJIDs() const;
+ virtual void setCanStartImpromptuChats(bool supportsImpromptu);
+ virtual void updateContacts(const std::vector<Contact::ref> &contacts);
+ virtual void addContacts(const std::vector<Contact::ref>& contacts);
+ virtual void setCanSupplyDescription(bool allowed);
protected:
virtual int nextId() const;
+
private slots:
void handleFirstPageRadioChange();
virtual void handleCurrentChanged(int);
virtual void handleAccepted();
+ void handleContactSuggestionRequested(const QString& text);
+ void addContact();
+ void handleAddViaSearch();
+ void handleListChanged(std::vector<Contact::ref> list);
+ void handleJIDsAdded(std::vector<JID> jids);
+
+ private:
+ void setFirstPage(QString title = "");
+ void setSecondPage();
+ void setThirdPage();
+
private:
void clearForm();
@@ -55,4 +78,7 @@ namespace Swift {
void handleSearch();
JID getContactJID() const;
+ Contact::ref getContact() const;
+ void addSearchedJIDToList(const Contact::ref& contact);
+ void handleOnSearchedJIDSelected(const Contact::ref& contact);
private:
@@ -62,9 +88,15 @@ namespace Swift {
UserSearchDelegate* delegate_;
QtUserSearchFirstPage* firstPage_;
+ QtUserSearchFirstMultiJIDPage* firstMultiJIDPage_;
QtUserSearchFieldsPage* fieldsPage_;
QtUserSearchResultsPage* resultsPage_;
QtUserSearchDetailsPage* detailsPage_;
JID myServer_;
+ JID roomJID_;
int lastPage_;
+ std::vector<Contact::ref> contactVector_;
+ SettingsProvider* settings_;
+ bool searchNext_;
+ bool supportsImpromptu_;
};
}