diff options
Diffstat (limited to 'Swift/QtUI/MUCSearch/QtMUCSearchWindow.cpp')
-rw-r--r-- | Swift/QtUI/MUCSearch/QtMUCSearchWindow.cpp | 277 |
1 files changed, 148 insertions, 129 deletions
diff --git a/Swift/QtUI/MUCSearch/QtMUCSearchWindow.cpp b/Swift/QtUI/MUCSearch/QtMUCSearchWindow.cpp index bafb958..f69da41 100644 --- a/Swift/QtUI/MUCSearch/QtMUCSearchWindow.cpp +++ b/Swift/QtUI/MUCSearch/QtMUCSearchWindow.cpp @@ -1,58 +1,68 @@ /* - * Copyright (c) 2010 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ -#include "Swift/QtUI/MUCSearch/QtMUCSearchWindow.h" +#include <Swift/QtUI/MUCSearch/QtMUCSearchWindow.h> + +#include <memory> +#include <vector> -#include <qdebug.h> #include <QMovie> +#include <QPushButton> #include <QScrollBar> +#include <QSortFilterProxyModel> #include <QTimer> -#include <QPushButton> -#include "Swift/Controllers/UIEvents/JoinMUCUIEvent.h" -#include "Swift/Controllers/UIEvents/AddMUCBookmarkUIEvent.h" -#include "Swift/QtUI/MUCSearch/MUCSearchModel.h" -#include "Swift/QtUI/MUCSearch/MUCSearchDelegate.h" -#include "Swift/QtUI/MUCSearch/MUCSearchEmptyItem.h" -#include "Swift/QtUI/QtSwiftUtil.h" +#include <Swift/Controllers/UIEvents/AddMUCBookmarkUIEvent.h> +#include <Swift/Controllers/UIEvents/JoinMUCUIEvent.h> + +#include <Swift/QtUI/MUCSearch/MUCSearchDelegate.h> +#include <Swift/QtUI/MUCSearch/MUCSearchEmptyItem.h> +#include <Swift/QtUI/MUCSearch/MUCSearchModel.h> +#include <Swift/QtUI/MUCSearch/QtLeafSortFilterProxyModel.h> +#include <Swift/QtUI/QtSwiftUtil.h> namespace Swift { QtMUCSearchWindow::QtMUCSearchWindow() { - ui_.setupUi(this); + ui_.setupUi(this); #ifndef Q_OS_MAC - setWindowIcon(QIcon(":/logo-icon-16.png")); + setWindowIcon(QIcon(":/logo-icon-16.png")); #endif - setModal(true); - ui_.filter_->hide(); - model_ = new MUCSearchModel(); - delegate_ = new MUCSearchDelegate(); - ui_.results_->setModel(model_); - ui_.results_->setItemDelegate(delegate_); - ui_.results_->setHeaderHidden(true); - ui_.results_->setRootIsDecorated(true); - ui_.results_->setAnimated(true); - ui_.results_->setAlternatingRowColors(true); - connect(ui_.searchButton, SIGNAL(clicked()), this, SLOT(handleSearch())); - connect(ui_.service_, SIGNAL(activated(const QString&)), this, SLOT(handleSearch(const QString&))); - connect(ui_.results_->selectionModel(), SIGNAL(selectionChanged (const QItemSelection&, const QItemSelection&)), this, SLOT(handleSelectionChanged (const QItemSelection&, const QItemSelection&))); - connect(ui_.results_, SIGNAL(activated(const QModelIndex&)), this, SLOT(handleActivated(const QModelIndex&))); - connect(ui_.results_, SIGNAL(activated(const QModelIndex&)), this, SLOT(handleActivated(const QModelIndex&))); - // Not using a button box, because i can't seem to be able to make the ok button non-default (on mac) - connect(ui_.okButton, SIGNAL(clicked()), this, SLOT(accept())); - ui_.okButton->setEnabled(false); - connect(ui_.cancelButton, SIGNAL(clicked()), this, SLOT(reject())); - - throbber_ = new QLabel(tr("Searching"), ui_.results_); - throbber_->setMovie(new QMovie(":/icons/throbber.gif", QByteArray(), throbber_)); - throbber_->setToolTip(tr("Searching")); - - hasHadScrollBars_ = false; - updateThrobberPosition(); - setSearchInProgress(false); + setModal(true); + model_ = new MUCSearchModel(); + sortFilterProxyModel_ = new QtLeafSortFilterProxyModel(this); + sortFilterProxyModel_->setSourceModel(model_); + sortFilterProxyModel_->setDynamicSortFilter(true); + delegate_ = new MUCSearchDelegate(); + ui_.results_->setModel(sortFilterProxyModel_); + ui_.results_->setItemDelegate(delegate_); + ui_.results_->setHeaderHidden(true); + ui_.results_->setRootIsDecorated(true); + ui_.results_->setAnimated(true); + ui_.results_->setAlternatingRowColors(true); + ui_.results_->setSortingEnabled(true); + ui_.results_->sortByColumn(0, Qt::AscendingOrder); + connect(ui_.searchButton_, SIGNAL(clicked()), this, SLOT(handleSearch())); + connect(ui_.service_, SIGNAL(activated(const QString&)), this, SLOT(handleSearch(const QString&))); + connect(ui_.results_->selectionModel(), SIGNAL(selectionChanged (const QItemSelection&, const QItemSelection&)), this, SLOT(handleSelectionChanged (const QItemSelection&, const QItemSelection&))); + connect(ui_.results_, SIGNAL(activated(const QModelIndex&)), this, SLOT(handleActivated(const QModelIndex&))); + connect(ui_.results_, SIGNAL(activated(const QModelIndex&)), this, SLOT(handleActivated(const QModelIndex&))); + // Not using a button box, because i can't seem to be able to make the ok button non-default (on mac) + connect(ui_.okButton, SIGNAL(clicked()), this, SLOT(accept())); + ui_.okButton->setEnabled(false); + connect(ui_.cancelButton, SIGNAL(clicked()), this, SLOT(reject())); + connect(ui_.filter_, SIGNAL(textChanged(const QString&)), this, SLOT(handleFilterStringChanged(const QString&))); + + throbber_ = new QLabel(tr("Searching"), ui_.results_); + throbber_->setMovie(new QMovie(":/icons/throbber.gif", QByteArray(), throbber_)); + throbber_->setToolTip(tr("Searching")); + + hasHadScrollBars_ = false; + updateThrobberPosition(); + setSearchInProgress(false); } QtMUCSearchWindow::~QtMUCSearchWindow() { @@ -60,136 +70,145 @@ QtMUCSearchWindow::~QtMUCSearchWindow() { } void QtMUCSearchWindow::resizeEvent(QResizeEvent* /*event*/) { - updateThrobberPosition(); + updateThrobberPosition(); } void QtMUCSearchWindow::updateThrobberPosition() { - bool isShown = throbber_->isVisible(); - int resultWidth = ui_.results_->width(); - int resultHeight = ui_.results_->height(); - //throbberWidth = throbber_->movie()->scaledSize().width(); - //throbberHeight = throbber_->movie()->scaledSize().height(); - int throbberWidth = 16; /* This is nasty, but the above doesn't work! */ - int throbberHeight = 16; - /* It's difficult (or I spent a while trying) to work out whether the scrollbars are currently shown and their appropriate size, - * because if you listen for the expanded/collapsed signals, you seem to get them before the scrollbars are updated. - * This seems an acceptable workaround. - */ - hasHadScrollBars_ |= ui_.results_->verticalScrollBar()->isVisible(); - int hMargin = hasHadScrollBars_ ? ui_.results_->verticalScrollBar()->width() + 2 : 2; - int vMargin = 2; /* We don't get horizontal scrollbars */ - throbber_->setGeometry(QRect(resultWidth - throbberWidth - hMargin, resultHeight - throbberHeight - vMargin, throbberWidth, throbberHeight)); /* include margins */ - throbber_->setVisible(isShown); + bool isShown = throbber_->isVisible(); + int resultWidth = ui_.results_->width(); + int resultHeight = ui_.results_->height(); + //throbberWidth = throbber_->movie()->scaledSize().width(); + //throbberHeight = throbber_->movie()->scaledSize().height(); + int throbberWidth = 16; /* This is nasty, but the above doesn't work! */ + int throbberHeight = 16; + /* It's difficult (or I spent a while trying) to work out whether the scrollbars are currently shown and their appropriate size, + * because if you listen for the expanded/collapsed signals, you seem to get them before the scrollbars are updated. + * This seems an acceptable workaround. + */ + hasHadScrollBars_ |= ui_.results_->verticalScrollBar()->isVisible(); + int hMargin = hasHadScrollBars_ ? ui_.results_->verticalScrollBar()->width() + 2 : 2; + int vMargin = 2; /* We don't get horizontal scrollbars */ + throbber_->setGeometry(QRect(resultWidth - throbberWidth - hMargin, resultHeight - throbberHeight - vMargin, throbberWidth, throbberHeight)); /* include margins */ + throbber_->setVisible(isShown); } void QtMUCSearchWindow::addSavedServices(const std::list<JID>& services) { - ui_.service_->clear(); - foreach (const JID& jid, services) { - ui_.service_->addItem(P2QSTRING(jid.toString())); - } - if (!services.empty()) { - ui_.service_->setEditText(P2QSTRING(services.begin()->toString())); - } - else { - ui_.service_->clearEditText(); - } + ui_.service_->clear(); + for (const auto& jid : services) { + ui_.service_->addItem(P2QSTRING(jid.toString())); + } + if (!services.empty()) { + ui_.service_->setEditText(P2QSTRING(services.begin()->toString())); + } + else { + ui_.service_->clearEditText(); + } } void QtMUCSearchWindow::handleActivated(const QModelIndex& index) { - if (!index.isValid()) { - return; - } - if (dynamic_cast<MUCSearchRoomItem*>(static_cast<MUCSearchItem*>(index.internalPointer()))) { - accept(); - } + if (!index.isValid()) { + return; + } + if (dynamic_cast<MUCSearchRoomItem*>(static_cast<MUCSearchItem*>(sortFilterProxyModel_->mapToSource(index).internalPointer()))) { + accept(); + } } void QtMUCSearchWindow::handleSearch() { - handleSearch(ui_.service_->currentText()); + handleSearch(ui_.service_->currentText()); } void QtMUCSearchWindow::handleSearch(const QString& service) { - if (!service.isEmpty()) { - onSearchService(JID(Q2PSTRING(service))); - } + if (!service.isEmpty()) { + onSearchService(JID(Q2PSTRING(service))); + } +} + +void QtMUCSearchWindow::handleFilterStringChanged(const QString& filterString) { + sortFilterProxyModel_->setFilterRegExp(filterString); } void QtMUCSearchWindow::show() { - QWidget::show(); - QWidget::activateWindow(); + ui_.filter_->clear(); + QWidget::show(); + QWidget::activateWindow(); } void QtMUCSearchWindow::clearList() { - model_->clear(); + model_->clear(); } void QtMUCSearchWindow::addService(const MUCService& service) { - updateThrobberPosition(); - MUCSearchServiceItem* serviceItem = new MUCSearchServiceItem(P2QSTRING(service.getJID().toString())); - if (service.getRooms().size() > 0) { - foreach (MUCService::MUCRoom room, service.getRooms()) { - new MUCSearchRoomItem(P2QSTRING(room.getNode()), serviceItem); - } - } - else { - new MUCSearchEmptyItem(serviceItem); - } - model_->addService(serviceItem); - ui_.results_->expandAll(); + updateThrobberPosition(); + auto serviceItem = std::make_shared<MUCSearchServiceItem>(P2QSTRING(service.getJID().toString())); + if (service.getRooms().size() > 0) { + std::vector<std::shared_ptr<MUCSearchItem>> rooms; + for (auto&& room : service.getRooms()) { + if (!room.getNode().empty()) { + rooms.push_back(std::make_shared<MUCSearchRoomItem>(P2QSTRING(room.getNode()))); + } + } + serviceItem->addRooms(rooms); + } + else { + serviceItem->addRoom(std::make_shared<MUCSearchEmptyItem>()); + } + model_->addService(serviceItem); + ui_.results_->expandAll(); } void QtMUCSearchWindow::setSearchInProgress(bool searching) { - if (searching) { - throbber_->movie()->start(); - } else { - throbber_->movie()->stop(); - } - throbber_->setVisible(searching); + if (searching) { + throbber_->movie()->start(); + } else { + throbber_->movie()->stop(); + } + throbber_->setVisible(searching); } void QtMUCSearchWindow::accept() { - MUCSearchRoomItem* room = getSelectedRoom(); - if (room) { - onFinished(JID(Q2PSTRING(room->getNode()), Q2PSTRING(room->getParent()->getHost()))); - } - else { - onFinished(boost::optional<JID>()); - } - QDialog::accept(); + MUCSearchRoomItem* room = getSelectedRoom(); + if (room) { + onFinished(JID(Q2PSTRING(room->getNode()), Q2PSTRING(room->getParent()->getHost()))); + } + else { + onFinished(boost::optional<JID>()); + } + QDialog::accept(); } void QtMUCSearchWindow::reject() { - onFinished(boost::optional<JID>()); - QDialog::reject(); + onFinished(boost::optional<JID>()); + QDialog::reject(); } void QtMUCSearchWindow::handleSelectionChanged(const QItemSelection&, const QItemSelection&) { - ui_.okButton->setEnabled(getSelectedRoom()); + ui_.okButton->setEnabled(getSelectedRoom()); } MUCSearchRoomItem* QtMUCSearchWindow::getSelectedRoom() 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 = ui_.results_->selectionModel()->selection(); - QModelIndexList lstIndex; - 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) { - lstIndex.append(ranges.at(i).model()->index(r, 0, parent)); - } - } - } - if (lstIndex.isEmpty()) { - return NULL; - } - else { - return dynamic_cast<MUCSearchRoomItem*>(static_cast<MUCSearchItem*>(lstIndex.first().internalPointer())); - } + // 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 = ui_.results_->selectionModel()->selection(); + QModelIndexList lstIndex; + 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) { + lstIndex.append(ranges.at(i).model()->index(r, 0, parent)); + } + } + } + if (lstIndex.isEmpty()) { + return nullptr; + } + else { + return dynamic_cast<MUCSearchRoomItem*>(static_cast<MUCSearchItem*>(sortFilterProxyModel_->mapToSource(lstIndex.first()).internalPointer())); + } } } |