summary refs log tree commit diff
diff options
context:
space:
mode:
authorKonstantinos Sideris <sideris.konstantin@gmail.com>2017-08-15 21:06:27 +0300
committerKonstantinos Sideris <sideris.konstantin@gmail.com>2017-08-15 21:06:27 +0300
commit8d81489e053c28173ca864064774bd07e2758a1d (patch)
treeca166acddaea998f70b22d8dbe3fa27ebb8115ed
parentFocus on the text input when switching rooms (diff)
downloadnheko-8d81489e053c28173ca864064774bd07e2758a1d.tar.xz
Ghetto room switcher
-rw-r--r--CMakeLists.txt2
-rw-r--r--Makefile2
-rw-r--r--include/ChatPage.h8
-rw-r--r--include/QuickSwitcher.h58
-rw-r--r--src/ChatPage.cc36
-rw-r--r--src/QuickSwitcher.cc114
-rw-r--r--src/RoomList.cc6
7 files changed, 224 insertions, 2 deletions
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()));
+		}
 	}
 }