mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-22 19:08:58 +03:00
Don't use a modal to edit room name and topic
This commit is contained in:
parent
82cdb483a9
commit
656fcac91c
8 changed files with 187 additions and 868 deletions
|
@ -338,7 +338,6 @@ set(SRC_FILES
|
||||||
src/ui/NhekoDropArea.cpp
|
src/ui/NhekoDropArea.cpp
|
||||||
src/ui/NhekoGlobalObject.cpp
|
src/ui/NhekoGlobalObject.cpp
|
||||||
src/ui/RoomSettings.cpp
|
src/ui/RoomSettings.cpp
|
||||||
src/ui/TextField.cpp
|
|
||||||
src/ui/Theme.cpp
|
src/ui/Theme.cpp
|
||||||
src/ui/ThemeManager.cpp
|
src/ui/ThemeManager.cpp
|
||||||
src/ui/UIA.cpp
|
src/ui/UIA.cpp
|
||||||
|
@ -532,7 +531,6 @@ qt5_wrap_cpp(MOC_HEADERS
|
||||||
src/ui/NhekoDropArea.h
|
src/ui/NhekoDropArea.h
|
||||||
src/ui/NhekoGlobalObject.h
|
src/ui/NhekoGlobalObject.h
|
||||||
src/ui/RoomSettings.h
|
src/ui/RoomSettings.h
|
||||||
src/ui/TextField.h
|
|
||||||
src/ui/Theme.h
|
src/ui/Theme.h
|
||||||
src/ui/ThemeManager.h
|
src/ui/ThemeManager.h
|
||||||
src/ui/UIA.h
|
src/ui/UIA.h
|
||||||
|
|
|
@ -107,15 +107,56 @@ ApplicationWindow {
|
||||||
hideErrorAnimation.restart();
|
hideErrorAnimation.restart();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Label {
|
|
||||||
text: roomSettings.roomName
|
TextEdit {
|
||||||
Layout.alignment: Qt.AlignHCenter
|
id: roomName
|
||||||
|
|
||||||
|
property bool isNameEditingAllowed: false
|
||||||
|
|
||||||
|
readOnly: !isNameEditingAllowed
|
||||||
|
textFormat: isNameEditingAllowed ? TextEdit.PlainText : TextEdit.RichText
|
||||||
|
text: isNameEditingAllowed ? roomSettings.plainRoomName : roomSettings.roomName
|
||||||
font.pixelSize: fontMetrics.font.pixelSize * 2
|
font.pixelSize: fontMetrics.font.pixelSize * 2
|
||||||
Layout.fillWidth: true
|
|
||||||
horizontalAlignment: TextEdit.AlignHCenter
|
|
||||||
color: Nheko.colors.text
|
color: Nheko.colors.text
|
||||||
wrapMode: Text.Wrap
|
|
||||||
textFormat: Text.RichText
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
Layout.maximumWidth: parent.width - (Nheko.paddingSmall * 2) - nameChangeButton.anchors.leftMargin - (nameChangeButton.width * 2)
|
||||||
|
horizontalAlignment: TextEdit.AlignHCenter
|
||||||
|
wrapMode: TextEdit.Wrap
|
||||||
|
selectByMouse: true
|
||||||
|
|
||||||
|
Keys.onShortcutOverride: event.key === Qt.Key_Enter
|
||||||
|
Keys.onPressed: {
|
||||||
|
if (event.matches(StandardKey.InsertLineSeparator) || event.matches(StandardKey.InsertParagraphSeparator)) {
|
||||||
|
roomSettings.changeName(roomName.text);
|
||||||
|
roomName.isNameEditingAllowed = false;
|
||||||
|
event.accepted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageButton {
|
||||||
|
id: nameChangeButton
|
||||||
|
visible: roomSettings.canChangeName
|
||||||
|
anchors.leftMargin: Nheko.paddingSmall
|
||||||
|
anchors.left: roomName.right
|
||||||
|
anchors.verticalCenter: roomName.verticalCenter
|
||||||
|
hoverEnabled: true
|
||||||
|
ToolTip.visible: hovered
|
||||||
|
ToolTip.text: qsTr("Change name of this room")
|
||||||
|
ToolTip.delay: Nheko.tooltipDelay
|
||||||
|
image: roomName.isNameEditingAllowed ? ":/icons/icons/ui/checkmark.svg" : ":/icons/icons/ui/edit.svg"
|
||||||
|
onClicked: {
|
||||||
|
if (roomName.isNameEditingAllowed) {
|
||||||
|
roomSettings.changeName(roomName.text);
|
||||||
|
roomName.isNameEditingAllowed = false;
|
||||||
|
} else {
|
||||||
|
roomName.isNameEditingAllowed = true;
|
||||||
|
roomName.focus = true;
|
||||||
|
roomName.selectAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
|
@ -134,17 +175,10 @@ ApplicationWindow {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageButton {
|
|
||||||
Layout.alignment: Qt.AlignHCenter
|
|
||||||
image: ":/icons/icons/ui/edit.svg"
|
|
||||||
visible: roomSettings.canChangeNameAndTopic
|
|
||||||
onClicked: roomSettings.openEditModal()
|
|
||||||
}
|
|
||||||
|
|
||||||
TextArea {
|
TextArea {
|
||||||
id: roomTopic
|
id: roomTopic
|
||||||
property bool cut: implicitHeight > 100
|
property bool cut: implicitHeight > 100
|
||||||
property bool showMore
|
property bool showMore: false
|
||||||
clip: true
|
clip: true
|
||||||
Layout.maximumHeight: showMore? Number.POSITIVE_INFINITY : 100
|
Layout.maximumHeight: showMore? Number.POSITIVE_INFINITY : 100
|
||||||
Layout.preferredHeight: implicitHeight
|
Layout.preferredHeight: implicitHeight
|
||||||
|
@ -153,10 +187,12 @@ ApplicationWindow {
|
||||||
Layout.leftMargin: Nheko.paddingLarge
|
Layout.leftMargin: Nheko.paddingLarge
|
||||||
Layout.rightMargin: Nheko.paddingLarge
|
Layout.rightMargin: Nheko.paddingLarge
|
||||||
|
|
||||||
text: TimelineManager.escapeEmoji(roomSettings.roomTopic)
|
property bool isTopicEditingAllowed: false
|
||||||
|
|
||||||
|
readOnly: !isTopicEditingAllowed
|
||||||
|
textFormat: isTopicEditingAllowed ? TextEdit.PlainText : TextEdit.RichText
|
||||||
|
text: isTopicEditingAllowed ? roomSettings.plainRoomTopic : roomSettings.roomTopic
|
||||||
wrapMode: TextEdit.WordWrap
|
wrapMode: TextEdit.WordWrap
|
||||||
textFormat: TextEdit.RichText
|
|
||||||
readOnly: true
|
|
||||||
background: null
|
background: null
|
||||||
selectByMouse: !Settings.mobileMode
|
selectByMouse: !Settings.mobileMode
|
||||||
color: Nheko.colors.text
|
color: Nheko.colors.text
|
||||||
|
@ -169,6 +205,29 @@ ApplicationWindow {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImageButton {
|
||||||
|
id: topicChangeButton
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
visible: roomSettings.canChangeTopic
|
||||||
|
hoverEnabled: true
|
||||||
|
ToolTip.visible: hovered
|
||||||
|
ToolTip.text: qsTr("Change topic of this room")
|
||||||
|
ToolTip.delay: Nheko.tooltipDelay
|
||||||
|
image: roomTopic.isTopicEditingAllowed ? ":/icons/icons/ui/checkmark.svg" : ":/icons/icons/ui/edit.svg"
|
||||||
|
onClicked: {
|
||||||
|
if (roomTopic.isTopicEditingAllowed) {
|
||||||
|
roomSettings.changeTopic(roomTopic.text);
|
||||||
|
roomTopic.isTopicEditingAllowed = false;
|
||||||
|
} else {
|
||||||
|
roomTopic.isTopicEditingAllowed = true;
|
||||||
|
roomTopic.showMore = true;
|
||||||
|
roomTopic.focus = true;
|
||||||
|
//roomTopic.selectAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
id: showMorePlaceholder
|
id: showMorePlaceholder
|
||||||
|
|
|
@ -5,13 +5,10 @@
|
||||||
|
|
||||||
#include "RoomSettings.h"
|
#include "RoomSettings.h"
|
||||||
|
|
||||||
#include <QApplication>
|
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QHBoxLayout>
|
|
||||||
#include <QImageReader>
|
#include <QImageReader>
|
||||||
#include <QMimeDatabase>
|
#include <QMimeDatabase>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <QVBoxLayout>
|
|
||||||
#include <mtx/events/event_type.hpp>
|
#include <mtx/events/event_type.hpp>
|
||||||
#include <mtx/responses/common.hpp>
|
#include <mtx/responses/common.hpp>
|
||||||
#include <mtx/responses/media.hpp>
|
#include <mtx/responses/media.hpp>
|
||||||
|
@ -23,153 +20,9 @@
|
||||||
#include "Logging.h"
|
#include "Logging.h"
|
||||||
#include "MatrixClient.h"
|
#include "MatrixClient.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
#include "ui/TextField.h"
|
|
||||||
|
|
||||||
using namespace mtx::events;
|
using namespace mtx::events;
|
||||||
|
|
||||||
EditModal::EditModal(const QString &roomId, QWidget *parent)
|
|
||||||
: QWidget(parent)
|
|
||||||
, roomId_{roomId}
|
|
||||||
{
|
|
||||||
setAutoFillBackground(true);
|
|
||||||
setAttribute(Qt::WA_DeleteOnClose, true);
|
|
||||||
setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
|
|
||||||
setWindowModality(Qt::WindowModal);
|
|
||||||
|
|
||||||
QFont largeFont;
|
|
||||||
largeFont.setPointSizeF(largeFont.pointSizeF() * 1.4);
|
|
||||||
setMinimumWidth(conf::window::minModalWidth);
|
|
||||||
setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
|
|
||||||
|
|
||||||
auto layout = new QVBoxLayout(this);
|
|
||||||
|
|
||||||
applyBtn_ = new QPushButton(tr("Apply"), this);
|
|
||||||
cancelBtn_ = new QPushButton(tr("Cancel"), this);
|
|
||||||
cancelBtn_->setDefault(true);
|
|
||||||
|
|
||||||
auto btnLayout = new QHBoxLayout;
|
|
||||||
btnLayout->addStretch(1);
|
|
||||||
btnLayout->setSpacing(15);
|
|
||||||
btnLayout->addWidget(cancelBtn_);
|
|
||||||
btnLayout->addWidget(applyBtn_);
|
|
||||||
|
|
||||||
nameInput_ = new TextField(this);
|
|
||||||
nameInput_->setLabel(tr("Name").toUpper());
|
|
||||||
topicInput_ = new TextField(this);
|
|
||||||
topicInput_->setLabel(tr("Topic").toUpper());
|
|
||||||
|
|
||||||
errorField_ = new QLabel(this);
|
|
||||||
errorField_->setWordWrap(true);
|
|
||||||
errorField_->hide();
|
|
||||||
|
|
||||||
layout->addWidget(nameInput_);
|
|
||||||
layout->addWidget(topicInput_);
|
|
||||||
layout->addLayout(btnLayout, 1);
|
|
||||||
|
|
||||||
auto labelLayout = new QHBoxLayout;
|
|
||||||
labelLayout->setAlignment(Qt::AlignHCenter);
|
|
||||||
labelLayout->addWidget(errorField_);
|
|
||||||
layout->addLayout(labelLayout);
|
|
||||||
|
|
||||||
connect(applyBtn_, &QPushButton::clicked, this, &EditModal::applyClicked);
|
|
||||||
connect(cancelBtn_, &QPushButton::clicked, this, &EditModal::close);
|
|
||||||
|
|
||||||
auto window = QApplication::activeWindow();
|
|
||||||
|
|
||||||
if (window != nullptr) {
|
|
||||||
auto center = window->frameGeometry().center();
|
|
||||||
move(center.x() - (width() * 0.5), center.y() - (height() * 0.5));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
EditModal::topicEventSent(const QString &topic)
|
|
||||||
{
|
|
||||||
errorField_->hide();
|
|
||||||
emit topicChanged(topic);
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
EditModal::nameEventSent(const QString &name)
|
|
||||||
{
|
|
||||||
errorField_->hide();
|
|
||||||
emit nameChanged(name);
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
EditModal::error(const QString &msg)
|
|
||||||
{
|
|
||||||
errorField_->setText(msg);
|
|
||||||
errorField_->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
EditModal::applyClicked()
|
|
||||||
{
|
|
||||||
// Check if the values are changed from the originals.
|
|
||||||
auto newName = nameInput_->text().trimmed();
|
|
||||||
auto newTopic = topicInput_->text().trimmed();
|
|
||||||
|
|
||||||
errorField_->hide();
|
|
||||||
|
|
||||||
if (newName == initialName_ && newTopic == initialTopic_) {
|
|
||||||
close();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
using namespace mtx::events;
|
|
||||||
auto proxy = std::make_shared<ThreadProxy>();
|
|
||||||
connect(proxy.get(), &ThreadProxy::topicEventSent, this, &EditModal::topicEventSent);
|
|
||||||
connect(proxy.get(), &ThreadProxy::nameEventSent, this, &EditModal::nameEventSent);
|
|
||||||
connect(proxy.get(), &ThreadProxy::error, this, &EditModal::error);
|
|
||||||
|
|
||||||
if (newName != initialName_ && !newName.isEmpty()) {
|
|
||||||
state::Name body;
|
|
||||||
body.name = newName.toStdString();
|
|
||||||
|
|
||||||
http::client()->send_state_event(
|
|
||||||
roomId_.toStdString(),
|
|
||||||
body,
|
|
||||||
[proxy, newName](const mtx::responses::EventId &, mtx::http::RequestErr err) {
|
|
||||||
if (err) {
|
|
||||||
emit proxy->error(QString::fromStdString(err->matrix_error.error));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
emit proxy->nameEventSent(newName);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newTopic != initialTopic_ && !newTopic.isEmpty()) {
|
|
||||||
state::Topic body;
|
|
||||||
body.topic = newTopic.toStdString();
|
|
||||||
|
|
||||||
http::client()->send_state_event(
|
|
||||||
roomId_.toStdString(),
|
|
||||||
body,
|
|
||||||
[proxy, newTopic](const mtx::responses::EventId &, mtx::http::RequestErr err) {
|
|
||||||
if (err) {
|
|
||||||
emit proxy->error(QString::fromStdString(err->matrix_error.error));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
emit proxy->topicEventSent(newTopic);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
EditModal::setFields(const QString &roomName, const QString &roomTopic)
|
|
||||||
{
|
|
||||||
initialName_ = roomName;
|
|
||||||
initialTopic_ = roomTopic;
|
|
||||||
|
|
||||||
nameInput_->setText(roomName);
|
|
||||||
topicInput_->setText(roomTopic);
|
|
||||||
}
|
|
||||||
|
|
||||||
RoomSettings::RoomSettings(QString roomid, QObject *parent)
|
RoomSettings::RoomSettings(QString roomid, QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
, roomid_{std::move(roomid)}
|
, roomid_{std::move(roomid)}
|
||||||
|
@ -244,6 +97,18 @@ RoomSettings::roomTopic() const
|
||||||
.replace(QLatin1String("\n"), QLatin1String("<br>"))));
|
.replace(QLatin1String("\n"), QLatin1String("<br>"))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString
|
||||||
|
RoomSettings::plainRoomName() const
|
||||||
|
{
|
||||||
|
return QString::fromStdString(info_.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString
|
||||||
|
RoomSettings::plainRoomTopic() const
|
||||||
|
{
|
||||||
|
return QString::fromStdString(info_.topic);
|
||||||
|
}
|
||||||
|
|
||||||
QString
|
QString
|
||||||
RoomSettings::roomId() const
|
RoomSettings::roomId() const
|
||||||
{
|
{
|
||||||
|
@ -340,12 +205,24 @@ RoomSettings::canChangeJoinRules() const
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
RoomSettings::canChangeNameAndTopic() const
|
RoomSettings::canChangeName() const
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return cache::hasEnoughPowerLevel({EventType::RoomName, EventType::RoomTopic},
|
return cache::hasEnoughPowerLevel(
|
||||||
roomid_.toStdString(),
|
{EventType::RoomName}, roomid_.toStdString(), utils::localUser().toStdString());
|
||||||
utils::localUser().toStdString());
|
} catch (const lmdb::error &e) {
|
||||||
|
nhlog::db()->warn("lmdb error: {}", e.what());
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RoomSettings::canChangeTopic() const
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return cache::hasEnoughPowerLevel(
|
||||||
|
{EventType::RoomTopic}, roomid_.toStdString(), utils::localUser().toStdString());
|
||||||
} catch (const lmdb::error &e) {
|
} catch (const lmdb::error &e) {
|
||||||
nhlog::db()->warn("lmdb error: {}", e.what());
|
nhlog::db()->warn("lmdb error: {}", e.what());
|
||||||
}
|
}
|
||||||
|
@ -387,26 +264,6 @@ RoomSettings::supportsRestricted() const
|
||||||
info_.version != "6" && info_.version != "7";
|
info_.version != "6" && info_.version != "7";
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
RoomSettings::openEditModal()
|
|
||||||
{
|
|
||||||
retrieveRoomInfo();
|
|
||||||
|
|
||||||
auto modal = new EditModal(roomid_);
|
|
||||||
modal->setFields(QString::fromStdString(info_.name), QString::fromStdString(info_.topic));
|
|
||||||
modal->raise();
|
|
||||||
modal->show();
|
|
||||||
connect(modal, &EditModal::nameChanged, this, [this](const QString &newName) {
|
|
||||||
info_.name = newName.toStdString();
|
|
||||||
emit roomNameChanged();
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(modal, &EditModal::topicChanged, this, [this](const QString &newTopic) {
|
|
||||||
info_.topic = newTopic.toStdString();
|
|
||||||
emit roomTopicChanged();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
RoomSettings::changeNotifications(int currentIndex)
|
RoomSettings::changeNotifications(int currentIndex)
|
||||||
{
|
{
|
||||||
|
@ -502,6 +359,74 @@ RoomSettings::changeAccessRules(int index)
|
||||||
updateAccessRules(roomid_.toStdString(), join_rule, guest_access);
|
updateAccessRules(roomid_.toStdString(), join_rule, guest_access);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RoomSettings::changeName(QString name)
|
||||||
|
{
|
||||||
|
// Check if the values are changed from the originals.
|
||||||
|
auto newName = name.trimmed().toStdString();
|
||||||
|
|
||||||
|
if (newName == info_.name) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
using namespace mtx::events;
|
||||||
|
auto proxy = std::make_shared<ThreadProxy>();
|
||||||
|
connect(proxy.get(), &ThreadProxy::nameEventSent, this, [this](QString newRoomName) {
|
||||||
|
this->info_.name = newRoomName.toStdString();
|
||||||
|
emit roomNameChanged();
|
||||||
|
});
|
||||||
|
connect(proxy.get(), &ThreadProxy::error, this, &RoomSettings::displayError);
|
||||||
|
|
||||||
|
state::Name body;
|
||||||
|
body.name = newName;
|
||||||
|
|
||||||
|
http::client()->send_state_event(
|
||||||
|
roomid_.toStdString(),
|
||||||
|
body,
|
||||||
|
[proxy, newName](const mtx::responses::EventId &, mtx::http::RequestErr err) {
|
||||||
|
if (err) {
|
||||||
|
emit proxy->error(QString::fromStdString(err->matrix_error.error));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit proxy->nameEventSent(QString::fromStdString(newName));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RoomSettings::changeTopic(QString topic)
|
||||||
|
{
|
||||||
|
// Check if the values are changed from the originals.
|
||||||
|
auto newTopic = topic.trimmed().toStdString();
|
||||||
|
|
||||||
|
if (newTopic == info_.topic) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
using namespace mtx::events;
|
||||||
|
auto proxy = std::make_shared<ThreadProxy>();
|
||||||
|
connect(proxy.get(), &ThreadProxy::topicEventSent, this, [this](QString newRoomTopic) {
|
||||||
|
this->info_.topic = newRoomTopic.toStdString();
|
||||||
|
emit roomTopicChanged();
|
||||||
|
});
|
||||||
|
connect(proxy.get(), &ThreadProxy::error, this, &RoomSettings::displayError);
|
||||||
|
|
||||||
|
state::Topic body;
|
||||||
|
body.topic = newTopic;
|
||||||
|
|
||||||
|
http::client()->send_state_event(
|
||||||
|
roomid_.toStdString(),
|
||||||
|
body,
|
||||||
|
[proxy, newTopic](const mtx::responses::EventId &, mtx::http::RequestErr err) {
|
||||||
|
if (err) {
|
||||||
|
emit proxy->error(QString::fromStdString(err->matrix_error.error));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit proxy->topicEventSent(QString::fromStdString(newTopic));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RoomSettings::updateAccessRules(const std::string &room_id,
|
RoomSettings::updateAccessRules(const std::string &room_id,
|
||||||
const mtx::events::state::JoinRules &join_rule,
|
const mtx::events::state::JoinRules &join_rule,
|
||||||
|
|
|
@ -5,9 +5,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QPushButton>
|
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
|
@ -16,8 +14,6 @@
|
||||||
|
|
||||||
#include "CacheStructs.h"
|
#include "CacheStructs.h"
|
||||||
|
|
||||||
class TextField;
|
|
||||||
|
|
||||||
/// Convenience class which connects events emmited from threads
|
/// Convenience class which connects events emmited from threads
|
||||||
/// outside of main with the UI code.
|
/// outside of main with the UI code.
|
||||||
class ThreadProxy : public QObject
|
class ThreadProxy : public QObject
|
||||||
|
@ -31,40 +27,6 @@ signals:
|
||||||
void stopLoading();
|
void stopLoading();
|
||||||
};
|
};
|
||||||
|
|
||||||
class EditModal : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
EditModal(const QString &roomId, QWidget *parent = nullptr);
|
|
||||||
|
|
||||||
void setFields(const QString &roomName, const QString &roomTopic);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void nameChanged(const QString &roomName);
|
|
||||||
void topicChanged(const QString &topic);
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void topicEventSent(const QString &topic);
|
|
||||||
void nameEventSent(const QString &name);
|
|
||||||
void error(const QString &msg);
|
|
||||||
|
|
||||||
void applyClicked();
|
|
||||||
|
|
||||||
private:
|
|
||||||
QString roomId_;
|
|
||||||
QString initialName_;
|
|
||||||
QString initialTopic_;
|
|
||||||
|
|
||||||
QLabel *errorField_;
|
|
||||||
|
|
||||||
TextField *nameInput_;
|
|
||||||
TextField *topicInput_;
|
|
||||||
|
|
||||||
QPushButton *applyBtn_;
|
|
||||||
QPushButton *cancelBtn_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class RoomSettings : public QObject
|
class RoomSettings : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -72,6 +34,8 @@ class RoomSettings : public QObject
|
||||||
Q_PROPERTY(QString roomVersion READ roomVersion CONSTANT)
|
Q_PROPERTY(QString roomVersion READ roomVersion CONSTANT)
|
||||||
Q_PROPERTY(QString roomName READ roomName NOTIFY roomNameChanged)
|
Q_PROPERTY(QString roomName READ roomName NOTIFY roomNameChanged)
|
||||||
Q_PROPERTY(QString roomTopic READ roomTopic NOTIFY roomTopicChanged)
|
Q_PROPERTY(QString roomTopic READ roomTopic NOTIFY roomTopicChanged)
|
||||||
|
Q_PROPERTY(QString plainRoomName READ plainRoomName NOTIFY roomNameChanged)
|
||||||
|
Q_PROPERTY(QString plainRoomTopic READ plainRoomTopic NOTIFY roomTopicChanged)
|
||||||
Q_PROPERTY(QString roomAvatarUrl READ roomAvatarUrl NOTIFY avatarUrlChanged)
|
Q_PROPERTY(QString roomAvatarUrl READ roomAvatarUrl NOTIFY avatarUrlChanged)
|
||||||
Q_PROPERTY(int memberCount READ memberCount CONSTANT)
|
Q_PROPERTY(int memberCount READ memberCount CONSTANT)
|
||||||
Q_PROPERTY(int notifications READ notifications NOTIFY notificationsChanged)
|
Q_PROPERTY(int notifications READ notifications NOTIFY notificationsChanged)
|
||||||
|
@ -79,7 +43,8 @@ class RoomSettings : public QObject
|
||||||
Q_PROPERTY(bool isLoading READ isLoading NOTIFY loadingChanged)
|
Q_PROPERTY(bool isLoading READ isLoading NOTIFY loadingChanged)
|
||||||
Q_PROPERTY(bool canChangeAvatar READ canChangeAvatar CONSTANT)
|
Q_PROPERTY(bool canChangeAvatar READ canChangeAvatar CONSTANT)
|
||||||
Q_PROPERTY(bool canChangeJoinRules READ canChangeJoinRules CONSTANT)
|
Q_PROPERTY(bool canChangeJoinRules READ canChangeJoinRules CONSTANT)
|
||||||
Q_PROPERTY(bool canChangeNameAndTopic READ canChangeNameAndTopic CONSTANT)
|
Q_PROPERTY(bool canChangeName READ canChangeName CONSTANT)
|
||||||
|
Q_PROPERTY(bool canChangeTopic READ canChangeTopic CONSTANT)
|
||||||
Q_PROPERTY(bool isEncryptionEnabled READ isEncryptionEnabled NOTIFY encryptionChanged)
|
Q_PROPERTY(bool isEncryptionEnabled READ isEncryptionEnabled NOTIFY encryptionChanged)
|
||||||
Q_PROPERTY(bool supportsKnocking READ supportsKnocking CONSTANT)
|
Q_PROPERTY(bool supportsKnocking READ supportsKnocking CONSTANT)
|
||||||
Q_PROPERTY(bool supportsRestricted READ supportsRestricted CONSTANT)
|
Q_PROPERTY(bool supportsRestricted READ supportsRestricted CONSTANT)
|
||||||
|
@ -90,6 +55,8 @@ public:
|
||||||
QString roomId() const;
|
QString roomId() const;
|
||||||
QString roomName() const;
|
QString roomName() const;
|
||||||
QString roomTopic() const;
|
QString roomTopic() const;
|
||||||
|
QString plainRoomName() const;
|
||||||
|
QString plainRoomTopic() const;
|
||||||
QString roomVersion() const;
|
QString roomVersion() const;
|
||||||
QString roomAvatarUrl();
|
QString roomAvatarUrl();
|
||||||
int memberCount() const;
|
int memberCount() const;
|
||||||
|
@ -98,8 +65,10 @@ public:
|
||||||
bool isLoading() const;
|
bool isLoading() const;
|
||||||
//! Whether the user has enough power level to send m.room.join_rules events.
|
//! Whether the user has enough power level to send m.room.join_rules events.
|
||||||
bool canChangeJoinRules() const;
|
bool canChangeJoinRules() const;
|
||||||
//! Whether the user has enough power level to send m.room.name & m.room.topic events.
|
//! Whether the user has enough power level to send m.room.name.
|
||||||
bool canChangeNameAndTopic() const;
|
bool canChangeName() const;
|
||||||
|
//! Whether the user has enough power level to send m.room.topic events.
|
||||||
|
bool canChangeTopic() const;
|
||||||
//! Whether the user has enough power level to send m.room.avatar event.
|
//! Whether the user has enough power level to send m.room.avatar event.
|
||||||
bool canChangeAvatar() const;
|
bool canChangeAvatar() const;
|
||||||
bool isEncryptionEnabled() const;
|
bool isEncryptionEnabled() const;
|
||||||
|
@ -108,9 +77,10 @@ public:
|
||||||
|
|
||||||
Q_INVOKABLE void enableEncryption();
|
Q_INVOKABLE void enableEncryption();
|
||||||
Q_INVOKABLE void updateAvatar();
|
Q_INVOKABLE void updateAvatar();
|
||||||
Q_INVOKABLE void openEditModal();
|
|
||||||
Q_INVOKABLE void changeAccessRules(int index);
|
Q_INVOKABLE void changeAccessRules(int index);
|
||||||
Q_INVOKABLE void changeNotifications(int currentIndex);
|
Q_INVOKABLE void changeNotifications(int currentIndex);
|
||||||
|
Q_INVOKABLE void changeTopic(QString topic);
|
||||||
|
Q_INVOKABLE void changeName(QString name);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void loadingChanged();
|
void loadingChanged();
|
||||||
|
|
|
@ -1,382 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
|
||||||
// SPDX-FileCopyrightText: 2022 Nheko Contributors
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#include "TextField.h"
|
|
||||||
|
|
||||||
#include <QCoreApplication>
|
|
||||||
#include <QEventTransition>
|
|
||||||
#include <QFontDatabase>
|
|
||||||
#include <QPaintEvent>
|
|
||||||
#include <QPainter>
|
|
||||||
#include <QPropertyAnimation>
|
|
||||||
#include <QRegularExpressionValidator>
|
|
||||||
|
|
||||||
TextField::TextField(QWidget *parent)
|
|
||||||
: QLineEdit(parent)
|
|
||||||
{
|
|
||||||
// Get rid of the focus border on macOS.
|
|
||||||
setAttribute(Qt::WA_MacShowFocusRect, 0);
|
|
||||||
|
|
||||||
QPalette pal;
|
|
||||||
|
|
||||||
state_machine_ = new TextFieldStateMachine(this);
|
|
||||||
label_ = nullptr;
|
|
||||||
label_font_size_ = 15;
|
|
||||||
show_label_ = false;
|
|
||||||
background_color_ = pal.color(QPalette::Window);
|
|
||||||
is_valid_ = true;
|
|
||||||
|
|
||||||
setFrame(false);
|
|
||||||
setAttribute(Qt::WA_Hover);
|
|
||||||
setMouseTracking(true);
|
|
||||||
setTextMargins(0, 4, 0, 6);
|
|
||||||
|
|
||||||
state_machine_->start();
|
|
||||||
QCoreApplication::processEvents();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TextField::setBackgroundColor(const QColor &color)
|
|
||||||
{
|
|
||||||
background_color_ = color;
|
|
||||||
emit backgroundColorChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
QColor
|
|
||||||
TextField::backgroundColor() const
|
|
||||||
{
|
|
||||||
return background_color_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TextField::setShowLabel(bool value)
|
|
||||||
{
|
|
||||||
if (show_label_ == value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
show_label_ = value;
|
|
||||||
|
|
||||||
if (!label_ && value) {
|
|
||||||
label_ = new TextFieldLabel(this);
|
|
||||||
state_machine_->setLabel(label_);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value) {
|
|
||||||
setContentsMargins(0, 23, 0, 0);
|
|
||||||
} else {
|
|
||||||
setContentsMargins(0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
TextField::hasLabel() const
|
|
||||||
{
|
|
||||||
return show_label_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TextField::setValid(bool valid)
|
|
||||||
{
|
|
||||||
is_valid_ = valid;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
TextField::isValid() const
|
|
||||||
{
|
|
||||||
QString s = text();
|
|
||||||
int pos = 0;
|
|
||||||
if (regexp_.pattern().isEmpty()) {
|
|
||||||
return is_valid_;
|
|
||||||
}
|
|
||||||
QRegularExpressionValidator v(QRegularExpression(regexp_), 0);
|
|
||||||
return v.validate(s, pos) == QValidator::Acceptable;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TextField::setLabelFontSize(qreal size)
|
|
||||||
{
|
|
||||||
label_font_size_ = size;
|
|
||||||
|
|
||||||
if (label_) {
|
|
||||||
QFont font(label_->font());
|
|
||||||
font.setPointSizeF(size);
|
|
||||||
label_->setFont(font);
|
|
||||||
label_->update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
qreal
|
|
||||||
TextField::labelFontSize() const
|
|
||||||
{
|
|
||||||
return label_font_size_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TextField::setLabel(const QString &label)
|
|
||||||
{
|
|
||||||
label_text_ = label;
|
|
||||||
setShowLabel(true);
|
|
||||||
label_->update();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString
|
|
||||||
TextField::label() const
|
|
||||||
{
|
|
||||||
return label_text_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TextField::setLabelColor(const QColor &color)
|
|
||||||
{
|
|
||||||
label_color_ = color;
|
|
||||||
emit labelColorChanged();
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
QColor
|
|
||||||
TextField::labelColor() const
|
|
||||||
{
|
|
||||||
if (!label_color_.isValid()) {
|
|
||||||
return QPalette().color(QPalette::Text);
|
|
||||||
}
|
|
||||||
|
|
||||||
return label_color_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TextField::setInkColor(const QColor &color)
|
|
||||||
{
|
|
||||||
ink_color_ = color;
|
|
||||||
emit inkColorChanged();
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
QColor
|
|
||||||
TextField::inkColor() const
|
|
||||||
{
|
|
||||||
if (!ink_color_.isValid()) {
|
|
||||||
return QPalette().color(QPalette::Text);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ink_color_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TextField::setUnderlineColor(const QColor &color)
|
|
||||||
{
|
|
||||||
underline_color_ = color;
|
|
||||||
emit underlineColorChanged();
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TextField::setRegexp(const QRegularExpression ®exp)
|
|
||||||
{
|
|
||||||
regexp_ = regexp;
|
|
||||||
}
|
|
||||||
|
|
||||||
QColor
|
|
||||||
TextField::underlineColor() const
|
|
||||||
{
|
|
||||||
if (!underline_color_.isValid()) {
|
|
||||||
if ((hasAcceptableInput() && isValid()) || !isModified())
|
|
||||||
return QPalette().color(QPalette::Highlight);
|
|
||||||
else
|
|
||||||
return Qt::red;
|
|
||||||
}
|
|
||||||
|
|
||||||
return underline_color_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
TextField::event(QEvent *event)
|
|
||||||
{
|
|
||||||
switch (event->type()) {
|
|
||||||
case QEvent::Resize:
|
|
||||||
case QEvent::Move: {
|
|
||||||
if (label_)
|
|
||||||
label_->setGeometry(rect());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return QLineEdit::event(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TextField::paintEvent(QPaintEvent *event)
|
|
||||||
{
|
|
||||||
QLineEdit::paintEvent(event);
|
|
||||||
|
|
||||||
QPainter painter(this);
|
|
||||||
|
|
||||||
if (text().isEmpty()) {
|
|
||||||
painter.setOpacity(1 - state_machine_->progress());
|
|
||||||
painter.fillRect(rect(), backgroundColor());
|
|
||||||
}
|
|
||||||
|
|
||||||
const int y = height() - 1;
|
|
||||||
const int wd = width() - 5;
|
|
||||||
|
|
||||||
QPen pen;
|
|
||||||
pen.setWidth(1);
|
|
||||||
pen.setColor(underlineColor());
|
|
||||||
painter.setPen(pen);
|
|
||||||
painter.setOpacity(1);
|
|
||||||
painter.drawLine(2, y, wd, y);
|
|
||||||
|
|
||||||
QBrush brush;
|
|
||||||
brush.setStyle(Qt::SolidPattern);
|
|
||||||
brush.setColor(inkColor());
|
|
||||||
|
|
||||||
const qreal progress = state_machine_->progress();
|
|
||||||
|
|
||||||
if (progress > 0) {
|
|
||||||
painter.setPen(Qt::NoPen);
|
|
||||||
painter.setBrush(brush);
|
|
||||||
const int w = (1 - progress) * static_cast<qreal>(wd / 2);
|
|
||||||
painter.drawRect(w + 2.5, height() - 2, wd - 2 * w, 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TextFieldStateMachine::TextFieldStateMachine(TextField *parent)
|
|
||||||
: QStateMachine(parent)
|
|
||||||
, text_field_(parent)
|
|
||||||
{
|
|
||||||
normal_state_ = new QState;
|
|
||||||
focused_state_ = new QState;
|
|
||||||
|
|
||||||
label_ = nullptr;
|
|
||||||
offset_anim_ = nullptr;
|
|
||||||
color_anim_ = nullptr;
|
|
||||||
progress_ = 0.0;
|
|
||||||
|
|
||||||
addState(normal_state_);
|
|
||||||
addState(focused_state_);
|
|
||||||
|
|
||||||
setInitialState(normal_state_);
|
|
||||||
|
|
||||||
QEventTransition *transition;
|
|
||||||
QPropertyAnimation *animation;
|
|
||||||
|
|
||||||
transition = new QEventTransition(parent, QEvent::FocusIn);
|
|
||||||
transition->setTargetState(focused_state_);
|
|
||||||
normal_state_->addTransition(transition);
|
|
||||||
|
|
||||||
animation = new QPropertyAnimation(this, "progress", this);
|
|
||||||
animation->setEasingCurve(QEasingCurve::InCubic);
|
|
||||||
animation->setDuration(310);
|
|
||||||
transition->addAnimation(animation);
|
|
||||||
|
|
||||||
transition = new QEventTransition(parent, QEvent::FocusOut);
|
|
||||||
transition->setTargetState(normal_state_);
|
|
||||||
focused_state_->addTransition(transition);
|
|
||||||
|
|
||||||
animation = new QPropertyAnimation(this, "progress", this);
|
|
||||||
animation->setEasingCurve(QEasingCurve::OutCubic);
|
|
||||||
animation->setDuration(310);
|
|
||||||
transition->addAnimation(animation);
|
|
||||||
|
|
||||||
normal_state_->assignProperty(this, "progress", 0);
|
|
||||||
focused_state_->assignProperty(this, "progress", 1);
|
|
||||||
|
|
||||||
setupProperties();
|
|
||||||
|
|
||||||
connect(text_field_, SIGNAL(textChanged(QString)), this, SLOT(setupProperties()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TextFieldStateMachine::setLabel(TextFieldLabel *label)
|
|
||||||
{
|
|
||||||
if (label_) {
|
|
||||||
delete label_;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offset_anim_) {
|
|
||||||
removeDefaultAnimation(offset_anim_);
|
|
||||||
delete offset_anim_;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (color_anim_) {
|
|
||||||
removeDefaultAnimation(color_anim_);
|
|
||||||
delete color_anim_;
|
|
||||||
}
|
|
||||||
|
|
||||||
label_ = label;
|
|
||||||
|
|
||||||
if (label_) {
|
|
||||||
offset_anim_ = new QPropertyAnimation(label_, "offset", this);
|
|
||||||
offset_anim_->setDuration(210);
|
|
||||||
offset_anim_->setEasingCurve(QEasingCurve::OutCubic);
|
|
||||||
addDefaultAnimation(offset_anim_);
|
|
||||||
|
|
||||||
color_anim_ = new QPropertyAnimation(label_, "color", this);
|
|
||||||
color_anim_->setDuration(210);
|
|
||||||
addDefaultAnimation(color_anim_);
|
|
||||||
}
|
|
||||||
|
|
||||||
setupProperties();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TextFieldStateMachine::setupProperties()
|
|
||||||
{
|
|
||||||
if (label_) {
|
|
||||||
const int m = text_field_->textMargins().top();
|
|
||||||
|
|
||||||
if (text_field_->text().isEmpty()) {
|
|
||||||
normal_state_->assignProperty(label_, "offset", QPointF(0, 26));
|
|
||||||
} else {
|
|
||||||
normal_state_->assignProperty(label_, "offset", QPointF(0, 0 - m));
|
|
||||||
}
|
|
||||||
|
|
||||||
focused_state_->assignProperty(label_, "offset", QPointF(0, 0 - m));
|
|
||||||
focused_state_->assignProperty(label_, "color", text_field_->inkColor());
|
|
||||||
normal_state_->assignProperty(label_, "color", text_field_->labelColor());
|
|
||||||
|
|
||||||
if (0 != label_->offset().y() && !text_field_->text().isEmpty()) {
|
|
||||||
label_->setOffset(QPointF(0, 0 - m));
|
|
||||||
} else if (!text_field_->hasFocus() && label_->offset().y() <= 0 &&
|
|
||||||
text_field_->text().isEmpty()) {
|
|
||||||
label_->setOffset(QPointF(0, 26));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
text_field_->update();
|
|
||||||
}
|
|
||||||
|
|
||||||
TextFieldLabel::TextFieldLabel(TextField *parent)
|
|
||||||
: QWidget(parent)
|
|
||||||
, text_field_(parent)
|
|
||||||
{
|
|
||||||
x_ = 0;
|
|
||||||
y_ = 26;
|
|
||||||
scale_ = 1;
|
|
||||||
color_ = parent->labelColor();
|
|
||||||
|
|
||||||
QFont font;
|
|
||||||
font.setWeight(60);
|
|
||||||
font.setLetterSpacing(QFont::PercentageSpacing, 102);
|
|
||||||
setFont(font);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TextFieldLabel::paintEvent(QPaintEvent *)
|
|
||||||
{
|
|
||||||
if (!text_field_->hasLabel())
|
|
||||||
return;
|
|
||||||
|
|
||||||
QPainter painter(this);
|
|
||||||
painter.setRenderHint(QPainter::Antialiasing);
|
|
||||||
painter.scale(scale_, scale_);
|
|
||||||
painter.setPen(color_);
|
|
||||||
painter.setOpacity(1);
|
|
||||||
|
|
||||||
QPointF pos(2 + x_, height() - 36 + y_);
|
|
||||||
painter.drawText(pos.x(), pos.y(), text_field_->label());
|
|
||||||
}
|
|
|
@ -1,201 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
|
||||||
// SPDX-FileCopyrightText: 2022 Nheko Contributors
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QColor>
|
|
||||||
#include <QLineEdit>
|
|
||||||
#include <QPaintEvent>
|
|
||||||
#include <QPropertyAnimation>
|
|
||||||
#include <QRegularExpression>
|
|
||||||
#include <QStateMachine>
|
|
||||||
#include <QtGlobal>
|
|
||||||
|
|
||||||
class TextField;
|
|
||||||
class TextFieldLabel;
|
|
||||||
class TextFieldStateMachine;
|
|
||||||
|
|
||||||
class TextField : public QLineEdit
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
Q_PROPERTY(QColor inkColor WRITE setInkColor READ inkColor NOTIFY inkColorChanged)
|
|
||||||
Q_PROPERTY(QColor labelColor WRITE setLabelColor READ labelColor NOTIFY labelColorChanged)
|
|
||||||
Q_PROPERTY(QColor underlineColor WRITE setUnderlineColor READ underlineColor NOTIFY
|
|
||||||
underlineColorChanged)
|
|
||||||
Q_PROPERTY(QColor backgroundColor WRITE setBackgroundColor READ backgroundColor NOTIFY
|
|
||||||
backgroundColorChanged)
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit TextField(QWidget *parent = nullptr);
|
|
||||||
|
|
||||||
void setInkColor(const QColor &color);
|
|
||||||
void setBackgroundColor(const QColor &color);
|
|
||||||
void setLabel(const QString &label);
|
|
||||||
void setLabelColor(const QColor &color);
|
|
||||||
void setLabelFontSize(qreal size);
|
|
||||||
void setShowLabel(bool value);
|
|
||||||
void setUnderlineColor(const QColor &color);
|
|
||||||
void setRegexp(const QRegularExpression ®exp);
|
|
||||||
void setValid(bool valid);
|
|
||||||
|
|
||||||
QColor inkColor() const;
|
|
||||||
QColor labelColor() const;
|
|
||||||
QColor underlineColor() const;
|
|
||||||
QColor backgroundColor() const;
|
|
||||||
QString label() const;
|
|
||||||
bool hasLabel() const;
|
|
||||||
bool isValid() const;
|
|
||||||
qreal labelFontSize() const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool event(QEvent *event) override;
|
|
||||||
void paintEvent(QPaintEvent *event) override;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void inkColorChanged();
|
|
||||||
void labelColorChanged();
|
|
||||||
void underlineColorChanged();
|
|
||||||
void backgroundColorChanged();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void init();
|
|
||||||
|
|
||||||
QColor ink_color_;
|
|
||||||
QColor background_color_;
|
|
||||||
QColor label_color_;
|
|
||||||
QColor underline_color_;
|
|
||||||
QString label_text_;
|
|
||||||
TextFieldLabel *label_;
|
|
||||||
TextFieldStateMachine *state_machine_;
|
|
||||||
bool show_label_;
|
|
||||||
QRegularExpression regexp_;
|
|
||||||
bool is_valid_;
|
|
||||||
qreal label_font_size_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class TextFieldLabel : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
Q_PROPERTY(qreal scale WRITE setScale READ scale NOTIFY scaleChanged)
|
|
||||||
Q_PROPERTY(QPointF offset WRITE setOffset READ offset NOTIFY offsetChanged)
|
|
||||||
Q_PROPERTY(QColor color WRITE setColor READ color NOTIFY colorChanged)
|
|
||||||
|
|
||||||
public:
|
|
||||||
TextFieldLabel(TextField *parent);
|
|
||||||
|
|
||||||
inline void setColor(const QColor &color);
|
|
||||||
inline void setOffset(QPointF pos);
|
|
||||||
inline void setScale(qreal scale);
|
|
||||||
|
|
||||||
inline QColor color() const;
|
|
||||||
inline QPointF offset() const;
|
|
||||||
inline qreal scale() const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void paintEvent(QPaintEvent *event) override;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void scaleChanged();
|
|
||||||
void offsetChanged();
|
|
||||||
void colorChanged();
|
|
||||||
|
|
||||||
private:
|
|
||||||
TextField *const text_field_;
|
|
||||||
|
|
||||||
QColor color_;
|
|
||||||
qreal scale_;
|
|
||||||
qreal x_;
|
|
||||||
qreal y_;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline void
|
|
||||||
TextFieldLabel::setColor(const QColor &color)
|
|
||||||
{
|
|
||||||
color_ = color;
|
|
||||||
emit colorChanged();
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void
|
|
||||||
TextFieldLabel::setOffset(QPointF pos)
|
|
||||||
{
|
|
||||||
x_ = pos.x();
|
|
||||||
y_ = pos.y();
|
|
||||||
emit offsetChanged();
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void
|
|
||||||
TextFieldLabel::setScale(qreal scale)
|
|
||||||
{
|
|
||||||
scale_ = scale;
|
|
||||||
emit scaleChanged();
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline QPointF
|
|
||||||
TextFieldLabel::offset() const
|
|
||||||
{
|
|
||||||
return QPointF(x_, y_);
|
|
||||||
}
|
|
||||||
inline qreal
|
|
||||||
TextFieldLabel::scale() const
|
|
||||||
{
|
|
||||||
return scale_;
|
|
||||||
}
|
|
||||||
inline QColor
|
|
||||||
TextFieldLabel::color() const
|
|
||||||
{
|
|
||||||
return color_;
|
|
||||||
}
|
|
||||||
|
|
||||||
class TextFieldStateMachine : public QStateMachine
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
Q_PROPERTY(qreal progress WRITE setProgress READ progress NOTIFY progressChanged)
|
|
||||||
|
|
||||||
public:
|
|
||||||
TextFieldStateMachine(TextField *parent);
|
|
||||||
|
|
||||||
inline void setProgress(qreal progress);
|
|
||||||
void setLabel(TextFieldLabel *label);
|
|
||||||
|
|
||||||
inline qreal progress() const;
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void setupProperties();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void progressChanged();
|
|
||||||
|
|
||||||
private:
|
|
||||||
QPropertyAnimation *color_anim_;
|
|
||||||
QPropertyAnimation *offset_anim_;
|
|
||||||
|
|
||||||
QState *focused_state_;
|
|
||||||
QState *normal_state_;
|
|
||||||
|
|
||||||
TextField *text_field_;
|
|
||||||
TextFieldLabel *label_;
|
|
||||||
|
|
||||||
qreal progress_;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline void
|
|
||||||
TextFieldStateMachine::setProgress(qreal progress)
|
|
||||||
{
|
|
||||||
progress_ = progress;
|
|
||||||
emit progressChanged();
|
|
||||||
text_field_->update();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline qreal
|
|
||||||
TextFieldStateMachine::progress() const
|
|
||||||
{
|
|
||||||
return progress_;
|
|
||||||
}
|
|
|
@ -8,54 +8,6 @@
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
#include <QPalette>
|
#include <QPalette>
|
||||||
|
|
||||||
namespace ui {
|
|
||||||
// Default font size.
|
|
||||||
const int FontSize = 16;
|
|
||||||
|
|
||||||
// Default avatar size. Width and height.
|
|
||||||
const int AvatarSize = 40;
|
|
||||||
|
|
||||||
enum class ButtonPreset
|
|
||||||
{
|
|
||||||
FlatPreset,
|
|
||||||
CheckablePreset
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class RippleStyle
|
|
||||||
{
|
|
||||||
CenteredRipple,
|
|
||||||
PositionedRipple,
|
|
||||||
NoRipple
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class OverlayStyle
|
|
||||||
{
|
|
||||||
NoOverlay,
|
|
||||||
TintedOverlay,
|
|
||||||
GrayOverlay
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class Role
|
|
||||||
{
|
|
||||||
Default,
|
|
||||||
Primary,
|
|
||||||
Secondary
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class ButtonIconPlacement
|
|
||||||
{
|
|
||||||
LeftIcon,
|
|
||||||
RightIcon
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class ProgressType
|
|
||||||
{
|
|
||||||
DeterminateProgress,
|
|
||||||
IndeterminateProgress
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace ui
|
|
||||||
|
|
||||||
class Theme : public QPalette
|
class Theme : public QPalette
|
||||||
{
|
{
|
||||||
Q_GADGET
|
Q_GADGET
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
#include <QFontDatabase>
|
|
||||||
|
|
||||||
#include "ThemeManager.h"
|
#include "ThemeManager.h"
|
||||||
|
|
||||||
QColor
|
QColor
|
||||||
|
|
Loading…
Reference in a new issue