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<QString, RoomState> state_manager_;
QMap<QString, QSharedPointer<RoomSettings>> settingsManager_;
+ QuickSwitcher *quickSwitcher_ = nullptr;
+ OverlayModal *quickSwitcherModal_ = nullptr;
+
// Matrix Client API provider.
QSharedPointer<MatrixClient> 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 <siderisk@auth.gr>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <QFrame>
+#include <QKeyEvent>
+#include <QVBoxLayout>
+
+#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<QString, QString> &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<QString, QString> 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<QString, QString> 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 <siderisk@auth.gr>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <QAbstractItemView>
+#include <QCompleter>
+#include <QDebug>
+#include <QStringListModel>
+#include <QTimer>
+
+#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<QString, QString>& 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<QWidget *>(it.value().data()));
+ }
}
}
|