diff options
Diffstat (limited to 'Swift')
| -rw-r--r-- | Swift/QtUI/QtMainWindow.cpp | 2 | ||||
| -rw-r--r-- | Swift/QtUI/Roster/QtFilterWidget.cpp | 55 | ||||
| -rw-r--r-- | Swift/QtUI/Roster/QtFilterWidget.h | 6 | ||||
| -rw-r--r-- | Swift/QtUI/Roster/QtTreeWidget.cpp | 29 | ||||
| -rw-r--r-- | Swift/QtUI/Roster/QtTreeWidget.h | 2 |
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 @@ -1,398 +1,398 @@ /* * Copyright (c) 2010-2011 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #include <Swift/QtUI/QtMainWindow.h> #include <boost/optional.hpp> #include <boost/bind.hpp> #include <boost/smart_ptr/make_shared.hpp> #include <QBoxLayout> #include <QComboBox> #include <QLineEdit> #include <QListWidget> #include <QListWidgetItem> #include <QPushButton> #include <QMenuBar> #include <QToolBar> #include <QAction> #include <QTabWidget> #include <Swiften/Base/Platform.h> #include <Swift/Controllers/UIEvents/RequestJoinMUCUIEvent.h> #include <Swift/Controllers/UIEvents/RequestHistoryUIEvent.h> #include <Swift/Controllers/UIEvents/RequestAddUserDialogUIEvent.h> #include <Swift/Controllers/UIEvents/RequestChatWithUserDialogUIEvent.h> #include <Swift/Controllers/UIEvents/RequestProfileEditorUIEvent.h> #include <Swift/Controllers/UIEvents/JoinMUCUIEvent.h> #include <Swift/Controllers/UIEvents/RequestAdHocUIEvent.h> #include <Swift/Controllers/UIEvents/RequestBlockListDialogUIEvent.h> #include <Swift/Controllers/SettingConstants.h> #include <Swift/QtUI/Roster/QtFilterWidget.h> #include <Swift/QtUI/QtSwiftUtil.h> #include <Swift/QtUI/QtTabWidget.h> #include <Swift/QtUI/QtSettingsProvider.h> #include <Swift/QtUI/QtLoginWindow.h> #include <Swift/QtUI/Roster/QtRosterWidget.h> #include <Swift/QtUI/QtUISettingConstants.h> #if defined(SWIFTEN_PLATFORM_MACOSX) #include <Swift/QtUI/CocoaUIHelpers.h> #elif defined(SWIFTEN_PLATFORM_WINDOWS) #include <Swift/QtUI/WinUIHelpers.h> #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); compactRosterAction_ = new QAction(tr("&Compact Roster"), this); compactRosterAction_->setCheckable(true); compactRosterAction_->setChecked(false); connect(compactRosterAction_, SIGNAL(toggled(bool)), SLOT(handleCompactRosterToggled(bool))); viewMenu->addAction(compactRosterAction_); handleCompactRosterToggled(settings_->getSetting(QtUISettingConstants::COMPACT_ROSTER)); showOfflineAction_ = new QAction(tr("&Show offline contacts"), this); showOfflineAction_->setCheckable(true); showOfflineAction_->setChecked(false); connect(showOfflineAction_, SIGNAL(toggled(bool)), SLOT(handleShowOfflineToggled(bool))); viewMenu->addAction(showOfflineAction_); handleShowOfflineToggled(settings_->getSetting(SettingConstants::SHOW_OFFLINE)); if (emoticonsExist) { showEmoticonsAction_ = new QAction(tr("&Show Emoticons"), this); showEmoticonsAction_->setCheckable(true); showEmoticonsAction_->setChecked(false); connect(showEmoticonsAction_, SIGNAL(toggled(bool)), SLOT(handleShowEmoticonsToggled(bool))); viewMenu->addAction(showEmoticonsAction_); handleShowEmoticonsToggled(settings_->getSetting(QtUISettingConstants::SHOW_EMOTICONS)); } //QAction* compactRosterAction_ = new QAction(tr("&Compact Roster"), this); //compactRosterAction_->setCheckable(true); //compactRosterAction_->setChecked(false); //connect(compactRosterAction_, SIGNAL(toggled(bool)), uiPreferences_, SLOT(setCompactRosters(bool))); //viewMenu->addAction(compactRosterAction_); QMenu* actionsMenu = new QMenu(tr("&Actions"), this); menus_.push_back(actionsMenu); QAction* editProfileAction = new QAction(tr("Edit &Profile…"), this); connect(editProfileAction, SIGNAL(triggered()), SLOT(handleEditProfileAction())); actionsMenu->addAction(editProfileAction); QAction* joinMUCAction = new QAction(tr("Enter &Room…"), this); connect(joinMUCAction, SIGNAL(triggered()), SLOT(handleJoinMUCAction())); actionsMenu->addAction(joinMUCAction); #ifdef SWIFT_EXPERIMENTAL_HISTORY QAction* viewLogsAction = new QAction(tr("&View History…"), this); connect(viewLogsAction, SIGNAL(triggered()), SLOT(handleViewLogsAction())); actionsMenu->addAction(viewLogsAction); #endif openBlockingListEditor_ = new QAction(tr("Edit &Blocking List…"), this); connect(openBlockingListEditor_, SIGNAL(triggered()), SLOT(handleEditBlockingList())); actionsMenu->addAction(openBlockingListEditor_); openBlockingListEditor_->setVisible(false); addUserAction_ = new QAction(tr("&Add Contact…"), this); addUserAction_->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_D)); addUserAction_->setShortcutContext(Qt::ApplicationShortcut); connect(addUserAction_, SIGNAL(triggered(bool)), this, SLOT(handleAddUserActionTriggered(bool))); actionsMenu->addAction(addUserAction_); editUserAction_ = new QAction(tr("&Edit Selected Contact…"), this); connect(editUserAction_, SIGNAL(triggered(bool)), treeWidget_, SLOT(handleEditUserActionTriggered(bool))); actionsMenu->addAction(editUserAction_); editUserAction_->setEnabled(false); chatUserAction_ = new QAction(tr("Start &Chat…"), this); chatUserAction_->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_N)); chatUserAction_->setShortcutContext(Qt::ApplicationShortcut); connect(chatUserAction_, SIGNAL(triggered(bool)), this, SLOT(handleChatUserActionTriggered(bool))); actionsMenu->addAction(chatUserAction_); serverAdHocMenu_ = new QMenu(tr("Run Server Command"), this); actionsMenu->addMenu(serverAdHocMenu_); actionsMenu->addSeparator(); QAction* signOutAction = new QAction(tr("&Sign Out"), this); connect(signOutAction, SIGNAL(triggered()), SLOT(handleSignOutAction())); actionsMenu->addAction(signOutAction); toggleRequestDeliveryReceipts_ = new QAction(tr("&Request Delivery Receipts"), this); toggleRequestDeliveryReceipts_->setCheckable(true); toggleRequestDeliveryReceipts_->setChecked(settings_->getSetting(SettingConstants::REQUEST_DELIVERYRECEIPTS)); connect(toggleRequestDeliveryReceipts_, SIGNAL(toggled(bool)), SLOT(handleToggleRequestDeliveryReceipts(bool))); QList< QAction* > generalMenuActions = loginMenus_.generalMenu->actions(); loginMenus_.generalMenu->insertAction(generalMenuActions.at(generalMenuActions.count()-2),toggleRequestDeliveryReceipts_); treeWidget_->onSomethingSelectedChanged.connect(boost::bind(&QAction::setEnabled, editUserAction_, _1)); setAvailableAdHocCommands(std::vector<DiscoItems::Item>()); QAction* adHocAction = new QAction(tr("Collecting commands..."), this); adHocAction->setEnabled(false); serverAdHocMenu_->addAction(adHocAction); serverAdHocCommandActions_.append(adHocAction); settings_->onSettingChanged.connect(boost::bind(&QtMainWindow::handleSettingChanged, this, _1)); } QtMainWindow::~QtMainWindow() { settings_->onSettingChanged.disconnect(boost::bind(&QtMainWindow::handleSettingChanged, this, _1)); } void QtMainWindow::handleTabChanged(int index) { settings_->storeSetting(QtUISettingConstants::CURRENT_ROSTER_TAB, index); } void QtMainWindow::handleToggleRequestDeliveryReceipts(bool enabled) { settings_->storeSetting(SettingConstants::REQUEST_DELIVERYRECEIPTS, enabled); } void QtMainWindow::handleShowCertificateInfo() { onShowCertificateRequest(); } void QtMainWindow::handleEditBlockingList() { uiEventStream_->send(boost::make_shared<RequestBlockListDialogUIEvent>()); } QtEventWindow* QtMainWindow::getEventWindow() { return eventWindow_; } QtChatListWindow* QtMainWindow::getChatListWindow() { return chatListWindow_; } void QtMainWindow::setRosterModel(Roster* roster) { treeWidget_->setRosterModel(roster); } void QtMainWindow::handleEditProfileRequest() { uiEventStream_->send(boost::make_shared<RequestProfileEditorUIEvent>()); } void QtMainWindow::handleEventCountUpdated(int count) { QColor eventTabColor = (count == 0) ? QColor() : QColor(255, 0, 0); // invalid resets to default int eventIndex = 2; tabs_->tabBar()->setTabTextColor(eventIndex, eventTabColor); QString text = tr("&Notices"); if (count > 0) { text += QString(" (%1)").arg(count); } tabs_->setTabText(eventIndex, text); } void QtMainWindow::handleChatCountUpdated(int count) { QColor chatTabColor = (count == 0) ? QColor() : QColor(255, 0, 0); // invalid resets to default int chatIndex = 1; tabs_->tabBar()->setTabTextColor(chatIndex, chatTabColor); QString text = tr("&Chats"); if (count > 0) { text += QString(" (%1)").arg(count); } tabs_->setTabText(chatIndex, text); } void QtMainWindow::handleAddUserActionTriggered(bool /*checked*/) { boost::shared_ptr<UIEvent> event(new RequestAddUserDialogUIEvent()); uiEventStream_->send(event); } void QtMainWindow::handleChatUserActionTriggered(bool /*checked*/) { boost::shared_ptr<UIEvent> event(new RequestChatWithUserDialogUIEvent()); uiEventStream_->send(event); } void QtMainWindow::handleSignOutAction() { loginMenus_.generalMenu->removeAction(toggleRequestDeliveryReceipts_); onSignOutRequest(); } void QtMainWindow::handleEditProfileAction() { uiEventStream_->send(boost::make_shared<RequestProfileEditorUIEvent>()); } void QtMainWindow::handleJoinMUCAction() { uiEventStream_->send(boost::make_shared<RequestJoinMUCUIEvent>()); } void QtMainWindow::handleViewLogsAction() { uiEventStream_->send(boost::make_shared<RequestHistoryUIEvent>()); } void QtMainWindow::handleStatusChanged(StatusShow::Type showType, const QString &statusMessage) { onChangeStatusRequest(showType, Q2PSTRING(statusMessage)); } void QtMainWindow::handleSettingChanged(const std::string& settingPath) { if (settingPath == SettingConstants::SHOW_OFFLINE.getKey()) { handleShowOfflineToggled(settings_->getSetting(SettingConstants::SHOW_OFFLINE)); } if (settingPath == QtUISettingConstants::SHOW_EMOTICONS.getKey()) { handleShowEmoticonsToggled(settings_->getSetting(QtUISettingConstants::SHOW_EMOTICONS)); } if (settingPath == SettingConstants::REQUEST_DELIVERYRECEIPTS.getKey()) { toggleRequestDeliveryReceipts_->setChecked(settings_->getSetting(SettingConstants::REQUEST_DELIVERYRECEIPTS)); } if (settingPath == QtUISettingConstants::COMPACT_ROSTER.getKey()) { handleCompactRosterToggled(settings_->getSetting(QtUISettingConstants::COMPACT_ROSTER)); } } void QtMainWindow::handleCompactRosterToggled(bool state) { settings_->storeSetting(QtUISettingConstants::COMPACT_ROSTER, state); compactRosterAction_->setChecked(settings_->getSetting(QtUISettingConstants::COMPACT_ROSTER)); } void QtMainWindow::handleShowOfflineToggled(bool state) { settings_->storeSetting(SettingConstants::SHOW_OFFLINE, state); showOfflineAction_->setChecked(settings_->getSetting(SettingConstants::SHOW_OFFLINE)); } void QtMainWindow::handleShowEmoticonsToggled(bool state) { settings_->storeSetting(QtUISettingConstants::SHOW_EMOTICONS, state); showEmoticonsAction_->setChecked(settings_->getSetting(QtUISettingConstants::SHOW_EMOTICONS)); } void QtMainWindow::setMyNick(const std::string& nick) { meView_->setNick(P2QSTRING(nick)); } void QtMainWindow::setMyJID(const JID& jid) { meView_->setJID(P2QSTRING(jid.toBare().toString())); } void QtMainWindow::setMyAvatarPath(const std::string& path) { meView_->setAvatar(P2QSTRING(path)); } void QtMainWindow::setMyStatusText(const std::string& status) { meView_->setStatusText(P2QSTRING(status)); } void QtMainWindow::setMyStatusType(StatusShow::Type type) { meView_->setStatusType(type); } void QtMainWindow::setConnecting() { meView_->setConnecting(); } void QtMainWindow::setStreamEncryptionStatus(bool tlsInPlaceAndValid) { meView_->setStreamEncryptionStatus(tlsInPlaceAndValid); } void QtMainWindow::openCertificateDialog(const std::vector<Certificate::ref>& chain) { openCertificateDialog(chain, this); } void QtMainWindow::openCertificateDialog(const std::vector<Certificate::ref>& chain, QWidget* parent) { #if defined(SWIFTEN_PLATFORM_MACOSX) CocoaUIHelpers::displayCertificateChainAsSheet(parent, chain); #elif defined(SWIFTEN_PLATFORM_WINDOWS) WinUIHelpers::displayCertificateChainAsSheet(parent, chain); #else QtCertificateViewerDialog::displayCertificateChainAsSheet(parent, chain); #endif } void QtMainWindow::handleAdHocActionTriggered(bool /*checked*/) { QAction* action = qobject_cast<QAction*>(sender()); assert(action); DiscoItems::Item command = serverAdHocCommands_[serverAdHocCommandActions_.indexOf(action)]; uiEventStream_->send(boost::shared_ptr<UIEvent>(new RequestAdHocUIEvent(command))); } void QtMainWindow::setAvailableAdHocCommands(const std::vector<DiscoItems::Item>& commands) { serverAdHocCommands_ = commands; foreach (QAction* action, serverAdHocCommandActions_) { delete action; } serverAdHocMenu_->clear(); serverAdHocCommandActions_.clear(); foreach (DiscoItems::Item command, commands) { QAction* action = new QAction(P2QSTRING(command.getName()), this); connect(action, SIGNAL(triggered(bool)), this, SLOT(handleAdHocActionTriggered(bool))); serverAdHocMenu_->addAction(action); serverAdHocCommandActions_.append(action); } if (serverAdHocCommandActions_.isEmpty()) { QAction* action = new QAction(tr("No Available Commands"), this); action->setEnabled(false); serverAdHocMenu_->addAction(action); serverAdHocCommandActions_.append(action); } } void QtMainWindow::setBlockingCommandAvailable(bool isAvailable) { openBlockingListEditor_->setVisible(isAvailable); } } 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 @@ -1,242 +1,255 @@ /* * Copyright (c) 2010-2012 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #include <Swift/QtUI/Roster/QtTreeWidget.h> #include <boost/smart_ptr/make_shared.hpp> #include <boost/bind.hpp> #include <QUrl> #include <QMimeData> #include <QObject> #include <QLabel> #include <QTimer> #include <QToolTip> #include <Swiften/Base/Platform.h> #include <Swift/Controllers/Roster/ContactRosterItem.h> #include <Swift/Controllers/Roster/GroupRosterItem.h> #include <Swift/Controllers/UIEvents/UIEventStream.h> #include <Swift/Controllers/UIEvents/RequestChatUIEvent.h> #include <Swift/Controllers/UIEvents/SendFileUIEvent.h> #include <Swift/Controllers/Settings/SettingsProvider.h> #include <Swift/QtUI/QtUISettingConstants.h> #include <Swift/QtUI/Roster/RosterModel.h> #include <QtSwiftUtil.h> namespace Swift { QtTreeWidget::QtTreeWidget(UIEventStream* eventStream, SettingsProvider* settings, MessageTarget messageTarget, QWidget* parent) : QTreeView(parent), tooltipShown_(false), messageTarget_(messageTarget) { eventStream_ = eventStream; settings_ = settings; model_ = new RosterModel(this, settings_->getSetting(QtUISettingConstants::USE_SCREENREADER)); setModel(model_); delegate_ = new RosterDelegate(this, settings_->getSetting(QtUISettingConstants::COMPACT_ROSTER)); setItemDelegate(delegate_); setHeaderHidden(true); #ifdef SWIFT_PLATFORM_MACOSX setAlternatingRowColors(true); #endif setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); expandAll(); setAnimated(true); setIndentation(0); #ifdef SWIFT_EXPERIMENTAL_FT setAcceptDrops(true); #endif setDragEnabled(true); setRootIsDecorated(true); connect(this, SIGNAL(activated(const QModelIndex&)), this, SLOT(handleItemActivated(const QModelIndex&))); connect(model_, SIGNAL(itemExpanded(const QModelIndex&, bool)), this, SLOT(handleModelItemExpanded(const QModelIndex&, bool))); connect(this, SIGNAL(expanded(const QModelIndex&)), this, SLOT(handleExpanded(const QModelIndex&))); connect(this, SIGNAL(collapsed(const QModelIndex&)), this, SLOT(handleCollapsed(const QModelIndex&))); connect(this, SIGNAL(clicked(const QModelIndex&)), this, SLOT(handleClicked(const QModelIndex&))); settings_->onSettingChanged.connect(boost::bind(&QtTreeWidget::handleSettingChanged, this, _1)); } QtTreeWidget::~QtTreeWidget() { settings_->onSettingChanged.disconnect(boost::bind(&QtTreeWidget::handleSettingChanged, this, _1)); delete model_; delete delegate_; } void QtTreeWidget::handleSettingChanged(const std::string& setting) { if (setting == QtUISettingConstants::COMPACT_ROSTER.getKey()) { delegate_->setCompact(settings_->getSetting(QtUISettingConstants::COMPACT_ROSTER)); repaint(); } } void QtTreeWidget::handleRefreshTooltip() { if (tooltipShown_) { QPoint position = QCursor::pos(); QModelIndex index = indexAt(mapFromGlobal(position)); QToolTip::showText(position, model_->data(index, Qt::ToolTipRole).toString()); } } void QtTreeWidget::setRosterModel(Roster* roster) { roster_ = roster; model_->setRoster(roster); expandAll(); } void QtTreeWidget::refreshTooltip() { // Qt needs some time to emit the events we need to detect tooltip's visibility correctly; 20 ms should be enough QTimer::singleShot(20, this, SLOT(handleRefreshTooltip())); } QtTreeWidgetItem* QtTreeWidget::getRoot() { return treeRoot_; } void QtTreeWidget::handleClicked(const QModelIndex& index) { GroupRosterItem* item = dynamic_cast<GroupRosterItem*>(static_cast<RosterItem*>(index.internalPointer())); if (item) { setExpanded(index, !isExpanded(index)); } currentChanged(index, QModelIndex()); } 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; } } } QTreeView::dragMoveEvent(event); } bool QtTreeWidget::event(QEvent* event) { QChildEvent* childEvent = NULL; if ((childEvent = dynamic_cast<QChildEvent*>(event))) { if (childEvent->polished()) { if (dynamic_cast<QLabel*>(childEvent->child())) { tooltipShown_ = true; } } else if (childEvent->removed()) { if (childEvent->child()->objectName() == "qtooltip_label") { tooltipShown_ = false; } } } return QAbstractItemView::event(event); } 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 @@ -1,74 +1,76 @@ /* * 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_; }; } |
Swift