summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Maudsley <richard.maudsley@isode.com>2014-07-01 12:54:14 (GMT)
committerRichard Maudsley <richard.maudsley@isode.com>2014-07-01 12:57:14 (GMT)
commit9179b54ac93ddc88765c3cd984916d7ffd130d20 (patch)
treeddcbacdd0228d52ba3f0ad4d6e8e5f09e8d12c87
parentf90a0307a16a93376270a84be61451faa9bd9701 (diff)
downloadswift-contrib-9179b54ac93ddc88765c3cd984916d7ffd130d20.zip
swift-contrib-9179b54ac93ddc88765c3cd984916d7ffd130d20.tar.bz2
Reset roster filter when hitting enter to start chat.
Test-Information: Enter search term and use keyboard arrows to move to select a contact and pressing enter will start a chat and clear the filter. Confirm that pressing escape still clears the filter without starting a chat and that the changes do not interfere with starting a chat normally by double clicking on a contact. Change-Id: I90f5d431da56896eeb10f16c0ba23bdc143c4857
-rw-r--r--Swift/QtUI/QtMainWindow.cpp2
-rw-r--r--Swift/QtUI/Roster/QtFilterWidget.cpp55
-rw-r--r--Swift/QtUI/Roster/QtFilterWidget.h6
-rw-r--r--Swift/QtUI/Roster/QtTreeWidget.cpp29
-rw-r--r--Swift/QtUI/Roster/QtTreeWidget.h2
5 files changed, 60 insertions, 34 deletions
diff --git a/Swift/QtUI/QtMainWindow.cpp b/Swift/QtUI/QtMainWindow.cpp
index 7af9728..1acc519 100644
--- a/Swift/QtUI/QtMainWindow.cpp
+++ b/Swift/QtUI/QtMainWindow.cpp
@@ -47,71 +47,71 @@
#else
#include <Swift/QtUI/QtCertificateViewerDialog.h>
#endif
namespace Swift {
QtMainWindow::QtMainWindow(SettingsProvider* settings, UIEventStream* uiEventStream, QtLoginWindow::QtMenus loginMenus, StatusCache* statusCache, bool emoticonsExist) : QWidget(), MainWindow(false), loginMenus_(loginMenus) {
uiEventStream_ = uiEventStream;
settings_ = settings;
setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
QBoxLayout *mainLayout = new QBoxLayout(QBoxLayout::TopToBottom, this);
mainLayout->setContentsMargins(0,0,0,0);
mainLayout->setSpacing(0);
meView_ = new QtRosterHeader(settings, statusCache, this);
mainLayout->addWidget(meView_);
connect(meView_, SIGNAL(onChangeStatusRequest(StatusShow::Type, const QString&)), this, SLOT(handleStatusChanged(StatusShow::Type, const QString&)));
connect(meView_, SIGNAL(onEditProfileRequest()), this, SLOT(handleEditProfileRequest()));
connect(meView_, SIGNAL(onShowCertificateInfo()), this, SLOT(handleShowCertificateInfo()));
tabs_ = new QtTabWidget(this);
#if QT_VERSION >= 0x040500
tabs_->setDocumentMode(true);
#endif
tabs_->setTabPosition(QTabWidget::South);
mainLayout->addWidget(tabs_);
contactsTabWidget_ = new QWidget(this);
contactsTabWidget_->setContentsMargins(0, 0, 0, 0);
QBoxLayout *contactTabLayout = new QBoxLayout(QBoxLayout::TopToBottom, contactsTabWidget_);
contactsTabWidget_->setLayout(contactTabLayout);
contactTabLayout->setSpacing(0);
contactTabLayout->setContentsMargins(0, 0, 0, 0);
treeWidget_ = new QtRosterWidget(uiEventStream_, settings_, this);
contactTabLayout->addWidget(treeWidget_);
- new QtFilterWidget(this, treeWidget_, contactTabLayout);
+ new QtFilterWidget(this, treeWidget_, uiEventStream_, contactTabLayout);
tabs_->addTab(contactsTabWidget_, tr("&Contacts"));
eventWindow_ = new QtEventWindow(uiEventStream_);
connect(eventWindow_, SIGNAL(onNewEventCountUpdated(int)), this, SLOT(handleEventCountUpdated(int)));
chatListWindow_ = new QtChatListWindow(uiEventStream_, settings_);
connect(chatListWindow_, SIGNAL(onCountUpdated(int)), this, SLOT(handleChatCountUpdated(int)));
tabs_->addTab(chatListWindow_, tr("C&hats"));
tabs_->addTab(eventWindow_, tr("&Notices"));
tabs_->setCurrentIndex(settings_->getSetting(QtUISettingConstants::CURRENT_ROSTER_TAB));
connect(tabs_, SIGNAL(currentChanged(int)), this, SLOT(handleTabChanged(int)));
tabBarCombo_ = NULL;
if (settings_->getSetting(QtUISettingConstants::USE_SCREENREADER)) {
tabs_->tabBar()->hide();
tabBarCombo_ = new QComboBox(this);
tabBarCombo_->setAccessibleName("Current View");
tabBarCombo_->addItem(tr("Contacts"));
tabBarCombo_->addItem(tr("Chats"));
tabBarCombo_->addItem(tr("Notices"));
tabBarCombo_->setCurrentIndex(tabs_->currentIndex());
mainLayout->addWidget(tabBarCombo_);
connect(tabBarCombo_, SIGNAL(currentIndexChanged(int)), tabs_, SLOT(setCurrentIndex(int)));
}
this->setLayout(mainLayout);
QMenu* viewMenu = new QMenu(tr("&View"), this);
menus_.push_back(viewMenu);
diff --git a/Swift/QtUI/Roster/QtFilterWidget.cpp b/Swift/QtUI/Roster/QtFilterWidget.cpp
index 5bd4669..2f08981 100644
--- a/Swift/QtUI/Roster/QtFilterWidget.cpp
+++ b/Swift/QtUI/Roster/QtFilterWidget.cpp
@@ -1,132 +1,139 @@
/*
* Copyright (c) 2013 Tobias Markmann
* Licensed under the simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
-#include <Swift/QtUI/Roster/QtFilterWidget.h>
-
#include <QLayout>
#include <QVBoxLayout>
#include <QKeyEvent>
#include <QEvent>
#include <QString>
#include <QEvent>
-
+#include <Swift/Controllers/UIEvents/RequestChatUIEvent.h>
+#include <Swift/Controllers/UIEvents/UIEventStream.h>
#include <Swift/QtUI/QtSwiftUtil.h>
+#include <Swift/QtUI/Roster/QtFilterWidget.h>
namespace Swift {
-QtFilterWidget::QtFilterWidget(QWidget* parent, QtTreeWidget* treeView, QBoxLayout* layout) : QWidget(parent), treeView_(treeView), fuzzyRosterFilter_(0), isModifierSinglePressed_(false) {
+QtFilterWidget::QtFilterWidget(QWidget* parent, QtTreeWidget* treeView, UIEventStream* eventStream, QBoxLayout* layout) : QWidget(parent), treeView_(treeView), eventStream_(eventStream), fuzzyRosterFilter_(0), isModifierSinglePressed_(false) {
int targetIndex = layout->indexOf(treeView);
QVBoxLayout* vboxLayout = new QVBoxLayout(this);
vboxLayout->setSpacing(0);
vboxLayout->setContentsMargins(0,0,0,0);
filterLineEdit_ = new QLineEdit(this);
filterLineEdit_->hide();
vboxLayout->addWidget(filterLineEdit_);
vboxLayout->addWidget(treeView);
setLayout(vboxLayout);
layout->insertWidget(targetIndex, this);
filterLineEdit_->installEventFilter(this);
treeView->installEventFilter(this);
sourceModel_ = treeView_->model();
}
QtFilterWidget::~QtFilterWidget() {
}
bool QtFilterWidget::eventFilter(QObject*, QEvent* event) {
if (event->type() == QEvent::KeyPress ||
event->type() == QEvent::KeyRelease ||
// InputMethodQuery got introduced in Qt 5.
#if QT_VERSION >= 0x050000
event->type() == QEvent::InputMethodQuery ||
#endif
event->type() == QEvent::InputMethod) {
event->ignore();
QKeyEvent* keyEvent = dynamic_cast<QKeyEvent*>(event);
if (keyEvent) {
if (keyEvent->key() == Qt::Key_Up || keyEvent->key() == Qt::Key_Down) {
return false;
} else if ((keyEvent->key() == Qt::Key_Left || keyEvent->key() == Qt::Key_Right) && filterLineEdit_->text().isEmpty()) {
return false;
} else if (keyEvent->key() == Qt::Key_Alt && event->type() == QEvent::KeyPress) {
isModifierSinglePressed_ = true;
} else if (keyEvent->key() == Qt::Key_Alt && event->type() == QEvent::KeyRelease && isModifierSinglePressed_) {
QPoint itemOffset(2,2);
QPoint contextMenuPosition = treeView_->visualRect(treeView_->currentIndex()).topLeft() + itemOffset;;
QApplication::postEvent(treeView_, new QContextMenuEvent(QContextMenuEvent::Keyboard, contextMenuPosition, treeView_->mapToGlobal(contextMenuPosition)));
return true;
} else if (keyEvent->key() == Qt::Key_Return) {
+ JID target = treeView_->selectedJID();
+ if (target.isValid()) {
+ eventStream_->send(boost::shared_ptr<UIEvent>(new RequestChatUIEvent(target)));
+ }
filterLineEdit_->setText("");
- return false;
+ updateRosterFilters();
} else if (keyEvent->key() == Qt::Key_Escape) {
filterLineEdit_->setText("");
} else {
isModifierSinglePressed_ = false;
}
}
filterLineEdit_->event(event);
filterLineEdit_->setVisible(!filterLineEdit_->text().isEmpty());
- // update roster filters
if (event->type() == QEvent::KeyRelease) {
- if (fuzzyRosterFilter_) {
- if (filterLineEdit_->text().isEmpty()) {
- // remove currently installed search filter and put old filters back
- treeView_->getRoster()->removeFilter(fuzzyRosterFilter_);
- delete fuzzyRosterFilter_;
- fuzzyRosterFilter_ = NULL;
- pushAllFilters();
- } else {
- // remove currently intsalled search filter and put new search filter in place
- updateSearchFilter();
- }
- } else {
- if (!filterLineEdit_->text().isEmpty()) {
- // remove currently installed filters and put a search filter in place
- popAllFilters();
- updateSearchFilter();
- }
- }
+ updateRosterFilters();
}
return true;
}
return false;
}
void QtFilterWidget::popAllFilters() {
std::vector<RosterFilter*> filters = treeView_->getRoster()->getFilters();
foreach(RosterFilter* filter, filters) {
filters_.push_back(filter);
treeView_->getRoster()->removeFilter(filter);
}
}
void QtFilterWidget::pushAllFilters() {
foreach(RosterFilter* filter, filters_) {
treeView_->getRoster()->addFilter(filter);
}
filters_.clear();
}
+void QtFilterWidget::updateRosterFilters() {
+ if (fuzzyRosterFilter_) {
+ if (filterLineEdit_->text().isEmpty()) {
+ // remove currently installed search filter and put old filters back
+ treeView_->getRoster()->removeFilter(fuzzyRosterFilter_);
+ delete fuzzyRosterFilter_;
+ fuzzyRosterFilter_ = NULL;
+ pushAllFilters();
+ } else {
+ // remove currently intsalled search filter and put new search filter in place
+ updateSearchFilter();
+ }
+ } else {
+ if (!filterLineEdit_->text().isEmpty()) {
+ // remove currently installed filters and put a search filter in place
+ popAllFilters();
+ updateSearchFilter();
+ }
+ }
+}
+
void QtFilterWidget::updateSearchFilter() {
if (fuzzyRosterFilter_) {
treeView_->getRoster()->removeFilter(fuzzyRosterFilter_);
delete fuzzyRosterFilter_;
fuzzyRosterFilter_ = NULL;
}
fuzzyRosterFilter_ = new FuzzyRosterFilter(Q2PSTRING(filterLineEdit_->text()));
treeView_->getRoster()->addFilter(fuzzyRosterFilter_);
treeView_->setCurrentIndex(sourceModel_->index(0, 0, sourceModel_->index(0,0)));
}
}
diff --git a/Swift/QtUI/Roster/QtFilterWidget.h b/Swift/QtUI/Roster/QtFilterWidget.h
index e33616b..94ebc2a 100644
--- a/Swift/QtUI/Roster/QtFilterWidget.h
+++ b/Swift/QtUI/Roster/QtFilterWidget.h
@@ -1,46 +1,50 @@
/*
* Copyright (c) 2013 Tobias Markmann
* Licensed under the simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#pragma once
#include <vector>
#include <QBoxLayout>
#include <QLineEdit>
#include <QWidget>
#include <Swift/Controllers/Roster/RosterFilter.h>
#include <Swift/Controllers/Roster/FuzzyRosterFilter.h>
#include <Swift/QtUI/Roster/QtTreeWidget.h>
namespace Swift {
+class UIEventStream;
+
class QtFilterWidget : public QWidget {
Q_OBJECT
public:
- QtFilterWidget(QWidget* parent, QtTreeWidget* treeView, QBoxLayout* layout = 0);
+ QtFilterWidget(QWidget* parent, QtTreeWidget* treeView, UIEventStream* eventStream, QBoxLayout* layout = 0);
virtual ~QtFilterWidget();
protected:
bool eventFilter(QObject*, QEvent* event);
private:
void popAllFilters();
void pushAllFilters();
+ void updateRosterFilters();
void updateSearchFilter();
private:
QLineEdit* filterLineEdit_;
QtTreeWidget* treeView_;
+ UIEventStream* eventStream_;
std::vector<RosterFilter*> filters_;
QAbstractItemModel* sourceModel_;
FuzzyRosterFilter* fuzzyRosterFilter_;
bool isModifierSinglePressed_;
};
}
diff --git a/Swift/QtUI/Roster/QtTreeWidget.cpp b/Swift/QtUI/Roster/QtTreeWidget.cpp
index fbe85de..5333260 100644
--- a/Swift/QtUI/Roster/QtTreeWidget.cpp
+++ b/Swift/QtUI/Roster/QtTreeWidget.cpp
@@ -106,78 +106,71 @@ void QtTreeWidget::handleClicked(const QModelIndex& index) {
QModelIndexList QtTreeWidget::getSelectedIndexes() const {
// Not using selectedIndexes(), because this seems to cause a crash in Qt (4.7.0) in the
// QModelIndexList destructor.
// This is a workaround posted in http://www.qtcentre.org/threads/16933 (although this case
// was resolved by linking against the debug libs, ours isn't, and we're not alone)
QItemSelection ranges = selectionModel()->selection();
QModelIndexList selectedIndexList;
for (int i = 0; i < ranges.count(); ++i) {
QModelIndex parent = ranges.at(i).parent();
int right = ranges.at(i).model()->columnCount(parent) - 1;
if (ranges.at(i).left() == 0 && ranges.at(i).right() == right) {
for (int r = ranges.at(i).top(); r <= ranges.at(i).bottom(); ++r) {
selectedIndexList.append(ranges.at(i).model()->index(r, 0, parent));
}
}
}
return selectedIndexList;
}
void QtTreeWidget::currentChanged(const QModelIndex& current, const QModelIndex& previous) {
RosterItem* item = NULL;
QModelIndexList selectedIndexList = getSelectedIndexes();
if (selectedIndexList.empty() || !selectedIndexList[0].isValid()) {
/* I didn't quite understand why using current didn't seem to work here.*/
}
else if (current.isValid()) {
item = static_cast<RosterItem*>(current.internalPointer());
item = dynamic_cast<ContactRosterItem*>(item);
}
onSomethingSelectedChanged(item);
QTreeView::currentChanged(current, previous);
}
void QtTreeWidget::handleItemActivated(const QModelIndex& index) {
- JID target;
- if (messageTarget_ == MessageDisplayJID) {
- target = JID(Q2PSTRING(index.data(DisplayJIDRole).toString()));
- target = target.toBare();
- }
- if (!target.isValid()) {
- target = JID(Q2PSTRING(index.data(JIDRole).toString()));
- }
+ JID target = jidFromIndex(index);
if (target.isValid()) {
eventStream_->send(boost::shared_ptr<UIEvent>(new RequestChatUIEvent(target)));
}
}
void QtTreeWidget::dragEnterEvent(QDragEnterEvent *event) {
if (event->mimeData()->hasUrls() && event->mimeData()->urls().size() == 1) {
event->acceptProposedAction();
}
}
void QtTreeWidget::dropEvent(QDropEvent *event) {
QModelIndex index = indexAt(event->pos());
if (index.isValid()) {
RosterItem* item = static_cast<RosterItem*>(index.internalPointer());
if (ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item)) {
if (contact->supportsFeature(ContactRosterItem::FileTransferFeature)) {
QString filename = event->mimeData()->urls().at(0).toLocalFile();
if (!filename.isEmpty()) {
eventStream_->send(boost::make_shared<SendFileUIEvent>(contact->getJID(), Q2PSTRING(filename)));
}
}
}
}
}
void QtTreeWidget::dragMoveEvent(QDragMoveEvent* event) {
QModelIndex index = indexAt(event->pos());
if (index.isValid()) {
RosterItem* item = static_cast<RosterItem*>(index.internalPointer());
if (ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item)) {
if (contact->supportsFeature(ContactRosterItem::FileTransferFeature)) {
event->accept();
return;
}
@@ -207,36 +200,56 @@ void QtTreeWidget::handleExpanded(const QModelIndex& index) {
GroupRosterItem* item = dynamic_cast<GroupRosterItem*>(static_cast<RosterItem*>(index.internalPointer()));
if (item) {
item->setExpanded(true);
}
}
void QtTreeWidget::handleCollapsed(const QModelIndex& index) {
GroupRosterItem* item = dynamic_cast<GroupRosterItem*>(static_cast<RosterItem*>(index.internalPointer()));
if (item) {
item->setExpanded(false);
}
}
void QtTreeWidget::handleModelItemExpanded(const QModelIndex& index, bool shouldExpand) {
if (!index.isValid()) {
return;
}
bool alreadyRight = this->isExpanded(index) == shouldExpand;
if (alreadyRight) {
return;
}
setExpanded(index, shouldExpand);
}
void QtTreeWidget::drawBranches(QPainter*, const QRect&, const QModelIndex&) const {
}
void QtTreeWidget::show() {
QWidget::show();
}
void QtTreeWidget::setMessageTarget(MessageTarget messageTarget) {
messageTarget_ = messageTarget;
}
+JID QtTreeWidget::jidFromIndex(const QModelIndex& index) const {
+ JID target;
+ if (messageTarget_ == MessageDisplayJID) {
+ target = JID(Q2PSTRING(index.data(DisplayJIDRole).toString()));
+ target = target.toBare();
+ }
+ if (!target.isValid()) {
+ target = JID(Q2PSTRING(index.data(JIDRole).toString()));
+ }
+ return target;
+}
+
+JID QtTreeWidget::selectedJID() const {
+ QModelIndexList list = selectedIndexes();
+ if (list.size() != 1) {
+ return JID();
+ }
+ return jidFromIndex(list[0]);
+}
+
}
diff --git a/Swift/QtUI/Roster/QtTreeWidget.h b/Swift/QtUI/Roster/QtTreeWidget.h
index 29e985d..cf2f73e 100644
--- a/Swift/QtUI/Roster/QtTreeWidget.h
+++ b/Swift/QtUI/Roster/QtTreeWidget.h
@@ -2,70 +2,72 @@
* Copyright (c) 2010-2014 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include <QDragEnterEvent>
#include <QDropEvent>
#include <QDragMoveEvent>
#include <QModelIndex>
#include <QTreeView>
#include <Swift/QtUI/Roster/RosterDelegate.h>
#include <Swift/QtUI/Roster/RosterModel.h>
#include <Swift/Controllers/UIInterfaces/ChatWindow.h>
namespace Swift {
class UIEventStream;
class SettingsProvider;
class QtTreeWidget : public QTreeView {
Q_OBJECT
public:
enum MessageTarget {MessageDefaultJID, MessageDisplayJID};
QtTreeWidget(UIEventStream* eventStream, SettingsProvider* settings, MessageTarget messageTarget, QWidget* parent = 0);
~QtTreeWidget();
void show();
QtTreeWidgetItem* getRoot();
void setRosterModel(Roster* roster);
Roster* getRoster() {return roster_;}
void refreshTooltip();
void setMessageTarget(MessageTarget messageTarget);
+ JID jidFromIndex(const QModelIndex& index) const;
+ JID selectedJID() const;
public:
boost::signal<void (RosterItem*)> onSomethingSelectedChanged;
private slots:
void handleItemActivated(const QModelIndex&);
void handleModelItemExpanded(const QModelIndex&, bool expanded);
void handleExpanded(const QModelIndex&);
void handleCollapsed(const QModelIndex&);
void handleClicked(const QModelIndex&);
void handleSettingChanged(const std::string& setting);
void handleRefreshTooltip();
protected:
void dragEnterEvent(QDragEnterEvent* event);
void dropEvent(QDropEvent* event);
void dragMoveEvent(QDragMoveEvent* event);
bool event(QEvent* event);
QModelIndexList getSelectedIndexes() const;
private:
void drawBranches(QPainter*, const QRect&, const QModelIndex&) const;
protected slots:
virtual void currentChanged(const QModelIndex& current, const QModelIndex& previous);
protected:
UIEventStream* eventStream_;
private:
RosterModel* model_;
Roster* roster_;
RosterDelegate* delegate_;
QtTreeWidgetItem* treeRoot_;
SettingsProvider* settings_;
bool tooltipShown_;
MessageTarget messageTarget_;