first
This commit is contained in:
+134
@@ -0,0 +1,134 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
project(ELAWIDGETTOOLS VERSION 2.0.0 LANGUAGES CXX)
|
||||
|
||||
set(EXPORT_NAME "ElaWidgetTools")
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")
|
||||
|
||||
SET(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/install CACHE PATH "Installation path" FORCE)
|
||||
add_definitions(-DELAWIDGETTOOLS_LIBRARY)
|
||||
option(ELAWIDGETTOOLS_BUILD_STATIC_LIB "Build static library." OFF)
|
||||
|
||||
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets)
|
||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)
|
||||
|
||||
FILE(GLOB ORIGIN *.h *.cpp)
|
||||
FILE(GLOB INCLUDE include/*.h)
|
||||
FILE(GLOB PRIVATE private/*.h private/*.cpp)
|
||||
FILE(GLOB DEVELOPER DeveloperComponents/*.h DeveloperComponents/*.cpp)
|
||||
|
||||
source_group(include FILES ${INCLUDE})
|
||||
source_group(private FILES ${PRIVATE})
|
||||
source_group(DeveloperComponents FILES ${DEVELOPER})
|
||||
|
||||
set(PROJECT_SOURCES
|
||||
${ORIGIN}
|
||||
${INCLUDE}
|
||||
${PRIVATE}
|
||||
${DEVELOPER}
|
||||
)
|
||||
|
||||
if (ELAWIDGETTOOLS_BUILD_STATIC_LIB)
|
||||
set(LIB_TYPE "STATIC")
|
||||
else ()
|
||||
set(LIB_TYPE "SHARED"
|
||||
DeveloperComponents/ElaKeyBinderContainer.cpp
|
||||
DeveloperComponents/ElaKeyBinderContainer.h)
|
||||
endif ()
|
||||
|
||||
if (${QT_VERSION_MAJOR} GREATER_EQUAL 6)
|
||||
qt_add_library(${EXPORT_NAME} ${LIB_TYPE}
|
||||
${PROJECT_SOURCES}
|
||||
)
|
||||
else ()
|
||||
add_library(${EXPORT_NAME} ${LIB_TYPE}
|
||||
${PROJECT_SOURCES}
|
||||
)
|
||||
endif ()
|
||||
|
||||
FILE(GLOB EXPORT_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/*.qrc
|
||||
)
|
||||
target_include_directories(${EXPORT_NAME} PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/private>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/DeveloperComponents>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
)
|
||||
|
||||
if (${QT_VERSION_MAJOR} GREATER_EQUAL 6)
|
||||
#遍历所有资源文件
|
||||
file(GLOB_RECURSE RES_PATHS *.png *.jpg *.svg *.ico *.ttf *.webp *.js)
|
||||
foreach (filepath ${RES_PATHS})
|
||||
string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" filename ${filepath})
|
||||
list(APPEND resource_files ${filename})
|
||||
endforeach (filepath)
|
||||
qt_add_resources(${EXPORT_NAME} "ElaWidgetTools"
|
||||
RESOURCES PREFIX "/"
|
||||
FILES
|
||||
${resource_files}
|
||||
)
|
||||
endif ()
|
||||
|
||||
if (MINGW)
|
||||
set_target_properties(${EXPORT_NAME} PROPERTIES PREFIX "")
|
||||
endif ()
|
||||
if (MSVC)
|
||||
set_target_properties(${EXPORT_NAME} PROPERTIES DEBUG_POSTFIX "d")
|
||||
endif ()
|
||||
|
||||
if (WIN32)
|
||||
target_link_libraries(${EXPORT_NAME} PUBLIC
|
||||
Qt${QT_VERSION_MAJOR}::Widgets
|
||||
D3D11
|
||||
DXGI
|
||||
)
|
||||
else ()
|
||||
target_link_libraries(${EXPORT_NAME} PUBLIC
|
||||
Qt${QT_VERSION_MAJOR}::Widgets
|
||||
)
|
||||
endif ()
|
||||
|
||||
|
||||
install(
|
||||
TARGETS ${EXPORT_NAME}
|
||||
EXPORT ${EXPORT_NAME}
|
||||
ARCHIVE DESTINATION lib
|
||||
LIBRARY DESTINATION lib
|
||||
RUNTIME DESTINATION bin
|
||||
)
|
||||
|
||||
install(FILES ${EXPORT_HEADERS} DESTINATION include)
|
||||
install(TARGETS ${EXPORT_NAME}
|
||||
RUNTIME DESTINATION ${CMAKE_BINARY_DIR}
|
||||
)
|
||||
|
||||
set(INCLUDE_DIRS include)
|
||||
set(LIBRARIES ${EXPORT_NAME})
|
||||
set(LIB_DIR lib)
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
write_basic_package_version_file(
|
||||
${PROJECT_BINARY_DIR}/${EXPORT_NAME}ConfigVersion.cmake
|
||||
VERSION 2.0.0
|
||||
COMPATIBILITY SameMajorVersion
|
||||
)
|
||||
|
||||
configure_package_config_file(
|
||||
${PROJECT_SOURCE_DIR}/${EXPORT_NAME}Config.cmake.in
|
||||
${PROJECT_BINARY_DIR}/${EXPORT_NAME}Config.cmake
|
||||
INSTALL_DESTINATION lib/cmake
|
||||
PATH_VARS INCLUDE_DIRS LIBRARIES LIB_DIR
|
||||
INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}
|
||||
)
|
||||
|
||||
install(
|
||||
FILES ${PROJECT_BINARY_DIR}/${EXPORT_NAME}Config.cmake ${PROJECT_BINARY_DIR}/${EXPORT_NAME}ConfigVersion.cmake DESTINATION lib/cmake
|
||||
)
|
||||
@@ -0,0 +1,45 @@
|
||||
#include "ElaBaseListView.h"
|
||||
|
||||
#include <QMouseEvent>
|
||||
|
||||
#include "ElaScrollBar.h"
|
||||
ElaBaseListView::ElaBaseListView(QWidget* parent)
|
||||
: QListView(parent)
|
||||
{
|
||||
setObjectName("ElaBaseListView");
|
||||
setStyleSheet(
|
||||
"ElaBaseListView{background-color: transparent;border:0px;}"
|
||||
"ElaBaseListView::item{border:none;}");
|
||||
setAutoScroll(false);
|
||||
setFocusPolicy(Qt::NoFocus);
|
||||
setVerticalScrollBar(new ElaScrollBar(this));
|
||||
setHorizontalScrollBar(new ElaScrollBar(this));
|
||||
setSelectionMode(QAbstractItemView::NoSelection);
|
||||
setMouseTracking(true);
|
||||
this->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
this->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||
setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||
}
|
||||
|
||||
ElaBaseListView::~ElaBaseListView()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaBaseListView::mousePressEvent(QMouseEvent* event)
|
||||
{
|
||||
Q_EMIT mousePress(indexAt(event->pos()));
|
||||
QListView::mousePressEvent(event);
|
||||
}
|
||||
|
||||
void ElaBaseListView::mouseReleaseEvent(QMouseEvent* event)
|
||||
{
|
||||
Q_EMIT mouseRelease(indexAt(event->pos()));
|
||||
QListView::mouseReleaseEvent(event);
|
||||
}
|
||||
|
||||
void ElaBaseListView::mouseDoubleClickEvent(QMouseEvent* event)
|
||||
{
|
||||
Q_EMIT mouseDoubleClick(indexAt(event->pos()));
|
||||
QListView::mouseDoubleClickEvent(event);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef ELABASELISTVIEW_H
|
||||
#define ELABASELISTVIEW_H
|
||||
|
||||
#include <QListView>
|
||||
#include <QModelIndex>
|
||||
|
||||
class ElaScrollBar;
|
||||
class ElaBaseListView : public QListView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ElaBaseListView(QWidget* parent = nullptr);
|
||||
~ElaBaseListView();
|
||||
Q_SIGNALS:
|
||||
Q_SIGNAL void mousePress(const QModelIndex& index);
|
||||
Q_SIGNAL void mouseRelease(const QModelIndex& index);
|
||||
Q_SIGNAL void mouseDoubleClick(const QModelIndex& index);
|
||||
|
||||
protected:
|
||||
virtual void mousePressEvent(QMouseEvent* event) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent* event) override;
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent* event) override;
|
||||
};
|
||||
|
||||
#endif // ELABASELISTVIEW_H
|
||||
@@ -0,0 +1,57 @@
|
||||
#include "ElaBreadcrumbBarDelegate.h"
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
#include "ElaTheme.h"
|
||||
ElaBreadcrumbBarDelegate::ElaBreadcrumbBarDelegate(QObject* parent)
|
||||
: QStyledItemDelegate{parent}
|
||||
{
|
||||
_themeMode = eTheme->getThemeMode();
|
||||
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) {
|
||||
_themeMode = themeMode;
|
||||
});
|
||||
}
|
||||
|
||||
ElaBreadcrumbBarDelegate::~ElaBreadcrumbBarDelegate()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaBreadcrumbBarDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
painter->save();
|
||||
painter->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
|
||||
painter->setPen(ElaThemeColor(_themeMode, BasicText));
|
||||
QRect itemRect = option.rect;
|
||||
QString breadcrumbDisplayData = index.data(Qt::DisplayRole).toString();
|
||||
QString breadcrumbUserData = index.data(Qt::UserRole).toString();
|
||||
if (breadcrumbUserData != "LastBreadcrumb")
|
||||
{
|
||||
if (_pPressIndex == index)
|
||||
{
|
||||
//鼠标按下
|
||||
painter->setPen(ElaThemeColor(_themeMode, BasicTextPress));
|
||||
}
|
||||
else
|
||||
{
|
||||
//不为最后一个 且没有被鼠标覆盖
|
||||
if (!(option.state & QStyle::State_MouseOver))
|
||||
{
|
||||
painter->setPen(ElaThemeColor(_themeMode, BasicTextNoFocus));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (breadcrumbDisplayData != ">")
|
||||
{
|
||||
painter->drawText(itemRect, Qt::AlignVCenter | Qt::AlignLeft, breadcrumbDisplayData);
|
||||
}
|
||||
else
|
||||
{
|
||||
//分隔符
|
||||
QFont iconFont = QFont("ElaAwesome");
|
||||
iconFont.setPixelSize(painter->font().pixelSize() * 0.785);
|
||||
painter->setFont(iconFont);
|
||||
itemRect.setX(itemRect.x() - itemRect.width() * 0.36);
|
||||
painter->drawText(itemRect, Qt::AlignCenter, QChar((unsigned short)ElaIconType::AngleRight));
|
||||
}
|
||||
painter->restore();
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef ELABREADCRUMBBARDELEGATE_H
|
||||
#define ELABREADCRUMBBARDELEGATE_H
|
||||
|
||||
#include <QModelIndex>
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
#include "Def.h"
|
||||
class ElaBreadcrumbBarDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PRIVATE_CREATE(QModelIndex, PressIndex)
|
||||
public:
|
||||
explicit ElaBreadcrumbBarDelegate(QObject* parent = nullptr);
|
||||
~ElaBreadcrumbBarDelegate();
|
||||
|
||||
protected:
|
||||
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
|
||||
private:
|
||||
ElaThemeType::ThemeMode _themeMode;
|
||||
};
|
||||
|
||||
#endif // ELABREADCRUMBBARDELEGATE_H
|
||||
@@ -0,0 +1,108 @@
|
||||
#include "ElaBreadcrumbBarModel.h"
|
||||
|
||||
ElaBreadcrumbBarModel::ElaBreadcrumbBarModel(QObject* parent)
|
||||
: QAbstractListModel{parent}
|
||||
{
|
||||
}
|
||||
|
||||
ElaBreadcrumbBarModel::~ElaBreadcrumbBarModel()
|
||||
{
|
||||
}
|
||||
|
||||
int ElaBreadcrumbBarModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
return _breadcrumbList.count() * 2 - 1;
|
||||
}
|
||||
|
||||
QVariant ElaBreadcrumbBarModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
if (index.row() % 2 == 0)
|
||||
{
|
||||
return _breadcrumbList[index.row() / 2];
|
||||
}
|
||||
else
|
||||
{
|
||||
return ">";
|
||||
}
|
||||
}
|
||||
else if (role == Qt::UserRole)
|
||||
{
|
||||
if (index.row() == _breadcrumbList.count() * 2 - 2 || index.row() == _breadcrumbList.count() * 2 - 3)
|
||||
{
|
||||
return QString("LastBreadcrumb");
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void ElaBreadcrumbBarModel::appendBreadcrumb(QString breadcrumb)
|
||||
{
|
||||
if (!breadcrumb.isEmpty())
|
||||
{
|
||||
if (_breadcrumbList.count() && _breadcrumbList.last() == breadcrumb)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (_breadcrumbList.count() >= 2 && _breadcrumbList[_breadcrumbList.count() - 2] == breadcrumb)
|
||||
{
|
||||
beginResetModel();
|
||||
_breadcrumbList.removeLast();
|
||||
endResetModel();
|
||||
return;
|
||||
}
|
||||
beginResetModel();
|
||||
_breadcrumbList.append(breadcrumb);
|
||||
endResetModel();
|
||||
}
|
||||
}
|
||||
|
||||
void ElaBreadcrumbBarModel::removeBreadcrumb(QString breadcrumb)
|
||||
{
|
||||
if (_breadcrumbList.contains(breadcrumb))
|
||||
{
|
||||
beginResetModel();
|
||||
_breadcrumbList.removeAt(_breadcrumbList.lastIndexOf(breadcrumb));
|
||||
endResetModel();
|
||||
}
|
||||
}
|
||||
|
||||
void ElaBreadcrumbBarModel::removeBreadcrumb(int index)
|
||||
{
|
||||
if (index >= _breadcrumbList.count())
|
||||
{
|
||||
return;
|
||||
}
|
||||
beginResetModel();
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
_breadcrumbList.remove(index, _breadcrumbList.count() - index);
|
||||
#else
|
||||
for (int i = _breadcrumbList.count() - 1; i >= 0; i--)
|
||||
{
|
||||
if (i < index)
|
||||
{
|
||||
break;
|
||||
}
|
||||
_breadcrumbList.removeAt(i);
|
||||
}
|
||||
#endif
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void ElaBreadcrumbBarModel::setBreadcrumbList(QStringList breadcrumbList)
|
||||
{
|
||||
beginResetModel();
|
||||
this->_breadcrumbList = breadcrumbList;
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
int ElaBreadcrumbBarModel::getBreadcrumbListCount()
|
||||
{
|
||||
return _breadcrumbList.count();
|
||||
}
|
||||
|
||||
QStringList ElaBreadcrumbBarModel::getBreadcrumbList()
|
||||
{
|
||||
return _breadcrumbList;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef ELABREADCRUMBBARMODEL_H
|
||||
#define ELABREADCRUMBBARMODEL_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
|
||||
class ElaBreadcrumbBarModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ElaBreadcrumbBarModel(QObject* parent = nullptr);
|
||||
~ElaBreadcrumbBarModel();
|
||||
|
||||
void appendBreadcrumb(QString breadcrumb);
|
||||
void removeBreadcrumb(QString breadcrumb);
|
||||
void removeBreadcrumb(int index);
|
||||
|
||||
void setBreadcrumbList(QStringList breadcrumbList);
|
||||
|
||||
int getBreadcrumbListCount();
|
||||
QStringList getBreadcrumbList();
|
||||
|
||||
protected:
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex& index, int role) const override;
|
||||
|
||||
private:
|
||||
QStringList _breadcrumbList;
|
||||
};
|
||||
|
||||
#endif // ELABREADCRUMBBARMODEL_H
|
||||
@@ -0,0 +1,187 @@
|
||||
#include "ElaCalendarDelegate.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QStyleOption>
|
||||
|
||||
#include "ElaTheme.h"
|
||||
ElaCalendarDelegate::ElaCalendarDelegate(ElaCalendarModel* calendarModel, QObject* parent)
|
||||
: QStyledItemDelegate{parent}
|
||||
{
|
||||
_pIsTransparent = false;
|
||||
_calendarModel = calendarModel;
|
||||
_pItemWidth = 42;
|
||||
_pItemHeight = 42;
|
||||
_nowDate = QDate::currentDate();
|
||||
_themeMode = eTheme->getThemeMode();
|
||||
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) {
|
||||
_themeMode = themeMode;
|
||||
});
|
||||
connect(_calendarModel, &ElaCalendarModel::displayModeChanged, this, &ElaCalendarDelegate::onCalendarModelDisplayModeChanged);
|
||||
}
|
||||
|
||||
ElaCalendarDelegate::~ElaCalendarDelegate()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaCalendarDelegate::onCalendarModelDisplayModeChanged()
|
||||
{
|
||||
switch (_calendarModel->getDisplayMode())
|
||||
{
|
||||
case YearMode:
|
||||
case MonthMode:
|
||||
{
|
||||
_pItemWidth = 53;
|
||||
_pItemHeight = 60;
|
||||
break;
|
||||
}
|
||||
case DayMode:
|
||||
{
|
||||
_pItemWidth = 42;
|
||||
_pItemHeight = 42;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ElaCalendarDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
if (_pIsTransparent)
|
||||
{
|
||||
return;
|
||||
}
|
||||
painter->save();
|
||||
painter->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
|
||||
ElaCalendarType displayModel = _calendarModel->getDisplayMode();
|
||||
switch (displayModel)
|
||||
{
|
||||
case YearMode:
|
||||
case MonthMode:
|
||||
{
|
||||
_drawYearOrMonth(painter, option, index);
|
||||
break;
|
||||
}
|
||||
case DayMode:
|
||||
{
|
||||
_drawDays(painter, option, index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
painter->restore();
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
}
|
||||
|
||||
QSize ElaCalendarDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
return QSize(_pItemWidth, _pItemHeight);
|
||||
}
|
||||
|
||||
void ElaCalendarDelegate::_drawYearOrMonth(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
QRectF itemRect = option.rect;
|
||||
bool isNow = false;
|
||||
ElaCalendarData data = index.data(Qt::UserRole).value<ElaCalendarData>();
|
||||
qreal baseRadius = _pItemWidth * 0.5;
|
||||
// 当前日期绘制
|
||||
ElaCalendarType displayMode = _calendarModel->getDisplayMode();
|
||||
if ((displayMode == ElaCalendarType::YearMode && data.year == _nowDate.year()) || (displayMode == ElaCalendarType::MonthMode && data.month == _nowDate.month() && data.year == _nowDate.year()))
|
||||
{
|
||||
isNow = true;
|
||||
QColor drawColor = option.state.testFlag(QStyle::State_MouseOver) ? ElaThemeColor(_themeMode, PrimaryHover) : ElaThemeColor(_themeMode, PrimaryNormal);
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(drawColor);
|
||||
painter->drawEllipse(itemRect.center(), baseRadius, baseRadius);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 覆盖和选中效果绘制
|
||||
if (option.state.testFlag(QStyle::State_MouseOver))
|
||||
{
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicHover));
|
||||
painter->drawEllipse(itemRect.center(), baseRadius, baseRadius);
|
||||
}
|
||||
}
|
||||
|
||||
// 文字绘制
|
||||
painter->setPen(isNow ? ElaThemeColor(_themeMode, BasicTextInvert) : ElaThemeColor(_themeMode, BasicText));
|
||||
painter->drawText(itemRect, Qt::AlignCenter, displayMode == ElaCalendarType::YearMode ? QString::number(data.year) : QString::number(data.month));
|
||||
QString desText = data.desText;
|
||||
if (!desText.isEmpty())
|
||||
{
|
||||
itemRect.adjust(0, 10, 0, 0);
|
||||
QFont font = painter->font();
|
||||
font.setPixelSize(9);
|
||||
painter->setFont(font);
|
||||
painter->drawText(itemRect, Qt::AlignTop | Qt::AlignHCenter, desText);
|
||||
}
|
||||
}
|
||||
|
||||
void ElaCalendarDelegate::_drawDays(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
qreal penWidth = 1.5;
|
||||
qreal baseRadius = _pItemWidth * 0.5 - penWidth;
|
||||
QVariant variant = index.data(Qt::UserRole);
|
||||
if (variant.isValid())
|
||||
{
|
||||
QRectF itemRect = option.rect;
|
||||
bool isNow = false;
|
||||
ElaCalendarData data = variant.value<ElaCalendarData>();
|
||||
// 当前日期绘制
|
||||
if (data.year == _nowDate.year() && data.month == _nowDate.month() && data.day == _nowDate.day())
|
||||
{
|
||||
isNow = true;
|
||||
QColor drawColor = option.state.testFlag(QStyle::State_MouseOver) ? ElaThemeColor(_themeMode, PrimaryHover) : ElaThemeColor(_themeMode, PrimaryNormal);
|
||||
if (option.state.testFlag(QStyle::State_Selected))
|
||||
{
|
||||
painter->setPen(QPen(drawColor, penWidth));
|
||||
painter->drawEllipse(itemRect.center(), baseRadius, baseRadius);
|
||||
painter->setBrush(drawColor);
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->drawEllipse(itemRect.center(), baseRadius - 2 * penWidth, baseRadius - 2 * penWidth);
|
||||
}
|
||||
else
|
||||
{
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(drawColor);
|
||||
painter->drawEllipse(itemRect.center(), baseRadius, baseRadius);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 覆盖和选中效果绘制
|
||||
if (option.state.testFlag(QStyle::State_Selected))
|
||||
{
|
||||
painter->setPen(QPen(option.state.testFlag(QStyle::State_MouseOver) ? ElaThemeColor(_themeMode, PrimaryHover) : ElaThemeColor(_themeMode, PrimaryNormal), penWidth));
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
painter->drawEllipse(itemRect.center(), baseRadius, baseRadius);
|
||||
}
|
||||
if (option.state.testFlag(QStyle::State_MouseOver))
|
||||
{
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicHover));
|
||||
if (option.state.testFlag(QStyle::State_Selected))
|
||||
{
|
||||
painter->drawEllipse(itemRect.center(), baseRadius - penWidth, baseRadius - penWidth);
|
||||
}
|
||||
else
|
||||
{
|
||||
painter->drawEllipse(itemRect.center(), baseRadius, baseRadius);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 文字绘制
|
||||
painter->setPen(isNow ? ElaThemeColor(_themeMode, BasicTextInvert) : ElaThemeColor(_themeMode, BasicText));
|
||||
painter->drawText(itemRect, Qt::AlignCenter, QString::number(data.day));
|
||||
QString desText = data.desText;
|
||||
if (!desText.isEmpty())
|
||||
{
|
||||
itemRect.adjust(0, 2 * penWidth, 0, 0);
|
||||
QFont font = painter->font();
|
||||
font.setPixelSize(9);
|
||||
painter->setFont(font);
|
||||
painter->drawText(itemRect, Qt::AlignTop | Qt::AlignHCenter, desText);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#ifndef ELACALENDARDELEGATE_H
|
||||
#define ELACALENDARDELEGATE_H
|
||||
|
||||
#include <QDate>
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
#include "Def.h"
|
||||
#include "ElaCalendarModel.h"
|
||||
class ElaCalendarDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PRIVATE_CREATE(int, ItemWidth)
|
||||
Q_PRIVATE_CREATE(int, ItemHeight)
|
||||
Q_PRIVATE_CREATE(bool, IsTransparent)
|
||||
public:
|
||||
explicit ElaCalendarDelegate(ElaCalendarModel* calendarModel, QObject* parent = nullptr);
|
||||
~ElaCalendarDelegate();
|
||||
|
||||
Q_SLOT void onCalendarModelDisplayModeChanged();
|
||||
|
||||
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
|
||||
private:
|
||||
ElaCalendarModel* _calendarModel{nullptr};
|
||||
ElaThemeType::ThemeMode _themeMode;
|
||||
QDate _nowDate;
|
||||
void _drawYearOrMonth(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
|
||||
void _drawDays(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
|
||||
};
|
||||
|
||||
#endif // ELACALENDARDELEGATE_H
|
||||
@@ -0,0 +1,152 @@
|
||||
#include "ElaCalendarModel.h"
|
||||
|
||||
ElaCalendarModel::ElaCalendarModel(QObject* parent)
|
||||
: QAbstractListModel{parent}
|
||||
{
|
||||
_pMinimumDate.setDate(1924, 1, 1);
|
||||
_pMaximumDate.setDate(2124, 12, 31);
|
||||
_initRowCount();
|
||||
}
|
||||
|
||||
ElaCalendarModel::~ElaCalendarModel()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaCalendarModel::setMinimumDate(QDate minimudate)
|
||||
{
|
||||
_pMinimumDate = minimudate;
|
||||
_initRowCount();
|
||||
}
|
||||
|
||||
QDate ElaCalendarModel::getMinimumDate() const
|
||||
{
|
||||
return _pMinimumDate;
|
||||
}
|
||||
|
||||
void ElaCalendarModel::setMaximumDate(QDate maximumDate)
|
||||
{
|
||||
_pMaximumDate = maximumDate;
|
||||
_initRowCount();
|
||||
}
|
||||
|
||||
QDate ElaCalendarModel::getMaximumDate() const
|
||||
{
|
||||
return _pMaximumDate;
|
||||
}
|
||||
|
||||
void ElaCalendarModel::setDisplayMode(ElaCalendarType displayMode)
|
||||
{
|
||||
beginResetModel();
|
||||
_displayMode = displayMode;
|
||||
endResetModel();
|
||||
Q_EMIT displayModeChanged();
|
||||
}
|
||||
|
||||
ElaCalendarType ElaCalendarModel::getDisplayMode() const
|
||||
{
|
||||
return _displayMode;
|
||||
}
|
||||
|
||||
QModelIndex ElaCalendarModel::getIndexFromDate(QDate date)
|
||||
{
|
||||
switch (_displayMode)
|
||||
{
|
||||
case YearMode:
|
||||
{
|
||||
return this->index(date.year() - _pMinimumDate.year());
|
||||
}
|
||||
case MonthMode:
|
||||
{
|
||||
return this->index((date.year() - _pMinimumDate.year()) * 12 + date.month() - 1);
|
||||
}
|
||||
case DayMode:
|
||||
{
|
||||
return this->index(_pMinimumDate.daysTo(date) + _offset);
|
||||
}
|
||||
}
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
QDate ElaCalendarModel::getDateFromIndex(const QModelIndex& index) const
|
||||
{
|
||||
if (!index.isValid() || index.row() < _offset)
|
||||
{
|
||||
return QDate();
|
||||
}
|
||||
return _pMinimumDate.addDays(index.row() - _offset);
|
||||
}
|
||||
|
||||
QVariant ElaCalendarModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
if (role == Qt::UserRole)
|
||||
{
|
||||
switch (_displayMode)
|
||||
{
|
||||
case YearMode:
|
||||
{
|
||||
return QVariant::fromValue<ElaCalendarData>(ElaCalendarData(_pMinimumDate.year() + index.row(), 1, 1));
|
||||
}
|
||||
case MonthMode:
|
||||
{
|
||||
int year = _pMinimumDate.year() + index.row() / 12;
|
||||
int month = index.row() % 12 + 1;
|
||||
if (month == 1)
|
||||
{
|
||||
return QVariant::fromValue<ElaCalendarData>(ElaCalendarData(year, month, 1, QString::number(year)));
|
||||
}
|
||||
else
|
||||
{
|
||||
return QVariant::fromValue<ElaCalendarData>(ElaCalendarData(_pMinimumDate.year() + index.row() / 12, month, 1));
|
||||
}
|
||||
}
|
||||
case DayMode:
|
||||
{
|
||||
if (index.row() >= _offset)
|
||||
{
|
||||
QDate date = getDateFromIndex(index);
|
||||
if (date.day() == 1)
|
||||
{
|
||||
return QVariant::fromValue<ElaCalendarData>(ElaCalendarData(date.year(), date.month(), date.day(), QString("%1月").arg(date.month())));
|
||||
}
|
||||
else
|
||||
{
|
||||
return QVariant::fromValue<ElaCalendarData>(ElaCalendarData(date.year(), date.month(), date.day()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
int ElaCalendarModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
switch (_displayMode)
|
||||
{
|
||||
case YearMode:
|
||||
{
|
||||
return _pMaximumDate.year() - _pMinimumDate.year() + 1;
|
||||
}
|
||||
case MonthMode:
|
||||
{
|
||||
return (_pMaximumDate.year() - _pMinimumDate.year() + 1) * 12;
|
||||
}
|
||||
case DayMode:
|
||||
{
|
||||
return _dayRowCount;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ElaCalendarModel::_initRowCount()
|
||||
{
|
||||
_dayRowCount = _pMinimumDate.daysTo(_pMaximumDate);
|
||||
_offset = _pMinimumDate.dayOfWeek();
|
||||
_dayRowCount += _offset + 1;
|
||||
}
|
||||
|
||||
int ElaCalendarModel::_getCurrentDay(int row) const
|
||||
{
|
||||
return _pMinimumDate.addDays(row - _offset).day();
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
#ifndef ELACALENDARMODEL_H
|
||||
#define ELACALENDARMODEL_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QDate>
|
||||
#include <QMetaType>
|
||||
|
||||
#include "stdafx.h"
|
||||
enum ElaCalendarType
|
||||
{
|
||||
YearMode = 0x0001,
|
||||
MonthMode = 0x0002,
|
||||
DayMode = 0x0003,
|
||||
};
|
||||
|
||||
struct ElaCalendarData : public QObjectData
|
||||
{
|
||||
public:
|
||||
ElaCalendarData(){};
|
||||
~ElaCalendarData(){};
|
||||
ElaCalendarData(int year, int month, int day, QString desText = "")
|
||||
: year(year), month(month), day(day), desText(desText){};
|
||||
ElaCalendarData(const ElaCalendarData& other)
|
||||
{
|
||||
year = other.year;
|
||||
month = other.month;
|
||||
day = other.day;
|
||||
desText = other.desText;
|
||||
}
|
||||
int year = 1924;
|
||||
int month = 1;
|
||||
int day = 1;
|
||||
QString desText{""};
|
||||
};
|
||||
Q_DECLARE_METATYPE(ElaCalendarData);
|
||||
|
||||
class ElaCalendarModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PRIVATE_CREATE_Q_H(QDate, MinimumDate)
|
||||
Q_PRIVATE_CREATE_Q_H(QDate, MaximumDate)
|
||||
public:
|
||||
explicit ElaCalendarModel(QObject* parent = nullptr);
|
||||
~ElaCalendarModel();
|
||||
|
||||
void setDisplayMode(ElaCalendarType displayType);
|
||||
ElaCalendarType getDisplayMode() const;
|
||||
|
||||
QModelIndex getIndexFromDate(QDate date);
|
||||
QDate getDateFromIndex(const QModelIndex& index) const;
|
||||
virtual QVariant data(const QModelIndex& index, int role) const override;
|
||||
|
||||
Q_SIGNALS:
|
||||
Q_SIGNAL void currentYearMonthChanged(QString date);
|
||||
Q_SIGNAL void displayModeChanged();
|
||||
|
||||
protected:
|
||||
virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
|
||||
private:
|
||||
int _offset{0};
|
||||
QDate _pMinimumDate;
|
||||
QDate _pMaximumDate;
|
||||
ElaCalendarType _displayMode{ElaCalendarType::DayMode};
|
||||
int _dayRowCount{0};
|
||||
void _initRowCount();
|
||||
int _getCurrentDay(int row) const;
|
||||
};
|
||||
|
||||
#endif // ELACALENDARMODEL_H
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
#include "ElaCalendarPickerContainer.h"
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
#include "ElaTheme.h"
|
||||
ElaCalendarPickerContainer::ElaCalendarPickerContainer(QWidget* parent)
|
||||
: QWidget{parent}
|
||||
{
|
||||
setWindowFlags(Qt::FramelessWindowHint | Qt::Popup | Qt::NoDropShadowWindowHint);
|
||||
setAttribute(Qt::WA_TranslucentBackground);
|
||||
setContentsMargins(0, 0, 0, 0);
|
||||
setObjectName("ElaCalendarPickerContainer");
|
||||
setStyleSheet("#ElaCalendarPickerContainer{background-color:transparent}");
|
||||
_themeMode = eTheme->getThemeMode();
|
||||
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) { _themeMode = themeMode; });
|
||||
}
|
||||
|
||||
ElaCalendarPickerContainer::~ElaCalendarPickerContainer()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaCalendarPickerContainer::paintEvent(QPaintEvent* event)
|
||||
{
|
||||
QPainter painter(this);
|
||||
painter.save();
|
||||
painter.setRenderHints(QPainter::Antialiasing);
|
||||
eTheme->drawEffectShadow(&painter, rect(), 6, 5);
|
||||
painter.restore();
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef ELACALENDARPICKERCONTAINER_H
|
||||
#define ELACALENDARPICKERCONTAINER_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "Def.h"
|
||||
class ElaCalendarPickerContainer : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ElaCalendarPickerContainer(QWidget* parent = nullptr);
|
||||
~ElaCalendarPickerContainer();
|
||||
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent* event) override;
|
||||
|
||||
private:
|
||||
ElaThemeType::ThemeMode _themeMode;
|
||||
};
|
||||
|
||||
#endif // ELACALENDARPICKERCONTAINER_H
|
||||
@@ -0,0 +1,43 @@
|
||||
#include "ElaCalendarTitleDelegate.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QStyleOption>
|
||||
|
||||
#include "ElaTheme.h"
|
||||
ElaCalendarTitleDelegate::ElaCalendarTitleDelegate(QObject* parent)
|
||||
: QStyledItemDelegate{parent}
|
||||
{
|
||||
_themeMode = eTheme->getThemeMode();
|
||||
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) {
|
||||
_themeMode = themeMode;
|
||||
});
|
||||
}
|
||||
|
||||
ElaCalendarTitleDelegate::~ElaCalendarTitleDelegate()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaCalendarTitleDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
painter->save();
|
||||
painter->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
|
||||
QRectF itemRect = option.rect;
|
||||
// 文字绘制
|
||||
QString title = index.data(Qt::UserRole).toString();
|
||||
if (!title.isEmpty())
|
||||
{
|
||||
painter->setPen(ElaThemeColor(_themeMode, BasicText));
|
||||
QFont font = painter->font();
|
||||
font.setWeight(QFont::Bold);
|
||||
painter->setFont(font);
|
||||
painter->drawText(itemRect, Qt::AlignCenter, title);
|
||||
}
|
||||
painter->restore();
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
}
|
||||
|
||||
QSize ElaCalendarTitleDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
return QSize(42, 30);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef ELACALENDARTITLEDELEGATE_H
|
||||
#define ELACALENDARTITLEDELEGATE_H
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
#include "Def.h"
|
||||
class ElaCalendarTitleDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ElaCalendarTitleDelegate(QObject* parent = nullptr);
|
||||
~ElaCalendarTitleDelegate();
|
||||
|
||||
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
|
||||
private:
|
||||
ElaThemeType::ThemeMode _themeMode;
|
||||
};
|
||||
|
||||
#endif // ELACALENDARTITLEDELEGATE_H
|
||||
@@ -0,0 +1,54 @@
|
||||
#include "ElaCalendarTitleModel.h"
|
||||
|
||||
ElaCalendarTitleModel::ElaCalendarTitleModel(QObject* parent)
|
||||
: QAbstractListModel{parent}
|
||||
{
|
||||
}
|
||||
|
||||
ElaCalendarTitleModel::~ElaCalendarTitleModel()
|
||||
{
|
||||
}
|
||||
|
||||
int ElaCalendarTitleModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
return 7;
|
||||
}
|
||||
|
||||
QVariant ElaCalendarTitleModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
if (role == Qt::UserRole)
|
||||
{
|
||||
switch (index.row())
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
return tr("日");
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
return tr("一");
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
return tr("二");
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
return tr("三");
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
return tr("四");
|
||||
}
|
||||
case 5:
|
||||
{
|
||||
return tr("五");
|
||||
}
|
||||
case 6:
|
||||
{
|
||||
return tr("六");
|
||||
}
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#ifndef ELACALENDARTITLEMODEL_H
|
||||
#define ELACALENDARTITLEMODEL_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
|
||||
class ElaCalendarTitleModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ElaCalendarTitleModel(QObject* parent = nullptr);
|
||||
~ElaCalendarTitleModel();
|
||||
|
||||
protected:
|
||||
virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
virtual QVariant data(const QModelIndex& index, int role) const override;
|
||||
};
|
||||
|
||||
#endif // ELACALENDARTITLEMODEL_H
|
||||
@@ -0,0 +1,63 @@
|
||||
#include "ElaCentralStackedWidget.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
|
||||
#include "ElaTheme.h"
|
||||
ElaCentralStackedWidget::ElaCentralStackedWidget(QWidget* parent)
|
||||
: QStackedWidget(parent)
|
||||
{
|
||||
setObjectName("ElaCentralStackedWidget");
|
||||
_themeMode = eTheme->getThemeMode();
|
||||
connect(eTheme, &ElaTheme::themeModeChanged, this, &ElaCentralStackedWidget::onThemeModeChanged);
|
||||
}
|
||||
|
||||
ElaCentralStackedWidget::~ElaCentralStackedWidget()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaCentralStackedWidget::onThemeModeChanged(ElaThemeType::ThemeMode themeMode)
|
||||
{
|
||||
_themeMode = themeMode;
|
||||
}
|
||||
|
||||
void ElaCentralStackedWidget::setIsTransparent(bool isTransparent)
|
||||
{
|
||||
this->_isTransparent = isTransparent;
|
||||
update();
|
||||
}
|
||||
|
||||
bool ElaCentralStackedWidget::getIsTransparent() const
|
||||
{
|
||||
return _isTransparent;
|
||||
}
|
||||
|
||||
void ElaCentralStackedWidget::setIsHasRadius(bool isHasRadius)
|
||||
{
|
||||
this->_isHasRadius = isHasRadius;
|
||||
update();
|
||||
}
|
||||
|
||||
void ElaCentralStackedWidget::paintEvent(QPaintEvent* event)
|
||||
{
|
||||
if (!_isTransparent)
|
||||
{
|
||||
QPainter painter(this);
|
||||
QRect targetRect = this->rect();
|
||||
targetRect.adjust(1, 1, 10, 10);
|
||||
painter.save();
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.setPen(QPen(ElaThemeColor(_themeMode, BasicBaseLine), 1.5));
|
||||
painter.setBrush(ElaThemeColor(_themeMode, WindowCentralStackBase));
|
||||
if (_isHasRadius)
|
||||
{
|
||||
painter.drawRoundedRect(targetRect, 10, 10);
|
||||
}
|
||||
else
|
||||
{
|
||||
painter.drawRect(targetRect);
|
||||
}
|
||||
painter.restore();
|
||||
}
|
||||
QStackedWidget::paintEvent(event);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef ELACENTRALSTACKEDWIDGET_H
|
||||
#define ELACENTRALSTACKEDWIDGET_H
|
||||
|
||||
#include <QStackedWidget>
|
||||
|
||||
#include "Def.h"
|
||||
class ElaCentralStackedWidget : public QStackedWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ElaCentralStackedWidget(QWidget* parent = nullptr);
|
||||
~ElaCentralStackedWidget();
|
||||
Q_SLOT void onThemeModeChanged(ElaThemeType::ThemeMode themeMode);
|
||||
|
||||
void setIsTransparent(bool isTransparent);
|
||||
bool getIsTransparent() const;
|
||||
|
||||
void setIsHasRadius(bool isHasRadius);
|
||||
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent* event) override;
|
||||
|
||||
private:
|
||||
ElaThemeType::ThemeMode _themeMode;
|
||||
bool _isTransparent{false};
|
||||
bool _isHasRadius{true};
|
||||
};
|
||||
|
||||
#endif // ELACENTRALSTACKEDWIDGET_H
|
||||
@@ -0,0 +1,131 @@
|
||||
#include "ElaCheckBoxStyle.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QPainter>
|
||||
#include <QStyleOption>
|
||||
|
||||
#include "ElaTheme.h"
|
||||
ElaCheckBoxStyle::ElaCheckBoxStyle(QStyle* style)
|
||||
{
|
||||
_pCheckIndicatorWidth = 21;
|
||||
_themeMode = eTheme->getThemeMode();
|
||||
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) { _themeMode = themeMode; });
|
||||
}
|
||||
|
||||
ElaCheckBoxStyle::~ElaCheckBoxStyle()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaCheckBoxStyle::drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const
|
||||
{
|
||||
// qDebug() << element << option->rect;
|
||||
switch (element)
|
||||
{
|
||||
case QStyle::CE_CheckBox:
|
||||
{
|
||||
if (const QStyleOptionButton* bopt = qstyleoption_cast<const QStyleOptionButton*>(option))
|
||||
{
|
||||
bool isEnabled = bopt->state.testFlag(QStyle::State_Enabled);
|
||||
painter->save();
|
||||
painter->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
|
||||
QRect checkBoxRect = bopt->rect;
|
||||
QRect checkRect(checkBoxRect.x(), checkBoxRect.y(), _pCheckIndicatorWidth, _pCheckIndicatorWidth);
|
||||
checkRect.adjust(1, 1, -1, -1);
|
||||
//复选框绘制
|
||||
painter->setPen(Qt::NoPen);
|
||||
if (bopt->state.testFlag(QStyle::State_On) || bopt->state.testFlag(QStyle::State_NoChange))
|
||||
{
|
||||
painter->setPen(Qt::NoPen);
|
||||
if (bopt->state.testFlag(QStyle::State_Sunken))
|
||||
{
|
||||
painter->setBrush(ElaThemeColor(_themeMode, PrimaryPress));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bopt->state.testFlag(QStyle::State_MouseOver))
|
||||
{
|
||||
painter->setBrush(ElaThemeColor(_themeMode, PrimaryHover));
|
||||
}
|
||||
else
|
||||
{
|
||||
painter->setBrush(ElaThemeColor(_themeMode, PrimaryNormal));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bopt->state.testFlag(QStyle::State_Sunken))
|
||||
{
|
||||
painter->setPen(ElaThemeColor(_themeMode, BasicBorderDeep));
|
||||
}
|
||||
else
|
||||
{
|
||||
painter->setPen(ElaThemeColor(_themeMode, BasicBorderDeep));
|
||||
if (bopt->state.testFlag(QStyle::State_MouseOver))
|
||||
{
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicHover));
|
||||
}
|
||||
else
|
||||
{
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicBase));
|
||||
}
|
||||
}
|
||||
}
|
||||
painter->drawRoundedRect(checkRect, 2, 2);
|
||||
//图标绘制
|
||||
painter->setPen(ElaThemeColor(ElaThemeType::Dark, BasicText));
|
||||
if (bopt->state.testFlag(QStyle::State_On))
|
||||
{
|
||||
painter->save();
|
||||
QFont iconFont = QFont("ElaAwesome");
|
||||
iconFont.setPixelSize(_pCheckIndicatorWidth * 0.75);
|
||||
painter->setFont(iconFont);
|
||||
painter->drawText(checkRect, Qt::AlignCenter, QChar((unsigned short)ElaIconType::Check));
|
||||
painter->restore();
|
||||
}
|
||||
else if (bopt->state.testFlag(QStyle::State_NoChange))
|
||||
{
|
||||
QLine checkLine(checkRect.x() + 3, checkRect.center().y(), checkRect.right() - 3, checkRect.center().y());
|
||||
painter->drawLine(checkLine);
|
||||
}
|
||||
//文字绘制
|
||||
painter->setPen(isEnabled ? ElaThemeColor(_themeMode, BasicText) : ElaThemeColor(_themeMode, BasicTextDisable));
|
||||
QRect textRect(checkRect.right() + 10, checkBoxRect.y(), checkBoxRect.width(), checkBoxRect.height());
|
||||
painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, bopt->text);
|
||||
painter->restore();
|
||||
}
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QProxyStyle::drawControl(element, option, painter, widget);
|
||||
}
|
||||
|
||||
int ElaCheckBoxStyle::pixelMetric(PixelMetric metric, const QStyleOption* option, const QWidget* widget) const
|
||||
{
|
||||
// qDebug() << metric << QProxyStyle::pixelMetric(metric, option, widget);
|
||||
switch (metric)
|
||||
{
|
||||
case QStyle::PM_IndicatorWidth:
|
||||
{
|
||||
return _pCheckIndicatorWidth;
|
||||
}
|
||||
case QStyle::PM_IndicatorHeight:
|
||||
{
|
||||
return _pCheckIndicatorWidth;
|
||||
}
|
||||
case QStyle::PM_CheckBoxLabelSpacing:
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QProxyStyle::pixelMetric(metric, option, widget);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef ELACHECKBOXSTYLE_H
|
||||
#define ELACHECKBOXSTYLE_H
|
||||
|
||||
#include <QProxyStyle>
|
||||
|
||||
#include "Def.h"
|
||||
class ElaCheckBoxStyle : public QProxyStyle
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PRIVATE_CREATE(int, CheckIndicatorWidth)
|
||||
public:
|
||||
explicit ElaCheckBoxStyle(QStyle* style = nullptr);
|
||||
~ElaCheckBoxStyle();
|
||||
void drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget = nullptr) const override;
|
||||
int pixelMetric(PixelMetric metric, const QStyleOption* option = nullptr, const QWidget* widget = nullptr) const override;
|
||||
|
||||
private:
|
||||
ElaThemeType::ThemeMode _themeMode;
|
||||
};
|
||||
|
||||
#endif // ELACHECKBOXSTYLE_H
|
||||
@@ -0,0 +1,53 @@
|
||||
#include "ElaColorDisplayDelegate.h"
|
||||
|
||||
#include <QColor>
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QStyleOption>
|
||||
|
||||
#include "ElaTheme.h"
|
||||
ElaColorDisplayDelegate::ElaColorDisplayDelegate(QObject* parent)
|
||||
: QStyledItemDelegate{parent}
|
||||
{
|
||||
_pThemeMode = eTheme->getThemeMode();
|
||||
}
|
||||
|
||||
ElaColorDisplayDelegate::~ElaColorDisplayDelegate()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaColorDisplayDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
painter->save();
|
||||
painter->setRenderHints(QPainter::Antialiasing);
|
||||
QRectF itemRect = option.rect;
|
||||
// 颜色球绘制
|
||||
QColor displayColor = index.data(Qt::UserRole).value<QColor>();
|
||||
if (displayColor.isValid())
|
||||
{
|
||||
painter->setPen(ElaThemeColor(_pThemeMode, PopupBorderHover));
|
||||
painter->setBrush(index.data(Qt::UserRole).value<QColor>());
|
||||
}
|
||||
else
|
||||
{
|
||||
QPen pen(ElaThemeColor(_pThemeMode, PopupBorderHover));
|
||||
pen.setStyle(Qt::DashLine);
|
||||
painter->setPen(pen);
|
||||
}
|
||||
painter->drawEllipse(itemRect.center(), 10, 10);
|
||||
|
||||
// 覆盖效果绘制
|
||||
if (option.state.testFlag(QStyle::State_MouseOver) || option.state.testFlag(QStyle::State_Selected))
|
||||
{
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
painter->drawEllipse(itemRect.center(), 13, 13);
|
||||
}
|
||||
|
||||
painter->restore();
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
}
|
||||
|
||||
QSize ElaColorDisplayDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
return QSize(30, 30);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef ELACOLORDISPLAYDELEGATE_H
|
||||
#define ELACOLORDISPLAYDELEGATE_H
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
#include "Def.h"
|
||||
class ElaColorDisplayDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PRIVATE_CREATE(ElaThemeType::ThemeMode, ThemeMode)
|
||||
public:
|
||||
explicit ElaColorDisplayDelegate(QObject* parent = nullptr);
|
||||
~ElaColorDisplayDelegate();
|
||||
|
||||
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
};
|
||||
|
||||
#endif // ELACOLORDISPLAYDELEGATE_H
|
||||
@@ -0,0 +1,74 @@
|
||||
#include "ElaColorDisplayModel.h"
|
||||
|
||||
ElaColorDisplayModel::ElaColorDisplayModel(QObject* parent)
|
||||
: QAbstractListModel{parent}
|
||||
{
|
||||
}
|
||||
|
||||
ElaColorDisplayModel::~ElaColorDisplayModel()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaColorDisplayModel::appendDisplayColor(QList<QColor> colorList)
|
||||
{
|
||||
beginResetModel();
|
||||
_displayColorList.append(colorList);
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void ElaColorDisplayModel::appendDisplayColor(QColor color)
|
||||
{
|
||||
beginResetModel();
|
||||
_displayColorList.append(color);
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void ElaColorDisplayModel::removeDisplayColor(int index)
|
||||
{
|
||||
if (index < 0 || index >= _displayColorList.count())
|
||||
{
|
||||
return;
|
||||
}
|
||||
beginResetModel();
|
||||
_displayColorList.removeAt(index);
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void ElaColorDisplayModel::replaceDisplayColor(QColor color, int index)
|
||||
{
|
||||
if (index < 0 || index >= _displayColorList.count())
|
||||
{
|
||||
return;
|
||||
}
|
||||
beginResetModel();
|
||||
_displayColorList[index] = color;
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
QList<QColor> ElaColorDisplayModel::getDisplayColorList() const
|
||||
{
|
||||
return _displayColorList;
|
||||
}
|
||||
|
||||
QColor ElaColorDisplayModel::getDisplayColor(int index) const
|
||||
{
|
||||
if (index < 0 || index >= _displayColorList.count())
|
||||
{
|
||||
return QColor();
|
||||
}
|
||||
return _displayColorList[index];
|
||||
}
|
||||
|
||||
int ElaColorDisplayModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
return _displayColorList.count();
|
||||
}
|
||||
|
||||
QVariant ElaColorDisplayModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
if (role == Qt::UserRole)
|
||||
{
|
||||
return QVariant::fromValue(_displayColorList[index.row()]);
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef ELACOLORDISPLAYMODEL_H
|
||||
#define ELACOLORDISPLAYMODEL_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QColor>
|
||||
class ElaColorDisplayModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ElaColorDisplayModel(QObject* parent = nullptr);
|
||||
~ElaColorDisplayModel();
|
||||
void appendDisplayColor(QList<QColor> colorList);
|
||||
void appendDisplayColor(QColor color);
|
||||
void removeDisplayColor(int index);
|
||||
void replaceDisplayColor(QColor color, int index);
|
||||
|
||||
QList<QColor> getDisplayColorList() const;
|
||||
QColor getDisplayColor(int index) const;
|
||||
|
||||
protected:
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex& index, int role) const override;
|
||||
|
||||
private:
|
||||
QList<QColor> _displayColorList;
|
||||
};
|
||||
|
||||
#endif // ELACOLORDISPLAYMODEL_H
|
||||
@@ -0,0 +1,120 @@
|
||||
#include "ElaColorPicker.h"
|
||||
|
||||
#include <QMouseEvent>
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
|
||||
#include "ElaTheme.h"
|
||||
ElaColorPicker::ElaColorPicker(QWidget* parent)
|
||||
: QWidget{parent}
|
||||
{
|
||||
setFixedSize(260, 260);
|
||||
_pThemeMode = eTheme->getThemeMode();
|
||||
// 初始化色相图
|
||||
QPixmap ColorPickerPix(QSize(257, 257));
|
||||
QImage ColorPickerImage = ColorPickerPix.toImage();
|
||||
for (int y = 0; y < ColorPickerImage.height(); y++)
|
||||
{
|
||||
for (int x = 0; x < ColorPickerImage.width(); x++)
|
||||
{
|
||||
QColor pixColor;
|
||||
pixColor.setHsvF((qreal)1 / ColorPickerPix.width() * x, 1 - (qreal)1 / ColorPickerPix.height() * y, 1);
|
||||
pixColor = pixColor.toRgb();
|
||||
ColorPickerImage.setPixelColor(x, y, pixColor);
|
||||
}
|
||||
}
|
||||
_colorPickerImage = ColorPickerImage;
|
||||
}
|
||||
|
||||
ElaColorPicker::~ElaColorPicker()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaColorPicker::setSelectedColor(QColor color)
|
||||
{
|
||||
_selectedColor = color;
|
||||
QColor hsvColor = color.toHsv();
|
||||
_selectedPoint = QPoint(257 * hsvColor.hue() / (qreal)360, 255 - 257 * hsvColor.saturation() / (qreal)255);
|
||||
update();
|
||||
}
|
||||
|
||||
QColor ElaColorPicker::getSelectedColor() const
|
||||
{
|
||||
return _selectedColor;
|
||||
}
|
||||
|
||||
void ElaColorPicker::mousePressEvent(QMouseEvent* event)
|
||||
{
|
||||
_selectedPoint = _adjustPointLimit(event->pos());
|
||||
_selectedColor = _colorPickerImage.pixelColor(_selectedPoint);
|
||||
Q_EMIT selectedColorChanged(_selectedColor);
|
||||
QWidget::mousePressEvent(event);
|
||||
update();
|
||||
}
|
||||
|
||||
void ElaColorPicker::mouseReleaseEvent(QMouseEvent* event)
|
||||
{
|
||||
_selectedPoint = _adjustPointLimit(event->pos());
|
||||
_selectedColor = _colorPickerImage.pixelColor(_selectedPoint);
|
||||
Q_EMIT selectedColorChanged(_selectedColor);
|
||||
QWidget::mouseReleaseEvent(event);
|
||||
update();
|
||||
}
|
||||
|
||||
void ElaColorPicker::mouseMoveEvent(QMouseEvent* event)
|
||||
{
|
||||
_selectedPoint = _adjustPointLimit(event->pos());
|
||||
_selectedColor = _colorPickerImage.pixelColor(_selectedPoint);
|
||||
Q_EMIT selectedColorChanged(_selectedColor);
|
||||
QWidget::mouseMoveEvent(event);
|
||||
update();
|
||||
}
|
||||
|
||||
void ElaColorPicker::paintEvent(QPaintEvent* event)
|
||||
{
|
||||
int penWidth = 3;
|
||||
int borderRadius = 5;
|
||||
QPainter painter(this);
|
||||
painter.save();
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
// 色相图绘制
|
||||
QRect pickerRect = rect();
|
||||
pickerRect.adjust(penWidth, penWidth, -penWidth, -penWidth);
|
||||
painter.setPen(QPen(ElaThemeColor(_pThemeMode, BasicBorder), penWidth));
|
||||
painter.drawRoundedRect(pickerRect, borderRadius, borderRadius);
|
||||
QPainterPath path;
|
||||
path.addRoundedRect(pickerRect, borderRadius, borderRadius);
|
||||
painter.setClipPath(path);
|
||||
painter.drawImage(pickerRect, _colorPickerImage);
|
||||
|
||||
// 取色点绘制
|
||||
if (!_selectedPoint.isNull())
|
||||
{
|
||||
painter.setPen(QPen(Qt::black, 2));
|
||||
painter.setBrush(Qt::NoBrush);
|
||||
painter.drawEllipse(_selectedPoint, 8, 8);
|
||||
}
|
||||
painter.restore();
|
||||
}
|
||||
|
||||
QPoint ElaColorPicker::_adjustPointLimit(QPoint point)
|
||||
{
|
||||
QRect pickerRect = rect();
|
||||
if (point.x() < 3)
|
||||
{
|
||||
point.setX(3);
|
||||
}
|
||||
else if (point.x() > pickerRect.right() - 3)
|
||||
{
|
||||
point.setX(pickerRect.right() - 3);
|
||||
}
|
||||
if (point.y() < 3)
|
||||
{
|
||||
point.setY(3);
|
||||
}
|
||||
else if (point.y() > pickerRect.bottom() - 3)
|
||||
{
|
||||
point.setY(pickerRect.bottom() - 3);
|
||||
}
|
||||
return point;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifndef ELACOLORPICKER_H
|
||||
#define ELACOLORPICKER_H
|
||||
|
||||
#include <QPixmap>
|
||||
#include <QWidget>
|
||||
|
||||
#include "Def.h"
|
||||
class ElaColorPicker : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PRIVATE_CREATE(ElaThemeType::ThemeMode, ThemeMode)
|
||||
|
||||
public:
|
||||
explicit ElaColorPicker(QWidget* parent = nullptr);
|
||||
~ElaColorPicker();
|
||||
|
||||
void setSelectedColor(QColor color);
|
||||
QColor getSelectedColor() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
Q_SIGNAL void selectedColorChanged(QColor selectedColor);
|
||||
|
||||
protected:
|
||||
virtual void mousePressEvent(QMouseEvent* event) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent* event) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent* event) override;
|
||||
virtual void paintEvent(QPaintEvent* event) override;
|
||||
|
||||
private:
|
||||
QImage _colorPickerImage;
|
||||
QPoint _selectedPoint;
|
||||
QColor _selectedColor;
|
||||
QPoint _adjustPointLimit(QPoint point);
|
||||
};
|
||||
|
||||
#endif // ELACOLORPICKER_H
|
||||
@@ -0,0 +1,31 @@
|
||||
#include "ElaColorPreview.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
|
||||
#include "ElaTheme.h"
|
||||
ElaColorPreview::ElaColorPreview(QWidget* parent)
|
||||
: QWidget{parent}
|
||||
{
|
||||
setFixedSize(50, 260);
|
||||
_pThemeMode = eTheme->getThemeMode();
|
||||
}
|
||||
|
||||
ElaColorPreview::~ElaColorPreview()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaColorPreview::paintEvent(QPaintEvent* event)
|
||||
{
|
||||
int penWidth = 3;
|
||||
int borderRadius = 5;
|
||||
QPainter painter(this);
|
||||
painter.save();
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
QRect viewRect = rect();
|
||||
viewRect.adjust(penWidth, penWidth, -penWidth, -penWidth);
|
||||
painter.setPen(QPen(ElaThemeColor(_pThemeMode, BasicBorder), penWidth));
|
||||
painter.setBrush(_pBaseColor);
|
||||
painter.drawRoundedRect(viewRect, borderRadius, borderRadius);
|
||||
painter.restore();
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef ELACOLORPREVIEW_H
|
||||
#define ELACOLORPREVIEW_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "Def.h"
|
||||
class ElaColorPreview : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PRIVATE_CREATE(QColor, BaseColor)
|
||||
Q_PRIVATE_CREATE(ElaThemeType::ThemeMode, ThemeMode)
|
||||
public:
|
||||
explicit ElaColorPreview(QWidget* parent = nullptr);
|
||||
~ElaColorPreview();
|
||||
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent* event) override;
|
||||
};
|
||||
|
||||
#endif // ELACOLORPREVIEW_H
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
#include "ElaColorValueSliderStyle.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPropertyAnimation>
|
||||
#include <QStyleOptionSlider>
|
||||
|
||||
#include "ElaTheme.h"
|
||||
ElaColorValueSliderStyle::ElaColorValueSliderStyle(QStyle* style)
|
||||
{
|
||||
_baseGradient = new QLinearGradient(0, 0, 100, 100);
|
||||
setProperty("circleRadius", 0.01);
|
||||
_themeMode = eTheme->getThemeMode();
|
||||
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) { _themeMode = themeMode; });
|
||||
}
|
||||
|
||||
ElaColorValueSliderStyle::~ElaColorValueSliderStyle()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaColorValueSliderStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget) const
|
||||
{
|
||||
switch (control)
|
||||
{
|
||||
case QStyle::CC_Slider:
|
||||
{
|
||||
const QStyleOptionSlider* sopt = qstyleoption_cast<const QStyleOptionSlider*>(option);
|
||||
if (!sopt)
|
||||
{
|
||||
break;
|
||||
}
|
||||
_baseGradient->setFinalStop(widget->rect().bottomRight());
|
||||
QColor highValueColor = _pBaseColor.toHsv();
|
||||
highValueColor.setHsv(highValueColor.hue(), highValueColor.saturation(), 255);
|
||||
QColor lowValueColor = _pBaseColor.toHsv();
|
||||
lowValueColor.setHsv(lowValueColor.hue(), lowValueColor.saturation(), 0);
|
||||
_baseGradient->setColorAt(0, highValueColor);
|
||||
_baseGradient->setColorAt(1, lowValueColor);
|
||||
painter->save();
|
||||
painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
|
||||
QRectF sliderRect = sopt->rect;
|
||||
sliderRect.adjust(1.5, 0, -1.5, 0);
|
||||
QRect sliderHandleRect = subControlRect(control, sopt, SC_SliderHandle, widget);
|
||||
sliderHandleRect.adjust(1, 1, -1, -1);
|
||||
// 滑槽
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(*_baseGradient);
|
||||
// 渐变背景
|
||||
painter->drawRoundedRect(QRectF(sliderRect.x(), sliderRect.y() + sliderRect.width() / 8, sliderRect.width(), sliderRect.height() - sliderRect.width() / 4), sliderRect.width() / 2, sliderRect.width() / 2);
|
||||
|
||||
// 滑块
|
||||
// 外圆形
|
||||
painter->setPen(ElaThemeColor(_themeMode, BasicBorder));
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicBase));
|
||||
painter->drawEllipse(QPointF(sliderHandleRect.center().x() + 1, sliderHandleRect.center().y() + 1), sliderHandleRect.width() / 2, sliderHandleRect.width() / 2);
|
||||
// 内圆形
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(ElaThemeColor(_themeMode, PrimaryNormal));
|
||||
if (_lastState == 0)
|
||||
{
|
||||
_lastState = sopt->state;
|
||||
}
|
||||
if (_circleRadius == 0)
|
||||
{
|
||||
_circleRadius = sliderHandleRect.width() / 3.8;
|
||||
}
|
||||
if (sopt->activeSubControls == SC_SliderHandle)
|
||||
{
|
||||
if (sopt->state & QStyle::State_Sunken)
|
||||
{
|
||||
if (sopt->state & QStyle::State_MouseOver)
|
||||
{
|
||||
if (!_lastState.testFlag(QStyle::State_Sunken))
|
||||
{
|
||||
_startRadiusAnimation(sliderHandleRect.width() / 2.8, sliderHandleRect.width() / 4.5, const_cast<QWidget*>(widget));
|
||||
_lastState = sopt->state;
|
||||
}
|
||||
painter->drawEllipse(QPointF(sliderHandleRect.center().x() + 1, sliderHandleRect.center().y() + 1), _circleRadius, _circleRadius);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sopt->state & QStyle::State_MouseOver)
|
||||
{
|
||||
if (!_lastState.testFlag(QStyle::State_MouseOver))
|
||||
{
|
||||
_startRadiusAnimation(_circleRadius, sliderHandleRect.width() / 2.8, const_cast<QWidget*>(widget));
|
||||
_lastState = sopt->state;
|
||||
}
|
||||
if (_lastState.testFlag(QStyle::State_Sunken))
|
||||
{
|
||||
_startRadiusAnimation(_circleRadius, sliderHandleRect.width() / 2.8, const_cast<QWidget*>(widget));
|
||||
_lastState = sopt->state;
|
||||
}
|
||||
painter->drawEllipse(QPointF(sliderHandleRect.center().x() + 1, sliderHandleRect.center().y() + 1), _circleRadius, _circleRadius);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_lastState.testFlag(QStyle::State_MouseOver) || _lastState.testFlag(QStyle::State_Sunken))
|
||||
{
|
||||
_startRadiusAnimation(_circleRadius, sliderHandleRect.width() / 3.8, const_cast<QWidget*>(widget));
|
||||
_lastState &= ~QStyle::State_MouseOver;
|
||||
_lastState &= ~QStyle::State_Sunken;
|
||||
}
|
||||
painter->drawEllipse(QPointF(sliderHandleRect.center().x() + 1, sliderHandleRect.center().y() + 1), _circleRadius, _circleRadius);
|
||||
}
|
||||
painter->restore();
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
QProxyStyle::drawComplexControl(control, option, painter, widget);
|
||||
}
|
||||
|
||||
int ElaColorValueSliderStyle::pixelMetric(PixelMetric metric, const QStyleOption* option, const QWidget* widget) const
|
||||
{
|
||||
switch (metric)
|
||||
{
|
||||
case QStyle::PM_SliderLength:
|
||||
{
|
||||
return 20;
|
||||
}
|
||||
case QStyle::PM_SliderThickness:
|
||||
{
|
||||
return 16;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QProxyStyle::pixelMetric(metric, option, widget);
|
||||
}
|
||||
|
||||
int ElaColorValueSliderStyle::styleHint(StyleHint hint, const QStyleOption* option, const QWidget* widget, QStyleHintReturn* returnData) const
|
||||
{
|
||||
if (hint == QStyle::SH_Slider_AbsoluteSetButtons)
|
||||
{
|
||||
return Qt::LeftButton;
|
||||
}
|
||||
return QProxyStyle::styleHint(hint, option, widget, returnData);
|
||||
}
|
||||
|
||||
void ElaColorValueSliderStyle::_startRadiusAnimation(qreal startRadius, qreal endRadius, QWidget* widget) const
|
||||
{
|
||||
ElaColorValueSliderStyle* style = const_cast<ElaColorValueSliderStyle*>(this);
|
||||
QPropertyAnimation* circleRadiusAnimation = new QPropertyAnimation(style, "circleRadius");
|
||||
connect(circleRadiusAnimation, &QPropertyAnimation::valueChanged, style, [=](const QVariant& value) {
|
||||
this->_circleRadius = value.toReal();
|
||||
widget->update(); });
|
||||
circleRadiusAnimation->setEasingCurve(QEasingCurve::InOutSine);
|
||||
circleRadiusAnimation->setStartValue(startRadius);
|
||||
circleRadiusAnimation->setEndValue(endRadius);
|
||||
circleRadiusAnimation->start(QAbstractAnimation::DeleteWhenStopped);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef ELACOLORVALUESLIDERSTYLE_H
|
||||
#define ELACOLORVALUESLIDERSTYLE_H
|
||||
|
||||
#include <QLinearGradient>
|
||||
#include <QProxyStyle>
|
||||
|
||||
#include "Def.h"
|
||||
class ElaColorValueSliderStyle : public QProxyStyle
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PRIVATE_CREATE(QColor, BaseColor)
|
||||
public:
|
||||
explicit ElaColorValueSliderStyle(QStyle* style = nullptr);
|
||||
~ElaColorValueSliderStyle();
|
||||
void drawComplexControl(ComplexControl control, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget = nullptr) const override;
|
||||
int pixelMetric(PixelMetric metric, const QStyleOption* option = nullptr, const QWidget* widget = nullptr) const override;
|
||||
int styleHint(StyleHint hint, const QStyleOption* option = nullptr, const QWidget* widget = nullptr, QStyleHintReturn* returnData = nullptr) const override;
|
||||
|
||||
private:
|
||||
ElaThemeType::ThemeMode _themeMode;
|
||||
QLinearGradient* _baseGradient{nullptr};
|
||||
mutable QStyle::State _lastState{0};
|
||||
mutable qreal _circleRadius{0};
|
||||
void _startRadiusAnimation(qreal startRadius, qreal endRadius, QWidget* widget) const;
|
||||
};
|
||||
|
||||
#endif // ELACOLORVALUESLIDERSTYLE_H
|
||||
@@ -0,0 +1,247 @@
|
||||
#include "ElaComboBoxStyle.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QStyleOption>
|
||||
|
||||
#include "ElaTheme.h"
|
||||
ElaComboBoxStyle::ElaComboBoxStyle(QStyle* style)
|
||||
{
|
||||
_pExpandIconRotate = 0;
|
||||
_pExpandMarkWidth = 0;
|
||||
_themeMode = eTheme->getThemeMode();
|
||||
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) { _themeMode = themeMode; });
|
||||
}
|
||||
|
||||
ElaComboBoxStyle::~ElaComboBoxStyle()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaComboBoxStyle::drawPrimitive(PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const
|
||||
{
|
||||
switch (element)
|
||||
{
|
||||
case QStyle::PE_Widget:
|
||||
{
|
||||
return;
|
||||
}
|
||||
#ifndef Q_OS_WIN
|
||||
case PE_PanelMenu:
|
||||
{
|
||||
return;
|
||||
}
|
||||
case PE_IndicatorArrowDown:
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
QProxyStyle::drawPrimitive(element, option, painter, widget);
|
||||
}
|
||||
|
||||
void ElaComboBoxStyle::drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const
|
||||
{
|
||||
switch (element)
|
||||
{
|
||||
case QStyle::CE_ComboBoxLabel:
|
||||
{
|
||||
return;
|
||||
}
|
||||
case QStyle::CE_ShapedFrame:
|
||||
{
|
||||
//container区域
|
||||
if (widget->objectName() == "ElaComboBoxContainer")
|
||||
{
|
||||
QRect viewRect = option->rect;
|
||||
painter->save();
|
||||
painter->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
|
||||
eTheme->drawEffectShadow(painter, viewRect, _shadowBorderWidth, 6);
|
||||
QRect foregroundRect(viewRect.x() + _shadowBorderWidth, viewRect.y(), viewRect.width() - 2 * _shadowBorderWidth, viewRect.height() - _shadowBorderWidth);
|
||||
painter->setPen(ElaThemeColor(_themeMode, PopupBorder));
|
||||
painter->setBrush(ElaThemeColor(_themeMode, PopupBase));
|
||||
painter->drawRoundedRect(foregroundRect, 3, 3);
|
||||
painter->restore();
|
||||
}
|
||||
return;
|
||||
}
|
||||
case QStyle::CE_ItemViewItem:
|
||||
{
|
||||
//覆盖高亮
|
||||
if (const QStyleOptionViewItem* vopt = qstyleoption_cast<const QStyleOptionViewItem*>(option))
|
||||
{
|
||||
int margin = 2;
|
||||
painter->save();
|
||||
painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
|
||||
painter->setPen(Qt::NoPen);
|
||||
QPainterPath path;
|
||||
QRect optionRect = option->rect;
|
||||
optionRect.adjust(margin, margin, -margin, -margin);
|
||||
#ifndef Q_OS_WIN
|
||||
optionRect.adjust(6, 0, -6, 0);
|
||||
#endif
|
||||
path.addRoundedRect(optionRect, 5, 5);
|
||||
if (option->state & QStyle::State_Selected)
|
||||
{
|
||||
if (option->state & QStyle::State_MouseOver)
|
||||
{
|
||||
// 选中时覆盖
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicSelectedHoverAlpha));
|
||||
painter->drawPath(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 选中
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicSelectedAlpha));
|
||||
painter->drawPath(path);
|
||||
}
|
||||
//选中Mark
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(ElaThemeColor(_themeMode, PrimaryNormal));
|
||||
painter->drawRoundedRect(QRectF(optionRect.x() + 3, optionRect.y() + optionRect.height() * 0.2, 3, optionRect.height() - +optionRect.height() * 0.4), 2, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (option->state & QStyle::State_MouseOver)
|
||||
{
|
||||
// 覆盖时颜色
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicHoverAlpha));
|
||||
painter->drawPath(path);
|
||||
}
|
||||
}
|
||||
// 文字绘制
|
||||
painter->setPen(ElaThemeColor(_themeMode, BasicText));
|
||||
painter->drawText(QRect(option->rect.x() + 15, option->rect.y(), option->rect.width() - 15, option->rect.height()), Qt::AlignVCenter, vopt->text);
|
||||
painter->restore();
|
||||
}
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
QProxyStyle::drawControl(element, option, painter, widget);
|
||||
}
|
||||
|
||||
void ElaComboBoxStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget) const
|
||||
{
|
||||
switch (control)
|
||||
{
|
||||
case QStyle::CC_ComboBox:
|
||||
{
|
||||
//主体显示绘制
|
||||
if (const QStyleOptionComboBox* copt = qstyleoption_cast<const QStyleOptionComboBox*>(option))
|
||||
{
|
||||
painter->save();
|
||||
painter->setRenderHints(QPainter::SmoothPixmapTransform | QPainter::Antialiasing | QPainter::TextAntialiasing);
|
||||
//背景绘制
|
||||
bool isEnabled = copt->state.testFlag(QStyle::State_Enabled);
|
||||
painter->setPen(ElaThemeColor(_themeMode, BasicBorder));
|
||||
painter->setBrush(isEnabled ? copt->state.testFlag(QStyle::State_MouseOver) ? ElaThemeColor(_themeMode, BasicHover) : ElaThemeColor(_themeMode, BasicBase) : ElaThemeColor(_themeMode, BasicDisable));
|
||||
QRect comboBoxRect = copt->rect;
|
||||
comboBoxRect.adjust(_shadowBorderWidth, 1, -_shadowBorderWidth, -1);
|
||||
painter->drawRoundedRect(comboBoxRect, 3, 3);
|
||||
// 底边线绘制
|
||||
painter->setPen(ElaThemeColor(_themeMode, BasicBaseLine));
|
||||
painter->drawLine(comboBoxRect.x() + 3, comboBoxRect.y() + comboBoxRect.height(), comboBoxRect.x() + comboBoxRect.width() - 3, comboBoxRect.y() + comboBoxRect.height());
|
||||
|
||||
//文字绘制
|
||||
QRect textRect = subControlRect(QStyle::CC_ComboBox, copt, QStyle::SC_ScrollBarSubLine, widget);
|
||||
painter->setPen(isEnabled ? ElaThemeColor(_themeMode, BasicText) : ElaThemeColor(_themeMode, BasicTextDisable));
|
||||
painter->drawText(textRect, Qt::AlignVCenter | Qt::AlignLeft, copt->currentText);
|
||||
//展开指示器绘制
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(ElaThemeColor(_themeMode, PrimaryNormal));
|
||||
painter->drawRoundedRect(QRectF(comboBoxRect.center().x() - _pExpandMarkWidth, comboBoxRect.y() + comboBoxRect.height() - 3, _pExpandMarkWidth * 2, 3), 2, 2);
|
||||
// 展开图标绘制
|
||||
QRect expandIconRect = subControlRect(QStyle::CC_ComboBox, copt, QStyle::SC_ScrollBarAddPage, widget);
|
||||
if (expandIconRect.isValid())
|
||||
{
|
||||
QFont iconFont = QFont("ElaAwesome");
|
||||
iconFont.setPixelSize(17);
|
||||
painter->setFont(iconFont);
|
||||
painter->setPen(isEnabled ? ElaThemeColor(_themeMode, BasicText) : ElaThemeColor(_themeMode, BasicTextDisable));
|
||||
painter->translate(expandIconRect.x() + (qreal)expandIconRect.width() / 2, expandIconRect.y() + (qreal)expandIconRect.height() / 2);
|
||||
painter->rotate(_pExpandIconRotate);
|
||||
painter->translate(-expandIconRect.x() - (qreal)expandIconRect.width() / 2, -expandIconRect.y() - (qreal)expandIconRect.height() / 2);
|
||||
painter->drawText(expandIconRect, Qt::AlignCenter, QChar((unsigned short)ElaIconType::AngleDown));
|
||||
painter->restore();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
QProxyStyle::drawComplexControl(control, option, painter, widget);
|
||||
}
|
||||
|
||||
QRect ElaComboBoxStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex* opt, SubControl sc, const QWidget* widget) const
|
||||
{
|
||||
switch (cc)
|
||||
{
|
||||
case QStyle::CC_ComboBox:
|
||||
{
|
||||
switch (sc)
|
||||
{
|
||||
case QStyle::SC_ScrollBarSubLine:
|
||||
{
|
||||
//文字区域
|
||||
QRect textRect = QProxyStyle::subControlRect(cc, opt, sc, widget);
|
||||
textRect.setLeft(16);
|
||||
textRect.setRight(textRect.right() - 15);
|
||||
return textRect;
|
||||
}
|
||||
case QStyle::SC_ScrollBarAddPage:
|
||||
{
|
||||
//展开图标区域
|
||||
QRect expandIconRect = QProxyStyle::subControlRect(cc, opt, sc, widget);
|
||||
expandIconRect.setLeft(expandIconRect.left() - 25);
|
||||
return expandIconRect;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return QProxyStyle::subControlRect(cc, opt, sc, widget);
|
||||
}
|
||||
|
||||
QSize ElaComboBoxStyle::sizeFromContents(ContentsType type, const QStyleOption* option, const QSize& size, const QWidget* widget) const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case QStyle::CT_ItemViewItem:
|
||||
{
|
||||
QSize itemSize = QProxyStyle::sizeFromContents(type, option, size, widget);
|
||||
itemSize.setHeight(35);
|
||||
return itemSize;
|
||||
}
|
||||
case QStyle::CT_ComboBox:
|
||||
{
|
||||
QSize comboBoxSize = QProxyStyle::sizeFromContents(type, option, size, widget);
|
||||
comboBoxSize.setWidth(comboBoxSize.width() + 26);
|
||||
return comboBoxSize;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QProxyStyle::sizeFromContents(type, option, size, widget);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef ELACOMBOBOXSTYLE_H
|
||||
#define ELACOMBOBOXSTYLE_H
|
||||
|
||||
#include <QProxyStyle>
|
||||
|
||||
#include "Def.h"
|
||||
class ElaComboBoxStyle : public QProxyStyle
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_CREATE(qreal, ExpandIconRotate)
|
||||
Q_PROPERTY_CREATE(qreal, ExpandMarkWidth)
|
||||
public:
|
||||
explicit ElaComboBoxStyle(QStyle* style = nullptr);
|
||||
~ElaComboBoxStyle();
|
||||
void drawPrimitive(PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget = nullptr) const override;
|
||||
void drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget = nullptr) const override;
|
||||
void drawComplexControl(ComplexControl control, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget = nullptr) const override;
|
||||
|
||||
QRect subControlRect(ComplexControl cc, const QStyleOptionComplex* opt, SubControl sc, const QWidget* widget) const override;
|
||||
QSize sizeFromContents(ContentsType type, const QStyleOption* option, const QSize& size, const QWidget* widget) const override;
|
||||
|
||||
private:
|
||||
ElaThemeType::ThemeMode _themeMode;
|
||||
int _shadowBorderWidth{6};
|
||||
};
|
||||
|
||||
#endif // ELACOMBOBOXSTYLE_H
|
||||
@@ -0,0 +1,22 @@
|
||||
#include "ElaComboBoxView.h"
|
||||
|
||||
#include <QMouseEvent>
|
||||
|
||||
ElaComboBoxView::ElaComboBoxView(QWidget* parent)
|
||||
: QListView(parent)
|
||||
{
|
||||
}
|
||||
|
||||
ElaComboBoxView::~ElaComboBoxView()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaComboBoxView::mousePressEvent(QMouseEvent* event)
|
||||
{
|
||||
QModelIndex index = indexAt(event->pos());
|
||||
if (index.isValid())
|
||||
{
|
||||
Q_EMIT itemPressed(index);
|
||||
}
|
||||
event->ignore();
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef ELACOMBOBOXVIEW_H
|
||||
#define ELACOMBOBOXVIEW_H
|
||||
|
||||
#include <QListView>
|
||||
|
||||
class ElaComboBoxView : public QListView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ElaComboBoxView(QWidget* parent = nullptr);
|
||||
~ElaComboBoxView();
|
||||
Q_SIGNALS:
|
||||
Q_SIGNAL void itemPressed(const QModelIndex& index);
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QMouseEvent* event) override;
|
||||
};
|
||||
|
||||
#endif // ELACOMBOBOXVIEW_H
|
||||
@@ -0,0 +1,77 @@
|
||||
#include "ElaCustomTabWidget.h"
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QVariant>
|
||||
|
||||
#include "ElaAppBar.h"
|
||||
#include "ElaTabBar.h"
|
||||
#include "ElaTabWidget.h"
|
||||
#include "ElaTabWidgetPrivate.h"
|
||||
ElaCustomTabWidget::ElaCustomTabWidget(QWidget* parent)
|
||||
: ElaCustomWidget(parent)
|
||||
{
|
||||
resize(700, 500);
|
||||
setWindowTitle("");
|
||||
setWindowIcon(QIcon());
|
||||
_customTabWidget = new ElaTabWidget(this);
|
||||
QTabBar* originTabBar = _customTabWidget->tabBar();
|
||||
originTabBar->hide();
|
||||
_customTabBar = new ElaTabBar(this);
|
||||
_customTabBar->setObjectName("ElaCustomTabBar");
|
||||
connect(_customTabBar, &ElaTabBar::tabMoved, this, [=](int from, int to) {
|
||||
_customTabWidget->tabBar()->moveTab(from, to);
|
||||
});
|
||||
connect(_customTabBar, &ElaTabBar::currentChanged, this, [=](int index) {
|
||||
_customTabWidget->setCurrentIndex(index);
|
||||
});
|
||||
connect(_customTabWidget, &ElaTabWidget::currentChanged, this, [=](int index) {
|
||||
if (index == -1)
|
||||
{
|
||||
close();
|
||||
}
|
||||
});
|
||||
connect(_customTabBar, &ElaTabBar::tabCloseRequested, originTabBar, &QTabBar::tabCloseRequested);
|
||||
|
||||
QWidget* customWidget = new QWidget(this);
|
||||
QVBoxLayout* customLayout = new QVBoxLayout(customWidget);
|
||||
customLayout->setContentsMargins(10, 0, 10, 0);
|
||||
customLayout->addStretch();
|
||||
customLayout->addWidget(_customTabBar);
|
||||
_appBar->setCustomWidget(ElaAppBarType::LeftArea, customWidget);
|
||||
setCentralWidget(_customTabWidget);
|
||||
}
|
||||
|
||||
ElaCustomTabWidget::~ElaCustomTabWidget()
|
||||
{
|
||||
while (_customTabWidget->count() > 0)
|
||||
{
|
||||
QWidget* closeWidget = _customTabWidget->widget(0);
|
||||
ElaTabWidget* originTabWidget = closeWidget->property("ElaOriginTabWidget").value<ElaTabWidget*>();
|
||||
|
||||
if (originTabWidget)
|
||||
{
|
||||
closeWidget->setProperty("CurrentCustomBar", QVariant::fromValue<ElaTabBar*>(nullptr));
|
||||
originTabWidget->addTab(closeWidget, _customTabWidget->tabIcon(0), _customTabWidget->tabText(0));
|
||||
}
|
||||
else
|
||||
{
|
||||
_customTabWidget->removeTab(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ElaCustomTabWidget::addTab(QWidget* widget, QIcon& tabIcon, const QString& tabTitle)
|
||||
{
|
||||
_customTabBar->addTab(tabIcon, tabTitle);
|
||||
_customTabWidget->addTab(widget, tabIcon, tabTitle);
|
||||
}
|
||||
|
||||
ElaTabBar* ElaCustomTabWidget::getCustomTabBar() const
|
||||
{
|
||||
return _customTabBar;
|
||||
}
|
||||
|
||||
ElaTabWidget* ElaCustomTabWidget::getCustomTabWidget() const
|
||||
{
|
||||
return _customTabWidget;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef ELACUSTOMTABWIDGET_H
|
||||
#define ELACUSTOMTABWIDGET_H
|
||||
|
||||
#include "ElaCustomWidget.h"
|
||||
|
||||
class ElaTabBar;
|
||||
class ElaTabWidget;
|
||||
class ElaCustomTabWidget : public ElaCustomWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ElaCustomTabWidget(QWidget* parent = nullptr);
|
||||
~ElaCustomTabWidget();
|
||||
void addTab(QWidget* widget, QIcon& tabIcon, const QString& tabTitle);
|
||||
ElaTabBar* getCustomTabBar() const;
|
||||
ElaTabWidget* getCustomTabWidget() const;
|
||||
|
||||
private:
|
||||
ElaTabBar* _customTabBar{nullptr};
|
||||
ElaTabWidget* _customTabWidget{nullptr};
|
||||
};
|
||||
|
||||
#endif // ELACUSTOMTABWIDGET_H
|
||||
@@ -0,0 +1,62 @@
|
||||
#include "ElaCustomWidget.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "ElaApplication.h"
|
||||
#include "ElaTheme.h"
|
||||
Q_TAKEOVER_NATIVEEVENT_CPP(ElaCustomWidget, _appBar);
|
||||
ElaCustomWidget::ElaCustomWidget(QWidget* parent)
|
||||
: QDialog{parent}
|
||||
{
|
||||
resize(500, 500); // 默认宽高
|
||||
setObjectName("ElaCustomWidget");
|
||||
// 自定义AppBar
|
||||
_appBar = new ElaAppBar(this);
|
||||
_appBar->setWindowButtonFlags(ElaAppBarType::MinimizeButtonHint | ElaAppBarType::MaximizeButtonHint | ElaAppBarType::CloseButtonHint);
|
||||
_mainLayout = new QVBoxLayout(this);
|
||||
_mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
_themeMode = eTheme->getThemeMode();
|
||||
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) {
|
||||
_themeMode = themeMode;
|
||||
update();
|
||||
});
|
||||
|
||||
_isEnableMica = eApp->getIsEnableMica();
|
||||
connect(eApp, &ElaApplication::pIsEnableMicaChanged, this, [=]() {
|
||||
_isEnableMica = eApp->getIsEnableMica();
|
||||
update();
|
||||
});
|
||||
eApp->syncMica(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
}
|
||||
|
||||
ElaCustomWidget::~ElaCustomWidget()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaCustomWidget::setCentralWidget(QWidget* widget)
|
||||
{
|
||||
if (!widget)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_centralWidget = widget;
|
||||
_mainLayout->addWidget(widget);
|
||||
widget->setVisible(true);
|
||||
}
|
||||
|
||||
void ElaCustomWidget::paintEvent(QPaintEvent* event)
|
||||
{
|
||||
if (!_isEnableMica)
|
||||
{
|
||||
QPainter painter(this);
|
||||
painter.save();
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.setBrush(ElaThemeColor(_themeMode, WindowBase));
|
||||
painter.drawRect(rect());
|
||||
painter.restore();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifndef ELACUSTOMWIDGET_H
|
||||
#define ELACUSTOMWIDGET_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
#include "Def.h"
|
||||
#include "ElaAppBar.h"
|
||||
|
||||
class QVBoxLayout;
|
||||
class ElaCustomWidget : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_TAKEOVER_NATIVEEVENT_H
|
||||
public:
|
||||
explicit ElaCustomWidget(QWidget* parent = nullptr);
|
||||
~ElaCustomWidget();
|
||||
|
||||
void setCentralWidget(QWidget* widget);
|
||||
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent* event) override;
|
||||
QVBoxLayout* _mainLayout{nullptr};
|
||||
ElaAppBar* _appBar{nullptr};
|
||||
QWidget* _centralWidget{nullptr};
|
||||
|
||||
private:
|
||||
ElaThemeType::ThemeMode _themeMode;
|
||||
bool _isEnableMica;
|
||||
};
|
||||
|
||||
#endif // ELACUSTOMWIDGET_H
|
||||
@@ -0,0 +1,88 @@
|
||||
#include "ElaDockWidgetTitleBar.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QPainter>
|
||||
|
||||
#include "ElaDockWidget.h"
|
||||
#include "ElaIconButton.h"
|
||||
#include "ElaText.h"
|
||||
#include "ElaTheme.h"
|
||||
ElaDockWidgetTitleBar::ElaDockWidgetTitleBar(QWidget* parent)
|
||||
: QWidget{parent}
|
||||
{
|
||||
_dockWidget = dynamic_cast<ElaDockWidget*>(parent);
|
||||
_iconLabel = new QLabel(this);
|
||||
_iconLabel->setPixmap(_dockWidget->windowIcon().pixmap(QSize(18, 18)));
|
||||
_titleLabel = new ElaText(_dockWidget->windowTitle(), this);
|
||||
_titleLabel->setWordWrap(false);
|
||||
_titleLabel->setTextPixelSize(13);
|
||||
|
||||
_floatButton = new ElaIconButton(ElaIconType::WindowRestore, 13, 32, 26, this);
|
||||
_floatButton->setLightHoverColor(ElaThemeColor(ElaThemeType::Light, BasicHoverAlpha));
|
||||
_floatButton->setDarkHoverColor(ElaThemeColor(ElaThemeType::Dark, BasicHoverAlpha));
|
||||
connect(_floatButton, &ElaIconButton::clicked, this, &ElaDockWidgetTitleBar::onFloatButtonClicked);
|
||||
_closeButton = new ElaIconButton(ElaIconType::Xmark, 17, 32, 26, this);
|
||||
_closeButton->setLightHoverColor(ElaThemeColor(ElaThemeType::Light, StatusDanger));
|
||||
_closeButton->setDarkHoverColor(ElaThemeColor(ElaThemeType::Dark, StatusDanger));
|
||||
connect(_closeButton, &ElaIconButton::clicked, this, &ElaDockWidgetTitleBar::onCloseButtonClicked);
|
||||
|
||||
_setVisibleFromFeatures(_dockWidget->features());
|
||||
connect(_dockWidget, &QDockWidget::featuresChanged, this, [=](QDockWidget::DockWidgetFeatures features) {
|
||||
_setVisibleFromFeatures(features);
|
||||
});
|
||||
connect(_dockWidget, &QDockWidget::windowTitleChanged, this, [=](const QString& title) {
|
||||
_titleLabel->setText(title);
|
||||
});
|
||||
connect(_dockWidget, &QDockWidget::windowIconChanged, this, [=](const QIcon& icon) {
|
||||
_iconLabel->setPixmap(icon.pixmap(QSize(18, 18)));
|
||||
});
|
||||
|
||||
QHBoxLayout* mainLayout = new QHBoxLayout(this);
|
||||
mainLayout->setSpacing(0);
|
||||
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||
mainLayout->addSpacing(5);
|
||||
mainLayout->addWidget(_iconLabel);
|
||||
mainLayout->addSpacing(10);
|
||||
mainLayout->addWidget(_titleLabel);
|
||||
mainLayout->addSpacing(10);
|
||||
mainLayout->addStretch();
|
||||
mainLayout->addWidget(_floatButton);
|
||||
mainLayout->addWidget(_closeButton);
|
||||
|
||||
//主题变更
|
||||
_themeMode = eTheme->getThemeMode();
|
||||
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) {
|
||||
_themeMode = themeMode;
|
||||
});
|
||||
}
|
||||
|
||||
ElaDockWidgetTitleBar::~ElaDockWidgetTitleBar()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaDockWidgetTitleBar::onFloatButtonClicked()
|
||||
{
|
||||
_dockWidget->setFloating(_dockWidget->isFloating() ? false : true);
|
||||
}
|
||||
|
||||
void ElaDockWidgetTitleBar::onCloseButtonClicked()
|
||||
{
|
||||
_dockWidget->close();
|
||||
}
|
||||
|
||||
void ElaDockWidgetTitleBar::paintEvent(QPaintEvent* event)
|
||||
{
|
||||
QPainter painter(this);
|
||||
painter.save();
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.setBrush(_dockWidget->isFloating() ? Qt::transparent : ElaThemeColor(_themeMode, BasicBaseAlpha));
|
||||
painter.drawRect(rect());
|
||||
painter.restore();
|
||||
}
|
||||
|
||||
void ElaDockWidgetTitleBar::_setVisibleFromFeatures(QDockWidget::DockWidgetFeatures features)
|
||||
{
|
||||
_floatButton->setVisible(features.testFlag(QDockWidget::DockWidgetFloatable));
|
||||
_closeButton->setVisible(features.testFlag(QDockWidget::DockWidgetClosable));
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifndef ELADOCKWIDGETTITLEBAR_H
|
||||
#define ELADOCKWIDGETTITLEBAR_H
|
||||
|
||||
#include <QDockWidget>
|
||||
#include <QLabel>
|
||||
#include <QWidget>
|
||||
|
||||
#include "Def.h"
|
||||
class ElaText;
|
||||
class ElaIconButton;
|
||||
class ElaDockWidget;
|
||||
class ElaDockWidgetTitleBar : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ElaDockWidgetTitleBar(QWidget* parent = nullptr);
|
||||
~ElaDockWidgetTitleBar();
|
||||
|
||||
Q_SLOT void onFloatButtonClicked();
|
||||
Q_SLOT void onCloseButtonClicked();
|
||||
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent* event) override;
|
||||
|
||||
private:
|
||||
friend class ElaDockWidgetPrivate;
|
||||
ElaThemeType::ThemeMode _themeMode;
|
||||
ElaDockWidget* _dockWidget{nullptr};
|
||||
QLabel* _iconLabel{nullptr};
|
||||
ElaText* _titleLabel{nullptr};
|
||||
ElaIconButton* _floatButton{nullptr};
|
||||
ElaIconButton* _closeButton{nullptr};
|
||||
void _setVisibleFromFeatures(QDockWidget::DockWidgetFeatures features);
|
||||
};
|
||||
|
||||
#endif // ELADOCKWIDGETTITLEBAR_H
|
||||
@@ -0,0 +1,322 @@
|
||||
#include "ElaDxgi.h"
|
||||
#ifdef Q_OS_WIN
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
|
||||
ElaDxgi::ElaDxgi(QObject* parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
_pIsInitSuccess = false;
|
||||
_pIsGrabActive = false;
|
||||
_pGrabFrameRate = 120;
|
||||
_pTimeoutMsValue = 50;
|
||||
_pIsGrabStoped = true;
|
||||
_pIsGrabCenter = false;
|
||||
}
|
||||
|
||||
ElaDxgi::~ElaDxgi()
|
||||
{
|
||||
releaseInterface();
|
||||
}
|
||||
|
||||
bool ElaDxgi::initialize(int dxID, int outputID)
|
||||
{
|
||||
_pIsInitSuccess = false;
|
||||
_pDxDeviceID = dxID;
|
||||
_pOutputDeviceID = outputID;
|
||||
releaseInterface();
|
||||
ID3D11Device* d3dDevice = nullptr;
|
||||
ID3D11DeviceContext* d3dContext = nullptr;
|
||||
D3D_FEATURE_LEVEL feat = D3D_FEATURE_LEVEL_11_0;
|
||||
HRESULT hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, nullptr, 0,
|
||||
D3D11_SDK_VERSION, &d3dDevice, &feat, &d3dContext);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
_pLastError = "Failed to D3D11CreateDevice ErrorCode = " + QString::number(uint(hr), 16);
|
||||
qDebug() << _pLastError;
|
||||
if (d3dDevice)
|
||||
{
|
||||
d3dDevice->Release();
|
||||
}
|
||||
if (d3dContext)
|
||||
{
|
||||
d3dContext->Release();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
IDXGIFactory* dxgiFactory = nullptr;
|
||||
CreateDXGIFactory(__uuidof(dxgiFactory), reinterpret_cast<void**>(&dxgiFactory));
|
||||
IDXGIAdapter* dxgiAdapter = nullptr;
|
||||
QVector<IDXGIAdapter*> dxgiAdapterVector;
|
||||
for (uint i = 0; dxgiFactory->EnumAdapters(i, &dxgiAdapter) != DXGI_ERROR_NOT_FOUND; ++i)
|
||||
{
|
||||
dxgiAdapterVector.append(dxgiAdapter);
|
||||
}
|
||||
dxgiFactory->Release();
|
||||
dxgiAdapter = nullptr;
|
||||
_pDxDeviceList.clear();
|
||||
for (int i = 0; i < dxgiAdapterVector.count(); i++)
|
||||
{
|
||||
IDXGIAdapter* adapt = dxgiAdapterVector.at(i);
|
||||
DXGI_ADAPTER_DESC desc;
|
||||
adapt->GetDesc(&desc);
|
||||
_pDxDeviceList.append(QString::fromWCharArray(desc.Description));
|
||||
}
|
||||
if (dxID >= 0 && dxID < dxgiAdapterVector.count())
|
||||
{
|
||||
dxgiAdapter = dxgiAdapterVector.at(dxID);
|
||||
}
|
||||
|
||||
if (!dxgiAdapter)
|
||||
{
|
||||
_pLastError = "Failed to found gpu";
|
||||
qDebug() << _pLastError;
|
||||
d3dDevice->Release();
|
||||
d3dContext->Release();
|
||||
for (auto adapter: dxgiAdapterVector)
|
||||
{
|
||||
adapter->Release();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
IDXGIOutput* dxgiOutput = nullptr;
|
||||
QVector<IDXGIOutput*> dxgiOutputVector;
|
||||
for (uint i = 0; dxgiAdapter->EnumOutputs(i, &dxgiOutput) != DXGI_ERROR_NOT_FOUND; ++i)
|
||||
{
|
||||
dxgiOutputVector.append(dxgiOutput);
|
||||
}
|
||||
for (auto adapter: dxgiAdapterVector)
|
||||
{
|
||||
adapter->Release();
|
||||
}
|
||||
dxgiOutput = nullptr;
|
||||
_pOutputDeviceList.clear();
|
||||
for (int i = 0; i < dxgiOutputVector.count(); i++)
|
||||
{
|
||||
const auto& output = dxgiOutputVector.at(i);
|
||||
DXGI_OUTPUT_DESC desc;
|
||||
output->GetDesc(&desc);
|
||||
_pOutputDeviceList.append(QString::fromWCharArray(desc.DeviceName));
|
||||
}
|
||||
if (outputID >= 0 && outputID < dxgiOutputVector.count())
|
||||
{
|
||||
dxgiOutput = dxgiOutputVector.at(outputID);
|
||||
}
|
||||
|
||||
if (!dxgiOutput)
|
||||
{
|
||||
_pLastError = "Failed to found screen!";
|
||||
qDebug() << _pLastError;
|
||||
d3dDevice->Release();
|
||||
d3dContext->Release();
|
||||
for (auto output: dxgiOutputVector)
|
||||
{
|
||||
output->Release();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
IDXGIOutput6* dxgiOutput6 = nullptr;
|
||||
hr = dxgiOutput->QueryInterface(__uuidof(IDXGIOutput6), reinterpret_cast<void**>(&dxgiOutput6));
|
||||
for (auto output: dxgiOutputVector)
|
||||
{
|
||||
output->Release();
|
||||
}
|
||||
if (FAILED(hr))
|
||||
{
|
||||
_pLastError = "Failed to QueryInterface IDXGIOutput6 ErrorCode = " + QString::number(uint(hr), 16);
|
||||
qDebug() << _pLastError;
|
||||
d3dDevice->Release();
|
||||
d3dContext->Release();
|
||||
dxgiOutput6->Release();
|
||||
return false;
|
||||
}
|
||||
UINT supportedFormatsCount = 1; // 支持的格式数
|
||||
DXGI_FORMAT supportedFormats[1] = {DXGI_FORMAT_B8G8R8A8_UNORM};
|
||||
hr = dxgiOutput6->DuplicateOutput1(d3dDevice, 0, supportedFormatsCount, supportedFormats, &_duplication);
|
||||
dxgiOutput6->Release();
|
||||
if (FAILED(hr))
|
||||
{
|
||||
_pLastError = "Failed to DuplicateOutput ErrorCode = " + QString::number(uint(hr), 16);
|
||||
qDebug() << _pLastError;
|
||||
d3dDevice->Release();
|
||||
d3dContext->Release();
|
||||
if (_duplication)
|
||||
{
|
||||
_duplication->Release();
|
||||
_duplication = nullptr;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
_device = d3dDevice;
|
||||
_context = d3dContext;
|
||||
_pIsInitSuccess = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
QImage ElaDxgi::getGrabImage() const
|
||||
{
|
||||
QImage grabImage(_imageBits, _descWidth, _descHeight, QImage::Format_ARGB32);
|
||||
if (_pIsGrabCenter)
|
||||
{
|
||||
return grabImage.copy(QRect((_descWidth - _pGrabArea.width()) / 2, (_descHeight - _pGrabArea.height()) / 2, _pGrabArea.width(), _pGrabArea.height()));
|
||||
}
|
||||
else
|
||||
{
|
||||
return grabImage.copy(_pGrabArea);
|
||||
}
|
||||
}
|
||||
|
||||
void ElaDxgi::onGrabScreen()
|
||||
{
|
||||
qreal startTime = 0;
|
||||
qreal endTime = 0;
|
||||
if (!_duplication || !_device || !_context)
|
||||
{
|
||||
setIsGrabStoped(true);
|
||||
return;
|
||||
}
|
||||
_pIsGrabStoped = false;
|
||||
while (_pIsGrabActive)
|
||||
{
|
||||
IDXGIResource* desktopRes = nullptr;
|
||||
DXGI_OUTDUPL_FRAME_INFO frameInfo;
|
||||
while (true)
|
||||
{
|
||||
if (!_pIsGrabActive)
|
||||
{
|
||||
setIsGrabStoped(true);
|
||||
return;
|
||||
}
|
||||
startTime = QDateTime::currentMSecsSinceEpoch();
|
||||
_duplication->ReleaseFrame();
|
||||
HRESULT hr = _duplication->AcquireNextFrame(_pTimeoutMsValue, &frameInfo, &desktopRes);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
if (hr != DXGI_ERROR_WAIT_TIMEOUT)
|
||||
{
|
||||
if (desktopRes)
|
||||
{
|
||||
desktopRes->Release();
|
||||
desktopRes = nullptr;
|
||||
}
|
||||
while (true)
|
||||
{
|
||||
if (!_duplication || !_device || !_context)
|
||||
{
|
||||
setIsGrabStoped(true);
|
||||
return;
|
||||
}
|
||||
if (initialize(_pDxDeviceID, _pOutputDeviceID))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (frameInfo.LastPresentTime.QuadPart)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
ID3D11Texture2D* textrueRes = nullptr;
|
||||
HRESULT hr = desktopRes->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&textrueRes));
|
||||
desktopRes->Release();
|
||||
if (FAILED(hr))
|
||||
{
|
||||
qDebug() << "Failed to ID3D11Texture2D result =" << QString::number(uint(hr), 16);
|
||||
continue;
|
||||
}
|
||||
textrueRes->GetDesc(&desc);
|
||||
D3D11_TEXTURE2D_DESC texDesc;
|
||||
ZeroMemory(&texDesc, sizeof(texDesc));
|
||||
texDesc.Width = desc.Width;
|
||||
texDesc.Height = desc.Height;
|
||||
texDesc.MipLevels = 1;
|
||||
texDesc.ArraySize = 1;
|
||||
texDesc.SampleDesc.Count = 1;
|
||||
texDesc.SampleDesc.Quality = 0;
|
||||
texDesc.Usage = D3D11_USAGE_STAGING;
|
||||
texDesc.Format = desc.Format;
|
||||
texDesc.BindFlags = 0;
|
||||
texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
||||
texDesc.MiscFlags = 0;
|
||||
_device->CreateTexture2D(&texDesc, nullptr, &_texture);
|
||||
_context->CopyResource(_texture, textrueRes);
|
||||
IDXGISurface1* surface = nullptr;
|
||||
hr = _texture->QueryInterface(__uuidof(IDXGISurface1), reinterpret_cast<void**>(&surface));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
qDebug() << "Failed to QueryInterface IDXGISurface1 ErrorCode ="
|
||||
<< QString::number(uint(hr), 16);
|
||||
continue;
|
||||
}
|
||||
|
||||
DXGI_MAPPED_RECT map;
|
||||
surface->Map(&map, DXGI_MAP_READ);
|
||||
_imageBits = static_cast<uchar*>(map.pBits);
|
||||
_descWidth = desc.Width;
|
||||
_descHeight = desc.Height;
|
||||
surface->Unmap();
|
||||
surface->Release();
|
||||
_texture->Release();
|
||||
Q_EMIT grabScreenOver();
|
||||
endTime = QDateTime::currentMSecsSinceEpoch();
|
||||
if (_lastGrabTime == 0)
|
||||
{
|
||||
_lastGrabTime = endTime - startTime; // 毫秒
|
||||
}
|
||||
else
|
||||
{
|
||||
_lastGrabTime = ((endTime - startTime) + _lastGrabTime) / 2.0;
|
||||
}
|
||||
_cpuSleepTime = (1000 - _lastGrabTime * _pGrabFrameRate) / _pGrabFrameRate;
|
||||
cpuSleep(_cpuSleepTime * 1000);
|
||||
// qDebug() << _cpuSleepTime << _lastGrabTime;
|
||||
}
|
||||
setIsGrabStoped(true);
|
||||
}
|
||||
|
||||
void ElaDxgi::releaseInterface()
|
||||
{
|
||||
if (_duplication)
|
||||
{
|
||||
_duplication->Release();
|
||||
_duplication = nullptr;
|
||||
}
|
||||
if (_device)
|
||||
{
|
||||
_device->Release();
|
||||
_device = nullptr;
|
||||
}
|
||||
if (_context)
|
||||
{
|
||||
_context->Release();
|
||||
_context = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void ElaDxgi::cpuSleep(int usec)
|
||||
{
|
||||
if (usec <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
LARGE_INTEGER cpuFerq;
|
||||
LARGE_INTEGER startTime;
|
||||
LARGE_INTEGER endTime;
|
||||
QueryPerformanceFrequency(&cpuFerq);
|
||||
QueryPerformanceCounter(&startTime);
|
||||
while (1)
|
||||
{
|
||||
QueryPerformanceCounter(&endTime);
|
||||
if (((endTime.QuadPart - startTime.QuadPart) * 1000000) / cpuFerq.QuadPart > usec)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,51 @@
|
||||
#ifndef ELADXGI_H
|
||||
#define ELADXGI_H
|
||||
|
||||
#include <QObject>
|
||||
#ifdef Q_OS_WIN
|
||||
#include <d3d11.h>
|
||||
#include <dxgi1_6.h>
|
||||
|
||||
#include <QPixmap>
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
class ElaDxgi : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PRIVATE_CREATE(QStringList, DxDeviceList)
|
||||
Q_PRIVATE_CREATE(QStringList, OutputDeviceList)
|
||||
Q_PRIVATE_CREATE(int, DxDeviceID);
|
||||
Q_PRIVATE_CREATE(int, OutputDeviceID);
|
||||
Q_PRIVATE_CREATE(QString, LastError)
|
||||
Q_PRIVATE_CREATE(bool, IsGrabActive)
|
||||
Q_PRIVATE_CREATE(QRect, GrabArea);
|
||||
Q_PRIVATE_CREATE(int, GrabFrameRate); // 截图帧数
|
||||
Q_PRIVATE_CREATE(int, TimeoutMsValue); // 超时等待
|
||||
Q_PRIVATE_CREATE(bool, IsInitSuccess);
|
||||
Q_PRIVATE_CREATE(bool, IsGrabStoped);
|
||||
Q_PRIVATE_CREATE(bool, IsGrabCenter);
|
||||
|
||||
public:
|
||||
explicit ElaDxgi(QObject* parent = nullptr);
|
||||
~ElaDxgi();
|
||||
bool initialize(int dxID, int outputID);
|
||||
QImage getGrabImage() const;
|
||||
Q_SLOT void onGrabScreen();
|
||||
Q_SIGNAL void grabScreenOver();
|
||||
|
||||
private:
|
||||
IDXGIOutputDuplication* _duplication{nullptr};
|
||||
ID3D11Device* _device{nullptr};
|
||||
ID3D11DeviceContext* _context{nullptr};
|
||||
ID3D11Texture2D* _texture{nullptr};
|
||||
qreal _lastGrabTime{0};
|
||||
qreal _cpuSleepTime{0};
|
||||
uchar* _imageBits{nullptr};
|
||||
int _descWidth{0};
|
||||
int _descHeight{0};
|
||||
void releaseInterface();
|
||||
void cpuSleep(int usec);
|
||||
};
|
||||
#endif
|
||||
#endif // ELADXGI_H
|
||||
@@ -0,0 +1,266 @@
|
||||
#include "ElaFooterDelegate.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QPropertyAnimation>
|
||||
|
||||
#include "ElaBaseListView.h"
|
||||
#include "ElaFooterModel.h"
|
||||
#include "ElaNavigationNode.h"
|
||||
#include "ElaTheme.h"
|
||||
ElaFooterDelegate::ElaFooterDelegate(QObject* parent)
|
||||
: QStyledItemDelegate{parent}
|
||||
{
|
||||
_pElaListView = nullptr;
|
||||
_themeMode = eTheme->getThemeMode();
|
||||
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) {
|
||||
_themeMode = themeMode;
|
||||
});
|
||||
setProperty("lastSelectMarkTop", 10.0);
|
||||
setProperty("lastSelectMarkBottom", 10.0);
|
||||
setProperty("selectMarkTop", 10.0);
|
||||
setProperty("selectMarkBottom", 10.0);
|
||||
// Mark向上
|
||||
_lastSelectMarkTopAnimation = new QPropertyAnimation(this, "lastSelectMarkTop");
|
||||
connect(_lastSelectMarkTopAnimation, &QPropertyAnimation::valueChanged, this, [=](const QVariant& value) {
|
||||
_lastSelectMarkTop = value.toReal();
|
||||
_pElaListView->viewport()->update(); });
|
||||
_lastSelectMarkTopAnimation->setDuration(300);
|
||||
_lastSelectMarkTopAnimation->setEasingCurve(QEasingCurve::InOutSine);
|
||||
|
||||
_selectMarkBottomAnimation = new QPropertyAnimation(this, "selectMarkBottom");
|
||||
connect(_selectMarkBottomAnimation, &QPropertyAnimation::valueChanged, this, [=](const QVariant& value) {
|
||||
_selectMarkBottom = value.toReal();
|
||||
_pElaListView->viewport()->update(); });
|
||||
_selectMarkBottomAnimation->setDuration(300);
|
||||
_selectMarkBottomAnimation->setEasingCurve(QEasingCurve::InOutSine);
|
||||
connect(_lastSelectMarkTopAnimation, &QPropertyAnimation::finished, this, [=]() {
|
||||
_isSelectMarkDisplay = true;
|
||||
_lastSelectedNode = nullptr;
|
||||
_selectMarkBottomAnimation->setStartValue(0);
|
||||
_selectMarkBottomAnimation->setEndValue(10);
|
||||
_selectMarkBottomAnimation->start(); });
|
||||
|
||||
// Mark向下
|
||||
_lastSelectMarkBottomAnimation = new QPropertyAnimation(this, "lastSelectMarkBottom");
|
||||
connect(_lastSelectMarkBottomAnimation, &QPropertyAnimation::valueChanged, this, [=](const QVariant& value) {
|
||||
_lastSelectMarkBottom = value.toReal();
|
||||
_pElaListView->viewport()->update(); });
|
||||
_lastSelectMarkBottomAnimation->setDuration(300);
|
||||
_lastSelectMarkBottomAnimation->setEasingCurve(QEasingCurve::InOutSine);
|
||||
|
||||
_selectMarkTopAnimation = new QPropertyAnimation(this, "selectMarkTop");
|
||||
connect(_selectMarkTopAnimation, &QPropertyAnimation::valueChanged, this, [=](const QVariant& value) {
|
||||
_selectMarkTop = value.toReal();
|
||||
_pElaListView->viewport()->update(); });
|
||||
_selectMarkTopAnimation->setDuration(300);
|
||||
_selectMarkTopAnimation->setEasingCurve(QEasingCurve::InOutSine);
|
||||
connect(_lastSelectMarkBottomAnimation, &QPropertyAnimation::finished, this, [=]() {
|
||||
_isSelectMarkDisplay = true;
|
||||
_lastSelectedNode = nullptr;
|
||||
_selectMarkTopAnimation->setStartValue(0);
|
||||
_selectMarkTopAnimation->setEndValue(10);
|
||||
_selectMarkTopAnimation->start(); });
|
||||
}
|
||||
|
||||
ElaFooterDelegate::~ElaFooterDelegate()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaFooterDelegate::navigationNodeStateChange(QVariantMap data)
|
||||
{
|
||||
if (data.contains("SelectMarkChanged"))
|
||||
{
|
||||
_lastSelectedNode = data.value("LastSelectedNode").value<ElaNavigationNode*>();
|
||||
ElaNavigationNode* selectedNode = data.value("SelectedNode").value<ElaNavigationNode*>();
|
||||
bool direction = _compareItemY(selectedNode, _lastSelectedNode);
|
||||
_lastSelectMarkTop = 10;
|
||||
_lastSelectMarkBottom = 10;
|
||||
_selectMarkTop = 10;
|
||||
_selectMarkBottom = 10;
|
||||
if (direction)
|
||||
{
|
||||
_lastSelectMarkTopAnimation->setStartValue(10);
|
||||
_lastSelectMarkTopAnimation->setEndValue(0);
|
||||
_lastSelectMarkTopAnimation->start();
|
||||
_lastSelectMarkBottomAnimation->stop();
|
||||
_selectMarkTopAnimation->stop();
|
||||
_isSelectMarkDisplay = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_lastSelectMarkBottomAnimation->setStartValue(10);
|
||||
_lastSelectMarkBottomAnimation->setEndValue(0);
|
||||
_lastSelectMarkBottomAnimation->start();
|
||||
_lastSelectMarkTopAnimation->stop();
|
||||
_selectMarkBottomAnimation->stop();
|
||||
_isSelectMarkDisplay = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ElaFooterDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
QStyleOptionViewItem viewOption(option);
|
||||
initStyleOption(&viewOption, index);
|
||||
ElaFooterModel* model = dynamic_cast<ElaFooterModel*>(const_cast<QAbstractItemModel*>(index.model()));
|
||||
ElaNavigationNode* node = index.data(Qt::UserRole).value<ElaNavigationNode*>();
|
||||
if (option.state.testFlag(QStyle::State_HasFocus))
|
||||
{
|
||||
viewOption.state &= ~QStyle::State_HasFocus;
|
||||
}
|
||||
QStyledItemDelegate::paint(painter, viewOption, index);
|
||||
// 背景绘制
|
||||
QRect itemRect = option.rect;
|
||||
painter->save();
|
||||
painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::TextAntialiasing);
|
||||
itemRect.setTop(itemRect.top() + 2);
|
||||
itemRect.setBottom(itemRect.bottom() - 2);
|
||||
QPainterPath path;
|
||||
path.addRoundedRect(itemRect, 8, 8);
|
||||
if (option.state & QStyle::State_Selected)
|
||||
{
|
||||
if (index == _pPressIndex)
|
||||
{
|
||||
// 选中时点击
|
||||
painter->fillPath(path, ElaThemeColor(_themeMode, BasicHoverAlpha));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (option.state & QStyle::State_MouseOver)
|
||||
{
|
||||
// 选中时覆盖
|
||||
painter->fillPath(path, ElaThemeColor(_themeMode, BasicSelectedHoverAlpha));
|
||||
}
|
||||
else
|
||||
{
|
||||
// 选中
|
||||
painter->fillPath(path, ElaThemeColor(_themeMode, BasicSelectedAlpha));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (index == _pPressIndex)
|
||||
{
|
||||
// 点击时颜色
|
||||
painter->fillPath(path, ElaThemeColor(_themeMode, BasicSelectedHoverAlpha));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (option.state & QStyle::State_MouseOver)
|
||||
{
|
||||
// 覆盖时颜色
|
||||
painter->fillPath(path, ElaThemeColor(_themeMode, BasicHoverAlpha));
|
||||
}
|
||||
}
|
||||
}
|
||||
painter->restore();
|
||||
|
||||
painter->save();
|
||||
painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::TextAntialiasing);
|
||||
itemRect = option.rect;
|
||||
|
||||
//顶边线绘制
|
||||
if (index.row() == 0)
|
||||
{
|
||||
painter->setPen(ElaThemeColor(_themeMode, BasicBaseLine));
|
||||
painter->drawLine(option.rect.x(), itemRect.y() + 1, option.rect.x() + option.rect.width(), itemRect.y() + 1);
|
||||
}
|
||||
// 图标绘制
|
||||
painter->setPen(index == _pPressIndex ? ElaThemeColor(_themeMode, BasicTextPress) : ElaThemeColor(_themeMode, BasicText));
|
||||
if (node->getAwesome() != ElaIconType::None)
|
||||
{
|
||||
painter->save();
|
||||
QFont iconFont = QFont("ElaAwesome");
|
||||
iconFont.setPixelSize(17);
|
||||
painter->setFont(iconFont);
|
||||
painter->drawText(QRect(itemRect.x(), itemRect.y(), _iconAreaWidth, itemRect.height()), Qt::AlignCenter, QChar((unsigned short)node->getAwesome()));
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
int keyPoints = node->getKeyPoints();
|
||||
if (keyPoints)
|
||||
{
|
||||
// KeyPoints
|
||||
painter->save();
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(Qt::white);
|
||||
painter->drawEllipse(QPoint(255, itemRect.y() + itemRect.height() / 2), 10, 10);
|
||||
painter->setBrush(ElaThemeColor(_themeMode, StatusDanger));
|
||||
painter->drawEllipse(QPoint(255, itemRect.y() + itemRect.height() / 2), 9, 9);
|
||||
painter->setPen(QPen(Qt::white, 2));
|
||||
QFont font = painter->font();
|
||||
font.setBold(true);
|
||||
if (keyPoints > 99)
|
||||
{
|
||||
keyPoints = 99;
|
||||
}
|
||||
if (keyPoints > 9)
|
||||
{
|
||||
font.setPixelSize(11);
|
||||
}
|
||||
else
|
||||
{
|
||||
font.setPixelSize(12);
|
||||
}
|
||||
painter->setFont(font);
|
||||
painter->drawText(keyPoints > 9 ? 248 : 251, itemRect.y() + itemRect.height() / 2 + 4, QString::number(keyPoints));
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
// 文字绘制
|
||||
painter->setPen(index == _pPressIndex ? ElaThemeColor(_themeMode, BasicTextPress) : ElaThemeColor(_themeMode, BasicText));
|
||||
QRect textRect;
|
||||
if (node->getAwesome() != ElaIconType::None)
|
||||
{
|
||||
textRect = QRect(itemRect.x() + _iconAreaWidth, itemRect.y(), itemRect.width() - _textRightSpacing - _indicatorIconAreaWidth - _iconAreaWidth, itemRect.height());
|
||||
}
|
||||
else
|
||||
{
|
||||
textRect = QRect(itemRect.x() + _leftPadding, itemRect.y(), itemRect.width() - _textRightSpacing - _indicatorIconAreaWidth - _leftPadding, itemRect.height());
|
||||
}
|
||||
QString text = painter->fontMetrics().elidedText(node->getNodeTitle(), Qt::ElideRight, textRect.width());
|
||||
painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, text);
|
||||
// 选中特效
|
||||
if (_isSelectMarkDisplay && (node == model->getSelectedNode()))
|
||||
{
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(ElaThemeColor(_themeMode, PrimaryNormal));
|
||||
painter->drawRoundedRect(QRectF(itemRect.x() + 3, itemRect.y() + _selectMarkTop, 3, itemRect.height() - _selectMarkTop - _selectMarkBottom), 3, 3);
|
||||
}
|
||||
if (node == _lastSelectedNode)
|
||||
{
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(ElaThemeColor(_themeMode, PrimaryNormal));
|
||||
painter->drawRoundedRect(QRectF(itemRect.x() + 3, itemRect.y() + _lastSelectMarkTop, 3, itemRect.height() - _lastSelectMarkTop - _lastSelectMarkBottom), 3, 3);
|
||||
}
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
QSize ElaFooterDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
QSize size = QStyledItemDelegate::sizeHint(option, index);
|
||||
size.setHeight(40);
|
||||
return size;
|
||||
}
|
||||
|
||||
bool ElaFooterDelegate::_compareItemY(ElaNavigationNode* node1, ElaNavigationNode* node2)
|
||||
{
|
||||
if (!node1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (!node2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (node1->getModelIndex().row() < node2->getModelIndex().row())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
#ifndef ELAFOOTERDELEGATE_H
|
||||
#define ELAFOOTERDELEGATE_H
|
||||
|
||||
#include <QModelIndex>
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
#include "Def.h"
|
||||
class ElaNavigationNode;
|
||||
class QPropertyAnimation;
|
||||
class ElaBaseListView;
|
||||
class ElaFooterDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PRIVATE_CREATE(ElaBaseListView*, ElaListView);
|
||||
Q_PRIVATE_CREATE(QModelIndex, PressIndex);
|
||||
|
||||
public:
|
||||
explicit ElaFooterDelegate(QObject* parent = nullptr);
|
||||
~ElaFooterDelegate();
|
||||
void navigationNodeStateChange(QVariantMap data);
|
||||
|
||||
protected:
|
||||
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
|
||||
private:
|
||||
int _leftPadding{11};
|
||||
int _iconAreaWidth{40};
|
||||
int _textRightSpacing{3};
|
||||
int _indicatorIconAreaWidth{24};
|
||||
qreal _lastSelectMarkTop{10};
|
||||
qreal _lastSelectMarkBottom{10};
|
||||
qreal _selectMarkTop{10};
|
||||
qreal _selectMarkBottom{10};
|
||||
bool _isSelectMarkDisplay{true};
|
||||
ElaNavigationNode* _lastSelectedNode{nullptr};
|
||||
ElaThemeType::ThemeMode _themeMode;
|
||||
QPropertyAnimation* _lastSelectMarkTopAnimation{nullptr};
|
||||
QPropertyAnimation* _lastSelectMarkBottomAnimation{nullptr};
|
||||
QPropertyAnimation* _selectMarkTopAnimation{nullptr};
|
||||
QPropertyAnimation* _selectMarkBottomAnimation{nullptr};
|
||||
bool _compareItemY(ElaNavigationNode* node1, ElaNavigationNode* node2);
|
||||
};
|
||||
|
||||
#endif // ELAFOOTERDELEGATE_H
|
||||
@@ -0,0 +1,68 @@
|
||||
#include "ElaFooterModel.h"
|
||||
|
||||
#include <QUuid>
|
||||
|
||||
#include "ElaNavigationNode.h"
|
||||
ElaFooterModel::ElaFooterModel(QObject* parent)
|
||||
: QAbstractListModel{parent}
|
||||
{
|
||||
_pSelectedNode = nullptr;
|
||||
}
|
||||
|
||||
ElaFooterModel::~ElaFooterModel()
|
||||
{
|
||||
qDeleteAll(_footerNodeList);
|
||||
}
|
||||
|
||||
int ElaFooterModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
return _footerNodeList.count();
|
||||
}
|
||||
|
||||
QVariant ElaFooterModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
if (role == Qt::UserRole)
|
||||
{
|
||||
if (index.row() < _footerNodeList.count())
|
||||
{
|
||||
return QVariant::fromValue(_footerNodeList[index.row()]);
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
ElaNavigationType::NodeOperateReturnType ElaFooterModel::addFooterNode(QString footerTitle, QString& footerKey, bool isHasFooterPage, int keyPoints, ElaIconType::IconName awesome)
|
||||
{
|
||||
if (_footerNodeList.count() >= 3)
|
||||
{
|
||||
return ElaNavigationType::FooterUpperLimit;
|
||||
}
|
||||
ElaNavigationNode* node = new ElaNavigationNode(footerTitle);
|
||||
node->setKeyPoints(keyPoints);
|
||||
node->setIsFooterNode(true);
|
||||
node->setIsHasFooterPage(isHasFooterPage);
|
||||
node->setAwesome(awesome);
|
||||
footerKey = node->getNodeKey();
|
||||
beginResetModel();
|
||||
_footerNodeList.append(node);
|
||||
endResetModel();
|
||||
node->setModelIndex(this->index(_footerNodeList.count() - 1));
|
||||
return ElaNavigationType::Success;
|
||||
}
|
||||
|
||||
int ElaFooterModel::getFooterNodeCount() const
|
||||
{
|
||||
return _footerNodeList.count();
|
||||
}
|
||||
|
||||
ElaNavigationNode* ElaFooterModel::getNavigationNode(QString footerKey)
|
||||
{
|
||||
for (auto node : _footerNodeList)
|
||||
{
|
||||
if (node->getNodeKey() == footerKey)
|
||||
{
|
||||
return node;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef ELAFOOTERMODEL_H
|
||||
#define ELAFOOTERMODEL_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
|
||||
#include "Def.h"
|
||||
#include "stdafx.h"
|
||||
class ElaNavigationNode;
|
||||
class ElaFooterModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PRIVATE_CREATE(ElaNavigationNode*, SelectedNode)
|
||||
public:
|
||||
explicit ElaFooterModel(QObject* parent = nullptr);
|
||||
~ElaFooterModel();
|
||||
ElaNavigationType::NodeOperateReturnType addFooterNode(QString footerTitle, QString& footerKey, bool isHasFooterPage, int keyPoints = 0, ElaIconType::IconName awesome = ElaIconType::None);
|
||||
int getFooterNodeCount() const;
|
||||
ElaNavigationNode* getNavigationNode(QString footerKey);
|
||||
|
||||
protected:
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex& index, int role) const override;
|
||||
|
||||
private:
|
||||
QList<ElaNavigationNode*> _footerNodeList;
|
||||
};
|
||||
|
||||
#endif // ELAFOOTERMODEL_H
|
||||
@@ -0,0 +1,86 @@
|
||||
#include "ElaIntValidator.h"
|
||||
|
||||
ElaIntValidator::ElaIntValidator(QObject* parent)
|
||||
: QIntValidator{parent}
|
||||
{
|
||||
_pIsHexMode = false;
|
||||
}
|
||||
|
||||
ElaIntValidator::ElaIntValidator(int bottom, int top, QObject* parent)
|
||||
: QIntValidator{bottom, top, parent}
|
||||
{
|
||||
_pIsHexMode = false;
|
||||
}
|
||||
|
||||
ElaIntValidator::~ElaIntValidator()
|
||||
{
|
||||
}
|
||||
|
||||
QValidator::State ElaIntValidator::validate(QString& input, int& pos) const
|
||||
{
|
||||
QString inputCopy = input;
|
||||
if (_pIsHexMode)
|
||||
{
|
||||
inputCopy.remove("#");
|
||||
if (!inputCopy.isEmpty())
|
||||
{
|
||||
bool isInt = false;
|
||||
int value = inputCopy.toInt(&isInt, 16);
|
||||
if (!isInt)
|
||||
{
|
||||
return QValidator::Invalid;
|
||||
}
|
||||
if (value < bottom() || value > top())
|
||||
{
|
||||
return QValidator::Invalid;
|
||||
}
|
||||
int topLength = QString::number(top(), 16).length();
|
||||
if (inputCopy.length() > topLength)
|
||||
{
|
||||
return QValidator::Invalid;
|
||||
}
|
||||
}
|
||||
inputCopy.prepend("#");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (input.isEmpty())
|
||||
{
|
||||
return QValidator::Intermediate;
|
||||
}
|
||||
bool isInt = false;
|
||||
int value = inputCopy.toInt(&isInt);
|
||||
if (!isInt)
|
||||
{
|
||||
return QValidator::Invalid;
|
||||
}
|
||||
if (value < bottom() || value > top())
|
||||
{
|
||||
return QValidator::Invalid;
|
||||
}
|
||||
}
|
||||
input = inputCopy;
|
||||
return QValidator::Acceptable;
|
||||
}
|
||||
|
||||
void ElaIntValidator::fixup(QString& input) const
|
||||
{
|
||||
if (_pIsHexMode)
|
||||
{
|
||||
QString inputComplete = _completeInput(input, QString::number(top(), 16).length());
|
||||
input = QString("#") + inputComplete;
|
||||
}
|
||||
else
|
||||
{
|
||||
input = QString::number(bottom());
|
||||
}
|
||||
}
|
||||
|
||||
QString ElaIntValidator::_completeInput(QString input, int length) const
|
||||
{
|
||||
while (input.length() < length)
|
||||
{
|
||||
input.prepend("0");
|
||||
}
|
||||
return input;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef ELAINTVALIDATOR_H
|
||||
#define ELAINTVALIDATOR_H
|
||||
|
||||
#include <QIntValidator>
|
||||
|
||||
#include "stdafx.h"
|
||||
class ElaIntValidator : public QIntValidator
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PRIVATE_CREATE(bool, IsHexMode)
|
||||
public:
|
||||
explicit ElaIntValidator(QObject* parent = nullptr);
|
||||
explicit ElaIntValidator(int bottom, int top, QObject* parent = nullptr);
|
||||
~ElaIntValidator();
|
||||
|
||||
QValidator::State validate(QString& input, int& pos) const override;
|
||||
void fixup(QString& input) const override;
|
||||
|
||||
private:
|
||||
QString _completeInput(QString input, int length) const;
|
||||
};
|
||||
|
||||
#endif // ELAINTVALIDATOR_H
|
||||
@@ -0,0 +1,144 @@
|
||||
#include "ElaKeyBinderContainer.h"
|
||||
#include "ElaKeyBinder.h"
|
||||
#include "ElaTheme.h"
|
||||
#include <QKeyEvent>
|
||||
#include <QMouseEvent>
|
||||
#include <QPainter>
|
||||
#include <QtMath>
|
||||
ElaKeyBinderContainer::ElaKeyBinderContainer(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
_keyBinder = dynamic_cast<ElaKeyBinder*>(parent);
|
||||
setStyleSheet("#ElaKeyBinderContainer{background-color:transparent;}");
|
||||
setFocusPolicy(Qt::StrongFocus);
|
||||
setMouseTracking(true);
|
||||
setFixedHeight(140);
|
||||
QFont textFont = font();
|
||||
textFont.setLetterSpacing(QFont::AbsoluteSpacing, 0.5);
|
||||
textFont.setPixelSize(16);
|
||||
setFont(textFont);
|
||||
_themeMode = eTheme->getThemeMode();
|
||||
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) {
|
||||
_themeMode = themeMode;
|
||||
});
|
||||
}
|
||||
|
||||
ElaKeyBinderContainer::~ElaKeyBinderContainer()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaKeyBinderContainer::logOrResetHistoryData(bool isLog)
|
||||
{
|
||||
if (isLog)
|
||||
{
|
||||
_historyBinderKeyText = _pBinderKeyText;
|
||||
_historyNativeVirtualBinderKey = _pNativeVirtualBinderKey;
|
||||
}
|
||||
else
|
||||
{
|
||||
_pBinderKeyText = _historyBinderKeyText;
|
||||
_pNativeVirtualBinderKey = _historyNativeVirtualBinderKey;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void ElaKeyBinderContainer::saveBinderChanged()
|
||||
{
|
||||
Q_EMIT _keyBinder->binderKeyTextChanged(_pBinderKeyText);
|
||||
Q_EMIT _keyBinder->nativeVirtualBinderKeyChanged(_pNativeVirtualBinderKey);
|
||||
if (_pBinderKeyText.isEmpty())
|
||||
{
|
||||
_keyBinder->setText(u8" 按键: " + QString(u8"未绑定") + " ");
|
||||
}
|
||||
else
|
||||
{
|
||||
_keyBinder->setText(u8" 按键: " + _pBinderKeyText + " ");
|
||||
}
|
||||
}
|
||||
|
||||
void ElaKeyBinderContainer::mousePressEvent(QMouseEvent* event)
|
||||
{
|
||||
switch (event->button())
|
||||
{
|
||||
case Qt::LeftButton:
|
||||
{
|
||||
_pBinderKeyText = "Mouse1";
|
||||
_pNativeVirtualBinderKey = 0x01;
|
||||
break;
|
||||
}
|
||||
case Qt::RightButton:
|
||||
{
|
||||
_pBinderKeyText = "Mouse2";
|
||||
_pNativeVirtualBinderKey = 0x02;
|
||||
break;
|
||||
}
|
||||
case Qt::MiddleButton:
|
||||
{
|
||||
_pBinderKeyText = "Middle";
|
||||
_pNativeVirtualBinderKey = 0x04;
|
||||
break;
|
||||
}
|
||||
case Qt::BackButton:
|
||||
{
|
||||
_pBinderKeyText = "Back";
|
||||
_pNativeVirtualBinderKey = 0x05;
|
||||
break;
|
||||
}
|
||||
case Qt::ForwardButton:
|
||||
{
|
||||
_pBinderKeyText = "Forward";
|
||||
_pNativeVirtualBinderKey = 0x06;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
QWidget::mousePressEvent(event);
|
||||
update();
|
||||
}
|
||||
|
||||
void ElaKeyBinderContainer::keyPressEvent(QKeyEvent* event)
|
||||
{
|
||||
if (!event->isAutoRepeat())
|
||||
{
|
||||
_pBinderKeyText = QKeySequence(event->key()).toString();
|
||||
_pNativeVirtualBinderKey = event->nativeVirtualKey();
|
||||
update();
|
||||
}
|
||||
QWidget::keyPressEvent(event);
|
||||
}
|
||||
|
||||
void ElaKeyBinderContainer::focusOutEvent(QFocusEvent* event)
|
||||
{
|
||||
QWidget::focusOutEvent(event);
|
||||
setFocus();
|
||||
}
|
||||
|
||||
void ElaKeyBinderContainer::paintEvent(QPaintEvent* event)
|
||||
{
|
||||
QPainter painter(this);
|
||||
painter.save();
|
||||
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
|
||||
// 顶部提示绘制
|
||||
painter.setPen(ElaThemeColor(_themeMode, BasicText));
|
||||
painter.drawText(QRect(20, 20, width(), 50), Qt::AlignLeft | Qt::AlignTop, u8"按下任意按键以进行绑定");
|
||||
if (_pBinderKeyText.isEmpty())
|
||||
{
|
||||
painter.restore();
|
||||
return;
|
||||
}
|
||||
// 中心文字背景绘制
|
||||
painter.setPen(ElaThemeColor(_themeMode, BasicBorder));
|
||||
painter.setBrush(ElaThemeColor(_themeMode, PrimaryNormal));
|
||||
qreal textWidth = fontMetrics().horizontalAdvance(_pBinderKeyText) * 1.3;
|
||||
qreal textHeight = fontMetrics().height() * 1.2;
|
||||
textWidth = qMax(textWidth, 35.0);
|
||||
textHeight = qMax(textHeight, 35.0);
|
||||
painter.drawRoundedRect(QRectF((width() - textWidth) / 2.0, rect().center().y() + 10, textWidth, textHeight), 5, 5);
|
||||
// 文字绘制
|
||||
painter.setPen(ElaThemeColor(_themeMode, BasicTextInvert));
|
||||
painter.drawText(QRectF((width() - textWidth) / 2.0, rect().center().y() + 10, textWidth, textHeight), Qt::AlignCenter, _pBinderKeyText);
|
||||
painter.restore();
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifndef ELAWIDGETTOOLS_SRC_DEVELOPERCOMPONENTS_ELAKEYBINDERCONTAINER_H_
|
||||
#define ELAWIDGETTOOLS_SRC_DEVELOPERCOMPONENTS_ELAKEYBINDERCONTAINER_H_
|
||||
|
||||
#include "Def.h"
|
||||
#include <QWidget>
|
||||
class ElaKeyBinder;
|
||||
class ElaKeyBinderContainer : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PRIVATE_CREATE(QString, BinderKeyText)
|
||||
Q_PRIVATE_CREATE(quint32, NativeVirtualBinderKey)
|
||||
public:
|
||||
explicit ElaKeyBinderContainer(QWidget* parent = nullptr);
|
||||
~ElaKeyBinderContainer();
|
||||
void logOrResetHistoryData(bool isLog);
|
||||
void saveBinderChanged();
|
||||
|
||||
protected:
|
||||
virtual void mousePressEvent(QMouseEvent* event) override;
|
||||
virtual void keyPressEvent(QKeyEvent* event) override;
|
||||
virtual void focusOutEvent(QFocusEvent* event) override;
|
||||
virtual void paintEvent(QPaintEvent* event) override;
|
||||
|
||||
private:
|
||||
QString _historyBinderKeyText;
|
||||
quint32 _historyNativeVirtualBinderKey{0};
|
||||
ElaThemeType::ThemeMode _themeMode;
|
||||
ElaKeyBinder* _keyBinder{nullptr};
|
||||
};
|
||||
|
||||
#endif//ELAWIDGETTOOLS_SRC_DEVELOPERCOMPONENTS_ELAKEYBINDERCONTAINER_H_
|
||||
@@ -0,0 +1,52 @@
|
||||
#include "ElaLCDNumberStyle.h"
|
||||
#include "ElaTheme.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QPainter>
|
||||
#include <QStyleOption>
|
||||
ElaLCDNumberStyle::ElaLCDNumberStyle(QStyle* style)
|
||||
{
|
||||
_pIsTransparent = false;
|
||||
_themeMode = eTheme->getThemeMode();
|
||||
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) {
|
||||
_themeMode = themeMode;
|
||||
});
|
||||
}
|
||||
|
||||
ElaLCDNumberStyle::~ElaLCDNumberStyle()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaLCDNumberStyle::drawControl(QStyle::ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const
|
||||
{
|
||||
switch (element)
|
||||
{
|
||||
case QStyle::CE_ShapedFrame:
|
||||
{
|
||||
if (const QStyleOptionFrame* fopt = qstyleoption_cast<const QStyleOptionFrame*>(option))
|
||||
{
|
||||
if (!_pIsTransparent)
|
||||
{
|
||||
// 背景绘制
|
||||
QRect numberRect = option->rect;
|
||||
painter->save();
|
||||
painter->setRenderHints(QPainter::Antialiasing);
|
||||
painter->setPen(Qt::NoPen);
|
||||
// 边框绘制
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicBorder));
|
||||
painter->drawRoundedRect(numberRect, 6, 6);
|
||||
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicBase));
|
||||
painter->drawRoundedRect(QRectF(numberRect.x() + 1.5, numberRect.y() + 1.5, numberRect.width() - 3, numberRect.height() - 3), 6, 6);
|
||||
painter->restore();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
QProxyStyle::drawControl(element, option, painter, widget);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef ELAWIDGETTOOLS_ELALCDNUMBERSTYLE_H
|
||||
#define ELAWIDGETTOOLS_ELALCDNUMBERSTYLE_H
|
||||
#include <QProxyStyle>
|
||||
|
||||
#include "Def.h"
|
||||
class ElaLCDNumberStyle : public QProxyStyle
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PRIVATE_CREATE(bool, IsTransparent)
|
||||
public:
|
||||
explicit ElaLCDNumberStyle(QStyle* style = nullptr);
|
||||
~ElaLCDNumberStyle();
|
||||
void drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget = nullptr) const override;
|
||||
|
||||
private:
|
||||
ElaThemeType::ThemeMode _themeMode;
|
||||
};
|
||||
|
||||
#endif //ELAWIDGETTOOLS_ELALCDNUMBERSTYLE_H
|
||||
@@ -0,0 +1,69 @@
|
||||
#include "ElaLineEditStyle.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QStyleOption>
|
||||
#include <QtMath>
|
||||
|
||||
#include "ElaTheme.h"
|
||||
ElaLineEditStyle::ElaLineEditStyle(QStyle* style)
|
||||
{
|
||||
_themeMode = eTheme->getThemeMode();
|
||||
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) { _themeMode = themeMode; });
|
||||
}
|
||||
|
||||
ElaLineEditStyle::~ElaLineEditStyle()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaLineEditStyle::drawPrimitive(PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const
|
||||
{
|
||||
switch (element)
|
||||
{
|
||||
case PE_PanelLineEdit:
|
||||
{
|
||||
if (const QStyleOptionFrame* fopt = qstyleoption_cast<const QStyleOptionFrame*>(option))
|
||||
{
|
||||
QRect lineEditRect = fopt->rect;
|
||||
painter->save();
|
||||
painter->setRenderHints(QPainter::Antialiasing);
|
||||
painter->setPen(Qt::NoPen);
|
||||
// 边框绘制
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicBorder));
|
||||
painter->drawRoundedRect(lineEditRect, 6, 6);
|
||||
// 背景绘制
|
||||
if (fopt->state & QStyle::State_HasFocus)
|
||||
{
|
||||
painter->setBrush(ElaThemeColor(_themeMode, DialogBase));
|
||||
}
|
||||
else if (fopt->state & QStyle::State_MouseOver)
|
||||
{
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicHover));
|
||||
}
|
||||
else
|
||||
{
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicBase));
|
||||
}
|
||||
painter->drawRoundedRect(QRectF(lineEditRect.x() + 1.5, lineEditRect.y() + 1.5, lineEditRect.width() - 3, lineEditRect.height() - 3), 6, 6);
|
||||
|
||||
// 底边线绘制
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicHemline));
|
||||
QPainterPath path;
|
||||
path.moveTo(6, lineEditRect.height());
|
||||
path.lineTo(lineEditRect.width() - 6, lineEditRect.height());
|
||||
path.arcTo(QRectF(lineEditRect.width() - 12, lineEditRect.height() - 12, 12, 12), -90, 45);
|
||||
path.lineTo(6 - 3 * std::sqrt(2), lineEditRect.height() - (6 - 3 * std::sqrt(2)));
|
||||
path.arcTo(QRectF(0, lineEditRect.height() - 12, 12, 12), 270, 45);
|
||||
path.closeSubpath();
|
||||
painter->drawPath(path);
|
||||
painter->restore();
|
||||
}
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
QProxyStyle::drawPrimitive(element, option, painter, widget);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef ELALINEEDITSTYLE_H
|
||||
#define ELALINEEDITSTYLE_H
|
||||
|
||||
#include <QProxyStyle>
|
||||
|
||||
#include "Def.h"
|
||||
class ElaLineEditStyle : public QProxyStyle
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ElaLineEditStyle(QStyle* style = nullptr);
|
||||
~ElaLineEditStyle();
|
||||
void drawPrimitive(PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget = nullptr) const override;
|
||||
|
||||
private:
|
||||
ElaThemeType::ThemeMode _themeMode;
|
||||
};
|
||||
|
||||
#endif // ELALINEEDITSTYLE_H
|
||||
@@ -0,0 +1,194 @@
|
||||
#include "ElaListViewStyle.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QStyleOption>
|
||||
|
||||
#include "ElaListView.h"
|
||||
#include "ElaTheme.h"
|
||||
ElaListViewStyle::ElaListViewStyle(QStyle* style)
|
||||
{
|
||||
_pItemHeight = 35;
|
||||
_pIsTransparent = false;
|
||||
_themeMode = eTheme->getThemeMode();
|
||||
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) {
|
||||
_themeMode = themeMode;
|
||||
});
|
||||
}
|
||||
|
||||
ElaListViewStyle::~ElaListViewStyle()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaListViewStyle::drawPrimitive(PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const
|
||||
{
|
||||
switch (element)
|
||||
{
|
||||
case QStyle::PE_PanelItemViewItem:
|
||||
{
|
||||
// Item背景
|
||||
if (const QStyleOptionViewItem* vopt = qstyleoption_cast<const QStyleOptionViewItem*>(option))
|
||||
{
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing);
|
||||
QRect itemRect = vopt->rect;
|
||||
itemRect.adjust(0, 2, 0, -2);
|
||||
QPainterPath path;
|
||||
path.addRoundedRect(itemRect, 4, 4);
|
||||
if (vopt->state & QStyle::State_Selected)
|
||||
{
|
||||
if (vopt->state & QStyle::State_MouseOver)
|
||||
{
|
||||
// 选中时覆盖
|
||||
painter->fillPath(path, ElaThemeColor(_themeMode, BasicSelectedHoverAlpha));
|
||||
}
|
||||
else
|
||||
{
|
||||
// 选中
|
||||
painter->fillPath(path, ElaThemeColor(_themeMode, BasicSelectedAlpha));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vopt->state & QStyle::State_MouseOver)
|
||||
{
|
||||
// 覆盖时颜色
|
||||
painter->fillPath(path, ElaThemeColor(_themeMode, BasicHoverAlpha));
|
||||
}
|
||||
}
|
||||
painter->restore();
|
||||
}
|
||||
return;
|
||||
}
|
||||
case QStyle::PE_PanelItemViewRow:
|
||||
{
|
||||
// Item背景隔行变色
|
||||
if (const QStyleOptionViewItem* vopt = qstyleoption_cast<const QStyleOptionViewItem*>(option))
|
||||
{
|
||||
if (vopt->features == QStyleOptionViewItem::Alternate)
|
||||
{
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing);
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicAlternating));
|
||||
painter->drawRect(vopt->rect);
|
||||
painter->restore();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
case QStyle::PE_Widget:
|
||||
{
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
QProxyStyle::drawPrimitive(element, option, painter, widget);
|
||||
}
|
||||
|
||||
void ElaListViewStyle::drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const
|
||||
{
|
||||
switch (element)
|
||||
{
|
||||
case QStyle::CE_ShapedFrame:
|
||||
{
|
||||
// viewport视口外的其他区域背景
|
||||
if (!_pIsTransparent)
|
||||
{
|
||||
QRect frameRect = option->rect;
|
||||
frameRect.adjust(1, 1, -1, -1);
|
||||
painter->save();
|
||||
painter->setRenderHints(QPainter::Antialiasing);
|
||||
painter->setPen(ElaThemeColor(_themeMode, PopupBorder));
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicBase));
|
||||
painter->drawRoundedRect(frameRect, 3, 3);
|
||||
painter->restore();
|
||||
}
|
||||
return;
|
||||
}
|
||||
case QStyle::CE_ItemViewItem:
|
||||
{
|
||||
if (const QStyleOptionViewItem* vopt = qstyleoption_cast<const QStyleOptionViewItem*>(option))
|
||||
{
|
||||
// 背景绘制
|
||||
this->drawPrimitive(QStyle::PE_PanelItemViewItem, option, painter, widget);
|
||||
|
||||
// 内容绘制
|
||||
QRect itemRect = option->rect;
|
||||
painter->save();
|
||||
painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::TextAntialiasing);
|
||||
const ElaListView* listView = dynamic_cast<const ElaListView*>(widget);
|
||||
QListView::ViewMode viewMode = listView->viewMode();
|
||||
// QRect checkRect = proxy()->subElementRect(SE_ItemViewItemCheckIndicator, vopt, widget);
|
||||
QRect iconRect = proxy()->subElementRect(SE_ItemViewItemDecoration, vopt, widget);
|
||||
QRect textRect = proxy()->subElementRect(SE_ItemViewItemText, vopt, widget);
|
||||
iconRect.adjust(_leftPadding, 0, 0, 0);
|
||||
textRect.adjust(_leftPadding, 0, 0, 0);
|
||||
// 图标绘制
|
||||
if (!vopt->icon.isNull())
|
||||
{
|
||||
QIcon::Mode mode = QIcon::Normal;
|
||||
if (!(vopt->state.testFlag(QStyle::State_Enabled)))
|
||||
{
|
||||
mode = QIcon::Disabled;
|
||||
}
|
||||
else if (vopt->state.testFlag(QStyle::State_Selected))
|
||||
{
|
||||
mode = QIcon::Selected;
|
||||
}
|
||||
QIcon::State state = vopt->state & QStyle::State_Open ? QIcon::On : QIcon::Off;
|
||||
vopt->icon.paint(painter, iconRect, vopt->decorationAlignment, mode, state);
|
||||
}
|
||||
// 文字绘制
|
||||
if (!vopt->text.isEmpty())
|
||||
{
|
||||
painter->setPen(ElaThemeColor(_themeMode, BasicText));
|
||||
painter->drawText(textRect, vopt->displayAlignment, vopt->text);
|
||||
}
|
||||
// 选中特效
|
||||
if (vopt->state.testFlag(QStyle::State_Selected) && viewMode == QListView::ListMode)
|
||||
{
|
||||
int heightOffset = itemRect.height() / 4;
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(ElaThemeColor(_themeMode, PrimaryNormal));
|
||||
painter->drawRoundedRect(QRectF(itemRect.x() + 3, itemRect.y() + heightOffset, 3, itemRect.height() - 2 * heightOffset), 3, 3);
|
||||
}
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
QProxyStyle::drawControl(element, option, painter, widget);
|
||||
}
|
||||
|
||||
QSize ElaListViewStyle::sizeFromContents(ContentsType type, const QStyleOption* option, const QSize& size, const QWidget* widget) const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case QStyle::CT_ItemViewItem:
|
||||
{
|
||||
QSize itemSize = QProxyStyle::sizeFromContents(type, option, size, widget);
|
||||
const ElaListView* listView = dynamic_cast<const ElaListView*>(widget);
|
||||
QListView::ViewMode viewMode = listView->viewMode();
|
||||
if (viewMode == QListView::ListMode)
|
||||
{
|
||||
itemSize.setWidth(itemSize.width() + _leftPadding);
|
||||
}
|
||||
itemSize.setHeight(_pItemHeight);
|
||||
return itemSize;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QProxyStyle::sizeFromContents(type, option, size, widget);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef ELALISTVIEWSTYLE_H
|
||||
#define ELALISTVIEWSTYLE_H
|
||||
|
||||
#include <QProxyStyle>
|
||||
|
||||
#include "Def.h"
|
||||
class ElaListViewStyle : public QProxyStyle
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_CREATE(int, ItemHeight)
|
||||
Q_PROPERTY_CREATE(bool, IsTransparent)
|
||||
public:
|
||||
explicit ElaListViewStyle(QStyle* style = nullptr);
|
||||
~ElaListViewStyle();
|
||||
void drawPrimitive(PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget = nullptr) const override;
|
||||
void drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget = nullptr) const override;
|
||||
QSize sizeFromContents(ContentsType type, const QStyleOption* option, const QSize& size, const QWidget* widget) const override;
|
||||
|
||||
private:
|
||||
ElaThemeType::ThemeMode _themeMode;
|
||||
int _leftPadding{11};
|
||||
};
|
||||
|
||||
#endif // ELALISTVIEWSTYLE_H
|
||||
@@ -0,0 +1,45 @@
|
||||
#include "ElaMaskWidget.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPropertyAnimation>
|
||||
ElaMaskWidget::ElaMaskWidget(QWidget* parent)
|
||||
: QWidget{parent}
|
||||
{
|
||||
setObjectName("ElaMaskWidget");
|
||||
setStyleSheet("#ElaMaskWidget{background-color:transparent;}");
|
||||
_pMaskAlpha = 0;
|
||||
}
|
||||
|
||||
ElaMaskWidget::~ElaMaskWidget()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaMaskWidget::doMaskAnimation(int endValue)
|
||||
{
|
||||
QPropertyAnimation* opacityAnimation = new QPropertyAnimation(this, "pMaskAlpha");
|
||||
connect(opacityAnimation, &QPropertyAnimation::valueChanged, this, [=](const QVariant& value) {
|
||||
update();
|
||||
});
|
||||
connect(opacityAnimation, &QPropertyAnimation::finished, this, [=]() {
|
||||
if (endValue == 0)
|
||||
{
|
||||
setVisible(false);
|
||||
}
|
||||
});
|
||||
opacityAnimation->setEasingCurve(QEasingCurve::InOutSine);
|
||||
opacityAnimation->setDuration(250);
|
||||
opacityAnimation->setStartValue(_pMaskAlpha);
|
||||
opacityAnimation->setEndValue(endValue);
|
||||
opacityAnimation->start(QAbstractAnimation::DeleteWhenStopped);
|
||||
}
|
||||
|
||||
void ElaMaskWidget::paintEvent(QPaintEvent* event)
|
||||
{
|
||||
QPainter painter(this);
|
||||
painter.save();
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.setBrush(QColor(0x00, 0x00, 0x00, _pMaskAlpha));
|
||||
painter.drawRect(rect());
|
||||
painter.restore();
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef ELAMASKWIDGET_H
|
||||
#define ELAMASKWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "stdafx.h"
|
||||
class ElaMaskWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_CREATE(int, MaskAlpha)
|
||||
public:
|
||||
explicit ElaMaskWidget(QWidget* parent = nullptr);
|
||||
~ElaMaskWidget();
|
||||
void doMaskAnimation(int endValue);
|
||||
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent* event) override;
|
||||
};
|
||||
|
||||
#endif // ELAMASKWIDGET_H
|
||||
@@ -0,0 +1,225 @@
|
||||
#include "ElaMenuBarStyle.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QPainter>
|
||||
#include <QStyleOption>
|
||||
|
||||
#include "ElaMenuBar.h"
|
||||
#include "ElaTheme.h"
|
||||
ElaMenuBarStyle::ElaMenuBarStyle(QStyle* style)
|
||||
{
|
||||
_themeMode = eTheme->getThemeMode();
|
||||
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) {
|
||||
_themeMode = themeMode;
|
||||
});
|
||||
}
|
||||
|
||||
ElaMenuBarStyle::~ElaMenuBarStyle()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaMenuBarStyle::drawPrimitive(PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const
|
||||
{
|
||||
switch (element)
|
||||
{
|
||||
case QStyle::PE_PanelButtonTool:
|
||||
{
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
QProxyStyle::drawPrimitive(element, option, painter, widget);
|
||||
}
|
||||
|
||||
void ElaMenuBarStyle::drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const
|
||||
{
|
||||
switch (element)
|
||||
{
|
||||
case QStyle::CE_ToolButtonLabel:
|
||||
{
|
||||
if (const QStyleOptionToolButton* topt = qstyleoption_cast<const QStyleOptionToolButton*>(option))
|
||||
{
|
||||
painter->save();
|
||||
painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
|
||||
painter->setPen(Qt::NoPen);
|
||||
if (topt->state.testFlag(QStyle::State_Enabled) && topt->state.testFlag(QStyle::State_MouseOver))
|
||||
{
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicHoverAlpha));
|
||||
painter->drawRect(topt->rect);
|
||||
}
|
||||
//展开图标
|
||||
painter->setPen(!topt->state.testFlag(QStyle::State_Enabled) ? Qt::gray : ElaThemeColor(_themeMode, BasicText));
|
||||
QFont iconFont = QFont("ElaAwesome");
|
||||
iconFont.setPixelSize(18);
|
||||
painter->setFont(iconFont);
|
||||
painter->drawText(topt->rect, Qt::AlignCenter, QChar((unsigned short)ElaIconType::AngleRight));
|
||||
painter->restore();
|
||||
}
|
||||
return;
|
||||
}
|
||||
case QStyle::CE_MenuBarEmptyArea:
|
||||
{
|
||||
return;
|
||||
}
|
||||
case QStyle::CE_MenuBarItem:
|
||||
{
|
||||
if (const QStyleOptionMenuItem* mopt = qstyleoption_cast<const QStyleOptionMenuItem*>(option))
|
||||
{
|
||||
if (mopt->menuItemType == QStyleOptionMenuItem::Separator)
|
||||
{
|
||||
return;
|
||||
}
|
||||
int menuBarHeight = widget->height();
|
||||
QRect menuItemRect = mopt->rect;
|
||||
painter->save();
|
||||
painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
|
||||
//背景绘制
|
||||
painter->setPen(Qt::NoPen);
|
||||
if (mopt->state.testFlag(QStyle::State_Enabled))
|
||||
{
|
||||
if (mopt->state.testFlag(QStyle::State_Sunken))
|
||||
{
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicPressAlpha));
|
||||
}
|
||||
else if (mopt->state.testFlag(QStyle::State_Selected))
|
||||
{
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicSelectedAlpha));
|
||||
}
|
||||
painter->drawRoundedRect(menuItemRect, 3, 3);
|
||||
}
|
||||
//图标和文字绘制
|
||||
QIcon icon = mopt->icon;
|
||||
QString menuText = mopt->text;
|
||||
QString iconText;
|
||||
menuText = menuText.replace("&", "");
|
||||
const ElaMenuBar* menuBar = dynamic_cast<const ElaMenuBar*>(widget);
|
||||
if (menuBar)
|
||||
{
|
||||
QAction* action = menuBar->actionAt(menuItemRect.center());
|
||||
if (action)
|
||||
{
|
||||
iconText = action->property("ElaIconType").toString();
|
||||
}
|
||||
}
|
||||
if (menuText.isEmpty())
|
||||
{
|
||||
//图标
|
||||
if (!iconText.isEmpty())
|
||||
{
|
||||
painter->save();
|
||||
painter->setPen(!mopt->state.testFlag(QStyle::State_Enabled) ? ElaThemeColor(_themeMode, BasicTextDisable) : ElaThemeColor(_themeMode, BasicText));
|
||||
QFont iconFont = QFont("ElaAwesome");
|
||||
iconFont.setPixelSize(menuBarHeight * 0.7);
|
||||
painter->setFont(iconFont);
|
||||
painter->drawText(menuItemRect, Qt::AlignCenter, iconText);
|
||||
painter->restore();
|
||||
}
|
||||
else if (!icon.isNull())
|
||||
{
|
||||
QRect menuIconRect(menuItemRect.center().x() - menuBarHeight * 0.4, menuItemRect.center().y() - menuBarHeight * 0.4, menuBarHeight * 0.8, menuBarHeight * 0.8);
|
||||
painter->drawPixmap(menuIconRect, icon.pixmap(menuBarHeight * 0.8, menuBarHeight * 0.8));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//图标 + 文字
|
||||
painter->setPen(!mopt->state.testFlag(QStyle::State_Enabled) ? ElaThemeColor(_themeMode, BasicTextDisable) : ElaThemeColor(_themeMode, BasicText));
|
||||
if (icon.isNull() && iconText.isEmpty())
|
||||
{
|
||||
painter->drawText(menuItemRect, Qt::AlignCenter, menuText);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!iconText.isEmpty())
|
||||
{
|
||||
QRectF menuIconRect(menuItemRect.x() + menuBarHeight * 0.1 + _menuBarItemMargin, menuBarHeight * 0.1, menuBarHeight * 0.8, menuBarHeight * 0.8);
|
||||
painter->save();
|
||||
QFont iconFont = QFont("ElaAwesome");
|
||||
iconFont.setPixelSize(menuBarHeight * 0.7);
|
||||
painter->setFont(iconFont);
|
||||
painter->drawText(menuIconRect, Qt::AlignCenter, iconText);
|
||||
painter->restore();
|
||||
painter->drawText(QRect(menuIconRect.right(), menuItemRect.y(), menuItemRect.width() - menuIconRect.width(), menuBarHeight), Qt::AlignCenter, menuText);
|
||||
}
|
||||
else
|
||||
{
|
||||
QRect menuIconRect(menuItemRect.x() + menuBarHeight * 0.1 + _menuBarItemMargin, menuBarHeight * 0.1, menuBarHeight * 0.8, menuBarHeight * 0.8);
|
||||
painter->drawPixmap(menuIconRect, icon.pixmap(menuBarHeight * 0.8, menuBarHeight * 0.8));
|
||||
painter->drawText(QRect(menuIconRect.right(), menuItemRect.y(), menuItemRect.width() - menuIconRect.width(), menuBarHeight), Qt::AlignCenter, menuText);
|
||||
}
|
||||
}
|
||||
}
|
||||
painter->restore();
|
||||
}
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QProxyStyle::drawControl(element, option, painter, widget);
|
||||
}
|
||||
|
||||
QSize ElaMenuBarStyle::sizeFromContents(ContentsType type, const QStyleOption* option, const QSize& size, const QWidget* widget) const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case QStyle::CT_MenuBar:
|
||||
{
|
||||
QSize menuBarHeight = QProxyStyle::sizeFromContents(type, option, size, widget);
|
||||
menuBarHeight.setHeight(widget->height());
|
||||
return menuBarHeight;
|
||||
}
|
||||
case QStyle::CT_MenuBarItem:
|
||||
{
|
||||
if (const QStyleOptionMenuItem* mopt = qstyleoption_cast<const QStyleOptionMenuItem*>(option))
|
||||
{
|
||||
QSize menuBarItemSize = QProxyStyle::sizeFromContents(type, option, size, widget);
|
||||
menuBarItemSize.setHeight(widget->height());
|
||||
if ((!mopt->icon.isNull()) && !mopt->text.isEmpty())
|
||||
{
|
||||
menuBarItemSize.setWidth(menuBarItemSize.width() + mopt->fontMetrics.horizontalAdvance(mopt->text) + 2 * _menuBarItemMargin);
|
||||
}
|
||||
if (!mopt->text.contains("&"))
|
||||
{
|
||||
menuBarItemSize.setWidth(menuBarItemSize.width() + 5);
|
||||
}
|
||||
return menuBarItemSize;
|
||||
}
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QProxyStyle::sizeFromContents(type, option, size, widget);
|
||||
}
|
||||
|
||||
int ElaMenuBarStyle::pixelMetric(PixelMetric metric, const QStyleOption* option, const QWidget* widget) const
|
||||
{
|
||||
switch (metric)
|
||||
{
|
||||
case QStyle::PM_MenuBarHMargin:
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
case QStyle::PM_MenuBarItemSpacing:
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
case QStyle::PM_ToolBarExtensionExtent:
|
||||
{
|
||||
return 26;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QProxyStyle::pixelMetric(metric, option, widget);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef ELAMENUBARSTYLE_H
|
||||
#define ELAMENUBARSTYLE_H
|
||||
|
||||
#include <QProxyStyle>
|
||||
|
||||
#include "Def.h"
|
||||
class ElaMenuBarStyle : public QProxyStyle
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ElaMenuBarStyle(QStyle* style = nullptr);
|
||||
~ElaMenuBarStyle();
|
||||
void drawPrimitive(PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget = nullptr) const override;
|
||||
void drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget = nullptr) const override;
|
||||
QSize sizeFromContents(ContentsType type, const QStyleOption* option, const QSize& size, const QWidget* widget) const override;
|
||||
int pixelMetric(PixelMetric metric, const QStyleOption* option = nullptr, const QWidget* widget = nullptr) const override;
|
||||
|
||||
private:
|
||||
ElaThemeType::ThemeMode _themeMode;
|
||||
int _menuBarItemMargin{0};
|
||||
};
|
||||
|
||||
#endif // ELAMENUBARSTYLE_H
|
||||
@@ -0,0 +1,233 @@
|
||||
#include "ElaMenuStyle.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QStyleOption>
|
||||
|
||||
#include "ElaMenu.h"
|
||||
#include "ElaTheme.h"
|
||||
ElaMenuStyle::ElaMenuStyle(QStyle* style)
|
||||
{
|
||||
_pMenuItemHeight = 32;
|
||||
_themeMode = eTheme->getThemeMode();
|
||||
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) {
|
||||
_themeMode = themeMode;
|
||||
});
|
||||
}
|
||||
|
||||
ElaMenuStyle::~ElaMenuStyle()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaMenuStyle::drawPrimitive(PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const
|
||||
{
|
||||
switch (element)
|
||||
{
|
||||
case QStyle::PE_PanelMenu:
|
||||
{
|
||||
// 高性能阴影
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing);
|
||||
eTheme->drawEffectShadow(painter, option->rect, _shadowBorderWidth, 6);
|
||||
// 背景绘制
|
||||
QRect foregroundRect(_shadowBorderWidth, _shadowBorderWidth, option->rect.width() - 2 * _shadowBorderWidth, option->rect.height() - 2 * _shadowBorderWidth);
|
||||
painter->setPen(ElaThemeColor(_themeMode, PopupBorder));
|
||||
painter->setBrush(ElaThemeColor(_themeMode, PopupBase));
|
||||
painter->drawRoundedRect(foregroundRect, 6, 6);
|
||||
painter->restore();
|
||||
return;
|
||||
}
|
||||
case QStyle::PE_FrameMenu:
|
||||
{
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
QProxyStyle::drawPrimitive(element, option, painter, widget);
|
||||
}
|
||||
|
||||
void ElaMenuStyle::drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const
|
||||
{
|
||||
switch (element)
|
||||
{
|
||||
case QStyle::CE_MenuItem:
|
||||
{
|
||||
//内容绘制 区分类型
|
||||
if (const QStyleOptionMenuItem* mopt = qstyleoption_cast<const QStyleOptionMenuItem*>(option))
|
||||
{
|
||||
if (mopt->menuItemType == QStyleOptionMenuItem::Separator)
|
||||
{
|
||||
QRect separatorRect = mopt->rect;
|
||||
painter->save();
|
||||
painter->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicBaseLine));
|
||||
painter->drawRoundedRect(QRectF(separatorRect.x() + separatorRect.width() * 0.055, separatorRect.center().y(), separatorRect.width() - separatorRect.width() * 0.11, 1.5), 1, 1);
|
||||
painter->restore();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
QRect menuRect = mopt->rect;
|
||||
qreal contentPadding = menuRect.width() * 0.055;
|
||||
qreal textLeftSpacing = menuRect.width() * 0.082;
|
||||
painter->save();
|
||||
painter->setRenderHints(QPainter::SmoothPixmapTransform | QPainter::Antialiasing | QPainter::TextAntialiasing);
|
||||
//覆盖效果
|
||||
if (mopt->state.testFlag(QStyle::State_Enabled) && (mopt->state.testFlag(QStyle::State_MouseOver) || mopt->state.testFlag(QStyle::State_Selected)))
|
||||
{
|
||||
QRect hoverRect = menuRect;
|
||||
hoverRect.adjust(0, 2, 0, -2);
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(ElaThemeColor(_themeMode, PopupHover));
|
||||
painter->drawRoundedRect(hoverRect, 5, 5);
|
||||
}
|
||||
//Icon绘制
|
||||
QIcon menuIcon = mopt->icon;
|
||||
//check绘制
|
||||
if (mopt->menuHasCheckableItems)
|
||||
{
|
||||
painter->save();
|
||||
painter->setPen(!mopt->state.testFlag(QStyle::State_Enabled) ? Qt::gray : _themeMode == ElaThemeType::Light ? Qt::black
|
||||
: Qt::white);
|
||||
QFont iconFont = QFont("ElaAwesome");
|
||||
iconFont.setPixelSize(_pMenuItemHeight * 0.57);
|
||||
painter->setFont(iconFont);
|
||||
painter->drawText(QRectF(menuRect.x() + contentPadding, menuRect.y(), _iconWidth, menuRect.height()), Qt::AlignCenter, mopt->checked ? QChar((unsigned short)ElaIconType::Check) : QChar((unsigned short)ElaIconType::None));
|
||||
painter->restore();
|
||||
}
|
||||
else
|
||||
{
|
||||
QString iconText;
|
||||
const ElaMenu* menu = dynamic_cast<const ElaMenu*>(widget);
|
||||
if (menu)
|
||||
{
|
||||
QAction* action = menu->actionAt(menuRect.center());
|
||||
if (action)
|
||||
{
|
||||
iconText = action->property("ElaIconType").toString();
|
||||
}
|
||||
}
|
||||
if (!iconText.isEmpty())
|
||||
{
|
||||
painter->save();
|
||||
painter->setPen(!mopt->state.testFlag(QStyle::State_Enabled) ? Qt::gray : _themeMode == ElaThemeType::Light ? Qt::black
|
||||
: Qt::white);
|
||||
QFont iconFont = QFont("ElaAwesome");
|
||||
iconFont.setPixelSize(_pMenuItemHeight * 0.57);
|
||||
painter->setFont(iconFont);
|
||||
painter->drawText(QRectF(menuRect.x() + contentPadding, menuRect.y(), _iconWidth, menuRect.height()), Qt::AlignCenter, iconText);
|
||||
painter->restore();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!menuIcon.isNull())
|
||||
{
|
||||
painter->drawPixmap(QRect(menuRect.x() + contentPadding, menuRect.center().y() - _iconWidth / 2, _iconWidth, _iconWidth), menuIcon.pixmap(_iconWidth, _iconWidth));
|
||||
}
|
||||
}
|
||||
}
|
||||
//文字和快捷键绘制
|
||||
if (!mopt->text.isEmpty())
|
||||
{
|
||||
QStringList textList = mopt->text.split("\t");
|
||||
painter->setPen(!mopt->state.testFlag(QStyle::State_Enabled) ? Qt::gray : _themeMode == ElaThemeType::Light ? Qt::black
|
||||
: Qt::white);
|
||||
|
||||
painter->drawText(QRectF(menuRect.x() + (_isAnyoneItemHasIcon ? contentPadding + textLeftSpacing : 0) + _iconWidth, menuRect.y(), menuRect.width(), menuRect.height()), Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, textList[0]);
|
||||
if (textList.count() > 1)
|
||||
{
|
||||
painter->drawText(QRectF(menuRect.x() + contentPadding + _iconWidth + textLeftSpacing, menuRect.y(), menuRect.width() - (contentPadding * 2 + _iconWidth + textLeftSpacing), menuRect.height()), Qt::AlignRight | Qt::AlignVCenter | Qt::TextSingleLine, textList[1]);
|
||||
}
|
||||
}
|
||||
//展开图标
|
||||
if (mopt->menuItemType == QStyleOptionMenuItem::SubMenu)
|
||||
{
|
||||
painter->save();
|
||||
painter->setPen(!mopt->state.testFlag(QStyle::State_Enabled) ? Qt::gray : _themeMode == ElaThemeType::Light ? Qt::black
|
||||
: Qt::white);
|
||||
QFont iconFont = QFont("ElaAwesome");
|
||||
iconFont.setPixelSize(18);
|
||||
painter->setFont(iconFont);
|
||||
painter->drawText(QRect(menuRect.right() - 25, menuRect.y(), 25, menuRect.height()), Qt::AlignVCenter, QChar((unsigned short)ElaIconType::AngleRight));
|
||||
painter->restore();
|
||||
}
|
||||
painter->restore();
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
case QStyle::CE_MenuEmptyArea:
|
||||
{
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
QProxyStyle::drawControl(element, option, painter, widget);
|
||||
}
|
||||
|
||||
int ElaMenuStyle::pixelMetric(PixelMetric metric, const QStyleOption* option, const QWidget* widget) const
|
||||
{
|
||||
switch (metric)
|
||||
{
|
||||
case QStyle::PM_SmallIconSize:
|
||||
{
|
||||
//图标宽度
|
||||
return _iconWidth;
|
||||
}
|
||||
case QStyle::PM_MenuPanelWidth:
|
||||
{
|
||||
//外围容器宽度
|
||||
return _shadowBorderWidth * 1.5;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QProxyStyle::pixelMetric(metric, option, widget);
|
||||
}
|
||||
|
||||
QSize ElaMenuStyle::sizeFromContents(ContentsType type, const QStyleOption* option, const QSize& size, const QWidget* widget) const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case QStyle::CT_MenuItem:
|
||||
{
|
||||
if (const QStyleOptionMenuItem* mopt = qstyleoption_cast<const QStyleOptionMenuItem*>(option))
|
||||
{
|
||||
if (mopt->menuItemType == QStyleOptionMenuItem::Separator)
|
||||
{
|
||||
break;
|
||||
}
|
||||
QSize menuItemSize = QProxyStyle::sizeFromContents(type, option, size, widget);
|
||||
const ElaMenu* menu = dynamic_cast<const ElaMenu*>(widget);
|
||||
if (menu->isHasIcon() || mopt->menuHasCheckableItems)
|
||||
{
|
||||
_isAnyoneItemHasIcon = true;
|
||||
}
|
||||
if (menu->isHasChildMenu())
|
||||
{
|
||||
return QSize(menuItemSize.width() + 20, _pMenuItemHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
return QSize(menuItemSize.width(), _pMenuItemHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QProxyStyle::sizeFromContents(type, option, size, widget);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef ELAMENUSTYLE_H
|
||||
#define ELAMENUSTYLE_H
|
||||
|
||||
#include <QProxyStyle>
|
||||
|
||||
#include "Def.h"
|
||||
|
||||
class ElaMenuStyle : public QProxyStyle
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_CREATE(int, MenuItemHeight);
|
||||
|
||||
public:
|
||||
explicit ElaMenuStyle(QStyle* style = nullptr);
|
||||
~ElaMenuStyle();
|
||||
void drawPrimitive(PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget = nullptr) const override;
|
||||
void drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget = nullptr) const override;
|
||||
int pixelMetric(PixelMetric metric, const QStyleOption* option = nullptr, const QWidget* widget = nullptr) const override;
|
||||
QSize sizeFromContents(ContentsType type, const QStyleOption* option, const QSize& size, const QWidget* widget) const override;
|
||||
|
||||
private:
|
||||
mutable bool _isAnyoneItemHasIcon{false};
|
||||
int _shadowBorderWidth{6};
|
||||
ElaThemeType::ThemeMode _themeMode;
|
||||
int _iconWidth{22};
|
||||
};
|
||||
|
||||
#endif // ELAMENUSTYLE_H
|
||||
@@ -0,0 +1,71 @@
|
||||
#include "ElaMicaBaseInitObject.h"
|
||||
|
||||
#include <QImage>
|
||||
|
||||
#include "ElaApplicationPrivate.h"
|
||||
#include "ElaExponentialBlur.h"
|
||||
ElaMicaBaseInitObject::ElaMicaBaseInitObject(ElaApplicationPrivate* appPrivate, QObject* parent)
|
||||
: QObject{parent}
|
||||
{
|
||||
_appPrivate = appPrivate;
|
||||
}
|
||||
|
||||
ElaMicaBaseInitObject::~ElaMicaBaseInitObject()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaMicaBaseInitObject::onInitMicaBase(QImage img)
|
||||
{
|
||||
// QColorDialog
|
||||
// 统一处理为1920*1080以节省空间
|
||||
img = img.scaled(QSize(1920, 1080), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||
|
||||
QImage blurImage = ElaExponentialBlur::doExponentialBlur(img, 500).toImage();
|
||||
QImage lightImage = blurImage;
|
||||
QImage darkImage = blurImage;
|
||||
QColor lightMixColor = QColor(0xF3, 0xF3, 0xF3);
|
||||
lightMixColor = lightMixColor.toHsv();
|
||||
QColor darkMixColor = QColor(0x20, 0x20, 0x20);
|
||||
darkMixColor = darkMixColor.toHsv();
|
||||
QColor originColor;
|
||||
QColor lightColor;
|
||||
QColor darkColor;
|
||||
int h, s, v;
|
||||
for (int y = 0; y < blurImage.height(); y++)
|
||||
{
|
||||
QRgb* line = (QRgb*)blurImage.scanLine(y);
|
||||
for (int x = 0; x < blurImage.width(); x++)
|
||||
{
|
||||
originColor = QColor(line[x]);
|
||||
originColor = originColor.toHsv();
|
||||
h = originColor.hsvHue();
|
||||
s = originColor.hsvSaturation();
|
||||
v = originColor.value();
|
||||
if (s / 20 > 11)
|
||||
{
|
||||
lightColor.setHsv(h, (s / 20 + 11) / 2, 250);
|
||||
}
|
||||
else
|
||||
{
|
||||
lightColor.setHsv(h, 11, 250);
|
||||
}
|
||||
lightColor = lightColor.toRgb();
|
||||
if (v / 1.1 > 40)
|
||||
{
|
||||
darkColor.setHsv(h, s / 2, (v / 1.1 + 40) / 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
darkColor.setHsv(h, s / 2, 40);
|
||||
}
|
||||
darkColor = darkColor.toRgb();
|
||||
lightImage.setPixel(x, y, qRgb(lightColor.red(), lightColor.green(), lightColor.blue()));
|
||||
darkImage.setPixel(x, y, qRgb(darkColor.red(), darkColor.green(), darkColor.blue()));
|
||||
}
|
||||
}
|
||||
_appPrivate->_lightBaseImage = lightImage.copy();
|
||||
_appPrivate->_darkBaseImage = darkImage.copy();
|
||||
// _appPrivate->_lightBaseImage.save("light.png", "PNG");
|
||||
// _appPrivate->_darkBaseImage.save("dark.png", "PNG");
|
||||
Q_EMIT initFinished();
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef ELAMICABASEINITOBJECT_H
|
||||
#define ELAMICABASEINITOBJECT_H
|
||||
|
||||
#include <QObject>
|
||||
class ElaApplicationPrivate;
|
||||
class ElaMicaBaseInitObject : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ElaMicaBaseInitObject(ElaApplicationPrivate* appPrivate, QObject* parent = nullptr);
|
||||
~ElaMicaBaseInitObject();
|
||||
Q_SLOT void onInitMicaBase(QImage img);
|
||||
Q_SIGNALS:
|
||||
Q_SIGNAL void initFinished();
|
||||
|
||||
private:
|
||||
ElaApplicationPrivate* _appPrivate{nullptr};
|
||||
};
|
||||
|
||||
#endif // ELAMICABASEINITOBJECT_H
|
||||
@@ -0,0 +1,284 @@
|
||||
#include "ElaNavigationModel.h"
|
||||
|
||||
#include <QIcon>
|
||||
#include <QJsonObject>
|
||||
|
||||
#include "ElaNavigationNode.h"
|
||||
ElaNavigationModel::ElaNavigationModel(QObject* parent)
|
||||
: QAbstractItemModel{parent}
|
||||
{
|
||||
_rootNode = new ElaNavigationNode("root");
|
||||
_rootNode->setIsRootNode(true);
|
||||
_rootNode->setIsExpanderNode(true);
|
||||
_pSelectedNode = nullptr;
|
||||
_pSelectedExpandedNode = nullptr;
|
||||
}
|
||||
|
||||
ElaNavigationModel::~ElaNavigationModel()
|
||||
{
|
||||
delete _rootNode;
|
||||
}
|
||||
|
||||
QModelIndex ElaNavigationModel::parent(const QModelIndex& child) const
|
||||
{
|
||||
if (!child.isValid())
|
||||
{
|
||||
return QModelIndex();
|
||||
}
|
||||
ElaNavigationNode* childNode = static_cast<ElaNavigationNode*>(child.internalPointer());
|
||||
ElaNavigationNode* parentNode = childNode->getParentNode();
|
||||
if (parentNode == _rootNode)
|
||||
{
|
||||
return QModelIndex();
|
||||
}
|
||||
else if (parentNode == nullptr)
|
||||
{
|
||||
return QModelIndex();
|
||||
}
|
||||
return createIndex(parentNode->getRow(), 0, parentNode);
|
||||
}
|
||||
|
||||
QModelIndex ElaNavigationModel::index(int row, int column, const QModelIndex& parent) const
|
||||
{
|
||||
if (!hasIndex(row, column, parent))
|
||||
{
|
||||
return QModelIndex();
|
||||
}
|
||||
ElaNavigationNode* parentNode;
|
||||
if (!parent.isValid())
|
||||
{
|
||||
parentNode = _rootNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
parentNode = static_cast<ElaNavigationNode*>(parent.internalPointer());
|
||||
}
|
||||
ElaNavigationNode* childNode = nullptr;
|
||||
if (parentNode->getChildrenNodes().count() > row)
|
||||
{
|
||||
childNode = parentNode->getChildrenNodes().at(row);
|
||||
}
|
||||
if (childNode)
|
||||
{
|
||||
return createIndex(row, column, childNode);
|
||||
}
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
int ElaNavigationModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
ElaNavigationNode* parentNode;
|
||||
if (parent.column() > 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (!parent.isValid())
|
||||
{
|
||||
parentNode = _rootNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
parentNode = static_cast<ElaNavigationNode*>(parent.internalPointer());
|
||||
}
|
||||
return parentNode->getChildrenNodes().count();
|
||||
};
|
||||
|
||||
int ElaNavigationModel::columnCount(const QModelIndex& parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
return 1;
|
||||
}
|
||||
|
||||
QVariant ElaNavigationModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
Q_UNUSED(index)
|
||||
Q_UNUSED(role)
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
ElaNavigationType::NodeOperateReturnType ElaNavigationModel::addExpanderNode(QString expanderTitle, QString& expanderKey, ElaIconType::IconName awesome)
|
||||
{
|
||||
ElaNavigationNode* node = new ElaNavigationNode(expanderTitle, _rootNode);
|
||||
node->setDepth(1);
|
||||
node->setIsVisible(true);
|
||||
node->setIsExpanderNode(true);
|
||||
node->setAwesome(awesome);
|
||||
beginInsertRows(QModelIndex(), _rootNode->getChildrenNodes().count(), _rootNode->getChildrenNodes().count());
|
||||
_rootNode->appendChildNode(node);
|
||||
_nodesMap.insert(node->getNodeKey(), node);
|
||||
endInsertRows();
|
||||
expanderKey = node->getNodeKey();
|
||||
return ElaNavigationType::NodeOperateReturnType::Success;
|
||||
}
|
||||
|
||||
ElaNavigationType::NodeOperateReturnType ElaNavigationModel::addExpanderNode(QString expanderTitle, QString& expanderKey, QString targetExpanderKey, ElaIconType::IconName awesome)
|
||||
{
|
||||
if (!_nodesMap.contains(targetExpanderKey))
|
||||
{
|
||||
return ElaNavigationType::NodeOperateReturnType::TargetNodeInvalid;
|
||||
}
|
||||
ElaNavigationNode* parentNode = _nodesMap.value(targetExpanderKey);
|
||||
if (!parentNode->getIsExpanderNode())
|
||||
{
|
||||
return ElaNavigationType::NodeOperateReturnType::TargetNodeTypeError;
|
||||
}
|
||||
if (parentNode->getDepth() > 10)
|
||||
{
|
||||
return ElaNavigationType::NodeOperateReturnType::TargetNodeDepthLimit;
|
||||
}
|
||||
ElaNavigationNode* node = new ElaNavigationNode(expanderTitle, parentNode);
|
||||
node->setDepth(parentNode->getDepth() + 1);
|
||||
node->setIsExpanderNode(true);
|
||||
node->setAwesome(awesome);
|
||||
if (parentNode->getIsVisible() && parentNode->getIsExpanded())
|
||||
{
|
||||
node->setIsVisible(true);
|
||||
}
|
||||
beginInsertRows(parentNode->getModelIndex(), parentNode->getChildrenNodes().count(), parentNode->getChildrenNodes().count());
|
||||
parentNode->appendChildNode(node);
|
||||
_nodesMap.insert(node->getNodeKey(), node);
|
||||
endInsertRows();
|
||||
expanderKey = node->getNodeKey();
|
||||
return ElaNavigationType::NodeOperateReturnType::Success;
|
||||
}
|
||||
|
||||
ElaNavigationType::NodeOperateReturnType ElaNavigationModel::addPageNode(QString pageTitle, QString& pageKey, ElaIconType::IconName awesome)
|
||||
{
|
||||
ElaNavigationNode* node = new ElaNavigationNode(pageTitle, _rootNode);
|
||||
node->setAwesome(awesome);
|
||||
node->setDepth(1);
|
||||
node->setIsVisible(true);
|
||||
beginInsertRows(QModelIndex(), _rootNode->getChildrenNodes().count(), _rootNode->getChildrenNodes().count());
|
||||
_rootNode->appendChildNode(node);
|
||||
_nodesMap.insert(node->getNodeKey(), node);
|
||||
endInsertRows();
|
||||
pageKey = node->getNodeKey();
|
||||
if (!_pSelectedNode)
|
||||
{
|
||||
_pSelectedNode = node;
|
||||
}
|
||||
return ElaNavigationType::NodeOperateReturnType::Success;
|
||||
}
|
||||
|
||||
ElaNavigationType::NodeOperateReturnType ElaNavigationModel::addPageNode(QString pageTitle, QString& pageKey, QString targetExpanderKey, ElaIconType::IconName awesome)
|
||||
{
|
||||
if (!_nodesMap.contains(targetExpanderKey))
|
||||
{
|
||||
return ElaNavigationType::NodeOperateReturnType::TargetNodeInvalid;
|
||||
}
|
||||
ElaNavigationNode* parentNode = _nodesMap.value(targetExpanderKey);
|
||||
if (!parentNode->getIsExpanderNode())
|
||||
{
|
||||
return ElaNavigationType::NodeOperateReturnType::TargetNodeTypeError;
|
||||
}
|
||||
if (parentNode->getDepth() > 10)
|
||||
{
|
||||
return ElaNavigationType::NodeOperateReturnType::TargetNodeDepthLimit;
|
||||
}
|
||||
ElaNavigationNode* node = new ElaNavigationNode(pageTitle, parentNode);
|
||||
node->setDepth(parentNode->getDepth() + 1);
|
||||
node->setAwesome(awesome);
|
||||
if (parentNode->getIsVisible() && parentNode->getIsExpanded())
|
||||
{
|
||||
node->setIsVisible(true);
|
||||
}
|
||||
beginInsertRows(parentNode->getModelIndex(), parentNode->getChildrenNodes().count(), parentNode->getChildrenNodes().count());
|
||||
parentNode->appendChildNode(node);
|
||||
_nodesMap.insert(node->getNodeKey(), node);
|
||||
endInsertRows();
|
||||
pageKey = node->getNodeKey();
|
||||
if (!_pSelectedNode)
|
||||
{
|
||||
_pSelectedNode = node;
|
||||
}
|
||||
return ElaNavigationType::NodeOperateReturnType::Success;
|
||||
}
|
||||
|
||||
ElaNavigationType::NodeOperateReturnType ElaNavigationModel::addPageNode(QString pageTitle, QString& pageKey, int keyPoints, ElaIconType::IconName awesome)
|
||||
{
|
||||
ElaNavigationNode* node = new ElaNavigationNode(pageTitle, _rootNode);
|
||||
node->setAwesome(awesome);
|
||||
node->setDepth(1);
|
||||
node->setIsVisible(true);
|
||||
node->setKeyPoints(keyPoints);
|
||||
beginInsertRows(QModelIndex(), _rootNode->getChildrenNodes().count(), _rootNode->getChildrenNodes().count());
|
||||
_rootNode->appendChildNode(node);
|
||||
_nodesMap.insert(node->getNodeKey(), node);
|
||||
endInsertRows();
|
||||
pageKey = node->getNodeKey();
|
||||
if (!_pSelectedNode)
|
||||
{
|
||||
_pSelectedNode = node;
|
||||
}
|
||||
return ElaNavigationType::NodeOperateReturnType::Success;
|
||||
}
|
||||
|
||||
ElaNavigationType::NodeOperateReturnType ElaNavigationModel::addPageNode(QString pageTitle, QString& pageKey, QString targetExpanderKey, int keyPoints, ElaIconType::IconName awesome)
|
||||
{
|
||||
if (!_nodesMap.contains(targetExpanderKey))
|
||||
{
|
||||
return ElaNavigationType::NodeOperateReturnType::TargetNodeInvalid;
|
||||
}
|
||||
ElaNavigationNode* parentNode = _nodesMap.value(targetExpanderKey);
|
||||
if (!parentNode->getIsExpanderNode())
|
||||
{
|
||||
return ElaNavigationType::NodeOperateReturnType::TargetNodeTypeError;
|
||||
}
|
||||
if (parentNode->getDepth() > 10)
|
||||
{
|
||||
return ElaNavigationType::NodeOperateReturnType::TargetNodeDepthLimit;
|
||||
}
|
||||
ElaNavigationNode* node = new ElaNavigationNode(pageTitle, parentNode);
|
||||
node->setDepth(parentNode->getDepth() + 1);
|
||||
node->setAwesome(awesome);
|
||||
node->setKeyPoints(keyPoints);
|
||||
if (parentNode->getIsVisible() && parentNode->getIsExpanded())
|
||||
{
|
||||
node->setIsVisible(true);
|
||||
}
|
||||
beginInsertRows(parentNode->getModelIndex(), parentNode->getChildrenNodes().count(), parentNode->getChildrenNodes().count());
|
||||
parentNode->appendChildNode(node);
|
||||
_nodesMap.insert(node->getNodeKey(), node);
|
||||
endInsertRows();
|
||||
pageKey = node->getNodeKey();
|
||||
if (!_pSelectedNode)
|
||||
{
|
||||
_pSelectedNode = node;
|
||||
}
|
||||
return ElaNavigationType::NodeOperateReturnType::Success;
|
||||
}
|
||||
|
||||
ElaNavigationNode* ElaNavigationModel::getNavigationNode(QString nodeKey) const
|
||||
{
|
||||
if (_nodesMap.contains(nodeKey))
|
||||
{
|
||||
return _nodesMap.value(nodeKey);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QList<ElaNavigationNode*> ElaNavigationModel::getRootExpanderNodes() const
|
||||
{
|
||||
QList<ElaNavigationNode*> expandedNodeList;
|
||||
for (auto node : _rootNode->getChildrenNodes())
|
||||
{
|
||||
if (node->getIsExpanderNode())
|
||||
{
|
||||
expandedNodeList.append(node);
|
||||
}
|
||||
}
|
||||
return expandedNodeList;
|
||||
}
|
||||
|
||||
QList<ElaNavigationNode*> ElaNavigationModel::getRootExpandedNodes() const
|
||||
{
|
||||
QList<ElaNavigationNode*> expandedNodeList;
|
||||
for (auto node : _rootNode->getChildrenNodes())
|
||||
{
|
||||
if (node->getIsExpanderNode() && node->getIsExpanded())
|
||||
{
|
||||
expandedNodeList.append(node);
|
||||
}
|
||||
}
|
||||
return expandedNodeList;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
#ifndef ELANAVIGATIONMODEL_H
|
||||
#define ELANAVIGATIONMODEL_H
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QObject>
|
||||
|
||||
#include "Def.h"
|
||||
#include "stdafx.h"
|
||||
class ElaNavigationNode;
|
||||
class ElaNavigationModel : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PRIVATE_CREATE(ElaNavigationNode*, SelectedNode)
|
||||
Q_PRIVATE_CREATE(ElaNavigationNode*, SelectedExpandedNode)
|
||||
|
||||
public:
|
||||
explicit ElaNavigationModel(QObject* parent = nullptr);
|
||||
~ElaNavigationModel();
|
||||
QModelIndex parent(const QModelIndex& child) const override;
|
||||
QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override;
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
||||
ElaNavigationType::NodeOperateReturnType addExpanderNode(QString expanderTitle, QString& expanderKey, ElaIconType::IconName awesome);
|
||||
ElaNavigationType::NodeOperateReturnType addExpanderNode(QString expanderTitle, QString& expanderKey, QString targetExpanderKey, ElaIconType::IconName awesome);
|
||||
ElaNavigationType::NodeOperateReturnType addPageNode(QString pageTitle, QString& pageKey, ElaIconType::IconName awesome);
|
||||
ElaNavigationType::NodeOperateReturnType addPageNode(QString pageTitle, QString& pageKey, QString targetExpanderKey, ElaIconType::IconName awesome);
|
||||
ElaNavigationType::NodeOperateReturnType addPageNode(QString pageTitle, QString& pageKey, int keyPoints, ElaIconType::IconName awesome);
|
||||
ElaNavigationType::NodeOperateReturnType addPageNode(QString pageTitle, QString& pageKey, QString targetExpanderKey, int keyPoints, ElaIconType::IconName awesome);
|
||||
|
||||
ElaNavigationNode* getNavigationNode(QString nodeKey) const;
|
||||
QList<ElaNavigationNode*> getRootExpanderNodes() const;
|
||||
QList<ElaNavigationNode*> getRootExpandedNodes() const;
|
||||
|
||||
private:
|
||||
mutable QMap<QString, ElaNavigationNode*> _nodesMap;
|
||||
ElaNavigationNode* _rootNode{nullptr};
|
||||
};
|
||||
|
||||
#endif // ELANAVIGATIONMODEL_H
|
||||
@@ -0,0 +1,166 @@
|
||||
#include "ElaNavigationNode.h"
|
||||
|
||||
#include <QUuid>
|
||||
|
||||
ElaNavigationNode::ElaNavigationNode(QString nodeTitle, ElaNavigationNode* parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
_pDepth = 0;
|
||||
_pKeyPoints = 0;
|
||||
_nodeKey = QUuid::createUuid().toString().remove("{").remove("}").remove("-");
|
||||
_nodeTitle = nodeTitle;
|
||||
_pIsRootNode = false;
|
||||
_pIsFooterNode = false;
|
||||
_pIsHasFooterPage = false;
|
||||
_pParentNode = parent;
|
||||
_pIsExpanderNode = false;
|
||||
_pIsVisible = false;
|
||||
}
|
||||
|
||||
ElaNavigationNode::~ElaNavigationNode()
|
||||
{
|
||||
qDeleteAll(_pChildrenNodes);
|
||||
}
|
||||
|
||||
QString ElaNavigationNode::getNodeKey() const
|
||||
{
|
||||
return _nodeKey;
|
||||
}
|
||||
|
||||
QString ElaNavigationNode::getNodeTitle() const
|
||||
{
|
||||
return _nodeTitle;
|
||||
}
|
||||
|
||||
void ElaNavigationNode::setIsExpanded(bool isExpanded)
|
||||
{
|
||||
_isExpanded = isExpanded;
|
||||
setChildVisible(isExpanded);
|
||||
}
|
||||
|
||||
bool ElaNavigationNode::getIsExpanded() const
|
||||
{
|
||||
return _isExpanded;
|
||||
}
|
||||
|
||||
void ElaNavigationNode::setChildVisible(bool isVisible)
|
||||
{
|
||||
if (isVisible)
|
||||
{
|
||||
for (auto node : _pChildrenNodes)
|
||||
{
|
||||
node->setIsVisible(isVisible);
|
||||
if (node->getIsExpanderNode() && !node->getIsExpanded())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
node->setChildVisible(isVisible);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto node : _pChildrenNodes)
|
||||
{
|
||||
node->setChildVisible(isVisible);
|
||||
node->setIsVisible(isVisible);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ElaNavigationNode::getIsHasChild() const
|
||||
{
|
||||
if (_pChildrenNodes.count() > 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ElaNavigationNode::getIsHasPageChild() const
|
||||
{
|
||||
if (_pChildrenNodes.count() == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (auto childNode : _pChildrenNodes)
|
||||
{
|
||||
if (!childNode->getIsExpanderNode())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (childNode->getIsHasPageChild())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ElaNavigationNode::appendChildNode(ElaNavigationNode* childNode)
|
||||
{
|
||||
if (_pIsExpanderNode)
|
||||
{
|
||||
_pChildrenNodes.append(childNode);
|
||||
}
|
||||
}
|
||||
|
||||
bool ElaNavigationNode::getIsChildHasKeyPoints() const
|
||||
{
|
||||
for (auto childNnode : _pChildrenNodes)
|
||||
{
|
||||
if (childNnode->getKeyPoints())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (childNnode->getIsChildHasKeyPoints())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ElaNavigationNode* ElaNavigationNode::getOriginalNode()
|
||||
{
|
||||
if (this->getParentNode()->getIsRootNode())
|
||||
{
|
||||
return this;
|
||||
}
|
||||
else
|
||||
{
|
||||
ElaNavigationNode* originalNode = this->getParentNode();
|
||||
while (!originalNode->getIsRootNode() && !originalNode->getParentNode()->getIsRootNode())
|
||||
{
|
||||
originalNode = originalNode->getParentNode();
|
||||
}
|
||||
return originalNode;
|
||||
}
|
||||
}
|
||||
|
||||
bool ElaNavigationNode::getIsChildNode(ElaNavigationNode* node)
|
||||
{
|
||||
if (_pChildrenNodes.count() > 0)
|
||||
{
|
||||
if (_pChildrenNodes.contains(node))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
for (auto childNnode : _pChildrenNodes)
|
||||
{
|
||||
if (childNnode->getIsChildNode(node))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int ElaNavigationNode::getRow() const
|
||||
{
|
||||
if (_pParentNode)
|
||||
{
|
||||
return _pParentNode->getChildrenNodes().indexOf(const_cast<ElaNavigationNode*>(this));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
#ifndef ELANAVIGATIONNODE_H
|
||||
#define ELANAVIGATIONNODE_H
|
||||
|
||||
#include <QModelIndex>
|
||||
#include <QObject>
|
||||
|
||||
#include "Def.h"
|
||||
|
||||
class ElaNavigationNode : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_CREATE(QList<ElaNavigationNode*>, ChildrenNodes)
|
||||
Q_PRIVATE_CREATE(ElaNavigationNode*, ParentNode)
|
||||
Q_PROPERTY_CREATE(ElaIconType::IconName, Awesome)
|
||||
Q_PROPERTY_CREATE(QModelIndex, ModelIndex)
|
||||
Q_PROPERTY_CREATE(int, KeyPoints)
|
||||
Q_PROPERTY_CREATE(int, Depth)
|
||||
Q_PROPERTY_CREATE(bool, IsRootNode)
|
||||
Q_PROPERTY_CREATE(bool, IsFooterNode)
|
||||
Q_PROPERTY_CREATE(bool, IsHasFooterPage)
|
||||
Q_PROPERTY_CREATE(bool, IsExpanderNode)
|
||||
Q_PROPERTY_CREATE(bool, IsVisible)
|
||||
public:
|
||||
explicit ElaNavigationNode(QString nodeTitle, ElaNavigationNode* parent = nullptr);
|
||||
~ElaNavigationNode();
|
||||
|
||||
QString getNodeKey() const;
|
||||
QString getNodeTitle() const;
|
||||
|
||||
void setIsExpanded(bool isExpanded);
|
||||
bool getIsExpanded() const;
|
||||
|
||||
void setChildVisible(bool isVisible);
|
||||
bool getIsHasChild() const;
|
||||
bool getIsHasPageChild() const;
|
||||
|
||||
void appendChildNode(ElaNavigationNode* childNode);
|
||||
|
||||
bool getIsChildHasKeyPoints() const;
|
||||
|
||||
ElaNavigationNode* getOriginalNode();
|
||||
bool getIsChildNode(ElaNavigationNode* node);
|
||||
|
||||
int getRow() const;
|
||||
|
||||
private:
|
||||
QString _nodeKey = "";
|
||||
QString _nodeTitle = "";
|
||||
bool _isExpanded{false};
|
||||
};
|
||||
|
||||
#endif // ELANAVIGATIONNODE_H
|
||||
@@ -0,0 +1,519 @@
|
||||
#include "ElaNavigationStyle.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QPropertyAnimation>
|
||||
#include <QStyleOption>
|
||||
|
||||
#include "ElaNavigationModel.h"
|
||||
#include "ElaNavigationNode.h"
|
||||
#include "ElaNavigationView.h"
|
||||
#include "ElaTheme.h"
|
||||
ElaNavigationStyle::ElaNavigationStyle(QStyle* style)
|
||||
{
|
||||
_pOpacity = 1;
|
||||
_pItemHeight = 40;
|
||||
_pLastSelectMarkTop = 10.0;
|
||||
_pLastSelectMarkBottom = 10.0;
|
||||
_pSelectMarkTop = 10.0;
|
||||
_pSelectMarkBottom = 10.0;
|
||||
|
||||
// Mark向上
|
||||
_lastSelectMarkTopAnimation = new QPropertyAnimation(this, "pLastSelectMarkTop");
|
||||
connect(_lastSelectMarkTopAnimation, &QPropertyAnimation::valueChanged, this, [=](const QVariant& value) { _pNavigationView->viewport()->update(); });
|
||||
_lastSelectMarkTopAnimation->setDuration(300);
|
||||
_lastSelectMarkTopAnimation->setEasingCurve(QEasingCurve::InOutSine);
|
||||
|
||||
_selectMarkBottomAnimation = new QPropertyAnimation(this, "pSelectMarkBottom");
|
||||
connect(_selectMarkBottomAnimation, &QPropertyAnimation::valueChanged, this, [=](const QVariant& value) { _pNavigationView->viewport()->update(); });
|
||||
_selectMarkBottomAnimation->setDuration(300);
|
||||
_selectMarkBottomAnimation->setEasingCurve(QEasingCurve::InOutSine);
|
||||
connect(_lastSelectMarkTopAnimation, &QPropertyAnimation::finished, this, [=]() {
|
||||
_isSelectMarkDisplay = true;
|
||||
_lastSelectedNode = nullptr;
|
||||
_selectMarkBottomAnimation->setStartValue(0);
|
||||
_selectMarkBottomAnimation->setEndValue(10);
|
||||
_selectMarkBottomAnimation->start(); });
|
||||
|
||||
// Mark向下
|
||||
_lastSelectMarkBottomAnimation = new QPropertyAnimation(this, "pLastSelectMarkBottom");
|
||||
connect(_lastSelectMarkBottomAnimation, &QPropertyAnimation::valueChanged, this, [=](const QVariant& value) { _pNavigationView->viewport()->update(); });
|
||||
_lastSelectMarkBottomAnimation->setDuration(300);
|
||||
_lastSelectMarkBottomAnimation->setEasingCurve(QEasingCurve::InOutSine);
|
||||
|
||||
_selectMarkTopAnimation = new QPropertyAnimation(this, "pSelectMarkTop");
|
||||
connect(_selectMarkTopAnimation, &QPropertyAnimation::valueChanged, this, [=](const QVariant& value) { _pNavigationView->viewport()->update(); });
|
||||
_selectMarkTopAnimation->setDuration(300);
|
||||
_selectMarkTopAnimation->setEasingCurve(QEasingCurve::InOutSine);
|
||||
connect(_lastSelectMarkBottomAnimation, &QPropertyAnimation::finished, this, [=]() {
|
||||
_isSelectMarkDisplay = true;
|
||||
_lastSelectedNode = nullptr;
|
||||
_selectMarkTopAnimation->setStartValue(0);
|
||||
_selectMarkTopAnimation->setEndValue(10);
|
||||
_selectMarkTopAnimation->start(); });
|
||||
_themeMode = eTheme->getThemeMode();
|
||||
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) {
|
||||
_themeMode = themeMode;
|
||||
});
|
||||
}
|
||||
|
||||
ElaNavigationStyle::~ElaNavigationStyle()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaNavigationStyle::drawPrimitive(PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const
|
||||
{
|
||||
switch (element)
|
||||
{
|
||||
case QStyle::PE_PanelItemViewItem:
|
||||
{
|
||||
// Item背景
|
||||
if (const QStyleOptionViewItem* vopt = qstyleoption_cast<const QStyleOptionViewItem*>(option))
|
||||
{
|
||||
painter->save();
|
||||
QModelIndex index = vopt->index;
|
||||
ElaNavigationNode* node = static_cast<ElaNavigationNode*>(index.internalPointer());
|
||||
if (this->_opacityAnimationTargetNode && node->getParentNode() == this->_opacityAnimationTargetNode)
|
||||
{
|
||||
painter->setOpacity(_pOpacity);
|
||||
}
|
||||
painter->setRenderHint(QPainter::Antialiasing);
|
||||
QRect itemRect = vopt->rect;
|
||||
itemRect.setTop(itemRect.top() + 2);
|
||||
itemRect.setBottom(itemRect.bottom() - 2);
|
||||
QPainterPath path;
|
||||
path.addRoundedRect(itemRect, 8, 8);
|
||||
if (vopt->state & QStyle::State_Selected)
|
||||
{
|
||||
if (index == _pPressIndex)
|
||||
{
|
||||
// 选中时点击
|
||||
painter->fillPath(path, ElaThemeColor(_themeMode, BasicHoverAlpha));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vopt->state & QStyle::State_MouseOver)
|
||||
{
|
||||
// 选中时覆盖
|
||||
painter->fillPath(path, ElaThemeColor(_themeMode, BasicSelectedHoverAlpha));
|
||||
}
|
||||
else
|
||||
{
|
||||
// 选中
|
||||
painter->fillPath(path, ElaThemeColor(_themeMode, BasicSelectedAlpha));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (index == _pPressIndex)
|
||||
{
|
||||
// 点击时颜色
|
||||
painter->fillPath(path, ElaThemeColor(_themeMode, BasicSelectedHoverAlpha));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vopt->state & QStyle::State_MouseOver)
|
||||
{
|
||||
// 覆盖时颜色
|
||||
painter->fillPath(path, ElaThemeColor(_themeMode, BasicHoverAlpha));
|
||||
}
|
||||
}
|
||||
}
|
||||
painter->restore();
|
||||
}
|
||||
return;
|
||||
}
|
||||
case QStyle::PE_PanelItemViewRow:
|
||||
{
|
||||
// 行背景
|
||||
return;
|
||||
}
|
||||
case QStyle::PE_IndicatorBranch:
|
||||
{
|
||||
// Branch指示器
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
QProxyStyle::drawPrimitive(element, option, painter, widget);
|
||||
}
|
||||
|
||||
void ElaNavigationStyle::drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const
|
||||
{
|
||||
switch (element)
|
||||
{
|
||||
case QStyle::CE_ShapedFrame:
|
||||
{
|
||||
// viewport视口外的其他区域背景
|
||||
return;
|
||||
}
|
||||
case QStyle::CE_ItemViewItem:
|
||||
{
|
||||
if (const QStyleOptionViewItem* vopt = qstyleoption_cast<const QStyleOptionViewItem*>(option))
|
||||
{
|
||||
// 背景绘制
|
||||
this->drawPrimitive(QStyle::PE_PanelItemViewItem, option, painter, widget);
|
||||
|
||||
// 内容绘制
|
||||
QRect itemRect = option->rect;
|
||||
painter->save();
|
||||
painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::TextAntialiasing);
|
||||
ElaNavigationNode* node = static_cast<ElaNavigationNode*>(vopt->index.internalPointer());
|
||||
ElaNavigationModel* model = dynamic_cast<ElaNavigationModel*>(const_cast<QAbstractItemModel*>(vopt->index.model()));
|
||||
|
||||
if (this->_opacityAnimationTargetNode && node->getParentNode() == this->_opacityAnimationTargetNode)
|
||||
{
|
||||
painter->setOpacity(_pOpacity);
|
||||
}
|
||||
|
||||
// 选中特效
|
||||
if (_isSelectMarkDisplay && (node == model->getSelectedNode() || node == model->getSelectedExpandedNode()))
|
||||
{
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(ElaThemeColor(_themeMode, PrimaryNormal));
|
||||
painter->drawRoundedRect(QRectF(itemRect.x() + 3, itemRect.y() + _pSelectMarkTop, 3, itemRect.height() - _pSelectMarkTop - _pSelectMarkBottom), 3, 3);
|
||||
}
|
||||
if (node == _lastSelectedNode)
|
||||
{
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(ElaThemeColor(_themeMode, PrimaryNormal));
|
||||
painter->drawRoundedRect(QRectF(itemRect.x() + 3, itemRect.y() + _pLastSelectMarkTop, 3, itemRect.height() - _pLastSelectMarkTop - _pLastSelectMarkBottom), 3, 3);
|
||||
}
|
||||
|
||||
// 图标绘制
|
||||
painter->setPen(vopt->index == _pPressIndex ? ElaThemeColor(_themeMode, BasicTextPress) : ElaThemeColor(_themeMode, BasicText));
|
||||
if (node->getAwesome() != ElaIconType::None)
|
||||
{
|
||||
painter->save();
|
||||
QFont iconFont = QFont("ElaAwesome");
|
||||
iconFont.setPixelSize(17);
|
||||
painter->setFont(iconFont);
|
||||
painter->drawText(QRect(itemRect.x(), itemRect.y(), _iconAreaWidth, itemRect.height()), Qt::AlignCenter, QChar((unsigned short)node->getAwesome()));
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
int viewWidth = widget->width();
|
||||
// 文字绘制
|
||||
painter->setPen(vopt->index == _pPressIndex ? ElaThemeColor(_themeMode, BasicTextPress) : ElaThemeColor(_themeMode, BasicText));
|
||||
QRect textRect;
|
||||
if (node->getAwesome() != ElaIconType::None)
|
||||
{
|
||||
textRect = QRect(itemRect.x() + _iconAreaWidth, itemRect.y(), itemRect.width() - _textRightSpacing - _indicatorIconAreaWidth - _iconAreaWidth, itemRect.height());
|
||||
}
|
||||
else
|
||||
{
|
||||
textRect = QRect(itemRect.x() + _leftPadding, itemRect.y(), itemRect.width() - _textRightSpacing - _indicatorIconAreaWidth - _leftPadding, itemRect.height());
|
||||
}
|
||||
QString text = painter->fontMetrics().elidedText(node->getNodeTitle(), Qt::ElideRight, textRect.width());
|
||||
painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, text);
|
||||
|
||||
if (viewWidth > 260)
|
||||
{
|
||||
// 展开图标 KeyPoints
|
||||
if (node->getIsExpanderNode())
|
||||
{
|
||||
if (node->getIsHasChild())
|
||||
{
|
||||
QRectF expandIconRect(itemRect.right() - _indicatorIconAreaWidth, itemRect.y(), 17, itemRect.height());
|
||||
|
||||
painter->save();
|
||||
QFont iconFont = QFont("ElaAwesome");
|
||||
iconFont.setPixelSize(17);
|
||||
painter->setFont(iconFont);
|
||||
painter->translate(expandIconRect.x() + (qreal)expandIconRect.width() / 2, expandIconRect.y() + (qreal)expandIconRect.height() / 2);
|
||||
if (node == _expandAnimationTargetNode)
|
||||
{
|
||||
painter->rotate(_pRotate);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (node->getIsExpanded())
|
||||
{
|
||||
//展开
|
||||
painter->rotate(-180);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 未展开
|
||||
painter->rotate(0);
|
||||
}
|
||||
}
|
||||
painter->translate(-expandIconRect.x() - (qreal)expandIconRect.width() / 2 + 1, -expandIconRect.y() - (qreal)expandIconRect.height() / 2);
|
||||
painter->drawText(expandIconRect, Qt::AlignVCenter, QChar((unsigned short)ElaIconType::AngleDown));
|
||||
painter->restore();
|
||||
}
|
||||
if (node->getIsChildHasKeyPoints())
|
||||
{
|
||||
painter->save();
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(ElaThemeColor(_themeMode, PrimaryNormal));
|
||||
painter->drawEllipse(QPoint(itemRect.right() - 17, itemRect.y() + 12), 3, 3);
|
||||
painter->restore();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int keyPoints = node->getKeyPoints();
|
||||
if (keyPoints)
|
||||
{
|
||||
// KeyPoints
|
||||
painter->save();
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(Qt::white);
|
||||
painter->drawEllipse(QPoint(itemRect.right() - 26, itemRect.y() + itemRect.height() / 2), 10, 10);
|
||||
painter->setBrush(ElaThemeColor(_themeMode, StatusDanger));
|
||||
painter->drawEllipse(QPoint(itemRect.right() - 26, itemRect.y() + itemRect.height() / 2), 9, 9);
|
||||
painter->setPen(QPen(Qt::white, 2));
|
||||
QFont font = painter->font();
|
||||
font.setBold(true);
|
||||
if (keyPoints > 99)
|
||||
{
|
||||
keyPoints = 99;
|
||||
}
|
||||
if (keyPoints > 9)
|
||||
{
|
||||
font.setPixelSize(11);
|
||||
}
|
||||
else
|
||||
{
|
||||
font.setPixelSize(12);
|
||||
}
|
||||
painter->setFont(font);
|
||||
painter->drawText(keyPoints > 9 ? itemRect.right() - 33 : itemRect.right() - 30, itemRect.y() + itemRect.height() / 2 + 4, QString::number(keyPoints));
|
||||
painter->restore();
|
||||
}
|
||||
}
|
||||
}
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
QProxyStyle::drawControl(element, option, painter, widget);
|
||||
}
|
||||
|
||||
QSize ElaNavigationStyle::sizeFromContents(ContentsType type, const QStyleOption* option, const QSize& size, const QWidget* widget) const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case QStyle::CT_ItemViewItem:
|
||||
{
|
||||
QSize itemSize = QProxyStyle::sizeFromContents(type, option, size, widget);
|
||||
itemSize.setHeight(_pItemHeight);
|
||||
return itemSize;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QProxyStyle::sizeFromContents(type, option, size, widget);
|
||||
}
|
||||
|
||||
void ElaNavigationStyle::navigationNodeStateChange(QVariantMap data)
|
||||
{
|
||||
if (data.contains("Expand"))
|
||||
{
|
||||
ElaNavigationNode* lastExpandNode = _expandAnimationTargetNode;
|
||||
_opacityAnimationTargetNode = data.value("Expand").value<ElaNavigationNode*>();
|
||||
_expandAnimationTargetNode = _opacityAnimationTargetNode;
|
||||
QPropertyAnimation* nodeOpacityAnimation = new QPropertyAnimation(this, "pOpacity");
|
||||
connect(nodeOpacityAnimation, &QPropertyAnimation::finished, this, [=]() { _opacityAnimationTargetNode = nullptr; });
|
||||
connect(nodeOpacityAnimation, &QPropertyAnimation::valueChanged, this, [=](const QVariant& value) {
|
||||
_pNavigationView->viewport()->update();
|
||||
});
|
||||
nodeOpacityAnimation->setDuration(600);
|
||||
nodeOpacityAnimation->setEasingCurve(QEasingCurve::InOutSine);
|
||||
nodeOpacityAnimation->setKeyValueAt(0.4, 0);
|
||||
nodeOpacityAnimation->setStartValue(0);
|
||||
nodeOpacityAnimation->setEndValue(1);
|
||||
nodeOpacityAnimation->start(QAbstractAnimation::DeleteWhenStopped);
|
||||
|
||||
QPropertyAnimation* rotateAnimation = new QPropertyAnimation(this, "pRotate");
|
||||
connect(rotateAnimation, &QPropertyAnimation::finished, this, [=]() { _expandAnimationTargetNode = nullptr; });
|
||||
connect(rotateAnimation, &QPropertyAnimation::valueChanged, this, [=](const QVariant& value) {
|
||||
_pNavigationView->viewport()->update();
|
||||
});
|
||||
rotateAnimation->setDuration(300);
|
||||
rotateAnimation->setEasingCurve(QEasingCurve::InOutSine);
|
||||
if (lastExpandNode == _expandAnimationTargetNode)
|
||||
{
|
||||
rotateAnimation->setStartValue(_pRotate);
|
||||
}
|
||||
else
|
||||
{
|
||||
rotateAnimation->setStartValue(0);
|
||||
}
|
||||
rotateAnimation->setEndValue(-180);
|
||||
rotateAnimation->start(QAbstractAnimation::DeleteWhenStopped);
|
||||
}
|
||||
else if (data.contains("Collapse"))
|
||||
{
|
||||
ElaNavigationNode* lastExpandNode = _expandAnimationTargetNode;
|
||||
_opacityAnimationTargetNode = data.value("Collapse").value<ElaNavigationNode*>();
|
||||
_expandAnimationTargetNode = _opacityAnimationTargetNode;
|
||||
_pOpacity = 0;
|
||||
|
||||
QPropertyAnimation* rotateAnimation = new QPropertyAnimation(this, "pRotate");
|
||||
connect(rotateAnimation, &QPropertyAnimation::finished, this, [=]() {
|
||||
_pOpacity = 1;
|
||||
_expandAnimationTargetNode = nullptr; });
|
||||
connect(rotateAnimation, &QPropertyAnimation::valueChanged, this, [=](const QVariant& value) {
|
||||
_pNavigationView->viewport()->update();
|
||||
});
|
||||
rotateAnimation->setDuration(300);
|
||||
rotateAnimation->setEasingCurve(QEasingCurve::InOutSine);
|
||||
if (lastExpandNode == _expandAnimationTargetNode)
|
||||
{
|
||||
rotateAnimation->setStartValue(_pRotate);
|
||||
}
|
||||
else
|
||||
{
|
||||
rotateAnimation->setStartValue(-180);
|
||||
}
|
||||
rotateAnimation->setEndValue(0);
|
||||
rotateAnimation->start(QAbstractAnimation::DeleteWhenStopped);
|
||||
}
|
||||
else if (data.contains("SelectMarkChanged"))
|
||||
{
|
||||
_lastSelectedNode = data.value("LastSelectedNode").value<ElaNavigationNode*>();
|
||||
ElaNavigationNode* selectedNode = data.value("SelectedNode").value<ElaNavigationNode*>();
|
||||
bool direction = _compareItemY(selectedNode, _lastSelectedNode);
|
||||
_pLastSelectMarkTop = 10;
|
||||
_pLastSelectMarkBottom = 10;
|
||||
_pSelectMarkTop = 10;
|
||||
_pSelectMarkBottom = 10;
|
||||
if (direction)
|
||||
{
|
||||
_lastSelectMarkTopAnimation->setStartValue(10);
|
||||
_lastSelectMarkTopAnimation->setEndValue(0);
|
||||
_lastSelectMarkTopAnimation->start();
|
||||
_lastSelectMarkBottomAnimation->stop();
|
||||
_selectMarkTopAnimation->stop();
|
||||
_isSelectMarkDisplay = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_lastSelectMarkBottomAnimation->setStartValue(10);
|
||||
_lastSelectMarkBottomAnimation->setEndValue(0);
|
||||
_lastSelectMarkBottomAnimation->start();
|
||||
_lastSelectMarkTopAnimation->stop();
|
||||
_selectMarkBottomAnimation->stop();
|
||||
_isSelectMarkDisplay = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ElaNavigationStyle::_compareItemY(ElaNavigationNode* node1, ElaNavigationNode* node2)
|
||||
{
|
||||
// 返回true 即node1 高于 node2
|
||||
if (!node1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!node2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// 同一父节点
|
||||
if (node1->getParentNode() == node2->getParentNode())
|
||||
{
|
||||
if (node1->getModelIndex().row() < node2->getModelIndex().row())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ElaNavigationNode* node1OriginalNode = node1->getOriginalNode();
|
||||
ElaNavigationNode* node2OriginalNode = node2->getOriginalNode();
|
||||
// 不同父节点 相同起源节点
|
||||
if (node1OriginalNode == node2OriginalNode)
|
||||
{
|
||||
int node1Depth = node1->getDepth();
|
||||
int node2Depth = node2->getDepth();
|
||||
// 相同深度
|
||||
if (node1Depth == node2Depth)
|
||||
{
|
||||
ElaNavigationNode* node1ParentNode = node1->getParentNode();
|
||||
ElaNavigationNode* node2ParentNode = node2->getParentNode();
|
||||
if (node1ParentNode->getModelIndex().row() < node2ParentNode->getModelIndex().row())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (node1Depth < node2Depth)
|
||||
{
|
||||
ElaNavigationNode* node2ParentNode = node2->getParentNode();
|
||||
while (node2ParentNode->getDepth() != node1Depth)
|
||||
{
|
||||
node2ParentNode = node2ParentNode->getParentNode();
|
||||
}
|
||||
// 父子节点关系
|
||||
if (node1 == node2ParentNode)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (node1->getModelIndex().row() < node2ParentNode->getModelIndex().row())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ElaNavigationNode* node1ParentNode = node1->getParentNode();
|
||||
while (node1ParentNode->getDepth() != node2Depth)
|
||||
{
|
||||
node1ParentNode = node1ParentNode->getParentNode();
|
||||
}
|
||||
if (node2 == node1ParentNode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (node1ParentNode->getModelIndex().row() < node2->getModelIndex().row())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (node1OriginalNode->getModelIndex().row() < node2OriginalNode->getModelIndex().row())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
#ifndef ELANAVIGATIONSTYLE_H
|
||||
#define ELANAVIGATIONSTYLE_H
|
||||
#include <QModelIndex>
|
||||
#include <QProxyStyle>
|
||||
|
||||
#include "Def.h"
|
||||
class ElaNavigationNode;
|
||||
class ElaNavigationView;
|
||||
class QPropertyAnimation;
|
||||
class ElaNavigationStyle : public QProxyStyle
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_CREATE(qreal, Opacity)
|
||||
Q_PROPERTY_CREATE(qreal, Rotate)
|
||||
Q_PROPERTY_CREATE(int, ItemHeight)
|
||||
Q_PRIVATE_CREATE(ElaNavigationView*, NavigationView)
|
||||
Q_PROPERTY_CREATE(qreal, LastSelectMarkTop)
|
||||
Q_PROPERTY_CREATE(qreal, LastSelectMarkBottom)
|
||||
Q_PROPERTY_CREATE(qreal, SelectMarkTop)
|
||||
Q_PROPERTY_CREATE(qreal, SelectMarkBottom)
|
||||
Q_PRIVATE_CREATE(QModelIndex, PressIndex)
|
||||
public:
|
||||
explicit ElaNavigationStyle(QStyle* style = nullptr);
|
||||
~ElaNavigationStyle();
|
||||
void drawPrimitive(PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget = nullptr) const override;
|
||||
void drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget = nullptr) const override;
|
||||
QSize sizeFromContents(ContentsType type, const QStyleOption* option, const QSize& size, const QWidget* widget) const override;
|
||||
|
||||
void navigationNodeStateChange(QVariantMap data);
|
||||
|
||||
private:
|
||||
ElaThemeType::ThemeMode _themeMode;
|
||||
bool _isSelectMarkDisplay{true};
|
||||
int _leftPadding{11};
|
||||
int _iconAreaWidth{40};
|
||||
int _textRightSpacing{3};
|
||||
int _indicatorIconAreaWidth{34};
|
||||
ElaNavigationNode* _opacityAnimationTargetNode{nullptr};
|
||||
ElaNavigationNode* _expandAnimationTargetNode{nullptr};
|
||||
ElaNavigationNode* _lastSelectedNode{nullptr};
|
||||
QPropertyAnimation* _lastSelectMarkTopAnimation{nullptr};
|
||||
QPropertyAnimation* _lastSelectMarkBottomAnimation{nullptr};
|
||||
QPropertyAnimation* _selectMarkTopAnimation{nullptr};
|
||||
QPropertyAnimation* _selectMarkBottomAnimation{nullptr};
|
||||
bool _compareItemY(ElaNavigationNode* node1, ElaNavigationNode* node2);
|
||||
};
|
||||
|
||||
#endif // ELANAVIGATIONSTYLE_H
|
||||
@@ -0,0 +1,122 @@
|
||||
#include "ElaNavigationView.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QHeaderView>
|
||||
#include <QModelIndex>
|
||||
#include <QMouseEvent>
|
||||
#include <QPainter>
|
||||
#include <QScrollBar>
|
||||
#include <QScroller>
|
||||
|
||||
#include "ElaMenu.h"
|
||||
#include "ElaNavigationModel.h"
|
||||
#include "ElaNavigationNode.h"
|
||||
#include "ElaNavigationStyle.h"
|
||||
#include "ElaScrollBar.h"
|
||||
|
||||
ElaNavigationView::ElaNavigationView(QWidget* parent)
|
||||
: QTreeView(parent)
|
||||
{
|
||||
setObjectName("ElaNavigationView");
|
||||
setStyleSheet("#ElaNavigationView{background-color:transparent;}");
|
||||
setAnimated(true);
|
||||
setHeaderHidden(true);
|
||||
setRootIsDecorated(false);
|
||||
setExpandsOnDoubleClick(false);
|
||||
setAutoScroll(false);
|
||||
setMouseTracking(true);
|
||||
setSelectionMode(QAbstractItemView::NoSelection);
|
||||
|
||||
// 滚动条设置
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
|
||||
ElaScrollBar* vScrollBar = new ElaScrollBar(this);
|
||||
connect(vScrollBar, &ElaScrollBar::rangeAnimationFinished, this, [=]() {
|
||||
doItemsLayout();
|
||||
});
|
||||
setVerticalScrollBar(vScrollBar);
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||
ElaScrollBar* floatVScrollBar = new ElaScrollBar(vScrollBar, this);
|
||||
floatVScrollBar->setIsAnimation(true);
|
||||
|
||||
_navigationStyle = new ElaNavigationStyle(this->style());
|
||||
_navigationStyle->setNavigationView(this);
|
||||
setStyle(_navigationStyle);
|
||||
|
||||
QScroller::grabGesture(this->viewport(), QScroller::LeftMouseButtonGesture);
|
||||
QScroller* scroller = QScroller::scroller(this->viewport());
|
||||
QScrollerProperties properties = scroller->scrollerProperties();
|
||||
properties.setScrollMetric(QScrollerProperties::MousePressEventDelay, 0);
|
||||
properties.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QScrollerProperties::OvershootAlwaysOff);
|
||||
properties.setScrollMetric(QScrollerProperties::VerticalOvershootPolicy, QScrollerProperties::OvershootAlwaysOn);
|
||||
properties.setScrollMetric(QScrollerProperties::OvershootDragResistanceFactor, 0.35);
|
||||
properties.setScrollMetric(QScrollerProperties::OvershootScrollTime, 0.5);
|
||||
properties.setScrollMetric(QScrollerProperties::FrameRate, QScrollerProperties::Fps60);
|
||||
scroller->setScrollerProperties(properties);
|
||||
|
||||
connect(scroller, &QScroller::stateChanged, this, [=](QScroller::State newstate) {
|
||||
if (newstate == QScroller::Pressed)
|
||||
{
|
||||
_navigationStyle->setPressIndex(indexAt(mapFromGlobal(QCursor::pos())));
|
||||
viewport()->update();
|
||||
}
|
||||
else if (newstate == QScroller::Scrolling || newstate == QScroller::Inactive)
|
||||
{
|
||||
_navigationStyle->setPressIndex(QModelIndex());
|
||||
}
|
||||
});
|
||||
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(this, &ElaNavigationView::customContextMenuRequested, this, &ElaNavigationView::onCustomContextMenuRequested);
|
||||
}
|
||||
|
||||
ElaNavigationView::~ElaNavigationView()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaNavigationView::navigationNodeStateChange(QVariantMap data)
|
||||
{
|
||||
this->_navigationStyle->navigationNodeStateChange(data);
|
||||
}
|
||||
|
||||
void ElaNavigationView::onCustomContextMenuRequested(const QPoint& pos)
|
||||
{
|
||||
QModelIndex posIndex = indexAt(pos);
|
||||
if (!posIndex.isValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
ElaNavigationNode* posNode = static_cast<ElaNavigationNode*>(posIndex.internalPointer());
|
||||
if (!posNode->getIsExpanderNode())
|
||||
{
|
||||
ElaMenu menu;
|
||||
menu.setMenuItemHeight(27);
|
||||
QAction* openAction = menu.addElaIconAction(ElaIconType::ObjectGroup, "在新窗口中打开");
|
||||
connect(openAction, &QAction::triggered, this, [=]() {
|
||||
Q_EMIT navigationOpenNewWindow(posNode->getNodeKey());
|
||||
});
|
||||
menu.exec(mapToGlobal(pos));
|
||||
}
|
||||
}
|
||||
|
||||
void ElaNavigationView::mouseDoubleClickEvent(QMouseEvent* event)
|
||||
{
|
||||
_navigationStyle->setPressIndex(indexAt(event->pos()));
|
||||
viewport()->update();
|
||||
QTreeView::mouseDoubleClickEvent(event);
|
||||
}
|
||||
|
||||
void ElaNavigationView::mouseReleaseEvent(QMouseEvent* event)
|
||||
{
|
||||
QTreeView::mouseReleaseEvent(event);
|
||||
if (event->button() == Qt::LeftButton)
|
||||
{
|
||||
QModelIndex index = indexAt(event->pos());
|
||||
if (index.isValid())
|
||||
{
|
||||
Q_EMIT navigationClicked(index);
|
||||
}
|
||||
_navigationStyle->setPressIndex(QModelIndex());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef ELANAVIGATIONVIEW_H
|
||||
#define ELANAVIGATIONVIEW_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QTreeView>
|
||||
|
||||
class ElaScrollBar;
|
||||
class ElaNavigationStyle;
|
||||
class ElaNavigationView : public QTreeView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ElaNavigationView(QWidget* parent = nullptr);
|
||||
~ElaNavigationView();
|
||||
void navigationNodeStateChange(QVariantMap data);
|
||||
|
||||
Q_SLOT void onCustomContextMenuRequested(const QPoint& pos);
|
||||
Q_SIGNALS:
|
||||
Q_SIGNAL void navigationClicked(const QModelIndex& index);
|
||||
Q_SIGNAL void navigationOpenNewWindow(QString nodeKey);
|
||||
|
||||
protected:
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent* event) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent* event) override;
|
||||
|
||||
private:
|
||||
ElaNavigationStyle* _navigationStyle{nullptr};
|
||||
};
|
||||
|
||||
#endif // ELANAVIGATIONVIEW_H
|
||||
@@ -0,0 +1,51 @@
|
||||
#include "ElaPivotModel.h"
|
||||
|
||||
ElaPivotModel::ElaPivotModel(QObject* parent)
|
||||
: QAbstractListModel{parent}
|
||||
{
|
||||
}
|
||||
|
||||
ElaPivotModel::~ElaPivotModel()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaPivotModel::appendPivot(QString pivot)
|
||||
{
|
||||
if (!pivot.isEmpty())
|
||||
{
|
||||
beginInsertRows(QModelIndex(), _pivotList.count(), _pivotList.count());
|
||||
_pivotList.append(pivot);
|
||||
endInsertRows();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ElaPivotModel::removePivot(QString pivot)
|
||||
{
|
||||
if (_pivotList.contains(pivot))
|
||||
{
|
||||
int index = _pivotList.lastIndexOf(pivot);
|
||||
beginRemoveRows(QModelIndex(), index, index);
|
||||
_pivotList.removeAt(index);
|
||||
endRemoveRows();
|
||||
}
|
||||
}
|
||||
|
||||
int ElaPivotModel::getPivotListCount() const
|
||||
{
|
||||
return _pivotList.count();
|
||||
}
|
||||
|
||||
int ElaPivotModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
return _pivotList.count();
|
||||
}
|
||||
|
||||
QVariant ElaPivotModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
return _pivotList[index.row()];
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef ELAPIVOTMODEL_H
|
||||
#define ELAPIVOTMODEL_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
|
||||
class ElaPivotModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ElaPivotModel(QObject* parent = nullptr);
|
||||
~ElaPivotModel();
|
||||
|
||||
void appendPivot(QString pivot);
|
||||
void removePivot(QString pivot);
|
||||
|
||||
int getPivotListCount() const;
|
||||
|
||||
protected:
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex& index, int role) const override;
|
||||
|
||||
private:
|
||||
QStringList _pivotList;
|
||||
};
|
||||
|
||||
#endif // ELAPIVOTMODEL_H
|
||||
@@ -0,0 +1,112 @@
|
||||
#include "ElaPivotStyle.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QStyleOption>
|
||||
|
||||
#include "ElaTheme.h"
|
||||
ElaPivotStyle::ElaPivotStyle(QStyle* style)
|
||||
{
|
||||
_pCurrentIndex = -1;
|
||||
_pPivotSpacing = 5;
|
||||
_themeMode = eTheme->getThemeMode();
|
||||
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) {
|
||||
_themeMode = themeMode;
|
||||
});
|
||||
}
|
||||
|
||||
ElaPivotStyle::~ElaPivotStyle()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaPivotStyle::drawPrimitive(PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const
|
||||
{
|
||||
switch (element)
|
||||
{
|
||||
case QStyle::PE_PanelItemViewRow:
|
||||
{
|
||||
return;
|
||||
}
|
||||
case QStyle::PE_Widget:
|
||||
{
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
QProxyStyle::drawPrimitive(element, option, painter, widget);
|
||||
}
|
||||
|
||||
void ElaPivotStyle::drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const
|
||||
{
|
||||
switch (element)
|
||||
{
|
||||
case QStyle::CE_ShapedFrame:
|
||||
{
|
||||
// viewport视口外的其他区域背景
|
||||
return;
|
||||
}
|
||||
case QStyle::CE_ItemViewItem:
|
||||
{
|
||||
if (const QStyleOptionViewItem* vopt = qstyleoption_cast<const QStyleOptionViewItem*>(option))
|
||||
{
|
||||
// 内容绘制
|
||||
painter->save();
|
||||
painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::TextAntialiasing);
|
||||
QRect textRect = proxy()->subElementRect(SE_ItemViewItemText, vopt, widget);
|
||||
textRect.adjust(0, 0, 0, -5);
|
||||
// 文字绘制
|
||||
if (!vopt->text.isEmpty())
|
||||
{
|
||||
if (_pPressIndex == vopt->index)
|
||||
{
|
||||
painter->setPen(ElaThemeColor(_themeMode, BasicTextPress));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_pCurrentIndex == vopt->index.row() || vopt->state.testFlag(QStyle::State_MouseOver))
|
||||
{
|
||||
painter->setPen(ElaThemeColor(_themeMode, BasicText));
|
||||
}
|
||||
else
|
||||
{
|
||||
painter->setPen(ElaThemeColor(_themeMode, BasicTextNoFocus));
|
||||
}
|
||||
}
|
||||
painter->drawText(textRect, Qt::AlignCenter, vopt->text);
|
||||
}
|
||||
painter->restore();
|
||||
}
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
QProxyStyle::drawControl(element, option, painter, widget);
|
||||
}
|
||||
|
||||
int ElaPivotStyle::pixelMetric(PixelMetric metric, const QStyleOption* option, const QWidget* widget) const
|
||||
{
|
||||
switch (metric)
|
||||
{
|
||||
case QStyle::PM_FocusFrameHMargin:
|
||||
{
|
||||
return _pPivotSpacing;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return QProxyStyle::pixelMetric(metric, option, widget);
|
||||
}
|
||||
|
||||
const QColor& ElaPivotStyle::getMarkColor()
|
||||
{
|
||||
return ElaThemeColor(_themeMode, PrimaryNormal);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef ELAPIVOTSTYLE_H
|
||||
#define ELAPIVOTSTYLE_H
|
||||
|
||||
#include <QModelIndex>
|
||||
#include <QProxyStyle>
|
||||
|
||||
#include "Def.h"
|
||||
class ElaPivotStyle : public QProxyStyle
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PRIVATE_CREATE(QModelIndex, PressIndex)
|
||||
Q_PRIVATE_CREATE(int, CurrentIndex)
|
||||
Q_PRIVATE_CREATE(int, PivotSpacing)
|
||||
public:
|
||||
explicit ElaPivotStyle(QStyle* style = nullptr);
|
||||
~ElaPivotStyle();
|
||||
void drawPrimitive(PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget = nullptr) const override;
|
||||
void drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget = nullptr) const override;
|
||||
int pixelMetric(PixelMetric metric, const QStyleOption* option = nullptr, const QWidget* widget = nullptr) const override;
|
||||
|
||||
const QColor& getMarkColor();
|
||||
|
||||
private:
|
||||
ElaThemeType::ThemeMode _themeMode;
|
||||
};
|
||||
|
||||
#endif // ELAPIVOTSTYLE_H
|
||||
@@ -0,0 +1,111 @@
|
||||
#include "ElaPivotView.h"
|
||||
|
||||
#include <QMouseEvent>
|
||||
#include <QPainter>
|
||||
#include <QPropertyAnimation>
|
||||
|
||||
#include "ElaPivotStyle.h"
|
||||
#include "ElaScrollBar.h"
|
||||
ElaPivotView::ElaPivotView(QWidget* parent)
|
||||
: QListView(parent)
|
||||
{
|
||||
_pMarkX = 0;
|
||||
_pMarkWidth = 40;
|
||||
_pMarkAnimationWidth = 0;
|
||||
setObjectName("ElaPivotView");
|
||||
setStyleSheet("#ElaPivotView{background-color:transparent;}");
|
||||
setMouseTracking(true);
|
||||
setVerticalScrollBar(new ElaScrollBar(this));
|
||||
setHorizontalScrollBar(new ElaScrollBar(this));
|
||||
this->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
this->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||
setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||
}
|
||||
|
||||
ElaPivotView::~ElaPivotView()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaPivotView::doCurrentIndexChangedAnimation(const QModelIndex& index)
|
||||
{
|
||||
if (index.row() >= 0)
|
||||
{
|
||||
QRect newIndexRect = visualRect(index);
|
||||
QPropertyAnimation* markAnimation = new QPropertyAnimation(this, "pMarkX");
|
||||
connect(markAnimation, &QPropertyAnimation::valueChanged, this, [=]() {
|
||||
update();
|
||||
});
|
||||
markAnimation->setDuration(300);
|
||||
markAnimation->setEasingCurve(QEasingCurve::InOutSine);
|
||||
if (_pPivotStyle->getCurrentIndex() >= 0)
|
||||
{
|
||||
markAnimation->setStartValue(_pMarkX);
|
||||
markAnimation->setEndValue(newIndexRect.center().x() - _pMarkWidth / 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
markAnimation->setStartValue(newIndexRect.center().x());
|
||||
markAnimation->setEndValue(newIndexRect.center().x() - _pMarkWidth / 2);
|
||||
|
||||
QPropertyAnimation* markWidthAnimation = new QPropertyAnimation(this, "pMarkAnimationWidth");
|
||||
markWidthAnimation->setDuration(300);
|
||||
markWidthAnimation->setEasingCurve(QEasingCurve::InOutSine);
|
||||
markWidthAnimation->setStartValue(0);
|
||||
markWidthAnimation->setEndValue(_pMarkWidth);
|
||||
markWidthAnimation->start(QAbstractAnimation::DeleteWhenStopped);
|
||||
}
|
||||
markAnimation->start(QAbstractAnimation::DeleteWhenStopped);
|
||||
}
|
||||
else
|
||||
{
|
||||
QRect newIndexRect = visualRect(model()->index(_pPivotStyle->getCurrentIndex(), 0));
|
||||
QPropertyAnimation* markAnimation = new QPropertyAnimation(this, "pMarkX");
|
||||
connect(markAnimation, &QPropertyAnimation::valueChanged, this, [=]() {
|
||||
update();
|
||||
});
|
||||
markAnimation->setDuration(300);
|
||||
markAnimation->setEasingCurve(QEasingCurve::InOutSine);
|
||||
markAnimation->setStartValue(_pMarkX);
|
||||
markAnimation->setEndValue(newIndexRect.center().x());
|
||||
markAnimation->start(QAbstractAnimation::DeleteWhenStopped);
|
||||
|
||||
QPropertyAnimation* markWidthAnimation = new QPropertyAnimation(this, "pMarkAnimationWidth");
|
||||
markWidthAnimation->setDuration(300);
|
||||
markWidthAnimation->setEasingCurve(QEasingCurve::InOutSine);
|
||||
markWidthAnimation->setStartValue(_pMarkAnimationWidth);
|
||||
markWidthAnimation->setEndValue(0);
|
||||
markWidthAnimation->start(QAbstractAnimation::DeleteWhenStopped);
|
||||
}
|
||||
setCurrentIndex(index);
|
||||
}
|
||||
|
||||
void ElaPivotView::mouseDoubleClickEvent(QMouseEvent* event)
|
||||
{
|
||||
_pPivotStyle->setPressIndex(indexAt(event->pos()));
|
||||
viewport()->update();
|
||||
QListView::mouseDoubleClickEvent(event);
|
||||
}
|
||||
|
||||
void ElaPivotView::mouseReleaseEvent(QMouseEvent* event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton)
|
||||
{
|
||||
_pPivotStyle->setPressIndex(QModelIndex());
|
||||
viewport()->update();
|
||||
}
|
||||
QListView::mouseReleaseEvent(event);
|
||||
}
|
||||
|
||||
void ElaPivotView::paintEvent(QPaintEvent* event)
|
||||
{
|
||||
QPainter painter(viewport());
|
||||
QRect viewPortRect = viewport()->rect();
|
||||
painter.save();
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.setBrush(_pPivotStyle->getMarkColor());
|
||||
painter.drawRoundedRect(QRect(_pMarkX, viewPortRect.bottom() - 4, _pMarkAnimationWidth, 3), 3, 3);
|
||||
painter.restore();
|
||||
QListView::paintEvent(event);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef ELAPIVOTVIEW_H
|
||||
#define ELAPIVOTVIEW_H
|
||||
|
||||
#include <QListView>
|
||||
|
||||
#include "stdafx.h"
|
||||
class ElaPivotStyle;
|
||||
class ElaPivotView : public QListView
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_CREATE(int, MarkX)
|
||||
Q_PRIVATE_CREATE(int, MarkWidth)
|
||||
Q_PROPERTY_CREATE(int, MarkAnimationWidth)
|
||||
Q_PRIVATE_CREATE(ElaPivotStyle*, PivotStyle)
|
||||
public:
|
||||
explicit ElaPivotView(QWidget* parent = nullptr);
|
||||
~ElaPivotView();
|
||||
void doCurrentIndexChangedAnimation(const QModelIndex& index);
|
||||
|
||||
protected:
|
||||
void mouseDoubleClickEvent(QMouseEvent* event) override;
|
||||
void mouseReleaseEvent(QMouseEvent* event) override;
|
||||
virtual void paintEvent(QPaintEvent* event) override;
|
||||
};
|
||||
|
||||
#endif // ELAPIVOTVIEW_H
|
||||
@@ -0,0 +1,66 @@
|
||||
#include "ElaPlainTextEditStyle.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QStyleOption>
|
||||
#include <QtMath>
|
||||
|
||||
#include "ElaTheme.h"
|
||||
ElaPlainTextEditStyle::ElaPlainTextEditStyle(QStyle* style)
|
||||
{
|
||||
_pExpandMarkWidth = 0;
|
||||
_themeMode = eTheme->getThemeMode();
|
||||
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) { _themeMode = themeMode; });
|
||||
}
|
||||
|
||||
ElaPlainTextEditStyle::~ElaPlainTextEditStyle()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaPlainTextEditStyle::drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const
|
||||
{
|
||||
switch (element)
|
||||
{
|
||||
case QStyle::CE_ShapedFrame:
|
||||
{
|
||||
if (const QStyleOptionFrame* fopt = qstyleoption_cast<const QStyleOptionFrame*>(option))
|
||||
{
|
||||
//背景绘制
|
||||
QRect editRect = option->rect;
|
||||
painter->save();
|
||||
painter->setRenderHints(QPainter::Antialiasing);
|
||||
painter->setPen(Qt::NoPen);
|
||||
// 边框绘制
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicBorder));
|
||||
painter->drawRoundedRect(editRect, 6, 6);
|
||||
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicBase));
|
||||
painter->drawRoundedRect(QRectF(editRect.x() + 1.5, editRect.y() + 1.5, editRect.width() - 3, editRect.height() - 3), 6, 6);
|
||||
|
||||
// 底边线绘制
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicHemline));
|
||||
QPainterPath path;
|
||||
path.moveTo(6, editRect.height());
|
||||
path.lineTo(editRect.width() - 6, editRect.height());
|
||||
path.arcTo(QRectF(editRect.width() - 12, editRect.height() - 12, 12, 12), -90, 45);
|
||||
path.lineTo(6 - 3 * std::sqrt(2), editRect.height() - (6 - 3 * std::sqrt(2)));
|
||||
path.arcTo(QRectF(0, editRect.height() - 12, 12, 12), 270, 45);
|
||||
path.closeSubpath();
|
||||
painter->drawPath(path);
|
||||
|
||||
//焦点指示器
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(ElaThemeColor(_themeMode, PrimaryNormal));
|
||||
painter->drawRoundedRect(QRectF(editRect.width() / 2 - _pExpandMarkWidth, editRect.height() - 2.5, _pExpandMarkWidth * 2, 2.5), 2, 2);
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
QProxyStyle::drawControl(element, option, painter, widget);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef ELAPLAINTEXTEDITSTYLE_H
|
||||
#define ELAPLAINTEXTEDITSTYLE_H
|
||||
|
||||
#include <QProxyStyle>
|
||||
|
||||
#include "Def.h"
|
||||
class ElaPlainTextEditStyle : public QProxyStyle
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_CREATE(qreal, ExpandMarkWidth)
|
||||
public:
|
||||
explicit ElaPlainTextEditStyle(QStyle* style = nullptr);
|
||||
~ElaPlainTextEditStyle();
|
||||
void drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget = nullptr) const override;
|
||||
|
||||
private:
|
||||
ElaThemeType::ThemeMode _themeMode;
|
||||
};
|
||||
|
||||
#endif // ELAPLAINTEXTEDITSTYLE_H
|
||||
@@ -0,0 +1,242 @@
|
||||
#include "ElaPopularCardFloater.h"
|
||||
|
||||
#include <QEvent>
|
||||
#include <QGraphicsOpacityEffect>
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QPropertyAnimation>
|
||||
|
||||
#include "ElaPopularCard.h"
|
||||
#include "ElaPopularCardPrivate.h"
|
||||
#include "ElaPushButton.h"
|
||||
#include "ElaTheme.h"
|
||||
ElaPopularCardFloater::ElaPopularCardFloater(ElaPopularCard* card, ElaPopularCardPrivate* cardPrivate, QWidget* parent)
|
||||
: QWidget{parent}
|
||||
{
|
||||
_card = card;
|
||||
_cardPrivate = cardPrivate;
|
||||
_pHoverOpacity = 0;
|
||||
_pHoverYOffset = 0;
|
||||
setObjectName("ElaPopularCardFloater");
|
||||
setStyleSheet("#ElaPopularCardFloater{background-color:transparent}");
|
||||
setMouseTracking(true);
|
||||
|
||||
_overButton = new ElaPushButton("获取", this);
|
||||
_opacityEffect = new QGraphicsOpacityEffect(_overButton);
|
||||
_opacityEffect->setOpacity(1);
|
||||
_overButton->setGraphicsEffect(_opacityEffect);
|
||||
_overButton->move(0, 0);
|
||||
_overButton->setLightDefaultColor(ElaThemeColor(ElaThemeType::Light, PrimaryNormal));
|
||||
_overButton->setLightHoverColor(ElaThemeColor(ElaThemeType::Light, PrimaryHover));
|
||||
_overButton->setLightPressColor(ElaThemeColor(ElaThemeType::Light, PrimaryPress));
|
||||
_overButton->setLightTextColor(Qt::white);
|
||||
_overButton->setDarkDefaultColor(ElaThemeColor(ElaThemeType::Dark, PrimaryNormal));
|
||||
_overButton->setDarkHoverColor(ElaThemeColor(ElaThemeType::Dark, PrimaryHover));
|
||||
_overButton->setDarkPressColor(ElaThemeColor(ElaThemeType::Dark, PrimaryPress));
|
||||
_overButton->setDarkTextColor(Qt::white);
|
||||
_overButton->setMinimumSize(0, 0);
|
||||
_overButton->setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
|
||||
connect(_overButton, &ElaPushButton::clicked, _card, &ElaPopularCard::popularCardButtonClicked);
|
||||
|
||||
_themeMode = eTheme->getThemeMode();
|
||||
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) { _themeMode = themeMode; });
|
||||
setVisible(false);
|
||||
}
|
||||
|
||||
ElaPopularCardFloater::~ElaPopularCardFloater()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaPopularCardFloater::showFloater()
|
||||
{
|
||||
_isHideAnimationFinished = true;
|
||||
_pHoverYOffset = 6;
|
||||
_pHoverOpacity = 1;
|
||||
_opacityEffect->setOpacity(1);
|
||||
|
||||
QPropertyAnimation* geometryAnimation = new QPropertyAnimation(this, "geometry");
|
||||
connect(geometryAnimation, &QPropertyAnimation::valueChanged, this, [=]() {
|
||||
update();
|
||||
});
|
||||
geometryAnimation->setEasingCurve(QEasingCurve::OutQuad);
|
||||
geometryAnimation->setDuration(300);
|
||||
QRect cardGeometry = QRect(_card->mapTo(_cardPrivate->_pCardFloatArea, QPoint(0, 0)), _card->size());
|
||||
QRect endGeometry = _calculateTargetGeometry(cardGeometry);
|
||||
QRect startGeometry = QRect(endGeometry.x() + _floatGeometryOffset, endGeometry.y() + _floatGeometryOffset, _card->width(), _card->height());
|
||||
geometryAnimation->setStartValue(startGeometry);
|
||||
geometryAnimation->setEndValue(endGeometry);
|
||||
geometryAnimation->start(QAbstractAnimation::DeleteWhenStopped);
|
||||
|
||||
//Button动画
|
||||
QPropertyAnimation* buttonAnimation = new QPropertyAnimation(_overButton, "geometry");
|
||||
buttonAnimation->setEasingCurve(QEasingCurve::OutQuad);
|
||||
buttonAnimation->setDuration(300);
|
||||
buttonAnimation->setStartValue(_cardPrivate->_interactiveTipsBaseRect);
|
||||
buttonAnimation->setEndValue(_cardPrivate->_buttonTargetRect);
|
||||
buttonAnimation->start(QAbstractAnimation::DeleteWhenStopped);
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
void ElaPopularCardFloater::hideFloater()
|
||||
{
|
||||
if (!_isHideAnimationFinished)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_isHideAnimationFinished = false;
|
||||
QPropertyAnimation* geometryAnimation = new QPropertyAnimation(this, "geometry");
|
||||
connect(geometryAnimation, &QPropertyAnimation::valueChanged, this, [=]() {
|
||||
QRect endGeometry = QRect(_card->mapTo(_cardPrivate->_pCardFloatArea, QPoint(0, 0)), _card->size());
|
||||
geometryAnimation->setEndValue(endGeometry);
|
||||
});
|
||||
connect(geometryAnimation, &QPropertyAnimation::finished, this, [=]() {
|
||||
_cardPrivate->_isFloating = false;
|
||||
setVisible(false);
|
||||
_card->update();
|
||||
});
|
||||
geometryAnimation->setEasingCurve(QEasingCurve::InOutSine);
|
||||
geometryAnimation->setDuration(300);
|
||||
QRect endGeometry = QRect(_card->mapTo(_cardPrivate->_pCardFloatArea, QPoint(0, 0)), _card->size());
|
||||
geometryAnimation->setStartValue(geometry());
|
||||
geometryAnimation->setEndValue(endGeometry);
|
||||
geometryAnimation->start(QAbstractAnimation::DeleteWhenStopped);
|
||||
|
||||
QPropertyAnimation* opacityAnimation = new QPropertyAnimation(this, "pHoverOpacity");
|
||||
opacityAnimation->setDuration(300);
|
||||
opacityAnimation->setStartValue(_pHoverOpacity);
|
||||
opacityAnimation->setEndValue(0);
|
||||
opacityAnimation->start(QAbstractAnimation::DeleteWhenStopped);
|
||||
|
||||
//内容调整动画
|
||||
QPropertyAnimation* hoverAnimation = new QPropertyAnimation(this, "pHoverYOffset");
|
||||
connect(hoverAnimation, &QPropertyAnimation::valueChanged, this, [=]() {
|
||||
update();
|
||||
});
|
||||
hoverAnimation->setDuration(300);
|
||||
hoverAnimation->setStartValue(_pHoverYOffset);
|
||||
hoverAnimation->setEndValue(0);
|
||||
hoverAnimation->start(QAbstractAnimation::DeleteWhenStopped);
|
||||
|
||||
//Button动画
|
||||
QPropertyAnimation* buttonAnimation = new QPropertyAnimation(_overButton, "geometry");
|
||||
buttonAnimation->setEasingCurve(QEasingCurve::InOutSine);
|
||||
buttonAnimation->setDuration(300);
|
||||
buttonAnimation->setStartValue(_overButton->geometry());
|
||||
QRectF endRect = _cardPrivate->_interactiveTipsBaseRect;
|
||||
endRect.adjust(0, 6, 0, 6);
|
||||
buttonAnimation->setEndValue(endRect);
|
||||
buttonAnimation->start(QAbstractAnimation::DeleteWhenStopped);
|
||||
|
||||
QPropertyAnimation* buttonOpacityAnimation = new QPropertyAnimation(_overButton->graphicsEffect(), "opacity");
|
||||
buttonOpacityAnimation->setEasingCurve(QEasingCurve::InOutSine);
|
||||
buttonOpacityAnimation->setDuration(350);
|
||||
buttonOpacityAnimation->setStartValue(1);
|
||||
buttonOpacityAnimation->setEndValue(0);
|
||||
buttonOpacityAnimation->start(QAbstractAnimation::DeleteWhenStopped);
|
||||
}
|
||||
|
||||
bool ElaPopularCardFloater::event(QEvent* event)
|
||||
{
|
||||
switch (event->type())
|
||||
{
|
||||
case QEvent::Leave:
|
||||
{
|
||||
hideFloater();
|
||||
break;
|
||||
}
|
||||
case QEvent::MouseButtonRelease:
|
||||
{
|
||||
Q_EMIT _card->popularCardClicked();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QWidget::event(event);
|
||||
}
|
||||
|
||||
void ElaPopularCardFloater::paintEvent(QPaintEvent* event)
|
||||
{
|
||||
QPainter painter(this);
|
||||
painter.save();
|
||||
painter.setRenderHints(QPainter::SmoothPixmapTransform | QPainter::Antialiasing | QPainter::TextAntialiasing);
|
||||
// 阴影绘制
|
||||
painter.setOpacity(_pHoverOpacity);
|
||||
QRect shadowRect = rect();
|
||||
shadowRect.adjust(0, 0, 0, -_pHoverYOffset);
|
||||
eTheme->drawEffectShadow(&painter, shadowRect, _cardPrivate->_shadowBorderWidth, _cardPrivate->_pBorderRadius);
|
||||
QRectF foregroundRect(_cardPrivate->_shadowBorderWidth, _cardPrivate->_shadowBorderWidth - _pHoverYOffset + 1, width() - 2 * _cardPrivate->_shadowBorderWidth, height() - 2 * _cardPrivate->_shadowBorderWidth);
|
||||
QRectF cardForegroundRect(_cardPrivate->_shadowBorderWidth, _cardPrivate->_shadowBorderWidth - _cardPrivate->_pHoverYOffset + 1, _card->width() - 2 * _cardPrivate->_shadowBorderWidth, _card->height() - 2 * _cardPrivate->_shadowBorderWidth);
|
||||
|
||||
//背景绘制
|
||||
painter.setOpacity(1);
|
||||
painter.setPen(ElaThemeColor(_themeMode, PopupBorderHover));
|
||||
painter.setBrush(ElaThemeColor(_themeMode, DialogBase));
|
||||
painter.drawRoundedRect(foregroundRect, _cardPrivate->_pBorderRadius, _cardPrivate->_pBorderRadius);
|
||||
painter.setClipRect(foregroundRect);
|
||||
//图片绘制
|
||||
painter.save();
|
||||
QRectF pixRect(foregroundRect.x() + cardForegroundRect.height() * 0.15, foregroundRect.y() + cardForegroundRect.height() * 0.15, cardForegroundRect.height() * 0.7, cardForegroundRect.height() * 0.7);
|
||||
|
||||
QPainterPath pixPath;
|
||||
pixPath.addRoundedRect(pixRect, 4, 4);
|
||||
painter.setClipPath(pixPath);
|
||||
painter.drawPixmap(pixRect, _cardPrivate->_pCardPixmap, _cardPrivate->_pCardPixmap.rect());
|
||||
painter.restore();
|
||||
|
||||
//文字绘制
|
||||
//Title
|
||||
painter.setPen(ElaThemeColor(_themeMode, BasicText));
|
||||
QFont font = painter.font();
|
||||
font.setWeight(QFont::Bold);
|
||||
font.setPixelSize(15);
|
||||
painter.setFont(font);
|
||||
int titleHeight = painter.fontMetrics().height();
|
||||
QRectF titleRect(pixRect.right() + _cardPrivate->_textHSpacing, pixRect.y(), _floatGeometryOffset * 2 + cardForegroundRect.width() - pixRect.width() - _cardPrivate->_textHSpacing * 2 - cardForegroundRect.height() * 0.15 - _cardPrivate->_buttonTargetRect.width(), titleHeight);
|
||||
QString titleText = painter.fontMetrics().elidedText(_cardPrivate->_pTitle, Qt::ElideRight, titleRect.width());
|
||||
painter.drawText(titleRect, Qt::AlignLeft | Qt::AlignTop | Qt::TextSingleLine, titleText);
|
||||
|
||||
//SubTitle
|
||||
font.setWeight(QFont::DemiBold);
|
||||
font.setPixelSize(13);
|
||||
painter.setFont(font);
|
||||
int subTitleHeight = painter.fontMetrics().height();
|
||||
QRectF subTitleRect(pixRect.right() + _cardPrivate->_textHSpacing, titleRect.bottom() + _cardPrivate->_textVSpacing, _floatGeometryOffset * 2 + cardForegroundRect.width() - pixRect.width() - _cardPrivate->_textHSpacing * 2 - cardForegroundRect.height() * 0.15 - _cardPrivate->_buttonTargetRect.width(), subTitleHeight);
|
||||
QString subTitleText = painter.fontMetrics().elidedText(_cardPrivate->_pSubTitle, Qt::ElideRight, subTitleRect.width());
|
||||
painter.drawText(subTitleRect, Qt::AlignLeft | Qt::AlignTop | Qt::TextSingleLine, subTitleText);
|
||||
|
||||
//DetailedText
|
||||
painter.setPen(ElaThemeColor(_themeMode, BasicDetailsText));
|
||||
int detailedTextHeight = painter.fontMetrics().height() * 2 + 2;
|
||||
QRectF detailedTextRect(pixRect.x(), pixRect.bottom() + cardForegroundRect.height() * 0.15, cardForegroundRect.width() + 2 * _floatGeometryOffset - _cardPrivate->_textHSpacing - cardForegroundRect.height() * 0.15, detailedTextHeight);
|
||||
QString detailedText = painter.fontMetrics().elidedText(_cardPrivate->_pDetailedText, Qt::ElideRight, detailedTextRect.width() * 1.9);
|
||||
painter.drawText(detailedTextRect, Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, detailedText);
|
||||
|
||||
//分割线绘制
|
||||
painter.setPen(ElaThemeColor(_themeMode, BasicBaseLine));
|
||||
painter.drawLine(foregroundRect.x(), detailedTextRect.bottom() + 5, foregroundRect.right(), detailedTextRect.bottom() + 5);
|
||||
|
||||
//CardFloatPixmap
|
||||
painter.drawPixmap(QRect(pixRect.x(), detailedTextRect.bottom() + 15, cardForegroundRect.bottom() + _floatGeometryOffset + 90 - detailedTextRect.bottom() - 15 - _cardPrivate->_shadowBorderWidth - 10, cardForegroundRect.bottom() + _floatGeometryOffset + 90 - detailedTextRect.bottom() - 15 - _cardPrivate->_shadowBorderWidth - 10), _cardPrivate->_pCardFloatPixmap);
|
||||
painter.restore();
|
||||
}
|
||||
|
||||
QRect ElaPopularCardFloater::_calculateTargetGeometry(QRect cardGeometry)
|
||||
{
|
||||
QRect targetGeometry = cardGeometry;
|
||||
targetGeometry.adjust(-_floatGeometryOffset, -_floatGeometryOffset, _floatGeometryOffset, 90);
|
||||
QRect windowRect = _cardPrivate->_pCardFloatArea->rect();
|
||||
if (targetGeometry.bottom() > windowRect.bottom())
|
||||
{
|
||||
int offset = targetGeometry.bottom() - windowRect.bottom();
|
||||
targetGeometry.adjust(0, -offset, 0, -offset);
|
||||
}
|
||||
if (targetGeometry.top() < windowRect.top())
|
||||
{
|
||||
int offset = targetGeometry.top() - windowRect.top();
|
||||
targetGeometry.adjust(0, -offset, 0, -offset);
|
||||
}
|
||||
return targetGeometry;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#ifndef ELAPOPULARCARDFLOATER_H
|
||||
#define ELAPOPULARCARDFLOATER_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "Def.h"
|
||||
class ElaPushButton;
|
||||
class ElaPopularCard;
|
||||
class ElaPopularCardPrivate;
|
||||
class QGraphicsOpacityEffect;
|
||||
class ElaPopularCardFloater : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_CREATE(qreal, HoverYOffset);
|
||||
Q_PROPERTY_CREATE(qreal, HoverOpacity);
|
||||
|
||||
public:
|
||||
explicit ElaPopularCardFloater(ElaPopularCard* card, ElaPopularCardPrivate* cardPrivate, QWidget* parent = nullptr);
|
||||
~ElaPopularCardFloater();
|
||||
void showFloater();
|
||||
void hideFloater();
|
||||
|
||||
protected:
|
||||
virtual bool event(QEvent* event) override;
|
||||
virtual void paintEvent(QPaintEvent* event) override;
|
||||
|
||||
private:
|
||||
friend class ElaPopularCard;
|
||||
ElaThemeType::ThemeMode _themeMode;
|
||||
ElaPushButton* _overButton{nullptr};
|
||||
QGraphicsOpacityEffect* _opacityEffect{nullptr};
|
||||
bool _isHideAnimationFinished{true};
|
||||
ElaPopularCard* _card{nullptr};
|
||||
ElaPopularCardPrivate* _cardPrivate{nullptr};
|
||||
QRect _calculateTargetGeometry(QRect cardGeometry);
|
||||
int _floatGeometryOffset{25};
|
||||
};
|
||||
|
||||
#endif // ELAPOPULARCARDFLOATER_H
|
||||
@@ -0,0 +1,155 @@
|
||||
#include "ElaProgressBarStyle.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QPainter>
|
||||
#include <QStyleOption>
|
||||
|
||||
#include "ElaTheme.h"
|
||||
ElaProgressBarStyle::ElaProgressBarStyle(QStyle* style)
|
||||
{
|
||||
setProperty("busyStartValue", 0);
|
||||
setProperty("busyEndValue", 0);
|
||||
_themeMode = eTheme->getThemeMode();
|
||||
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) { _themeMode = themeMode; });
|
||||
}
|
||||
|
||||
ElaProgressBarStyle::~ElaProgressBarStyle()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaProgressBarStyle::drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const
|
||||
{
|
||||
switch (element)
|
||||
{
|
||||
case QStyle::CE_ProgressBarGroove:
|
||||
{
|
||||
//背景轨道
|
||||
painter->save();
|
||||
painter->setRenderHints(QPainter::Antialiasing);
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicChute));
|
||||
painter->drawRoundedRect(option->rect, 3, 3);
|
||||
painter->restore();
|
||||
return;
|
||||
}
|
||||
case QStyle::CE_ProgressBarContents:
|
||||
{
|
||||
//滑块
|
||||
const QStyleOptionProgressBar* popt = qstyleoption_cast<const QStyleOptionProgressBar*>(option);
|
||||
if (!popt)
|
||||
{
|
||||
break;
|
||||
}
|
||||
QRect contentRect = popt->rect;
|
||||
painter->save();
|
||||
painter->setRenderHints(QPainter::Antialiasing);
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(ElaThemeColor(_themeMode, PrimaryNormal));
|
||||
const bool inverted = popt->invertedAppearance;
|
||||
bool reverse = popt->direction == Qt::RightToLeft;
|
||||
if (inverted)
|
||||
{
|
||||
reverse = !reverse;
|
||||
}
|
||||
if (popt->minimum == 0 && popt->maximum == 0)
|
||||
{
|
||||
//忙碌动画
|
||||
int startValue = this->property("busyStartValue").toInt();
|
||||
if (startValue < 0)
|
||||
{
|
||||
startValue = 0;
|
||||
}
|
||||
int endValue = this->property("busyEndValue").toInt();
|
||||
if (popt->state & QStyle::State_Horizontal)
|
||||
{
|
||||
if (endValue > contentRect.width())
|
||||
{
|
||||
endValue = contentRect.width();
|
||||
}
|
||||
int busyWidth = endValue - startValue;
|
||||
if (reverse)
|
||||
{
|
||||
painter->translate((contentRect.x() + contentRect.width()) / 2, contentRect.y());
|
||||
painter->rotate(180);
|
||||
painter->translate(-(contentRect.x() + contentRect.width()) / 2, -contentRect.y() - contentRect.height() * 0.90);
|
||||
}
|
||||
painter->drawRoundedRect(QRectF(startValue, contentRect.y(), busyWidth, contentRect.height()), 3, 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (endValue > contentRect.height())
|
||||
{
|
||||
endValue = contentRect.height();
|
||||
}
|
||||
int busyHeight = endValue - startValue;
|
||||
painter->drawRoundedRect(QRectF(contentRect.x(), contentRect.height() - endValue, contentRect.width(), busyHeight), 3, 3);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
qreal ratio = popt->progress / (qreal)(popt->maximum - popt->minimum);
|
||||
if (popt->state & QStyle::State_Horizontal)
|
||||
{
|
||||
if (reverse)
|
||||
{
|
||||
painter->translate((contentRect.x() + contentRect.width()) / 2, contentRect.y());
|
||||
painter->rotate(180);
|
||||
painter->translate(-(contentRect.x() + contentRect.width()) / 2, -contentRect.y() - contentRect.height() * 0.90);
|
||||
}
|
||||
painter->drawRoundedRect(QRectF(contentRect.x(), contentRect.y(), contentRect.width() * ratio, contentRect.height()), 3, 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
painter->drawRoundedRect(QRectF(contentRect.x(), contentRect.y() + contentRect.height() * (1 - ratio), contentRect.width(), contentRect.height() * ratio), 3, 3);
|
||||
}
|
||||
}
|
||||
painter->restore();
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
QProxyStyle::drawControl(element, option, painter, widget);
|
||||
}
|
||||
|
||||
QRect ElaProgressBarStyle::subElementRect(SubElement element, const QStyleOption* option, const QWidget* widget) const
|
||||
{
|
||||
switch (element)
|
||||
{
|
||||
case QStyle::SE_ProgressBarGroove:
|
||||
case QStyle::SE_ProgressBarContents:
|
||||
{
|
||||
QRect textRect = subElementRect(SE_ProgressBarLabel, option, widget);
|
||||
const QStyleOptionProgressBar* popt = qstyleoption_cast<const QStyleOptionProgressBar*>(option);
|
||||
if (!popt)
|
||||
{
|
||||
break;
|
||||
}
|
||||
QRect contentRect = popt->rect;
|
||||
int width = contentRect.width();
|
||||
int height = contentRect.height();
|
||||
if (popt->state & QStyle::State_Horizontal)
|
||||
{
|
||||
contentRect.setTop(contentRect.top() + height * 0.45);
|
||||
contentRect.setBottom(contentRect.bottom() - height * 0.30);
|
||||
if (!(popt->minimum == 0 && popt->maximum == 0))
|
||||
{
|
||||
contentRect.setWidth(contentRect.width() - textRect.width());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
contentRect.setLeft(contentRect.left() + width * 0.375);
|
||||
contentRect.setRight(contentRect.right() - width * 0.375);
|
||||
}
|
||||
return contentRect;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QProxyStyle::subElementRect(element, option, widget);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef ELAPROGRESSBARSTYLE_H
|
||||
#define ELAPROGRESSBARSTYLE_H
|
||||
|
||||
#include <QProxyStyle>
|
||||
|
||||
#include "Def.h"
|
||||
class ElaProgressBarStyle : public QProxyStyle
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ElaProgressBarStyle(QStyle* style = nullptr);
|
||||
~ElaProgressBarStyle();
|
||||
void drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget = nullptr) const override;
|
||||
QRect subElementRect(SubElement element, const QStyleOption* option, const QWidget* widget) const override;
|
||||
|
||||
private:
|
||||
ElaThemeType::ThemeMode _themeMode;
|
||||
};
|
||||
|
||||
#endif // ELAPROGRESSBARSTYLE_H
|
||||
@@ -0,0 +1,104 @@
|
||||
#include "ElaRadioButtonStyle.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QStyleOption>
|
||||
|
||||
#include "ElaTheme.h"
|
||||
ElaRadioButtonStyle::ElaRadioButtonStyle(QStyle* style)
|
||||
{
|
||||
_themeMode = eTheme->getThemeMode();
|
||||
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) { _themeMode = themeMode; });
|
||||
}
|
||||
|
||||
ElaRadioButtonStyle::~ElaRadioButtonStyle()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaRadioButtonStyle::drawPrimitive(PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const
|
||||
{
|
||||
switch (element)
|
||||
{
|
||||
case PE_IndicatorRadioButton:
|
||||
{
|
||||
const QStyleOptionButton* bopt = qstyleoption_cast<const QStyleOptionButton*>(option);
|
||||
if (!bopt)
|
||||
{
|
||||
break;
|
||||
}
|
||||
QRect buttonRect = bopt->rect;
|
||||
buttonRect.adjust(1, 1, -1, -1);
|
||||
painter->save();
|
||||
painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
|
||||
|
||||
if (bopt->state & QStyle::State_Off)
|
||||
{
|
||||
painter->setPen(QPen(ElaThemeColor(_themeMode, BasicBorder), 1.5));
|
||||
if (bopt->state & QStyle::State_MouseOver)
|
||||
{
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicHover));
|
||||
}
|
||||
else
|
||||
{
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicBase));
|
||||
}
|
||||
painter->drawEllipse(QPointF(buttonRect.center().x() + 1, buttonRect.center().y() + 1), 8.5, 8.5);
|
||||
}
|
||||
else
|
||||
{
|
||||
painter->setPen(Qt::NoPen);
|
||||
// 外圆形
|
||||
painter->setBrush(ElaThemeColor(_themeMode, PrimaryNormal));
|
||||
painter->drawEllipse(QPointF(buttonRect.center().x() + 1, buttonRect.center().y() + 1), buttonRect.width() / 2, buttonRect.width() / 2);
|
||||
// 内圆形
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicTextInvert));
|
||||
if (bopt->state & QStyle::State_Sunken)
|
||||
{
|
||||
if (bopt->state & QStyle::State_MouseOver)
|
||||
{
|
||||
painter->drawEllipse(QPointF(buttonRect.center().x() + 1, buttonRect.center().y() + 1), buttonRect.width() / 4.5, buttonRect.width() / 4.5);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bopt->state & QStyle::State_MouseOver)
|
||||
{
|
||||
painter->drawEllipse(QPointF(buttonRect.center().x() + 1, buttonRect.center().y() + 1), buttonRect.width() / 3.5, buttonRect.width() / 3.5);
|
||||
}
|
||||
else
|
||||
{
|
||||
painter->drawEllipse(QPointF(buttonRect.center().x() + 1, buttonRect.center().y() + 1), buttonRect.width() / 4, buttonRect.width() / 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
painter->restore();
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QProxyStyle::drawPrimitive(element, option, painter, widget);
|
||||
}
|
||||
|
||||
int ElaRadioButtonStyle::pixelMetric(PixelMetric metric, const QStyleOption* option, const QWidget* widget) const
|
||||
{
|
||||
switch (metric)
|
||||
{
|
||||
case QStyle::PM_ExclusiveIndicatorWidth:
|
||||
{
|
||||
return 20;
|
||||
}
|
||||
case QStyle::PM_ExclusiveIndicatorHeight:
|
||||
{
|
||||
return 20;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QProxyStyle::pixelMetric(metric, option, widget);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef ELARADIOBUTTONSTYLE_H
|
||||
#define ELARADIOBUTTONSTYLE_H
|
||||
|
||||
#include <QProxyStyle>
|
||||
|
||||
#include "Def.h"
|
||||
class ElaRadioButtonStyle : public QProxyStyle
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ElaRadioButtonStyle(QStyle* style = nullptr);
|
||||
~ElaRadioButtonStyle();
|
||||
void drawPrimitive(PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget = nullptr) const override;
|
||||
int pixelMetric(PixelMetric metric, const QStyleOption* option = nullptr, const QWidget* widget = nullptr) const override;
|
||||
|
||||
private:
|
||||
ElaThemeType::ThemeMode _themeMode;
|
||||
};
|
||||
|
||||
#endif // ELARADIOBUTTONSTYLE_H
|
||||
@@ -0,0 +1,192 @@
|
||||
#include "ElaScrollBarStyle.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QPropertyAnimation>
|
||||
#include <QStyleOptionSlider>
|
||||
#include <QtMath>
|
||||
|
||||
#include "ElaScrollBar.h"
|
||||
#include "ElaTheme.h"
|
||||
ElaScrollBarStyle::ElaScrollBarStyle(QStyle* style)
|
||||
{
|
||||
_pIsExpand = false;
|
||||
_pOpacity = 0;
|
||||
_pScrollBar = nullptr;
|
||||
_pSliderExtent = 2.4;
|
||||
_themeMode = eTheme->getThemeMode();
|
||||
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) { _themeMode = themeMode; });
|
||||
}
|
||||
|
||||
ElaScrollBarStyle::~ElaScrollBarStyle()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaScrollBarStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget) const
|
||||
{
|
||||
//QStyle::SC_ScrollBarGroove QStyle::SC_ScrollBarAddLine QStyle::SC_ScrollBarSubLine上指示器
|
||||
switch (control)
|
||||
{
|
||||
case QStyle::CC_ScrollBar:
|
||||
{
|
||||
if (const QStyleOptionSlider* sopt = qstyleoption_cast<const QStyleOptionSlider*>(option))
|
||||
{
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing);
|
||||
painter->setPen(Qt::NoPen);
|
||||
QRect scrollBarRect = sopt->rect;
|
||||
if (_pIsExpand)
|
||||
{
|
||||
// 背景绘制
|
||||
painter->setOpacity(_pOpacity);
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicBase));
|
||||
painter->drawRoundedRect(scrollBarRect, 6, 6);
|
||||
//指示器绘制 center()在此处不适用 存在外围边距宽度 需手动计算
|
||||
int sideLength = 8;
|
||||
painter->setBrush(ElaThemeColor(_themeMode, ScrollBarHandle));
|
||||
if (sopt->orientation == Qt::Horizontal)
|
||||
{
|
||||
QRect leftIndicatorRect = subControlRect(control, sopt, QStyle::SC_ScrollBarSubLine, widget);
|
||||
QRect rightIndicatorRect = subControlRect(control, sopt, QStyle::SC_ScrollBarAddLine, widget);
|
||||
// 左三角
|
||||
qreal centerLeftX = leftIndicatorRect.x() + leftIndicatorRect.width() / 2;
|
||||
qreal centerRightX = rightIndicatorRect.x() + rightIndicatorRect.width() / 2;
|
||||
qreal centerY = leftIndicatorRect.height() / 2;
|
||||
QPainterPath leftPath;
|
||||
leftPath.moveTo(centerLeftX - qCos(30 * M_PI / 180.0) * sideLength / 2, centerY);
|
||||
leftPath.lineTo(centerLeftX + qCos(30 * M_PI / 180.0) * sideLength / 2, centerY + sideLength / 2);
|
||||
leftPath.lineTo(centerLeftX + qCos(30 * M_PI / 180.0) * sideLength / 2, centerY - sideLength / 2);
|
||||
leftPath.closeSubpath();
|
||||
painter->drawPath(leftPath);
|
||||
|
||||
// 右三角
|
||||
QPainterPath rightPath;
|
||||
rightPath.moveTo(centerRightX + qCos(30 * M_PI / 180.0) * sideLength / 2, centerY);
|
||||
rightPath.lineTo(centerRightX - qCos(30 * M_PI / 180.0) * sideLength / 2, centerY + sideLength / 2);
|
||||
rightPath.lineTo(centerRightX - qCos(30 * M_PI / 180.0) * sideLength / 2, centerY - sideLength / 2);
|
||||
rightPath.closeSubpath();
|
||||
painter->drawPath(rightPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
QRect upIndicatorRect = subControlRect(control, sopt, QStyle::SC_ScrollBarSubLine, widget);
|
||||
QRect downIndicatorRect = subControlRect(control, sopt, QStyle::SC_ScrollBarAddLine, widget);
|
||||
qreal centerToTop = (sideLength / 2) / qCos(30 * M_PI / 180.0);
|
||||
qreal centerToBottom = (sideLength / 2) * qTan(30 * M_PI / 180.0);
|
||||
// 上三角
|
||||
qreal centerX = upIndicatorRect.width() / 2.0;
|
||||
qreal centerUpY = upIndicatorRect.center().y() + 2;
|
||||
qreal centerDownY = downIndicatorRect.center().y() + 2;
|
||||
QPainterPath upPath;
|
||||
upPath.moveTo(centerX, centerUpY - centerToTop);
|
||||
upPath.lineTo(centerX + sideLength / 2, centerUpY + centerToBottom);
|
||||
upPath.lineTo(centerX - sideLength / 2, centerUpY + centerToBottom);
|
||||
upPath.closeSubpath();
|
||||
painter->drawPath(upPath);
|
||||
|
||||
// 下三角
|
||||
QPainterPath downPath;
|
||||
downPath.moveTo(centerX, centerDownY + centerToBottom);
|
||||
downPath.lineTo(centerX + sideLength / 2, centerDownY - centerToTop);
|
||||
downPath.lineTo(centerX - sideLength / 2, centerDownY - centerToTop);
|
||||
downPath.closeSubpath();
|
||||
painter->drawPath(downPath);
|
||||
}
|
||||
}
|
||||
painter->setOpacity(1);
|
||||
//滑块绘制
|
||||
QRectF sliderRect = subControlRect(control, sopt, QStyle::SC_ScrollBarSlider, widget);
|
||||
painter->setBrush(ElaThemeColor(_themeMode, ScrollBarHandle));
|
||||
if (sopt->orientation == Qt::Horizontal)
|
||||
{
|
||||
sliderRect.setRect(sliderRect.x(), sliderRect.bottom() - _sliderMargin - _pSliderExtent, sliderRect.width(), _pSliderExtent);
|
||||
}
|
||||
else
|
||||
{
|
||||
sliderRect.setRect(sliderRect.right() - _sliderMargin - _pSliderExtent, sliderRect.y(), _pSliderExtent, sliderRect.height());
|
||||
}
|
||||
painter->drawRoundedRect(sliderRect, _pSliderExtent / 2.0, _pSliderExtent / 2.0);
|
||||
painter->restore();
|
||||
}
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
QProxyStyle::drawComplexControl(control, option, painter, widget);
|
||||
}
|
||||
|
||||
int ElaScrollBarStyle::pixelMetric(PixelMetric metric, const QStyleOption* option, const QWidget* widget) const
|
||||
{
|
||||
// qDebug() << metric << QProxyStyle::pixelMetric(metric, option, widget);
|
||||
switch (metric)
|
||||
{
|
||||
case QStyle::PM_ScrollBarExtent:
|
||||
{
|
||||
return _scrollBarExtent;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QProxyStyle::pixelMetric(metric, option, widget);
|
||||
}
|
||||
|
||||
int ElaScrollBarStyle::styleHint(StyleHint hint, const QStyleOption* option, const QWidget* widget, QStyleHintReturn* returnData) const
|
||||
{
|
||||
if (hint == QStyle::SH_ScrollBar_LeftClickAbsolutePosition)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return QProxyStyle::styleHint(hint, option, widget, returnData);
|
||||
}
|
||||
|
||||
void ElaScrollBarStyle::startExpandAnimation(bool isExpand)
|
||||
{
|
||||
if (isExpand)
|
||||
{
|
||||
_pIsExpand = true;
|
||||
QPropertyAnimation* opacityAnimation = new QPropertyAnimation(this, "pOpacity");
|
||||
connect(opacityAnimation, &QPropertyAnimation::valueChanged, this, [=]() {
|
||||
_pScrollBar->update();
|
||||
});
|
||||
opacityAnimation->setDuration(250);
|
||||
opacityAnimation->setEasingCurve(QEasingCurve::InOutSine);
|
||||
opacityAnimation->setStartValue(_pOpacity);
|
||||
opacityAnimation->setEndValue(1);
|
||||
opacityAnimation->start(QAbstractAnimation::DeleteWhenStopped);
|
||||
|
||||
QPropertyAnimation* extentAnimation = new QPropertyAnimation(this, "pSliderExtent");
|
||||
extentAnimation->setDuration(250);
|
||||
extentAnimation->setEasingCurve(QEasingCurve::InOutSine);
|
||||
extentAnimation->setStartValue(_pSliderExtent);
|
||||
extentAnimation->setEndValue(_scrollBarExtent - 2 * _sliderMargin);
|
||||
extentAnimation->start(QAbstractAnimation::DeleteWhenStopped);
|
||||
}
|
||||
else
|
||||
{
|
||||
QPropertyAnimation* opacityAnimation = new QPropertyAnimation(this, "pOpacity");
|
||||
connect(opacityAnimation, &QPropertyAnimation::finished, this, [=]() {
|
||||
_pIsExpand = false;
|
||||
});
|
||||
connect(opacityAnimation, &QPropertyAnimation::valueChanged, this, [=]() {
|
||||
_pScrollBar->update();
|
||||
});
|
||||
opacityAnimation->setDuration(250);
|
||||
opacityAnimation->setEasingCurve(QEasingCurve::InOutSine);
|
||||
opacityAnimation->setStartValue(_pOpacity);
|
||||
opacityAnimation->setEndValue(0);
|
||||
opacityAnimation->start(QAbstractAnimation::DeleteWhenStopped);
|
||||
|
||||
QPropertyAnimation* extentAnimation = new QPropertyAnimation(this, "pSliderExtent");
|
||||
extentAnimation->setDuration(250);
|
||||
extentAnimation->setEasingCurve(QEasingCurve::InOutSine);
|
||||
extentAnimation->setStartValue(_pSliderExtent);
|
||||
extentAnimation->setEndValue(2.4);
|
||||
extentAnimation->start(QAbstractAnimation::DeleteWhenStopped);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef ELASCROLLBARSTYLE_H
|
||||
#define ELASCROLLBARSTYLE_H
|
||||
#include <QProxyStyle>
|
||||
|
||||
#include "Def.h"
|
||||
class ElaScrollBar;
|
||||
class ElaScrollBarStyle : public QProxyStyle
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PRIVATE_CREATE(bool, IsExpand)
|
||||
Q_PROPERTY_CREATE(qreal, Opacity)
|
||||
Q_PROPERTY_CREATE(qreal, SliderExtent)
|
||||
Q_PRIVATE_CREATE(ElaScrollBar*, ScrollBar)
|
||||
public:
|
||||
explicit ElaScrollBarStyle(QStyle* style = nullptr);
|
||||
~ElaScrollBarStyle();
|
||||
void drawComplexControl(ComplexControl control, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget = nullptr) const override;
|
||||
int pixelMetric(PixelMetric metric, const QStyleOption* option = nullptr, const QWidget* widget = nullptr) const override;
|
||||
int styleHint(StyleHint hint, const QStyleOption* option = nullptr, const QWidget* widget = nullptr, QStyleHintReturn* returnData = nullptr) const override;
|
||||
void startExpandAnimation(bool isExpand);
|
||||
|
||||
private:
|
||||
ElaThemeType::ThemeMode _themeMode;
|
||||
qreal _sliderMargin{2.5};
|
||||
int _scrollBarExtent{10};
|
||||
};
|
||||
|
||||
#endif // ELASCROLLBARSTYLE_H
|
||||
@@ -0,0 +1,164 @@
|
||||
#include "ElaSliderStyle.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPropertyAnimation>
|
||||
#include <QStyleOptionSlider>
|
||||
|
||||
#include "ElaTheme.h"
|
||||
ElaSliderStyle::ElaSliderStyle(QStyle* style)
|
||||
{
|
||||
setProperty("circleRadius", 0.01);
|
||||
_themeMode = eTheme->getThemeMode();
|
||||
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) { _themeMode = themeMode; });
|
||||
}
|
||||
|
||||
ElaSliderStyle::~ElaSliderStyle()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaSliderStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget) const
|
||||
{
|
||||
switch (control)
|
||||
{
|
||||
case QStyle::CC_Slider:
|
||||
{
|
||||
const QStyleOptionSlider* sopt = qstyleoption_cast<const QStyleOptionSlider*>(option);
|
||||
if (!sopt)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
painter->save();
|
||||
painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
|
||||
QRect sliderRect = sopt->rect;
|
||||
QRect sliderHandleRect = subControlRect(control, sopt, SC_SliderHandle, widget);
|
||||
sliderHandleRect.adjust(1, 1, -1, -1);
|
||||
// 滑槽
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicChute));
|
||||
if (sopt->orientation == Qt::Horizontal)
|
||||
{
|
||||
// 未滑过
|
||||
painter->drawRoundedRect(QRect(sliderRect.x() + sliderRect.height() / 8, sliderRect.y() + sliderRect.height() * 0.375, sliderRect.width() - sliderRect.height() / 4, sliderRect.height() / 4), sliderRect.height() / 8, sliderRect.height() / 8);
|
||||
// 已滑过
|
||||
painter->setBrush(ElaThemeColor(_themeMode, PrimaryNormal));
|
||||
painter->drawRoundedRect(QRect(sliderRect.x() + sliderRect.height() / 8, sliderRect.y() + sliderRect.height() * 0.375, sliderHandleRect.x(), sliderRect.height() / 4), sliderRect.height() / 8, sliderRect.height() / 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 未滑过
|
||||
painter->drawRoundedRect(QRect(sliderRect.x() + sliderRect.width() * 0.375, sliderRect.y() + sliderRect.width() / 8, sliderRect.width() / 4, sliderRect.height() - sliderRect.width() / 4), sliderRect.width() / 8, sliderRect.width() / 8);
|
||||
// 已滑过
|
||||
painter->setBrush(ElaThemeColor(_themeMode, PrimaryNormal));
|
||||
painter->drawRoundedRect(QRect(sliderRect.x() + sliderRect.width() * 0.375, sliderHandleRect.y(), sliderRect.width() / 4, sliderRect.height() - sliderRect.width() / 8 - sliderHandleRect.y()), sliderRect.width() / 8, sliderRect.width() / 8);
|
||||
}
|
||||
// 滑块
|
||||
// 外圆形
|
||||
painter->setPen(ElaThemeColor(_themeMode, BasicBorder));
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicBase));
|
||||
painter->drawEllipse(QPointF(sliderHandleRect.center().x() + 1, sliderHandleRect.center().y() + 1), sliderHandleRect.width() / 2, sliderHandleRect.width() / 2);
|
||||
// 内圆形
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(ElaThemeColor(_themeMode, PrimaryNormal));
|
||||
if (_lastState == 0)
|
||||
{
|
||||
_lastState = sopt->state;
|
||||
}
|
||||
if (_circleRadius == 0)
|
||||
{
|
||||
_circleRadius = sliderHandleRect.width() / 3.8;
|
||||
}
|
||||
if (sopt->activeSubControls == SC_SliderHandle)
|
||||
{
|
||||
if (sopt->state & QStyle::State_Sunken)
|
||||
{
|
||||
if (sopt->state & QStyle::State_MouseOver)
|
||||
{
|
||||
if (!_lastState.testFlag(QStyle::State_Sunken))
|
||||
{
|
||||
_startRadiusAnimation(sliderHandleRect.width() / 2.8, sliderHandleRect.width() / 4.5, const_cast<QWidget*>(widget));
|
||||
_lastState = sopt->state;
|
||||
}
|
||||
painter->drawEllipse(QPointF(sliderHandleRect.center().x() + 1, sliderHandleRect.center().y() + 1), _circleRadius, _circleRadius);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sopt->state & QStyle::State_MouseOver)
|
||||
{
|
||||
if (!_lastState.testFlag(QStyle::State_MouseOver))
|
||||
{
|
||||
_startRadiusAnimation(_circleRadius, sliderHandleRect.width() / 2.8, const_cast<QWidget*>(widget));
|
||||
_lastState = sopt->state;
|
||||
}
|
||||
if (_lastState.testFlag(QStyle::State_Sunken))
|
||||
{
|
||||
_startRadiusAnimation(_circleRadius, sliderHandleRect.width() / 2.8, const_cast<QWidget*>(widget));
|
||||
_lastState = sopt->state;
|
||||
}
|
||||
painter->drawEllipse(QPointF(sliderHandleRect.center().x() + 1, sliderHandleRect.center().y() + 1), _circleRadius, _circleRadius);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_lastState.testFlag(QStyle::State_MouseOver) || _lastState.testFlag(QStyle::State_Sunken))
|
||||
{
|
||||
_startRadiusAnimation(_circleRadius, sliderHandleRect.width() / 3.8, const_cast<QWidget*>(widget));
|
||||
_lastState &= ~QStyle::State_MouseOver;
|
||||
_lastState &= ~QStyle::State_Sunken;
|
||||
}
|
||||
painter->drawEllipse(QPointF(sliderHandleRect.center().x() + 1, sliderHandleRect.center().y() + 1), _circleRadius, _circleRadius);
|
||||
}
|
||||
painter->restore();
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
QProxyStyle::drawComplexControl(control, option, painter, widget);
|
||||
}
|
||||
|
||||
int ElaSliderStyle::pixelMetric(PixelMetric metric, const QStyleOption* option, const QWidget* widget) const
|
||||
{
|
||||
switch (metric)
|
||||
{
|
||||
case QStyle::PM_SliderLength:
|
||||
{
|
||||
return 20;
|
||||
}
|
||||
case QStyle::PM_SliderThickness:
|
||||
{
|
||||
return 20;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QProxyStyle::pixelMetric(metric, option, widget);
|
||||
}
|
||||
|
||||
int ElaSliderStyle::styleHint(StyleHint hint, const QStyleOption* option, const QWidget* widget, QStyleHintReturn* returnData) const
|
||||
{
|
||||
if (hint == QStyle::SH_Slider_AbsoluteSetButtons)
|
||||
{
|
||||
return Qt::LeftButton;
|
||||
}
|
||||
return QProxyStyle::styleHint(hint, option, widget, returnData);
|
||||
}
|
||||
|
||||
void ElaSliderStyle::_startRadiusAnimation(qreal startRadius, qreal endRadius, QWidget* widget) const
|
||||
{
|
||||
ElaSliderStyle* style = const_cast<ElaSliderStyle*>(this);
|
||||
QPropertyAnimation* circleRadiusAnimation = new QPropertyAnimation(style, "circleRadius");
|
||||
connect(circleRadiusAnimation, &QPropertyAnimation::valueChanged, style, [=](const QVariant& value) {
|
||||
this->_circleRadius = value.toReal();
|
||||
widget->update(); });
|
||||
circleRadiusAnimation->setEasingCurve(QEasingCurve::InOutSine);
|
||||
circleRadiusAnimation->setStartValue(startRadius);
|
||||
circleRadiusAnimation->setEndValue(endRadius);
|
||||
circleRadiusAnimation->start(QAbstractAnimation::DeleteWhenStopped);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef ELASLIDERSTYLE_H
|
||||
#define ELASLIDERSTYLE_H
|
||||
|
||||
#include <QProxyStyle>
|
||||
|
||||
#include "Def.h"
|
||||
class ElaSliderStyle : public QProxyStyle
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ElaSliderStyle(QStyle* style = nullptr);
|
||||
~ElaSliderStyle();
|
||||
void drawComplexControl(ComplexControl control, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget = nullptr) const override;
|
||||
int pixelMetric(PixelMetric metric, const QStyleOption* option = nullptr, const QWidget* widget = nullptr) const override;
|
||||
int styleHint(StyleHint hint, const QStyleOption* option = nullptr, const QWidget* widget = nullptr, QStyleHintReturn* returnData = nullptr) const override;
|
||||
|
||||
private:
|
||||
ElaThemeType::ThemeMode _themeMode;
|
||||
mutable QStyle::State _lastState{0};
|
||||
mutable qreal _circleRadius{0};
|
||||
void _startRadiusAnimation(qreal startRadius, qreal endRadius, QWidget* widget) const;
|
||||
};
|
||||
|
||||
#endif // ELASLIDERSTYLE_H
|
||||
@@ -0,0 +1,173 @@
|
||||
#include "ElaSpinBoxStyle.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QStyleOptionSpinBox>
|
||||
|
||||
#include "ElaTheme.h"
|
||||
ElaSpinBoxStyle::ElaSpinBoxStyle(QStyle* style)
|
||||
{
|
||||
_themeMode = eTheme->getThemeMode();
|
||||
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) { _themeMode = themeMode; });
|
||||
}
|
||||
|
||||
ElaSpinBoxStyle::~ElaSpinBoxStyle()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaSpinBoxStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget) const
|
||||
{
|
||||
switch (control)
|
||||
{
|
||||
case QStyle::CC_SpinBox:
|
||||
{
|
||||
const QStyleOptionSpinBox* sopt = qstyleoption_cast<const QStyleOptionSpinBox*>(option);
|
||||
if (!sopt)
|
||||
{
|
||||
break;
|
||||
}
|
||||
painter->save();
|
||||
painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
|
||||
//背景
|
||||
painter->setPen(ElaThemeColor(_themeMode, BasicBorder));
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicBase));
|
||||
painter->drawRoundedRect(sopt->rect, 4, 4);
|
||||
//添加按钮
|
||||
QRect addLineRect = subControlRect(control, sopt, SC_ScrollBarAddLine, widget);
|
||||
if (sopt->activeSubControls == SC_ScrollBarAddLine)
|
||||
{
|
||||
if (sopt->state & QStyle::State_Sunken && sopt->state & QStyle::State_MouseOver)
|
||||
{
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicPressAlpha));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sopt->state & QStyle::State_MouseOver)
|
||||
{
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicHoverAlpha));
|
||||
}
|
||||
else
|
||||
{
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicBaseDeep));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicBaseDeep));
|
||||
}
|
||||
QPainterPath addLinePath;
|
||||
addLinePath.moveTo(addLineRect.topLeft());
|
||||
addLinePath.lineTo(addLineRect.bottomLeft());
|
||||
addLinePath.lineTo(addLineRect.right() - 4, addLineRect.bottom());
|
||||
addLinePath.arcTo(QRectF(addLineRect.right() - 8, addLineRect.bottom() - 8, 8, 8), -90, 90);
|
||||
addLinePath.lineTo(addLineRect.right(), addLineRect.y() + 4);
|
||||
addLinePath.arcTo(QRectF(addLineRect.right() - 8, addLineRect.y(), 8, 8), 0, 90);
|
||||
addLinePath.closeSubpath();
|
||||
painter->drawPath(addLinePath);
|
||||
|
||||
//减少按钮
|
||||
QRect subLineRect = subControlRect(control, sopt, SC_ScrollBarSubLine, widget);
|
||||
if (sopt->activeSubControls == SC_ScrollBarSubLine)
|
||||
{
|
||||
if (sopt->state & QStyle::State_Sunken && sopt->state & QStyle::State_MouseOver)
|
||||
{
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicPressAlpha));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sopt->state & QStyle::State_MouseOver)
|
||||
{
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicHoverAlpha));
|
||||
}
|
||||
else
|
||||
{
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicBaseDeep));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicBaseDeep));
|
||||
}
|
||||
QPainterPath subLinePath;
|
||||
subLinePath.moveTo(subLineRect.topRight());
|
||||
subLinePath.lineTo(subLineRect.x() + 4, subLineRect.y());
|
||||
subLinePath.arcTo(QRectF(subLineRect.x(), subLineRect.y(), 8, 8), 90, 90);
|
||||
subLinePath.lineTo(subLineRect.x(), subLineRect.bottom() - 4);
|
||||
subLinePath.arcTo(QRectF(subLineRect.x(), subLineRect.bottom() - 8, 8, 8), 180, 90);
|
||||
subLinePath.lineTo(subLineRect.bottomRight());
|
||||
subLinePath.closeSubpath();
|
||||
painter->drawPath(subLinePath);
|
||||
//底边线
|
||||
if (sopt->state & QStyle::State_HasFocus)
|
||||
{
|
||||
painter->setPen(QPen(ElaThemeColor(_themeMode, PrimaryNormal), 2));
|
||||
painter->drawLine(subLineRect.right() + 1, subLineRect.y() + subLineRect.height() - 2, addLineRect.left() - 1, subLineRect.y() + subLineRect.height() - 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
painter->setPen(ElaThemeColor(_themeMode, BasicHemline));
|
||||
painter->drawLine(subLineRect.right() + 1, subLineRect.y() + subLineRect.height() - 1, addLineRect.left() - 1, subLineRect.y() + subLineRect.height() - 1);
|
||||
}
|
||||
|
||||
//添加图标
|
||||
QFont iconFont = QFont("ElaAwesome");
|
||||
iconFont.setPixelSize(17);
|
||||
painter->setFont(iconFont);
|
||||
painter->setPen(ElaThemeColor(_themeMode, BasicText));
|
||||
painter->drawText(addLineRect, Qt::AlignCenter, QChar((unsigned short)ElaIconType::Plus));
|
||||
//减小图标
|
||||
painter->drawText(subLineRect, Qt::AlignCenter, QChar((unsigned short)ElaIconType::Minus));
|
||||
painter->restore();
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
QProxyStyle::drawComplexControl(control, option, painter, widget);
|
||||
}
|
||||
|
||||
QRect ElaSpinBoxStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex* opt, SubControl sc, const QWidget* widget) const
|
||||
{
|
||||
QRect rect = QProxyStyle::subControlRect(cc, opt, sc, widget);
|
||||
switch (cc)
|
||||
{
|
||||
case CC_SpinBox:
|
||||
{
|
||||
switch (sc)
|
||||
{
|
||||
case SC_ScrollBarAddLine:
|
||||
{
|
||||
//增加按钮
|
||||
QRect spinBoxRect = QProxyStyle::subControlRect(cc, opt, SC_SpinBoxFrame, widget);
|
||||
return QRect(spinBoxRect.width() - spinBoxRect.height(), 0, spinBoxRect.height(), spinBoxRect.height());
|
||||
}
|
||||
case SC_ScrollBarSubLine:
|
||||
{
|
||||
//减少按钮
|
||||
QRect spinBoxRect = QProxyStyle::subControlRect(cc, opt, SC_SpinBoxFrame, widget);
|
||||
return QRect(0, 0, spinBoxRect.height(), spinBoxRect.height());
|
||||
}
|
||||
case SC_SpinBoxEditField:
|
||||
{
|
||||
QRect spinBoxRect = QProxyStyle::subControlRect(cc, opt, SC_SpinBoxFrame, widget);
|
||||
return QRect(spinBoxRect.height(), 0, spinBoxRect.width() - 2 * spinBoxRect.height(), spinBoxRect.height());
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rect;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef ELASPINBOXSTYLE_H
|
||||
#define ELASPINBOXSTYLE_H
|
||||
|
||||
#include <QProxyStyle>
|
||||
|
||||
#include "Def.h"
|
||||
class ElaSpinBoxStyle : public QProxyStyle
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ElaSpinBoxStyle(QStyle* style = nullptr);
|
||||
~ElaSpinBoxStyle();
|
||||
void drawComplexControl(ComplexControl control, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget = nullptr) const override;
|
||||
QRect subControlRect(ComplexControl cc, const QStyleOptionComplex* opt, SubControl sc, const QWidget* widget) const override;
|
||||
|
||||
private:
|
||||
ElaThemeType::ThemeMode _themeMode;
|
||||
};
|
||||
|
||||
#endif // ELASPINBOXSTYLE_H
|
||||
@@ -0,0 +1,80 @@
|
||||
#include "ElaStatusBarStyle.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QPainter>
|
||||
#include <QStyleOption>
|
||||
|
||||
#include "ElaTheme.h"
|
||||
ElaStatusBarStyle::ElaStatusBarStyle(QStyle* style)
|
||||
{
|
||||
_themeMode = eTheme->getThemeMode();
|
||||
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) { _themeMode = themeMode; });
|
||||
}
|
||||
|
||||
ElaStatusBarStyle::~ElaStatusBarStyle()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaStatusBarStyle::drawPrimitive(PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const
|
||||
{
|
||||
switch (element)
|
||||
{
|
||||
case QStyle::PE_PanelStatusBar:
|
||||
{
|
||||
//背景绘制
|
||||
QRect statusBarRect = option->rect;
|
||||
painter->save();
|
||||
painter->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
|
||||
painter->setPen(ElaThemeColor(_themeMode, BasicBorder));
|
||||
painter->setBrush(ElaThemeColor(_themeMode, BasicBaseAlpha));
|
||||
painter->drawRect(statusBarRect);
|
||||
painter->restore();
|
||||
return;
|
||||
}
|
||||
case QStyle::PE_FrameStatusBarItem:
|
||||
{
|
||||
//间隔符绘制
|
||||
QRect statusBarItemRect = option->rect;
|
||||
painter->save();
|
||||
painter->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(ElaThemeColor(_themeMode, PrimaryNormal));
|
||||
painter->drawRoundedRect(QRectF(statusBarItemRect.right() - 3, statusBarItemRect.y() + statusBarItemRect.height() * 0.1, 3, statusBarItemRect.height() - statusBarItemRect.height() * 0.2), 2, 2);
|
||||
painter->restore();
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
QProxyStyle::drawPrimitive(element, option, painter, widget);
|
||||
}
|
||||
|
||||
void ElaStatusBarStyle::drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const
|
||||
{
|
||||
switch (element)
|
||||
{
|
||||
case QStyle::CE_SizeGrip:
|
||||
{
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QProxyStyle::drawControl(element, option, painter, widget);
|
||||
}
|
||||
|
||||
QSize ElaStatusBarStyle::sizeFromContents(ContentsType type, const QStyleOption* option, const QSize& size, const QWidget* widget) const
|
||||
{
|
||||
//qDebug() << type << QProxyStyle::sizeFromContents(type, option, size, widget);
|
||||
return QProxyStyle::sizeFromContents(type, option, size, widget);
|
||||
}
|
||||
|
||||
int ElaStatusBarStyle::pixelMetric(PixelMetric metric, const QStyleOption* option, const QWidget* widget) const
|
||||
{
|
||||
return QProxyStyle::pixelMetric(metric, option, widget);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef ELASTATUSBARSTYLE_H
|
||||
#define ELASTATUSBARSTYLE_H
|
||||
|
||||
#include <QProxyStyle>
|
||||
|
||||
#include "Def.h"
|
||||
class ElaStatusBarStyle : public QProxyStyle
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ElaStatusBarStyle(QStyle* style = nullptr);
|
||||
~ElaStatusBarStyle();
|
||||
void drawPrimitive(PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget = nullptr) const override;
|
||||
void drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget = nullptr) const override;
|
||||
QSize sizeFromContents(ContentsType type, const QStyleOption* option, const QSize& size, const QWidget* widget) const override;
|
||||
int pixelMetric(PixelMetric metric, const QStyleOption* option = nullptr, const QWidget* widget = nullptr) const override;
|
||||
|
||||
private:
|
||||
ElaThemeType::ThemeMode _themeMode;
|
||||
};
|
||||
|
||||
#endif // ELASTATUSBARSTYLE_H
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
#include "ElaSuggestBoxSearchViewContainer.h"
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
#include "ElaTheme.h"
|
||||
ElaSuggestBoxSearchViewContainer::ElaSuggestBoxSearchViewContainer(QWidget* parent)
|
||||
: QWidget{parent}
|
||||
{
|
||||
setContentsMargins(8, 8, 8, 8);
|
||||
setObjectName("ElaSuggestBoxSearchViewBaseWidget");
|
||||
setStyleSheet("#ElaSuggestBoxSearchViewBaseWidget{background-color:transparent}");
|
||||
_themeMode = eTheme->getThemeMode();
|
||||
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) { _themeMode = themeMode; });
|
||||
}
|
||||
|
||||
ElaSuggestBoxSearchViewContainer::~ElaSuggestBoxSearchViewContainer()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaSuggestBoxSearchViewContainer::paintEvent(QPaintEvent* event)
|
||||
{
|
||||
QPainter painter(this);
|
||||
painter.save();
|
||||
painter.setRenderHints(QPainter::Antialiasing);
|
||||
eTheme->drawEffectShadow(&painter, rect(), 6, 8);
|
||||
painter.setPen(ElaThemeColor(_themeMode, PopupBorder));
|
||||
painter.setBrush(ElaThemeColor(_themeMode, PopupBase));
|
||||
QRect foregroundRect(6, 0, rect().width() - 2 * 6, rect().height() - 6);
|
||||
painter.drawRoundedRect(foregroundRect, 8, 8);
|
||||
painter.restore();
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
#ifndef ELASUGGESTBOXSEARCHVIEWCONTAINER_H
|
||||
#define ELASUGGESTBOXSEARCHVIEWCONTAINER_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "Def.h"
|
||||
class ElaSuggestBoxSearchViewContainer : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ElaSuggestBoxSearchViewContainer(QWidget* parent = nullptr);
|
||||
~ElaSuggestBoxSearchViewContainer();
|
||||
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent* event) override;
|
||||
|
||||
private:
|
||||
ElaThemeType::ThemeMode _themeMode;
|
||||
};
|
||||
|
||||
#endif // ELASUGGESTBOXSEARCHVIEWCONTAINER_H
|
||||
@@ -0,0 +1,79 @@
|
||||
#include "ElaSuggestDelegate.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
|
||||
#include "ElaSuggestBoxPrivate.h"
|
||||
#include "ElaSuggestModel.h"
|
||||
#include "ElaTheme.h"
|
||||
ElaSuggestDelegate::ElaSuggestDelegate(QObject* parent)
|
||||
: QStyledItemDelegate{parent}
|
||||
{
|
||||
_themeMode = eTheme->getThemeMode();
|
||||
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) { _themeMode = themeMode; });
|
||||
}
|
||||
|
||||
ElaSuggestDelegate::~ElaSuggestDelegate()
|
||||
{
|
||||
}
|
||||
|
||||
void ElaSuggestDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
int margin = 2;
|
||||
QStyleOptionViewItem viewOption(option);
|
||||
initStyleOption(&viewOption, index);
|
||||
|
||||
ElaSuggestModel* model = dynamic_cast<ElaSuggestModel*>(const_cast<QAbstractItemModel*>(index.model()));
|
||||
ElaSuggestion* suggest = model->getSearchSuggestion(index.row());
|
||||
if (option.state.testFlag(QStyle::State_HasFocus))
|
||||
{
|
||||
viewOption.state &= ~QStyle::State_HasFocus;
|
||||
}
|
||||
painter->save();
|
||||
painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
|
||||
QPainterPath path;
|
||||
QRect optionRect = option.rect;
|
||||
optionRect.adjust(margin * 2, margin, -margin * 2, -margin);
|
||||
path.addRoundedRect(optionRect, 8, 8);
|
||||
if (option.state & QStyle::State_Selected)
|
||||
{
|
||||
if (option.state & QStyle::State_MouseOver)
|
||||
{
|
||||
//选中时覆盖
|
||||
painter->fillPath(path, ElaThemeColor(_themeMode, BasicSelectedHoverAlpha));
|
||||
}
|
||||
else
|
||||
{
|
||||
//选中
|
||||
painter->fillPath(path, ElaThemeColor(_themeMode, BasicSelectedAlpha));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (option.state & QStyle::State_MouseOver)
|
||||
{
|
||||
//覆盖时颜色
|
||||
painter->fillPath(path, ElaThemeColor(_themeMode, BasicHoverAlpha));
|
||||
}
|
||||
}
|
||||
//文字绘制
|
||||
painter->setPen(ElaThemeColor(_themeMode, BasicText));
|
||||
painter->drawText(option.rect.x() + 37, option.rect.y() + 25, suggest->getSuggestText());
|
||||
|
||||
//图标绘制
|
||||
if (suggest->getElaIcon() != ElaIconType::None)
|
||||
{
|
||||
QFont iconFont = QFont("ElaAwesome");
|
||||
iconFont.setPixelSize(17);
|
||||
painter->setFont(iconFont);
|
||||
painter->drawText(option.rect.x() + 11, option.rect.y() + 26, QChar((unsigned short)suggest->getElaIcon()));
|
||||
}
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
QSize ElaSuggestDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
QSize size = QStyledItemDelegate::sizeHint(option, index);
|
||||
size.setHeight(40);
|
||||
return size;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef ELASUGGESTDELEGATE_H
|
||||
#define ELASUGGESTDELEGATE_H
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
#include "Def.h"
|
||||
class ElaSuggestDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ElaSuggestDelegate(QObject* parent = nullptr);
|
||||
~ElaSuggestDelegate();
|
||||
|
||||
protected:
|
||||
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
|
||||
private:
|
||||
ElaThemeType::ThemeMode _themeMode;
|
||||
};
|
||||
|
||||
#endif // ELASUGGESTDELEGATE_H
|
||||
@@ -0,0 +1,46 @@
|
||||
#include "ElaSuggestModel.h"
|
||||
|
||||
ElaSuggestModel::ElaSuggestModel(QObject* parent)
|
||||
: QAbstractListModel{parent}
|
||||
{
|
||||
}
|
||||
|
||||
ElaSuggestModel::~ElaSuggestModel()
|
||||
{
|
||||
}
|
||||
|
||||
int ElaSuggestModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
return _suggestionVector.count();
|
||||
}
|
||||
|
||||
QVariant ElaSuggestModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void ElaSuggestModel::setSearchSuggestion(QVector<ElaSuggestion*> suggestionVector)
|
||||
{
|
||||
if (suggestionVector.count() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
beginResetModel();
|
||||
_suggestionVector = suggestionVector;
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void ElaSuggestModel::clearSearchNode()
|
||||
{
|
||||
this->_suggestionVector.clear();
|
||||
}
|
||||
|
||||
ElaSuggestion* ElaSuggestModel::getSearchSuggestion(int row)
|
||||
{
|
||||
if (row >= _suggestionVector.count())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return _suggestionVector[row];
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user