forked from github_mirror/framelesshelper
259 lines
9.2 KiB
C++
259 lines
9.2 KiB
C++
/*
|
|
* MIT License
|
|
*
|
|
* Copyright (C) 2020 by wangwenx190 (Yuhang Zhao)
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*/
|
|
|
|
#include "widget.h"
|
|
#include "../../framelesshelper.h"
|
|
#include <QEvent>
|
|
#include <QGraphicsDropShadowEffect>
|
|
#include <QHBoxLayout>
|
|
#include <QLabel>
|
|
#include <QPainter>
|
|
#include <QPushButton>
|
|
#include <QSpacerItem>
|
|
#include <QVBoxLayout>
|
|
|
|
Q_GLOBAL_STATIC(FramelessHelper, framelessHelper)
|
|
|
|
ContentsWidget::ContentsWidget(QWidget *parent) : QWidget(parent)
|
|
{
|
|
setAttribute(Qt::WA_StyledBackground);
|
|
}
|
|
|
|
void ContentsWidget::setShouldDrawWindowBorder(const bool val)
|
|
{
|
|
m_bShouldDrawWindowBorder = val;
|
|
update();
|
|
}
|
|
|
|
bool ContentsWidget::getShouldDrawWindowBorder() const
|
|
{
|
|
return m_bShouldDrawWindowBorder;
|
|
}
|
|
|
|
void ContentsWidget::paintEvent(QPaintEvent *event)
|
|
{
|
|
QWidget::paintEvent(event);
|
|
if (m_bShouldDrawWindowBorder) {
|
|
QPainter painter(this);
|
|
painter.save();
|
|
painter.setPen({window()->isActiveWindow() ? Qt::black : Qt::darkGray, 1.5});
|
|
painter.drawLine(0, 0, width(), 0);
|
|
painter.drawLine(0, height(), width(), height());
|
|
painter.drawLine(0, 0, 0, height());
|
|
painter.drawLine(width(), 0, width(), height());
|
|
painter.restore();
|
|
}
|
|
}
|
|
|
|
Widget::Widget(QWidget *parent) : QWidget(parent)
|
|
{
|
|
titleBarHeight = framelessHelper()->getTitleBarHeight();
|
|
createWinId();
|
|
setupUi();
|
|
initBackgroundWindow();
|
|
installEventFilter(this);
|
|
}
|
|
|
|
bool Widget::isNormal() const
|
|
{
|
|
return (!isMinimized() && !isMaximized() && !isFullScreen());
|
|
}
|
|
|
|
void Widget::setupUi()
|
|
{
|
|
contentsWidget = new ContentsWidget(this);
|
|
contentsWidget->setObjectName(QString::fromUtf8("contentsWidget"));
|
|
contentsWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
|
const QSize systemButtonSize = {qRound(titleBarHeight * 1.5), titleBarHeight};
|
|
const QSize systemIconSize = {17, 17};
|
|
titleBarWidget = new QWidget(contentsWidget);
|
|
titleBarWidget->setObjectName(QString::fromUtf8("titleBarWidget"));
|
|
titleBarWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
|
titleBarWidget->setFixedHeight(titleBarHeight);
|
|
windowIconButton = new QPushButton(this);
|
|
windowIconButton->setObjectName(QString::fromUtf8("windowIconButton"));
|
|
windowIconButton->setFixedSize(systemIconSize);
|
|
windowIconButton->setIconSize(systemIconSize);
|
|
connect(this, &Widget::windowIconChanged, windowIconButton, &QPushButton::setIcon);
|
|
windowTitleLabel = new QLabel(this);
|
|
QFont f = font();
|
|
f.setPointSizeF(8.63);
|
|
windowTitleLabel->setFont(f);
|
|
connect(this, &Widget::windowTitleChanged, windowTitleLabel, &QLabel::setText);
|
|
minimizeButton = new QPushButton(this);
|
|
minimizeButton->setObjectName(QString::fromUtf8("minimizeButton"));
|
|
minimizeButton->setFixedSize(systemButtonSize);
|
|
minimizeButton->setIconSize(systemButtonSize);
|
|
minimizeButton->setIcon(QIcon(QString::fromUtf8(":/images/button_minimize_black.svg")));
|
|
connect(minimizeButton, &QPushButton::clicked, this, &Widget::showMinimized);
|
|
maximizeButton = new QPushButton(this);
|
|
maximizeButton->setObjectName(QString::fromUtf8("maximizeButton"));
|
|
maximizeButton->setFixedSize(systemButtonSize);
|
|
maximizeButton->setIconSize(systemButtonSize);
|
|
maximizeButton->setIcon(QIcon(QString::fromUtf8(":/images/button_maximize_black.svg")));
|
|
connect(maximizeButton, &QPushButton::clicked, this, [this]() {
|
|
if (isMaximized()) {
|
|
showNormal();
|
|
} else {
|
|
showMaximized();
|
|
}
|
|
});
|
|
closeButton = new QPushButton(this);
|
|
closeButton->setObjectName(QString::fromUtf8("closeButton"));
|
|
closeButton->setFixedSize(systemButtonSize);
|
|
closeButton->setIconSize(systemButtonSize);
|
|
closeButton->setIcon(QIcon(QString::fromUtf8(":/images/button_close_black.svg")));
|
|
connect(closeButton, &QPushButton::clicked, this, &Widget::close);
|
|
const auto titleBarWidgetLayout = new QHBoxLayout(titleBarWidget);
|
|
titleBarWidgetLayout->setSpacing(0);
|
|
titleBarWidgetLayout->setContentsMargins(0, 0, 0, 0);
|
|
titleBarWidgetLayout->addSpacerItem(
|
|
new QSpacerItem(7, 20, QSizePolicy::Fixed, QSizePolicy::Fixed));
|
|
titleBarWidgetLayout->addWidget(windowIconButton);
|
|
titleBarWidgetLayout->addSpacerItem(
|
|
new QSpacerItem(3, 20, QSizePolicy::Fixed, QSizePolicy::Fixed));
|
|
titleBarWidgetLayout->addWidget(windowTitleLabel);
|
|
titleBarWidgetLayout->addStretch();
|
|
titleBarWidgetLayout->addWidget(minimizeButton);
|
|
titleBarWidgetLayout->addWidget(maximizeButton);
|
|
titleBarWidgetLayout->addWidget(closeButton);
|
|
titleBarWidget->setLayout(titleBarWidgetLayout);
|
|
const auto contentsWidgetLayout = new QVBoxLayout(contentsWidget);
|
|
contentsWidgetLayout->setSpacing(0);
|
|
contentsWidgetLayout->setContentsMargins(1, 1, 1, 0);
|
|
contentsWidgetLayout->addWidget(titleBarWidget);
|
|
contentsWidgetLayout->addStretch();
|
|
contentsWidget->setLayout(contentsWidgetLayout);
|
|
const auto backgroundWindowLayout = new QVBoxLayout(this);
|
|
backgroundWindowLayout->setSpacing(0);
|
|
backgroundWindowLayout->addWidget(contentsWidget);
|
|
setLayout(backgroundWindowLayout);
|
|
setStyleSheet(QString::fromUtf8(R"(
|
|
#contentsWidget {
|
|
background-color: #f0f0f0;
|
|
}
|
|
|
|
#titleBarWidget {
|
|
background-color: white;
|
|
}
|
|
|
|
#windowIconButton, #minimizeButton, #maximizeButton, #closeButton {
|
|
border-style: none;
|
|
background-color: transparent;
|
|
}
|
|
|
|
#minimizeButton:hover, #maximizeButton:hover {
|
|
background-color: #80c7c7c7;
|
|
}
|
|
|
|
#minimizeButton:pressed, #maximizeButton:pressed {
|
|
background-color: #80808080;
|
|
}
|
|
|
|
#closeButton:hover {
|
|
background-color: #e81123;
|
|
}
|
|
|
|
#closeButton:pressed {
|
|
background-color: #8c0a15;
|
|
}
|
|
)"));
|
|
}
|
|
|
|
void Widget::initBackgroundWindow()
|
|
{
|
|
QWindow *win = windowHandle();
|
|
framelessHelper()->removeWindowFrame(win);
|
|
framelessHelper()->addIgnoreObject(win, windowIconButton);
|
|
framelessHelper()->addIgnoreObject(win, minimizeButton);
|
|
framelessHelper()->addIgnoreObject(win, maximizeButton);
|
|
framelessHelper()->addIgnoreObject(win, closeButton);
|
|
framelessHelper()->setTitleBarHeight(titleBarHeight + framelessHelper()->getBorderHeight());
|
|
//setAttribute(Qt::WA_Hover);
|
|
setAttribute(Qt::WA_NoSystemBackground);
|
|
setAttribute(Qt::WA_TranslucentBackground);
|
|
shadowEffect = new QGraphicsDropShadowEffect(this);
|
|
shadowEffect->setOffset(0, 0);
|
|
contentsWidget->setGraphicsEffect(shadowEffect);
|
|
setFrameShadowEnabled();
|
|
setFrameShadowActive();
|
|
}
|
|
|
|
void Widget::setFrameShadowEnabled(const bool enable)
|
|
{
|
|
if (enable) {
|
|
const int bw = framelessHelper()->getBorderWidth();
|
|
const int bh = framelessHelper()->getBorderHeight();
|
|
layout()->setContentsMargins(bw, bh, bw, bh);
|
|
shadowEffect->setEnabled(true);
|
|
} else {
|
|
shadowEffect->setEnabled(false);
|
|
layout()->setContentsMargins(0, 0, 0, 0);
|
|
}
|
|
}
|
|
|
|
void Widget::setFrameShadowActive(const bool active)
|
|
{
|
|
if (active) {
|
|
shadowEffect->setColor({0, 0, 0, 80});
|
|
shadowEffect->setBlurRadius(25);
|
|
} else {
|
|
shadowEffect->setColor({0, 0, 0, 60});
|
|
shadowEffect->setBlurRadius(20);
|
|
}
|
|
}
|
|
|
|
bool Widget::eventFilter(QObject *object, QEvent *event)
|
|
{
|
|
Q_ASSERT(object);
|
|
Q_ASSERT(event);
|
|
if (object == this) {
|
|
switch (event->type()) {
|
|
case QEvent::WindowStateChange: {
|
|
const bool normal = isNormal();
|
|
contentsWidget->setShouldDrawWindowBorder(normal);
|
|
setFrameShadowEnabled(normal);
|
|
framelessHelper()->setTitleBarHeight(
|
|
titleBarHeight + (normal ? framelessHelper()->getBorderHeight() : 0));
|
|
const QString maxIconPath = QString::fromUtf8(":/images/button_maximize_black.svg");
|
|
const QString restoreIconPath = QString::fromUtf8(":/images/button_restore_black.svg");
|
|
maximizeButton->setIcon(QIcon(normal ? maxIconPath : restoreIconPath));
|
|
} break;
|
|
case QEvent::WindowActivate: {
|
|
if (isNormal()) {
|
|
setFrameShadowActive();
|
|
}
|
|
} break;
|
|
case QEvent::WindowDeactivate: {
|
|
if (isNormal()) {
|
|
setFrameShadowActive(false);
|
|
}
|
|
} break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return QWidget::eventFilter(object, event);
|
|
}
|