RibbonUI: Initial repo.

This commit is contained in:
Mentalflow 2023-08-19 22:46:52 +08:00
parent de8731342b
commit 41b84deaf4
Signed by: Mentalflow
GPG Key ID: 5AE68D4401A2EE71
72 changed files with 14277 additions and 1 deletions

73
.github/workflows/macos-shared.yml vendored Normal file
View File

@ -0,0 +1,73 @@
name: MacOS (Shared Library)
on:
push:
paths:
- '*.txt'
- 'example/**'
- 'lib_source/**'
- 'scripts/**'
- '.github/workflows/macos-shared.yml'
pull_request:
paths:
- '*.txt'
- 'example/**'
- 'lib_source/**'
- 'scripts/**'
- '.github/workflows/macos-shared.yml'
jobs:
build:
name: Build
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-12]
qt_ver: [6.2.4]
qt_arch: [clang_64]
env:
targetName: RibbonUI-APP
steps:
- name: Check out repository
uses: actions/checkout@v3
with:
submodules: recursive
- name: Install Qt
uses: jurplel/install-qt-action@v3
with:
version: ${{ matrix.qt_ver }}
arch: ${{ matrix.qt_arch }}
modules: 'qt5compat qtmultimedia qtshadertools qtimageformats'
- name: Set up Ninja
uses: seanmiddleditch/gha-setup-ninja@v3
with:
version: 1.10.2
- name: build macos
run: |
cmake --version
mkdir build
cd build
cmake -DCMAKE_MESSAGE_LOG_LEVEL=STATUS -DCMAKE_PREFIX_PATH=/Users/runner/work/RibbonUI/Qt/6.2.4/macos -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=Release -GNinja ..
cmake --build . --target all --config Release --parallel
- name: package
run: |
# 拷贝依赖
macdeployqt /Users/runner/work/RibbonUI/RibbonUI/build/example/${targetName}.app -qmldir=. -verbose=1 -dmg
- uses: actions/upload-artifact@v2
with:
name: ${{ env.targetName }}_${{ matrix.os }}_${{matrix.qt_ver}}.zip
path: /Users/runner/work/RibbonUI/RibbonUI/build/example/${{ env.targetName }}.app
- name: uploadRelease
if: startsWith(github.event.ref, 'refs/tags/')
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: /Users/runner/work/RibbonUI/RibbonUI/build/example/${{ env.targetName }}.dmg
asset_name: ${{ env.targetName }}_${{ github.ref_name }}_${{ matrix.os }}_Qt${{ matrix.qt_ver }}.dmg
tag: ${{ github.ref }}
overwrite: true

73
.github/workflows/macos-static.yml vendored Normal file
View File

@ -0,0 +1,73 @@
name: MacOS (Static Library)
on:
push:
paths:
- '*.txt'
- 'example/**'
- 'lib_source/**'
- 'scripts/**'
- '.github/workflows/macos-shared.yml'
pull_request:
paths:
- '*.txt'
- 'example/**'
- 'lib_source/**'
- 'scripts/**'
- '.github/workflows/macos-shared.yml'
jobs:
build:
name: Build
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-12]
qt_ver: [6.2.4]
qt_arch: [clang_64]
env:
targetName: RibbonUI-APP
steps:
- name: Check out repository
uses: actions/checkout@v3
with:
submodules: recursive
- name: Install Qt
uses: jurplel/install-qt-action@v3
with:
version: ${{ matrix.qt_ver }}
arch: ${{ matrix.qt_arch }}
modules: 'qt5compat qtmultimedia qtshadertools qtimageformats'
- name: Set up Ninja
uses: seanmiddleditch/gha-setup-ninja@v3
with:
version: 1.10.2
- name: build macos
run: |
cmake --version
mkdir build
cd build
cmake -DCMAKE_MESSAGE_LOG_LEVEL=STATUS -DCMAKE_PREFIX_PATH=/Users/runner/work/RibbonUI/Qt/6.2.4/macos -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=Release -DRIBBONUI_BUILD_STATIC_LIB=ON -GNinja ..
cmake --build . --target all --config Release --parallel
- name: package
run: |
# 拷贝依赖
macdeployqt /Users/runner/work/RibbonUI/RibbonUI/build/example/${targetName}.app -qmldir=. -verbose=1 -dmg
- uses: actions/upload-artifact@v2
with:
name: ${{ env.targetName }}_${{ matrix.os }}_${{matrix.qt_ver}}.zip
path: /Users/runner/work/RibbonUI/RibbonUI/build/example/${{ env.targetName }}.app
- name: uploadRelease
if: startsWith(github.event.ref, 'refs/tags/')
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: /Users/runner/work/RibbonUI/RibbonUI/build/example/${{ env.targetName }}.dmg
asset_name: ${{ env.targetName }}_${{ github.ref_name }}_${{ matrix.os }}_Qt${{ matrix.qt_ver }}.dmg
tag: ${{ github.ref }}
overwrite: true

89
.github/workflows/ubuntu-shared.yml vendored Normal file
View File

@ -0,0 +1,89 @@
name: Ubuntu (Shared Library)
on:
workflow_dispatch:
push:
paths:
- '*.txt'
- 'lib_source/**'
- 'example/**'
- 'scripts/**'
- '.github/workflows/ubuntu-shared.yml'
pull_request:
paths:
- '*.txt'
- 'lib_source/**'
- 'example/**'
- 'scripts/**'
- '.github/workflows/ubuntu-shared.yml'
jobs:
build:
name: Build
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-20.04]
qt_ver: [6.2.4]
qt_arch: [gcc_64]
env:
targetName: RibbonUI-APP
steps:
- name: Check out repository
uses: actions/checkout@v3
with:
submodules: recursive
- name: Install Qt
uses: jurplel/install-qt-action@v3
with:
version: ${{ matrix.qt_ver }}
arch: ${{ matrix.qt_arch }}
modules: 'qt5compat qtmultimedia qtshadertools qtimageformats'
- name: Set up Ninja
uses: seanmiddleditch/gha-setup-ninja@v3
with:
version: 1.10.2
- name: ubuntu install GL library
run: sudo apt-get install -y libxcb-cursor0 libgl1-mesa-dev libxcb1-dev libgtk-3-dev libxkbcommon-x11-dev libxcb-icccm4-dev libxcb-image0-dev libxcb-keysyms1-dev libxcb-randr0-dev libxcb-shape0-dev libxcb-xfixes0-dev libxcb-xinerama0-dev libxcb-sync-dev libxcb-render-util0-dev libxcb-shm0-dev
- name: build ubuntu
run: |
ninja --version
cmake --version
mkdir build
cd build
cmake -DCMAKE_MESSAGE_LOG_LEVEL=STATUS -DCMAKE_PREFIX_PATH=/home/runner/work/RibbonUI/Qt/6.2.4/gcc_64 -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_BUILD_TYPE=Release -GNinja ..
cmake --build . --target all --config Release --parallel
- name: install QT linux deploy
uses: miurahr/install-linuxdeploy-action@v1
with:
plugins: qt appimage
- name: Check if svg file exists
run: if [ ! -f "${targetName}.svg" ]; then echo "File not found, creating..."; touch ${targetName}.svg; fi
- name: package
run: |
# make sure Qt plugin finds QML sources so it can deploy the imported files
export QML_SOURCES_PATHS=./
# 拷贝依赖
linuxdeploy-x86_64.AppImage --plugin=qt --output=appimage --create-desktop-file --icon-file=${targetName}.svg --executable=/home/runner/work/RibbonUI/RibbonUI/build/example/${targetName} --appdir /home/runner/work/RibbonUI/RibbonUI/build/example/
mv ${{ env.targetName }}-*.AppImage ${{ env.targetName }}.AppImage
- uses: actions/upload-artifact@v2
with:
name: ${{ env.targetName }}_${{ matrix.os }}_${{matrix.qt_ver}}
path: ${{ env.targetName }}.AppImage
- name: uploadRelease
if: startsWith(github.event.ref, 'refs/tags/')
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ env.targetName }}.AppImage
asset_name: ${{ env.targetName }}_${{ github.ref_name }}_${{ matrix.os }}_Qt${{ matrix.qt_ver }}.AppImage
tag: ${{ github.ref }}
overwrite: true

89
.github/workflows/ubuntu-static.yml vendored Normal file
View File

@ -0,0 +1,89 @@
name: Ubuntu (Static Library)
on:
workflow_dispatch:
push:
paths:
- '*.txt'
- 'lib_source/**'
- 'example/**'
- 'scripts/**'
- '.github/workflows/ubuntu-shared.yml'
pull_request:
paths:
- '*.txt'
- 'lib_source/**'
- 'example/**'
- 'scripts/**'
- '.github/workflows/ubuntu-shared.yml'
jobs:
build:
name: Build
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-20.04]
qt_ver: [6.2.4]
qt_arch: [gcc_64]
env:
targetName: RibbonUI-APP
steps:
- name: Check out repository
uses: actions/checkout@v3
with:
submodules: recursive
- name: Install Qt
uses: jurplel/install-qt-action@v3
with:
version: ${{ matrix.qt_ver }}
arch: ${{ matrix.qt_arch }}
modules: 'qt5compat qtmultimedia qtshadertools qtimageformats'
- name: Set up Ninja
uses: seanmiddleditch/gha-setup-ninja@v3
with:
version: 1.10.2
- name: ubuntu install GL library
run: sudo apt-get install -y libxcb-cursor0 libgl1-mesa-dev libxcb1-dev libgtk-3-dev libxkbcommon-x11-dev libxcb-icccm4-dev libxcb-image0-dev libxcb-keysyms1-dev libxcb-randr0-dev libxcb-shape0-dev libxcb-xfixes0-dev libxcb-xinerama0-dev libxcb-sync-dev libxcb-render-util0-dev libxcb-shm0-dev
- name: build ubuntu
run: |
ninja --version
cmake --version
mkdir build
cd build
cmake -DCMAKE_MESSAGE_LOG_LEVEL=STATUS -DCMAKE_PREFIX_PATH=/home/runner/work/RibbonUI/Qt/6.2.4/gcc_64 -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_BUILD_TYPE=Release -DRIBBONUI_BUILD_STATIC_LIB=ON -GNinja ..
cmake --build . --target all --config Release --parallel
- name: install QT linux deploy
uses: miurahr/install-linuxdeploy-action@v1
with:
plugins: qt appimage
- name: Check if svg file exists
run: if [ ! -f "${targetName}.svg" ]; then echo "File not found, creating..."; touch ${targetName}.svg; fi
- name: package
run: |
# make sure Qt plugin finds QML sources so it can deploy the imported files
export QML_SOURCES_PATHS=./
# 拷贝依赖
linuxdeploy-x86_64.AppImage --plugin=qt --output=appimage --create-desktop-file --icon-file=${targetName}.svg --executable=/home/runner/work/RibbonUI/RibbonUI/build/example/${targetName} --appdir /home/runner/work/RibbonUI/RibbonUI/build/example/
mv ${{ env.targetName }}-*.AppImage ${{ env.targetName }}.AppImage
- uses: actions/upload-artifact@v2
with:
name: ${{ env.targetName }}_${{ matrix.os }}_${{matrix.qt_ver}}
path: ${{ env.targetName }}.AppImage
- name: uploadRelease
if: startsWith(github.event.ref, 'refs/tags/')
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ env.targetName }}.AppImage
asset_name: ${{ env.targetName }}_${{ github.ref_name }}_${{ matrix.os }}_Qt${{ matrix.qt_ver }}.AppImage
tag: ${{ github.ref }}
overwrite: true

View File

@ -0,0 +1,90 @@
name: Windows MinGW (Shared Library)
on:
push:
paths:
- '*.txt'
- 'lib_source/**'
- 'example/**'
- 'scripts/**'
- '.github/workflows/windows-mingw-shared.yml'
pull_request:
paths:
- '*.txt'
- 'example/**'
- 'lib_source/**'
- 'scripts/**'
- '.github/workflows/windows-mingw-shared.yml'
jobs:
build:
name: Build
runs-on: windows-2022
strategy:
matrix:
include:
- qt_arch: win64_mingw
qt_ver: 6.2.4
qt_tools: "tools_mingw,9.0.0-1-202203221220,qt.tools.win64_mingw900"
qt_tools_mingw_install: mingw900_64
env:
targetName: RibbonUI-APP.exe
fileName: RibbonUI-APP
steps:
- name: Check out repository
uses: actions/checkout@v3
with:
submodules: recursive
- name: Install Qt
uses: jurplel/install-qt-action@v3
with:
version: ${{ matrix.qt_ver }}
arch: ${{ matrix.qt_arch }}
modules: 'qt5compat qtmultimedia qtshadertools qtimageformats'
- name: Qt6 environment configuration
if: ${{ startsWith( matrix.qt_ver, 6 ) }}
shell: pwsh
run: |
Write-Output "${{ env.Qt6_DIR }}/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
Write-Output "${{ env.Qt6_DIR }}/../../Tools/${{ matrix.qt_tools_mingw_install }}/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- name: where is cmake & where is mingw32-make
shell: pwsh
run: |
Get-Command -Name 'cmake' | Format-List
Get-Command -Name 'mingw32-make' | Format-List
- name: mingw-build
id: build
shell: cmd
run: |
mkdir build
cd build
cmake -DCMAKE_MESSAGE_LOG_LEVEL=STATUS -DCMAKE_PREFIX_PATH=D:\a\RibbonUI\Qt\6.2.4\mingw_64 -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_BUILD_TYPE=Release -GNinja ..
cmake --build . --target all --config Release --parallel
- name: package
id: package
env:
archiveName: ${{ env.fileName }}-${{ matrix.qt_arch }}-${{ matrix.qt_ver }}
shell: pwsh
run: |
& scripts\windows-mingw-publish.ps1 ${env:archiveName} ${env:targetName}
$name = ${env:archiveName}
echo "::set-output name=packageName::$name"
- uses: actions/upload-artifact@v2
with:
name: ${{ steps.package.outputs.packageName }}
path: ${{ steps.package.outputs.packageName }}
- name: uploadRelease
if: startsWith(github.event.ref, 'refs/tags/')
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ steps.package.outputs.packageName }}.zip
asset_name: ${{ env.fileName }}_${{ github.ref_name }}_${{ matrix.qt_arch }}_Qt${{ matrix.qt_ver }}.zip
tag: ${{ github.ref }}
overwrite: true

View File

@ -0,0 +1,90 @@
name: Windows MinGW (Static Library)
on:
push:
paths:
- '*.txt'
- 'lib_source/**'
- 'example/**'
- 'scripts/**'
- '.github/workflows/windows-mingw-shared.yml'
pull_request:
paths:
- '*.txt'
- 'example/**'
- 'lib_source/**'
- 'scripts/**'
- '.github/workflows/windows-mingw-shared.yml'
jobs:
build:
name: Build
runs-on: windows-2022
strategy:
matrix:
include:
- qt_arch: win64_mingw
qt_ver: 6.2.4
qt_tools: "tools_mingw,9.0.0-1-202203221220,qt.tools.win64_mingw900"
qt_tools_mingw_install: mingw900_64
env:
targetName: RibbonUI-APP.exe
fileName: RibbonUI-APP
steps:
- name: Check out repository
uses: actions/checkout@v3
with:
submodules: recursive
- name: Install Qt
uses: jurplel/install-qt-action@v3
with:
version: ${{ matrix.qt_ver }}
arch: ${{ matrix.qt_arch }}
modules: 'qt5compat qtmultimedia qtshadertools qtimageformats'
- name: Qt6 environment configuration
if: ${{ startsWith( matrix.qt_ver, 6 ) }}
shell: pwsh
run: |
Write-Output "${{ env.Qt6_DIR }}/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
Write-Output "${{ env.Qt6_DIR }}/../../Tools/${{ matrix.qt_tools_mingw_install }}/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- name: where is cmake & where is mingw32-make
shell: pwsh
run: |
Get-Command -Name 'cmake' | Format-List
Get-Command -Name 'mingw32-make' | Format-List
- name: mingw-build
id: build
shell: cmd
run: |
mkdir build
cd build
cmake -DCMAKE_MESSAGE_LOG_LEVEL=STATUS -DCMAKE_PREFIX_PATH=D:\a\RibbonUI\Qt\6.2.4\mingw_64 -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_BUILD_TYPE=Release -DRIBBONUI_BUILD_STATIC_LIB=ON -GNinja ..
cmake --build . --target all --config Release --parallel
- name: package
id: package
env:
archiveName: ${{ env.fileName }}-${{ matrix.qt_arch }}-${{ matrix.qt_ver }}
shell: pwsh
run: |
& scripts\windows-mingw-publish.ps1 ${env:archiveName} ${env:targetName}
$name = ${env:archiveName}
echo "::set-output name=packageName::$name"
- uses: actions/upload-artifact@v2
with:
name: ${{ steps.package.outputs.packageName }}
path: ${{ steps.package.outputs.packageName }}
- name: uploadRelease
if: startsWith(github.event.ref, 'refs/tags/')
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ steps.package.outputs.packageName }}.zip
asset_name: ${{ env.fileName }}_${{ github.ref_name }}_${{ matrix.qt_arch }}_Qt${{ matrix.qt_ver }}.zip
tag: ${{ github.ref }}
overwrite: true

View File

@ -0,0 +1,85 @@
name: Windows MSVC (Shared Library)
on:
push:
paths:
- '*.txt'
- 'lib_source/**'
- 'example/**'
- 'scripts/**'
- '.github/workflows/windows-msvc-shared.yml'
pull_request:
paths:
- '*.txt'
- 'example/**'
- 'lib_source/**'
- 'scripts/**'
- '.github/workflows/windows-msvc-shared.yml'
jobs:
build:
name: Build
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [windows-2019]
include:
- qt_ver: 6.2.4
qt_arch: win64_msvc2019_64
msvc_arch: x64
qt_arch_install: msvc2019_64
env:
targetName: RibbonUI-APP.exe
fileName: RibbonUI-APP
steps:
- name: Check out repository
uses: actions/checkout@v3
with:
submodules: recursive
- name: Install Qt
uses: jurplel/install-qt-action@v3
with:
version: ${{ matrix.qt_ver }}
arch: ${{ matrix.qt_arch }}
modules: 'qt5compat qtmultimedia qtshadertools qtimageformats'
- name: msvc-build
id: build
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.msvc_arch }}
mkdir build
cd build
cmake -DCMAKE_MESSAGE_LOG_LEVEL=STATUS -DCMAKE_PREFIX_PATH=D:\a\RibbonUI\Qt\6.2.4\msvc2019_64 -DCMAKE_C_COMPILER=cl -DCMAKE_CXX_COMPILER=cl -DCMAKE_BUILD_TYPE=Release -GNinja ..
cmake --build . --target all --config Release --parallel
echo winSdkDir=%WindowsSdkDir% >> %GITHUB_ENV%
echo winSdkVer=%WindowsSdkVersion% >> %GITHUB_ENV%
echo vcToolsInstallDir=%VCToolsInstallDir% >> %GITHUB_ENV%
echo vcToolsRedistDir=%VCToolsRedistDir% >> %GITHUB_ENV%
- name: package
id: package
env:
archiveName: ${{ env.fileName }}-${{ matrix.qt_arch }}-${{ matrix.qt_ver }}
msvcArch: ${{ matrix.msvc_arch }}
shell: pwsh
run: |
& scripts\windows-publish.ps1 ${env:archiveName} ${env:targetName}
# 记录packageName给后续step
$name = ${env:archiveName}
echo "::set-output name=packageName::$name"
- uses: actions/upload-artifact@v2
with:
name: ${{ steps.package.outputs.packageName }}
path: ${{ steps.package.outputs.packageName }}
- name: uploadRelease
if: startsWith(github.event.ref, 'refs/tags/')
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ steps.package.outputs.packageName }}.zip
asset_name: ${{ env.fileName }}_${{ github.ref_name }}_${{ matrix.qt_arch }}_Qt${{ matrix.qt_ver }}.zip
tag: ${{ github.ref }}
overwrite: true

View File

@ -0,0 +1,85 @@
name: Windows MSVC (Static Library)
on:
push:
paths:
- '*.txt'
- 'lib_source/**'
- 'example/**'
- 'scripts/**'
- '.github/workflows/windows-msvc-shared.yml'
pull_request:
paths:
- '*.txt'
- 'example/**'
- 'lib_source/**'
- 'scripts/**'
- '.github/workflows/windows-msvc-shared.yml'
jobs:
build:
name: Build
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [windows-2019]
include:
- qt_ver: 6.2.4
qt_arch: win64_msvc2019_64
msvc_arch: x64
qt_arch_install: msvc2019_64
env:
targetName: RibbonUI-APP.exe
fileName: RibbonUI-APP
steps:
- name: Check out repository
uses: actions/checkout@v3
with:
submodules: recursive
- name: Install Qt
uses: jurplel/install-qt-action@v3
with:
version: ${{ matrix.qt_ver }}
arch: ${{ matrix.qt_arch }}
modules: 'qt5compat qtmultimedia qtshadertools qtimageformats'
- name: msvc-build
id: build
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.msvc_arch }}
mkdir build
cd build
cmake -DCMAKE_MESSAGE_LOG_LEVEL=STATUS -DCMAKE_PREFIX_PATH=D:\a\RibbonUI\Qt\6.2.4\msvc2019_64 -DCMAKE_C_COMPILER=cl -DCMAKE_CXX_COMPILER=cl -DCMAKE_BUILD_TYPE=Release -DRIBBONUI_BUILD_STATIC_LIB=ON -GNinja ..
cmake --build . --target all --config Release --parallel
echo winSdkDir=%WindowsSdkDir% >> %GITHUB_ENV%
echo winSdkVer=%WindowsSdkVersion% >> %GITHUB_ENV%
echo vcToolsInstallDir=%VCToolsInstallDir% >> %GITHUB_ENV%
echo vcToolsRedistDir=%VCToolsRedistDir% >> %GITHUB_ENV%
- name: package
id: package
env:
archiveName: ${{ env.fileName }}-${{ matrix.qt_arch }}-${{ matrix.qt_ver }}
msvcArch: ${{ matrix.msvc_arch }}
shell: pwsh
run: |
& scripts\windows-publish.ps1 ${env:archiveName} ${env:targetName}
# 记录packageName给后续step
$name = ${env:archiveName}
echo "::set-output name=packageName::$name"
- uses: actions/upload-artifact@v2
with:
name: ${{ steps.package.outputs.packageName }}
path: ${{ steps.package.outputs.packageName }}
- name: uploadRelease
if: startsWith(github.event.ref, 'refs/tags/')
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ steps.package.outputs.packageName }}.zip
asset_name: ${{ env.fileName }}_${{ github.ref_name }}_${{ matrix.qt_arch }}_Qt${{ matrix.qt_ver }}.zip
tag: ${{ github.ref }}
overwrite: true

31
.gitignore vendored
View File

@ -7,7 +7,7 @@
*.lai
*.so
*.so.*
*.dll
#*.dll
*.dylib
# Qt-es
@ -52,3 +52,32 @@ compile_commands.json
*creator.user*
*_qmlcache.qrc
# ---> macOS
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "3rdparty/framelesshelper"]
path = 3rdparty/framelesshelper
url = git@github.com:wangwenx190/framelesshelper.git

1
3rdparty/framelesshelper vendored Submodule

@ -0,0 +1 @@
Subproject commit d9ce1c4302ceabfd8748a7658ae9a2d918575303

BIN
3rdparty/mingw/libcrypto-1_1-x64.dll vendored Normal file

Binary file not shown.

BIN
3rdparty/mingw/libgcc_s_seh-1.dll vendored Normal file

Binary file not shown.

BIN
3rdparty/mingw/libssl-1_1-x64.dll vendored Normal file

Binary file not shown.

BIN
3rdparty/mingw/libstdc++-6.dll vendored Normal file

Binary file not shown.

BIN
3rdparty/mingw/libwinpthread-1.dll vendored Normal file

Binary file not shown.

BIN
3rdparty/msvc/libcrypto-1_1-x64.dll vendored Normal file

Binary file not shown.

BIN
3rdparty/msvc/libssl-1_1-x64.dll vendored Normal file

Binary file not shown.

BIN
3rdparty/msvc/vcruntime140_1.dll vendored Normal file

Binary file not shown.

27
CMakeLists.txt Normal file
View File

@ -0,0 +1,27 @@
cmake_minimum_required(VERSION 3.16)
project(RibbonUI_Project VERSION 1.0 LANGUAGES CXX)
option(RIBBONUI_BUILD_EXAMPLES "Build RibbonUI APP." ON)
option(RIBBONUI_BUILD_FRAMELESSHEPLER "Build FramelessHelper." ON)
option(RIBBONUI_BUILD_STATIC_LIB "Build RibbonUI static library." OFF)
if (RIBBONUI_BUILD_EXAMPLES)
add_subdirectory(example)
endif()
if (RIBBONUI_BUILD_FRAMELESSHEPLER)
set(FRAMELESSHELPER_BUILD_STATIC ON)
set(FRAMELESSHELPER_NO_SUMMARY OFF)
set(FRAMELESSHELPER_NO_DEBUG_OUTPUT ON)
set(FRAMELESSHELPER_BUILD_WIDGETS OFF)
add_subdirectory(3rdparty/framelesshelper)
endif()
add_subdirectory(lib_source)
message("---------------------------- RibbonUI ----------------------------")
message("Build RibbonUI APP: ${RIBBONUI_BUILD_EXAMPLES}")
message("Build FramelessHelper: ${RIBBONUI_BUILD_FRAMELESSHEPLER}")
message("Build RibbonUI static library: ${RIBBONUI_BUILD_STATIC_LIB}")
message("------------------------------------------------------------------")

93
example/CMakeLists.txt Normal file
View File

@ -0,0 +1,93 @@
cmake_minimum_required(VERSION 3.21)
project(RibbonUIAPP VERSION 1.0.0.0 LANGUAGES CXX)
set(CMAKE_AUTOMOC ON)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if(APPLE)
set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64" CACHE STRING "" FORCE)
endif()
set(PROJECT_COMPANY "Mentalflow's Lab")
set(PROJECT_COPYRIGHT "Copyright (c) 2023 Mentalflow's Lab. All rights reserved.")
set(PROJECT_DOMAIN "dev.ourdocs.cn.ribbonuiapp")
set(PROJECT_BUNDLE_NAME RibbonUI-APP)
add_definitions(-DRIBBONUIAPP_VERSION=1,0,0,0)
find_package(Qt6 COMPONENTS Quick REQUIRED)
set(sources_files example.cpp)
if (WIN32)
set(app_icon_resource_windows "${CMAKE_CURRENT_SOURCE_DIR}/resources/icon.rc")
qt_add_executable(${PROJECT_NAME}
${sources_files}
"${CMAKE_CURRENT_SOURCE_DIR}/resources/icon.rc"
)
file(TO_CMAKE_PATH "/" PATH_SEPARATOR)
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
set(DLLPATH ${CMAKE_SOURCE_DIR}/3rdparty/msvc/*.dll)
else()
set(DLLPATH ${CMAKE_SOURCE_DIR}/3rdparty/mingw/*.dll)
endif()
string(REPLACE "/" ${PATH_SEPARATOR} DLLPATH "${DLLPATH}")
file(GLOB DLL_FILES ${DLLPATH})
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${DLL_FILES}
"${CMAKE_BINARY_DIR}${PATH_SEPARATOR}example"
)
elseif(APPLE)
set(MACOSX_BUNDLE_ICON_FILE AppIcon)
set(App_ICON "${CMAKE_CURRENT_SOURCE_DIR}/resources/imgs/AppIcon.icns")
set_source_files_properties(${App_ICON} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
qt_add_executable(${PROJECT_NAME}
${sources_files}
${App_ICON}
)
else ()
qt_add_executable(${PROJECT_NAME}
${sources_files}
)
endif ()
qt_add_qml_module(${PROJECT_NAME}
URI ${PROJECT_NAME}
VERSION 1.0
QML_FILES example.qml components/RibbonWindow.qml
RESOURCES resources/imgs/heart.png resources/imgs/search.png resources/icon.rc
)
set_target_properties(${PROJECT_NAME} PROPERTIES
MACOSX_BUNDLE_GUI_IDENTIFIER ${PROJECT_DOMAIN}
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
MACOSX_BUNDLE_BUNDLE_NAME ${PROJECT_BUNDLE_NAME}
MACOSX_BUNDLE_COPYRIGHT ${PROJECT_COPYRIGHT}
MACOSX_BUNDLE TRUE
WIN32_EXECUTABLE TRUE
OUTPUT_NAME ${PROJECT_BUNDLE_NAME}
)
if(RIBBONUI_BUILD_STATIC_LIB)
add_definitions(-DRIBBONUI_BUILD_STATIC_LIB)
target_link_libraries(${PROJECT_NAME} PRIVATE
Qt::Quick
RibbonUIplugin
FramelessHelper::Core
FramelessHelper::Quick
)
else()
target_link_libraries(${PROJECT_NAME} PRIVATE
Qt::Quick
RibbonUI
FramelessHelper::Core
FramelessHelper::Quick
)
endif()
target_compile_definitions(${PROJECT_NAME} PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

View File

@ -0,0 +1,76 @@
import QtQuick
import RibbonUI
import org.wangwenx190.FramelessHelper
Window {
id:window
default property alias content: container.data
property alias title_bar: titleBar
property alias popup: pop
property bool comfirmed_quit: false
visible: false
color: {
if (FramelessHelper.blurBehindWindowEnabled) {
return "transparent";
}
if (FramelessUtils.systemTheme === FramelessHelperConstants.Dark) {
return FramelessUtils.defaultSystemDarkColor;
}
return FramelessUtils.defaultSystemLightColor;
}
FramelessHelper.onReady: {
FramelessHelper.titleBarItem = titleBar;
FramelessHelper.moveWindowToDesktopCenter();
window.visible = true;
}
RibbonTitleBar {
id: titleBar
}
Item{
id:container
anchors{
top: titleBar.bottom
left: parent.left
right: parent.right
bottom: parent.bottom
}
clip: true
}
Connections{
target: RibbonTheme
function onTheme_modeChanged() {
if (RibbonTheme.dark_mode)
FramelessUtils.systemTheme = FramelessHelperConstants.Dark
else
FramelessUtils.systemTheme = FramelessHelperConstants.Light
}
}
Rectangle{
z:99
anchors.fill: parent
color: !RibbonTheme.dark_mode ? Qt.rgba(255,255,255,0.3) : Qt.rgba(0,0,0,0.3)
visible: !Window.active
}
RibbonPopup{
id: pop
}
RibbonPopupDialog{
id: dialog
positiveText: qsTr("Quit")
neutralText: qsTr("Minimize")
negativeText: qsTr("Cancel")
message: "Do you want to quit the APP?"
title: "Please note"
buttonFlags: RibbonPopupDialogType.NegativeButton | RibbonPopupDialogType.PositiveButton | RibbonPopupDialogType.NeutralButton
onNeutralClicked: window.visibility = Window.Minimized
onPositiveClicked: {
comfirmed_quit = true
Qt.quit()
}
}
onClosing:function(event){
event.accepted = comfirmed_quit
if (!comfirmed_quit)
dialog.open()
}
}

42
example/example.cpp Normal file
View File

@ -0,0 +1,42 @@
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QtQml/qqmlextensionplugin.h>
#include <FramelessHelper/Quick/framelessquickmodule.h>
#include <FramelessHelper/Core/private/framelessconfig_p.h>
FRAMELESSHELPER_USE_NAMESPACE
#ifdef RIBBONUI_BUILD_STATIC_LIB
Q_IMPORT_QML_PLUGIN(RibbonUIPlugin)
#endif
int main(int argc, char *argv[])
{
qputenv("QT_QUICK_CONTROLS_STYLE","Basic");
FramelessHelper::Quick::initialize();
QGuiApplication app(argc, argv);
#ifdef Q_OS_WIN
FramelessConfig::instance()->set(Global::Option::ForceHideWindowFrameBorder);
#endif
FramelessConfig::instance()->set(Global::Option::DisableLazyInitializationForMicaMaterial);
FramelessConfig::instance()->set(Global::Option::CenterWindowBeforeShow);
FramelessConfig::instance()->set(Global::Option::ForceNonNativeBackgroundBlur);
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
#ifdef Q_OS_MACOS
FramelessConfig::instance()->set(Global::Option::ForceNonNativeBackgroundBlur,false);
#endif
QQmlApplicationEngine engine;
FramelessHelper::Quick::registerTypes(&engine);
#ifdef RIBBONUI_BUILD_STATIC_LIB
engine.addImportPath("qrc:/");
#endif
const QUrl url(u"qrc:/RibbonUIAPP/example.qml"_qs);
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}

726
example/example.qml Normal file
View File

@ -0,0 +1,726 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import QtQuick.Controls.Material
import QtQuick.Window
import RibbonUI
import org.wangwenx190.FramelessHelper
import "components"
RibbonWindow {
id:root
width: 1200
height: 800
title: qsTr("RibbonUI APP")
property bool modern_style: RibbonTheme.modern_style
RibbonTabBar {
id: tab_bar
modern_style: root.modern_style
right_tool_bar: RowLayout{
spacing: 10
RibbonButton{
text:"Test Button 1"
icon_source: RibbonIcons.Alert
checkable: true
}
RibbonButton{
text:"Test Button 2"
}
}
RibbonTabPage{
id: basic_page
title: qsTr("Basic")
RibbonTabGroup{
width: slider_layout.width + 20
text: qsTr("Slider")
RowLayout{
id: slider_layout
anchors.centerIn: parent
height: parent.height
spacing: 0
RibbonSlider{
Layout.alignment: Qt.AlignVCenter
slide_width: 40
horizontal: false
value: 20
}
RibbonSlider{
Layout.alignment: Qt.AlignVCenter
slide_width: 40
horizontal: false
show_button: false
value: 40
}
ColumnLayout{
spacing: 0
Layout.alignment: Qt.AlignVCenter
RibbonSlider{
Layout.alignment: Qt.AlignHCenter
slide_width: 40
value: 60
}
RibbonSlider{
Layout.alignment: Qt.AlignHCenter
slide_width: 40
show_button: false
value: 80
}
}
}
}
RibbonTabGroup{
width: switch_layout.width + 30
text: qsTr("Switch Button")
RowLayout{
id: switch_layout
anchors.centerIn: parent
height: parent.height
spacing: 0
ColumnLayout{
spacing: 5
RibbonSwitchButton{
text: "Button"
grabber_checked_color: "red"
checked: true
}
RibbonSwitchButton{
text: "Button"
text_on_left: true
grabber_checked_color: "orange"
checked: true
}
RibbonSwitchButton{
grabber_checked_color: "blue"
}
}
ColumnLayout{
spacing: 5
RibbonSwitchButton{
text: "Button"
show_grabber_text: false
grabber_checked_color: "green"
}
RibbonSwitchButton{
text: "Button"
show_grabber_text: false
text_on_left: true
grabber_checked_color: "indigo"
checked: true
}
RibbonSwitchButton{
show_grabber_text: false
grabber_checked_color: "yellow"
checked: true
}
}
}
}
RibbonTabGroup{
width: checkbox_layout.width + 30
text: qsTr("CheckBox")
RowLayout{
id: checkbox_layout
anchors.centerIn: parent
height: parent.height
spacing: 0
ColumnLayout{
spacing: 10
RibbonCheckBox{
text: "CheckBox"
icon_filled_bg_color: "blue"
checked: true
}
RibbonCheckBox{
text: "CheckBox"
text_on_left: true
icon_filled_bg_color: "red"
}
RowLayout{
spacing: 30
RibbonCheckBox{
icon_filled_bg_color:"orange"
tip_text: "CheckBox"
show_tooltip: true
checked: true
}
RibbonCheckBox{
icon_filled_bg_color:"purple"
}
}
}
}
}
RibbonTabGroup{
width: button_layout.width + 30
text: qsTr("Button")
RowLayout{
id: button_layout
anchors.centerIn: parent
height: parent.height
spacing: 1
ColumnLayout{
spacing: 10
RibbonButton{
text:"Button"
icon_source: RibbonIcons.Accessibility
checkable: true
}
RibbonButton{
text:"Button"
}
RibbonButton{
text:"Button"
show_tooltip: false
}
}
ColumnLayout{
spacing: 10
RibbonButton{
text:"Button"
show_bg:false
icon_source: RibbonIcons.Beaker
checkable: true
}
RibbonButton{
text:"Button"
show_bg:false
}
RibbonButton{
text:"Button"
show_bg:false
show_tooltip: false
}
}
ColumnLayout{
spacing: 10
RibbonButton{
show_bg:false
icon_source: RibbonIcons.Badge
icon_source_filled: RibbonIcons_Filled.Badge
checkable: true
tip_text: "Button"
}
RibbonButton{
show_bg:false
icon_source: RibbonIcons.Clock
icon_source_filled: RibbonIcons_Filled.Clock
tip_text: "Button"
}
RibbonButton{
show_bg:false
icon_source: RibbonIcons.Board
icon_source_filled: RibbonIcons_Filled.Board
checkable: true
tip_text: "Button"
show_tooltip: false
}
}
}
}
RibbonTabGroup{
width: pushbutton_layout.width + 30
text: qsTr("Push Button")
RowLayout{
id: pushbutton_layout
anchors.centerIn: parent
height: parent.height
spacing: 10
RibbonPushButton{
text: qsTr("No Menu")
icon_source: RibbonIcons.AttachText
}
RibbonPushButton{
text: qsTr("Menu")
icon_source: RibbonIcons.MeetNow
Action{
text: "Test Item 1"
}
RibbonMenuSeparator{}
Action{
text: "Test Item 2"
enabled: false
}
}
RibbonPushButton{
text: qsTr("No Menu")
icon_source: "qrc:/RibbonUIAPP/resources/imgs/heart.png"
icon_size: height-5
}
RibbonPushButton{
text: qsTr("Menu")
icon_source: "qrc:/RibbonUIAPP/resources/imgs/search.png"
Action{
text: "Test Item 3"
}
RibbonMenuSeparator{}
Action{
text: "Test Item 4"
enabled: false
}
}
}
}
}
RibbonTabPage{
title: qsTr("Input")
RibbonTabGroup{
width: lineedit_layout.width + 30
text: qsTr("Line Edit")
RowLayout{
id: lineedit_layout
anchors.centerIn: parent
height: parent.height
spacing: 10
ColumnLayout{
spacing: 10
Layout.fillHeight: true
RibbonLineEdit{
}
RibbonLineEdit{
show_clear_btn:false
}
}
ColumnLayout{
spacing: 10
Layout.fillHeight: true
RibbonLineEdit{
icon_source:RibbonIcons.Search
}
RibbonLineEdit{
icon_source:RibbonIcons.Keyboard
show_clear_btn:false
}
}
}
}
RibbonTabGroup{
width: lineedit_layout.width + 30
text: qsTr("Text Edit")
RowLayout{
id: textedit_layout
anchors.centerIn: parent
height: parent.height
spacing: 10
ColumnLayout{
spacing: 30
Layout.fillHeight: true
RibbonTextEdit{
max_height: 50
}
RibbonTextEdit{
max_height: 30
show_clear_btn:false
}
}
ColumnLayout{
spacing: 30
Layout.fillHeight: true
RibbonTextEdit{
max_height: 50
icon_source:RibbonIcons.Search
}
RibbonTextEdit{
max_height: 30
icon_source:RibbonIcons.Keyboard
show_clear_btn:false
}
}
}
}
RibbonTabGroup{
width: combobox_layout.width + 30
text: qsTr("Combo Box")
RowLayout{
id: combobox_layout
anchors.centerIn: parent
height: parent.height
spacing: 10
ColumnLayout{
spacing: 10
Layout.fillHeight: true
RibbonComboBox{
model: ListModel {
ListElement { text: "Test Item 1" }
ListElement { text: "Test Item 2" }
ListElement { text: "Test Item 3" }
}
}
RibbonComboBox{
editable: true
model: ListModel {
id: model
ListElement { text: "Test Item 1" }
ListElement { text: "Test Item 2" }
ListElement { text: "Test Item 3" }
}
onAccepted: {
if (find(editText) === -1 && editText)
model.append({text: editText})
}
}
}
ColumnLayout{
spacing: 10
Layout.fillHeight: true
RibbonComboBox{
model: ListModel {
ListElement { text: "Test Item 1" }
ListElement { text: "Test Item 2" }
ListElement { text: "Test Item 3" }
}
icon_source: RibbonIcons.Beaker
}
RibbonComboBox{
editable: true
model: ListModel {
id: model_1
ListElement { text: "Test Item 1" }
ListElement { text: "Test Item 2" }
ListElement { text: "Test Item 3" }
}
icon_source: RibbonIcons.Calendar
onAccepted: {
if (find(editText) === -1 && editText)
model_1.append({text: editText})
}
}
}
}
}
RibbonTabGroup{
width: spinbox_layout.width + 30
text: qsTr("Spin Box")
show_border: false
RowLayout{
id: spinbox_layout
anchors.centerIn: parent
height: parent.height
spacing: 10
ColumnLayout{
spacing: 10
Layout.fillHeight: true
RibbonSpinBox{
width: 100
}
RibbonSpinBox{
id: spinbox
width: 80
icon_source: RibbonIcons.DataPie
validator: DoubleValidator {
bottom: Math.min(spinbox.from, spinbox.to)
top: Math.max(spinbox.from, spinbox.to)
}
textFromValue: function(value, locale) {
return Number(value / 100).toLocaleString(locale, 'f', 2)
}
valueFromText: function(text, locale) {
return Number.fromLocaleString(locale, text) * 100
}
}
}
}
}
}
RibbonTabPage{
title: qsTr("Others")
RibbonTabGroup{
width: text_layout.width + 30
text: qsTr("Text")
RowLayout{
id: text_layout
anchors.centerIn: parent
height: parent.height
spacing: 10
ColumnLayout{
spacing: 10
Layout.fillHeight: true
RibbonText{
font.pixelSize: 13
text: "Test Text"
}
RibbonText{
font.pixelSize: 13
text: "Test Text (Read Only)"
view_only: true
}
}
}
}
RibbonTabGroup{
width: menu_layout.width + 30
text: qsTr("Menu")
RowLayout{
id: menu_layout
anchors.centerIn: parent
height: parent.height
spacing: 10
RibbonButton{
text: qsTr("Open Menu")
icon_source: RibbonIcons.Open
onClicked: menu.popup()
}
}
}
RibbonTabGroup{
width: popup_layout.width + 30
text: qsTr("Popup")
RowLayout{
id: popup_layout
anchors.centerIn: parent
height: parent.height
spacing: 10
ColumnLayout{
spacing: 10
Layout.fillHeight: true
RibbonButton{
text: qsTr("Open Popup")
icon_source: RibbonIcons.Open
onClicked: popup.open()
}
RibbonButton{
text: qsTr("Open Popup Dialog (Double Choices)")
icon_source: RibbonIcons.Open
onClicked: {
dialog.buttonFlags = RibbonPopupDialogType.NegativeButton | RibbonPopupDialogType.PositiveButton
dialog.open()
}
}
RibbonButton{
text: qsTr("Open Popup Dialog (Triple Choices)")
icon_source: RibbonIcons.Open
onClicked: {
dialog.buttonFlags = RibbonPopupDialogType.NegativeButton | RibbonPopupDialogType.PositiveButton | RibbonPopupDialogType.NeutralButton
dialog.open()
}
}
}
RibbonPopup{
id: popup
height: 200
width: height
}
RibbonPopupDialog{
id: dialog
}
}
}
RibbonTabGroup{
width: theme_layout.width + 30
text: qsTr("Theme")
RowLayout{
id: theme_layout
anchors.centerIn: parent
height: parent.height
spacing: 10
RibbonComboBox{
model: ListModel {
id: model_theme
ListElement { text: "Light" }
ListElement { text: "Dark" }
ListElement { text: "System" }
}
icon_source: RibbonIcons.DarkTheme
Component.onCompleted: {
let str = (RibbonTheme.theme_mode === RibbonThemeType.System ? "System" : RibbonTheme.theme_mode === RibbonThemeType.Light ? "Light" : "Dark")
currentIndex = find(str)
}
onActivated: {
if (currentText === "System")
RibbonTheme.theme_mode = RibbonThemeType.System
else if (currentText === "Light")
RibbonTheme.theme_mode = RibbonThemeType.Light
else
RibbonTheme.theme_mode = RibbonThemeType.Dark
}
}
}
}
}
}
RibbonPaperView{
id: view
anchors{
top: parent.top
bottom: parent.bottom
}
top_padding: tab_bar.height
bottom_padding: bottom_bar.height
page_width: (page_slider.value / 100.0) * width
spacing: 0
ColumnLayout{
Layout.alignment: Qt.AlignCenter
Layout.topMargin: 30
spacing: 20
RibbonText{
Layout.alignment: Qt.AlignHCenter
Layout.topMargin: 50
text: "RibbonUI"
font{
pixelSize: 50
bold: true
italic: true
}
}
Image {
source: "qrc:/RibbonUI/resources/imgs/icon.png"
fillMode:Image.PreserveAspectFit
Layout.preferredHeight: 300
Layout.preferredWidth: height
Layout.alignment: Qt.AlignHCenter
layer.enabled: true
layer.effect: RibbonShadow{}
}
RibbonText{
Layout.alignment: Qt.AlignHCenter
text: "A Lightweight, minimalist and \nelegant Qt component library."
font{
pixelSize: 30
bold: true
italic: true
}
}
RibbonText{
Layout.alignment: Qt.AlignHCenter
text: "Author: mentalfl0w"
font{
pixelSize: 25
bold: true
italic: true
}
}
RibbonText{
Layout.alignment: Qt.AlignHCenter
text: "Email: mentalflow@ourdocs.cn"
font{
pixelSize: 25
bold: true
italic: true
}
}
RibbonText{
Layout.alignment: Qt.AlignHCenter
text: `Current Version: V${RibbonUI.version}`
font{
pixelSize: 20
bold: true
italic: true
}
}
}
}
RibbonBottomBar{
id: bottom_bar
anchors{
left: parent.left
right: parent.right
bottom: parent.bottom
}
right_content: RowLayout{
clip: true
spacing:1
Layout.preferredHeight: parent.height
layoutDirection: Qt.RightToLeft
RibbonSlider{
id: page_slider
slide_width: 80
show_filled_color: false
value: 70
}
RibbonButton{
text:"Test Button 3"
show_bg:false
adapt_height:true
icon_source: RibbonIcons.Airplane
}
RibbonButton{
text:"Test Button 4"
show_bg:false
adapt_height:true
}
}
RibbonButton{
text:"Test Button 5"
show_bg:false
adapt_height:true
icon_source: RibbonIcons.AccessTime
checkable: true
}
RibbonButton{
text:"Test Button 6"
show_bg:false
adapt_height:true
}
RibbonButton{
show_bg:false
adapt_height:true
icon_source: RibbonIcons.AppStore
checkable: true
tip_text: "Test Button 7"
}
}
title_bar.right_content:RowLayout{
spacing: 1
layoutDirection: Qt.RightToLeft
RibbonButton{
show_bg:false
icon_source: RibbonIcons.CalendarStar
icon_source_filled: RibbonIcons_Filled.CalendarStar
checkable: true
tip_text: "Test Button 11"
hover_color: Qt.rgba(0,0,0, 0.3)
pressed_color: Qt.rgba(0,0,0, 0.4)
text_color: title_bar.title_text_color
text_color_reverse: false
}
}
title_bar.left_content:RowLayout{
spacing: 1
RibbonButton{
show_bg:false
icon_source: RibbonIcons.ChevronDown
tip_text: "Test Button 8"
hover_color: Qt.rgba(0,0,0, 0.3)
pressed_color: Qt.rgba(0,0,0, 0.4)
text_color: title_bar.title_text_color
text_color_reverse: false
RibbonMenu{
id:menu
width: 200
Action{
text: "Test Long Text Test Long Text Test Long Text"
checkable: true
}
RibbonMenuSeparator{}
Action{
text: "Test Item 1"
enabled: false
}
RibbonMenu{
width: parent.width
title: "Sub Menu"
Action { text: qsTr("Test Item 2") }
Action { text: qsTr("Test Item 3") }
}
}
onClicked:menu.popup()
}
RibbonButton{
show_bg:false
icon_source: RibbonIcons.Apps
icon_source_filled: RibbonIcons_Filled.Apps
checkable: true
tip_text: "Test Button 9"
hover_color: Qt.rgba(0,0,0, 0.3)
pressed_color: Qt.rgba(0,0,0, 0.4)
text_color: title_bar.title_text_color
text_color_reverse: false
enabled: false
}
}
}

42
example/resources/icon.rc Normal file
View File

@ -0,0 +1,42 @@
#include <windows.h>
IDI_ICON1 ICON "imgs/icon.ico"
#define STR(x) #x
#define VER_JOIN(a,b,c,d) STR(a.b.c.d)
#define VER_JOIN_(x) VER_JOIN x
#define VER_STR VER_JOIN_((RIBBONUIAPP_VERSION))
VS_VERSION_INFO VERSIONINFO
FILEVERSION RIBBONUIAPP_VERSION
PRODUCTVERSION RIBBONUIAPP_VERSION
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS VS_FF_DEBUG
#else
FILEFLAGS 0x0L
#endif
FILEOS VOS_NT_WINDOWS32
FILETYPE VFT_APP
FILESUBTYPE VFT2_UNKNOWN
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "Comments", "Made by Mentalflow."
VALUE "CompanyName", "Mentalflow"
VALUE "FileDescription", "RibbonUI APP"
VALUE "FileVersion", VER_STR
VALUE "InternalName", ""
VALUE "LegalCopyright", "Copyright (C) 2023"
VALUE "OriginalFilename", ""
VALUE "ProductName", "RibbonUI APP"
VALUE "ProductVersion", VER_STR
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

64
lib_source/CMakeLists.txt Normal file
View File

@ -0,0 +1,64 @@
cmake_minimum_required(VERSION 3.21)
project(RibbonUI VERSION 1.0.0.0 LANGUAGES CXX)
set(CMAKE_AUTOMOC ON)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if(APPLE)
set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64" CACHE STRING "" FORCE)
endif()
find_package(Qt6 6.2 COMPONENTS Core Quick Qml ShaderTools REQUIRED)
add_definitions(-DRIBBONUI_VERSION=1,0,0,0)
if (RIBBONUI_BUILD_STATIC_LIB)
set(LIB_TYPE "STATIC")
set(PLUGIN_TARGET_NAME "")
qt_add_resources(${PROJECT_NAME} RibbonUI.qmltypes qmldir)
else()
set(LIB_TYPE "SHARED")
set(PLUGIN_TARGET_NAME ${PROJECT_NAME})
endif()
qt_add_library(${PROJECT_NAME} ${LIB_TYPE})
qt_add_qml_module(${PROJECT_NAME}
PLUGIN_TARGET ${PLUGIN_TARGET_NAME}
OUTPUT_DIRECTORY ${CMAKE_PREFIX_PATH}/qml/RibbonUI
URI RibbonUI
VERSION 1.0
QML_FILES qml/RibbonTabBar.qml qml/RibbonTabButton.qml qml/RibbonView.qml
qml/RibbonTabPage.qml qml/RibbonTabGroup.qml qml/RibbonButton.qml
qml/RibbonBottomBar.qml qml/RibbonIcon.qml qml/RibbonToolTip.qml
qml/RibbonTitleBar.qml qml/RibbonSlider.qml qml/RibbonSwitchButton.qml
qml/RibbonCheckBox.qml qml/RibbonMenu.qml qml/RibbonMenuItem.qml
qml/RibbonShadow.qml qml/RibbonBlur.qml qml/RibbonMenuSeparator.qml
qml/RibbonPaperView.qml qml/RibbonPushButton.qml qml/RibbonRectangle.qml
qml/RibbonText.qml qml/RibbonTextBoxMenu.qml qml/RibbonPopup.qml
qml/RibbonPopupDialog.qml qml/RibbonLineEdit.qml qml/RibbonTextEdit.qml
qml/RibbonComboBox.qml qml/RibbonSpinBox.qml
SOURCES ribbonui.cpp ribbonui.h definitions.h ribbontheme.h ribbontheme.cpp
RESOURCES resources/FluentSystemIcons-Resizable.ttf resources/imgs/icon.png
)
qt_add_shaders(${PROJECT_NAME} "shaders"
BATCHABLE
PRECOMPILE
OPTIMIZED
PREFIX
"RibbonUI"
FILES
"effects/gaussianblur.frag"
)
target_compile_definitions(${PROJECT_NAME}
PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
target_link_libraries(${PROJECT_NAME} PRIVATE
Qt::Quick
Qt::CorePrivate
Qt::QuickPrivate
Qt::QmlPrivate
)
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

4759
lib_source/RibbonUI.qmltypes Normal file

File diff suppressed because it is too large Load Diff

4724
lib_source/definitions.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,42 @@
#version 440
layout(location = 0) in vec2 qt_TexCoord0;
layout(location = 0) out vec4 fragColor;
layout(std140, binding = 0) uniform buf {
mat4 qt_Matrix;
float qt_Opacity;
vec2 pixelStep;
int radius;
float deviation;
};
layout(binding = 1) uniform sampler2D src;
#define PI 3.1415926538
float gaussianWeight(vec2 coords)
{
float x2 = pow(coords.x, 2.0);
float y2 = pow(coords.y, 2.0);
float deviation2 = pow(deviation, 2.0);
return (1.0 / (2.0 * PI * deviation2)) * exp(-(x2 + y2) / (2.0 * deviation2));
}
void main(void)
{
vec4 sum = vec4(0.0);
float gaussianSum = 0.0;
for (int x = -radius; x <= radius; ++x) {
for (int y = -radius; y <= radius; ++y) {
vec2 c = qt_TexCoord0 + vec2(x, y) * pixelStep;
float w = gaussianWeight(vec2(x, y));
vec4 color = texture(src, c);
sum += color * w;
gaussianSum += w;
}
}
fragColor = sum / gaussianSum * qt_Opacity;
}

View File

@ -0,0 +1,41 @@
import QtQuick
import Qt5Compat.GraphicalEffects
import RibbonUI
Rectangle {
id: control
color: "transparent"
property int blur_radius: 32
property alias target: effect.sourceItem
property rect target_rect : Qt.rect(control.x, control.y, control.width, control.height)
property color mask_color: RibbonTheme.dark_mode ? "#212629" : "white"
property double mask_opacity: 0.5
property alias mask_border: mask.border
ShaderEffectSource {
id: effect
anchors.fill: parent
sourceRect: target_rect
sourceItem: target
layer.enabled: true
layer.effect: FastBlur{
radius: blur_radius
}
}
Rectangle{
id: mask
anchors.fill: parent
color: mask_color
opacity: mask_opacity
radius: control.radius
}
// ShaderEffect{
// id:blur
// anchors.fill: parent
// property var src: effect
// property int radius: blur_radius
// property real deviation: 8
// property var pixelStep: Qt.vector2d(1/src.width, 1/src.height)
// fragmentShader: "qrc:/RibbonUI/effects/gaussianblur.frag.qsb"
// }
}

View File

@ -0,0 +1,83 @@
import QtQuick
import QtQuick.Layouts
import RibbonUI
Item {
id: root
height: 25
clip: true
property alias left_content: left.data
property alias right_content: right.data
default property alias content: left.data
property bool modern_style: RibbonTheme.modern_style
property bool dark_mode: RibbonTheme.dark_mode
property bool show_version: true
property double bg_opacity: 0.8
anchors{
left: parent.left
right: parent.right
bottom: parent.bottom
}
Rectangle{
visible: !modern_style
color: "#3D3D3D"
anchors.fill: parent
opacity: bg_opacity
gradient: Gradient {
GradientStop { position: 0.0; color: dark_mode ? "#474949" : "#E4E3E4" }
GradientStop { position: 0.5; color: dark_mode ? "#434444" : "#DFDEDE" }
GradientStop { position: 1.0; color: dark_mode ? "#3D3D3D" : "#D9D9D9" }
}
}
Rectangle{
visible: modern_style
color: dark_mode ? "#141414" : "#F5F5F5"
opacity: bg_opacity
anchors.fill: parent
}
Rectangle{
anchors{
top: parent.top
left: parent.left
right: parent.right
}
color: dark_mode ? modern_style ? "#3B3A39":"#282828" : modern_style ? "white":"#A1A2A2"
height: 1
}
RowLayout{
id: left
Layout.maximumWidth: parent.width - right.width
height: parent.height
spacing: 1
anchors{
left: parent.left
leftMargin: 20
}
}
RowLayout{
id: right
Layout.maximumWidth: parent.width - left.width
height: parent.height
spacing: 1
anchors{
right: parent.right
rightMargin: 20
}
layoutDirection: Qt.RightToLeft
RibbonButton{
visible: show_version
show_bg:false
text: `Designed with RibbonUI V${RibbonUI.version}`
adapt_height: true
show_tooltip: false
onClicked: Qt.openUrlExternally("https://github.com/mentalfl0w/RibbonUI")
}
}
}

View File

@ -0,0 +1,126 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import RibbonUI
Button {
id: root
property bool dark_mode: RibbonTheme.dark_mode
property bool show_bg: true
property bool show_hovered_bg: true
property bool adapt_height: false
property bool show_tooltip: true
property var icon_source
property var icon_source_filled
property alias image_icon: pic_icon
property alias ribbon_icon: rib_icon
property string bg_color: dark_mode ? "#626262" : "white"
property string hover_color: dark_mode ? show_bg ? "#818181" : "#5E5D5D" : show_bg ? "#ECEAE9" : "#B0B0B1"
property string pressed_color: dark_mode ? show_bg ? "#424242" : "#5C5C5C" : show_bg ? "#CCCBCB" : "#9D9B9B"
property string checked_color: pressed_color
property string text_color: dark_mode ? "white" : "black"
property bool text_color_reverse: true
property string tip_text: text
opacity: enabled ? 1.0 : 0.3
padding: 0
leftPadding: 0
rightPadding: 0
focusPolicy:Qt.TabFocus
background: Rectangle{
implicitWidth: contentItem.implicitWidth
implicitHeight: contentItem.implicitHeight
visible: show_bg
border.color: dark_mode ? "#7F7F7F" : "#D2D1CE"
border.width: 1
radius: 3
color: bg_color
}
contentItem: Item{
implicitWidth: layout.width + 13
implicitHeight: adapt_height?root.parent.height>=layout.height?root.parent.height:layout.height:layout.height + 10
Rectangle{
anchors.fill: parent
radius: 3
color: {
if (root.pressed)
return pressed_color
if (root.hovered)
return hover_color
if (root.checked)
return checked_color
return "transparent"
}
visible: show_hovered_bg
Behavior on color {
ColorAnimation {
duration: 60
easing.type: Easing.OutSine
}
}
}
RowLayout{
id: layout
anchors.centerIn: parent
height: Math.max(rib_icon.visible ? rib_icon.contentHeight : 0, pic_icon.visible ? pic_icon.height : 0, label.contentHeight)
width: {
let w = 0
w += rib_icon.visible ? rib_icon.contentWidth : 0
w += pic_icon.visible ? pic_icon.width : 0
w += label.text ? label.contentWidth : 0
w += (rib_icon.visible || pic_icon.visible) && label.text ? spacing : 0
return w
}
RibbonIcon{
id :rib_icon
icon_source: typeof(root.icon_source) === "number" ? root.icon_source : 0
icon_source_filled: typeof(root.icon_source_filled) === "number" ? root.icon_source_filled : icon_source
icon_size: label.contentHeight
visible: typeof(root.icon_source) === "number"
Layout.alignment: Qt.AlignVCenter
filled: pressed || checked
color: {
if (!show_bg && (hovered || checked || pressed) && text_color_reverse)
return Qt.lighter(text_color)
else
return text_color
}
Behavior on color {
ColorAnimation {
duration: 60
easing.type: Easing.OutSine
}
}
}
Image {
id: pic_icon
source: typeof(root.icon_source) === "string" ? root.icon_source : ""
visible: typeof(root.icon_source) === "string"
fillMode:Image.PreserveAspectFit
height: label.contentHeight
width: height
Layout.alignment: Qt.AlignVCenter
}
Text {
id: label
text: root.text
Layout.alignment: Qt.AlignVCenter
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font.pixelSize: 12
font.family: Qt.platform.os === "osx" ? "PingFang SC" : "Microsoft YaHei UI"
color: {
if (!show_bg && (hovered || checked || pressed) && text_color_reverse)
return Qt.lighter(text_color)
else
return text_color
}
}
}
RibbonToolTip{
text: tip_text
visible: hovered && show_tooltip && text
}
}
}

View File

@ -0,0 +1,90 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import RibbonUI
Button {
id: control
padding: 0
leftPadding: 0
rightPadding: 0
focusPolicy:Qt.TabFocus
checkable: true
property bool dark_mode: RibbonTheme.dark_mode
property int btn_size: 20
property string border_color: dark_mode ? "white" : "black"
property double border_width: 1.4
property string icon_color: "white"
property string icon_filled_bg_color: "#2143AB"
property string text_color: dark_mode ? "white" : "black"
property int text_size: 11
property bool text_bold: false
property bool text_on_left: false
property bool show_tooltip: false
property string tip_text: text
background: Item{}
contentItem: Item{
id: item
implicitHeight: btn_layout.height + btn_layout.margins*2
implicitWidth: btn_layout.width + btn_layout.margins*2
RowLayout{
id: btn_layout
property int margins: 4
anchors.centerIn: parent
layoutDirection: control.text_on_left ? Qt.RightToLeft : Qt.LeftToRight
Rectangle {
id: bg
implicitHeight: control.btn_size
implicitWidth: implicitHeight
color: "transparent"
border{
color: control.border_color
width: control.border_width
}
radius: 4.5
Rectangle{
id: bg_fill
anchors.fill: parent
scale: control.hovered || control.pressed ? 0.6 : 1.05
radius: 4.5
color: !control.pressed?control.icon_filled_bg_color:Qt.darker(control.icon_filled_bg_color)
visible: control.hovered || control.pressed || control.checked
Behavior on scale{
NumberAnimation{
duration: 150
easing.type: Easing.OutSine
}
}
}
RibbonIcon{
id: check_icon
anchors.centerIn: bg
icon_source: RibbonIcons.Checkmark
icon_source_filled: RibbonIcons_Filled.Checkmark
font.pixelSize: bg.height-4
filled: checked
visible: control.pressed || control.checked
color: !control.pressed?control.icon_color:Qt.darker(control.icon_color)
}
RibbonToolTip{
text: tip_text
visible: hovered && show_tooltip && text
}
}
Text {
id:label
text:control.text
Layout.alignment: Qt.AlignVCenter
font{
family: Qt.platform.os === "osx" ? "PingFang SC" : "Microsoft YaHei UI"
pixelSize: control.text_size
bold: control.text_bold
}
color: text_color
visible: text
}
}
}
}

View File

@ -0,0 +1,203 @@
import QtQuick
import QtQuick.Controls
import RibbonUI
ComboBox {
id: control
property bool dark_mode: RibbonTheme.dark_mode
property int icon_source
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
implicitContentWidth + leftPadding + rightPadding)
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
implicitContentHeight + topPadding + bottomPadding,
implicitIndicatorHeight + topPadding + bottomPadding)
leftPadding: padding + (!control.mirrored || !indicator || !indicator.visible ? 0 : indicator.width + spacing)
rightPadding: padding + (control.mirrored || !indicator || !indicator.visible ? 0 : indicator.width + spacing)
font.pixelSize: 13
opacity: enabled ? 1.0 : 0.3
delegate: ItemDelegate {
id: item
padding: 6
width: ListView.view.width
text: control.textRole ? (Array.isArray(control.model) ? modelData[control.textRole] : model[control.textRole]) : modelData
palette.text: control.palette.text
palette.highlightedText: control.palette.highlightedText
highlighted: control.highlightedIndex === index
hoverEnabled: control.hoverEnabled
contentItem: RibbonText{
id:label
view_only: true
text: item.text
font.pixelSize: control.font.pixelSize
font.weight: control.currentIndex === index ? Font.DemiBold : Font.Normal
color: dark_mode ? "white" : highlighted ? "white" : "black"
}
background: Rectangle{
implicitWidth: item.width - 10
implicitHeight: label.contentHeight + 14
color: !dark_mode ? "#506BBD" : "#2A4299"
visible: down || highlighted || visualFocus
radius: 4
}
}
indicator: RibbonIcon{
x: control.mirrored ? control.padding : control.width - width - control.padding
y: control.topPadding + (control.availableHeight - height) / 2
padding: 5
icon_size: 15
icon_source: RibbonIcons.ChevronDown
rotation: control.down ? 180 : 0
color: dark_mode ? "white" : "black"
Behavior on rotation {
NumberAnimation{
duration: 100
easing.type: Easing.OutSine
}
}
Behavior on color {
ColorAnimation {
duration: 60
easing.type: Easing.OutSine
}
}
}
contentItem: RibbonLineEdit {
id: edit
leftPadding: (!control.mirrored ? 12 : control.editable && activeFocus ? 3 : 1) + icon.visible ? icon.contentWidth + padding*2 : 0
rightPadding: (control.mirrored ? 12 : control.editable && activeFocus ? 3 : 1) + clear_btn.visible ? clear_btn.width + padding*2 : 0
topPadding: 6 - control.padding
bottomPadding: 6 - control.padding
text: control.editable ? control.editText : control.displayText
enabled: control.editable
autoScroll: control.editable
readOnly: control.down
inputMethodHints: control.inputMethodHints
validator: control.validator
selectByMouse: control.selectTextByMouse
opacity: 1
font: control.font
color: dark_mode ? "white" : "black"
selectionColor: dark_mode ? "#4F5E7F" : "#BECDE8"
selectedTextColor: dark_mode ? "white" : "black"
verticalAlignment: Text.AlignVCenter
icon_source: control.icon_source
onCommit: {
accepted()
}
background: Rectangle{
visible: control.enabled && control.editable && !control.flat
radius: 4
implicitHeight: 20
implicitWidth: 140
color: "transparent"
Behavior on color {
ColorAnimation {
duration: 60
easing.type: Easing.OutSine
}
}
}
}
background: Rectangle {
implicitWidth: 150
implicitHeight: 20
radius: 4
color: {
color: {
if (control.down)
return dark_mode ? "#858585" : "#C9CACA"
if (control.hovered)
return dark_mode ? "#5A5B5A" : "#E4E4E4"
return dark_mode ? "#383838" : "#FFFFFF"
}
}
RibbonRectangle{
color: dark_mode ? "#383838" : "#FFFFFF"
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: parent.border.width
radius: parent.radius
topRightRadius: 0
bottomRightRadius: 0
width: parent.width - parent.border.width * 2 - indicator.width
height: parent.height - parent.border.width * 2
}
border.color: edit.cursorVisible ? dark_mode ? "#869CCD" : "#486495" : dark_mode ? "#5E5F5E" : "#B9B9B8"
border.width: 1
visible: !control.flat || control.down
}
popup: Popup {
id: pop
y: control.height
width: control.width
height: origin_height
property int origin_height: Math.min(contentItem.implicitHeight, control.Window.height - topMargin - bottomMargin)
topMargin: 6
bottomMargin: 6
contentItem: ListView {
clip: true
implicitHeight: contentHeight
model: control.delegateModel
currentIndex: control.highlightedIndex
highlightMoveDuration: 0
ScrollIndicator.vertical: ScrollIndicator { }
}
background: RibbonBlur{
radius: 5
mask_opacity: 1
mask_border.color: RibbonTheme.dark_mode ? "#5C5D5D" : "#B5B4B5"
mask_border.width: 1
}
enter: Transition {
NumberAnimation {
properties: "height"
from:0
to: pop.origin_height
duration: 100
easing.type: Easing.OutSine
}
NumberAnimation {
property: "opacity"
duration: 100
from:0
to:1
easing.type: Easing.OutSine
}
}
exit:Transition {
NumberAnimation {
properties: "height"
from: pop.origin_height
to:0
duration: 100
easing.type: Easing.OutSine
}
NumberAnimation {
property: "opacity"
duration: 100
from:1
to:0
easing.type: Easing.OutSine
}
}
}
}

View File

@ -0,0 +1,29 @@
import QtQuick
import QtQuick.Controls
import RibbonUI
Text {
property int icon_source
property int icon_size: 20
property bool filled: false
property int icon_source_filled
onIcon_sourceChanged: {
if (typeof(icon_source_filled) === 'undefined' || icon_source_filled === icon_source)
icon_source_filled = icon_source - 1
}
color: "black"
id:text_icon
font.family: loader.name
font.pixelSize: icon_size
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: (String.fromCharCode(filled ? icon_source_filled : icon_source).toString(16))
FontLoader{
id: loader
source: "qrc:/RibbonUI/resources/FluentSystemIcons-Resizable.ttf"
}
}

View File

@ -0,0 +1,90 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import RibbonUI
TextField{
id: control
autoScroll:true
property bool dark_mode: RibbonTheme.dark_mode
property int icon_source
property bool show_clear_btn: true
property alias clear_btn: clear_btn
property alias icon: icon
focus: true
color: dark_mode ? "white" : "black"
padding: 5
leftPadding: icon.visible ? icon.contentWidth + padding*2 : padding
rightPadding: clear_btn.visible ? clear_btn.width + padding*2 : padding
placeholderText: qsTr("Please input:")
placeholderTextColor: dark_mode ? Qt.rgba(255,255,255,0.5) : Qt.rgba(0,0,0,0.5)
selectByMouse: true
selectionColor: dark_mode ? "#4F5E7F" : "#BECDE8"
selectedTextColor: dark_mode ? "white" : "black"
opacity: enabled ? 1.0 : 0.3
signal commit()
width:150
height:20
onCommit: cursorVisible = false
background: Rectangle{
radius: 4
implicitHeight: 20
implicitWidth: 150
color: dark_mode ? "#383838" : "#FFFFFF"
border.color: control.cursorVisible ? dark_mode ? "#869CCD" : "#486495" : dark_mode ? "#5E5F5E" : "#B9B9B8"
border.width: 1
Behavior on color {
ColorAnimation {
duration: 60
easing.type: Easing.OutSine
}
}
}
Keys.onEnterPressed: commit()
Keys.onReturnPressed: commit()
MouseArea{
anchors.fill: parent
cursorShape: Qt.IBeamCursor
acceptedButtons: Qt.RightButton
onClicked: control.echoMode !== TextInput.Password && menu.popup()
focus: true
}
RibbonTextBoxMenu{
id:menu
input_item: control
}
RibbonIcon{
id: icon
anchors{
left: parent.left
leftMargin: parent.padding
verticalCenter: parent.verticalCenter
}
icon_source: parent.icon_source
icon_size: parent.height - parent.padding
visible: icon_source
color: dark_mode ? "white" : "black"
Behavior on color {
ColorAnimation {
duration: 60
easing.type: Easing.OutSine
}
}
}
RibbonButton{
id: clear_btn
anchors{
right: parent.right
rightMargin: parent.padding
verticalCenter: parent.verticalCenter
}
show_bg: false
show_hovered_bg: false
tip_text: qsTr("Clear")
icon_source: RibbonIcons.Dismiss
height: parent.height - parent.padding
width: height
visible: parent.text&&show_clear_btn&&control.cursorVisible
onClicked: parent.clear()
}
}

View File

@ -0,0 +1,57 @@
import QtQuick
import QtQuick.Controls
import RibbonUI
Menu {
id:control
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
contentWidth + leftPadding + rightPadding)
implicitHeight: Math.min(Math.max(implicitBackgroundHeight + topInset + bottomInset,
contentHeight + topPadding + bottomPadding))
overlap: 1
padding: 5
property bool dark_mode: RibbonTheme.dark_mode
property string bg_color: !dark_mode ? "#E8E9E9" : "#303131"
enter: Transition {
NumberAnimation {
property: "opacity"
from:0
to: 1
duration: 70
easing.type: Easing.OutSine
}
}
exit:Transition {
NumberAnimation {
property: "opacity"
from: 1
to:0
duration: 70
easing.type: Easing.OutSine
}
}
delegate: RibbonMenuItem{}
contentItem: ListView {
implicitHeight: contentHeight
model: control.contentModel
interactive: Window.window
? contentHeight + control.topPadding + control.bottomPadding > Window.window.height
: false
clip: true
currentIndex: control.currentIndex
ScrollIndicator.vertical: ScrollIndicator {}
}
background: Rectangle {
implicitWidth: 250
implicitHeight: 20
layer.enabled: true
layer.effect: RibbonShadow{
shadow_color: "black"
}
border.color: dark_mode ? "#5C5D5D" : "#B5B4B5"
border.width: 1
color: bg_color
radius: 4
}
}

View File

@ -0,0 +1,125 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import RibbonUI
MenuItem {
id: control
property bool dark_mode: RibbonTheme.dark_mode
property var icon_source
property var icon_source_filled
property bool show_tooltip: label.contentWidth < label.implicitWidth
property alias image_icon: pic_icon
property alias ribbon_icon: rib_icon
property string bg_color: !dark_mode ? "#E8E9E9" : "#303131"
property string hover_color: !dark_mode ? "#506BBD" : "#2A4299"
property string text_color: dark_mode ? "white" : hovered ? "white" : "black"
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
implicitContentWidth + leftPadding + rightPadding)
implicitHeight: visible ? Math.max(implicitBackgroundHeight + topInset + bottomInset,
implicitContentHeight + topPadding + bottomPadding,
implicitIndicatorHeight + topPadding + bottomPadding) : 0
opacity: enabled ? 1.0 : 0.3
padding: 0
leftPadding: 12
rightPadding: 0
verticalPadding: 0
focusPolicy:Qt.TabFocus
spacing: 5
indicator: RibbonIcon {
x: control.text ? (control.mirrored ? control.width - width - control.rightPadding : control.leftPadding) : control.leftPadding + (control.availableWidth - width) / 2
y: control.topPadding + (control.availableHeight - height) / 2
visible: control.checkable || control.checked
filled: control.hovered || control.pressed
icon_source: control.checked ? RibbonIcons.CheckmarkCircle : RibbonIcons.Circle
icon_source_filled: control.checked ? RibbonIcons_Filled.CheckmarkCircle : RibbonIcons_Filled.Circle
color: text_color
icon_size: label.contentHeight
}
arrow: RibbonIcon {
x: control.mirrored ? control.padding : control.width - width - control.padding
y: control.topPadding + (control.availableHeight - height) / 2
color: text_color
visible: control.subMenu
icon_source: RibbonIcons.ChevronCircleRight
icon_source_filled: RibbonIcons_Filled.ChevronCircleRight
icon_size: label.contentHeight
}
contentItem: Item{
RowLayout{
readonly property real arrowPadding: control.subMenu && control.arrow ? control.arrow.width + control.spacing : 0
readonly property real indicatorPadding: control.checkable && control.indicator ? control.indicator.width + control.spacing : 0
anchors.leftMargin: !control.mirrored ? indicatorPadding : arrowPadding
anchors.rightMargin: control.mirrored ? indicatorPadding : arrowPadding
anchors.fill: parent
spacing: control.spacing
height: Math.max(rib_icon.visible ? rib_icon.contentHeight : 0, pic_icon.visible ? pic_icon.height : 0, label.contentHeight)
layoutDirection: control.mirrored ? Qt.RightToLeft : Qt.LeftToRight
width: {
let w = control.width
w = w - arrowPadding - indicatorPadding - 25
return w
}
RibbonIcon{
id :rib_icon
icon_source: typeof(control.icon_source) === "number" ? control.icon_source : 0
icon_source_filled: typeof(control.icon_source_filled) === "number" ? control.icon_source_filled : icon_source
icon_size: label.contentHeight
visible: typeof(control.icon_source) === "number"
Layout.alignment: Qt.AlignVCenter
filled: pressed || checked
color: text_color
}
Image {
id: pic_icon
source: typeof(control.icon_source) === "string" ? control.icon_source : ""
visible: typeof(control.icon_source) === "string"
fillMode:Image.PreserveAspectFit
height: label.contentHeight
width: height
Layout.alignment: Qt.AlignVCenter
}
Text {
id: label
text: control.text
Layout.alignment: Qt.AlignVCenter
verticalAlignment: Text.AlignVCenter
font.pixelSize: 13
elide: Text.ElideRight
font.family: Qt.platform.os === "osx" ? "PingFang SC" : "Microsoft YaHei UI"
color: text_color
Layout.preferredWidth:{
let w = 0
w += rib_icon.visible ? rib_icon.contentWidth : 0
w += pic_icon.visible ? pic_icon.width : 0
w += (rib_icon.visible || pic_icon.visible) && label.text ? spacing : 0
return parent.width - w
}
}
RibbonToolTip{
id: tooltip
visible: hovered && show_tooltip && control.text
text: control.text
}
}
}
background: Item {
implicitWidth: 230
implicitHeight: label.contentHeight + 14
Rectangle {
anchors.centerIn: parent
anchors.margins: 6
width: parent.width
height: parent.height - anchors.margins / 2
clip: visible
radius: 4
color: control.hovered ?hover_color : bg_color
}
}
}

View File

@ -0,0 +1,24 @@
import QtQuick
import QtQuick.Controls
import RibbonUI
MenuSeparator {
id: control
property bool dark_mode: RibbonTheme.dark_mode
property string color: dark_mode ? "#4A4B4C" : "#D1D2D2"
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
implicitContentWidth + leftPadding + rightPadding)
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
implicitContentHeight + topPadding + bottomPadding)
padding: 0
leftPadding: 10
rightPadding: leftPadding
verticalPadding: 0
contentItem: Rectangle {
implicitWidth: 230
implicitHeight: 1
color: control.color
}
}

View File

@ -0,0 +1,37 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import RibbonUI
RibbonView {
id: control
property int page_width: width * 0.7
property int page_height: 1000
default property alias content: container.data
Rectangle{
id: container_bg
Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
Layout.topMargin: modern_style ? 20 : 30
Layout.bottomMargin: modern_style ? 20 : 30
radius: modern_style ? 10 : 5
color: dark_mode ? "#262626" : "white"
implicitWidth: control.page_width
implicitHeight: control.page_height
layer.enabled: true
layer.effect: RibbonShadow {
id: effect
shadow_opacity:modern_style ? 0.2 : 0.5
}
ColumnLayout{
id:container
spacing: control.spacing
clip: true
anchors{
top: parent.top
left: parent.left
right: parent.right
}
width: parent.width
}
}
}

View File

@ -0,0 +1,92 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import QtQuick.Window
import RibbonUI
import Qt5Compat.GraphicalEffects
Popup {
id: popup
padding: 0
modal: true
anchors.centerIn: Overlay.overlay
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
property bool show_close_btn: true
property bool blur_enabled: false
property alias target: blur.target
property alias target_rect: blur.target_rect
property alias radius: blur.radius
enter: Transition {
NumberAnimation {
properties: "scale"
from:0.5
to:1
duration: 100
easing.type: Easing.OutSine
}
NumberAnimation {
property: "opacity"
duration: 100
from:0
to:1
easing.type: Easing.OutSine
}
}
exit:Transition {
NumberAnimation {
properties: "scale"
from:1
to:0.5
duration: 100
easing.type: Easing.OutSine
}
NumberAnimation {
property: "opacity"
duration: 100
from:1
to:0
easing.type: Easing.OutSine
}
}
background: Item{
RectangularGlow {
id: effect
anchors.fill: blur
anchors.margins: blur.border.width
glowRadius: 20
spread: 0
color: RibbonTheme.dark_mode ? Qt.rgba(255,255,255,0.1) : Qt.rgba(0,0,0,0.1)
cornerRadius: blur.radius + glowRadius + 10
}
RibbonBlur{
implicitHeight: parent.height
implicitWidth: parent.width
id: blur
radius: 20
mask_opacity: blur_enabled ? 0.5 : 1
mask_border.color: RibbonTheme.dark_mode ? "#5C5D5D" : "#B5B4B5"
mask_border.width: 1
}
}
contentItem: Item{
RibbonButton{
anchors{
top:parent.top
topMargin: 8
right:parent.right
rightMargin: topMargin
}
show_bg: false
show_hovered_bg: false
icon_source: RibbonIcons.Dismiss
onClicked: close()
visible: show_close_btn
}
}
Overlay.modal:Rectangle{
color:"transparent"
}
Overlay.modeless:Rectangle{
color:"transparent"
}
}

View File

@ -0,0 +1,119 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import QtQuick.Window
import RibbonUI
RibbonPopup {
id: control
property string title: "Title"
property string message: "Message"
property string neutralText: "Neutral"
property string negativeText: "Negative"
property string positiveText: "Positive"
property bool dark_mode: RibbonTheme.dark_mode
show_close_btn: false
radius: 5
signal neutralClicked
signal negativeClicked
signal positiveClicked
property int buttonFlags: RibbonPopupDialogType.NegativeButton | RibbonPopupDialogType.PositiveButton
focus: true
implicitWidth: 250
implicitHeight: text_title.height + text_message.height + layout_actions.height + layout_actions.anchors.topMargin + layout_actions.anchors.bottomMargin
Rectangle {
id:layout_content
anchors.fill: parent
color: 'transparent'
radius:5
RibbonText{
id:text_title
font.pixelSize: 24
text:title
view_only: true
topPadding: 15
leftPadding: 15
rightPadding: 15
wrapMode: Text.WrapAnywhere
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
anchors{
top:parent.top
left: parent.left
right: parent.right
}
}
RibbonText{
id:text_message
font.pixelSize: 13
wrapMode: Text.WrapAnywhere
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text:message
view_only: true
topPadding: 15
leftPadding: 15
rightPadding: 15
bottomPadding: 15
anchors{
top:text_title.bottom
left: parent.left
right: parent.right
}
}
RowLayout{
id:layout_actions
anchors{
topMargin: 15
left: parent.left
leftMargin: 15
right: parent.right
rightMargin: 15
bottom: parent.bottom
bottomMargin: 15
}
height: 30
spacing: 15
RibbonButton{
id:negative_btn
Layout.fillWidth: true
Layout.fillHeight: true
visible: control.buttonFlags&RibbonPopupDialogType.NegativeButton
text: negativeText
show_tooltip: false
onClicked: {
negativeClicked()
control.close()
}
}
RibbonButton{
id:neutral_btn
Layout.fillWidth: true
Layout.fillHeight: true
visible: control.buttonFlags&RibbonPopupDialogType.NeutralButton
text: neutralText
show_tooltip: false
onClicked: {
neutralClicked()
control.close()
}
}
RibbonButton{
id:positive_btn
Layout.fillWidth: true
Layout.fillHeight: true
visible: control.buttonFlags&RibbonPopupDialogType.PositiveButton
text: positiveText
show_tooltip: false
bg_color: dark_mode ? "#8AAAEB" : "#2C59B7"
text_color: "white"
hover_color: dark_mode ? Qt.rgba(255, 255, 255, 0.3) : Qt.rgba(0, 0, 0, 0.3)
pressed_color: dark_mode ? Qt.rgba(255, 255, 255, 0.5) : Qt.rgba(0,0,0, 0.5)
onClicked: {
positiveClicked()
control.close()
}
}
}
}
}

View File

@ -0,0 +1,130 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import RibbonUI
Item {
id: root
property bool dark_mode: RibbonTheme.dark_mode
property bool show_tooltip: true
property var icon_source
property string hover_color: dark_mode ? "#414140" : "#D8D9D9"
property string pressed_color: dark_mode ? "#5B5B5C" : "#BCBCBC"
property string buddy_hover_color: dark_mode ? "#383838" : "#E1E1E1"
property string text_color: dark_mode ? "white" : "black"
property string tip_text: text
property string text
default property alias content: m.contentData
property int icon_size: height
signal clicked()
opacity: enabled ? 1.0 : 0.3
implicitWidth: left.width + right.width
implicitHeight: left.height
RowLayout{
id: btn
anchors.centerIn: parent
spacing: 0
RibbonRectangle{
id: left
topLeftRadius: 3
bottomLeftRadius: topLeftRadius
topRightRadius:m.count ? 0 : topLeftRadius
bottomRightRadius:m.count ? 0 : topLeftRadius
implicitWidth: label.contentWidth > 40 ? label.contentWidth - (m.count ? 5 : -5) : 40
implicitHeight: 40
color: {
if (left_th.pressed)
return pressed_color
if (left_hh.hovered)
return hover_color
if (right_hh.hovered)
return buddy_hover_color
return "transparent"
}
RibbonIcon{
id :rib_icon
anchors.centerIn: parent
icon_source: typeof(root.icon_source) === "number" ? root.icon_source : 0
icon_source_filled: typeof(root.icon_source) === "number" ? root.icon_source - 1 : 0
icon_size: root.icon_size
visible: typeof(root.icon_source) === "number"
Layout.alignment: Qt.AlignVCenter
filled: left_th.pressed
color: text_color
}
Image {
id: pic_icon
anchors.centerIn: parent
source: typeof(root.icon_source) === "string" ? root.icon_source : ""
visible: typeof(root.icon_source) === "string"
fillMode:Image.PreserveAspectFit
height: icon_size
width: height
Layout.alignment: Qt.AlignVCenter
}
HoverHandler{
id: left_hh
}
TapHandler{
id: left_th
onTapped: clicked()
}
}
RibbonRectangle{
id: right
topRightRadius:3
bottomRightRadius:3
implicitWidth: 12
implicitHeight: 40
visible: m.count
color: {
if (right_th.pressed||m.opened)
return pressed_color
if (right_hh.hovered)
return hover_color
if (left_hh.hovered)
return buddy_hover_color
return "transparent"
}
RibbonIcon{
anchors.centerIn: parent
icon_source: RibbonIcons.ChevronDown
icon_source_filled: RibbonIcons.ChevronDown - 1
icon_size: 15
Layout.alignment: Qt.AlignVCenter
filled: right_th.pressed
color: text_color
}
HoverHandler{
id: right_hh
}
TapHandler{
id: right_th
onTapped: m.popup()
}
}
RibbonToolTip{
text: tip_text
visible: (left_hh.hovered || right_hh.hovered)&& show_tooltip && text
}
}
RibbonMenu{
id:m
width: 100
}
Text {
id: label
text: root.text
anchors{
top: btn.bottom
horizontalCenter: btn.horizontalCenter
}
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font.pixelSize: 12
font.family: Qt.platform.os === "osx" ? "PingFang SC" : "Microsoft YaHei UI"
color: text_color
}
}

View File

@ -0,0 +1,69 @@
import QtQuick
import QtQuick.Controls
import Qt5Compat.GraphicalEffects
Item {
id: control
property string color
property int radius: 0
property int topLeftRadius: radius
property int topRightRadius: radius
property int bottomLeftRadius: radius
property int bottomRightRadius: radius
default property alias contentItem: container.data
onWidthChanged: {
canvas.requestPaint()
}
onHeightChanged: {
canvas.requestPaint()
}
onTopLeftRadiusChanged: {
canvas.requestPaint()
}
onTopRightRadiusChanged: {
canvas.requestPaint()
}
onBottomLeftRadiusChanged: {
canvas.requestPaint()
}
onBottomRightRadiusChanged: {
canvas.requestPaint()
}
onColorChanged: {
canvas.requestPaint()
}
Canvas {
id: canvas
anchors.fill: parent
onPaint: {
var ctx = getContext("2d")
ctx.clearRect(0, 0, width, height)
ctx.beginPath()
ctx.moveTo(control.topLeftRadius, 0)
ctx.lineTo(width - control.topRightRadius, 0)
ctx.arcTo(width, 0, width, control.topRightRadius, control.topRightRadius)
ctx.lineTo(width, height - control.bottomRightRadius)
ctx.arcTo(width, height, width - control.bottomRightRadius, height, control.bottomRightRadius)
ctx.lineTo(control.bottomLeftRadius, height)
ctx.arcTo(0, height, 0, height - control.bottomLeftRadius, control.bottomLeftRadius)
ctx.lineTo(0, control.topLeftRadius)
ctx.arcTo(0, 0, control.topLeftRadius, 0, control.topLeftRadius)
ctx.closePath()
ctx.fillStyle = control.color
ctx.fill()
}
}
Rectangle {
id: container
anchors.fill: parent
color: control.color
opacity: 0
}
OpacityMask {
anchors.fill: canvas
source: container
maskSource: canvas
invert: control.color === "transparent"
}
}

View File

@ -0,0 +1,14 @@
import QtQuick
import Qt5Compat.GraphicalEffects
import RibbonUI
DropShadow {
property double shadow_opacity: 0.2
property color shadow_color: RibbonTheme.dark_mode ? "white" : "black"
transparentBorder: true
color: Qt.rgba(shadow_color.r,shadow_color.g,shadow_color.b,shadow_opacity)
radius: 8
horizontalOffset: 0
verticalOffset: 0
spread: 0
}

View File

@ -0,0 +1,169 @@
import QtQuick
import QtQuick.Controls
import Qt5Compat.GraphicalEffects
import RibbonUI
Item {
id: control
height: horizontal ? container.implicitHeight : container.implicitWidth
width: horizontal ? container.implicitWidth : show_button ? Math.max(container.implicitHeight,subtract_button.width,add_button.width) : container.implicitHeight
property bool show_tooltip: true
property bool show_filled_color: true
property bool show_button: true
property bool horizontal: true
property int slide_width: 150
property int slide_height: 4
property alias value: slide.value
property bool dark_mode: RibbonTheme.dark_mode
Item{
id: container
anchors.centerIn: parent
implicitHeight: slide.implicitHeight
implicitWidth: slide.implicitWidth + add_button.width + subtract_button.width
rotation: horizontal ? 0 : -90
RibbonButton{
id: add_button
anchors{
right: parent.right
verticalCenter: parent.verticalCenter
}
height: parent.height -3
icon_source: RibbonIcons.Add
icon_source_filled: RibbonIcons_Filled.Add
show_bg: false
show_tooltip: false
show_hovered_bg: false
rotation: horizontal ? 0 : 90
visible: show_button
enabled: slide.value !== 100
text_color: dark_mode ? "white" : "black"
opacity: enabled ? 1 : 0.2
onClicked:
{
tooltip.show(slide.value,1000)
slide.increase()
}
Behavior on text_color {
ColorAnimation {
duration: 60
easing.type: Easing.OutSine
}
}
}
RibbonButton{
id: subtract_button
anchors{
left: parent.left
verticalCenter: parent.verticalCenter
}
height: parent.height -3
show_bg: false
show_tooltip: false
show_hovered_bg: false
icon_source: RibbonIcons.Subtract
icon_source_filled: RibbonIcons_Filled.Subtract
rotation: horizontal ? 0 : 90
visible: show_button
text_color: dark_mode ? "white" : "black"
opacity: enabled ? 1 : 0.2
enabled: slide.value !== 0
onClicked:
{
tooltip.show(slide.value,1000)
slide.decrease()
}
Behavior on text_color {
ColorAnimation {
duration: 60
easing.type: Easing.OutSine
}
}
}
Slider {
id: slide
to: 100
stepSize: 1
anchors{
leftMargin: -5
left: show_button ? subtract_button.right : parent.left
right: show_button ? add_button.left : parent.right
rightMargin: -5
verticalCenter: add_button.verticalCenter
}
implicitWidth: Math.max(implicitBackgroundWidth + leftPadding + rightPadding, implicitHandleWidth + leftPadding + rightPadding)
implicitHeight: Math.max(implicitBackgroundHeight + topPadding + bottomPadding, implicitHandleHeight + topPadding + bottomPadding)
property int slide_length: 150
property int slide_width: 5
handle: Rectangle{
x: slide.leftPadding + (slide.horizontal ? slide.visualPosition * (slide.availableWidth - width) : (slide.availableWidth - width) / 2)
y: slide.topPadding + (slide.horizontal ? (slide.availableHeight - height) / 2 : slide.visualPosition * (slide.availableHeight - height)) - 1
implicitWidth: 12
implicitHeight: 12
color: dark_mode ? "#A1A2A1" : "#EDEEEE"
radius: 12
layer.enabled: true
layer.effect: RibbonShadow {
shadow_opacity: 0.2
shadow_color: "black"
}
scale: slide.pressed ? 1.1 : slide.hovered ? 1.2 : 1
Behavior on color {
ColorAnimation {
duration: 60
easing.type: Easing.OutSine
}
}
Behavior on scale {
NumberAnimation{
duration: 150
easing.type: Easing.OutSine
}
}
}
background: Item {
x: slide.leftPadding + (slide.horizontal ? 0 : (slide.availableWidth - width) / 2)
y: slide.topPadding + (slide.horizontal ? (slide.availableHeight - height) / 2 : 0) - 1
implicitWidth: slide.horizontal ? control.slide_width : control.slide_height
implicitHeight: slide.horizontal ? control.slide_height : control.slide_width
width: slide.horizontal ? slide.availableWidth : implicitWidth
height: slide.horizontal ? implicitHeight : slide.availableHeight
Rectangle{
anchors.fill: parent
radius: 2
color: dark_mode ? "#7C7C7C" : "#8F8F8F"
Behavior on color {
ColorAnimation {
duration: 60
easing.type: Easing.OutSine
}
}
}
scale: slide.horizontal && slide.mirrored ? -1 : 1
Rectangle {
y: slide.horizontal ? 0 : slide.visualPosition * parent.height
width: slide.horizontal ? slide.position * parent.width : control.slide_height
height: slide.horizontal ? control.slide_height : slide.position * parent.height
radius: 3
color: show_filled_color ? dark_mode ? "#8AAAEB" : "#5DA3E8" : dark_mode ? "#7C7C7C" : "#8F8F8F"
Behavior on color {
ColorAnimation {
duration: 60
easing.type: Easing.OutSine
}
}
}
}
}
RibbonToolTip{
id: tooltip
parent: slide.handle
visible: show_tooltip && slide.pressed
text: slide.value
}
}
}

View File

@ -0,0 +1,100 @@
import QtQuick
import QtQuick.Controls
import RibbonUI
SpinBox {
id: control
property bool dark_mode: RibbonTheme.dark_mode
property int icon_source
font.pixelSize: 13
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
90 /* minimum */ )
implicitHeight: Math.max(implicitBackgroundHeight, up.implicitIndicatorHeight + down.implicitIndicatorHeight)
+ topInset + bottomInset
spacing: 2
// Push the background right to make room for the indicators
rightInset: up.implicitIndicatorWidth + spacing
leftPadding: 0
topPadding: 0
rightPadding: 0
bottomPadding: 0
validator: IntValidator {
locale: control.locale.name
bottom: Math.min(control.from, control.to)
top: Math.max(control.from, control.to)
}
contentItem: RibbonLineEdit {
text: control.displayText
font: control.font
color: dark_mode ? "white" : "black"
selectionColor: dark_mode ? "#4F5E7F" : "#BECDE8"
selectedTextColor: dark_mode ? "white" : "black"
horizontalAlignment: Qt.AlignLeft
verticalAlignment: Qt.AlignVCenter
icon_source: control.icon_source
icon.icon_size: 16
topPadding: 2
bottomPadding: 2
leftPadding: 10 + icon.visible ? icon.contentWidth + padding*2 : 0
rightPadding: (10 + clear_btn.visible ? clear_btn.width + padding*2 : 0) + up.indicator.width
readOnly: !control.editable
validator: control.validator
inputMethodHints: control.inputMethodHints
}
up.indicator: RibbonButton{
z: 1
x: parent.width - width
y: (parent.height / 2) - height + 2
implicitWidth: 20 - 2
implicitHeight: 12 - 2
icon_source: RibbonIcons.ChevronUp
ribbon_icon.icon_size: 10
show_bg: false
show_tooltip: false
onHoveredChanged: control.up.hovered = hovered
onPressedChanged: control.up.pressed = pressed
onClicked: increase()
}
down.indicator: RibbonButton{
z:1
x: parent.width - width
y: (parent.height / 2) - height - 1 + up.indicator.height
implicitWidth: 20 - 2
implicitHeight: 12 - 2
icon_source: RibbonIcons.ChevronDown
ribbon_icon.icon_size: 10
show_bg: false
show_tooltip: false
onHoveredChanged: control.down.hovered = hovered
onPressedChanged: control.down.pressed = pressed
onClicked: decrease()
}
background: Rectangle {
implicitWidth: 80
implicitHeight: 25
radius: 4
color: {
color: {
if (control.down)
return dark_mode ? "#858585" : "#C9CACA"
if (control.hovered)
return dark_mode ? "#5A5B5A" : "#E4E4E4"
return dark_mode ? "#383838" : "#FFFFFF"
}
}
}
}

View File

@ -0,0 +1,205 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import RibbonUI
Button {
id: control
padding: 0
leftPadding: 0
rightPadding: 0
focusPolicy:Qt.TabFocus
checkable: true
property bool dark_mode: RibbonTheme.dark_mode
property bool show_grabber_text: true
property string grabber_text: control.checked ? qsTr("Open") : qsTr("Close")
property string text_color: dark_mode ? "white" : "black"
property int text_size: 11
property string grabber_checked_color: dark_mode ? "#8AAAEB" : "#2850A4"
property string grabber_unchecked_color: dark_mode ? "#292929" : "white"
property string grabber_text_checked_color: dark_mode ? "black" : "white"
property string grabber_text_unchecked_color: dark_mode ? "white" : "black"
property string grabber_color: dark_mode ? control.pressed ? "#F8F8F8" : "white" : control.pressed ? "#4D4D4D":"#616161"
property string border_color: dark_mode ? "white" : "#616161"
property double border_width: 1.4
property bool text_bold: false
property bool text_on_left: false
property bool show_tooltip: false
property string tip_text: text
background:Item{}
contentItem:Item{
id: item
implicitHeight: btn_layout.height + btn_layout.margins*2
implicitWidth: btn_layout.width + btn_layout.margins*2
RowLayout{
id: btn_layout
property int margins: 4
spacing: 4
anchors.centerIn: parent
layoutDirection: control.text_on_left ? Qt.RightToLeft : Qt.LeftToRight
Item{
id: btn
implicitHeight: 20
implicitWidth: control.show_grabber_text ? 20 + grabber_text.anchors.margins * 2 + grabber_text.contentWidth : 40
Rectangle{
id:bg
implicitWidth: btn.implicitWidth + border.width
implicitHeight: btn.implicitHeight + border.width
anchors.verticalCenter: parent.verticalCenter
border.color: border_color
border.width: border_width
radius: 12
states: [
State{
name:"checked"
when: control.checked
PropertyChanges {
target: bg
color: grabber_checked_color
}
},
State{
name:"unchecked"
when: !control.checked
PropertyChanges {
target: bg
color: grabber_unchecked_color
}
}
]
transitions: [
Transition {
from: "checked"
to:"unchecked"
ColorAnimation {
from: grabber_checked_color
to: grabber_unchecked_color
duration: 200
easing.type: Easing.OutSine
}
},
Transition {
from: "unchecked"
to:"checked"
ColorAnimation {
from: grabber_unchecked_color
to: grabber_checked_color
duration: 200
easing.type: Easing.OutSine
}
}
]
}
Rectangle{
id: grabber
implicitHeight: bg.implicitHeight - anchors.margins*2
implicitWidth:implicitHeight
radius: width / 2
color: grabber_color
anchors{
verticalCenter: parent.verticalCenter
margins: 4
}
scale: control.hovered && !control.pressed ? 1.2 : control.pressed ? 1.1 : 1.0
x: control.checked ? btn.implicitWidth - anchors.margins - implicitWidth : anchors.margins
z: 1
Behavior on x {
NumberAnimation{
duration: 150
easing.type: Easing.OutSine
}
}
Behavior on scale {
NumberAnimation{
duration: 150
easing.type: Easing.OutSine
}
}
layer.enabled: true
layer.effect: RibbonShadow{
shadow_opacity: 0.2
shadow_color: "black"
}
}
Text {
id: grabber_text
text: control.grabber_text
anchors.verticalCenter: parent.verticalCenter
anchors.margins: 4
visible: control.show_grabber_text
x: control.checked ? grabber.x - anchors.margins - contentWidth : grabber.x + grabber.width + anchors.margins
z: 0
font{
family: Qt.platform.os === "osx" ? "PingFang SC" : "Microsoft YaHei UI"
pixelSize: 9
bold: true
}
Behavior on x {
NumberAnimation{
duration: 150
easing.type: Easing.OutSine
}
}
states: [
State{
name:"checked"
when: control.checked
PropertyChanges {
target: grabber_text
color: grabber_text_checked_color
}
},
State{
name:"unchecked"
when: !control.checked
PropertyChanges {
target: grabber_text
color: grabber_text_unchecked_color
}
}
]
transitions: [
Transition {
from: "checked"
to:"unchecked"
ColorAnimation {
from: grabber_text_checked_color
to: grabber_text_unchecked_color
duration: 200
easing.type: Easing.OutSine
}
},
Transition {
from: "unchecked"
to:"checked"
ColorAnimation {
from: grabber_text_checked_color
to: grabber_text_unchecked_color
duration: 200
easing.type: Easing.OutSine
}
}
]
}
RibbonToolTip{
text: tip_text
visible: hovered && show_tooltip && text
}
}
Text {
id:label
text:control.text
Layout.alignment: Qt.AlignVCenter
font{
family: Qt.platform.os === "osx" ? "PingFang SC" : "Microsoft YaHei UI"
pixelSize: control.text_size
bold: control.text_bold
}
color: text_color
visible: text
}
}
}
}

View File

@ -0,0 +1,302 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Qt5Compat.GraphicalEffects
import RibbonUI
Item{
id: root
height: folded ? top_border.height + bar.contentHeight + bottom_border.height: modern_style ? 200 : 180
anchors{
top: parent.top
left: parent.left
right:parent.right
}
clip: true
property bool folded: false
property int last_index
default property alias content: stack.contentData
property alias right_tool_bar: tool_bar.data
property bool modern_style: RibbonTheme.modern_style
property bool dark_mode: RibbonTheme.dark_mode
property string bg_color: dark_mode ? "#2D2D2D" : "#F4F5F3"
property double bg_opacity: 0.8
property string border_color: dark_mode ? "black" : "#CCCCCC"
Component {
id: ribbonTabButton
RibbonTabButton{
}
}
Rectangle {
id: top_border
anchors.top: parent.top
width: parent.width
height: 1
color: modern_style ? "transparent" : bg_color
opacity:bg_opacity
Behavior on color {
ColorAnimation {
duration: 60
easing.type: Easing.OutSine
}
}
}
Item {
id:bg
anchors
{
top: modern_style ? bar.bottom : top_border.bottom
left: parent.left
right: parent.right
bottom:bottom_border.top
topMargin: modern_style ? 10 :0
leftMargin: modern_style ? 10 :0
rightMargin: modern_style ? 10 :0
bottomMargin: modern_style ? 10 :0
}
clip: true
opacity:bg_opacity
Rectangle{
anchors.fill: parent
color: bg_color
opacity:bg_opacity
radius: modern_style ? 10 :0
Behavior on color {
ColorAnimation {
duration: 60
easing.type: Easing.OutSine
}
}
}
}
RibbonShadow {
id: effect
enabled: modern_style
visible: modern_style
source: bg
anchors.fill: bg
}
TabBar {
id: bar
z:1
anchors{
top:top_border.bottom
left: parent.left
right:tool_bar.left
}
background: Item{}
position: TabBar.Header
currentIndex: stack.currentIndex
}
RowLayout{
id: tool_bar
z:2
spacing: 10
width: 200
height: bar.contentHeight
layoutDirection: Qt.RightToLeft
anchors{
top:top_border.bottom
right:parent.right
rightMargin: tool_bar.spacing
}
}
SwipeView {
id: stack
z:0
anchors{
top:bar.bottom
left: parent.left
right:parent.right
}
clip: true
property int origin_height: root.height - bar.contentHeight - top_border.height * 2
height: origin_height
currentIndex: bar.currentIndex
background: Item{
anchors{
fill: parent
topMargin: modern_style ? 10 :0
leftMargin: modern_style ? 10 :0
rightMargin: modern_style ? 10 :0
bottomMargin: modern_style ? 10 :0
}
}
contentItem: ListView {
anchors{
fill: parent
topMargin: modern_style ? 10 :0
leftMargin: modern_style ? 10 :0
rightMargin: modern_style ? 10 :0
bottomMargin: modern_style ? 10 :0
}
clip: true
model: stack.contentModel
interactive: stack.interactive
currentIndex: stack.currentIndex
focus: stack.focus
spacing: stack.spacing
orientation: stack.orientation
snapMode: ListView.SnapOneItem
boundsBehavior: Flickable.StopAtBounds
highlightRangeMode: ListView.StrictlyEnforceRange
preferredHighlightBegin: 0
preferredHighlightEnd: 0
highlightMoveDuration: 250
maximumFlickVelocity: 4 * (stack.orientation === Qt.Horizontal ? width : height)
RibbonButton{
anchors{
right: parent.right
bottom: parent.bottom
rightMargin: 5
bottomMargin: 5
}
icon_source: RibbonIcons.ChevronDown
Behavior on rotation {
NumberAnimation{
duration: 100
easing.type: Easing.OutSine
}
}
rotation: folded ? 0 : 180
onClicked: folded = !folded
show_bg: false
show_hovered_bg: false
tip_text: folded ? qsTr("Show") : qsTr("Hide")
text_color: dark_mode ? "white" : "black"
}
}
states: [
State{
name:"fold"
when: root.folded
PropertyChanges {
target: stack
height:0
}
},
State{
name:"unfold"
when: !root.folded
PropertyChanges {
target: stack
height:origin_height
}
}
]
transitions: [
Transition {
from: "fold"
to:"unfold"
NumberAnimation {
properties: "height"
duration: 167
easing.type: Easing.OutSine
}
},
Transition {
from: "unfold"
to:"fold"
NumberAnimation {
properties: "height"
duration: 167
easing.type: Easing.OutSine
}
}
]
Component.onCompleted: {
for (let i=0,sign=0; i < stack.contentData.length; i++)
{
var item = stack.contentData[i]
if(item instanceof RibbonTabPage){
let btn = ribbonTabButton.createObject(bar,{text:qsTr(item.title),index:i})
if (sign===0)
{
btn.checked = true
sign++
}
btn.need_fold.connect(hide_stack)
root.foldedChanged.connect(function(){btn.setFolded(folded)})
}
}
}
}
Rectangle {
id: bottom_border
anchors.top: stack.bottom
width: parent.width
height: 1
color: modern_style ? "transparent" : bg_color
opacity:bg_opacity
Rectangle{
anchors{
left: parent.left
right: parent.right
bottom: parent.bottom
}
z: 3
color: border_color
height: 1
visible: !modern_style
Behavior on color {
ColorAnimation {
duration: 60
easing.type: Easing.OutSine
}
}
}
Behavior on color {
ColorAnimation {
duration: 60
easing.type: Easing.OutSine
}
}
}
Behavior on height {
NumberAnimation {
duration: 167
easing.type: Easing.OutSine
}
}
Timer{
id: timer
interval: 500
repeat: false
onTriggered: folded = false
}
//onModern_styleChanged: refresh()
function hide_stack(need_hide, index)
{
if (typeof(last_index)==='undefined'||last_index===index||last_index!==index&&!need_hide)
{
folded = need_hide && !folded
}
last_index = index
}
function refresh()
{
if(!folded)
{
folded = true
timer.start()
}
}
}

View File

@ -0,0 +1,79 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import RibbonUI
TabButton {
id: control
signal need_fold(bool needed, int index)
property bool folded: false
property int index
property bool dark_mode: RibbonTheme.dark_mode
property string underline_unchecked_color: dark_mode ? "#666666" : RibbonTheme.modern_style ? "#A2A2A2" : "#D1D1D1"
property string underline_checked_color: dark_mode ? "#8AAAEB" : "#2E4C93"
property string font_color: dark_mode ? "white" : "black"
background: Item{}
contentItem: Item{
implicitHeight:btn_text.contentHeight + 8
implicitWidth: btn_text.contentWidth
Text {
id :btn_text
text: control.text
font{
family: Qt.platform.os === "osx" ? "PingFang SC" : "Microsoft YaHei UI"
pixelSize: 13
bold: true
}
color: font_color
height: contentHeight
anchors{
centerIn: parent
}
Behavior on color {
ColorAnimation {
duration: 60
easing.type: Easing.OutSine
}
}
}
Rectangle{
id: btn_underline
height: 3
width: control.hovered && control.checked && !folded ? btn_text.contentWidth + 15 : btn_text.contentWidth
color: {
if (control.hovered && (!control.checked || folded))
return underline_unchecked_color
if (control.checked && !folded)
return underline_checked_color
return "transparent"
}
radius: 3
anchors
{
horizontalCenter: parent.horizontalCenter
bottom: parent.bottom
bottomMargin: 1
}
Behavior on width {
NumberAnimation{
duration: 150
easing.type: Easing.OutSine
}
}
}
}
width: implicitWidth + 15
height: implicitHeight + 6
onClicked: {
need_fold(checked&&!folded, index)
}
function setFolded(value)
{
folded = value
}
}

View File

@ -0,0 +1,69 @@
import QtQuick
import QtQuick.Layouts
import RibbonUI
Item {
id:control
width: container.width
property alias text: label.text
property alias show_border: line.visible
default property alias content: container.data
property int contenHeight: container.height
property bool dark_mode: RibbonTheme.dark_mode
property string font_color: dark_mode ? "white" : "black"
property string border_color: dark_mode ? "#525252" : "#D4D4D4"
Layout.fillHeight: true
clip: true
Text {
id :label
text: control.text
font{
family: Qt.platform.os === "osx" ? "PingFang SC" : "Microsoft YaHei UI"
pixelSize: 12
bold: true
}
color: font_color
height: contentHeight
anchors{
horizontalCenter: control.horizontalCenter
bottom: control.bottom
bottomMargin: 5
}
Behavior on color {
ColorAnimation {
duration: 60
easing.type: Easing.OutSine
}
}
}
Rectangle{
id: line
width: 1
height: control.height - label.anchors.bottomMargin*3
color: border_color
anchors{
verticalCenter: control.verticalCenter
right:control.right
}
Behavior on color {
ColorAnimation {
duration: 60
easing.type: Easing.OutSine
}
}
}
Item {
id: container
anchors{
top: control.top
left: control.left
right: line.left
bottom: label.text ? label.top : control.bottom
margins: 5
}
clip: true
}
}

View File

@ -0,0 +1,17 @@
import QtQuick
import QtQuick.Layouts
Item {
property string title
default property alias content: container.data
clip: true
RowLayout{
id: container
spacing: 0
anchors{
top:parent.top
bottom:parent.bottom
left: parent.left
}
}
}

View File

@ -0,0 +1,35 @@
import QtQuick
import QtQuick.Controls
import RibbonUI
TextEdit {
id: control
readOnly: true
color: dark_mode ? "white" : "black"
property bool dark_mode: RibbonTheme.dark_mode
property bool view_only: false
padding: 0
topPadding: 0
leftPadding: 0
rightPadding: 0
bottomPadding: 0
selectByMouse: true
selectionColor: dark_mode ? "#4F5E7F" : "#BECDE8"
selectedTextColor: dark_mode ? "white" : "black"
wrapMode: TextEdit.WrapAnywhere
onSelectedTextChanged: {
control.forceActiveFocus()
}
enabled: !view_only
font.family: Qt.platform.os === "osx" ? "PingFang SC" : "Microsoft YaHei UI"
MouseArea{
anchors.fill: parent
cursorShape: Qt.IBeamCursor
acceptedButtons: Qt.RightButton
onClicked: control.echoMode !== TextInput.Password && menu.popup()
}
RibbonTextBoxMenu{
id:menu
input_item: control
}
}

View File

@ -0,0 +1,46 @@
import QtQuick
import QtQuick.Controls
import RibbonUI
RibbonMenu{
property var input_item
id:menu
width: 100
onVisibleChanged: {
input_item.forceActiveFocus()
}
Connections{
target: input_item
function onTextChanged() {
menu.close()
}
}
RibbonMenuItem{
text: qsTr("Cut")
visible: input_item.selectedText !== "" && !input_item.readOnly
onClicked: {
input_item.cut()
}
}
RibbonMenuItem{
text: qsTr("Copy")
visible: input_item.selectedText !== ""
onClicked: {
input_item.copy()
}
}
RibbonMenuItem{
text: qsTr("Paste")
visible: input_item.canPaste
onClicked: {
input_item.paste()
}
}
RibbonMenuItem{
text: qsTr("Select All")
visible: input_item.text !== ""
onClicked: {
input_item.selectAll()
}
}
}

View File

@ -0,0 +1,112 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import RibbonUI
Item{
id: control
property alias text: textedit.text
property alias icon_source: textedit.icon_source
property alias show_clear_btn: textedit.show_clear_btn
property alias textedit: textedit
property int max_height: 80
property bool dark_mode: RibbonTheme.dark_mode
signal commit()
width: 150
height: Math.min(flickview.contentHeight, max_height)
Flickable{
id: flickview
anchors.fill: parent
contentWidth: parent.width
contentHeight: textedit.implicitHeight
ScrollBar.vertical: ScrollBar {
anchors.right: flickview.right
anchors.rightMargin: 2
}
boundsBehavior: Flickable.StopAtBounds
clip: true
TextArea.flickable:TextArea {
id: textedit
property int icon_source
property bool show_clear_btn: true
focus: true
color: dark_mode ? "white" : "black"
padding: 5
leftPadding: icon.visible ? icon.contentWidth + padding*2 : padding
rightPadding: clear_btn.visible ? clear_btn.width + padding*2 : padding
placeholderText: qsTr("Please input:")
placeholderTextColor: dark_mode ? Qt.rgba(255,255,255,0.5) : Qt.rgba(0,0,0,0.5)
selectByMouse: true
selectionColor: dark_mode ? "#4F5E7F" : "#BECDE8"
selectedTextColor: dark_mode ? "white" : "black"
wrapMode: Text.WrapAnywhere
opacity: enabled ? 1.0 : 0.3
signal commit()
onCommit: {
cursorVisible = false
control.commit()
}
background: Rectangle{
id:bg
radius: 4
color: dark_mode ? "#383838" : "#FFFFFF"
border.color: textedit.cursorVisible ? dark_mode ? "#869CCD" : "#486495" : dark_mode ? "#5E5F5E" : "#B9B9B8"
border.width: 1
Behavior on color {
ColorAnimation {
duration: 60
easing.type: Easing.OutSine
}
}
}
Keys.onEnterPressed: commit()
Keys.onReturnPressed: commit()
MouseArea{
anchors.fill: parent
cursorShape: Qt.IBeamCursor
acceptedButtons: Qt.RightButton
onClicked: textedit.echoMode !== TextInput.Password && menu.popup()
focus: true
}
RibbonTextBoxMenu{
id:menu
input_item: textedit
}
}
}
RibbonIcon{
id: icon
anchors{
left: parent.left
leftMargin: textedit.padding
verticalCenter: parent.verticalCenter
}
icon_source: textedit.icon_source
icon_size: 26 - textedit.padding
visible: icon_source
color: dark_mode ? "white" : "black"
Behavior on color {
ColorAnimation {
duration: 60
easing.type: Easing.OutSine
}
}
}
RibbonButton{
id: clear_btn
anchors{
right: parent.right
rightMargin: textedit.padding
verticalCenter: parent.verticalCenter
}
show_bg: false
show_hovered_bg: false
tip_text: qsTr("Clear")
icon_source: RibbonIcons.Dismiss
height: 26 - textedit.padding
width: height
visible: textedit.text&&show_clear_btn&&textedit.cursorVisible
onClicked: textedit.clear()
}
}

View File

@ -0,0 +1,150 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import RibbonUI
Item {
id: control
height: 30
property string title: Window.window.title
property bool show_style_switch: true
property bool show_darkmode_btn: true
property bool dark_mode: RibbonTheme.dark_mode
property bool modern_style: RibbonTheme.modern_style
property string title_color: modern_style ? "transparent" : dark_mode ? "#282828" : "#2C59B7"
property string title_text_color: modern_style ? dark_mode ? "white" : "black" : "white"
default property alias content: left_container.data
property alias left_content: left_container.data
property alias right_content: right_container.data
anchors {
top: parent.top
left: parent.left
right: parent.right
}
z: 100
Rectangle{
id: bg
anchors.fill: parent
color: title_color
Behavior on color {
ColorAnimation {
duration: 60
easing.type: Easing.OutSine
}
}
}
Text {
id: title_text
anchors.centerIn: parent
text: control.title
font.family: Qt.platform.os === "osx" ? "PingFang SC" : "Microsoft YaHei UI"
color: title_text_color
Behavior on color {
ColorAnimation {
duration: 60
easing.type: Easing.OutSine
}
}
}
RowLayout{
id: left_container
spacing: 1
anchors{
top: parent.top
left: parent.left
bottom: parent.bottom
leftMargin: Qt.platform.os === "osx" ? 65 : 10
}
Layout.maximumWidth: (parent.width - title_text.contentWidth) / 2
}
RowLayout{
id: right_container
spacing: 1
anchors{
top: parent.top
right: parent.right
bottom: parent.bottom
rightMargin: 10
}
Layout.maximumWidth: (parent.width - title_text.contentWidth) / 2
layoutDirection: Qt.RightToLeft
RowLayout{
visible: Qt.platform.os !== "osx"
layoutDirection: Qt.RightToLeft
spacing: 0
Layout.rightMargin: Qt.platform.os === "osx" ? -5 : 0
RibbonButton{
show_bg:false
icon_source: RibbonIcons.Dismiss
icon_source_filled: RibbonIcons_Filled.Dismiss
text_color: titleBar.title_text_color
hover_color: "#ED6B5E"
pressed_color: "#B55149"
text_color_reverse: false
tip_text: qsTr("Close")
onClicked: Window.window.close()
}
RibbonButton{
show_bg:false
icon_source: RibbonIcons.Subtract
icon_source_filled: RibbonIcons_Filled.Subtract
text_color: titleBar.title_text_color
hover_color: "#F4BE4F"
pressed_color: "#B78F3B"
text_color_reverse: false
tip_text: qsTr("Minimize")
font.bold: pressed || checked
onClicked: Window.window.visibility = Window.Minimized
}
RibbonButton{
show_bg:false
icon_source: Window.window.visibility === Window.Maximized ? RibbonIcons.ArrowMinimize : RibbonIcons.ArrowMaximize
text_color: titleBar.title_text_color
hover_color: "#61C554"
pressed_color: "#48953F"
text_color_reverse: false
tip_text: Window.window.visibility === Window.Maximized ? qsTr("Restore") : qsTr("Maximize")
onClicked: {
if (Window.window.visibility === Window.Maximized)
Window.window.visibility = Window.Windowed
else
Window.window.visibility = Window.Maximized
}
}
}
RibbonSwitchButton{
text: qsTr("Style")
grabber_text: checked ? qsTr("Modern") : qsTr("Classic")
text_color: titleBar.title_text_color
grabber_color: "#F9F9F9"
grabber_checked_color: "#BEC1C9"
grabber_unchecked_color: "#334668"
grabber_text_unchecked_color: "white"
grabber_text_checked_color: "black"
onClicked: RibbonTheme.modern_style = checked
visible: show_style_switch
}
RibbonButton{
show_bg:false
icon_source: RibbonIcons.DarkTheme
icon_source_filled: RibbonIcons_Filled.DarkTheme
checkable: true
tip_text: qsTr("Dark Mode")
hover_color: Qt.rgba(0,0,0, 0.3)
pressed_color: Qt.rgba(0,0,0, 0.4)
text_color: title_text_color
text_color_reverse: false
onClicked: {
RibbonTheme.theme_mode = checked ? RibbonThemeType.Dark : RibbonThemeType.Light
}
checked: RibbonTheme.dark_mode
visible: show_darkmode_btn
}
}
}

View File

@ -0,0 +1,25 @@
import QtQuick
import QtQuick.Controls
import Qt5Compat.GraphicalEffects
import RibbonUI
ToolTip {
id: control
delay: 1000
font.pixelSize: 10
font.family: Qt.platform.os === "osx" ? "PingFang SC" : "Microsoft YaHei UI"
contentItem: Text {
text: control.text
font: control.font
color: RibbonTheme.dark_mode ? "white" : "black"
}
background: Rectangle {
radius: 3
color: RibbonTheme.dark_mode ? "#2C2C29" : "#E0E0E2"
layer.enabled: true
layer.effect: RibbonShadow{}
border.color: dark_mode ? "#5C5D5D" : "#B5B4B5"
border.width: 1
}
}

View File

@ -0,0 +1,86 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Qt5Compat.GraphicalEffects
import RibbonUI
Item {
id: root
default property alias content: container.data
property bool modern_style: RibbonTheme.modern_style
property bool dark_mode: RibbonTheme.dark_mode
property int spacing: 5
property int top_padding: 0
property int bottom_padding: 0
z:-2
clip: true
anchors{
left: parent.left
right:parent.right
}
Rectangle{
id:bg
anchors.fill: parent
color: dark_mode ? "#282828" : "#ECECEC"
visible: !modern_style
}
RibbonBlur{
id: top_mask
anchors{
left: parent.left
right: parent.right
top: parent.top
}
height: Math.abs(top_padding)
target: flickview
mask_opacity: 0
visible: flickview.contentY > container_bg.anchors.topMargin
clip: true
target_rect: Qt.rect(x,y-top_padding,width,height)
}
Item{
id: clipper
anchors.horizontalCenter: parent.horizontalCenter
anchors.top:top_mask.bottom
implicitHeight: parent.height - Math.abs(top_padding) - Math.abs(bottom_padding)
implicitWidth: parent.width
clip: true
Flickable{
id:flickview
anchors.fill: parent
contentWidth: parent.width
contentHeight: container.height
ScrollBar.vertical: ScrollBar {
anchors.right: flickview.right
anchors.rightMargin: 2
}
boundsBehavior: Flickable.StopAtBounds
ColumnLayout{
id:container
anchors{
top: parent.top
horizontalCenter: parent.horizontalCenter
}
width: parent.width
}
}
}
RibbonBlur{
id: bottom_mask
anchors{
left: parent.left
right: parent.right
bottom: parent.bottom
}
height: Math.abs(bottom_padding)
target: flickview
mask_opacity: 0
visible: bottom_padding
clip: true
target_rect: Qt.rect(x,y-top_padding,width,height)
}
}

36
lib_source/qmldir Normal file
View File

@ -0,0 +1,36 @@
module RibbonUI
linktarget RibbonUI
optional plugin RibbonUI
classname RibbonUIPlugin
typeinfo RibbonUI.qmltypes
prefer :/RibbonUI/
RibbonTabBar 1.0 qml/RibbonTabBar.qml
RibbonTabButton 1.0 qml/RibbonTabButton.qml
RibbonView 1.0 qml/RibbonView.qml
RibbonTabPage 1.0 qml/RibbonTabPage.qml
RibbonTabGroup 1.0 qml/RibbonTabGroup.qml
RibbonButton 1.0 qml/RibbonButton.qml
RibbonBottomBar 1.0 qml/RibbonBottomBar.qml
RibbonIcon 1.0 qml/RibbonIcon.qml
RibbonToolTip 1.0 qml/RibbonToolTip.qml
RibbonTitleBar 1.0 qml/RibbonTitleBar.qml
RibbonSlider 1.0 qml/RibbonSlider.qml
RibbonSwitchButton 1.0 qml/RibbonSwitchButton.qml
RibbonCheckBox 1.0 qml/RibbonCheckBox.qml
RibbonMenu 1.0 qml/RibbonMenu.qml
RibbonMenuItem 1.0 qml/RibbonMenuItem.qml
RibbonShadow 1.0 qml/RibbonShadow.qml
RibbonBlur 1.0 qml/RibbonBlur.qml
RibbonMenuSeparator 1.0 qml/RibbonMenuSeparator.qml
RibbonPaperView 1.0 qml/RibbonPaperView.qml
RibbonPushButton 1.0 qml/RibbonPushButton.qml
RibbonRectangle 1.0 qml/RibbonRectangle.qml
RibbonText 1.0 qml/RibbonText.qml
RibbonTextBoxMenu 1.0 qml/RibbonTextBoxMenu.qml
RibbonPopup 1.0 qml/RibbonPopup.qml
RibbonPopupDialog 1.0 qml/RibbonPopupDialog.qml
RibbonLineEdit 1.0 qml/RibbonLineEdit.qml
RibbonTextEdit 1.0 qml/RibbonTextEdit.qml
RibbonComboBox 1.0 qml/RibbonComboBox.qml
RibbonSpinBox 1.0 qml/RibbonSpinBox.qml

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

View File

@ -0,0 +1,66 @@
#include "ribbontheme.h"
#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0))
#include <QStyleHints>
#elif ((QT_VERSION >= QT_VERSION_CHECK(6, 2, 1)))
#include <QtGui/qpa/qplatformtheme.h>
#include <QtGui/private/qguiapplication_p.h>
#else
#include <QPalette>
#endif
#include <QGuiApplication>
RibbonTheme::RibbonTheme()
{
connect(this, &RibbonTheme::theme_modeChanged, this, [=](){
emit dark_modeChanged();
});
_theme_mode = RibbonThemeType::ThemeMode::System;
_system_theme_mode = current_theme();
modern_style(false);
qApp->installEventFilter(this);
}
RibbonTheme* RibbonTheme::instance(){
static RibbonTheme instance;
return &instance;
}
bool RibbonTheme::eventFilter(QObject *obj, QEvent *event)
{
Q_UNUSED(obj);
if (event->type() == QEvent::ApplicationPaletteChange || event->type() == QEvent::ThemeChange)
{
_system_theme_mode = current_theme();
if (_theme_mode == RibbonThemeType::ThemeMode::System)
Q_EMIT theme_modeChanged();
event->accept();
return true;
}
return false;
}
RibbonThemeType::ThemeMode RibbonTheme::current_theme()
{
#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0))
return (QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Light) ?
RibbonThemeType::ThemeMode::Light : RibbonThemeType::ThemeMode::Dark;
#elif ((QT_VERSION >= QT_VERSION_CHECK(6, 2, 1)))
if (const QPlatformTheme * const theme = QGuiApplicationPrivate::platformTheme()) {
return (theme->appearance() == QPlatformTheme::Appearance::Light) ?
RibbonThemeType::ThemeMode::Light : RibbonThemeType::ThemeMode::Dark;
}
return RibbonThemeType::ThemeMode::Light;
#else
QPalette palette = qApp->palette();
QColor color = palette.color(QPalette::Window).rgb();
return (color.red() * 0.2126 + color.green() * 0.7152 + color.blue() * 0.0722 > 255 / 2) ? RibbonThemeType::ThemeMode::Light : RibbonThemeType::ThemeMode::Dark;
#endif
}
bool RibbonTheme::dark_mode()
{
return _theme_mode == RibbonThemeType::ThemeMode::System ? _system_theme_mode == RibbonThemeType::ThemeMode::Dark
: _theme_mode == RibbonThemeType::ThemeMode::Dark;
}

28
lib_source/ribbontheme.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef RIBBONTHEME_H
#define RIBBONTHEME_H
#include <QQuickItem>
#include "definitions.h"
class RibbonTheme : public QQuickItem
{
Q_OBJECT
QML_ELEMENT
QML_SINGLETON
QML_NAMED_ELEMENT(RibbonTheme)
Q_PROPERTY(bool dark_mode READ dark_mode() NOTIFY dark_modeChanged FINAL)
Q_PROPERTY_RW(RibbonThemeType::ThemeMode,theme_mode)
Q_PROPERTY_RW(bool,modern_style)
public:
RibbonTheme();
static RibbonTheme* instance();
Q_SIGNAL void dark_modeChanged();
bool dark_mode();
private:
bool eventFilter(QObject *obj, QEvent *event);
RibbonThemeType::ThemeMode current_theme();
RibbonThemeType::ThemeMode _system_theme_mode;
};
#endif // RIBBONTHEME_H

16
lib_source/ribbonui.cpp Normal file
View File

@ -0,0 +1,16 @@
#include "ribbonui.h"
#define STR(x) #x
#define JOIN(a,b,c,d) STR(a.b.c.d)
#define VER_JOIN(x) JOIN x
RibbonUI::RibbonUI(QQuickItem *parent)
: QQuickItem(parent)
{
version(VER_JOIN((RIBBONUI_VERSION)));
}
RibbonUI* RibbonUI::instance(){
static RibbonUI instance;
return &instance;
}

19
lib_source/ribbonui.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef RIBBONUI_H
#define RIBBONUI_H
#include <QQuickItem>
#include "definitions.h"
class RibbonUI : public QQuickItem
{
Q_OBJECT
QML_ELEMENT
QML_SINGLETON
QML_NAMED_ELEMENT(RibbonUI)
Q_PROPERTY_RW(QString, version)
public:
explicit RibbonUI(QQuickItem *parent = nullptr);
static RibbonUI* instance();
};
#endif // RIBBONUI_H

View File

@ -0,0 +1,34 @@
[CmdletBinding()]
param (
[string] $archiveName, [string] $targetName
)
# 外部环境变量包括:
# archiveName: ${{ matrix.qt_ver }}-${{ matrix.qt_arch }}
# archiveName: 5.15.2-win64_mingw81
$scriptDir = $PSScriptRoot
$currentDir = Get-Location
Write-Host "currentDir" $currentDir
Write-Host "scriptDir" $scriptDir
function Main() {
New-Item -ItemType Directory $archiveName
# 拷贝exe
Copy-Item D:\a\RibbonUI\RibbonUI\build\example\* $archiveName\ -Force -Recurse | Out-Null
# 拷贝依赖
windeployqt --qmldir . --plugindir $archiveName\plugins --no-translations --compiler-runtime $archiveName\$targetName
# 删除不必要的文件
$excludeList = @("*.qmlc", "*.ilk", "*.exp", "*.lib", "*.pdb")
Remove-Item -Path $archiveName -Include $excludeList -Recurse -Force
# 打包zip
Compress-Archive -Path $archiveName $archiveName'.zip'
}
if ($null -eq $archiveName || $null -eq $targetName) {
Write-Host "args missing, archiveName is" $archiveName ", targetName is" $targetName
return
}
Main

View File

@ -0,0 +1,51 @@
[CmdletBinding()]
param (
[string] $archiveName, [string] $targetName
)
# 外部环境变量包括:
# archiveName: ${{ matrix.qt_ver }}-${{ matrix.qt_arch }}
# winSdkDir: ${{ steps.build.outputs.winSdkDir }}
# winSdkVer: ${{ steps.build.outputs.winSdkVer }}
# vcToolsInstallDir: ${{ steps.build.outputs.vcToolsInstallDir }}
# vcToolsRedistDir: ${{ steps.build.outputs.vcToolsRedistDir }}
# msvcArch: ${{ matrix.msvc_arch }}
# winSdkDir: C:\Program Files (x86)\Windows Kits\10\
# winSdkVer: 10.0.19041.0\
# vcToolsInstallDir: C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.28.29333\
# vcToolsRedistDir: C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Redist\MSVC\14.28.29325\
# archiveName: 5.9.9-win32_msvc2015
# msvcArch: x86
$scriptDir = $PSScriptRoot
$currentDir = Get-Location
Write-Host "currentDir" $currentDir
Write-Host "scriptDir" $scriptDir
function Main() {
New-Item -ItemType Directory $archiveName
# 拷贝exe
Copy-Item D:\a\RibbonUI\RibbonUI\build\example\* $archiveName\ -Force -Recurse | Out-Null
# 拷贝依赖
windeployqt --qmldir . --plugindir $archiveName\plugins --no-translations --compiler-runtime $archiveName\$targetName
# 删除不必要的文件
$excludeList = @("*.qmlc", "*.ilk", "*.exp", "*.lib", "*.pdb")
Remove-Item -Path $archiveName -Include $excludeList -Recurse -Force
# 拷贝vcRedist dll
$redistDll="{0}{1}\*.CRT\*.dll" -f $env:vcToolsRedistDir.Trim(),$env:msvcArch
Copy-Item $redistDll $archiveName\
# 拷贝WinSDK dll
$sdkDll="{0}Redist\{1}ucrt\DLLs\{2}\*.dll" -f $env:winSdkDir.Trim(),$env:winSdkVer.Trim(),$env:msvcArch
Copy-Item $sdkDll $archiveName\
# 打包zip
Compress-Archive -Path $archiveName $archiveName'.zip'
}
if ($null -eq $archiveName || $null -eq $targetName) {
Write-Host "args missing, archiveName is" $archiveName ", targetName is" $targetName
return
}
Main