调整了布局

dev-VirtualTexture
wuyize 2022-10-23 19:25:43 +08:00
parent d7329e78e6
commit 341a03be81
49 changed files with 7184 additions and 27 deletions

View File

@ -4,6 +4,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00
VisualStudioVersion = 17.2.32519.379
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ArchitectureColoredPainting", "ArchitectureColoredPainting\ArchitectureColoredPainting.vcxproj", "{3FE96A33-2BB7-4686-A710-3EB8E3BBD709}"
ProjectSection(ProjectDependencies) = postProject
{B982E745-C0B1-46B3-A27B-743AF105F2D0} = {B982E745-C0B1-46B3-A27B-743AF105F2D0}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "QGoodWindow", "QGoodWindow\QGoodWindow.vcxproj", "{B982E745-C0B1-46B3-A27B-743AF105F2D0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -15,6 +20,10 @@ Global
{3FE96A33-2BB7-4686-A710-3EB8E3BBD709}.Debug|x64.Build.0 = Debug|x64
{3FE96A33-2BB7-4686-A710-3EB8E3BBD709}.Release|x64.ActiveCfg = Release|x64
{3FE96A33-2BB7-4686-A710-3EB8E3BBD709}.Release|x64.Build.0 = Release|x64
{B982E745-C0B1-46B3-A27B-743AF105F2D0}.Debug|x64.ActiveCfg = Debug|x64
{B982E745-C0B1-46B3-A27B-743AF105F2D0}.Debug|x64.Build.0 = Debug|x64
{B982E745-C0B1-46B3-A27B-743AF105F2D0}.Release|x64.ActiveCfg = Release|x64
{B982E745-C0B1-46B3-A27B-743AF105F2D0}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -32,7 +32,7 @@
</ImportGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="QtSettings">
<QtInstall>5.15.2_msvc2019_64</QtInstall>
<QtModules>core;gui;widgets</QtModules>
<QtModules>core;gui;widgets;winextras</QtModules>
<QtBuildConfig>debug</QtBuildConfig>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="QtSettings">
@ -61,11 +61,13 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>$(SolutionDir)QGoodWindow;%(AdditionalIncludeDirectories);$(Qt_INCLUDEPATH_)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>$(SolutionDir)QGoodWindow;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="Configuration">
@ -95,9 +97,12 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="src\CaptionButton.cpp" />
<ClCompile Include="src\Editor\EditorWidget.cpp" />
<ClCompile Include="src\IconWidget.cpp" />
<ClCompile Include="src\main.cpp" />
<ClCompile Include="src\MainWindow.cpp" />
<ClCompile Include="src\NavigationBarWidget.cpp" />
<ClCompile Include="src\Renderer\BvhTree.cpp" />
<ClCompile Include="src\Renderer\Camera.cpp" />
<ClCompile Include="src\Renderer\CubicBezier.cpp" />
@ -113,12 +118,17 @@
<ClCompile Include="src\Renderer\ShortCutTree.cpp" />
<ClCompile Include="src\Renderer\StraightLine.cpp" />
<ClCompile Include="src\SvgParser.cpp" />
<ClCompile Include="src\TitleWidget.cpp" />
<QtRcc Include="MainWindow.qrc" />
<QtUic Include="EditorWidget.ui" />
<QtUic Include="FramelessWindow.ui" />
<QtUic Include="MainWindow.ui" />
<QtUic Include="NavigationBarWidget.ui" />
<QtUic Include="RendererWidget.ui" />
</ItemGroup>
<ItemGroup>
<None Include="darkstyle.qss" />
<None Include="lightstyle.qss" />
<None Include="Shaders\depth_init.comp" />
<None Include="Shaders\depth_mipmap.comp" />
<None Include="Shaders\final.frag" />
@ -137,6 +147,10 @@
<None Include="Shaders\ssgi.comp" />
</ItemGroup>
<ItemGroup>
<QtMoc Include="src\TitleWidget.h" />
<QtMoc Include="src\IconWidget.h" />
<QtMoc Include="src\CaptionButton.h" />
<QtMoc Include="src\NavigationBarWidget.h" />
<QtMoc Include="src\Renderer\RendererWidget.h" />
<ClInclude Include="src\SvgParser.h" />
<QtMoc Include="src\MainWindow.h" />
@ -156,6 +170,11 @@
<ClInclude Include="src\Renderer\StraightLine.h" />
<QtMoc Include="src\Renderer\RendererGLWidget.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\QGoodWindow\QGoodWindow.vcxproj">
<Project>{b982e745-c0b1-46b3-a27b-743af105f2d0}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Condition="Exists('$(QtMsBuild)\qt.targets')">
<Import Project="$(QtMsBuild)\qt.targets" />

View File

@ -9,10 +9,6 @@
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>qrc;rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Form Files">
<UniqueIdentifier>{99349809-55BA-4b9d-BF79-8FDBB0286EB3}</UniqueIdentifier>
<Extensions>ui</Extensions>
@ -21,9 +17,6 @@
<UniqueIdentifier>{639EADAA-A684-42e4-A9AD-28FC9BCB8F7C}</UniqueIdentifier>
<Extensions>ts</Extensions>
</Filter>
<Filter Include="Resource Files\Shaders">
<UniqueIdentifier>{60515177-3da7-420f-8f5b-27c16bb2b77b}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\Editor">
<UniqueIdentifier>{bd91d673-6674-478d-a43d-54ac6c09d77f}</UniqueIdentifier>
</Filter>
@ -36,14 +29,23 @@
<Filter Include="Source Files\Renderer">
<UniqueIdentifier>{f52671e3-3263-45e6-8d6c-976d19dc7e24}</UniqueIdentifier>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{7a710fdd-46c9-44ff-aae7-7809e9c34d23}</UniqueIdentifier>
</Filter>
<Filter Include="Resource Files\Shaders">
<UniqueIdentifier>{60515177-3da7-420f-8f5b-27c16bb2b77b}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<QtRcc Include="MainWindow.qrc">
<Filter>Resource Files</Filter>
</QtRcc>
<QtUic Include="MainWindow.ui">
<Filter>Form Files</Filter>
</QtUic>
<QtUic Include="NavigationBarWidget.ui">
<Filter>Form Files</Filter>
</QtUic>
<QtUic Include="FramelessWindow.ui">
<Filter>Form Files</Filter>
</QtUic>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\Editor\EditorWidget.cpp">
@ -100,6 +102,18 @@
<ClCompile Include="src\Renderer\RendererWidget.cpp">
<Filter>Source Files\Renderer</Filter>
</ClCompile>
<ClCompile Include="src\NavigationBarWidget.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CaptionButton.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\IconWidget.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\TitleWidget.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<QtMoc Include="src\Renderer\RendererGLWidget.h">
@ -114,6 +128,18 @@
<QtMoc Include="src\Renderer\RendererWidget.h">
<Filter>Header Files\Renderer</Filter>
</QtMoc>
<QtMoc Include="src\NavigationBarWidget.h">
<Filter>Header Files</Filter>
</QtMoc>
<QtMoc Include="src\CaptionButton.h">
<Filter>Header Files</Filter>
</QtMoc>
<QtMoc Include="src\IconWidget.h">
<Filter>Header Files</Filter>
</QtMoc>
<QtMoc Include="src\TitleWidget.h">
<Filter>Header Files</Filter>
</QtMoc>
</ItemGroup>
<ItemGroup>
<None Include="Shaders\shader.frag">
@ -164,6 +190,12 @@
<None Include="Shaders\ssgi.comp">
<Filter>Resource Files\Shaders</Filter>
</None>
<None Include="darkstyle.qss">
<Filter>Resource Files</Filter>
</None>
<None Include="lightstyle.qss">
<Filter>Resource Files</Filter>
</None>
</ItemGroup>
<ItemGroup>
<QtUic Include="EditorWidget.ui">
@ -217,4 +249,9 @@
<Filter>Source Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<QtRcc Include="MainWindow.qrc">
<Filter>Resource Files</Filter>
</QtRcc>
</ItemGroup>
</Project>

View File

@ -31,6 +31,9 @@
<property name="text">
<string>纹理编辑</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
</layout>

View File

@ -0,0 +1,208 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FramelessWindow</class>
<widget class="QWidget" name="FramelessWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>560</width>
<height>544</height>
</rect>
</property>
<property name="windowTitle">
<string/>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QWidget" name="windowFrame" native="true">
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="styleSheet">
<string notr="true">#windowFrame{ background-color:palette(Window);}</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>1</number>
</property>
<property name="topMargin">
<number>1</number>
</property>
<property name="rightMargin">
<number>1</number>
</property>
<property name="bottomMargin">
<number>1</number>
</property>
<item>
<widget class="TitleWidget" name="windowTitlebar" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="styleSheet">
<string notr="true">#windowTitlebar{border: 0px none palette(base); border-top-left-radius:5px; border-top-right-radius:5px; background-color:palette(shadow); height:20px;}</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,0,0,0,0,0">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="spacer">
<property name="minimumSize">
<size>
<width>4</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>4</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="IconWidget" name="icon" native="true">
<property name="minimumSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="contextMenuPolicy">
<enum>Qt::NoContextMenu</enum>
</property>
<property name="styleSheet">
<string notr="true">#icon {background-color:palette(shadow);}</string>
</property>
</widget>
</item>
<item>
<widget class="TitleWidget" name="titleWidget" native="true"/>
</item>
<item>
<widget class="CaptionButton" name="minimizeButton" native="true"/>
</item>
<item>
<widget class="CaptionButton" name="restoreButton" native="true"/>
</item>
<item>
<widget class="CaptionButton" name="maximizeButton" native="true"/>
</item>
<item>
<widget class="CaptionButton" name="closeButton" native="true"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="windowContent" native="true">
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="styleSheet">
<string notr="true">#windowContent{
border: 0px none palette(base);
border-radius:0px 0px 5px 5px;
}</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
<customwidget>
<class>CaptionButton</class>
<extends>QWidget</extends>
<header>CaptionButton.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>IconWidget</class>
<extends>QWidget</extends>
<header>IconWidget.h</header>
</customwidget>
<customwidget>
<class>TitleWidget</class>
<extends>QWidget</extends>
<header>TitleWidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@ -16,5 +16,15 @@
<file>Shaders/model_shadow.geom</file>
<file>Shaders/shadow_mapping.comp</file>
<file>Shaders/ssgi.comp</file>
<file>images/icon.png</file>
<file>images/icon_window_close.png</file>
<file>images/icon_window_maximize.png</file>
<file>images/icon_window_minimize.png</file>
<file>images/icon_window_restore.png</file>
<file>darkstyle.qss</file>
<file>lightstyle.qss</file>
</qresource>
<qresource prefix="/qt/etc">
<file>qt.conf</file>
</qresource>
</RCC>

View File

@ -13,6 +13,9 @@
<property name="windowTitle">
<string>MainWindow</string>
</property>
<property name="styleSheet">
<string notr="true">font: 10pt &quot;Segoe UI, Microsoft YaHei UI&quot;;</string>
</property>
<widget class="QWidget" name="centralWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@ -21,6 +24,9 @@
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
@ -34,7 +40,10 @@
<number>0</number>
</property>
<item>
<layout class="QVBoxLayout" name="verticalLayout_4" stretch="0">
<layout class="QVBoxLayout" name="verticalLayout_4" stretch="1">
<property name="spacing">
<number>0</number>
</property>
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
@ -42,10 +51,29 @@
<widget class="QTabWidget" name="tabWidget">
<property name="font">
<font>
<family>Microsoft YaHei UI</family>
<pointsize>13</pointsize>
<family>Segoe UI, Microsoft YaHei UI</family>
<pointsize>10</pointsize>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
</font>
</property>
<property name="styleSheet">
<string notr="true">QTabBar::tab {
height: 0px;
margin-top:0px;
}
QTabWidget::tab-bar
{
height: 0px;
top:0px;
}
QTabWidget::pane {
border: 0px;
background-color: rgba(0, 0, 0, 0);
}
</string>
</property>
<property name="tabPosition">
<enum>QTabWidget::North</enum>
</property>
@ -53,7 +81,13 @@
<enum>QTabWidget::Rounded</enum>
</property>
<property name="currentIndex">
<number>1</number>
<number>0</number>
</property>
<property name="elideMode">
<enum>Qt::ElideNone</enum>
</property>
<property name="tabsClosable">
<bool>false</bool>
</property>
<widget class="EditorWidget" name="editorWidget">
<attribute name="title">

View File

@ -0,0 +1,100 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>NavigationBarWidgetClass</class>
<widget class="QWidget" name="NavigationBarWidgetClass">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>612</width>
<height>41</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>40</height>
</size>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string>NavigationBarWidget</string>
</property>
<property name="styleSheet">
<string notr="true">QRadioButton::indicator {
width: 0px;
border: 0px;
background-color: rgba(0, 0, 0, 0);
}</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QPushButton" name="radioButton0">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>纹理编辑</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="radioButton1">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>场景渲染</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>

View File

@ -13,7 +13,7 @@
<property name="windowTitle">
<string>RendererWidget</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,1">
<property name="leftMargin">
<number>0</number>
</property>
@ -26,6 +26,22 @@
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0">
<property name="sizeConstraint">

View File

@ -0,0 +1,297 @@
QToolTip{
color:palette(text);
background-color:palette(base);
border:1px solid palette(highlight);
border-radius:0px;
}
QStatusBar{
background-color:qlineargradient(x1:0,y1:0,x2:0,y2:1,stop:0 rgba(25,25,25,127),stop:1 rgba(53,53,53,75));
color:palette(mid);
}
QMenuBar{
background-color:qlineargradient(x1:0,y1:0,x2:0,y2:1,stop:0 rgba(25,25,25,127),stop:1 rgba(53,53,53,75));
border-bottom:2px solid rgba(25,25,25,75);
}
QMenuBar::item{
spacing:2px;
padding:3px 4px;
background:transparent;
}
QMenuBar::item:selected{
background-color:qlineargradient(x1:0,y1:0,x2:0,y2:1,stop:0 rgba(106,106,106,255),stop:1 rgba(106,106,106,75));
border-left:1px solid rgba(106,106,106,127);
border-right:1px solid rgba(106,106,106,127);
}
QMenuBar::item:pressed{
background-color:palette(highlight);
color:rgba(255,255,255,255);
border-left:1px solid rgba(25,25,25,127);
border-right:1px solid rgba(25,25,25,127);
}
QMenu{
background-color:palette(window);
border:1px solid palette(shadow);
}
QMenu::item{
padding:3px 15px 3px 15px;
border:1px solid transparent;
}
QMenu::item:disabled{
background-color:rgba(35,35,35,127);
color:palette(disabled);
}
QMenu::item:selected{
border-color:rgba(147,191,236,127);
background:palette(highlight);
color:rgba(255,255,255,255);
}
QMenu::icon:checked{
background-color:qlineargradient(x1:0,y1:1,x2:0,y2:0,stop:0 rgba(25,25,25,127),stop:1 rgba(53,53,53,75));
border:1px solid palette(highlight);
border-radius:2px;
}
QMenu::separator{
height:1px;
background:palette(alternate-base);
margin-left:5px;
margin-right:5px;
}
QMenu::indicator{
width:15px;
height:15px;
}
QMenu::indicator:non-exclusive:checked{
padding-left:2px;
}
QMenu::indicator:non-exclusive:unchecked{
padding-left:2px;
}
QMenu::indicator:exclusive:checked{
padding-left:2px;
}
QMenu::indicator:exclusive:unchecked{
padding-left:2px;
}
QToolBar::top{
background-color:qlineargradient(x1:0,y1:0,x2:0,y2:1,stop:0 rgba(25,25,25,127),stop:1 rgba(53,53,53,75));
border-bottom:3px solid qlineargradient(x1:0,y1:0,x2:0,y2:1,stop:0 rgba(25,25,25,127),stop:1 rgba(53,53,53,75));
}
QToolBar::bottom{
background-color:qlineargradient(x1:0,y1:1,x2:0,y2:0,stop:0 rgba(25,25,25,127),stop:1 rgba(53,53,53,75));
border-top:3px solid qlineargradient(x1:0,y1:1,x2:0,y2:0,stop:0 rgba(25,25,25,127),stop:1 rgba(53,53,53,75));
}
QToolBar::left{
background-color:qlineargradient(x1:0,y1:0,x2:1,y2:0,stop:0 rgba(25,25,25,127),stop:1 rgba(53,53,53,75));
border-right:3px solid qlineargradient(x1:0,y1:0,x2:1,y2:0,stop:0 rgba(25,25,25,127),stop:1 rgba(53,53,53,75));
}
QToolBar::right{
background-color:qlineargradient(x1:1,y1:0,x2:0,y2:0,stop:0 rgba(25,25,25,127),stop:1 rgba(53,53,53,75));
border-left:3px solid qlineargradient(x1:1,y1:0,x2:0,y2:0,stop:0 rgba(25,25,25,127),stop:1 rgba(53,53,53,75));
}
QMainWindow::separator{
width:6px;
height:5px;
padding:2px;
}
QSplitter::handle:horizontal{
width:10px;
}
QSplitter::handle:vertical{
height:10px;
}
QMainWindow::separator:hover,QSplitter::handle:hover{
background:palette(highlight);
}
QDockWidget::title{
padding:4px;
background-color:qlineargradient(x1:0,y1:1,x2:0,y2:0,stop:0 rgba(25,25,25,127),stop:1 rgba(53,53,53,75));
border:1px solid rgba(25,25,25,75);
border-bottom:2px solid rgba(25,25,25,75);
}
QDockWidget{
titlebar-close-icon:url(:/darkstyle/icon_close.png);
titlebar-normal-icon:url(:/darkstyle/icon_restore.png);
}
QDockWidget::close-button,QDockWidget::float-button{
subcontrol-position:top right;
subcontrol-origin:margin;
position:absolute;
top:3px;
bottom:0px;
width:20px;
height:20px;
}
QDockWidget::close-button{
right:3px;
}
QDockWidget::float-button{
right:25px;
}
QGroupBox{
background-color:rgba(66,66,66,50%);
margin-top:27px;
border:1px solid rgba(25,25,25,127);
border-radius:4px;
}
QGroupBox::title{
subcontrol-origin:margin;
subcontrol-position:left top;
padding:4px 6px;
margin-left:3px;
background-color:qlineargradient(x1:0,y1:1,x2:0,y2:0,stop:0 rgba(25,25,25,127),stop:1 rgba(53,53,53,75));
border:1px solid rgba(25,25,25,75);
border-bottom:2px solid rgb(127,127,127);
border-top-left-radius:4px;
border-top-right-radius:4px;
}
QTabWidget::pane{
background-color:rgba(66,66,66,50%);
border-top:1px solid rgba(25,25,25,50%);
}
QTabWidget::tab-bar{
left:3px;
top:1px;
}
QTabBar{
background-color:transparent;
qproperty-drawBase:0;
border-bottom:1px solid rgba(25,25,25,50%);
}
QTabBar::tab{
padding:4px 6px;
background-color:qlineargradient(x1:0,y1:1,x2:0,y2:0,stop:0 rgba(25,25,25,127),stop:1 rgba(53,53,53,75));
border:1px solid rgba(25,25,25,75);
border-top-left-radius:4px;
border-top-right-radius:4px;
}
QTabBar::tab:selected,QTabBar::tab:hover{
background-color:qlineargradient(x1:0,y1:0,x2:0,y2:1,stop:0 rgba(53,53,53,127),stop:1 rgba(66,66,66,50%));
border-bottom-color:rgba(66,66,66,75%);
}
QTabBar::tab:selected{
border-bottom:2px solid palette(highlight);
}
QTabBar::tab::selected:disabled{
border-bottom:2px solid rgb(127,127,127);
}
QTabBar::tab:!selected{
margin-top:2px;
}
QTabBar::close-button {
border:1px solid transparent;
border-radius:2px;
}
QTabBar::close-button:hover {
background-color:qlineargradient(x1:0,y1:0,x2:0,y2:1,stop:0 rgba(106,106,106,255),stop:1 rgba(106,106,106,75));
border:1px solid palette(base);
}
QTabBar::close-button:pressed {
background-color:qlineargradient(x1:0,y1:1,x2:0,y2:0,stop:0 rgba(25,25,25,127),stop:1 rgba(53,53,53,75));
border:1px solid palette(base);
}
QCheckBox::indicator{
width:18px;
height:18px;
}
QRadioButton::indicator{
width:18px;
height:18px;
}
QTreeView, QTableView{
alternate-background-color:palette(window);
background:palette(base);
}
QTreeView QHeaderView::section, QTableView QHeaderView::section{
background-color:qlineargradient(x1:0,y1:1,x2:0,y2:0,stop:0 rgba(25,25,25,127),stop:1 rgba(53,53,53,75));
border-style:none;
border-bottom:1px solid palette(dark);
padding-left:5px;
padding-right:5px;
}
QTreeView::item:selected:disabled, QTableView::item:selected:disabled{
background:rgb(80,80,80);
}
QTreeView::branch{
background-color:palette(base);
}
QTreeView::branch:has-children:!has-siblings:closed,
QTreeView::branch:closed:has-children:has-siblings{
border-image:none;
}
QTreeView::branch:open:has-children:!has-siblings,
QTreeView::branch:open:has-children:has-siblings{
border-image:none;
}
QScrollBar:vertical{
background:palette(base);
border-top-right-radius:2px;
border-bottom-right-radius:2px;
width:16px;
margin:0px;
}
QScrollBar::handle:vertical{
background-color:palette(alternate-base);
border-radius:2px;
min-height:20px;
margin:2px 4px 2px 4px;
}
QScrollBar::handle:vertical:hover{
background-color:palette(highlight);
}
QScrollBar::add-line:vertical{
background:none;
height:0px;
subcontrol-position:right;
subcontrol-origin:margin;
}
QScrollBar::sub-line:vertical{
background:none;
height:0px;
subcontrol-position:left;
subcontrol-origin:margin;
}
QScrollBar:horizontal{
background:palette(base);
height:16px;
margin:0px;
}
QScrollBar::handle:horizontal{
background-color:palette(alternate-base);
border-radius:2px;
min-width:20px;
margin:4px 2px 4px 2px;
}
QScrollBar::handle:horizontal:hover{
background-color:palette(highlight);
}
QScrollBar::add-line:horizontal{
background:none;
width:0px;
subcontrol-position:bottom;
subcontrol-origin:margin;
}
QScrollBar::sub-line:horizontal{
background:none;
width:0px;
subcontrol-position:top;
subcontrol-origin:margin;
}
QSlider::handle:horizontal{
border-radius:4px;
border:1px solid rgba(25,25,25,255);
background-color:palette(alternate-base);
min-height:20px;
margin:0 -4px;
}
QSlider::handle:horizontal:hover{
background:palette(highlight);
}
QSlider::add-page:horizontal{
background:palette(base);
}
QSlider::sub-page:horizontal{
background:palette(highlight);
}
QSlider::sub-page:horizontal:disabled{
background:rgb(80,80,80);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 364 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 B

View File

@ -0,0 +1,2 @@
chcp 65001
"E:\Qt\Tools\QtCreator\bin\jom\jom.exe" %*

View File

@ -0,0 +1,2 @@
[Platforms]
WindowsArguments = fontengine=freetype

View File

@ -0,0 +1,261 @@
/*
The MIT License (MIT)
Copyright © 2018-2022 Antonio Dias
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "captionbutton.h"
CaptionButton::CaptionButton(QWidget *parent) : QWidget(parent)
{
m_is_active = false;
m_is_under_mouse = false;
m_is_pressed = false;
m_icon_dark = false;
setAttribute(Qt::WA_Hover);
}
CaptionButton::~CaptionButton()
{
}
QPixmap CaptionButton::drawIcon(const QPixmap &icon, bool active, bool force_light)
{
QImage tmp = icon.toImage();
if (!active)
{
for (int i = 0; i < tmp.height(); i++)
{
for (int j = 0; j < tmp.width(); j++)
{
QColor pixel = QColor::fromRgba(tmp.pixel(j, i));
pixel.setRedF(pixel.redF() * 0.5f);
pixel.setGreenF(pixel.greenF() * 0.5f);
pixel.setBlueF(pixel.blueF() * 0.5f);
tmp.setPixel(j, i, pixel.rgba());
}
}
}
if (m_icon_dark && !force_light)
tmp.invertPixels();
return QPixmap::fromImage(tmp);
}
void CaptionButton::init(IconType type)
{
m_type = type;
setColors();
drawIcons();
}
void CaptionButton::drawIcons()
{
switch (m_type)
{
case IconType::Minimize:
{
QPixmap icon = QPixmap(":/images/icon_window_minimize.png");
m_active_icon = drawIcon(icon, true);
m_inactive_icon = drawIcon(icon, false);
break;
}
case IconType::Restore:
{
QPixmap icon = QPixmap(":/images/icon_window_restore.png");
m_active_icon = drawIcon(icon, true);
m_inactive_icon = drawIcon(icon, false);
break;
}
case IconType::Maximize:
{
QPixmap icon = QPixmap(":/images/icon_window_maximize.png");
m_active_icon = drawIcon(icon, true);
m_inactive_icon = drawIcon(icon, false);
break;
}
case IconType::Close:
{
QPixmap icon = QPixmap(":/images/icon_window_close.png");
m_active_icon = drawIcon(icon, true);
m_inactive_icon = drawIcon(icon, false);
m_close_icon_hover = drawIcon(icon, true, true);
break;
}
}
}
void CaptionButton::setColors()
{
if (m_icon_dark)
{
if (m_type == IconType::Close)
{
m_normal = QColor("transparent");
m_hover = QColor("#F00000");
m_pressed = QColor("#F1707A");
}
else
{
m_normal = QColor("transparent");
m_hover = QColor("#E5E5E5");
m_pressed = QColor("#CACACB");
}
}
else
{
if (m_type == IconType::Close)
{
m_normal = QColor("transparent");
m_hover = QColor("#F00000");
m_pressed = QColor("#F1707A");
}
else
{
m_normal = QColor("transparent");
m_hover = QColor("#505050");
m_pressed = QColor("#3F3F3F");
}
}
repaint();
}
void CaptionButton::setIconMode(bool icon_dark)
{
m_icon_dark = icon_dark;
drawIcons();
setColors();
repaint();
}
void CaptionButton::setActive(bool is_active)
{
m_is_active = is_active;
repaint();
}
void CaptionButton::setState(int state)
{
switch (state)
{
case QEvent::HoverEnter:
{
m_is_under_mouse = true;
repaint();
break;
}
case QEvent::HoverLeave:
{
m_is_under_mouse = false;
repaint();
break;
}
case QEvent::MouseButtonPress:
{
m_is_pressed = true;
m_is_under_mouse = true;
repaint();
break;
}
case QEvent::MouseButtonRelease:
{
m_is_pressed = false;
m_is_under_mouse = false;
repaint();
break;
}
default:
break;
}
}
void CaptionButton::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
QPixmap current_icon = m_active_icon;
QColor current_color = m_normal;
//Change icon if needed
if (m_is_under_mouse)
{
if (m_type == IconType::Close)
current_icon = m_close_icon_hover;
}
else
{
if (!m_is_active)
current_icon = m_inactive_icon;
}
//Change background color if needed
if (m_is_pressed)
{
if (m_is_under_mouse)
current_color = m_pressed;
}
else
{
if (m_is_under_mouse)
current_color = m_hover;
}
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
painter.fillRect(rect(), current_color);
QRect target_rect;
target_rect = current_icon.rect();
target_rect.setSize(QSize(16, 16));
target_rect = QRect(rect().center() - target_rect.center(), target_rect.size());
painter.drawPixmap(target_rect, current_icon);
}

View File

@ -0,0 +1,81 @@
/*
The MIT License (MIT)
Copyright © 2018-2022 Antonio Dias
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef CAPTIONBUTTON_H
#define CAPTIONBUTTON_H
#include <QtCore>
#include <QtGui>
#include <QtWidgets>
class CaptionButton : public QWidget
{
Q_OBJECT
public:
explicit CaptionButton(QWidget *parent = nullptr);
~CaptionButton();
enum class IconType
{
Minimize,
Restore,
Maximize,
Close
};
void init(IconType type);
signals:
void clicked();
public slots:
void setIconMode(bool icon_dark);
void setActive(bool is_active);
void setState(int state);
private:
//Functions
QPixmap drawIcon(const QPixmap &icon, bool active, bool force_light = false);
void setColors();
void drawIcons();
void paintEvent(QPaintEvent *event);
//Variables
QPixmap m_inactive_icon;
QPixmap m_active_icon;
QPixmap m_close_icon_hover;
QColor m_normal;
QColor m_hover;
QColor m_pressed;
IconType m_type;
bool m_is_active;
bool m_is_under_mouse;
bool m_is_pressed;
bool m_icon_dark;
};
#endif // CAPTIONBUTTON_H

View File

@ -0,0 +1,75 @@
/*
The MIT License (MIT)
Copyright © 2018-2022 Antonio Dias
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "iconwidget.h"
#define ICONWIDTH 16
#define ICONHEIGHT 16
IconWidget::IconWidget(QWidget *parent) : QWidget(parent)
{
m_active = true;
}
void IconWidget::setPixmap(const QPixmap &pixmap)
{
m_pixmap = pixmap;
QImage tmp = m_pixmap.toImage();
for (int i = 0; i < m_pixmap.width(); i++)
{
for (int j = 0; j < m_pixmap.height(); j++)
{
int gray = qGray(tmp.pixel(i, j));
int alpha = qAlpha(tmp.pixel(i, j));
tmp.setPixel(i, j, qRgba(gray, gray, gray, alpha));
}
}
m_grayed_pixmap = QPixmap::fromImage(tmp);
repaint();
}
void IconWidget::setActive(bool active)
{
m_active = active;
repaint();
}
void IconWidget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
painter.drawPixmap((width() - ICONWIDTH)/ 2,
(height() - ICONHEIGHT) / 2,
ICONWIDTH, ICONHEIGHT,
m_active ? m_pixmap : m_grayed_pixmap);
}

View File

@ -0,0 +1,52 @@
/*
The MIT License (MIT)
Copyright © 2018-2022 Antonio Dias
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef ICONWIDGET_H
#define ICONWIDGET_H
#include <QtCore>
#include <QtGui>
#include <QtWidgets>
class IconWidget : public QWidget
{
Q_OBJECT
public:
explicit IconWidget(QWidget *parent = nullptr);
public slots:
void setPixmap(const QPixmap &pixmap);
void setActive(bool active);
private:
//Functions
void paintEvent(QPaintEvent *event);
//Variables
QPixmap m_pixmap;
QPixmap m_grayed_pixmap;
bool m_active;
};
#endif // ICONWIDGET_H

View File

@ -1,12 +1,491 @@
#include "MainWindow.h"
#include "Renderer/RendererGLWidget.h"
#include "qslider.h"
#include <QPushButton>
#include "NavigationBarWidget.h"
#include <qDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
inline void fontTheme()
{
QFont defaultFont = qApp->font();
defaultFont.setPointSize(defaultFont.pointSize() + 2);
qApp->setFont(defaultFont);
}
inline void setThemeStyleSheet(bool dark)
{
QFile file(dark ? ":/darkstyle.qss" : ":/lightstyle.qss");
if (!file.open(QFile::ReadOnly))
return;
const QString style_sheet = QLatin1String(file.readAll());
file.close();
qApp->setStyleSheet(style_sheet);
}
inline void darkTheme()
{
QPalette darkPalette = qApp->palette();
darkPalette.setColor(QPalette::Window, QColor(53, 53, 53));
darkPalette.setColor(QPalette::WindowText, QColor(255, 255, 255));
darkPalette.setColor(QPalette::Disabled, QPalette::WindowText, QColor(127, 127, 127));
darkPalette.setColor(QPalette::Base, QColor(42, 42, 42));
darkPalette.setColor(QPalette::AlternateBase, QColor(66, 66, 66));
darkPalette.setColor(QPalette::ToolTipBase, QColor(255, 255, 255));
darkPalette.setColor(QPalette::ToolTipText, QColor(255, 255, 255));
darkPalette.setColor(QPalette::Text, QColor(255, 255, 255));
darkPalette.setColor(QPalette::Disabled, QPalette::Text, QColor(127, 127, 127));
darkPalette.setColor(QPalette::Dark, QColor(35, 35, 35));
darkPalette.setColor(QPalette::Shadow, QColor(20, 20, 20));
darkPalette.setColor(QPalette::Button, QColor(53, 53, 53));
darkPalette.setColor(QPalette::ButtonText, QColor(255, 255, 255));
darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, QColor(127, 127, 127));
darkPalette.setColor(QPalette::BrightText, QColor(255, 0, 0));
darkPalette.setColor(QPalette::Link, QColor(42, 130, 218));
darkPalette.setColor(QPalette::Highlight, QColor(42, 130, 218));
darkPalette.setColor(QPalette::Disabled, QPalette::Highlight, QColor(80, 80, 80));
darkPalette.setColor(QPalette::HighlightedText, QColor(255, 255, 255));
darkPalette.setColor(QPalette::Disabled, QPalette::HighlightedText, QColor(127, 127, 127));
qApp->setPalette(darkPalette);
setThemeStyleSheet(true /*dark*/);
}
inline void lightTheme()
{
QPalette lightPalette = qApp->palette();
lightPalette.setColor(QPalette::Window, QColor(240, 240, 240));
lightPalette.setColor(QPalette::WindowText, QColor(0, 0, 0));
lightPalette.setColor(QPalette::Disabled, QPalette::WindowText, QColor(120, 120, 120));
lightPalette.setColor(QPalette::Base, QColor(255, 255, 255));
lightPalette.setColor(QPalette::AlternateBase, QColor(233, 231, 227));
lightPalette.setColor(QPalette::ToolTipBase, QColor(255, 255, 220));
lightPalette.setColor(QPalette::ToolTipText, QColor(0, 0, 0));
lightPalette.setColor(QPalette::Text, QColor(0, 0, 0));
lightPalette.setColor(QPalette::Disabled, QPalette::Text, QColor(120, 120, 120));
lightPalette.setColor(QPalette::Dark, QColor(160, 160, 160));
lightPalette.setColor(QPalette::Shadow, QColor(105, 105, 105));
lightPalette.setColor(QPalette::Button, QColor(240, 240, 240));
lightPalette.setColor(QPalette::ButtonText, QColor(0, 0, 0));
lightPalette.setColor(QPalette::Disabled, QPalette::ButtonText, QColor(120, 120, 120));
lightPalette.setColor(QPalette::BrightText, QColor(0, 0, 255));
lightPalette.setColor(QPalette::Link, QColor(51, 153, 255));
lightPalette.setColor(QPalette::Highlight, QColor(0, 0, 255));
lightPalette.setColor(QPalette::Disabled, QPalette::Highlight, QColor(51, 153, 255));
lightPalette.setColor(QPalette::HighlightedText, QColor(255, 255, 255));
lightPalette.setColor(QPalette::Disabled, QPalette::HighlightedText, QColor(255, 255, 255));
qApp->setPalette(lightPalette);
setThemeStyleSheet(false /*dark*/);
}
FramelessWindow::FramelessWindow(QWidget* parent) : QWidget(parent), ui(new Ui::FramelessWindow)
{
ui->setupUi(this);
}
FramelessWindow::~FramelessWindow()
{
delete ui;
}
CentralWidget::CentralWidget(QWidget* parent) : QMainWindow(parent)
{
ui.setupUi(this);
NavigationBarWidget* navigationBarWidget = new NavigationBarWidget();
QHBoxLayout* tabBarLayout = new QHBoxLayout(ui.tabWidget);
tabBarLayout->setSpacing(0);
tabBarLayout->setMargin(0);
tabBarLayout->addWidget(navigationBarWidget, 0, Qt::AlignTop | Qt::AlignHCenter);
QObject::connect(navigationBarWidget->buttonGroup, &QButtonGroup::idClicked,
ui.tabWidget, &QTabWidget::setCurrentIndex);
QObject::connect(ui.tabWidget, &QTabWidget::currentChanged,
ui.rendererWidget, &RendererWidget::currentTabChanged);
}
CentralWidget::~CentralWidget()
{
}
MainWindow::MainWindow(QWidget* parent)
: QGoodWindow(parent)
{
// if the system will draw borders or if this application must do that
m_draw_borders = !QGoodWindow::shouldBordersBeDrawnBySystem();
m_dark = QGoodWindow::isSystemThemeDark();
// create frameless window
m_window = new FramelessWindow(this);
m_central_widget = new CentralWidget(m_window);
// add the mainwindow to our custom frameless window
m_window->ui->windowContent->layout()->addWidget(m_central_widget);
connect(this, &QGoodWindow::windowTitleChanged, this, [=](const QString& title) {
m_window->ui->titleWidget->setText(title);
});
connect(this, &QGoodWindow::windowIconChanged, this, [=](const QIcon& icon) {
m_window->ui->icon->setPixmap(icon.pixmap(16, 16));
});
int iconWidth = 30;
int captionButtonWidth = 45, captionButtonHeight = 30;
m_window->ui->icon->setFixedSize(iconWidth, 20);
m_window->ui->titleWidget->setFixedHeight(captionButtonHeight);
m_window->ui->minimizeButton->setFixedSize(captionButtonWidth, captionButtonHeight);
m_window->ui->maximizeButton->setFixedSize(captionButtonWidth, captionButtonHeight);
m_window->ui->restoreButton->setFixedSize(captionButtonWidth, captionButtonHeight);
m_window->ui->closeButton->setFixedSize(captionButtonWidth, captionButtonHeight);
m_window->ui->minimizeButton->init(CaptionButton::IconType::Minimize);
m_window->ui->maximizeButton->init(CaptionButton::IconType::Maximize);
m_window->ui->restoreButton->init(CaptionButton::IconType::Restore);
m_window->ui->closeButton->init(CaptionButton::IconType::Close);
connect(m_window->ui->minimizeButton, &CaptionButton::clicked, this, &MainWindow::showMinimized);
connect(m_window->ui->maximizeButton, &CaptionButton::clicked, this, &MainWindow::showMaximized);
connect(m_window->ui->restoreButton, &CaptionButton::clicked, this, &MainWindow::showNormal);
connect(m_window->ui->closeButton, &CaptionButton::clicked, this, &MainWindow::close);
connect(this, &QGoodWindow::captionButtonStateChanged, this, &MainWindow::captionButtonStateChanged);
setMargins(captionButtonHeight, iconWidth, 0, captionButtonWidth * 3);
setCaptionButtonsHandled(true, Qt::TopRightCorner);
// Overlap close with maximize and maximize with minimize
setCloseMask(QRect(captionButtonWidth * 2, 0, rightCaptionButtonsRect().width(), rightCaptionButtonsRect().height()));
setMaximizeMask(QRect(captionButtonWidth * 1, 0, rightCaptionButtonsRect().width(), rightCaptionButtonsRect().height()));
setMinimizeMask(QRect(0, 0, rightCaptionButtonsRect().width(), rightCaptionButtonsRect().height()));
auto theme_change_func = [=] {
if (m_dark)
darkTheme();
else
lightTheme();
//Icon color inverse of m_dark to contrast.
m_window->ui->minimizeButton->setIconMode(!m_dark);
m_window->ui->maximizeButton->setIconMode(!m_dark);
m_window->ui->restoreButton->setIconMode(!m_dark);
m_window->ui->closeButton->setIconMode(!m_dark);
};
QShortcut* shortcut1 = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_S), this);
connect(shortcut1, &QShortcut::activated, this, [=] {
m_dark = !m_dark;
theme_change_func();
});
connect(this, &QGoodWindow::systemThemeChanged, this, [=] {
m_dark = QGoodWindow::isSystemThemeDark();
theme_change_func();
});
theme_change_func();
setWindowIcon(QIcon(":/images/icon.png"));
setWindowTitle("ArchitectureColoredPainting");
resize(m_central_widget->size());
setCentralWidget(m_window);
move(QGuiApplication::primaryScreen()->availableGeometry().center() - rect().center());
}
MainWindow::~MainWindow()
{}
void MainWindow::styleWindow()
{
bool window_active = isActiveWindow();
bool window_no_state = windowState().testFlag(Qt::WindowNoState);
//bool draw_borders = m_draw_borders;
bool draw_borders = false;
if (window_active)
{
if (window_no_state)
{
if (draw_borders)
{
m_window->ui->windowTitlebar->setStyleSheet(
QStringLiteral("#windowTitlebar{border: 0px none palette(shadow);}"));
m_window->ui->windowFrame->setStyleSheet(
QStringLiteral("#windowFrame{border: 1px solid palette(highlight);"
"background-color: palette(Window);}"));
}
else
{
m_window->ui->windowTitlebar->setStyleSheet(
QStringLiteral("#windowTitlebar{border: 0px none palette(shadow);}"));
m_window->ui->windowFrame->setStyleSheet(
QStringLiteral("#windowFrame{border: 0px solid palette(highlight);"
"background-color: palette(Window);}"));
}
}
else
{
m_window->ui->windowTitlebar->setStyleSheet(
QStringLiteral("#windowTitlebar{border: 0px none palette(shadow);"
"background-color :palette(shadow); height:20px;}"));
m_window->ui->windowFrame->setStyleSheet(
QStringLiteral("#windowFrame{border: 0px none palette(dark);"
"background-color: palette(Window);}"));
}
}
else
{
if (window_no_state)
{
if (draw_borders)
{
m_window->ui->windowTitlebar->setStyleSheet(
QStringLiteral("#windowTitlebar{border: 0px none palette(shadow);"
"background-color: palette(dark); height:20px;}"));
m_window->ui->windowFrame->setStyleSheet(
QStringLiteral("#windowFrame{border: 1px solid #000000;"
"background-color: palette(Window);}"));
}
else
{
m_window->ui->windowTitlebar->setStyleSheet(
QStringLiteral("#windowTitlebar{border: 0px none palette(shadow);"
"background-color: palette(dark); height:20px;}"));
m_window->ui->windowFrame->setStyleSheet(
QStringLiteral("#windowFrame{border: 0px solid #000000;"
"background-color: palette(Window);}"));
}
}
else
{
m_window->ui->windowTitlebar->setStyleSheet(
QStringLiteral("#titlebarWidget{border: 0px none palette(shadow);"
"background-color: palette(dark); height: 20px;}"));
m_window->ui->windowFrame->setStyleSheet(
QStringLiteral("#windowFrame{border: 0px none palette(shadow);"
"background-color: palette(Window);}"));
}
}
m_window->ui->icon->setActive(window_active);
m_window->ui->titleWidget->setActive(window_active);
if (!isMinimized())
{
m_window->ui->maximizeButton->setVisible(window_no_state);
m_window->ui->restoreButton->setVisible(!window_no_state);
}
m_window->ui->minimizeButton->setActive(window_active);
m_window->ui->maximizeButton->setActive(window_active);
m_window->ui->restoreButton->setActive(window_active);
m_window->ui->closeButton->setActive(window_active);
}
void MainWindow::captionButtonStateChanged(const QGoodWindow::CaptionButtonState& state)
{
switch (state)
{
// Hover enter
case QGoodWindow::CaptionButtonState::MinimizeHoverEnter:
{
m_window->ui->minimizeButton->setState(QEvent::HoverEnter);
break;
}
case QGoodWindow::CaptionButtonState::MaximizeHoverEnter:
{
if (!isMaximized())
m_window->ui->maximizeButton->setState(QEvent::HoverEnter);
else
m_window->ui->restoreButton->setState(QEvent::HoverEnter);
break;
}
case QGoodWindow::CaptionButtonState::CloseHoverEnter:
{
m_window->ui->closeButton->setState(QEvent::HoverEnter);
break;
}
// Hover leave
case QGoodWindow::CaptionButtonState::MinimizeHoverLeave:
{
m_window->ui->minimizeButton->setState(QEvent::HoverLeave);
break;
}
case QGoodWindow::CaptionButtonState::MaximizeHoverLeave:
{
if (!isMaximized())
m_window->ui->maximizeButton->setState(QEvent::HoverLeave);
else
m_window->ui->restoreButton->setState(QEvent::HoverLeave);
break;
}
case QGoodWindow::CaptionButtonState::CloseHoverLeave:
{
m_window->ui->closeButton->setState(QEvent::HoverLeave);
break;
}
// Mouse button press
case QGoodWindow::CaptionButtonState::MinimizePress:
{
m_window->ui->minimizeButton->setState(QEvent::MouseButtonPress);
break;
}
case QGoodWindow::CaptionButtonState::MaximizePress:
{
if (!isMaximized())
m_window->ui->maximizeButton->setState(QEvent::MouseButtonPress);
else
m_window->ui->restoreButton->setState(QEvent::MouseButtonPress);
break;
}
case QGoodWindow::CaptionButtonState::ClosePress:
{
m_window->ui->closeButton->setState(QEvent::MouseButtonPress);
break;
}
// Mouse button release
case QGoodWindow::CaptionButtonState::MinimizeRelease:
{
m_window->ui->minimizeButton->setState(QEvent::MouseButtonRelease);
break;
}
case QGoodWindow::CaptionButtonState::MaximizeRelease:
{
if (!isMaximized())
m_window->ui->maximizeButton->setState(QEvent::MouseButtonRelease);
else
m_window->ui->restoreButton->setState(QEvent::MouseButtonRelease);
break;
}
case QGoodWindow::CaptionButtonState::CloseRelease:
{
m_window->ui->closeButton->setState(QEvent::MouseButtonRelease);
break;
}
// Mouse button clicked
case QGoodWindow::CaptionButtonState::MinimizeClicked:
{
emit m_window->ui->minimizeButton->clicked();
break;
}
case QGoodWindow::CaptionButtonState::MaximizeClicked:
{
if (!isMaximized())
emit m_window->ui->maximizeButton->clicked();
else
emit m_window->ui->restoreButton->clicked();
break;
}
case QGoodWindow::CaptionButtonState::CloseClicked:
{
emit m_window->ui->closeButton->clicked();
break;
}
default:
break;
}
}
bool MainWindow::event(QEvent* event)
{
switch (event->type())
{
case QEvent::Show:
case QEvent::WindowActivate:
case QEvent::WindowDeactivate:
case QEvent::WindowStateChange:
{
styleWindow();
break;
}
case QEvent::StyleChange:
{
QColor active_color = qApp->palette().color(QPalette::WindowText);
QColor inactive_color = qApp->palette().color(QPalette::Disabled, QPalette::WindowText);
m_window->ui->titleWidget->setTitleColor(active_color, inactive_color);
break;
}
default:
break;
}
return QGoodWindow::event(event);
}
bool MainWindow::nativeEvent(const QByteArray& eventType, void* message, long* result)
{
#ifdef Q_OS_WIN
MSG* msg = static_cast<MSG*>(message);
switch (msg->message)
{
case WM_THEMECHANGED:
case WM_DWMCOMPOSITIONCHANGED:
{
//Keep window theme on Windows theme change events.
QTimer::singleShot(1000, this, [=] {
if (m_dark)
darkTheme();
else
lightTheme();
});
break;
}
default:
break;
}
#endif
return QGoodWindow::nativeEvent(eventType, message, result);
}
void MainWindow::closeEvent(QCloseEvent* event)
{
/* int result = QMessageBox::question(this, "Close window", "Are you sure to close?");
if (result != QMessageBox::Yes)
event->ignore();*/
}

View File

@ -2,15 +2,55 @@
#include <QtWidgets/QMainWindow>
#include "ui_MainWindow.h"
#include "ui_FramelessWindow.h"
class MainWindow : public QMainWindow
#define QGOODWINDOW
#include <QGoodWindow>
class FramelessWindow : public QWidget
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
explicit FramelessWindow(QWidget* parent = nullptr);
~FramelessWindow();
Ui::FramelessWindow* ui;
};
class CentralWidget : public QMainWindow
{
Q_OBJECT
public:
explicit CentralWidget(QWidget* parent = nullptr);
~CentralWidget();
Ui::MainWindowClass ui;
};
class MainWindow : public QGoodWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget* parent = nullptr);
~MainWindow();
private:
Ui::MainWindowClass ui;
//Functions
void styleWindow();
void captionButtonStateChanged(const QGoodWindow::CaptionButtonState& state);
bool event(QEvent* event);
bool nativeEvent(const QByteArray& eventType, void* message, long* result);
void closeEvent(QCloseEvent* event);
//Variables
FramelessWindow* m_window;
CentralWidget* m_central_widget;
bool m_draw_borders;
bool m_dark;
};

View File

@ -0,0 +1,14 @@
#include "NavigationBarWidget.h"
NavigationBarWidget::NavigationBarWidget(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
buttonGroup = new QButtonGroup(this);
buttonGroup->addButton(ui.radioButton0, 0);
buttonGroup->addButton(ui.radioButton1, 1);
ui.radioButton0->setChecked(true);
;}
NavigationBarWidget::~NavigationBarWidget()
{}

View File

@ -0,0 +1,18 @@
#pragma once
#include <QWidget>
#include <QButtonGroup>
#include "ui_NavigationBarWidget.h"
class NavigationBarWidget : public QWidget
{
Q_OBJECT
public:
NavigationBarWidget(QWidget *parent = nullptr);
~NavigationBarWidget();
QButtonGroup* buttonGroup;
private:
Ui::NavigationBarWidgetClass ui;
};

View File

@ -17,8 +17,7 @@ RendererGLWidget::RendererGLWidget(QWidget* parent)
, camera(QVector3D(0.0f, 100.0f, 0.0f))
, light(&camera)
{
//startTimer(1000 / QGuiApplication::primaryScreen()->refreshRate());
startTimer(1);
//startTimer();
lastFrame = std::clock();
setFocusPolicy(Qt::StrongFocus);
QSurfaceFormat format;
@ -51,6 +50,19 @@ RendererGLWidget::~RendererGLWidget()
}
}
void RendererGLWidget::startTimer()
{
//startTimer(1000 / QGuiApplication::primaryScreen()->refreshRate());
if (timerId == -1)
timerId = QObject::startTimer(1);
}
void RendererGLWidget::stopTimer()
{
killTimer(timerId);
timerId = -1;
}
void RendererGLWidget::setMainLightPitch(float pitch)
{
//qDebug() << "pitch" << pitch;
@ -393,7 +405,7 @@ void RendererGLWidget::paintGL()
void RendererGLWidget::resizeGL(int width, int height)
{
frameWidth = ceil( devicePixelRatioF() * width);
frameWidth = ceil(devicePixelRatioF() * width);
frameHeight = ceil(devicePixelRatioF() * height);
qDebug() << frameWidth << "x" << frameHeight;
camera.Ratio = (float)frameWidth / (float)frameHeight;
@ -557,6 +569,7 @@ void RendererGLWidget::timerEvent(QTimerEvent* event)
float yoffset = center.y() - cursor().pos().y();
camera.ProcessMouseMovement(xoffset, yoffset);
cursor().setPos(center);
//qDebug() << center;
}
if (pressedKeys.contains(Qt::Key_W)) {

View File

@ -19,6 +19,8 @@ public:
RendererGLWidget(QWidget* parent = nullptr);
~RendererGLWidget();
void startTimer();
void stopTimer();
public slots:
void setMainLightPitch(float pitch);
void setMainLightYaw(float yaw);
@ -34,6 +36,7 @@ protected:
void focusOutEvent(QFocusEvent* event) override;
private:
int timerId = -1;
int frameWidth, frameHeight;
int depthWidth, depthHeight;
QSet<int> pressedKeys;

View File

@ -13,3 +13,15 @@ RendererWidget::RendererWidget(QWidget *parent)
RendererWidget::~RendererWidget()
{}
void RendererWidget::currentTabChanged(int index)
{
if (index == 1)
{
ui.openGLWidget->startTimer();
}
else
{
ui.openGLWidget->stopTimer();
}
}

View File

@ -8,9 +8,11 @@ class RendererWidget : public QWidget
Q_OBJECT
public:
RendererWidget(QWidget *parent = nullptr);
~RendererWidget();
public slots:
void currentTabChanged(int index);
private:
Ui::RendererWidgetClass ui;
};

View File

@ -0,0 +1,80 @@
/*
The MIT License (MIT)
Copyright © 2018-2022 Antonio Dias
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "titlewidget.h"
TitleWidget::TitleWidget(QWidget *parent) : QWidget(parent)
{
m_active = false;
}
void TitleWidget::setText(const QString &text)
{
m_title = text;
repaint();
}
void TitleWidget::setActive(bool active)
{
m_active = active;
repaint();
}
void TitleWidget::setTitleColor(const QColor &active_color, const QColor &inactive_color)
{
m_active_color = active_color;
m_inactive_color = inactive_color;
repaint();
}
void TitleWidget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing);
QFont font;
font.setPointSize(10);
#ifdef Q_OS_WIN
font.setFamily("Segoe UI, Microsoft YaHei UI");
#else
font.setFamily(qApp->font().family());
#endif
painter.setFont(font);
QPen pen;
pen.setColor(m_active ? m_active_color : m_inactive_color);
painter.setPen(pen);
QFontMetrics metrics(painter.font());
QSize title_size = metrics.size(0, m_title);
QString title = metrics.elidedText(m_title, Qt::ElideRight, width());
painter.drawText(0, (height() - title_size.height()) / 2, title_size.width(), title_size.height(), 0, title);
}

View File

@ -0,0 +1,54 @@
/*
The MIT License (MIT)
Copyright © 2018-2022 Antonio Dias
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef TITLEWIDGET_H
#define TITLEWIDGET_H
#include <QtCore>
#include <QtGui>
#include <QtWidgets>
class TitleWidget : public QWidget
{
Q_OBJECT
public:
explicit TitleWidget(QWidget *parent = nullptr);
public slots:
void setText(const QString &text);
void setActive(bool active);
void setTitleColor(const QColor &active_color, const QColor &inactive_color);
private:
//Functions
void paintEvent(QPaintEvent *event);
//Variables
QString m_title;
bool m_active;
QColor m_active_color;
QColor m_inactive_color;
};
#endif // TITLEWIDGET_H

22
QGoodWindow/.qmake.stash Normal file
View File

@ -0,0 +1,22 @@
QMAKE_CXX.QT_COMPILER_STDCXX = 199711L
QMAKE_CXX.QMAKE_MSC_VER = 1932
QMAKE_CXX.QMAKE_MSC_FULL_VER = 193231329
QMAKE_CXX.COMPILER_MACROS = \
QT_COMPILER_STDCXX \
QMAKE_MSC_VER \
QMAKE_MSC_FULL_VER
QMAKE_CXX.INCDIRS = \
"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Tools\\MSVC\\14.32.31326\\ATLMFC\\include" \
"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Tools\\MSVC\\14.32.31326\\include" \
"C:\\Program Files (x86)\\Windows Kits\\NETFXSDK\\4.8\\include\\um" \
"C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.19041.0\\ucrt" \
"C:\\Program Files (x86)\\Windows Kits\\10\\\\include\\10.0.19041.0\\\\shared" \
"C:\\Program Files (x86)\\Windows Kits\\10\\\\include\\10.0.19041.0\\\\um" \
"C:\\Program Files (x86)\\Windows Kits\\10\\\\include\\10.0.19041.0\\\\winrt" \
"C:\\Program Files (x86)\\Windows Kits\\10\\\\include\\10.0.19041.0\\\\cppwinrt"
QMAKE_CXX.LIBDIRS = \
"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Tools\\MSVC\\14.32.31326\\ATLMFC\\lib\\x64" \
"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Tools\\MSVC\\14.32.31326\\lib\\x64" \
"C:\\Program Files (x86)\\Windows Kits\\NETFXSDK\\4.8\\lib\\um\\x64" \
"C:\\Program Files (x86)\\Windows Kits\\10\\lib\\10.0.19041.0\\ucrt\\x64" \
"C:\\Program Files (x86)\\Windows Kits\\10\\\\lib\\10.0.19041.0\\\\um\\x64"

25
QGoodWindow/QGoodWindow Normal file
View File

@ -0,0 +1,25 @@
/*
The MIT License (MIT)
Copyright © 2021 Antonio Dias
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "src/qgoodwindow.h"

View File

@ -0,0 +1,92 @@
#The MIT License (MIT)
#Copyright © 2021-2022 Antonio Dias
#Permission is hereby granted, free of charge, to any person obtaining a copy
#of this software and associated documentation files (the "Software"), to deal
#in the Software without restriction, including without limitation the rights
#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
#copies of the Software, and to permit persons to whom the Software is
#furnished to do so, subject to the following conditions:
#The above copyright notice and this permission notice shall be included in all
#copies or substantial portions of the Software.
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
#SOFTWARE.
QT += core gui widgets
CONFIG += c++11
SOURCES += \
$$PWD/src/qgoodwindow.cpp
HEADERS += \
$$PWD/src/qgoodwindow.h
INCLUDEPATH += $$PWD
win32 {
equals(QT_MAJOR_VERSION, 5){
QT += winextras
}
SOURCES += \
$$PWD/src/shadow.cpp
HEADERS += \
$$PWD/src/common.h \
$$PWD/src/shadow.h
LIBS += -lUser32 -lGdi32
DEFINES += QGOODWINDOW
CONFIG += qgoodwindow
}
unix:!mac:!android {
equals(QT_MAJOR_VERSION, 5){
QT += testlib x11extras
}
equals(QT_MAJOR_VERSION, 6){
QT += gui-private
}
SOURCES += \
$$PWD/src/shadow.cpp
HEADERS += \
$$PWD/src/shadow.h
LIBS += -lX11
CONFIG += link_pkgconfig
PKGCONFIG += gtk+-2.0
DEFINES += QGOODWINDOW
CONFIG += qgoodwindow
}
mac {
OBJECTIVE_SOURCES += \
$$PWD/src/macosnative.mm
SOURCES += \
$$PWD/src/notification.cpp
HEADERS += \
$$PWD/src/macosnative.h \
$$PWD/src/notification.h
LIBS += -framework Foundation -framework Cocoa -framework AppKit
DEFINES += QGOODWINDOW
CONFIG += qgoodwindow
}

View File

@ -0,0 +1,213 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{B982E745-C0B1-46B3-A27B-743AF105F2D0}</ProjectGuid>
<RootNamespace>QGoodWindow</RootNamespace>
<Keyword>QtVS_v304</Keyword>
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion>10.0.19041.0</WindowsTargetPlatformMinVersion>
<QtMsBuild Condition="'$(QtMsBuild)'=='' or !Exists('$(QtMsBuild)\qt.targets')">$(MSBuildProjectDirectory)\QtMsBuild</QtMsBuild>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<PlatformToolset>v143</PlatformToolset>
<OutputDirectory>release\</OutputDirectory>
<ATLMinimizesCRunTimeLibraryUsage>false</ATLMinimizesCRunTimeLibraryUsage>
<CharacterSet>NotSet</CharacterSet>
<ConfigurationType>StaticLibrary</ConfigurationType>
<IntermediateDirectory>release\</IntermediateDirectory>
<PrimaryOutput>QGoodWindow</PrimaryOutput>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<PlatformToolset>v143</PlatformToolset>
<OutputDirectory>debug\</OutputDirectory>
<ATLMinimizesCRunTimeLibraryUsage>false</ATLMinimizesCRunTimeLibraryUsage>
<CharacterSet>NotSet</CharacterSet>
<ConfigurationType>StaticLibrary</ConfigurationType>
<IntermediateDirectory>debug\</IntermediateDirectory>
<PrimaryOutput>QGoodWindow</PrimaryOutput>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Target Name="QtMsBuildNotFound" BeforeTargets="CustomBuild;ClCompile" Condition="!Exists('$(QtMsBuild)\qt.targets') or !Exists('$(QtMsBuild)\qt.props')">
<Message Importance="High" Text="QtMsBuild: could not locate qt.targets, qt.props; project may not build correctly." />
</Target>
<ImportGroup Label="ExtensionSettings" />
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ImportGroup Condition="Exists('$(QtMsBuild)\qt_defaults.props')">
<Import Project="$(QtMsBuild)\qt_defaults.props" />
</ImportGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>debug\</OutDir>
<IntDir>debug\</IntDir>
<TargetName>QGoodWindow</TargetName>
<IgnoreImportLibrary>true</IgnoreImportLibrary>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>release\</OutDir>
<IntDir>release\</IntDir>
<TargetName>QGoodWindow</TargetName>
<IgnoreImportLibrary>true</IgnoreImportLibrary>
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Label="QtSettings" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<QtInstall>5.15.2_msvc2019_64</QtInstall>
<QtModules>core;gui;widgets;winextras</QtModules>
</PropertyGroup>
<PropertyGroup Label="QtSettings" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<QtInstall>5.15.2_msvc2019_64</QtInstall>
<QtModules>core;gui;widgets;winextras</QtModules>
</PropertyGroup>
<ImportGroup Condition="Exists('$(QtMsBuild)\qt.props')">
<Import Project="$(QtMsBuild)\qt.props" />
</ImportGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<AdditionalIncludeDirectories>GeneratedFiles\$(ConfigurationName);GeneratedFiles;.;release;/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>-Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 %(AdditionalOptions)</AdditionalOptions>
<AssemblerListingLocation>release\</AssemblerListingLocation>
<BrowseInformation>false</BrowseInformation>
<DebugInformationFormat>None</DebugInformationFormat>
<DisableSpecificWarnings>4577;4467;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<ExceptionHandling>Sync</ExceptionHandling>
<ObjectFileName>release\</ObjectFileName>
<Optimization>MaxSpeed</Optimization>
<PreprocessorDefinitions>_WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WIN64;QGOODWINDOW;NDEBUG;QT_NO_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessToFile>false</PreprocessToFile>
<ProgramDataBaseFileName>
</ProgramDataBaseFileName>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<SuppressStartupBanner>true</SuppressStartupBanner>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<WarningLevel>Level3</WarningLevel>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<AdditionalDependencies>User32.lib;Gdi32.lib;shell32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>C:\openssl\lib;C:\Utils\my_sql\mysql-5.7.25-winx64\lib;C:\Utils\postgresql\pgsql\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalOptions>"/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions)</AdditionalOptions>
<DataExecutionPrevention>true</DataExecutionPrevention>
<GenerateDebugInformation>false</GenerateDebugInformation>
<IgnoreImportLibrary>true</IgnoreImportLibrary>
<LinkIncremental>false</LinkIncremental>
<OptimizeReferences>true</OptimizeReferences>
<OutputFile>$(OutDir)\QGoodWindow.exe</OutputFile>
<RandomizedBaseAddress>true</RandomizedBaseAddress>
<SubSystem>Windows</SubSystem>
<SuppressStartupBanner>true</SuppressStartupBanner>
</Link>
<Midl>
<DefaultCharType>Unsigned</DefaultCharType>
<EnableErrorChecks>None</EnableErrorChecks>
<WarningLevel>0</WarningLevel>
</Midl>
<ResourceCompile>
<PreprocessorDefinitions>_WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WIN64;QGOODWINDOW;NDEBUG;QT_NO_DEBUG;QT_WIDGETS_LIB;QT_WINEXTRAS_LIB;QT_GUI_LIB;QT_CORE_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<QtMoc>
<CompilerFlavor>msvc</CompilerFlavor>
<Include>D:/??2022/ArchitectureColoredPainting/QGoodWindow/$(Configuration)/moc_predefs.h</Include>
<ExecutionDescription>Moc'ing %(Identity)...</ExecutionDescription>
<DynamicSource>output</DynamicSource>
<QtMocDir>$(Configuration)</QtMocDir>
<QtMocFileName>moc_%(Filename).cpp</QtMocFileName>
</QtMoc>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<AdditionalIncludeDirectories>GeneratedFiles\$(ConfigurationName);GeneratedFiles;.;debug;/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>-Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 %(AdditionalOptions)</AdditionalOptions>
<AssemblerListingLocation>debug\</AssemblerListingLocation>
<BrowseInformation>false</BrowseInformation>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>4577;4467;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<ExceptionHandling>Sync</ExceptionHandling>
<ObjectFileName>debug\</ObjectFileName>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WIN64;QGOODWINDOW;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessToFile>false</PreprocessToFile>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<SuppressStartupBanner>true</SuppressStartupBanner>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<WarningLevel>Level3</WarningLevel>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<AdditionalDependencies>User32.lib;Gdi32.lib;shell32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>C:\openssl\lib;C:\Utils\my_sql\mysql-5.7.25-winx64\lib;C:\Utils\postgresql\pgsql\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalOptions>"/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions)</AdditionalOptions>
<DataExecutionPrevention>true</DataExecutionPrevention>
<GenerateDebugInformation>true</GenerateDebugInformation>
<IgnoreImportLibrary>true</IgnoreImportLibrary>
<OutputFile>$(OutDir)\QGoodWindow.exe</OutputFile>
<RandomizedBaseAddress>true</RandomizedBaseAddress>
<SubSystem>Windows</SubSystem>
<SuppressStartupBanner>true</SuppressStartupBanner>
</Link>
<Midl>
<DefaultCharType>Unsigned</DefaultCharType>
<EnableErrorChecks>None</EnableErrorChecks>
<WarningLevel>0</WarningLevel>
</Midl>
<ResourceCompile>
<PreprocessorDefinitions>_WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WIN64;QGOODWINDOW;QT_WIDGETS_LIB;QT_WINEXTRAS_LIB;QT_GUI_LIB;QT_CORE_LIB;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<QtMoc>
<CompilerFlavor>msvc</CompilerFlavor>
<Include>D:/??2022/ArchitectureColoredPainting/QGoodWindow/$(Configuration)/moc_predefs.h</Include>
<ExecutionDescription>Moc'ing %(Identity)...</ExecutionDescription>
<DynamicSource>output</DynamicSource>
<QtMocDir>$(Configuration)</QtMocDir>
<QtMocFileName>moc_%(Filename).cpp</QtMocFileName>
</QtMoc>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="src\qgoodwindow.cpp" />
<ClCompile Include="src\shadow.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\common.h" />
<QtMoc Include="src\qgoodwindow.h">
</QtMoc>
<QtMoc Include="src\shadow.h">
</QtMoc>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="debug\moc_predefs.h.cbt">
<FileType>Document</FileType>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\mkspecs\features\data\dummy.cpp;%(AdditionalInputs)</AdditionalInputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">cl -Bx"$(QTDIR)\bin\qmake.exe" -nologo -Zc:wchar_t -FS -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -Zi -MDd -W3 -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 -wd4577 -wd4467 -E $(QTDIR)\mkspecs\features\data\dummy.cpp 2&gt;NUL &gt;debug\moc_predefs.h</Command>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Generate moc_predefs.h</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">debug\moc_predefs.h;%(Outputs)</Outputs>
</CustomBuild>
<CustomBuild Include="release\moc_predefs.h.cbt">
<FileType>Document</FileType>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\mkspecs\features\data\dummy.cpp;%(AdditionalInputs)</AdditionalInputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">cl -Bx"$(QTDIR)\bin\qmake.exe" -nologo -Zc:wchar_t -FS -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -O2 -MD -W3 -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 -wd4577 -wd4467 -E $(QTDIR)\mkspecs\features\data\dummy.cpp 2&gt;NUL &gt;release\moc_predefs.h</Command>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Generate moc_predefs.h</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">release\moc_predefs.h;%(Outputs)</Outputs>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
</CustomBuild>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Condition="Exists('$(QtMsBuild)\qt.targets')">
<Import Project="$(QtMsBuild)\qt.targets" />
</ImportGroup>
<ImportGroup Label="ExtensionTargets" />
</Project>

View File

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Generated Files">
<UniqueIdentifier>{71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11}</UniqueIdentifier>
<Extensions>cpp;c;cxx;moc;h;def;odl;idl;res;</Extensions>
</Filter>
<Filter Include="Generated Files">
<UniqueIdentifier>{71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11}</UniqueIdentifier>
<Extensions>cpp;c;cxx;moc;h;def;odl;idl;res;</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\qgoodwindow.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\shadow.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\common.h">
<Filter>Header Files</Filter>
</ClInclude>
<QtMoc Include="src\qgoodwindow.h">
<Filter>Header Files</Filter>
</QtMoc>
<QtMoc Include="src\shadow.h">
<Filter>Header Files</Filter>
</QtMoc>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="debug\moc_predefs.h.cbt">
<Filter>Generated Files</Filter>
</CustomBuild>
<CustomBuild Include="release\moc_predefs.h.cbt">
<Filter>Generated Files</Filter>
</CustomBuild>
</ItemGroup>
</Project>

Binary file not shown.

Binary file not shown.

Binary file not shown.

79
QGoodWindow/src/common.h Normal file
View File

@ -0,0 +1,79 @@
/*
The MIT License (MIT)
Copyright © 2018-2022 Antonio Dias
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef COMMON_H
#define COMMON_H
#ifdef _WIN32
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT _WIN32_WINNT_VISTA
#endif
#include <QtCore>
#include <QtGui>
#include <QtWidgets>
#ifdef Q_OS_LINUX
#define BORDERWIDTH 10 //PIXELS
#define MOVERESIZE_MOVE 8 //X11 Fixed Value
#endif
#if defined Q_OS_LINUX || defined Q_OS_MAC
//The positive values are mandatory on Linux and arbitrary on macOS,
//using the same for convenience.
//The negative value are arbitrary on both platforms.
#define NO_WHERE -1
#define HTMINBUTTON -2
#define HTMAXBUTTON -3
#define HTCLOSE -4
#define TOP_LEFT 0
#define TOP 1
#define TOP_RIGHT 2
#define LEFT 7
#define RIGHT 3
#define BOTTOM_LEFT 6
#define BOTTOM 5
#define BOTTOM_RIGHT 4
#define TITLE_BAR 8
#endif
#ifdef Q_OS_WIN
#include <windows.h>
#define BORDERWIDTH (GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER))
#endif
#endif // COMMON_H

View File

@ -0,0 +1,50 @@
/*
The MIT License (MIT)
Copyright © 2021-2022 Antonio Dias
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef MACOSNATIVE_H
#define MACOSNATIVE_H
#include "notification.h"
extern Notification notification;
//\cond HIDDEN_SYMBOLS
namespace macOSNative
{
void registerThemeChangeNotification();
void registerNotification(const char *notification_name, long wid);
void unregisterNotification();
inline void handleNotification(const char *notification_name, long wid)
{
notification.notification(notification_name, wid);
}
void setStyle(long winid, bool fullscreen);
const char *themeName();
}
//\endcond
#endif // MACOSNATIVE_H

View File

@ -0,0 +1,148 @@
/*
The MIT License (MIT)
Copyright © 2021-2022 Antonio Dias
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "macosnative.h"
#include <Cocoa/Cocoa.h>
void macOSNative::setStyle(long winid, bool fullscreen)
{
NSView *nativeView = reinterpret_cast<NSView*>(winid);
NSWindow *nativeWindow = [nativeView window];
if (!fullscreen)
{
[nativeWindow setStyleMask:NSWindowStyleMaskResizable |
NSWindowStyleMaskMiniaturizable |
NSWindowStyleMaskClosable |
NSWindowStyleMaskTitled |
NSWindowStyleMaskFullSizeContentView];
[nativeWindow setMovableByWindowBackground:NO];
[nativeWindow setMovable:NO];
[nativeWindow setTitlebarAppearsTransparent:YES];
[nativeWindow setShowsToolbarButton:NO];
[nativeWindow setTitleVisibility:NSWindowTitleHidden];
[nativeWindow standardWindowButton:NSWindowMiniaturizeButton].hidden = YES;
[nativeWindow standardWindowButton:NSWindowCloseButton].hidden = YES;
[nativeWindow standardWindowButton:NSWindowZoomButton].hidden = YES;
[nativeWindow makeKeyWindow];
}
else
{
[nativeWindow setStyleMask:0];
}
}
//\cond HIDDEN_SYMBOLS
@interface Handler : NSObject
{
}
@end
//\endcond
Handler *m_handler;
void macOSNative::registerNotification(const char *notification_name, long wid)
{
NSView *nativeView = reinterpret_cast<NSView*>(wid);
NSWindow *nativeWindow = [nativeView window];
[[NSNotificationCenter defaultCenter]
addObserver:m_handler
selector:@selector(NotificationHandler:)
name:[NSString stringWithUTF8String:notification_name]
object:nativeWindow];
}
void macOSNative::unregisterNotification()
{
[[NSNotificationCenter defaultCenter]
removeObserver:m_handler];
[m_handler release];
}
//\cond HIDDEN_SYMBOLS
@implementation Handler
+ (void)load
{
m_handler = static_cast<Handler*>(self);
}
+(void)NotificationHandler:(NSNotification*)notification
{
const NSString *str = [notification name];
const NSWindow *nativeWindow = [notification object];
const NSView *nativeView = [nativeWindow contentView];
const char *cstr = [str cStringUsingEncoding:NSUTF8StringEncoding];
macOSNative::handleNotification(cstr, long(nativeView));
}
@end
//\endcond
//\cond HIDDEN_SYMBOLS
@interface ThemeChangeHandler : NSObject
{
}
@end
//\endcond
ThemeChangeHandler *m_theme_change_handler;
//\cond HIDDEN_SYMBOLS
@implementation ThemeChangeHandler
+ (void)load
{
m_theme_change_handler = static_cast<ThemeChangeHandler*>(self);
}
+(void)ThemeChangeNotification:(NSNotification*)notification
{
const NSString *str = [notification name];
const char *cstr = [str cStringUsingEncoding:NSUTF8StringEncoding];
macOSNative::handleNotification(cstr, 0);
}
@end
//\endcond
void macOSNative::registerThemeChangeNotification()
{
[[NSDistributedNotificationCenter defaultCenter]
addObserver:m_theme_change_handler
selector:@selector(ThemeChangeNotification:)
name:@"AppleInterfaceThemeChangedNotification"
object:nil];
}
const char *macOSNative::themeName()
{
NSString *str = [[NSUserDefaults standardUserDefaults] stringForKey:@"AppleInterfaceStyle"];
const char *cstr = [str cStringUsingEncoding:NSUTF8StringEncoding];
return cstr;
}

View File

@ -0,0 +1,67 @@
/*
The MIT License (MIT)
Copyright © 2021-2022 Antonio Dias
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "notification.h"
#include "qgoodwindow.h"
#include "macosnative.h"
Notification::Notification()
{
}
void Notification::addWindow(void *ptr)
{
m_ptr_list.append(ptr);
}
void Notification::removeWindow(void *ptr)
{
m_ptr_list.removeAll(ptr);
}
void Notification::registerNotification(const QByteArray &name, WId wid)
{
macOSNative::registerNotification(name.constData(), long(wid));
}
void Notification::notification(const char *notification_name, long wid)
{
const QByteArray notification = QByteArray(notification_name);
for (void *ptr : m_ptr_list)
{
QGoodWindow *gw = static_cast<QGoodWindow*>(ptr);
if (wid == 0)
{
gw->notificationReceiver(notification);
}
else if (gw->winId() == WId(wid))
{
gw->notificationReceiver(notification);
break;
}
}
}

View File

@ -0,0 +1,47 @@
/*
The MIT License (MIT)
Copyright © 2021-2022 Antonio Dias
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef NOTIFICATION_H
#define NOTIFICATION_H
#include <QtCore>
#include <QtWidgets>
//\cond HIDDEN_SYMBOLS
class Notification
{
public:
Notification();
void addWindow(void *ptr);
void removeWindow(void *ptr);
void notification(const char *notification_name, long wid);
void registerNotification(const QByteArray &name, WId wid);
private:
QList<void*> m_ptr_list;
};
//\endcond
#endif // NOTIFICATION_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,446 @@
/*
The MIT License (MIT)
Copyright © 2018-2022 Antonio Dias
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef QGOODWINDOW_H
#define QGOODWINDOW_H
#include <QtCore>
#include <QtGui>
#include <QtWidgets>
#ifdef QGOODWINDOW
#ifdef Q_OS_WIN
namespace QGoodWindowUtils
{
class NativeEventFilter;
}
#endif
#if defined Q_OS_WIN || defined Q_OS_LINUX
class Shadow;
#endif
#endif
/** **QGoodWindow** class contains the public API's to control the behavior of the customized window.
*
* On Windows, **QGoodWindow** class inherits from `QMainWindow` which is used as a native widget that
* creates, fill and control the native window of **QGoodWindow**.
*
* On Linux and macOS the **QGoodWindow** behaves like a frameless `QMainWindow`.
*/
class QGoodWindow : public QMainWindow
{
Q_OBJECT
public:
/** Constructor of *QGoodWindow*.
*
* On Windows creates the native window, turns the `QMainWindow` as a native widget,
* creates the shadow, initialize default values and calls the `QMainWindow`
* parent constructor.
*
* On Linux creates the frameless `QMainWindow`, use the shadow only to create resize borders,
* and the real shadow is draw by current Linux window manager.
*
* On macOS creates a `QMainWindow` with full access to the title bar,
* and hide native minimize, zoom and close buttons.
*/
explicit QGoodWindow(QWidget *parent = nullptr,
const QColor &clear_color =
QColor(!isSystemThemeDark() ? Qt::white : Qt::black));
/** Destructor of *QGoodWindow*. */
~QGoodWindow();
/** Enum that contains caption buttons states when it's states are handled by *QGoodWindow*.*/
enum class CaptionButtonState
{
/** Minimize button hover enter. */
MinimizeHoverEnter,
/** Minimize button hover leave. */
MinimizeHoverLeave,
/** Minimize button press. */
MinimizePress,
/** Minimize button release. */
MinimizeRelease,
/** Minimize button clicked. */
MinimizeClicked,
/** Maximize or restore button hover enter. */
MaximizeHoverEnter,
/** Maximize or restore button hover leave. */
MaximizeHoverLeave,
/** Maximize or restore button press. */
MaximizePress,
/** Maximize or restore button release. */
MaximizeRelease,
/** Maximize or restore button clicked. */
MaximizeClicked,
/** Close button hover enter. */
CloseHoverEnter,
/** Close button hover leave. */
CloseHoverLeave,
/** Close button press. */
ClosePress,
/** Close button release. */
CloseRelease,
/** Close button clicked. */
CloseClicked
};
//Functions
/** Returns the window id of the *QGoodWindow*. */
WId winId() const;
//Variables
/** Reserved. */
QPointer<QTimer> m_theme_change_timer;
signals:
/** On handled caption buttons, this SIGNAL report the state of these buttons. */
void captionButtonStateChanged(const QGoodWindow::CaptionButtonState &state);
/** Notify that the system has changed between light and dark mode. */
void systemThemeChanged();
public slots:
/*** QGOODWINDOW FUNCTIONS BEGIN ***/
/** Returns if the current system theme is dark or not. */
static bool isSystemThemeDark();
/** Returns if there is a one pixel margin around window for resizing or not, i.e. if system draw margins. */
static bool shouldBordersBeDrawnBySystem();
/** On Windows, Linux and macOS, returns the actual title bar height, on other OSes returns 0. */
int titleBarHeight() const;
/** On Windows, Linux and macOS, return the actual icon width, on other OSes returns 0. */
int iconWidth() const;
/** On Windows, Linux and macOS, returns the left margin of the customized title bar, on other OSes returns 0. */
int leftMargin() const;
/** On Windows, Linux and macOS, returns the right margin of the customized title bar, on other OSes returns 0. */
int rightMargin() const;
/** Set the tile bar height, icon width, left and right margins of the customized title bar. */
void setMargins(int title_bar_height, int icon_width, int left, int right);
/** Set the mask for the left margin of the customized title bar. */
void setLeftMask(const QRegion &mask);
/** Set the mask for the right margin of the customized title bar. */
void setRightMask(const QRegion &mask);
/** Set if the caption buttons should be handled by *QGoodWindow* and on which \e corner, valid only top left and top right corners. */
void setCaptionButtonsHandled(bool handled, const Qt::Corner &corner = Qt::TopRightCorner);
/** Set the location and shape of handled minimize button, relative to handled corner. */
void setMinimizeMask(const QRegion &mask);
/** Set the location and shape of handled maximize button, relative to handled corner. */
void setMaximizeMask(const QRegion &mask);
/** Set the location and shape of handled close button, relative to handled corner. */
void setCloseMask(const QRegion &mask);
/** Get the size that should be the size of the mask on the left margin of the customized title bar. */
QSize leftMaskSize() const;
/** Get the size that should be the size of the mask on the right margin of the customized title bar. */
QSize rightMaskSize() const;
/** If caption buttons are handled on left corner, their buttons masks should be in the bounds of this rect. */
QRect leftCaptionButtonsRect() const;
/** If caption buttons are handled on right corner, their buttons masks should be in the bounds of this rect. */
QRect rightCaptionButtonsRect() const;
/*** QGOODWINDOW FUNCTIONS END ***/
/** Set fixed size for *QGoodWindow* to width \e w and height \e h. */
void setFixedSize(int w, int h);
/** Set fixed size for *QGoodWindow* to \e size. */
void setFixedSize(const QSize &size);
/** Returns the geometry for *QGoodWindow* including extended frame and excluding shadow. */
QRect frameGeometry() const;
/** Returns the client area geometry. */
QRect geometry() const;
/** Returns the client area size, position is always `QPoint(0, 0)`. */
QRect rect() const;
/** Position of the window on screen. */
QPoint pos() const;
/** Size of the window on screen. */
QSize size() const;
/** X position of the window on screen. */
int x() const;
/** Y position of the window on screen. */
int y() const;
/** Width of the window. */
int width() const;
/** Height of the window. */
int height() const;
/** Move the window to \e x - \e y coordinates. */
void move(int x, int y);
/** Move the window to \e pos. */
void move(const QPoint &pos);
/** Resize the window to \e width - \e height size. */
void resize(int width, int height);
/** Resize the window to \e size. */
void resize(const QSize &size);
/** Set geometry to pos \e x - \e y, width \e w and height \e h. */
void setGeometry(int x, int y, int w, int h);
/** Set geometry to \e rect. */
void setGeometry(const QRect &rect);
/** Activates the *QGoodWindow*. */
void activateWindow();
/** Shows the *QGoodWindow*. */
void show();
/** Shows or restore the *QGoodWindow*. */
void showNormal();
/** Shows or maximize the *QGoodWindow*. */
void showMaximized();
/** Minimize the *QGoodWindow*. */
void showMinimized();
/** Turns the *QGoodWindow* into full screen mode. Including the title bar. */
void showFullScreen();
/** Hide the *QGoodWindow*. */
void hide();
/** Close the *QGoodWindow*. */
void close();
/** Returns if the *QGoodWindow* is visible or not. */
bool isVisible() const;
/** Returns if the *QGoodWindow* is enabled or not. */
bool isEnabled() const;
/** Returns if the *QGoodWindow* is the foreground window or not. */
bool isActiveWindow() const;
/** Returns if the *QGoodWindow* is maximized or not. */
bool isMaximized() const;
/** Returns if the *QGoodWindow* is minimized or not. */
bool isMinimized() const;
/** Returns if the *QGoodWindow* is in full screen mode or not. */
bool isFullScreen() const;
/** Returns the *QGoodWindow* state. */
Qt::WindowStates windowState() const;
/** Sets the state of the *QGoodWindow* to \e state. */
void setWindowState(Qt::WindowStates state);
/** Returns the window handle of the *QGoodWindow*. */
QWindow *windowHandle() const;
/** Returns the opacity of the *QGoodWindow*. */
qreal windowOpacity() const;
/** Sets the opacity of the *QGoodWindow* to \e level. Where 0.0 is fully transparent and 1.0 fully opaque. */
void setWindowOpacity(qreal level);
/** Returns the title of the *QGoodWindow*. */
QString windowTitle() const;
/** Sets the title of the *QGoodWindow* to \e title. */
void setWindowTitle(const QString &title);
/** Returns the icon of the *QGoodWindow*. */
QIcon windowIcon() const;
/** Sets the icon of the *QGoodWindow* to \e icon. */
void setWindowIcon(const QIcon &icon);
protected:
//Functions
bool event(QEvent *event);
bool eventFilter(QObject *watched, QEvent *event);
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
bool nativeEvent(const QByteArray &eventType, void *message, long *result);
#else
bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result);
#endif
private:
#ifdef QGOODWINDOW
#ifdef Q_OS_WIN
//Functions
void initGW();
void destroyGW();
static LRESULT WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
void handleActivation();
void handleDeactivation();
void setWidgetFocus();
void enableCaption();
void disableCaption();
void frameChanged();
void sizeMoveWindow();
LRESULT ncHitTest(int x, int y);
void showContextMenu(int x, int y);
void showContextMenu();
QWidget *bestParentForModalWindow();
void moveCenterWindow(QWidget *widget);
bool winButtonHover(long button);
//Variables
HWND m_hwnd;
bool m_win_use_native_borders;
QPointer<QMainWindow> m_main_window;
QPointer<Shadow> m_shadow;
QPointer<QWidget> m_helper_widget;
QGoodWindowUtils::NativeEventFilter *m_native_event;
QWindow *m_window_handle;
QPointer<QWidget> m_focus_widget;
bool m_closed;
bool m_is_full_screen;
QRect m_rect_origin;
bool m_active_state;
Qt::WindowState m_state;
QColor m_clear_color;
friend class QGoodWindowUtils::NativeEventFilter;
#endif
#ifdef Q_OS_LINUX
//Functions
void setCursorForCurrentPos();
void startSystemMoveResize();
void sizeMove();
void sizeMoveBorders();
//Variables
QList<QPointer<Shadow>> m_shadow_list;
int m_margin;
QPoint m_cursor_pos;
bool m_resize_move;
bool m_resize_move_started;
qreal m_pixel_ratio;
friend class Shadow;
#endif
#ifdef Q_OS_MAC
//Functions
void notificationReceiver(const QByteArray &notification);
//Variables
QPoint m_pos;
bool m_mouse_button_pressed;
bool m_on_animate_event;
friend class Notification;
#endif
#if defined Q_OS_LINUX || defined Q_OS_MAC
//Functions
int ncHitTest(int x, int y);
//Variables
int m_last_move_button;
#endif
#if defined Q_OS_WIN || defined Q_OS_LINUX
bool m_fixed_size;
#endif
#ifdef Q_OS_LINUX
bool m_last_fixed_size_value;
#endif
//Functions
void buttonEnter(long button);
void buttonLeave(long button);
bool buttonPress(long button);
bool buttonRelease(long button, bool valid_click);
//Variables
QPointer<QTimer> m_hover_timer;
QRegion m_left_mask;
QRegion m_right_mask;
QRegion m_min_mask;
QRegion m_max_mask;
QRegion m_cls_mask;
bool m_dark;
bool m_caption_buttons_handled;
Qt::Corner m_caption_buttons_corner;
int m_title_bar_height;
int m_icon_width;
int m_left_margin;
int m_right_margin;
bool m_is_caption_button_pressed;
long m_last_caption_button_hovered;
long m_caption_button_pressed;
#endif
};
#endif // QGOODWINDOW_H

258
QGoodWindow/src/shadow.cpp Normal file
View File

@ -0,0 +1,258 @@
/*
The MIT License (MIT)
Copyright © 2018-2022 Antonio Dias
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "shadow.h"
#ifdef Q_OS_LINUX
#include "qgoodwindow.h"
#endif
#ifdef Q_OS_WIN
#define SHADOWWIDTH qCeil(10 * m_pixel_ratio)
#define COLOR1 QColor(0, 0, 0, 75)
#define COLOR2 QColor(0, 0, 0, 30)
#define COLOR3 QColor(0, 0, 0, 1)
#endif
#ifdef Q_OS_WIN
Shadow::Shadow(qreal pixel_ratio, HWND hwnd) : QWidget()
{
m_pixel_ratio = pixel_ratio;
m_hwnd = hwnd;
m_active = true;
setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::Tool);
setAttribute(Qt::WA_NoSystemBackground);
setAttribute(Qt::WA_TranslucentBackground);
setAttribute(Qt::WA_TransparentForMouseEvents);
m_timer = new QTimer(this);
connect(m_timer, &QTimer::timeout, this, &Shadow::show);
m_timer->setInterval(500/*Time to wait before showing shadow when showLater() is callled.*/);
m_timer->setSingleShot(true);
}
#endif
#ifdef Q_OS_LINUX
Shadow::Shadow(QWidget *parent) : QWidget(parent)
{
m_parent = qobject_cast<QGoodWindow*>(parent);
setWindowFlags(Qt::Window |
Qt::FramelessWindowHint |
Qt::WindowDoesNotAcceptFocus |
Qt::BypassWindowManagerHint);
setAttribute(Qt::WA_NoSystemBackground);
setAttribute(Qt::WA_TranslucentBackground);
}
#endif
int Shadow::shadowWidth()
{
#ifdef Q_OS_WIN
return SHADOWWIDTH;
#else
return 0;
#endif
}
void Shadow::showLater()
{
#ifdef Q_OS_WIN
m_timer->stop();
m_timer->start();
#endif
}
void Shadow::show()
{
#ifdef Q_OS_WIN
if (m_timer->isActive())
return;
if (!IsWindowEnabled(m_hwnd))
return;
QWidget::show();
QWidget::raise();
SetWindowPos(m_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
#else
QWidget::show();
#endif
}
void Shadow::hide()
{
#ifdef Q_OS_WIN
m_timer->stop();
if (!isVisible())
return;
QWidget::hide();
#else
QWidget::hide();
#endif
}
void Shadow::setActive(bool active)
{
#ifdef Q_OS_WIN
m_active = active;
repaint();
#else
Q_UNUSED(active)
#endif
}
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
bool Shadow::nativeEvent(const QByteArray &eventType, void *message, long *result)
#else
bool Shadow::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
#endif
{
#ifdef Q_OS_WIN
MSG* msg = static_cast<MSG*>(message);
switch (msg->message)
{
case WM_ACTIVATE:
{
switch (msg->wParam)
{
case WA_ACTIVE:
case WA_CLICKACTIVE:
{
//When shadow got focus, transfer it to main window.
SetForegroundWindow(m_hwnd);
break;
}
default:
break;
}
break;
}
case WM_MOUSEACTIVATE:
{
//When shadow got focus, transfer it to main window.
SetForegroundWindow(m_hwnd);
//Prevent main window from "focus flickering".
*result = MA_NOACTIVATE;
return true;
}
case WM_NCMOUSEMOVE:
case WM_NCLBUTTONDOWN:
case WM_NCLBUTTONUP:
case WM_NCLBUTTONDBLCLK:
case WM_NCHITTEST:
{
//Transfer the above messages to main window,
//this way the resize and snap effects happens also
//when interacting with the shadow, and acts like a secondary border.
*result = long(SendMessageW(m_hwnd, msg->message, msg->wParam, msg->lParam));
return true;
}
default:
break;
}
#endif
return QWidget::nativeEvent(eventType, message, result);
}
void Shadow::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
#ifdef Q_OS_WIN
//Draw shadow
const int shadow_width = SHADOWWIDTH;
QPainter painter(this);
painter.setCompositionMode(QPainter::CompositionMode_Source);
if (!m_active)
{
painter.fillRect(rect(), QColor(0, 0, 0, 1));
QRect rect1 = rect().adjusted(shadow_width, shadow_width, -shadow_width, -shadow_width);
painter.fillRect(rect1, Qt::transparent);
return;
}
QPixmap radial_gradient = QPixmap(shadow_width * 2, shadow_width * 2);
{
//Draw a radial gradient then split it in 4 parts and draw it to corners and edges
radial_gradient.fill(QColor(0, 0, 0, 1));
QPainter painter(&radial_gradient);
painter.setRenderHint(QPainter::Antialiasing);
painter.setCompositionMode(QPainter::CompositionMode_Source);
QRadialGradient gradient(shadow_width, shadow_width, shadow_width);
gradient.setColorAt(0.0, COLOR1);
gradient.setColorAt(0.2, COLOR2);
gradient.setColorAt(0.5, COLOR3);
QPen pen(Qt::transparent, 0);
painter.setPen(pen);
painter.setBrush(gradient);
painter.drawEllipse(0, 0, shadow_width * 2, shadow_width * 2);
}
QRect rect1 = rect().adjusted(shadow_width, shadow_width, -shadow_width, -shadow_width);
painter.drawPixmap(0, 0, shadow_width, shadow_width, radial_gradient, 0, 0, shadow_width, shadow_width); //Top-left corner
painter.drawPixmap(rect().width() - shadow_width, 0, radial_gradient, shadow_width, 0, shadow_width, shadow_width); //Top-right corner
painter.drawPixmap(0, rect().height() - shadow_width, radial_gradient, 0, shadow_width, shadow_width, shadow_width); //Bottom-left corner
painter.drawPixmap(rect().width() - shadow_width, rect().height() - shadow_width, radial_gradient, shadow_width, shadow_width, shadow_width, shadow_width); //Bottom-right corner
painter.drawPixmap(shadow_width, 0, rect1.width(), shadow_width, radial_gradient, shadow_width, 0, 1, shadow_width); //Top
painter.drawPixmap(0, shadow_width, shadow_width, rect1.height(), radial_gradient, 0, shadow_width, shadow_width, 1); //Left
painter.drawPixmap(rect1.width() + shadow_width, shadow_width, shadow_width, rect1.height(), radial_gradient, shadow_width, shadow_width, shadow_width, 1); //Right
painter.drawPixmap(shadow_width, rect1.height() + shadow_width, rect1.width(), shadow_width, radial_gradient, shadow_width, shadow_width, 1, SHADOWWIDTH); //Bottom
#endif
#ifdef Q_OS_LINUX
if (!m_parent)
return;
QPainter painter(this);
painter.setCompositionMode(QPainter::CompositionMode_Source);
painter.fillRect(rect(), Qt::transparent);
#endif
}

77
QGoodWindow/src/shadow.h Normal file
View File

@ -0,0 +1,77 @@
/*
The MIT License (MIT)
Copyright © 2018-2022 Antonio Dias
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef SHADOW_H
#define SHADOW_H
#include <QtCore>
#include <QtGui>
#include <QtWidgets>
#ifdef Q_OS_LINUX
class QGoodWindow;
#endif
//\cond HIDDEN_SYMBOLS
class Shadow : public QWidget
{
Q_OBJECT
public:
#ifdef Q_OS_WIN
explicit Shadow(qreal pixel_ratio, HWND hwnd);
#endif
#ifdef Q_OS_LINUX
explicit Shadow(QWidget *parent);
#endif
public slots:
void showLater();
void show();
void hide();
void setActive(bool active);
int shadowWidth();
private:
//Functions
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
bool nativeEvent(const QByteArray &eventType, void *message, long *result);
#else
bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result);
#endif
void paintEvent(QPaintEvent *event);
//Variables
#ifdef Q_OS_WIN
HWND m_hwnd;
QTimer *m_timer;
bool m_active;
qreal m_pixel_ratio;
#endif
#ifdef Q_OS_LINUX
QPointer<QGoodWindow> m_parent;
#endif
};
//\endcond
#endif // SHADOW_H