mirror of https://github.com/Nheko-Reborn/nheko
pull/493/head
commit
7a356f3832
@ -0,0 +1,56 @@ |
||||
import QtQuick 2.13 |
||||
import QtQuick.Layouts 1.13 |
||||
import QtQuick.Controls 2.13 |
||||
|
||||
TextField { |
||||
id: input |
||||
palette: colors |
||||
|
||||
background: Rectangle { |
||||
color: colors.base |
||||
} |
||||
|
||||
Rectangle { |
||||
id: blueBar |
||||
|
||||
anchors.top: parent.bottom |
||||
anchors.horizontalCenter: parent.horizontalCenter |
||||
|
||||
color: colors.highlight |
||||
height: 1 |
||||
width: parent.width |
||||
|
||||
Rectangle { |
||||
id: blackBar |
||||
|
||||
anchors.verticalCenter: blueBar.verticalCenter |
||||
anchors.horizontalCenter: parent.horizontalCenter |
||||
|
||||
height: parent.height+1 |
||||
width: 0 |
||||
color: colors.text |
||||
|
||||
states: State { |
||||
name: "focused"; when: input.activeFocus == true |
||||
PropertyChanges { |
||||
target: blackBar |
||||
width: blueBar.width |
||||
} |
||||
} |
||||
|
||||
transitions: Transition { |
||||
from: "" |
||||
to: "focused" |
||||
reversible: true |
||||
|
||||
NumberAnimation { |
||||
target: blackBar |
||||
properties: "width" |
||||
duration: 500 |
||||
easing.type: Easing.InOutQuad |
||||
alwaysRunToEnd: true |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,97 @@ |
||||
import QtQuick 2.9 |
||||
import QtQuick.Controls 2.3 |
||||
import im.nheko 1.0 |
||||
|
||||
Popup { |
||||
id: quickSwitcher |
||||
|
||||
property int textHeight: 32 |
||||
property int textMargin: 8 |
||||
|
||||
x: parent.width / 2 - width / 2 |
||||
y: parent.height / 4 - height / 2 |
||||
width: parent.width / 2 |
||||
modal: true |
||||
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside |
||||
parent: Overlay.overlay |
||||
palette: colors |
||||
|
||||
Overlay.modal: Rectangle { |
||||
color: "#aa1E1E1E" |
||||
} |
||||
|
||||
MatrixTextField { |
||||
id: roomTextInput |
||||
|
||||
anchors.fill: parent |
||||
font.pixelSize: quickSwitcher.textHeight * 0.6 |
||||
padding: textMargin |
||||
color: colors.text |
||||
|
||||
onTextEdited: { |
||||
completerPopup.completer.setSearchString(text) |
||||
} |
||||
|
||||
Keys.onPressed: { |
||||
if (event.key == Qt.Key_Up && completerPopup.opened) { |
||||
event.accepted = true; |
||||
completerPopup.up(); |
||||
} else if (event.key == Qt.Key_Down && completerPopup.opened) { |
||||
event.accepted = true; |
||||
completerPopup.down(); |
||||
} else if (event.matches(StandardKey.InsertParagraphSeparator)) { |
||||
completerPopup.finishCompletion() |
||||
event.accepted = true; |
||||
} |
||||
} |
||||
} |
||||
|
||||
Completer { |
||||
id: completerPopup |
||||
|
||||
x: roomTextInput.x |
||||
y: roomTextInput.y + roomTextInput.height + textMargin |
||||
width: parent.width |
||||
completerName: "room" |
||||
bottomToTop: false |
||||
fullWidth: true |
||||
avatarHeight: textHeight |
||||
avatarWidth: textHeight |
||||
centerRowContent: false |
||||
rowMargin: 8 |
||||
rowSpacing: 6 |
||||
|
||||
closePolicy: Popup.NoAutoClose |
||||
} |
||||
|
||||
onOpened: { |
||||
completerPopup.open() |
||||
delay(200, function() { |
||||
roomTextInput.forceActiveFocus() |
||||
}) |
||||
} |
||||
|
||||
onClosed: { |
||||
completerPopup.close() |
||||
} |
||||
|
||||
Connections { |
||||
onCompletionSelected: { |
||||
TimelineManager.setHistoryView(id) |
||||
TimelineManager.highlightRoom(id) |
||||
quickSwitcher.close() |
||||
} |
||||
target: completerPopup |
||||
} |
||||
|
||||
Timer { |
||||
id: timer |
||||
} |
||||
|
||||
function delay(delayTime, cb) { |
||||
timer.interval = delayTime; |
||||
timer.repeat = false; |
||||
timer.triggered.connect(cb); |
||||
timer.start(); |
||||
} |
||||
} |
@ -1,129 +0,0 @@ |
||||
// SPDX-FileCopyrightText: 2017 Konstantinos Sideris <siderisk@auth.gr>
|
||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include <QCompleter> |
||||
#include <QPainter> |
||||
#include <QStringListModel> |
||||
#include <QStyleOption> |
||||
#include <QTimer> |
||||
#include <QtConcurrent> |
||||
|
||||
#include "Cache.h" |
||||
#include "QuickSwitcher.h" |
||||
#include "popups/SuggestionsPopup.h" |
||||
|
||||
Q_DECLARE_METATYPE(std::vector<RoomSearchResult>) |
||||
|
||||
RoomSearchInput::RoomSearchInput(QWidget *parent) |
||||
: TextField(parent) |
||||
{} |
||||
|
||||
void |
||||
RoomSearchInput::keyPressEvent(QKeyEvent *event) |
||||
{ |
||||
switch (event->key()) { |
||||
case Qt::Key_Tab: |
||||
case Qt::Key_Down: { |
||||
emit selectNextCompletion(); |
||||
event->accept(); |
||||
break; |
||||
} |
||||
case Qt::Key_Backtab: |
||||
case Qt::Key_Up: { |
||||
emit selectPreviousCompletion(); |
||||
event->accept(); |
||||
break; |
||||
} |
||||
default: |
||||
TextField::keyPressEvent(event); |
||||
} |
||||
} |
||||
|
||||
void |
||||
RoomSearchInput::hideEvent(QHideEvent *event) |
||||
{ |
||||
emit hiding(); |
||||
TextField::hideEvent(event); |
||||
} |
||||
|
||||
QuickSwitcher::QuickSwitcher(QWidget *parent) |
||||
: QWidget(parent) |
||||
{ |
||||
qRegisterMetaType<std::vector<RoomSearchResult>>(); |
||||
setMaximumWidth(450); |
||||
|
||||
QFont font; |
||||
font.setPointSizeF(font.pointSizeF() * 1.5); |
||||
|
||||
roomSearch_ = new RoomSearchInput(this); |
||||
roomSearch_->setFont(font); |
||||
roomSearch_->setPlaceholderText(tr("Search for a room...")); |
||||
|
||||
topLayout_ = new QVBoxLayout(this); |
||||
topLayout_->addWidget(roomSearch_); |
||||
|
||||
connect(this, |
||||
&QuickSwitcher::queryResults, |
||||
this, |
||||
[this](const std::vector<RoomSearchResult> &rooms) { |
||||
auto pos = mapToGlobal(roomSearch_->geometry().bottomLeft()); |
||||
|
||||
popup_.setFixedWidth(width()); |
||||
popup_.addRooms(rooms); |
||||
popup_.move(pos.x() - topLayout_->margin(), pos.y() + topLayout_->margin()); |
||||
popup_.show(); |
||||
}); |
||||
|
||||
connect(roomSearch_, &QLineEdit::textEdited, this, [this](const QString &query) { |
||||
if (query.isEmpty()) { |
||||
popup_.hide(); |
||||
return; |
||||
} |
||||
|
||||
QtConcurrent::run([this, query = query.toLower()]() { |
||||
try { |
||||
emit queryResults(cache::searchRooms(query.toStdString())); |
||||
} catch (const lmdb::error &e) { |
||||
qWarning() << "room search failed:" << e.what(); |
||||
} |
||||
}); |
||||
}); |
||||
|
||||
connect(roomSearch_, |
||||
&RoomSearchInput::selectNextCompletion, |
||||
&popup_, |
||||
&SuggestionsPopup::selectNextSuggestion); |
||||
connect(roomSearch_, |
||||
&RoomSearchInput::selectPreviousCompletion, |
||||
&popup_, |
||||
&SuggestionsPopup::selectPreviousSuggestion); |
||||
connect(&popup_, &SuggestionsPopup::itemSelected, this, [this](const QString &room_id) { |
||||
reset(); |
||||
emit roomSelected(room_id); |
||||
}); |
||||
connect(roomSearch_, &RoomSearchInput::hiding, this, [this]() { popup_.hide(); }); |
||||
connect(roomSearch_, &QLineEdit::returnPressed, this, [this]() { |
||||
reset(); |
||||
popup_.selectHoveredSuggestion(); |
||||
}); |
||||
} |
||||
|
||||
void |
||||
QuickSwitcher::paintEvent(QPaintEvent *) |
||||
{ |
||||
QStyleOption opt; |
||||
opt.init(this); |
||||
QPainter p(this); |
||||
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); |
||||
} |
||||
|
||||
void |
||||
QuickSwitcher::keyPressEvent(QKeyEvent *event) |
||||
{ |
||||
if (event->key() == Qt::Key_Escape) { |
||||
event->accept(); |
||||
reset(); |
||||
} |
||||
} |
@ -1,65 +0,0 @@ |
||||
// SPDX-FileCopyrightText: 2017 Konstantinos Sideris <siderisk@auth.gr>
|
||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once |
||||
|
||||
#include <QAbstractItemView> |
||||
#include <QKeyEvent> |
||||
#include <QVBoxLayout> |
||||
#include <QWidget> |
||||
|
||||
#include "popups/SuggestionsPopup.h" |
||||
#include "ui/TextField.h" |
||||
|
||||
class RoomSearchInput : public TextField |
||||
{ |
||||
Q_OBJECT |
||||
public: |
||||
explicit RoomSearchInput(QWidget *parent = nullptr); |
||||
|
||||
signals: |
||||
void selectNextCompletion(); |
||||
void selectPreviousCompletion(); |
||||
void hiding(); |
||||
|
||||
protected: |
||||
void keyPressEvent(QKeyEvent *event) override; |
||||
void hideEvent(QHideEvent *event) override; |
||||
bool focusNextPrevChild(bool) override { return false; }; |
||||
}; |
||||
|
||||
class QuickSwitcher : public QWidget |
||||
{ |
||||
Q_OBJECT |
||||
|
||||
public: |
||||
QuickSwitcher(QWidget *parent = nullptr); |
||||
|
||||
signals: |
||||
void closing(); |
||||
void roomSelected(const QString &roomid); |
||||
void queryResults(const std::vector<RoomSearchResult> &rooms); |
||||
|
||||
protected: |
||||
void keyPressEvent(QKeyEvent *event) override; |
||||
void showEvent(QShowEvent *) override { roomSearch_->setFocus(); } |
||||
void paintEvent(QPaintEvent *event) override; |
||||
|
||||
private: |
||||
void reset() |
||||
{ |
||||
emit closing(); |
||||
roomSearch_->clear(); |
||||
} |
||||
|
||||
// Current highlighted selection from the completer.
|
||||
int selection_ = -1; |
||||
|
||||
QVBoxLayout *topLayout_; |
||||
RoomSearchInput *roomSearch_; |
||||
|
||||
//! Autocomplete popup box with the room suggestions.
|
||||
SuggestionsPopup popup_; |
||||
}; |
Loading…
Reference in new issue