From 8d81489e053c28173ca864064774bd07e2758a1d Mon Sep 17 00:00:00 2001 From: Konstantinos Sideris Date: Tue, 15 Aug 2017 21:06:27 +0300 Subject: [PATCH] Ghetto room switcher --- CMakeLists.txt | 2 + Makefile | 2 +- include/ChatPage.h | 8 +++ include/QuickSwitcher.h | 58 ++++++++++++++++++++ src/ChatPage.cc | 36 +++++++++++++ src/QuickSwitcher.cc | 114 ++++++++++++++++++++++++++++++++++++++++ src/RoomList.cc | 6 ++- 7 files changed, 224 insertions(+), 2 deletions(-) create mode 100644 include/QuickSwitcher.h create mode 100644 src/QuickSwitcher.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index e9f7fb55..926448df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -136,6 +136,7 @@ set(SRC_FILES src/UserInfoWidget.cc src/Versions.cc src/WelcomePage.cc + src/QuickSwitcher.cc src/main.cc src/ui/Avatar.cc @@ -211,6 +212,7 @@ qt5_wrap_cpp(MOC_HEADERS include/TopRoomBar.h include/TrayIcon.h include/TextInputWidget.h + include/QuickSwitcher.h include/WelcomePage.h include/ui/Avatar.h diff --git a/Makefile b/Makefile index b8d9d050..54ef1e16 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,7 @@ app: release-debug $(APP_TEMPLATE) @echo "Created '$(APP_NAME).app' in '$(APP_TEMPLATE)'" app-install: app - cp -rf $(APP_TEMPLATE) /Applications/Nheko.app + cp -Rf $(APP_TEMPLATE) /Applications/ dmg: app hdiutil create $(MAC_DIST_DIR)/Nheko.dmg \ diff --git a/include/ChatPage.h b/include/ChatPage.h index 88d4435e..13d6c8e9 100644 --- a/include/ChatPage.h +++ b/include/ChatPage.h @@ -23,6 +23,7 @@ #include "Cache.h" #include "MatrixClient.h" +#include "QuickSwitcher.h" #include "RoomList.h" #include "RoomSettings.h" #include "RoomState.h" @@ -61,10 +62,14 @@ private slots: void startSync(); void logout(); +protected: + void keyPressEvent(QKeyEvent *event) override; + private: void updateDisplayNames(const RoomState &state); void updateRoomState(RoomState &room_state, const QJsonArray &events); void loadStateFromCache(); + void showQuickSwitcher(); QHBoxLayout *topLayout_; Splitter *splitter; @@ -98,6 +103,9 @@ private: QMap state_manager_; QMap> settingsManager_; + QuickSwitcher *quickSwitcher_ = nullptr; + OverlayModal *quickSwitcherModal_ = nullptr; + // Matrix Client API provider. QSharedPointer client_; diff --git a/include/QuickSwitcher.h b/include/QuickSwitcher.h new file mode 100644 index 00000000..1f4c8835 --- /dev/null +++ b/include/QuickSwitcher.h @@ -0,0 +1,58 @@ +/* + * nheko Copyright (C) 2017 Konstantinos Sideris + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include +#include + +#include "TextField.h" + +class RoomSearchInput : public TextField +{ + Q_OBJECT +public: + explicit RoomSearchInput(QWidget *parent = nullptr); + +protected: + void keyPressEvent(QKeyEvent *event) override; + bool focusNextPrevChild(bool next) override; +}; + +class QuickSwitcher : public QFrame +{ + Q_OBJECT +public: + explicit QuickSwitcher(QWidget *parent = nullptr); + + void setRoomList(const QMap &rooms); + +signals: + void closing(); + void roomSelected(const QString &roomid); + +protected: + void keyPressEvent(QKeyEvent *event) override; + void showEvent(QShowEvent *event) override; + +private: + QVBoxLayout *topLayout_; + RoomSearchInput *roomSearch_; + + QMap rooms_; +}; diff --git a/src/ChatPage.cc b/src/ChatPage.cc index 43b1f0d3..55933d25 100644 --- a/src/ChatPage.cc +++ b/src/ChatPage.cc @@ -32,6 +32,7 @@ #include "CreateEventContent.h" #include "HistoryVisibilityEventContent.h" #include "JoinRulesEventContent.h" +#include "MainWindow.h" #include "MemberEventContent.h" #include "NameEventContent.h" #include "PowerLevelsEventContent.h" @@ -563,6 +564,41 @@ void ChatPage::loadStateFromCache() sync_timer_->start(sync_interval_); } +void ChatPage::keyPressEvent(QKeyEvent *event) +{ + if (event->key() == Qt::Key_K) { + if (event->modifiers() == Qt::ControlModifier) + showQuickSwitcher(); + } +} + +void ChatPage::showQuickSwitcher() +{ + if (quickSwitcher_ == nullptr) { + quickSwitcher_ = new QuickSwitcher(this); + + connect(quickSwitcher_, &QuickSwitcher::roomSelected, room_list_, &RoomList::highlightSelectedRoom); + connect(quickSwitcher_, &QuickSwitcher::closing, this, [=]() { + if (this->quickSwitcherModal_ != nullptr) + this->quickSwitcherModal_->fadeOut(); + }); + } + + if (quickSwitcherModal_ == nullptr) { + quickSwitcherModal_ = new OverlayModal(MainWindow::instance(), quickSwitcher_); + quickSwitcherModal_->setDuration(0); + quickSwitcherModal_->setColor(QColor(30, 30, 30, 170)); + } + + QMap rooms; + + for (auto it = state_manager_.constBegin(); it != state_manager_.constEnd(); ++it) + rooms.insert(it.value().getName(), it.key()); + + quickSwitcher_->setRoomList(rooms); + quickSwitcherModal_->fadeIn(); +} + ChatPage::~ChatPage() { sync_timer_->stop(); diff --git a/src/QuickSwitcher.cc b/src/QuickSwitcher.cc new file mode 100644 index 00000000..3bdd26ea --- /dev/null +++ b/src/QuickSwitcher.cc @@ -0,0 +1,114 @@ +/* + * nheko Copyright (C) 2017 Konstantinos Sideris + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include + +#include "QuickSwitcher.h" + +RoomSearchInput::RoomSearchInput(QWidget* parent) + : TextField(parent) +{ +} + +bool RoomSearchInput::focusNextPrevChild(bool next) +{ + Q_UNUSED(next); + + return false; +} + +void RoomSearchInput::keyPressEvent(QKeyEvent* event) +{ + if (event->key() == Qt::Key_Tab) { + auto completer = this->completer(); + + if (completer) { + // Enable the current item if its valid. + completer->popup()->setCurrentIndex(completer->currentIndex()); + + if (!completer->setCurrentRow(completer->currentRow() + 1)) + completer->setCurrentRow(0); + } + + event->accept(); + return; + } + + TextField::keyPressEvent(event); +} + +QuickSwitcher::QuickSwitcher(QWidget* parent) + : QFrame(parent) +{ + setMaximumWidth(400); + setStyleSheet("background-color: #f9f9f9"); + + QFont font; + font.setPixelSize(20); + + roomSearch_ = new RoomSearchInput(this); + roomSearch_->setFont(font); + roomSearch_->setPlaceholderText(tr("Find a room...")); + + QStringList wordList; + QCompleter* completer = new QCompleter(wordList, this); + completer->setCaseSensitivity(Qt::CaseInsensitive); + + roomSearch_->setCompleter(completer); + + topLayout_ = new QVBoxLayout(this); + topLayout_->setMargin(20); + topLayout_->setSpacing(0); + topLayout_->addWidget(roomSearch_); + + connect(roomSearch_, &QLineEdit::returnPressed, this, [=]() { + emit closing(); + emit roomSelected(rooms_[this->roomSearch_->text().trimmed()]); + + roomSearch_->clear(); + }); +} + +void QuickSwitcher::setRoomList(const QMap& rooms) +{ + rooms_ = rooms; + + QStringList search_items = rooms.keys(); + + if (!roomSearch_->completer()) + return; + + roomSearch_->completer()->setModel(new QStringListModel(search_items)); +} + +void QuickSwitcher::showEvent(QShowEvent*) +{ + roomSearch_->setFocus(); +} + +void QuickSwitcher::keyPressEvent(QKeyEvent* event) +{ + if (event->key() == Qt::Key_Escape) { + roomSearch_->clear(); + event->accept(); + emit closing(); + } +} diff --git a/src/RoomList.cc b/src/RoomList.cc index 042391a2..a35ef2f8 100644 --- a/src/RoomList.cc +++ b/src/RoomList.cc @@ -166,8 +166,12 @@ void RoomList::highlightSelectedRoom(const QString &room_id) calculateUnreadMessageCount(); for (auto it = rooms_.constBegin(); it != rooms_.constEnd(); it++) { - if (it.key() != room_id) + if (it.key() != room_id) { it.value()->setPressedState(false); + } else { + it.value()->setPressedState(true); + scrollArea_->ensureWidgetVisible(qobject_cast(it.value().data())); + } } }