Remove a few now unused files
This commit is contained in:
parent
392a4be858
commit
f44d8e916b
@ -331,24 +331,14 @@ set(SRC_FILES
|
|||||||
src/timeline/RoomlistModel.cpp
|
src/timeline/RoomlistModel.cpp
|
||||||
|
|
||||||
# UI components
|
# UI components
|
||||||
src/ui/DropShadow.cpp
|
|
||||||
src/ui/FlatButton.cpp
|
|
||||||
src/ui/Label.cpp
|
|
||||||
src/ui/LoadingIndicator.cpp
|
|
||||||
src/ui/MxcAnimatedImage.cpp
|
src/ui/MxcAnimatedImage.cpp
|
||||||
src/ui/MxcMediaProxy.cpp
|
src/ui/MxcMediaProxy.cpp
|
||||||
src/ui/NhekoCursorShape.cpp
|
src/ui/NhekoCursorShape.cpp
|
||||||
src/ui/NhekoDropArea.cpp
|
src/ui/NhekoDropArea.cpp
|
||||||
src/ui/NhekoGlobalObject.cpp
|
src/ui/NhekoGlobalObject.cpp
|
||||||
src/ui/OverlayModal.cpp
|
|
||||||
src/ui/OverlayWidget.cpp
|
src/ui/OverlayWidget.cpp
|
||||||
src/ui/RaisedButton.cpp
|
|
||||||
src/ui/Ripple.cpp
|
|
||||||
src/ui/RippleOverlay.cpp
|
|
||||||
src/ui/RoomSettings.cpp
|
src/ui/RoomSettings.cpp
|
||||||
src/ui/SnackBar.cpp
|
|
||||||
src/ui/TextField.cpp
|
src/ui/TextField.cpp
|
||||||
src/ui/TextLabel.cpp
|
|
||||||
src/ui/Theme.cpp
|
src/ui/Theme.cpp
|
||||||
src/ui/ThemeManager.cpp
|
src/ui/ThemeManager.cpp
|
||||||
src/ui/ToggleButton.cpp
|
src/ui/ToggleButton.cpp
|
||||||
@ -395,7 +385,6 @@ set(SRC_FILES
|
|||||||
src/RoomDirectoryModel.cpp
|
src/RoomDirectoryModel.cpp
|
||||||
src/RoomsModel.cpp
|
src/RoomsModel.cpp
|
||||||
src/Utils.cpp
|
src/Utils.cpp
|
||||||
src/WelcomePage.cpp
|
|
||||||
src/main.cpp
|
src/main.cpp
|
||||||
|
|
||||||
third_party/blurhash/blurhash.cpp
|
third_party/blurhash/blurhash.cpp
|
||||||
@ -538,23 +527,14 @@ qt5_wrap_cpp(MOC_HEADERS
|
|||||||
src/timeline/RoomlistModel.h
|
src/timeline/RoomlistModel.h
|
||||||
|
|
||||||
# UI components
|
# UI components
|
||||||
src/ui/FlatButton.h
|
|
||||||
src/ui/Label.h
|
|
||||||
src/ui/LoadingIndicator.h
|
|
||||||
src/ui/MxcAnimatedImage.h
|
src/ui/MxcAnimatedImage.h
|
||||||
src/ui/MxcMediaProxy.h
|
src/ui/MxcMediaProxy.h
|
||||||
src/ui/Menu.h
|
|
||||||
src/ui/NhekoCursorShape.h
|
src/ui/NhekoCursorShape.h
|
||||||
src/ui/NhekoDropArea.h
|
src/ui/NhekoDropArea.h
|
||||||
src/ui/NhekoGlobalObject.h
|
src/ui/NhekoGlobalObject.h
|
||||||
src/ui/OverlayWidget.h
|
src/ui/OverlayWidget.h
|
||||||
src/ui/RaisedButton.h
|
|
||||||
src/ui/Ripple.h
|
|
||||||
src/ui/RippleOverlay.h
|
|
||||||
src/ui/RoomSettings.h
|
src/ui/RoomSettings.h
|
||||||
src/ui/SnackBar.h
|
|
||||||
src/ui/TextField.h
|
src/ui/TextField.h
|
||||||
src/ui/TextLabel.h
|
|
||||||
src/ui/Theme.h
|
src/ui/Theme.h
|
||||||
src/ui/ThemeManager.h
|
src/ui/ThemeManager.h
|
||||||
src/ui/ToggleButton.h
|
src/ui/ToggleButton.h
|
||||||
@ -596,7 +576,6 @@ qt5_wrap_cpp(MOC_HEADERS
|
|||||||
src/UsersModel.h
|
src/UsersModel.h
|
||||||
src/RoomDirectoryModel.h
|
src/RoomDirectoryModel.h
|
||||||
src/RoomsModel.h
|
src/RoomsModel.h
|
||||||
src/WelcomePage.h
|
|
||||||
src/ReadReceiptsModel.h
|
src/ReadReceiptsModel.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -22,7 +22,6 @@
|
|||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
#include "encryption/DeviceVerificationFlow.h"
|
#include "encryption/DeviceVerificationFlow.h"
|
||||||
#include "encryption/Olm.h"
|
#include "encryption/Olm.h"
|
||||||
#include "ui/OverlayModal.h"
|
|
||||||
#include "ui/Theme.h"
|
#include "ui/Theme.h"
|
||||||
#include "ui/UserProfile.h"
|
#include "ui/UserProfile.h"
|
||||||
#include "voip/CallManager.h"
|
#include "voip/CallManager.h"
|
||||||
@ -1050,8 +1049,6 @@ ChatPage::initiateLogout()
|
|||||||
|
|
||||||
emit loggedOut();
|
emit loggedOut();
|
||||||
});
|
});
|
||||||
|
|
||||||
emit showOverlayProgressBar();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -28,7 +28,6 @@
|
|||||||
#include "CacheStructs.h"
|
#include "CacheStructs.h"
|
||||||
#include "notifications/Manager.h"
|
#include "notifications/Manager.h"
|
||||||
|
|
||||||
class OverlayModal;
|
|
||||||
class TimelineViewManager;
|
class TimelineViewManager;
|
||||||
class UserSettings;
|
class UserSettings;
|
||||||
class NotificationsManager;
|
class NotificationsManager;
|
||||||
@ -112,7 +111,6 @@ signals:
|
|||||||
void showNotification(const QString &msg);
|
void showNotification(const QString &msg);
|
||||||
void showLoginPage(const QString &msg);
|
void showLoginPage(const QString &msg);
|
||||||
void showUserSettingsPage();
|
void showUserSettingsPage();
|
||||||
void showOverlayProgressBar();
|
|
||||||
|
|
||||||
void ownProfileOk();
|
void ownProfileOk();
|
||||||
void setUserDisplayName(const QString &name);
|
void setUserDisplayName(const QString &name);
|
||||||
|
@ -41,21 +41,17 @@
|
|||||||
#include "UserSettingsPage.h"
|
#include "UserSettingsPage.h"
|
||||||
#include "UsersModel.h"
|
#include "UsersModel.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
#include "WelcomePage.h"
|
|
||||||
#include "emoji/EmojiModel.h"
|
#include "emoji/EmojiModel.h"
|
||||||
#include "emoji/Provider.h"
|
#include "emoji/Provider.h"
|
||||||
#include "encryption/DeviceVerificationFlow.h"
|
#include "encryption/DeviceVerificationFlow.h"
|
||||||
#include "encryption/SelfVerificationStatus.h"
|
#include "encryption/SelfVerificationStatus.h"
|
||||||
#include "timeline/DelegateChooser.h"
|
#include "timeline/DelegateChooser.h"
|
||||||
#include "timeline/TimelineViewManager.h"
|
#include "timeline/TimelineViewManager.h"
|
||||||
#include "ui/LoadingIndicator.h"
|
|
||||||
#include "ui/MxcAnimatedImage.h"
|
#include "ui/MxcAnimatedImage.h"
|
||||||
#include "ui/MxcMediaProxy.h"
|
#include "ui/MxcMediaProxy.h"
|
||||||
#include "ui/NhekoCursorShape.h"
|
#include "ui/NhekoCursorShape.h"
|
||||||
#include "ui/NhekoDropArea.h"
|
#include "ui/NhekoDropArea.h"
|
||||||
#include "ui/NhekoGlobalObject.h"
|
#include "ui/NhekoGlobalObject.h"
|
||||||
#include "ui/OverlayModal.h"
|
|
||||||
#include "ui/SnackBar.h"
|
|
||||||
#include "ui/UIA.h"
|
#include "ui/UIA.h"
|
||||||
#include "voip/WebRTCSession.h"
|
#include "voip/WebRTCSession.h"
|
||||||
|
|
||||||
@ -101,8 +97,6 @@ MainWindow::MainWindow(QWindow *parent)
|
|||||||
this,
|
this,
|
||||||
SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
|
SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
|
||||||
|
|
||||||
connect(chat_page_, SIGNAL(contentLoaded()), this, SLOT(removeOverlayProgressBar()));
|
|
||||||
|
|
||||||
trayIcon_->setVisible(userSettings_->tray());
|
trayIcon_->setVisible(userSettings_->tray());
|
||||||
|
|
||||||
// load cache on event loop
|
// load cache on event loop
|
||||||
|
@ -10,11 +10,9 @@
|
|||||||
|
|
||||||
#include <QQuickView>
|
#include <QQuickView>
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
#include <QStackedWidget>
|
|
||||||
#include <QSystemTrayIcon>
|
#include <QSystemTrayIcon>
|
||||||
|
|
||||||
#include "UserSettingsPage.h"
|
#include "UserSettingsPage.h"
|
||||||
#include "ui/OverlayModal.h"
|
|
||||||
|
|
||||||
#include "jdenticoninterface.h"
|
#include "jdenticoninterface.h"
|
||||||
|
|
||||||
@ -22,9 +20,6 @@ class ChatPage;
|
|||||||
class RegisterPage;
|
class RegisterPage;
|
||||||
class WelcomePage;
|
class WelcomePage;
|
||||||
|
|
||||||
class LoadingIndicator;
|
|
||||||
class OverlayModal;
|
|
||||||
class SnackBar;
|
|
||||||
class TrayIcon;
|
class TrayIcon;
|
||||||
class UserSettings;
|
class UserSettings;
|
||||||
class MxcImageProvider;
|
class MxcImageProvider;
|
||||||
|
@ -33,8 +33,7 @@
|
|||||||
#include "UserSettingsPage.h"
|
#include "UserSettingsPage.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
#include "encryption/Olm.h"
|
#include "encryption/Olm.h"
|
||||||
#include "ui/FlatButton.h"
|
#include "ui/Theme.h"
|
||||||
#include "ui/ToggleButton.h"
|
|
||||||
#include "voip/CallDevices.h"
|
#include "voip/CallDevices.h"
|
||||||
|
|
||||||
#include "config/nheko.h"
|
#include "config/nheko.h"
|
||||||
|
@ -1,88 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Konstantinos Sideris <siderisk@auth.gr>
|
|
||||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
|
||||||
// SPDX-FileCopyrightText: 2022 Nheko Contributors
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QLayout>
|
|
||||||
#include <QPainter>
|
|
||||||
#include <QStyleOption>
|
|
||||||
|
|
||||||
#include "Config.h"
|
|
||||||
#include "WelcomePage.h"
|
|
||||||
#include "ui/RaisedButton.h"
|
|
||||||
#include "ui/TextLabel.h"
|
|
||||||
|
|
||||||
WelcomePage::WelcomePage(QWidget *parent)
|
|
||||||
: QWidget(parent)
|
|
||||||
{
|
|
||||||
auto topLayout_ = new QVBoxLayout(this);
|
|
||||||
topLayout_->setSpacing(20);
|
|
||||||
topLayout_->setAlignment(Qt::AlignCenter);
|
|
||||||
|
|
||||||
QFont headingFont;
|
|
||||||
headingFont.setPointSizeF(headingFont.pointSizeF() * 2);
|
|
||||||
QFont subTitleFont;
|
|
||||||
subTitleFont.setPointSizeF(subTitleFont.pointSizeF() * 1.5);
|
|
||||||
|
|
||||||
QIcon icon{QIcon::fromTheme("nheko", QIcon{":/logos/splash.png"})};
|
|
||||||
|
|
||||||
auto logo_ = new QLabel(this);
|
|
||||||
logo_->setPixmap(icon.pixmap(256));
|
|
||||||
logo_->setAlignment(Qt::AlignCenter);
|
|
||||||
|
|
||||||
QString heading(tr("Welcome to nheko! The desktop client for the Matrix protocol."));
|
|
||||||
QString main(tr("Enjoy your stay!"));
|
|
||||||
|
|
||||||
auto intoTxt_ = new TextLabel(heading, this);
|
|
||||||
intoTxt_->setFont(headingFont);
|
|
||||||
intoTxt_->setAlignment(Qt::AlignCenter);
|
|
||||||
|
|
||||||
auto subTitle = new TextLabel(main, this);
|
|
||||||
subTitle->setFont(subTitleFont);
|
|
||||||
subTitle->setAlignment(Qt::AlignCenter);
|
|
||||||
|
|
||||||
topLayout_->addStretch(1);
|
|
||||||
topLayout_->addWidget(logo_);
|
|
||||||
topLayout_->addWidget(intoTxt_);
|
|
||||||
topLayout_->addWidget(subTitle);
|
|
||||||
|
|
||||||
auto btnLayout_ = new QHBoxLayout();
|
|
||||||
btnLayout_->setSpacing(20);
|
|
||||||
btnLayout_->setContentsMargins(0, 20, 0, 20);
|
|
||||||
|
|
||||||
const int fontHeight = QFontMetrics{subTitleFont}.height();
|
|
||||||
const int buttonHeight = fontHeight * 2.5;
|
|
||||||
const int buttonWidth = fontHeight * 8;
|
|
||||||
|
|
||||||
auto registerBtn = new RaisedButton(tr("REGISTER"), this);
|
|
||||||
registerBtn->setMinimumSize(buttonWidth, buttonHeight);
|
|
||||||
registerBtn->setFontSize(subTitleFont.pointSizeF());
|
|
||||||
registerBtn->setCornerRadius(conf::btn::cornerRadius);
|
|
||||||
|
|
||||||
auto loginBtn = new RaisedButton(tr("LOGIN"), this);
|
|
||||||
loginBtn->setMinimumSize(buttonWidth, buttonHeight);
|
|
||||||
loginBtn->setFontSize(subTitleFont.pointSizeF());
|
|
||||||
loginBtn->setCornerRadius(conf::btn::cornerRadius);
|
|
||||||
|
|
||||||
btnLayout_->addStretch(1);
|
|
||||||
btnLayout_->addWidget(registerBtn);
|
|
||||||
btnLayout_->addWidget(loginBtn);
|
|
||||||
btnLayout_->addStretch(1);
|
|
||||||
|
|
||||||
topLayout_->addLayout(btnLayout_);
|
|
||||||
topLayout_->addStretch(1);
|
|
||||||
|
|
||||||
connect(registerBtn, &QPushButton::clicked, this, &WelcomePage::userRegister);
|
|
||||||
connect(loginBtn, &QPushButton::clicked, this, &WelcomePage::userLogin);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
WelcomePage::paintEvent(QPaintEvent *)
|
|
||||||
{
|
|
||||||
QStyleOption opt;
|
|
||||||
opt.initFrom(this);
|
|
||||||
QPainter p(this);
|
|
||||||
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
|
||||||
// SPDX-FileCopyrightText: 2022 Nheko Contributors
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
class WelcomePage : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit WelcomePage(QWidget *parent = nullptr);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void paintEvent(QPaintEvent *) override;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
// Notify that the user wants to login in.
|
|
||||||
void userLogin();
|
|
||||||
|
|
||||||
// Notify that the user wants to register.
|
|
||||||
void userRegister();
|
|
||||||
};
|
|
@ -1,108 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
|
||||||
// SPDX-FileCopyrightText: 2022 Nheko Contributors
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#include "DropShadow.h"
|
|
||||||
|
|
||||||
#include <QLinearGradient>
|
|
||||||
#include <QPainter>
|
|
||||||
|
|
||||||
void
|
|
||||||
DropShadow::draw(QPainter &painter,
|
|
||||||
qint16 margin,
|
|
||||||
qreal radius,
|
|
||||||
QColor start,
|
|
||||||
QColor end,
|
|
||||||
qreal startPosition,
|
|
||||||
qreal endPosition0,
|
|
||||||
qreal endPosition1,
|
|
||||||
qreal width,
|
|
||||||
qreal height)
|
|
||||||
{
|
|
||||||
painter.setPen(Qt::NoPen);
|
|
||||||
|
|
||||||
QLinearGradient gradient;
|
|
||||||
gradient.setColorAt(startPosition, start);
|
|
||||||
gradient.setColorAt(endPosition0, end);
|
|
||||||
|
|
||||||
// Right
|
|
||||||
QPointF right0(width - margin, height / 2);
|
|
||||||
QPointF right1(width, height / 2);
|
|
||||||
gradient.setStart(right0);
|
|
||||||
gradient.setFinalStop(right1);
|
|
||||||
painter.setBrush(QBrush(gradient));
|
|
||||||
// Deprecated in 5.13: painter.drawRoundRect(
|
|
||||||
// QRectF(QPointF(width - margin * radius, margin), QPointF(width, height -
|
|
||||||
// margin)), 0.0, 0.0);
|
|
||||||
painter.drawRoundedRect(
|
|
||||||
QRectF(QPointF(width - margin * radius, margin), QPointF(width, height - margin)), 0.0, 0.0);
|
|
||||||
|
|
||||||
// Left
|
|
||||||
QPointF left0(margin, height / 2);
|
|
||||||
QPointF left1(0, height / 2);
|
|
||||||
gradient.setStart(left0);
|
|
||||||
gradient.setFinalStop(left1);
|
|
||||||
painter.setBrush(QBrush(gradient));
|
|
||||||
painter.drawRoundedRect(
|
|
||||||
QRectF(QPointF(margin * radius, margin), QPointF(0, height - margin)), 0.0, 0.0);
|
|
||||||
|
|
||||||
// Top
|
|
||||||
QPointF top0(width / 2, margin);
|
|
||||||
QPointF top1(width / 2, 0);
|
|
||||||
gradient.setStart(top0);
|
|
||||||
gradient.setFinalStop(top1);
|
|
||||||
painter.setBrush(QBrush(gradient));
|
|
||||||
painter.drawRoundedRect(QRectF(QPointF(width - margin, 0), QPointF(margin, margin)), 0.0, 0.0);
|
|
||||||
|
|
||||||
// Bottom
|
|
||||||
QPointF bottom0(width / 2, height - margin);
|
|
||||||
QPointF bottom1(width / 2, height);
|
|
||||||
gradient.setStart(bottom0);
|
|
||||||
gradient.setFinalStop(bottom1);
|
|
||||||
painter.setBrush(QBrush(gradient));
|
|
||||||
painter.drawRoundedRect(
|
|
||||||
QRectF(QPointF(margin, height - margin), QPointF(width - margin, height)), 0.0, 0.0);
|
|
||||||
|
|
||||||
// BottomRight
|
|
||||||
QPointF bottomright0(width - margin, height - margin);
|
|
||||||
QPointF bottomright1(width, height);
|
|
||||||
gradient.setStart(bottomright0);
|
|
||||||
gradient.setFinalStop(bottomright1);
|
|
||||||
gradient.setColorAt(endPosition1, end);
|
|
||||||
painter.setBrush(QBrush(gradient));
|
|
||||||
painter.drawRoundedRect(QRectF(bottomright0, bottomright1), 0.0, 0.0);
|
|
||||||
|
|
||||||
// BottomLeft
|
|
||||||
QPointF bottomleft0(margin, height - margin);
|
|
||||||
QPointF bottomleft1(0, height);
|
|
||||||
gradient.setStart(bottomleft0);
|
|
||||||
gradient.setFinalStop(bottomleft1);
|
|
||||||
gradient.setColorAt(endPosition1, end);
|
|
||||||
painter.setBrush(QBrush(gradient));
|
|
||||||
painter.drawRoundedRect(QRectF(bottomleft0, bottomleft1), 0.0, 0.0);
|
|
||||||
|
|
||||||
// TopLeft
|
|
||||||
QPointF topleft0(margin, margin);
|
|
||||||
QPointF topleft1(0, 0);
|
|
||||||
gradient.setStart(topleft0);
|
|
||||||
gradient.setFinalStop(topleft1);
|
|
||||||
gradient.setColorAt(endPosition1, end);
|
|
||||||
painter.setBrush(QBrush(gradient));
|
|
||||||
painter.drawRoundedRect(QRectF(topleft0, topleft1), 0.0, 0.0);
|
|
||||||
|
|
||||||
// TopRight
|
|
||||||
QPointF topright0(width - margin, margin);
|
|
||||||
QPointF topright1(width, 0);
|
|
||||||
gradient.setStart(topright0);
|
|
||||||
gradient.setFinalStop(topright1);
|
|
||||||
gradient.setColorAt(endPosition1, end);
|
|
||||||
painter.setBrush(QBrush(gradient));
|
|
||||||
painter.drawRoundedRect(QRectF(topright0, topright1), 0.0, 0.0);
|
|
||||||
|
|
||||||
// Widget
|
|
||||||
painter.setBrush(QBrush(QColor(0xff, 0xff, 0xff)));
|
|
||||||
painter.setRenderHint(QPainter::Antialiasing);
|
|
||||||
painter.drawRoundedRect(
|
|
||||||
QRectF(QPointF(margin, margin), QPointF(width - margin, height - margin)), radius, radius);
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
|
||||||
// SPDX-FileCopyrightText: 2022 Nheko Contributors
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QColor>
|
|
||||||
|
|
||||||
class QPainter;
|
|
||||||
|
|
||||||
class DropShadow
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static void draw(QPainter &painter,
|
|
||||||
qint16 margin,
|
|
||||||
qreal radius,
|
|
||||||
QColor start,
|
|
||||||
QColor end,
|
|
||||||
qreal startPosition,
|
|
||||||
qreal endPosition0,
|
|
||||||
qreal endPosition1,
|
|
||||||
qreal width,
|
|
||||||
qreal height);
|
|
||||||
};
|
|
@ -1,730 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
|
||||||
// SPDX-FileCopyrightText: 2022 Nheko Contributors
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#include <QEventTransition>
|
|
||||||
#include <QFontDatabase>
|
|
||||||
#include <QIcon>
|
|
||||||
#include <QMouseEvent>
|
|
||||||
#include <QPaintEvent>
|
|
||||||
#include <QPainter>
|
|
||||||
#include <QPainterPath>
|
|
||||||
#include <QResizeEvent>
|
|
||||||
#include <QSignalTransition>
|
|
||||||
|
|
||||||
#include "FlatButton.h"
|
|
||||||
#include "Ripple.h"
|
|
||||||
#include "RippleOverlay.h"
|
|
||||||
#include "ThemeManager.h"
|
|
||||||
|
|
||||||
// The ampersand is automatically set in QPushButton or QCheckbx
|
|
||||||
// by KDEPlatformTheme plugin in Qt5.
|
|
||||||
// [https://bugs.kde.org/show_bug.cgi?id=337491]
|
|
||||||
//
|
|
||||||
// A workaroud is to add
|
|
||||||
//
|
|
||||||
// [Development]
|
|
||||||
// AutoCheckAccelerators=false
|
|
||||||
//
|
|
||||||
// to ~/.config/kdeglobals
|
|
||||||
static QString
|
|
||||||
removeKDEAccelerators(QString text)
|
|
||||||
{
|
|
||||||
return text.remove(QChar('&'));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FlatButton::init()
|
|
||||||
{
|
|
||||||
ripple_overlay_ = new RippleOverlay(this);
|
|
||||||
state_machine_ = new FlatButtonStateMachine(this);
|
|
||||||
role_ = ui::Role::Default;
|
|
||||||
ripple_style_ = ui::RippleStyle::PositionedRipple;
|
|
||||||
icon_placement_ = ui::ButtonIconPlacement::LeftIcon;
|
|
||||||
overlay_style_ = ui::OverlayStyle::GrayOverlay;
|
|
||||||
bg_mode_ = Qt::TransparentMode;
|
|
||||||
fixed_ripple_radius_ = 64;
|
|
||||||
corner_radius_ = 3;
|
|
||||||
base_opacity_ = 0.13;
|
|
||||||
font_size_ = 10; // 10.5;
|
|
||||||
use_fixed_ripple_radius_ = false;
|
|
||||||
|
|
||||||
setStyle(&ThemeManager::instance());
|
|
||||||
setAttribute(Qt::WA_Hover);
|
|
||||||
setMouseTracking(true);
|
|
||||||
setCursor(QCursor(Qt::PointingHandCursor));
|
|
||||||
|
|
||||||
QPainterPath path;
|
|
||||||
path.addRoundedRect(rect(), corner_radius_, corner_radius_);
|
|
||||||
|
|
||||||
ripple_overlay_->setClipPath(path);
|
|
||||||
ripple_overlay_->setClipping(true);
|
|
||||||
|
|
||||||
state_machine_->setupProperties();
|
|
||||||
state_machine_->startAnimations();
|
|
||||||
}
|
|
||||||
|
|
||||||
FlatButton::FlatButton(QWidget *parent, ui::ButtonPreset preset)
|
|
||||||
: QPushButton(parent)
|
|
||||||
{
|
|
||||||
init();
|
|
||||||
applyPreset(preset);
|
|
||||||
}
|
|
||||||
|
|
||||||
FlatButton::FlatButton(const QString &text, QWidget *parent, ui::ButtonPreset preset)
|
|
||||||
: QPushButton(text, parent)
|
|
||||||
{
|
|
||||||
init();
|
|
||||||
applyPreset(preset);
|
|
||||||
}
|
|
||||||
|
|
||||||
FlatButton::FlatButton(const QString &text, ui::Role role, QWidget *parent, ui::ButtonPreset preset)
|
|
||||||
: QPushButton(text, parent)
|
|
||||||
{
|
|
||||||
init();
|
|
||||||
applyPreset(preset);
|
|
||||||
setRole(role);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FlatButton::applyPreset(ui::ButtonPreset preset)
|
|
||||||
{
|
|
||||||
switch (preset) {
|
|
||||||
case ui::ButtonPreset::FlatPreset:
|
|
||||||
setOverlayStyle(ui::OverlayStyle::NoOverlay);
|
|
||||||
break;
|
|
||||||
case ui::ButtonPreset::CheckablePreset:
|
|
||||||
setOverlayStyle(ui::OverlayStyle::NoOverlay);
|
|
||||||
setCheckable(true);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FlatButton::setRole(ui::Role role)
|
|
||||||
{
|
|
||||||
role_ = role;
|
|
||||||
state_machine_->setupProperties();
|
|
||||||
}
|
|
||||||
|
|
||||||
ui::Role
|
|
||||||
FlatButton::role() const
|
|
||||||
{
|
|
||||||
return role_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FlatButton::setForegroundColor(const QColor &color)
|
|
||||||
{
|
|
||||||
foreground_color_ = color;
|
|
||||||
emit foregroundColorChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
QColor
|
|
||||||
FlatButton::foregroundColor() const
|
|
||||||
{
|
|
||||||
if (!foreground_color_.isValid()) {
|
|
||||||
if (bg_mode_ == Qt::OpaqueMode) {
|
|
||||||
return ThemeManager::instance().themeColor(QStringLiteral("BrightWhite"));
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (role_) {
|
|
||||||
case ui::Role::Primary:
|
|
||||||
return ThemeManager::instance().themeColor(QStringLiteral("Blue"));
|
|
||||||
case ui::Role::Secondary:
|
|
||||||
return ThemeManager::instance().themeColor(QStringLiteral("Gray"));
|
|
||||||
case ui::Role::Default:
|
|
||||||
default:
|
|
||||||
return ThemeManager::instance().themeColor(QStringLiteral("Black"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return foreground_color_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FlatButton::setBackgroundColor(const QColor &color)
|
|
||||||
{
|
|
||||||
background_color_ = color;
|
|
||||||
emit backgroundColorChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
QColor
|
|
||||||
FlatButton::backgroundColor() const
|
|
||||||
{
|
|
||||||
if (!background_color_.isValid()) {
|
|
||||||
switch (role_) {
|
|
||||||
case ui::Role::Primary:
|
|
||||||
return ThemeManager::instance().themeColor(QStringLiteral("Blue"));
|
|
||||||
case ui::Role::Secondary:
|
|
||||||
return ThemeManager::instance().themeColor(QStringLiteral("Gray"));
|
|
||||||
case ui::Role::Default:
|
|
||||||
default:
|
|
||||||
return ThemeManager::instance().themeColor(QStringLiteral("Black"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return background_color_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FlatButton::setOverlayColor(const QColor &color)
|
|
||||||
{
|
|
||||||
overlay_color_ = color;
|
|
||||||
setOverlayStyle(ui::OverlayStyle::TintedOverlay);
|
|
||||||
emit overlayColorChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
QColor
|
|
||||||
FlatButton::overlayColor() const
|
|
||||||
{
|
|
||||||
if (!overlay_color_.isValid()) {
|
|
||||||
return foregroundColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
return overlay_color_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FlatButton::setDisabledForegroundColor(const QColor &color)
|
|
||||||
{
|
|
||||||
disabled_color_ = color;
|
|
||||||
emit disabledForegroundColorChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
QColor
|
|
||||||
FlatButton::disabledForegroundColor() const
|
|
||||||
{
|
|
||||||
if (!disabled_color_.isValid()) {
|
|
||||||
return ThemeManager::instance().themeColor(QStringLiteral("FadedWhite"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return disabled_color_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FlatButton::setDisabledBackgroundColor(const QColor &color)
|
|
||||||
{
|
|
||||||
disabled_background_color_ = color;
|
|
||||||
emit disabledBackgroundColorChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
QColor
|
|
||||||
FlatButton::disabledBackgroundColor() const
|
|
||||||
{
|
|
||||||
if (!disabled_background_color_.isValid()) {
|
|
||||||
return ThemeManager::instance().themeColor(QStringLiteral("FadedWhite"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return disabled_background_color_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FlatButton::setFontSize(qreal size)
|
|
||||||
{
|
|
||||||
font_size_ = size;
|
|
||||||
|
|
||||||
QFont f(font());
|
|
||||||
f.setPointSizeF(size);
|
|
||||||
setFont(f);
|
|
||||||
|
|
||||||
emit fontSizeChanged();
|
|
||||||
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
qreal
|
|
||||||
FlatButton::fontSize() const
|
|
||||||
{
|
|
||||||
return font_size_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FlatButton::setOverlayStyle(ui::OverlayStyle style)
|
|
||||||
{
|
|
||||||
overlay_style_ = style;
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
ui::OverlayStyle
|
|
||||||
FlatButton::overlayStyle() const
|
|
||||||
{
|
|
||||||
return overlay_style_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FlatButton::setRippleStyle(ui::RippleStyle style)
|
|
||||||
{
|
|
||||||
ripple_style_ = style;
|
|
||||||
}
|
|
||||||
|
|
||||||
ui::RippleStyle
|
|
||||||
FlatButton::rippleStyle() const
|
|
||||||
{
|
|
||||||
return ripple_style_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FlatButton::setIconPlacement(ui::ButtonIconPlacement placement)
|
|
||||||
{
|
|
||||||
icon_placement_ = placement;
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
ui::ButtonIconPlacement
|
|
||||||
FlatButton::iconPlacement() const
|
|
||||||
{
|
|
||||||
return icon_placement_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FlatButton::setCornerRadius(qreal radius)
|
|
||||||
{
|
|
||||||
corner_radius_ = radius;
|
|
||||||
updateClipPath();
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
qreal
|
|
||||||
FlatButton::cornerRadius() const
|
|
||||||
{
|
|
||||||
return corner_radius_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FlatButton::setBackgroundMode(Qt::BGMode mode)
|
|
||||||
{
|
|
||||||
bg_mode_ = mode;
|
|
||||||
state_machine_->setupProperties();
|
|
||||||
}
|
|
||||||
|
|
||||||
Qt::BGMode
|
|
||||||
FlatButton::backgroundMode() const
|
|
||||||
{
|
|
||||||
return bg_mode_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FlatButton::setBaseOpacity(qreal opacity)
|
|
||||||
{
|
|
||||||
base_opacity_ = opacity;
|
|
||||||
state_machine_->setupProperties();
|
|
||||||
}
|
|
||||||
|
|
||||||
qreal
|
|
||||||
FlatButton::baseOpacity() const
|
|
||||||
{
|
|
||||||
return base_opacity_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FlatButton::setCheckable(bool value)
|
|
||||||
{
|
|
||||||
state_machine_->updateCheckedStatus();
|
|
||||||
state_machine_->setCheckedOverlayProgress(0);
|
|
||||||
|
|
||||||
QPushButton::setCheckable(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FlatButton::setHasFixedRippleRadius(bool value)
|
|
||||||
{
|
|
||||||
use_fixed_ripple_radius_ = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
FlatButton::hasFixedRippleRadius() const
|
|
||||||
{
|
|
||||||
return use_fixed_ripple_radius_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FlatButton::setFixedRippleRadius(qreal radius)
|
|
||||||
{
|
|
||||||
fixed_ripple_radius_ = radius;
|
|
||||||
setHasFixedRippleRadius(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
QSize
|
|
||||||
FlatButton::sizeHint() const
|
|
||||||
{
|
|
||||||
ensurePolished();
|
|
||||||
|
|
||||||
QSize label(fontMetrics().size(Qt::TextSingleLine, removeKDEAccelerators(text())));
|
|
||||||
|
|
||||||
int w = 20 + label.width();
|
|
||||||
int h = label.height();
|
|
||||||
|
|
||||||
if (!icon().isNull()) {
|
|
||||||
w += iconSize().width() + FlatButton::IconPadding;
|
|
||||||
h = qMax(h, iconSize().height());
|
|
||||||
}
|
|
||||||
|
|
||||||
return QSize(w, 20 + h);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FlatButton::checkStateSet()
|
|
||||||
{
|
|
||||||
state_machine_->updateCheckedStatus();
|
|
||||||
QPushButton::checkStateSet();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FlatButton::mousePressEvent(QMouseEvent *event)
|
|
||||||
{
|
|
||||||
if (ui::RippleStyle::NoRipple != ripple_style_) {
|
|
||||||
QPoint pos;
|
|
||||||
qreal radiusEndValue;
|
|
||||||
|
|
||||||
if (ui::RippleStyle::CenteredRipple == ripple_style_) {
|
|
||||||
pos = rect().center();
|
|
||||||
} else {
|
|
||||||
pos = event->pos();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (use_fixed_ripple_radius_) {
|
|
||||||
radiusEndValue = fixed_ripple_radius_;
|
|
||||||
} else {
|
|
||||||
radiusEndValue = static_cast<qreal>(width()) / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ripple *ripple = new Ripple(pos);
|
|
||||||
|
|
||||||
ripple->setRadiusEndValue(radiusEndValue);
|
|
||||||
ripple->setOpacityStartValue(0.35);
|
|
||||||
ripple->setColor(foregroundColor());
|
|
||||||
ripple->radiusAnimation()->setDuration(250);
|
|
||||||
ripple->opacityAnimation()->setDuration(250);
|
|
||||||
|
|
||||||
ripple_overlay_->addRipple(ripple);
|
|
||||||
}
|
|
||||||
|
|
||||||
QPushButton::mousePressEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FlatButton::mouseReleaseEvent(QMouseEvent *event)
|
|
||||||
{
|
|
||||||
QPushButton::mouseReleaseEvent(event);
|
|
||||||
state_machine_->updateCheckedStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FlatButton::resizeEvent(QResizeEvent *event)
|
|
||||||
{
|
|
||||||
QPushButton::resizeEvent(event);
|
|
||||||
updateClipPath();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FlatButton::paintEvent(QPaintEvent *event)
|
|
||||||
{
|
|
||||||
Q_UNUSED(event)
|
|
||||||
|
|
||||||
QPainter painter(this);
|
|
||||||
painter.setRenderHint(QPainter::Antialiasing);
|
|
||||||
|
|
||||||
const qreal cr = corner_radius_;
|
|
||||||
|
|
||||||
if (cr > 0) {
|
|
||||||
QPainterPath path;
|
|
||||||
path.addRoundedRect(rect(), cr, cr);
|
|
||||||
|
|
||||||
painter.setClipPath(path);
|
|
||||||
painter.setClipping(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
paintBackground(&painter);
|
|
||||||
|
|
||||||
painter.setOpacity(1);
|
|
||||||
painter.setClipping(false);
|
|
||||||
|
|
||||||
paintForeground(&painter);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FlatButton::paintBackground(QPainter *painter)
|
|
||||||
{
|
|
||||||
const qreal overlayOpacity = state_machine_->overlayOpacity();
|
|
||||||
const qreal checkedProgress = state_machine_->checkedOverlayProgress();
|
|
||||||
|
|
||||||
if (Qt::OpaqueMode == bg_mode_) {
|
|
||||||
QBrush brush;
|
|
||||||
brush.setStyle(Qt::SolidPattern);
|
|
||||||
|
|
||||||
if (isEnabled()) {
|
|
||||||
brush.setColor(backgroundColor());
|
|
||||||
} else {
|
|
||||||
brush.setColor(disabledBackgroundColor());
|
|
||||||
}
|
|
||||||
|
|
||||||
painter->setOpacity(1);
|
|
||||||
painter->setBrush(brush);
|
|
||||||
painter->setPen(Qt::NoPen);
|
|
||||||
painter->drawRect(rect());
|
|
||||||
}
|
|
||||||
|
|
||||||
QBrush brush;
|
|
||||||
brush.setStyle(Qt::SolidPattern);
|
|
||||||
painter->setPen(Qt::NoPen);
|
|
||||||
|
|
||||||
if (!isEnabled()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((ui::OverlayStyle::NoOverlay != overlay_style_) && (overlayOpacity > 0)) {
|
|
||||||
if (ui::OverlayStyle::TintedOverlay == overlay_style_) {
|
|
||||||
brush.setColor(overlayColor());
|
|
||||||
} else {
|
|
||||||
brush.setColor(Qt::gray);
|
|
||||||
}
|
|
||||||
|
|
||||||
painter->setOpacity(overlayOpacity);
|
|
||||||
painter->setBrush(brush);
|
|
||||||
painter->drawRect(rect());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isCheckable() && checkedProgress > 0) {
|
|
||||||
const qreal q = Qt::TransparentMode == bg_mode_ ? 0.45 : 0.7;
|
|
||||||
brush.setColor(foregroundColor());
|
|
||||||
painter->setOpacity(q * checkedProgress);
|
|
||||||
painter->setBrush(brush);
|
|
||||||
QRect r(rect());
|
|
||||||
r.setHeight(static_cast<qreal>(r.height()) * checkedProgress);
|
|
||||||
painter->drawRect(r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define COLOR_INTERPOLATE(CH) (1 - progress) * source.CH() + progress *dest.CH()
|
|
||||||
|
|
||||||
void
|
|
||||||
FlatButton::paintForeground(QPainter *painter)
|
|
||||||
{
|
|
||||||
if (isEnabled()) {
|
|
||||||
painter->setPen(foregroundColor());
|
|
||||||
const qreal progress = state_machine_->checkedOverlayProgress();
|
|
||||||
|
|
||||||
if (isCheckable() && progress > 0) {
|
|
||||||
QColor source = foregroundColor();
|
|
||||||
QColor dest = Qt::TransparentMode == bg_mode_ ? Qt::white : backgroundColor();
|
|
||||||
if (qFuzzyCompare(1, progress)) {
|
|
||||||
painter->setPen(dest);
|
|
||||||
} else {
|
|
||||||
painter->setPen(QColor(COLOR_INTERPOLATE(red),
|
|
||||||
COLOR_INTERPOLATE(green),
|
|
||||||
COLOR_INTERPOLATE(blue),
|
|
||||||
COLOR_INTERPOLATE(alpha)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
painter->setPen(disabledForegroundColor());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (icon().isNull()) {
|
|
||||||
painter->drawText(rect(), Qt::AlignCenter, removeKDEAccelerators(text()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSize textSize(fontMetrics().size(Qt::TextSingleLine, removeKDEAccelerators(text())));
|
|
||||||
QSize base(size() - textSize);
|
|
||||||
|
|
||||||
const int iw = iconSize().width() + IconPadding;
|
|
||||||
QPoint pos((base.width() - iw) / 2, 0);
|
|
||||||
|
|
||||||
QRect textGeometry(pos + QPoint(0, base.height() / 2), textSize);
|
|
||||||
QRect iconGeometry(pos + QPoint(0, (height() - iconSize().height()) / 2), iconSize());
|
|
||||||
|
|
||||||
/* if (ui::LeftIcon == icon_placement_) { */
|
|
||||||
/* textGeometry.translate(iw, 0); */
|
|
||||||
/* } else { */
|
|
||||||
/* iconGeometry.translate(textSize.width() + IconPadding, 0); */
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
painter->drawText(textGeometry, Qt::AlignCenter, removeKDEAccelerators(text()));
|
|
||||||
|
|
||||||
QPixmap pixmap = icon().pixmap(iconSize());
|
|
||||||
QPainter icon(&pixmap);
|
|
||||||
icon.setCompositionMode(QPainter::CompositionMode_SourceIn);
|
|
||||||
icon.fillRect(pixmap.rect(), painter->pen().color());
|
|
||||||
painter->drawPixmap(iconGeometry, pixmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FlatButton::updateClipPath()
|
|
||||||
{
|
|
||||||
const qreal radius = corner_radius_;
|
|
||||||
|
|
||||||
QPainterPath path;
|
|
||||||
path.addRoundedRect(rect(), radius, radius);
|
|
||||||
ripple_overlay_->setClipPath(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
FlatButtonStateMachine::FlatButtonStateMachine(FlatButton *parent)
|
|
||||||
: QStateMachine(parent)
|
|
||||||
, button_(parent)
|
|
||||||
, top_level_state_(new QState(QState::ParallelStates))
|
|
||||||
, config_state_(new QState(top_level_state_))
|
|
||||||
, checkable_state_(new QState(top_level_state_))
|
|
||||||
, checked_state_(new QState(checkable_state_))
|
|
||||||
, unchecked_state_(new QState(checkable_state_))
|
|
||||||
, neutral_state_(new QState(config_state_))
|
|
||||||
, neutral_focused_state_(new QState(config_state_))
|
|
||||||
, hovered_state_(new QState(config_state_))
|
|
||||||
, hovered_focused_state_(new QState(config_state_))
|
|
||||||
, pressed_state_(new QState(config_state_))
|
|
||||||
, overlay_opacity_(0)
|
|
||||||
, checked_overlay_progress_(parent->isChecked() ? 1 : 0)
|
|
||||||
, was_checked_(false)
|
|
||||||
{
|
|
||||||
Q_ASSERT(parent);
|
|
||||||
|
|
||||||
parent->installEventFilter(this);
|
|
||||||
|
|
||||||
config_state_->setInitialState(neutral_state_);
|
|
||||||
addState(top_level_state_);
|
|
||||||
setInitialState(top_level_state_);
|
|
||||||
|
|
||||||
checkable_state_->setInitialState(parent->isChecked() ? checked_state_ : unchecked_state_);
|
|
||||||
QSignalTransition *transition;
|
|
||||||
QPropertyAnimation *animation;
|
|
||||||
|
|
||||||
transition = new QSignalTransition(this, SIGNAL(buttonChecked()));
|
|
||||||
transition->setTargetState(checked_state_);
|
|
||||||
unchecked_state_->addTransition(transition);
|
|
||||||
|
|
||||||
animation = new QPropertyAnimation(this, "checkedOverlayProgress", this);
|
|
||||||
animation->setDuration(200);
|
|
||||||
transition->addAnimation(animation);
|
|
||||||
|
|
||||||
transition = new QSignalTransition(this, SIGNAL(buttonUnchecked()));
|
|
||||||
transition->setTargetState(unchecked_state_);
|
|
||||||
checked_state_->addTransition(transition);
|
|
||||||
|
|
||||||
animation = new QPropertyAnimation(this, "checkedOverlayProgress", this);
|
|
||||||
animation->setDuration(200);
|
|
||||||
transition->addAnimation(animation);
|
|
||||||
|
|
||||||
addTransition(button_, QEvent::FocusIn, neutral_state_, neutral_focused_state_);
|
|
||||||
addTransition(button_, QEvent::FocusOut, neutral_focused_state_, neutral_state_);
|
|
||||||
addTransition(button_, QEvent::Enter, neutral_state_, hovered_state_);
|
|
||||||
addTransition(button_, QEvent::Leave, hovered_state_, neutral_state_);
|
|
||||||
addTransition(button_, QEvent::Enter, neutral_focused_state_, hovered_focused_state_);
|
|
||||||
addTransition(button_, QEvent::Leave, hovered_focused_state_, neutral_focused_state_);
|
|
||||||
addTransition(button_, QEvent::FocusIn, hovered_state_, hovered_focused_state_);
|
|
||||||
addTransition(button_, QEvent::FocusOut, hovered_focused_state_, hovered_state_);
|
|
||||||
addTransition(this, SIGNAL(buttonPressed()), hovered_state_, pressed_state_);
|
|
||||||
addTransition(button_, QEvent::Leave, pressed_state_, neutral_focused_state_);
|
|
||||||
addTransition(button_, QEvent::FocusOut, pressed_state_, hovered_state_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FlatButtonStateMachine::setOverlayOpacity(qreal opacity)
|
|
||||||
{
|
|
||||||
overlay_opacity_ = opacity;
|
|
||||||
emit overlayOpacityChanged();
|
|
||||||
button_->update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FlatButtonStateMachine::setCheckedOverlayProgress(qreal opacity)
|
|
||||||
{
|
|
||||||
checked_overlay_progress_ = opacity;
|
|
||||||
emit checkedOverlayProgressChanged();
|
|
||||||
button_->update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FlatButtonStateMachine::startAnimations()
|
|
||||||
{
|
|
||||||
start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FlatButtonStateMachine::setupProperties()
|
|
||||||
{
|
|
||||||
QColor overlayColor;
|
|
||||||
|
|
||||||
if (Qt::TransparentMode == button_->backgroundMode()) {
|
|
||||||
overlayColor = button_->backgroundColor();
|
|
||||||
} else {
|
|
||||||
overlayColor = button_->foregroundColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
const qreal baseOpacity = button_->baseOpacity();
|
|
||||||
|
|
||||||
neutral_state_->assignProperty(this, "overlayOpacity", 0);
|
|
||||||
neutral_focused_state_->assignProperty(this, "overlayOpacity", 0);
|
|
||||||
hovered_state_->assignProperty(this, "overlayOpacity", baseOpacity);
|
|
||||||
hovered_focused_state_->assignProperty(this, "overlayOpacity", baseOpacity);
|
|
||||||
pressed_state_->assignProperty(this, "overlayOpacity", baseOpacity);
|
|
||||||
checked_state_->assignProperty(this, "checkedOverlayProgress", 1);
|
|
||||||
unchecked_state_->assignProperty(this, "checkedOverlayProgress", 0);
|
|
||||||
|
|
||||||
button_->update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FlatButtonStateMachine::updateCheckedStatus()
|
|
||||||
{
|
|
||||||
const bool checked = button_->isChecked();
|
|
||||||
if (was_checked_ != checked) {
|
|
||||||
was_checked_ = checked;
|
|
||||||
if (checked) {
|
|
||||||
emit buttonChecked();
|
|
||||||
} else {
|
|
||||||
emit buttonUnchecked();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
FlatButtonStateMachine::eventFilter(QObject *watched, QEvent *event)
|
|
||||||
{
|
|
||||||
if (QEvent::FocusIn == event->type()) {
|
|
||||||
QFocusEvent *focusEvent = static_cast<QFocusEvent *>(event);
|
|
||||||
if (focusEvent && Qt::MouseFocusReason == focusEvent->reason()) {
|
|
||||||
emit buttonPressed();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return QStateMachine::eventFilter(watched, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FlatButtonStateMachine::addTransition(QObject *object,
|
|
||||||
const char *signal,
|
|
||||||
QState *fromState,
|
|
||||||
QState *toState)
|
|
||||||
{
|
|
||||||
addTransition(new QSignalTransition(object, signal), fromState, toState);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FlatButtonStateMachine::addTransition(QObject *object,
|
|
||||||
QEvent::Type eventType,
|
|
||||||
QState *fromState,
|
|
||||||
QState *toState)
|
|
||||||
{
|
|
||||||
addTransition(new QEventTransition(object, eventType), fromState, toState);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FlatButtonStateMachine::addTransition(QAbstractTransition *transition,
|
|
||||||
QState *fromState,
|
|
||||||
QState *toState)
|
|
||||||
{
|
|
||||||
transition->setTargetState(toState);
|
|
||||||
|
|
||||||
QPropertyAnimation *animation;
|
|
||||||
|
|
||||||
animation = new QPropertyAnimation(this, "overlayOpacity", this);
|
|
||||||
animation->setDuration(150);
|
|
||||||
transition->addAnimation(animation);
|
|
||||||
|
|
||||||
fromState->addTransition(transition);
|
|
||||||
}
|
|
@ -1,198 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
|
||||||
// SPDX-FileCopyrightText: 2022 Nheko Contributors
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QStateMachine>
|
|
||||||
|
|
||||||
#include "Theme.h"
|
|
||||||
|
|
||||||
class RippleOverlay;
|
|
||||||
class FlatButton;
|
|
||||||
|
|
||||||
class FlatButtonStateMachine : public QStateMachine
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
Q_PROPERTY(
|
|
||||||
qreal overlayOpacity WRITE setOverlayOpacity READ overlayOpacity NOTIFY overlayOpacityChanged)
|
|
||||||
Q_PROPERTY(qreal checkedOverlayProgress WRITE setCheckedOverlayProgress READ
|
|
||||||
checkedOverlayProgress NOTIFY checkedOverlayProgressChanged)
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit FlatButtonStateMachine(FlatButton *parent);
|
|
||||||
|
|
||||||
void setOverlayOpacity(qreal opacity);
|
|
||||||
void setCheckedOverlayProgress(qreal opacity);
|
|
||||||
|
|
||||||
inline qreal overlayOpacity() const;
|
|
||||||
inline qreal checkedOverlayProgress() const;
|
|
||||||
|
|
||||||
void startAnimations();
|
|
||||||
void setupProperties();
|
|
||||||
void updateCheckedStatus();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void buttonPressed();
|
|
||||||
void buttonChecked();
|
|
||||||
void buttonUnchecked();
|
|
||||||
|
|
||||||
void overlayOpacityChanged();
|
|
||||||
void checkedOverlayProgressChanged();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool eventFilter(QObject *watched, QEvent *event) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void addTransition(QObject *object, const char *signal, QState *fromState, QState *toState);
|
|
||||||
void addTransition(QObject *object, QEvent::Type eventType, QState *fromState, QState *toState);
|
|
||||||
void addTransition(QAbstractTransition *transition, QState *fromState, QState *toState);
|
|
||||||
|
|
||||||
FlatButton *const button_;
|
|
||||||
|
|
||||||
QState *const top_level_state_;
|
|
||||||
QState *const config_state_;
|
|
||||||
QState *const checkable_state_;
|
|
||||||
QState *const checked_state_;
|
|
||||||
QState *const unchecked_state_;
|
|
||||||
QState *const neutral_state_;
|
|
||||||
QState *const neutral_focused_state_;
|
|
||||||
QState *const hovered_state_;
|
|
||||||
QState *const hovered_focused_state_;
|
|
||||||
QState *const pressed_state_;
|
|
||||||
|
|
||||||
qreal overlay_opacity_;
|
|
||||||
qreal checked_overlay_progress_;
|
|
||||||
|
|
||||||
bool was_checked_;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline qreal
|
|
||||||
FlatButtonStateMachine::overlayOpacity() const
|
|
||||||
{
|
|
||||||
return overlay_opacity_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline qreal
|
|
||||||
FlatButtonStateMachine::checkedOverlayProgress() const
|
|
||||||
{
|
|
||||||
return checked_overlay_progress_;
|
|
||||||
}
|
|
||||||
|
|
||||||
class FlatButton : public QPushButton
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
Q_PROPERTY(QColor foregroundColor WRITE setForegroundColor READ foregroundColor NOTIFY
|
|
||||||
foregroundColorChanged)
|
|
||||||
Q_PROPERTY(QColor backgroundColor WRITE setBackgroundColor READ backgroundColor NOTIFY
|
|
||||||
backgroundColorChanged)
|
|
||||||
Q_PROPERTY(
|
|
||||||
QColor overlayColor WRITE setOverlayColor READ overlayColor NOTIFY overlayColorChanged)
|
|
||||||
Q_PROPERTY(QColor disabledForegroundColor WRITE setDisabledForegroundColor READ
|
|
||||||
disabledForegroundColor NOTIFY disabledForegroundColorChanged)
|
|
||||||
Q_PROPERTY(QColor disabledBackgroundColor WRITE setDisabledBackgroundColor READ
|
|
||||||
disabledBackgroundColor NOTIFY disabledBackgroundColorChanged)
|
|
||||||
Q_PROPERTY(qreal fontSize WRITE setFontSize READ fontSize NOTIFY fontSizeChanged)
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit FlatButton(QWidget *parent = nullptr,
|
|
||||||
ui::ButtonPreset preset = ui::ButtonPreset::FlatPreset);
|
|
||||||
explicit FlatButton(const QString &text,
|
|
||||||
QWidget *parent = nullptr,
|
|
||||||
ui::ButtonPreset preset = ui::ButtonPreset::FlatPreset);
|
|
||||||
FlatButton(const QString &text,
|
|
||||||
ui::Role role,
|
|
||||||
QWidget *parent = nullptr,
|
|
||||||
ui::ButtonPreset preset = ui::ButtonPreset::FlatPreset);
|
|
||||||
|
|
||||||
void applyPreset(ui::ButtonPreset preset);
|
|
||||||
|
|
||||||
void setBackgroundColor(const QColor &color);
|
|
||||||
void setBackgroundMode(Qt::BGMode mode);
|
|
||||||
void setBaseOpacity(qreal opacity);
|
|
||||||
void setCheckable(bool value);
|
|
||||||
void setCornerRadius(qreal radius);
|
|
||||||
void setDisabledBackgroundColor(const QColor &color);
|
|
||||||
void setDisabledForegroundColor(const QColor &color);
|
|
||||||
void setFixedRippleRadius(qreal radius);
|
|
||||||
void setFontSize(qreal size);
|
|
||||||
void setForegroundColor(const QColor &color);
|
|
||||||
void setHasFixedRippleRadius(bool value);
|
|
||||||
void setIconPlacement(ui::ButtonIconPlacement placement);
|
|
||||||
void setOverlayColor(const QColor &color);
|
|
||||||
void setOverlayStyle(ui::OverlayStyle style);
|
|
||||||
void setRippleStyle(ui::RippleStyle style);
|
|
||||||
void setRole(ui::Role role);
|
|
||||||
|
|
||||||
QColor foregroundColor() const;
|
|
||||||
QColor backgroundColor() const;
|
|
||||||
QColor overlayColor() const;
|
|
||||||
QColor disabledForegroundColor() const;
|
|
||||||
QColor disabledBackgroundColor() const;
|
|
||||||
|
|
||||||
qreal fontSize() const;
|
|
||||||
qreal cornerRadius() const;
|
|
||||||
qreal baseOpacity() const;
|
|
||||||
|
|
||||||
bool hasFixedRippleRadius() const;
|
|
||||||
|
|
||||||
ui::Role role() const;
|
|
||||||
ui::OverlayStyle overlayStyle() const;
|
|
||||||
ui::RippleStyle rippleStyle() const;
|
|
||||||
ui::ButtonIconPlacement iconPlacement() const;
|
|
||||||
|
|
||||||
Qt::BGMode backgroundMode() const;
|
|
||||||
|
|
||||||
QSize sizeHint() const override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
int IconPadding = 0;
|
|
||||||
|
|
||||||
void checkStateSet() override;
|
|
||||||
void mousePressEvent(QMouseEvent *event) override;
|
|
||||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
|
||||||
void resizeEvent(QResizeEvent *event) override;
|
|
||||||
void paintEvent(QPaintEvent *event) override;
|
|
||||||
|
|
||||||
virtual void paintBackground(QPainter *painter);
|
|
||||||
virtual void paintForeground(QPainter *painter);
|
|
||||||
virtual void updateClipPath();
|
|
||||||
|
|
||||||
void init();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void foregroundColorChanged();
|
|
||||||
void backgroundColorChanged();
|
|
||||||
void overlayColorChanged();
|
|
||||||
void disabledForegroundColorChanged();
|
|
||||||
void disabledBackgroundColorChanged();
|
|
||||||
void fontSizeChanged();
|
|
||||||
|
|
||||||
private:
|
|
||||||
RippleOverlay *ripple_overlay_;
|
|
||||||
FlatButtonStateMachine *state_machine_;
|
|
||||||
|
|
||||||
ui::Role role_;
|
|
||||||
ui::RippleStyle ripple_style_;
|
|
||||||
ui::ButtonIconPlacement icon_placement_;
|
|
||||||
ui::OverlayStyle overlay_style_;
|
|
||||||
|
|
||||||
Qt::BGMode bg_mode_;
|
|
||||||
|
|
||||||
QColor background_color_;
|
|
||||||
QColor foreground_color_;
|
|
||||||
QColor overlay_color_;
|
|
||||||
QColor disabled_color_;
|
|
||||||
QColor disabled_background_color_;
|
|
||||||
|
|
||||||
qreal fixed_ripple_radius_;
|
|
||||||
qreal corner_radius_;
|
|
||||||
qreal base_opacity_;
|
|
||||||
qreal font_size_;
|
|
||||||
|
|
||||||
bool use_fixed_ripple_radius_;
|
|
||||||
};
|
|
@ -1,33 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Konstantinos Sideris <siderisk@auth.gr>
|
|
||||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
|
||||||
// SPDX-FileCopyrightText: 2022 Nheko Contributors
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#include "Label.h"
|
|
||||||
#include <QMouseEvent>
|
|
||||||
|
|
||||||
Label::Label(QWidget *parent, Qt::WindowFlags f)
|
|
||||||
: QLabel(parent, f)
|
|
||||||
{}
|
|
||||||
|
|
||||||
Label::Label(const QString &text, QWidget *parent, Qt::WindowFlags f)
|
|
||||||
: QLabel(text, parent, f)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void
|
|
||||||
Label::mousePressEvent(QMouseEvent *e)
|
|
||||||
{
|
|
||||||
pressPosition_ = e->pos();
|
|
||||||
emit pressed(e);
|
|
||||||
QLabel::mousePressEvent(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Label::mouseReleaseEvent(QMouseEvent *e)
|
|
||||||
{
|
|
||||||
emit released(e);
|
|
||||||
if (pressPosition_ == e->pos())
|
|
||||||
emit clicked(e);
|
|
||||||
QLabel::mouseReleaseEvent(e);
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
|
||||||
// SPDX-FileCopyrightText: 2022 Nheko Contributors
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QLabel>
|
|
||||||
|
|
||||||
class Label : public QLabel
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit Label(QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags());
|
|
||||||
explicit Label(const QString &text,
|
|
||||||
QWidget *parent = Q_NULLPTR,
|
|
||||||
Qt::WindowFlags f = Qt::WindowFlags());
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void clicked(QMouseEvent *e);
|
|
||||||
void pressed(QMouseEvent *e);
|
|
||||||
void released(QMouseEvent *e);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void mousePressEvent(QMouseEvent *e) override;
|
|
||||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
|
||||||
|
|
||||||
QPoint pressPosition_;
|
|
||||||
};
|
|
@ -1,84 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
|
||||||
// SPDX-FileCopyrightText: 2022 Nheko Contributors
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#include "LoadingIndicator.h"
|
|
||||||
|
|
||||||
#include <QPaintEvent>
|
|
||||||
#include <QPainter>
|
|
||||||
#include <QTimer>
|
|
||||||
|
|
||||||
LoadingIndicator::LoadingIndicator(QWidget *parent)
|
|
||||||
: QWidget(parent)
|
|
||||||
, interval_(70)
|
|
||||||
, angle_(0)
|
|
||||||
, color_(Qt::black)
|
|
||||||
{
|
|
||||||
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
|
||||||
setFocusPolicy(Qt::NoFocus);
|
|
||||||
|
|
||||||
timer_ = new QTimer(this);
|
|
||||||
connect(timer_, SIGNAL(timeout()), this, SLOT(onTimeout()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
LoadingIndicator::paintEvent(QPaintEvent *e)
|
|
||||||
{
|
|
||||||
Q_UNUSED(e)
|
|
||||||
|
|
||||||
if (!timer_->isActive())
|
|
||||||
return;
|
|
||||||
|
|
||||||
QPainter painter(this);
|
|
||||||
painter.setRenderHint(QPainter::Antialiasing);
|
|
||||||
|
|
||||||
int width = qMin(this->width(), this->height());
|
|
||||||
|
|
||||||
int outerRadius = (width - 4) * 0.5f;
|
|
||||||
int innerRadius = outerRadius * 0.78f;
|
|
||||||
|
|
||||||
int capsuleRadius = (outerRadius - innerRadius) / 2;
|
|
||||||
|
|
||||||
for (int i = 0; i < 8; ++i) {
|
|
||||||
QColor color = color_;
|
|
||||||
|
|
||||||
color.setAlphaF(1.0f - (i / 8.0f));
|
|
||||||
|
|
||||||
painter.setPen(Qt::NoPen);
|
|
||||||
painter.setBrush(color);
|
|
||||||
|
|
||||||
qreal radius = capsuleRadius * (1.0f - (i / 16.0f));
|
|
||||||
|
|
||||||
painter.save();
|
|
||||||
|
|
||||||
painter.translate(rect().center());
|
|
||||||
painter.rotate(angle_ - i * 45.0f);
|
|
||||||
|
|
||||||
QPointF center = QPointF(-capsuleRadius, -innerRadius);
|
|
||||||
painter.drawEllipse(center, radius * 2, radius * 2);
|
|
||||||
|
|
||||||
painter.restore();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
LoadingIndicator::start()
|
|
||||||
{
|
|
||||||
timer_->start(interval_);
|
|
||||||
show();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
LoadingIndicator::stop()
|
|
||||||
{
|
|
||||||
timer_->stop();
|
|
||||||
hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
LoadingIndicator::onTimeout()
|
|
||||||
{
|
|
||||||
angle_ = (angle_ + 45) % 360;
|
|
||||||
repaint();
|
|
||||||
}
|
|
@ -1,49 +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 <QWidget>
|
|
||||||
|
|
||||||
class QPainter;
|
|
||||||
class QTimer;
|
|
||||||
class QPaintEvent;
|
|
||||||
class LoadingIndicator : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
|
|
||||||
|
|
||||||
public:
|
|
||||||
LoadingIndicator(QWidget *parent = nullptr);
|
|
||||||
|
|
||||||
void paintEvent(QPaintEvent *e) override;
|
|
||||||
|
|
||||||
void start();
|
|
||||||
void stop();
|
|
||||||
|
|
||||||
QColor color() { return color_; }
|
|
||||||
void setColor(QColor color)
|
|
||||||
{
|
|
||||||
color_ = color;
|
|
||||||
emit colorChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
int interval() { return interval_; }
|
|
||||||
void setInterval(int interval) { interval_ = interval; }
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void onTimeout();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void colorChanged();
|
|
||||||
|
|
||||||
private:
|
|
||||||
int interval_;
|
|
||||||
int angle_;
|
|
||||||
|
|
||||||
QColor color_;
|
|
||||||
QTimer *timer_;
|
|
||||||
};
|
|
@ -1,26 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
|
||||||
// SPDX-FileCopyrightText: 2022 Nheko Contributors
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QMenu>
|
|
||||||
|
|
||||||
#include "Config.h"
|
|
||||||
|
|
||||||
class Menu : public QMenu
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
Menu(QWidget *parent = nullptr)
|
|
||||||
: QMenu(parent){};
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void leaveEvent(QEvent *e) override
|
|
||||||
{
|
|
||||||
hide();
|
|
||||||
|
|
||||||
QMenu::leaveEvent(e);
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,62 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Konstantinos Sideris <siderisk@auth.gr>
|
|
||||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
|
||||||
// SPDX-FileCopyrightText: 2022 Nheko Contributors
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#include <QPainter>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
|
|
||||||
#include "OverlayModal.h"
|
|
||||||
|
|
||||||
OverlayModal::OverlayModal(QWidget *parent)
|
|
||||||
: OverlayWidget(parent)
|
|
||||||
, color_{QColor(30, 30, 30, 170)}
|
|
||||||
{
|
|
||||||
layout_ = new QVBoxLayout(this);
|
|
||||||
layout_->setSpacing(0);
|
|
||||||
layout_->setContentsMargins(10, 40, 10, 20);
|
|
||||||
setContentAlignment(Qt::AlignCenter);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
OverlayModal::setWidget(QWidget *widget)
|
|
||||||
{
|
|
||||||
// Delete the previous widget
|
|
||||||
if (layout_->count() > 0) {
|
|
||||||
QLayoutItem *item;
|
|
||||||
while ((item = layout_->takeAt(0)) != nullptr) {
|
|
||||||
delete item->widget();
|
|
||||||
delete item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
layout_->addWidget(widget);
|
|
||||||
content_ = widget;
|
|
||||||
content_->setFocus();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
OverlayModal::paintEvent(QPaintEvent *event)
|
|
||||||
{
|
|
||||||
Q_UNUSED(event);
|
|
||||||
|
|
||||||
QPainter painter(this);
|
|
||||||
painter.fillRect(rect(), color_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
OverlayModal::mousePressEvent(QMouseEvent *e)
|
|
||||||
{
|
|
||||||
if (isDismissible_ && content_ && !content_->geometry().contains(e->pos()))
|
|
||||||
hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
OverlayModal::keyPressEvent(QKeyEvent *event)
|
|
||||||
{
|
|
||||||
if (event->key() == Qt::Key_Escape) {
|
|
||||||
event->accept();
|
|
||||||
hide();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Konstantinos Sideris <siderisk@auth.gr>
|
|
||||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
|
||||||
// SPDX-FileCopyrightText: 2022 Nheko Contributors
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QKeyEvent>
|
|
||||||
#include <QMouseEvent>
|
|
||||||
#include <QPaintEvent>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
|
|
||||||
#include "OverlayWidget.h"
|
|
||||||
|
|
||||||
class OverlayModal : public OverlayWidget
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
OverlayModal(QWidget *parent);
|
|
||||||
|
|
||||||
void setColor(QColor color) { color_ = color; }
|
|
||||||
void setDismissible(bool state) { isDismissible_ = state; }
|
|
||||||
|
|
||||||
void setContentAlignment(QFlags<Qt::AlignmentFlag> flag) { layout_->setAlignment(flag); }
|
|
||||||
void setWidget(QWidget *widget);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void paintEvent(QPaintEvent *event) override;
|
|
||||||
void keyPressEvent(QKeyEvent *event) override;
|
|
||||||
void mousePressEvent(QMouseEvent *event) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
QWidget *content_;
|
|
||||||
QVBoxLayout *layout_;
|
|
||||||
|
|
||||||
QColor color_;
|
|
||||||
|
|
||||||
//! Decides whether or not the modal can be removed by clicking into it.
|
|
||||||
bool isDismissible_ = true;
|
|
||||||
};
|
|
154
src/ui/Painter.h
154
src/ui/Painter.h
@ -1,154 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
|
||||||
// SPDX-FileCopyrightText: 2022 Nheko Contributors
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QFontMetrics>
|
|
||||||
#include <QPaintDevice>
|
|
||||||
#include <QPainter>
|
|
||||||
#include <QPainterPath>
|
|
||||||
#include <QtGlobal>
|
|
||||||
|
|
||||||
class Painter : public QPainter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit Painter(QPaintDevice *device)
|
|
||||||
: QPainter(device)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void drawTextLeft(int x, int y, const QString &text)
|
|
||||||
{
|
|
||||||
QFontMetrics m(fontMetrics());
|
|
||||||
drawText(x, y + m.ascent(), text);
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawTextRight(int x, int y, int outerw, const QString &text, int textWidth = -1)
|
|
||||||
{
|
|
||||||
QFontMetrics m(fontMetrics());
|
|
||||||
if (textWidth < 0) {
|
|
||||||
textWidth = m.horizontalAdvance(text);
|
|
||||||
}
|
|
||||||
drawText((outerw - x - textWidth), y + m.ascent(), text);
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawPixmapLeft(int x, int y, const QPixmap &pix, const QRect &from)
|
|
||||||
{
|
|
||||||
drawPixmap(QPoint(x, y), pix, from);
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawPixmapLeft(const QPoint &p, const QPixmap &pix, const QRect &from)
|
|
||||||
{
|
|
||||||
return drawPixmapLeft(p.x(), p.y(), pix, from);
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawPixmapLeft(int x, int y, int w, int h, const QPixmap &pix, const QRect &from)
|
|
||||||
{
|
|
||||||
drawPixmap(QRect(x, y, w, h), pix, from);
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawPixmapLeft(const QRect &r, const QPixmap &pix, const QRect &from)
|
|
||||||
{
|
|
||||||
return drawPixmapLeft(r.x(), r.y(), r.width(), r.height(), pix, from);
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawPixmapLeft(int x, int y, int outerw, const QPixmap &pix)
|
|
||||||
{
|
|
||||||
Q_UNUSED(outerw);
|
|
||||||
drawPixmap(QPoint(x, y), pix);
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawPixmapLeft(const QPoint &p, int outerw, const QPixmap &pix)
|
|
||||||
{
|
|
||||||
return drawPixmapLeft(p.x(), p.y(), outerw, pix);
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawPixmapRight(int x, int y, int outerw, const QPixmap &pix, const QRect &from)
|
|
||||||
{
|
|
||||||
drawPixmap(QPoint((outerw - x - (from.width() / pix.devicePixelRatio())), y), pix, from);
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawPixmapRight(const QPoint &p, int outerw, const QPixmap &pix, const QRect &from)
|
|
||||||
{
|
|
||||||
return drawPixmapRight(p.x(), p.y(), outerw, pix, from);
|
|
||||||
}
|
|
||||||
void
|
|
||||||
drawPixmapRight(int x, int y, int w, int h, int outerw, const QPixmap &pix, const QRect &from)
|
|
||||||
{
|
|
||||||
drawPixmap(QRect((outerw - x - w), y, w, h), pix, from);
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawPixmapRight(const QRect &r, int outerw, const QPixmap &pix, const QRect &from)
|
|
||||||
{
|
|
||||||
return drawPixmapRight(r.x(), r.y(), r.width(), r.height(), outerw, pix, from);
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawPixmapRight(int x, int y, int outerw, const QPixmap &pix)
|
|
||||||
{
|
|
||||||
drawPixmap(QPoint((outerw - x - (pix.width() / pix.devicePixelRatio())), y), pix);
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawPixmapRight(const QPoint &p, int outerw, const QPixmap &pix)
|
|
||||||
{
|
|
||||||
return drawPixmapRight(p.x(), p.y(), outerw, pix);
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawAvatar(const QPixmap &pix, int w, int h, int d)
|
|
||||||
{
|
|
||||||
QPainterPath pp;
|
|
||||||
pp.addEllipse((w - d) / 2, (h - d) / 2, d, d);
|
|
||||||
|
|
||||||
QRect region((w - d) / 2, (h - d) / 2, d, d);
|
|
||||||
|
|
||||||
setClipPath(pp);
|
|
||||||
drawPixmap(region, pix);
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawLetterAvatar(const QString &c,
|
|
||||||
const QColor &penColor,
|
|
||||||
const QColor &brushColor,
|
|
||||||
int w,
|
|
||||||
int h,
|
|
||||||
int d)
|
|
||||||
{
|
|
||||||
QRect region((w - d) / 2, (h - d) / 2, d, d);
|
|
||||||
|
|
||||||
setPen(Qt::NoPen);
|
|
||||||
setBrush(brushColor);
|
|
||||||
|
|
||||||
drawEllipse(region.center(), d / 2, d / 2);
|
|
||||||
|
|
||||||
setBrush(Qt::NoBrush);
|
|
||||||
drawEllipse(region.center(), d / 2, d / 2);
|
|
||||||
|
|
||||||
setPen(penColor);
|
|
||||||
drawText(region.translated(0, -1), Qt::AlignCenter, c);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class PainterHighQualityEnabler
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PainterHighQualityEnabler(Painter &p)
|
|
||||||
: _painter(p)
|
|
||||||
{
|
|
||||||
hints_ =
|
|
||||||
QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::TextAntialiasing;
|
|
||||||
|
|
||||||
_painter.setRenderHints(hints_);
|
|
||||||
}
|
|
||||||
|
|
||||||
~PainterHighQualityEnabler()
|
|
||||||
{
|
|
||||||
if (hints_)
|
|
||||||
_painter.setRenderHints(hints_, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
PainterHighQualityEnabler(const PainterHighQualityEnabler &other) = delete;
|
|
||||||
PainterHighQualityEnabler &operator=(const PainterHighQualityEnabler &other) = delete;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Painter &_painter;
|
|
||||||
QPainter::RenderHints hints_ = {};
|
|
||||||
};
|
|
@ -1,92 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
|
||||||
// SPDX-FileCopyrightText: 2022 Nheko Contributors
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#include <QEventTransition>
|
|
||||||
#include <QPropertyAnimation>
|
|
||||||
|
|
||||||
#include "RaisedButton.h"
|
|
||||||
|
|
||||||
void
|
|
||||||
RaisedButton::init()
|
|
||||||
{
|
|
||||||
shadow_state_machine_ = new QStateMachine(this);
|
|
||||||
normal_state_ = new QState;
|
|
||||||
pressed_state_ = new QState;
|
|
||||||
effect_ = new QGraphicsDropShadowEffect;
|
|
||||||
|
|
||||||
effect_->setBlurRadius(7);
|
|
||||||
effect_->setOffset(QPointF(0, 2));
|
|
||||||
effect_->setColor(QColor(0, 0, 0, 75));
|
|
||||||
|
|
||||||
setBackgroundMode(Qt::OpaqueMode);
|
|
||||||
setMinimumHeight(42);
|
|
||||||
setGraphicsEffect(effect_);
|
|
||||||
setBaseOpacity(0.3);
|
|
||||||
|
|
||||||
shadow_state_machine_->addState(normal_state_);
|
|
||||||
shadow_state_machine_->addState(pressed_state_);
|
|
||||||
|
|
||||||
normal_state_->assignProperty(effect_, "offset", QPointF(0, 2));
|
|
||||||
normal_state_->assignProperty(effect_, "blurRadius", 7);
|
|
||||||
|
|
||||||
pressed_state_->assignProperty(effect_, "offset", QPointF(0, 5));
|
|
||||||
pressed_state_->assignProperty(effect_, "blurRadius", 29);
|
|
||||||
|
|
||||||
QAbstractTransition *transition;
|
|
||||||
|
|
||||||
transition = new QEventTransition(this, QEvent::MouseButtonPress);
|
|
||||||
transition->setTargetState(pressed_state_);
|
|
||||||
normal_state_->addTransition(transition);
|
|
||||||
|
|
||||||
transition = new QEventTransition(this, QEvent::MouseButtonDblClick);
|
|
||||||
transition->setTargetState(pressed_state_);
|
|
||||||
normal_state_->addTransition(transition);
|
|
||||||
|
|
||||||
transition = new QEventTransition(this, QEvent::MouseButtonRelease);
|
|
||||||
transition->setTargetState(normal_state_);
|
|
||||||
pressed_state_->addTransition(transition);
|
|
||||||
|
|
||||||
QPropertyAnimation *animation;
|
|
||||||
|
|
||||||
animation = new QPropertyAnimation(effect_, "offset", this);
|
|
||||||
animation->setDuration(100);
|
|
||||||
shadow_state_machine_->addDefaultAnimation(animation);
|
|
||||||
|
|
||||||
animation = new QPropertyAnimation(effect_, "blurRadius", this);
|
|
||||||
animation->setDuration(100);
|
|
||||||
shadow_state_machine_->addDefaultAnimation(animation);
|
|
||||||
|
|
||||||
shadow_state_machine_->setInitialState(normal_state_);
|
|
||||||
shadow_state_machine_->start();
|
|
||||||
}
|
|
||||||
|
|
||||||
RaisedButton::RaisedButton(QWidget *parent)
|
|
||||||
: FlatButton(parent)
|
|
||||||
{
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
RaisedButton::RaisedButton(const QString &text, QWidget *parent)
|
|
||||||
: FlatButton(parent)
|
|
||||||
{
|
|
||||||
init();
|
|
||||||
setText(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
RaisedButton::event(QEvent *event)
|
|
||||||
{
|
|
||||||
if (QEvent::EnabledChange == event->type()) {
|
|
||||||
if (isEnabled()) {
|
|
||||||
shadow_state_machine_->start();
|
|
||||||
effect_->setEnabled(true);
|
|
||||||
} else {
|
|
||||||
shadow_state_machine_->stop();
|
|
||||||
effect_->setEnabled(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return FlatButton::event(event);
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
|
||||||
// SPDX-FileCopyrightText: 2022 Nheko Contributors
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QGraphicsDropShadowEffect>
|
|
||||||
#include <QState>
|
|
||||||
#include <QStateMachine>
|
|
||||||
|
|
||||||
#include "FlatButton.h"
|
|
||||||
|
|
||||||
class RaisedButton : public FlatButton
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit RaisedButton(QWidget *parent = nullptr);
|
|
||||||
explicit RaisedButton(const QString &text, QWidget *parent = nullptr);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool event(QEvent *event) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void init();
|
|
||||||
|
|
||||||
QStateMachine *shadow_state_machine_;
|
|
||||||
QState *normal_state_;
|
|
||||||
QState *pressed_state_;
|
|
||||||
QGraphicsDropShadowEffect *effect_;
|
|
||||||
};
|
|
@ -1,116 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
|
||||||
// SPDX-FileCopyrightText: 2022 Nheko Contributors
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#include "Ripple.h"
|
|
||||||
#include "RippleOverlay.h"
|
|
||||||
|
|
||||||
Ripple::Ripple(const QPoint ¢er, QObject *parent)
|
|
||||||
: QParallelAnimationGroup(parent)
|
|
||||||
, overlay_(nullptr)
|
|
||||||
, radius_anim_(animate("radius"))
|
|
||||||
, opacity_anim_(animate("opacity"))
|
|
||||||
, radius_(0)
|
|
||||||
, opacity_(0)
|
|
||||||
, center_(center)
|
|
||||||
{
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ripple::Ripple(const QPoint ¢er, RippleOverlay *overlay, QObject *parent)
|
|
||||||
: QParallelAnimationGroup(parent)
|
|
||||||
, overlay_(overlay)
|
|
||||||
, radius_anim_(animate("radius"))
|
|
||||||
, opacity_anim_(animate("opacity"))
|
|
||||||
, radius_(0)
|
|
||||||
, opacity_(0)
|
|
||||||
, center_(center)
|
|
||||||
{
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Ripple::setRadius(qreal radius)
|
|
||||||
{
|
|
||||||
Q_ASSERT(overlay_);
|
|
||||||
|
|
||||||
if (radius_ == radius)
|
|
||||||
return;
|
|
||||||
|
|
||||||
radius_ = radius;
|
|
||||||
overlay_->update();
|
|
||||||
|
|
||||||
emit radiusChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Ripple::setOpacity(qreal opacity)
|
|
||||||
{
|
|
||||||
Q_ASSERT(overlay_);
|
|
||||||
|
|
||||||
if (opacity_ == opacity)
|
|
||||||
return;
|
|
||||||
|
|
||||||
opacity_ = opacity;
|
|
||||||
overlay_->update();
|
|
||||||
|
|
||||||
emit opacityChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Ripple::setColor(const QColor &color)
|
|
||||||
{
|
|
||||||
if (brush_.color() == color)
|
|
||||||
return;
|
|
||||||
|
|
||||||
brush_.setColor(color);
|
|
||||||
|
|
||||||
if (overlay_)
|
|
||||||
overlay_->update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Ripple::setBrush(const QBrush &brush)
|
|
||||||
{
|
|
||||||
brush_ = brush;
|
|
||||||
|
|
||||||
if (overlay_)
|
|
||||||
overlay_->update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Ripple::destroy()
|
|
||||||
{
|
|
||||||
Q_ASSERT(overlay_);
|
|
||||||
|
|
||||||
overlay_->removeRipple(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
QPropertyAnimation *
|
|
||||||
Ripple::animate(const QByteArray &property, const QEasingCurve &easing, int duration)
|
|
||||||
{
|
|
||||||
QPropertyAnimation *animation = new QPropertyAnimation;
|
|
||||||
animation->setTargetObject(this);
|
|
||||||
animation->setPropertyName(property);
|
|
||||||
animation->setEasingCurve(easing);
|
|
||||||
animation->setDuration(duration);
|
|
||||||
|
|
||||||
addAnimation(animation);
|
|
||||||
|
|
||||||
return animation;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Ripple::init()
|
|
||||||
{
|
|
||||||
setOpacityStartValue(0.5);
|
|
||||||
setOpacityEndValue(0);
|
|
||||||
setRadiusStartValue(0);
|
|
||||||
setRadiusEndValue(300);
|
|
||||||
|
|
||||||
brush_.setColor(Qt::black);
|
|
||||||
brush_.setStyle(Qt::SolidPattern);
|
|
||||||
|
|
||||||
connect(this, SIGNAL(finished()), this, SLOT(destroy()));
|
|
||||||
}
|
|
154
src/ui/Ripple.h
154
src/ui/Ripple.h
@ -1,154 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
|
||||||
// SPDX-FileCopyrightText: 2022 Nheko Contributors
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QBrush>
|
|
||||||
#include <QEasingCurve>
|
|
||||||
#include <QParallelAnimationGroup>
|
|
||||||
#include <QPoint>
|
|
||||||
#include <QPropertyAnimation>
|
|
||||||
|
|
||||||
class RippleOverlay;
|
|
||||||
|
|
||||||
class Ripple : public QParallelAnimationGroup
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
Q_PROPERTY(qreal radius WRITE setRadius READ radius NOTIFY radiusChanged)
|
|
||||||
Q_PROPERTY(qreal opacity WRITE setOpacity READ opacity NOTIFY opacityChanged)
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit Ripple(const QPoint ¢er, QObject *parent = nullptr);
|
|
||||||
Ripple(const QPoint ¢er, RippleOverlay *overlay, QObject *parent = nullptr);
|
|
||||||
|
|
||||||
inline void setOverlay(RippleOverlay *overlay);
|
|
||||||
|
|
||||||
void setRadius(qreal radius);
|
|
||||||
void setOpacity(qreal opacity);
|
|
||||||
void setColor(const QColor &color);
|
|
||||||
void setBrush(const QBrush &brush);
|
|
||||||
|
|
||||||
inline qreal radius() const;
|
|
||||||
inline qreal opacity() const;
|
|
||||||
inline QColor color() const;
|
|
||||||
inline QBrush brush() const;
|
|
||||||
inline QPoint center() const;
|
|
||||||
|
|
||||||
inline QPropertyAnimation *radiusAnimation() const;
|
|
||||||
inline QPropertyAnimation *opacityAnimation() const;
|
|
||||||
|
|
||||||
inline void setOpacityStartValue(qreal value);
|
|
||||||
inline void setOpacityEndValue(qreal value);
|
|
||||||
inline void setRadiusStartValue(qreal value);
|
|
||||||
inline void setRadiusEndValue(qreal value);
|
|
||||||
inline void setDuration(int msecs);
|
|
||||||
|
|
||||||
protected slots:
|
|
||||||
void destroy();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void radiusChanged();
|
|
||||||
void opacityChanged();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Q_DISABLE_COPY(Ripple)
|
|
||||||
|
|
||||||
QPropertyAnimation *animate(const QByteArray &property,
|
|
||||||
const QEasingCurve &easing = QEasingCurve::OutQuad,
|
|
||||||
int duration = 800);
|
|
||||||
|
|
||||||
void init();
|
|
||||||
|
|
||||||
RippleOverlay *overlay_;
|
|
||||||
|
|
||||||
QPropertyAnimation *const radius_anim_;
|
|
||||||
QPropertyAnimation *const opacity_anim_;
|
|
||||||
|
|
||||||
qreal radius_;
|
|
||||||
qreal opacity_;
|
|
||||||
|
|
||||||
QPoint center_;
|
|
||||||
QBrush brush_;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline void
|
|
||||||
Ripple::setOverlay(RippleOverlay *overlay)
|
|
||||||
{
|
|
||||||
overlay_ = overlay;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline qreal
|
|
||||||
Ripple::radius() const
|
|
||||||
{
|
|
||||||
return radius_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline qreal
|
|
||||||
Ripple::opacity() const
|
|
||||||
{
|
|
||||||
return opacity_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline QColor
|
|
||||||
Ripple::color() const
|
|
||||||
{
|
|
||||||
return brush_.color();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline QBrush
|
|
||||||
Ripple::brush() const
|
|
||||||
{
|
|
||||||
return brush_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline QPoint
|
|
||||||
Ripple::center() const
|
|
||||||
{
|
|
||||||
return center_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline QPropertyAnimation *
|
|
||||||
Ripple::radiusAnimation() const
|
|
||||||
{
|
|
||||||
return radius_anim_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline QPropertyAnimation *
|
|
||||||
Ripple::opacityAnimation() const
|
|
||||||
{
|
|
||||||
return opacity_anim_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void
|
|
||||||
Ripple::setOpacityStartValue(qreal value)
|
|
||||||
{
|
|
||||||
opacity_anim_->setStartValue(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void
|
|
||||||
Ripple::setOpacityEndValue(qreal value)
|
|
||||||
{
|
|
||||||
opacity_anim_->setEndValue(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void
|
|
||||||
Ripple::setRadiusStartValue(qreal value)
|
|
||||||
{
|
|
||||||
radius_anim_->setStartValue(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void
|
|
||||||
Ripple::setRadiusEndValue(qreal value)
|
|
||||||
{
|
|
||||||
radius_anim_->setEndValue(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void
|
|
||||||
Ripple::setDuration(int msecs)
|
|
||||||
{
|
|
||||||
radius_anim_->setDuration(msecs);
|
|
||||||
opacity_anim_->setDuration(msecs);
|
|
||||||
}
|
|
@ -1,67 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
|
||||||
// SPDX-FileCopyrightText: 2022 Nheko Contributors
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#include <QPainter>
|
|
||||||
|
|
||||||
#include "Ripple.h"
|
|
||||||
#include "RippleOverlay.h"
|
|
||||||
|
|
||||||
RippleOverlay::RippleOverlay(QWidget *parent)
|
|
||||||
: OverlayWidget(parent)
|
|
||||||
, use_clip_(false)
|
|
||||||
{
|
|
||||||
setAttribute(Qt::WA_TransparentForMouseEvents);
|
|
||||||
setAttribute(Qt::WA_NoSystemBackground);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
RippleOverlay::addRipple(Ripple *ripple)
|
|
||||||
{
|
|
||||||
ripple->setOverlay(this);
|
|
||||||
ripples_.push_back(ripple);
|
|
||||||
ripple->start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
RippleOverlay::addRipple(const QPoint &position, qreal radius)
|
|
||||||
{
|
|
||||||
Ripple *ripple = new Ripple(position);
|
|
||||||
ripple->setRadiusEndValue(radius);
|
|
||||||
addRipple(ripple);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
RippleOverlay::removeRipple(Ripple *ripple)
|
|
||||||
{
|
|
||||||
if (ripples_.removeOne(ripple))
|
|
||||||
delete ripple;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
RippleOverlay::paintEvent(QPaintEvent *event)
|
|
||||||
{
|
|
||||||
Q_UNUSED(event)
|
|
||||||
|
|
||||||
QPainter painter(this);
|
|
||||||
painter.setRenderHint(QPainter::Antialiasing);
|
|
||||||
painter.setPen(Qt::NoPen);
|
|
||||||
|
|
||||||
if (use_clip_)
|
|
||||||
painter.setClipPath(clip_path_);
|
|
||||||
|
|
||||||
for (auto it = ripples_.constBegin(); it != ripples_.constEnd(); ++it)
|
|
||||||
paintRipple(&painter, *it);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
RippleOverlay::paintRipple(QPainter *painter, Ripple *ripple)
|
|
||||||
{
|
|
||||||
const qreal radius = ripple->radius();
|
|
||||||
const QPointF center = ripple->center();
|
|
||||||
|
|
||||||
painter->setOpacity(ripple->opacity());
|
|
||||||
painter->setBrush(ripple->brush());
|
|
||||||
painter->drawEllipse(center, radius, radius);
|
|
||||||
}
|
|
@ -1,62 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
|
||||||
// SPDX-FileCopyrightText: 2022 Nheko Contributors
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QPainterPath>
|
|
||||||
|
|
||||||
#include "OverlayWidget.h"
|
|
||||||
|
|
||||||
class Ripple;
|
|
||||||
|
|
||||||
class RippleOverlay : public OverlayWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit RippleOverlay(QWidget *parent = nullptr);
|
|
||||||
|
|
||||||
void addRipple(Ripple *ripple);
|
|
||||||
void addRipple(const QPoint &position, qreal radius = 300);
|
|
||||||
|
|
||||||
void removeRipple(Ripple *ripple);
|
|
||||||
|
|
||||||
inline void setClipping(bool enable);
|
|
||||||
inline bool hasClipping() const;
|
|
||||||
|
|
||||||
inline void setClipPath(const QPainterPath &path);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Q_DISABLE_COPY(RippleOverlay)
|
|
||||||
|
|
||||||
void paintRipple(QPainter *painter, Ripple *ripple);
|
|
||||||
|
|
||||||
QList<Ripple *> ripples_;
|
|
||||||
QPainterPath clip_path_;
|
|
||||||
bool use_clip_;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline void
|
|
||||||
RippleOverlay::setClipping(bool enable)
|
|
||||||
{
|
|
||||||
use_clip_ = enable;
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool
|
|
||||||
RippleOverlay::hasClipping() const
|
|
||||||
{
|
|
||||||
return use_clip_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void
|
|
||||||
RippleOverlay::setClipPath(const QPainterPath &path)
|
|
||||||
{
|
|
||||||
clip_path_ = path;
|
|
||||||
update();
|
|
||||||
}
|
|
@ -1,136 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
|
||||||
// SPDX-FileCopyrightText: 2022 Nheko Contributors
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#include <QPainter>
|
|
||||||
|
|
||||||
#include "SnackBar.h"
|
|
||||||
|
|
||||||
constexpr int STARTING_OFFSET = 1;
|
|
||||||
constexpr int BOX_PADDING = 10;
|
|
||||||
constexpr double MIN_WIDTH = 400.0;
|
|
||||||
constexpr double MIN_WIDTH_PERCENTAGE = 0.3;
|
|
||||||
|
|
||||||
SnackBar::SnackBar(QWidget *parent)
|
|
||||||
: OverlayWidget(parent)
|
|
||||||
, offset_anim(this, "offset", this)
|
|
||||||
{
|
|
||||||
QFont font;
|
|
||||||
font.setPointSizeF(font.pointSizeF() * 1.2);
|
|
||||||
font.setWeight(QFont::Weight::Thin);
|
|
||||||
setFont(font);
|
|
||||||
|
|
||||||
boxHeight_ = QFontMetrics(font).height() * 2;
|
|
||||||
offset_ = STARTING_OFFSET;
|
|
||||||
position_ = SnackBarPosition::Top;
|
|
||||||
|
|
||||||
hideTimer_.setSingleShot(true);
|
|
||||||
|
|
||||||
offset_anim.setStartValue(1.0);
|
|
||||||
offset_anim.setEndValue(0.0);
|
|
||||||
offset_anim.setDuration(100);
|
|
||||||
offset_anim.setEasingCurve(QEasingCurve::OutCubic);
|
|
||||||
|
|
||||||
connect(this, &SnackBar::offsetChanged, this, [this]() mutable { repaint(); });
|
|
||||||
connect(
|
|
||||||
&offset_anim, &QPropertyAnimation::finished, this, [this]() { hideTimer_.start(10000); });
|
|
||||||
|
|
||||||
connect(&hideTimer_, SIGNAL(timeout()), this, SLOT(hideMessage()));
|
|
||||||
|
|
||||||
hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
SnackBar::start()
|
|
||||||
{
|
|
||||||
if (messages_.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
show();
|
|
||||||
raise();
|
|
||||||
|
|
||||||
offset_anim.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
SnackBar::hideMessage()
|
|
||||||
{
|
|
||||||
stopTimers();
|
|
||||||
hide();
|
|
||||||
|
|
||||||
if (!messages_.empty())
|
|
||||||
// Moving on to the next message.
|
|
||||||
messages_.pop_front();
|
|
||||||
|
|
||||||
// Resetting the starting position of the widget.
|
|
||||||
offset_ = STARTING_OFFSET;
|
|
||||||
|
|
||||||
if (!messages_.empty())
|
|
||||||
start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
SnackBar::stopTimers()
|
|
||||||
{
|
|
||||||
hideTimer_.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
SnackBar::showMessage(const QString &msg)
|
|
||||||
{
|
|
||||||
messages_.push_back(msg);
|
|
||||||
|
|
||||||
// There is already an active message.
|
|
||||||
if (isVisible())
|
|
||||||
return;
|
|
||||||
|
|
||||||
start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
SnackBar::mousePressEvent(QMouseEvent *)
|
|
||||||
{
|
|
||||||
hideMessage();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
SnackBar::paintEvent(QPaintEvent *event)
|
|
||||||
{
|
|
||||||
Q_UNUSED(event)
|
|
||||||
|
|
||||||
if (messages_.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto message_ = messages_.front();
|
|
||||||
|
|
||||||
QPainter p(this);
|
|
||||||
p.setRenderHint(QPainter::Antialiasing);
|
|
||||||
|
|
||||||
QBrush brush;
|
|
||||||
brush.setStyle(Qt::SolidPattern);
|
|
||||||
brush.setColor(bgColor_);
|
|
||||||
p.setBrush(brush);
|
|
||||||
|
|
||||||
QRect r(0, 0, std::max(MIN_WIDTH, width() * MIN_WIDTH_PERCENTAGE), boxHeight_);
|
|
||||||
|
|
||||||
p.setPen(Qt::white);
|
|
||||||
QRect br = p.boundingRect(r, Qt::AlignHCenter | Qt::AlignTop | Qt::TextWordWrap, message_);
|
|
||||||
|
|
||||||
p.setPen(Qt::NoPen);
|
|
||||||
r = br.united(r).adjusted(-BOX_PADDING, -BOX_PADDING, BOX_PADDING, BOX_PADDING);
|
|
||||||
|
|
||||||
const qreal s = 1 - offset_;
|
|
||||||
|
|
||||||
if (position_ == SnackBarPosition::Bottom)
|
|
||||||
p.translate((width() - (r.width() - 2 * BOX_PADDING)) / 2,
|
|
||||||
height() - BOX_PADDING - s * (r.height()));
|
|
||||||
else
|
|
||||||
p.translate((width() - (r.width() - 2 * BOX_PADDING)) / 2,
|
|
||||||
s * (r.height()) - 2 * BOX_PADDING);
|
|
||||||
|
|
||||||
br.moveCenter(r.center());
|
|
||||||
p.drawRoundedRect(r.adjusted(0, 0, 0, 4), 4, 4);
|
|
||||||
p.setPen(textColor_);
|
|
||||||
p.drawText(br, Qt::AlignHCenter | Qt::AlignTop | Qt::TextWordWrap, message_);
|
|
||||||
}
|
|
@ -1,98 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
|
||||||
// SPDX-FileCopyrightText: 2022 Nheko Contributors
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QCoreApplication>
|
|
||||||
#include <QPaintEvent>
|
|
||||||
#include <QPropertyAnimation>
|
|
||||||
#include <QTimer>
|
|
||||||
#include <deque>
|
|
||||||
|
|
||||||
#include "OverlayWidget.h"
|
|
||||||
|
|
||||||
enum class SnackBarPosition
|
|
||||||
{
|
|
||||||
Bottom,
|
|
||||||
Top,
|
|
||||||
};
|
|
||||||
|
|
||||||
class SnackBar : public OverlayWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
Q_PROPERTY(
|
|
||||||
QColor bgColor READ backgroundColor WRITE setBackgroundColor NOTIFY backgroundColorChanged)
|
|
||||||
Q_PROPERTY(QColor textColor READ textColor WRITE setTextColor NOTIFY textColorChanged)
|
|
||||||
Q_PROPERTY(double offset READ offset WRITE setOffset NOTIFY offsetChanged)
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit SnackBar(QWidget *parent);
|
|
||||||
|
|
||||||
QColor backgroundColor() const { return bgColor_; }
|
|
||||||
void setBackgroundColor(const QColor &color)
|
|
||||||
{
|
|
||||||
bgColor_ = color;
|
|
||||||
update();
|
|
||||||
emit backgroundColorChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
QColor textColor() const { return textColor_; }
|
|
||||||
void setTextColor(const QColor &color)
|
|
||||||
{
|
|
||||||
textColor_ = color;
|
|
||||||
update();
|
|
||||||
emit textColorChanged();
|
|
||||||
}
|
|
||||||
void setPosition(SnackBarPosition pos)
|
|
||||||
{
|
|
||||||
position_ = pos;
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
double offset() { return offset_; }
|
|
||||||
void setOffset(double offset)
|
|
||||||
{
|
|
||||||
if (offset != offset_) {
|
|
||||||
offset_ = offset;
|
|
||||||
emit offsetChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void showMessage(const QString &msg);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void offsetChanged();
|
|
||||||
void backgroundColorChanged();
|
|
||||||
void textColorChanged();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void paintEvent(QPaintEvent *event) override;
|
|
||||||
void mousePressEvent(QMouseEvent *event) override;
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void hideMessage();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void stopTimers();
|
|
||||||
void start();
|
|
||||||
|
|
||||||
QColor bgColor_;
|
|
||||||
QColor textColor_;
|
|
||||||
|
|
||||||
qreal bgOpacity_;
|
|
||||||
qreal offset_;
|
|
||||||
|
|
||||||
std::deque<QString> messages_;
|
|
||||||
|
|
||||||
QTimer hideTimer_;
|
|
||||||
|
|
||||||
double boxHeight_;
|
|
||||||
|
|
||||||
QPropertyAnimation offset_anim;
|
|
||||||
|
|
||||||
SnackBarPosition position_;
|
|
||||||
};
|
|
@ -1,123 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
|
||||||
// SPDX-FileCopyrightText: 2022 Nheko Contributors
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#include "ui/TextLabel.h"
|
|
||||||
|
|
||||||
#include <QAbstractTextDocumentLayout>
|
|
||||||
#include <QDesktopServices>
|
|
||||||
#include <QEvent>
|
|
||||||
#include <QWheelEvent>
|
|
||||||
|
|
||||||
#include "Utils.h"
|
|
||||||
|
|
||||||
bool
|
|
||||||
ContextMenuFilter::eventFilter(QObject *obj, QEvent *event)
|
|
||||||
{
|
|
||||||
if (event->type() == QEvent::MouseButtonPress) {
|
|
||||||
emit contextMenuIsOpening();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return QObject::eventFilter(obj, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
TextLabel::TextLabel(QWidget *parent)
|
|
||||||
: TextLabel(QString(), parent)
|
|
||||||
{}
|
|
||||||
|
|
||||||
TextLabel::TextLabel(const QString &text, QWidget *parent)
|
|
||||||
: QTextBrowser(parent)
|
|
||||||
{
|
|
||||||
document()->setDefaultStyleSheet(QStringLiteral("a {color: %1; }").arg(utils::linkColor()));
|
|
||||||
|
|
||||||
setText(text);
|
|
||||||
setOpenExternalLinks(true);
|
|
||||||
|
|
||||||
// Make it look and feel like an ordinary label.
|
|
||||||
setReadOnly(true);
|
|
||||||
setFrameStyle(QFrame::NoFrame);
|
|
||||||
QPalette pal = palette();
|
|
||||||
pal.setColor(QPalette::Base, Qt::transparent);
|
|
||||||
setPalette(pal);
|
|
||||||
|
|
||||||
// Wrap anywhere but prefer words, adjust minimum height on the fly.
|
|
||||||
setLineWrapMode(QTextEdit::WidgetWidth);
|
|
||||||
setWordWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
|
|
||||||
connect(document()->documentLayout(),
|
|
||||||
&QAbstractTextDocumentLayout::documentSizeChanged,
|
|
||||||
this,
|
|
||||||
&TextLabel::adjustHeight);
|
|
||||||
document()->setDocumentMargin(0);
|
|
||||||
|
|
||||||
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
|
||||||
setFixedHeight(0);
|
|
||||||
|
|
||||||
connect(this, &TextLabel::linkActivated, this, &TextLabel::handleLinkActivation);
|
|
||||||
|
|
||||||
auto filter = new ContextMenuFilter(this);
|
|
||||||
installEventFilter(filter);
|
|
||||||
connect(filter, &ContextMenuFilter::contextMenuIsOpening, this, [this]() {
|
|
||||||
contextMenuRequested_ = true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TextLabel::focusOutEvent(QFocusEvent *e)
|
|
||||||
{
|
|
||||||
QTextBrowser::focusOutEvent(e);
|
|
||||||
|
|
||||||
// We keep the selection available for the context menu.
|
|
||||||
if (contextMenuRequested_) {
|
|
||||||
contextMenuRequested_ = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QTextCursor cursor = textCursor();
|
|
||||||
cursor.clearSelection();
|
|
||||||
setTextCursor(cursor);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TextLabel::mousePressEvent(QMouseEvent *e)
|
|
||||||
{
|
|
||||||
link_ = (e->button() & Qt::LeftButton) ? anchorAt(e->pos()) : QString();
|
|
||||||
QTextBrowser::mousePressEvent(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TextLabel::mouseReleaseEvent(QMouseEvent *e)
|
|
||||||
{
|
|
||||||
if (e->button() & Qt::LeftButton && !link_.isEmpty() && anchorAt(e->pos()) == link_) {
|
|
||||||
emit linkActivated(link_);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QTextBrowser::mouseReleaseEvent(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TextLabel::wheelEvent(QWheelEvent *event)
|
|
||||||
{
|
|
||||||
event->ignore();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TextLabel::handleLinkActivation(const QUrl &url)
|
|
||||||
{
|
|
||||||
auto parts = url.toString().split('/');
|
|
||||||
auto defaultHandler = [](const QUrl &url) { QDesktopServices::openUrl(url); };
|
|
||||||
|
|
||||||
if (url.host() != QLatin1String("matrix.to") || parts.isEmpty())
|
|
||||||
return defaultHandler(url);
|
|
||||||
|
|
||||||
try {
|
|
||||||
using namespace mtx::identifiers;
|
|
||||||
parse<User>(parts.last().toStdString());
|
|
||||||
} catch (const std::exception &) {
|
|
||||||
return defaultHandler(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
emit userProfileTriggered(parts.last());
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
|
||||||
// SPDX-FileCopyrightText: 2022 Nheko Contributors
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QSize>
|
|
||||||
#include <QString>
|
|
||||||
#include <QTextBrowser>
|
|
||||||
#include <QUrl>
|
|
||||||
|
|
||||||
class QMouseEvent;
|
|
||||||
class QFocusEvent;
|
|
||||||
class QWheelEvent;
|
|
||||||
|
|
||||||
class ContextMenuFilter : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit ContextMenuFilter(QWidget *parent)
|
|
||||||
: QObject(parent)
|
|
||||||
{}
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void contextMenuIsOpening();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class TextLabel : public QTextBrowser
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
TextLabel(const QString &text, QWidget *parent = nullptr);
|
|
||||||
TextLabel(QWidget *parent = nullptr);
|
|
||||||
|
|
||||||
void wheelEvent(QWheelEvent *event) override;
|
|
||||||
void clearLinks() { link_.clear(); }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void mousePressEvent(QMouseEvent *e) override;
|
|
||||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
|
||||||
void focusOutEvent(QFocusEvent *e) override;
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void adjustHeight(const QSizeF &size) { setFixedHeight(size.height()); }
|
|
||||||
void handleLinkActivation(const QUrl &link);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void userProfileTriggered(const QString &user_id);
|
|
||||||
void linkActivated(const QUrl &link);
|
|
||||||
|
|
||||||
private:
|
|
||||||
QString link_;
|
|
||||||
bool contextMenuRequested_ = false;
|
|
||||||
};
|
|
Loading…
Reference in New Issue
Block a user